SpectraRust/.claude/skills/codegraph-guide/references/phase3-verify.md
fmq e2c1a4580a feat: F2R 重构全部完成 + 自动化脚本改进
Phase 1 翻译 (完成):
- TLUSTY 350 函数 100% 翻译
- SYNSPEC 168 函数 100% 翻译
- ~495 Rust 模块

Phase 2 集成 (完成):
- TLUSTY RESOLV 7 个 TODO 全部清除
- TLUSTY Runner IJALI 频率选择实现
- OPFRAC ioniz.dat 解析完整实现
- SYNSPEC Runner 编排流程连接完成
- SYNSPEC RESOLV OPAC→RTE→OUTPRI 调用链完整

Phase 3 验证 (完成, 修复 8 处 bug):
- INITIA: compute_hydrogen_level_bounds 索引混合修复
- INILIN: GAMR0/GS0/GW0 展宽公式修复, 经典 VdW 公式修复
- INIBL0: CNM 常数 2.997925e18→e17 修复
- OPAC: Lyman IJ=2 修正缺失修复
- RTE: minv3 矩阵求逆符号错误修复

自动化脚本改进:
- specf2r.sh: 添加 429 限流退避、完成检测、同步等待
- SKILL.md: 三阶段工作流 + 状态文件系统
- references/: Phase 1/2/3 独立参考文档

新增:
- src/bin/synspec.rs: SYNSPEC 可执行文件入口
- .f2r_phase/.f2r_tasks/.f2r_complete: 状态管理文件

编译: 0 错误 | Clippy: 0 错误 | 测试: voigt 28 + eldens 5 通过

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 14:54:53 +08:00

211 lines
6.9 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.

