openmodelicafmipyfmi

FMU FMI simulation, no evaluation of some equations after initialization


I believe my problem is somehow related to this previous question but I was not able to fix my problem with their advices.

Here is a minimal non working example. I have a simple electrical circuit with a commutating switch in it (developed in openModelica). I want to modify the value of switch.control depending on the value of an input Parameter. To do that I have the following:

model MinimalNonWorkingExemple

 parameter Modelica.Blocks.Interfaces.RealInput openclose;
 Modelica.Electrical.Analog.Ideal.IdealCommutingSwitch switch;
 Modelica.Electrical.Analog.Basic.Ground G;

equation
 connect(switch.p, G.p);
 connect(switch.n2, G.p);
 connect(switch.n1, G.p);

 switch.control = if openclose > 0.5 then true else false;
end MinimalNonWorkingExemple;

Note: I tried many combination between parameter, input, etc...

I want to make an iterative simulation (for instance simulate 60 seconds of the system but with 60 consecutive simulations of 1 second). This is to be able to change the input value (openclose) according to another FMU simulation.

As a result I can modify the value of the input from pyFMI. (when I read it, the changed is taken into account). However, the "new value" is not taken into account neither in my equations.

Here is my pyfmi script:

# Import the load function (load_fmu)
from pyfmi import load_fmu
import numpy as np 
from pylab import *

def simulate(model, res, startTime,finalTime, initialState):
 if res == None:
    opts=model.simulate_options()
    opts['initialize']=True
 else:
    opts=model.simulate_options()
    opts['initialize']=False

 for s in initialState:
    model.set(s[0],s[1])

 res = model.simulate(start_time = startTime, final_time=finalTime, options=opts)
 return res


 #main part
 model = load_fmu('MinimalNonWorkingExemple.fmu')
 switchClose = ['openclose', [0.0]]
 switchOpen = ['openclose', [1.0]]

 #Simulate an FMU
 res = simulate(model, None, 0, 50, [switchOpen])

 v = res["openclose"]
 v2 = res["switch.control"]

 res = simulate(model, res, 50, 100, [switchClose])
 v = np.concatenate((v,res["openclose"]))
 v2 = np.concatenate((v2,res["switch.control"]))

 res = simulate(model, res, 100, 200, [switchOpen])
 v = np.concatenate((v,res["openclose"]))
 v2 = np.concatenate((v2,res["switch.control"]))

 print v
 print v2

Basically I simulate during 50 units of time then I change the value of the openclose variable, then simulating again, switching again and re-simulating. As a result I obtained:

 openclose:      [ 1.  1.  1.  1.  0.  0.  0.  0.  1.  1.  1.  1.]
 switch.control: [ 1.  1.  1.  1.  1.  1.  1.  1.  1.  1.  1.  1.]

Actually, only the set made before the first call to model.simulate(...) propagates its value in the system.

I tried to understand the annotation(Evaluate = false) proposed here but it did not work. I'm not sure if it is related since I can actually change my value. The problem is that the equations based on this parameter seems only evaluated during initialisation :-/

Any idea/help would be very welcome...


Solution

  • As far as I can understand, the FMI standard says that after you initialize the model your changes to the parameters will not affect the model anymore. So, one has to use reset and re-initialize the model so the changes are picked up again. It seems to work fine with this code:

    # Import the load function (load_fmu)
    from pyfmi import load_fmu
    import numpy as np 
    from pylab import *
    
    def simulate(model, res, startTime,finalTime, initialState):
      if res == None:
        opts=model.simulate_options()
        opts['initialize']=True
      else:
        model.reset()
        opts=model.simulate_options()
        opts['initialize']=True
    
      for s in initialState:
        model.set(s[0],s[1])
    
      res = model.simulate(start_time = startTime, final_time=finalTime, options=opts)
      return res
    
    
    #main part
    model = load_fmu('MinimalNonWorkingExemple.fmu')
    print model.get_description()
    model.set_log_level(7)
    switchClose = ['openclose', [0.0]]
    switchOpen = ['openclose', [1.0]]
    
    #Simulate an FMU
    res = simulate(model, None, 0, 50, [switchOpen])
    
    v = res["openclose"]
    v2 = res["switch.control"]
    
    res = simulate(model, res, 50, 100, [switchClose])
    v = np.concatenate((v,res["openclose"]))
    v2 = np.concatenate((v2,res["switch.control"]))
    
    res = simulate(model, res, 100, 200, [switchOpen])
    v = np.concatenate((v,res["openclose"]))
    v2 = np.concatenate((v2,res["switch.control"]))
    
    print v
    print v2
    

    The result is:

    [ 1.  1.  1.  1.  0.  0.  0.  0.  1.  1.  1.  1.]
    [ 1.  1.  1.  1.  0.  0.  0.  0.  1.  1.  1.  1.]
    

    You can see also the discussion here: http://ext5.modelon.ideon.se/5858

    It might work also if you make openclose an input (no parameter) and then give an input object to the simulation (openclose, time, value) as in the example here: http://www.jmodelica.org/assimulo_home/pyfmi_1.0/pyfmi.examples.html#module-pyfmi.examples.fmu_with_input However, I haven't tried it so it might not work.