rtx-cfd: OverlapMap::region_force — momentum flux into a background region (control-volume face formula, one-sided next to holes); overset_cfd1 prints the four momentum routes (CV box, ring outer, hole boundary, wall) and their defects at the settled state
Documentation / Build API Documentation (push) Canceled after 0s
Documentation / Build User Guide (push) Canceled after 0s
CI / WASM Build + Size Check (push) Canceled after 0s
CI / Distributed Training Tests (push) Canceled after 0s
CI / Build CPU-Only (Explicit) (push) Canceled after 0s
CI / Python Bindings (maturin) (macos-latest) (push) Canceled after 0s
CI / Python Bindings (maturin) (ubuntu-latest) (push) Canceled after 0s
CI / Test (ubuntu-latest) (push) Canceled after 0s
Performance Benchmarks / Run Benchmarks (push) Canceled after 0s
CI / Format Check (push) Canceled after 0s
CI / Clippy Check (push) Canceled after 0s
CI / Build (macos-latest) (push) Canceled after 0s
CI / Build (ubuntu-latest) (push) Canceled after 0s
CI / Test (macos-latest) (push) Canceled after 0s
CI / CI Success (push) Canceled after 0s
Documentation / Build API Documentation (push) Canceled after 0s
Documentation / Build User Guide (push) Canceled after 0s
CI / WASM Build + Size Check (push) Canceled after 0s
CI / Distributed Training Tests (push) Canceled after 0s
CI / Build CPU-Only (Explicit) (push) Canceled after 0s
CI / Python Bindings (maturin) (macos-latest) (push) Canceled after 0s
CI / Python Bindings (maturin) (ubuntu-latest) (push) Canceled after 0s
CI / Test (ubuntu-latest) (push) Canceled after 0s
Performance Benchmarks / Run Benchmarks (push) Canceled after 0s
CI / Format Check (push) Canceled after 0s
CI / Clippy Check (push) Canceled after 0s
CI / Build (macos-latest) (push) Canceled after 0s
CI / Build (ubuntu-latest) (push) Canceled after 0s
CI / Test (macos-latest) (push) Canceled after 0s
CI / CI Success (push) Canceled after 0s
Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01X2GmJXeQ2njUecEKiJZ1G2
This commit is contained in:
co-authored by
Claude Fable 5.1
parent
5f780447de
commit
134ac03870
@@ -509,6 +509,160 @@ impl OverlapMap {
|
||||
|
||||
/// Background-side overlap mass defect: `Σ_fringe |Σ_f sign F_f|`
|
||||
/// (volume flux), the continuity the fringe cells do not enforce.
|
||||
/// The force the background transmits INTO the region of cells whose
|
||||
/// class satisfies `inside` — the sum over the region's boundary faces
|
||||
/// of `sigma·n − rho u (u·n)` with `n` pointing out of the region, the
|
||||
/// control-volume formula of `EmbeddedMask::control_volume_force`
|
||||
/// without the unsteady term (a settled-state diagnostic). Values are
|
||||
/// taken from non-hole cells only: a face next to a hole cell uses the
|
||||
/// one-sided stencil from its valid side, so the hole boundary itself
|
||||
/// (`inside = Hole`) is evaluated from the fringe's stamped values.
|
||||
///
|
||||
/// Two regions make the P4 momentum-defect measurement: `Fringe |
|
||||
/// Hole` (what the active region passes to the ring) and `Hole` (what
|
||||
/// the ring passes on); their difference is the fringe ring's momentum
|
||||
/// defect, and the hole boundary against the patch's wall force is the
|
||||
/// patch region's.
|
||||
pub fn region_force(
|
||||
&self,
|
||||
field: &FlowField,
|
||||
rho: f64,
|
||||
mu: f64,
|
||||
inside: impl Fn(CellClass) -> bool,
|
||||
) -> (f64, f64) {
|
||||
let (nx, ny, dx, dy) = (self.nx, self.ny, self.dx, self.dy);
|
||||
let valid = |j: isize, i: isize| -> bool {
|
||||
j >= 0
|
||||
&& i >= 0
|
||||
&& (j as usize) < ny
|
||||
&& (i as usize) < nx
|
||||
&& self.class(j as usize, i as usize) != CellClass::Hole
|
||||
};
|
||||
let is_in = |j: isize, i: isize| -> bool {
|
||||
j >= 0
|
||||
&& i >= 0
|
||||
&& (j as usize) < ny
|
||||
&& (i as usize) < nx
|
||||
&& inside(self.class(j as usize, i as usize))
|
||||
};
|
||||
// Face-located u is valid when either adjacent cell is; likewise v.
|
||||
let uf_valid = |j: isize, i: isize| valid(j, i - 1) || valid(j, i);
|
||||
let vf_valid = |j: isize, i: isize| valid(j - 1, i) || valid(j, i);
|
||||
let u = |j: isize, i: isize| field.u[(j as usize, i as usize)];
|
||||
let v = |j: isize, i: isize| field.v[(j as usize, i as usize)];
|
||||
let p = |j: isize, i: isize| field.p[(j as usize, i as usize)];
|
||||
// Cell-centred v and u (averages of the cell's two faces).
|
||||
let v_c = |j: isize, i: isize| 0.5 * (v(j, i) + v(j + 1, i));
|
||||
let u_c = |j: isize, i: isize| 0.5 * (u(j, i) + u(j, i + 1));
|
||||
// Average of the valid members of a pair, or `None`.
|
||||
let pair = |a: Option<f64>, b: Option<f64>| match (a, b) {
|
||||
(Some(a), Some(b)) => Some(0.5 * (a + b)),
|
||||
(Some(a), None) | (None, Some(a)) => Some(a),
|
||||
(None, None) => None,
|
||||
};
|
||||
// Derivative across `x0 → x1 → x2` (spacing `h`): central when both
|
||||
// ends are valid, one-sided otherwise, zero when nothing is.
|
||||
let deriv = |m: Option<f64>, c: f64, pl: Option<f64>, h: f64| match (m, pl) {
|
||||
(Some(m), Some(pl)) => (pl - m) / (2.0 * h),
|
||||
(Some(m), None) => (c - m) / h,
|
||||
(None, Some(pl)) => (pl - c) / h,
|
||||
(None, None) => 0.0,
|
||||
};
|
||||
let (mut fx, mut fy) = (0.0, 0.0);
|
||||
for jc in 0..ny as isize {
|
||||
for ic in 0..nx as isize {
|
||||
if !is_in(jc, ic) {
|
||||
continue;
|
||||
}
|
||||
// Vertical faces: west (u face ic, n = −x) and east (ic + 1, +x).
|
||||
for (i, sign, nj, ni) in [(ic, -1.0, jc, ic - 1), (ic + 1, 1.0, jc, ic + 1)] {
|
||||
if is_in(nj, ni) || nj < 0 || ni < 0 || ni >= nx as isize {
|
||||
continue;
|
||||
}
|
||||
let j = jc;
|
||||
let un = u(j, i);
|
||||
let p_f = pair(
|
||||
valid(j, i - 1).then(|| p(j, i - 1)),
|
||||
valid(j, i).then(|| p(j, i)),
|
||||
)
|
||||
.unwrap_or(0.0);
|
||||
let dudx = deriv(
|
||||
uf_valid(j, i - 1).then(|| u(j, i - 1)),
|
||||
un,
|
||||
(i < nx as isize && uf_valid(j, i + 1)).then(|| u(j, i + 1)),
|
||||
dx,
|
||||
);
|
||||
let dudy = deriv(
|
||||
(j >= 1 && uf_valid(j - 1, i)).then(|| u(j - 1, i)),
|
||||
un,
|
||||
(j + 1 < ny as isize && uf_valid(j + 1, i)).then(|| u(j + 1, i)),
|
||||
dy,
|
||||
);
|
||||
let vw = valid(j, i - 1).then(|| v_c(j, i - 1));
|
||||
let ve = valid(j, i).then(|| v_c(j, i));
|
||||
let dvdx = match (vw, ve) {
|
||||
(Some(a), Some(b)) => (b - a) / dx,
|
||||
(Some(a), None) => {
|
||||
(a - if valid(j, i - 2) { v_c(j, i - 2) } else { a }) / dx
|
||||
}
|
||||
(None, Some(b)) => {
|
||||
((if valid(j, i + 1) { v_c(j, i + 1) } else { b }) - b) / dx
|
||||
}
|
||||
(None, None) => 0.0,
|
||||
};
|
||||
let v_f = pair(vw, ve).unwrap_or(0.0);
|
||||
let sxx = -p_f + 2.0 * mu * dudx;
|
||||
let sxy = mu * (dudy + dvdx);
|
||||
fx += sign * (sxx - rho * un * un) * dy;
|
||||
fy += sign * (sxy - rho * v_f * un) * dy;
|
||||
}
|
||||
// Horizontal faces: south (v face jc, n = −y) and north (jc + 1, +y).
|
||||
for (j, sign, nj, ni) in [(jc, -1.0, jc - 1, ic), (jc + 1, 1.0, jc + 1, ic)] {
|
||||
if is_in(nj, ni) || nj < 0 || nj >= ny as isize {
|
||||
continue;
|
||||
}
|
||||
let i = ic;
|
||||
let vn = v(j, i);
|
||||
let p_f = pair(
|
||||
valid(j - 1, i).then(|| p(j - 1, i)),
|
||||
valid(j, i).then(|| p(j, i)),
|
||||
)
|
||||
.unwrap_or(0.0);
|
||||
let dvdy = deriv(
|
||||
vf_valid(j - 1, i).then(|| v(j - 1, i)),
|
||||
vn,
|
||||
(j < ny as isize && vf_valid(j + 1, i)).then(|| v(j + 1, i)),
|
||||
dy,
|
||||
);
|
||||
let dvdx = deriv(
|
||||
(i >= 1 && vf_valid(j, i - 1)).then(|| v(j, i - 1)),
|
||||
vn,
|
||||
(i + 1 < nx as isize && vf_valid(j, i + 1)).then(|| v(j, i + 1)),
|
||||
dx,
|
||||
);
|
||||
let us = valid(j - 1, i).then(|| u_c(j - 1, i));
|
||||
let un_ = valid(j, i).then(|| u_c(j, i));
|
||||
let dudy = match (us, un_) {
|
||||
(Some(a), Some(b)) => (b - a) / dy,
|
||||
(Some(a), None) => {
|
||||
(a - if valid(j - 2, i) { u_c(j - 2, i) } else { a }) / dy
|
||||
}
|
||||
(None, Some(b)) => {
|
||||
((if valid(j + 1, i) { u_c(j + 1, i) } else { b }) - b) / dy
|
||||
}
|
||||
(None, None) => 0.0,
|
||||
};
|
||||
let u_f = pair(us, un_).unwrap_or(0.0);
|
||||
let syy = -p_f + 2.0 * mu * dvdy;
|
||||
let sxy = mu * (dudy + dvdx);
|
||||
fx += sign * (sxy - rho * u_f * vn) * dx;
|
||||
fy += sign * (syy - rho * vn * vn) * dx;
|
||||
}
|
||||
}
|
||||
}
|
||||
(fx, fy)
|
||||
}
|
||||
|
||||
pub fn background_mass_defect(&self, field: &FlowField) -> f64 {
|
||||
let (dx, dy) = (self.dx, self.dy);
|
||||
self.fringe_cells
|
||||
|
||||
Reference in New Issue
Block a user