# Phase 3: 验证工作流参考
> 状态待启动Phase 2 集成完成后进入)
> 模式:参照 `tlusty-iteration` skill 的逐模块严格验证流程
## 文件路径
| 内容 | 路径 |
|------|------|
| Fortran 源码 | `tlusty/extracted/*.f`、`synspec/extracted/*.f` |
| Rust 源码 | `src/tlusty/`、`src/synspec/` |
| 验证进度 | `.claude/skills/codegraph-guide/references/verify-progress.md` |
| TLUSTY Fortran 测试 | `$TLUSTY/tests/tlusty/hhe/` |
| SYNSPEC Fortran 测试 | `$TLUSTY/tests/synspec/hhe/` |
| TLUSTY Rust 测试 | `tests/tlusty/hhe_rust/` |
| SYNSPEC Rust 测试 | `tests/synspec/hhe/` |
## 测试方式
### TLUSTY 端到端
```bash
# Fortran 参考
cd $TLUSTY/tests/tlusty/hhe
$TLUSTY/tlusty/tlusty.exe < hhe35lt.5 > hhe35lt.6
cp fort.7 hhe35lt.7.ref
# Rust
cargo build --bin tlusty
cd tests/tlusty/hhe_rust
rm -f fort.7
../../../target/debug/tlusty < hhe35lt.5 > rust.6 2>stderr.txt
# 对比
diff hhe35lt.7.ref fort.7
```
### SYNSPEC 端到端
```bash
# 准备(测试目录 tests/synspec/hhe/ 已有 fort.8、fort.55.con 等文件)
cd tests/synspec/hhe
cp hhe35nl.7 fort.8
ln -sf fort.55.con fort.55
# Fortran 参考(生成 results_original/ 中的 .spec/.cont/.iden
# 需要先编译gfortran -O3 -fno-automatic -mcmodel=large -o synspec.exe synspec54.f
./synspec.exe < hhe35nl.5
# Rust
cargo build --bin synspec
cd tests/synspec/hhe
rm -f fort.7
../../../target/debug/synspec < hhe35nl.5 > rust.6 2>stderr.txt
# 对比(与 Fortran 参考结果比对)
diff results_original/hhe35nl.spec fort.7
```
## 验证工作流(严格遵守)
```
每次会话:
1. 读取 verify-progress.md → 恢复验证进度
2. 运行 Rust → 与 Fortran 参考输出对比
3. 输出完全一致 → 更新 verify-progress.md → 结束
4. 输出不一致 → 从断点继续逐模块验证:
a. 读取 verify-progress.md 中 "下一个待验证模块"
b. ★ 必须先读取对应的 Fortran 文件,逐行理解原始逻辑
c. 然后读取对应的 Rust 文件
d. 逐行对比: 调用顺序、变量映射、索引转换、逻辑分支
e. 发现差异 → 立即修复 → cargo build 验证
f. 更新 verify-progress.md → 继续下一个模块
5. 全部通过 → 运行测试套件 → 更新 verify-progress.md
```
## ★ 核心原则:必须参考 Fortran 代码
```
严禁凭猜测修改代码!每次修改前必须:
1. 先读取对应的 Fortran 源码文件
2. 理解 Fortran 的确切逻辑流程
3. 找到 Fortran 中的对应行
4. 然后对照修改 Rust 代码
违反此原则是产生 bug 的最主要原因。
```
## 验证顺序
### TLUSTY 调用链
```
TLUSTY (tlusty.f)
→ START (start.f)
→ INITIA (initia.f) ★ 最大模块
→ HEDIF (hedif.f) [可选]
→ COMSET (comset.f)
→ PRDINI (prdini.f)
→ RESOLV (resolv.f)
→ INILAM, LINSEL, OPAINI ...
→ OPACF0, OPACF1, RTEFR1 ...
→ LUCY (lucy.f)
→ OUTPUT
→ ACCEL2 (accel2.f)
→ SOLVE / SOLVES / RYBSOL
→ MATGEN → BRTE, BHE, BRE
→ MATINV
```
### SYNSPEC 调用链
```
SYNSPEC (synspec54.f)
→ START
→ INITIA → STATE0, RDATA
→ INPMOD / INKUR
→ TINT, INIMOD
→ INILIN → read_line_list
→ INIBL0 / INIBL1
→ RESOLV
→ INILAM, HYLSET, HE2SET
→ INIBLA, INIBLM
→ OPAC → HYDLIN, LINOP, ...
→ RTE / RTECD
→ OUTPRI
```
## 模块文件映射
### TLUSTY
| Fortran 模块 | Fortran 文件 | Rust 文件 | 子目录 |
|-------------|-------------|-----------|--------|
| TLUSTY | tlusty.f | `src/tlusty/main.rs` | (主程序) |
| START | start.f | `src/tlusty/io/start.rs` | io/ |
| INITIA | initia.f | `src/tlusty/io/initia.rs` | io/ |
| RESOLV | resolv.f | `src/tlusty/io/resolv.rs` | io/ |
| ACCEL2 | accel2.f | `src/tlusty/math/ali/accel2.rs` | math/ali/ |
| SOLVE | solve.f | `src/tlusty/math/solvers/solve.rs` | math/solvers/ |
特殊映射(多合一 Rust 文件):
- `bhe.rs` ← BHE, BHED, BHEZ
- `gfree.rs` ← GFREE0, GFREED, GFREE1
- `interpolate.rs` ← YINT, LAGRAN
- `sgmer.rs` ← SGMER0, SGMER1, SGMERD
- `ctdata.rs` ← HCTION, HCTRECOM
- `cross.rs` ← CROSS, CROSSD
- `expint.rs` ← EINT, EXPINX
- `erfcx.rs` ← ERFCX, ERFCIN
math 子目录: ali, atomic, continuum, convection, eos, hydrogen, interpolation, odf, opacity, partition, population, radiative, rates, solvers, special, temperature, utils
### SYNSPEC
| Fortran 模块 | Fortran 文件 | Rust 文件 | 子目录 |
|-------------|-------------|-----------|--------|
| SYNSPEC | synspec54.f | `src/bin/synspec.rs``src/synspec/runner.rs` | bin/ |
| INITIA | initia.f | `src/synspec/math/initia_synspec.rs` | math/ |
| INILIN | inilin.f | `src/synspec/math/inilin.rs` | math/ |
| RESOLV | resolv.f | `src/synspec/math/resolv.rs` | math/ |
| OPAC | opac.f | `src/synspec/math/opac.rs` | math/ |
| RTE | rte.f | `src/synspec/math/rte.rs` | math/ |
| OUTPRI | outpri.f | `src/synspec/math/outpri.rs` | math/ |
## 检查清单(每个模块必须逐项验证)
```
[ ] 调用顺序: Fortran CALL 顺序 == Rust 函数顺序
[ ] 变量映射: Fortran COMMON 变量 → 正确的 Rust struct 字段
[ ] 数组下标: 1-based→0-based, Fortran 列主序→Rust 行主序
[ ] 循环边界: DO I=1,N → 0..n, DO I=N,1,-1 → (0..n).rev()
[ ] IF 条件: .AND.→&&, .OR.→||, .EQ.→==, .NE.→!=, 全覆盖
[ ] 赋值完整性: 每个 Fortran 赋值都有对应 Rust 赋值(无遗漏)
[ ] I/O 语句: WRITE/READ/PRINT 对应 Rust 的文件 I/O
[ ] 函数调用: 每个子程序调用参数正确传递
[ ] 回调模式: 回调/closure 必须调用实际函数(不能是空壳 NoOp
[ ] 数学公式: 常数和计算公式与特殊函数完全一致
[ ] 编译验证: cargo build 无错误
[ ] DATA 语句: 已预提取到 src/data.rs
```
## 判断标准
模块检查结果只有三种状态:
```
通过 — 逐行对比一致,调用完整,无空壳,逻辑相同。通过时立即检查下一个模块
未通过 — 发现具体差异,修复后 cargo build 通过,但输出仍不一致
跳过 — 不需要检查(如纯工具函数,已有充分单元测试覆盖)
```
## 修复原则
```
1. 严格对照 Fortran: 按 Fortran 代码行号逐行对比 Rust 实现
2. 保持调用顺序: Fortran 中的 CALL 顺序必须严格保持
3. 正确映射 COMMON: 使用 Fortran INCLUDE 文件确认变量含义
4. 控制流程等价: IF/DO/SELECT CASE 逻辑必须一致
5. 数组下标转换: Fortran 列主序 1-based → Rust 行主序 0-based
6. 不能用 NoOp 回调: 如果 Fortran 有 CALLRust 必须调用实际函数
7. 复杂模块分解: 分步骤修复,每步验证编译
```
## 完成标准
1. TLUSTY 端到端: `fort.7` 与 Fortran 参考二进制一致
2. SYNSPEC 端到端: `fort.7` 与 Fortran 参考二进制一致
3. `cargo clippy` 零错误
4. 相关模块的单元测试通过(禁止全量测试,内存会被占满)
5. 全部通过后创建 `.f2r_complete` 文件