Files
DCTS/docs/spectrum_correctness_analysis.md
fmq 43b82b1ae2 feat(all): 物理正确性五重硬门槛、输入文件结构化与 fort.55 错位修复、conv 诊断 DB 化与阶段归因修复、ORELAX 收敛修复与导入工具下线
物理正确性校验体系(common/conv_check.rs +494 行)
- 新增 5 类硬门槛:能量守恒(.6)、温度结构(.7)、emflux 积分校验(.emflux,含全 NaN 判失败)、假收敛排查(itek 轨迹首末比)、b 因子合理性(.bfac)
- runner 在 TLUSTY 阶段结束后执行全部校验,任一失败判 final_converged=false
- GridConfig 新增 8 个可配阈值,经 scheduler→executor→runner 全链路透传

输入文件配置结构化重构(config.rs +1453 行)
- TlustyInput 拆为 dot5/nst 分层结构,字段名严格映射 tlusty208.f READ 语句;SynspecInput 重构为 9 个 Fort55Line 子结构体
- 移除 ChainStep.metals 字段,元素集改由 dot5.atoms/ions 显式声明(gen_input5/nst_writer 同步重写为三源融合 / 分层覆盖)
- fort.55 修复行结构 bug:补全分子表行(7→9 行),IDSTD 50→0 错位修正(影响全部光谱线强归一化,需重算 SYNSPEC 阶段)

conv 诊断 DB 化与阶段归因修复(server)
- 单点详情 conv 面板从磁盘 conv.json 改读 DB grid_points.summary_json;grid_points 新增 summary_json/last_elapsed_sec 两列(旧库幂等 ALTER)
- record_task_report 阶段归因列加 CASE 守卫 + clear_synspec 对称处理,修复 synspec-only/TLUSTY-only 重跑污染统计
- 新增 summary_merge.rs 点级增量合并,避免重跑覆盖诊断字段

收敛性 ORELAX 修复与 seed_chain 可配(sdB_cno.yaml + node)
- nl 阶段加 orelax=0.5、seed_nc 加 orelax=0.3,阻尼中温区 relc 振荡发散
- seed_chain 块可配,executor 优先采用用户配置而非内置默认链

导入工具下线
- 删除 import_results 客户端工具及 Windows 推送脚本;移除 /admin/import_seed 端点
- 改为服务端临时 migrate_conv 端点(扫 conv.json 增量合并入库,迁移后可删)

文档与分析
- 新增 1305 失败点根因分析、fort.14 全 NaN 物理含义分析两份深度文档
- spectrum_correctness_analysis 两次修订标注已修复项;fetch_results.sh 修 trap RETURN 的 set -u 报错
2026-08-09 12:09:48 +08:00

37 KiB
Raw Permalink Blame History

收敛恒星光谱的物理正确性保证调研

调研日期:2026-08-04 范围:TLUSTY 208 + SYNSPEC 54 计算的恒星大气与光谱的物理正确性保证方法。 前置文档:docs/tlusty&synspec收敛性判断.md(程序"是否崩溃/收敛"的判定,是本调研的下层;该文档 §4 记录了漏洞 1-5 的修复历程)。 核心命题:程序正常退出(rc=0)且 max_relc < chmax ≠ 光谱在物理上正确。本文调研介于两者之间的静默错误来源与验证方法。 方法:源码级静态分析 + 天体物理方法学综述 + 三方独立复核。

修订说明(2026-08-07:本调研初版(2026-08-04)基于修复前的代码状态撰写。经核查,漏洞 1(.spec 内容校验)、漏洞 2(fort.9 缺失分支虚构 best_max_relc)、漏洞 4(NaN 阈值)已在后续提交中修复。fort.55 字段错位(§5)也已修复——SynspecInput 重构为 9 个按行子结构体,与 SYNSPEC READ(55,*) 语句一一对应,IDSTD 从 50 修正为 0(自动 2ND/3)。本次修订同步了这些已修复项的现状,仅保留仍真实存在的缺口(.6 能量守恒解析、诊断产物未解析)。

修订说明(2026-08-08:经源码级二次核查,同步近期重构导致的引用漂移与数据更新:① 行号校正——runner.rs:613→:598runner.rs:660→:645nst_writer.rs:16ND 默认已迁至 config.rs:712 default_nd())、synspec54.f:1157→:1230IBFAC 经 READ(84,*) 读出)、hhe35nl.6:340→:341;② 结构体名 StageSummary 更正为 StepSummarymodels.rs:590);③ ND/ions 表述更正——二者已非硬编码,分别在 config.rs:712/833 作为可配默认值(经 YAML 覆盖,见 workflows/sdB_cno.yaml:63-90);④ §5.2 DOPSTD 公式补全为 DSTD=SQRT(1.4E7*TSTD+VTS) + DOPSTD=1.E7/ALAM0*DSTD;⑤ §1.3 fort.13 改述为"默认结构性排除";⑥ 数据统计刷新——网格点 284→361,.iden 格式分类 44/221→92 逐线表/243 频率网格/26 其他;⑦ EQW 断言更正——逐线表 EQW 并非全为 0,约 43/92(≈47%)含非零值(强线可达上千 mA),但作为系统化 EW 来源仍不可靠,结论(改走 .spec 数值积分)不变。


0. TL;DR

