3. 模型库架构设计原则

一个 Modelica 模型库能否被长期复用,往往不取决于单个模型写得多精巧,而取决于它的架构是否清晰。架构设计要回答的核心问题是:模型放在哪里、叫什么名字、对外暴露什么、内部如何实现、以后怎么加新东西、怎么改而不破坏别人。本节围绕包结构、命名空间、接口与实现分离、可扩展性、可维护性和版本管理初步展开,目标是让读者能规划出一个可交付、可演进的库骨架。

包结构:用目录层级表达领域分解

Modelica 中 package 既是命名空间,也对应文件系统中的目录。一个库通常以顶层包为根,向下按“领域—子系统—部件—基础类”逐层分解。以某热管理库 ThermalLib 为例,可采用如下结构:

ThermalLib/
  package.mo            // 顶层包,含 uses 与版本注解
  UsersGuide/           // 文档与示例说明
  Examples/             // 可直接仿真的系统级示例
  Interfaces/           // 接口、连接器、部分模型
  Media/                // 介质属性
  Components/
    Pumps/
    Valves/
    HeatExchangers/
  Sources/              // 边界条件与激励
  Sensors/              // 测量与信号输出
  Utilities/            // 函数、常量、枚举

分解粒度要服务于复用:Interfaces 放连接器和 partial 基类,Components 放可替换的具体实现,Examples 放验证用例。判断结构是否合理,可以看“新增一个换热器型号”是否只需在 HeatExchangers 下加一个文件,而不必改动其它目录。

命名空间:让名字可预测、可定位

命名空间的价值在于唯一性和可读性。建议遵循“从一般到具体”的命名顺序,类名用大驼峰,实例名用小驼峰,连接器类型以 Port 结尾。例如 ThermalLib.Components.HeatExchangers.PlateHE 一眼可知其归属。库内引用优先使用相对路径(如 Interfaces.FluidPort),跨库引用使用完整路径或 import:

import Modelica.SIunits.Temperature;
import ThermalLib.Interfaces.FluidPort;

要避免把实现细节暴露在顶层命名空间,也不要在不同层级重复同名类。命名一旦发布就应视为契约,改名会直接破坏下游模型。

接口与实现分离:替换实现而不动系统

这是库可复用的关键。做法是先用 partial model 或 connector 定义“对外长什么样”,再让具体模型 extends 它。例如定义泵的接口基类:

partial model PartialPump
  replaceable package Medium = ThermalLib.Media.Water;
  Interfaces.FluidPort_a port_a;
  Interfaces.FluidPort_b port_b;
  Modelica.Blocks.Interfaces.RealInput N_set;
  parameter Real etaNom = 0.7;
end PartialPump;

具体泵 CentrifugalPump 继承该基类并实现方程。系统模型只依赖 PartialPump,通过 replaceable 与 redeclare 在装配时选择型号。这样接口稳定、实现可换,验证用例也能复用同一套连接关系。

ThermalLib 架构:接口稳定、实现可替换 ThermalLib(顶层包) Interfaces(接口层) FluidPort_a / FluidPort_b PartialPump / PartialHX Medium 可替换包 Components(实现层) CentrifugalPump PlateHE / ShellTubeHE ValveLinear / ValveEqual% Examples(验证层) CoolingLoop PumpCurveCheck HXRatingTest extends 实例化 装配期替换:redeclare package Medium = Glycol50;redeclare CentrifugalPump pump 系统模型只依赖 Interfaces,换型号不改连接与方程 版本管理:version="1.2.0" + uses(ThermalLib(version="1.2.0")) 主版本变更 = 接口不兼容;次版本 = 新增兼容;修订 = 修正

可扩展性与可维护性:为变化留出位置

可扩展性体现在“加新实现不改老代码”。常用手段包括:用 replaceable 声明可替换部件、用枚举或 choices 限定可选实现、把公共参数上提到基类。可维护性则要求:每个类职责单一、方程与参数有注释、单位统一使用 Modelica.SIunits、避免在多个文件中复制同一段方程。一个实用检查是——若某参数在三个以上模型中重复出现,就应上提到 partial 基类或 Utilities 常量中。

下面给出一个可填写的库骨架检查表,用于在提交前快速自检:

检查项合格判据常见问题
包结构领域分解清晰,Interfaces/Components/Examples 分离所有模型堆在顶层
命名空间类名唯一、路径可预测、无重名跨层同名、随意缩写
接口分离系统只依赖 partial/connector直接依赖具体型号
可扩展新增型号仅加文件,不改系统改基类导致连锁修改
可维护单位统一、注释完整、无重复方程硬编码数值、缺注释
版本version 注解与 uses 一致,变更记录可查无版本号、静默改接口

版本管理初步:把接口当契约

Modelica 库通过 annotation(version="1.2.0") 声明自身版本,通过 uses(ThermalLib(version="1.2.0")) 声明依赖版本。建议采用语义化版本:主版本号变更表示接口不兼容(如删除连接器、改参数名),次版本号表示向后兼容的新增(如新增泵型号),修订号表示不改变接口的修正(如修方程、改注释)。发布时同步更新 UsersGuide 中的变更记录,并在 Examples 中保留可回归的验证用例。这样,下游用户升级前就能判断风险,库也具备了持续演进的基础。

实践建议:先冻结 Interfaces 层,再并行开发 Components;每次发布前用 Examples 全量仿真一遍,确认接口未破坏、结果仍在预期范围内。