ibpsa / project1-boptest

Building Optimization Performance Tests
Other
107 stars 69 forks source link

Recompile wrapper.fmu #653

Closed fsievers93 closed 1 month ago

fsievers93 commented 3 months ago

Hi there, I am trying to recompile the MultiZoneResidentialHydronic testcase with an explitcit time stepping scheme. as far as I understood, I need to generate the FMU from the wrapped.mo file: project1-boptest//testcases/multizone_residential_hydronic/models/wrapped.mo

At first, I thought I'd need to use the compile_fmu.py. However, this requires the pymodelica libraray, which seems to be quite outdated and is not available on pip or conda. Is there an other way to get it? I also couldn't find a gitRepo. The other option, that I see, is OpenModelica. Here I encountered the issue that I could not find the in MultiZoneresidentialHydronic/package.mo referenced Construciton and ARTEMIS library. Trying to generate the FMU without those libraries results in the following errors:

""" [326] 14:22:21 Translation Error [Buildings.Fluid.Sources.BaseClasses.Outside: 83:22-109:86]: Variable weaBus.TDryBul not found in scope Outside.

[327] 14:22:44 Scripting Error [AppData/Roaming/.openmodelica/libraries/Buildings 8.0.0/Fluid/Sensors/MassFlowRate.mo:20:7-31:97:writable] Error: No matching function found for String(/Real/ mod.pumEmiSystem.senMasFlo.m_flow, leftjustified = /Boolean/ false, significantDigits = /Integer/ 3). Candidates are: String(enumeration(:) $e, Integer minimumLength = 0, Boolean leftJustified = true) => String String(Integer $i, Integer minimumLength = 0, Boolean leftJustified = true) => String String(Boolean $b, Integer minimumLength = 0, Boolean leftJustified = true) => String String(Real $r, Integer significantDigits = 6, Integer minimumLength = 0, Boolean leftJustified = true) => String String(Real $r, String format) => String .... [348] 14:26:49 Translation Error Initialization problem is structural singular. Please, check the initial conditions.

[352] 14:26:49 Translation Error Internal error IndexReduction.pantelidesIndexReduction failed! System is structurally singular and cannot be handled because the number of unassigned equations is larger than the number of states. Use -d=bltdump to get more information.

[353] 14:26:49 Translation Error Internal error Transformation Module PFPlusExt index Reduction Method Pantelides failed!

[354] 14:26:49 Translation Error [C:/OM123/OM64bit/OMCompiler/Compiler/SimCode/SimCodeUtil.mo: 4689:9-4689:59]: Internal error function createStateSetsSets failed.

[355] 14:26:49 Translation Error [C:/OM123/OM64bit/OMCompiler/Compiler/SimCode/SimCodeUtil.mo: 803:5-803:146]: Internal error function createSimCode failed [Transformation from optimised DAE to simulation code structure failed] """

It would be awesome, if you could give me a hint on how to get it up running. Thanks a lot in advance!

dhblum commented 3 months ago

You can compile the wrapped.fmu using the JModelica-based Docker container we use for unit testing. The Dockerfile is here: https://github.com/ibpsa/project1-boptest/blob/master/testing/Dockerfile. The target for it's use to compile models in the testing makefile is here: https://github.com/ibpsa/project1-boptest/blob/master/testing/makefile#L66C1-L66C23.

Basically, you can re-compile any test case in the repo by $ cd testing, then make compile_testcase_model TESTCASE=<test case name>. That will use the parsing/parser.py and the testcases/<test case name>/models/compile_fmu.py scripts to compile the FMU.

Hope that helps give you ideas.

Just curious, so are you looking to recompile the FMU using explicit euler? You'd have to change the relevant lines in parsing/parser.py, which ultimately compile the FMU, to specify a new solver.

dhblum commented 3 months ago

Ah one correction in the above. To re-compile any test case in the repo, be sure to build the Docker container first by $ cd testing, then $ make build_jm_image.

fsievers93 commented 2 months ago

Thanks for aswer and "Yes" I'd like to run the fmu with the "ExplicitEuler" solver. Unfortunately, it's not quite working yet.

When I posted that quetion, I thought I only need to change the solver in: testcases/multizone_residential_hydronic/models/MultiZoneResidentialHydronic/TestCase.mo because it was the only place wher it was specified. However recompiling the testcase afterwards didn't change anything.

Setting fmu.simulate_options()['solver']="ExplicitEuler" in testcase.py selected the solver I wanted, but initialising the simulation still throws an error.

