555a72cbc04e1d21ad35367a6b915b05dbbc1a34
3
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
327da7ff47 |
rtx-cfd: multigrid-PCG projection — 30x faster, same answers — and the CFD1 refinement study
Performance Benchmarks / Run Benchmarks (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
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
Falsifier 4 of the Turek–Hron geometry decision fired (the SOR projection
cost 0.09 s/step at 250x41 and an hour per run at 5 mm); this answers it.
solvers::incompressible::poisson: PoissonProblem (cell-centred five-point
SPD operator as per-cell face coefficients + Dirichlet diagonal extra +
active mask) and solve_multigrid_pcg — conjugate gradient preconditioned
by one V-cycle of geometric multigrid: aggregation by 2 per direction (odd
sizes absorbed, coarse cell active iff any child is), the Galerkin coarse
operator for piecewise-constant prolongation / summation restriction,
symmetric Gauss–Seidel smoothing, coarse correction scaled by 2 (Braess's
under-correction of unsmoothed aggregation; scalar, so the preconditioner
stays symmetric and positive on range(A)), L1 TRUE-residual stop with a
stagnation guard. Singular systems are handled per connected component of
the active cells (mean projection and level per pure-Neumann component;
the anchor's component to p[anchor] = 0). PoissonSolverKind::{Sor,
Multigrid} on PisoParameters / EmbeddedParameters; Sor is the default and
its code is byte-for-byte untouched; an unconverged multigrid solve falls
back to the SOR sweeps for that projection.
Verified (poisson/tests.rs, tests/poisson_equivalence.rs):
- PCG iterations to cut the residual 1e-8 on the closed Neumann box at
32^2..256^2: 4, 4, 4, 4; ragged masked domains 8/8/8;
- manufactured recoveries to ~1e-14; Galerkin identity A_c v = R A P v to
7e-15 on every level (masked, outlet column, non-uniform conductances);
V-cycle symmetric to 1e-14; NaN-poisoned inactive cells untouched;
- two Neumann components with opposite imbalances, and a Dirichlet
component beside an imbalanced Neumann one (review scenarios): converge,
each component right up to its own constant;
- speed vs plain SOR at the same stop: 22.7x (128^2), 41x (256^2);
- same answers as SOR: PISO MMS 4.6e-8 relative, Taylor–Green divergence
1.4e-9 every step, embedded-circle MMS 7e-8, no-body bit-identity with MG
on both solvers, channel+outlet+circle 1.4e-10; CFD1 loads identical to
four digits at 0.003 s/step vs 0.094 (30x).
CFD1 refinement study (tests/turek_hron_cfd.rs, three grids, 257 s):
h = 10 / 6.6 / 5 mm -> control-volume drag 15.6156 / 15.2829 / 15.0988 vs
14.2929 (+9.25 / +6.93 / +5.64%), apparent order 0.71, Richardson
extrapolate 14.04; surface route and lift not monotone (flag 2/3/4 cells
thick) — the test asserts the measured band at the finest grid.
Built with a 4-agent workflow (core, integration, refinement study,
adversarial review); the review found no defects and four risks, three
fixed here (per-component projection, one symmetric smoother-sweep
parameter, acting on `converged` with an SOR fallback) and one recorded
(isotropic aggregation loses grid-independence on anisotropic cells).
rtx-cfd 301 -> 318 green.
Co-Authored-By: Claude Fable 5 <[email protected]>
|
||
|
|
b321a9aba7 |
rtx-cfd: Taylor-Green validates PISO's transient path — and fixes the projection's inner solve
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
With k = pi the decaying Taylor-Green vortex has zero normal velocity on the unit box for all time, so it fits the closed staggered domain exactly, with ZERO body force: convection is balanced identically by the true TG pressure and the decay comes from viscosity alone. This exercises exactly what the steady MMS harness cannot see — the time derivative, the unsteady pressure coupling and the projection's splitting error. The time-decaying tangential wall velocity enters by re-setting the wall hook each step. Measured (16/32/64, dt ~ h^2): L2 velocity 2.267e-2, 1.153e-2, 5.841e-3 — orders 0.97 and 0.98, first-order upwind's rate — and the kinetic-energy deficit against the exact e^(-4 nu pi^2 T) halves per refinement (0.0690, 0.0360, 0.0185; ratios 1.92, 1.95), within 2.3% on the finest mesh. Every step divergence-free to ~1e-7. Its first run caught two defects in the projection's inner solver: - The inner Gauss-Seidel stop summed the per-sweep iterate CHANGE — the same movement-not-residual pseudo-criterion the SIMPLE census flagged: slow modes move little per sweep while their residual is still large. - Plain GS contracts smooth modes by only 1 - O(h^2) per sweep, so the 400-sweep cap left max |div u| ~ 1e-2, GROWING with mesh size (8e-3 at 16^2 to 2e-2 at 64^2). The inner stop now measures the true equation residual, the sweep is SOR at the optimal Poisson factor omega = 2/(1 + sin(pi h)), and it converges relative to each projection's own source with a floor tied to the outer mass tolerance — so a long steady march no longer burns a hundred sweeps per step polishing negligible corrections. The steady MMS harness had masked all of this: a march to steady state iterates the projection to death regardless, which is why its divergence read 1e-9 while a 205-step transient left 1e-2. mms_piso's steady-state criterion is 1e-6 (was 1e-7): per-step projection noise at the mass tolerance floors |du/dt| just below 1e-6, and the L2 errors under measurement are 1e-2 to 1e-3. Its results are unchanged to six figures and still match SIMPLE's. 288 rtx-cfd tests, 0 failing. Co-Authored-By: Claude Fable 5 <[email protected]> |
||
|
|
9b097fca0d |
rtx-cfd: PISO validated by manufactured solution — after fixing the inverted projection
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
PisoSolver was the only major solver in the workspace with no verification of any kind. Writing the MMS harness for it (tests/mms_piso.rs) and inspecting the implementation found the census's defect species again: - The pressure correction had its SIGN inverted: it solved -lap(p') = +rho div(u*)/dt and then corrected with u = u* - (dt/rho) grad(p'), so each projection DOUBLED the divergence instead of removing it. - The momentum sweeps froze the near-wall lines (1..ny-1) and the pressure correction skipped the outer ring of cells (1..nx-1) — both exactly the defects repaired in SIMPLE. - The "explicit" predictor read neighbours the same sweep had already overwritten, so the step depended on sweep order. - The pressure gradient was dropped entirely on the last interior face. Rewritten as a genuinely explicit predictor plus anchored-Neumann projection on the staggered grid, with the conventions SIMPLE now embodies: near-wall lines are unknowns with half-cell wall diffusion, continuity on every cell, boundary faces are prescribed data. Momentum-source and wall-velocity hooks added so the manufactured solution can reach it. Measured (16 -> 32 -> 64): L2 velocity 3.516214e-2, 1.953750e-2, 1.037512e-2 — orders 0.85 and 0.91, first-order upwind's rate — with max |div u| ~ 1e-9 in every cell. The errors agree with SIMPLE's on the same meshes to six or seven significant figures: an implicit under-relaxed outer iteration and an explicit time-marching projection land on the same discrete steady solution, which is what sharing a spatial discretisation must produce and is very hard for two independently wrong solvers to fake. 285 tests, 0 failing. Co-Authored-By: Claude Fable 5 <[email protected]> |