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

114 lines
7.7 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.
# DCTS 物理计算与流程设计 (Physics Pipeline Design)
> 本文档阐述 DCTS 核心物理计算引擎的设计原理、TLUSTY/SYNSPEC 计算链(冷启动 / 种子步进),
> 以及基于策略链(Strategy Chain)的回退机制与种子匹配算法。
> 阶段独立配置(`enabled` / `policy` / `strategies`)的完整设计见
> [`task_engine_decoupling_design.md`](./task_engine_decoupling_design.md)。
---
## 1. 物理计算链原理
TLUSTY 通过**完全线性化 (Complete Linearization)** 方法求解恒星大气结构的 NLTE(非局部热力学平衡)统计平衡方程与辐射转移方程。由于线性化的收敛半径有限,若初始猜想(初猜)偏离真解较远,迭代极易发生数值发散。
DCTS 把单点计算拆分为 **TLUSTY 大气结构求解 + SYNSPEC 光谱合成**两个独立阶段(各自有 `enabled` 开关)。TLUSTY 阶段内再按执行策略选用不同收敛链:
**冷启动链 (ColdRun`default_cold_chain`)**
```mermaid
flowchart LR
Stage1["1. LTE 灰大气\n(lte / tlusty)\n解析灰色初猜"] --> Stage2["2. NLTE 连续谱\n(nc / tlusty)\n收敛电离平衡"]
Stage2 --> Stage3["3. NLTE 完整谱线\n(nl / tlusty)\n包含线跃迁求解"]
Stage3 --> Stage4["4. 合成光谱\n(synspec)\n输出 .spec / .cont"]
```
**种子步进链 (SeedStep`default_seed_chain`)**:直接以近邻已收敛大气为热启动起点,**跳过 lte 灰大气阶段**:
```mermaid
flowchart LR
Seed1["1. NLTE 连续谱热启动\n(seed_nc / tlusty)\n以种子 .7 作 fort.8 初猜"] --> Seed2["2. NLTE 完整谱线\n(nl / tlusty)\n精化收敛"]
Seed2 --> Seed3["3. 合成光谱\n(synspec)"]
```
### 各阶段物理配置与功能明细
阶段配置见 `common::runner::default_cold_chain` / `default_seed_chain``StageConfig`):
| 阶段 | 执行程序 | 物理含义 | 关键参数 | 迭代上限 |
| :--- | :--- | :--- | :--- | :--- |
| **1. LTE 灰大气 (lte)** | `tlusty.exe` | 解析灰色不透明度求解温度结构,无需种子,提供合理起点。 | `lte=T, ltgray=T, niter=0, ilvlin=0` | 0 次(生成初始结构) |
| **2. NLTE 连续谱 (nc)** | `tlusty.exe` | 切换到 NLTE,忽略束缚-束缚线跃迁(`ilvlin=0`),收敛基础电离平衡。 | `lte=F, ltgray=F, ilvlin=0, niter=10` | 10 次 |
| **3. NLTE 完整谱线 (nl)** | `tlusty.exe` | 引入全部线跃迁(`ilvlin=100`),求解包含非平衡辐射场的大气结构;**要求收敛**(`require_converged=true`)。 | `lte=F, ltgray=F, ilvlin=100, niter=100` | 100 次 |
| **3'. 种子热启动 (seed_nc)** | `tlusty.exe` | 以近邻收敛大气 `.7``fort.8` 初猜做 NLTE 连续谱收敛(跳过低温度灰大气阶段)。 | `lte=F, ltgray=F, ilvlin=0, niter=20, ichang=0` | 20 次 |
| **4. 合成光谱 (synspec)** | `synspec.exe` | 基于收敛大气结构(`.7`),计算高分辨率合成光谱。 | 波长窗/展宽/截断由 `synspec:` 数值参数配置 | — |
> 阶段标签由 workflow 配置保证唯一(`lte`/`nc`/`nl`/`seed_nc`),各阶段输入卡/日志/大气/收敛诊断
> 以 `<name>.<label>.<后缀>` 快照落盘归档(见 [`tlusty_result_artifacts.md`](./tlusty_result_artifacts.md))。
---
## 2. 冷启动链 vs 种子步进链(策略链机制)
在极端高有效温度、极低氦丰度或强金属线空白区,从 LTE 灰大气直接启动的冷启动链容易发散。DCTS 通过 **策略链 (Strategy Chain)** 机制处理:工作流可配置 `tlusty_strategies`(如 `["cold_run", "seed_step"]`),调度器按顺序派发,失败时弹出链首、以剩余链回退重试(见 `task_engine_decoupling_design.md §4.2`)。
```mermaid
flowchart TD
Start([开始计算指定网格点]) --> Resolve[调度器解析策略链\nresolve_dispatchable_chain]
Resolve --> Exec[执行链首策略]
Exec --> Check{nl 阶段物理收敛?}
Check -- "是 (Success)" --> RunSyn[运行 Synspec 生成光谱] --> Save[结果入库 & 汇报成功]
Check -- "否 (失败)" --> Pop[服务端弹出链首策略\ntrigger_strategy_fallback]
Pop --> Rest{剩余链非空?}
Rest -- "是,下一顺位 seed_step" --> FindSeed[查全局种子池找近邻收敛 .7 种子]
FindSeed --> HasSeed{找到合规种子?}
HasSeed -- "是" --> Inject[注入 seed_point_name\n重置 pending 再派发] --> Exec
HasSeed -- "否" --> Hold[保持 pending 待种子出现后自愈\nseed_step 顺位暂存链尾)]
Rest -- "否(链耗尽)" --> Fail[标记任务彻底失败]
```
要点:
1. **派发门控**:链首为 `seed_step` 时必须能查到近邻种子才可派发;无种子则暂存该顺位到链尾、继续解析下一项(保证终止性,重复 seed_step 不陷入死循环)。初始派发与失败回退共用 `resolve_dispatchable_chain`
2. **种子注入**`seed_step` 派发时服务端在 `tasks` 行写入 `seed_point_name`,节点凭此下载种子大气(`GET /api/seed/<name>`),TLUSTY 以种子 `.7` 作为 `fort.8` 热启动输入,跳过灰大气阶段直接跑 `seed_nc -> nl`
3. **回退语义**:仅 `failed` 状态且状态实际迁移时触发(2026-08-02 修复,杜绝重复失败报告触发多余 seed_step);回退保留派发时的策略链快照,不修改原 `policy`
---
## 3. 种子匹配算法 (Seed Finding)
种子池是**全局共享的物理资源池**`seeds` 表 + 内存缓存 + 索引,跨工作流共享)。收敛且大气干净(无 NaN)的结果上报时,`.7` 大气原子写入 `seeds_dir/<name>/<name>.7` 并入库。
### 3.1 exact_family 桶索引
`(teff/5000, logg×100, loghe×100)` 量化成 `SeedBucketKey`,插入时写入 floor/floor+1 的 8 个笛卡尔积桶,查询时查 8 桶 → O(1)~O(小) 缩候选集,桶内再精算距离(量化只缩候选、不影响正确性)。
### 3.2 有向 CNO 距离(非对称,核心创新)
exact_family 判定(同物理族,仅 CNO 不同):`Δteff<5000 && Δlogg<0.01 && Δloghe<0.01`。候选按**有向 CNO 距离**排序:
```
delta = target cand(对 logc / logn / logo 各分量)
delta > 0(目标更富,坏方向)→ 惩罚 4.0 × delta
delta < 0(目标更贫,好方向)→ 惩罚 1.0 × |delta|
```
**数据标定依据**:对历史 1191 个真实 seed_step 配对的成败统计——贫金属方向(种子更富、目标往贫走)成功率 42–54%,富金属方向仅 3–11%(`he=-4` 时 54% vs 3%,差 18 倍)。物理解释:从高金属收敛解**减少**金属是稳定微扰;反过来**增加**金属时,新增紫外谱线辐射驱动会破坏已建立的辐射平衡 → 发散出现 NaN。
### 3.3 全局距离(跨 teff
exact_family 未命中时退化到全量扫描,候选需 `d ≤ 3.0`
```
d = Δteff/5000 + Δlogg×2 + Δloghe×0.5 + Δcno×0.1
```
权重物理意义:Teff 主导黑体势(÷5000 归一);logg 破坏静力学压强平衡最烈(×2);loghe 次之(×0.5);CNO 影响紫外谱线辐射驱动,方向性已由有向距离表达(×0.1)。
---
## 4. 节点端执行与现场处理
1. **种子获取**seed_step 任务凭 `seed_point_name` 下载种子 `.7`,落 `.seed_cache/`(LRU 上限 8),再复制私有副本进 slot 沙盒作为 `fort.8`
2. **沙盒生命周期**:任务算完 → 上报成功(或失败,尽力而为)→ **白名单归档**`result_dir/<name>/`,永久保留)→ **清理沙盒**;节点重启时也会**清理残留的 `task_*` 沙盒**2026-08-02 修复:避免强杀遗留工作目录写满磁盘)。归档白名单与 TLUSTY fort 单元语义详见 [`tlusty_result_artifacts.md`](./tlusty_result_artifacts.md)。
3. **节点无感知**:节点只执行 `strategies[0]` + 注入的 `seed_point_name`,对回退过程完全无感知,调度与计算解耦。