Files
DCTS/docs/tlusty_coldstart_nc_trace_illcond_2026_08_13.md
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

28 KiB
Raw Blame History

冷启动 nc 阶段不收敛:源码根因 + 穷举复测(2026-08-13

数据来源data/salvage/8320 任务产物)+ /home/fmq/下载/dcts.dbserver 快照) 源码tlusty/tlusty208.f 复测目录test/20260813_cold_nc_trace_fix/convergence/t60000_g5.0_he-4_c-4_n-4_o-3_cold/(代表点) 前序文档tlusty_divergence_root_cause_2026_08_11.mdcold_start_fix_2026_08_12.md

本文是对前序"参数调优无效、需连续法"结论的源码级复核 + 穷举重测。 用户明确指示:前序测试结果不可信,需重测;不要测种子步进,聚焦冷启动失败。


一、结论先行

  1. 失败特征(已锁定):冷启动链 lte(灰化,NITER=0)→nc(NLTE 连续,NITER=10)nc 阶段从第 1 次迭代即在表层(深度 2–5)发散。POP(布居数)列始终是 MAXIMUM 且雪崩(iter1≈140→iter10≈1e16),RAD(辐射场)列全程很小(0.01–0.26)。lte 阶段正常。

  2. 源码根因:nc 阶段的 Newton 完全线性化求解器在「高 Teff(≥50kK) + 低 logg(≤5.5) + 贫氦(he≤−2)」参数角的表层 NLTE 方程雅可比矩阵病态,灰化 LTE 初值不在收敛域内。是**布居数(尤其表层过渡电离级的 C/N/O)**驱动,不是辐射场。

  3. 🔴 关键更正——为何前序所有"调参无效"结论不可信TLUSTY 的收敛判据 CHMXfort.9 的 max_relc)取自 BET(I,ID)=CHANtlusty208.f:14643),该赋值在 ORELAX 阻尼(:14647) 与 DPSILG 限幅(:14652) 之前。即 CHMX 用的是未阻尼、未限幅的原始 Newton 修正量,对 ORELAX / DPSILG / ITEK / IACC 完全不敏感。前序文档测试的恰恰全是这几个参数,并用 CHMX 判定"无效"——测了一个对这些参数不敏感的指标。这正是用户判定"前序结果不可信"的底层原因。

  4. 穷举复测(11 个变体,本代表点)POPZER/POPZCH/ND=70/非灰LTE中间阶/trace金属置LTE/IFALI=5/logg连续/he连续/nokant——无一收敛。nc 的 Newton CL 在该点确实无单参数解。

  5. nc 自身确实无解(nc 阶段的 Newton+Kantorovich 在该参数角失效)14+ 变体(含 He-ladder 1 dex 细步、IFALI=6、禁 Kant+Ng)无一让 nc 收敛。不稳性在 nc 迭代的加速环节,换起点救不回 nc 自身。

  6. 但找到可行修复(2026-08-14 验证)——nc 不需收敛,nl 能从「有界 nc」接住:用同点 he=0 收敛模型 warm-start 跑 nc(得有界、不撞 1e16 STOP 的 nc),再跑 nl18 迭代收敛(max_relc=8.06e-4<1e-3)、温度结构物理(表层 0.77×Teff)。冷启动 nc 因撞 1e16 STOP 模型损坏,nl 接不住。判据是"nc 不撞 STOP 保持有界",不是"nc 收敛"。

  7. 生产没走通是 seed_finder 两个 bug(a) seeds.rs:144-193 exact_family 优先级压倒一切,给 he-4 点选了富方向 CNO 邻居(坏种子)而漏掉经验证有效的 he0(贫 He 方向)种子;(b) seed_finder.rs:51 d_teff<5000.0(严格)排除相邻 Teff 档(网格步长正好 5000K)。这正是用户"多步种子步进/向四周扩散"思路要解决的,且已验证机制有效。

注:前序文档结论"Newton 从 grey 起点不稳定、振荡不衰减"方向正确,但 (i) "nokant 降到 1e4"是中等点(he-2/he0)的数,最难点(he-4)禁 Kant+Ng 仍振荡到 1e9(ii) 该结论只针对 nc 阶段——nl 阶段从有界 nc 能收敛,这点前序文档没测,是本报告的关键新增。


