Skip to content

Add GMRES(m) linear solver — scalar, AVX2, NEON, OMP backends (ROADMA…#198

Merged
shaia merged 6 commits into
masterfrom
feature/gmres-linear-solver
Jul 7, 2026
Merged

Add GMRES(m) linear solver — scalar, AVX2, NEON, OMP backends (ROADMA…#198
shaia merged 6 commits into
masterfrom
feature/gmres-linear-solver

Conversation

@shaia

@shaia shaia commented Jul 5, 2026

Copy link
Copy Markdown
Owner

…P §1.2)

Restarted GMRES(m) completes the Krylov solver suite and provides a non-symmetric-capable solver for future implicit integrators (§1.5). On the current SPD Poisson operator it cross-validates against CG to within 1e-4 max-diff.

Algorithm choices that prevented silent bugs:

  • Right preconditioning so the Hessenberg residual estimate equals the true unpreconditioned residual, keeping stats.final_residual and the CG cross-check consistent.
  • Convergence decided on the recomputed true residual after each restart, not the cheap Givens estimate, which drifts below the real residual on finer grids due to loss of MGS orthogonality.
  • Dense O(m²) Givens/Hessenberg/back-sub kept as plain scalar in every backend (AVX2, NEON, OMP) for byte-consistent results across backends.

New sources: linear_solver_gmres.c (scalar), linear_solver_gmres_simd_template.h (vectorizes only O(n) primitives), linear_solver_gmres_avx2.c, _neon.c, _omp.c. New tests: test_gmres.c (12 cases), test_gmres_avx2.c, test_gmres_neon.c, plus GMRES OMP case in test_omp_consistency.c. All 75 fast-suite tests pass. GPU backend deferred (noted in ROADMAP).

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds a restarted GMRES(m) linear solver to the Poisson solver suite, including scalar, OpenMP, and SIMD (AVX2/NEON) implementations, along with new unit/consistency tests and documentation updates. This expands the library’s Krylov solver coverage to include a method suitable for future non-symmetric operators while cross-validating against existing CG behavior on the current SPD Poisson operator.

Changes:

  • Implement restarted GMRES(m) across scalar, OpenMP, and SIMD (AVX2/NEON) backends and wire it into solver creation/dispatch.
  • Add new GMRES-focused unit tests plus cross-backend consistency tests (scalar vs SIMD, scalar vs OMP), and hook them into CTest.
  • Update public API/docs/roadmap to reflect the new method and the new params.restart knob.

Reviewed changes

Copilot reviewed 18 out of 18 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
tests/math/test_omp_consistency.c Adds OMP vs scalar GMRES consistency test and registers it in the existing OMP consistency test runner.
tests/math/test_gmres.c New comprehensive GMRES(m) unit test suite (creation/init, convergence, CG cross-checks, restart behavior, preconditioning seam, error handling).
tests/math/test_gmres_neon.c New NEON-vs-scalar numerical consistency test for GMRES SIMD backend.
tests/math/test_gmres_avx2.c New AVX2-vs-scalar numerical consistency test for GMRES SIMD backend.
ROADMAP.md Updates solver backend matrix and roadmap text to mark GMRES(m) implemented and clarify GPU SOR status.
lib/src/solvers/linear/simd/linear_solver_simd_dispatch.c Extends SIMD dispatcher to route GMRES to AVX2 or NEON implementations at runtime.
lib/src/solvers/linear/simd_template/linear_solver_gmres_simd_template.h Introduces the parameterized SIMD GMRES(m) implementation used by AVX2 and NEON backends.
lib/src/solvers/linear/omp/linear_solver_gmres_omp.c Adds OpenMP-parallel GMRES(m) backend (parallel O(n) primitives; dense pieces remain scalar).
lib/src/solvers/linear/neon/linear_solver_gmres_neon.c Adds NEON macro wrapper and includes the GMRES SIMD template (with OpenMP requirement).
lib/src/solvers/linear/avx2/linear_solver_gmres_avx2.c Adds AVX2 macro wrapper and includes the GMRES SIMD template (with OpenMP requirement).
lib/src/solvers/linear/cpu/linear_solver_gmres.c Adds scalar reference GMRES(m) implementation (right-preconditioned Jacobi seam, restart loop).
lib/src/solvers/linear/linear_solver.c Adds params.restart defaulting and GMRES factory wiring in poisson_solver_create().
lib/src/solvers/linear/linear_solver_internal.h Declares GMRES factories and introduces GMRES constants (default restart, breakdown threshold).
lib/include/cfd/solvers/poisson_solver.h Extends public API with POISSON_METHOD_GMRES, params.restart, and GMRES solver type strings.
lib/CMakeLists.txt Adds GMRES sources to scalar/SIMD/OMP build source lists.
docs/reference/solvers.md Documents GMRES(m) usage, parameters, and supported backends.
docs/reference/api-reference.md Updates reference docs to include GMRES method and the restart parameter.
CMakeLists.txt Adds GMRES tests to the build and registers them with CTest.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread tests/math/test_gmres.c
Comment thread tests/math/test_omp_consistency.c Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 18 out of 18 changed files in this pull request and generated 2 comments.

Comment thread docs/reference/api-reference.md Outdated
Comment thread docs/reference/api-reference.md

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 18 out of 18 changed files in this pull request and generated 2 comments.

Comment thread docs/reference/api-reference.md Outdated
Comment thread docs/reference/api-reference.md
@shaia shaia force-pushed the feature/gmres-linear-solver branch from d04469c to 70f7c65 Compare July 7, 2026 04:37
shaia added 5 commits July 7, 2026 07:40
…P §1.2)

