Opened 4 years ago

Closed 4 years ago

#6160 closed defect (invalid)

FMU behaviour depending on library style

Reported by: bode@… 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:

https://github.com/upb-lea/openmodelica-microgrid-gym/blob/feature_41_construction_branch/fmu/grid.mo

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:

https://github.com/upb-lea/openmodelica-microgrid-gym/tree/feature_75_library/OpenModelica_Microgrids

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)

omg_grid.Grids.Network.fmu (759.8 KB ) - added by bode@… 4 years ago.
new library format, not working
grid.network.fmu (754.3 KB ) - added by bode@… 4 years ago.
old library format, working
grid.network2.fmu (762.1 KB ) - added by bode@… 4 years ago.
old format for minimal example
OpenModelica_Microgrids.Grids.Network2.fmu (769.1 KB ) - added by bode@… 4 years ago.
new format for minimal example
current_new.png (31.7 KB ) - added by bode@… 4 years ago.
currents with the new library
resistance_new.png (14.2 KB ) - added by anonymous 4 years ago.
resistance of the new library
current_old.png (28.2 KB ) - added by bode@… 4 years ago.
currents with the old library
resistor_old.png (11.8 KB ) - added by bode@… 4 years ago.
resistance of the old library

Change History (17)

comment:1 by Andreas Heuermann, 4 years ago

Owner: changed from Lennart Ochel to Andreas Heuermann
Status: newassigned

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.

by bode@…, 4 years ago

Attachment: omg_grid.Grids.Network.fmu added

new library format, not working

by bode@…, 4 years ago

Attachment: grid.network.fmu added

old library format, working

comment:2 by bode@…, 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 Andreas Heuermann, 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 bode@…, 4 years ago

Attachment: grid.network2.fmu added

old format for minimal example

by bode@…, 4 years ago

new format for minimal example

by bode@…, 4 years ago

Attachment: current_new.png added

currents with the new library

by anonymous, 4 years ago

Attachment: resistance_new.png added

resistance of the new library

by bode@…, 4 years ago

Attachment: current_old.png added

currents with the old library

by bode@…, 4 years ago

Attachment: resistor_old.png added

resistance of the old library

comment:4 by bode@…, 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 Andreas Heuermann, 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 bode@…, 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 Andreas Heuermann, 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 bode@…, 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 Andreas Heuermann, 4 years ago

Resolution: invalid
Status: assignedclosed

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.

Note: See TracTickets for help on using tickets.