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),並使用處於模式 1 且帶有空白外部檔案的 CLI 檢查它。 切勿信任那些已「使用.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 的種子化條目),即使在文獻中沒有列出到該道的分支。
- 在擬合範圍內開啟的每個道都應包含在模型中——這是預設行為。 每當擬合範圍擴展時(一個新的能量窗口,或一個達到更高能量的數據集),列出在範圍頂部以下開啟的所有分割:每個殘留核的每個激發態(ENSDF)和其他輕粒子分割(d、t、³He、...),閾值為 Ex = sepE + e2。在擬合之前,為每個道添加一對,無需詢問:每個能級上每個道自旋的最低允許 L;根據第 2 項在閾值處或低於閾值 0.5 MeV 範圍內的能級以及背景極點上進行種子化,在其他地方設為惰性(0,固定)。將新的出口添加至每個求和段(總截面、總 (n, p)、(n, α)、...)。切勿在閾值處截斷數據窗口。截斷是權宜之計:在 readme 中記錄它以及迫使截斷的道,並將其列入評估員的待辦事項列表。
(DeBoer 2026-10-30,11B+α 高能擴展: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,2-27-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:普通 chi2 從 701k 在一次優化後變為 1,190k,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 的能級,其能量保持固定)的 Wigner 極限框——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 的第一階段)
在 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、...)、停止規則和現有決策及其所有者和日期。然後:
python3 -m rmfit.audit <base>.azr --out AUDIT.md # 預飛,無引擎會話:零自由寬度、1 keV 合併、
# 標稱歸一化 != 1、normError 作為分數、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。
自 2026-11-07 起,第 3b 節的三項空閒時間審查是生成的,而非手寫的:
python3 -m rmfit.cli <dir> audit --kind all # audits/{input,data,literature}/PROMPT.md + empty 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
…
[為翻譯而截斷]