2. Modelica语言基础
Modelica 是一种面向对象的、非因果的物理系统建模语言。与传统的因果建模语言(如 Simulink 中信号从输入流向输出)不同,Modelica 的核心思想是用方程描述物理规律,由编译器自动决定求解顺序。理解变量与参数声明、数据类型、方程与算法段、初始方程、注释与单位这五个基础要素,是写出可运行、可复用模型的前提。本节以“是什么—怎么写—如何判断正确”为主线,配合一个机械与电气系统的建模示例,帮助读者建立第一手的建模直觉。
一、变量与参数声明
在 Modelica 中,所有物理量都必须先声明类型,再使用。声明的基本形式是 类型 修饰符 变量名(单位, 初值, 取值范围)。其中最常见的两类是 parameter 与普通变量:
- parameter(参数):在仿真开始前由用户赋值,仿真过程中保持不变。例如质量
parameter Real m = 1.0、电阻parameter Real R = 10。参数是模型的“可配置接口”。 - 变量(variable):仿真过程中随时间变化,由方程求解得到。例如速度
Real v、电流Real i。 - 常量 constant:编译期确定,如
constant Real g = 9.80665。
修饰符 input、output 用于定义模型的对外接口;flow、stream 用于连接器中的守恒量。初学者最容易犯的错误是把本应作为参数的物理量写成普通变量,导致模型无法配置;或者把本应求解的变量写成参数,导致方程数不足。
二、数据类型
Modelica 内置了丰富的数据类型,常用的有:
| 类型 | 含义 | 典型用途 |
|---|---|---|
| Real | 实数(连续量) | 位移、速度、电压、电流 |
| Integer | 整数 | 计数、状态编号 |
| Boolean | 布尔量 | 开关状态、事件条件 |
| String | 字符串 | 标签、注释信息 |
| enumeration | 枚举 | 离散工作模式 |
此外,Modelica 标准库还提供了带单位的类型,如 Modelica.Units.SI.Length、Modelica.Units.SI.Voltage。使用带单位类型可以让编译器进行量纲检查,避免“把电压当电流用”这类低级错误。数组、记录(record)和连接器(connector)也是常用结构,连接器本质上是一种特殊的记录类型,用于在组件之间传递物理量。
三、方程与算法段
Modelica 的方程段(equation section)是模型的主体,用 equation 关键字引导。方程是声明式的,等号两边没有“赋值”含义,而是表示“两边相等”。例如:
model MassSpring
parameter Real m = 1.0;
parameter Real k = 10.0;
Real x(start = 1.0);
Real v;
equation
der(x) = v;
m * der(v) = -k * x;
end MassSpring;
这里 der(x) 表示 x 对时间的导数。两个方程、两个未知量 x 和 v,系统可解。注意:方程数量必须与未知量数量匹配,否则编译报错。
算法段(algorithm section)则用 algorithm 引导,是命令式的,按顺序执行赋值语句,常用于实现离散逻辑、查表或迭代计算。例如:
algorithm
if x > 0 then
y := 1;
else
y := -1;
end if;
经验规则:能用方程表达物理规律时优先用方程,因为方程更利于符号求解和复用;只有在需要显式控制流程(如状态机、条件分支)时才使用算法段。
四、初始方程
动态模型需要初始条件才能求解。Modelica 提供 initial equation 段专门用于设定初始状态,例如:
initial equation
x = 1.0;
v = 0.0;
如果不写初始方程,编译器会尝试用变量的 start 属性作为初值,但这只是“建议值”,不保证满足所有约束。对于高阶系统或存在代数环的模型,显式写出初始方程能显著提高求解成功率。判断初始条件是否合理的方法是:检查初始时刻所有方程是否同时成立,以及初始加速度是否与物理直觉一致。
五、注释与单位
Modelica 支持两种注释:// 单行注释和 /* ... */ 多行注释。更重要的是注解(annotation),它以 annotation(...) 形式出现,用于给工具传递元信息,如图标、文档、实验设置:
annotation(
Icon(graphics = {Rectangle(extent = {{-100,100},{100,-100}})}),
experiment(StartTime = 0, StopTime = 10, Tolerance = 1e-6)
);
单位信息通常写在变量声明的括号里,如 Real v(unit = "m/s")。配合 displayUnit 可以在结果查看器中自动换算显示单位。养成“每个物理量都写单位”的习惯,是工程级模型的基本素养。
六、简单机械与电气系统建模示例
下面给出一个“质量—弹簧—阻尼”机械系统与“电阻—电感—电容”电气系统的对照示例。两者在数学结构上完全同构,这正是 Modelica 跨领域建模能力的体现。
model MechanicalSystem
parameter Real m = 1.0 "质量 kg";
parameter Real c = 0.5 "阻尼 N·s/m";
parameter Real k = 10.0 "刚度 N/m";
Real x(start = 1.0) "位移 m";
Real v "速度 m/s";
equation
der(x) = v;
m * der(v) = -c * v - k * x;
end MechanicalSystem;
model ElectricalSystem
parameter Real L = 1.0 "电感 H";
parameter Real R = 0.5 "电阻 Ω";
parameter Real C = 0.1 "电容 F";
Real q(start = 1.0) "电荷 C";
Real i "电流 A";
equation
der(q) = i;
L * der(i) = -R * i - q / C;
end ElectricalSystem;
两个模型的方程形式完全一致:der(状态) = 速度类变量,惯性系数 * der(速度) = -阻尼项 - 刚度项。机械系统中 m 对应电感 L,c 对应电阻 R,k 对应 1/C。仿真时间设为 0~10 s,容差 1e-6,可以观察到欠阻尼振荡衰减过程。判断结果是否合理:位移从 1 m 出发,经过若干次振荡后趋于 0,且振荡周期约为 2π√(m/k) ≈ 1.99 s,与理论值一致。
dassl 仿真,然后在绘图窗口同时绘制 x 与 q,观察两条曲线是否重合。若重合,说明两个系统确实同构;若偏差较大,检查参数单位是否统一。der(x) = v 导致方程数不足;把 parameter 写成普通变量导致无法配置;单位混用(如把 mm 当 m)导致数值异常。编译报错时优先检查“方程数与未知量数是否相等”。