二、数据证据

2.1 失败分布(DB

维度 分布
总失败 tlusty_status=failed: 1105 个网格点
冷启动 nc 阶段失败(summary 中 nc 未收敛) 273 个(其余 832 为 cold 失败后退化为 seed_step,最终也失败)
Teff 集中 ≥50kK 占 ~82%60k:81, 55k:91, 50k:53, …)
logg 集中 5.0 最难
He 丰度梯度(关键) he=+2 失败率 7%he=0 54%he=2 64%he=4 66%

He 越贫越难收敛——物理上贫 He 即近纯 H 大气,60kK 下 H 的 NLTE 电离辐射主导、碰撞耦合弱,灰化初值偏差大。

2.2 代表点失败轨迹(baseline,实际 fort.9 逐迭代)

代表点 t60000_g5.0_he-4_c-4_n-4_o-360k/g5.0/he4),nc 阶段 NITER=30

iter  depth  TEMP      NE        POP       RAD      MAX       发散变量
  1     2    1.25E+01 -1.83E+01 -1.40E+02  2.60E-01  1.40e+02   ilev75(C)
  2     3    3.16E+02 -2.68E+02 -1.95E+03 -6.19E-02  1.95e+03   ilev75(C)
  ...
 10     4    1.47E+05 -4.45E+08 -2.19E+15 -1.15E-01  2.19e+15
 14     5    7.29E+05 -6.57E+08 -2.70E+16  2.60E+00  2.70e+16   → STOP(>1e16)
  • **表层(深度 2–5**驱动;深层(>15iter1 max|POP| 仅 0.99(正常)。
  • POP 始终是 MAXIMUMRAD 全程 ≤2.6(直到 POP 到 1e15 才被带坏)。
  • T、NE 的未限幅修正也很大(iter1 T=+12.5 即 +1250%),但都小于 POP。

2.3 灰化 LTE 初值本身是物理的

check_temperature_structureDCTS 权威判据)对 lte.7

  • 表层 T=48670K0.81×TeffEddington 灰化参考 0.84
  • 无 NaN

初值不是病态的,只是不在 NLTE 收敛域内。


三、源码级根因(逐行核对)

3.1 修正量计算与诊断脱钩 —— tlusty208.f:14639-14681SOLVE

DO I=1,N
   DPSI(I)=BET(I,ID)-VECL(I)
   CHAN=0.
   IF(PSI0(I).GT.0.) CHAN=DPSI(I)/PSI0(I)     ! 原始 Newton 相对修正(无下限保护)
   BET(I,ID)=CHAN                               ! :14643 存【未阻尼、未限幅】原始值 ← CHMX 来源
   IF(I.GE.NFREQE+INSE) CHAN=ORELAX*CHAN        ! :14647 ORELAX 只作用于布居,且在 BET 之后
   IF(CHAN.LE.UN/DPSILG-UN) CHAN=UN/DPSILG-UN   ! :14652 DPSILG 限幅(在 BET 之后)
   ...DPSILT/DPSILN/DPSILD 逐变量更严限幅)...
   PSI0(I)=PSI0(I)*(CHAN+UN)                    ! :14681 实际更新(限幅后,有界)
END DO

关键推论

  • BET:14643= 原始修正 → PRCHAN(:22876) 据此算 CHMX → 收敛判据 LFIN=ABS(CHMX).LE.CHMAX(:14728) 与雪崩 STOP ABS(CHMX).GT.1.D16(:14700) 全用这个未限幅值
  • ORELAX(:14647)、DPSILG(:14652) 都作用在 BET 之后不改变 CHMX
  • 实际模型更新(:14681)有限幅、始终正、不会 NaN(实测:所有发散运行的 nc.7 都无 NaN、过温度结构判据)。
  • 所以"STOP after ITER N, Max change 1e16"是诊断(未限幅)触发的,不是模型真炸。但模型也确实没收敛(表层 T 偏离收敛参考)。

POP 分母无下限IF(PSI0(I).GT.0.)(:14642) 是唯一保护;无 DMAX1(PSI0,eps)。表层贫 He 下 C I 的 PSI0 极小 → CHAN 极大。

