Opened 4 years ago
Last modified 3 years ago
#6080 new defect
Changing parameters of a model via Python
Reported by: | Owned by: | Lennart Ochel | |
---|---|---|---|
Priority: | high | Milestone: | |
Component: | FMI | Version: | v1.16.0-dev |
Keywords: | Cc: |
Description
I created a minimal example (DC-Voltage, Load) in OpenModelica. Afterwards, I created an FMU and used it via Python.
Problem summary: By using just a Resistor as a load, i can´t change the parameters via python. After adding an Inductor to the model, I can change some parameters and the simulation reacts to this changes.
In this simple model, there is nothing which could cause troubles from the electrical engineering part, the problem must be somewhere else.
Model Set-up
Problematical Model:
model testbench parameter Real v_DC (start = 100); Modelica.Blocks.Sources.RealExpression realExpression(y = v_DC) annotation( Placement(visible = true, transformation(origin = {-70, 70}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); Modelica.Electrical.Analog.Sources.SignalVoltage signalVoltage annotation( Placement(visible = true, transformation(origin = {-30, 46}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); Modelica.Electrical.Analog.Basic.Resistor resistor(R = 10) annotation( Placement(visible = true, transformation(origin = {-30, 14}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); Modelica.Electrical.Analog.Basic.Ground ground annotation( Placement(visible = true, transformation(origin = {28, 28}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); equation connect(realExpression.y, signalVoltage.v) annotation( Line(points = {{-58, 70}, {-30, 70}, {-30, 58}, {-30, 58}}, color = {0, 0, 127})); connect(signalVoltage.n, resistor.n) annotation( Line(points = {{-20, 46}, {-6, 46}, {-6, 14}, {-20, 14}, {-20, 14}}, color = {0, 0, 255})); connect(signalVoltage.n, ground.p) annotation( Line(points = {{-20, 46}, {28, 46}, {28, 38}, {28, 38}}, color = {0, 0, 255})); connect(resistor.p, signalVoltage.p) annotation( Line(points = {{-40, 14}, {-40, 14}, {-40, 46}, {-40, 46}}, color = {0, 0, 255})); annotation( uses(Modelica(version = "3.2.3"))); end testbench;
model testbench parameter Real v_DC (start = 100); Modelica.Blocks.Sources.RealExpression realExpression(y = v_DC) annotation( Placement(visible = true, transformation(origin = {-70, 70}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); Modelica.Electrical.Analog.Sources.SignalVoltage signalVoltage annotation( Placement(visible = true, transformation(origin = {-30, 46}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); Modelica.Electrical.Analog.Basic.Resistor resistor(R = 10) annotation( Placement(visible = true, transformation(origin = {-30, 14}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); Modelica.Electrical.Analog.Basic.Ground ground annotation( Placement(visible = true, transformation(origin = {28, 28}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); Modelica.Electrical.Analog.Basic.Inductor inductor annotation( Placement(visible = true, transformation(origin = {-60, 14}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); equation connect(realExpression.y, signalVoltage.v) annotation( Line(points = {{-58, 70}, {-30, 70}, {-30, 58}, {-30, 58}}, color = {0, 0, 127})); connect(signalVoltage.n, resistor.n) annotation( Line(points = {{-20, 46}, {-6, 46}, {-6, 14}, {-20, 14}, {-20, 14}}, color = {0, 0, 255})); connect(signalVoltage.n, ground.p) annotation( Line(points = {{-20, 46}, {28, 46}, {28, 38}, {28, 38}}, color = {0, 0, 255})); connect(inductor.n, resistor.p) annotation( Line(points = {{-50, 14}, {-40, 14}, {-40, 14}, {-40, 14}}, color = {0, 0, 255})); connect(signalVoltage.p, inductor.p) annotation( Line(points = {{-40, 46}, {-74, 46}, {-74, 14}, {-70, 14}, {-70, 14}}, color = {0, 0, 255})); annotation( uses(Modelica(version = "3.2.3"))); end testbench;
Used Software
Windows 10
OpenModelica 1.16.0
PyFMI 2.5
Spyder 3.3.6
FMU Creation
Created the FMU with a .mos file with the following settings:
OpenModelica.Scripting.loadFile("testbench.mo"); getErrorString();
setCommandLineOptions("-d=newInst"); getErrorString();
setCommandLineOptions("-d=initialization"); getErrorString();
setCommandLineOptions("--simCodeTarget=Cpp"); getErrorString();
setCommandLineOptions("-d=-disableDirectionalDerivatives"); getErrorString();
OpenModelica.Scripting.translateModelFMU(testbench, version="2.0", fmuType = "me"); getErrorString();
Python code for testing
import pylab as P import numpy as N from pyfmi import load_fmu def run_demo(with_plots=True): model = load_fmu('testbench.fmu') Tstart = 0.0 # Tend = 0.1 dt = 0.0001 model.setup_experiment(start_time = Tstart) model.enter_initialization_mode() model.exit_initialization_mode() time = Tstart model.enter_continuous_time_mode() x = model.continuous_states model.set('resistor.R', 1000) model.set('v_DC', 5700) vref = [model.get_variable_valueref('resistor.i')] vref2 = [model.get_variable_valueref('resistor.R')] t_sol = [Tstart] sol = [model.get_real(vref)] sol2 = [model.get_real(vref2)] while time < Tend: 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)') if __name__ == "__main__": run_demo()
Bugs
In the second model (with the inductor), a change of the DC voltage (model.set('v_DC', 5700)) leads to a proportional change of the current at resistor1. This works as it should.
A change of the value of the resistor (model.set('resistor.R', 10000)) does not affect the current in the resistor in any way. The printing the value shows the one which was actually set (see second plotted figure), but for the calculation of the current, the default value which was selected in OpenModelica is used.
In the first model (without inductor), neither a change in the DC voltage nor a change in the Resistor affect the current in the resistor, though should.
Within other models, changing the value of the resistor works with the demanded result, and we had difficulties setting the voltage of the source.
Is there a mistake in the way of setting the parameters, a bug in OpenModelica, in PyFMI, or what is going on here?
Change History (9)
comment:1 by , 4 years ago
Milestone: | 1.16.0 → 1.17.0 |
---|
comment:2 by , 4 years ago
comment:4 by , 4 years ago
Replying to trista.arinomo@…:
ignore my comment, did not read the ticket properly. sorry
No problem, still thank you for your interest :-)
In Our main toolbox, it is with our actual model possible to change the resistors (4. Level), but not the v_DC (first level).
But yes, the Level seems to be in the settings important, since it is (as far as I know) only possible to hand ove inputs to the first level, and not to the ones behind it.
comment:5 by , 4 years ago
i was testing you model a little bit and able to change the parameters of resistor.R and inductor.L and got a right result (at least almost the same results from simulation in OM) when i set the model parametes in the initialization mode
model.setup_experiment(start_time = Tstart) model.enter_initialization_mode() model.set('resistor.R', 100) model.set('inductor.L',10) model.exit_initialization_mode() time = Tstart model.enter_continuous_time_mode() x = model.continuous_states model.set('v_DC', 5700)
so i assume you have to set parameter of sub-models in initializaiton mode, and the top model could be changed in continous time mode.
hope it helps, and if its incorrect than maybe dev will tell us the preferable approch for manipulating parameter in FMU
comment:6 by , 4 years ago
This helps a little, thank you!
But this is not the whole truth, especially since it seems to be possible for some parameters to be changed in the cont. time mode.
And this feature is important for us. We wrote an open source toolbox for machine learning in inverter tuning in electrical grids. One important feature is a loadstep, meaning a change of the resistor (and inductor...) after a certain simulation time. So changing them in the cont. mode in between some simulation steps is really important for us. It seems to work sometimes, but not reliable.
The developer (modelon) does not seem to be to motivated in answering questions, especially since the main developer of this project left the company, at least as far as I know.
comment:7 by , 4 years ago
Somehow, it seems to be an FMU issue.
writing the model.set(...) in between enter- and exit_initialization_mode() works for most models fine. Even during simulations, so that a parameterchange within the middle of a simulation works.
But in some models, absolutely nothing happens. I can not even chance the value of a resistor. The FMU is generated with the same .mos file, it is a similar type of simulation, but not even the value of the resistor gets changed.
From this package:
https://github.com/upb-lea/openmodelica-microgrid-gym/blob/measurment/fmu/grid.mo
I am using the model grid.testbench_SC2
It consists of 3 inputs, a 3-phase inverter which transforms the input with the gain v_DC to a voltage, and a LC filter. The phases behind the filter are shortcutted.
Generate the FMU via
OpenModelica.Scripting.loadFile("grid.mo"); getErrorString(); setCommandLineOptions("-d=newInst"); getErrorString(); setCommandLineOptions("-d=initialization"); getErrorString(); setCommandLineOptions("--simCodeTarget=Cpp"); getErrorString(); setCommandLineOptions("-d=-disableDirectionalDerivatives"); getErrorString(); OpenModelica.Scripting.translateModelFMU(grid.testbench_SC2, version="2.0", fmuType = "me"); getErrorString();
Here, the first strange thing happens: I only get warnings for fixed startvalues of 2 of the 3 state-variables of the model, the inductor currents.
The third inductorcurrent (inductor1) is not mentioned.
Testing the FMU with following code showed that there were big issues which could not be solved/explained with the previously gained insights.
import pylab as P import numpy as N from pyfmi import load_fmu def run_demo(with_plots=True): model = load_fmu('grid.testbench_SC2.fmu') Tstart = 0.0 # Tend = 0.1 dt = 0.0001 n = 0 model.setup_experiment(start_time=Tstart) model.enter_initialization_mode() model.set('inverter1.v_DC', 570) # This parameterchange works model.set('rl.resistor1.R', 10) # This parameterchange does not work model.exit_initialization_mode() time = Tstart model.enter_continuous_time_mode() x = model.continuous_states vref = [model.get_variable_valueref('rl.resistor1.i')] vref2 = [model.get_variable_valueref('rl.resistor1.R')] vref3 = [model.get_variable_valueref('rl.resistor2.R')] t_sol = [Tstart] sol = [model.get_real(vref)] sol2 = [model.get_real(vref2)] sol3 = [model.get_real(vref2)] model.set('rl.resistor2.R', 10) while time < Tend: model.set('i1p1', 0) model.set('i1p2', 1) model.set('i1p3', 0) model.enter_initialization_mode() model.set('rl.resistor2.R', 100) model.exit_initialization_mode() dx = model.get_derivatives() n = n + 1 if n == 200: model.enter_initialization_mode() model.set('inverter1.v_DC', 5700) # this change works again model.set('rl.resistor1.R', 100) # This does not work model.exit_initialization_mode() print(n) # check if the if-condition was fulfilled 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)] sol3 += [model.get_real(vref3)] 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.figure(3) P.plot(t_sol, N.array(sol3)[:, 0]) P.title(model.get_name()) P.ylabel('Resistor2 (Ohm)') P.xlabel('Time (s)') P.show() if __name__ == "__main__": run_demo()
In theory, i should have been able to change the resistor while being in the initialization_mode, isn´t it?
So has anyone any clue, why this is not possible?
comment:8 by , 4 years ago
Milestone: | 1.17.0 → 1.18.0 |
---|
Retargeted to 1.18.0 because of 1.17.0 timed release.
Just curious, have you try to add a parameter for resistor in the highest model?
e.g.
if I understand correctly, you can only set parameter on the highest model layer on FMU but not sub-model. CMIIW