将 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 笔误
196 lines
10 KiB
Markdown
196 lines
10 KiB
Markdown
# 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/ROUT(FORMAL 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.14)vs 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/Hz,OUTPRI 注释明确
|
||
"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 默认 1400–1410 Å) |
|
||
| 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 重算。
|