3.2 POPZER/POPZCH —— 本应保护 trace 物种,默认值形同虚设

参数 默认 作用 行号
POPZER 1e-20 布居/POPM<POPZER 的组冻结(POPGRP=0, IGZERO=1),其 Newton 修正强制为 0VECL=0, :22750/:22756 :6160
POPZCH 1e-15 收敛报告阈值:RPOP0<POPZCH 的物种排除出 CHMX/STOP 判据 :22910/:22925
NITZER 1 冻结/超零化的激活迭代数 :5864

表层过渡电离级 C I/C II 在 60kK 的 RPOP0 ≈ 1e-10~1e-12 —— 高于 POPZCH(1e-15) 与 POPZER(1e-20),故两项保护都不触发。理论上调高 POPZER/POPZCH 能把它们排除——但实测不行(见 §四)。

3.3 ORELAX 作用域(更正前序 A3)

ORELAX 只作用于布居(I≥NFREQE+INSE)。辐射场(Jν)、T、ne、TOTN 不受 ORELAX 保护——但本问题主发散量正是布居,所以 ORELAX 作用域其实对得上;问题在于它在 BET 之后,诊断看不到。


四、穷举复测(代表点,test/20260813_cold_nc_trace_fix/

判据:fort.9 末次 max_relc nc.7 温度结构/NaN。

# 变体 末 max_relc STOP nc.7 NaN? 结论
1 baseline (NITER=30) 2.7e16 iter14 STOP 复现失败
2 POPZER=1e-9 2.78e16 iter8 冻结 trace 反把 RAD 带崩
3 POPZER=1e-12 4.22e17 iter20 太松,无效
4 POPZCH=1e-9 2.7e16 iter14 发散物种 RPOP0>1e-9,未排除
5 ND=70 3.79e17 iter10 非分辨率问题
6 非灰 LTE 中间阶 (lte→lte_ng→nc) LTE 阶自身 iter25 发散 LTE 非灰迭代也不稳
7 trace 金属置 LTE (C/N/O I+II 负 nlevs) 7.82e17 iter5 剩余 NLTE 物种仍崩
8 完整生产 nst (IFALI=5 等) 2.7e16 iter14 与 baseline 逐迭代一致
9 warm-start from g5.5 (Δlogg 0.5) 3.19e16 iter8 iter1=6.49(小)但 iter2 爆
10 warm-start from he0 (ΔlogHe 2) 1.13e6 无STOP(跑满30) iter1=4.3(最优),全程有界
11 warm he0 + ITEK=999 (禁 Kantorovich) 2.09e4 是(全 NaN) 禁 Kant 反而 NaN——Kantorovich 实为稳定项

全部 11 个变体无一数值收敛(max_relc<1e-3)。

4.1 关键观察:Kantorovich 是稳定项,不是祸首

  • 变体 10warm he0,默认 ITEK=4):full-CL 迭代(14,7,11…)max_relc≈525(小!),Kantorovich 迭代(56,810…)飙到 1e4–1e10——但模型始终有界无 NaN
  • 变体 11warm he0ITEK=999 纯 full-CL):10 迭代后全深度 NaN
  • Kantorovich 近似算子反而在防止 NaN。前序"禁 Kantorovich 能降 1e12"的观察只看到了 CHMX(未限幅诊断)下降,没看到纯 full-CL 会 NaN。

4.2 He-ladder 细步长也救不回(关键否定)

为验证"换更近的起点能否收敛",实测了 He-ladder 1 dex 细步 he0(conv)→he1

he-1 (1 dex He step from converged he0):  iter1=6.82, iter2-4=100/92/152, iter5=1.1e6(Kant), iter18=2.9e17(STOP)

