22 KiB
组件模型建模规范 v1
状态:2026-09-10 更新为 Python 声明、C 数值实现 适用对象:人工开发者、代码生成工具和 AI 编程助手 配套读取规范:组件库分类、发现与读取规范 v1 端口供需规范:气动端口变量供需合同
1. 文档目标
本文档规定采用 Python 元数据与 C 数值内核的元件应如何创建、修改、测试和注册。完成后的模型必须 同时满足四个使用方:
- C 编译器能够读取模型声明、生成系统代码并调用 C 方程。
- System XML 能够根据稳定类型找到模型。
- React Flow 能够自动显示图标、端口和参数。
- 结果页面能够根据结构化元数据展示变量。
本文档是模型代码的开发合同。若本文档与当前代码行为不一致,应把它视为缺陷: 先核对实际实现,再在同一次修改中同步代码、测试和文档,禁止让两套规则长期并存。
2. 开始前先判断任务类型
2.1 新增公开模型
公开模型会出现在前端组件库中,也能被 System XML 创建。必须:
- 放入某个组件库的分类目录。
- 实现完整模型契约。
- 加入该库
library.py的models清单。 - 添加目录、契约、方程和最小仿真测试。
2.2 修改已有公开模型
必须先判断改动是否破坏已有工程:
| 改动 | 版本建议 | 兼容性要求 |
|---|---|---|
| 修复数值实现但不改变契约 | 修订版本 | 若提高 modelVersion,既有 XML 会因精确版本不匹配而被拒绝;需明确是否真的变更合同 |
| 新增有默认值的参数或结果 | 次版本 | 新 XML 必须写全当前参数;本阶段不提供旧文件自动迁移 |
| 修改界面名称或图标 | 库修订版本 | 不修改机器标识 |
| 修改方程的物理语义 | 根据影响提高次版本或主版本 | 补充基准和变更说明 |
| 删除、改名端口或参数 | 主版本 | 当前格式直接拒绝旧端口或参数;如以后需要兼容,再单独设计迁移器 |
修改 MODEL_TYPE |
视为新模型 | 旧类型必须保留迁移映射 |
2.3 新增内部模型
不进入前端目录的研究模型不加入 library.py。需要执行时仍应编写 C 内核并显式纳入编译器支持合同;不要恢复旧 Python 求解路径。
2.4 新增物理域
仅新增模型类不足以支持新物理域。除了模型,还必须设计:
PortDefinition和端口变量。- 变量角色与连接规则。
- 网络兼容性检查。
- 代数方程和 stream/signal 传播。
- XML 端口协议。
- 前端连线兼容规则。
- 最小闭合系统与求解测试。
没有完成这些基础能力时,不得仅通过修改 domain 字符串宣称支持新物理域。
3. 开发前必须读取的文件
人工或 AI 在修改模型前,应按顺序读取:
- 本文档。
- 目标库的
library.py。 - 同分类中物理行为最接近的现有模型。
core/base.py。core/ports.py。core/metadata.py。core/catalog.py。registry.py中的启动校验。- 与目标模型最接近的测试。
不要只根据文件名、前端图标或旧 XML 猜测模型语义。
4. 文件位置和命名
公开模型放在:
app/simulation/components/<library_id>/<category_id>/<model_module>.py
例如:
app/simulation/components/experimental/storage/cylinder.py
app/simulation/components/experimental/flow/orifice.py
app/simulation/components/experimental/junctions/tee.py
规则:
- 一个公开模型原则上对应一个文件和一个主要模型类。
- 模块名、
MODEL_TYPE、端口名和参数名使用稳定机器标识。 MODEL_TYPE使用小写snake_case。- 参数和结果变量允许保留已有热力学惯例,如
T0、T、U。 - 中文名称只写入
label,不能代替机器标识。 - 求解器、介质和网络通用逻辑不得复制到模型文件。
5. 公开模型完整契约
每个公开模型类必须在自身类体中显式声明:
MODEL_TYPE = "example_component"
MODEL_VERSION = "1.0.0"
PORTS = (...)
PARAMETERS = (...)
RESULT_VARIABLES = (...)
DISPLAY = ...
同时必须实现:
@classmethod
def create(
cls,
*,
name: str,
medium: IdealGasMedium,
parameters: Mapping[str, float],
) -> Component:
...
注册器要求这些字段直接存在于公开模型类中。不要依赖父类隐式提供
MODEL_TYPE、MODEL_VERSION、PORTS、PARAMETERS、RESULT_VARIABLES、
DISPLAY 或 create()。
6. 基类选择
AlgebraicComponent 表示没有积分状态的元件;DynamicComponent 表示有积分状态的元件;ThermodynamicVolumeComponent 提供标准 m,U,p,T,rho,u,h 结果声明。这些基类只描述模型,不再实现数值求值方法。
构造函数负责参数校验、几何预处理和端口注册。介质对象保存物性常量与模型选择。状态初值、流量、焓、受力和导数必须在 C 中计算。
用 EQUATIONS 或 equation_definitions() 声明结构化连接约束,返回 EquationDefinition,包括关系、变量和归属,不包含运行时残差值。__MODEL__ 占位符由基类替换为实例名。该声明供网络结构展示与检查使用,不替代 C 方程或构建支持白名单。
7. 端口建模规范
当前气动模型使用:
PortDefinition.pneumatic(
"port_a",
nominal_role="bidirectional",
computation=THERMODYNAMIC_SUPPLY,
)
上例适用于提供温度/压力的储气端,THERMODYNAMIC_SUPPLY 从 core.port_computation 导入。阀门或管道阻力端应按实际模型选择 FLOW_SUPPLY;不能给所有气动端口套用同一个供需模板。
气动端口包含:
| 变量 | 角色 | 连接规则 | SI 单位 |
|---|---|---|---|
p |
effort |
equal |
Pa |
m_flow |
flow |
sumToZero |
kg/s |
h_outflow |
stream |
streamMix |
J/kg |
volume |
signal |
directed |
m3 |
volume_flow |
signal |
directed |
m3/s |
必须遵守:
m_flow > 0表示质量流入当前组件。nominal_role只用于界面和默认布局,不限制实际流向。- 物理连接的端点顺序不代表流向;具体子模型仍可规定固定的变量供需,例如 PN3NODE2 的参考口。
- 所有声明端口必须使用
register_declared_port()创建。 DISPLAY.ports必须与PORTS名称集合完全一致。- 分支连接使用三通等连接元件,不能让一个物理端口直接连接多条边。
禁止:
- 在模型内部根据画布左右方向判断流向。
- 为了前端显示另造一套端口名。
- 把
port_a固定解释为真实入口、把port_b固定解释为真实出口。 - 直接绕过端口状态读写其他组件对象。
7.1 新元件先写逐变量接口表
新模型必须先在模型说明中列明每个端口的下列信息,再写元数据和 C 代码:
| 信息 | 必须回答的问题 |
|---|---|
| 物理含义、机器名、SI 单位 | 传递的是温度还是比焓?能量还是能量流率? |
| 提供方/使用方 | 该变量由本部件提供、从对端取得,还是需要连接方程共同确定? |
| 提供方式 | 来自当前状态、固定值、另一个端口的别名,还是由公式计算? |
| 计算依赖 | 计算该输出具体需要哪些输入、状态和参数?不要只写“依赖某部件”。 |
| 符号与坐标 | 正号代表流入还是流出?机械量采用什么方向?映射原模型时是否取反? |
| 必需性及默认值 | 缺少对端变量时能否用有物理依据的默认值?何时应当报错? |
| 条件变化 | 参数是否改变可用端口、输入输出关系?反向流、零流量或切换时怎样处理? |
固定参数放在 PARAMETERS,例如管径、长度、初始温度 T0;随仿真变化的端口量放在接口定义中,例如当前温度 T。固定开度变体可以有意用参数代替开度信号,但应使用独立模型类型并说明差异。
7.2 供需声明与当前实现边界
PORTS 是权威来源。当前 PortComputation 的 inputs/outputs 支持 p、T、m_flow、H_flow 四个气动量;reference_port 只表达 p/T 从另一个端口输入复制的关系。前端目录与 JSON/XML 校验从注册表恢复这些声明,工程快照不能覆盖它们。
H_flow 表示能量流率(W),只用于当前接口供需检查,不能当作已经存在的 C 运行时端口字段;运行时仍使用 h_outflow 和质量流率。两种表达的单位、符号及零流量处理必须在 C 方程中正确转换。
mode="fixed"表示该子模型的接口供需是固定要求;它不表示输出数值为常量,也不是固定积分步长。mode="equation"表示允许连接方程联合确定变量。必须有相应 C 求解能力支持,不得为了绕过错误接线而随意改为此模式。- 新移植部件如有明确的固定输入输出,应按原始接口声明并验证。现有非节点部件采用
equation是本阶段保留已有联合求解能力的策略,不能把它当作所有 Amesim 子模型的原始接口定义。 - 新模型需要声明容积、机械量、任意输出依赖或可选输入默认值时,应先同步扩展供需数据结构、注册器、目录 schema、前后端检查与测试。当前四变量接口尚不能完整承载这些信息,不得只在注释或 JSON 中添加编译器不读取的字段。
7.3 从 Amesim 移植时的对照要求
以明确的 Amesim 版本和子模型编号为依据读取端口变量表及其实现;图标相同或端口数量相同不足以证明模型等价。每个原始变量都应有映射记录:保留、换名、单位/符号变换、由其他量导出、仅保留默认值,或明确不支持。
既要记录普通输入/输出,也要记录状态、固定输出、别名、取反别名、可选输入及默认值。例如 PNCH012 的容积输入和 MECMAS21 的加速度端口量,不能因为当前四变量气动模板没有对应字段就不作说明。
接口方向对齐、局部公式对齐和完整仿真曲线对齐是三项不同的验证;不能用其中一项替代其他两项。实验组件及自行简化的变体,不应宣称与 Amesim 原子模型一比一相同。
7.4 为计算排序准备元件步骤
元件说明和 C 接入应区分:状态/物性输出、连接量与局部代数计算、状态导数、展示输出。例如储气元件先由当前状态提供温度和压力,得到流量后再算导数,不能把整个元件当作一个不可拆分的步骤。
端口供需合同不承载任意计算步骤的依赖图。当前扩展 C 生成器使用 Computation 记录内置气动方程的输入、输出与 C 语句,再自动排序及划分局部循环。新模型须显式接入这些计算关系;只注册 PORTS/PARAMETERS 不会自动生成数值方程。参考值复制与能量汇总应拆开,多输出 C 调用必须正确列出读取参数与写出结果,见 C 求值排序规范。
新增或修改接口至少验证:合法连接、输入无人提供、冲突连接、参考链及参考环、反向/零流量、可选输入默认值、单位/符号映射,以及独立解析或外部基准下的 C 结果。没有对应机制的能力必须标记为尚未支持。
8. 参数建模规范
所有用户可配置输入必须使用 ParameterDefinition:
ParameterDefinition(
name="volume",
label="容积",
quantity="volume",
unit="m3",
default=0.1,
minimum=0.0,
minimum_exclusive=True,
)
字段含义:
| 字段 | 规则 |
|---|---|
name |
稳定机器名,同时用于 XML、工程文件和 create() |
label |
前端显示名称,不能为空 |
quantity |
受控物理量标识 |
unit |
后端 SI 基准单位 |
default |
必须能够创建有效模型 |
minimum / maximum |
必须反映方程有效范围 |
minimum_exclusive |
用于直径、容积等严格大于零的量 |
当前受控单位定义在 SI_UNIT_BY_QUANTITY:
| quantity | SI 单位 |
|---|---|
acceleration |
m/s2 |
area |
m2 |
dimensionless |
空字符串 |
density |
kg/m³ |
flow_coefficient |
kg/(s*Pa^0.5) |
force |
N |
heat_transfer_coefficient |
W/(m2*K) |
internal_energy |
J |
length |
m |
mass |
kg |
mass_flow |
kg/s |
pressure |
Pa |
specific_enthalpy |
J/kg |
specific_internal_energy |
J/kg |
temperature |
K |
time |
s |
translational_damping |
N/(m/s) |
translational_stiffness |
N/m |
velocity |
m/s |
volume |
m3 |
volume_flow |
m3/s |
windage |
N/(m/s)^2 |
新增物理量时必须先扩展后端受控单位表,再评估前端是否需要单位换算选项。禁止在
单个模型中私自拼写新的同义 quantity。
构造函数必须调用:
self.set_parameter_values(
{
"volume": volume,
"p0": p0,
"T0": T0,
}
)
保存值、方程计算和结果输出都使用 SI。前端显示单位变化不能改变后端参数语义。
9. 结果变量规范
9.1 组件级结果
组件自身状态或派生量使用 ResultVariableDefinition:
ResultVariableDefinition(
name="pressure_drop",
label="压降",
quantity="pressure",
unit="Pa",
category="derived",
order=10,
)
声明的每个输出必须在 C 生成器的输出布局中有对应值。测试应核对实际 EXE 输出键与 result_variable_metadata() 一致,不再实现 Python component_result_values()。
9.2 端口结果
端口结果由 PORTS 的端口变量自动产生,不要在 RESULT_VARIABLES 中重复声明
port_a.p、port_a.m_flow 等字段。
9.3 禁止暴露的内容
以下内容默认不能作为用户结果:
- 非线性求解器内部未知量索引。
- 缩放残差和迭代缓存。
- 仅用于调试的临时中间值。
- 可以由已有结果稳定推导、但没有明确工程用途的重复字段。
10. 显示声明规范
公开模型必须声明 DISPLAY:
DISPLAY = ComponentDisplaySpec(
label="示例阻力元件",
library_id="experimental",
category_id="flow",
symbol="generic",
ports=(
PortDisplaySpec("port_a", "left", order=10),
PortDisplaySpec("port_b", "right", order=20),
),
order=90,
)
规则:
library_id必须等于所属库 ID。category_id必须存在于所属库的categories。symbol是前端图形键,不是模型类型。- 未实现专用图标时使用新的稳定键,前端会回退到通用图形。
- 只有确实需要专用工程图标时才修改前端图标渲染器。
side只允许left或right。- 旋转和镜像不能改变端口名或物理语义。
11. 标准创建入口
create() 是注册器创建模型的唯一入口:
@classmethod
def create(
cls,
*,
name: str,
medium: IdealGasMedium,
parameters: Mapping[str, float],
) -> ExampleComponent:
return cls(
name=name,
medium=medium,
coefficient=parameters["coefficient"],
)
注册器会在调用前:
- 补齐默认参数。
- 拒绝未知参数。
- 检查有限值和边界。
调用后还会检查:
- 返回对象类型正确。
- 实例
model_type与MODEL_TYPE一致。 - 实际端口与
PORTS完全一致。 - 实例保存的参数与规范化参数完全一致。
create() 不应重复实现参数默认值和边界校验,也不能静默修改传入参数。
12. C 方程实现要求
- 在
native/components/kernels.c及native/include/kernels.h实现物性或元件数值公式。 - 在
native_codegen/extended.py注册状态、端口、参数、初始化与输出映射;符合简单拓扑的模型还应核对compiler.py快速路径。 - 在
native_codegen/contracts.py声明支持版本,不允许仅注册 Python 模型就声称具备 C 求解能力。 - 当前状态与试探状态分离,求值不能覆盖已接受状态。无效物性、欠定连接和不收敛必须明确失败。
- 信号跳变和限位事件接入 C 运行库;不能改动刚度、阻尼或容差来隐藏数值错误。
- 保持 SI 单位和端口流入为正,核对逆流、质量/能量守恒及边界状态。
13. 模型实现示例
可参照 气瓶声明、气腔声明、C 内核 与 系统 C 生成器。完整开发顺序见 组件目录说明。
Python create() 只创建经校验的描述对象;C model_init() 生成质量、能量及机械状态,model_eval() 计算导数和输出。两者通过生成的状态/参数布局关联。
14. 注册模型
模型文件完成后,只修改所属库的 library.py:
models=(
# 已有模型
"app.simulation.components.experimental.flow.example_restriction:ExampleRestriction",
)
禁止:
- 直接修改
COMPONENT_MODEL_REGISTRY。 - 在前端复制参数和端口定义作为正式来源。
- 递归扫描组件目录自动导入所有
.py。 - 同时注册两个相同
MODEL_TYPE。 - 把测试类、抽象基类或内部算例模型加入公开清单。
15. 测试要求
每个公开模型至少添加:
- 静态契约测试。
- 默认参数创建测试。
- 参数边界测试。
- 端口与显示布局一致性测试。
- C 方程与独立解析解或冻结参考值对照。
- 零流量或反向流动测试。
- 目录输出测试。
- 最小 XML 编译测试。
- 使用 C RK45/BDF 的短时仿真与事件测试。
推荐先运行:
.\.venv-win\Scripts\python.exe -m unittest `
tests.test_component_registry `
tests.test_component_catalog `
tests.test_component_metadata
然后运行完整回归:
.\.venv-win\Scripts\python.exe -m unittest discover -s tests
目录契约影响前端时还要运行:
cd frontend
$env:Path = 'F:\Master\SystemSimulationApp\.tools\node-v24.18.0-win-x64;' + $env:Path
npm.cmd run build
16. 修改已有模型的安全步骤
- 找到
MODEL_TYPE的所有 XML、工程和测试引用。 - 记录修改前的端口、参数、结果和默认行为。
- 判断版本级别和是否需要迁移。
- 先增加或修改测试,明确预期物理行为。
- 修改模型类,不在注册器和前端复制规则。
- 检查默认实例和旧参数是否仍能创建。
- 检查最小系统是否仍然闭合。
- 运行针对性测试和完整回归。
- 同步本文档或模型专属说明中的物理假设。
17. 人工或 AI 的任务输入卡
为了减少猜测,新增模型前建议先填写:
模型中文名称:
MODEL_TYPE:
所属 library_id:
所属 category_id:
物理域:
模型用途和边界:
端口列表及含义:
参数列表、SI 单位、默认值和范围:
状态变量:
代数方程或微分方程:
正流量约定:
需要显示的组件结果:
已知参考模型或工程公式:
最小测试系统:
允许的近似:
明确不实现的能力:
如果关键物理信息缺失,AI 应先通过现有模型、测试或用户提供的参考补齐;不能仅凭 组件名称自行创造方程。
18. AI 修改协议
AI 创建或修改模型时必须遵守:
修改前
- 读取第 3 节列出的文件。
- 检查工作区已有改动,不能覆盖无关修改。
- 明确模型是公开模型还是内部模型。
- 明确端口物理域、状态、参数、方程和结果。
- 找到最接近的现有模型并沿用代码风格。
修改中
- 将物理契约保存在模型类中。
- 只在库清单中登记公开模型。
- 不修改集中注册表来加入单个模型。
- 不为了让测试通过而放宽全局校验。
- 不改变现有模型标识,除非任务明确要求迁移。
- 不把前端拖拽方向当作物理流向。
- 不把求解器失败简单隐藏为默认结果。
修改后
- 展示涉及的模型、清单和测试文件。
- 报告版本变化和兼容性影响。
- 运行针对性测试、完整后端测试和必要的前端构建。
- 检查
GET /api/components/catalog中的模型、分类、端口和参数。 - 告知用户需要重启 FastAPI 才能加载新的 Python 模块。
- 未执行的校验必须明确说明原因。
19. 常见失败与处理
| 现象 | 常见原因 | 处理 |
|---|---|---|
| FastAPI 启动时报模型缺少声明 | 字段继承自父类或漏写 | 在公开模型类中显式声明 |
| 模型未出现在前端 | 未加入 library.py 或后端未重启 |
检查清单并重启 FastAPI |
| 前端显示红色“加载失败” | /api/components/catalog 不可用或目录合同无效 |
悬停状态查看详情,再检查 8000 端口和接口响应 |
| 显示端口校验失败 | DISPLAY.ports 与 PORTS 不一致 |
使用相同端口名和完整集合 |
| 单位校验失败 | quantity 与 SI 单位不匹配 |
使用受控单位表或先扩展规范 |
| 默认模型无法注册 | 默认参数越界或构造函数未保存参数 | 修复默认值和 set_parameter_values() |
| XML 报不支持模型 | XML type 与 MODEL_TYPE 不一致 |
修正类型或提供迁移 |
| 模型可显示但无法仿真 | 只完成目录元数据,方程或物理域求解未实现 | 补齐方程、网络和求解测试 |
20. 完成定义
一个模型只有同时满足以下条件才算完成:
- 模型契约完整且启动校验通过。
- 默认参数和边界有效。
- 端口、参数和结果具有稳定物理含义。
- 方程覆盖零流量、正常流动和必要的反向流动。
- 模型已加入正确库清单。
- 目录接口能自动输出模型。
- 前端无需复制参数和端口定义即可使用。
- XML 能映射到正确模型。
- 最小系统能够编译;声称可仿真的模型必须产生有限结果。
- 针对性测试、完整回归和必要的前端构建通过。
- 文档记录了模型假设、适用范围和已知限制。