With FMPy you can extract a list of the continuous states from the model description by following the derivative
attribute of the model variables (see FMI Specification 2.0.4, p.57).
fmu_filename = 'MyModel.fmu'
model_description = read_model_description(fmu_filename)
continuous_states = []
for variable in model_description.modelVariables:
if variable.derivative is not None:
continuous_states.append(variable.derivative)
Note that it is not allowed to set the values of variables with causality local
(see FMI Specification 2.0.4, p. 108). This includes the continuous states of a Co-Simulation FMU.
To retrieve and restore the state of a Co-Simulation FMU you have to use the FMU State API (see FMI Specification 2.0.4, p. 26).
# this script demonstrates how to pause and continue a simulation
# with FMPy (https://github.com/CATIA-Systems/FMPy) using get/set FMU state
from fmpy import *
from shutil import rmtree
import numpy as np
# FMI 2.0 BouncingBall model from the Reference FMUs v0.0.22
# https://github.com/modelica/Reference-FMUs/releases/download/v0.0.22/Reference-FMUs-0.0.22.zip
fmu_filename = 'BouncingBall.fmu'
model_description = read_model_description(fmu_filename)
if not model_description.coSimulation.canGetAndSetFMUstate:
raise Exception("The FMU does not support get/set FMU state.")
unzipdir = extract(fmu_filename)
# instantiate the FMU before simulating it, so we can keep it alive
fmu_instance = instantiate_fmu(
unzipdir=unzipdir,
model_description=model_description,
)
# simulation time when we pause the simulation
pause_time = 0.75
# use the step_finished callback to stop the simulation at pause_time
def step_finished(time, recorder):
""" Callback function that is called after every step """
return time < pause_time # stop the simulation early when time >= 2
# simulate up to pause_time
result1 = simulate_fmu(
filename=unzipdir,
model_description=model_description,
fmu_instance=fmu_instance,
output_interval=0.05,
terminate=False,
step_finished=step_finished
)
# retrieve the FMU state
fmu_state = fmu_instance.getFMUState()
# continue the simulation
result2 = simulate_fmu(
filename=unzipdir,
model_description=model_description,
fmu_instance=fmu_instance,
start_time=pause_time,
output_interval=0.05,
fmu_state=fmu_state
)
# combine and plot the results
plot_result(np.concatenate((result1, result2)), events=True, markers=True)
# clean up
fmu_instance.freeInstance()
rmtree(unzipdir, ignore_errors=True)
