Files
SystemSimulationApp/tests/manual/context_access_diagnostic.md
ljz 7611f13208 修复循环信号与事件采样并接入 LSTP 接触定位,补充八路验证及复用实验
相较上一版 Jacobian 确定性复用更新,本次补齐事件边界一致性、结果两侧采样及接触事件定位;保留已有物性复用和组件力学公式。

- 统一 UD00 信号求值与下一事件查询的绝对时间边界,修复循环边界浮点舍入导致的阶段错位、重复或漏报,并覆盖零时长、多阶段及长周期场景。
- 引入原生输出语义 v2:保留规则网格真实时间,补充内部时间事件和状态事件的左邻及事件后采样,按保存时间、状态和离散模式重放结果。
- 两条代码生成路径均发出 LSTP 接触描述,默认定位间隙过零及非负力模式的力截断;仅在接受事件时更新防重复记录,增加 contactEvents 诊断计数。
- 补充 MASS/LSTP 独立事件实验、八路全曲线与驱动阶段配对评估,以及 Amesim 不连续点输出对照和力差定位报告;MASS 新增释放机制仍保留为独立实验。
- 保存局部 probe、context 访问与回退、shadow replay、R288 real skip/typed replay 及阀门数值尾部诊断工具和报告;未证明净收益的实验不启用为生产默认优化。
- 更新原生运行说明和元件建模规范,补充信号边界、输出语义、接触事件和实验依赖回归测试。

验证:五组专项回归共 34 项全部通过;37 个待提交 Python 文件语法检查通过;git diff --cached --check 通过。
2026-09-17 23:50:13 +08:00

