From 782422e800506d73b61aeda9476ac145804be6ef Mon Sep 17 00:00:00 2001 From: Ying-Li Niu <64801511@qq.com> Date: Fri, 12 Jun 2026 15:15:10 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E6=B7=BB=E5=8A=A0=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E5=BB=BA=E8=AE=AE=E6=96=87=E6=A1=A3=20optimization/workbuddy.m?= =?UTF-8?q?d?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 涵盖架构/性能/代码质量/配置/测试/引擎一致性/UX 等 9 个方面、26 条具体建议,标注实施优先级和工作量。 --- optimization/workbuddy.md | 303 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 303 insertions(+) create mode 100644 optimization/workbuddy.md diff --git a/optimization/workbuddy.md b/optimization/workbuddy.md new file mode 100644 index 0000000..011c924 --- /dev/null +++ b/optimization/workbuddy.md @@ -0,0 +1,303 @@ +# Dynamics 项目优化建议 + +> 分析日期:2026-06-12 +> 版本:main (43 commits) + +--- + +## 1. 架构优化 + +### 1.1 compute.py 拆分(高优先级) + +**现状**:`compute.py` 1618 行,混合了以下职责: +- 物理引擎(数值积分方法 ~10 个函数) +- 文件 I/O(JSON/text 读写) +- 外部引擎管理(subprocess 调用) +- 参数加载与解析 +- 主入口 main() + +**建议**:按职责拆分为独立模块 + +``` +compute/ +├── __init__.py # 导出公共 API +├── core.py # 物理引擎: 数值积分方法, 力的计算 (~200 行) +├── io.py # 文件 I/O: save/load display/trajectory (~300 行) +├── params.py # 参数加载: load_coord_file, load_bond 等 (~150 行) +├── runner.py # 运行管理: run_simulation, run_engine, run_from_config (~200 行) +├── engine_helper.py # 外部引擎: 校准, subprocess, 进度监控 (~150 行) +└── main.py # 主入口: main(), if __name__ == "__main__" (~30 行) +``` + +**收益**:可单独测试物理算法、文件读写、引擎调用 + +### 1.2 外部引擎代码重构(中优先级) + +**现状**:C/C++/Fortran 引擎各自实现了一套: +- JSON 读取/写入(3 套独立实现) +- 物理算法(复制粘贴) +- display.txt / trajectory.txt 输出 + +**建议**: +- C 和 C++ 引擎共用头文件/函数库 +- 物理算法提取为公共库(`engines/common/`) +- Fortran 更新支持 `save_trajectory` 兼容 + +--- + +## 2. 性能优化 + +### 2.1 外部引擎校准耗时(高) + +**现状**:`run_engine()` 每次执行前先跑 1000 步校准测速(`_calib_nt = min(1000, max(100, total_steps // 10))`),对短时运行(~1000 步)校准占比高达 50%。 + +**建议**: +- 缓存校准结果:按 `(engine, NT, DT, NSTEP, n_atoms)` 哈希缓存 +- 或对短运行 (<5000 步) 跳过校准 +- 或只在校准目录为空时执行 + +```python +# 建议改动 +_calib_cache = os.path.join(script_dir, "engines", engine, "_calib_cache.json") +if os.path.exists(_calib_cache): + with open(_calib_cache) as f: + _calib_data = json.load(f) + if _calib_data.get("key") == _calib_key: + _step_time = _calib_data["step_time"] + _overhead = _calib_data["overhead"] + skip_calibration() +``` + +### 2.2 display.txt 读取加速(已完成) + +**现状**:已从逐行 `split()+float()` 改为 `np.genfromtxt()` 批量解析,200帧×120原子 加载仅 0.087s(测试已通过)。 + +### 2.3 Python 引擎性能(低) + +**现状**:Python 引擎比 C 引擎慢约 6-8 倍(43s vs 7s for 10 万步)。对 50 万步以上的长时间模拟不适用。 + +**建议**: +- 使用 Numba JIT 加速力的计算 +- 或使用 `numpy.vectorize` 替代 Python 循环(力的计算中已部分使用 numpy 数组操作) +- 文档中注明 Python 引擎仅适用于小规模测试 + +### 2.4 校准数据的进度条(已修复) + +校准后进度条使用实时帧号更新,不再使用时间估算,避免了 `0% → 100%` 跳变。但注意校准本身不显示进度。 + +--- + +## 3. 代码质量 + +### 3.1 消除全局变量(高优先级) + +**现状**:`compute.py` 定义了 40+ 个模块级全局变量: + +```python +box_a = None +alpha = None +ATOM_IDS = None +... +``` + +所有算法函数直接依赖这些全局变量,导致: +- 无法并发运行两个模拟 +- 无法单元测试单个函数 +- 函数签名无法自文档化 + +**建议**:将全局状态封装为 `SimulationState` 类: + +```python +@dataclass +class SimulationState: + box_a: float = 10.0 + atom_ids: np.ndarray = None + atom_masses: np.ndarray = None + ... + +def leapfrog(state: SimulationState, ...): + ... +``` + +### 3.2 draw.py 全局变量(中优先级) + +**现状**:类似的问题,`draw.py` 用了 ~30 个模块级变量: + +```python +DISPLAY_X = ... +DISP_ALL_X = ... +N_FRAMES = ... +frame_idx = 0 +``` + +**建议**:封装为 `AnimationData` 和 `CameraState` 类 + +### 3.3 废弃文件清理(低优先级) + +以下文件可能已废弃或重复: + +| 文件 | 行数 | 判断 | +|------|------|------| +| `sample.py` | 184 | 已不再被调用(抽帧已移至引擎内部) | +| `build_release_zip.py` | - | 打包脚本,非核心功能 | +| `export_web_data.py` | - | 导出脚本,非核心功能 | +| `migrate_npz_outputs.py` | - | 迁移脚本,一次性使用 | +| `tools/NumericalMethods.py` | - | 可能已过时 | +| `build/` (CMake 相关) | - | 与独立引擎编译无关 | + +--- + +## 4. 配置管理 + +### 4.1 input.txt 格式统一(高优先级) + +**现状**:6 个案例的 `input.txt` 格式不统一: + +| 字段 | case01 | case06 | +|------|--------|--------| +| `save_trajectory` | ❌ 缺失 | ✅ 有 | +| `camera_distance/elevation/azimuth` | ❌ 缺失 | ✅ 有 | +| `move_camera` | ❌ 缺失 | ✅ 有 | +| `step_sample` | 仍然写 1 | 已改为 0 | +| `step_plot`配置 | 旧注释格式 | 新注释格式 | + +**建议**: + +```yaml +# 统一模板 +flow: + step_simulate: 1 + step_sample: 0 # 引擎已内置抽帧 + step_animation: 1 + save_trajectory: 0 # 默认不保留 + +physics: + box_a: 10.0 + G: [0, 0, -9.8] + method: leapfrog + T_total: 10.0 + NSTEP: 100 + DT: 0.001 + +render: + use_marker: 0 + alpha: [0.0]*6 + ball_color: [0.9, 0.2, 0.2] + box_color: [0.8, 0.8, 0.85] + camera: + distance: 40.0 + elevation: 0 + azimuth: 0 + move: false +``` + +### 4.2 YAML 结构优化(中优先级) + +**现状**:`ball_color_r/g/b` 三个独立的键,YAML 列表更自然: + +```yaml +# 当前 +ball_color_r: 0.90 +ball_color_g: 0.20 +ball_color_b: 0.20 + +# 建议 +ball_color: [0.90, 0.20, 0.20] +``` + +--- + +## 5. 测试与质量 + +### 5.1 缺少测试(高优先级) + +**现状**:无单元测试、无集成测试。每次修改只能手动跑案例。 + +**建议**: +- 为 `compute.py` 的物理算法(Leapfrog、Euler 等)添加 pytest 测试 +- 为文件 I/O(`save_display_txt` / `load_display_txt` 读写一致性)添加测试 +- 添加一个 `examples/case00` 最小验证案例(2 个原子,10 步) +- CI:`pytest` + 简单的集成测试脚本 + +### 5.2 缺少类型标注(中优先级) + +```python +# 现状 +def leapfrog(x, y, z, vx, vy, vz, dt, m, g, b): + +# 建议 +def leapfrog( + x: np.ndarray, y: np.ndarray, z: np.ndarray, + vx: np.ndarray, vy: np.ndarray, vz: np.ndarray, + dt: float, m: np.ndarray, g: np.ndarray, b: np.ndarray +) -> tuple[np.ndarray, np.ndarray, np.ndarray, + np.ndarray, np.ndarray, np.ndarray]: +``` + +--- + +## 6. 引擎一致性 + +### 6.1 Fortran 引擎更新(高) + +**现状**:Fortran 引擎**不支持** `save_trajectory=0` 模式,总是写 JSON 格式的 `trajectory.txt`。需要: + +1. 读取 `save_trajectory` 参数 +2. 计算时按 NSTEP 采样 +3. 写 display.txt 新格式 +4. 按条件跳过 trajectory.txt 输出 + +参考 C 引擎的 `write_display_txt` 实现(约 40 行代码)。 + +### 6.2 参数默认值一致性(中) + +各引擎的 `SimParams` 默认值不一致: + +| 参数 | C | C++ | Fortran | +|------|---|---|---------| +| `box_a` | 无默认 | 10.0 | 10.0 (代码中) | +| `method` | leapfrog | leapfrog | leapfrog | +| `save_trajectory` | 0 | 1 | 不支持 | + +--- + +## 7. 用户体验 + +### 7.1 进度条改进(低) + +- 外部引擎校准阶段不显示进度(建议加 "校准中…" 文本) +- Fortran 引擎支持时,增加进度消息 + +### 7.2 缓存一致性(已修复) + +已修复:`display.txt` 在 `save_trajectory=0` 时不再保留 `trajectory.txt`,外部引擎路径总是从 `trajectory.txt` 重新抽帧。 + +### 7.3 move_camera.txt 实时生效(已修复) + +`draw.py` 直接读取 `move_camera.txt`,修改后重启动画即可生效,无需重新跑模拟。 + +--- + +## 8. 实施优先级 + +| 优先级 | 内容 | 预估工作量 | +|--------|------|-----------| +| P0 | Fortran 引擎支持 save_trajectory=0 | 2-3h | +| P0 | 全局变量封装为 SimulationState | 3-4h | +| P1 | compute.py 模块拆分 | 4-6h | +| P1 | 添加单元测试 (pytest) | 3-5h | +| P1 | input.txt 格式统一 (6个案例) | 1-2h | +| P2 | 校准缓存加速 | 1-2h | +| P2 | 废弃文件清理 | 0.5h | +| P3 | draw.py 封装 AnimationData | 2-3h | +| P3 | 类型标注 | 2-3h | + +--- + +## 9. 快速 wins(半小时内可完成) + +1. ✅ 更新 Fortran 引擎(参考 C 的 `write_display_txt` 迁移) +2. ✅ 删除 `sample.py`(已废弃) +3. ✅ 统一 6 个案例的 `input.txt` 格式 +4. ✅ 添加 `save_trajectory` 到 case01-05 的 default 配置 +5. ✅ 统一 `ball_color_r/g/b` 为 `ball_color` 列表