@@ -375,6 +375,187 @@ GinkgoJL_CG
375375GinkgoJL_GMRES
376376```
377377
378+ ### PETSc.jl
379+
380+ !!! note
381+
382+ Using this solver requires loading PETSc.jl and MPI.jl, and initialising MPI:
383+ ```julia
384+ using PETSc, MPI, SparseMatricesCSR # SparseMatricesCSR is optional but recommended for best performance
385+ MPI.Init()
386+ ```
387+
388+ !!! warning "Serial only"
389+
390+ The current implementation supports only **single-process** solves (`MPI.COMM_SELF`).
391+ Passing a multi-rank communicator will raise an error. MPI-parallel support is planned
392+ for a future release.
393+
394+ ` PETScAlgorithm ` wraps PETSc's KSP (Krylov subspace) solvers and exposes the full PETSc
395+ preconditioner interface using [ PETSc.jl] ( https://github.com/JuliaParallel/PETSc.jl ) . It works with ** dense matrices** , ** ` SparseMatrixCSC ` ** , and
396+ ** ` SparseMatrixCSR ` ** (from [ SparseMatricesCSR.jl] ( https://github.com/gridap/SparseMatricesCSR.jl ) ).
397+
398+ #### Solver type
399+
400+ The first positional argument selects the KSP algorithm. Any string accepted by
401+ [ ` KSPSetType ` ] ( https://petsc.org/release/manualpages/KSP/KSPSetType/ ) can be passed as a ` Symbol ` .
402+ The most commonly used options are:
403+
404+ | Symbol | Method | Notes |
405+ | :--- | :--- | :--- |
406+ | ` :gmres ` (default) | GMRES | General non-symmetric systems |
407+ | ` :fgmres ` | Flexible GMRES | Allows variable preconditioner |
408+ | ` :lgmres ` | LGMRES | Augmented GMRES, better for restarting |
409+ | ` :cg ` | Conjugate Gradient | SPD systems only |
410+ | ` :fcg ` | Flexible CG | CG with variable preconditioner |
411+ | ` :minres ` | MINRES | Symmetric indefinite systems |
412+ | ` :symmlq ` | SYMMLQ | Symmetric indefinite systems |
413+ | ` :bcgs ` | BiCGStab | Non-symmetric, more stable than BiCG |
414+ | ` :fbcgs ` | Flexible BiCGStab | BiCGStab with variable preconditioner |
415+ | ` :bcgsl ` | BiCGStab(ℓ) | Stabilised BiCGStab variant |
416+ | ` :bicg ` | BiConjugate Gradient | Non-symmetric |
417+ | ` :cgs ` | CGS | Non-symmetric, faster but less stable |
418+ | ` :tfqmr ` | TFQMR | Transpose-free QMR |
419+ | ` :tcqmr ` | TCQMR | Transpose-free QMR variant |
420+ | ` :cr ` | Conjugate Residuals | Symmetric systems |
421+ | ` :gcr ` | GCR | Generalized CR, flexible preconditioner |
422+ | ` :chebyshev ` | Chebyshev iteration | Requires eigenvalue bounds; good for smoothing |
423+ | ` :richardson ` | Richardson iteration | Stationary; mainly used as smoother |
424+ | ` :lsqr ` | LSQR | Least-squares problems |
425+ | ` :cgls ` | CGLS | Least-squares problems |
426+ | ` :preonly ` | Preconditioner only | Use with ` :lu ` for a direct solve |
427+ | ` :none ` | No solver | Identity; useful for debugging |
428+
429+ #### Preconditioners
430+
431+ Preconditioners are selected via the ` pc_type ` keyword. Any string accepted by
432+ [ ` PCSetType ` ] ( https://petsc.org/release/manualpages/PC/PCSetType/ ) can be passed as a ` Symbol ` .
433+ The most commonly used options are:
434+
435+ | Symbol | Preconditioner | Notes |
436+ | :--- | :--- | :--- |
437+ | ` :none ` (default) | No preconditioner | Useful for well-conditioned problems |
438+ | ` :jacobi ` | Diagonal (Jacobi) scaling | Cheap; good for diagonally dominant systems |
439+ | ` :pbjacobi ` | Point Block Jacobi | Fixed-size dense blocks along the diagonal |
440+ | ` :sor ` | SOR / Gauss-Seidel | Successive over-relaxation |
441+ | ` :eisenstat ` | Eisenstat SSOR | Symmetric SOR; cheaper than a full SSOR sweep |
442+ | ` :ilu ` | Incomplete LU | General sparse systems |
443+ | ` :icc ` | Incomplete Cholesky | SPD systems; symmetric analogue of ILU |
444+ | ` :lu ` | Exact LU (direct) | Use with ` :preonly ` for a direct solve |
445+ | ` :cholesky ` | Exact Cholesky (direct) | SPD systems; use with ` :preonly ` |
446+ | ` :bjacobi ` | Block Jacobi | Applies an independent ILU/LU solve per block |
447+ | ` :asm ` | Additive Schwarz | Overlapping domain decomposition |
448+ | ` :gasm ` | Generalized Additive Schwarz | Multi-level ASM variant |
449+ | ` :gamg ` | Algebraic Multigrid (GAMG) | No hierarchy needed; good for PDEs |
450+ | ` :hypre ` | Hypre BoomerAMG | Excellent AMG for large ill-conditioned systems |
451+ | ` :kaczmarz ` | Kaczmarz | Row-projection smoother |
452+
453+ A separate matrix for building the preconditioner can be supplied via ` prec_matrix ` :
454+
455+ ``` julia
456+ PETScAlgorithm (:gmres ; prec_matrix = P)
457+ ```
458+
459+ #### Matrix format recommendations
460+
461+ PETSc operates internally on 0-based CSR arrays. The recommended matrix format is
462+ ** ` SparseMatrixCSR{0} ` ** (from SparseMatricesCSR.jl), which matches PETSc's native layout
463+ exactly:
464+
465+ - ** ` SparseMatrixCSR{0} ` ** — * fastest* : zero-copy path on construction; direct ` copyto! `
466+ on value-only updates.
467+ - ** ` SparseMatrixCSR{1} ` ** — slightly slower than ` {0} ` on construction (index shift on
468+ cold start), same fast value-update path.
469+ - ** ` SparseMatrixCSC ` ** — supported, but requires a CSC→CSR permutation and scatter on
470+ every value update.
471+ - ** Dense ` Matrix ` ** — supported via ` MatSeqDense ` ; works out of the box.
472+
473+ ``` julia
474+ using SparseMatricesCSR, SparseArrays
475+
476+ A_csc = spdiagm (- 1 => - ones (n- 1 ), 0 => 2 ones (n), 1 => - ones (n- 1 ))
477+
478+ # Recommended: one-liner to build SparseMatrixCSR{0} from a CSC matrix.
479+ # Note: this mutates A_csc's internal storage (colptr/rowvals are shifted in-place).
480+ # Use a copy if you need to keep A_csc usable afterwards.
481+ A = SparseMatrixCSR {0} (transpose (sparse (transpose (A_csc))))
482+ ```
483+
484+ #### Basic usage
485+
486+ ``` julia
487+ using LinearSolve, PETSc, MPI, SparseArrays, LinearAlgebra
488+ MPI. Init ()
489+
490+ n = 200
491+ A = sprand (n, n, 0.05 ); A = A + A' + 20 I
492+ b = rand (n)
493+
494+ # Simple one-shot solve with ILU preconditioner
495+ sol = solve (LinearProblem (A, b), PETScAlgorithm (:gmres ; pc_type = :ilu ))
496+ @show norm (A * sol. u - b) / norm (b)
497+ ```
498+
499+ #### Repeated solves (same sparsity pattern, values change)
500+
501+ When the sparsity pattern is fixed across calls,
502+ the KSP is reused and only the matrix values are updated.
503+
504+ ``` julia
505+ using LinearSolve, PETSc, MPI, SparseArrays, SparseMatricesCSR, LinearAlgebra
506+ import SciMLBase
507+ MPI. Init ()
508+
509+ n = 200
510+ A_csc = sprand (n, n, 0.05 ); A_csc = A_csc + A_csc' + 20 I
511+ b = rand (n)
512+
513+ # Convert to SparseMatrixCSR{0} once — getrowptr/getcolval require a CSR matrix
514+ A = SparseMatrixCSR {0} (transpose (sparse (transpose (A_csc))))
515+
516+ cache = SciMLBase. init (LinearProblem (A, b), PETScAlgorithm (:gmres ; pc_type = :ilu ))
517+ solve! (cache)
518+
519+ # Extract the fixed sparsity structure once (0-based row pointers and column indices)
520+ rowptr0 = copy (SparseMatricesCSR. getrowptr (A))
521+ colval0 = copy (SparseMatricesCSR. getcolval (A))
522+
523+ # Iterate: only nzval changes, sparsity pattern is fixed
524+ for t in 1 : 10
525+ new_vals = A. nzval .* (1 + 0.1 * t) # e.g. time-varying coefficients
526+ A_new = SparseMatrixCSR {0} (n, n, rowptr0, colval0, new_vals)
527+ SciMLBase. reinit! (cache; A = A_new, b = rand (n))
528+ solve! (cache)
529+ end
530+ ```
531+
532+ #### Extra PETSc options
533+
534+ Any PETSc Options Database key can be forwarded via ` ksp_options ` :
535+
536+ ``` julia
537+ PETScAlgorithm (:gmres ;
538+ pc_type = :ilu ,
539+ ksp_options = (ksp_monitor = " " , ksp_rtol = 1e-12 , pc_factor_levels = 2 ))
540+ ```
541+
542+ #### Memory management
543+
544+ PETSc objects live in C-managed memory outside Julia's GC. Call
545+ ` cleanup_petsc_cache! ` explicitly when finished to release resources promptly:
546+
547+ ``` julia
548+ PETScExt = Base. get_extension (LinearSolve, :LinearSolvePETScExt )
549+ PETScExt. cleanup_petsc_cache! (sol) # after solve(...)
550+ PETScExt. cleanup_petsc_cache! (cache) # after init/solve! cycle
551+ ```
552+
553+ A GC finalizer is registered as a safety net, but explicit cleanup is strongly preferred.
554+
555+ ``` @docs
556+ PETScAlgorithm
557+ ```
558+
378559### LinearSolvePyAMG.jl
379560
380561!!! note
0 commit comments