Files
rustytorch/crates/specialized/rtx-cfd/tests/embedded3_wall_position.rs
T
Omar SobhandClaude Fable 5.1 fdfb6da769
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 (macos-latest) (push) Waiting to run
Documentation / Build API Documentation (push) Failing after 4s
Documentation / Build User Guide (push) Successful in 4s
CI / Clippy Check (push) Failing after 2m24s
CI / Build CPU-Only (Explicit) (push) Failing after 3s
CI / Format Check (push) Failing after 11s
CI / Build (ubuntu-latest) (push) Failing after 1m58s
Performance Benchmarks / Run Benchmarks (push) Successful in 2m44s
embedded3 S2-5: the cut wall sat ½(1−α)h inside the body — cross diffusion over the open-part centroid spacing (RTX_E3_DIFFUSION_CENTROID; host + e3_cut.cu, shift tables, point-implicit excess); flat-wall effective-position instrument; DFG 2D-1 ladder tests (device + host); knobs tried and refuted along the way (oblique distance, axis exchange, centroid pressure gradient)
Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-18 10:54:52 -05:00

103 lines
3.5 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.
//! S2-5 instrument: where does the cut wall sit? Poiseuille flow along z
//! (periodic, body force `f`) between an EMBEDDED flat wall at `y = y_w`
//! (cut at a chosen fraction θ of a cell) and the domain's top wall. The
//! flow rate per unit width is `f (H y_w)³ / (12 μ)`, so the measured
//! rate gives the effective wall position `y_eff`; the offset
//! `(y_eff y_w)/h` must vanish at second order and is the number the
//! DFG ladder reads as an effective radius ≈ 0.2 h short.
use rtx_cfd::solvers::incompressible::ConvectionScheme;
use rtx_cfd::solvers::incompressible::embedded3::{
Body, Boundaries, Field, Fluid, Grid, Parameters, Side, Solver, WallScheme,
};
const MU: f64 = 0.1;
const F: f64 = 1.0;
const HY: f64 = 1.0;
fn offset(ny: usize, theta: f64) -> (f64, Vec<(f64, f64, f64)>) {
let h = HY / ny as f64;
let (nx, nz) = (3 * ny, 2);
let y_w = (ny as f64 / 4.0).floor() * h + theta * h;
let exact = move |y: f64| {
if y > y_w {
F / (2.0 * MU) * (y - y_w) * (HY - y)
} else {
0.0
}
};
let mut solver = Solver::new(
Fluid {
density: 1.0,
viscosity: MU,
reference_velocity: 1.0,
reference_length: 1.0,
},
Parameters {
corrector_steps: 2,
tolerance: 1e-10,
convection_scheme: ConvectionScheme::Upwind,
wall_scheme: WallScheme::CutCell,
boundaries: Boundaries {
z0: Side::Periodic,
z1: Side::Periodic,
..Boundaries::default()
},
..Parameters::default()
},
);
solver.set_boundary_velocity(move |_x, y, _z, _t| (0.0, 0.0, exact(y)));
solver.set_momentum_source(|_, _, _, _| (0.0, 0.0, F));
solver.set_body(Body::from_sdf(move |_x, y, _z, _t| y - y_w));
let g = Grid::cubic(nx, ny, nz, h);
let mut field = Field::new(g);
for k in 0..=nz {
for j in 0..ny {
for i in 0..nx {
if k < nz || true {
let idx = g.wface(k.min(nz), j, i);
field.w[idx] = exact((j as f64 + 0.5) * h);
}
}
}
}
solver.initialize(&mut field);
let dt = 0.5 * h * h / (6.0 * MU);
let steps = (3.0 / dt).ceil() as usize;
for _ in 0..steps {
solver.advance(&mut field, dt);
}
let mask = solver.mask().expect("mask");
let i = nx / 2;
let mut q = 0.0;
let mut profile = Vec::new();
for j in 0..ny {
let f = g.wface(0, j, i);
let a = mask.a_w(f);
q += a * field.w[f] * h;
let y = (j as f64 + 0.5) * h;
if a > 0.0 && profile.len() < 4 {
profile.push((a, field.w[f], exact(y)));
}
}
let y_eff = HY - (12.0 * MU * q / F).cbrt();
((y_eff - y_w) / h, profile)
}
#[test]
#[ignore = "S2-5 instrument: the cut wall's effective position on a flat wall (a minute on the host)"]
fn flat_wall_effective_position() {
for ny in [16usize, 32] {
for theta in [0.05, 0.25, 0.5, 0.75, 0.95] {
let (off, profile) = offset(ny, theta);
let p: Vec<String> = profile
.iter()
.map(|(a, w, e)| format!("α {a:.2} w {w:.5} (exact at the face centre {e:.5})"))
.collect();
println!(
" ny {ny} θ {theta:.2}: effective wall offset {off:+.4} h (positive = the wall sits inside the fluid); first open faces: {}",
p.join("; ")
);
}
}
}