SpectraRust/REFACTORING_PLAN.md
2026-03-19 14:05:33 +08:00

277 lines
5.3 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.

# 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<f64>` |
| `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行最简单)