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
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
93 lines
3.6 KiB
Rust
93 lines
3.6 KiB
Rust
//! 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(())
|
||
}
|