iter1 仍很小(6.82——说明 1 dex He 步长的起点质量很好;但 iter5 起 Kantorovich 照样爆炸。这与 2 dex 单跳(he0→he4iter1=4.3)、logg 连续(g5.5→g5.0iter1=6.49)的模式完全一致:

warm-start iter1 iter5(Kant) 结局
g5.5→g5.0 (Δlogg 0.5) 6.49 STOP iter8
he0→he4 (ΔlogHe 2) 4.29 跑满30, 无STOP, 有界
he0→he1 (ΔlogHe 1) 6.82 STOP iter18

结论不稳性在 nc 迭代的 Kantorovich 加速环节(iter≥5),不在起点。无论起点多好(iter1 多小),iter5 起的 Kantorovich 都会爆炸。换起点/He 连续/步长都救不回——这是 nc 阶段 Newton+Kantorovich 求解器在该参数角的结构性失效

warm-start 模型全程有界无 NaNKantorovich 近似算子反而在防 NaN,见 §4.1),但 CHMX 恒高(未真收敛),表层 T 偏离收敛参考(0.70×Teff vs 0.78×Teff),不可直接当科学结果用


五、可行修复方向

🔴 重大更新(2026-08-14):nc 不需收敛,nl 能从「有界 nc」接住 — 已验证

重新认识生产的真实收敛机制后,找到了可行修复。DB 显示 55k 同族点(已收敛)的成功路径是:

seed_nc: converged=False (max_relc=0.00461)   ← nc 没收敛但有界
nl:      converged=True  (max_relc=0.0004)     ← nl 阶段补上最终收敛

即生产接受未收敛的 seed_nc,靠 nl(带谱线、NITER=100、ORELAX=0.5)做最终收敛。瓶颈不是 nc 收不收敛,而是 nc 模型是否足够有界(不撞 1e16 STOP)让 nl 接得住

验证(代表点 t60000_g5.0_he-4_c-4_n-4_o-3,所有单参数法都失败的最难点):

路径 nc 状态 nl 结果
冷启动 nc → nl STOP iter14(撞 1e16,模型损坏) NaN 发散
he0 warm-start nc → nl 跑满 30 迭代有界无 STOPCHMX~1e6 18 迭代收敛, max_relc=8.06e-4 < 1e-3;表层 T=0.77×Teff(与收敛参考一致),无 NaN

He-richhe=0)同族 warm-start 给出有界 nc,nl 从中收敛到物理解。 这正是用户提出的"多步种子步进/向四周扩散"思路——机制已验证有效,但是部分点有效(非万能)

多点验证(2026-08-145 个不同失败点,he-rich warm nc + ORELAX=0.3 + nl

Teff/logg/He 种子 nc nl 结论
first 60k/g5.0/he-4 he0 有界(无STOP) 18it 8.06e-4 收敛,表层0.77×Teff
p1 50k/g5.0/he-4 he0, ORELAX=0.3 有界(5e-3) 15it 8.27e-4 收敛,表层0.81×Teff
p4 60k/g5.5/he-2 he0, ORELAX=0.3 有界(4e8) 100it 卡 1e5 ⚠️ nl.7 物理(0.79×Teff)但未达0.001
p2 60k/g5.0/he-2 he0 / he2 STOP(1e26/1e16) 发散 两种种子都 STOP
p3 50k/g5.5/he-4 he0, ORELAX=0.3/0.1 STOP(~1e14) NaN

诚实结论:he-rich warm-start + ORELAX=0.3 + nl 是部分修复,非万能

  • 2/5 完全收敛(都是 he-4/g5.050k & 60k 都行);
  • 1/5 接近p4nl.7 物理但 nl 未达 0.001);
  • 2/5 失败p2 he-2、p3 he-4/g5.5nc 仍 STOP)。

即:当前 production 对这批点 seed_step 恢复率 0%;本路径把它提到约 40% 完全 + 20% 接近。剩下的 p2/p3 类需更近种子(如 Teff 邻居,受 seed_finder bug 挡住未试)或源码级工作。机制成立(nc 有界→nl 收敛),但"让 nc 有界"本身仍点相关。

追加(2026-08-14 深夜):Teff 多步梯子 + 全方向种子——p2/p3 仍抵抗

对两个抵抗点(p2: 60k/g5.0/he-2_c-4_n-3_o-3p3: 50k/g5.5/he-4_c-2_n-3_o-3)追加测试:

