Files
rustytorch/crates/specialized/rtx-cfd/tests/overset_mms.rs
T
Omar SobhandClaude Fable 5.1 62df6bd628
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
Documentation / Build API Documentation (push) Canceled after 0s
Documentation / Build User Guide (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
rtx-cfd: overset P3b — the reclassification impulse located (the fringe ring is a staircase of the interpolated velocities' mass defect) and removed by a converged fringe flux balance (default on): falsifier max spike 594 → 5.50 N/m at the FSI2 step (staircase 6490), 10.95 / 16.79 at dt/2 / dt/4 (12600 / 25600), rms spike 0.07% of the force, far probe 6 (7900), KE per event 4.9e-3 J/m falling with Δt (2.6 fixed)
OverlapMap::balance_fringe_fluxes: Gauss–Seidel through the prescribed faces of
every fringe cell to 1e-12 of the prescribed flux scale (≤ 50 sweeps), after
every fringe stamping (3 fixed sweeps 101 N/m, 10 sweeps 5.5 — converged is the
rule). OversetParameters: fringe_flux_balance (default on, RTX_OVERSET_NO_BALANCE
off), fringe_balance_tolerance, refill_turned_active (measured no effect: 593.7 →
593.8; kept as the record), stall_rounds opt-in. P3b locating trace
RTX_OVERSET_TRACE_SP (continuity source by class change in cell volumes/step,
stored-pressure jump of turned-active cells): the flipped cells' mass source
≤ 6e-3 cell volumes/step, their stored pressure 5–10% of the range off their
neighbours (4.4% on the static MMS — the meshes' discretization disagreement).
Knock-outs refuted (RTX_OVERSET_H1 keep own face velocities, H4 no warm start,
pressure refill): 593–597 N/m each. S4 MMS with the balance: velocity errors
within 0.1% of the pinned values, the background's overlap mass defect 1e-13 by
construction, pressure errors unchanged. overset_mms prints pressure
diagnostics; overset_falsifier records the balanced ladder (regression guard
20 N/m at dt; RTX_OVERSET_FALSIFIER_STRICT asserts the registered gates — (ii)
holds at dt, misses at dt/2, dt/4; (iv) fails: residual ∝ 1/Δt^0.8).

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01X2GmJXeQ2njUecEKiJZ1G2
2026-09-05 19:16:16 -07:00

93 lines
3.6 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//! A-P2, step S4 (`docs/overset_metal_campaign.md` §5.9): the two-mesh
//! manufactured solution on the static overset.
//!
//! Unit square (closed box, exact Dirichlet velocity on every side, the
//! `mms_piso.rs` field and source, upwind) with the phantom circle at
//! (0.6, 0.45) r = 0.2 as the patch's inner wall (the exact velocity as its
//! Dirichlet), the skewed stretched annulus to r = 0.354 as the patch
//! (outer spacing = h), background n = 32 / 64 / 128. Gates: the
//! background's L2 on its fluid faces within 1.5× the embedded-circle
//! ladder (8.489e-3 / 4.341e-3 at n = 32 / 64) and first order to 128; the
//! patch's L2 on its interior cells ≤ 2× the background's at equal h and
//! first order; both divergence-free on their equation-carrying cells;
//! Schwarz rounds per corrector recorded; the overlap mass defect per step,
//! both sides, relative to the overlap flux scale — measured first.
mod overset_common;
use overset_common::{march, orders};
use rtx_cfd::CfdResult;
#[tokio::test]
async fn two_mesh_mms_recovers_the_single_mesh_levels_on_both_meshes() -> CfdResult<()> {
let reference = [8.489e-3, 4.341e-3];
let only: Option<usize> = std::env::var("RTX_OVERSET_N")
.ok()
.and_then(|v| v.parse().ok());
let tol: f64 = std::env::var("RTX_OVERSET_SCHWARZ")
.ok()
.and_then(|v| v.parse().ok())
.unwrap_or(1e-3);
let mut bg = Vec::new();
let mut patch = Vec::new();
for (idx, n) in [32usize, 64, 128].into_iter().enumerate() {
if only.is_some_and(|o| o != n) {
continue;
}
let m = march(n, tol).await?;
println!(
" overset n={n}: L2 background {:.6e} patch {:.6e} ({} steps); Schwarz rounds mean {:.2} max {} (failures {}); \
worst bg residual {:.2e}, patch div {:.2e}; overlap mass defect (of the overlap flux) at steady state bg {:.3e} patch {:.3e}, worst over the transient bg {:.3e} patch {:.3e}",
m.l2_background,
m.l2_patch,
m.steps,
m.mean_rounds,
m.max_rounds,
m.schwarz_failures,
m.worst_bg_residual,
m.worst_patch_div_rel,
m.final_defect_bg_rel,
m.final_defect_patch_rel,
m.worst_defect_bg_rel,
m.worst_defect_patch_rel
);
println!(
" pressure: L2 (mean-shifted) background {:.3e} patch {:.3e}; level offset between the meshes {:+.3e}; largest fringe-vs-neighbours jump {:.3e} of the exact range",
m.l2_p_background, m.l2_p_patch, m.p_offset_between_meshes, m.p_fringe_jump_rel
);
if let Some(r) = reference.get(idx) {
assert!(
m.l2_background < 1.5 * r,
"n = {n}: background L2 {:.3e} > 1.5x embedded circle {r:.3e}",
m.l2_background
);
}
assert!(
m.l2_patch < 2.0 * m.l2_background,
"n = {n}: patch L2 {:.3e} > 2x background {:.3e}",
m.l2_patch,
m.l2_background
);
assert!(
m.worst_patch_div_rel < 1e-9,
"patch divergence {:.3e}",
m.worst_patch_div_rel
);
bg.push(m.l2_background);
patch.push(m.l2_patch);
}
if only.is_none() {
let (ob, op) = (orders(&bg), orders(&patch));
println!(" overset orders: background {ob:?}, patch {op:?}");
assert!(
ob.iter().all(|&x| (0.75..1.3).contains(&x)),
"background orders {ob:?}"
);
assert!(
op.iter().all(|&x| (0.7..1.6).contains(&x)),
"patch orders {op:?}"
);
}
Ok(())
}