Files
DCTS/workflows/sdB_cno.yaml
T
fmq b058e66722 feat(all): NaN 伪收敛否决与 nl_tight 能量回退、emflux 检验 4π 修正、nst 行宽与种子边界修复、gfATO 谱线表接通与网格加密 9216 点、阶段分项统计与跳板机部署
物理修复(400 失败点归因,见 docs/failed400_nan_pseudo_convergence_2026_08_17.md):
- runner: 阶段 converged 后复查 fort.7,含 NaN/Inf 即否决(fort.9 全零伪收敛,
  曾致 261 点误跳过 nl_direct 回退);否决阶段不产出种子,阻断污染传播
- runner: nl_tight 回退——仅能量边际失败时以 CHMAX 收紧 10× 从自身模型续迭代,
  残差降幅 ~10×;execute_tlusty_stage 抽取供主链与回退共用
- conv_check: fort.14 为 Eddington 通量 Hλ,积分需乘 4π 再比 σTeff⁴
  (旧版 ratio 稳定 0.0796=1/4π,全点系统性假阳性)+ 回归测试
- nst_writer: 单行超 80 字符被 TLUSTY 静默截断,IFALI/JALI/TRAD 等从未生效;
  按 75 字符自动换行
- seed_finder: Teff 容忍度改含边界 <=,相邻 5000K 档恢复互为种子 + 回归测试

谱线表与网格:
- 默认线表 gfVIS99 → gfATO(全波段 18-23000Å),TaskSpec.linelist 支持工作流
  级覆盖,节点按需下载(进程互斥锁防并发重复下载 238MB)
- sdB_cno Teff 加密至 5000K 步长,432 → 9216 点;tlusty/synspec 静态二进制更新

统计与部署:
- grid 汇总改按 tlusty_status/synspec_status 分项计数,新增 tlusty_failed/
  synspec_failed/synspec_pending,前端详情页双视图适配
- deploy/fetch_results 支持跳板机 ProxyJump 与 SSH 主连接复用,fetch 新增 --force;
- Docker 构建支持 CARGO_MIRROR/USE_MIRRORS 国内镜像参数;移除 tools/ 拷贝
- 新增 tlusty-synspec-test skill 与 6 篇根因分析/验证文档
2026-08-17 23:55:26 +08:00

