210 lines
11 KiB
Markdown
210 lines
11 KiB
Markdown
## 审计结论(第二轮)
|
||
|
||
本轮审计的视角与上一轮不同。上一轮聚焦"主链路上是否有显式 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 缺口 |
|