rtx-cfd: PatchConvection::TvdVanAlbada — van Albada deferred correction on the curvilinear predictor (downwind-side linear weight, gradient-ratio r over the face d lengths, far-upwind across the opposite face, boundary faces upwind); annulus MMS orders 2.10/1.69 at 0.24× upwind; cylinder-flag MMS orders 1.98/1.97 (1.06× upwind — diffusion-dominated, recorded); knobs RTX_OVERSET_CFD1_TVD, RTX_OVERSET_MAX_ROUNDS, RTX_CF_SCHEME
CI / Test (ubuntu-latest) (push) Canceled after 0s
CI / Build CPU-Only (Explicit) (push) Canceled after 0s
Documentation / Build User Guide (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
Performance Benchmarks / Run Benchmarks (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 / WASM Build + Size Check (push) Canceled after 0s
CI / Distributed Training Tests (push) Canceled after 0s
CI / CI Success (push) Canceled after 0s
Documentation / Build API Documentation (push) Canceled after 0s
CI / Test (ubuntu-latest) (push) Canceled after 0s
CI / Build CPU-Only (Explicit) (push) Canceled after 0s
Documentation / Build User Guide (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
Performance Benchmarks / Run Benchmarks (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 / WASM Build + Size Check (push) Canceled after 0s
CI / Distributed Training Tests (push) Canceled after 0s
CI / CI Success (push) Canceled after 0s
Documentation / Build API Documentation (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
02c855b9c4
commit
5f780447de
@@ -88,6 +88,14 @@ pub enum PatchConvection {
|
||||
Upwind,
|
||||
/// No convection: the Stokes limit, for the second-order MMS gate.
|
||||
None,
|
||||
/// Deferred-correction TVD with the van Albada limiter (the harness's
|
||||
/// scheme): the upwind face value plus `w_up psi(r) (phi_dn − phi_up)`,
|
||||
/// `w_up` the mesh's linear weight of the downwind side and `r` the
|
||||
/// ratio of the two one-sided gradients (so a linear field on a
|
||||
/// stretched row gives `r = 1` and the mesh's own linear face value).
|
||||
/// Faces whose far-upwind cell lies outside the patch fall back to
|
||||
/// upwind. Explicit, like the rest of the predictor's convection.
|
||||
TvdVanAlbada,
|
||||
}
|
||||
|
||||
/// How the across-patch diffusion is time-stepped.
|
||||
|
||||
@@ -65,7 +65,7 @@ impl CurvilinearPisoSolver {
|
||||
// is dropped but the mesh flux stays: the conservative
|
||||
// update needs `−Σ sign δV_f u_f` whenever the mesh moves.
|
||||
let fluid = match self.params.convection {
|
||||
PatchConvection::Upwind => field.flux[f],
|
||||
PatchConvection::Upwind | PatchConvection::TvdVanAlbada => field.flux[f],
|
||||
PatchConvection::None => 0.0,
|
||||
};
|
||||
let out = sign * (fluid - geo.swept[f] / dt);
|
||||
@@ -82,6 +82,12 @@ impl CurvilinearPisoSolver {
|
||||
};
|
||||
(field.u[up], field.v[up])
|
||||
}
|
||||
PatchConvection::TvdVanAlbada => {
|
||||
let other = if p == c { q } else { p };
|
||||
let (up, dn) = if out >= 0.0 { (c, other) } else { (other, c) };
|
||||
let (du, dv) = self.tvd_correction(field, f, up, dn);
|
||||
(field.u[up] + du, field.v[up] + dv)
|
||||
}
|
||||
// The Stokes limit has no upwind scheme to be
|
||||
// consistent with; the mesh flux takes the linear
|
||||
// face value and keeps its second order (upwinding
|
||||
@@ -154,6 +160,54 @@ impl CurvilinearPisoSolver {
|
||||
(uh, vh)
|
||||
}
|
||||
|
||||
/// The van Albada deferred correction to the upwind face value of `f`
|
||||
/// between the upwind cell `up` and the downwind cell `dn`: `w_up psi(r)
|
||||
/// (phi_dn − phi_up)` for `u` and `v`, zero when the far-upwind cell
|
||||
/// (across `up`'s opposite face) lies outside the patch.
|
||||
fn tvd_correction(&self, field: &PatchField, f: usize, up: usize, dn: usize) -> (f64, f64) {
|
||||
let mesh = &self.mesh;
|
||||
let faces = mesh.cell_faces(up);
|
||||
let Some(pos) = faces.iter().position(|&(g, _)| g == f) else {
|
||||
return (0.0, 0.0);
|
||||
};
|
||||
let g = faces[pos ^ 1].0;
|
||||
let far_face = &mesh.faces()[g];
|
||||
let far = match (far_face.owner, far_face.neigh) {
|
||||
(Some(a), Some(b)) => {
|
||||
if a == up {
|
||||
b
|
||||
} else {
|
||||
a
|
||||
}
|
||||
}
|
||||
_ => return (0.0, 0.0),
|
||||
};
|
||||
let face = &mesh.faces()[f];
|
||||
// Linear weight of the downwind side: `1 − w` when the owner is
|
||||
// upwind, `w` when the neighbour is.
|
||||
let w_up = if face.owner == Some(up) {
|
||||
1.0 - face.w
|
||||
} else {
|
||||
face.w
|
||||
};
|
||||
let len = |d: [f64; 2]| (d[0] * d[0] + d[1] * d[1]).sqrt();
|
||||
let (df, dg) = (len(face.d), len(far_face.d));
|
||||
let limited = |phi: &[f64]| -> f64 {
|
||||
let near = phi[dn] - phi[up];
|
||||
if near.abs() < 1e-300 {
|
||||
return 0.0;
|
||||
}
|
||||
let r = (phi[up] - phi[far]) / dg * df / near;
|
||||
let psi = if r > 0.0 {
|
||||
(r * r + r) / (r * r + 1.0)
|
||||
} else {
|
||||
0.0
|
||||
};
|
||||
w_up * psi * near
|
||||
};
|
||||
(limited(&field.u), limited(&field.v))
|
||||
}
|
||||
|
||||
/// `(I − dt ν L_n/V^{n+1}) û = rhs` along every s-line, Thomas algorithm.
|
||||
fn solve_lines(
|
||||
&self,
|
||||
|
||||
Reference in New Issue
Block a user