202 lines
11 KiB
YAML
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.
# 6 维 CNO NLTE 热亚矮星网格的配置文件。
# 所有丰度均为 log10(nX/nH).5 文件中的 abn 字段设为 10**logX。
#
# 网格各维范围:
# Teff : 20000 - 80000 K
# logg : 5.0 - 6.5
# logHe: -4 - 2 He/H 数密度比:1e-4 .. 100
# logC : -4 - -1 C/H1e-4 .. 0.1;太阳 C/H≈-3.6,落在区间内)
# logN : -4 - -1 N/H:太阳 N/H≈-4.2
# logO : -4 - -1 O/H:太阳 O/H≈-3.3
# CNO 范围已修正为物理上的 sdB 范围,不再是超太阳(旧版 -2..1 会发散)
# ---- 网格轴:显式列出各维采样点 ----
# grid:
# teff: [20000, 60000]
# logg: [5.0]
# loghe: [-2]
# logc: [-4]
# logn: [-4]
# logo: [-4]
grid:
teff: [20000, 25000, 30000, 35000, 40000, 45000, 50000, 55000, 60000]
logg: [5.0, 5.5, 6.0, 6.5]
loghe: [-4, -2, 0, 2]
logc: [-4, -3, -2, -1]
logn: [-4, -3, -2, -1]
logo: [-4, -3, -2, -1]
# 共 9*4*4*4*4*4 = 9216 个点
# ---- TLUSTY 输入文件全局参数(.5 + nst 的非阶段差异部分)----
# 与 .5 文件 + nst 文件全字段一一对应(见 config.rs 的 Dot5Input / NstInput)。
# gridteff/logg/丰度)和 tlusty_chainlte/ltgray/ilvlin 等)在运行时覆写对应字段。
# 删掉本块 → 走 TlustyInput::default()(与下方声明完全等价)。
tlusty_input:
# .5 文件配置(tlusty208.f:178-450 的 READ(IBUFF,*) 顺序)
dot5:
# 行1 几何(grid 覆写 teff/loggtype=stellar 恒星大气,disk 吸积盘)
geometry: {type: stellar, teff: 35000.0, logg: 5.5}
# 行2 LTE/LTGRAYchain 覆写)
lte: false
ltgray: false
# 行3 nst 文件名(空串=不读 nst)
finstd: "nst"
# 行4 NFREAD 连续频率网格点数(>0 从预设表读)
nfread: 2000
# 行5 IABSET 丰度集选择(不列出=默认 01=abun1 表,2=abun0 表)
# iabset: null
# 行5+ atoms 块(grid 覆写 He/C/N/O 的 abn;列出哪些行就渲染哪些元素)
# mode: 2=显式统计平衡(H/He/CNO), 0=不参与(Li/Be/B); abn=grid 注入或 "0." 太阳默认
atoms:
- {iat: 1, mode: 2, abn: "0.", modpf: 0} # H
- {iat: 2, mode: 2, modpf: 0} # He (abn 由 grid)
- {iat: 3, mode: 0, abn: "0.", modpf: 0} # Li
- {iat: 4, mode: 0, abn: "0.", modpf: 0} # Be
- {iat: 5, mode: 0, abn: "0.", modpf: 0} # B
- {iat: 6, mode: 2, modpf: 0} # C (abn 由 grid)
- {iat: 7, mode: 2, modpf: 0} # N (abn 由 grid)
- {iat: 8, mode: 2, modpf: 0} # O (abn 由 grid)
# ions 块(chain 覆写每行 ilvlin;列出哪些行就渲染哪些元素)
# 显式列出完整 22 行表(H/He/C/N/O)。如需去掉某元素,删对应 iat 行即可;
# 如需加 Fe 等,追加对应行。nonstd≠0 时配 nonstd_extra 附加行(ODF/NONSTD)。
# 注:ilvlin 由 tlusty_chain 的各阶段注入(nlevs==1 裸核强制 0),此处不列。
ions:
# H (iat=1)
- {iat: 1, iz: 0, nlevs: 9, nonstd: 0, typion: " H 1", filei: "data/h1.dat"}
- {iat: 1, iz: 1, nlevs: 1, nonstd: 0, typion: " H 2", filei: " "}
# He (iat=2)
- {iat: 2, iz: 0, nlevs: 14, nonstd: 0, typion: "He 1", filei: "data/he1.dat"}
- {iat: 2, iz: 1, nlevs: 14, nonstd: 0, typion: "He 2", filei: "data/he2.dat"}
- {iat: 2, iz: 2, nlevs: 1, nonstd: 0, typion: "He 3", filei: " "}
# C (iat=6)
- {iat: 6, iz: 0, nlevs: 40, nonstd: 0, typion: " C 1", filei: "data/c1.dat"}
- {iat: 6, iz: 1, nlevs: 22, nonstd: 0, typion: " C 2", filei: "data/c2.dat"}
- {iat: 6, iz: 2, nlevs: 46, nonstd: 0, typion: " C 3", filei: "data/c3_34+12lev.dat"}
- {iat: 6, iz: 3, nlevs: 25, nonstd: 0, typion: " C 4", filei: "data/c4.dat"}
- {iat: 6, iz: 4, nlevs: 1, nonstd: 0, typion: " C 5", filei: " "}
# N (iat=7)
- {iat: 7, iz: 0, nlevs: 34, nonstd: 0, typion: " N 1", filei: "data/n1.dat"}
- {iat: 7, iz: 1, nlevs: 42, nonstd: 0, typion: " N 2", filei: "data/n2_32+10lev.dat"}
- {iat: 7, iz: 2, nlevs: 32, nonstd: 0, typion: " N 3", filei: "data/n3.dat"}
- {iat: 7, iz: 3, nlevs: 48, nonstd: 0, typion: " N 4", filei: "data/n4_34+14lev.dat"}
- {iat: 7, iz: 4, nlevs: 16, nonstd: 0, typion: " N 5", filei: "data/n5.dat"}
- {iat: 7, iz: 5, nlevs: 1, nonstd: 0, typion: " N 6", filei: " "}
# O (iat=8)
- {iat: 8, iz: 0, nlevs: 33, nonstd: 0, typion: " O 1", filei: "data/o1_23+10lev.dat"}
- {iat: 8, iz: 1, nlevs: 48, nonstd: 0, typion: " O 2", filei: "data/o2_36+12lev.dat"}
- {iat: 8, iz: 2, nlevs: 41, nonstd: 0, typion: " O 3", filei: "data/o3_28+13lev.dat"}
- {iat: 8, iz: 3, nlevs: 39, nonstd: 0, typion: " O 4", filei: "data/o4.dat"}
- {iat: 8, iz: 4, nlevs: 6, nonstd: 0, typion: " O 5", filei: "data/o5.dat"}
- {iat: 8, iz: 5, nlevs: 1, nonstd: 0, typion: " O 6", filei: " "}
# CHANGE 块(ICHANG<0 时每能级行;不列出 = 无)
change: null
# nst 高频关键字(236 个中物理相关的,按用途分组)
# 默认值为 sdB 调优值(非 TLUSTY 原始默认)。ChainStep 的 niter/chmax 等阶段级覆盖。
nst:
depth: {nd: 50, nmu: 3, nlambd: 3, isplin: 0}
frequency: {ispodf: 1, ddnu: 50.0, cnu1: 6.0, cnu2: 3.0, nftail: 21, dftail: 0.25,
frcmax: 0.0, frcmin: 0.0, frlmax: 0.0, frlmin: 0.0}
physics: {vtb: 2.0, hmix0: -1.0, mltype: 1, ipturb: 1, ielcor: -1, ibfint: 1, ihecor: 0}
radiative_transfer: {irte: 0, ibc: 3, ifryb: 0, ioptab: 0, ifmol: 0}
nlte: {ifali: 5, ifpopr: 4, jali: 1}
irradiation: {trad: 0.0, wdil: 0.0}
temperature: {tfloor: 8000.0, tdisk: 0.0, tmolim: 9000.0}
# nst 冷门关键字逃逸口(诊断打印 IPR*/内部开关 IOP* 等 ~200 个)
# 示例(当前未启用):
# nst_extra_keys:
# - [CUTBAL, "0.3"]
# - [NDGREY, "20"]
nst_extra_keys: []
# ---- 收敛链 ----
# 参与计算的元素集 / 电离态 **不再由链配置(metals)控制**,而是在上方
# tlusty_input.dot5.atoms8 元素)与 dot5.ions(22 行)中显式声明;此处每个
# step 只控制阶段参数(lte/ltgray/ilvlin/niter/chmax 等)。
# 已验证的三步配方 (tests/sdB_spectra/GUIDE.md 实测, Teff=35000 logg=5.5):
# LTE grey (T T, NITER=0) -> NLTE 连续谱 (nc, ilvlin=0) -> NLTE 谱线 (nl, ilvlin=100)
# nc 步是关键:在不考虑谱线扰动下收敛 NLTE 电离平衡,给 nl 一个稳定种子。
# 跳过 ncgrey -> 完整 NLTE)会发散。
#
# 各 step 的隐式默认值在此显式写出(与代码兜底等价,见下):
# - chmax: 0.001 —— 收敛阈值(runner.rs 兜底默认;缺省时与原兜底完全一致)
# - itek / ichang / idlte / iacc / orelax 留空 → 用 tlusty 内部默认(未结构化为可写值)。
# 注意:设 CHMAX=0.1 会让 nc 提前停止,给 nl 一个坏种子导致发散——勿调大。
#
# nc 的 NITER=10 是实测最优(tests/sdB_spectra/GUIDE.md NITER 扫描结论):
# - NITER=10 总耗时 12.4min35000K CNO 完整模型)
# - 光谱精度 vs NITER=50 差异仅 6e-6(完全等价)
# - NITER=50 浪费 2.2× 时间,NITER=200/500 更浪费且无收益
# 物理上 nc(纯连续谱)缺少谱线约束,外层温度永不真正收敛——追求高 NITER
# 没意义。nl(含谱线)会自修正到正确解(流量差异 <3e-12)。
tlusty_chain:
- {label: lte, lte: T, ltgray: T, ilvlin: 0, require_converged: false, niter: 0, chmax: 0.001}
- {label: nc, lte: F, ltgray: F, ilvlin: 0, require_converged: false, niter: 10, chmax: 0.001}
# nl 步加 orelax=0.5:谱线(ilvlin=100)扰动大,欠松弛阻尼 Newton 步长振荡,
# 避免中温区(20-45kK) nl 阶段 relc 振荡发散(实测验证)。
- {label: nl, lte: F, ltgray: F, ilvlin: 100, require_converged: true, niter: 100, chmax: 0.001, orelax: 0.5}
# 种子热启动链(seed_step 策略用,cold_run 失败后回退)。
# seed_nc 从已收敛邻居热启动,起点扰动小,用更激进的 orelax=0.3;
# nl 与 cold_run 链一致 orelax=0.5。空时 executor 回退 default_seed_chain()(代码内置同值)。
seed_chain:
- {label: seed_nc, lte: F, ltgray: F, ilvlin: 0, require_converged: false, niter: 20, chmax: 0.001, orelax: 0.3}
- {label: nl, lte: F, ltgray: F, ilvlin: 100, require_converged: true, niter: 100, chmax: 0.001, orelax: 0.5}
# ---- 光谱合成 SYNSPEC 输入参数(fort.55 控制卡,9 行子结构体)----
# 启用开关见下方 synspec_stage 块。
#
# fort.55 字段与 synspec54.f 的 READ(55,*) 语句逐行一一对应,字段名严格使用
# SYNSPEC 源码变量名。各行含义见 crates/common/src/config.rs 的 Fort55Line* 文档注释。
# 仅列出与默认值不同的字段;未列出的字段走 SynspecInput::default()(见 config.rs)。
#
# 重要修复:
# - line1.idstd 从旧实现的 50(错位 bug,强制最深层)修正为 0(自动取 2*ND/3≈33,
# τ≈1 参考层)。此变更影响光谱线强归一化,修正后所有光谱需重算(见 §5)。
# - 新增 line_mol(分子表行):SYNSPEC 在 IMODE∈[-3,1] 时会额外读这一行,旧实现漏生成
# 导致 VTB 行被吞、vturb 被错误覆盖。现默认 nmlist=0(无分子线)。
# - line_vtb 默认 -1.0(不覆盖大气 vturb=2 km/s);如需自定义湍流速度设非负值。
synspec_input:
line1: {imode: 0, idstd: 0, iprin: 1} # 行1: IMODE, IDSTD(=0 自动 2ND/3), IPRIN
# line2-line5 走默认(INMOD=1 TLUSTY 模型 / IOPHLI 被 SYNSPEC 强制 0 / IFREQ=1 INLTE=1 / Stark 表全 0
line6:
alam0: 3000.0 # 光谱波长起始点 (Å)
alast: 7000.0 # 光谱波长终止点 (Å)
cutoff0: 10 # 谱线截止距离(推荐 5-10
cutoffs: 0 # 连续谱间距(0→内部取 3
relop: 0.0001 # 线心/连续不透明度最小比
space: 0.01 # 相邻频率点最大间距 (Å)
# line_mol (nmlist=0 无分子表) / line_vtb (vtb=-1 不覆盖大气 vturb) / line_ang (NMU0=0 不算比强度) 走默认
# ====================================================================
# 阶段独立配置(见 docs/task_engine_decoupling_design.md §2-§3
#
# TLUSTY / SYNSPEC 视为正交独立阶段,每阶段三维:
# enabled : 是否执行该阶段
# policy : skip_converged(增量) | force_recompute(强制重算) | skip_failed(忽略失败)
# strategies : 策略链队列,按回退优先级排序;节点执行 strategies[0],失败后服务端弹出首项
#
# 此处显式声明与旧 seed_step_fallback/synspec 块等价的默认配置,便于前端面板编辑。
# 旧字段(seed_step_fallback / synspec)保留作回退兜底,resolve 方法优先用本块。
# ====================================================================
tlusty_stage:
enabled: true
policy: skip_converged
strategies: [cold_run, seed_step]
# ---- 种子步进回退(旧字段,保留兼容;新配置见下方 tlusty_stage 块)----
# 冷启动失败时,自动用已收敛的邻居模型作种子,用 LTGRAY=F 热启动重试。
# 这是高温 He-poor / 富金属区收敛的关键(见 EXPERIENCE.md §5Y)。
# 失败的冷启动结果会备份到 <model>.coldfail/ 目录。
seed_step_fallback: true
synspec_stage:
enabled: true
policy: skip_converged
strategies: [standard]
# ---- 执行参数 ----
timeout_sec: 7200 # 单模型墙钟时间上限(120分钟)