## 审计结论(第二轮) 本轮审计的视角与上一轮不同。上一轮聚焦"主链路上是否有显式 bug"(找到了 16 项)。本轮审计的四个维度: | 维度 | 上一轮 | 本轮 | |---|---|---| | 主链路正确性 | 找显式 bug | 确认修补正确、无回归 | | 代码架构质量 | 少量提及 | 系统评估 Python 层职责分离 | | 新代码 | 不存在 | streakline.py 全篇 + test runners | | 跨层一致性 | 仅一处 | 系统性检查 config → compiler → kernel → docs 同步 | 核心结论:**上次 16 项修补经逐条审查确认正确,无回归。** ### 第二轮修改完成状态 根据审计发现,已完成以下修改: | 修改项 | 状态 | |---|---| | EsoPull 添加 y=1/NY-2 半格 bounce-back 修正(D2Q9 + D3Q19) | ✅ 已实施 | | `macro.cuh` diagnostic 函数标注 | ✅ 已标注 `// --- Diagnostic only ---` | | `config.py` `omega_max` 默认值 1.99 → 1.96 | ✅ 已修改 | | `BC_MOVING`/`BC_PERIODIC` 代码注释说明 | ✅ 已添加 TODO 注释 | | Streakline 模块重构:779 行单文件 → `common/streakline/` 子包 (5 文件) | ✅ 已完成 | | `run_kan99b_streakline.py` 更新为新 API | ✅ 已完成 | | `run_exp_ctrl_matrix_streakline.py` 更新为新 API | ✅ 已完成 | | `render_vorticity_field` 移到 `common/render.py` | ✅ 已完成 | | `ParticleTrailSet` 移到 `common/pathline.py` | ✅ 已完成 | | 向后兼容 shim `common/streakline.py` | ✅ 已创建(带 DeprecationWarning) | --- ## 状态说明 - `[已确认]` 经代码审查确认正确 - `[无法确认: 需运行验证]` 需数值算例确认,不能单靠读代码定论 - `[新发现]` 本轮审计首次发现 - `[已修复]` 已实施修改 - `[保留说明]` 当前不修,但需在代码或文档中明确限制 --- ## 第一轮审计修补确认 逐一确认 16 项"已解决"修补在代码中的真实状态。**全部 [已确认],无回归。** | 问题 | 结论 | 关键文件:行号 | |---|---|---| | `lbm/__init__.py` 导出错误 | 已确认 | 当前导出真实存在的 `add_vortex` | | forcing 主链路 + 预因子不一致 | 已确认 — 三模型统一使用 `c_tau = 1-omega/2` | `operators/collision_srt.cuh:15`, `collision_trt.cuh:35`, `collision_mrt.cuh:41/116` | | TRT outlet NEQ 重构未补齐 | 已确认 — COMPILE_MODEL==0\|1 时全分布 damped NEQ | `boundary/outlet/pressure_neq.cuh:45-51` (D2Q9) | | `add_vortex()` 动量当速度 | 已确认 — `ux = sum(f*cx) / rho_safe` | `lbm/initializers.py:57-58` | | Sensor 面积归一化 | 已确认 — ObjectManager 层已提供 | `body/manager.py` | | `sync_to_gpu()` 重置非流体 | 已确认 — 已收缩为只覆盖 obstacle interior | `body/manager.py` | | curved donor 合法性 | 已确认 — 扩展到实际 domain flags | `body/objects.py` `_donor_is_fluid` | | curved Bouzidi 时序 | 已确认 — 步前写入 obstacle source slot | `lbm/stepper.py:70-71` → `step/aux_kernels.cu:14` | | `q >= 0.5` 分支读错时间层 | 已确认 — 读 `load_ddf(fi, ...)` 即同一步 post-collision | `boundary/curved_boundary.cuh:73-75` | | moving wall 修正未按 q 分支 | 已确认 — 分三路:fallback / q<0.5 / q>=0.5 | `boundary/curved_boundary.cuh:30-43` | | 初始化链路 flag 叠加顺序 | 已确认 — obstacle overlay → init kernel preserve → equilibrium | `step/init_flow.cu:48-52`, `lbm/stepper.py:43-54` | | `config_body.json` 未进入初始化 | 已确认 — Simulation 已消费 | `simulation.py` | | inlet `U0` 语义 | 已确认 — 已补充截面平均速度注释 | `configs/CONFIG.md`, `README` | --- ## 本轮发现与处理 ### CUDA Kernel 层 | 严重度 | 问题 | 文件:行号 | 处理 | |---|---|---|---| | **[新发现]** [高] | **`BC_MOVING` 与 `BC_PERIODIC` 标记未在 step kernel 中分发。** `core/flags.cuh` 定义了两种标记,但 step kernel 中没有 `is_moving()` 或 `is_periodic()` 分支。设了这两种标记的 cell 会静默 fall through 到 `bounce_back_swap()`。 | `step/one_step_double.cu`, `step/one_step_esopull.cu` | **[保留说明]** 已添加 TODO 注释,暂不实现 | | **[新发现]** [高] | **EsoPull 缺少 y=1/NY-2 的显式半格 bounce-back 修正。** Double-buffer 路径有该修正而 EsoPull 无。 | `step/one_step_esopull.cu` | **[已修复]** 已添加 D2Q9 和 D3Q19 分支,标注了未来可能需要更精确方案 | | **[新发现]** [中] | **`USE_DDF_SHIFTING` 路径完整性存疑。** 审查后确认:`macro.cuh` 和 `init_flow.cu` 已处理 shifted,各 collision/curved operator 通过 `load_ddf`/`store_ddf` 抽象层自动适配。**实际已完整,无需修改。** | — | **[已确认无需处理]** | | **[新发现]** [低] | **`compute_pressure` 与 `compute_pressure_perturbation` 未标注诊断用途。** | `operators/macro.cuh:160-166` | **[已修复]** 已标注 `// --- Diagnostic only ---` | | **[新发现]** [低] | **Curved/Sensor kernel 无运行时下标越界保护。** 完全依赖 host 侧验证。 | `step/aux_kernels.cu:26-99` | **[保留说明]** 设计选择:不引入多余合法性检查 | ### 第一轮遗留待验证项复查 | 待验证项 | 状态 | 说明 | |---|---|---| | **MRT D2Q9 moment transform/inverse** | **[无法确认: 需运行验证]** | 方向索引与 paired ordering 自洽,moment 投影物理正确。但全部系数的数值精度需在 Poiseuille 或衰减涡算例中验证。 | | **EsoPull 邻壁 vs double-buffer 一致性** | **[已修复]** | 已添加 y=1/NY-2 反弹修正。需运行验证确认。 | | **Force 提取与 host 侧归一化** | **[无需处理]** | Cd/Cl 管道经确认语义一致。 | | **Plain linear Bouzidi / TRT 不兼容** | **[保留说明]** | 注释已存在且准确,引用了 [Gin08b]。无方法级替代方案。 | --- ## 架构与设计审计 ### Streakline 模块重构 **旧 `common/streakline.py` (779 行) 已被拆解为 `common/streakline/` 子包:** ``` src/CelerisLab/common/ streakline/ 后处理子包 __init__.py 导出 Streakline, ReleaseConfig, IntegratorConfig _config.py 配置 dataclass + FlowFrame 内部类 _integrate.py 核心积分引擎 (RK4 + 时空插值) _render.py 密度图渲染 (render_density) _streakline.py Streakline 类 (被动消费者) render.py 涡度计算与渲染 (从旧 streakline 移出) pathline.py ParticleTrailSet + render_trails (从旧 streakline 移出) preprocess.py 增加 cylinders_from_triangle_layout ``` **核心设计变更:** | 旧设计 | 新设计 | |---|---| | `run_streakline_online(sim, ...)` 控制仿真循环 | `Streakline.observe(ux, uy, step)` 被动接收帧 | | `run_streakline_offline(frames, ...)` 批处理帧列表 | 移除(无需求) | | `render_streakline_density(positions, ages, ...)` 15 参数 | `Streakline.render(path)` 内部维护状态 | | `ParticleTrailSet` 与正确实现混在同一文件 | 移到独立 `pathline.py` | | `render_vorticity_field` 与粒子跟踪无关 | 移到独立 `render.py` | | `gaussian_blur2d` 用 `np.apply_along_axis` | 改为显式 `for` 循环 + `np.convolve` | | `minimal_axes=True/False` 分支重复 | 合并为单路径 `_save_minimal_image` | **用法示例:** ```python streak = Streakline(release_points=..., nx=nx, ny=ny, cylinders=...) # 在自己的仿真循环中: macro = sim.get_macroscopic() streak.observe(ux=macro["ux"], uy=macro["uy"], step=step) # ...同时可以做 body actions、checkpoint、其他模块... streak.render("output.png") ``` ### Body 模块 | 严重度 | 问题 | 行号 | 处理 | |---|---|---|---| | **[架构]** | **`ObjectManager` 承担 8 种以上职责。** `sync_to_gpu()` 单枪匹马编排了全部流程。 | `body/manager.py` (423 行) | **[暂不处理]** | | **[架构]** | **`Cylinder.get_curved_list()` ~180 行包含 7 种职责。** 内嵌函数无法单独测试。 | `body/objects.py:110-291` | **[暂不处理]** | | **[架构]** | **自上一轮审计以来 body 模块重构进展为零。** | 全部 | **[暂不处理]** | ### Config/API 层 | 严重度 | 问题 | 行号 | 处理 | |---|---|---|---| | **[已确认]** | **FP16C 被正确拒绝。** | `config.py:119-123` | ✅ | | **[已确认]** | **28/28 参数通过四层一致性检查。** | B4a 参数追踪表 | ✅ | | **[已确认]** | **OBS 布局四层完全匹配。** | B4d 对比表 | ✅ | | **[架构/低]** | **CONFIG.md 写"建议整除"而非"必须"。** 代码用 ceiling division。 | `configs/CONFIG.md:13`, `lbm/stepper.py:272-274` | **[保留说明]** | | **[已修复]** | **`LBMConfig` 默认 `omega_max=1.99` → `1.96`,与 JSON/CONFIG 一致。** | `config.py:84` | ✅ | ### 跨层 Flag/常量同步 | 问题 | 状态 | |---|---| | **`FLAG_*` 常量 Python ↔ CUDA 同步** | **[已确认]** 全部一致 | | **`LBMParams` struct 布局耦合** | **[保留说明]** | | **V_TAYLOR 硬编码 1** | **[保留说明]** | --- ## 测试覆盖率审计 ### Validation runner 与文档一致性 | 结论 | 项目 | 说明 | |---|---|---| | **[通过]** | Sah04 runner S1-S4 | 四个锚点全部定义并运行 | | **[缺口]** | Sah04 runner `--u-max` | `u_max_nominal=0.1` 写死 | | **[缺口]** | Sah04 runner high-beta 网格 | 默认直径与文档推荐不一致 | | **[通过]** | Kan99b runner K1-K5 | 全部 5 个 case,K2 有 gate | | **[缺口]** | Kan99b runner K3-K5 | 未做抑制分类自动检测 | | **[通过]** | 输出机器可读 | 均输出 JSON/CSV | ### 测试基础设施 | 严重度 | 结论 | |---|---| | **[严重缺口]** | **零 pytest/unittest 基础设施。** | | **[严重缺口]** | **四个旧待验证项仅 EsoPull 已修,余三项(MRT、curved boundary、force 归一化)未覆盖。** | ### 建议的最低测试覆盖面(优先级排列) 1. **MRT 单元测试**(uniform flow / Poiseuille / decaying vortex)— 单元级 2. **力系数归一化测试** — 单元级 3. **Curved boundary 单列测试** — 单元级 4. **EsoPull vs double-buffer 一致性**(Poiseuille 流对比)— 单元/集成级 5. **Validation runner smoke 测试** — 验证级 --- ## 保留说明 - **`BC_MOVING` / `BC_PERIODIC` 未分发** — 已标注 TODO,暂不实现 - **Curved/Sensor kernel 无运行时越界检查** — 设计选择(依赖 host 验证) - **Plain linear Bouzidi 与 TRT 不天然相容** [Gin08b] — 注释已存在 - **Curved wall 无质量守恒修正** — 长时间高 Re 周期 curved flow 可能出现力漂移 [San18] - **入口 `U0` 是截面平均速度**,抛物入口峰值为 `1.5*U0` - **角点 flag 语义不一致**:初始化时按 inlet/outlet 分类,边界核又落回 `bounce_back_swap()` - **3D 刚体旋转契约是 z 轴占位实现**(`aux_kernels.cu:58-63`,`Ww = 0.0f`) - **Curved boundary 仍是圆形几何特化**,没有为任意离散几何留出入路径 - **`LBMParams` struct 布局** 在 Python `struct.pack` 与 CUDA struct 之间硬耦合 - **CONFIG.md NT 整除性措辞**:写"建议",代码用 ceiling division --- ## 修改项汇总 | 类别 | 计数 | |---|---| | 第一轮修补确认 | 12 项全部 [已确认] | | 本轮已修复 | 6 项 | | 保留说明 | 10 项 | | 暂不处理 | Body 重构 / 测试基础设施 / Validation runner 缺口 |