CelerisLab/docs/audit/body_refactor_notes.md

325 lines
9.9 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.

## 目标
第二阶段不再以补丁式修 bug 为主,而是重建 `body``LBM` 之间的模块边界,形成可持续扩展到 Bouzidi、IBM、粒子和多相耦合的骨架。重构后的代码需要保持短文件、清晰职责、显式契约并避免几何语义直接渗入 CUDA 核心计算链路。
## 第一阶段与第二阶段的边界
### 第一阶段
目标是验证当前修复后的代码没有恶化,并保住最基本执行链路。
- 能稳定计算流场
- 能读取力与力矩
- Bouzidi 路径不出现新的时序性错误
- 初始化、flag、object overlay 不再互相污染
- 现有接口不做大改,只修运行期 bug 和明显契约错误
### 第二阶段
目标是结构性重构,而不是继续在旧链路上叠加特例。
- 重构 `body`
- 重构 curved boundary 数据链
- 为 IBM 预留统一入口
- 为简单几何和离散几何建立同一中间表示
- 为未来多相与多物理场保留清晰耦合面
## 当前架构的核心问题
### 主要问题
| 模块 | 当前问题 | 后果 |
|---|---|---|
| `body` | 几何、flag overlay、compact list、action、obs、coupling 混在一起 | 任一功能扩展都会牵动整条链路 |
| `objects.py` | 几何对象直接生成 Bouzidi 专用数据 | 简单几何和离散几何无法共享同一接口 |
| `curved_boundary` | 几何解释、边界格式、移动壁修正、力提取绑在同一层 | 替换边界方法成本高 |
| `ObjectManager` | 过度集中,已经接近万能管理器 | 可读性下降,后续只能继续膨胀 |
| host-device contract | 分散在多个文件,缺少统一定义 | 调试困难,容易出现隐式耦合 |
### 本质判断
当前最大问题不是公式本身,而是缺少稳定的中间层。几何对象、边界方法、运行时打包目前没有被拆开,导致代码很难既简洁又可扩展。
结合本轮修 bug 的经验,再补一条判断:很多问题不是几何本身出错,而是 donor、fallback、time layer 这类数值语义散落在不同文件中,读代码时必须来回跳转才能确认。当前项目更适合把这些语义集中写进少数注释位置,而不是继续加更多隐式保护逻辑。
## 第二阶段的目标架构
### 顶层模块
保持两大物理模块:
- `LBM`
- `body`
但它们之间不直接互相了解实现细节,而通过显式中间数据结构耦合。
### 推荐分层
| 层级 | 职责 | 不应负责 |
|---|---|---|
| `simulation` | 装配模块,定义推进顺序 | 几何处理,边界公式细节 |
| `body` | 几何、刚体状态、预处理、力回收 | DDF 操作LBM 核心算法 |
| `lbm` | 格子流体、collision、streaming、boundary operator | 几何来源,刚体业务语义 |
| `coupling` | cut-link、IBM marker、body-fluid 数据交换 | 具体几何类定义,具体 collision 实现 |
## 推荐的 body 内部结构
### 目标
`body` 应只表达拉格朗日对象和几何处理,不直接承载 LBM 业务逻辑。
补充边界:`body` 负责管理对象并产出统一 cut-link 几何记录,`lbm` 只消费 cut-link 做数值计算。对象类型区分、几何来源、以及“该记录来自圆柱还是离散几何”都不应进入 LBM kernel 视野。
### 推荐文件树
```text
body
geometry
base
circle
sphere
polygon
mesh
state
rigid_body_state
particle_state
preprocess
flag_overlay
cut_links
ibm_markers
sensors
runtime
action_buffer
telemetry_buffer
registry
coupling
wall_velocity
force_torque
```
### 说明
- `geometry` 只回答几何问题
- `state` 只保存状态量
- `preprocess` 负责把几何投影到欧拉网格
- `runtime` 负责 GPU 上传与 buffer 管理
- `coupling` 负责 body 与 fluid 的交换规则
进一步要求:
- `geometry` 不直接生成 Bouzidi 专用 SoA
- `preprocess` 先产出统一 cut-link 结果,再由更薄的一层做运行时打包
- `runtime` 不回头参与几何判断
- 单文件保持简短,避免再出现一个文件同时含几何、打包、上传、观测解释四类职责
## 推荐的 LBM 边界
### LBM 应该看到什么
LBM 只应看到这些输入:
- `flag`
- `cut-link records`
- `IBM marker records`
- `runtime params`
- `obs buffers`
LBM 不应知道:
- 该 link 来自圆柱还是三角网格
- 该对象是粒子还是障碍物
- 该边界记录由哪种 host 几何算法产生
## curved boundary 的重构方向
### 核心原则
不要把 curved boundary 等同于 Bouzidi。
需要拆成三个维度:
- 几何表示
- 边界处理方法
- 运动模型
补充一条实现原则donor、fallback、time layer 等关键数值语义,优先通过集中注释写清楚,不额外引入很多“自动保证语义”的复杂逻辑。当前项目更优先保持代码短、直、可读。
### 建议的统一中间表示
定义通用 `cut-link record`,至少包含:
| 字段 | 含义 |
|---|---|
| `fluid_idx` | 流体格点索引 |
| `dir` | 指向边界的格子方向 |
| `q` | 交点沿链路的位置 |
| `body_id` | 所属物体 |
| `hit_point` | 壁面交点 |
| `lever_arm` | 相对参考点的力臂 |
| `normal` | 壁面法向 |
| `motion_tag` | 静止、平移、旋转等 |
| `scheme_tag` | Bouzidi、half-way、未来 TRT-compatible scheme |
| `fallback_tag` | donor 非法时的退化方式 |
补充约束:
- `cut-link record` 只表达几何命中结果与最小运行时字段,不直接长成某一种 kernel 专用格式
- donor 的来源与时间层语义不额外做复杂自动推断,靠集中注释写清楚
- 记录字段命名要直接对应 kernel 使用含义,避免同一字段在不同文件中有不同解释
### 这样做的好处
- 圆形和离散几何可以输出同一种记录
- Bouzidi 与 IBM 可以共享一部分几何预处理
- boundary kernel 只消费记录,不关心几何来源
- 以后替换边界方法时,不必回改对象类
- donor、fallback、hit-point 这类契约可以在少数固定注释位置集中说明,而不是散落在对象类和 kernel 两侧
## IBM 的预留方式
IBM 不应和 Bouzidi 混成一条链,而应与 cut-link 平行。
建议另设统一 `marker record`,用于:
- 插值点位置
- 支撑域格点
- 权重
- 与刚体的归属关系
这样未来可以并存:
- cut-link boundary
- IBM boundary
- 混合策略
## 运行时契约的建议
### 必须显式化的契约
应把 host-device contract 从各文件中收口,单独维护。
建议集中定义:
- action buffer layout
- telemetry buffer layout
- cut-link record layout
- marker record layout
- force torque sign convention
- body velocity contract
### 运动状态契约
即使短期只做 2D 圆柱旋转,也建议按最终形式设计:
| 状态 | 建议字段 |
|---|---|
| 平移 | `vx vy vz` |
| 角运动 | `wx wy wz` 或 2D 的 `omega` 特化视图 |
| 参考点 | `cx cy cz` |
| 姿态 | `theta` 或旋转表示 |
不要再把 3D 路径固化为“只读一个 z 轴 `omega`”。
## 第二阶段推荐顺序
### 阶段 2A
先把职责边界拆开,不追求新功能。
-`ObjectManager`
- 建立 `BodyRegistry`
- 建立 clean `runtime buffer`
- 建立单独的 geometry preprocess 层
- 把“对象管理”和“cut-link 产出”分开
验收标准:
- `body` 不再直接知道具体 LBM kernel 调度
- `ObjectManager` 不再承担几何、obs、state、flag 全部职责
- `objects.py` 不再直接输出某一种 boundary method 专用打包格式
### 阶段 2B
重构 curved boundary 数据链。
- 定义统一 `cut-link record`
- 让圆柱先输出新 record
- 让 Bouzidi kernel 消费新 record
- 把现有 `CurvedLinkSoA` 从“Bouzidi 专用”改成“通用 cut-link buffer`
- donor 与 fallback 的契约集中写入注释,不额外增加复杂语义保护代码
验收标准:
- kernel 不需要知道几何来源
- host 侧可以替换 cut-link builder 而不改 kernel 接口
- 读 builder 与 kernel 时,不需要跨很多文件才能理解 donor 和 fallback 的基本语义
### 阶段 2C
为 IBM 留入口。
- 定义 `marker record`
- 预留独立 preprocess 和 runtime buffer
- 暂不实现完整 IBM 细节,只把架构位置留好
验收标准:
- IBM 不需要重写 body 骨架
- IBM 与 Bouzidi 可以共存于同一 body 系统
### 阶段 2D
补文档与契约说明。
- 当前能力
- 预留能力
- 不支持项
- 2D 与 3D 差异
- TRT 与 plain Bouzidi 的限制
## 不建议做的事
- 不要继续强化万能 `ObjectManager`
- 不要让几何对象直接生成某一种边界格式专用 SoA
- 不要把 curved boundary 和 Bouzidi 永久绑定
- 不要在 3D 运动契约上继续堆占位特例
- 不要在第二阶段把多相、IBM、粒子一起全做完
- 不要为了“自动保证语义”继续增加很多隐式逻辑分支,优先用集中注释把契约写清楚
- 不要引入必须跨很多文件来回跳转才能理解的 host-kernel 组织方式
## 第二阶段完成后的理想状态
### 代码层面
- 文件更短
- 模块职责更单一
- host-device contract 更显式
- kernel 更专注于数值操作
- geometry 与 boundary method 解耦
### 扩展层面
后续可自然扩展到:
- 离散几何 cut-link
- IBM marker 链路
- 粒子和刚体共用 body runtime
- 多相流对 body 的额外 coupling
### 维护层面
后续新增功能时,优先在对应层增加文件,而不是回到单个 manager 中继续堆逻辑。
## 建议的执行方式
第二阶段执行前,先固定一个简短设计约束:
- 单文件不过长
- 新增模块必须有明确职责说明
- 任何 host-device 数据结构必须有集中定义
- 新接口先定义契约,再写 kernel
- 能通过新增 builder 解决的问题,不要回写到 geometry 类中
- donor、fallback、time-layer 等关键数值语义必须在少数固定位置集中注释说明
- 优先保持文件短和职责单一,不为“保险”堆太多诊断与保护代码
这个阶段的核心产出不是新功能,而是一个能长期承载新功能的骨架。