# TLUSTY/SYNSPEC Rust 重构计划 ## 概述 **目标**: 将 TLUSTY/SYNSPEC Fortran 代码渐进式重构为 Rust **策略**: 从 `tlusty/extracted/` 中无 COMMON 依赖的纯函数开始,一个文件一个文件地重构 **代码规模**: - TLUSTY: 304 个单元,195 个纯函数 - SYNSPEC: 168 个单元,93 个纯函数 --- ## 1. 重构原则 1. **渐进式**: 每次只重构一个文件,保持系统可用 2. **测试驱动**: 每个重构的函数必须有测试验证 3. **精度保证**: 与 Fortran 输出对比,相对误差 < 1e-10 4. **文档先行**: 记录每个函数的算法和边界条件 --- ## 2. 源文件位置 ``` tlusty/extracted/ # TLUSTY 拆分后的文件 ├── expo.f # 纯函数示例 ├── yint.f ├── tridag.f ├── ... ├── _PURE_UNITS.txt # 无 COMMON 依赖的函数列表 ├── _COMMON_ANALYSIS.txt # COMMON 依赖分析 └── _SUMMARY.txt # 提取摘要 synspec/extracted/ # SYNSPEC 拆分后的文件 └── ... ``` --- ## 3. 推荐重构顺序 按文件大小从小到大排序(简单优先): ```bash # 查看最小文件 cd /home/fmq/program/tlusty/tl208-s54/rust while read name; do if [ -f "tlusty/extracted/${name,,}.f" ]; then lines=$(wc -l < "tlusty/extracted/${name,,}.f") echo "$lines $name" fi done < tlusty/extracted/_PURE_UNITS.txt | sort -n | head -20 ``` **第一批 (最简单)**: | 顺序 | 文件 | 行数 | 功能 | |------|------|------|------| | 1 | expo.f | 10 | 安全指数函数 | | 2 | quit.f | 10 | 退出子程序 | | 3 | ffcros.f | 13 | 截面计算 | | 4 | gamsp.f | 14 | 展宽因子 | | 5 | sgmer1.f | 14 | Stark展宽 | | 6 | sgmerd.f | 15 | Stark展宽 | | 7 | lagran.f | 16 | Lagrange插值 | | 8 | gntk.f | 17 | Gaunt因子 | | 9 | raph.f | 17 | 有理化函数 | | 10 | cross.f | 18 | 截面计算 | | 11 | eint.f | 18 | 指数积分 | | 12 | sghe12.f | 18 | He 展宽 | | 13 | yint.f | 18 | 二次插值 | | 14 | erfcin.f | 20 | 误差函数补 | | 15 | erfcx.f | 20 | 缩放误差函数 | | 16 | gfree1.f | 21 | Gaunt自由 | | 17 | sbfhmi_old.f | 22 | H- 截面 | | 18 | tridag.f | 22 | 三对角矩阵求解 | | 19 | timing.f | 24 | 计时 | | 20 | expint.f | 30 | 指数积分 | --- ## 4. 单文件重构流程 ### Step 1: 读取并分析 Fortran 源码 ```bash # 读取源文件 cat tlusty/extracted/expo.f ``` 记录以下信息: - 函数名/子程序名 - 输入参数及其类型 - 返回值 - 算法逻辑 - 边界条件 ### Step 2: 创建 Rust 项目结构 (首次执行) ```bash cd /home/fmq/program/tlusty/tl208-s54/rust # 创建 Cargo.toml cat > Cargo.toml << 'EOF' [package] name = "tlusty-rust" version = "0.1.0" edition = "2021" [dependencies] ndarray = "0.15" num-traits = "0.2" anyhow = "1.0" [dev-dependencies] approx = "0.5" EOF # 创建目录 mkdir -p src/math src/physics tests/fixtures ``` ### Step 3: 编写 Rust 实现 ```rust // src/math/expo.rs /// 安全的指数函数,限制输入范围防止溢出 pub fn expo(x: f64) -> f64 { const CRIT: f64 = 80.0; x.clamp(-CRIT, CRIT).exp() } #[cfg(test)] mod tests { use super::*; use approx::assert_relative_eq; #[test] fn test_expo() { assert_relative_eq!(expo(0.0), 1.0); assert_relative_eq!(expo(1.0), std::f64::consts::E); // 大数被限制 assert_relative_eq!(expo(100.0), 80.0_f64.exp()); } } ``` ### Step 4: 更新 lib.rs ```rust // src/lib.rs pub mod math; // 已完成的重构 pub mod expo; ``` ### Step 5: 运行测试 ```bash cargo test expo ``` ### Step 6: 记录进度 ```bash echo "expo - 10行 - ✓ 完成" >> REFACTORING_PROGRESS.txt ``` --- ## 5. Fortran 语法转换参考 ### 变量类型 | Fortran | Rust | |---------|------| | `IMPLICIT REAL*8(A-H,O-Z)` | `f64` | | `INTEGER` | `i32` | | `LOGICAL` | `bool` | | `CHARACTER*N` | `[u8; N]` 或 `String` | ### 数组 | Fortran (1-indexed) | Rust (0-indexed) | |---------------------|------------------| | `DIMENSION A(3)` | `a: [f64; 3]` | | `DIMENSION A(N)` | `a: &[f64]` 或 `Vec` | | `A(1)` | `a[0]` | ### 控制结构 ```fortran IF (X .LT. 0) THEN Y = -X ELSE Y = X END IF ``` ```rust let y = if x < 0.0 { -x } else { x }; ``` --- ## 6. 测试规范 ### 单元测试 每个重构的函数必须有: 1. 正常值测试 2. 边界值测试 3. 特殊情况测试 ### 回归测试 对于复杂函数,用 Fortran 生成参考数据: ```bash # 创建 Fortran 测试程序 cat > test_expint.f << 'EOF' program test_expint IMPLICIT REAL*8(A-H,O-Z) do 10 x = 0.1, 10.0, 0.5 y = expint(x) write(*,*) x, y 10 continue end FUNCTION EXPINT(X) IMPLICIT REAL*8(A-H,O-Z) ... (复制原函数) END EOF gfortran -o test_expint test_expint.f ./test_expint > tests/fixtures/expint_expected.txt ``` --- ## 7. 进度跟踪 创建文件 `REFACTORING_PROGRESS.txt`: ``` # 重构进度 # 格式: 函数名 - 行数 - 状态 - 完成日期 ## 已完成 expo - 10 - ✓ - 2026-03-XX ## 进行中 (无) ## 待处理 yint - 18 - ⬜ tridag - 22 - ⬜ ... ``` --- ## 8. 下一步行动 **新会话启动后**: 1. 读取本文档: `cat REFACTORING_PLAN.md` 2. 查看进度: `cat REFACTORING_PROGRESS.txt` 3. 选择下一个文件(从未完成的最小文件开始) 4. 按照流程执行重构 **第一个文件**: `expo.f` (10行,最简单)