如何使用 FMPy 提取(连续时间)状态列表?

jan*_*ter 3 modelica fmi pyfmi

在一些交互式仿真工作中,可以方便地仿真到某个时间点,更改一些参数,然后继续仿真。

使用FMU进行仿真,则需要重新加载或重置FMU,然后为系统状态输入新的初始值,该初始值是先前仿真的状态的最终值。您还需要以与之前的模拟类似的方式输入与默认值不同的参数值。

当您使用 PyFMI 时,有一个方便的关联函数 get_states_list() ,如下所示:

  from pyfmi import load_fmu
  ...
  model = load_fmu('file of fmu')
  stateDict = model.get_states_list()
Run Code Online (Sandbox Code Playgroud)

字典 stateDict 包含连续时间状态,这对于进一步自动更新初始状态值与先前模拟的最终状态值非常有帮助。据我了解,可能的离散时间状态不包括在内,并且需要手动处理。

如何使用 FMPy 获得类似的(连续时间)状态字典?或者更好的是,还包括离散时间状态?

Tor*_*mer 6

使用 FMPy,您可以按照(参见FMI 规范 2.0.4、第 57 页和第 61 页)derivative中的未知数属性从模型描述中提取连续状态列表。ModelStructure/Derivatives

from fmpy import *

fmu_filename = 'MyModel.fmu'

model_description = read_model_description(fmu_filename)

continuous_states = \
    [unknown.variable.derivative for unknown in model_description.derivatives]
Run Code Online (Sandbox Code Playgroud)

请注意,不允许设置具有因果关系的变量值local(请参阅FMI 规范 2.0.4,第 108 页)。这包括协同仿真 FMU 的连续状态。

要检索和恢复协同仿真 FMU 的状态,您必须使用 FMU 状态 API(请参阅FMI 规范 2.0.4,第 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)

Run Code Online (Sandbox Code Playgroud)

结果