embedded3 item 9b: the device step carries a static cut-cell mask (e3_cut.cu: cut predictor, apertured merged continuity with the fold, owner-read corrections; device CG off-stencil links) — host = device to 2e-10 (CFD1 cylinder nz 4) and 4e-14 (sphere) under tight tolerances
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 / Test (macos-latest) (push) Blocked by required conditions
CI / Test (ubuntu-latest) (push) Blocked by required conditions
CI / Build (macos-latest) (push) Waiting to run
CI / Clippy Check (push) Failing after 4s
Performance Benchmarks / Run Benchmarks (push) Failing after 5s
CI / Format Check (push) Failing after 4s
CI / Build (ubuntu-latest) (push) Failing after 4s
Documentation / Build User Guide (push) Successful in 5s
CI / Build CPU-Only (Explicit) (push) Failing after 56s
Documentation / Build API Documentation (push) Failing after 58s
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 / Test (macos-latest) (push) Blocked by required conditions
CI / Test (ubuntu-latest) (push) Blocked by required conditions
CI / Build (macos-latest) (push) Waiting to run
CI / Clippy Check (push) Failing after 4s
Performance Benchmarks / Run Benchmarks (push) Failing after 5s
CI / Format Check (push) Failing after 4s
CI / Build (ubuntu-latest) (push) Failing after 4s
Documentation / Build User Guide (push) Successful in 5s
CI / Build CPU-Only (Explicit) (push) Failing after 56s
Documentation / Build API Documentation (push) Failing after 58s
Co-Authored-By: Claude Fable 5.1 <[email protected]>
This commit is contained in:
co-authored by
Claude Fable 5.1
parent
0fa05f2056
commit
3b3d6c84c0
@@ -0,0 +1,180 @@
|
||||
//! embedded3 item 9b: the device step carrying a static cut-cell mask —
|
||||
//! host vs device on the manufactured sphere (CutCell, merging in) and on
|
||||
//! the CFD1 cylinder (nz 4 periodic), fields agreeing to the registered
|
||||
//! `1e-9·scale` over 100 steps under TIGHT tolerances (inner stop 1e-6,
|
||||
//! mass 1e-12 — item 7's identity rule; under the default tolerances the
|
||||
//! two CGs differ at the inner-stop level and the agreement is reported),
|
||||
//! equal corrector counts; the device step time recorded.
|
||||
//!
|
||||
//! `RTX_CUDA_ARCH=sm_120 cargo test --release -p rtx-cfd --features cuda --test embedded3_device_cut -- --nocapture`
|
||||
#![cfg(feature = "cuda")]
|
||||
|
||||
mod embedded3_sphere;
|
||||
|
||||
use embedded3_sphere::{C, MU, R, RHO, boundary3, source3, u3, v3, w3};
|
||||
use rtx_cfd::solvers::incompressible::ConvectionScheme;
|
||||
use rtx_cfd::solvers::incompressible::embedded3::step::device::DeviceStep;
|
||||
use rtx_cfd::solvers::incompressible::embedded3::{
|
||||
Body, Boundaries, Field, Fluid, Grid, Parameters, Side, Solver, WallScheme,
|
||||
};
|
||||
|
||||
fn max_diff(a: &[f64], b: &[f64]) -> f64 {
|
||||
a.iter()
|
||||
.zip(b)
|
||||
.fold(0.0_f64, |m, (&x, &y)| m.max((x - y).abs()))
|
||||
}
|
||||
|
||||
fn scale(a: &[f64]) -> f64 {
|
||||
a.iter().fold(0.0_f64, |m, &x| m.max(x.abs()))
|
||||
}
|
||||
|
||||
/// Builds two identical solvers (host and device) and marches both.
|
||||
fn march(
|
||||
make: &dyn Fn(bool) -> (Solver, Grid),
|
||||
dt: f64,
|
||||
steps: usize,
|
||||
label: &str,
|
||||
bound: Option<f64>,
|
||||
tight: bool,
|
||||
) {
|
||||
let make = |t: bool| make(t);
|
||||
let (mut host, g) = make(tight);
|
||||
let mut fh = Field::new(g);
|
||||
host.initialize(&mut fh);
|
||||
let (mut dev_solver, _) = make(tight);
|
||||
let mut fd = Field::new(g);
|
||||
dev_solver.initialize(&mut fd);
|
||||
let mut device = DeviceStep::new(dev_solver, g);
|
||||
device.upload(&fd);
|
||||
let merged = device.merged_cells();
|
||||
let start = std::time::Instant::now();
|
||||
let mut differ = 0;
|
||||
for _ in 0..steps {
|
||||
let rh = host.advance(&mut fh, dt);
|
||||
let rd = device.advance(dt);
|
||||
if rh.corrector_steps_performed != rd.corrector_steps_performed {
|
||||
differ += 1;
|
||||
}
|
||||
}
|
||||
let device_seconds = start.elapsed().as_secs_f64();
|
||||
device.download(&mut fd);
|
||||
let du = max_diff(&fh.u, &fd.u)
|
||||
.max(max_diff(&fh.v, &fd.v))
|
||||
.max(max_diff(&fh.w, &fd.w));
|
||||
let su = scale(&fh.u).max(scale(&fh.v)).max(scale(&fh.w));
|
||||
let dp = max_diff(&fh.p, &fd.p);
|
||||
let sp = scale(&fh.p).max(RHO);
|
||||
println!(
|
||||
" {label} (tight {tight}): {steps} steps, {merged} merged cells; host vs device max |Δu| {du:.3e} on {su:.3e}, max |Δp| {dp:.3e} on {sp:.3e}; corrector counts differ on {differ} steps; {:.1} ms per step (host + device)",
|
||||
1e3 * device_seconds / steps as f64
|
||||
);
|
||||
if let Some(bound) = bound {
|
||||
assert!(du < bound * su, "velocity differs: {du:.3e} on {su:.3e}");
|
||||
assert!(dp < bound * sp, "pressure differs: {dp:.3e} on {sp:.3e}");
|
||||
// The corrector counts are reported, not gated: at a mass
|
||||
// tolerance of 1e-12 the two residuals differ in their last digits
|
||||
// (the fields agree to rounding regardless).
|
||||
}
|
||||
}
|
||||
|
||||
fn tolerances(tight: bool) -> (f64, f64) {
|
||||
if tight { (1e-12, 1e-6) } else { (1e-8, 1e-2) }
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sphere_cut_cell_host_equals_device() {
|
||||
let n = 12;
|
||||
let h = 1.0 / n as f64;
|
||||
let dt = 0.4 * (h * h / (4.0 * MU / RHO)).min(h);
|
||||
let make = |tight: bool| {
|
||||
let (tolerance, inner_stop_factor) = tolerances(tight);
|
||||
let mut solver = Solver::new(
|
||||
Fluid {
|
||||
density: RHO,
|
||||
viscosity: MU,
|
||||
reference_velocity: 1.0,
|
||||
reference_length: 1.0,
|
||||
},
|
||||
Parameters {
|
||||
corrector_steps: 2,
|
||||
tolerance,
|
||||
inner_stop_factor,
|
||||
convection_scheme: ConvectionScheme::Upwind,
|
||||
wall_scheme: WallScheme::CutCell,
|
||||
..Parameters::default()
|
||||
},
|
||||
);
|
||||
solver.set_momentum_source(|x, y, z, _t| source3(x, y, z));
|
||||
solver.set_boundary_velocity(|x, y, z, _t| boundary3(x, y, z));
|
||||
solver.set_body(
|
||||
Body::sphere(move |_t| C, R)
|
||||
.with_surface_velocity(|x, y, z, _t| (u3(x, y, z), v3(x, y, z), w3(x, y, z))),
|
||||
);
|
||||
(solver, Grid::cubic(n, n, n, h))
|
||||
};
|
||||
march(&make, dt, 100, "sphere MMS n 12 CutCell", None, false);
|
||||
march(&make, dt, 100, "sphere MMS n 12 CutCell", Some(1e-9), true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cylinder_cut_cell_host_equals_device() {
|
||||
use rtx_cfd::solvers::incompressible::EmbeddedBody;
|
||||
let ny = 41;
|
||||
let nz = 4;
|
||||
let h = 0.41 / ny as f64;
|
||||
let nx = (2.2 / h).round() as usize;
|
||||
let dt = 2e-3;
|
||||
let make = |tight: bool| {
|
||||
let (tolerance, inner_stop_factor) = tolerances(tight);
|
||||
let mut solver = Solver::new(
|
||||
Fluid {
|
||||
density: 1.0,
|
||||
viscosity: 1e-3,
|
||||
reference_velocity: 0.2,
|
||||
reference_length: 0.1,
|
||||
},
|
||||
Parameters {
|
||||
corrector_steps: 2,
|
||||
tolerance,
|
||||
inner_stop_factor,
|
||||
convection_scheme: ConvectionScheme::Upwind,
|
||||
wall_scheme: WallScheme::CutCell,
|
||||
boundaries: Boundaries {
|
||||
x1: Side::PressureOutlet,
|
||||
z0: Side::Periodic,
|
||||
z1: Side::Periodic,
|
||||
..Boundaries::default()
|
||||
},
|
||||
..Parameters::default()
|
||||
},
|
||||
);
|
||||
solver.set_boundary_velocity(move |x, y, _z, _t| {
|
||||
if x <= 0.0 {
|
||||
(1.5 * 0.2 * 4.0 * y * (0.41 - y) / (0.41 * 0.41), 0.0, 0.0)
|
||||
} else {
|
||||
(0.0, 0.0, 0.0)
|
||||
}
|
||||
});
|
||||
let circle = EmbeddedBody::from_sdf(|x, y, _t| {
|
||||
((x - 0.2_f64).powi(2) + (y - 0.2_f64).powi(2)).sqrt() - 0.05
|
||||
});
|
||||
solver.set_body(Body::extruded(circle, nz as f64 * h));
|
||||
(solver, Grid::cubic(nx, ny, nz, h))
|
||||
};
|
||||
march(
|
||||
&make,
|
||||
dt,
|
||||
100,
|
||||
"CFD1 cylinder ny 41 nz 4 periodic CutCell",
|
||||
None,
|
||||
false,
|
||||
);
|
||||
march(
|
||||
&make,
|
||||
dt,
|
||||
100,
|
||||
"CFD1 cylinder ny 41 nz 4 periodic CutCell",
|
||||
Some(1e-9),
|
||||
true,
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user