← Explainer · Markdown · Source on GitHub
# Regression validation: quick, multigrid and full Build the Release solution once, then run `verify-all` from the PolyCFD root. `full` remains the default. Every selection requires explicit CUDA by default and never silently falls back to a CPU accelerator. The same runner provides durable reports, evidence hashes, stop-on-failure and check-boundary resume for all subsets. ## Chebyshev diffusion — 2026-09-26 SOL-02a replaced the weighted-Jacobi diffusion primary phase with Chebyshev semi-iteration on undamped Jacobi ([Diffusion README](/src/PolyCfd.Gpu/Diffusion/README); tolerance, 400/800 budgets, colored fallback and device bytes unchanged). The final SOL-02a build (frozen as `output/builds/sol02a` until SOL-02c removes it; the report's provenance records its assembly hashes) passes **`verify-all --suite quick`** (`output/validation/sol02a-fix-quick/report.json`): 14/14 regression checks, 1,067 core and 613 CUDA tests without failures or skips, and the nine scientific workloads. Its performance check against the pre-change reference `output/validation/sol04a-quick/performance-reference.json` passes on an idle machine (idle checks in `output/validation/sol02a-fix-idle-checks/`): median solver step of the moving fans −62.5% (semi-Lagrangian) and −61.5% (MacCormack), backward step −3.0%, other cases +0.2 to −5.9%; small-case elapsed increases (+12.8% to +44.9%, under a second each) stay within their noise floors. The build before the review fix pass (`output/validation/sol02a-quick/`) gave the same result; the fix pass changed no scenario result (identical per-step iteration counts, bitwise-equal final fields except the cavity-sphere case's run-to-run floor). On the short 128³ fan the median diffusion count falls from 266 to 56 and final fields differ from the Jacobi build by relative L2 about 3e-6. Free device memory does not drop over 200 repeated diffusion or pressure solves (`output/validation/sol02a-free-memory.json`). The prescribed-flow enclosure's four 20-step startup controls accept at cap 800 and its step-3 audit converges in 76 iterations with independent host residual 9.289e-7 (WSL; see the [enclosure plan](https://github.com/hankbeasley/polycfd/blob/18102808d7066ed97d8908d66755a68df8d0516e/docs/plans/prescribed-flow-enclosure.md)). The multigrid and full suites, their performance comparisons and SOL-02b follow in the [solver seams plan](https://github.com/hankbeasley/polycfd/blob/18102808d7066ed97d8908d66755a68df8d0516e/docs/plans/solver-seams-chebyshev.md); until then this is quick-suite evidence only. **CPU backend not run (user directive).** ## Diffusion fallback validation — 2026-09-24 This section validated the previous weighted-Jacobi primary phase with the colored fallback; it keeps its frozen-build binding as history. **Full CUDA scientific checks pass; overall regression remains failed on timing (30/31 required checks).** The report is `output/validation/diffusion-full-verified-20260924/report.json`, bound to frozen `output/builds/diffusion-verified-20260924` artifacts. All **1,525 selected tests**, **25 native simulations**, the five-case channel study/replay and saved-field regressions pass. Both full fans pass. The planar analytical velocity error is 0.8565%; the principal 128³ cavity differs from OpenFOAM by 0.6822%. All 22 nonlinear snapshots pass regression, with maximum velocity changes 0.002690% / 0.004534% at base/half timestep. Separate strict coarse-cavity and spectral qualifications retain their known failed verdicts. No physical reference or limit changed. The guarded full run took **233.104 raw-clock minutes (3 h 53 min)**, excluding the subsequent timing control/retry. This is observed completion time under the recorded workload, not an isolated solver-performance claim. The shared 800-sweep cap supersedes the historical 200-sweep setting in the frozen 2026-09-19 channel configuration; the five-case physical acceptance criteria are unchanged. The first performance attempt failed against the unchanged historical reference. One deliberate retry remeasured all nine scientific workloads successfully and reused every completed long check. It still fails backward-step elapsed +32.9%, median +25.8%, and shear-Z/planar-SL medians +25.8%, against the unchanged 20% allowance and noise floors. Both failed attempts remain intact. A control using the exact historical libraries and matching scientific identities also fails its old gate (backward-step elapsed +41.8%, median +24.9%). Monitoring revealed intermittent Windows PolyCFD workers during both timing sequences. These runs are **not isolated timings**; do not treat them as proof of a patch-related slowdown, a speedup, or grounds to replace a reference. Arrange a quiet Windows test session before another deliberate timing phase. OpenFOAM and its old 200-sweep continuation remain paused until the new required gate passes. The current solver passes its earlier matched before/after comparison: 316.324 → 288.697 s process time. Balanced isolated-kernel observations are within about 1–2% on the two tested ordinary-path grids. Variable workstation load limits performance conclusions. Four 20-step enclosure controls, an independent step-3 residual audit and 92 focused diffusion tests pass; these do not establish t=16 enclosure accuracy. The final GPU DLL matches the measured cleaned build. Final repository static/CUDA verification passes **1,579 tests** (1,052 core, 481 GPU and 46 workbench CUDA), zero failures/skips, in `output/verify/diffusion-verified-static-gpu-20260924/receipt.json`. All 37 focused retry/resume tests pass. The initial static/fast attempt retains workbench schema/event-stream failures; its 1,000 UI tests and build passed. The Linux documentation-checker error was fixed and static rerun successfully. That initial receipt is `output/verify/diffusion-correction-static-fast-20260924/receipt.json`. Receipt `notRun` entries distinguish the selected repository tiers from this separate numerical suite. **CPU backend not run (user directive).** The initial candidate's full attempt, `output/validation/diffusion-full-20260924`, stopped at timing after 1,519 selected tests and nine scientific workloads passed; its long cases were not run. That failure and the first completed final-build report are preserved. All measurements, build identities, worker observations and remaining limitations are in the [maintained diagnostic report] (unavailable local reference: `../../openfoam/compare/ENCLOSURE_N128_DIAGNOSTICS.md`) and [machine-readable evidence] (unavailable local reference: `../../openfoam/compare/enclosure_diffusion_fix.json`). ## Post-pull integration — 2026-09-24 The requested commit integrates upstream `422be0b` (Workbench Gate B). The measured diffusion implementation and performance-retry helper are unchanged; upstream already includes the lifecycle assertion correction and adds output failure coverage, so its test version was retained. `python3 tools/verify static fast gpu --artifacts-path output/builds/diffusion-post-pull-20260924 --output output/verify/diffusion-post-pull-20260924` passed 1,066 core, 482 GPU, 730 Workbench host and 1,010 UI tests, with no skips. Workbench CUDA passed 53/54: `FaultMatrixTests.AKillAtEachBoundaryPreservesOutputsNeverDuplicatesDispatchAndProvesExitBeforeTheSlotReopens` failed for `AfterStart / KillService`, asserting that a later worker launched before the test observed the orphan exit. This worker-recovery failure is unresolved; the failed receipt and TRX remain in that output directory. The first UI typecheck/build failed because the pulled Playwright dependency was not installed. After `npm ci --no-audit --no-fund` in `src/workbench-ui`, `npm run build` passed (including typechecking), with its log retained as `ui-build-after-install.log` in the same receipt directory. The lockfile was unchanged. A fresh `python3 tools/verify static` using separate artifacts passes all 11 steps in `output/verify/diffusion-post-pull-static-20260924/receipt.json`. The aggregate first receipt remains failed; follow-up results do not erase it. Both receipts list `verify-all` as required and not run by `tools/verify`. The full numerical suite above belongs to the preserved pre-pull build; it was not rerun for this integration and is not a full pass for the pulled tree. Its unresolved performance gate remains documented. **CPU backend not run (user directive).** ## Choose coverage for the change | Selection | Use for | Expected duration on this RTX 3080 workstation | | --- | --- | --- | | `--suite quick` | Routine numerical, API, scenario, advection or diffusion changes; broad first check | **8–12 minutes**, estimate | | `--suite multigrid` | Changes confined to MG smoothing, restriction/prolongation, hierarchy or preconditioning | **6–10 minutes**, estimate | | `--suite full` | Shared solver/indexing/geometry changes, long-time stability, force statistics, refinement, or final broad numerical acceptance | **About 3¼–4 hours**, observed full runs; latest 3 h 53 min before timing retries | The short-suite estimates are assembled from previous check timings, not measured end-to-end results of these new subsets. Build time is additional. CPU/GPU load, JIT and clock variation affect runtime. The full duration uses the preserved v5 run's two `CLOCK_MONOTONIC_RAW` storage-guard intervals (about 3 h 16 min including its brief checkpoint/resume gap), before removing about one minute of duplicate short simulations. OpenFOAM reference generation is separate. For **Jacobi pressure/nullspace changes**, use quick: it includes the tight residual regression and a 20-step 128×128×256 stationary fan through the historical step-6 failure. For **multigrid**, the focused GPU selection includes shared PCG, pressure, projection, BLAS, boundary/halo, div-grad, moving-wall, session and moving workflow tests. It deliberately keeps Jacobi comparison controls. All core tests other than the duplicate simulation wrappers also run. Selecting only classes named `Multigrid` would miss these integration contracts. The session-level memory audit (`InspectionPreflightTests`) sits outside the selection, but the per-solver footprint test (`Multigrid.PressureSolverFootprintTests`) is inside it, so a multigrid run still fails when a solver buffer changes without its owner's byte function. The pressure solver contract and transfer-budget theories over both solver kinds (`Numerics.Pcg.PressureSolverContractTests`, `PressureSolverResourceTests`) are inside it too. For **shared pressure, diffusion, advection, geometry or indexing changes**, start with quick and use full before claiming broad numerical acceptance. Both long fan schemes remain valuable for accumulated error; do not shrink the 128³ moving-fan grid because that changes the hub connectivity. Force-related changes need the full cylinder statistics window. Schema/docs-only work can use its focused checks from [AGENTS.md](https://github.com/hankbeasley/polycfd/blob/18102808d7066ed97d8908d66755a68df8d0516e/AGENTS.md) without a solver suite. UI checks remain separate. No automatic changed-file dependency inference is used. Membership and filters are explicit in [SuiteCases.cs](https://github.com/hankbeasley/polycfd/blob/18102808d7066ed97d8908d66755a68df8d0516e/validation/PolyCfd.Validation/Suites/SuiteCases.cs); the multigrid GPU selection is pinned by a committed [snapshot](https://github.com/hankbeasley/polycfd/blob/18102808d7066ed97d8908d66755a68df8d0516e/test/PolyCfd.Gpu.Tests/Suites/multigrid-selection.txt) that a test compares by reflection, so renaming a test cannot silently shrink it. Both are protected paths for [`tools/verify`](https://github.com/hankbeasley/polycfd/blob/18102808d7066ed97d8908d66755a68df8d0516e/test/README.md#one-command-verification), which never runs these suites itself; when numerical code changed it prints the suite this table suggests (multigrid for multigrid-only code, otherwise quick, then full) as advice. Reports bind the chosen subset, filters, inputs, build and references. A passing subset means **that subset passed**; it does not mean full validation passed. ## Commands and prerequisites Run performance checks sequentially without competing CFD jobs. Accuracy checks may share the machine when appropriate, but their timings do not establish a performance result. Use a fresh output for each build/selection. ```bash dotnet build PolyCfd.sln -c Release dotnet src/PolyCfd.Cli/bin/Release/net10.0/PolyCfd.Cli.dll verify-all \ --suite quick --backend cuda --output output/validation/quick \ --performance-baseline /path/to/accepted-raw-performance.json --check-performance dotnet src/PolyCfd.Cli/bin/Release/net10.0/PolyCfd.Cli.dll verify-all \ --suite multigrid --backend cuda --output output/validation/multigrid \ --performance-baseline /path/to/accepted-raw-performance.json --check-performance \ --comparison-root ../openfoam --python ../openfoam/.venv/bin/python dotnet src/PolyCfd.Cli/bin/Release/net10.0/PolyCfd.Cli.dll verify-all \ --suite full --backend cuda --output output/validation/full \ --performance-baseline /path/to/accepted-raw-performance.json --check-performance \ --comparison-root ../openfoam --python ../openfoam/.venv/bin/python ``` Quick needs no independent OpenFOAM fields. Multigrid needs the comparison repo, its `compare/subsets/cavity.py`, Python dependencies in `compare/requirements.txt`, and the hash-matched `cavity-64` entry in `compare/suite_references.json`. It compares the final field at t=10 with the original velocity/energy/profile/pressure limits; it makes no mesh-refinement or timestep-refinement claim. Full needs the complete reference inventory and channel protocol inputs. Missing evidence stays incomplete. All three selections measure the **same nine performance workloads**, so the same accepted baseline applies. On this workstation the preserved local reference is `../openfoam/enclosure/runs/incremental-projection/before-suite/performance.json`. It is local run data, not guaranteed in a fresh clone. References must match case keys, clock, timing boundary, device and environment. Old stopwatch references are incompatible and are not rescaled. The 20% allowance and noise floors are unchanged. Without a reference, the performance check is **incomplete**; independent numerical checks still run and the overall exit code remains 2. `--keep-going` controls continuation after failed regression checks, not this missing-reference verdict. Never record a new baseline merely to make a failed comparison pass. Use `--record-performance --performance-baseline /new/path.json` only for an intentional new reference; it never overwrites one. See [performance scope](/docs/PERFORMANCE_VALIDATION). To check only the selected test projects first, add `--stop-after gpu-tests`. The rest stays pending and the exit code is 2. Continue with the identical command, remove `--stop-after`, and add `--resume`. Changing `--suite` requires a new output; it cannot turn a previous subset into a full pass. ### Isolated builds while another campaign owns frozen binaries Do not rebuild over test/CLI deployments bound to a running or resumable campaign. Use .NET's separate artifacts directory and tell the suite where its matching test binaries are. This avoids stale test dependencies without copying deployments. ```bash dotnet build PolyCfd.sln -c Release --artifacts-path output/builds/my-validation dotnet output/builds/my-validation/bin/PolyCfd.Cli/release/PolyCfd.Cli.dll verify-all \ --artifacts-path output/builds/my-validation \ --suite quick --backend cuda --output output/validation/my-quick \ --performance-baseline /path/to/accepted-raw-performance.json --check-performance ``` The option points to the same artifacts root used for the build. The suite runs `bin/<test-project>/release/<test-project>.dll` and verifies production DLLs against the executing CLI. Without it, normal `test/<project>/bin/Release/net10.0` paths apply. ## Coverage and expensive checks | Coverage | Quick | Multigrid | Full | | --- | --- | --- | --- | | Core contracts and validator tests | All | All | All | | GPU tests | All CUDA-compatible | Pressure/MG and shared integration selection | All CUDA-compatible | | Nine scientific controls and unchanged performance gate | Yes | Yes | Yes | | Stationary fan, original Jacobi settings and full grid | First 20 steps | Small cross-solver tests | Full 1,000 steps | | 64³ cavity t=10 and independent final-field comparison | No | Yes | Yes | | Poiseuille both schemes, cavity sphere, obstacle channel, cylinder force window | No | No | Yes | | Both 128³ ten-revolution fans; planar 128³ t=20 | No | No | Yes | | Full cavity and nonlinear Taylor–Green refinement matrices | No | No | Yes | | Channel v2 five steady cases/replay | Startup unit test only | Startup unit test only | Yes | | Principal cavity refinement and direct nonlinear trajectory regression | No | No | Yes | | Strict full cavity/spectral qualification | Not requested | Not requested | Separate verdict, unchanged limits | Eight xUnit simulation wrappers (two planar, four periodic controls, two moving fans) have `SuiteCase=Mandatory`. `verify-all` excludes those wrappers because it runs the same cases explicitly with their scientific checks and timing. Ordinary `dotnet test` still runs them. Tests of rejection/validation logic remain selected. This removes about one minute of repeated work without removing a scientific case. The previous full report's rounded per-check times explain the main costs: | Group | Approximate duration | Reason retained in full | | --- | --- | --- | | Both ten-revolution fans | 65 min | Long-time moving geometry/diffusion/advection stability | | Cavity + nonlinear vortex matrices | 55 min | Spatial/timestep refinement and full-field trajectories; half-step runs account for about 30 min | | Full stationary fan | 23 min | Sustained tight Jacobi convergence and cut-cell conservation | | Cylinder force window | 16 min | Complete, settled shedding-cycle statistics | | Both Poiseuille trajectories | 9 min | Analytical startup and wall/diffusion accuracy for both schemes | These component times are approximate report timestamps, not isolated performance benchmarks. Final field analysis takes only seconds and reuses simulation outputs; removing that analysis would lose useful evidence with little saving. The full suite means this explicit catalog, not proof of every possible physical problem. CPU-specific backend contracts (`Backend=CPU`) are excluded for a CUDA run and listed in report provenance. Tests run on CUDA unless `POLYCFD_TEST_BACKEND=cpu` selects the CPU accelerator explicitly; `--backend cpu` sets it for its test projects, and the selector exists only in test code. Test projects run with the checked-in serial [`test/gpu.runsettings`](https://github.com/hankbeasley/polycfd/blob/18102808d7066ed97d8908d66755a68df8d0516e/test/gpu.runsettings), copied into each attempt and hashed into the provenance. Host metadata and analytical calculations still execute normally. Skipped tests are reported as incomplete rather than counted as passes. UI tests, the workbench tests and OpenFOAM reference **generation** are outside this solver regression catalog. The comparison checkout supplies `compare/validate_suite_accuracy.py` and the hash-bound `compare/suite_references.json` inventory. It reads current suite HDF5 fields without duplicate exports. Required field regression checks retain the original 64³/128³ cavity accuracy limits, 64³→128³ refinement and 128³ timestep limits, and require decreasing 32³/64³/128³ velocity errors. Full coarse cavity qualification remains a separate result with the original 2% limits. For nonlinear Taylor–Green, direct 128³ before/after fields at both timesteps are compared at t=0,2,…,20 against the preserved periodic-index-corrected production trajectories. Every velocity L2 and kinetic-energy difference must be <=0.1%. This bound was set before the first direct comparison; it is numerical regression acceptance, not a continuum accuracy claim. The unchanged 2% spectral accuracy and refinement gates still execute and retain failed results independently. The catalog is explicit and independent of arbitrary files in `Baselines/`. Use `baseline replay` to check a specific complete saved reference. Historical CSV-only data remain preserved; missing settings are never inferred from folder names or silently converted into a current reference. The separate enclosure reference/campaign and UI tests are outside this solver regression catalog. ## Results and restart `<output>/report.json` is written atomically before and after every check. It lists all planned checks, their states, attempts, evidence hashes, build/dependency and reference identities, actual device and performance results. Test fingerprints include deployed dependencies and fixtures; generated `output/` and `TestResults/` directories and debug symbols are excluded so a test run does not invalidate its own resume. Each attempt has its own log and outcome; numerical runs retain their normal scenario and verification records. `unit-tests` and `gpu-tests` retain TRX results with individual failures. The report contains `regressionState` and `qualificationState`; each check explicitly records `qualificationOnly`, which is bound into the resume identity. Exit codes are 0 (all regression checks passed and all selected qualification checks attempted), 1 (regression failure), 2 (incomplete regression or pending work), and 130 (canceled). A failed/incomplete scientific qualification stays failed/incomplete even when the regression exit code is zero. The console prints both verdicts. A resumed report cannot reclassify a failed regression as qualification. The default stops at the first failed **regression check**. Qualification failures are recorded and the remaining qualification checks run. A test-project check finishes its test run before the suite stops. Inspect the evidence before continuing. Add `--keep-going` to continue independent checks after understood failures. Resume with the **same command and output**, adding `--resume`; add `--retry-failed` only when deliberately retrying failed checks. Failed attempts remain intact. If the performance gate is retried, all nine mandatory workloads are remeasured sequentially with their scientific checks in the new performance attempt directory. Previously completed long checks and original timings stay intact. A failed fresh scientific check cannot reuse an earlier passing timing. The first performance attempt uses the original nine measurements without duplicating them. Retry after addressing the suspected timing condition; retain every attempt and do not repeat until a favorable sample appears. After the remaining checks finish, add `--stop-after performance` to bound a deliberate timing retry; completed later results remain visible and retain their verdicts. Completed checks are reused only if the build, catalog, backend, environment, references and artifact hashes still match. Changed binaries or inputs require a fresh output. A lock prevents two writers sharing one output. Resume works at check boundaries: an interrupted case/test project/study restarts in a fresh attempt, while earlier completed checks are reused. It is not a mid-simulation fluid-state checkpoint. Use `--stop-after performance` (or another report check ID) for a bounded phase, then omit it when resuming; the later catalog entries remain pending and the phase cannot report overall success. A completed test project with skipped tests is reused with its incomplete verdict; successful tests need not run again. Missing prerequisites and interruptions are retried. A new or changed reference changes the suite identity and requires a new output. On WSL, check both the Linux filesystem and `/mnt/c`. Use the comparison repo's `run_with_storage_guard.py` to reserve backing-volume space for full runs. The current cavity/nonlinear fields, including geometry, require about 1.655 GiB uncompressed. Suite exports use the existing lossless shuffle/deflate level-1 writer; constant geometry compresses strongly and no field precision is changed. Allow at least 1.1 GiB for the compressed field matrix, plus tests, manifests and logs. This is an estimate; the guard monitors actual free space throughout execution. Bounded phases can budget their own remaining outputs and recheck actual free space before the next phase; do not admit the whole matrix against a smaller output estimate. The separate enclosure campaign needs its own output budget. ## Portable verification identities The full-suite rollout found a pre-existing platform dependency: verification hashes included the serializer's OS-specific newline, and the embedded backward-step reference hash depended on Git checkout line endings. Hashing now uses LF on every platform. Existing Linux identities and numerical reference values remain unchanged. The fixture retains all original Windows hashes and checks them independently alongside the canonical identities. An old Windows record can be converted explicitly to a **new directory**: ```bash dotnet src/PolyCfd.Cli/bin/Release/net10.0/PolyCfd.Cli.dll baseline convert \ /path/to/windows-record --output /path/to/canonical-record ``` Conversion verifies the original hash before normalizing it, checks the known independent reference fingerprint, preserves result/field bytes, records the mapping, and leaves the source untouched. An altered identity or unrelated reference is rejected; normal record reads accept only the canonical identity. ## Subset implementation verification — 2026-09-21 VAL-05's isolated Release build passes **682 core + 180 selected GPU tests**, no failures or skips, using CUDA. Five comparison tests pass; the new cavity entry point reproduces the previous 64³ field verdict (velocity L2 difference 1.30577%) against unchanged limits. The new 20-step full-grid Jacobi fan also passes on CUDA. Checkpoint resume reuses the three completed backend/test-project checks; later checks remain pending and the bounded suite correctly exits 2. Quick catalog selection and duplicate-wrapper exclusion are checked explicitly. [Evidence and commands] (unavailable local reference: `../output/validation/validation-subsets-20260921/assessment.json`) record the selected tests, initial corrected test-assertion failure, and preserved comparison inputs. Core/GPU/Execution DLLs are byte-identical to CFG-01's build. No full suite or performance gate was rerun for this orchestration change. The checks shared the machine with OpenFOAM and do not establish new performance numbers or measured end-to-end durations for the subsets. The ready CLI is `output/validation/validation-subsets-20260921/artifacts/bin/PolyCfd.Cli/release/PolyCfd.Cli.dll`; pass `--artifacts-path output/validation/validation-subsets-20260921/artifacts` when using it. The normal earlier deployment remains intact for the enclosure continuation. The previous full result below belongs to its frozen build. ## Local regression result — 2026-09-21 **Full CUDA regression passes: 31/31 required checks, exit 0.** Both independent scientific qualification checks were attempted and remain **failed** at their original limits. Regression success does not qualify every grid or physical problem. The completed output is [`verify-all-regression-20260921-v5`] (unavailable local reference: `../output/validation/verify-all-regression-20260921-v5/report.json`), using frozen Release build `verify-all-build-20260921-v4` on the RTX 3080. The subsequent MacCormack-default update is checked separately in [`maccormack-default-20260921`] (unavailable local reference: `../output/validation/maccormack-default-20260921/assessment.json`): Release build, schemas and 1,097 core/GPU tests pass. It pins established suite schemes explicitly; the full numerical/performance suite below belongs to the preserved v4 build and was not rerun for the default-selection change. The new CLI is in that follow-up's isolated `artifacts/bin/PolyCfd.Cli/release/` directory; the normal prior test deployment is retained so the completed frozen suite stays resumable. A future source rebuild uses the new defaults. All checks have one attempt. A completed-suite `--resume` took 4.00 raw-clock seconds and reused all 33 results without changing their identities, attempts or artifact hashes; a real earlier checkpoint also reused the first 13 checks. [Restart evidence] (unavailable local reference: `../output/validation/verify-all-regression-20260921-v5/completed-resume.json`) retains the exact command. Do not rebuild over this frozen executable or modify its bound references, test deployment or comparison scripts. | Required coverage | Current result | | --- | --- | | Release build | Zero warnings/errors | | Core and GPU tests | 682 + 413 = **1,095 passed**, zero failures or skips; CUDA selection, documented CPU-only exclusions | | Native scientific simulations | **25/25 passed**, including nine mandatory controls, full stationary fan and cylinder force window, both ten-revolution fans, planar vortex, four cavity and three nonlinear vortex runs | | Planar 128³ analytical trajectory to t=20 | Maximum velocity error **0.8565%**, within the original 2% limit | | Channel v2, five cases plus replay | Pass; finest flow error **0.19869%**, spatial ratio **4.02098**, steady timestep spread **2.1233e-6** of reference flow versus 1e-5; analytical startup-order test passes | | Principal 128³ cavity at t=10 | Velocity difference **0.6822%**, energy difference **0.0538%**, final maxDiv **5.722e-6**; 64³/128³ accuracy, fine refinement and half-timestep checks pass | | Nonlinear trajectory regression | All 22 snapshots pass; maximum before/after velocity differences **0.00269% / 0.00456%** at base/half timestep, below the predeclared 0.1% bound | | Nine-case performance gate | Pass against the unchanged reference, 20% allowance and existing noise floors; largest median-step increase **18.4%**, backward-step whole-case **+10.7%**, median step **+11.8%** | | Comparison and continuation tests | 129 comparison Python tests and six continuation tests passed | The [field regression] (unavailable local reference: `../output/validation/verify-all-regression-20260921-v5/field-regression/attempt-001/assessment.json`) and [channel assessment] (unavailable local reference: `../output/validation/verify-all-regression-20260921-v5/channel-refinement/attempt-001/study/assessment.json`) retain individual measurements. Strict cavity qualification still fails at 32³ (**2.6127%** velocity error) and 32³→64³ refinement (**3.0860%**), both against 2% limits. Nonlinear spectral velocity errors remain **10.0688% / 9.6864%** at 128³ base/half timestep against 2%; spatial difference is **29.8321%**, and timestep difference **1.6731%** exceeds 0.5%. Neither reference nor these limits was changed. These failed qualification results remain in the same report. The substantive solver correction is small: Jacobi PCG projects its recursive residual to zero volume-weighted mean after each update for singular pressure boundaries, reusing the existing device operation. No new option, buffer or production diagnostic API was added. Fixed-pressure and multigrid solves are unchanged. The [stationary-fan guide](https://github.com/hankbeasley/polycfd/blob/18102808d7066ed97d8908d66755a68df8d0516e/docs/STATIONARY_FAN_VALIDATION.md) records the failure mechanism, two new tests that fail on the old solver, 24 focused passing pressure tests and the full 1,000-step passing fan. Two matched five-step startup pairs measured **+8.0% raw process time** and +18.9% in the existing integration stopwatch diagnostics; these are bounded startup costs, not full-interval throughput. Validation was simplified by removing implicit discovery of historical CSV-only baselines, two empty skipped placeholders and noisy unit-test speed assertions. Explicit baseline replay remains available; repeated large-grid numerical tests and the existing performance gate retain their respective coverage. The versioned channel protocol measures steady timestep sensitivity and analytical startup convergence separately. Its original v1 ratio failure remains preserved. Failed attempts are retained: v3 exposes stationary-fan step-6 nonconvergence; v4 stops on shear-Y median timing **+20.5%** versus the unchanged 20% allowance. Three alternating old/new repetitions of that multigrid workload all put the new build inside the original limit and show no fix-related slowdown. The unchanged build then passed the fresh full v5 suite. See `output/validation/verify-all-timing-investigation-20260921/`; no baseline or performance threshold was relaxed. The enclosure reference campaign has resumed under the 18 GiB storage reserve. Its replacement continuation verifies this completed report, the channel-v2 assessment and every frozen CLI dependency before launching the separate CUDA matrix after reference qualification. The [enclosure handoff] (unavailable local reference: `../../openfoam/enclosure/README.md#restart-and-handoff`) and [workboard](/docs/WORKBOARD) carry its current state. Enclosure qualification and the production comparison remain incomplete. ### Preserved original combined-gate result (v2) At completion of the original v2 attempt, all catalog entries had been attempted. That suite was **failed**, with 27 passed, three failed and 12 incomplete checks. No v2 simulation remained running. The 27 passed entries comprise the CUDA backend check, performance gate and **25 scientific simulations**. Internal numerical acceptance and independent physical accuracy remain separate verdicts. | Evidence | Result | | --- | --- | | Release solution | Build passes, zero warnings/errors | | Final core/GPU test projects | 1,088 passed, zero failed, three existing skips | | Focused runner/identity tests | 56 passed, included in the project counts above | | Comparison Python suite | 122 passed | | Full-project restart | Reused both completed test projects with one attempt each | | Mandatory scientific controls | All nine passed | | Additional physical cases | Both Poiseuille schemes, cavity sphere, channel obstacle, stationary fan and full refined cylinder force window passed | | Long native cases | Both ten-revolution fans; planar 128³ to t=20; four cavity and three nonlinear Taylor–Green runs passed | | Planar analytical trajectory | Maximum velocity error 0.856%; energy-decay error 1.651%, both within limits | | Performance gate | Passed against unchanged pre-pressure reference: backward-step elapsed +2.8%, median step +1.4%; largest median-step increase +10.2% (short shear-Y case), within the existing 20% allowance and noise floors | | Frozen channel study | Failed steady temporal-ratio gate: 0.44955 versus required 1.5–2.5; finest flow error 0.19869% | | Independent cavity matrix | Failed at 32³ (2.613% velocity difference) and 32³→64³ refinement (3.086%); 64³/128³ field comparisons, 64³→128³ refinement and 128³ timestep checks pass | | Principal 128³ cavity at t=10 | OpenFOAM velocity difference 0.6822%, kinetic energy difference 0.0538%; final maximum divergence 5.722e-6, below 1e-5 | | Nonlinear Taylor–Green qualification | Failed: maximum spectral-reference velocity error 10.0688% at 128³, 9.6864% with half timestep; target 2% | | Nonlinear refinement | Failed: 64³→128³ velocity difference 29.832%; 128³ timestep difference 1.673% versus 0.5% limit | | Independent enclosure qualification | Incomplete: qualified reference fixture is absent; no new enclosure simulation launched | The channel assessment JSON exactly matches the preserved incremental-pressure study. It is the previously identified steady-state convergence-ratio failure, not a newly appearing change in those measurements. See the existing [channel assessment](https://github.com/hankbeasley/polycfd/blob/18102808d7066ed97d8908d66755a68df8d0516e/docs/DUCT_ACCURACY.md) for the small steady timestep differences and separate transient convergence evidence. Its frozen limits remain unchanged. The nonlinear Taylor–Green errors likewise reproduce the earlier approximately 10.07% / 9.69% results; native stability does not satisfy the stricter field limits. Cavity energy-history interpolation uses only one-second native samples and is not a resolved startup-trajectory validation; the accepted comparisons above use the final full-volume fields. The 12 incomplete check entries consist of two test projects with three existing skips, nine legacy saved CSV configurations lacking replay inputs, and the missing qualified enclosure reference. These are not passes. At that stage the enclosure campaign/controller remained paused. The completed v5 regression above now supplies the prerequisite for the replacement continuation. Evidence is under `output/validation/verify-all-regression-20260921-v2/` (`report.json`, `handoff.json`, per-check logs/TRX/outcomes and independent `assessment.json` files). The frozen CLI remains under `output/validation/verify-all-build-20260921-v2/`. Resume and postprocessing reused all completed simulations. The channel failure stopped the numerical phase; `--resume --keep-going` then evaluated saved cavity/Taylor–Green fields and recorded the missing enclosure prerequisite without retrying failed studies. All failed attempts and original references remain intact. Changed solver/analysis inputs require a new suite identity and output; do not rebuild over the frozen evidence. Storage cleanup removed 185 historical intermediate exports (16.063 GiB), retaining canonical comparison snapshots, initial/final native fields and every bound reference. Windows free space measured about 39.5 GiB immediately after that cleanup; recheck live capacity before further runs. Continue to reserve 18 GiB and budget new outputs separately. See the [cleanup inventory] (unavailable local reference: `../../openfoam/compare/cleanup-20260921.json`).