170 lines
14 KiB
Markdown
Raw Permalink 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.
# 两个 operation 的 context 访问级诊断
## 结论
两个案例均能按“查询 key 和首次匹配关系 → 消费字段 → 有序更新与追加”建立局部清单。完整仿真中,每例各验证 896 对 baseline/probe:查询 key、命中状态、逻辑条目对应后的消费值、valid 测试及有序写入一致,operation 输出逐位一致。
- **group 18 / R475 / position 52**:Jacobian 200 中 `states[74].p` 确实被两次 PT 查询扫描读取,但两次都在压力比较处排除。它没有成为物性计算输入;`states[74].T/h/rho/isentropic` 均未被该 operation 读取。因此,**本次入口差异不影响查询选择和计算**,不能表述为“这个字段完全没被读取”,也不能无条件忽略任意压力变化。
- **group 6 / R288 / position 16**:Jacobian 200 的入口 count 从 baseline 12 变为 probe 13。两次 PT 查询均 miss,逻辑新条目应从 baseline 12/13 映射到 probe 13/14;退出 count 应为 15。probe 原有 slot 12 必须保留。
这是独立诊断 worker 的验证结果。生产求解器、现有 local-probe guard 和整段回放策略没有修改;不能据此直接允许整个 R475 复用。
具体数值、每次查询的完整 key、valid 测试和逐项有序写入见 [实测清单](context_access_checklists.md)。以下解释这些清单如何用于后续设计。
## 验证范围与方法
输入 `tests/data/test-mql-8-corrected.json`,BDF,0–10 s,采样间隔 0.01 s,rtol=1e-8。位置、group、Jacobian 序号均采用已有诊断的 0 起始编号。Windows / GCC 8.1.0;本次没有执行 Linux 验收。
独立 worker 来源为 `test/context-fallback-20260917/worker`。生成时,仅在副本内包装实际字段读取、valid 位测试、赋值、结构体清零、count++、查询和分配点,保留原表达式、短路条件和原 guard。Jacobian scalar get 经输出指针写入 `rho` 的路径也单独记录。
原始事件带有执行顺序、函数、context 域、字节偏移及原始位值。PT/PH 查询记录 medium kind、全部七个 medium 浮点参数、p 和 T/h;校验器独立扫描当前重放状态,检查所有匹配项、首个匹配 slot,以及实际扫描到的 valid 测试序列。miss 后的 `allocate` 事件给出所选追加 slot。
观察器和 memo 指针还校验了当前 context 的归属,以及同一 Jacobian 内 baseline/probe 的绑定一致性,不只是比较“是否非空”。日志中的原始地址仅用于本次进程诊断,不作为跨进程、跨机器的逻辑 key。
**前后快照仅作校验终点**:逐条读取须与当时 context 一致;逐条写入须重建退出 context 的每个有效字节,包括未改动旧条目和其余 pipe 槽。另独立检查原代码规定的新条目初始化顺序及 pipe 的 11 次写入,因而删除 `pipe.valid=0` 这类同值写入也会验收失败。未初始化槽清零前的内容未知,不把它计作“已知同值写入”。
`operations.json` 中的 `consumed` 是选择完成后的实际字段读取集合;查询扫描的 `p/T/h/medium` 和 valid 测试在原始事件中单独保留。新条目内部的计算读取也在集合内,但这些值不是需要和入口旧条目比较的前置条件。
## 案例一:group 18,R475 内 position 52
operation 为 `flow:amesim_pnl0001_17.port_1`,输出 `q[152]`,使用 `pipe_cache[28]`。
### 查询及必要前置条件
Jacobian 200,t≈0.372854446 s,入口 count=75,capacity=256。
| 项目 | baseline | probe |
|---|---:|---:|
| states[74].p | 15019640.74937454 | 15019641.148960622 |
| states[74].T | 460.10768147887495 | 460.1076863719882 |
| states[74].valid | 21 | 21 |
| 上游 PT key 的 p | 15019625.056587901 | 相同 |
| 上游 PT key 的 T | 529.0977489177745 | 相同 |
| 下游 PT key 的 p | 15019613.376778807 | 相同 |
| 下游 PT key 的 T | 529.0975843945621 | 相同 |
完整 medium key 为 `(real_helium=1, R=2077.26439404998, cp=5193.1609851249505, Tref=293.15, slope=0, mu=1.96e-5, muT=293.15, S=79.4)`。实际二进制位值保存在事件和清单来源 JSON 中,不依赖上表小数显示精度。
两次 PT 都 miss,分别扫描 75、76 项,追加到 slot 75、76。slot 74 的两次访问均为 `valid & 1 → p == query.p`;压力不等后短路,未读取其 T 或 medium。满足同样排除关系即可允许这项差异,不要求两次入口的 slot 74 压力相等。
此时 `p[44] <= g[40].p`:温度来自 `g[40].T`,没有 PH 查询,`h[178]` 没有被本次分支消费。需要保持压力方向、近零流量分支、实际温度来源、medium 和管道常量一致。
### 实际读取 → 必须保留的 probe 数据
- 上游新条目:p、T、medium、mu、rho、isentropic_factor、isentropic_exponent,以及温度观察器/Jacobian memo 指针。
- 下游新条目:p、T、medium、rho、两个 isentropic 字段和上述指针;没有消费下游 mu/h。
- 选中后的 valid 测试依次为:上游 MU=0、ISENTROPIC=0、RHO=0;下游 ISENTROPIC=0、RHO=0;再次上游 RHO=4。
- `pipe_cache[28]` 入口只读 valid=0,其余旧键字段被短路跳过。
- 保留 probe 的 `states[0:75]` 全部内容,尤其是 slot 74 的新 p/T;其他 39 个 pipe 槽保持 probe 值。这条实测路径没有写任何已有物性条目。
### 有序字段更新与追加动作
1. count 75→76;在 slot 75 整体清零,依次写 medium、p、T、valid=PT、temperatures、jacobian。
2. 写 mu,`valid |= MU`;写 rho,`valid |= RHO`;写 factor、exponent,`valid |= ISENTROPIC`。上游最终 valid=29。
3. count 76→77;同样初始化 slot 76;写 rho、RHO 位、factor、exponent、ISENTROPIC 位。下游最终 valid=21,未写 h/mu 的计算值,但初始化清零必须执行。
4. pipe[28] 按顺序写 valid=0、medium、p1、p2、T、diameter、length、roughness、kind、flow、valid=1。首次 valid=0 是真实的 0→0 写入。
5. 输出 `q[152]=-1.4080633385291488e-6`;model evaluator 返回 1。
### 不能省略的其他实测分支
| position 52 查询序列 | probe 次数 | 代表 Jacobian |
|---|---:|---:|
| PT miss → PT miss | 727 | 200 |
| PH miss → PT miss(登记 h)→ PT hit → PT miss | 167 | 2 |
| PH hit → PT hit → PT miss | 1 | 1 |
| 无物性查询,近零流量 | 1 | 0 |
PH miss 路径需要测试 H 位并显式写 h、`valid |= H`,随后 pipe 的 PT 查询复用这个刚创建的逻辑条目;不能把后一次 hit 另当一次追加。PH hit 路径实际消费已有条目的 T,随后读取其已有效的 mu/rho/isentropic 字段;这些入口载荷必须比较。Jacobian 1 中首次匹配为 slot 7,仅新增下游条目。两条补充分支的完整 key 和写入顺序已收入实测清单。
全程有 24 对入口 count 不同,偏移为 +1 或 +2;其查询和逻辑字段仍一致。位置 52 也需要动态 slot 映射,不能固定为 75/76。
## 案例二:group 6,R288 / position 16
operation 为 `flow:amesim_pnl0001_1.port_1`,输出 `q[45]`,使用 `pipe_cache[0]`。
### 查询及必要前置条件
Jacobian 200 的 medium 与上例相同:
| 逻辑条目 / 查询顺序 | p | T | baseline slot | probe slot |
|---|---:|---:|---:|---:|
| 上游 U | 15019678.822746754 | 291.8496414260662 | miss → 12 | miss → 13 |
| 下游 D | 15019662.638804033 | 291.84951601402554 | miss → 13 | miss → 14 |
baseline 扫描 12、13 项;probe 扫描 13、14 项。probe 增加的入口项都不匹配当前查询,且两次追加时均有容量。**相同逻辑条目由查询 key 和创建次序定义,不能用“相同数组下标”定义。**
此时 `p[3] <= g[4].p`,使用 `g[4].T`,未消费 `h[64]`。需要比较实际压力/温度输入、medium/管道常量,以及查询和分支前置条件。
### 实际读取 → 必须保留的 probe 数据
U、D 的消费字段及 valid 测试与上例的两次 PT miss 路径一致,只需映射到 probe slot 13/14。pipe[0] 只消费入口 valid=0。
**保留 probe `states[0:13]` 的每个字段,包括 slot 12,以及其他全部 pipe 槽。** 本 operation 没有对已有物性条目的写入。入口 count 不需要等于 baseline,但它决定下一次追加位置,不能忽略其作用。
### 有序字段更新与追加动作
1. 在 probe 当前尾部追加 U:count 13→14,slot 13 完整初始化,写 mu/rho/factor/exponent 和对应 valid 位,最终 valid=29。
2. 重新按更新后的 probe context 查询 D;miss 后 count 14→15,slot 14 初始化,写 rho/factor/exponent 和对应 valid 位,最终 valid=21。
3. pipe[0] 执行同样的 11 次有序写入,包括同值 valid=0。
4. `q[45]=-3.34452871903457e-6`,model evaluator 返回 1。
把 baseline slot 12/13 的退出快照直接覆盖到 probe 会损坏原 slot 12;把 count 恢复为 baseline 14 会丢失 probe 的有效尾项。正确动作是“保留 probe 前缀,在 probe 当前 count 顺序追加”。
896 对中,638 对存在 count 差异,最大偏移 +4;829 对走两次 PT miss,67 对走近零流量路径且不增加 count。全部能建立一致的逻辑映射。
## 比较、保留、写回与 fallback 的边界
| 入口差异 / 动作 | 本次清单要求 |
|---|---|
| 未选中的条目 p/T/h/medium 不同 | 可允许数值不同,但必须验证仍被当前查询排除,不改变首次匹配关系 |
| count / slot 平移 | 可允许;用当前 probe count 检查容量,按 key/首次命中和创建顺序建立映射 |
| 选中已有条目的有效载荷不同 | 必须比较本分支实际消费的 T、mu、rho、factor、exponent 等;不一致则 fallback |
| valid 位不同 | 比较实际测试的掩码结果;未知分支不可放行。`valid |= flag` 应保留其余 probe 位,不能泛化为整字覆盖 |
| 入口未被读取的 h 或 pipe 旧键值不同 | 本分支可以忽略比较;仍须保留未被实际写入的 probe 数据 |
| 新条目 | 当前尾部追加;完整初始化再按事件次序赋值,同值写入也不能删除 |
| 已有条目更新 | 两例的完整运行未观察到。插桩已覆盖相关赋值,但不能声称已实测该分支;若后续出现,需要保留其原有有效字段、按映射定点更新 |
| 容量不足、无效 key、scratch 路径 | 本次未出现。清单要求 fallback,不能套用“必定追加两项” |
| 非空 temperature observer | 本次均为 NULL;非空会有外部观察器副作用,未验证,fallback |
| pipe 入口命中分支改变 | 本次目标槽均 valid=0;若变为有效需重新核验完整 pipe key、flow 载荷和分支,不能沿用本清单 |
| 首匹配不同 / 重复 key 改变匹配先后 | fallback;单纯“某处有同 key”不够 |
Jacobian scalar memo 是另一个需要保留的作用域:其 key、get 命中、put 尝试、recording/capacity 已记录。Jacobian 200 baseline 的两次 density 和一次 pipe scalar get 为 miss,probe 均 hit;返回数值一致。此处不能简单回放 baseline 的 memo 写入或统计副作用。当前诊断不修改该 memo;后续局部复用必须维持其生命周期和统计语义。
operation 本身是一次 double 赋值,没有独立 int 状态码。记录的是实际输出/pipe flow,以及包围它的 model evaluator 返回值;没有虚构 operation 成功码。
## 验收结果
- 3,584 次 operation(2 案例 × baseline/probe × 896),全部访问校验和退出 context 重放一致。
- 1,382,612 次字段/基址读取逐条核对通过;valid 掩码测试另外记录并校验。
- 每例 896 对的完整查询 key、hit/miss、首次匹配关系经过独立验证;按逻辑映射后的消费字段集合、valid 测试及有序写入一致。
- 136,606 次显式写入,其中 **10,614 次已知同值写入**;检查包括 pipe valid 的 0→0,未把未初始化槽的清零算作已知同值写入。
- 状态、输出、事件及所有 896 个 132×132 Jacobian 的 SHA-256 与已有未插桩基线一致;矩阵元素共 15,611,904 个。
- accepted=10,840,rejected=918,nfev=44,467,njev=896,nlu=3,106;Newton iterations=19,371,Newton convergence failures=798,均与基线一致。
- 2,688 次包含目标 operation 的 model evaluator 调用均返回 1;baseline 每次含两个目标 operation,所以该数小于 operation 数量。
- 证据校验器另有 6 个负例:遗漏同值写入、rho 读取错误、追加使用 baseline slot、恢复 baseline count、错误首匹配、错误 valid 位结果。它们是对证据校验器的反例测试,**不是已实现的生产 fallback 测试**。
插桩会引入大量日志开销,本次时长不用于评价优化收益。容量耗尽、scratch、非空 observer、已有物性条目更新及 pipe 命中分支未在这两个案例内实测,仍是未来实现时的明确边界。
## 复现与交付文件
需先保留已有 local-probe、context-fallback worker 及其 baseline 验证文件。它们的生成入口分别是 `local_probe_experiment.py`、`diagnose_context_fallback.py`;本次脚本会对缺失来源报错,不生成替代基线。
```powershell
.venv-win\Scripts\python.exe tests/manual/diagnose_context_access.py prepare
.venv-win\Scripts\python.exe tests/manual/diagnose_context_access.py run
.venv-win\Scripts\python.exe tests/manual/analyze_context_access.py
.venv-win\Scripts\python.exe tests/manual/verify_context_access_evidence.py
```
所有路径由脚本所在项目目录推导。原始证据和生成 worker 位于 `test/context-access-20260917/`,属于被 Git 忽略的运行产物:
- `worker/build.json`:来源及插桩源码 SHA-256。
- `audit/access.jsonl`:逐次实际查询、读取、测试、写入、分配、输出和返回事件。
- `audit/measurement.json`:全量仿真数值一致性哈希。
- `summary.json`:逐 Jacobian 的两路径对应关系。
- `operations.json`:全部 3,584 次 operation 的查询、消费字段、valid 测试、有序更新与追加。
- `jacobian-200.json`:两个主案例的原始事件和结构化清单。
- `negative-checks.json`:六项证据负例结果。
本报告及 [实测数值清单](context_access_checklists.md) 保存在 `tests/manual/`,可与诊断脚本一起提交。