当前 pipeline 对光谱正确性的保证基本停留在"数值收敛"层面,完全没有做物理不变量校验。三方调研发现:

  1. 最高 ROI 缺口TLUSTY 已经无条件地把能量守恒诊断TOTAL SURFACE FLUX、逐深度 RAD/TOTCON/TOT(RAD+CON)/TOT)写进已归档的 .6 文件,却从未被任何 Rust 代码解析。这是 Hubeny 官方推荐的 1% 判据,零成本可得,是物理正确性的第一道硬门槛。
  2. 系统性的配方风险(已修复,见 §5fort55_writer.rs 写的字段 idrv/ifreq 与 SYNSPEC 实际读取的 IDSTD/IPRIN 错位。已重构为 9 个按行子结构体与 SYNSPEC READ(55,*) 语句一一对应,IDSTD 修正为 0(自动 2ND/3),并补全了原漏生成的分子表行(避免 VTB 行被吞导致 vturb 错误覆盖)。
  3. 网格级错误传播:通过 converged && !nan 门控上传的种子大气(.7),会把"伪收敛但物理未平衡"的点扩散给整个物理族——这是网格计算特有的静默放大机制,现有检查无法识别。
  4. 完整的方法学分层(§6):硬门槛(线上每点)→ 质量监控(抽样)→ 深度核查(线下基准比对),覆盖辐射平衡、光谱自洽、网格一致性、外部基准四个维度。外部基准的特殊性(§3.4):本网格是 CNO 全 NLTE 独立扫描,社区经典网格均不含 CNO NLTE,故外部基准对 CNO 维度失效——需用网格内部 CNO 物理自洽验证(路线 A+ 同代码栈 Pacheco 2021(路线 C)替代。

1. 当前已产出但未利用的物理诊断

这是后续做正确性校验的基础——很多信息 TLUSTY/SYNSPEC 已经产出,只是我们没解析。

1.1 能量守恒诊断(最关键,零成本可得)

TLUSTY 在 LFIN(最终迭代)时由 OUTPRI 子程序无条件写出,位于 .6 文件(unit 6,已归档):

TOTAL SURFACE FLUX 6.77712339D+12        ← 实际积分通量 TOTF
ID  MASS  TAUROSS  TEMP  NE  DENS  P_gas  LOG(G_rad)  RAD/TOT  CON/TOT  (RAD+CON)/TOT
 1  ...                                         1.001E+00  0.000E+00  1.00106E+00
  • FLTT = SIG4P * TEFF**4(预期通量 = σTeff⁴/4π,SIG4PBASICS.FOR:51
  • RAD/TOT = 辐射通量 / σTeff⁴
  • (RAD+CON)/TOT = 总通量(辐射+对流)/ σTeff⁴ —— 此列应≈1.0
  • 实测样本(收敛良好的 sdB 模型,28 次迭代,hhe35nl.6:341):(RAD+CON)/TOT = 1.00106E+00(逐深度恒定,能量守恒误差 0.1%)。未收敛/发散模型的此列会显著偏离 1(典型表现是表层偏离或逐深度不单调),是物理正确性的第一道硬门槛。

关键事实.6 已在归档白名单(STAGE_SNAPSHOT_SUFFIXES 含 "6"),但 crates/ 下无任何代码解析它。数据已就位,只差一个 .6 解析器写入 conv.json

1.2 辐射平衡逐深度残差(被覆盖丢失)

TLUSTY RECHCK 子程序(tlusty208.f:49854)在 LFIN 时无条件调用,逐深度计算 re=(吸收−发射)/发射 写入 unit 17fort.17)。但 unit 17 随后被 SYNSPEC OUTPRI 覆盖写连续谱(synspec54.f:3371)——成功路径下 RECHCK 输出永久丢失,仅 SYNSPEC 失败时 .cont 里残留的才是 RECHCK 表(这也是 .cont 后缀二义性的来源)。

修复方向:仿照 .bfac/.emflux 的快照做法,在 RECHCK 后/SYNSPEC 前快照 fort.17。

1.3 其他未启用 / 未解析的诊断

诊断 子程序 unit→文件 启用条件 现状
能量守恒总表 OUTPRI 6→.6 无条件 已产出,未解析(最高 ROI
辐射平衡逐深度 RECHCK 17→.cont 无条件 被 SYNSPEC 覆盖丢失
统计平衡残差 CHCKSE 16→fort.16 ICHCKP≠0nst 未设) 未启用
冷却/加热率 COOLRT 86/87/88 ICOOLP≠0nst 未设) 未启用
出射辐射场谱 OUTPRI 13→fort.13 无条件 默认结构性排除(非 BARE_KEEPS、不带 <name>. 前缀,result_filter.rs:67-72;与 fort.1/2/3 等中间单元同等处理,非专门列入排除名单)
TLUSTY 出射谱 OUTPRI 14→.emflux 无条件 已快照归档,未解析(可做 bolometric 积分)
b 因子(NLTE 偏离) OUTPRI 12→.bfac 无条件 已快照归档,未解析
SYNSPEC 谱线统计 START/OUTPRI 6→.log 无条件 已归档,未解析(含 LINES-TOTAL、波长范围、等效宽度)

1.4 conv.json 的现状

ModelSummary / StepSummary / ConvCheckResultmodels.rs:616/590/564)记录的字段全部是数值收敛指标max_relc, last_iter, worst_depth, synspec_rc 等),没有任何物理正确性字段(能量守恒、辐射平衡、统计平衡残差)。


2. 静默错误的物理来源

"程序正常退出但光谱物理错误"的四层来源,按严重度排序。每层给出源码证据与可检测性。

2.1 第一层:TLUSTY 大气结构错误(光谱错误的根因)

