embedded3 S2-7b A1: the moving wall's mass flux from the body's true normal at the wall foot (RTX_E3_WALL_FLUX=true, host prototype, device refuses it) — the wall flux of a rotating cylinder 5e-3 → 1e-9 of ΩR h², the rotating wall's cut-cell pressure error 0.33 → 0.11 (n 16) / 0.30 → 0.09 (n 32) of ρ(ΩR)², full cells second order; the rotating wall's offset unchanged (−0.02 h)
CI / Build (macos-latest) (push) Waiting to run
CI / Test (ubuntu-latest) (push) Blocked by required conditions
Documentation / Build API Documentation (push) Failing after 4s
CI / Format Check (push) Failing after 11s
CI / Test (macos-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 CPU-Only (Explicit) (push) Failing after 4s
Documentation / Build User Guide (push) Successful in 4s
CI / Build (ubuntu-latest) (push) Failing after 1m39s
CI / Clippy Check (push) Failing after 1m52s
Performance Benchmarks / Run Benchmarks (push) Successful in 2m20s

Co-Authored-By: Claude Fable 5.1 <[email protected]>
This commit is contained in:
Omar Sobh
2026-09-20 07:58:10 -05:00
co-authored by Claude Fable 5.1
parent d25a36d908
commit 599023d786
4 changed files with 27 additions and 1 deletions
@@ -223,6 +223,7 @@ impl Mask {
wall_order2_centroid: false, wall_order2_centroid: false,
wall_exchange_foot: false, wall_exchange_foot: false,
conv_sides_exact: false, conv_sides_exact: false,
wall_flux_true_normal: false,
grad_weights: None, grad_weights: None,
diffusion_centroid: false, diffusion_centroid: false,
face_shifts: None, face_shifts: None,
@@ -699,6 +700,18 @@ impl Mask {
(j as f64 + 0.5) * g.dy, (j as f64 + 0.5) * g.dy,
(k as f64 + 0.5) * g.dz, (k as f64 + 0.5) * g.dz,
]; ];
// S2-7b A1: the flux through the TRUE surface at the wall foot —
// `A_w (u_b · n)` with n the body's own normal into the body.
if self.wall_flux_true_normal {
let (s, n) = self.interpolant_distance_and_normal(cut, x);
let foot = [x[0] - s * n[0], x[1] - s * n[1], x[2] - s * n[2]];
let v = body.surface_velocity(foot[0], foot[1], foot[2], t);
let eps = 1e-6 * g.dx.min(g.dy).min(g.dz);
let (n1, n2, n3) = body.normal(foot[0], foot[1], foot[2], t, eps);
let a_w = (w[0] * w[0] + w[1] * w[1] + w[2] * w[2]).sqrt();
// `normal` points out of the solid: into the body is its negative.
return -a_w * (v.0 * n1 + v.1 * n2 + v.2 * n3);
}
let mut flux = 0.0; let mut flux = 0.0;
for (c, wc) in w.iter().enumerate() { for (c, wc) in w.iter().enumerate() {
flux += self.surface_velocity_at(body, x, c, t) * wc; flux += self.surface_velocity_at(body, x, c, t) * wc;
@@ -178,7 +178,9 @@ impl DeviceStep {
"the order-2 second point at the neighbour's centroid (S2-7) is a host prototype: the device kernels do not carry it" "the order-2 second point at the neighbour's centroid (S2-7) is a host prototype: the device kernels do not carry it"
); );
assert!( assert!(
!solver.params.wall_exchange_foot && !solver.params.conv_sides_exact, !solver.params.wall_exchange_foot
&& !solver.params.conv_sides_exact
&& !solver.params.wall_flux_true_normal,
"the axis-foot exchange / exact convective sides (S2-7b) are host prototypes: the device kernels do not carry them" "the axis-foot exchange / exact convective sides (S2-7b) are host prototypes: the device kernels do not carry them"
); );
assert!( assert!(
@@ -174,6 +174,13 @@ pub struct Parameters {
/// faces across, the cell-centre planes along) instead of the averages /// faces across, the cell-centre planes along) instead of the averages
/// of whole-face fluxes. `RTX_E3_CONV_SIDES=exact`; the device refuses it. /// of whole-face fluxes. `RTX_E3_CONV_SIDES=exact`; the device refuses it.
pub conv_sides_exact: bool, pub conv_sides_exact: bool,
/// HOST PROTOTYPE (S2-7b, A1): a moving wall's mass flux from the body's
/// TRUE normal at the wall foot, `A_w (u_b · n_true)` (zero for a
/// tangentially moving wall), instead of `u_b · W_c` with the
/// interpolant's facet vector, which pumps `U_b h/R` through every facet
/// of a rotating or flexing wall. `RTX_E3_WALL_FLUX=true`; the device
/// refuses it.
pub wall_flux_true_normal: bool,
/// S2-5: the cross-direction diffusion between two faces over the /// S2-5: the cross-direction diffusion between two faces over the
/// distance between their OPEN-PART CENTROIDS (a cut face's velocity /// distance between their OPEN-PART CENTROIDS (a cut face's velocity
/// is its open part's mean, ½h(1 α) off the face centre along the /// is its open part's mean, ½h(1 α) off the face centre along the
@@ -218,6 +225,7 @@ impl Default for Parameters {
wall_exchange_axis: std::env::var("RTX_E3_WALL_EXCHANGE").map_or(true, |v| v != "h"), wall_exchange_axis: std::env::var("RTX_E3_WALL_EXCHANGE").map_or(true, |v| v != "h"),
wall_exchange_foot: std::env::var("RTX_E3_WALL_EXCHANGE").is_ok_and(|v| v == "axisfoot"), wall_exchange_foot: std::env::var("RTX_E3_WALL_EXCHANGE").is_ok_and(|v| v == "axisfoot"),
conv_sides_exact: std::env::var("RTX_E3_CONV_SIDES").is_ok_and(|v| v == "exact"), conv_sides_exact: std::env::var("RTX_E3_CONV_SIDES").is_ok_and(|v| v == "exact"),
wall_flux_true_normal: std::env::var("RTX_E3_WALL_FLUX").is_ok_and(|v| v == "true"),
pressure_centroid: std::env::var("RTX_E3_PRESSURE_CENTROID").is_ok_and(|v| v == "1"), pressure_centroid: std::env::var("RTX_E3_PRESSURE_CENTROID").is_ok_and(|v| v == "1"),
momentum_volume_tiled: std::env::var("RTX_E3_MOMENTUM_VOLUME") momentum_volume_tiled: std::env::var("RTX_E3_MOMENTUM_VOLUME")
.is_ok_and(|v| v == "tiled"), .is_ok_and(|v| v == "tiled"),
@@ -366,6 +374,7 @@ impl Solver {
m.wall_order2_centroid = self.params.wall_order2_centroid; m.wall_order2_centroid = self.params.wall_order2_centroid;
m.wall_exchange_foot = self.params.wall_exchange_foot; m.wall_exchange_foot = self.params.wall_exchange_foot;
m.conv_sides_exact = self.params.conv_sides_exact; m.conv_sides_exact = self.params.conv_sides_exact;
m.wall_flux_true_normal = self.params.wall_flux_true_normal;
m.diffusion_centroid = self.params.diffusion_centroid; m.diffusion_centroid = self.params.diffusion_centroid;
if self.params.diffusion_centroid { if self.params.diffusion_centroid {
m.compute_face_shifts(); m.compute_face_shifts();
@@ -118,6 +118,7 @@ pub struct Mask {
/// exchange; the convective sides from the sides' own apertures. /// exchange; the convective sides from the sides' own apertures.
pub(super) wall_exchange_foot: bool, pub(super) wall_exchange_foot: bool,
pub(super) conv_sides_exact: bool, pub(super) conv_sides_exact: bool,
pub(super) wall_flux_true_normal: bool,
/// The centroid prototype's pressure-gradient weights per u / v / w face. /// The centroid prototype's pressure-gradient weights per u / v / w face.
/// The centroid-distance cross diffusion (S2-5). /// The centroid-distance cross diffusion (S2-5).
pub(super) diffusion_centroid: bool, pub(super) diffusion_centroid: bool,
@@ -548,6 +549,7 @@ impl Mask {
wall_order2_centroid: false, wall_order2_centroid: false,
wall_exchange_foot: false, wall_exchange_foot: false,
conv_sides_exact: false, conv_sides_exact: false,
wall_flux_true_normal: false,
grad_weights: None, grad_weights: None,
diffusion_centroid: false, diffusion_centroid: false,
face_shifts: None, face_shifts: None,