- server/db: 拆 4929 行 db.rs 单体为 db/ 目录,migrations.rs 引入 PRAGMA user_version
版本化迁移运行器(M1~M13)
- 任务引擎 Phase 6/7b/7c 改名收敛:EngineStageConfig→PhaseConfig、StagePolicy→ResumePolicy、
Converged→Completed、删除 task_type 列、success_method 拆 tlusty_/synspec_ 双列、
新增 tlusty_status/synspec_status 半失败阶段守卫
- 科学正确性加固:conv_check 任意行 NaN/Inf/溢出判无效(0 行容忍)、新增 spec_is_valid
校验 SYNSPEC 脏谱、itek_history 逐次迭代全量保真、fmt_abn powf 溢出饱和
- 用户配置真正接通:tlusty_chain/tlusty_input 由死字段经 调度器→TaskSpec→executor→runner
透传生效;config 加载期 validate + deny_unknown_fields + 解析失败记 warn
- 调度修复:H1 活锁(pending_strategies 跳过已失败策略)、种子查找错误不再静默降级冷启动
- dashboard: 阶段配置面板 tlusty_stage/synspec_stage、"已完成"标签、迭代诊断展示
- docs: 新增 database_refactor_design.md,同步 database/api/PIPELINE/workflow_detail
386 lines
19 KiB
Markdown
386 lines
19 KiB
Markdown
# CNO 网格完整计算流程
|
||
|
||
> 本文档说明完整理论光谱网格的计算流程:每个网格点的计算阶段、每阶段的配置、
|
||
> 配置原理、CPU/并行机制、以及如何统计每个阶段的信息(时间、收敛等)。
|
||
> 当前实现为 **Rust 分布式 C/S + MQ 架构**(非早期 Python 单机脚本),调度与阶段配置
|
||
> 详见 `architecture.md` / `task_engine_decoupling_design.md`。
|
||
|
||
---
|
||
|
||
## 1. 总体架构
|
||
|
||
```
|
||
workflows/<wf>.yaml (网格点 + 阶段独立配置 + 策略链)
|
||
│
|
||
▼
|
||
server GridScheduler (schedule_pending_tasks)
|
||
│ 原子选点(claim_pending_grid_points) → 生成 TaskSpec
|
||
▼
|
||
MQ task_queue (SQLite,pending/claimed 状态机)
|
||
│ Worker 轮询 claim 抢占(pull 模型)
|
||
▼
|
||
node executor(每任务独立沙盒 task_<id>/)
|
||
│ 按 tlusty_strategies[0] 执行收敛链
|
||
├── ColdRun : lte → nc → nl → synspec
|
||
├── SeedStep : seed_nc → nl → synspec(凭 seed_point_name 下载种子 .7 热启动)
|
||
▼
|
||
结果上报(report)→ 白名单归档 result_dir/<name>/ → 清理沙盒
|
||
│ 收敛且干净 → .7 入种子库 seeds(供他点热启动)
|
||
```
|
||
|
||
策略链回退:当前策略失败 → 服务端弹出链首 → 下一顺位(如 `seed_step`)注入种子重试,
|
||
详见 `design.md §2` 与 `task_engine_decoupling_design.md §4.2`。
|
||
|
||
---
|
||
|
||
## 2. 每个网格点的计算阶段
|
||
|
||
每个网格点(一组 Teff/logg/logHe/logC/logN/logO 参数)经过 **TLUSTY 大气求解 + SYNSPEC
|
||
光谱合成**。TLUSTY 阶段按执行策略选用不同收敛链(`common::runner` 的 `default_cold_chain` /
|
||
`default_seed_chain`)。
|
||
|
||
**冷启动链**(适用 20-40K 及大部分易收敛点):
|
||
|
||
| 阶段 | 程序 | 做什么 | NITER | 典型耗时 |
|
||
|------|------|--------|-------|---------|
|
||
| 1. LTE 灰大气 | tlusty | `lte=T, ltgray=T` 模式,解析求灰色 T(τ) 结构 | 0 | 1-3 秒 |
|
||
| 2. nc(NLTE 连续谱)| tlusty | `lte=F, ltgray=F` + `ilvlin=0`,收敛电离平衡(无线跃迁)| **10** | 1-5 分钟 |
|
||
| 3. nl(NLTE 含线)| tlusty | `lte=F, ltgray=F` + `ilvlin=100`,加全部谱线跃迁(要求收敛)| 100 | 5-20 分钟 |
|
||
| 4. synspec | synspec | 用 nl 大气合成可观测光谱 | — | 3-10 秒 |
|
||
|
||
**阶段间依赖**:1→2→3→4 严格顺序。每阶段用上一阶段的 `.7` 大气作种子(fort.8)。
|
||
|
||
> 冷启动链在高温/He-poor/富金属区会发散,此时按策略链回退走 **种子步进链**
|
||
> (seed_nc→nl,跳过 LTE grey 直接热启动)。
|
||
|
||
### 为什么是这 4 个阶段(原理)
|
||
|
||
Tlusty 的 NLTE 求解用**迭代线性化**(complete linearization)。线性化的收敛半径
|
||
有限——当初猜离真解太远时迭代发散。四个阶段逐步缩小初猜与真解的差距:
|
||
|
||
- **阶段1(LTE 灰大气)**:LTE + 灰色不透明度假设下解析求温度结构。提供物理
|
||
合理的起点,不需要种子(从零开始)。
|
||
- **阶段2(nc 连续谱)**:切换到 NLTE,但 `ilvlin=0` 不含束缚-束缚线跃迁。
|
||
线跃迁是统计平衡方程中最敏感的非线性项;先不加线,只收敛电离平衡(光致电离
|
||
+复合),得到稳定的 NLTE 布居数结构。**跳过此步直接 grey→含线 NLTE 必发散。**
|
||
- **阶段3(nl 含线)**:加入全部线跃迁(ilvlin=100)。从已收敛的 nc 种子起步,
|
||
线扰动小,快速收敛(典型 ~15 次迭代)。
|
||
- **阶段4(synspec)**:用 nl 阶段收敛的大气模型,计算指定波长范围的合成光谱。
|
||
|
||
### 2.1 种子步进链(seed_step)—— 高温区破局
|
||
|
||
当冷启动链发散时(典型:60000-80000K + He-poor + 富金属),策略链回退切换到
|
||
**种子步进链**(`default_seed_chain`),跳过 LTE grey 冷启动,直接用邻居已收敛的
|
||
`.7` 热启动:
|
||
|
||
| 阶段 | 做什么 | 关键标志 | NITER |
|
||
|------|--------|---------|-------|
|
||
| seed_nc | 从种子热启动 NLTE 连续谱 | `ltgray=F`(读 fort.8) + `ichang=0` | 20 |
|
||
| nl | 含谱线完整 NLTE(要求收敛)| `ilvlin=100` | 100 |
|
||
|
||
**触发流程**(服务端策略链机制,非节点端自行判断):
|
||
1. 初始派发链首策略(如 `cold_run`);失败上报(`failed_stage="tlusty"`)后,
|
||
服务端 `trigger_strategy_fallback` 弹出链首,重置点 pending,再派发下一顺位。
|
||
2. 若下一顺位为 `seed_step`:服务端在全局种子库按**有向 CNO 距离**找最近邻收敛种子,
|
||
注入 `seed_point_name` 后派发;无种子则暂存顺位待种子出现。
|
||
3. 节点凭 `seed_point_name` 下载种子 `.7`(`GET /api/seed/<name>`),作 fort.8 热启动跑
|
||
`seed_nc → nl`。
|
||
|
||
**原理**(`tlusty208.f` 源码确认,详见 EXPERIENCE.md):
|
||
- `LTGREY=T` → `CALL LTEGR` 生成灰大气(**忽略 fort.8**,冷启动);
|
||
- `LTGREY=F` → `CALL INPMOD` 读 fort.8 作初猜(**热启动**)。
|
||
- `ICHANG=0`:种子与目标模型原子完全一致(同为 H/He/CNO 设置),只改
|
||
Teff/logg/丰度,不需要重映射布居数。
|
||
|
||
> **物理极限(如实标注)**:80000K + He-poor + logCNO=-1 即使种子步进也发散
|
||
> (CNO 高价离子主导不透明度,金属 ×10 跳跃线性化无法阻尼)。网格如实标
|
||
> `converged=false`,不强制成功——这些极端参数组合观测上本就罕见。
|
||
>
|
||
> **ICRSW 是死代码**:源码中 `SUBROUTINE SWITCH` 定义但从未被 CALL,
|
||
> 默认 CRSW≡1.0 无阻尼效果。不要依赖 ICRSW 稳定化(见 §7.8)。
|
||
|
||
---
|
||
|
||
## 3. 每阶段的配置信息与原理
|
||
|
||
### 3.1 `.5` 文件(每阶段一份,三阶段相同 NATOMS/ions,只改 3 处)
|
||
|
||
```
|
||
第1行: TEFF GRAV (三阶段相同:目标参数)
|
||
第2行: LTE LTGRAY (阶段1=T T,阶段2/3=F F;种子步进链全 F)
|
||
第3行: nst 文件名 (固定写 'nst',内容每阶段由 nst_writer 生成)
|
||
第4行: NFREAD (=2000 → 展开约 75443 个频率点;不要用 50)
|
||
第5行: NATOMS (=8: H,He,空×3,C,N,O)
|
||
第6+行: atoms (mode abn modpf) (C/N/O 的 mode=2 显式NLTE, abn=10^logX)
|
||
ions段: iat iz nlevs ilast ilvlin nonstd typion filei
|
||
(阶段1/2/seed_nc: ilvlin=0; 阶段3/nl: ilvlin=100 ← 关键区别)
|
||
```
|
||
|
||
**为什么 NATOMS/ions 三阶段必须相同**:每阶段的 `.7` 大气记录了每个能级的
|
||
布居数。种子与目标的能级结构必须一一对应,否则读取时索引错位 → NaN。
|
||
|
||
### 3.2 nst 文件(非标准参数,每阶段统一结构,NITER 不同)
|
||
|
||
`nst_writer::generate_nst_content` 对**所有阶段(含 lte)统一生成两行**:
|
||
```
|
||
ND=50,NLAMBD=3,VTB=2.,ISPODF=1,DDNU=50.,CNU1=6.,[CHMAX=..][,ITEK=..],NITER=<阶段>
|
||
[ORELAX=..][,IDLTE=..][,IACC=..][,ICHANG=..],IELCOR=-1
|
||
```
|
||
- lte: `NITER=0`(灰大气不迭代,只做一次形式解)
|
||
- nc: `NITER=10`, nl: `NITER=100`, seed_nc: `NITER=20`
|
||
- **不设 CHMAX**(用默认 0.001,强迫 nc 真正收敛)
|
||
- **不设 ITEK**(用默认 4)
|
||
- 尾部统一 `IELCOR=-1`(电子密度修正关闭)
|
||
- 参数分行写(line1 ≤64c, line2 余下),避免 tlusty nst 解析器 ~72 字符行宽截断
|
||
|
||
每个参数的作用与原理:
|
||
|
||
| 参数 | 作用 | 为什么这样设 |
|
||
|------|------|-------------|
|
||
| `ND` | 大气深度点数 | 50(sdB 标准配置) |
|
||
| `NLAMBD` | lambda 迭代频率点数 | 3(频率网格细化,用户验证配方) |
|
||
| `VTB` | 微湍流速度 km/s | 2.(sdB 典型值) |
|
||
| `ISPODF` | 频率网格开关 | 1(启用细化频率网格) |
|
||
| `DDNU` | 频率间隔因子 | 50.(频率网格细化参数) |
|
||
| `CNU1` | 频率网格起点 | 6.(频率网格细化参数) |
|
||
| `NITER` | 最大迭代数 | nc=10(实测最优),nl=100,seed_nc=20 |
|
||
| `IELCOR` | 电子密度修正 | -1(关闭) |
|
||
|
||
> **关键:不设 CHMAX(用默认 0.001)、不设 ITEK(用默认 4)、不设 IDLTE/ORELAX。**
|
||
> 之前版本设了 CHMAX=0.1 导致 nc 没真正收敛,是大部分失败的根本原因。
|
||
> 详见 EXPERIENCE.md §4 的错误记录。
|
||
>
|
||
> **nc 的 NITER=10 是实测最优**(GUIDE.md NITER 扫描结论):
|
||
> - nc(纯连续谱)缺少谱线约束,外层温度永不真正收敛,只在外层漂移;
|
||
> - NITER=10 vs NITER=50 的最终光谱差异仅 6e-6(完全等价);
|
||
> - nl(含谱线)会自修正到正确解,无论 nc 给什么初值;
|
||
> - NITER=10 总耗时 ~12 分钟(35000K CNO),NITER=50 浪费 2.2× 时间。
|
||
|
||
### 3.3 synspec 配置(fort.55 + 谱线表)
|
||
|
||
```
|
||
fort.55 控制卡: 波长窗/展宽/截断(由 workflow YAML 的 `synspec_input:` 块或代码默认配置)
|
||
谱线表 fort.19: data 下 gf 谱线数据(含 C/N/O 线)
|
||
```
|
||
- 代码默认波长窗为 **1400–1410 Å**(`SynspecInput` 默认),实际使用通常配置到
|
||
目标波段(如 3000-7000Å 光学波段,覆盖 C II 4267、C III 4647 等)。
|
||
- 大气来自 nl 阶段的 `.7`(复制为 fort.8)。
|
||
|
||
---
|
||
|
||
## 4. CPU 与并行机制
|
||
|
||
### 4.1 每个网格点只用一个 CPU 核
|
||
|
||
**是的。** tlusty.exe 和 synspec.exe 是 Fortran 编译的单线程程序,每个实例只用
|
||
1 个 CPU 核。网格点的并行不是靠程序内部的多线程,而是靠**同时启动多个程序实例**
|
||
(分布在多台计算节点上)。
|
||
|
||
### 4.2 如何做到并行(分布式 Pull 模型)
|
||
|
||
并行由 **多计算节点 + 每节点多槽位** 构成:
|
||
|
||
- **节点**:每个物理设备跑一个 `node` 进程,`DCTS_MAX_SLOTS` 控制该节点并发槽位数
|
||
(管理员可经心跳配额动态下调)。
|
||
- **队列**:服务端把 pending 点推入 MQ,Worker 只要 `active_slots < effective_max_slots`
|
||
就持续 `claim` 抢占(pull 模型,天然负载均衡)。
|
||
- **沙盒隔离**:每任务独立工作目录 `data/work/task_<id>/`,fort.* 文件互不冲突,
|
||
这是并行安全的基础。
|
||
- 早期 Python 单机 `multiprocessing.Pool` 架构已废弃。
|
||
|
||
### 4.3 吞吐量估算(参考)
|
||
|
||
| 模型类型 | 单点耗时 | 参考吞吐(若干节点) | 收敛性 |
|
||
|---------|---------|-------------|--------|
|
||
| 20000-40000K(标准 sdB 区)| ~12-25 分钟 | 随节点槽位总数线性扩展 | 冷启动全区间可靠 |
|
||
| 60000K + He-rich/低金属 | ~10-15 分钟 | 同上 | 冷启动或一步种子步进 |
|
||
| 80000K + He-rich/低金属 | ~3-5 分钟(种子步进)| 同上 | 冷启动失败→种子步进成功 |
|
||
| 80000K + He-poor + logCNO=-1 | — | — | **真实物理极限,发散**(如实标注) |
|
||
|
||
---
|
||
|
||
## 5. 如何统计每阶段信息
|
||
|
||
### 5.1 当前已记录的信息(conv.json)
|
||
|
||
每个网格点完成后,`result_dir/<模型名>/conv.json`(节点归档)与
|
||
`seeds_dir/<模型名>/conv.json`(服务端)记录:
|
||
|
||
```json
|
||
{
|
||
"name": "t40000_g6.0_he0_c-1_n-1_o-1",
|
||
"params": {"teff":40000, "logg":6.0, "loghe":0, "logc":-1, "logn":-1, "logo":-1},
|
||
"converged": true,
|
||
"final_max_relc": 0.0069,
|
||
"atmosphere_has_nan": false,
|
||
"synspec_rc": 0,
|
||
"elapsed_sec": 715.0, ← 总耗时(所有阶段+synspec之和)
|
||
"seed": null, ← 冷启动为 null;走种子步进时为邻居 .7 路径
|
||
"stages": [
|
||
{
|
||
"label": "lte",
|
||
"converged": true,
|
||
"max_relc": 0.0,
|
||
"note": "NITER=0 grey start",
|
||
"elapsed_sec": 2.1
|
||
},
|
||
{
|
||
"label": "nc",
|
||
"converged": false, ← nc 不要求收敛,作种子即可(NITER=10)
|
||
"max_relc": 0.957,
|
||
"worst_depth": 1, "last_iter": 10, "n_depths": 50,
|
||
"elapsed_sec": 62.4
|
||
},
|
||
{
|
||
"label": "nl",
|
||
"converged": true,
|
||
"max_relc": 0.0069,
|
||
"worst_depth": 1, "last_iter": 17, "n_depths": 50,
|
||
"elapsed_sec": 7.8
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
> **走种子步进链时**:`seed` 指向邻居 `.7`,`stages` 里没有 `lte`,而是
|
||
> `seed_nc`(`ltgray=F` 热启动,NITER=20)→ `nl`。
|
||
> 注意:`conv.json` 不含 `seed_step_used` / `coldfail_backup` 布尔字段(旧版字段已移除);
|
||
> 收敛手段归因由服务端 `tasks` 表的 `tlusty_strategies[0]`(cold_run / seed_step)聚合统计
|
||
> (Phase 6 起 `task_type` 列已删除,策略链首项即当前执行策略的权威快照)。
|
||
|
||
每阶段记录:`converged`(是否收敛)、`max_relc`(最大相对变化)、
|
||
`worst_depth`(最差深度点)、`last_iter`(迭代次数)、`n_depths`(深度点数)、
|
||
`elapsed_sec`(本阶段耗时)。
|
||
|
||
### 5.2 每阶段时间记录(已实现)
|
||
|
||
runner 在每个阶段的循环开始/结束处计时,conv.json 里每个 stage 有
|
||
`elapsed_sec`,synspec 也有单独的 `synspec_sec`。另归档保留各阶段快照:
|
||
`<name>.<label>.5/.6/.err/.nst/.7` 与收敛诊断 `<name>.<label>_chmax*.9`(见
|
||
`tlusty_result_artifacts.md`)。
|
||
|
||
### 5.3 统计整个网格的信息
|
||
|
||
早期 `grid_status.json` 文件已废弃;当前状态统计由服务端 API 实时查询 DB 提供:
|
||
|
||
- `GET /api/workflows`:各工作流内联进度(total/completed/failed/running…,`completed` 由 7c 改名自 `converged`)
|
||
- `GET /api/workflows/:name/stats`:单工作流统计(含 `cold_run_converged` / `seed_step_converged`)
|
||
- `GET /api/workflows/:name/points`:逐点列表(可过滤 status/method/wave/q,分页)
|
||
- `GET /api/workflows/:name/progress`:进度-时间序列曲线
|
||
- 种子步进命中数 = `tasks` 表 `json_extract(tlusty_strategies,'$[0]')='seed_step'` 且 `status='completed'` 的聚合
|
||
|
||
前端 Dashboard 直接消费以上端点渲染(首页卡片、详情页概览/点表/平行集合分析图)。
|
||
|
||
### 5.4 单个网格点的详细收敛诊断
|
||
|
||
- 从节点 `result_dir/<模型>/` 读取 `<模型>.<label>_chmax*.9`(每阶段收敛诊断,
|
||
含最大相对变化随迭代下降过程)。
|
||
- 阶段日志 `<模型>.<label>.6/.err` 查看 tlusty 输出与报错。
|
||
- 光谱 `*.spec` / 连续谱 `*.cont` / b 因子 `*.bfac` / 出射谱 `*.emflux` 供物理分析。
|
||
|
||
---
|
||
|
||
## 6. 完整操作步骤
|
||
|
||
### 第1步:配置工作流(workflows/<wf>.yaml 的 grid 段)
|
||
```yaml
|
||
grid:
|
||
teff: [20000, 30000, 40000, 60000] # 各维采样点列表
|
||
logg: [5.0, 6.0]
|
||
loghe: [-2, 0]
|
||
logc: [-4, -2, -1] # 亚太阳范围(已修正;旧版 -1..1 会发散)
|
||
logn: [-4, -2, -1]
|
||
logo: [-4, -2, -1]
|
||
# 共 4*2*2*3*3*3 = 432 个点
|
||
tlusty_stage: # TLUSTY 阶段独立配置(enabled/policy/strategies)
|
||
enabled: true
|
||
policy: skip_converged
|
||
strategies: ["cold_run", "seed_step"] # 策略链:冷启动失败回退种子步进
|
||
synspec_stage: # SYNSPEC 阶段独立配置(enabled/policy/strategies)
|
||
enabled: true
|
||
policy: skip_converged
|
||
strategies: ["standard"]
|
||
synspec_input: # SYNSPEC 数值参数(fort.55 波长范围等)
|
||
wstart: 3000.0
|
||
wend: 7000.0
|
||
```
|
||
|
||
### 第2步:创建并启动工作流(HTTP API / Dashboard)
|
||
```bash
|
||
# 创建/保存工作流(config_yaml 上传)
|
||
curl -X POST localhost:8090/api/workflows -H "Authorization: Bearer $ADMIN_TOKEN" \
|
||
-F name=sdB_cno -F config_yaml=@workflows/sdB_cno.yaml
|
||
|
||
# 启动(进入 initializing → running,后台异步建网格并派发)
|
||
curl -X POST localhost:8090/api/workflows/sdB_cno/start \
|
||
-H "Authorization: Bearer $ADMIN_TOKEN"
|
||
```
|
||
也可直接在 Dashboard「工作流 → 启动配置 → 启动」操作。启动后调度器按 wave(难度)
|
||
顺序把点推入 MQ,各节点 pull 抢占计算。
|
||
|
||
### 第3步:监控
|
||
- Dashboard:工作流卡片进度条、详情页概览(统计/进度曲线/ETA)、逐点表、平行集合分析图。
|
||
- API:`GET /api/workflows/:name/stats` / `:name/points` / `:name/progress`。
|
||
- 服务端日志:`RUST_LOG=info ./server`。
|
||
|
||
### 第4步:断点续算 / 增量
|
||
- 工作流默认 `policy: skip_converged`:启动时跳过已收敛点、重试已失败点。
|
||
- 加密网格:往 `grid` 各维列表加更多点后保存并重启工作流(自动跳过已完成,只算新点)。
|
||
- 高温区加密建议先冷启动算 He-rich/低金属的"桥头堡"模型,建立种子库再扩散到
|
||
难收敛点(见 §7.1)。
|
||
|
||
### 单点调试
|
||
```bash
|
||
# 把单个点置回 pending 重跑(或在 Dashboard 详情页查看该点尝试历史/阶段诊断)
|
||
curl -X POST localhost:8090/api/workflows/sdB_cno/points \
|
||
-H "Authorization: Bearer $ADMIN_TOKEN" -F point_name=t40000_...
|
||
```
|
||
> 早期 Python 的 `run_grid.py` / `run_one.py` / `seed_step.py` 脚本与 `src/` 目录已废弃。
|
||
|
||
---
|
||
|
||
## 7. 注意事项
|
||
|
||
1. **种子步进回退(核心机制)**:`tlusty_strategies` 链含 `seed_step` 时(默认推荐
|
||
`["cold_run", "seed_step"]`),冷启动失败的点会自动回退到种子步进链:服务端在全局
|
||
种子库找近邻已收敛 `.7`,`ltgray=F + ichang=0` 热启动重跑。这是高温/He-poor/富金属区的
|
||
决定性破局手段(详见 §2.1)。
|
||
**种子匹配**:两级匹配——exact_family(同 Teff/logg/logHe 族,CNO 用有向距离:富方向
|
||
重罚 4×、贫方向 1×)与 global 加权距离(`d_teff/5000 + d_logg×2 + d_loghe×0.5 +
|
||
d_cno×0.1 ≤ 3.0`),不再是早期简单的绝对跨度阈值(见 `seed_finder.rs` / `design.md §3`)。
|
||
跨度过大(如 cno-4 直接跳 cno-1,1000× 金属跳跃)即便种子步进也发散 → 这是真实物理
|
||
极限,网格如实标注。
|
||
**种子库建立策略**:高温区建议先冷启动算 He-rich 或低金属的"桥头堡"模型,建立种子库
|
||
再扩散到难收敛点(如 cno-4 → cno-2 → cno-1 多步跳板)。
|
||
|
||
2. **断点续算判定**:`conv.json` 里 `converged=true` 的点会被跳过。假收敛
|
||
(`atmosphere_has_nan=true`)的点会被重算。
|
||
|
||
3. **失败处理**:单点失败(发散/崩溃)不中断整个网格;当前策略失败触发策略链回退,
|
||
链耗尽则标记 failed。高温难点的失败大多是真实物理极限(见 §2.1),不强制成功。
|
||
|
||
4. **磁盘空间**:节点端归档 `result_dir` 永久保留(无 LRU 淘汰),每个模型约
|
||
2-10MB 白名单产物(`.spec/.cont/.iden/.7/.bfac/.emflux/各阶段快照/日志`)。沙盒
|
||
`task_*` 工作目录结算后清理,节点重启时清理残留。
|
||
|
||
5. **并行安全**:每任务独立沙盒(`data/work/task_<id>/`),fort.* 文件不冲突。可安全并行。
|
||
|
||
6. **nst 文件行长限制(已修复)**:tlusty 的 nst 解析器有 ~72 字符的行宽限制。
|
||
如果参数太多写在一行(如加了 IDLTE/IACC 后 >72 字符),行尾的参数会被
|
||
静默截断。`nst_writer` 把参数分两行写(line1≤64c, line2 余下参数)。
|
||
这是个隐蔽 bug——截断后 tlusty 不报错而是用默认值,导致"看似成功实则参数
|
||
没生效"。
|
||
|
||
7. **fort.84 残留(已修复)**:tlusty 运行时会在工作目录写 fort.84(nst 参数的
|
||
内部表示)。如果下一次 tlusty 运行(不同 NATOMS)读到旧的 fort.84,会报
|
||
"Bad integer for item 48" 崩溃。runner 每次运行前删除 fort.84。
|
||
|
||
8. **收敛可靠性(如实)**:用正确配方(无 CHMAX/ITEK, NFREAD=2000, nc NITER=10)
|
||
后,20000-40000K 全区间冷启动可靠收敛;60000-80000K + He-rich/低金属用
|
||
种子步进可解决;**80000K + He-poor + logCNO=-1 是真实物理极限**
|
||
(CNO 高价离子主导不透明度,金属 ×10 跳跃线性化无法阻尼),网格如实标记
|
||
未收敛。之前版本的"8/8 边界全部成功"不准确(基于错误的 CHMAX=0.1)。
|
||
`ICRSW`(Hummer & Voels 切换)在 tlusty208 **原版中是死代码**
|
||
(SUBROUTINE SWITCH 从未被 CALL,CRSW≡1.0),不要依赖它稳定化;
|
||
即便源码修复启用后实测对难点也无帮助。详见 EXPERIENCE.md。
|