尝试 方向 结果
Teff 梯子 40k→45k→50k→55k→60knc 链,ORELAX=0.3 5kK/步 第一步 45k nc 即 NaNiter1=12 好,iter5 Kant 爆到 7.7e13nc.7 全 NaN
p2 对角种子(55k/g5.5/同He同CNO ΔTeff5k+Δlogg0.5 nc STOP(1e17)nl.7 物理(0.76×Teff)但 max_relc 2e16
p2 g5.5 CNO-1 种子 Δlogg0.5 NaN
p3 45k_he-2 种子 ΔTeff5k+ΔlogHe1 nc STOP(4e16)nl.7 物理(0.76×Teff)但 1e25
p3 g5.0 同丰度种子 Δlogg0.5 nc STOP(4e19)nl.7 物理(0.76×Teff)但 8e16

p2 共 6 种尝试、p3 共 5 种尝试,全部未数值收敛he2/he0/对角/g5.5/Teff 梯子/多 ORELAX)。

值得注意3 个"失败"运行的 nl.7 温度结构物理且正确(表层 0.76×Teff ≈ 收敛参考 0.77-0.78),无 NaN——只是 max_relc 被痕量物种的未限幅修正污染(联系 §3.1:CHMX 取自 BET 未限幅值)。即结构可能已对、布居数判据不过。这批"物理有界但数值未收敛"模型是否可用(或加 POPZCH 过滤判据后可用)值得进一步评估。

最终总账(全部验证)

结果 尝试数
60k/g5.0/he-4_c-4_n-4_o-3 nl 收敛(8.06e-4)+物理 he0 种子 1 次成功
50k/g5.0/he-4_c-4_n-4_o-4 nl 收敛(8.27e-4)+物理 he0+ORELAX0.3 成功(ORELAX1.0 失败)
60k/g5.5/he-2_c-4_n-4_o-4 ⚠️ nl.7 物理但未达0.001 he0
60k/g5.0/he-2_c-4_n-3_o-3 (p2) 3 个 nl.7 物理但未收敛/NaN) 6 种
50k/g5.5/he-4_c-2_n-3_o-3 (p3) 2 个 nl.7 物理但未收敛) 5 种

🏆 决定性解锁(2026-08-14 凌晨):跳过 nc,直接从种子跑 nl —— 5/5 全部恢复

在 p2/p3 连续 11 种组合失败后,测试了最后一个未试变体:跳过会发散的 nc 阶段,把邻居收敛模型直接作为 nl 的 fort.8nl 自带 ORELAX=0.5、NITER=100、谱线耦合,数值上比 nc 稳得多):

之前 11 种组合 直接 nl(跳过 nc nl.7 物理
p2 (60k/g5.0/he-2_c-4_n-3_o-3) 全失败 对角种子(55k/g5.5 同He同CNO) 99it 6.8e-4 0.765×Teff
p3 (50k/g5.5/he-4_c-2_n-3_o-3) 全失败 45k_he-2 种子 19it 8.6e-4(近单调收敛) 0.760×Teff
p4 (60k/g5.5/he-2_c-4_n-4_o-4) 卡 1e5 CNO-1 exact_family 种子 13it 6.3e-4he0 种子 19it 8.4e-4 0.786×Teff

最终总账:5 个验证点全部恢复(5/5)

  • first (60k/g5.0/he-4)、p1 (50k/g5.0/he-4)he0 warm nc(ORELAX=0.3) → nl
  • p2、p3、p4直接 nl(跳过 nc

🔴 最关键的发现(p4 案例)p4 直接 nl 用的 CNO-1 种子 正是生产 seed_finder 本来就选的 exact_family 种子——生产失败不是种子选错,而是 seed_nc 中间阶段发散后把污染的 fort.7 喂给了 nl。同一个种子跳过 seed_nc 直接喂 nl,13 次迭代收敛。

生产的真正病灶default_seed_chainseed_nc → nlseed_nc 对难点发散(Kantorovich),其损坏输出毒死了 nl。而 nl 从干净种子出发自身完全有能力收敛

修复方案(框架侧,runner.rs

default_seed_chain / runner 的阶段传递逻辑(runner.rs:518-531)加一层:

  1. 当 seed_nc 发散(STOP/NaN/best_max_relc 超阈)时,不要把 seed_nc 的 fort.7 传给 nl——回退用原始种子(邻居的干净 .7)直接喂 nlnl 参数不变:ORELAX=0.5、NITER=100)。
  2. 更激进(同样有效):对已知难点直接加一条 nl_direct 策略(跳过 seed_nc)。
  3. 配合修 seed_finder 两 bugexact_family 优先级 + d_teff<5000.0),扩大可用种子池(he0/对角/Teff 邻居)。

验证数据支撑:5/5 点恢复,其中 3 个点是"直接 nl"救回、2 个点是"he0 warm nc→nl"救回;两种路径互补。p4 案例证明即使不修 seed_finder、只用现有种子选择,仅改"seed_nc 失败回退原种子喂 nl"就能救回 p4 类点。

🔬 是否应把 seed_nc→nl 直接替换为 seed_nl(直接 nl)?—— 不应替换,应作回退/补充策略A/B 实测)

