fsi2 harness: RTX_FSI2O_PATCH_CONVECTION knob (tvd default / upwind / none) on the overset patch, printed in the march's coupling header and the replay's PRESCRIBED header — P5-3's near-wake dispersion test on the ny 62 fixed-motion replay; harness files under the pinned toolchain's cargo fmt
CI / Build CPU-Only (Explicit) (push) Failing after 4s
Documentation / Build User Guide (push) Successful in 6s
CI / Clippy Check (push) Failing after 44s
Performance Benchmarks / Run Benchmarks (push) Successful in 2m57s
CI / Build (ubuntu-latest) (push) Failing after 2m6s
Documentation / Build API Documentation (push) Failing after 5s
CI / Format Check (push) Failing after 11s
CI / Build (macos-latest) (push) Failing after 10s
CI / Test (macos-latest) (push) Skipped
CI / Test (ubuntu-latest) (push) Skipped
CI / Python Bindings (maturin) (macos-latest) (push) Skipped
CI / Python Bindings (maturin) (ubuntu-latest) (push) Skipped
CI / WASM Build + Size Check (push) Skipped
CI / Distributed Training Tests (push) Skipped
CI / CI Success (push) Failing after 1s

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01LzcjQX7tvgn87CQCyg9Cfr
This commit is contained in:
Omar Sobh
2026-09-12 21:18:03 -05:00
co-authored by Claude Fable 5.1
parent 754dcd3679
commit ff7cc2d739
4 changed files with 71 additions and 41 deletions
@@ -8,8 +8,8 @@
mod fsi2_harness;
use fsi2_harness::overset_march::{run_march_overset, OversetMarchConfig};
use fsi2_harness::{case_from_env, FSI2};
use fsi2_harness::overset_march::{OversetMarchConfig, run_march_overset};
use fsi2_harness::{FSI2, case_from_env};
const REF_UY_AMP: f64 = 80.6e-3;
const REF_UY_FREQ: f64 = 2.0;
@@ -245,12 +245,7 @@ fn fsi2_overset_probe_death_from_instant() {
// that would build.
let mut extra = String::new();
if let Some(a0) = msg.find("acceptor ") {
let k: usize = msg[a0 + 9..]
.split(' ')
.next()
.unwrap()
.parse()
.unwrap();
let k: usize = msg[a0 + 9..].split(' ').next().unwrap().parse().unwrap();
let c = mesh.cell(mesh.nn() - 1, k);
let ac = mesh.centre(c);
let inner = mesh.node_xy(mesh.node(0, k));
@@ -268,7 +263,15 @@ fn fsi2_overset_probe_death_from_instant() {
}
extra = format!(
" — acceptor {k} centre ({:.3}, {:.3}); its ray: wall node ({:.3}, {:.3}), outer ({:.3}, {:.3}), thickness {:.2} h, hole depth {:.2} h, band {:.2} h; overlap_rows that build: {rows_ok:?}",
ac[0], ac[1], inner[0], inner[1], outer[0], outer[1], thick / h, hole_depth / h, (thick - hole_depth) / h
ac[0],
ac[1],
inner[0],
inner[1],
outer[0],
outer[1],
thick / h,
hole_depth / h,
(thick - hole_depth) / h
);
}
if let Some(i0) = msg.find("cell (") {
@@ -294,11 +297,19 @@ fn fsi2_overset_probe_death_from_instant() {
let inner = mesh.node_xy(mesh.node(0, s));
let outer = mesh.node_xy(mesh.node(mesh.nn(), s));
let r8 = mesh.node_xy(mesh.node(8, s));
let thick = ((outer[0] - inner[0]).powi(2) + (outer[1] - inner[1]).powi(2)).sqrt();
let hole_depth = ((r8[0] - inner[0]).powi(2) + (r8[1] - inner[1]).powi(2)).sqrt();
let thick =
((outer[0] - inner[0]).powi(2) + (outer[1] - inner[1]).powi(2)).sqrt();
let hole_depth =
((r8[0] - inner[0]).powi(2) + (r8[1] - inner[1]).powi(2)).sqrt();
extra += &format!(
" — cell ({j}, {i}) at ({x:.3}, {y:.3}); nearest wall node s = {s} at ({:.3}, {:.3}); ray thickness {:.3} h, hole depth (row 8) {:.3} h, overlap band {:.3} h; outer node ({:.3}, {:.3})",
inner[0], inner[1], thick / h, hole_depth / h, (thick - hole_depth) / h, outer[0], outer[1]
inner[0],
inner[1],
thick / h,
hole_depth / h,
(thick - hole_depth) / h,
outer[0],
outer[1]
);
let _ = CellClass::Hole;
}
@@ -318,7 +329,7 @@ fn fsi2_overset_probe_death_from_instant() {
/// derivative between knots (the GCL's premise for a prescribed wall).
#[test]
fn replay_passes_through_knots_with_their_velocities() {
use fsi2_harness::replay::{ramp, Replay};
use fsi2_harness::replay::{Replay, ramp};
let f = |t: f64| vec![(3.0 * t).sin(), 0.5 * t * t];
let df = |t: f64| vec![3.0 * (3.0 * t).cos(), t];
let knots: Vec<(f64, Vec<f64>, Vec<f64>)> = [0.0, 0.4, 0.9, 1.5]
@@ -364,7 +375,7 @@ fn replay_passes_through_knots_with_their_velocities() {
#[test]
fn fsi2_overset_prescribed_motion() {
use fsi2_harness::overset::OversetFluid;
use fsi2_harness::replay::{ramp, Replay};
use fsi2_harness::replay::{Replay, ramp};
let Ok(replay_dir) = std::env::var("RTX_FSI2O_REPLAY") else {
println!(" RTX_FSI2O_REPLAY unset — nothing to replay");
return;
@@ -402,9 +413,10 @@ fn fsi2_overset_prescribed_motion() {
let dt = fluid.dt_fluid;
let (d_rigid, l_rigid) = fluid.measure_force();
println!(
" PRESCRIBED ny = {ny}: dt {dt:.3e}, rigid drag {d_rigid:.2} lift {l_rigid:.2}, replay from t = {t0} (ramp {ramp_w} s) to {t_end}; patch offset {} h × {} rows",
" PRESCRIBED ny = {ny}: dt {dt:.3e}, rigid drag {d_rigid:.2} lift {l_rigid:.2}, replay from t = {t0} (ramp {ramp_w} s) to {t_end}; patch offset {} h × {} rows, patch convection {:?}",
std::env::var("RTX_FSI2O_PATCH_OFFSET").unwrap_or_else(|_| "6".into()),
std::env::var("RTX_FSI2O_PATCH_ROWS").unwrap_or_else(|_| "12".into())
std::env::var("RTX_FSI2O_PATCH_ROWS").unwrap_or_else(|_| "12".into()),
fsi2_harness::overset::patch_convection(),
);
let mut csv = std::env::var("RTX_FSI2O_CSV").ok().map(|p| {
use std::io::Write as _;
@@ -436,18 +448,19 @@ fn fsi2_overset_prescribed_motion() {
if let Err(e) = fluid.set_geometry(&d_r, &v_r) {
panic!("set_geometry died at step {step}, t = {t_new:.4}: {e:?}");
}
let (rounds_max, schwarz_ok, bg_res, patch_div, reclassified, e_stamp, e_reclass) = match fluid.step() {
Ok(r) => (
r.rounds.iter().copied().max().unwrap_or(0),
r.schwarz_converged,
r.background_residual,
r.patch_max_divergence,
r.reclassified_cells,
r.stamp_energy,
r.reclass_energy,
),
Err(e) => panic!("fluid step died at step {step}, t = {t_new:.4}: {e:?}"),
};
let (rounds_max, schwarz_ok, bg_res, patch_div, reclassified, e_stamp, e_reclass) =
match fluid.step() {
Ok(r) => (
r.rounds.iter().copied().max().unwrap_or(0),
r.schwarz_converged,
r.background_residual,
r.patch_max_divergence,
r.reclassified_cells,
r.stamp_energy,
r.reclass_energy,
),
Err(e) => panic!("fluid step died at step {step}, t = {t_new:.4}: {e:?}"),
};
let (defect_patch, defect_bg, _) = fluid.last_defects.get();
fluid.commit_base();
let (nodal, _, _) = fluid.sample_load(&d_r);