Files
DCTS/docs/tlusty_result_artifacts.md
T
fmq cd370d88e7 feat(all): 任务引擎双阶段解耦、僵尸涡旋修复、动态 CPU 配额与前端详情页重构
将 TLUSTY/SYNSPEC 拆为各自独立的 enabled/policy/strategies 阶段,
以策略链自动弹栈取代单级 seed_step 布尔回退;定向修复 2026-08-02
僵尸任务涡旋事故;新增节点并发配额热调;前端详情页从 1412 行巨型
视图拆为薄控制器 + detail 子模块,并补齐工具层与单测。

引擎与调度(task_engine_decoupling_design.md)
- models.rs: 新增 StagePolicy / EngineStageConfig / TaskSpec 阶段字段、
  normalize_compat() 校正旧版在途消息策略链、failed_stage 归因
- scheduler.rs: resolve_dispatchable_chain 派发门控、
  trigger_strategy_fallback 按 failed_stage 精确弹栈;启动期
  force_recompute/skip_converged(默认)/skip_failed 三策略
- db.rs: tasks 表 +7 列持久化阶段配置;终态守卫
  (mark_grid_point_running 仅 pending/queued→running;
  record_task_report 拒绝迟到失败翻黑 converged);策略弹栈快照

僵尸涡旋修复(runbook-20260802-zombie-vortex-fix.md)
- 全链路跨库活性交叉校验:派发/claim/孤儿回收/回退统一查 MQ 队列活性,
  活则放行、死则清僵尸,结构性消除"每点重复派发"
- stop/重启卫生:清队列同步 delete_tasks_by_ids,杜绝遗留 pending 行
- report_task: 幂等吸收 + 409 区分迟到冗余结果,仅 state_changed 时回退
- MQ: NULL workflow_name 回填 __legacy__、requeue 后迟到上报被 403 竞态修复

动态 CPU 配额(dynamic_cpu_slots_design.md)
- admin.rs: POST /admin/nodes/:id/quota(Option<Option<i32>> 区分
  缺字段/显式 null);nodes 表 +admin_max_slots
- worker.rs: effective_max_slots = min(admin, physical),心跳下发原子生效

科学产物保全(tlusty_result_artifacts.md)
- runner.rs: SYNSPEC 启动前快照 fort.12/fort.14 → .bfac/.emflux 防覆盖
- 半失败点(大气收敛+光谱失败)改判 Failed 并写入 note;仅 SYNSPEC
  场景不再恒判失败;撤销归档 LRU 200 上限改为永久保留
- executor.rs: 透传 synspec_params 数值参数(此前固定 None)

前端(dashboard/)
- workflowDetail.js 1412→328 行,拆出 views/detail/{ctx,overview,
  pointsTable,parSets,pointPanel}.js,AbortController 治理监听/请求生命周期
- 删除 wfActions.js,新增 wfEnginePanel.js(双阶段三维配置编辑面板)
- 新增 utils/{errors,format,icons,polling,yamlStage}.js 纯函数模块
- 路由级动态 import 代码分割;节点配额三点菜单 + Modal 管理
- 首次引入 node:test 单测(format/polling/yamlStage/psCache,644 行)
- 系统性补齐 a11y:skip-link、ARIA、Tab 键盘漫游、toast 关闭、退出动画

文档与工具
- 新增 6 篇设计/调研:引擎解耦、动态配额、涡旋 runbook、
  光谱正确性分析、收敛判断、产物归档
- PIPELINE/design/api/database 等协同重写为分布式 C/S 架构口径
- scripts/fetch_results.sh 跨节点产物备份;import_results 按 cno 升序导入
- workflows/sdB_cno.yaml: 新增 tlusty/synspec_stage 配置块,修正 wstart 笔误
2026-08-04 23:40:52 +08:00