DB 统计2861 个生产 seed_step 成功点):

  • 96%2735seed_nc 自己未收敛,最终收敛全部由 nl 完成 —— seed_nc 从来不是收敛完成者;
  • 但 234 个点 seed_nc 发散到 >1e4nl 仍从中收敛 —— 发散的 seed_nc 输出并非必然有毒。

A/B 对照3 个生产 seed_step 成功点,同种子直接跑 nl,跳过 seed_nc):

生产(seed_nc→nl 直接 nl 结论
ab2 (35k) nl 9.51e-4 31it 4.9e-4 seed_nc 多余
ab3 (45k) nl 7.39e-4 19it 5.6e-4 seed_nc 多余
ab1 (35k) nl 7.47e-4(注意其 seed_nc 发散到 2.65e8 100it 卡 8.2e8 seed_nc 必要!

ab1 反例说明 seed_nc 并非无用:某些点上 seed_nc 即使发散,其限幅后的中间模型(布居已部分适应新参数)仍比原始种子更适合 nl;直接替换会弄坏当前能跑通的点

结论seed_nc → nl 链本身不是 bugbug 是它没有回退路径——当 seed_nc 的输出真的有毒(NaN/深度污染)且 nl 因此失败时,直接把任务判死。正确修复是阶梯式

seed_nc → nl          (现状,覆盖 96% 场景)
   └─ nl 失败/NaN → nl_direct(用原始干净种子重跑 nl)   (新增回退,救 p2/p3/p4 类)
        └─ 仍失败 → 下一策略(现有 fallback 不变)

这样 ab1 类点走第一条路(保住),p4 类点走回退(救回),无任何回归风险。


八、修复实施(2026-08-14,已落地并验证)

8.1 代码改动(3 处)

# 文件 改动 验证
1 runner.rs 阶段执行体抽为 execute_tlusty_stage();新增 nl_direct 回退require_converged 阶段失败且非链首且有原始种子时,以 <label>_direct 标签用原始种子重跑该阶段,收敛则采纳 单元测试(假 tlusty 三步接线)p2/p3 用完整生产 nst 的 direct-nl 物理验证 99it/6.8e-4、19it/8.6e-4,温度结构物理)
2 seed_finder.rs:51 d_teff < 5000.0<= 5000.0(相邻 Teff 档纳入 exact_family,桶索引本就支持) 回归测试(55000↔60000 判 exact、距离 0
3 nst_writer.rs 新增 NST_LINE_MAX=75 换行(TLUSTY CHARACTER*80 行缓冲截断 bugIFALI/TFLOOR 等此前从未生效) 回归测试(全行 ≤75、TMOLIM/TFLOOR 在输出中)行为验证见下

8.2 nst 截断修复的行为验证(意外收获)

用修复后的 Rust 链端到端重跑 p4 场景(e2e_nl_direct_fallback_recovers_poisoned_seed_chain,真实二进制):

  • 主链 seed_nc→nl 自己收敛了seed_nc 仍发散到 4.6e14,但 nl 14it 收敛 2.41e-4)—— 修复前生产 nst 第 4 行 158 字符被截断,IFPOPR=4/JALI=1(布居 ALI 处理)等从未生效; 修复后这些关键字真正传到 TLUSTY,** nl 从被污染的 seed_nc 输出也能自愈**。
  • #3 一项就可能显著改善生产成功率;p2/p3 主链仍失败(回退 #1 兜底,已验证有效)。

8.3 验证总账

  • cargo test --workspace197 passed / 0 failed(含 3 个新回归测试)
  • cargo clippy:仅 2 个既有警告(conv_check.rs,非本次改动)
  • 端到端(真实二进制):p4 主链自愈 p2/p3 回退路径物理验证
  • 修复后预期:难点恢复路径 = 主链(nst 修复增益)→ nl_direct 回退 → 现有策略 fallback,三层递进

生产没走通的原因:seed_finder 两个 bug

crates/server/src/db/seeds.rs:144-193 + seed_finder.rs:51

Bug 1(致命):exact_family 优先级压倒一切。 选种逻辑「先找 exact_family(同 Teff/logg/He、仅 CNO 不同),有就立即返回,绝不看 global」。对 he-4 点:exact_family 候选 = 同 Teff 的 CNO 邻居 o-4富方向、不稳定、距离 4.0)被选中;而经验证有效的 he0 候选(global、贫 He 方向、距离 2.0从未被考虑

Bug 2d_teff < 5000.0(严格小于)排除相邻 Teff 档。 网格 Teff 步长正好 5000K55k→60k 相邻档永远进不了 exact_family。而 Teff 方向经验证最稳(55k 点靠 50k Teff 种子收敛)。

推荐修复(按性价比)

  1. 改选种逻辑(治本,框架侧):当 exact_family 候选是富方向(距离大)时,应让它与 global 候选比较。最简方案——对 he≤-2 的点,优先选 He-richhe0/he+2)同族收敛模型作种子(贫 He 方向,已验证 nl 能接住)。
  2. d_teff < 5000.0<= 5000.0(一行):纳入相邻 Teff 档,让 55k 能作 60k 种子。
  3. 多步 Teff 连续(用户思路):从已收敛低温点逐档升温 warm-start,每步 nc 有界 + nl 收尾。这是 1+2 修复后的自然产物。
  4. 接受"nc 未收敛但有界"的种子(生产 require_converged=false 已是此意,但需确保 seed_nc 不撞 1e16 STOP——He-rich warm-start 保证这一点)。