错误来源 物理后果 源码证据 当前是否捕获 严重度
NITER 截断被当收敛 大气未达统计平衡,布居数错误 tlusty208.f:14728 LFIN=ABS(CHMX).LE.CHMAX.OR.ITER.GE.NITEROR 短路:CHMX 再大也会因 ITER≥NITER 判 LFIN 部分(conv_check.rs 重判 max_relc<chmax,但若截断时"刚好"<chmax 则通过) 极高
ACCEL2/Ng 加速伪收敛 加速外推后下次 CHMX 人为变小,提前判收敛但平衡未达成 tlusty208.f:29693-29797,无加速后发散回退检查 未捕获(max_relc 变小与真收敛难区分)
模型截断但物理不充分 关键 H/He 跃迁被省略,NLTE 种群错误但程序正常 默认原子模型 default_ions()config.rs:833,可经 YAML tlusty_input.dot5.ions 覆盖,workflows/sdB_cno.yaml:63-90 即显式列出完整 22 行表)H=9lev、HeI=14、HeII=14;远低于 MLEVEL=1134 上限 未捕获(需物理判断)
ND=50 深度网格偏稀 大气结构分辨率不足,谱合成输入质量差 default_nd()config.rs:712,经 TlustyInput.nst.depth.nd 可配)ND=50 默认;BASICS.FOR:9 MDEPTH=100 未捕获(需对比 ND=99 中-高

2.2 第二层:SYNSPEC 谱合成错误

错误来源 物理后果 源码证据 当前是否捕获 严重度
★fort.55 字段错位(已修复,见 §5) 标准深度取最深层(IDSTD=50=ND、输出详尽度偏离;IOPHLI 无论写何值都被 SYNSPEC 无条件置 0(见 §5.2 fort55_writer.rs:5imode,idrv,ifreq 与 SYNSPEC synspec54.f:253IMODE,IDSTD,IPRIN 错位。已重构为 9 子结构体按行一一对应config.rs Fort55Line1-6 + Fort55LineMol/Vtb/Ang 已修复(IDSTD 现 0=自动 2ND/3 高(系统性) → 已消解
NLTE 静默降级为 LTE 匹配不上的 NLTE 线被 set to LTE,线强度错误但程序继续 synspec54.f:9114-9176,仅写 fort.11 计数 未捕获(DCTS 不解析 fort.11
IBFAC=0 默认全程按 LTE 读种群 fort.8 不含/不全含 NLTE 种群时种群保持 LTE 不替换 synspec54.f:1230 READ(84,*) 读出 IBFAC,默认 0:11220 NUMP>IP 才替换 未捕获
波长网格步长固定且窗口窄 窄线被漏掉,谱"正常但缺线" SPACE=0.01config.rs:1519 default_space());默认窗口仅 1400-1410Å(config.rs:1508,1511 default_alam0/alast),sdB_cno 工作流显式配 3000-7000Å 未捕获 中-高
线表缺失(只链 fort.19 缺关键谱线,有计数但无"应有线却缺失"校验 runner.rs:598 symlink 单一 runtime.linelistsynspec54.f:9157 NLIN0 计数 未捕获

2.3 第三层:数据传递与种子继承(网格级错误放大)

错误来源 物理后果 源码证据 当前是否捕获 严重度
★种子继承的错误传播 伪收敛点的 .7 通过 converged && !nan 门控上传为种子,被相邻 SeedStep 点热启动,错误沿网格拓扑传播directed_cno_distance 倾向选贫方向,一个坏种子可污染整个 Teff/logg 族 reporter.rs:122 种子门控 converged && !atmo_has_nanexecutor.rs:221 读取种子 bytesseed_finder.rs:26-40 有向最近邻选种(RICH_PENALTY=4.0 > POOR_PENALTY=1.0,倾向贫方向) 未捕获(坏种子本身"通过"了所有检查) 极高

2.4 第四层:编译/数值精度

错误来源 物理后果 源码证据 当前是否捕获 严重度
生产编译无 -fcheck/-ffpe-trap 数组越界、IEEE 异常 → rc=0 + 静默写越界内存,产出无 NaN 标记但物理错误的大气 deployment.md:86,90 gfortran -fno-automatic -O3 未捕获(详见 tlusty&synspec收敛性判断.md §4 漏洞 3

详见 tlusty&synspec收敛性判断.md 的 gfortran 运行时错误退出码实测表。


3. 天体物理验证方法学

每个方法标注:验证的物理不变量、操作步骤、容差判据、所需数据、实现难度、线上/线下。

3.1 大气模型层面(TLUSTY 产出)

方法 验证的物理不变量 容差/判据 所需数据 难度 时机
通量守恒 每深度 πF(rad+conv)=σTeff⁴ (RAD+CON)/TOT 偏离 1 ≤1%(Hubeny 官方判据);任一深度 >5% 直接判坏 .6 末表 线上
max_relc 收敛门槛 状态向量相对修正已可忽略 < chmax(默认 10⁻³,对 sdB/早型星合理;精密线分析可收紧到 10⁻⁴) *_chmax*.9 低(已实现) 线上
假收敛排查 max_relc 单调下降 ≥3 个量级 初始/最终 max_relc ≥10³ fort.9 全序列 抽样
NaN/Inf 否决(收紧) 所有深度点温度/密度为有限物理值 任意 1 行命中即否决(已实现 0 行容忍,conv_check.rs:264-265 .7 线上
温度结构边界 T(τ) 落在物理合理范围 表层 T ≲ 2-3×Teffidstd 处 T≈(2/3)Teff;总体 10¹-10⁸ K .7 抽样
统计平衡残差(NLTE 跃迁平衡 R_ij·n_i=R_ji·n_j、粒子数守恒 b 因子无 NaN/Inf;关键能级 b∈10⁻³-10³ .bfac 抽样

对 TLUSTY 的已知坑(a) fort.9 缺失分支虚构 best_max_relc=0.0已修复:现按 niter==0/niter>0 区分——grey start 保留 converged=true 但 best_max_relc=None;异常返回 INFINITYrunner.rs:448-477conv_check.rs:88-98);(b) Kantorovich 加速的伪收敛风险;(c) 表层(worst_depth=1)最易出 NaN。

3.2 光谱合成层面(SYNSPEC 产出)

方法 验证的物理不变量 容差/判据 所需数据 难度 时机
NaN/负值/零行否决(最关键) 归一化谱∈[0,1],绝对流量≥0,无 NaN/Inf 0 容忍(任意一个即判坏) .spec.cont 线上
Rayleigh-Jeans 尾 Planck 检验 长波端连续谱 → Bλ(Teff) 斜率与 Bλ(Teff) 一致;偏离 >20% 异常 .cont + Teff 抽样
总积分流量能量守恒 ∫Fλ dλ ≈ σTeff⁴(bolometric 偏离 <1-2% .emflux(全频率范围) 抽样
连续谱自洽(TLUSTY vs SYNSPEC 同波长点 .emflux.cont 水平一致 连续谱区差异 <1-2% .emflux + .cont 抽样
Balmer 线基准 Hα/Hβ EW 随 Teff/logg 已知行为 线心深度∈(0,1)sdB 的 Hβ EW 约 5-15Å;高 Teff(>30kK) 不应异常强 光学 .spec 抽样
He 线电离序列 He II/He I 强度比随 Teff 单调 比值突变 = NLTE 电离平衡错 光学 .spec 抽样

归一化谱 vs 绝对流量谱:归一化谱只验线形/线强,不能验能量守恒;绝对流量谱(.emflux.cont)才能验通量守恒与 Planck。两者必须分别处理。

3.3 网格层面(内部一致性)

方法 验证的物理不变量 容差/判据 所需数据 难度 时机
相邻点平滑性(一阶差分) 光谱随参数连续变化 连续谱单步 Δ<10-15%;线 EW<30% 全网格 .cont/EW 线下
二阶差分 / 离群点检测 光谱无孤立异常 r>4σ 或 |残差|>20% 标 outlier 全网格光谱 线下
沿等参数线单调性 Balmer/He 线随 Teff/logg 已知单调趋势 出现锯齿/反转 = 可疑 全网格光谱序列 线下
收敛质量地图 max_relc 在网格上无孤立坏区 孤立高 max_relc 点(邻居都收敛)= 可疑 全网格 conv.json 线下

已知坑:网格在 80kK+He-poor+富金属区有真实物理极限(CNO 高价离子主导不透明度,线性化无法阻尼)——这片成片失败是物理真实的,不应误判为 bug;但孤立单点失败(邻居都好)才需要复查。

3.4 外部基准比对(ground truth

核心矛盾与适用性说明(本网格特有):本网格是 6 维 sdB + H/He/CNO 全 NLTE 独立扫描(Teff 20-60kK、logg 5.0-6.5、logHe 4..2、logC/logN/logO 各 4..1,见 workflows/sdB_cno.yaml)。社区经典网格 OSTAR2002/BSTAR2006/NLTE-OBGRID 均不含 CNO 的 NLTE 同时建模CNO 按 LTE 或仅 H/He NLTE),PHOENIX/ATLAS9 更无。因此逐点外部比对 CNO 维度几乎不可能——任何外部基准最多只能验证 H/He 部分。正确破局:用代码同源性验证实现正确性,用网格内部物理规律验证 CNO NLTE 物理正确性。

路线 A(最高 ROI):网格内部 CNO 物理自洽验证

这是本网格独有的、外部基准反而做不到的验证。CNO NLTE 有强可检验预测:线强对丰度的单调响应 + CNO 互不耦合。已有 361 个网格点数据(data/result/ 实测,持续增长),零额外计算成本。

校验 物理不变量 判据 所需数据 难度
C 线 EW 随 logC 单调 固定 Teff/logg/logHeC II/C III 线强随 C 丰度单调递增 同族 4 个 logC 点 EW 单调,无反转/平台 同族 .spec + 线表
CNO 线互不耦合 固定 C/N,扫 O 时 C/N 线 EW 几乎不变(NLTE 交叉耦合弱) C 线 EW 跨 logO 变化 <5% 同族 .spec + 线表
电离序列协同 N III 4634-4641 与 He II 4686 协同增减(共依赖 ne/T) 两线强度比在网格上平滑无突变 .spec 序列

EW 数据来源的现实约束:理想情况下从 .idenSYNSPEC fort.12 逐线表)直接读 EQW 字段(synspec54.f:9719 WRITE(12,603) ...EQW...)。但经核查,当前归档的 361 个 .iden 存在两个问题:(1) EQW 字段(第 7 列)大面积缺失——SYNSPEC 仅在线心强度权重 WW1 非零时才填 EQW:9705),当前配置下多数逐线表行的 EQW 仍为 0.0,仅约 43/92(≈47%)的逐线表含非零 EQW(强线如 He II 3203Å 的 EQW 可达上千 mA),作为系统化 EW 来源并不可靠;(2) 格式不统一——仅 92 个是逐线表格式,243 个是频率网格格式,另有 26 个其他形态(data/result/ 实测)。因此 EW 实测需改走.spec 归一化谱按线窗口数值积分∫(1F)dλ),不能依赖 .iden。线波长定位参考线表(fort.19)。此为路线 A 脚本的实现前提。

路线 B:TLUSTY 官方 hhe 样本的退化比对(端到端回归)

仓库已有 hotsd/tlusty (副本)/hhe35nl.6 等 TLUSTY 官方 H/He NLTE 标准样本(Teff=35000K不含 CNO)。这是同源码、同原子数据的最干净回归测试。

  • 操作:用本 pipeline 跑一个 logC=logN=logO=10(等效无 CNO)的点,配置与 hhe35nl 对齐。
  • 判据.7 大气结构(T(τ)、逐深度温度/密度/电子密度)与官方样本逐深度一致到 <0.1%——CNO 丰度趋零时物理上退化为纯 H/He,任何偏离都指向 pipeline 的输入封装/参数传递 bug。
  • 覆盖:直接验证 §2.1(深度网格、模型截断)、§2.2(fort.55 字段错位的副作用)是否影响大气结构。投入低(跑 1 个点)。

路线 C:同代码栈社区网格——Pacheco & Díaz 2021

唯一能做近似逐点比对的社区基准,因为与本网格用完全相同的代码栈

维度 本网格 Pacheco 2021ApJS 256, 41 可比性
代码 TLUSTY v208 + SYNSPEC 54 TLUSTY v205/v208 + SYNSPEC 54 同版本,差异最小
Teff 20k/30k/40k/50k/60k 20k/25k/30k/35k/45k/65k 重叠 20k/30k(余插值)
logg 5.0/5.5/6.0/6.5 4.5/5.5/6.5 重叠 5.5/6.5
logHe 4..2 He-poor/He-rich 两支(约 3..+2 ⚠️ 仅两端可比
CNO logC/N/O 各 4..1 独立扫描 整体 solar 或 [Fe/H]1.5 两组固定比例 无法逐点比对 CNO 维度
波长 3000-7000Å 1000-10000Å @ 0.01Å 本网格是其子集
数据 公开:SpecModels / SVO / Vizier 可下载

比对策略(绕开 CNO 丰度差异):

  1. 连续谱形状3200-3700Å、4400-4800Å 无强 CNO 线窗口):取本网格 CNO 最接近太阳(logC≈−3.6/N≈−4.2/O≈−3.3)的点,在相同 Teff/logg/logHe 下比对连续谱,容差 1-2%
  2. CNO 线波长定位:线强因丰度不同而异,但 C II 4267、C III 4640-4650、N III 4630-4640 的线心波长必须一致(同套原子数据),漂移 = 线表加载错。
  3. 非重叠点插值Teff=40k/50k 用其 35k/45k/65k 插值曲线,本网格点应落 ±5% 内。

数据获取http://specmodels.iag.usp.br/http://svo2.cab.inta-csic.es/theory//newov2/

路线 D:实测光谱 ground truth——SDSS / LAMOST sdB 库

终极基准是真实恒星。大量 sdB 有实测光谱 + 已测定参数:

  • SDSS hotSubDwarf catalogKepler et al. 2015-2019~10⁴ 颗):每颗有 Teff/logg/logHe 及部分 C/N 丰度。
  • 选 5-10 颗参数落入本网格的 sdB,取最近邻网格点,卷积仪器轮廓(SDSS R≈2000)后比对。
  • 容差:线轮廓吻合、Balmer/He EW 10-15%(含噪声与投影自转)。

经典社区网格的适用范围(仅 H/He 部分)

下列网格不含 CNO NLTE,只能用于验证 H/He 连续谱与 Balmer/He 线,不能验证 CNO 维度

基准 CNO 处理 可验证 数据来源
OSTAR2002 / BSTAR2006Lanz & Hubeny 2003/2007 LTE H/He 连续谱、线轮廓 tlusty.oca.eu
NLTE-OBGRID LTE H/He 连续谱(更完整 H 原子) MAST archive.stsci.edu/hlsp/nlte-obgrid
PHOENIX / ATLAS9 LTE(独立代码) 独立代码交叉(光学几个百分点;UV 可达 10-20%) STScI
CALSPEC 标准星(Bohlin+2020 TLUSTY WD 网格 1500Å-30μm 1% 一致(仅适用 WD,非 sdB MASTGD153/GD71

优先级与实测系统误差

务实排序(针对"无 CNO 外部基准"现实)

  1. P0 路线 A(网格内部 CNO 单调性/解耦)——数据现成,CNO 独有验证,投入最低。
  2. P0 路线 B(hhe 退化比对)——同源码回归测试,最干净。
  3. P1 路线 CPacheco 2021)——唯一同版本同物理基准,连续谱/线位。
  4. P2 路线 DSDSS 实测)——终极 ground truth,投入最高。

实测比对(路线 D)必须考虑的系统误差:消光(RV=3.1)、视向速度、instrumental broadening(需 ROTINS 卷积)、距离/标度因子。


4. 物理红旗清单(一票否决)

以下任一出现即光谱不可信,必须标记复查:

红旗 物理含义 检测方法
连续谱出现负值或 NaN 辐射转移数值失败 .spec/.cont 任意点 <0 或 NaN
归一化谱线心深度 >1(流量 <0 线吸收过度/数值错 归一化谱任意点 <0 或 >1.05
.spec 全零或行数异常少 SYNSPEC 中途 quit 留脏数据 行数 <预期×0.9 或全零
总积分流量偏离 σTeff⁴ >2% 能量不守恒 积分 .emflux
通量守恒表末列偏离 1 >1%(任一深度) 辐射平衡未达 .6 末表
表层温度 >>Teff(如 >3×Teff T(τ) 结构非物理 .7 表层 T
热星(Teff>30kKBalmer 线异常强 NLTE 电离算错 测 Hα/Hβ EW 比对基准
连续谱斜率与 Teff 不符 温度结构错 RJ 尾比对 Bλ(Teff)
沿 Teff 序列 Balmer/He 线非单调 局部点 NLTE 错 网格级单调性检查
孤立单点与四邻插值偏离 >20% 该点异常 离群点检测

5. fort.55 字段错位问题(已修复)

状态:已修复(2026-08-07。本节保留问题描述作为历史记录,处置见 §5.3。 影响所有光谱的系统性 bug:Rust 端 SynspecInput 的字段命名与 SYNSPEC READ(55,*) 语句的变量名脱节,且大量字段硬编码不可配。修复方式是重构为 9 个按行分组的子结构体,字段名与 SYNSPEC 源码一一对应。

5.1 事实(修复前的错位)

SynspecInput 是扁平 7 字段结构体,与 SYNSPEC fort.55 的 9 行 30+ 字段规范脱节:

  • 第 1 行错位fort55_writer.rs:5(旧)写 imode, idrv, ifreqSYNSPEC synspec54.f:253IMODE, IDSTD, IPRIN。即 idrv=50 被当作 IDSTD=50ifreq=1 被当作 IPRIN=1。而真正的 IFREQ(频率网格开关)在第 4 行(synspec54.f:2146)。
  • 第 6 行错位:旧字段 abs_cutoff=0.01 被写到 SPACE 位置(相邻频率点间距),而非任何"截止"参数。真正的截止参数 CUTOF0(行6第3列)被硬编码为 10、CUTOFS(连续谱间距,行6第4列)硬编码为 0,均不可配。
  • 第 2-5 行全硬编码INMOD/INTRPL/ICHANG/ICHEMC(行2)、IOPHLI/nun*(行3)、IFREQ/INLTE/ICONTL/INLIST/IFHE2(行4)、IHYDPR/IHE1PR/IHE2PR(行5)全部不可通过 YAML 配置。
  • 行 7/8 完全缺失:VTB(湍流速度,行7)、NMU0/ANG0/IFLUX(角度/比强度,行8)不生成,靠 SYNSPEC 的 err=/end= 标号侥幸跳过——脆弱巧合。

5.2 影响(修复前的物理后果)

  • IDSTD=50=ND,最深层):SYNSPEC 的标准深度(synspec54.f:2152-2155,仅在 IDSTD=0 时自动取 2*ND/3≈33)本应自动取 2*ND/3≈33,现被强制取最深层。该层的 T/ne 用于谱线多普勒宽度(DSTD=SQRT(1.4E7*TSTD+VTS)synspec54.f:2265;再 DOPSTD=1.E7/ALAM0*DSTD:8131/8728)、参考丰度(AVAB)、波长网格步长的归一化基准。实测 8 个不同 Teff/logg/He/CNO 的收敛点,sqrt(T50/T33) 稳定在 2.0-2.13,即 DOPSTD 系统性偏大 ~100-113%VTS 与 1.E7/ALAM0 系数对 IDSTD 错层带来的相对放大不改变此量级结论)。AB0=EXP(...)/DOPSTD/AVAB:8913)直接影响每条谱线的线强归一化,且 IF(AB0.LT.UN) GO TO 10:8914)还改变哪些谱线被保留。
  • IPRIN=1:SYNSPEC 的输出详尽度开关,仅影响 .log 里打印的诊断量多少,不影响光谱数值。
  • IOPHLI 被 SYNSPEC 无条件置 0SYNSPEC synspec54.f:255 读取 IOPHLI 后,:269 紧接 iophli=0(注释 disabling an old option无条件覆盖。即无论 fort.55 写什么,Lyman 线翼准分子卫星线处理都被必然关闭。这是 SYNSPEC 源码的既定行为,非 fort.55 错位所致。

5.3 处置(已实施)

修复方式:重构 SynspecInputconfig.rs)为 9 个按行分组的子结构体(Fort55Line1..Fort55Line6 + Fort55LineMol + Fort55LineVtb + Fort55LineAng),字段名严格使用 SYNSPEC 源码变量名,行内字段顺序与 READ(55,*) 语句完全一致。每字段带文档注释(物理含义 + synspec54.f 行号)。generate_fort55_contentfort55_writer.rs)改为按子结构体逐行序列化。SynspecInput::validate()config.rs)在配置加载时校验不触发不支持的条件读取路径(DM 数组/显式角度/风模式/分子 iunitm)。

覆盖范围fort.55 全部 9 行 30+ 字段均可通过 YAML synspec_input 块按行配置,支持后续不同工作流(sdB/sdO/WD 等)的差异化参数。单元测试覆盖行数、字段对齐、VTB 默认负值、默认值关键字段、全自定义五个维度。

行为变化

修复前 修复后 影响
IDSTD 50(最深层,错位) 0(自动取 2ND/3≈33 光谱线强归一化修正,所有光谱需重算
IPRIN 1(被 ifreq 错位占用) 1(语义正确,显式可配) 无行为变化
真正的 IFREQ 1(硬编码行4 1(显式可配) 无行为变化
行7 分子表 漏生成(VTB 行被吞) 显式生成 nmlist=0 修正行序错位(原靠 EOF 兜底)
行8 VTB 漏生成(end=30 跳过→vturb 保持 2 生成 -1.0vtb<0 不覆盖→vturb 保持 2 无行为变化(均保持大气 vturb=2)
行9 NMU0 漏生成(end=100 跳过) 生成 0(不算比强度) 无行为变化
其余字段 硬编码 可配,默认值与原硬编码一致 无行为变化

行7 分子表的关键性SYNSPEC 在 IMODE∈[-3,1](默认满足)时会额外读一行分子表(synspec54.f:2208)。gfortran list-directed READ 满足变量列表后消费整行剩余——若漏生成此行,VTB 行会被分子表 READ 吞掉,导致 vtb 读到 NMU0 行的首值,if(vtb.ge.0.) 触发 vturb 被覆盖为 0(审查 Critical-1)。显式生成 nmlist=0 行可保证行序对齐。VTB 默认 -1.0 是双重保险:即使行序错位,vtb<0 也不会触发覆盖。

重算指引fort.55 只影响 SYNSPEC 阶段,TLUSTY 大气结构(.7)不受影响,种子库可继续用。重算只需把 synspec_stage.policy 临时改为 force_recompute 重跑 SYNSPEC 阶段,无需重算 TLUSTY。


6. 分层验证策略建议

按"必须做 / 建议做 / 可选做"分层,标注每项的现状与所需投入。

第一层:硬门槛(线上,每个点必跑,0 容忍,失败即标记重算)

# 校验项 现状 所需投入 依据
1 SYNSPEC .spec/.cont 内容校验(NaN/Inf/负值/全零/行数) 已修复(漏洞 1spec_is_validconv_check.rs:287-335)在 runner.rs:645 调用,校验 NaN/Inf/溢出/行数不足/全零 tlusty&synspec收敛性判断.md §4 漏洞 1P0
2 大气 NaN 否决收紧到 0 行容忍 已修复(漏洞 4atmosphere_has_nan 现 0 行容忍(conv_check.rs:264-265),含 NaN/Inf/*** 溢出/E+300 超高指数四类 conv_check.rs:264
3 max_relc < chmax + is_finite + fort.9 真实存在 已修复(漏洞 2 进阶)fort.9 缺失返回 INFINITYniter==0grey start)与 niter>0(异常)分流,best_max_relc=None 不再虚构 0.0 runner.rs:448-477conv_check.rs:88-98
4 通量守恒 (RAD+CON)/TOT 偏离 1 ≤1%(从 .6 提取) 未做(数据已就位) 低(写一个 .6 解析器) §1.1Hubeny 官方判据

第二层:质量监控(线上抽样 + 线下定期)

# 校验项 现状 所需投入
5 总积分流量 vs σTeff⁴(.emflux,偏离 <2% 未做,数据已归档 中(bolometric 积分)
6 Rayleigh-Jeans 尾 Planck 斜率检验 未做
7 TLUSTY .emflux 与 SYNSPEC .cont 连续谱自洽 未做
8 假收敛排查(max_relc 下降 ≥3 个量级) 未做
9 收敛质量热图(网格级 max_relc 分布) 未做 低(数据在 conv.json
10 温度结构边界(表层 T、idstd 处 T) 未做

第三层:深度核查(线下,建库时 + 每次配方变更时)

外部基准的适用性见 §3.4:经典网格(OSTAR/BSTAR/NLTE-OBGRID不含 CNO NLTE,仅能验证 H/He 部分;CNO 维度的外部比对首选 Pacheco 2021(同代码栈),其余靠网格内部物理规律(路线 A)。

# 校验项 所需投入 对应路线
11 网格内部 CNO 单调性/解耦(固定 Teff/logg/logHe 扫 logC/N/O §3.4 路线 A
12 hhe 官方样本退化比对CNO=10 退化到纯 H/He,与 hhe35nl 逐深度对比) §3.4 路线 B
13 Pacheco 2021 连续谱/线位比对(同代码栈,重叠 Teff/logg/logHe 点) §3.4 路线 C
14 与 OSTAR2002/BSTAR2006/NLTE-OBGRID 重叠点 H/He 部分比对(不含 CNO 验证) §3.4 经典网格表
15 与 PHOENIX/ATLAS9 独立代码比对(H/He 连续谱交叉) 中-高 §3.4 经典网格表
16 与 SDSS/LAMOST 实测 sdB 比对(卷积仪器轮廓后) §3.4 路线 D
17 Balmer/He 线序列单调性与基准
18 网格二阶差分离群点检测
19 统计平衡残差 / b 因子合理性(.bfac

配方变更触发规则

任何以下变更必须重跑第三层深度核查:CHMAX/NITER/ND 改动、原子模型/线表(fort.19)更新、TLUSTY/SYNSPEC 重编译(尤其加 -fcheck/-ffpe-trap)、丰度网格范围调整、fort.55 字段修复(§5


7. 综合判断

当前 pipeline 在"光谱物理正确性校验"上基本没做 —— 只做了数值收敛性(max_relc)和最低限度的完整性(.7 无 NaN、synspec 退出码),完全没有能量守恒、辐射平衡、统计平衡这三项核心物理不变量校验。

投入产出比排序

  1. P0:解析 .6 的能量守恒诊断(§1.1)—— 数据已就位,Hubeny 官方 1% 判据,是物理正确性的第一道硬门槛。第一层硬门槛 #1/#2/#3 已在近期提交修复(.spec 内容校验、NaN 0 行容忍、fort.9 缺失分流),此项 #4 是第一层唯一仍真实存在的缺口
  2. P1fort.55 字段错位修复(已完成,见 §5——SynspecInput 已重构为 9 子结构体与 SYNSPEC 一一对应,IDSTD 修正为 0。待办:重算受影响光谱(把 synspec_stage.policyforce_recompute 重跑 SYNSPEC 阶段,TLUSTY 大气不受影响)。
  3. P1:网格级种子传播校验(§2.3)—— 这是网格计算特有的静默放大机制,可通过"同一物理族下游点的 max_relc/通量守恒分布异常"间接检测。
  4. P2:质量监控层(§6 第二层)—— bolometric 积分、Planck 检验、连续谱自洽。
  5. P2:深度核查层(§6 第三层,§3.4)—— 分两支:(a) 网格内部 CNO 单调性 + hhe 退化比对(路线 A/B,数据现成、CNO 独有,优先做);(b) 外部基准——同代码栈的 Pacheco 2021(路线 C)是唯一能比 CNO 连续谱/线位的社区网格;经典网格(OSTAR/BSTAR/NLTE-OBGRID)不含 CNO NLTE,仅能验证 H/He 部分。

8. 参考资料

官方文档

  • Hubeny 2017, "A Brief Introductory Guide to TLUSTY and SYNSPEC"arXiv:1706.01859)—— 通量守恒 1% 判据、假收敛、ND=50 B 星例、改丰度警告
  • TLUSTY User's Guide IIIarXiv:1706.01937)—— fort.9 收敛日志格式、unit 6 辐射平衡表
  • TLUSTY User's Guide IV, Hubeny 2021arXiv:2104.02829)—— CHMAX=10⁻⁴ 高精度例

社区基准网格(ground truth

适用性:以下经典网格均不含 CNO NLTE 同时建模CNO 按 LTE),只能验证 H/He 部分(§3.4)。本网格(sdB + CNO 全 NLTE)的外部基准首选 Pacheco 2021(同代码栈、含 CNO NLTE)。

  • Pacheco & Díaz 2021ApJS 256, 41, DOI:10.3847/1538-4365/ac2508)—— TLUSTY v208 + SYNSPEC 54(与本网格同版本),sdB/sdO NLTE 含 C/N/O NLTE 线覆盖;Teff 10-65kK、logg 4.5-6.5、He-poor/rich 两支;1000-10000Å @ 0.01Å;数据公开(SpecModels specmodels.iag.usp.br / SVO svo2.cab.inta-csic.es/theory//newov2 / Vizier)。CNO 丰度为整体 solar 或 [Fe/H]−1.5 两组固定比例,非独立扫描——不能逐点比对 CNO 维度,但可比对连续谱形状与线波长定位。
  • Németh et al. 2014ASPC 481, 95arXiv:1308.0252)—— Pacheco 2021 的前身,TLUSTY/SYNSPEC NLTE sdB/sdO 网格(3200-7200Å),覆盖 (He-)sdB/sdO 全参数空间。
  • Latour et al. 2011ApJ 733, 100)—— sdO NLTE 网格(TLUSTY/SYNSPEC),含 H+He 及可选 C/N/O NLTE 模型。
  • OSTAR2002 / BSTAR2006tlusty.oca.eu)—— Lanz & Hubeny 2003/2007 社区标准网格(H/He NLTECNO LTE
  • NLTE-OBGRIDMAST archive.stsci.edu/hlsp/nlte-obgrid)—— Hubeny 更新版(H/He NLTECNO LTE
  • WD-GRIDMAST archive.stsci.edu/hlsp/wd-grid)—— Bohlin+2020 白矮星 NLTE 网格,1500Å-30μm 对 CALSPEC 1% 一致(仅适用 WD,非 sdB

交叉代码比对

  • Witzke+2021, MPS-ATLASA&A)—— 三代码流量差异:~400nm 最大,其他波段几个百分点
  • CASTELLI/Kurucz ATLAS9STScI

本仓库内相关文档

  • docs/tlusty&synspec收敛性判断.md —— rc 不可靠性、fort.9/NaN 阈值漏洞 1-5 修复历程、gfortran 退出码实测(第一层硬门槛的依据;注意该文档 §4 部分漏洞描述仍是修复前状态,本文档已同步现状)
  • docs/tlusty_result_artifacts.md —— fort 单元语义、.emflux/.bfac 快照、TLUSTY fort.14 与 SYNSPEC .spec 关系
  • docs/PIPELINE.md —— 阶段链、nst 配方(ND=50、默认 CHMAX=0.001)、物理极限区

源码证据

  • 能量守恒诊断:tlusty208.f:14179-14191,14271-14273OUTPRI);:49854RECHCK);实测 hotsd/tlusty (副本)/hhe35nl.6:341(RAD+CON)/TOT=1.00106E+00,收敛良好)
  • fort.55 错位(已修复):旧 fort55_writer.rs:5imode,idrv,ifreq vs SYNSPEC synspec54.f:253IMODE,IDSTD,IPRIN;现重构为 config.rsFort55Line1-Fort55Line6 + Fort55LineMol/Fort55LineVtb/Fort55LineAng 9 子结构体按行对应。synspec54.f:269 iophli=0 无条件覆盖(已核实,SYNSPEC 既定行为)。
  • 种子传播:reporter.rs:122(门控)、executor.rs:221(读种子 bytes)、seed_finder.rs:26-40(有向最近邻)
  • 漏洞 1 修复:conv_check.rs:287-335spec_is_valid)、runner.rs:645(调用点)
  • 漏洞 4 修复:conv_check.rs:264-2650 行容忍)
  • 漏洞 2 进阶修复:runner.rs:448-477conv_check.rs:88-98