Opened 4 years ago
Closed 4 years ago
#6160 closed defect (invalid)
FMU behaviour depending on library style
Reported by: | Owned by: | Andreas Heuermann | |
---|---|---|---|
Priority: | high | Milestone: | 1.17.0 |
Component: | FMI | Version: | v1.17.0-dev |
Keywords: | FMU PyFMI Python | Cc: |
Description
We created a toolbox for the simulation of microgrids.
In the first run, everything was just written in a single ".mo" file, in this case grid.mo. Not really structured and pretty slow, since a really big file needs to be changed with every action.
The following file of a older branch shows the structure of the old model:
Later on, we followed the example of many other OpenModelica libraries, and made a library out of it, which is structured in many different files and folders, which are connected to each other. Way faster, tidier, and looks better.
The package.mo file opens the library:
Problem:
Creating a FMU (2.0, ME) from both versions works totally fine, simulating it in python works with identical results, except one point:
After the strucure change, it is not possible to change parameters anymore via PyFMI. The value itself gets changed, which is visible by plotting the direct value (for example something like resistor1.R). But for the simulation results (like currents, voltages), the default value which was set in OpenModelica is used.
The main difference - at least for my point of view - is that not all ODEs are in the same folder, and something with the parametertransfer between the different folders goes wrong, but this is just an absolutely blind guess.
If anyone knows more about the topic, or even has a solution for us that we could keep on using the new, structured library, please let me know :-)
Best Regards!
Henrik
Attachments (8)
Change History (17)
comment:1 by , 4 years ago
Owner: | changed from | to
---|---|
Status: | new → assigned |
comment:2 by , 4 years ago
We set the params with the set-function:
def set_params(self, **kwargs): self.model.initialize() self.model.set(*zip(*kwargs.items()))
The model.initialize before every set of the params solved a similar issue for the first time. At the very first beginning, we used
model.enter_initialization_mode() model.exit_initialization_mode()
just at the very beginning of the simulation, but only with model.initialize before every parameterchange, the new value was used for the simulation. Otherwise, only the deafault value set in openmodelica was used, like it it the problem here.
right now, the only import tool we was pyfmi, but i try to create an other version with fmpy this afternoon.
At first, I was using the the nightly 1.17 (freshly installed last thursday), for testing purposes i went down to OpenModelica v1.16.0-dev.beta1 (64-bit). with the 1.16, it shows the same behaviour on windows 10, manjaro and kubuntu.
I uploaded the two fmu files we use as default, one working and one which is not working.
The parameter is definitive changeable. No errors from pyfmi while trying, and when I plot the changed parameter over time, the changed, new value is shown in the result. But this value just has no effect on the rest of the simulation. A doubled resistor should for example the reduce the current through it. The value of the resistor decreases, but the value of the current stays the same.
comment:3 by , 4 years ago
What variable are you trying to change? What is the name of it in both FMUs?
A few parameters are missing in the new modelDescription.xml:
rl1.resistor1.T
, rl1.resistor1.T_heatPort
, rl1.resistor1.T_ref
,rl1.resistor1.alpha
, rl1.resistor2.T
, rl1.resistor2.T_heatPort
, rl1.resistor2.T_ref
,rl1.resistor2.alpha
,
rl1.resistor3.T
, rl1.resistor3.T_heatPort
, rl1.resistor3.T_ref
,rl1.resistor3.alpha
,
rl1.resistor1.useHeatPort
, rl1.resistor2.useHeatPort
, rl1.resistor3.useHeatPort
.
To see why I would need to check the sources or much better a minimal working example.
by , 4 years ago
Attachment: | OpenModelica_Microgrids.Grids.Network2.fmu added |
---|
new format for minimal example
comment:4 by , 4 years ago
Oooops, sorry Andreas, I just noticed that the text I wrote didn´t appear in here, just the files I attached!
I try to change the resistance values of the resistors, for example "rl1.resistor1.R". Since we don´t take care of any temperature effects, all thermal values don´t affect our simulation, and they don´t exist in both fmu´s, since in both library, the same resistor without thermal characteristics are taken.
I created a minimal example. The simple euler forward is not designed for a case like this, but it keeps the program easy and straight forward, and you can see everything which is somehow faulty. Although the value of the resistor in the new library changes, stays the current the same. With the old library, you can see how the current is supposed to look like, just comment/uncomment line 12 or 13.
I really hope you know the reason and can tell us how to fix this issue :-)
import pylab as P import numpy as N from pyfmi import load_fmu def run_demo(with_plots=True): # Model selection: first one is the old library, which is working, # second one is the new library, which uses for the calculation the default value of 20 Ohm #model = load_fmu('grid.network2.fmu') model = load_fmu('OpenModelica_Microgrids.Grids.Network2.fmu') Tstart = 0.0 # Tend = 0.05 dt = 0.000001 # really small steps to stabilize the euler forward solver, which is chosen for simplicity in this example. # works, but leads to noisy results, which don´t matter in this showcase model.initialize() time = Tstart model.enter_continuous_time_mode() x = model.continuous_states #Initial set of resistor to see if there is a change at all #10 Ohm should leat to a peak current of about 32 A, while 20 Ohm results in about 16 A model.set('rl1.resistor1.R', 10) vref = [model.get_variable_valueref('rl1.resistor1.i')] vref2 = [model.get_variable_valueref('rl1.resistor1.R')] t_sol = [Tstart] sol = [model.get_real(vref)] sol2 = [model.get_real(vref2)] while time < Tend: if time > Tend/2: # loadchange for visualisation after half the simulation model.set('rl1.resistor1.R', 5) dx = model.get_derivatives() time = time + dt model.time = time x = x + dt * dx model.continuous_states = x t_sol += [time] sol += [model.get_real(vref)] sol2 += [model.get_real(vref2)] if with_plots: P.figure(1) P.plot(t_sol, N.array(sol)[:, 0]) P.title(model.get_name()) P.ylabel('Current at Resistor1 (A)') P.xlabel('Time (s)') P.figure(2) P.plot(t_sol, N.array(sol2)[:, 0]) P.title(model.get_name()) P.ylabel('Resistor1 (Ohm)') P.xlabel('Time (s)') P.show() if __name__ == "__main__": run_demo()
comment:5 by , 4 years ago
The variable rl1.resistor1.R
is a fixed parameter for both FMUs.
<ScalarVariable name="rl1.resistor1.R" valueReference="167" description="Resistance at temperature T_ref" variability="fixed" causality="calculatedParameter" > <Real unit="Ohm"/> </ScalarVariable>
From the FMI specification:
"fixed": The value of the variable is fixed after initialization, in other words, after fmi2ExitInitializationMode was called the variable value does not change anymore.
So you need to change the value to the parameter after fmi2EnterInitializationMode
and before fmi2ExitInitializationMode
was called.
Doing something like this hould work:
[...] model.initialize() time = Tstart model.set('rl1.resistor1.R', 10) model.enter_continuous_time_mode() [...]
I haven't tested it though (I can't install pyfmi).
But in any case it should not be a difference how the model is written (with or without a library structure).
comment:6 by , 4 years ago
PyFMI can´t be installed for soem reasons via pip, but an installation via condaforge works fine.
conda install -c conda-forge pyfmi
I tried it in the way you suggested, but it has no influence at all.
Same old value of 20 Ohm is used for the whole simulation.
But well, since everything else is absolutely identical, the difference must be somewhere there.
comment:7 by , 4 years ago
So just to be sure I tested with OMSimulator:
oms_setTempDirectory("./temp/") oms_newModel("model") oms_addSystem("model.root", oms_system_sc) -- instantiate FMUs oms_addSubModel("model.root.oldFMU", "grid.network.fmu") oms_addSubModel("model.root.mewFMU", "omg_grid.Grids.Network.fmu") -- simulation settings oms_setResultFile("model", "results.mat") oms_setStopTime("model", 1) oms_setFixedStepSize("model.root", 1e-4) oms_instantiate("model") oms_setReal("model.root.oldFMU.rl1.resistor1.R", 10) oms_setReal("model.root.mewFMU.rl1.resistor1.R", 10) oms_initialize("model") oms_simulate("model") oms_terminate("model") oms_delete("model")
and get:
# /c/Program\ Files/OpenModelica1.17.0-dev-64bit/bin/OMSimulator.exe runTest.lua info: Set temp directory to "D:/workspace\Testitesttest\tickets\ticket6060" info: Set working directory to "D:/workspace\Testitesttest\tickets\ticket6060" info: New temp directory has been created: "./temp/" info: Set temp directory to "./temp" info: New model "model" with corresponding temp directory "./temp\model-tctv295w" warning: It is not allowed to provide a start value if initial="calculated" or causality="independent". warning: It is not allowed to provide a start value if initial="calculated" or causality="independent". info: maximum step size for 'model.root': 0.100000 info: Result file: results.mat (bufferSize=1) info: Final Statistics for 'model.root': NumSteps = 12 NumRhsEvals = 13 NumLinSolvSetups = 3 NumNonlinSolvIters = 12 NumNonlinSolvConvFails = 0 NumErrTestFails = 0 info: 2 warnings info: 0 errors
So it is simply not allowed to change the value of `rl1.resistor1.R. Compare with the FMI specification 2.2.7 Definition of Model Variables (ModelVariables)
Without looking at the source code I would guess that the parameter R
is dependent of some other parameter. If you want to change R
you have to find that one and change it accordingly.
comment:8 by , 4 years ago
Since the models are absolutely identical, it makes no sense that R is in one case dependent on something else. It also makes no sense from an engineering point of view :-(
Did I see it right that the warning is the same for both models, the working one and the broken one?
comment:9 by , 4 years ago
Resolution: | → invalid |
---|---|
Status: | assigned → closed |
Did I see it right that the warning is the same for both models, the working one and the broken one?
Yes. It should not work in any cases and FMPy is not behaving correctly for those FMUs or not reporting errors / warnings.
But I can't see a problem for the FMU export from OpenModelica. So I'm closing this issue for now. If you have further problems please ask in the forum or open a new ticket.
How exactly are you changing the parameters in PyFMI? And did you try to do the same with a different FMI importing tool?
Which version of OMC (
omc --version
) are you using and on what OS?Can you upload an example FMU that shows this behavior?
If PYFMI just uses
fmi2SetXXX
to change values it shouldn't make a difference.Maybe the parameter you want to change isn't changeable any more? Look into the modelDescription.xml for the specific parameter.