ERROR Failed to initialize test simulation: Traceback (most recent call last): boptest-1 | File "/home/developer/testcase.py", line 172, in __simulation boptest-1 | input=input_object) boptest-1 | File "src/pyfmi/fmi.pyx", line 7573, in pyfmi.fmi.FMUModelME2.simulate boptest-1 | File "src/pyfmi/fmi.pyx", line 301, in pyfmi.fmi.ModelBase._exec_simulate_algorithm boptest-1 | File "src/pyfmi/fmi.pyx", line 297, in pyfmi.fmi.ModelBase._exec_simulate_algorithm boptest-1 | File "/usr/local/JModelica/Python/pyfmi/fmi_algorithm_drivers.py", line 552, in solve boptest-1 | self.simulator.simulate(self.final_time, self.ncp) boptest-1 | File "assimulo/ode.pyx", line 168, in assimulo.ode.ODE.simulate boptest-1 | File "assimulo/ode.pyx", line 288, in assimulo.ode.ODE.simulate boptest-1 | File "assimulo/explicit_ode.pyx", line 101, in assimulo.explicit_ode.Explicit_ODE._simulate boptest-1 | File "assimulo/explicit_ode.pyx", line 187, in assimulo.explicit_ode.Explicit_ODE._simulate boptest-1 | File "assimulo/solvers/euler.pyx", line 553, in assimulo.solvers.euler.ExplicitEuler.integrate boptest-1 | File "assimulo/solvers/euler.pyx", line 589, in assimulo.solvers.euler.ExplicitEuler.integrate boptest-1 | File "assimulo/explicit_ode.pyx", line 303, in assimulo.explicit_ode.Explicit_ODE.event_locator boptest-1 | File "assimulo/solvers/euler.pyx", line 531, in assimulo.solvers.euler.ExplicitEuler.set_problem_data.event_func boptest-1 | File "/usr/local/JModelica/Python/pyfmi/simulation/assimulo_interface.py", line 781, in g boptest-1 | eventInd = self._model.get_event_indicators() boptest-1 | File "src/pyfmi/fmi.pyx", line 7299, in pyfmi.fmi.FMUModelME2.get_event_indicators boptest-1 | FMUException: Failed to get the event indicators at time: 2.592000E+07.

So it seems like I am missing something. What is it that I have to change in parsing/parser.py?

dhblum commented 2 months ago

https://github.com/ibpsa/project1-boptest/blob/master/parsing/parser.py#L182 is where the compile_fmu function from pymodelica is called to compile the wrapped.fmu.

fsievers93 commented 2 months ago

Ah ok thx. I didnt realize that I was still using an older version of the repo where you were using type="me" for the fmu build and you did the integration with pyfmi. In the current verison you use type="cs". I tried it with both versions. However, it doesn't seem to work with Euler. Calling the initialize-endpoint always results in the error posted above.

dhblum commented 2 months ago

Thanks for reporting. I'm sorry I haven't done any testing with that model using Euler as a solver.

fsievers93 commented 2 months ago

No, worries. In the end, it's a stiff problem and Euler is not the right method. I just wanted to check by how far it is off, as CVode was running into too small timesteps with a custom control input.

dhblum commented 2 months ago

What do you mean by "CVode was running into too small timesteps?" Are you getting the Failed To Initialize error with CVode? If so, what time are you initializing the simulation to and what is your custom control input? I'd like to know more to see if there's an issue with the model that needs to be addressed.

fsievers93 commented 2 months ago

With CVode the initialisation works fine. Only for some of the control input from my MPC I am running into issues. When the timestep is getting too smal t' = t+h; h->0, which results in t'==t. This can happen when integrating over discontinuities, but reducing the time step to 30 seconds should resolve that problem, as I integrate only inbetween discontinuities. However, I still ran into the same problems. The control inputs I am using are: boi_oveBoi_u, conHeaBth_oveActHea_u, conHeaLiv_oveActHea_u, conHeaRo1_oveActHea_u, conHeaRo2_oveActHea_u, conHeaRo3_oveActHea_u, oveEmiPum_u, oveMixValSup_u. Exmaple inputs that lead to the issue described above are: [0.85822387, 0.13129965, 1. , 1. , 0.22337468, 0.10093482, 0.00403944, 0.23338267]

dhblum commented 2 months ago

So are you setting the pump control signal to 0.00403944? This is a very small number but not zero, which might be causing some numerical instabilities in the flow network with such small flow and pressure rise. This is really just a guess, but could you try setting a lower limit on the pump control signal to, say 0.1, if not 0?

fsievers93 commented 2 months ago

The normal range from the pump is 0 to 0.25. Therefore,i build in a np.maximum(0.01, u), but this didnt change anything tho. My guess was that there are two issues.

  1. When you turn on the boiler you need to turn on the pump at some point.
  2. When you turn on the boiler you need to set the mix-valve in a position that the boiler is getting more water.

Adding a line which forced the pump to be at least 0.05 when the boiler is on, makes it run through most of the times. Adding an additional line to set the mix valve signal equal to boiler signal fixes the second issue, and the simulation runs through. It seems to fix most of the issues, but do you think the reason is correct?

dhblum commented 2 months ago

@EttoreZ can you help address @fsievers93 's issue?

EttoreZ commented 2 months ago

dear @fsievers93 going through your post:

  1. The boiler and the pump are controlled in the same way (error between Tset_living and Tliving), with two different PIs and slightly different coefficients, so their trends should be pretty much aligned.
  2. There should be a safety on the boiler maximum temperature, but the solver may struggle to find a solution on the safety loop when flow rate is very small. This causes the temperature in the boiler volume to go above 100 (threshold for water) crashing the simulation.

Your solution reinforces my thinking that 2. could be the case. One solution to this problem is to add a small delay to boiler on signal so that the pump can start without problems. Furthermore, currently the flow rate to the radiators is controlled by both the variable speed pump and by the mixing valve tracking respectively the supply temperature setpoint. To make the system a bit more simple from a numerics standpoint, I would suggest converting the pump to "ON" or "OFF" based on boiler signal, while keeping the mixing valve to track supply temperature to the radiators. However, the pump signal would remain accessible as control signal for more advanced control strategies, so a warning may be added to the documentation mentioning that if pump signal is overwritten and boiler is running it may crash the simulation (this is a situation that should never happen in reality anyways). @dhblum what do you think?

dhblum commented 1 month ago

Closed by https://github.com/ibpsa/project1-boptest/pull/667.