8.7 KiB
八路 50 秒仿真在 10.8 秒终止的原因核查
2026-09-13,Windows,本地 system-optimization 工作区。此次定位问题,在 test/mql8-50s-20260913/ 创建独立输入、源码和日志副本,没有修改正式求解器、原始 JSON、AME 或运行中的后端。
结论:已复现 10.8 秒终止,由两层问题叠加造成。AME 转换/审计遗漏 UD00 循环开关的枚举转换,使本应单次输出的两个信号周期重复;信号重启后,CVODE 成功完成一个小于当前时间浮点分辨率的步,外层封装因返回时间相同立即判失败。 这不是此次运行超时,也没有观察到 CVODE 返回雅可比或线性分解错误。
1. 输入身份与参数核对
用户确认后续八路验证默认使用下列仓库文件,本次网页仅修改终止时间:
| 输入 | 本次 SHA-256 |
|---|---|
tests/data/test-mql-8-corrected.json |
670977bef67e62d9c66e8af497bada208bd72a7301be45128d185d47282cf288 |
tests/data/test_mql.ame |
319b27ac1b8ceb7e960cc05592efbfc19664e70479fe9bf36000b823c3c928f8 |
AME 已由用户更新,不能继续使用历史 1ff0ea42… 的 10 秒归档身份。本次归档 .results 有 1002 个时间点,覆盖 0~50 秒,所有具名保存值有限;本轮读取此归档,没有重新运行 Amesim。
以现有审计工具核对:157 个元件、178 条连接逐端口匹配,1092 项公开参数在原工具的数值/单位规则下全部相等;1015 项直接绑定参数也核对图纸与 .param/.data。但下文两个枚举的语义不相等,因此“数字全部相同”不能作为参数语义一致的结论。其余参数本轮未发现数值差异,不将此等同于全部元件实现已逐项验收。
| 设置 | 本次原生复现 | 当前 AME |
|---|---|---|
| 终止时间 | 50 s,副本仅由原 JSON 的 10 s 延长 | 50 s |
| 输出间隔 | 0.01 s | 0.05 s |
| 最大积分步长 | 1e30 s | 1e30 s |
| 相对误差限 | 后端默认 1e-8 | 1e-7 |
| 积分算法 | CVODE/BDF 7.4.0 | 保留归档设置,不把内部枚举直接等同于 BDF |
原 JSON 仍保存 10 s、输出间隔 0.01 s,所以原审计工具最后的时间设置断言按预期失败。其物理参数与连接审计记录已经写出,不能把该断言当作仿真故障。
2. 两个 UD00 的循环开关被错误对齐
当前应用公共协议由 app/simulation/components/amesim/signals/sources.py 定义为 0=否、1=是。本机 Amesim 2404 的 libsig/submodels/UD00.c 明确只有 iscyclic == 2 才执行循环分支,其余合法值 1 执行单次分支。
因此正确的外部转换应为 AME 1 → 公共协议 0,AME 2 → 公共协议 1。不能直接修改现有 C 内核中布尔值 1 的含义,否则会破坏用户合法创建的循环信号。
AME 图纸与 .param/.data 中两个开关均为 1;当前 JSON 也保存 1。tests/test_test_mql_ame_contract.py::_expected_parameters 按单位转换后直接比较数字,没有处理这一枚举映射;八路审计工具复用该方法,因而漏报。此前仅运行 10 秒,尚未越过这个差异首次产生影响的时刻。
两个信号有效阶段均为 0.8 秒 + 10 秒,总长度为 10.8 秒:
| 信号 | 0~0.8 s | 0.8~10.8 s | AME 在 10.8 s 后 | 原 JSON 在 10.8 s |
|---|---|---|---|---|
amesim_ud00_1 |
1e17 | 49000 | 保持 49000 | 跳回 1e17 |
amesim_ud00_2 |
1e12 | 0 | 保持 0 | 跳回 1e12 |
该差异既由源代码和参数表证实,也由 AME 保存的 output@piecewiselinear、output@piecewiselinear_1 曲线与原生失败结果最后一点直接证实。AME 在 10.8 s 邻近、11 s 和 50 s 均保持末段值。
3. 求解器封装过早终止
原生结果:success=false、simulatedUntil=10.8、Native integration failed to advance.,接受步 8848、拒绝步 669、雅可比计算 682 次、无着色回退。执行限额为 300 秒,而此次纯求解仅约 9.888 秒,排除超时。
在隔离 C 副本中仅增加日志,数值结果与原版的终点和求解计数相同。10.8 秒信号重启后,CVODE 返回:
flag = 0 (CV_SUCCESS)
t = next = internal = 10.800000000000001
last step = actual initial step = 2.092542956622022e-16 s
next proposed step = 1.072750168401015e-14 s
internal accepted steps = 1
10.8 附近两个相邻双精度时间数的间隔约为 1.7763568394002505e-15 s,大于这一步。因此状态更新后返回的时间数字仍相同。native/runtime/cvode_solver.c 中的 if (flag<0 || next<=t) goto cleanup; 把“负返回码”和“成功但时间暂未改变”合并为同一种立即退出条件。CVODE 的 0 确实代表成功,见 官方返回码说明。
诊断副本在 CV_SUCCESS && next == t 时允许有限次继续,不人工增加时间、不改变误差限,不执行零长度采样/碰撞处理。该诊断保留了原来的循环输入,仍完整到达 50 秒:总计出现 12 次这样的返回,最长连续 6 次,均恢复前进。这证明本次外层立即退出条件过早,不代表可以无限忽略不前进或接受任意不连续输入的精度。
4. 两个独立对照
所有对照使用相同物理参数、BDF、rtol=1e-8、最大步长 1e30 s、输出间隔 0.01 s。下列都是单次诊断观察,不作为性能优化统计。
| 对照 | 改动 | 结果 | C 求解墙钟 |
|---|---|---|---|
| 原模型 + 正式内核 | 仅延长到 50 s | 停在 10.8 s | 9.888 s |
| 语义对齐模型 + 正式内核 | 两个 UD00 的 iscyclic 改为 0 | 完成 50 s | 9.851 s |
| 原循环模型 + 诊断内核 | 对成功但时间未变提供有限次继续 | 完成 50 s | 11.805 s |
第二项没有修改求解器,返回 5002 个严格递增采样点,全部数据有限;56 个气体质量状态的总质量最大漂移为 1.2434497875801753e-14 kg。两个信号的末段值与 AME 相符。此项证明对齐信号语义即可让当前模型完整运行,不宣称已通过双方全部 50 秒曲线的等精度验收。
第三项仍具有与 AME 不同的周期激励,产生 9 次机械状态转换,不能作为 AME 对照模型或直接交付为正式修复。诊断的连续 8 次保护上限只用于验证假设,正式实现需明确停滞处理规则和诊断。
5. 建议修复范围
- 修正 AME→公共协议枚举映射及审计,按语义对齐这两个模型参数;保持公共协议 0/1 不变。补上“单次保持末值”和“循环跨周期”的转换与长时间测试,不能用双方都写 1 的测试继续自证正确。
- 区分 CVODE 失败返回、时间倒退、成功但暂时无可表示时间增量。对最后一种提供有上限且可取消的继续机制,记录内部步数、实际步长和停滞次数;仍无法推进时明确报错,避免笼统提示。不得强行用 nextafter 推动系统时间以跳过积分。
- 正式验收包括该八路 50 秒模型、真正的周期信号、单次斜坡结束后的保持行为、事件/采样完整性与失败诊断,并在 Windows 和 Linux 上分别验证。稀疏求解优化安排在这些正确性问题之后。
本轮未修改生产代码或原始工程,仅提供已经完成 50 秒运行的诊断 JSON:test/mql8-50s-20260913/model-50s-semantic-aligned.json。它与原 JSON 仅有终止时间及两个循环开关的差异。
6. 证据与复现
证据目录 test/mql8-50s-20260913/:
sources/identity.json、输入快照:来源身份;检查结束时原始文件 SHA 未改变。parameter-audit/audit.json、parameter-audit.log:逐参数、逐端口映射与时间设置差异。archive-summary.json:AME 保存结果时间范围及有限性。production-retry/:正式内核复现;traced-boundary/:仅增加日志的同故障验证。semantic-aligned/:对齐开关后的完整结果,validation.json包含采样、有限性与质量守恒检查。stationary-probe/:停滞继续的诊断源码、实际构建信息和完整结果;cause-evidence.json汇总信号差异及 CVODE 返回信息。diagnose.py:复用正式输入、代码生成、构建与执行入口。重新运行需使用新的--name,避免覆盖原始证据。--trace --allow-stationary只修改 test 下的源码副本。
Windows 使用 .venv-win/Scripts/python.exe -B test/mql8-50s-20260913/diagnose.py run --name 新目录名。语义对齐组加 --input model-50s-semantic-aligned.json。本轮没有 Linux 实机结果。
最初一次诊断编译在受限进程环境中遇到 GCC CreateProcess 错误,尚未开始求解;保留 production-default/input.xml。随后正常 Windows 进程环境构建成功并稳定复现 10.8 秒中断,两者属于不同阶段的问题,不能混为同一根因。