11 KiB
新组件注册示例与验证记录
文档版本:1.0.0;修订日期:2026-09-12;代码基线:22579e5。
本文由原 app/simulation/components/example.md 迁入并重写,配合注册流程、建模规范和库读取规范使用。示例在隔离源码副本中实际执行,正式组件库不增加演练型号。它验证当前接入流程,不是待发布的新物理模型。
1. 示例合同
新建第三个库 registration_demo、分类 signals、型号 registration_demo_ramp,类名 DemoRamp,模型版本 1.0.0。复用图形键 amesim_step0,增加 C 模块 demo_signal;图形键不决定数值行为。
公式为:
y(t) = offset + amplitude × t / duration
| 参数 | SI / 默认值 | 约束 |
|---|---|---|
offset |
无量纲 / 2 | 有限值 |
amplitude |
无量纲 / 3 | 有限值 |
duration |
s / 1 | 有限且严格大于零 |
唯一端口 out 是信号输出,显示在右侧。组件输出 y 与端口输出 out.signal 相同。模型无积分状态、无事件、无气动参考口。Python 类显式声明 MODEL_TYPE/MODEL_VERSION/PORTS/PARAMETERS/RESULT_VARIABLES/DISPLAY/create;构造函数保存参数并注册端口。完整可执行类及各处接入代码保存在后端演练脚本,不再维护另一份易过期的代码副本。
C 函数是:
#include "kernels.h"
double native_demo_ramp(double t, double offset, double amplitude, double duration) {
return offset + amplitude * t / duration;
}
duration > 0 由组件参数合同检查。本演练用已校验的参数生成 C 常量,不能据此认为任意外部输入都已校验,或任意有限幅值不会溢出;它是受限输入的接入示例。
2. 分阶段注册:有意遗漏与实际失败
每阶段使用新 Python 进程,避免已导入模块掩盖发现入口变化。脚本在对应失败处断言错误原因,最终阶段要求成功。
| 阶段 | 已完成的步骤 | 实际结果 / 规范含义 |
|---|---|---|
unlisted |
新类和库文件存在,未启用库 | 注册表没有新型号;目录扫描不会自动注册 |
catalog_only |
启用新库与清单 | 目录、参数和 XML 校验通过;原生生成报 no native contract |
native_discovery_only |
将新库加入 extended.catalog_contracts() |
原生版本与模型合同不匹配;还需 SUPPORTED_VERSIONS |
contract_only |
补支持版本 | 报 Native output mapping incomplete,缺少 ramp_1.y 和 ramp_1.out.signal;版本白名单不会实现方程 |
lowered_without_module_export |
扩展生成器输出分支、C 函数和公共头文件 | 链接报 undefined reference to native_demo_ramp;模块未纳入按需导出 |
complete |
补 modules.py::EXPORTS、诊断聚合包含清单、经核对的函数识别 |
构建与 RK45/BDF 运行通过 |
实际修改仅发生在生成的 sandbox/:新库的四个 Python 文件、registry.py、extended.py、contracts.py、modules.py、jacobian.py、kernels.h、新 C 模块及诊断聚合入口。生产源码没有新增该类型。
该函数只读取时间和参数,没有状态依赖。将其纳入受控函数识别集不等于验证了任意多输出函数、投影或新动态模型的雅可比结构;这些仍按专项规范审查。
3. 浏览器导入过程中发现的额外边界
| 初次尝试 | 实际行为 | 已采用的处理与规范修订 |
|---|---|---|
把目录 ports 原样写入工程 |
信号端口带 positiveFlowDirection: null,浏览器拒绝;后端仍可转出有效 XML |
工程快照按前端结构规范化,信号端口省略该字段;保留错误导入检查 |
| 连线只写端点 | 缺 data.isContactEdge,浏览器拒绝 |
普通连线显式保存 data: {"isContactEdge": false} |
| 尝试把时长从 s 切到 ms | 当前只有 s 选项 | 验证已有 SI 参数编辑;不把新增单位描述成目录自动支持 |
| 使用未接线的独立信号源点击运行 | 后端是未接端口警告,前端检查为错误并阻止仿真 | 网页改用完整接线网络;区分单元件后端测试与网页系统测试 |
合法信号端口快照示例:
{"name":"out","kind":"signal","domain":"signal","nominalRole":"output","side":"right"}
网页案例使用四个元件、三条连接:
ramp_1.out -> force_1.res
force_1.port_2 -- mass_1.port_2
mass_1.port_1 -- zero_1.port_1
force_1 使用 FORC 的正向信号转力,mass_1 使用 MECMAS21(质量 10 kg、零初始位移/速度、禁用摩擦和限位),zero_1 是 F000。网页把 duration 从 1 s 改为 2 s,因此 F(t)=2+1.5t N,质量块的独立解析参考为:
v(t) = 0.2t + 0.075t²
x(t) = 0.1t² + 0.025t³
4. 本版规范的逐项校正
| 旧规范不匹配之处 | 本版处理 |
|---|---|
| 仅描述 experimental,仍计划未来建立正式库 | 核对当前 experimental/amesim 两库;临时隐藏由库 ID 决定 |
| “加入 library 就完成注册/无需其他修改” | 明确元数据发现与原生发现、版本、方程和模块链接四个独立检查点 |
C 公式仍要求放 kernels.c |
改为 modules/*.c、kernels.h 和模块导出/依赖;聚合文件仅用于诊断 |
启动校验要求 Python component_result_values() |
删除过期要求,改为元数据校验、C 输出映射及 EXE 输出的分层检查 |
| Python 状态声明容易被理解为自动得到 C 状态 | 明确索引、初值、导数和结果由具体生成路径实现 |
| 前端新增能力仅需图标 | 补齐动态端口、新编辑器、新物理量/单位、介质和连线规则的条件修改范围 |
| 目录、工程和 XML 合同被混用 | 补信号端口 null、连线 data 字段、SI 参数、完整参数、网页必接端口要求 |
| 无原生模块缓存、雅可比、新状态尺度要求 | 新增导出/依赖、缓存失效、状态依赖和容差量纲检查项 |
| “不支持迁移”的表述过于绝对 | 区分 XML 精确版本、前端型号专用处理和未实现的通用迁移框架 |
| 未区分跨平台适配与实际验收 | 分别记录 Linux/Windows 状态,新 C/构建/缓存能力同样适用 |
修改发生在现行规范正文,不只在本表列出待办。文件分工和迁移位置见规范索引。
5. 验证结果与范围
最终可复现记录放在本地 test/component-registration-20260912-verified/,该目录被 Git 忽略。
| 验证 | 结果与边界 |
|---|---|
| 六阶段发现、版本、输出、链接检查 | 全部符合阶段预期,最终构建成功 |
| 后端独立元件,RK45 与 BDF | 0~1 s,0.1 s 采样,各 11 点;y 解析误差为 0,端口输出与组件输出相同 |
| 重复构建 | 完整模型命中,对象编译 0 次 |
| 参数 duration 1→2 | 模型对象重编译 1 次,其余 8 个对象复用,最终输出 3.5 |
| 失败输入 | 错误 modelVersion、零 duration、XML 缺 duration 均被拒绝 |
| 浏览器 | 真实 Chromium、真实目录/API/C 程序;发现、拖入、错误 JSON 拒绝、完整工程导入、参数编辑、JSON/XML 导出、两次 BDF、曲线显示、结果文件/CSV、刷新恢复 |
| 网页解析对照 | 信号与输出力逐点误差 < 1e-12;质量块最大位移差 1.26236e-11 m、速度差 2.36616e-13 m/s(门槛分别为 1e-7) |
| 网页缓存与保存 | 第二次运行完整模型缓存命中;CSV 中新元件两列符合解析值;刷新恢复与保存结果完全一致 |
| 生产目录回归 | 注册、目录、元数据共 23 项测试通过;生产仍为 27 类,原生版本一致,演练类型未进入生产库 |
| Windows | 未实际执行;本机无 Windows 运行环境,不宣称双平台验收完成 |
第一轮缺导出的链接失败已生成部分共享对象,因此 firstCompleteBuild 不是全空缓存耗时;本演练不作性能优化结论。目录结构、失败阶段、函数接入在 Linux 得到实证,Windows 仍需用现有工具链执行复现与对应回归。
本案例不覆盖新物理域、动态端口、新编辑器、非平凡的雅可比着色、新非线性环或气动固定参考口,也不代表完成了 Amesim 等价性验证。此次修改仅为规范和演练工具,未修改共享求解行为,因此没有再次运行八路性能基准。
主要证据文件:summary.json、各阶段 *.json/*.log、input.xml、project.json(后端独立案例)、browser-project.json(网页完整网络)、browser/summary.json、网页导出与截图。探索中的失败记录在旁边的 test/component-registration-20260912/ 和 test/component-registration-20260912-final/;最终结论以 -verified 目录为准。
6. 复现方法
前提:仓库 Python 依赖、现有 C/SUNDIALS 工具链和前端依赖可用。前端源代码变化后先在 frontend/ 执行 npm run build,演练会复制现有 frontend/dist/。环境、工具链和浏览器不随 Git 提交。
Linux,从仓库根目录生成全新目录(已存在会拒绝覆盖):
.venv/bin/python tests/manual/rehearse_component_registration.py --output-dir test/registration-replay
另开终端启动隔离后端,使用同一 Python 环境:
registration_repo="$PWD"
cd test/registration-replay/sandbox
"$registration_repo/.venv/bin/python" -m uvicorn app.main:app --host 127.0.0.1 --port 8036
回到仓库根目录运行浏览器脚本:
node tests/manual/browser_component_registration.mjs test/registration-replay/browser-project.json test/registration-replay/browser http://127.0.0.1:8036
本机采用 .tools/node-v24.18.0-linux-x64/bin/node。若使用此前补充的浏览器动态库,在命令前设置:
export LD_LIBRARY_PATH="$PWD/.venv/native/browser-libs/usr/lib/x86_64-linux-gnu${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
Windows PowerShell 对应入口(须先配置现有 Windows C/SUNDIALS 工具链及 Playwright 浏览器,以下不是已通过记录):
$registrationRepo = (Get-Location).Path
$registrationPython = Join-Path $registrationRepo '.venv-win\Scripts\python.exe'
& $registrationPython tests/manual/rehearse_component_registration.py --output-dir test/registration-replay-win
Set-Location test/registration-replay-win/sandbox
& $registrationPython -m uvicorn app.main:app --host 127.0.0.1 --port 8036
在另一个 PowerShell 终端回到仓库,运行同一 .mjs 脚本,输入换成 test/registration-replay-win/browser-project.json,Node 使用本机 Windows 路径。浏览器与 Python 均使用原平台环境,不复制 Linux 动态库。
完成后在启动 uvicorn 的终端按 Ctrl+C。演练使用临时端口 8036;本次未启动用户已停止的 5173/8000。删除生成目录即可清理演练源码、结果与缓存;生产组件及现行规范不依赖这些生成物。