Search code examples
modelicafmipyfmi

How to dynamically get the value of a variable in pyfmi


For example, this is my modelica model

model Test
  Real x(start = 1000);
  input Real k;
equation 
  der(x) = -k * x;
end Test;
from pyfmi import load_fmu

model = load_fmu('D:/FMU/Test.fmu')
model.initialize(0,10)

def f(time):
    global model
    x = model.get('x')
    return time*0.1

inputs = ('k', f)
result = model.simulate(final_time=10, input=inputs)

How can I get the value of x in function f,or how can I get the value of the current state and then adjust the input parameters to continue the simulation? I tried to get it via model.get(), but failed. Thanks a lot for your help!


Solution

  • A fifth solution! As Christian Bertsch pointed out above, you may want to read out a state from the model and not just time. This is actually possible.

    Let the model be:

    model Test2
       input Real k;
       parameter Real x_start = 1000;
       Real x(start=x_start, fixed=true);
    equation
       der(x) = -k*x;
    end Test2;
    

    And use the script:

    # Setup framework
    from pymodelica import compile_fmu 
    from pyfmi import load_fmu
    import matplotlib.pyplot as plt
    
    # Compile model
    fmu_model = compile_fmu('Test2','Test2.mo',target='cs')
    
    # Load model
    model = load_fmu(fmu_model)
    
    # k variation
    def f(time):
       k=model.get('x')
       return k
    
    # Simulate
    result = model.simulate(input=('k', f), start_time=0, final_time=2)
    
    # Plot results
    plt.figure()
    plt.semilogy(result['time'], result['x'])
    plt.xlabel('Time'); plt.ylabel('x'); plt.grid()
    plt.show()
    

    You get the output:

    enter image description here

    If you change to FMU of ME type you get a slightly better output:

    enter image description here

    This improvement around time zero is due to the fact that CS is only updated at events during the simulation while for ME you get a more continuous result.