Restarted GMRES(m) completes the Krylov solver suite and provides a
non-symmetric-capable solver for future implicit integrators (§1.5).
On the current SPD Poisson operator it cross-validates against CG
to within 1e-4 max-diff.

Algorithm choices that prevented silent bugs:
- Right preconditioning so the Hessenberg residual estimate equals the
  true unpreconditioned residual, keeping stats.final_residual and the
  CG cross-check consistent.
- Convergence decided on the recomputed true residual after each restart,
  not the cheap Givens estimate, which drifts below the real residual on
  finer grids due to loss of MGS orthogonality.
- Dense O(m²) Givens/Hessenberg/back-sub kept as plain scalar in every
  backend (AVX2, NEON, OMP) for byte-consistent results across backends.

New sources: linear_solver_gmres.c (scalar), linear_solver_gmres_simd_template.h
(vectorizes only O(n) primitives), linear_solver_gmres_avx2.c, _neon.c, _omp.c.
New tests: test_gmres.c (12 cases), test_gmres_avx2.c, test_gmres_neon.c, plus
GMRES OMP case in test_omp_consistency.c. All 75 fast-suite tests pass.
GPU backend deferred (noted in ROADMAP).
…norm-for-norm stats match

The docstring claimed the test validates stats.final_residual against a
recomputed true residual, but the independent check uses the max-norm while
the reported residual is a 2-norm — so it verifies smallness, not an exact
norm match. Reword to match what the test actually asserts.
The test allows an RMS L2 difference up to 1e-9 (parallel-reduction rounding),
so the solutions are numerically consistent, not bit-for-bit identical. Fix the
docstring to reflect the actual tolerance-bounded assertion.
The Poisson methods snippet used a nonexistent type name (poisson_method_t),
fabricated fixed numeric values, listed a POISSON_METHOD_PCG that does not
exist, and omitted GAUSS_SEIDEL and MULTIGRID. Mirror the real enum from
poisson_solver.h and note that preconditioning is a separate params field, so
consumers get an accurate, copy-pasteable reference.
verbose is a bool (not int), the preconditioner field type is
poisson_precond_type_t (not poisson_precond_t), and the omega default is 0
(auto-optimal), not 1.5. Mirror poisson_solver.h so the struct is
copy-pasteable into real code.
@shaia shaia force-pushed the feature/gmres-linear-solver branch from 70f7c65 to b21d0fe Compare July 7, 2026 04:42
@shaia shaia merged commit 9a17e7f into master Jul 7, 2026
18 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants