# 模型库开发规范
模型库的开发过程中需要遵循相应的开发规范,以确保模型库的高质量和可扩展性,并方便其进行集成和管理。
# 模型库组织结构规范
清晰的模型库层次架构,能够让模型库具有很强的可重用性和重构性,能够全面直观的展示模型库信息,方便用户在此基础上进行快速的应用、完善和拓展。 架构设计中引入 Package 的概念帮助组织 Modelica 模型中的 models、connectors 等元件,将相关的模型有机地组合在一起。将一个领域中的元件及接口组织在一起的 Package 就叫做“库”。这些库往往是以一个整体的形式被引用,但是库中总是包含若干个子模型库,就模型库的逻辑结构内容,可参考如下:
| 名称 | 描述 | 说明 | |
|---|---|---|---|
| UsersGuide | 用户指导 | 模型库介绍、版本信息、作者信息及其他信息 | |
| Common(可分开) | Types | 类型 | 存放模型库中所有自定义类型 |
| Interfaces | 接口 | 模型接口,存放 connector 连接器模型 | |
| Functions | 函数 | 存放模型库中所有函数 | |
| Icons | 图标 | 存放模型库中所有模型图标 | |
| Resources | 外部函数 | 包含 Include、Library 子目录存放外部函数用以集成 Fortran、C 代码,以及 lib、dll 等函数库 | |
| AeroPowerSystem(视开发内容而定) | 航空动力装置模型库 | 基于子系统 SubSystems、组件 Components、基础元件 Basics 层次由高向低划分的系统模型库 | |
| ControlSystem(视开发内容而定) | 控制系统模型库 | 基于子系统 SubSystems、组件 Components、基础元件 Basics 层次由高向低划分的系统模型库 | |
| HydraulicSystem(视开发内容而定) | 液压系统模型库 | 基于子系统 SubSystems、组件 Components、基础元件 Basics层次由高向低划分的系统模型库 | |
| …… | …… | …… | |
| Experiments | 示例 | 系统模型示例集,主要包括各种仿真工况下的仿真模型 | |
| Tests | 测试 | 模型测试用例,用于模型开发过程中的测试,在模型库交付时移除该内容 | |
以航空发动机多物理领域模型库为示例,模型库结构如下图所示:
当模型依赖外部资源时,如图片、数据文件、C 代码等,需要保证模型对资源的引用路径为相对路径,建议在模型库 Package 文件夹下新建 Resources 文件,并按类别存放对应的文件,如下为外部动态库的存放示例:
# 模型编码规范
# 命名
命名需要在减少命名冲突的基础上增强模型代码的可读性。
- 减少命名冲突:建模过程中需要定义的参量、变量及系统自带的标识符和关键字之间应避免命名冲突。如:A 常用于表示面积、截面积等,因而在整个模型库中应该尽量减少字母 A 被用于其他含义的变量命名;
- 增强模型代码的可读性:对参数和变量的命名,除了可以方便地进行方程代码的书写,实现物理模型的行为外,还需要能够使读者快速理解该参数、变量的含义或者作用,更快地理解整个模型,因此其参数、变量的命名最好与其定义相对应,如长度的命名常常用单词 length 或者直接用大写字母 L 表示。
命名规则如下:
类命名
- 对于一个或多个单词全拼组成的类名,每个单词首字母应大写,如 Exampe、ExanplePackeg、PartialModel 等;
- 对于存在大写简写元素的类,为避免引起歧义,每个独立元素之间用下划线连接,如 AD_Conversion(数模转换器)等;
- 对于类的实例化。首字母应小写,其它遵循以上原则,如 example、examplePackage 等。
参数或变量命名
- 变量的名字尽量能显示出变量的含义;
- 对于一个单词的参数或变量名,一般均采用小写字母,如 height、area等;
- 对于多个单词组成的参数或变量名,每个单词之间用下划线隔开,angles_start、real_time等;
- 对于只有一个字母的参数或变量名,其命名需根据实际情况确定,如:T(温度)、I (转动惯量)、t(时间)等。
连接器命名
- 对于标准库(Modelica3.2 标准库及以上版本)中已存在的连接器,可直接继承使用,无需再另行定义,如:电气 Pin;机械 Flange_a、Flange_b 等;
- 对于需新定义的连接器及变量命名,须遵循类命名、参数和变量命名规则。
常用航空术语命名规范
航空领域有着自己的专业术语与缩写,收集此类名词并合理运用到 Modelica 建模中,可以避免命名过于冗长,使 Modelica 模型库更为专业化,参见《航空专业英语缩写索引》、《英汉航空航天工程词典》及相关设计规范文档,具体根据项目研发定制统一的命名规范。
| 缩写 | 解释 | 全称 |
|---|---|---|
| APU | 辅助动力装置 | Auxiliary Power Unit |
| ATS | 自动油门系统 | Autothrottle System |
| EEC | 发动机电子控制器 | Electronic Engine Control |
| EGT | 排气温度 | Exhaust Gas Temperature |
| …… | …… | …… |
# 模型行为和方程
对于一个物理系统而言,各组成部分内部及各组成部分之间的物理关系本身并没有因果性,因此,模型中应当是对模型行为的自然描述而无需考虑计算顺序。这种基于方程的建模方式称为陈述式建模,又称为非因果建模,与之相对的是过程式建模或因果性建模。
Modelica 是基于方程的建模语言,在上述的类型定义中可以看到,中间有明确的行为区域用于以方程来描述模型行为,作为对陈述式建模的补充,Modelica 同时支持过程式建模方法。
陈述式建模的特点之一是通过方程而非赋值来描述模型行为。Modelica 支持陈述式/过程式混合建模,分别以 equation 和 algorithm 来分别描述方程和赋值,区别在于,equation 定义的方程组间的求解顺序将由软件推断确定,而 algorithm 定义的则按照定义顺序进行求解。例如:
- 陈述式建模
model BasedOnEquation
Real x;
Real y;
Real z;
equation
x + y + z = 1;
x + 2 * z = y;
x - y = time;
end BasedOnEquation;
- 过程式建模
model BaseOnAlgorithm
Real x;
Real y;
Real z;
algorithm
z := -time / 2;
y := (1 - z - time) / 2;
x := 1 - y - z;
end BaseOnAlgorithm;
陈述式建模的最大优点是:用户建模时只需专注于物理问题的陈述,而无需考虑物理问题的错综复杂的求解过程怎样实现,因而建模更加简单,所建模型更加健壮。
对一个物理系统而言,其各组成部分内部及各组成部分之间的物理关系本身就是非因果的,这与 Modelica 语言倡导的陈述式建模理念是完全吻合的。
# 代码结构
为了实现模型库编码风格的统一,模型库创建过程中应遵循如下的 Modelica 模型编码顺序:
- 继承类语句,如 import、extend、outer等;
- 模型参数,parameter;
- 模型变量;
- 模型接口,FluidPort_a/flange_a;
- 初始方程,initial equation;
- 方程和算法,equation、algorithm。
具体代码结构示例如下形式:
model FixedDoubleActingCylinder "缸体固定式双作用液压缸"
//第一部分:继承类语句如import、extend、outer等;
extends Utilities.Icons.FixedDoubleActingCylinder2;
extends Components.BasicModels.TwoPortsCylinder_piston;
//第二部分:模型参数,parameter;
parameter SI.Diameter D = 0.05 "活塞直径"
annotation (Dialog(tab = "结构参数",group = "基本参数"));
parameter SI.Diameter d = 0.024 "活塞杆直径"
annotation (Dialog(tab = "结构参数",group = "基本参数"));
……
//第三部分:模型变量;
SI.Length s(start = initialPosition) "活塞位移";
SI.Velocity v "活塞运动速度";
SI.Acceleration a "活塞运动加速度";
……
//第四部分:模型的接口;
Modelica.Mechanics.Translational.Interfaces.Flange_a flange_a固体接口
annotation (…)
……
//第五部分:初始方程,initial equation;
initial equation
v = 0"活塞初始速度";
//第六部分:方程和算法,equation、algorithm;
equation
//速度、加速度方程
v = der(s);
a = der(v);
//左右腔等效容积
effVolume_L = activeArea_L * s + deadVolume;
effVolume_R = activeArea_R * (L - s) + deadVolume;
……
end FixedDoubleActingCylinder;
# 注释
建立的所有类别(package,model,function)都需要相应的注释,一般类注释普遍采用下面的形式,一般用""进行注释,如:
package AeroEngine_HyMo"航空发动机液压元部件模型库"
model Pipe "管道"
……
end Pipe;
function ReynoldsNumber "雷诺数函数"
……
end ReynoldsNumber;
end AeroEngine_HyMo;
# 参变量注释
定义的每个参量,变量都要注释该参变量的含义,增强代码的可读性,注释语尽量简明扼要,一般用""进行注释,如:
parameter SI.Length L = 1 "管道长度";
parameter SI.Diameter d = 0.02 "管道内径";
SI.Area A = d ^ 2 * Constants.pi / 4 "管截面积";
SI.Volume V = L * A "管道容积";
# 方程注释
在模型代码的方程区域,某一个方程的含义或某一部分方程的含义都要注释清楚,一般用//进行注释,如:
Equation
//流量方程
m_flow = sign(dp) * A * Cq * sqrt(2 * rho * noEvent(abs(dp)));
# 参数及参数框设计
# 参数定义
定义模型参数包括参数数据类型、名称、默认值、量纲、必要的描述信息等,参数示例如下:
| 参数类型 | 参数名称 / 默认值 / 量纲 | 参数说明 |
|---|---|---|
| Modelica.SIunits.Length | Stroke = 0.03 | 换向阀行程 |
| Boolean | Init=false | 阀芯初始位置是否由输入决定 |
| Real | Cq=0.7 | 流量系数 |
| … | … | … |
# 参数框定义
参数框中的参数显示都是按照先定义先显示的原则,包括 Tab/Group 的显示,所以参数框的显示最好按照参数的重要程度进行有别显示,进行参数分类显示时一般遵循这样几点原则:
- 参数少,分 Group;
- 参数多,分 Tab;
- 重要共性参数(介质)单独分开,Tab/Group 统一;
- 参数的一般分类:
- 工质参数
- 结构参数
- 初始条件(变量初始化及初始参数)
- ……
参数框设计代码:
parameter SI.Diameter D = 0.05 "活塞直径"
annotation (Dialog(tab = "结构参数", group = "基本参数"));
parameter SI.Diameter d = 0.024 "活塞杆直径"
annotation (Dialog(tab = "结构参数", group = "基本参数"));
parameter SI.Mass m = 0.5 "活塞质量"
annotation (Dialog(tab = "结构参数", group = "基本参数"));
parameter SI.Length L = 2 "活塞行程"
annotation (Dialog(tab = "结构参数", group = "基本参数"));
parameter SI.TranslationalDampingConstant c = 2000 "活塞运动阻尼"
annotation (Dialog(tab = "结构参数", group = "基本参数"));
parameter SI.Volume deadVolume = 1e-6 "死区容积
annotation (Dialog(tab = "限位参数"));
parameter SI.TranslationalSpringConstant c_c = 1e8 "接触刚度"
annotation (Dialog(tab = "限位参数"));
参数框显示结果:
# 接口定义
为避免系统模型集成阶段由接口带来的问题,在系统分析设计初期就需要将接口定义清晰,以及各系统间的连接方式。
接口说明内容包括:模型输入/输出变量的数据类型、维数、名称、量纲、必要的描述信息,接口说明示例如下:
| 接口 | 数据类型 | 名称 | 量纲 | 描述 | 其他说明 |
|---|---|---|---|---|---|
| 输入 | Real[1,1] | H | m | 飞行高度 | 高度表接口 |
| Real[1,1] | Ma | 1 | 飞行马赫数 | 空速表接口 | |
| Real[1,1] | TLADeg | deg | 油门杆角度 | / | |
| … | … | … | … | … | |
| 输出 | Real[1,1] | qm_f | kg/s | 燃油流量 | / |
| … | … | … | … | … |
针对特定行业接口主要包含机械接口、电接口、热接口、信息接口和流体接口。
# 机械特性接口
- 模型输入接口:
| / | flow变量 | flow变量 | 势变量 | 势变量 |
|---|---|---|---|---|
| 变量类型 | Force | Torque | Position | Frames.Orientation |
| 变量名称 | f[3] | t[3] | r_0[3] | R |
| 描述 | 剪切力 | 剪切力矩 | 从世界坐标系原点到连接点的位置向量(相对世界坐标系) | 将世界坐标系转到连接点的方向向量 |
| 功能 | 机械多体接口,描述了剪切力、剪切力矩和两个方向向量 | |||
- 模型输出接口:
| / | flow变量 | flow变量 | 势变量 | 势变量 |
|---|---|---|---|---|
| 变量类型 | Force | Torque | Position | Frames.Orientation |
| 变量名称 | f[3] | t[3] | r_0[3] | R |
| 描述 | 剪切力 | 剪切力矩 | 从世界坐标系原点到连接点的位置向量(相对世界坐标系) | 将世界坐标系转到连接点的方向向量 |
| 功能 | 机械多体接口,描述了剪切力、剪切力矩和两个方向向量 | |||
# 电特性接口
- 模型输入接口:
| / | flow变量 | 势变量 |
|---|---|---|
| 变量类型 | Current | Voltage |
| 变量名称 | i | v |
| 描述 | 电流 | 电压 |
| 功能 | 用于基本模型中电流和电压的传递 | |
- 模型输出接口:
| / | flow变量 | 势变量 |
|---|---|---|
| 变量类型 | Current | Voltage |
| 变量名称 | i | v |
| 描述 | 电流 | 电压 |
| 功能 | 用于基本模型中电流和电压的传递 | |
# 热特性接口
- 模型输入接口:
| / | flow变量 | 势变量 |
|---|---|---|
| 变量类型 | HeatFlowRate | Temperature |
| 变量名称 | Q_flow | T |
| 描述 | 接口热流量 | 接口温度 |
| 功能 | 用于基本模型中热流量和温度的传递 | |
- 模型输出接口:
| / | flow变量 | 势变量 |
|---|---|---|
| 变量类型 | HeatFlowRate | Temperature |
| 变量名称 | Q_flow | T |
| 描述 | 接口热流量 | 接口温度 |
| 功能 | 用于基本模型中热流量和温度的传递 | |
# 信息特性接口
- 模型输入接口:
| / | 变量类型 | 变量名称 | 描述 | 功能 |
|---|---|---|---|---|
| RealInput | Real | input | 实型信号输入接口 | 实型数据传递 |
| RealOutput | Real | output | 实型信号输出接口 | |
| IntegerInput | Integer | input | 整型信号输入接口 | 整型数据传递 |
| IntegerOutput | Integer | output | 整型信号输出接口 | |
| BooleanInput | Boolean | input | 布尔型信号输入接口 | 布尔型数据传递 |
| BooleanOutput | Boolean | output | 布尔型信号输入接口 |
- 模型输出接口:
| / | 变量类型 | 变量名称 | 描述 | 功能 |
|---|---|---|---|---|
| RealInput | Real | input | 实型信号输入接口 | 实型数据传递 |
| RealOutput | Real | output | 实型信号输出接口 | |
| IntegerInput | Integer | input | 整型信号输入接口 | 整型数据传递 |
| IntegerOutput | Integer | output | 整型信号输出接口 | |
| BooleanInput | Boolean | input | 布尔型信号输入接口 | 布尔型数据传递 |
| BooleanOutput | Boolean | output | 布尔型信号输入接口 |
# 流体特性接口
- 模型输入接口:
| / | flow变量 | 势变量 | Stream变量 | Stream变量 |
|---|---|---|---|---|
| 变量类型 | VolumeFlowRate | AbsolutePressure | SpecificEnthalpy | MassFraction |
| 变量名称 | w | p | h | Xi |
| 描述 | 接口质量流 | 接口压力 | 接口比焓 | 接口组分质量分数 |
| 功能 | 一维流体接口,用于基本模型中流动工质的质量流、压力、比焓和组分的传递 | |||
- 模型输出接口:
| / | flow变量 | 势变量 | Stream变量 | Stream变量 |
|---|---|---|---|---|
| 变量类型 | VolumeFlowRate | AbsolutePressure | SpecificEnthalpy | MassFraction |
| 变量名称 | w | p | h | Xi |
| 描述 | 接口质量流 | 接口压力 | 接口比焓 | 接口组分质量分数 |
| 功能 | 一维流体接口,用于基本模型中流动工质的质量流、压力、比焓和组分的传递 | |||
# 模型图形布局规范
基于组件连接构建系统模型时,应对系统模型进行合理布局,兼顾系统模型的可读性与美观性。注意以下几点:
- 能显示出系统的层次结构,可用画图工具将重要区域标注,并附上简单的文字说明;
- 合理利用空间,各组件连接紧凑,互不干涉;
- 尽量使系统模型结构整体看起来赏心悦目,并显示出其专业性。
可以参考如下模型的布局:
# 模型用户指南编写规范
新建的模型库信息一般都是通过建立 UsersGuide 库进行相应地说明,一般模型库的 UsersGuide 主要分为这样几部分:
- Overview(综述)——模型库特点,构架等;
- UsersGuide(用户指导)——使用说明,开发说明等;
- ReleaseNotes(版本日志)——版本修订日志;
- Help(帮助)——关联用户说明手册或者 FAQ;
- References(参考资料)——模型库建模主要参考资料;
- Contant(联系方式)——开发者的相关信息。
对于任何一个组件模型及系统模型,应给出详尽的说明文档,清楚明了的说明该模型的功能、用法及注意事项。从使用者角度出发对模型简介、模型原理、模型接口、模型参数等方面进行描述,可参见附录A。
- 简介,对模型的功能及用法进行简要描述;
- 原理,阐述模型的结构与原理,以及模型开发所应用到的理论基础、理论公式等信息;
- 接口,包括模型的输入、输出接口的类型、描述信息;
- 参数,包括模型参数的类型、量纲、描述信息。
# 模型工程化实践规范
# 改善模型健壮性
模型编码时需要注意模型的健壮性,不仅要对每个元件进行充分的测试,也需要防止库被误用。
- 输出限幅,最大值、最小值限制等,可使用断言语句或加入限幅组件模型等,如:assert(i*v<1e6,”Maxinum power exceeded”);
- 使用 final 关键字和限制属性;
- 好的文档,给使用者意见和提醒,减少误用。
# 提高仿真效率
尽量使用 equation 如果没有特殊的目的,请尽量使用 equation。原因是在 algorithm 块中,变量可能被赋值多次,使得工具无法对其进行符号分析,提高仿真效率。例如,无法得到求解雅阁比矩阵的函数。
避免不必要的事件 事件会中断积分算法,从而影响仿真速度,因此避免不必要的事件可以较大地提供仿真速度。如:
der(x)= noEvent(if y<0 then 0 else y^2);
- 合适的积分算法
积分算法有自己的适用范围,因此需要模型的特点,采用合适的算法,例如模型是刚性的,则需要采用求解刚性问题的积分算法。
- 合适的误差
误差越小仿真时间越长,结果越可靠,而误差越大仿真速度越快,但结果越不可靠。可以使用不同的误差仿真,比较它们的结果,而确定合适的误差。
- 为函数提供雅阁比函数
对于隐式方程组,分析器使用符号推导,得到求解雅阁比矩阵的函数,避免数据求解。由于分析器不能推导用户自定义函数,因此如果用户为自定义函数提供导数函数,可以提高仿真效率。如:
model JacobianExample
Real x,y;
function f
input Real x;
output Real y;
annotation (derivative=f_Jac);
algorithm
y := sin(x)+cos(x)+x;
end f;
function f_Jac
input Real x;
input Real dx;
output Real dy;
algorithm
dy := dx * (cos(x)-sin(x)+1);
end f_Jac;
equation
der(y) = 2.0;
y = f(x);
end JacobianExample;
- 变量消除
分析器会进行符号处理,消除别名变量。因此用户手动消除别名变量对仿真速度没有影响,而且容易使代码变得不直观。除非有证据表明消除变量对仿真速度有影响,否则不建议手动消除别名变量。如:
model Resistor
import Modelica.SIunits;
import Modelica.Electrical;
//不建议消除//
SIunits.Voltage v "Voltage from pin p to n";
SIunits.Current i "Current entering at pin p";
Electrical.Analog.Interfaces.Pin p "Positive";
//不建议消除//
Electrical.Analog.Interfaces.Pin n "Negative";
parameter SIunits.Resistance R = 300 "Resistance";
//建议消除
equation
v = p.v - n.v;
0 = p.i + n.i;
i = p.i;
i * R = v;
//
//消除后的方程//
R * p.i = p.v - n.v;
p.i + n.i = 0;
end Resistor;
# 模型测试规范
模型测试规范包括模型测试验证流程和结果评价方法。模型测试验证流程用于规范模型测试过程,结果评价方法用于规范模型测试评价结果。
# 测试验证流程
模型验证的总体方法是模型仿真结果文件与可靠数据进行比较判断。其流程如图所示:分别用模型库及系统的物理试验数据或(和)同类软件的仿真结果数据来和仿真结果数据作对比、分析,从而完成模型验证。
对于以上模型验证流程,其数据来源包括三种,第一种为设计文件数据,第二种为同类软件仿真结果数据,第三种为物理试验数据。模型验证的层次分二层,第一层为模型库组件模型的验证,第二层为系统模型的验证。
# 结果评价
组件模型的测试需得到指定的关键数据结果,并且与对应物理试验结果进行比较。具体结果评价方法可参考静态误差与动态误差评价方式。
# 稳态误差
评价方式
对于稳态误差的评价方法,下面提供几种误差衡量指标:
- 平均偏差:根据每个采样时刻的仿真值与实际值之间差值的绝对值与仿真值之间的比值来计算误差百分比,最后通过加权的方式来获取整批数据的误差:
- 最大误差:即为所有采样时刻的仿真值与实际值的最大值。
静态误差的使用适用于稳态过程,即系统的输出数据达到一个固定的稳态值时进行评价。适用于大多数模型的仿真结果评价。
# 动态误差
评价方式
对于动态误差的评价方法,即当输入数据为连续变化时,系统的输出数据没有一个固定的稳态值时,无法计算系统输出的稳态误差,此时,可考虑以累计误差为评价标准进行衡量。

累计误差:取试验、仿真曲线绝对值,通过积分的方式计算绝对值曲线面积与各采样点绝对误差曲线面积来反映误差大小,相当于将每个时刻的误差进行累计。累积误差计算方式如下:
误 差 试 验 仿 真 试 验 试 验 其中
为绝对误差曲线与时间轴所围成的面积,误 差 为试验曲线绝对值与时间轴所围成的面积,试 验 为采样时间, 为对应每个采样的序号。
应用场景示例
如在下列连续变化输入的动态仿真过程中,选择以累计误差评价动态误差的方式,比较合适。
其误差计算结果为:
- 仿真绝对值曲线面积:239.7146
- 试验绝对值曲线面积:247.0526
- 误差计算:3.06%
# 模型库版本管理规范
在模型库构建以及后期维护过程中,存在大量的模型库版本迭代,应对模型库的版本进行管理,确保版本的准确性和可追溯性。
# 版本命名
模型库版本命名主要由 5 部分组成,第一部分为模型库名称,第二部分为主版本号,第三部分为子版本号,第四部分为日期版本号和希腊字母版本号,第五部分为项目缩写名称。希腊字母版本号共有 4 种,分别为 Alpha、Beta、RC、Release。例如:HyMo_1_1_20180810_Release_BJHFYYJM。
- 模型库名称:指用户所构建的模型库名称,通常是系统物理属性等的英文全称或英文简写;
- 主版本号:当模型库由较大变动,如增加多个模块或这整体架构发生变化,此时可根据需要进行修改;
- 子版本号:当模型功能有一定增加或变化,如提高模型粒度等,可根据需要进行修改;
- 日期版本号:用于记录修改时间,每天对模型的修改都需要更改日期版本号;
- Alpha 版:主要指模型以实现功能为主,该版本模型存在较多问题,需进行修改;
- Beta 版:较 Alpha 版修改了严重问题,但仍存在一定缺陷,需要经过多次测试来进一步消除;
- RC 版:该版本相对成熟,已修正了绝大部分错误,与最终版本接近;
- Release 版:经过多轮修改后的最终版本。
# 版本升级
主要针对主版本号和子版本号,其基数均为 0 或 1,在每一次模型版本发生变更时,均在当前版本号上加 1,并以文本或其它形式标注每个版本号对应的变更内容。