325 lines
9.9 KiB
Markdown
325 lines
9.9 KiB
Markdown
## 目标
|
||
|
||
第二阶段不再以补丁式修 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 等关键数值语义必须在少数固定位置集中注释说明
|
||
- 优先保持文件短和职责单一,不为“保险”堆太多诊断与保护代码
|
||
|
||
这个阶段的核心产出不是新功能,而是一个能长期承载新功能的骨架。 |