241 lines
6.6 KiB
Markdown
241 lines
6.6 KiB
Markdown
---
|
||
name: tlusty-iteration
|
||
description: "TLUSTY Rust主程序迭代开发与Fortran对比测试。触发条件:(1) 用户提到'迭代测试'、'对比测试'、'主程序开发';(2) 用户想验证Rust实现与Fortran的一致性;(3) 继续TLUSTY主程序开发;(4) 运行TLUSTY测试用例。提供完整迭代流程、测试方法、差异分析。"
|
||
---
|
||
|
||
# TLUSTY Rust 主程序迭代与对比测试
|
||
|
||
本技能指导 Rust TLUSTY 主程序的迭代开发,目标是使输出与 Fortran 参考实现一致。
|
||
|
||
---
|
||
|
||
## 当前状态 (2026-03-26)
|
||
|
||
### 已完成的工作
|
||
|
||
1. **OPCTAB 表读取实现** (`opacity_table.rs`):
|
||
- 支持文本格式 OPCTAB 文件读取
|
||
- 2D 插值 (温度-密度)
|
||
- Rosseland 和 Planck 平均不透明度计算
|
||
- 环境变量 `OPCTAB` 指定表路径
|
||
|
||
2. **测试验证**:
|
||
- 成功加载 `optab11_7f.dat` (100000 频率点)
|
||
- 表范围: T = 3000-15000 K, ρ = 1e-12 - 1e-6 g/cm³
|
||
|
||
### 核心问题:OPCTAB 温度范围限制
|
||
|
||
**问题**: 可用的 OPCTAB 表 (`optab11_7f.dat`) 仅覆盖 3000-15000 K,但测试用例 Teff = 35000 K 超出此范围。
|
||
|
||
**Fortran 的处理方式**:
|
||
- 当 `ioptab = 0` (默认) 时,使用 `OPACF0` 从原子物理计算不透明度
|
||
- OPACF0 计算: 束缚-自由、自由-自由、H⁻、H₂⁺ 等贡献
|
||
- 这需要完整的原子数据 (能级、跃迁、截面)
|
||
|
||
**Rust 当前处理**:
|
||
- 当 T 超出表范围时,回退到 Kramers 近似
|
||
- κ_bf ≈ 4.3e-25 * (1e4/T)^3.5
|
||
- κ_es = σ_e * ne / ρ
|
||
|
||
### 解决方案 (按优先级)
|
||
|
||
1. **寻找更高温度的 OPCTAB 表** (最简单)
|
||
- 需要覆盖 10000-50000 K 的表
|
||
- 可从 OPAL 或 OPLIB 获取
|
||
|
||
2. **实现 OPACF0** (最准确)
|
||
- 从原子数据计算束缚-自由不透明度
|
||
- 计算自由-自由 (Kramers)
|
||
- 添加 H⁻、H₂⁺ 贡献
|
||
- 需要大量原子物理模块
|
||
|
||
3. **改进 Kramers 近似** (折中)
|
||
- 添加温度/密度相关修正
|
||
- 参考 OPAL/OPLIB 公式
|
||
|
||
### 测试对比 (Teff=35000K, 超出 OPCTAB 范围)
|
||
|
||
| 参数 | Rust (Kramers) | Fortran (OPACF0) | 问题 |
|
||
|------|----------------|------------------|------|
|
||
| 表面柱质量 | 7.4e-6 | 2.9e-7 g/cm² | **25x 偏高** |
|
||
| 输出列数 | 40 | 42 | 缺少 2 列 |
|
||
|
||
**根本原因**: Kramers 不透明度太低 → 需要更多质量才能达到相同光深
|
||
|
||
|
||
---
|
||
|
||
## 项目文件结构
|
||
|
||
```
|
||
SpectraRust/
|
||
├── src/
|
||
│ ├── bin/tlusty.rs # Rust 主程序入口
|
||
│ └── tlusty/
|
||
│ ├── io/ # I/O 模块 (ltegr, start, model...)
|
||
│ ├── math/ # 数学模块 (eos, continuum, ali...)
|
||
│ └── state/ # 状态结构 (constants, atomic, model...)
|
||
├── tests/
|
||
│ ├── tlusty/
|
||
│ │ ├── hhe_fortran/ # Fortran 输入文件和参考输出
|
||
│ │ └── hhe_rust/ # Rust 输入文件和输出
|
||
├── tlusty/
|
||
│ └── extracted/ # 提取的 Fortran 源码 (304 个模块)
|
||
│ ├── tlusty.f # 主程序
|
||
│ ├── start.f # 初始化
|
||
│ ├── ltegr.f # LTE 灰大气
|
||
│ └── ...
|
||
└── .claude/skills/
|
||
└── fortran-analyzer/scripts/
|
||
└── analyze_fortran.py # 模块分析脚本
|
||
```
|
||
|
||
|
||
---
|
||
|
||
## 迭代工作流程
|
||
|
||
### Step 1: 运行对比测试
|
||
|
||
#### 生成 Fortran 参考输出
|
||
如果需要重新生成 Fortran 参考输出:
|
||
|
||
```bash
|
||
# 1. 进入测试目录
|
||
cd tests/tlusty/hhe_fortran
|
||
# 2. 确保有 data 链接
|
||
ln -sf $TLUSTY/data data
|
||
|
||
# 3. 运行 Fortran
|
||
$TLUSTY/tlusty/tlusty.exe < hhe35lt.5 > fortran.6
|
||
|
||
# 4. 复制输出
|
||
cp fort.7 fort.7.ref
|
||
```
|
||
|
||
#### 运行 Rust
|
||
```bash
|
||
cargo build
|
||
|
||
cd tests/tlusty/hhe_rust
|
||
ln -sf $TLUSTY/data data
|
||
../../../target/debug/tlusty < hhe35lt.5 > rust.6 2>&1
|
||
|
||
# 对比第一深度点
|
||
echo "=== Rust ===" && head -3 hhe_rust/fort.7
|
||
echo "=== Fortran ===" && head -3 hhe_fortran/fort.7
|
||
```
|
||
|
||
### Step 2: 定位差异来源
|
||
|
||
```bash
|
||
# 提取温度列对比
|
||
paste <(awk '{print NR, $3}' hhe_rust/fort.7) <(awk '{print $3}' hhe_fortran/fort.7) | \
|
||
awk '{diff=$2-$3; if(diff<0)diff=-diff; if(diff>100) print $1, $2, $3, diff}'
|
||
|
||
# 提取电子密度对比
|
||
paste <(awk '{print NR, $6}' hhe_rust/fort.7) <(awk '{print $6}' hhe_fortran/fort.7) | \
|
||
awk '{diff=$2-$3; if(diff<0)diff=-diff; if($2>0 && diff/$2>0.05) print $1, $2, $3}'
|
||
```
|
||
|
||
### Step 3: 分析 Fortran 源码
|
||
|
||
```bash
|
||
# 查看目标模块
|
||
cat tlusty/extracted/eldens.f | head -100
|
||
|
||
# 查看 COMMON 块依赖
|
||
grep -E "INCLUDE|COMMON" tlusty/extracted/eldens.f
|
||
|
||
# 查看调用关系
|
||
grep -E "CALL|FUNCTION" tlusty/extracted/eldens.f
|
||
```
|
||
|
||
### Step 4: 修复 Rust 代码
|
||
|
||
1. 找到对应的 Rust 模块 (`src/tlusty/math/eos/eldens.rs`)
|
||
2. 对比 Fortran 逻辑
|
||
3. 修复差异
|
||
4. 编译测试
|
||
|
||
```bash
|
||
# 编译
|
||
cargo build 2>&1 | grep -E "error|warning" | head -20
|
||
|
||
# 单元测试
|
||
cargo test eldens 2>&1 | tail -20
|
||
```
|
||
|
||
### Step 5: 重新对比
|
||
|
||
重复 Step 1,验证差异是否缩小
|
||
|
||
---
|
||
|
||
## 模块分析与对应 (使用 analyze_fortran.py)
|
||
|
||
### 查看模块对应表
|
||
|
||
```bash
|
||
# 查看所有模块的 Rust 实现状态
|
||
python3 .claude/skills/fortran-analyzer/scripts/analyze_fortran.py 2>&1 | \
|
||
grep -E ",done$" | head -30
|
||
|
||
# 查看特定模块的 Rust 对应
|
||
python3 .claude/skills/fortran-analyzer/scripts/analyze_fortran.py 2>&1 | \
|
||
grep -i "ELDENS\|ROSSOP\|STEQQEQ"
|
||
|
||
# 输出格式: fortran_file,unit_name,unit_type,is_pure,common_deps,call_deps,has_io,rust_module,status
|
||
```
|
||
|
||
### 查看依赖树
|
||
|
||
```bash
|
||
# 查看主程序依赖树
|
||
python3 .claude/skills/fortran-analyzer/scripts/analyze_fortran.py --tree TLUSTY
|
||
|
||
# 查看特定模块依赖树
|
||
python3 .claude/skills/fortran-analyzer/scripts/analyze_fortran.py --tree LTEGR
|
||
python3 .claude/skills/fortran-analyzer/scripts/analyze_fortran.py --tree ELDENS
|
||
python3 .claude/skills/fortran-analyzer/scripts/analyze_fortran.py --tree RESOLV
|
||
```
|
||
|
||
### 查看重构优先级
|
||
|
||
```bash
|
||
# 查看未实现模块的优先级列表
|
||
python3 .claude/skills/fortran-analyzer/scripts/analyze_fortran.py --priority | head -30
|
||
```
|
||
|
||
### 当前关键模块状态
|
||
|
||
**LTE 模型核心**:
|
||
```bash
|
||
python3 .claude/skills/fortran-analyzer/scripts/analyze_fortran.py 2>&1 | \
|
||
grep -E "LTEGR|ROSSOP|ELDENS|STEQQEQ|WNSTOR|SABOLF|MEANOPT"
|
||
```
|
||
|
||
**辐射转移模块**:
|
||
```bash
|
||
python3 .claude/skills/fortran-analyzer/scripts/analyze_fortran.py 2>&1 | \
|
||
grep -E "RESOLV|SOLVE|ALIFR|RHSGEN|EMAT"
|
||
```
|
||
|
||
**不透明度模块**:
|
||
```bash
|
||
python3 .claude/skills/fortran-analyzer/scripts/analyze_fortran.py 2>&1 | \
|
||
grep -E "OPACF|OPADD|OPCTAB|OPACT"
|
||
```
|
||
|
||
|
||
## 相关 Skills
|
||
|
||
| Skill | 用途 |
|
||
|-------|------|
|
||
| `fortran-analyzer` | 分析模块依赖关系 |
|
||
| `fortran-to-rust` | 模块重构指南 |
|
||
|
||
---
|
||
|
||
|