102 lines
8.7 KiB
Markdown
102 lines
8.7 KiB
Markdown
# 八路 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 秒中断,两者属于不同阶段的问题,不能混为同一根因。
|