FMU中时间概念的连续性和离散性实际上是变量的属性。并且FMU都能够包含连续时间的变量或是离散时间的变量。在模型交换类型和联合仿真类的FMU通信中可以看到这一点。 在FMI2.0中通过通信点来进行数据交换的通信结构是离散的。 一、模型交换:导入工具提供求解器 仿真工具之间模型集成非常紧密。 在导入工具和模型之间的接口非常复杂。 导入工具必须提供合适的求解器。 二、联合仿真:导出工具提供求解器 模型和求解器之间有着紧密的耦合关系。 导入工具和模型之间的接口相对简单。 可以选择不同的联合仿真算法和通信步长来实现更稳定精确的仿真方案。 三、联合仿真的接口Interface 通信时间步长可以和内部步长不同,通信时间步长主要是不同FMU之间交换信息,而在各自的内部可以时是不同的可变时间步长。 在联合仿真接口中,参数会根据FMI标准有着典型的调用顺序: 得到输出:fmiGetXXX(...) 触发计算直到下一个通信节点:fmidoStep(...) 设置输入值:fmi2SetXXX(...) 以C代码为例: 使用FMI2Instantiate函数实例化FMU CALL instantiationToken, fmi2Flase, fmi2Flase)) 其中涉及到的参数分别是FMI实例、FMU资源的URI、声明FMU的类型为联合仿真、唯一标识符、是否显示FMU的GUI和是否启动日志记录的参数。 应用初始值和输出 CALL (applyStartValues(S, settings)); CALL startTime, true , true , false )); 设置参数并进入初始化模式,如果有FMU初始状态文件的话,可以在实例化FMU后执行 CALL 0 startTime, fmiFalse, 0 )); CALL (FMI2EnterInitializationMode(S)); CALL (FMI2ExitInitializationMode(S)); 进入仿真循环,按照时间步长进行采样和应用输入 for (ubsigned long step = 0 ;; step++) { const outputInterval; ... CALL (FMISample(S, time, result)); CALL (FMIApplyInput(S, input, time, true , true , false )); ...... const outputInterval, fmiTrue); ...... CALL (FMIGetBooleanStatues(S, fmi2Terminated, &terminated)) ...... CALL (FMI2GetRealStatus(S, fmi2LastSuccessfulTime, &lastSuccessfulTime)); CALL (FMISample(S, lastSuccessfulTime, result)); ...... 联合仿真算法作用 联合仿真算法不属于FMI标准的一部分,其作用主要是用于: 推进整个仿真系统的时间,使得各个子系统的FMU组件在 每个时间步长上同步执行仿真计算,即代码中仿真循环的部分。 交换输入和输出数据。 触发时钟信号,用于同步不同仿真组件或触发某些操作,即代码中。 settings startTime + step * settings outputInterval; FMI2DoStep (S, time, settings outputInterval, fmiTrue); 处理事件,例如状态变化、外部输入、内部条件触发等,即代码中。 CALL (FMI2GetRealStatus(S, fmi2LastSuccessfulTime, &lastSuccessfulTime)); CALL (FMISample(S, lastSuccessfulTime, result)); 四、模型描述文件是并行的 模型描述文件modelDescription.xml包含了关于FMU所有的静态信息,其定义了FMU支持的接口类型,无论是模型交换或是联合仿真,同时解释了模型变量,包括了输入、输出以及相关参数,以便导入工具进行访问。 除此之外也会包含模型接口的一些信息,比如模型连接时数据是符合输入输出的。 并且在模型描述文件中还会声明一些属性标志,比如“needsExcutionTool”,这一属性表示需要特定的程序或是特定的库文件才能够执行FMU,所以在导入FMU时,在导入工具中需要一个额外的包装Wrapper,并不真正的参与计算,而是用来实现模型、求解工具和执行之间进行通信。