Skip to content

Add Jacobi and BiCGSTAB OpenMP linear solvers - #202

Merged
shaia merged 7 commits into
masterfrom
omp-jacobi-bicgstab-solvers
Sep 12, 2026
Merged

Add Jacobi and BiCGSTAB OpenMP linear solvers#202
shaia merged 7 commits into
masterfrom
omp-jacobi-bicgstab-solvers

Conversation

@shaia

@shaia shaia commented Jul 25, 2026

Copy link
Copy Markdown
Owner

Completes the OpenMP linear-solver tier (previously only CG, GMRES, and Red-Black SOR), so the parallel projection/pressure paths can select these methods instead of falling back to unavailable.

Both are selectable via poisson_solver_create(method, POISSON_BACKEND_OMP) and follow the existing cg_omp/redblack_omp pattern: per-element updates are identical to the scalar reference, so results agree within reduction rounding (verified by new scalar-vs-OMP consistency tests). BiCGSTAB keeps the scalar solve loop and breakdown checks verbatim, parallelizing only the primitives.

Plain lexicographic SOR stays scalar/SIMD-only: it is inherently sequential, and its parallel form is the existing Red-Black SOR OMP solver.

Also updates the stale BiCGSTAB backend test, which asserted OMP create() returns NULL, to the runtime availability contract.

Completes the OpenMP linear-solver tier (previously only CG, GMRES, and
Red-Black SOR), so the parallel projection/pressure paths can select these
methods instead of falling back to unavailable.

Both are selectable via poisson_solver_create(method, POISSON_BACKEND_OMP)
and follow the existing cg_omp/redblack_omp pattern: per-element updates are
identical to the scalar reference, so results agree within reduction rounding
(verified by new scalar-vs-OMP consistency tests). BiCGSTAB keeps the scalar
solve loop and breakdown checks verbatim, parallelizing only the primitives.

Plain lexicographic SOR stays scalar/SIMD-only: it is inherently sequential,
and its parallel form is the existing Red-Black SOR OMP solver.

Also updates the stale BiCGSTAB backend test, which asserted OMP create()
returns NULL, to the runtime availability contract.
@shaia
shaia requested a review from Copilot July 25, 2026 17:43
@shaia shaia self-assigned this Jul 25, 2026

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 completes the OpenMP (“OMP”) tier for Poisson/linear solvers by adding Jacobi and BiCGSTAB OMP backends, enabling parallel pressure/projection paths to select these methods instead of falling back to unavailable backends.

Changes:

  • Add new OpenMP implementations for Jacobi and BiCGSTAB linear solvers and register them in the solver factory/build.
  • Add scalar-vs-OMP consistency tests for Jacobi and BiCGSTAB, and update the BiCGSTAB backend-availability test to follow the runtime contract.
  • Update documentation (ROADMAP/CHANGELOG) to reflect the completed OMP linear-solver tier and clarify why plain lexicographic SOR remains non-OMP.

Reviewed changes

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

Show a summary per file
File Description
tests/math/test_omp_consistency.c Adds Jacobi + BiCGSTAB scalar-vs-OMP consistency tests and wires them into the test runner.
tests/math/test_bicgstab.c Updates backend-availability expectations to match runtime poisson_solver_backend_available() contract.
ROADMAP.md Marks Jacobi/BiCGSTAB OMP as done and documents why plain SOR remains sequential.
lib/src/solvers/linear/omp/linear_solver_jacobi_omp.c New Jacobi OpenMP backend (parallel interior sweep, common solve loop).
lib/src/solvers/linear/omp/linear_solver_bicgstab_omp.c New BiCGSTAB OpenMP backend (OMP-parallel primitives, scalar-identical solve loop).
lib/src/solvers/linear/linear_solver.c Registers the new OMP solver factories for Jacobi and BiCGSTAB.
lib/src/solvers/linear/linear_solver_internal.h Exposes new OMP factory prototypes under CFD_ENABLE_OPENMP.
lib/include/cfd/solvers/poisson_solver.h Adds solver type string constants for the new OMP variants.
lib/CMakeLists.txt Adds new OMP solver sources to the OpenMP build source list.
CHANGELOG.md Documents the new OpenMP backends and their selection/consistency guarantees.

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

