我正在使用 Dymola 2019 将我的 Modelica 模型转换为 FMU,然后我使用 JModelica 进行模拟(我从 2018 年 3 月 15 日开始使用 JModelica 2.2 版)。我的目标是能够模拟某个时期,分析结果,根据这些结果修改某些参数,然后在使用新参数值的同时从中断的地方继续之前的模拟。
我知道get_fmu_state
andset_fmu_state
在技术上应该能够做到这一点,但是在尝试实现它时我没有设法使它工作,并且 PyFMI 目录中似乎没有任何示例使用其中任何一个功能。我尝试了以下方法:
from pyfmi import load_fmu
model = load_fmu("FMU_generated_by_Dymola.fmu")
res1 = model.simulate(final_time=5.0)
state = model.get_fmu_state()
#Here I would ideally like to use res1 to vary some parameters
model = load_fmu("FMU_generated_by_Dymola.fmu")
model.initialize()
opts = model.simulate_options()
opts['initialize'] = False
model.set_fmu_state(state)
res2 = model.simulate(start_time=5.0,final_time=10.0,options=opts)
上面的代码在不引发任何异常的情况下工作,尽管它确实在最后打印了以下警告:WARNING:root:The simulation start time (5.000000) and the current time in the model (0.000000) is different. Is the simulation start time correctly set?
. 但更重要的是,当在一个相对复杂的模型上尝试使用 Modelicasample()
函数定期更改的离散实变量时,该离散变量的状态似乎在第二次模拟中变得不可变。它的初始值从第一次模拟结束时延续,但之后不再改变。因此,在前面的代码中,将产生与以下代码中res2
截然不同的结果:res3
from pyfmi import load_fmu
model = load_fmu("FMU_generated_by_Dymola.fmu")
res3 = model.simulate(final_time=10.0)
即使将通信点的数量增加一倍res3
以更准确地反映,差异仍然存在res2
。我不知道为什么我的真实离散变量在使用set_fmu_state()
. 有没有人有任何想法?我没有set_fmu_state()
正确使用吗?
还值得注意的是,我也看过这个问题,但这显然需要使用compile_fmu()
而不是load_fmu()
为了使用该"state_initial_equations": True
选项(更不用说它似乎不适用于模拟中未包含的变量结果)。我也看过这个问题,但这是专门针对 Dymola 而不是 JModelica 的,并且依赖于结果文件中存在的所需状态,但情况并非总是如此。
编辑
为了让我的问题更清楚,我在下面提供了一个示例模型。
model DiscreteContinuous
discrete Real discr "Discrete variable";
Real cont "Continuous variable";
initial equation
discr=0;
cont=0;
equation
when sample(0,2) then
discr=pre(discr)+1;
end when;
der(cont)=1;
end DiscreteContinuous;
之后,使用 Dymola 2019 将此模型转换为 FMU 格式,然后使用 JModelica 在我的问题中运行 Python。首先,以下结果res3
符合预期:
In [1]: res3['discr'][-1]
Out [1]: 6.0
In [2]: res3['discr'][0]
Out [2]: 1.0
但是,以下结果res2
表明,虽然连续变量在使用 时表现如预期,但另一方面set_fmu_state()
,离散变量在整个第二次模拟中不会发生变化:
In [3]: res2['discr'][-1]
Out [3]: 3.0
In [4]: res2['discr'][0]
Out [4]: 3.0
In [5]: res2['cont'][-1]
Out [5]: 9.9999999999999929
In [6]: res2['cont'][0]
Out [6]: 4.9999999999999964