rmfit流程
rmfit(位于/groups/rdeboer1/user/rdeboer1/R-matrix/rmfit/,详见README)实现了评估员手动完成的步骤——抛光、翻转干涉符号、添加或移除能级、关闭可疑数据集——将这些步骤组织为可恢复的子流程,由一个脚本在单个集群节点上运行,新的会话可以从STATUS.md处继续执行。它不作为包安装:
export PYTHONPATH=/groups/rdeboer1/user/rdeboer1/R-matrix
python3 -m rmfit.cli <campaign_dir> <command> [options]
在针对新反应执行第一个命令之前,请从上到下阅读本文档;对于恢复活动而言,“读取状态”和“循环”部分已足够。方法优化记录在日志末尾。
1. 读取状态,绝不重新计算
一个活动目录包含了新会话所需的一切:
STATUS.md—— 每个结构的最佳验证目标、最近的轮次和日志行。使用status重新生成;status --json生成紧凑转储。readme—— 实验笔记本(rmfit 每轮追加一个段落;你自己添加的内容使用log "...")。归档惯例:在接触任何内容之前先阅读它。campaign.log—— 驱动程序打印的每一行;rmfit_sge.log/rmfit_*.log—— 集群作业日志。ledger.sqlite+candidates/*.npz—— 每个候选向量及其得分。当前最优解是得分经verified(一个全新的单会话全模型评估)验证的最佳候选者。分片得分用于排序;已验证得分用于报告。campaign.json—— 基础模型、引擎标志、分片数量、边界策略、搜索配置。<reaction>.azr+.sav—— 当前最优解的GUI可审查导出。variants/—— 分片文件、窗口模型、含/不含能级文件(可丢弃的)。
首先运行 qstat -u $USER:每个目录一次只运行一个活动命令(它们共享账本和 variants/)。登录节点用于 status、report、log、export 以及短时间测试(最多6个工作线程,最多30分钟)。其他所有操作都作为作业运行。
2. 启动一个新的反应活动
先决条件(在反应的拟合目录中执行这些操作,而不是在活动目录中):
- 一个可以在GUI中打开的
.azr文件,包含data/目录、一个output/目录和一个readme文件。了解此反应使用的CLI模式标志(--use-brune、--ignore-externals、--no-long-wavelength等):它们不在.azr文件中,因反应而异(参见~/R-matrix/CLAUDE.md),rmfit 需要它们作为--flagsJSON。 - 在构建之上之前,重现上一次完成的拟合:通过名称加载其
param.sav文件(pyazr),确认目标值与chiSquared.out(chi2 + 正态罚项)匹配,然后将其烘焙到一个干净文件中(rmfit.engine.bake),并使用CLI在模式1下使用空白外部文件进行检查。永远不要相信一个“已验证”但使用.sav作为外部文件的烘焙结果(这会覆盖<levels>部分),也永远不要使用来自正在运行或已崩溃拟合的参数——只使用最后完成的拟合的参数。清除无效的能级行。 - 将任何新的数据集合并到烘焙文件上(
AzrModel.add_data_segment),限于能级方案覆盖的能量范围(set_segment_energy_range),归一化设置为自由,系统误差反映论文中的值。检查每个新文件:单个负值或尖峰截面可能主导目标值。 - 将所有这些记录在反应目录的
readme中。
首次拟合:在任何全局拟合之前构建初始参数(DeBoer, 2026-10-25 —— 后续重新评估)
临时性的。 这是DeBoer的一般性建议,在端到端尝试之前记录下来。一旦10B+α(第一个使用此方法的反应,10B+a/10-25-26_Rmatrix_Claude)有了真实的拟合结果,请在此记录有效和无效的部分,并相应地更改或放弃该流程。
DeBoer:“固定一个代表性数据集的归一化,但让其他数据集变化。这最初为截面提供了更固定的标度,但仍允许那些归一化不一致但形状一致的数据集不妨碍拟合。在我们的案例中,由于我们在每个道中都有数据,我建议我们首先固定自己的数据,让其他数据集变化。此外,我们应该确保允许每个粒子对的最低l道变化,为每个能级赋予一个小的非零值,即使文献没有给出该能级到该道的分支。我还建议从低能量开始,逐个对能级进行一些抛光,看看它如何匹配数据。然后回来尝试添加能级,在那些明显存在共振但能量和/或宽度与任何已知能级都不匹配的地方。在拥有合理好的初始参数之前,我不会尝试真正的拟合。”
作为流程:
- 用一组代表性数据集固定标度。 固定其归一化为1(当我们的数据覆盖每个道时,使用我们自己的数据);让其他每个数据集的归一化自由变化。那些形状一致但标度不同的数据集就不会阻碍拟合。
- 为每个对的最低L道播种,针对每个能级。 赋予它一个小的非零振幅(0.01 γ_W,在引擎中设置;物理占位符非常小,参见2026-10-25的播种条目),即使文献没有列出到该道的分支。
- 拟合范围内的每个道默认都包含在模型中。 每当拟合范围扩展(新的能量窗口,或达到更高能量的数据集)时,列出在范围顶部以下开放的每个分划(partition):每个剩余核的每个激发态(ENSDF)和其他轻粒子分划(d, t, ³He, ...),阈值为 Ex = sepE + e2。在拟合之前为每个分划添加一个对,无需询问:每个能级上每个道自旋的最低允许L;在阈值处或低于阈值0.5 MeV内的能级和背景极点上按照第2条播种,其他地方为惰性(0,固定)。将新的出口添加到每个求和段(总截面、总(n,p)、(n,α), ...)。不要在阈值处截断数据窗口。截断是权宜之计:在readme中记录它以及迫使其截断的道,并将其列出供评估员审查。
(DeBoer 2026-10-30,11B+α HE扩展:ELBE ¹⁴N+n总截面曾在E_n 5.1 MeV处被截断,因为¹⁴N(n,n₄)没有对。这使得拟合的顶部1.2 MeV缺少其最强约束,即一个归一化固定的总截面。构建器示例:
11B+a/10-27-26_HE_claude/model/add_pairs_he.py,7个对 n4 a3 d0 p1 n5 n6 p2。) - 从低能量向上,逐个能级进行。 一次抛光一个能级(其能量和宽度,加上自由归一化),针对周围的数据,查看它匹配得如何。
- 然后添加能级,在那些明显存在共振且已知能级在能量和/或宽度上与之不匹配的地方。
- 只有在此之后才进行真正的(全局)拟合:对结果执行
init活动。
原因(10B+α 阶段1,2026-10-25):从糟糕起点(χ²/N ≈ 200,2027-02-25的能级加上接近零的新道)开始的全局抛光,用缺失的强度换取了归一化。当所有归一化都自由时,在150次评估中几乎所有归一化都下降到0.38-0.68。限制在0.7-1.5时,八个归一化卡在边界上,拟合在χ²/N 12.7处停滞。当χ² ~ 10⁵时,百分之几的归一化先验几乎不增加代价(10B+a/10-25-26_rmfit_stage1,_stage1b)。
然后,在一个新的带日期的活动目录中(<reaction>/<M>-<D>-<YY>_rmfit_campaign/):
mkdir <dir> && cp <base>.azr <dir>/ && cp -r data <dir>/data && mkdir <dir>/output
python3 -m rmfit.cli <dir> init --base <dir>/<base>.azr [--sav <base>.sav] --nshards 24 \
--flags '{"use_long_wavelength": false, "ignore_externals": true, "use_brune": true}' \
--policy '{"theta2_cap": 1.0, "bg_theta2_cap": 3.0, "bg_energy": <Ex above the data>, "e_window": 0.3, "norm_range": [0.2, 5.0]}' \
--search '{"top_k": 6, "pairs_per_group": 4, "stage1_nfev": 30, "stage2_nfev": 60, "union_nfev": 100}'
--flags 直接传递给 pyazr.azure2(),因此参数化在其中选择:"use_brune": true(Brune,归档默认值)、"use_park": true(Park:拟合向量保存观测到的约化宽度振幅,Gamma = 2 P gamma^2;参见AZURE2技能的“Park参数化”)、"use_brune": false(标准Lane-Thomas)。每个活动使用一种基组——账本的向量、.npz快照和.sav伴侣文件都基于此基组。
可选的 --objective JSON(campaign.json 中的 objective,deBoer等人2017年拟合部分):{"dataset_weight": "reduced", "dataset_key": "file", "loss": "sivia"}。dataset_weight: reduced 是约化卡方方法(每个数据集的卡方除以其点数,再按N/K重新缩放,以使目标值保持卡方量级;罚项行不加权)——它阻止具有小误差的大数据集占主导地位;loss: sivia 用Sivia更宽的PDF替换卡方,-2 log[(1 - e^{-R^2/2})/R^2] - 2 log 2(小残差时 ~R^2/2,异常值时 ~2 log R^2:异常值被降权,如同其误差棒被膨胀一样)。Sivia损失应用于由每个数据集的参考chi2/N标准化后的残差(loss_scale: dataset,由 init 从普通基准线计算并存储在campaign.json中):如果不这样做,对于chi2/N ~ 20-300的模型,每个点都位于对数尾部,数据相对于二次正态罚项损失约10倍的权重,拟合会发生漂移(13C+a,2026-09-08:普通卡方701k -> 1190k,一次抛光MANA即被放弃,归一化跳到标称值)。两种方法都“在统计上不正确,但在误差棒被低估时有用”。目标值是活动的一个属性:在不同目标值下验证的候选者不可比较,因此目标值的更改意味着一个新的活动目录(使用先前的导出作为种子)。无论目标值如何,REPORT.md 和 segment_scores 都保持每个数据集的普通卡方值。在 rmfit/tests/test_objective_13n.py 中验证。
init 验证基准线(一次全模型评估),注册结构,写入 STATUS.md 和作业脚本 run_crc_rmfit(24核 long 节点,邮件发送至 [email protected],-m abe)。重新运行 init 会保留现有的配置,除非提供了新值。策略含义:theta2_cap 是物理能级的Wigner极限盒,bg_theta2_cap 用于背景极点(Ex >= bg_energy 的能级,其能量保持固定)——3.0是初始猜测,不是物理默认值:在信任它之前,请检查基准线的背景振幅已经位于何处(init 的帽子审计);12C+alpha弹性散射可能需要大约100(参见2026-09-30的日志条目);e_window 是每次抛光时一个能级的能量自由度(MeV);norm_range 倍乘标称归一化。narrow_window(可选,例如 {"gamma_kev": 5, "factor": 3, "min_kev": 1})使一个自由部分宽度之和小于 gamma_kev 的能级保持在当前能量 ±max(min_kev, factor·Γ) 的范围内,而不是 ±e_window,这样一次抛光就不能将一个窄能级带离其峰值(13C+a 9/2+ 在一次收紧边界抛光中漂移了180 keV)。分片数 = 核心数;分片是精确的(卡方对段是可加的),因此更多的分片只加快速度。
对新模型的成本检查(init 后的 campaign.log):一次分片目标值计算应该在几秒内,雅可比矩阵在几十秒内。如果一个具有目标效应卷积的段占主导地位(正如Cierjacks在13C+a上的情况),rmfit自身会对其进行折叠(model.ConvSpec);复合“求和”段允许作为卷积片。
2b. 规范、审计、决策(2026-11-07;R-matrix/rmfit/DESIGN.md 的阶段1)
在 init 之前,编写活动的规范(spec.json,模板 rmfit/templates/SPEC_TEMPLATE.json,模式定义在 rmfit/spec.py):每个数据集及其角色(anchor = 归一化固定在标称值;free 带有 prior_sigma;excluded 带有原因;screen)、拟合窗口、冻结块、必须存在的对、边界/目标值/搜索、驱动程序可以自主执行的操作(pre_authorized:adopt_level true / false / 规则、flip_adopt、dataset_off_adopt,...)、停止规则以及常设决策(standing decisions)及其所有者和日期。然后:
python3 -m rmfit.audit <base>.azr --out AUDIT.md # 预检,无引擎会话:零自由宽度,1 keV合并,
# 标称归一化 != 1,normError作为FRACTION,FLAG列作为
# 错误,微小误差,重复,尖峰,阈值,测试段上的 <targetInt>
# 传统.sav名称,输出路径,引擎引脚
python3 -m rmfit.cli <dir> init --base ... --spec spec.json # flags/policy/search/objective/nshards 优先
# 来自规范,除非另外给出;与.azr的HIGH级分歧会拒绝init
python3 -m rmfit.cli <dir> spec check # 任何时候:SPEC_CHECK.md;规范渲染 -> SPEC.md;审计 -> AUDIT.md
HIGH级审计发现必须在基准线之前修复(或记录在规范的常设决策中作为已接受)。在活动期间,规范未回答的任何问题都转到 DECISIONS.md(rmfit decisions 列出,rmfit decide D-003 "adopt" --by DeBoer 回答);一个能级添加,如果规范未预授权其 accept,则记录为 accept-pending,并加入一个排队的决策,并且不会被采纳(旧的自动采纳仅适用于没有规范的活动)。可复制使用的规范草稿:10B+a/11-6-26_s5_highE/spec_draft.json、13C+a/11-06-26_merged_regionD/spec_draft.json。
第3b节中的三项空闲时间审查是生成的,而不是手写的,自2026-11-07起:
python3 -m rmfit.cli <dir> audit --kind all # audits/{input,data,literature}/PROMPT.md + 空 FINDINGS.md
# 将每个 PROMPT.md 交给后台子代理(Agent工具,更便宜的模型,最多三个同时运行);它写入 FINDINGS.md
python3 -m rmfit.cli <dir> audit --findings # 每个 FINDINGS.md 中未验证的(候选)行
python3 -m rmfit.cli <dir> audit --status data 1 confirmed --note "line 4007 check