196 lines
10 KiB
Markdown
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.
# TLUSTY 结果产物分析:Node 归档白名单与 fort 单元快照
> 本文档记录对 TLUSTY/SYNSPEC 源码的单元号(fort.N)语义分析,以及据此确定的
> Node 端结果归档(`result_dir`)白名单与 TLUSTY b 因子/出射谱快照的设计依据。
> 源码路径:TLUSTY 位于 `/home/fmq/program/SpectraRust/tlusty/``tlusty208.f`),
> SYNSPEC 位于 `/home/fmq/program/SpectraRust/synspec/``synspec54.f`)。
> 归档逻辑实现于 `crates/node/src/executor.rs`、`crates/common/src/runner.rs`、
> `crates/common/src/result_filter.rs`。
## 1. 背景与问题
Node 每个任务算完后,把沙盒 `work_dir/task_<id>/<name>/` 内的产物拷贝到持久归档
`result_dir/<name>/`。归档采用**白名单**策略(`is_result_worthy`),只保留有语义价值
的产物,丢弃 Tlusty/Synspec 运行时的中间工作单元(旧版 catch-all 会把它们一并搬进
归档,每个模型浪费约 2MB / 4.8MB)。
需要回答的核心问题:
1. 当前归档到底保留了哪些文件?
2. TLUSTY 的 `fort.12`b 因子)、`fort.14`(出射谱)、`fort.69`(计时日志)是否有
保存价值?—— 需以 TLUSTY 源码为准。
3. TLUSTY 出射谱(fort.14)与 SYNSPEC 输出的 `.spec` 有什么区别,是否冗余?
## 2. Node 结果归档机制(现状)
- **归档路径**`result_dir/<name>/``result_dir` 由 node 配置指定,默认为 `data/result/`)。
- **触发时机**:上报成功后(上报失败也归档,用于排错),随后清理沙盒。
- **原子写入**:先拷为 `.result.tmp.<uuid>` 再 rename,防止半截文件。
- **无 LRU 上限**:所有已算网格点产物永久保留(2026-08-02 撤销此前 200 目录上限)。
- **白名单判定**`common::result_filter::is_result_worthy(fname, model_name)`
### 2.1 保留的文件(白名单)
`model_name` 为网格点权威名,如 `t20000_g5.0_he-2_c-4_n-4_o-4`
**裸名保留**(不以 model_name 为前缀,有独立语义):
| 文件 | 语义 |
|------|------|
| `conv.json` | 收敛摘要 |
| `fort.8` | SYNSPEC 输入大气 |
| `fort.55` | SYNSPEC 控制卡 |
**科学核心** `<name>.<后缀>`
| 后缀 | 来源 | 语义 |
|------|------|------|
| `.7` | TLUSTY/SYNSPEC | 最终大气 |
| `.spec` | SYNSPEC fort.7 | 合成光谱(高分辨率) |
| `.cont` | SYNSPEC fort.17 | 连续谱 |
| `.iden` | SYNSPEC fort.12 | 谱线证认表 |
| `.log` | SYNSPEC | SYNSPEC 日志 |
| `.bfac` | TLUSTY fort.12 快照 | 最终模型 b 因子(非 LTE 偏离因子) |
| `.emflux` | TLUSTY fort.14 快照 | 最终模型出射谱(波长 Å + Fλ) |
**阶段快照** `<name>.<label>.<后缀>`label ∈ `lte`/`nc`/`nl`/`seed_nc`):
- `.5`(输入卡)、`.6`(输出日志)、`.err`(错误日志)、`.nst`(控制卡)、`.7`(该阶段大气)
**收敛诊断** `<name>.<label>_chmax*.9`**唯一保留的 .9 形态**(裸 `<name>.<label>.9`
`_chmax*.9` 内容重复,runner 源头已停止写出)。
### 2.2 丢弃的内容
- 所有 Tlusty 中间工作单元:`fort.1/2/3/10/11/13/14/18/22/42/44/50/57/69/82/95`
- `fort.84`NATOMS 崩溃缓存)、`.tmp` 残留
- 符号链接(`data``fort.19` 等共享 runtime 资源)、子目录
- 不以 `<name>.` 开头且不在裸名列表的文件、未知后缀/未知阶段标签
- `fort.12` / `fort.17`:被 runner 消费(见 §4.1)后删除
## 3. TLUSTY fort 单元语义(源码分析)
TLUSTY 每次运行到达最终迭代(`LFIN=.TRUE.`)时,经 `OUTPRI`tlusty208.f:14156,调用点
:3889)一次性写出多个单元。各单元语义与行号:
| 单元 | 内容 | 源码位置 | 判定 |
|------|------|----------|------|
| `fort.12` | **b 因子(非 LTE 偏离因子表)**:头 2I5 + 每深度 TEMP/ELEC/DENS/BFAC,格式 701/702/703 | :14344 | 科学价值高,需快照 |
| `fort.13` | 出射辐射场(FREQ, FLUX=H(ν), FH=Eddington 因子),格式 602 | :14185 | 与 fort.14 同源,未快照 |
| `fort.14` | **出射谱(波长 Å + Fλ)**,格式 614 `F15.3,1pe15.3` | :14188 | 科学价值高,需快照 |
| `fort.17` | 每深度布居数 POPUL(格式 503 | :14124 | SYNSPEC 覆盖后转存 `.cont` |
| `fort.20` | b 因子 BFAC(另一分支) | :14119 | 未保留 |
| `fort.22` | 绝对 b 因子 BFAB | :14346 | 未保留 |
| `fort.69` | **迭代计时日志**`TIMING` 子程序写 IP/MOD/TIME/DT/ROUTFORMAL SOLUTION / LINEARIZATION),格式 600 | :29937 | 纯性能诊断,丢弃 |
> 注意:`OUTPRI` 仅在最终迭代调用,故每个单元内保存的是**最后一次迭代**的最终值。
> 收敛链上最后一次 TLUSTY 运行即最终模型。
## 4. SYNSPEC 对 unit 12/14 的覆盖与丢失风险
### 4.1 单元号复用导致覆盖
TLUSTY 与 SYNSPEC **同目录串行执行**,且两个程序复用相同的单元号:
| 单元 | TLUSTY 写 | SYNSPEC 写 |
|------|-----------|-----------|
| 12 | b 因子 | 谱线证认表(synspec54.f:9719,格式 603 |
| 14 | 出射谱 | 谱线数据(synspec54.f:9852,格式 601 |
由于 TLUSTY 先跑、SYNSPEC 后跑,SYNSPEC 会把 `fort.12`/`fort.14` 覆盖。现有 runner
流程:
1. TLUSTY 写 b 因子 + 出射谱 → **被 SYNSPEC 覆盖**
2. SYNSPEC 写 `fort.7`(谱)、`fort.17`(连续谱)、`fort.12`(谱线证认表)
3. runner 将 `fort.7``.spec``fort.17``.cont``fort.12``.iden`,随后删除 `fort.12`/`fort.17`
**结论**:归档里的 `.iden` 保存的是 SYNSPEC 的谱线证认表(覆盖后的 fort.12),
**TLUSTY 的 b 因子与出射谱在覆盖前无任何快照,会被静默丢失** —— 这是真实的数据损失点。
### 4.2 快照决策
- `fort.69`:纯计时日志,**不保存**(无科学内容)。
- `fort.12`b 因子)与 `fort.14`(出射谱):**需快照**。
## 5. 实现:快照 b 因子 + 出射谱
### 5.1 快照命名与白名单
| 源文件 | 快照名 | 白名单后缀 |
|--------|--------|-----------|
| `fort.12` | `<name>.bfac` | `bfac`(加入 `SCIENCE_SUFFIXES` |
| `fort.14` | `<name>.emflux` | `emflux`(加入 `SCIENCE_SUFFIXES` |
### 5.2 插入点
`runner::run_model_with_timeout`:**收敛链循环结束后、SYNSPEC 启动前**调用
`snapshot_tlusty_outputs(&model_dir, name)`。此时 fort.12/14 是最后一次 TLUSTY 运行
(最终模型)的产物,且尚未被 SYNSPEC 覆盖。仅 SYNSPEC 场景(tlusty 未运行)下
fort.12/14 不存在,函数按文件存在性静默跳过。
### 5.3 变更文件
- `crates/common/src/runner.rs`:新增 `snapshot_tlusty_outputs()` + 调用 + 2 个测试
- `crates/common/src/result_filter.rs``SCIENCE_SUFFIXES``bfac`/`emflux` + 文档 + 测试
- `crates/node/src/executor.rs`:归档文档、`test_save_result_artifacts` 同步 + 修正
`fort.13` 注释(原误标为"NLTE 跃迁频率网格",实为出射辐射场 FREQ/FLUX/FH
## 6. TLUSTY 出射谱(fort.14vs SYNSPEC `.spec`
两者**转换公式完全相同、物理量一致**,差异在网格密度、线不透明度处理、覆盖范围与用途。
### 6.1 相同点
- 公式一字不差:`Fλ = H(ν) × ν² / c`
- TLUSTY:14188):`FLAM=FLUX(IJP)*FREQ(IJP)*FREQ(IJP)/2.997925E18`
- SYNSPEC:3365):`FLAM=FLUX(IJ)*FREQ(IJ)*FREQ(IJ)*CAS``CAS=1./2.997925D18`
- `FLUX` 都是表面出射 Eddington 通量 H(ν)erg/cm²/s/sterad/HzOUTPRI 注释明确
"precisely the second moment H(freq) at the surface")。
- 同一波长点的连续谱水平应当一致。
### 6.2 差异点
| 维度 | TLUSTY fort.14 | SYNSPEC `.spec` |
|------|---------------|-----------------|
| 网格密度 | 模型自身频率网格(NFREQ 个点,数百~数千,非均匀) | 以每条谱线为中心的细网格(`FR0=FREQ0(IL0)`SPACE/CUTOFF/DOPSTD 采样线轮廓,密度高几个量级) |
| 线不透明度 | 模型求解时的粗/近似线处理(不透明度采样/ODF/超能级),只体现最强线 | 完整线表(fort.19)逐细频点重解辐射转移,得到分辨开的真实线轮廓 |
| 波长覆盖 | 整个模型宽带频率范围 | 仅 fort.55 指定窗口(dcts 默认 14001410 Å) |
| FLUX 来源 | 模型迭代过程的自洽辐射场解(顺带用于通量守恒检查 TOTF) | 用已收敛大气在细网格重新解 RT |
| 用途/下游 | 模型副带品,快速看谱/校验 | 科学产品,注释明说 "serves as input to ROTINS"(转动/仪器展宽卷积),用于与观测对比 |
### 6.3 实际含义
两者是**同一物理量(表面 Fλ)在不同分辨率和线处理下的版本**,非两种东西。叠画时
连续谱重合,`.spec` 显示被分辨开的精细谱线轮廓,fort.14 中弱线基本不可见。归档同时
保留二者不构成冗余:`.emflux` 代表模型自身辐射场(宽带、粗,可独立校验),`.spec`
代表最终高分辨率合成谱(窄窗、细,与观测对比的产品)。
## 7. 完整归档文件清单(快照实施后)
```
result_dir/<name>/
├── conv.json
├── fort.8 # SYNSPEC 输入大气(裸名保留)
├── fort.55 # SYNSPEC 控制卡(裸名保留)
├── <name>.7 # 最终大气
├── <name>.spec # SYNSPEC 合成光谱
├── <name>.cont # SYNSPEC 连续谱
├── <name>.iden # SYNSPEC 谱线证认表
├── <name>.log # SYNSPEC 日志
├── <name>.bfac # TLUSTY 最终 b 因子(快照 fort.12
├── <name>.emflux # TLUSTY 最终出射谱(快照 fort.14
├── <name>.<label>.5 # 阶段输入卡快照
├── <name>.<label>.6 # 阶段输出日志快照
├── <name>.<label>.err # 阶段错误日志快照
├── <name>.<label>.nst # 阶段控制卡快照
├── <name>.<label>.7 # 阶段大气快照
└── <name>.<label>_chmax*.9 # 阶段收敛诊断(唯一保留的 .9)
```
## 8. 后续可选优化
- `fort.13`(出射辐射场,含 Eddington 因子 FH)未快照;如需保留,在
`snapshot_tlusty_outputs` 中加 `("fort.13", "emrad")` 并在白名单加 `emrad` 后缀即可。
- `fort.20`b 因子)、`fort.22`(绝对 b 因子)同属 b 因子家族;如需保留可在 TLUSTY
阶段结束后一并快照,但 `fort.12` 已覆盖相对 b 因子,绝对 b 因子可由 POPUL/POPLTE 重算。