Comment thread lib/src/solvers/linear/omp/linear_solver_jacobi_omp.c
Comment thread lib/src/solvers/linear/omp/linear_solver_bicgstab_omp.c
The interior sweep casts nx/ny to int for its OpenMP loop bounds; a larger
dimension overflows the cast and the sweep silently does no work. Fail init
with CFD_ERROR_LIMIT_EXCEEDED so the solver never runs on unsupported dims.
bicgstab_size_to_int() maps an nx/ny above INT_MAX to 0, so every OMP
primitive skips its sweep, the initial residual reads zero, and the solver
reports false convergence. Fail init with CFD_ERROR_LIMIT_EXCEEDED before
allocating the work vectors.
Master's #206 renamed bicgstab_size_to_int, so once master is merged the OMP
BiCGSTAB primitives call an undeclared function and every CI build fails to
link.
Master's linear_solver_primitives_omp.h already provides dot_product, axpy,
apply_laplacian, compute_residual and copy_vector for the OMP Krylov solvers;
private copies here would let the implementations drift apart.
Master's poisson_solver_validate_grid_size also rejects grids whose nx*ny*nz
wraps size_t, which the hand-rolled INT_MAX checks missed: BiCGSTAB OMP would
allocate undersized work vectors and Jacobi OMP would memcpy a wrapped size.
Cover both in the shared oversized-grid table test instead of one-off tests.

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.

🔵 Needs a closer look

Add 3D OpenMP coverage for the new Jacobi and BiCGSTAB paths.

Review details

Suppressed comments (3)

tests/math/test_omp_consistency.c:410

  • These new consistency tests only initialize nz=1, but both implementations add a separate nz>1 path using k_start/k_end/stride_z. The existing 3D OMP suite covers only CG and Red-Black SOR (tests/math/test_poisson_3d.c:765-770), so z-plane indexing and boundary handling for the new Jacobi and BiCGSTAB backends can regress without being detected. Please add 3D OMP coverage for both methods, preferably comparing them with the scalar backends.
void test_jacobi_omp_vs_scalar(void) {

tests/math/test_omp_consistency.c:413

  • This new consistency test only initializes a 2D problem (nz == 1), so it never exercises the new Jacobi OMP 3D k_start/k_end and stride_z path. The existing 3D OMP suite covers CG and Red-Black SOR but not Jacobi; add a 3D Jacobi OMP-vs-scalar or convergence case before relying on this backend for 3D projection solves.
void test_jacobi_omp_vs_scalar(void) {
    double dx = (XMAX - XMIN) / (NX - 1);
    double dy = (YMAX - YMIN) / (NY - 1);
    size_t n = NX * NY;

tests/math/test_omp_consistency.c:514

  • This new consistency test also hard-codes nz == 1, leaving the new BiCGSTAB OMP 3D stencil and per-plane parallel primitives untested. The existing 3D OMP tests register only CG and Red-Black SOR, so add a 3D BiCGSTAB OMP-vs-scalar or convergence case to cover the path used by 3D callers.
void test_bicgstab_omp_vs_scalar(void) {
    double dx = (XMAX - XMIN) / (NX - 1);
    double dy = (YMAX - YMIN) / (NY - 1);
    size_t n = NX * NY;
  • Files reviewed: 11/11 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

@shaia
shaia merged commit 219f63b into master Sep 12, 2026
19 checks passed
shaia added a commit that referenced this pull request Sep 12, 2026
…lper

Merging master brings #202's Jacobi and BiCGSTAB comparisons, which call
init_sinusoidal_rhs with the old 2D signature and do not compile against this
branch's nz/dz version. Pass the 2D arguments explicitly, fail rather than skip
when an available OMP backend returns a NULL solver (the policy this branch
introduces), and reuse interior_rms_diff for the solution difference.
shaia added a commit that referenced this pull request Sep 12, 2026
…age (#207)

* Fail OMP consistency tests on a NULL solver and widen GMRES OMP coverage

Unity counts TEST_IGNORE as a pass, so a regressed OMP dispatch arm skipped the
only consistency check while CI stayed green. The GMRES OMP comparison now
covers Jacobi, restart 5 and 1, 3D, non-square, zero-RHS and max-iteration
cases, run at 1, 2 and 4 threads through OMP_NUM_THREADS because on MSVC the
test cannot reach the library's OpenMP runtime in-process. GMRES also joins the
3D Poisson and MG-preconditioner rejection tests.

* Compare 3D backend solutions field by field, not by error norm

The OMP- and SIMD-vs-scalar 3D checks compared each run's L2 error against the
analytical field, so two different solutions with equal error norms passed.
Keep both solutions and assert their interior RMS difference against a 1e-9
same-solver tolerance (measured 1.6e-15..4.0e-15 across OMP at 1-8 threads and
AVX2). The CG OMP and SIMD comparisons predate this PR; GMRES inherited the flaw.

* Adapt master's Jacobi/BiCGSTAB OMP consistency tests to the 3D RHS helper

Merging master brings #202's Jacobi and BiCGSTAB comparisons, which call
init_sinusoidal_rhs with the old 2D signature and do not compile against this
branch's nz/dz version. Pass the 2D arguments explicitly, fail rather than skip
when an available OMP backend returns a NULL solver (the policy this branch
introduces), and reuse interior_rms_diff for the solution difference.
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