238 lines
19 KiB
Markdown
238 lines
19 KiB
Markdown
# 新组件注册流程与交付规范
|
||
|
||
文档版本:1.1.0
|
||
修订日期:2026-09-12
|
||
核对代码基线:`22579e5`(缓存功能 Windows 平台适配)。本文是新增网页建模与原生仿真组件的总流程;专项字段规则见[规范索引](README.md),执行证据见[注册示例与验证](component-registration-example-v1.md)。文档版本独立于模型和协议版本。
|
||
|
||
本版通过隔离源码中的斜坡信号源注册演练校正现有规范。演练组件和编译缓存不加入正式组件库;可复现脚本保留在 `tests/manual/`。
|
||
|
||
## 1. 当前架构与完成边界
|
||
|
||
当前有两条接入链路。元数据注册控制组件发现和编辑;原生支持控制能否生成并执行数值模型。注册类不会自动获得 C 求解能力。
|
||
|
||
```mermaid
|
||
flowchart TD
|
||
A[组件物理定义与 Python 声明] --> B[library.py 与注册校验]
|
||
B --> C[组件目录 API]
|
||
C --> D[前端组件库、参数面板和端口]
|
||
D --> E[工程 JSON 与执行 XML]
|
||
E --> F[校验并构造网络]
|
||
B --> F
|
||
F --> G[C 支持合同与系统代码生成]
|
||
H[公共 C 数值模块] --> I[按需编译、缓存和链接]
|
||
G --> I
|
||
I --> J[独立 C 程序积分与输出]
|
||
J --> K[网页结果、保存和 CSV]
|
||
```
|
||
|
||
源码依据:
|
||
|
||
- [注册中心](../../app/simulation/registry.py):`ENABLED_COMPONENT_LIBRARIES` → `library.py` → `validate_component_model_class()` / `create()` → 注册表。
|
||
- [目录 API 与网络构造](../../app/main.py):`/api/components/catalog`、`compile_system_xml_network()`、`_compile_solver_network()`。
|
||
- [原生入口](../../app/simulation/native_codegen/compiler.py):`compile_native_program()` 检查类型和版本,再选择紧凑路径或扩展路径。
|
||
- [扩展生成器](../../app/simulation/native_codegen/extended.py):按具体模型实现状态、方程与输出映射。
|
||
- [前端工作台](../../frontend/src/App.tsx):`normalizeComponentCatalog()`、工程读写及通用参数处理。
|
||
|
||
本次直接加载注册目录核对:`experimental` 5 类、`amesim` 22 类,共 27 类;原生版本表与注册版本一致。这是当前快照,不应成为未来新增组件后的固定数量要求。
|
||
|
||
以下标识不可混为一谈:
|
||
|
||
| 标识 | 作用 | 示例 |
|
||
| --- | --- | --- |
|
||
| `library.id` | 发布和发现边界 | `amesim` |
|
||
| `category.id` | 前端组件面板分组 | `flow` |
|
||
| `MODEL_TYPE` | 工程/XML/原生支持的模型类型 | `amesim_pnor001` |
|
||
| `DISPLAY.symbol` | 前端图形渲染键 | 可以与 MODEL_TYPE 相同,也可以复用已有图形 |
|
||
| C 功能模块 | 数值代码组织及对象缓存粒度 | `orifice`、`pipe` |
|
||
|
||
界面分类与 C 功能模块没有自动的一一映射。不同型号可以调用同一个公共 C 函数;同一型号也可以依赖多个模块。
|
||
|
||
## 2. 新增组件的实际步骤
|
||
|
||
### 第一步:确定物理合同和接入范围(必做)
|
||
|
||
先整理模型依据、适用介质/物理域、计算公式、符号约定、有效范围和未支持能力。明确它是无状态代数组件、动态组件,还是编译期介质定义。若是新增物理域或新种类的介质,须单独评估网络、XML、前端连线、物性和原生生成支持,不能只新增一个 `domain` 或类型字符串。
|
||
|
||
建议首先形成四张表:
|
||
|
||
- 参数:机器名、物理意义、SI 单位、默认值、范围、枚举、显示条件和是否影响端口/状态数量。
|
||
- 端口:稳定名称、物理域、连接类型、各变量含义、正方向、供需关系、参考来源及是否必须连接。
|
||
- 状态:名称、含义、单位、初值公式、导数公式、允许范围、绝对误差尺度及相关事件。
|
||
- 输出:稳定名称、含义、单位、显示名称、计算公式和所属组件/端口。
|
||
|
||
### 第二步:编写 Python 组件声明(必做)
|
||
|
||
文件放在 `app/simulation/components/<library>/<category>/`,参照同类模型。现有代码存在一个文件容纳多个相关型号的情况;“每模型单文件”是整理建议,不是注册器的硬性要求。
|
||
|
||
公开模型类必须在自己的类体显式声明:
|
||
|
||
```python
|
||
MODEL_TYPE
|
||
MODEL_VERSION
|
||
PORTS
|
||
PARAMETERS
|
||
RESULT_VARIABLES
|
||
DISPLAY
|
||
|
||
@classmethod
|
||
def create(cls, *, name, medium, parameters):
|
||
...
|
||
```
|
||
|
||
这七项由 [registry.py](../../app/simulation/registry.py) 检查,不能只从父类隐式继承。可以显式引用已有声明,例如 `RESULT_VARIABLES = Parent.RESULT_VARIABLES`。
|
||
|
||
构造过程调用 `set_parameter_values()` 保存完整规范化参数,使用 `register_declared_port()` 注册声明的端口,并保存介质和常量。参数合法性包括单字段范围和跨参数约束;默认参数必须能够创建描述对象。公共创建入口填充缺省值后还会核对实例类型、端口和参数是否与声明一致。
|
||
|
||
Python 可以做参数验证和常量几何换算;运行时物性、流量、力和状态导数由 C 计算。`EQUATIONS` / `equation_definitions()` 是结构化约束声明,不会被自动翻译成完整 C 数值方程。仅设置 `DynamicComponent.state_size` 也不会自动分配原生积分状态。
|
||
|
||
### 第三步:落实端口语义(必做,静态与数值两侧一致)
|
||
|
||
`PORTS` 是物理接口来源,`DISPLAY.ports` 是显示布局,两者的名称集合必须一致。当前显示端口基础声明支持 `left/right`,旋转和镜像由前端处理,不能直接写未经实现的显示边。
|
||
|
||
气动端口需要区分:
|
||
|
||
- 名义入口/出口及实际正反流。
|
||
- 哪些量由本端提供,哪些量由对端提供。
|
||
- 是否是固定供需的参考口或支路口;`reference_port` 指向哪个真实参考来源。
|
||
|
||
使用 [port_computation.py](../../app/simulation/core/port_computation.py) 的既有合同或声明准确的新合同。参考关系不会随流向反转而自动改变;不能从图标左右位置推断物理参考口。端口流量遵守现有“流入组件为正”的合同。
|
||
|
||
参数决定端口启停时,同时实现类级和实例级有效端口查询,并核对必须连接的端口。前端目前对 LMECHN1 的动态端口还有专门逻辑,尚无统一的参数化端口目录协议;新动态端口模型要明确补齐前端规则及变更参数后旧连线的处理。
|
||
|
||
### 第四步:加入受控组件清单(必做)
|
||
|
||
在所属库 `library.py` 的 `models` 中加入 `完整模块路径:类名`。如新增界面分类,同步该库 `categories` 和 `DISPLAY.category_id`。不要直接修改运行时 `COMPONENT_MODEL_REGISTRY`,也不要扫描目录执行任意 Python 文件。
|
||
|
||
新库需增加 `ComponentLibrarySpec`,并加入 `registry.py` 的 `ENABLED_COMPONENT_LIBRARIES`。另外,当前 `extended.py::catalog_contracts()` 仍显式读取 `amesim` 和 `experimental` 两个库,**新增第三个库还必须扩展这一原生发现入口**。
|
||
|
||
前端当前按库 ID 隐藏 `experimental`。加入实验库的模型可以被后端发现,但不会出现在左侧公开组件列表;`temporary` 标记不是现有隐藏规则。
|
||
|
||
### 第五步:实现或复用 C 数值内核(数值接入必做,新增 C 文件按需)
|
||
|
||
先判断现有公共函数是否已经满足方程。如果只需已有内核加不同参数或组合,可以复用,避免按元件实例复制内核。
|
||
|
||
新增函数应放在 `native/components/modules/` 的合适模块,公共接口在 [kernels.h](../../native/include/kernels.h) 声明;新增独立模块时再建立新的 `.c`。当前五模块为物性、孔口、管路、机械和信号。
|
||
|
||
按需构建由 [modules.py](../../app/simulation/native_codegen/modules.py) 的 `EXPORTS` 和 `DEPENDENCIES` 决定。增加新导出函数或模块依赖时应同步这里;只在头文件写声明不会保证模块进入链接。新模块如需参与聚合诊断,还要加入 `native/components/kernels.c` 的包含清单。
|
||
|
||
`kernels.c` 现在是诊断聚合入口,生产构建不直接编译它;不能同时链接聚合入口与各模块,否则产生重复定义。
|
||
|
||
内核应说明非法状态、非有限值及迭代失败的处理。新气动计算优先传递现有 `NativePropertyCache` 上下文;试算不能污染已接受状态,也不能把跨状态的旧物性无条件复用。沿用 C11、严格浮点和已有 Windows/Linux 构建约定。
|
||
|
||
### 第六步:接入系统代码生成、依赖和数值精度(必做)
|
||
|
||
在 `native_codegen/extended.py` 接入该具体型号的:
|
||
|
||
1. 有效端口、连接组及介质选择。
|
||
2. 状态编号、初值、必要的状态约束/投影。
|
||
3. 代数关系、流量、焓和力计算。
|
||
4. 状态导数及全部可见输出赋值。
|
||
5. 分段信号、限位或其他事件(适用时)。
|
||
|
||
目前这些逻辑包含具体类型集合与分支,例如 `GAS_TYPES`、`NODES`、`RESISTORS`;简单地把新型号塞进某个集合,不能保证后续分支正确处理它。
|
||
|
||
计算输入/输出通过 `Computation` / `EvaluationSchedule` 接入 [求值排序](../../app/simulation/native_codegen/schedule.py)。多输出函数要准确声明读取量和写出量;参考值复制与依赖流量的混合计算应分开;正流、逆流、零流量和各离散模式的依赖均需覆盖。新增不被当前局部求解器支持的非线性环,要实现对应求解或明确拒绝。
|
||
|
||
还需核对 [雅可比结构](../../app/simulation/native_codegen/jacobian.py) 的状态依赖。新的多输出调用、投影和分支不能遗漏依赖;无法证明时允许使用保守逐列差分,不能为保持着色而把未知依赖当作常量。适用时给生成的 `model`/`model.exe` 传入 `--verify-jacobian` 核对;Python 包装 CLI 没有同名选项。
|
||
|
||
新增状态量需要检查 [绝对误差尺度](../../app/simulation/native_codegen/tolerances.py)。当前按状态字段名区分质量、位移/速度,其余默认 `1e-8`;新物理量不能未经量纲评估直接套默认值。
|
||
|
||
`compiler.py` 保留紧凑生成路径,但新型号不一定需要同步实现第二套路径。正确做法是确认它被路由到已支持的生成路径;只有纳入紧凑路径或改变两路径共享行为时,才同步实现并做路径对照。不要只扩充 `_STORAGE_ANCHORED_TYPES` 却漏掉对应计算。
|
||
|
||
实现并验证后,将 `MODEL_TYPE: MODEL_VERSION` 加入 [contracts.py](../../app/simulation/native_codegen/contracts.py)。这是支持承诺,不能用加入白名单代替真正的数值实现。
|
||
|
||
### 第七步:核对前端图形与交互(必查,代码修改按需)
|
||
|
||
对普通固定端口、现有编辑器和现有单位的模型,组件库列表、参数名称/默认值/边界/枚举/显隐条件通过目录自动生成。通常不用在 `App.tsx` 再添加一份型号参数表或新建仿真 API。
|
||
|
||
需要新图形时,在 `frontend/src/componentSymbols/` 实现渲染,并加入 [ComponentSymbol.tsx](../../frontend/src/ComponentSymbol.tsx) 的 `symbolRegistry`。完整图形定义包含 `viewBox`、图标尺寸、节点占地、端口锚点;按参数变化的图形还需相应布局函数。没有专用图形时当前有通用边框回退,但它不代表专用图形已经验收。
|
||
|
||
以下情况需额外前端工作:
|
||
|
||
| 新能力 | 需要核对的入口 |
|
||
| --- | --- |
|
||
| 新图形/锚点 | `componentSymbols/*`、`ComponentSymbol.tsx` |
|
||
| 新参数编辑器 | `core/metadata.py` / 注册校验、目录解析、`ParameterTable.tsx` / `App.tsx` |
|
||
| 新单位或物理量的单位切换 | 后端 `SI_UNIT_BY_QUANTITY`、共享参数 `schemas/parameter-units.json`、结果 `RESULT_UNIT_OPTIONS`;三入口回归 |
|
||
| 动态端口 | 后端有效端口接口、前端端口显示/连线处理和参数变更逻辑 |
|
||
| 新物理域/连接规则 | `core/ports.py`、网络/XML 校验、前端连线检查及 C 生成 |
|
||
| 特殊介质定义/引用 | XML/前端的目录角色、网络识别的介质定义基类、介质注册与引用选择逻辑 |
|
||
|
||
浏览器检查应覆盖端口号、实际连线端点、旋转/镜像、参数改变后的布局及导入导出。图形变了不能偷偷改变物理端口名称或参考关系。
|
||
|
||
### 第八步:核对工程文件、版本和输出(必做)
|
||
|
||
普通已有协议下的模型通过注册表即可被通用 XML 流程识别,通常不需要修改 XSD 或添加型号专用 API。
|
||
|
||
- XML 要求精确匹配 `modelVersion`,参数集合完整且没有未知字段;Python 工厂可填默认值不等于 XML 可以任意缺参数。
|
||
- 外部工程 JSON v2 的数值和表达式统一按所选单位解释,网页/HTTP/CLI 预处理后才进入 SI 数值边界。旧 v1 数值不能重复换算。组件版本差异提示后允许执行;型号、端口、参数错误继续拒绝。导出时只对通过校验的节点升级版本,按[输入合同](backend-interface-version-spec-v1.md#61-工程存储与执行入口)验收旧文件和重新导出的文件。
|
||
- 采用实际浏览器导出的工程结构,不直接复制目录对象。例如信号端口快照须省略 `positiveFlowDirection: null`;连线须保存 `data.isContactEdge` 布尔字段;后端转 XML 成功不能代替浏览器导入检查,见[目录与快照差异](component-library-spec-v1.md#143-目录对象与工程快照不是同一协议)。
|
||
- 网页当前要求所有显示端口恰好连接一次。后端单元件算例的未接端口警告不能替代网页完整网络验收。
|
||
- 发布后保持模型/端口/参数/结果机器名稳定。提高版本可能使旧 XML 被拒绝;当前没有通用自动迁移框架,前端仅存在部分特定型号迁移逻辑。
|
||
- `RESULT_VARIABLES` 中可见项与活动端口的可见变量必须在实际 C 输出中全部赋值,结果键/单位应与网页、缓存恢复、CSV 一致。
|
||
|
||
### 第九步:分层测试和双平台验收(必做,按物理适用性选择案例)
|
||
|
||
| 层次 | 最少核验内容 | 现有入口示例 |
|
||
| --- | --- | --- |
|
||
| 声明与注册 | 全局类型唯一、版本、默认可创建、非法/边界参数、端口/显示/结果一致 | `test_component_registry`、`test_component_catalog`、`test_component_metadata` |
|
||
| 接口与文件 | 正确连接、缺口/错误参考被拒绝、JSON/XML 往返、版本不兼容 | `test_port_computation`、`test_system_xml_v3`、型号专项 |
|
||
| 元件数值 | 独立公式或可信参考、正常/零值/边界/逆向、守恒和明确失败 | 型号 C 专项、`--init` / `--probe` |
|
||
| 系统求解 | 包含新元件的最小闭合网络,RK45/BDF(适用时),事件、顺序打乱与输出完整 | `test_native_codegen`、`test_native_schedule`、`test_native_catalog` |
|
||
| 雅可比 | 状态依赖覆盖、模式切换、必要的完整矩阵核对 | `test_native_jacobian_structure`、`test_native_jacobian_runtime` |
|
||
| 编译与缓存 | 空缓存构建、完整命中、参数/模块变化后正确失效、缺失模块链接失败能被发现 | `test_native_build_cache`、`test_native_cache_platform` |
|
||
| 浏览器 | 发现/拖入/编辑/连线/旋转镜像、运行、结果可查看、IndexedDB 保存、下载/CSV/刷新恢复分别核查 | `frontend/tests/e2e/` 的相关测试 |
|
||
| 双平台 | Windows 与 Linux 实际构建和运行;Windows `.exe` / DLL / 路径 / 文件系统能力 | `native-windows` CI、跨平台集成测试 |
|
||
|
||
新增模型要有自己的可执行案例,不能只改变“现有 27 类”的数量断言。已有测试包含固定类型清单/数量,新增后需合理更新覆盖期望,并证明新型号确实执行。
|
||
|
||
数值参考来自独立解析结果、可信外部结果或经过审查的冻结基准;不能从待验实现自动生成“预期值”来证明自身正确。保留原有参考,不直接覆盖历史基线掩盖差异。
|
||
|
||
对共享内核/求解器的修改,沿用修正八路作为系统回归与性能案例;新元件自身仍需最小闭合案例。只有八路无法运行且短期无解,才退回四路。性能对照分别记录构建、求解、结果处理与网页可查看/保存;无可信 Amesim 曲线或耗时则明确跳过相应对比。
|
||
|
||
Windows 验收遵循 [跨平台交付约定](跨平台交付约定.md)。模拟测试与代码适配不能代称 Windows 实机运行通过。
|
||
|
||
## 3. 常见修改范围
|
||
|
||
| 文件/区域 | 新增普通型号时是否必改 |
|
||
| --- | --- |
|
||
| 所属组件库中的 Python 声明 | 必改 |
|
||
| 所属库 `library.py` | 必改 |
|
||
| `native_codegen/extended.py` 或已确定的生成适配入口 | 必须接入;当前通常需修改 |
|
||
| `native_codegen/contracts.py` | 必改 |
|
||
| `native/components/modules/*.c` / `kernels.h` | 新数值函数才改;已有内核可复用 |
|
||
| `native_codegen/modules.py` | 新导出函数或新模块依赖时改 |
|
||
| `native_codegen/compiler.py` 紧凑路径 | 新型号纳入该路径或共享行为受影响时改 |
|
||
| `schedule.py` / `jacobian.py` / `tolerances.py` | 核对生成器接入;现有机制不足、新函数依赖或新状态尺度需要时改 |
|
||
| 前端图形注册与渲染 | 需要专用图形或布局时改 |
|
||
| `App.tsx` / `ParameterTable.tsx` | 动态端口、新编辑器、新单位等现有元数据能力不足时改 |
|
||
| `app/main.py` / `app/system_xml.py` / XSD | 普通型号通常不改;新协议/物理域/介质机制时改 |
|
||
| 注册、型号数值、系统和浏览器测试 | 增加相应案例并更新受影响的覆盖期望 |
|
||
|
||
## 4. 组件接入交付资料
|
||
|
||
每个拟交付的新型号提供“组件接入说明”,按适用性填写以下栏目;未涉及的能力写明不适用:
|
||
|
||
1. **身份与版本**:类型、类路径、所属库/分类、模型版本、图形键、关联已有型号及兼容性处理。
|
||
2. **物理依据**:参考来源、完整方程、假设、适用范围、未支持功能。
|
||
3. **参数表**:SI 值、默认值、边界、枚举、条件显示、几何常量预处理。
|
||
4. **端口表与标号图**:变量、正方向、供需、参考口、动态启停和必接要求。
|
||
5. **状态/事件/结果表**:初值、导数、误差尺度、事件行为、输出键和单位。
|
||
6. **原生接入表**:C 函数、所属模块、依赖、生成路径、计算顺序、雅可比依赖与缓存失效范围。
|
||
7. **前端/文件合同**:图形及锚点、单位和编辑器、JSON/XML 示例、旧工程处理。
|
||
8. **验证记录**:最小算例、独立参考来源、误差门槛、失败路径、Windows/Linux 实际结果和网页验证;性能数据按阶段区分。
|
||
|
||
验证记录区分三个完成状态:
|
||
|
||
- **已注册**:目录/工厂/XML 类型与参数校验通过。
|
||
- **可求解**:原生构建、独立数值对照、闭合网络运行和输出检查通过。
|
||
- **可交付**:浏览器交互/文件往返/保存及 Windows/Linux 验证通过,兼容性和资料齐全。
|
||
|
||
这些是文档中的验收状态,当前目录 API 尚未提供对应的统一字段;不要向工程 JSON 添加未实现的状态协议。
|
||
|
||
## 5. 本版修订与维护
|
||
|
||
本版已在专项规范中修正:旧 C 文件入口、移除的 Python 结果接口、新库的两条发现入口、原生版本与方程的独立接入、前端条件能力、目录与工程快照差异、网页完整接线要求、精确版本和专用迁移的边界,以及模块缓存、雅可比依赖和 Windows 验证要求。
|
||
|
||
具体逐项对照、失败阶段和最终测试结果见[注册示例与验证](component-registration-example-v1.md)。后续代码架构变更时更新对应专项规范及本流程;不在文档中维护第二份可执行型号参数表。
|