# 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/H:1e-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, 30000, 40000, 50000, 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] # 共 4*2*2*3*3*3 = 432 个点 # ---- TLUSTY 输入文件全局参数(.5 + nst 的非阶段差异部分)---- # 与 .5 文件 + nst 文件全字段一一对应(见 config.rs 的 Dot5Input / NstInput)。 # grid(teff/logg/丰度)和 tlusty_chain(lte/ltgray/ilvlin 等)在运行时覆写对应字段。 # 删掉本块 → 走 TlustyInput::default()(与下方声明完全等价)。 tlusty_input: # .5 文件配置(tlusty208.f:178-450 的 READ(IBUFF,*) 顺序) dot5: # 行1 几何(grid 覆写 teff/logg;type=stellar 恒星大气,disk 吸积盘) geometry: {type: stellar, teff: 35000.0, logg: 5.5} # 行2 LTE/LTGRAY(chain 覆写) lte: false ltgray: false # 行3 nst 文件名(空串=不读 nst) finstd: "nst" # 行4 NFREAD 连续频率网格点数(>0 从预设表读) nfread: 2000 # 行5 IABSET 丰度集选择(不列出=默认 0;1=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.atoms(8 元素)与 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 一个稳定种子。 # 跳过 nc(grey -> 完整 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.4min(35000K 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)。 # 失败的冷启动结果会备份到 .coldfail/ 目录。 seed_step_fallback: true synspec_stage: enabled: true policy: skip_converged strategies: [standard] # ---- 执行参数 ---- timeout_sec: 7200 # 单模型墙钟时间上限(120分钟)