diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..6f4f2e1 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,15 @@ +# Do not change the line endings by default +* -text + +# Explicitly declare text files we want to always be normalized and converted +# to native line endings on checkout. +*.c text +*.h text +*.mo text +*.mos text +*.order text +.gitattributes text +.gitignore text +*.md text +*.htm* text +.mailmap text diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9a6f609 --- /dev/null +++ b/.gitignore @@ -0,0 +1,44 @@ +# Ignore Dymola output, log and temporary files (in alphabetical order) +####################################################################### +*.bak-mo +*.mof +buildlog.txt +dsfinal.txt +dsin.txt +dslog.txt +dsmodel.c +dsmodelext[0-9].c +dsres.txt +dymosim* +empty.txt +request +stat +status +stop +# Ignore files created by the unit tests. +simulator.log + +# Temporary files generated by emacs # +###################################### +*~ +\#*\# + +# .mat output files # +##################### +*.mat + +# Python compiled files # +######################### +*.pyc + +# Files generated by OS X +######################### +.DS_Store + +# encrypted files for export +############################ +*.moe + +*. + +OpenHPL/Resources/Documents/UsersGuide_src/auto/ diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..109a126 --- /dev/null +++ b/LICENSE @@ -0,0 +1,236 @@ + ACADEMIC PUBLIC LICENSE + version 1.1.1 + + Copyright (C) 2003, 2010, 2015, 2015 Andras Varga (v1.1) + Copyright (C) 2019 Dietmar Winkler (adapted for OpenHPL) + + + Preamble + + This license contains the terms and conditions of using OpenHPL in +noncommercial settings: at academic institutions for teaching and research +use and for personal or educational purposes. You will find that this +license provides noncommercial users of OpenHPL with rights that are +similar to the well-known GNU General Public License, yet it retains the +possibility for OpenHPL authors to financially support the development by +selling commercial licenses. In fact, if you intend to use OpenHPL in a +"for-profit" environment, where research is conducted to develop or enhance +a product, is used in a commercial service offering, or when an entity uses +OpenHPL to participate in government-funded, EU-funded, military or similar +research projects, then you need to obtain a commercial license. + + What are the rights given to noncommercial users? Similarly to GPL, you +have the right to use the software, to distribute copies, to receive source +code, to change the software and distribute your modifications or the +modified software. Also similarly to the GPL, if you distribute verbatim or +modified copies of this software, they must be distributed under this +license. + + By modeling the GPL, this license guarantees that you are safe when using +OpenHPL in your work, for teaching or research. This license guarantees +that OpenHPL will remain available free of charge for nonprofit use. You +can modify OpenHPL to your purposes, and you can also share your modifications. +Even in the unlikely case of the authors abandoning OpenHPL entirely, this +license permits anyone to continue developing it from the last release, and +to create further releases under this license. + + We believe that the combination of noncommercial open-source and commercial +licensing will be beneficial for the whole user community, because income from +commercial licenses will enable faster development and a higher level of +software quality, while further enjoying the informal, open communication +and collaboration channels of open source development. + + The precise terms and conditions for using, copying, distribution and +modification follow. + + + ACADEMIC PUBLIC LICENSE + + TERMS AND CONDITIONS FOR USE, COPYING, DISTRIBUTION AND MODIFICATION + + 0. Definitions + + "Program" means a copy of OpenHPL, which is said to be distributed under +this Academic Public License. + + "Work based on the Program" means either the Program or any derivative work +under copyright law: that is to say, a work containing the Program or a +portion of it, either verbatim or with modifications and/or translated into +another language. (Hereinafter, translation is included without limitation +in the term "modification".) + + "Using the Program" means any act of creating executables that contain or +directly use libraries that are part of the Program, running any of the +tools that are part of the Program, or creating works based on the Program. + +Each licensee is addressed as "you". + + 1. Permission is hereby granted to use the Program free of charge for +noncommercial purposes, including teaching and academic research at +universities, colleges and other educational institutions and personal +non-profit purposes. For using the Program for commercial purposes, +including but not restricted to consulting activities, design of commercial +hardware or software networking products, and joint research with a +commercial entity, government-funded, EU-funded, military or similar +research projects, you have to contact the Author or visit www.omnest.com +for an appropriate license. Permission is also granted to use the Program +for a reasonably limited period of time for the purpose of evaluating its +usefulness for a particular purpose. + + 2. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + + 3. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 2 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose regulations for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. +(If the same, independent sections are distributed as part of a package +that is otherwise reliant on, or is based on the Program, then the +distribution of the whole package, including but not restricted to the +independent section, must be on the unmodified terms of this License, +regadless of who the author of the included sections was.) + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based or reliant on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +storage or distribution medium does not bring the other work under +the scope of this License. + + 4. You may copy and distribute the Program (or a work based on it, +under Section 3) in object code or executable form under the terms of +Sections 2 and 3 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 2 and 3 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 2 and 3 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you received + the program in object code or executable form with such an offer, + in accord with Subsection b) above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 6. You are not required to accept this License, since you have not +signed it. Nothing else grants you permission to modify or distribute +the Program or its derivative works; law prohibits these actions +if you do not accept this License. Therefore, by modifying or distributing +the Program (or any work based on the Program), you indicate your +acceptance of this License and all its terms and conditions for copying, +distributing or modifying the Program or works based on it, to do so. + + 7. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 8. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + + 9. If the distribution and/or use of the Program are restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + NO WARRANTY + + 10. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 11. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED ON IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS diff --git a/OpenHPL/Constants.mo b/OpenHPL/Constants.mo new file mode 100644 index 0000000..1c8fbab --- /dev/null +++ b/OpenHPL/Constants.mo @@ -0,0 +1,36 @@ +within OpenHPL; +record Constants "Constants for this library" + extends Modelica.Icons.Record; + parameter Modelica.SIunits.Acceleration g = Modelica.Constants.g_n "gravity" annotation ( + Dialog(enable=false, group = "Constants")); + parameter Modelica.SIunits.Density rho = 997.0 "density" annotation ( + Dialog(group = "Properties")); + parameter Modelica.SIunits.DynamicViscosity mu = 0.89e-3 "dynamic viscosity of water" annotation ( + Dialog(group = "Properties")); + parameter Modelica.SIunits.Height eps = 5e-2 "pipe roughness height" annotation ( + Dialog(group = "Properties")); + parameter Modelica.SIunits.Pressure p_a = 1.013e5 "Atmospheric pressure" annotation ( + Dialog(group = "Constants")); + parameter Modelica.SIunits.Compressibility beta = 4.5e-10 "water compressibility" annotation ( + Dialog(group = "Properties")); + parameter Modelica.SIunits.Compressibility beta_total = 1 / rho / 1000 ^ 2 "total compressibility" annotation ( + Dialog(group = "Properties")); + parameter Boolean Steady = false "If checked - simulation starts from Steady State" annotation ( + choices(checkBox = true), + Dialog(group = "Initialization")); + parameter Modelica.SIunits.VolumeFlowRate V_0 = 19.077 "Initial flow rate through the system" annotation ( + Dialog(group = "Initialization")); + //parameter Boolean TempUse = false "If checked - the water temperature is not constant" annotation (choices(checkBox = true), Dialog(group = "Initialization")); + //parameter Modelica.SIunits.Temperature T_i = 273 + 10 "Initial water temperature" annotation (Dialog(group = "Initialization", enable = TempUse)); + parameter Modelica.SIunits.Frequency f = 50 "Initial frequency" annotation ( + Dialog(group = "Initialization")); + parameter Modelica.SIunits.SpecificHeatCapacity c_p = 4200 annotation ( + Dialog(group = "Constants")); + annotation ( + Documentation(info = "
Here, common parameters are determined for this library.
It is possible to insert this class to models and use the common parameters for whole library.
+ "), + defaultComponentName = "Const", + defaultComponentPrefixes = "inner", + missingInnerMessage = "No 'Const' component is defined. A default component will be used, and generate constants", + defaultComponentPrefixes = "inner"); +end Constants; diff --git a/OpenHPL/Controllers/package.mo b/OpenHPL/Controllers/package.mo new file mode 100644 index 0000000..3d89bf9 --- /dev/null +++ b/OpenHPL/Controllers/package.mo @@ -0,0 +1,379 @@ +within OpenHPL; +package Controllers "Collection of different controllers" + extends Modelica.Icons.Package; + + extends Icons.Governor; + + model Governor "Govenor/control model" + extends OpenHPL.Icons.Governor; + outer Constants Const "using standart class with constants"; + //// control parameters of the governor + parameter Modelica.SIunits.Time T_p = 0.04 "Pilot servomotor time constant" annotation ( + Dialog(group = "Controller settings")); + parameter Modelica.SIunits.Time T_g = 0.2 "Main servomotor integration time" annotation ( + Dialog(group = "Controller settings")); + parameter Modelica.SIunits.Time T_r = 1.75 "Transient droop time constant" annotation ( + Dialog(group = "Controller settings")); + parameter Real lookup_table[:, :] = [0.0, 0.0; 0.01, 0.06; 0.22, 0.25; 0.53, 0.5; 0.8, 0.75; 1.0, 0.95; 1.05, 1.0] "Table matrix (grid = first column; e.g., table=[0, 0; 1, 1; 2, 4])" annotation ( + Dialog(group = "System settings")); + parameter Real droop = 0.1 "Droop" annotation ( + Dialog(group = "Controller settings")); + parameter Real delta = 0.04 "Transient droop" annotation ( + Dialog(group = "Controller settings")); + parameter Real Y_gv_max = 0.05 "Max guide vane opening rate" annotation ( + Dialog(group = "System settings")); + parameter Real Y_gv_min = 0.2 "Max guide vane closing rate" annotation ( + Dialog(group = "System settings")); + parameter Real Y_gv_ref = 0.72151 "Initial guide vane opening rate" annotation ( + Dialog(group = "System settings")); + parameter Modelica.SIunits.Frequency f_ref = Const.f "Refference frequency" annotation ( + Dialog(group = "System settings")); + parameter Modelica.SIunits.Power Pn = 104e6 "Refference frequency" annotation ( + Dialog(group = "System settings")); + //// connectors + Modelica.Blocks.Interfaces.RealInput P_ref annotation ( + Placement(visible = true, transformation(extent = {{-140, 20}, {-100, 60}}, rotation = 0), iconTransformation(extent = {{-140, 20}, {-100, 60}}, rotation = 0))); + Modelica.Blocks.Interfaces.RealOutput Y_gv annotation ( + Placement(visible = true, transformation(extent = {{100, -10}, {120, 10}}, rotation = 0), iconTransformation(extent = {{100, -10}, {120, 10}}, rotation = 0))); + Modelica.Blocks.Interfaces.RealInput f annotation ( + Placement(visible = true, transformation(origin = {-120, -40}, extent = {{-20, -20}, {20, 20}}, rotation = 0))); + //// blocks + Modelica.Blocks.Tables.CombiTable1D look_up_table(table = lookup_table) annotation ( + Placement(visible = true, transformation(origin = {-54, 40}, extent = {{10, -10}, {-10, 10}}, rotation = 180))); + Modelica.Blocks.Continuous.TransferFunction pilot_servo(a = {T_p, 1}, b = {1}, initType = Modelica.Blocks.Types.Init.InitialOutput, y_start = 0) annotation ( + Placement(visible = true, transformation(origin = {-40, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Modelica.Blocks.Continuous.TransferFunction main_servo(a = { 1, 0}, b = {1}, initType = Modelica.Blocks.Types.Init.InitialOutput, y_start = Y_gv_ref) annotation ( + Placement(visible = true, transformation(origin = {46, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Modelica.Blocks.Math.Gain gain_T_s(k = 1 / T_g) annotation ( + Placement(visible = true, transformation(origin = {-10, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Modelica.Blocks.Nonlinear.Limiter limiter_dotY_gv(limitsAtInit = true, uMax = Y_gv_max, uMin = -Y_gv_min) annotation ( + Placement(visible = true, transformation(origin = {18, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Modelica.Blocks.Nonlinear.Limiter limiter_Y_gv(limitsAtInit = true, uMax = 1, uMin = 0) annotation ( + Placement(visible = true, transformation(origin = {76, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Modelica.Blocks.Continuous.TransferFunction control(a = {T_r, 1}, b = {delta * T_r, 0}, initType = Modelica.Blocks.Types.Init.InitialOutput, y_start = 0) annotation ( + Placement(visible = true, transformation(origin = {62, -30}, extent = {{10, -10}, {-10, 10}}, rotation = 0))); + Modelica.Blocks.Math.Gain gain_droop(k = droop) annotation ( + Placement(visible = true, transformation(origin = {62, -56}, extent = {{10, -10}, {-10, 10}}, rotation = 0))); + Modelica.Blocks.Math.Gain gain_P(k = 1 / Pn) annotation ( + Placement(visible = true, transformation(origin = {-84, 40}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); + Modelica.Blocks.Math.Add add1 annotation ( + Placement(visible = true, transformation(origin = {8, -44}, extent = {{10, -10}, {-10, 10}}, rotation = 0))); + Modelica.Blocks.Math.Add3 add2(k2 = -1, k3 = -1) annotation ( + Placement(visible = true, transformation(origin = {-58, -24}, extent = {{-10, -10}, {10, 10}}, rotation = 90))); + Modelica.Blocks.Math.Add add3(k1 = -1, k2 = +1) annotation ( + Placement(visible = true, transformation(origin = {-58, -60}, extent = {{10, -10}, {-10, 10}}, rotation = -90))); + Modelica.Blocks.Math.Gain gain_f(k = 1 / f_ref) annotation ( + Placement(visible = true, transformation(origin = {-84, -62}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); + Modelica.Blocks.Sources.Constant const(k = 1) annotation ( + Placement(visible = true, transformation(origin = {-30, -80}, extent = {{10, -10}, {-10, 10}}, rotation = 0))); + Modelica.Blocks.Math.Gain gain_droop2(k = droop) annotation ( + Placement(visible = true, transformation(origin = {-80, -4}, extent = {{-10, 10}, {10, -10}}, rotation = -90))); + //Modelica.Blocks.Interfaces.RealInput P_g annotation (Placement(visible = true, transformation(extent = {{-128, -54}, {-88, -14}}, rotation = 0), iconTransformation(extent = {{-120, 24}, {-80, 64}}, rotation = 0))); + initial equation + //Y_gv = Y_gv_ref; + //x_r = delta * Y_gv; + //u = 0; + equation + connect(gain_droop2.y, add2.u1) annotation ( + Line(points = {{-80, -14}, {-80, -14}, {-80, -44}, {-66, -44}, {-66, -36}, {-66, -36}}, color = {0, 0, 127})); + connect(look_up_table.y[1], gain_droop2.u) annotation ( + Line(points = {{-42, 40}, {-34, 40}, {-34, 20}, {-80, 20}, {-80, 8}, {-80, 8}}, color = {0, 0, 127})); + connect(gain_P.y, look_up_table.u[1]) annotation ( + Line(points = {{-72, 40}, {-66, 40}}, color = {0, 0, 127})); + connect(P_ref, gain_P.u) annotation ( + Line(points = {{-120, 40}, {-96, 40}}, color = {0, 0, 127})); + connect(add1.u1, control.y) annotation ( + Line(points = {{20, -38}, {34, -38}, {34, -30}, {52, -30}}, color = {0, 0, 127})); + connect(gain_droop.y, add1.u2) annotation ( + Line(points = {{52, -56}, {36, -56}, {36, -50}, {20, -50}}, color = {0, 0, 127})); + connect(add1.y, add2.u3) annotation ( + Line(points = {{-3, -44}, {-50, -44}, {-50, -36}}, color = {0, 0, 127})); + connect(limiter_Y_gv.y, gain_droop.u) annotation ( + Line(points = {{88, 0}, {92, 0}, {92, -56}, {74, -56}, {74, -56}}, color = {0, 0, 127})); + connect(limiter_Y_gv.y, control.u) annotation ( + Line(points = {{88, 0}, {92, 0}, {92, -30}, {74, -30}, {74, -30}, {74, -30}}, color = {0, 0, 127})); + connect(limiter_Y_gv.y, Y_gv) annotation ( + Line(points = {{88, 0}, {110, 0}}, color = {0, 0, 127})); + connect(const.y, add3.u1) annotation ( + Line(points = {{-40, -80}, {-52, -80}, {-52, -72}, {-52, -72}}, color = {0, 0, 127})); + connect(gain_f.y, add3.u2) annotation ( + Line(points = {{-84, -72}, {-84, -72}, {-84, -92}, {-64, -92}, {-64, -72}, {-64, -72}}, color = {0, 0, 127})); + connect(f, gain_f.u) annotation ( + Line(points = {{-120, -40}, {-84, -40}, {-84, -48}, {-84, -48}, {-84, -50}}, color = {0, 0, 127})); + connect(add3.y, add2.u2) annotation ( + Line(points = {{-58, -48}, {-58, -48}, {-58, -36}, {-58, -36}}, color = {0, 0, 127})); + connect(add2.y, pilot_servo.u) annotation ( + Line(points = {{-58, -13}, {-58, 0}, {-52, 0}}, color = {0, 0, 127})); + connect(main_servo.y, limiter_Y_gv.u) annotation ( + Line(points = {{58, 0}, {64, 0}, {64, 0}, {64, 0}}, color = {0, 0, 127})); + connect(gain_T_s.y, limiter_dotY_gv.u) annotation ( + Line(points = {{2, 0}, {4, 0}, {4, 0}, {6, 0}}, color = {0, 0, 127})); + connect(limiter_dotY_gv.y, main_servo.u) annotation ( + Line(points = {{29, 0}, {34, 0}}, color = {0, 0, 127})); + connect(pilot_servo.y, gain_T_s.u) annotation ( + Line(points = {{-28, 0}, {-22, 0}, {-22, 0}, {-22, 0}}, color = {0, 0, 127})); + //// define curve for control signal based on power + //look_up_table.u[1] = P_ref / Pn; + //Y_gv_ref = look_up_table.y[1]; + //// governor model + //dd = delta * Y_gv - x_r; + //e = 1 - f / f_ref - dd + droop * (Y_gv_ref - Y_gv); + //(P_ref/103e6 - P_g/103e6); + //T_r * der(x_r) + x_r = delta * Y_gv; + //T_p * der(u) + u = e; + //if Y_gv < 0 and u < 0 or Y_gv > 1 and u > 0 then + // der(Y_gv) = 0; + //elseif u / T_g >= Y_gv_max then + // der(Y_gv) = Y_gv_max; + //elseif u / T_g <= (-Y_gv_min) then + // der(Y_gv) = -Y_gv_min; + //else + // der(Y_gv) = u / T_g; + //end if; + annotation ( + Documentation(info = "This is a simple model of the governor that controls the guide vane oppening in the turbine based on the reference power production.Copyright © 2019
+The group can be contacted by email: OpenHPL@simulati.no
+This Source Code Form is subject to the terms of the +ACADEMIC PUBLIC LICENSE.
+" + + annotation ( + preferredView="info", + DocumentationClass=false, + Icon(graphics={ + Text( + extent={{-100,140},{100,100}}, + lineColor={0,127,0}, + textString="%name%"), + Ellipse( + extent={{-100,100},{100,-100}}, + lineColor={0,127,0}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Ellipse( + extent={{-60,60},{60,-60}}, + lineColor={0,127,72}, + fillColor={0,127,0}, + fillPattern=FillPattern.Solid), + Ellipse( + extent={{-40,40},{40,-40}}, + lineColor={255,255,255}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Rectangle( + extent={{28,22},{64,-20}}, + lineColor={255,255,255}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid)})); +end Copyright; diff --git a/OpenHPL/ElectroMech/Generators/SimpleGen.mo b/OpenHPL/ElectroMech/Generators/SimpleGen.mo new file mode 100644 index 0000000..f8e67d8 --- /dev/null +++ b/OpenHPL/ElectroMech/Generators/SimpleGen.mo @@ -0,0 +1,61 @@ +within OpenHPL.ElectroMech.Generators; +model SimpleGen "Model of a simple generator" + outer Constants Const "Using standard class with constants"; + import Modelica.Constants.pi; + extends OpenHPL.Icons.Generator; + //// geometrical parameters of the agreggate + parameter Modelica.SIunits.MomentOfInertia J = 2e5 "Moment of inertia of the generator"; + parameter Modelica.SIunits.Efficiency theta_e = 0.99 "Generator's electrical efficiency"; + parameter Real k_b = 1000 "Friction factor in the aggregate bearing box [W-s3/rad3]"; + parameter Integer p = 12 "Number of poles"; + //// condition of steady state + parameter Boolean SteadyState = Const.Steady "If true - starts from Steady State" annotation ( + Dialog(group = "Initialization")); + //// staedy state value for angular velocity + parameter Modelica.SIunits.AngularVelocity w_0 = Const.f * 4 * pi / p "Initial angular velocity" annotation ( + Dialog(group = "Initialization")); + //// condition for output + parameter Boolean UseFrequencyOutput = true "If checked - get a connector for frequency output" annotation ( + choices(checkBox = true)); + //// variables + Modelica.SIunits.AngularVelocity w(start = w_0) "Angular velocity"; + Modelica.SIunits.Energy K_a "Kinetic energy"; + Modelica.SIunits.EnergyFlowRate W_ts_dot "Shaft power"; + Modelica.SIunits.EnergyFlowRate W_fa "Friction losses"; + Modelica.SIunits.EnergyFlowRate W_g = u / theta_e "Electrical power"; + //// conectors + Modelica.Blocks.Interfaces.RealInput u "Electrical demand" annotation ( + Placement(visible = true, transformation(extent={{-140,-20},{-100,20}}, rotation = 0), iconTransformation(extent = {{-120, -20}, {-80, 20}}, rotation = 0))); + Modelica.Blocks.Interfaces.RealOutput f if UseFrequencyOutput "Output of generator frequency" + annotation ( + Placement(transformation(extent={{100,-10},{120,10}}))); + Modelica.Blocks.Interfaces.RealInput P_in = W_ts_dot "Input of mechanical power" annotation ( + Placement(visible = true, transformation(origin={3.55271e-15,120}, + extent={{-20,-20},{20,20}}, rotation = 270))); + Modelica.Blocks.Interfaces.RealOutput w_out = w "Output angular velocity of the generator" + annotation ( + Placement(visible = true, transformation(origin={110,60}, extent={{-10,-10}, + {10,10}}, rotation=0))); +initial equation + if SteadyState == true then + der(K_a) = 0; + else + w = w_0; + end if; +equation + //// frequency + f = p / 120 * 30 * w / pi; + //// generator energy balance + K_a = 0.5 * J * w ^ 2; + W_fa = 0.5 * k_b * w ^ 2; + der(K_a) = W_ts_dot - W_fa - W_g; + annotation ( + Documentation(info="Simple model of an ideal generator with friction.
+This model has inputs as electric power available on the grid and the turbine shaft power. +This model based on the angular momentum balance, which depends on the turbine shaft power, + the friction loss in the aggregate rotation and the power taken up by the generator.
++ +
+")); +end SimpleGen; diff --git a/OpenHPL/ElectroMech/Generators/SynchGen.mo b/OpenHPL/ElectroMech/Generators/SynchGen.mo new file mode 100644 index 0000000..d4c199a --- /dev/null +++ b/OpenHPL/ElectroMech/Generators/SynchGen.mo @@ -0,0 +1,113 @@ +within OpenHPL.ElectroMech.Generators; +model SynchGen "Simple model of the generator connected to the grid" + extends OpenHPL.Icons.Generator; + outer Constants Const "Using standard class with constants"; + import Modelica.Constants.pi; + //// parameters of the generator + parameter Modelica.SIunits.Power P_op = 80e6 "Active power drawn from generator at Steady State operating condition" annotation ( + Dialog(group = "Nominal parameters")), Q_op = 50e6 "Reactive power drawn from generator at SS operating condition" annotation ( + Dialog(group = "Nominal parameters")); + parameter Modelica.SIunits.Resistance Ra = 0.01 "Phase winding resistance" annotation ( + Dialog(group = "Nominal parameters")), Re = 0.1 "Equivalent network resistance" annotation ( + Dialog(group = "Network")), xd = 12 "d_axis reactance" annotation ( + Dialog(group = "d-q axes")), xq = 12 "q_axis reactance" annotation ( + Dialog(group = "d-q axes")), xxd = 1.7 "d_axis transient reactance" annotation ( + Dialog(group = "Transient d-q axes")), xxq = 1.7 "q_axis transient reactance" annotation ( + Dialog(group = "Transient d-q axes")), xe = 1.4 "Equivalent network reactance" annotation ( + Dialog(group = "Network")); + parameter Modelica.SIunits.Time TTdo = 6 "d_axis transient open-circuit time constant" annotation ( + Dialog(group = "Transient d-q axes")), TTqo = 0.1 "q_axis transient open-circuit time constant" annotation ( + Dialog(group = "Transient d-q axes")), TE = 0.05 "Excitation system time constant" annotation ( + Dialog(group = "Excitation system")), TFE = 1 "Stablizer time constant" annotation ( + Dialog(group = "Stablizer")); + parameter Modelica.SIunits.Voltage Vs = 15000 "Network rms voltage" annotation ( + Dialog(group = "Network")), Efmin = 50000 "Min field voltage" annotation ( + Dialog(group = "Transient d-q axes")), Efmax = 50000 "Max field voltage" annotation ( + Dialog(group = "Transient d-q axes")); + parameter Real KE = 400 "Excitation system gain" annotation ( + Dialog(group = "Excitation system")), KF = 0.025 "Stablizer gain" annotation ( + Dialog(group = "Stablizer")); + parameter Integer np = 12 "Number of poles" annotation ( + Dialog(group = "Nominal parameters")); + parameter Modelica.SIunits.AngularVelocity Wm_op = Const.f * pi / 3 "Grid angular velocity" annotation ( + Dialog(group = "Network")); + parameter Modelica.SIunits.MomentOfInertia J = 2e5 "Moment of inertia of the generator" annotation ( + Dialog(group = "Mechanical part")); + parameter Real k_b = 1000 "Friction factor in the generator bearing box, W*s3/rad3" annotation ( + Dialog(group = "Mechanical part")); + parameter Boolean UseFrequencyOutput = true "If checked - get a connector for frequency output" annotation ( + choices(checkBox = true), + Dialog(group = "Network")), SelfInitialization = false "If checked - specify initial values" annotation ( + choices(checkBox = true), + Dialog(group = "Initialization")); + parameter Modelica.SIunits.Angle DELTA_0 = 37.6452 annotation ( + Dialog(group = "Initialization", enable = SelfInitialization)); + parameter Modelica.SIunits.Voltage EEd_0 = -7207.13 "" annotation ( + Dialog(group = "Initialization", enable = SelfInitialization)), EEq_0 = 18005.2 "" annotation ( + Dialog(group = "Initialization", enable = SelfInitialization)), Ef_0 = 38110.4 "" annotation ( + Dialog(group = "Initialization", enable = SelfInitialization)), Vstabilizer_0 = 0 "" annotation ( + Dialog(group = "Initialization", enable = SelfInitialization)); + parameter Modelica.SIunits.AngularVelocity w_0 = 500 * pi / 30 "" annotation ( + Dialog(group = "Initialization", enable = SelfInitialization)); + //// variables + Modelica.SIunits.Angle PHI_op = atan(Q_op / P_op) "Power angle at Steady State", DELTA_op = atan((I_op * (xq + xe) * cos(PHI_op) - I_op * (Ra + Re) * sin(PHI_op)) / (Vs + I_op * (Ra + Re) * cos(PHI_op) + I_op * (xq + xe) * sin(PHI_op))), DELTA; + Modelica.SIunits.Current I_op = sqrt(P_op ^ 2 + Q_op ^ 2) / (3 * Vs) "RMS current (per phase) of the generator", Id_op = -I_op * sin(DELTA_op + PHI_op), Iq_op = I_op * cos(DELTA_op + PHI_op), Idq[2], Id, Iq, It; + Modelica.SIunits.Voltage Ef_op = Vs * cos(DELTA_op) + (Ra + Re) * Iq_op - (xd + xe) * Id_op, Vt_op = sqrt((Vs + I_op * Re * cos(PHI_op) + I_op * xe * sin(PHI_op)) ^ 2 + (I_op * xe * cos(PHI_op) - I_op * Re * sin(PHI_op)) ^ 2), Vtr = Ef_op / KE + Vt_op, Vstabilizer_op = 0, EEd_op = (xxd - xq) * Iq_op, EEq_op = Ef_op + (xd - xxd) * Id_op, Vt, EEd, EEq, Ef, Vstabilizer; + Modelica.SIunits.AngularVelocity w_op = 500 * pi / 30, w; + Modelica.SIunits.Resistance Temp[2, 2]; + Modelica.SIunits.Power Pe, Qe; + Modelica.SIunits.EnergyFlowRate W_ts_dot, W_fa; + //// conectors + Modelica.Blocks.Interfaces.RealOutput f = np / 120 * 30 * w / pi if UseFrequencyOutput "Output generator frequency" annotation ( + Placement(transformation(extent={{100,-10},{120,10}}))); + Modelica.Blocks.Interfaces.RealOutput w_out = w "Output of the generator's angular velocity" annotation (Placement(visible = true, transformation(origin={110,60}, extent={{-10,-10}, + {10,10}}, rotation=0))); + Modelica.Blocks.Interfaces.RealInput P_in = W_ts_dot "Input of mechanical power" annotation ( + Placement(transformation(extent={{-20,-20},{20,20}}, rotation = 270, origin={0,120}))); +initial equation + if SelfInitialization == false then + EEd = EEd_op; + EEq = EEq_op; + DELTA = DELTA_op; + Ef = Ef_op; + Vstabilizer = Vstabilizer_op; + w = w_op; + else + EEd = EEd_0; + EEq = EEq_0; + DELTA = DELTA_0; + Ef = Ef_0; + Vstabilizer = Vstabilizer_0; + w = w_0; + end if; +equation + //// voltage-current relation + Temp = [Ra + Re, xxq + xe; (-xxd) - xe, Ra + Re]; + Temp * Idq = {EEd + Vs * sin(DELTA), EEq - Vs * cos(DELTA)}; + Id = Idq[1]; + Iq = Idq[2]; + Vt = sqrt((EEd - Ra * Id - xxq * Iq) ^ 2 + (EEq - Ra * Iq + xxd * Id) ^ 2); + It = sqrt(Id ^ 2 + Iq ^ 2); + Pe = 3 * (EEd * Id + EEq * Iq); + Qe = sqrt(9 * Vt ^ 2 * It ^ 2 - Pe ^ 2); + //// dynamic equations + TTqo * der(EEd) = (-EEd) + (xxq - xq) * Iq; + TTdo * der(EEq) = (-EEq) + (xd - xxd) * Id + Ef; + der(DELTA) = (w - Wm_op) * np / 2; + //if Ef >= Efmax and ((-Ef) + KE * (Vtr - Vt - Vstabilizer)) / TE > 0 then + // der(Ef) = 0; + //elseif Ef < (-Efmin) and ((-Ef) + KE * (Vtr - Vt - Vstabilizer)) / TE < 0 then + // der(Ef) = 0; + //else + //der(Ef) = ((-Ef) + KE * (Vtr - Vt)) / TE; + der(Ef) = ((-Ef) + KE * (Vtr - Vt - Vstabilizer)) / TE; + //end if; + der(Vstabilizer) = ((-Vstabilizer) + KF * der(Ef)) / TFE; + //// Mechanical equation + W_fa = 0.5 * k_b * w ^ 2; + der(w) = (W_ts_dot - Pe) / (J * w); + // - W_fa; + //// + annotation ( + Documentation(info="This is a model of the generator that is connected to the grid. This model coud give some transient results. However, it is better to use generator models from IPSL.