Git Product home page Git Product logo

metroscope-modeling-library's Introduction

Metroscope Modeling Library

Metroscope TSP License GitHub release (with filter)

πŸ“ƒ Content

The Metroscope Modeling Library contains modelica modules for industrial components such as pumps, turbines, heat exchangers, to build steady-state digital twins of industrial process. The associated documentation contains explanation of the library equations.

πŸ—οΈ Usage

  • When creating a Digital Twin you should only use official releases of Metroscope Modeling Library. Official releases can be downloaded from here.
  • In your model, you should add a line in annotation, containing the following : uses(MetroscopeModelingLibrary(version(="3.0.1")) in which you replace the version number ("3.0.1") by the one you use. That way you will get a warning if you use your model with a wrong version of the library.
  • If you need additionnal features, please ask for them using issues

πŸ“– Documentation

Library documentation is available in this public Notion space. You can use comments in the documentation to ask questions about the library. Please do not include any proprieraty information. In order to comment the page, you need to create a Notion account.

πŸ› Reporting a bug

GitHub issues by-label

  • Report your issues on issues page
  • Do not attach sensitive data to the GitHub issue you create
  • Provide following information
    • A clear and concise description of what the bug is
    • Steps to reproduce the bahavior
    • A clear and concise description of what you expected to happen.
    • Your configuration (OS, Modelica version, Metroscope Modeling Library version, modeling software & version)

πŸ‘¨β€πŸ’» Contributions

GitHub issues by-label

Your contributions are very welcome. To contribute, you have to clone or fork the repository Metroscope Modeling Library: git clone [email protected]:Metroscope-dev/metroscope-modeling-library.git

To suggest changes, you have to:

  • checkout main branch: git checkout main
  • pull last changes: git pull
  • create a new branch: git checkout -b new-branch-name
  • commit your changes & push your code
  • create a pull request
    • Give a meaningfule title to your pull request (examples: Fix eta_is SteamTurbine or Add SteamTurbine)
    • Provide a comment explaining the changes
      • Aim of the changes
      • Description of the changes
      • If associated to an open GitHub issue, provide its url

For the sake of efficiency, create a draft pull request if you still have work to do before having your pull request reviewed (see Github documentation if needed).

Notify the MML team for a review of your PR.

ℹ️ Attribution notice

Licensed by Metroscope under the Modelica License 2 Copyright Β© 2023, Metroscope.

This Modelica package is free software and the use is completely at your own risk; it can be redistributed and/or modified under the terms of the Modelica License 2. For license conditions (including the disclaimer of warranty) see Modelica.UsersGuide.ModelicaLicense2 or visit http://www.modelica.org/licenses/ModelicaLicense2.

Metroscope Modeling Library is a Derivative Work of ThermoSysPro:

metroscope-modeling-library's People

Contributors

andreabartolini avatar arthurr-met avatar casella avatar edwing-met avatar hadrienp-met avatar helenev-met avatar laurentm-met avatar moritzn-met avatar nabily-met avatar pierre-eliep-met avatar valentind-met avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

metroscope-modeling-library's Issues

Model TestReheater fails during initialization in OpenModelica

Model Test.UnitTest.WaterSteam.HeatExchangers.TestReheater fails during initialization in OpenModelica.

The Newton solver fails while trying to solve system 156, which has the following iteration variables:

[1] Real sink_hot_CondSteam.basicTransport.h_in(start=100000, nominal=500000)
[2] Real sink_hot_CondSteam.h_in(start=100000, nominal=500000)
[3] Real Reheater.Kth_cond(start=2000, nominal=1)
[4] Real Reheater.S_deh(start=250, nominal=1)
[5] Real Reheater.condensing_hot.h_out(start=100000, nominal=500000)
[6] Real Reheater.condensing_hot.h_in(start=100000, nominal=500000)
[7] Real Reheater.deheating_hot.h_in(start=100000, nominal=500000)
[8] Real sink_hot_CondSteam.Q_in(start=500, nominal=1)
[9] Real source_hot_SatSteam.basicTransport.h_in(start=100000, nominal=500000)

The solution found by Dymola is very far from these start values. In particular:

  • enthalpies are in the range of wet or superheated steam (1-2 MJ/kg), not cold water (100 kJ/kg)
  • S_deh turns out to be zero
  • Kth_cond is much higher than the start value, at about 70 kW/m2K
  • Q_in is much lower than the start value, at 44 kg/s

It is probably advisable to provide some default values which are appropriate for steam enthalpies (e.g. 1e6 instead of 1e5).

Also the presence of noEvent could be questionable - it could be replaced by smooth(0, ).

One thing worth investigating is that Dymola splits the computation in two cascaded sub-systems, the second computing only S_cond, S_deh, Kth_cond, Kth_deh, while OpenModelica keeps this computation together with the computation of the enthalpies. In principle, strong component analysis should give the same results in both tools, even though the individual strong components may be solved differently.

Model TestStaticCentrifugalPump fails in OpenModelica

Model MetroscopeModelingLibrary.Tests.UnitTests.WaterSteam.Machines.TestStaticCentrifugalPump fails during initialization in OpenModelica. Some analysis reveals that one torn nonlinear equations has the following iteration variables and initial values:

[1] Real staticCentrifugalPump.rhom(start=998, nominal=1)
[2] Real source.C_out.H(start=5e+07, nominal=1)
[3] Real staticCentrifugalPump.C_out.h_vol(start=100000, nominal=1)
[4] Real staticCentrifugalPump.Qv0(start=0.5, nominal=1)
[5] Real staticCentrifugalPump.Qv(start=0.5, nominal=1)
[6] Real source.C_out.h_vol(start=100000, nominal=1)

The following torn equations:

(torn) staticCentrifugalPump.h_in := (-source.C_out.H) / Q
(torn) staticCentrifugalPump.rho_in := 
  Modelica.Media.Water.IF97_Utilities.waterBaseProp_ph(P_source, staticCentrifugalPump.h_in, 0, 0).rho

cause the following error

Error in region computation of IF97 steam tables(p = 200000, h = -500000)

This happens because the default start attribute for the port enthalpy flow H is +5e7, i.e. 50 MW entering, but it also used for C_out.H, where the flow is actually leaving. Hence the wrong sign.

Of course one could set a negative start value for the outlet port, thus at least avoiding the negative specific enthalpy values. But this is still not robust, because if the value is not correct, one could very easily get chilled water or plasma.

As already mentioned in #14, I believe that using stream connectors could lead to a more numerically robust design.

I checked how Dymola solves the problem. In this case, Dymola select a slightly different set of tearing variables

sink.basicTransport.h_in = 100000
sink.basicTransport.h_out = 100000
staticCentrifugalPump.C_out.h_vol = 100000
staticCentrifugalPump.Qv = 0.5
staticCentrifugalPump.Qv0 = 0.5
source.basicTransport.h_out = 100000
source.basicTransport.h_in = 100000
staticCentrifugalPump.C_in.h_vol = 100000
staticCentrifugalPump.h_in = 100000
staticCentrifugalPump.rhom = 998

which has a few more variables, but only includes specific enthalpies, no enthalpy flows. With this choice, the Dymola Newton solver manages to converge to the solution.

However, the way Modelica tools select tearing variables is often difficult to predict (and a trade secret in case of Dymola), so I guess one should try not to depend on this too much.

Adding "partial" to partial component names

In order to make it cristal clear that your are using a partial component, it should appear in the name. Example: for now, the partial pump componenet is called "Pump" instead of "PartialPump". But it is declared as "partial model" -> which means that you cannot use the component whitout specifying a medium or adding equation.
So why not explicitly write it in the component name ?

Topological models should be marked as partial

Topological models in the Metroscope library, e.g., MetroscopeModelingLibrary.Tests.SimpleExamples.PowerPlant.MetroscopiaNPP.MetroscopiaNPP_topological, are structurally lacking some closure equations.

Hence, they should be marked as partial, so the compiler knows that they are not balanced, and will provide appropriate feedback if one checks them or tries to simulate them.

Ditto for partial models such as MetroscopeModelingLibrary.Common.Partial.BasicTransportModel

MetroscopiaNPP_direct_withStartValues is very slow in OpenModelica

The model MetroscopeModelingLibrary.Tests.SimpleExamples.PowerPlant.MetroscopiaNPP.MetroscopiaNPP_direct_withStartValues simulates successfully in OpenModelica but is very slow. There are two main reasons for that.

The first is that currently OpenModelica does not recognize that certain variables are only a function of parameters or constanst, and hence can be computed once and for all during initialization. Hence, the big nonlinear system is solved 500 times, since there are 500 reporting intervals in the simulation setup. This is a known issue (see #8026) that will eventually be resolved. In the meantime, one can set only two simulation intervals, to avoid the problem.

The second is that the solution of big nonlinear system (equation 2000) during the simulation phase takes over 30 iterations, as you can see by turning on the LOG_NLS debug flag. This makes no sense, since the iterations start at the solution find during initialization, so one iteration should be enough for the solver to figure out that the solution is good enough. This could be due to problems in the termination criterion of the OMC nonlinear solver. However, increasing the relative tolerances of the Newton solver from 1e-12 to 1e-6 via -newtonFTol=1e-6 and -newtonXTol=1e-6 only reduces the number of iterations marginally.

This is probably due to these two unknowns:

[ 1] SteamExtraction_LP.mainFlow.C_in.H  =    1.6710505e+09             nom =                1
[ 2] SteamExtraction_HP.mainFlow.C_in.H  =    2.6392254e+09             nom =                1

The nominal attribute of both is not set, so there is no scaling factor (check
2017-CasellaBraun-EOOLT.pdf to see why it is important) for very large variables, and I guess that can be problematic. It may be that setting proper nominal values on enthalpies and enthalpy flows ensures better scaling, and thus improves the solver convergence.
.

Why not using Medium.types for all thermodynamic property types?

The Modelica.Media medium packages re-define types for basic thermodynamic properties with appropriate, fluid-specific attributes, e.g. min, max, start, nominal, etc.

Why aren't they used consistently across the whole library, whenever a Medium package is defined?

Use of undeclared variables in class StodolaTurbine

The model MetroscopeModelingLibrary.Common.Machines.StodolaTurbine uses many variables which are not declared, e.g. Te, x_in, x_m, etc., so it cannot be used.

@valentindrou, this looks like a zombie model that should just be removed. Do we miss something?

Model TestSuperheater fails during simulation in OpenModelica

Model MetroscopeModelingLibrary.Tests.UnitTests.WaterSteam.HeatExchangers.TestSuperheater fails at time = 0.017 during simulation

[ 1]             sink_hot_Cond.Q_in  =                0
[ 2]             sink_hot_Cond.P_in  =        5999999.8
[ 3]   Superheater.CondVap_hot.h_in  =        178941.97
[ 4] Superheater.CondSupH_hot.h_out  =        178941.97
[ 5]  Superheater.CondSupH_hot.h_in  =        813743.84
[ 6] Superheater.CondSupH_hot.C_out.h_vol  =       -665826.29
[ 7]    Superheater.C_hot_out.h_vol  =       -1112741.3
[ 8] sink_hot_Cond.basicTransport.h_out  =        178941.97
[ 9] sink_hot_Cond.basicTransport.h_in  =        178941.97
[10] source_hot_mainSt.basicTransport.h_in  =        2805239.7
[11] source_hot_mainSt.basicTransport.h_out  =        2805239.7
[12]  Superheater.DesHSupH_hot.h_in  =        2805239.7
division by zero at time 0.017, (a=0) / (b=0), where divisor b expression is: sink_hot_Cond.Q_in
model terminate | Simulation terminated by an assert at time: 0.017

Analysis of the way the equations are solved in system 390 reveals the following torn equation:

(assign) sink_hot_Cond.h_in := (-sink_hot_Cond.basicTransport.C_out.H) / sink_hot_Cond.Q_in

where sink_ot_Cond.Q_in is an iteration variable of the process. When the simulation starts, this variable is very close to zero, but not actually zero, because the Newton algorithm is happy with a very small residual, so the specific enthalpy is still well-defined. However, after some simulation steps, a few more Newton steps are performed, so it eventually reaches machine zero and the solution blows up.

Dymola is slightly smarter, because it understands that the solution is actually constant, so it only computes it once, with Q_in = 1e-15, and doesn't fail. But the solution is still very fragile.

IMHO the fundamental problem here is the connector design with the flow variable H, which is doomed to get singular whenever the flow rate becomes zero. We fought with this problem in the early 2010's for a few years in the Modelica.Fluid design group, until we eventually came up with the stream connector concept, which turned out to be a lot more robust. I would suggest to upgrade the library to use it, even though the task is not completely trivial.

Non-partial models should be balanced

According to the Modelica Language Specification, Section 4.7, models which are not partial should be locally balanced, i.e. containing the same number of equations and variables, assuming certain additional equations are counted for their connectors and boundary conditions.

Partial models are incomplete and cannot be directly instantiated, but they should rather be extended by somehow adding the missing equations, so they may not be balanced (yet).

We understand that the design philosophy of the Metroscope library is that most components still have some degrees of freedom (= missing equations), that are then added at the system level when specifying forward or reverse causality. In general, Modelica compilers are tolerant w.r.t. the balancedness rule, i.e. they would still compile a globally balanced model even though some of its components are not locally balanced. However, in order to avoid ending up scratching one's head to figure out what is the missing equation in a system model, it is good practice to specify how many degrees of freedom do these component models have.

This can be done using the connector input semantics, see Section 4.7 again. If a model has, say, two degrees of freedom, e.g. corresponding to a pressure and an enthalpy variables, it is possible to declare them using these connector input types:

connector InputPressure = input Modelica.Units.SI.Pressure;

InputPressure p;

When doing the equation counting, the Modelica compiler counts one additional equation for each connector input, so it can determine if the model will eventually be balanced once two additional equations are provided, somewhere in the system.

Notice that those two equations may actually involved those two very same variables (the pressure and the enthalpy), but they could also involve other ones. This mechanism was invented to handle the equations of state of fluid models (as explained in the example of the specification) but it can also be used for your purposes.

Most of the models in the library can be fixed in a straightforward way, by just declaring the appropriate input connector variables. However, some problematic model remain, because their intended use is too flexible in some sense. These should be discussed individually

  • Junctions.FlashTank gets overconstrained, because it extends a balanced model and there is no way to make a connector input variable a regular one when extending a model
  • Junctions.PressureConnector: it is not clear to us what purpose it serves and how it can be fixed
  • Multifluid.HeatExchangers.WaterFlueGasesEvaporator: it is not clear who are the degrees of freedom
  • Common.Partial.BasicTransport model looks like a partial model, but then it is instantiated directly in Tests.UnitTests.WaterSteam.PressureLosses.TestSingularPressureLossAndHeatLoss that provides the missing three equations, so we can't declare it as partial

[Sensors] Nominal values in sensors

The nominal values are not defined in the same way in the flow sensor and pressure / temperature sensor :

  • In one case the nominal value is the same as the start.
  • In one case it is assigned a value directly.

I think the first option is better.

MetroscopiaNPP_faulty_withStartValues

After applying PR #22, model MetroscopeModelingLibrary.Tests.SimpleExamples.PowerPlant.MetroscopiaNPP.MetroscopiaNPP_faulty_withStartValues fails during initialization. These are the selected start values, obtained via LOG_NLS:

[1] Real HPReheater.S_deh(start=0, nominal=1)
[2] Real SteamExtraction_Tank.extractedFlow.C_in.H(start=6.27146e+08, nominal=1)
[3] Real SteamExtraction_HP.extractedFlow.C_in.H(start=6.1713e+07, nominal=1)
[4] Real LowPressureTurbine_2.h_out(start=2.1796e+06, nominal=500000)
[5] Real SteamExtraction_LP.mainFlow.C_in.H(start=1.6711e+09, nominal=1)
[6] Real HPpump.h_in(start=888248, nominal=500000)
[7] Real LPpump.rhom(start=993.002, nominal=1)
[8] Real LowPressureTurbine_1.h_out(start=2.63447e+06, nominal=500000)
[9] Real HighPressureTurbine_2.h_out(start=2.65078e+06, nominal=500000)
[10] Real HighPressureTurbine_1.h_out(start=2.72802e+06, nominal=500000)
[11] Real LPpump.h_in(start=163127, nominal=500000)
[12] Real LPpump.P_in(start=6979.75, nominal=100000)
[13] Real PressureLoss_after_drum.P_out(start=1.8319e+06, nominal=100000)
[14] Real Bypass_SH2Cond.P_out(start=90000, nominal=100000)
[15] Real condenser.Tsat(start=312.094, nominal=300)
[16] Real PressureLoss_DryerCondensats2.P_out(start=500006, nominal=100000)
[17] Real Bypass_SHCV2Cond.P_in(start=100000, nominal=100000)
[18] Real FuiteTub_LPReheater.P_in(start=100000, nominal=100000)
[19] Real HPCondReheater_valve.P_out(start=3.1003e+06, nominal=100000)
[20] Real condenser.coldSide.h_out(start=89271.5, nominal=500000)
[21] Real HPCondReheaterControlValve.P_out(start=1.82931e+06, nominal=100000)
[22] Real PressureLoss_SteamExtractionHP2.P_out(start=3.1003e+06, nominal=100000)
[23] Real condenser.coldSide.h_in(start=63182.4, nominal=500000)
[24] Real Bypass_SETank2Cond.P_in(start=100000, nominal=100000)
[25] Real steamDryer.P_in(start=1.93984e+06, nominal=100000)
[26] Real Bypass_SH2Cond.P_in(start=100000, nominal=100000)
[27] Real FuiteTub_HPReheater.P_in(start=100000, nominal=100000)
[28] Real Bypass_SELP2Cond.P_in(start=100000, nominal=100000)
[29] Real Bypass_SEHP2Cond.P_in(start=100000, nominal=100000)
[30] Real condenser.Q_cold(start=4500, nominal=1)
[31] Real Qo_SteamDryer(start=45.7393, nominal=1)
[32] Real PressureLoss_DryerCondensats2.Qm(start=50.9551, nominal=1)
[33] Real HPReheater.Q_cold(start=1011.49, nominal=1)
[34] Real HPCondReheater_valve.Q_out(start=-21.2628, nominal=1)
[35] Real Superheater.Q_cold(start=685.277, nominal=1)
[36] Real PressureLoss_SteamExtractionHP2.Qm(start=43.8847, nominal=1)
[37] Real Qo_WaterSuctionPump(start=685.277, nominal=1)
[38] Real PressureLoss_after_drum.h_out(start=888248, nominal=500000)
[39] Real steamGenerator.steamSource.basicTransport.h_in(start=2.79423e+06, nominal=500000)
[40] Real steamGenerator.steamSource.basicTransport.h_out(start=2.79423e+06, nominal=500000)
[41] Real HPcontrolValve.C_out.h_vol(start=2.79423e+06, nominal=1)
[42] Real HighPressureTurbine_1.C_out.h_vol(start=2.72802e+06, nominal=1)
[43] Real SteamExtraction_HP.C_ext_out.h_vol(start=2.64247e+06, nominal=1)
[44] Real PressureLoss_SteamExtractionHP.C_out.h_vol(start=1.89032e+06, nominal=1)
[45] Real PressureLoss_SteamExtractionHP2.C_out.h_vol(start=1.89032e+06, nominal=1)
[46] Real HPReheater.deheating_hot.C_out.h_vol(start=1.89032e+06, nominal=1)
[47] Real HPReheater.condensing_hot.C_out.h_vol(start=1.01703e+06, nominal=1)
[48] Real HPCondReheaterControlValve.C_in.h_vol(start=928671, nominal=1)
[49] Real PressureLoss_DryerCondensats.C_out.h_vol(start=901588, nominal=1)
[50] Real steamDryer.C_liquid_out.h_vol(start=901588, nominal=1)
[51] Real steamDryer.C_vapor_out.h_vol(start=2.79773e+06, nominal=1)
[52] Real Superheater.CondVap_cold.C_out.h_vol(start=2.79773e+06, nominal=1)
[53] Real Superheater.CondSupH_cold.C_out.h_vol(start=2.8506e+06, nominal=1)
[54] Real Superheater.DesHSupH_cold.h_in(start=2.8506e+06, nominal=500000)
[55] Real Superheater.DesHSupH_hot.h_in(start=2.79423e+06, nominal=500000)
[56] Real Superheater.C_cold_out.h_vol(start=2.8506e+06, nominal=1)
[57] Real LowPressureTurbine_1.C_out.h_vol(start=2.63447e+06, nominal=1)
[58] Real SteamExtraction_LP.h_in(start=2.63447e+06, nominal=1)
[59] Real SteamExtraction_LP.C_ext_out.h_vol(start=2.53475e+06, nominal=1)
[60] Real Bypass_SELP2Cond.h_in(start=100000, nominal=500000)
[61] Real Bypass_SELP2Cond.h_out(start=100000, nominal=500000)
[62] Real SteamExtraction_LP.C_main_out.h_vol(start=2.64248e+06, nominal=1)
[63] Real condenser.hotSide.h_in(start=2.06514e+06, nominal=500000)
[64] Real condenser.incond_out.C_in.h_vol(start=100000, nominal=1)
[65] Real condenser.incond_out.C_out.h_vol(start=100000, nominal=1)
[66] Real PressureLoss_Condenser.C_in.h_vol(start=163127, nominal=1)
[67] Real LPpump.C_in.h_vol(start=163127, nominal=1)
[68] Real PumpControlValve.C_in.h_vol(start=165582, nominal=1)
[69] Real PressureLoss_Condenser.h_out(start=163127, nominal=500000)
[70] Real PressureLoss_Condenser.h_in(start=163127, nominal=500000)
[71] Real condenser.waterHeightPressureLoss.h_out(start=100000, nominal=500000)
[72] Real condenser.waterHeightPressureLoss.h_in(start=100000, nominal=500000)
[73] Real condenser.incond_out.h_out(start=100000, nominal=500000)
[74] Real condenser.incond_out.h_in(start=100000, nominal=500000)
[75] Real PressureLoss_before_drum.h_in(start=306457, nominal=500000)
[76] Real PressureLoss_before_drum.h_out(start=306457, nominal=500000)
[77] Real HPCondReheaterControlValve.C_out.h_vol(start=888248, nominal=1)
[78] Real HPcontrolValve.h_out(start=2.79423e+06, nominal=500000)
[79] Real HighPressureTurbine_1.h_in(start=2.79423e+06, nominal=500000)
[80] Real BypassHPCV2Cond.P_in(start=100000, nominal=100000)
[81] Real HighPressureTurbine_2.C_out.h_vol(start=2.65078e+06, nominal=1)
[82] Real SteamExtraction_HP.C_main_out.h_vol(start=2.73002e+06, nominal=1)
[83] Real SteamExtraction_Tank.C_main_out.h_vol(start=2.67909e+06, nominal=1)
[84] Real PressureLoss_ExhaustHP.C_out.h_vol(start=2.67909e+06, nominal=1)
[85] Real PressureLoss_DryerCondensats1.h_in(start=2.56332e+06, nominal=500000)
[86] Real PressureLoss_DryerCondensats1.h_out(start=2.56332e+06, nominal=500000)
[87] Real PressureLoss_DryerCondensats1.C_in.h_vol(start=2.56332e+06, nominal=1)
[88] Real Bypass_SETank2Cond.h_in(start=100000, nominal=500000)
[89] Real Bypass_SETank2Cond.h_out(start=100000, nominal=500000)
[90] Real PressureLoss_ExhaustHP.h_out(start=2.67909e+06, nominal=500000)
[91] Real PressureLoss_ExhaustHP.h_in(start=2.67909e+06, nominal=500000)
[92] Real SteamExtraction_Tank.mainFlow.h_out(start=2.67909e+06, nominal=500000)
[93] Real SteamExtraction_Tank.h_in(start=2.65078e+06, nominal=1)
[94] Real PressureLoss_SteamExtractionHP.h_in(start=2.64247e+06, nominal=500000)
[95] Real SteamExtraction_HP.mainFlow.h_out(start=2.73002e+06, nominal=500000)
[96] Real HighPressureTurbine_2.h_in(start=2.73002e+06, nominal=500000)
[97] Real SteamExtraction_HP.h_in(start=2.72802e+06, nominal=1)
[98] Real PressureLoss_SteamExtractionHP.h_out(start=2.64247e+06, nominal=500000)
[99] Real HPcontrolValve.h_in(start=2.79423e+06, nominal=500000)
[100] Real HPpump.C_in.h_vol(start=888248, nominal=1)
[101] Real PressureLoss_before_drum.C_in.h_vol(start=306457, nominal=1)
[102] Real PlaqSep_LPReheater.h_out(start=100000, nominal=500000)
[103] Real PlaqSep_LPReheater.h_in(start=100000, nominal=500000)
[104] Real LPReheater.C_cold_in.h_vol(start=165582, nominal=1)
[105] Real LPReheater.condensing_cold.C_out.h_vol(start=306457, nominal=1)
[106] Real FuiteTub_LPReheater.h_in(start=100000, nominal=500000)
[107] Real FuiteTub_LPReheater.h_out(start=100000, nominal=500000)
[108] Real LPCondReheaterControlValve.C_in.h_vol(start=640185, nominal=1)
[109] Real LPReheater.deheating_hot.C_out.h_vol(start=2.53475e+06, nominal=1)
[110] Real LPReheater.C_hot_in.h_vol(start=2.53475e+06, nominal=1)
[111] Real LPCondReheaterControlValve.h_in(start=640185, nominal=500000)
[112] Real LPCondReheaterControlValve.h_out(start=640185, nominal=500000)
[113] Real LPReheater.deheating_cold.h_out(start=306457, nominal=500000)
[114] Real LPReheater.deheating_cold.h_in(start=306457, nominal=500000)
[115] Real LPReheater.condensing_cold.h_out(start=306457, nominal=500000)
[116] Real LPReheater.condensing_cold.h_in(start=165582, nominal=500000)
[117] Real steamDryer.vaporSide.h_in(start=2.67909e+06, nominal=500000)
[118] Real PressureLoss_DryerCondensats.h_in(start=901588, nominal=500000)
[119] Real PressureLoss_DryerCondensats.h_out(start=901588, nominal=500000)
[120] Real LPCondReheaterControlValve.C_out.h_vol(start=2.06514e+06, nominal=1)
[121] Real condenser.incond_in.C_out.h_vol(start=100000, nominal=1)
[122] Real Bypass_SteamGen2Cond.h_in(start=100000, nominal=500000)
[123] Real Bypass_SteamGen2Cond.h_out(start=100000, nominal=500000)
[124] Real BypassHPCV2Cond.h_in(start=100000, nominal=500000)
[125] Real BypassHPCV2Cond.h_out(start=100000, nominal=500000)
[126] Real Bypass_SHCV2Cond.h_out(start=100000, nominal=500000)
[127] Real Bypass_SHCV2Cond.h_in(start=100000, nominal=500000)
[128] Real Bypass_SEHP2Cond.h_out(start=100000, nominal=500000)
[129] Real Bypass_SEHP2Cond.h_in(start=100000, nominal=500000)
[130] Real HPReheater.purge_hot.h_out(start=928671, nominal=500000)
[131] Real HPReheater.purge_cold.h_out(start=897734, nominal=500000)
[132] Real HPReheater.condensing_cold.C_in.h_vol(start=897734, nominal=1)
[133] Real HPReheater.condensing_cold.h_in(start=897734, nominal=500000)
[134] Real HPReheater.condensing_hot.h_in(start=1.89032e+06, nominal=500000)
[135] Real HPReheater.deheating_hot.h_out(start=1.89032e+06, nominal=500000)
[136] Real HPReheater.deheating_cold.h_out(start=935623, nominal=500000)
[137] Real HPReheater.C_cold_in.h_vol(start=893901, nominal=1)
[138] Real FuiteTub_HPReheater.h_in(start=100000, nominal=500000)
[139] Real FuiteTub_HPReheater.h_out(start=100000, nominal=500000)
[140] Real PlaqSep_HPReheater.h_out(start=100000, nominal=500000)
[141] Real PlaqSep_HPReheater.h_in(start=100000, nominal=500000)
[142] Real HPReheater.deheating_cold.C_in.h_vol(start=935623, nominal=1)
[143] Real HPReheater.deheating_hot.h_in(start=1.89032e+06, nominal=500000)
[144] Real PressureLoss_SteamExtractionHP2.h_out(start=1.89032e+06, nominal=500000)
[145] Real PressureLoss_SteamExtractionHP2.h_in(start=1.89032e+06, nominal=500000)
[146] Real HPReheater.condensing_hot.h_out(start=1.01703e+06, nominal=500000)
[147] Real HPReheater.purge_hot.h_in(start=1.01703e+06, nominal=500000)
[148] Real HPReheater.condensing_cold.h_out(start=935623, nominal=500000)
[149] Real HPReheater.deheating_cold.h_in(start=935623, nominal=500000)
[150] Real Bypass_HPR2Cond.h_in(start=100000, nominal=500000)
[151] Real Bypass_HPR2Cond.h_out(start=100000, nominal=500000)
[152] Real Superheater.DesHSupH_cold.h_out(start=2.8506e+06, nominal=500000)
[153] Real Bypass_SH2Cond.h_in(start=100000, nominal=500000)
[154] Real Bypass_SH2Cond.h_out(start=100000, nominal=500000)
[155] Real Bypass_SD2Cond.h_in(start=100000, nominal=500000)
[156] Real Bypass_SD2Cond.h_out(start=100000, nominal=500000)
[157] Real steamDryer.h_in(start=2.67909e+06, nominal=1)
[158] Real steamDryerValve.h_in(start=901588, nominal=500000)
[159] Real steamDryerValve.h_out(start=901588, nominal=500000)
[160] Real steamDryer.liquidSide.h_in(start=2.67909e+06, nominal=500000)
[161] Real SuperHeaterControlValve.h_in(start=2.79423e+06, nominal=500000)
[162] Real SuperHeaterControlValve.h_out(start=2.79423e+06, nominal=500000)
[163] Real SuperHeaterControlValve.C_in.h_vol(start=2.79423e+06, nominal=1)
[164] Real LowPressureTurbine_1.h_in(start=2.8506e+06, nominal=500000)
[165] Real LowPressureTurbine_2.h_in(start=2.64248e+06, nominal=500000)
[166] Real SteamExtraction_LP.mainFlow.h_out(start=2.64248e+06, nominal=500000)
[167] Real PressureLoss_DryerCondensats2.h_out(start=2.53475e+06, nominal=500000)
[168] Real LPReheater.deheating_hot.h_in(start=2.53475e+06, nominal=500000)
[169] Real LPReheater.condensing_hot.h_in(start=2.53475e+06, nominal=500000)
[170] Real PressureLoss_DryerCondensats2.h_in(start=2.53475e+06, nominal=500000)
[171] Real Superheater.CondSupH_cold.h_in(start=2.79773e+06, nominal=500000)
[172] Real Superheater.CondSupH_hot.h_in(start=2.79423e+06, nominal=500000)
[173] Real Superheater.C_hot_in.h_vol(start=2.79423e+06, nominal=1)
[174] Real Superheater.CondSupH_hot.C_out.h_vol(start=1.0901e+06, nominal=1)
[175] Real Superheater.CondVap_hot.h_in(start=1.0901e+06, nominal=500000)
[176] Real Superheater.CondVap_cold.h_in(start=2.79773e+06, nominal=500000)
[177] Real Superheater.CondVap_cold.h_out(start=2.79773e+06, nominal=500000)
[178] Real Superheater.CondSupH_hot.h_out(start=1.0901e+06, nominal=500000)
[179] Real Superheater.CondSupH_cold.h_out(start=2.8506e+06, nominal=500000)
[180] Real LPpump.Qv0(start=0.690107, nominal=1)
[181] Real PumpControlValve.h_out(start=165582, nominal=500000)
[182] Real PumpControlValve.h_in(start=165582, nominal=500000)
[183] Real condenser.incond_in.h_out(start=100000, nominal=500000)
[184] Real condenser.incond_in.h_in(start=100000, nominal=500000)
[185] Real coldSink.basicTransport.h_out(start=89271.5, nominal=500000)
[186] Real condenser.C_cold_out.h_vol(start=89271.5, nominal=1)
[187] Real coldSource.C_out.h_vol(start=63182.4, nominal=1)
[188] Real coldSource.basicTransport.h_in(start=63182.4, nominal=500000)
[189] Real FuiteTub_SuperHeater.h_in(start=100000, nominal=500000)
[190] Real FuiteTub_SuperHeater.h_out(start=100000, nominal=500000)
[191] Real HPCondReheaterControlValve.h_out(start=928671, nominal=500000)
[192] Real HPCondReheaterControlValve.h_in(start=928671, nominal=500000)
[193] Real PressureLoss_SteamExtractionHP1.C_out.h_vol(start=1.0901e+06, nominal=1)
[194] Real Superheater.C_hot_out.h_vol(start=1.0901e+06, nominal=1)
[195] Real steamGenerator.waterSupplySink.h_in(start=935623, nominal=500000)
[196] Real HPReheater.C_cold_out.h_vol(start=935623, nominal=1)
[197] Real steamGenerator.waterSupplySink.basicTransport.h_out(start=935623, nominal=500000)
[198] Real steamGenerator.waterSupplySink.basicTransport.h_in(start=935623, nominal=500000)
[199] Real PressureLoss_SteamExtractionHP1.h_in(start=1.0901e+06, nominal=500000)
[200] Real PressureLoss_SteamExtractionHP1.h_out(start=1.0901e+06, nominal=500000)
[201] Real HPCondReheater_valve.h_in(start=1.0901e+06, nominal=500000)
[202] Real HPCondReheater_valve.h_out(start=1.0901e+06, nominal=500000)
[203] Real HPpump.Qv0(start=1.18118, nominal=1)
[204] Real HPReheater.purge_cold.h_in(start=893901, nominal=500000)

Some of them are still at their default values, e.g.

[189] Real FuiteTub_SuperHeater.h_in(start=100000, nominal=500000)

This is because the set of tearing variables selected by Dymola is not the same as the one by OMC. BTW, note that even Dymola could change the selection from one version to the next, if the tearing algorithm is updated.

Partial models should be placed in separate packages

It is common practice in Modelica libraries (although not mandatory) to put all partial models in separate packages, usually named BaseClasses. In the Metroscope library, they are found together with usable models, e.g. BoundaryConditions.PartialBoundaryCondition. This can be a bit confusing to people using the library to drag-and-drop components into a system model.

Of course doing this would create a non-backwards compatible library. Automatic conversion scripts could be prepared to make the transition smooth. It is up to you to decide if this is worth the trouble (maybe not).

MetroscopiaNPP_direct doesn't work in Dymola either

We tested MetroscopeModelingLibrary.Tests.SimpleExamples.PowerPlant.MetroscopiaNPP.MetroscopiaNPP_direct in Dymola 2022, and it fails during initialization. Did it work with previous versions of the tool?

Icon annotations appearing multiple times in some models

Dymola pedantic check reports that some models have multiple Icon annotations, which is not compliant to the standard and may create problems in other tools. See Common.Sensors.BaseSensors.BaseFlowSensor and Common.Sensors.BaseSensors.BaseDifferenceSensor.

We should check if both contain relevant graphical features and merge them, or else just keep one of them.

Model TestSuperheater_PartialCondensation fails

The situation is the same as in #12:

[ 1]             sink_hot_Cond.Q_in  =              500		 nom =                1
[ 2] source_hot_mainSt.basicTransport.h_out  =           100000		 nom =           500000
[ 3]  Superheater.DesHSupH_hot.h_in  =           100000		 nom =           500000
[ 4]  Superheater.CondSupH_hot.h_in  =           100000		 nom =           500000
[ 5] Superheater.CondSupH_hot.C_out.h_vol  =           100000		 nom =                1
[ 6] source_hot_mainSt.basicTransport.h_in  =           100000		 nom =           500000
[ 7]   Superheater.CondVap_hot.h_in  =           100000		 nom =           500000
[ 8] Superheater.CondSupH_hot.h_out  =           100000		 nom =           500000
[ 9]    Superheater.C_hot_out.h_vol  =           100000		 nom =                1
[10] sink_hot_Cond.basicTransport.h_in  =           100000		 nom =           500000
[11] sink_hot_Cond.basicTransport.h_out  =           100000		 nom =           500000

the start values for the enthalpy are all set at the default of 100000, which is too low for steam. Also the start value for Q at 500 is probably quite far off.

Additionally, some nominal values are incorrectly set to 1. This is probably not so important, since max(x.start, x.nominal) is used for scaling, but it could have some effect on the solver's ability to converge from a problematic initialization. Questionable selection of nominal attributes during alias elimination by OMC is probably involved.

Add package and model icons

Dymola adds some icons to packages and models without any by default, while OMC doesn't. The specification doesn't say anything about default icons, so the Dymola behaviour is somewhat questionable.

The right approach is to have all package models, and I'd say also models that can be simulated, to extend the appropriate classes from Modelica.Icons.

Replaceable medium models should have the proper constraining class

All water component models in the library contain code as

  replaceable package water =
      MetroscopeModelingLibrary.WaterSteam.Medium.WaterSteamMedium;

This code means that it is later possible to redeclare water to be a subtype of WaterSteamMedium, i.e., some medium that inherits from it, so you can add stuff, but not really change it. I guess what you want instead is to be able to use different water media. One way to do this is to write

  replaceable package water =
      MetroscopeModelingLibrary.WaterSteam.Medium.WaterSteamMedium
      constrainedby Modelica.Media.Interfaces.PartialTwoPhaseMedium;

which declares the pool of candidates to be all two-phase medium models - you get them in the drop-down menu. However, that also includes stuff like R134a, that you may not want to see. To address this issue, you can define a base class for water media in your library, e.g.

 partial package BaseWaterSteamMedium
   extends Modelica.Media.Interfaces.PartialTwoPhaseMedium;

then have all of the water medium packages in your library extend from it, and then use it as constraining class inside the component.

I would also suggest to use capital letters (as in Water) for package names, following the Conventions of the Modelica Standard library. This is of course a matter of style, so it's not strictly necessary to do that.

Rename variables of the sources and sinks

  • Delete the PartialBoundaryConditions
  • In the sink model, use _in for all quantities
  • In the source model, use _out for all quantities
  • shouldn't the source also have initialization parameters for h,P,Q,T ?

Model TestStodolaTurbine fails in OpenModelica

The simulation of model MetroscopeModelingLibrary.Tests.UnitTests.WaterSteam.Machines.TestStodolaTurbine in OpenModelica fails during initialization.

The Newton solver fails while trying to solve system 35, which has the following iteration variables:

[1] Real stodolaTurbine.C_out.H(start=5e+07, nominal=1)
[2] Real stodolaTurbine.h_in(start=2.7e+06, nominal=500000)
[3] Real stodolaTurbine.P_out(start=5.5e+06, nominal=100000)
[4] Real source.C_out.h_vol(start=100000, nominal=1)
[5] Real stodolaTurbine.C_out.h_vol(start=100000, nominal=1)

The start values are obviously inadequate, in particular the specific enthalpies are in the range of liquid water instead of steam, and C_out.H has the wrong sign, and an arbitrary value of 50 MW.

The same considerations put forth in #15 apply, in particular a redesign of connectors using stream variables would probably be helpful.

BasicTransportModel should be redesigned

In case stream connectors are introduced, BasicTransportModel should be redesigned, since its internal equations will be completely different. At that point one could consider making it "more modular" by adding components and defining extended versions of it, so that balanced models can be used;

Metroscopia_NPP models without start values fail during intialization using OpenModelica

After merging in PR #22, all non-partial (see #18) models in the MetroscopiaNPP compile successfully, then fail during initialization.

The reason is always the same: the set of selected tearing variables contains specific enthalpies with very off-the-mark start values, as well as enthalpy flows with extremely off-the-mark values (even with the wrong sign).

There are two possible ways to fix this problem

Add proper start values

Add h_start, Q_start parameters to all components, and use them to properly set the start attributes of enthalpy and flows throughout the model. This requires "reasonable" values to be input for those parameters i all models. For specific enthalpies, reasonable defaults could be provided as a function of the phase (liquid, 2-phase, superheated steam). For flow rates, this really depends on the size of the plant, there is no one-fits-all default.

This solution allows not to change the equations of the models, but it probably requires to provide meaningful values to all those parameters, thus making all existing system models invalid, because they don't. Also, it is well-known from the days of the Fluid Group of the Modelica Association that the solution using enthalpy flow is numerically fragile, also and specifically in case of zero or reversing flows, see discussion in #14.

Change the ports to use stream variables

This is a more robust solution, but may require significant changes to the equations of several components, because the way to write balance equations and property computation in a robust way is completely different.

In any case, having proper start values for enthalpies and mass flow rate would help a lot, even in case stream variables are used, so I would introduce them anyway.

We propose the following steps:

  1. Add parameters for hstart and Qstart to all components
  2. Adapt the current models to compute proper start values for potential iteration variables
  3. Switch to stream connectors

Steps 1. and 2. are less demanding, and step 1. is needed anyway for step 3. All these options are beyond the scope of the current contract.

[Local balance] FluidSinks are not locally balance

Currently, sinks are not locally balanced if we keep the no flow reversal equations in its code :

  C_in.h_outflow = 0; // Never used arbitrary value
  C_in.Xi_outflow = zeros(Medium.nXi); // No flow reversal

But if we remove them we have to put them in every model using a sink as for h_vol before

Non-standard or invalid annotations should be removed

The library currently contains many instance of the following annotations:

  • Placement annotations outside of the proper context (graphical annotations)
  • Window annotations, which are not in the Modelica Language Specification
  • empty DymolaStoredError annotations, which are also not in the language specification

In all likelyhood these are all leftovers generated by previous versions of Dymola, and can be safely removed. We are investigating with Dassault Systèmes what is/was the purpose of the Window annotation, maybe is served some useful purpose, and in that case we hope this can now be handled by proper vendor-specific annotations, e.g. __Dymola_Window, which would instead be compliant with the standard.

Start values are directly applied in MetroscopiaNPP

Models such as MetroscopeModelingLibrary.Tests.SimpleExamples.PowerPlant.MetroscopiaNPP.MetroscopiaNPP_direct_withStartValues sets start values directly on individual variables. There are two problems with this approach.

The first is that the set of tearing variables depends on the tearing algorithm, so different tools may require start attributes on different variable sets. The second is that some of those values are correlated.

One could define some parameters (e.g. T_start, p_start) in the models, and then set start attributes based on them, so the number of inputs from the end user is reduced.

Change string parameter "monophasic_counter_current" for "shell_and_tube"

Eq for shell and tube HX has been modified. Until now, shell & tube comp were using a counter-current HX eq. To match the correct config, the string parameter leading to the shell & tube eq must be "shell_and_tube" and no longer "monophasic_counter_current".

The change must be done in :

  • Power.HeatExchange.NTUHeatExchange
  • all the watersteam components modelling shell & tube HX.

OpenSteamGenerator contains connectors with unredeclared medium package

MetroscopeModelingLibrary.WaterSteam.HeatExchangers.OpenSteamGenerator instantiates fluid port connectors without redeclaring their Medium models. Hence, they remain declared with Medium = Modelica.Media.Interfaces.PartialMedium. Dymola accepts this and looks for the required information in the partial class; if it finds it, it goes on silently.

However, this is not compliant to the Modelica Specification, Section 5.3.2, which explicitly forbids instantiating classes from within partial classes.

The class we look inside shall not be partial in a simulation model.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.