3

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...

Sarah N
  • 518
  • 7
  • 22
Danto N
  • 65
  • 7
  • It seems that we remove the if equation completely and put in just the selected branch based on openclose > 0.5. However, if you don't give the full model is hard to debug. You could try to rewrite the if equation to an if expression: switch.control = if openclose > 0.5 then true else false; – Adrian Pop Aug 08 '15 at 16:29
  • Thanks for the explanation, I think you're right. Changing the form of the equation does not change anything :-/ I modified my original post to provide a minimal non working example. I hope it will help us to understand how to fix that. Thanks – Danto N Aug 09 '15 at 08:42

1 Answers1

2

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.

Adrian Pop
  • 4,034
  • 13
  • 16
  • Hi,thanks again for the help. Resetting and restoring the state of the model was a workaround I already experiments but it fails in some cases. (For instance for the following openmodelica model: *Modelica::Mechanics::MultiBody::Examples::Systems::RobotR3::fullRobot* with the following error: `params[i] = model.get(i) File "fmi.pyx", line 227, in pyfmi.fmi.ModelBase.get (src/pyfmi/fmi.c:4099) File "fmi.pyx", line 3612, in pyfmi.fmi.FMUModelBase2._get (src/pyfmi/fmi.c:31666) pyfmi.fmi.FMUException: Type not supported. ` so I though it was not a correct solution. – Danto N Aug 10 '15 at 12:05
  • I also tried with the *input object* solution but the result is the same than in the original post... If resetting is the only way, I'll do it but it takes a a big amount of time during simulation. **However, it sounds to me important to introduce the notion of `volatile variable` in modelica to enable the full use of FMU and co-simulation more generally.** What do you think ? thanks again – Danto N Aug 10 '15 at 12:46
  • edit: the *save, reset and restore way* works fine for some simple models. For more complex model like the *FullRobot* mentioned in a previous comment, it fails :-/ after avoiding the error from restoring and saving (enumeration type cannot be set and keyError problems) I obtained two different simulations depending if I do it in one call to model.simulate(...) or in two consecutive calls... I think I will open another question but it would be great to enable modification of specific variables from a FMU :) thanks a lot for your help – Danto N Aug 10 '15 at 13:10