rtx-fsi: pin FSI3's release response and settled cycle
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

Two tiers in the FSI2 pattern. The committed default (t_end 4.2) pins
the deterministic release response at the digit-stable measurement
(uy 10.7684 +- 23.5726 mm, ux -2.8982; +-35% bands, 2x onset-growth
floor against a measured 4.6x). The sticky-mask study configuration
(HYST>0, subcycle 2, t_end >= 8.4, ny 62 or 82) pins the settled
flapping cycle measured across two grids at t_end 8.5 / window(2.0):
uy amp in [38, 72] mm (measured 50.2 / 57.6; the un-flapped release
and every pre-hysteresis dead march sit far below, and the reference
+-34.9 sits OUTSIDE — landing inside the reference band is a loud
finding, not a regression), mids, crossing-frequency in [4.4, 6.8]
(covers the estimator's measured beat-scatter — the DFT puts both
grids at 5.4-5.6 vs ref 5.46), and drag MEDIAN in [380, 530]
(measured 454.0 vs ref 460.2). WindowStats gains drag/lift medians —
the honest central loads (the extreme-based mids are noise-dominated
at large deformation).

Band anchors computed exactly as the test computes them, replayed
offline against the run 7/8/10 CSVs (deterministic trajectories).
Verified: both committed defaults green with the release pins live,
trajectories digit-identical (FSI3's loads line gains the medians,
FSI2's output byte-identical). The t_end 8.5 study pin runs at both
grids are in flight.

Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01X2GmJXeQ2njUecEKiJZ1G2
This commit is contained in:
Omar Sobh
2026-08-28 07:56:51 -05:00
co-authored by Claude Fable 5
parent 137a62c4ea
commit a49602cf16
2 changed files with 115 additions and 6 deletions
@@ -23,9 +23,14 @@
//! # What is pinned
//!
//! Machinery invariants every run (conservation, finite state, coupling
//! bookkeeping). Physics bands arrive with the measurements — this
//! file's first commits carry the harness through the release response
//! only; the study record lives in omni-cortex `solver_status.md`.
//! bookkeeping). The committed default (t_end = 4.2) pins the
//! deterministic release response (uy 10.77 ± 23.57 mm, ±35% bands).
//! Study horizons under the sticky mask (`RTX_FSI3_HYST=0.25
//! RTX_FSI3_STALLX=10 RTX_FSI3_T_END=8.5`, ny 62 or 82) pin the
//! settled flapping cycle measured 2026-08-27/28 — uy amp 5058 mm
//! across the grids (reference 34.90; two-grid agreement 2.3% by p95,
//! the gap grid-converged), honest drag median 454 vs reference 460.2.
//! The full study record lives in omni-cortex `solver_status.md`.
//!
//! Environment knobs: `RTX_FSI3_*` — the same set as `RTX_FSI2_*` (see
//! `turek_hron_fsi2.rs`) plus `RTX_FSI3_OMEGA0`, `RTX_FSI3_TRACE`,
@@ -148,9 +153,9 @@ fn fsi3_added_mass_flag() {
let w = result.window(2.0);
println!(
" loads over the window: drag {:.2} ± {:.2} (ref {REF_DRAG_MEAN} ± {REF_DRAG_AMP}), \
lift {:.2} ± {:.2} (ref {REF_LIFT_MEAN} ± {REF_LIFT_AMP})",
w.drag_mid, w.drag_amp, w.lift_mid, w.lift_amp
" loads over the window: drag {:.2} ± {:.2} median {:.2} (ref {REF_DRAG_MEAN} ± \
{REF_DRAG_AMP}), lift {:.2} ± {:.2} median {:.2} (ref {REF_LIFT_MEAN} ± {REF_LIFT_AMP})",
w.drag_mid, w.drag_amp, w.drag_median, w.lift_mid, w.lift_amp, w.lift_median
);
println!(
" FSI3 (fluid ny = {ny}, flag {flag_nx}x2 Quad8, dt = {:.2e}, {}): coupled {} \
@@ -206,4 +211,97 @@ fn fsi3_added_mass_flag() {
result.coupled_steps,
result.worst_stall
);
// Physics bands, by horizon and configuration (the FSI2 pattern:
// the march is deterministic, so the short committed horizon
// carries tight regression bands on the release response; study
// horizons pin the MEASURED settled cycle, band-generous across
// the two grids that measured it. If a change moves any of these
// numbers, that is a finding either way and must be loud.)
let default_release = config.subcycle == 2
&& config.mask_hysteresis == 0.0
&& config.coupler == "iqn"
&& ny == 62
&& flag_nx == 35
&& (t_end - 4.2).abs() < 1e-9;
let hyst_cycle = config.subcycle == 2
&& config.mask_hysteresis > 0.0
&& config.coupler == "iqn"
&& flag_nx == 35
&& (ny == 62 || ny == 82)
&& t_end >= 8.4;
if default_release {
// The committed default: the release response over [4.0, 4.2],
// measured 2026-08-26 and digit-stable across four bit-identity
// re-verifications: uy 10.7684 ± 23.5726 mm, ux -2.8982 mm,
// onset amp 3.698e-3 -> 1.716e-2 (4.6x growth). Bands are ±35%
// for cross-platform floating-point drift in a growing
// transient (the FSI2 default's margin), not an accuracy claim.
assert!(
(7.0e-3..=14.6e-3).contains(&w.uy_mid),
"release uy mid {:.4e} left [7.0e-3, 14.6e-3] (measured 1.0768e-2)",
w.uy_mid
);
assert!(
(15.3e-3..=31.9e-3).contains(&w.uy_amp),
"release uy amp {:.4e} left [15.3e-3, 31.9e-3] (measured 2.3573e-2)",
w.uy_amp
);
assert!(
(-3.92e-3..=-1.88e-3).contains(&w.ux_mid),
"release ux mid {:.4e} left [-3.92e-3, -1.88e-3] (measured -2.8982e-3)",
w.ux_mid
);
assert!(
w.amp_late > 2.0 * w.amp_early,
"the release is not growing: onset amp {:.3e} -> {:.3e} (measured 4.6x)",
w.amp_early,
w.amp_late
);
} else if hyst_cycle {
// Study horizons, the sticky-mask configuration (band 0.25h,
// STALLX 10): the settled flapping cycle, measured 2026-08-27/28
// at t_end = 8.5 / window(2.0) — ny 62: uy 3.07 ± 50.25 mm
// (run 7), ny 82: 8.13 ± 57.55 mm (run 8); reference
// 1.45 ± 34.90. The AMPLITUDE discriminates: the un-flapped
// release and every pre-hysteresis dead march sit far below
// 38 mm, and the reference itself sits outside the band — a
// change landing INSIDE the reference band is a loud finding,
// not a regression.
assert!(
(38.0e-3..=72.0e-3).contains(&w.uy_amp),
"cycle uy amp {:.4e} left [38e-3, 72e-3] (measured 50.2e-3 / 57.6e-3 at ny 62/82)",
w.uy_amp
);
assert!(
(-8.0e-3..=22.0e-3).contains(&w.uy_mid),
"cycle uy mid {:.4e} left [-8e-3, 22e-3] (measured 3.1e-3 / 8.1e-3)",
w.uy_mid
);
assert!(
(-14.0e-3..=-2.0e-3).contains(&w.ux_mid),
"cycle ux mid {:.4e} left [-14e-3, -2e-3] (measured -4.9e-3 / -9.4e-3)",
w.ux_mid
);
// The crossing estimator is beat-biased on 2 s windows (it read
// 4.87 / 6.25 Hz where the DFT puts both grids at 5.4-5.6, ref
// 5.46); its band covers the estimator's measured scatter, not
// the physics.
if let Some(f) = w.frequency {
assert!(
(4.4..=6.8).contains(&f),
"cycle crossing-frequency {f:.3} left [4.4, 6.8] (measured 4.87 / 6.25)"
);
}
// The honest central drag (window median of the interval-median
// record): 454.0 at ny 62 (run 10) vs reference 460.2 — a loud
// tripwire on the load path, not an amplitude claim (the
// oscillation amplitudes are surface-route-unmeasurable; see
// omni-cortex solver_status.md).
assert!(
(380.0..=530.0).contains(&w.drag_median),
"cycle drag median {:.1} left [380, 530] (measured 454.0, ref 460.2)",
w.drag_median
);
}
}