embedded3 item 11: moving bodies (end-of-step mask, fresh-cell refill, space-time cut cell: step-averaged apertures, GCL wall flux, Reynolds-transport momentum), the 3D fresh-cell falsifier (plate / circle / stadium, wall + control-volume routes) and the Lipschitz sweep; ghost wall reproduces the 2D falsifier to the digit; cut wall 5–14× smoother on the circle, gates not met (fresh cell's first step); wall.rs split (impose.rs)
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 / Clippy Check (push) Failing after 3s
CI / Build (ubuntu-latest) (push) Failing after 4s
CI / Format Check (push) Failing after 4s
Performance Benchmarks / Run Benchmarks (push) Failing after 5s
Documentation / Build User Guide (push) Successful in 6s
CI / Build CPU-Only (Explicit) (push) Failing after 1m6s
Documentation / Build API Documentation (push) Failing after 1m9s

Co-Authored-By: Claude Fable 5.1 <[email protected]>
This commit is contained in:
Omar Sobh
2026-09-17 16:20:35 -05:00
co-authored by Claude Fable 5.1
parent 0e4c97ed24
commit 5b1621e6ad
12 changed files with 1406 additions and 419 deletions
@@ -0,0 +1,100 @@
//! embedded3 item 11b: the wall's smoothness in the interface position.
//! The manufactured sphere is marched to steady state at `M + 1` centres
//! spaced `h/M` apart across one cell along x; at each the load error
//! `E(δ) = F(δ) F_exact(δ)` (the exact force moves with the sphere and
//! is subtracted) is measured on the scheme's route. The largest jump of
//! `E` between neighbouring positions, relative to the load, and the
//! Lipschitz quotient `|ΔE| / (Δδ |F|)` are reported for both walls.
//! Registered gate (`docs/embedded3_campaign.md` item 11): the cut wall's
//! largest neighbouring jump < 1 % of the load with a bounded quotient.
//!
//! Default run: 8 positions at n = 24 (about two minutes on the host);
//! the gated `#[ignore]` variant sweeps 40.
mod embedded3_sphere;
use embedded3_sphere::{C, exact_force_and_flux, measure};
use rtx_cfd::solvers::incompressible::embedded3::WallScheme;
fn norm(a: [f64; 3]) -> f64 {
(a[0] * a[0] + a[1] * a[1] + a[2] * a[2]).sqrt()
}
struct Sweep {
/// Largest neighbouring jump of the load error relative to the load.
max_jump: f64,
/// Largest Lipschitz quotient `|ΔE| / (Δδ |F|)` (per unit length).
max_quotient: f64,
}
fn sweep(n: usize, positions: usize, scheme: WallScheme) -> Sweep {
let h = 1.0 / n as f64;
let step = h / positions as f64;
let mut errors: Vec<[f64; 3]> = Vec::new();
let mut scale = 0.0_f64;
for m in 0..=positions {
let c = (C.0 + m as f64 * step, C.1, C.2);
let (fe, _) = exact_force_and_flux(c);
let r = measure(n, scheme, c);
let e = [
r.force_surface[0] - fe[0],
r.force_surface[1] - fe[1],
r.force_surface[2] - fe[2],
];
scale = scale.max(norm(fe));
println!(
" {scheme:?} δ = {:.4} h: F {:.5?} exact {:.5?} error {:.3e} (rel {:.3e})",
m as f64 / positions as f64,
r.force_surface,
fe,
norm(e),
norm(e) / norm(fe)
);
errors.push(e);
}
let mut max_jump = 0.0_f64;
for w in errors.windows(2) {
let d = norm([w[1][0] - w[0][0], w[1][1] - w[0][1], w[1][2] - w[0][2]]);
max_jump = max_jump.max(d / scale);
}
let max_quotient = max_jump / step;
println!(
" {scheme:?}: largest neighbouring jump {:.3e} of the load (spacing {:.3e} = h/{positions}); Lipschitz quotient {:.3e} per unit length",
max_jump, step, max_quotient
);
Sweep {
max_jump,
max_quotient,
}
}
#[test]
fn sphere_load_across_one_cell() {
let ghost = sweep(24, 8, WallScheme::GhostBinary);
let cut = sweep(24, 8, WallScheme::CutCell);
println!(
" jumps: ghost {:.3e}, cut {:.3e} ({:.1}x smaller); quotients: ghost {:.3e}, cut {:.3e}",
ghost.max_jump,
cut.max_jump,
ghost.max_jump / cut.max_jump.max(1e-300),
ghost.max_quotient,
cut.max_quotient
);
assert!(ghost.max_jump.is_finite() && cut.max_jump.is_finite());
}
#[test]
#[ignore = "item 11's gated sweep (40 positions, both walls; tens of minutes on the host)"]
fn sphere_load_lipschitz_gate() {
let ghost = sweep(24, 40, WallScheme::GhostBinary);
let cut = sweep(24, 40, WallScheme::CutCell);
println!(
" GATE: cut largest jump {:.3e} of the load (ghost {:.3e}); cut quotient {:.3e} (ghost {:.3e})",
cut.max_jump, ghost.max_jump, cut.max_quotient, ghost.max_quotient
);
assert!(
cut.max_jump < 0.01,
"cut-cell jump {:.3e} of the load",
cut.max_jump
);
}