在 Engee 中运行 FMI 模型
在 Julia 环境中运行 FMU 模型,获取仿真结果并用于进一步计算。
任务描述
FMI(功能模拟接口)标准涉及将模型打包到 FMU(功能模拟单元)文件中,该文件包含一组方程或系统建模代码(可能支持 Engee 中可调用的各种编程语言:Python、Java、Fortran、C++ 等,包括 Julia)。
举个例子,让我们看看用 Dymola 建立的弹簧和钟摆模型。要运行该模型,我们需要FMI.jl
库和一组训练模型,这些模型收集在FMIZoo.jl
软件包中。
Pkg.add( ["FMI", "FMIZoo"] )
让我们连接已安装的库:
using FMI
using FMIZoo
我们将对这样一个模型进行模拟:

FMI.jl
库允许您以多种方式运行 FMI/FMU 模型,我们将展示其中两种:
- 通过命令
simulate
- 通过创建自己的仿真循环和命令
fmi2DoStep
。
创建时间矢量(设置模拟的开始tStart
、结束Stop
和时间步长tStep
):
tStart = 0.0
tStep = 0.1
tStop = 8.0
tSave = tStart:tStep:tStop
运行调频单元模型的最简单方案
让我们从模型软件包FMIZoo.jl
中加载模型SpringFrictionPendulum1D
。
fmu = loadFMU( "SpringFrictionPendulum1D", "Dymola", "2022x" )
info(fmu)
运行该模型的计算,指定模拟时间的开始和结束以及存储变量mass.s
。由于模型中存在摩擦,振荡幅度会逐渐减小,一段时间后载荷会静止。
simData = simulate(fmu, (tStart, tStop); recordValues=["mass.s"], saveat=tSave)
plot( simData )
计算结束后,必须从内存中卸载 FMU 模型,并删除所有时间数据。
unloadFMU(fmu)
创建自己的模拟周期
在更复杂的情况下,例如需要将多个模型的工作联系起来时,可以组织一个计算循环,让模型沿着某个时间矢量在其相空间中采取步骤。
让我们加载 FMU 模型:
fmu = loadFMU("SpringFrictionPendulum1D", "Dymola", "2022x")
步骤函数需要一个专门准备的模型(具体实现),我们将使用fmi2Instantiate
创建该模型。这样就可以通过一个 FMU 文件初始化多个模型。
instanceFMU = fmi2Instantiate!(fmu)
在下一个单元中,我们将进行实验设置 (fmi2SetupExperiment
) ,指定模拟时间间隔的开始和结束,然后将模型调入初始化模式 (fmi2EnterInitializationMode
) 并在初始化后获得其初始状态 (fmi2ExitInitializationMode
) 。
fmi2SetupExperiment(instanceFMU, tStart, tStop)
fmi2EnterInitializationMode(instanceFMU) # установить исходное состояние
fmi2ExitInitializationMode(instanceFMU) # прочитать исходное состояние
现在我们可以在计算循环中运行模型。固定步长函数fmi2DoStep
tStep
允许该模型的计算步长。如果模型有输入参数或接受的数据,可以在循环中进行更改。
values = []
for t in tSave
# выставить входные параметры модели, если требуется
# ...
fmi2DoStep(instanceFMU, tStep)
# сохранить выходы модели
value = fmi2GetReal(instanceFMU, "mass.s")
push!(values, value)
end
plot(tSave, values)
计算结束时,我们必须释放内存并删除中间文件。
fmi2Terminate(instanceFMU)
fmi2FreeInstance!(instanceFMU)
unloadFMU(fmu)
结论
我们使用单一命令运行了一个简单的调频装置模型,并找出了如何组织一个计算循环,在此循环中,我们可以更新模型的输入参数,并根据输出数据做出运行决策。