这是我参与11月更文挑战的第7天,活动详情查看:2021最后一次更文挑战
本文是来自于FMI2.0规范的第四章联合仿真的译文,基于机翻与个人理解修订而成。
一、开题
本文定义了函数模拟接口(FMI)用于在联合仿真环境中联合两个或更多仿真模型(FMI进行共模)。联合仿真是一种相当常见的方法,用于仿真仿真的技术系统和相关的物理现象,着重于稳定性(time-dependent)问题。
联合模拟(coupling simulation ):应用共享网格技术,解决数字化环境下多学科CAE视图模型耦合仿真的难题。
时间依赖性:time-dependent
联合仿真的设计是为了与多个子系统模型耦合,它们已由其仿真器及其求解器导出为可运行代码;还可用于仿真工具的耦合(仿真器耦合,工具耦合)。
在工具耦合情况下,仿真工具提供的FMU实现类将FMI函数的调用包装为API调用(C->其它语言
)。此外,还需要使用仿真工具来对FMU进行联合仿真。最常见的是,基于工具耦合的联合仿真在分布式硬件上实现了由不同计算机处理不同的子系统,其中包括不同的操作系统(集群计算机,计算机农场,不同位置的计算机)。
子系统之间的数据交换和通信通常使用一种网络通信技术(例如MPI,TCP / IP)完成。该通信层的定义不是FMI标准的一部分,但可以使用FMI来实现分布式联合仿真方案,如下图所示
主机必须实现通信层,用于建立网络通信的其他参数(例如,远程计算机的标识,端口号,用户帐户)将通过主机的GUI进行设置,而这些数据都不会通过FMI API传输。
二、数学描述
- 基础
联合仿真利用了仿真过程中所有的阶段都会遇到的耦合问题(模块化结构),从针对不同仿真工具(可以是功能强大的仿真器以及简单的C程序)中各个子系统单独的模型设置和预处理开始。
在进行时间积分时,将限制子系统间的数据交换只能在离散的通信点tci中进行, 对所有子系统独立执行仿真。对于模拟耦合,子系统中的仿真工具独自完成仿真数据的可视化和后处理。在不同的上下文中,通信点tci、通信步长tci->tci+1 以及通信步长总个数hci:=tci+1- tci 分别称为取样点(同步点)、宏步长和取样率。FMI中用于联合仿真的术语“通信点”是指联合仿真环境中子系统之间的通信,不应与用于将仿真结果保存到文件中的输出点混合使用,
取样:指的是取样的时间点
宏步长:指的是两次取样的时间间隔
取样率(Sampling Rate)是指在数码音频和视频技术应用中,当进行模拟/数码转换时,每秒钟对模拟信号进行取样时的快慢次数。例如,CD和MD的取样率为44.1kHz,表示每秒钟对模拟音频信号进行了44100次取样。取样率越高,转换的精度就越高,重放出的模拟信号波形就越接近原始的模拟信号波形。取样率的高低。决定了所能转换模拟信号的频率上限。
FMI为联合仿真提供了一个接口标准,提供了与时间依赖性相关的耦合系统的解决方案,该耦合系统由时间连续(由平稳差分方程描述的模型组件)或时间离散(由差分方程描述的模型组件,例如离散控制器)的子系统组成。在耦合系统的块表示中,子系统由具有(内部)状态变量x(t)*的块表示,这些块通过子系统输入 *u(t) 和子系统输出 y(t) 连接到其他耦合的子系统(模块)的模块。在这个框架中,子系统间的物理连接由所有子系统的输入 u(t) 和输出 y(t) 间的数学耦合条件表示。
差分方程:包含未知函数的差分及自变数的方程。在求微分方程的数值解时,常把其中的微分用相应的差分来近似,所导出的方程就是差分方程。通过解差分方程来求微分方程的近似解,是连续问题离散化的一个例子。
为了进行联合仿真,必须实现两个基本函数组:
- 子系统之间的数据交换函数
- 用于算法问题的函数,以同步所有子系统的仿真,并从初始时间tc0:= tstart到结束时间tcN:=tstop执行通信步长tci->tci+1。
在用于联合仿真的FMI中,这两个函数都在一个软件组件中实现,即联合仿真主机(Master)。子系统(Slave)之间的数据交换仅通过主站进行,从站之间没有直接通信;主函数可以通过特殊的软件工具(单独的仿真背板)或所涉及的仿真工具之一来实现。最常见的是,耦合系统可以在嵌套的协同仿真环境中进行仿真,并且用于协同仿真的 FMI 适用于层次结构的每个级别。
用于联合仿真的FMI定义了在联合仿真环境中主机与所有从机(子系统)之间进行通信的接口规则。最常见的主站算法是在每个通信点tci停止所有从站的仿真(时间积分)、收集所有子系统的输出y(tci)、调整子系统输入u(tci)将这些子系统输入分配给从站,然后继续与下一个交互步骤tc<sub>i</sub>->tc<sub>i+1</sub> = tc<sub>i</sub> + hc
的(协同)仿真,交互步长为固定参数hc。在每个从站中,适合的求解器应当被用于给定交互步长 tci->tci+1 的子系统之一求积分。最简单的联合仿真算法通过冻结数据u(tci)来近似 tci≤t <tci + 1的(未知)子系统输入u(t),(t> tci)。用于联合仿真的FMI支持这种经典的暴力解法以及更复杂的主算法,旨在支持一类非常通用主算法,但它本身并未定义主算法。
从站支持更复杂的主站算法的能力,在从站的XML描述中包含一组功能标志(capability flags)。典型的例子是
- 具有处理可变通信步长hci的 能力
- 具有使用减小的通信步长重复执行被拒绝的通信步长tci≤t <tci + 1的 能力
- 提供支持插值的输出时间的导数
- 提供雅可比行列式的能力
用于联合仿真的 FMI 仅限于具有以下属性的从站:
- 所有计算参数值 v(t) 是在预先定义的时间间隔(tstart <= t <= tstop)中的时间依赖函数(fmi2SetupExperiment,stopTimeDefined=fmi2True)
- 通常,所有计算(模拟)都随着时间的增加而进行。当前时间t从tstart 到 tstop逐步允许。从站的算法可能拥有属性在[tstart, tstop]整个时间间隔或部分间隔中重复仿真。
- 可以为从站提供一个时间值tci(tstart <= tci <= tstop)
- 当时间到达tci,从站能够中断模拟
- 在中断仿真期间,从站(独立求解器)可以从输入u(tci)获取值,将值发送到输出 y(tci)。
- 每当从站中的模拟中断时,新的时间取值tci+1(tci <= tci+1 <= tstop)可以给出时间子区间(tci < t <= tci+1)
- 子间隔长度hci是第i个通讯步的长度(通信步长必须大于零):hci=tci+1-tci
用于联合仿真的FMI相关流程如下
- 该流程从实例化和初始化(准备好所有从设备进行计算,建立通信链接)开始
- 然后进行仿真(强制从设备模拟通信step)
- 最后在完成时关闭
- 数学模型
本节包含联合仿真 FMU 的正式数学模型,可以作出以下基本假设:
- 从模拟器被主模拟器视为纯粹的采样数据系统,可以是
+ “真实的”采样数据系统(离散控制器;输入和输出可以是Real,Integer,Boolean,String或枚举类型。此类变量的定义为variability =“ discrete”;最小FMU外部可访问的采样周期由元素DefaultExperiment中的属性stepSize定义)
+ 混合ODE被集成在通信点间(对时间连续系统的采样存取),在其中内部事件可能发生并被处理,但在FMU外部看不到。在此假定此混合ODE的所有输入和所有输出均为实际信号(以variability =“ continuous”定义)
+ 上述系统的组合
- 主站和从站之间的通信仅在一组离散的时刻进行,这些时间点称为通信点。
FMI联合仿真模型相关变量描述:
- t:自变量time∈ℝ(causality =“independent”定义的变量);第i个通信点表示为t=tci,通信步长表示为hci = tci+1 - tci
- v:所有暴露变量的向量
- p:仿真过程中不变的参数
- 不带下标符号引用p 表示独立参数(causality = “parameter”);
- 因变参数 pcalculated(causality = “calculatedParameter”)
- 可调参数 ptune(causality = “parameter”、variability= “tunable”)
- u(tci):输入变量
- y(tci):输出变量
- w(tci):不能用于FMU连接的FMU的局部变量,通过causality = “local”定义
- xc(t):用实际连续时间变量的向量表示连续时间状态
- xd(t):离散时间变量
- .xd(t):上一个离散时间变量
存在如下定义:
- 在通信点上,主站向从站提供通用输入
- 从机向主机提供通用输出
- Initialization:从站是一个采样数据系统,其内部状态(连续时间或离散时间都没关系)需要初始化为t=tc0。这是通过辅助函数执行的[此关系在 下的xml文件中定义]。计算FMI联合仿真模型的解意味着将解过程分为两个阶段,并且在每个阶段中使用不同的方程式和解方法。可以根据以下模式对阶段进行分类
- Initialization Mode:如果从站与其他模型循环连接,则可以对FMU方程进行迭代。在这种模式下,将求解代数方程
- Step Mode:通过对常微分、代数和离散方程进行数值求解,此模式用于计算通信点上所有(实际)连续时间和离散时间变量的值。如果从站与其他模型循环连接,则不可能对FMU方程进行迭代
下表中使用的函数fmi2SetXXX是fmi2SetReal,fmi2SetBoolean,fmi2SetInteger和fmi2SetString的缩写。函数fmi2GetXXX是函数fmi2GetReal,fmi2GetBoolean,fmi2GetInteger和fmi2GetString的缩写
方程式 | FMI函数 |
---|---|
初始化模式之前的方程式(状态机中的“实例化”) | |
设置 i=0并设置自变量的tci | fmi2SetupExperiment |
设置变量vinitial=exact以及vinitial=approx | fmi2SetXXX |
初始化模式之后的方程式 | |
在 t=t0时进入初始化模式(激活初始化,离散时间和连续时间方程式) | fmi2EnterInitializationMode |
设置变量vinitial=exact(包括初始值为xc,initial=exact独立参数p和连续时间状态) | fmi2SetXXX |
设置连续时间以及离散时间输入 uc+d(tc0)以及可以选择设置连续时间导数的输入ucj(tc0) | fmi2SetXXX、fmi2SetRealInputDerivative |
vInitialUnknows:=finit(uc,ud,t0,vinitial=exact) | fmi2GetXXX、fmi2GetDirectionalDerivativ |
退出初始化模式(停用初始化方程式) | fmi2ExitInitializationMode |
Step模式下的方程式(状态机中的“ stepComplete”,“ stepInProgress” | |
设置独立的可调参数ptune(不要设置其他参数pother) | fmi2SetXXX |
设置参数连续时间和离散时间输入 uc+d(tci)以及可选参数连续时间输入 uc(j)(tci)的导数 | fmi2SetXXX、fmi2SetRealInputDerivative |
tci+1:=tci+hci (yc+d,yc(j),wc+d)tci+1 := fdoStep(uc+d,uc(j),tci,hci,ptune,pother)tcitci:=tci+1其中fdoStep也是内部变量的函数 | fmi2DoStepfmi2GetXXXfmi2GetRealOutputDerivativesfmi2GetDirectionalDerivative |
三、FMI应用程序编程接口
本节包含用于从C程序访问联合仿真从站的输入/输出数据和状态信息的接口说明。
- 输入/输出值和参数的传输
输入变量、输出变量以及变量 通过本节中定义的fmi2GetXXX和fmi2SetXXX函数进行传输。
为了使从机能够在通信步长间使用连续实数作为输入的插值,可以提供输入对时间的导数;为了允许更高阶的插值,还可以设置更高阶的导数。从机是否能够进行插值由函数属性canInterpolateInputs提供(假如输入为速度,那么需要提供速度对时间的导数,即速率;那么在两个时间点间,可以使用速率*时间t
求出时间t时的速度)。以下是相关函数:
fmi2SetRealInputDerivatives
:
1 | css复制代码-- 设置实数输入变量在第n个时间点的导数 |
使用该函数的限制与fmi2SetReal函数相同。输入及其导数是在通信时间步开始时设置的。为了允许实际输出变量作为其他从站输入在通讯步间进行插值/逼近,可以读取输出相对于时间的导数。从站是否能够提供输出导数由函数标志MaxOutputDerivativeOrder
(无符号整数类型)决定;它定义了输出导数的阶数。如果实际阶数较低(因为积分算法的阶数较低),则检索到的值为0。例如:内部多项式为1阶,并且主机请求输出变量的二阶导数,则从机将返回零。
fmi2GetRealOutputDerivatives
:
1 | css复制代码-- 检索输出值的第n个导数 |
返回的输出变量对应于当前从机时间,例如在成功执行fmi2DoStep后,返回值与通信时间步的结束有关。
- 计算
2.1 fmi2DoStep
时间步长的计算由以下函数控制
1 | scss复制代码 fmi2Status fmi2DoStep(fmi2Component c, |
该函数用于计算时间步长,参数currentCommunicationPoint表示主机的当前通信点(tci)、参数communicationStepSize表示通信步长(hci > 0.0)。从站必须集成,直到tci+1 = tci +hci.【调用环境定义了通信点,fmi2DoStep必须求精确到tci +hci 的积分来与这些点进行同步。而如何实现此目标取决于fmi2DoStep】。
在调用fmi2ExitInitializationMode
函数之后,第一次调用fmiDoStep时,参数currentCommunicationPoint
必须等于由fmi2SetupExperiment
设置的startTime
参数。【参数currentCommunicationPoint
不会被正式使用,定义它是为了解决主节点与从节点间FMU状态不匹配的问题:由前一个的fmi2DoStep
或fmi2SetFMUStatecall
函数定义的参数currentCommunicationPoint
、从节点中的FMU状态必须彼此一致】
例如,如果从节点未按照上述要求对自变量使用更新公式(tci+1 = tci +hci),而是在内部使用自己的更新公式,例如tcs,i+1 = tcs,i +hcs,i (fmi2DoStep函数中,tci=currentCommunicationPoint);则从节点可以使用时间增量hcs,i :=(tci-tcs,i)+hci(替代hcs,i :=hci)去避免主节点时间tci+1和从节点内部时间tcs,i+1偏差过大。
在此次模拟运行中,如果在currentCommunicationPoint到预先设定的时刻之间不再调用fmi2SetFMUState
函数,则设置参数noSetFMUStatePriorToCurrentPoint
= “fmi2True” [从节点可以使用该标志刷新结果缓冲区]。
函数返回值:
fmi2OK
—— 直到通信步长(主时间步)结束,每一子步长计算都成功。fmi2Discard
—— 从节点只成功计算出通讯步长的部分间隔,主节点可以调用相应的fmi2GetXXXStatus
函数来获取更多信息。如果可能的话,主节点应使用更短的通信步长重复模拟。只有函数fmi2GetFMUState
当前(失败)步骤开始时记录了 FMU 状态,才能重复步长;这是通过调用fmi2SetFMUState
并随后使用新的communicationStepSize
调用fmi2DoStep
来实现的。fmi2Error
—— FMU 遇到错误。该 FMU 实例无法继续模拟。如果其中一个函数返回 fmi2Error,则可以尝试通过调用fmi2SetFMUstate
从以前存储的 FMU 状态重新启动仿真。fmi2Fatal
—— 所有 FMU 实例的模型计算都无法修复(例如,由于在执行 fmi 函数期间出现访问冲突或整数除以零等运行时异常)fmi2Pending
—— 从节点异步执行,即开始执行时立即返回。如果从节点返回这个状态,主节点必须调用函数fmi2GetStatus(...,fmi2DoStep,...)
来确定从节点是否完成;另一种方法是等待slave调用回调函数fmi2StepFinished
;而调用函数fmi2CancelStep
可以取消当前的计算。如果返回这个值,在fmi2DoStep
执行期间,不允许调用其它函数。
如果fmi2DoStep
返回了fmi2Pending
,则可以调用fmi2CancelStep
函数停止当前的异步执行。
1 | scss复制代码fmi2Status fmi2CancelStep(fmi2Component c); |
如果用户或从节点之一停止运行联合仿真,则主节点调用次函数。之后,只允许调用fmi2Reset
或fmi2FreeInstance
。
- 获取从节点的状态信息
通过以下函数向主节点反馈从节点的当前状态信息:
1 | arduino复制代码fmi2Status fmi2GetStatus(fmi2Component c,const fmi2StatusKind s, fmi2Status* value); |
通知主节点有关模拟运行的实际状态,由参数fmi2StatusKind
决定要返回的状态信息。从节点可以提供哪些状态信息取决于从节点的能力。如果需要从节点无法检索的状态,它将返回状态fmi2Discard
。
结构体fmi2StatusKind包含以下状态:
状态 | 类型 | 描述 |
---|---|---|
fmi2DoStepStatus | fmi2Status | 当fmi2DoStep函数返回fmi2Pending时可以调用。如果计算未完成,该函数将提供fmi2Pending。否则,该函数将返回异步执行的fmi2DoStep调用的结果。 |
fmi2PendingStatus | fmi2String | 当fmi2DoStep函数返回fmi2Pending时可以调用。该函数提供一个字符串,该字符串告知当前正在运行的异步fmi2DoStep计算的状态 |
fmi2LastSuccessfulTime | fmi2Real | 返回上一个成功完成的通信步骤的结束时间。可以在fmi2DoStep(…)返回fmi2Discard之后调用。 |
fmi2Terminate | fmi2Boolean | 如果从节点希望终止仿真,则返回true。可以在fmi2DoStep(…)返回fmi2Discard之后调用。使用fmi2LastSuccessfulTime确定从节点终止的时刻 |
- 主节点到从节点调用次序的状态机
以下状态机定义了fmi规范所支持的调用序列
状态机的每个状态对应于模拟的某个特定阶段,如下所示:
- instantiated(实例化):在这种状态下,可以设置起始值和估计值(变量属性initial = “exact” or “approx.”)、设置导数、设置仿真条件
- Initialization Mode(初始化模式):在这种状态下,方程式可用于确定所有输出(以及导出工具到处的其他可选变量)、可以通过fmi2GetXXX调用变量是在xml文件中的 下定义的(causality=”output”)变量、可以设置initial=”exact”的变量以及具有variability=”input”的变量
- slaveInitialized(从节点初始化):在这种状态下,将对从节点进行初始化并执行联合仿真计算;使用函数“ fmi2DoStep”执行计算直到下一个通讯点。根据返回值,从节点处于不同的状态
+ step complete
+ step failed
+ step canceled
- terminated(终止):在这种状态下,可以获取仿真最后时刻的解。
注:在初始化模式下,可以根据xml文件中的元素
<ModelStructure>、 <InitialUnknowns>
定义模型结构,使用fmi2SetXXX设置输入变量,并使用fmi2GetXXX获取输出变量。【例如,如果一个输出y1取决于两个输入u1,u2,则必须先设置这两个输入,然后才能获取y1。 如果另外输出y2取决于输入u3,则可以设置u3,然后再获取y2;可以通过使用适当的数值算法来处理初始化模式下连接的FMU上的人工或“真实”代数环。】
“slaveInitialized”状态还有一个额外的限制,在fmi2SetXXX函数之后如果没有fmi2DoStep调用,则不允许调用fmi2GetXXX函数。
与模型交换类型的FMI相反,为了避免缓存存在不同的解释,联合仿真的fmi2DoStep
函数将执行实际的计算,而不是使用fmi2GetXXX
函数。因此,模型交换时调用的fmi2GetXXX
、fmi2SetXXX
序列无法处理通讯点处的虚拟代数环。
四、FMU联合仿真(CoSimulation)
- 标签的定义
联合仿真功能在模型描述文件中的 标签定义,相关定义如下:
相关结构如下:
- CoSimulation
- modelIdentifier:类名缩写
- needsExecution:决定是否需要外部工具执行模型
- canHandleVariableCommunicationStepSize:从节点可以处理可变的通信步长。对于每个校准,通信步长(fmi2DoStep函数的参数communicationStepSize)在每次调用中不需要固定不变
- canInterpolateInputs:从节点能够对连续输入插值
- maxOutputDerivativeOrder:从节点能够提供最大阶数的输出导数
- canRunAsynchronuously :异步
- canBeInstantiatedOnlyOncePerProcess:单FMU单实例(如果需要多个实例,则必须在不同的进程中实例化 FMU)
- canNotUseMemoryManagementFunctions:如果为true,则从节点使用自身的函数进行内存分配和释放;忽略fmi2Instantiate中给出的回调函数 allocateMemory、freeMemory
- canGetAndSetFMUstate:如果为true,则 仿真环境可以查询和恢复内部FMU状态(即支持fmi2GetFMUstate,fmi2SetFMUstate,fmi2FreeFMUstate)
- canSerializeFMUstate:如果为true,则仿真环境可以序列化内部FMU状态,即FMU支持fmi2SerializedFMUstateSize,fmi2SerializeFMUstate,fmi2DeSerializeFMUstate。如果是这种情况,则标记canGetAndSetFMUstate也必须为true。
- providesDirectionalDerivative:如果为true,在通信点时可以使用fmi2GetDirectionalDerivative(..)计算方程的方向导数。
- SourceFiles:资源文件
- 实例
1 | xml复制代码<?xml version="1.0" encoding="UTF8"?> |
五、结语
模型交换是指同一仿真环境下某一个仿真实例生成(符合 FMI 接口定义)的可移植可调用的数学模型库;而联合仿真指的是将不同仿真环境(分布式或跨工具)的输入输出按照 FMI 标准定义好,通过Master Algorithm(ssp、dcp)传输数据,协同计算。
《Functional Mock-up Interface forModel Exchange and Co-Simulation v2.0》
本文转载自: 掘金