S2-9: the flag on the recorded FSI2 kinematics — fsi2_overset_dump_centreline (rtx-fsi) exports the saved instants' wetted-node d/ḋ as a centreline per knot (clamp + 70 columns); tests/embedded3_flag_kinematics (cubic Hermite through the knots with their velocities, t = 0 at RTX_E3_FLAG_KIN_T0, a 0.5 s ramp from the undeflected line, arc-length interpolation along the stations) drives both the 3D/slab flag (RTX_E3_FLAG_KINEMATICS, both in-plane surface-velocity components, the record's period) and the 2D reference; the analytic paths unchanged (same tuples)
CI / Build (macos-latest) (push) Waiting to run
CI / Test (macos-latest) (push) Blocked by required conditions
CI / Test (ubuntu-latest) (push) Blocked by required conditions
CI / Python Bindings (maturin) (macos-latest) (push) Blocked by required conditions
CI / Python Bindings (maturin) (ubuntu-latest) (push) Blocked by required conditions
CI / WASM Build + Size Check (push) Blocked by required conditions
CI / Distributed Training Tests (push) Blocked by required conditions
CI / CI Success (push) Blocked by required conditions
CI / Build CPU-Only (Explicit) (push) Failing after 4s
Documentation / Build API Documentation (push) Failing after 4s
Documentation / Build User Guide (push) Successful in 6s
CI / Format Check (push) Failing after 13s
CI / Build (ubuntu-latest) (push) Failing after 1m56s
CI / Clippy Check (push) Failing after 2m12s
Performance Benchmarks / Run Benchmarks (push) Successful in 2m54s

Co-Authored-By: Claude Fable 5.1 <[email protected]>
This commit is contained in:
Omar Sobh
2026-09-20 21:27:26 -05:00
co-authored by Claude Fable 5.1
parent 03a9c9686e
commit f1714fb926
4 changed files with 268 additions and 22 deletions
@@ -649,3 +649,71 @@ fn fsi2_overset_prescribed_motion() {
mean(&|w| w.3[2])
);
}
/// S2-9: the recorded FSI2 kinematics as a CENTRELINE per instant for the
/// 3D flag (`RTX_FSI2O_REPLAY=dir`, `RTX_FSI2O_NY`, `RTX_FSI2O_CENTRELINE_CSV=out`):
/// per knot, t and per station (the clamp, then each bottom/top column
/// root → tip) the deformed midpoint (x, y) and its velocity (vx, vy).
#[test]
#[ignore = "S2-9 export: needs RTX_FSI2O_REPLAY (the saved instants)"]
fn fsi2_overset_dump_centreline() {
use fsi2_harness::overset::OversetFluid;
use fsi2_harness::replay::Replay;
use std::io::Write as _;
let Ok(replay_dir) = std::env::var("RTX_FSI2O_REPLAY") else {
println!(" RTX_FSI2O_REPLAY unset");
return;
};
let out = std::env::var("RTX_FSI2O_CENTRELINE_CSV").expect("RTX_FSI2O_CENTRELINE_CSV");
let ny: usize = std::env::var("RTX_FSI2O_NY").ok().and_then(|v| v.parse().ok()).unwrap_or(62);
let case = case_from_env("FSI2O", FSI2);
let fluid = OversetFluid::build_case(case, ny, 35, 100, 3).expect("overset fluid");
let itf = &fluid.interface;
let replay = Replay::load(&replay_dir);
let n = 2 * itf.wetted.len();
assert_eq!(replay.d[0].len(), n, "the instants' d does not match this interface");
// Columns root → tip: bottom is root → tip, top is tip → root.
let cols: Vec<(usize, usize)> = itf
.bottom
.iter()
.copied()
.zip(itf.top.iter().rev().copied())
.collect();
for &(b, t) in &cols {
assert!((itf.reference[b].0 - itf.reference[t].0).abs() < 1e-9, "bottom / top columns disagree");
}
let mut f = std::fs::File::create(&out).expect("csv");
write!(f, "t").unwrap();
for i in 0..=cols.len() {
write!(f, ",x{i},y{i},vx{i},vy{i}").unwrap();
}
writeln!(f).unwrap();
let clamp = (fsi2_harness::FLAG_X0, 0.5 * (fsi2_harness::FLAG_Y0 + fsi2_harness::FLAG_Y1));
for (k, &tk) in replay.times.iter().enumerate() {
let (d, dd) = (&replay.d[k], &replay.dd[k]);
write!(f, "{tk:.6}").unwrap();
write!(f, ",{:.9},{:.9},0,0", clamp.0, clamp.1).unwrap();
for &(b, t) in &cols {
let (xb, yb) = (itf.reference[b].0 + d[2 * b], itf.reference[b].1 + d[2 * b + 1]);
let (xt, yt) = (itf.reference[t].0 + d[2 * t], itf.reference[t].1 + d[2 * t + 1]);
let (vxb, vyb, vxt, vyt) = (dd[2 * b], dd[2 * b + 1], dd[2 * t], dd[2 * t + 1]);
write!(
f,
",{:.9},{:.9},{:.9},{:.9}",
0.5 * (xb + xt),
0.5 * (yb + yt),
0.5 * (vxb + vxt),
0.5 * (vyb + vyt)
)
.unwrap();
}
writeln!(f).unwrap();
}
println!(
" centreline: {} instants over [{:.4}, {:.4}] s, {} stations → {out}",
replay.times.len(),
replay.times[0],
replay.times.last().unwrap(),
cols.len() + 1
);
}