embedded3 S2-4: quadratic wall gradient behind Parameters::wall_order (host predictor, operator route, e3_cut.cu; RTX_E3_WALL_ORDER); density pin holds at order 2
CI / Clippy Check (push) Failing after 3s
CI / Build (ubuntu-latest) (push) Failing after 4s
CI / Build CPU-Only (Explicit) (push) Failing after 4s
CI / Format Check (push) Failing after 5s
Documentation / Build API Documentation (push) Failing after 4s
Documentation / Build User Guide (push) Successful in 4s
Performance Benchmarks / Run Benchmarks (push) Successful in 2m40s
CI / Build (macos-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
CI / Test (macos-latest) (push) Canceled after 0s
CI / Test (ubuntu-latest) (push) Canceled after 0s
CI / Python Bindings (maturin) (macos-latest) (push) Canceled after 0s
CI / Python Bindings (maturin) (ubuntu-latest) (push) Canceled after 0s

Co-Authored-By: Claude Fable 5.1 <[email protected]>
This commit is contained in:
Omar Sobh
2026-09-18 07:21:57 -05:00
co-authored by Claude Fable 5.1
parent 53b1babb91
commit cda973df26
7 changed files with 87 additions and 9 deletions
@@ -209,6 +209,7 @@ impl Mask {
merge_master: Vec::new(),
scheme: crate::solvers::incompressible::ConvectionScheme::Upwind,
density: 1.0,
wall_order: 1,
};
mask.compute_merging(None);
Ok(mask)
@@ -306,6 +307,47 @@ impl Mask {
self.compute_merging(Some(old));
}
/// The wall-gradient coefficients of the unknown face of component
/// `c` at `p` with control volume `cv`: `u'(0) = c_1 (u_f − U_b) + c_2
/// (u_n − U_b)` with `u_n` the face returned (one lattice step away
/// from the body along the wall normal's dominant axis). Order 1, or
/// no open neighbour: `(1/d_f, 0, None)`.
pub(super) fn wall_gradient(
&self,
c: usize,
p: [i64; 3],
cv: &CvGeometry,
) -> (f64, f64, Option<usize>) {
let linear = (1.0 / cv.distance, 0.0, None);
if self.wall_order < 2 {
return linear;
}
let a_w =
(cv.wall[0] * cv.wall[0] + cv.wall[1] * cv.wall[1] + cv.wall[2] * cv.wall[2]).sqrt();
if a_w == 0.0 {
return linear;
}
let n = [cv.wall[0] / a_w, cv.wall[1] / a_w, cv.wall[2] / a_w];
let mut d = 0;
for k in 1..3 {
if n[k].abs() > n[d].abs() {
d = k;
}
}
// `n` points into the body: step the other way.
let mut q = p;
q[d] -= if n[d] > 0.0 { 1 } else { -1 };
let open = self.aperture(c, q).is_some_and(|a| a > 0.0);
if !open {
return linear;
}
let f = self.lattice().face(c, q).expect("open face");
let h = [self.grid.dx, self.grid.dy, self.grid.dz];
let d1 = cv.distance;
let d2 = d1 + h[d] * n[d].abs();
(d2 / (d1 * (d2 - d1)), -d1 / (d2 * (d2 - d1)), Some(f))
}
pub(super) fn lattice(&self) -> Lattice {
Lattice {
g: self.grid,
@@ -659,7 +701,9 @@ impl Mask {
continue;
}
let ub = self.surface_velocity_at(body, lat.face_position(c, p), c, t);
force[c] += mu * a_w * (values[c][idx] - ub) / cv.distance;
let (c1, c2, nb) = self.wall_gradient(c, p, &cv);
let un = nb.map_or(ub, |f| values[c][f]);
force[c] += mu * a_w * (c1 * (values[c][idx] - ub) + c2 * (un - ub));
}
}
}