## 目标

第二阶段不再以补丁式修 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 等关键数值语义必须在少数固定位置集中注释说明
- 优先保持文件短和职责单一，不为“保险”堆太多诊断与保护代码

这个阶段的核心产出不是新功能，而是一个能长期承载新功能的骨架。