Skip to content

CSR matrix and docs for PETSc extension#949

Merged
ChrisRackauckas merged 4 commits into
SciML:mainfrom
Iddingsite:CSRMatrixmode
Apr 10, 2026
Merged

CSR matrix and docs for PETSc extension#949
ChrisRackauckas merged 4 commits into
SciML:mainfrom
Iddingsite:CSRMatrixmode

Conversation

@Iddingsite
Copy link
Copy Markdown
Contributor

@Iddingsite Iddingsite commented Apr 10, 2026

Following #894, I have added support for CSR matrices using SparseMatricesCSR.jl as PETSc uses this format by default. I took some inspirations from GridapPETSc.jl as SparseMatricesCSR.jl was also designed for this package I believe.

Checklist

  • Appropriate tests were added
  • Any code changes were done in a way that does not break public API
  • All documentation related to code changes were updated
  • The new code follows the
    contributor guidelines, in particular the SciML Style Guide and
    COLPRAC.
  • Any new documentation only uses public API

Additional context

It brings about a 10% speedup in general for large problem (tested from 1000 to 10000 unknowns) compared to CSC format because there is no need to convert from one format to the other.

So things like that work:

using LinearSolve, SparseArrays, SparseMatricesCSR, PETSc, MPI

MPI.Initialized() || MPI.Init()

# ── Build a simple sparse matrix (CSC first, then convert) ───────────────────
n = 100
A_csc = spdiagm(-1 => -ones(n-1), 0 => 2ones(n), 1 => -ones(n-1))  # 1D Laplacian
b = rand(n)

# ── Option 1: SparseMatrixCSR{1} (1-based, default) ──────────────────────────
# Simple but incurs an index-shift on every cold start.
A_csr1 = SparseMatrixCSR(A_csc)

prob = LinearProblem(A_csr1, b)
sol  = solve(prob, PETScAlgorithm(:gmres; pc_type = :ilu))
@show norm(A_csc * sol.u - b)

# ── Option 2: SparseMatrixCSR{0} (0-based) — zero-copy fast path ─────────────
# No index shift needed on cold start; canonical form matches PETSc directly.
csr1    = SparseMatrixCSR(A_csc)
rowptr0 = getrowptr(csr1) .- one(eltype(getrowptr(csr1)))
colval0 = getcolval(csr1) .- one(eltype(getcolval(csr1)))
A_csr0  = SparseMatrixCSR{0}(n, n, rowptr0, colval0, copy(csr1.nzval))

prob = LinearProblem(A_csr0, b)
sol  = solve(prob, PETScAlgorithm(:gmres; pc_type = :ilu))
@show norm(A_csc * sol.u - b)

# ── Option 3: cache + reinit (Case-3 hot path) ───────────────────────────────
# Same sparsity pattern, values change — reuses the KSP.
import SciMLBase

cache = SciMLBase.init(LinearProblem(A_csr0, b), PETScAlgorithm(:gmres))
solve!(cache)

for scale in [1.0, 1.5, 2.0]
    A_new = SparseMatrixCSR{0}(n, n, rowptr0, colval0, copy(csr1.nzval) .* scale)
    SciMLBase.reinit!(cache; A = A_new, b = rand(n))
    solve!(cache)
    @show norm(A_new * cache.u - cache.b)
end

The PR also simplifies some things for the CSC case and fix PETSc version to 0.4.8 because of an important bug fix in PETSc.jl.

Done with Claude's help.

@Iddingsite
Copy link
Copy Markdown
Contributor Author

I have added a doc entry because I think it is mostly usable now. What's missing is MPI support. I may give it a try at some point.

@Iddingsite Iddingsite changed the title CSR matrix for PETSc extension CSR matrix and docs for PETSc extension Apr 10, 2026
@Iddingsite
Copy link
Copy Markdown
Contributor Author

I believe Test failures are unrelated to this PR

@Iddingsite Iddingsite mentioned this pull request Apr 10, 2026
5 tasks
@ChrisRackauckas ChrisRackauckas merged commit 44bcee0 into SciML:main Apr 10, 2026
190 of 196 checks passed
@Iddingsite Iddingsite deleted the CSRMatrixmode branch April 10, 2026 20:08
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