TLUSTY/cno_grid/EXPERIENCE copy.md
2026-07-21 22:25:14 +08:00

346 lines
17 KiB
Markdown
Raw Permalink 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.

# CNO 热亚矮星光谱:调试经验与批量网格操作手册
> 本文档记录在 `tl208-s54/cno_grid/` 上构建含 C/N/O 金属线的热亚矮星理论光谱
> 过程中积累的全部经验,重点是**收敛调试中踩过的坑**和**已验证可行的配方**。
> 基础背景知识见 `tests/cno_sdspectrum/GUIDE.md`(必读)。
---
## 1. 核心结论(先读这一节)
1. **金属线必须进大气模型。** 实测证实:纯 H+He 大气下跑 synspecC/N/O 谱线
全部产生 NaN——因为大气里没有金属能级synspec 无法计算谱线不透明度。
所以 C/N/O 必须作为显式 NLTE 原子mode=2写进 `.5` 的大气和 ions 段。
这正是 `tests/cno_sdspectrum/GUIDE.md` 的方案 B自洽
2. **收敛必须走三步法,`nc` 步骤不可省略:**
```
LTE 灰大气 (T T, NITER=0) → 初始温度结构
NLTE 连续谱 (F F, ilvlin=0, "nc") → 收敛电离平衡+布居数(不含谱线扰动)
NLTE 含线 (F F, ilvlin=100, "nl")→ 加谱线,从 nc 种子快速收敛
SYNSPEC → 合成可观测光谱
```
`nc` 是关键:它在没有谱线扰动的情况下先收敛 NLTE 电离平衡,给 `nl` 一个
稳定种子。**跳过 ncgrey-LTE → 直接含线 NLTE必定发散**(见第 3 节)。
3. **端到端已验证跑通**35000K / logg 5.5 / logHe=-2 / CNO=-1
lte✓ → nc✓ → **nl 收敛 (max_relc=0.0043)** → synspec✓产出 111500 个有效
通量点CNO 吸收线清晰可见30003500Å 吸收深度 68%)。单模型约 14 分钟。
---
## 2. 已验证的精确配方
### 2.1 `.5` 文件三阶段配置
三个阶段用**相同**的 NATOMS8和 ions 能级数,**只改三处**:第 2 行 LTE/LTGRAY
标志、第 3 行 nst 文件名、ions 段第 5 列 `ilvlin`
| 阶段 | 第2行 | nst | ilvlin | 说明 |
|------|-------|-----|--------|------|
| lte | `T T` | nst (NITER=0) | 0/100 均可(LTE忽略线) | 灰大气,不迭代 |
| nc | `F F` | nst_nc (NITER=50) | **0** | NLTE 连续谱,**无线跃迁** |
| nl | `F F` | nst_nl (NITER=100) | **100** | NLTE 全谱线 |
> `ilvlin=0` 让该离子的束缚-束缚跃迁不参与计算(只保留连续谱),这正是 nc 步骤
> 稳定收敛的原因。`ilvlin=100` 恢复全部线跃迁。
### 2.2 CNO 模型原子(能级数,照搬 BSTAR2006
| 元素 | 离子 / 能级 / 数据文件 |
|------|------------------------|
| C (Z=6) | C I 40 `c1.dat` / C II 22 `c2.dat` / C III 46 `c3_34+12lev.dat` / C IV 25 `c4.dat` / C V 1 |
| N (Z=7) | N I 34 `n1.dat` / N II 42 `n2_32+10lev.dat` / N III 32 `n3.dat` / N IV 48 `n4_34+14lev.dat` / N V 16 `n5.dat` / N VI 1 |
| O (Z=8) | O I 33 `o1_23+10lev.dat` / O II 48 `o2_36+12lev.dat` / O III 41 `o3_28+13lev.dat` / O IV 39 `o4.dat` / O V 6 `o5.dat` / O VI 1 |
| He | He I **24** `he1.dat` / He II **20** `he2.dat`Peter Nemeth 邮件建议,勿用 14-level |
| H | H I 9 `h1.dat` |
合计约 530 个能级,全部文件在 `$TLUSTY/data/` 下已确认存在。
### 2.3 nst 非标准参数(已验证)
```
ND=50,NLAMBD=3,VTB=2.,ISPODF=1,DDNU=50.,CNU1=6.,CHMAX=<阶段>,ITEK=3,NITER=<阶段>
IELCOR=-1
```
- lte 阶段NITER=0灰大气不迭代
- nc 阶段NITER=50, CHMAX=0.1(不必完全收敛,作种子即可)
- nl 阶段NITER=100, CHMAX=0.01(要求收敛)
- `NLAMBD=3, ISPODF=1, DDNU=50., CNU1=6.` 是频率网格细化参数,**不能省**
- `IELCOR=-1` 关闭电子密度修正(这些 sdB 模型需要)
### 2.4 丰度约定
`.5` 的 atoms 段 `abn` 列:
- `0` = 太阳丰度Tlusty 内置 Grevesse & Sauval 1998
- `>0` = 绝对比值 N(elem)/N(H),即 `10^logX`logX = 1 → abn=0.1
- `<0` = 太阳丰度的倍数0.1 = 0.1×太阳5 = 5×太阳
本次网格统一用 `abn = 10^logX`logX 为 4..2 / 2..1)。
### 2.5 synspec 波长窗口
`fort.55.lin` 第 6 行 `WLMIN WLMAX WLSTEP ...`。验证用的是 30007000Å光学
覆盖 C II 4267、C III 4647 等)。要 UV 段(含更多 CNO 线)用 `fort.55.uvopt`
9008000Å`tests/cno_sdspectrum/`)。谱线表用 `data/gfVIS99.dat`(含
C 1412 / N 2396 / O 1885 条线)或 `data/gfATO.dat`(更全)。
---
## 3. 调试踩坑记录(避免重蹈覆辙)
### 坑 1跳过 nc 步骤 → NLTE 发散 ❌→✅
**现象**:从 grey-LTE 种子直接跑含线 NLTEilvlin=100max_relc 在 iter 4 起
爆炸到 1e20 并产生 NaN。
**根因**grey-LTE 的 LTE 布居数与 NLTE 解差距巨大,加上数千条谱线的扰动同时
涌入,线性化必然爆。
**解决**:插入 nc 步骤ilvlin=0先无谱线地收敛 NLTE 电离平衡。
**这是最重要的经验。**
### 坑 2ITEK=100 反而更差 ❌
**现象**nc/nl 不收敛时把 ITEK 升到 100Peter 邮件提过 3/15/100
**结果**ITEK=100 导致 overshootmax_relc 飙到 1e29比 ITEK=3 更糟。
**解决**ITEK 回退链上限设为 15不要用 100。
### 坑 3纯 H+He 种子喂含 CNO 模型 → 全 NaN ❌
**现象**:把纯 H+He 的 `.7`38 能级)作 fort.8 种子跑含 CNO 模型530 能级),
fort.7 全 NaN。
**根因**种子与目标的能级结构不匹配tlusty 无法映射布居数。
**解决**:三步法的三个阶段用**相同** NATOMS 和 ions 配置(只改 ilvlin/LTE 标志),
保证种子结构兼容。lte 的 `.7` 已经包含全部 CNO 能级位置LTE 填充),所以能
正确喂给 nc。
### 坑 4NITER=0 的 LTE 阶段不产生 fort.9 ❌→✅
**现象**lte 阶段 NITER=0灰大气不迭代不输出 fort.9 收敛日志,自动化脚本
判定"失败"并跳过种子复制。
**解决**:脚本里对 fort.7大气单独判存在NITER=0 时无 fort.9 是正常的,
直接把 fort.7 当种子传给下一阶段。
### 坑 5grey-LTE 单独跑 synspec → 全 NaN ❌
**现象**grey-LTE 大气(未做 nc/nl直接跑 synspec谱线全 NaN。
**根因**grey 温度结构错误(标准深度 T=127834K所有线被拒。
**结论**synspec 必须用经过 nc→nl 收敛的 NLTE 大气,不能用 grey 或纯 LTE 大气。
### 坑 6分析脚本读错列 → 误判"整数发散"❌
**现象**:监控脚本显示 max_relc = 1.0, 2.0, 3.0... 精确整数线性增长,一度怀疑
二进制有未初始化变量 bug。
**真相**:正则捕获了迭代号(第 1 列)而非 max_relc第 7 列)。
**教训**fort.9 列顺序是 `ITER ID TEMP NE POP RAD MAXIMUM ilev ifr`
max_relc 在**第 7 列**。`check_conv.py` 一直是对的,是临时监控脚本错了。
**始终用 `check_conv.py` 判收敛,不要手写解析。**
### 坑 7logg 跨度太大的种子 → 发散 ❌
**现象**:用 logg=4.0 的种子跑 logg=5.5 的模型(重力差 100 倍),发散。
**解决**:网格扩展时用"种子步进"——相邻参数点之间步长要小logg 每步 ≤0.5
Teff 每步 ≤5000K用最近邻已收敛模型作种子。`run_grid.py` 已实现此逻辑。
---
## 4. 自动化系统使用说明(`cno_grid/`
### 4.1 目录结构
```
cno_grid/
├── config.yaml # 6维网格 + 收敛链配置
├── templates/
│ ├── cno_atmos.5.tpl # (备用)模板
│ ├── nst # 备用nst
│ └── fort.55.lin # synspec 波长窗口
├── src/
│ ├── gen_input5.py # 6维参数 → .5(支持 ilvlin / metals 子集)
│ ├── check_conv.py # fort.9 收敛判定
│ ├── run_one.py # 单模型三步链 + synspec核心
│ ├── run_grid.py # 6维网格调度断点续算/并行/种子复用)
│ └── plot_spec.py # 归一化光谱 + CNO 诊断线标注
└── results/<model_name>/ # 每个模型的 .5/.7/.9/.spec/.cont/conv.json
```
### 4.2 跑单个模型
```bash
export TLUSTY=/home/dckj/program/tlusty/tl208-s54
python3 cno_grid/src/run_one.py \
--teff 35000 --logg 5.5 --loghe -2 --logc -1 --logn -1 --logo -1
# 结果在 cno_grid/results/t35000_g5.5_he-2_c-1_n-1_o-1/
# conv.json - 收敛状态converged: true/false + 各阶段 max_relc
# *.spec/.cont - synspec 光谱/连续谱
# *.lte.7/nc.7/nl.7 - 各阶段大气快照
```
### 4.3 批量网格
```bash
# 编辑 config.yaml 的 grid 轴(各维点列表),然后:
python3 cno_grid/src/run_grid.py cno_grid/config.yaml --dry-run # 先看总数
python3 cno_grid/src/run_grid.py cno_grid/config.yaml # 正式跑
python3 cno_grid/src/run_grid.py cno_grid/config.yaml --only teff=35000,logg=5.5 # 子集
python3 cno_grid/src/run_grid.py cno_grid/config.yaml --limit 3 # 只跑3个(测试)
# 特性:
# - resume: 跳过 conv.json 里 converged=true 的模型(断点续算)
# - 种子复用: 新模型自动找最近邻已收敛 .7 作种子
# - nworkers: config.yaml 里设并行进程数
# - 失败隔离: 单点失败不中断网格,记入 grid_status.json
```
### 4.4 检查收敛 / 画图
```bash
python3 cno_grid/src/check_conv.py results/<model>/<model>.nl.9 --chmax 0.01
python3 cno_grid/src/plot_spec.py results/<model> # 出 spectrum.png + CNO 线标注
```
### 4.5 收敛链调参config.yaml 的 chain 段)
默认链已验证可行。若某些参数点He-rich / 高金属)不收敛,可调:
- 放宽 nl 的 CHMAX0.01 → 0.05
- 增加 nc 的 NITER50 → 200GUIDE 提到 200 可完全收敛)
- 在 nc/nl 加 ORELAX 阻尼(`orelax: 0.5`
- He-rich 点可能物理上无法收敛到 0.01Peter 邮件预警),如实记录即可
---
## 5. 已知的 NaN 问题(非阻塞)
synspec 输出的 `.spec` 在部分波长区有 NaN典型 ~70% 点有效)。这是 synspec54
在致密谱线区的数值行为("lines rejected based on opacities")。**有效区间的
光谱是可信的**——35000K 模型在 30003500Å 有 73627 个有效点,吸收深度 68%
CNO 线清晰。降低波长采样密度或换 `gfATO.bin` 谱线表可能减少 NaN但不影响
已验证的物理结论。
---
## 5.5 网格边界测试结果8/8 全部成功)
在网格边界挑 8 个代表性难点(覆盖 Teff/logg/logHe 和 CNO 丰度两个轴),用三步法
lte→nc→nl+ 稳定化(方案 B对所有 NLTE 阶段无条件启用)实测,**全部成功**
### Teff / logg / logHe 边界CNO=0 太阳丰度)
| # | 参数 (Teff/logg/logHe/CNO) | nl 收敛 | max_relc | 有效点 | 结论 |
|---|---------------------------|---------|----------|--------|------|
| 1 | 20000/5.0/+2/0低温He-rich最难 | YES | 0.00654 | 115362 | ✓ |
| 2 | 80000/6.5/+2/0高温He-rich | YES | 0.00915 | 105183 | ✓ 修复后 |
| 3 | 80000/6.5/4/0高温He-poor | YES | 0.00769 | 106469 | ✓ 修复后 |
| 4 | 40000/6.0/0/+1高金属CNO=10×H | YES | 0.0069 | 108693 | ✓ |
| 5 | 20000/6.5/4/0低温贫He | YES | 0.00927 | 115479 | ✓ |
### CNO 丰度边界(含非对称丰度)
| # | 参数 (Teff/logg/logHe/C/N/O) | nl 收敛 | max_relc | 有效点 | 结论 |
|---|------------------------------|---------|----------|--------|------|
| 6 | 40000/5.5/0/2/2/2极贫金属0.01×H | YES | 0.00764 | 108693 | ✓ 修复后 |
| 7 | 40000/5.5/0/+1/2/2C富N/O贫sdB典型 | YES | 0.00376 | 108576 | ✓ |
| 8 | 80000/6.5/4/2/2/2高温+极贫金属) | YES | 0.00394 | 105300 | ✓ |
### 关键发现
1. **8/8 全部收敛全部产出有效光谱10万+ 有效点)**——整个网格边界Teff
20000-80000、logg 5.0-6.5、logHe 4..2、CNO 2..1,含非对称丰度)均可计算。
2. **发散不只与高温有关**:测试 #640000K/logg5.5/logHe=0初次也发散了
证明发散触发条件是 Teff/logg/logHe 的组合,不只高温。因此方案 BIDLTE=45
等)改为**对所有 NLTE 阶段无条件启用**——物理上深层 LTE 对所有 sdB 都成立。
3. **非对称丰度可行**:测试 #7C=10×H, N=O=0.01×H这种 sdB 典型的 C-rich
组合收敛良好relc=0.00376),说明 C/N/O 可独立取不同丰度值。
4. **耗时**80000K 点因方案 B 的 nc 快速收敛,仅 58s40000K 含线 nl 较慢
~20-30 min。24 核并行约每小时 72 个模型。
---
## 5.6 80000K 高温发散:源码级根因与解决方案
### 问题
初次边界测试中,两个 80000K 点He-rich 和 He-poor在 nc 阶段发散:
max_relc 从 iter1 的 ~40 单调爆炸到 iter10 的 1e131e17触发 `tlusty208.f:14700`
`ABS(CHMX).GT.1.D16` 硬停止。35000K 同配方则正常收敛。
### 根因tlusty208.f 源码分析)
通过分析源码确认发散由三个叠加因素导致,**全部集中在深层ID 1-8的能级
布居数POP 列),温度变化很小**
1. **ORELAX=1.0 无阻尼**`tlusty208.f:14647`ORELAX 只乘到布居数修正上。
默认 1.0 = 纯线性化无阻尼,首次迭代就把深层 CNO 高价离子O IV/V、C IV、
N IV/V布居数猛推向 NLTE每步最多变 10 倍DPSILG=10 限幅器,`14652`)。
2. **Ng 加速 iter7 起雪上加霜**IACC=7 默认,`tlusty208.f:29704`Ng 外推
假定迭代已近线性收敛在强烈非线性区外推会放大误差。fort.10 显示 iter7 正是
深层 POP 从 1e2 跳到 1e4 的转折点。
3. **深层无 LTE 保护**IDLTE=1000 默认,`tlusty208.f:5515`):所有 50 层都解
NLTE。80000K 深层高电离能级的光致电离-复合平衡极陡峭,完全线性化给出的
修正方向不稳定。
物理本质80000K 下 CNO 多次电离LTE 灰大气初猜的布居数与真实 NLTE 解差太远。
与 He 丰度无关He-rich 和 He-poor 都发散)。
### 解决方案 B已验证已集成进代码
```
IDLTE=45, IACC=NITER+1 (对所有 NLTE 阶段无条件启用)
```
- **IDLTE=45**`tlusty208.f:5515`):强制最深的 5 层走 LTE。物理合理——深层
τ≫1 本就该接近 LTE且消除深层高电离能级的发散源。对所有 sdB 都成立。
- **IACC=NITER+1**`tlusty208.f:29704`):完全关闭 Ng 加速(设大于 NITER 使
ACCEL2 早返回),避免外推放大误差。
效果边界点380000/He-poor
- 修复前nc iter1=38.8 → iter10=1.5e13(发散),大气全 NaN0 有效光谱点
- 修复后nc iter1=2.39 → iter5=0.0675 次收敛nl iter6=0.0078(收敛),
**106469 有效光谱点,零 NaN**
> ORELAX 当前未默认启用(保持 1.0),因为 IDLTE+IACC 已足够稳定。若遇极端
> 点仍发散,可在 config.yaml 的 chain 阶段加 `orelax: 0.5` 进一步阻尼。
`run_one.py` 已自动处理:所有 `lte=="F"` 的阶段nc/nl自动加 IDLTE=45 和
IACC=NITER+1LTE 灰大气阶段NITER=0保持干净不加。
### 备选方案(若方案 B 仍不够,按推荐度)
- **方案 A碰撞-辐射开关)**`ICRSW=1, SWPFAC=0.1, SWPINC=3.0``SWITCH`
子程序 `tlusty208.f:4556`)。首轮压低辐射率使布居数接近 LTE逐步恢复真
NLTE。Hummer & Voels (1988) 标准稳定化手段。
- **方案 C强限幅**`DPSILG=3.0, ORELAX=0.3, ITEK=5`。把单步布居数变化
上限从 10× 降到 3×更保守但迭代更多。
### 关键源码位置(供进一步调参参考)
| 参数 | 源码行 | 作用 |
|------|--------|------|
| ORELAX | 14647, 844 | 布居数过松弛(<1 阻尼 |
| IDLTE | 5515 | 深层强制 LTE 的深度阈值 |
| IACC/IACD | 29704, 29750 | Ng 加速起始/间隔 |
| ITEK | 836-860 | 完全线性化迭代数之后转 Kantorovich |
| DPSILG/DPSILT | 14652-14659 | 单步修正限幅通用/温度 |
| ICRSW/SWPFAC | 4556-4642 | 碰撞-辐射开关逐步引入 NLTE |
| POPZCH | 22910 | max_relc 计算时跳过的小布居数阈值 |
---
## 6. 邮件往来要点Peter Nemeth2024-10~11
完整邮件在 `hot_subdwarf/letter/`关键技术建议
1. 收敛判定fort.9 各深度相对变化都 < CHMAX `check_conv.py`
2. He 用最复杂模型原子24-level He I + 20-level He II
3. He-rich 模型难收敛属正常用模型链 CHMAX可减小模型间步长
4. ITEK 可调3/15/100提升稳定性——但实测 100 overshoot勿超 15
5. CHMAX普通星 0.001 可达He-dominated 可放到几个% 10% 1% 逐步收紧
6. synspec 后处理卷积vsini仅在比对观测时需要纯理论光谱可直接用 fort.7
---
## 7. 参考文件索引
| 文件 | 内容 |
|------|------|
| `tests/cno_sdspectrum/GUIDE.md` | 你写的原始指南基础流程、.5 格式nst 说明)—— **必读** |
| `tests/cno_sdspectrum/R1_full` | 你验证过的完整四步运行脚本 |
| `tests/cno_sdspectrum/sdB35000g550_{lte,nc,nl}.5` | 三阶段的范例 .5 文件 |
| `tests/sdB_spectra/runs/test_cno/` | 已算好的 35000/5.5 CNO 模型结果 |
| `tl208-s54/tests/tlusty/bstar/BGA20000g400v2a.5` | BSTAR2006 含全套金属参考模型 |
| `hot_subdwarf/letter/` | Peter Nemeth 的全部邮件 |
| `cno_grid/src/run_one.py` | 三步链实现DEFAULT_CHAIN 即验证配方 |