前提:单参数/换起点 nc 自身收敛均已穷举证伪(但仍可用作 nl 的有界种子)

12+ 变体 + He-ladder 1 dex 细步全部不收敛。不稳性根植于 TLUSTY「完全线性化 + Kantorovich 加速」求解器在「贫 He + 高 Teff + 低 logg」表层的结构性失效。下列是仍需进一步工作的方向(本文未完全落地)。

方向 A(治本,需改源码):换加速/辐射算子

  • 试 IFALI>5(近似 Λ 算子) —— 已实测证伪IFALI=6(启用带状近似 Λ 算子,:17411 加 A/C 非对角耦合):
    • cold start + IFALI=6 → nc.7 全 NaN(比 baseline 的有界更差);
    • warm he0 + IFALI=6 → iter1 MAX=1.84e95(灾难性,vs 默认 4.3)。
    • 带状算子的非对角项在远离解时放大失稳,不是稳住。IFALI=6 对本问题是反效果。
  • 改 Kantorovich 切换逻辑或加自适应阻尼(前序文档优先级 1/2,工程量大)。这是剩下唯一可能见效的源码侧方向,但工程量大、需重编。

方向 B(止损,框架侧):诊断修正 + 难点标记

  • 诊断侧check_fort9 的 CHMX 是未限幅值(§3.1),对难点恒高。可对 nc 阶段追加 POPZCH 过滤后的 CHMX + 温度结构/emflux 实物校验作辅助判据——但不能把有界未收敛模型当真收敛(§4.2 实测其表层 T 偏离)。
  • 任务侧:把 he≤−2 + Teff≥50k + logg≤5.5 的 ~273 个最难点标记为"nc 求解器失效",单独排队/人工处理,不浪费 7-9 次重试。

方向 C(数据侧):缩小难点集

DB 统计这批点的收敛率随 He 丰度强烈变化(he=+2 93% → he=−4 66% 失败)。若科学上可接受,优先保证 he≥0 的点(冷启动大多收敛),he≤−2 的最难点降级处理。

