rtx-cfd: the wall treatment is second order, not first — correct the record
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 / Test (ubuntu-latest) (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 / 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
Documentation / Build User Guide (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 / Test (ubuntu-latest) (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 / 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
Documentation / Build User Guide (push) Canceled after 0s
Performance Benchmarks / Run Benchmarks (push) Canceled after 0s
CI / Format Check (push) Canceled after 0s
The manufactured-solution test carried a hypothesis for why the observed
order sits below 1: that `(u_P - u_wall)/(dy/2)` approximates the wall
gradient at y = dy/4 rather than at the wall, making the near-wall rows
first order.
Measuring in the Stokes limit refutes it. With convection negligible every
remaining operator is second order, so the observed rate there reports the
wall treatment directly:
rho = 1.000 (Re = 20.00) 3.52e-2 1.95e-2 1.04e-2 orders 0.85 0.91
rho = 0.001 (Re = 0.02) 2.21e-3 5.35e-4 1.28e-4 orders 2.05 2.06
2.05 and 2.06. The half-cell wall term is second-order accurate and the
Stokes discretisation reaches its nominal rate. The shortfall at Re = 20 is
first-order upwind and nothing else, which is what a first-order convection
scheme is supposed to give.
Comment corrected rather than left standing: a plausible explanation that
happens to be wrong is worse than none, because it sends the next person
to fix something that is not broken.
Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 5
parent
698c844926
commit
1a740e0b2c
@@ -59,7 +59,9 @@
|
|||||||
//! below are the ones that a plausible-but-wrong discretisation fails:
|
//! below are the ones that a plausible-but-wrong discretisation fails:
|
||||||
//!
|
//!
|
||||||
//! 1. **Observed order of the velocity error.** 0.85 and 0.91 over
|
//! 1. **Observed order of the velocity error.** 0.85 and 0.91 over
|
||||||
//! 16 -> 32 -> 64, approaching 1 from below. It was 0.48.
|
//! 16 -> 32 -> 64, approaching 1 from below. It was 0.48. In the Stokes
|
||||||
|
//! limit the same measurement gives 2.05 and 2.06, so the shortfall below 1
|
||||||
|
//! is first-order upwind convection, not the discretisation.
|
||||||
//! 2. **Divergence, split between the outer ring of cells and the interior.**
|
//! 2. **Divergence, split between the outer ring of cells and the interior.**
|
||||||
//! A converged SIMPLE solve must satisfy discrete continuity to solver
|
//! A converged SIMPLE solve must satisfy discrete continuity to solver
|
||||||
//! tolerance in *every* cell. Splitting the measure is what exposes a
|
//! tolerance in *every* cell. Splitting the measure is what exposes a
|
||||||
@@ -308,17 +310,28 @@ async fn observed_order_matches_the_convection_scheme() -> CfdResult<()> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// 0.80, not 1.0. The measured rates are 0.848 (16 -> 32) and 0.905
|
// 0.80, not 1.0. The measured rates are 0.848 (16 -> 32) and 0.905
|
||||||
// (32 -> 64) — approaching 1 from below, which is what a first-order scheme
|
// (32 -> 64), approaching 1 from below — which is exactly what first-order
|
||||||
// carrying a first-order wall treatment does: `(u_P - u_wall)/(dy/2)`
|
// upwind convection gives.
|
||||||
// approximates the wall gradient at `y = dy/4` rather than at the wall, so
|
//
|
||||||
// the near-wall rows converge at first order too but with a larger
|
// The wall treatment is *not* the limiter, contrary to what this comment
|
||||||
// constant, and its share of the norm shrinks as the mesh refines.
|
// first claimed. Repeating the measurement in the Stokes limit, where
|
||||||
|
// convection is negligible and every remaining operator is second order,
|
||||||
|
// gives observed order 2.05 and 2.06:
|
||||||
|
//
|
||||||
|
// rho = 1.000 (Re = 20.00) 3.5162e-2 1.9537e-2 1.0375e-2 0.85 0.91
|
||||||
|
// rho = 0.001 (Re = 0.02) 2.2131e-3 5.3510e-4 1.2812e-4 2.05 2.06
|
||||||
|
//
|
||||||
|
// So the near-wall half-cell term is second-order accurate and the whole
|
||||||
|
// Stokes discretisation reaches its nominal rate. The shortfall below 1 at
|
||||||
|
// Re = 20 is upwind's `O(h)` numerical viscosity and nothing else, which
|
||||||
|
// means a second-order convection scheme is now the thing that moves this
|
||||||
|
// number — and that work is no longer blocked behind an unverified
|
||||||
|
// discretisation.
|
||||||
//
|
//
|
||||||
// The bound sits just under the worst measured rate rather than at the
|
// The bound sits just under the worst measured rate rather than at the
|
||||||
// theoretical 1, because asserting a rate the solver does not yet reach
|
// theoretical 1 because the rate is still climbing at 64. It still has
|
||||||
// either fails the suite or invites someone to quietly weaken it later. It
|
// teeth: before the near-wall rows became unknowns the rates were 0.475 and
|
||||||
// still has teeth: before the near-wall rows became unknowns the rates were
|
// 0.470, and this fails them by a wide margin.
|
||||||
// 0.475 and 0.470, and this fails them by a wide margin.
|
|
||||||
for (i, &rate) in rates.iter().enumerate() {
|
for (i, &rate) in rates.iter().enumerate() {
|
||||||
assert!(
|
assert!(
|
||||||
rate > 0.80,
|
rate > 0.80,
|
||||||
|
|||||||
Reference in New Issue
Block a user