rtx-fsi: decouple the retry threshold from the widened stall acceptance
Performance Benchmarks / Run Benchmarks (push) Canceled after 0s
CI / Format Check (push) Canceled after 0s
CI / Clippy Check (push) Canceled after 0s
CI / Build (macos-latest) (push) Canceled after 0s
CI / Build (ubuntu-latest) (push) Canceled after 0s
CI / Test (macos-latest) (push) Canceled after 0s
CI / Test (ubuntu-latest) (push) Canceled after 0s
CI / Build CPU-Only (Explicit) (push) Canceled after 0s
CI / Python Bindings (maturin) (macos-latest) (push) Canceled after 0s
CI / Python Bindings (maturin) (ubuntu-latest) (push) Canceled after 0s
CI / WASM Build + Size Check (push) Canceled after 0s
CI / Distributed Training Tests (push) Canceled after 0s
CI / CI Success (push) Canceled after 0s
Documentation / Build API Documentation (push) Canceled after 0s
Documentation / Build User Guide (push) Canceled after 0s

The first STALLX draft used one threshold for both, which silently
disabled the history-reset retry for the widened band: a stall in
[5x, STALLX x) was accepted unretried where runs 2/3 retried it —
caught by trajectory divergence at t = 5.7 (runs 2/3 digit-identical
there; the run-5 variant killed at 2.3 h, artifacts preserved as
*_unretried_variant_*). Now `retry_at` stays the old 5x-or-increment
window (retry semantics bit-identical to the pre-knob code at any
STALLX), and `stall_accept` widens only the post-retry acceptance.
Default STALLX=5 keeps both thresholds equal — committed defaults
unchanged.

Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Lnyrw33Lu6rUhW42E9KHwq
This commit is contained in:
Omar Sobh
2026-08-25 07:41:34 -05:00
co-authored by Claude Fable 5
parent 992cd76449
commit 3207f2d4c6
@@ -451,13 +451,20 @@ pub fn run_march(case: BenchmarkCase, config: &MarchConfig) -> MarchResult {
.sum::<f64>()
.sqrt();
let tol_step = tol_floor.max(rtol * increment);
// Acceptance beyond the tolerance: `stall_accept` x the
// tolerance (noise bouncing over a well-predicted step; see the
// config field for why FSI3's cycle needs a wider multiple than
// the default 5) or an order below the step's own increment
// (the rare violent step near peak motion — the s = 1 FSI2 run
// died at residual = 9% of its increment). Counted as stalls
// and bounded by the caller.
// Two thresholds, deliberately decoupled (the first STALLX
// draft used one and silently DISABLED the history-reset retry
// for the widened band — caught by trajectory divergence at
// t = 5.7 where runs 2/3 were digit-identical):
// `retry_at` is the OLD acceptance (5x the tolerance, or an
// order below the step's own increment — the rare violent step
// near peak motion; the s = 1 FSI2 run died at residual = 9% of
// its increment): any stall at or above it still gets the
// measured-valuable history reset + one retry from the
// predictor. `acceptable` (stall_accept x, default the same 5x
// — bit-identical) widens only the POST-RETRY acceptance, so a
// developed-cycle bistable stall the retry cannot fix is
// accepted and counted instead of fatal.
let retry_at = (5.0 * tol_step).max(0.1 * increment);
let acceptable = (stall_accept * tol_step).max(0.1 * increment);
let mut outcome = if let Some(iqn) = iqn.as_mut() {
iqn.set_tolerance(tol_step).unwrap();
@@ -481,7 +488,7 @@ pub fn run_march(case: BenchmarkCase, config: &MarchConfig) -> MarchResult {
e,
rtx_fsi::FsiError::CouplingNotConverged { residual, .. }
| rtx_fsi::FsiError::CouplingDiverged { residual, .. }
if *residual >= acceptable
if *residual >= retry_at
);
if recoverable {
iqn_ref.reset_history();