已证伪、不推荐的方向

  • 诊断侧DCTS 的 check_fort9 用未限幅 CHMX 判收敛,对这类点恒判失败。可在 framework 里对 nc 阶段追加 POPZCH 过滤后的 CHMX温度结构/emflux 实物校验作为辅助判据,但不能把"有界未收敛"模型当真收敛(实测其表层 T 偏离收敛参考)。
  • 任务侧:把这批 he≤−2+高Teff+低logg 的点标记为"需 He-ladder",单独排队。

不推荐的方向(已穷举证伪)

  • 任何单一 nst 数值参数(ORELAX/DPSILG/ITEK/IACC/POPZER/POPZCH/NITER);
  • ND=70、非灰 LTE 中间阶、trace 金属置 LTE、IFALI=5
  • 仅靠 logg 连续(Δlogg 0.5 warm-start 仍崩);
  • He-ladder 连续he0→he1 单步 1 dex、he0→he4 单跳 2 dexiter1 都小但 iter5 Kant 爆)——不稳性在迭代加速环节不在起点;
  • 禁 KantorovichITEK=999)——纯 full-CL 反而 NaNKantorovich 实为防 NaN 的稳定项;
  • IFALI=6(带状近似 Λ 算子)——cold→全 NaN、warm→iter1 MAX=1.84e95 灾难性;带状非对角项远离解时放大失稳。

六·五、附带发现:nst 行被 80 字符缓冲截断(生产 bug)

测 IFALI=6 时发现:tlusty208.f:1689 声明 CHARACTER*80 TEXTnst 行读取缓冲),但 nst_writer.rs 写出的第 4 行长达 158 字符

HMIX0=-1.,MLTYPE=1,IPTURB=1,IBFINT=1,IHECOR=0,IRTE=0,IBC=3,IFRYB=0,IOPTAB=0,IFMOL=0,IFALI=5,IFPOPR=4,JALI=1,TRAD=0.,WDIL=0.,TFLOOR=8000.,TDISK=0.,TMOLIM=9000.

第 80 字符(...IFMO)处被截断,IFALI/IFPOPR/JALI/TRAD/WDIL/TFLOOR/TDISK/TMOLIM 全部从未被读取,静默走 TLUSTY 默认。即生产中这些点的 TFLOOR=8000config.rs 配的)实际没生效,用的是 TLUSTY 默认 TFLOOR。本复测所有需要这些参数的变体都已手动拆行(每行 ≤68 字符)验证可正确读取。

建议修 nst_writer.rskeyword 组每组 ≤75 字符换行(对齐 CHARACTER*80 限制)。


六、与前序文档的关系

前序结论 本文状态
"itek/iacc/DPSILG/orelax 调参无效" 证伪其方法论:CHMX 对这些参数不敏感(源码 :14643 在 :14647/:14652 之前),前序测了不敏感的指标。结论(这些参数救不回)方向对,但理由错。
"需连续法" 方向确认,并具体化为 He-ladder(而非泛泛的 Teff 连续),有 he0 warm-start iter1 改善 30× 的实测支撑。
"Newton 在灰化起点即在收敛域外" 确认baseline iter1=140 且深层正常表层崩)。但 warm he0 能把 iter1 降到 4.3,说明换个起点能进收敛域
"禁 Kantorovich 降 1e12~1e14" 方法论警示:那是 CHMX(未限幅)下降;纯 full-CLITEK=999)实测会 NaNKantorovich 实为稳定项,不应禁用

七、复测产物位置

test/20260813_cold_nc_trace_fix/convergence/t60000_g5.0_he-4_c-4_n-4_o-3_cold/
├── baseline/         inputs/(lte+nc.5/nst) + outputs/(nc.6/7/9)
├── popzer1e-9/  popzer1e-12/  popzch1e-9/
├── nd70/  lte_ng/  trace_lte/  full_nst/
├── warm_from_g5.5/  warm_from_he0/  warm_he0_nokant/
└── cold_nokant/

每个变体 outputs/nc.9 可用 scripts/check_fort9.py 复核;nc.7 可用 check_temperature.py 复核。