Files
SystemSimulationApp/docs/other/八路50秒仿真在10.8秒终止的原因核查-2026-09-13.md
T

102 lines
8.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 八路 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 返回:
```text
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 确实代表成功,见 [官方返回码说明](https://sundials.readthedocs.io/en/latest/cvode/Constants_link.html)。
诊断副本在 `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. 建议修复范围
1. 修正 AME→公共协议枚举映射及审计,按语义对齐这两个模型参数;保持公共协议 0/1 不变。补上“单次保持末值”和“循环跨周期”的转换与长时间测试,不能用双方都写 1 的测试继续自证正确。
2. 区分 CVODE 失败返回、时间倒退、成功但暂时无可表示时间增量。对最后一种提供有上限且可取消的继续机制,记录内部步数、实际步长和停滞次数;仍无法推进时明确报错,避免笼统提示。不得强行用 nextafter 推动系统时间以跳过积分。
3. 正式验收包括该八路 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 秒中断,两者属于不同阶段的问题,不能混为同一根因。