Skip to content

Initialize sparse Jacobian caches with stored values#3833

Merged
ChrisRackauckas merged 1 commit into
SciML:masterfrom
ChrisRackauckas-Claude:fix-sparse-jacobian-zero-init
Jul 8, 2026
Merged

Initialize sparse Jacobian caches with stored values#3833
ChrisRackauckas merged 1 commit into
SciML:masterfrom
ChrisRackauckas-Claude:fix-sparse-jacobian-zero-init

Conversation

@ChrisRackauckas-Claude

@ChrisRackauckas-Claude ChrisRackauckas-Claude commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

This PR should be ignored until reviewed by @ChrisRackauckas.

Summary

  • initialize Jacobian and W caches with nonzero stored values before LinearSolve setup
  • preserve sparse prototype structure by setting only existing nzval entries for sparse matrices
  • add a sparse Rosenbrock cache regression test that checks J and W keep their sparse pattern and stored values immediately after init

Fixes #3830.

Local verification

  • ~/.juliaup/bin/julia +1.12 --project=. -e 'using OrdinaryDiffEqRosenbrock, SparseArrays, LinearAlgebra; function f!(du,u,p,t); du .= u; end; jacproto = sparse(1.0I, 4, 4); prob = ODEProblem(ODEFunction(f!; jac_prototype=jacproto), ones(4), (0.0, 1.0)); integ = init(prob, Rodas5P()); @show nnz(integ.cache.J) nnz(integ.cache.W); @show nonzeros(integ.cache.J); @show nonzeros(integ.cache.W); @assert nnz(integ.cache.J) == 4; @assert nnz(integ.cache.W) == 4; @assert all(==(1), nonzeros(integ.cache.J)); @assert all(==(1), nonzeros(integ.cache.W))'
  • ODEDIFFEQ_TEST_GROUP=Sparse ~/.juliaup/bin/julia +1.12 --project=lib/OrdinaryDiffEqDifferentiation -e 'using Pkg; Pkg.test(; test_args=String[])'
  • ~/.juliaup/bin/julia +1.12 -e 'using Runic; exit(Runic.main(ARGS))' -- --check lib/OrdinaryDiffEqDifferentiation/src/derivative_utils.jl lib/OrdinaryDiffEqDifferentiation/test/sparse/nonfulldiagonal_sparse_tests.jl

Note: repository-wide Runic check was also run with --check --diff --verbose .; it fails on unrelated files. A clean-master check reproduced that failure and bisected it to 661f605637 / PR #3777.

Comment on lines +1135 to +1138
J = similar(f.jac_prototype)
W = similar(J)
fill!(J, zero(eltype(J)))
fill!(W, zero(eltype(W)))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Should use zero instead of similar to start it. though actually, if it's zero then dropzeros is wrong... so maybe something like fill with ones? Benchmark and see if zeroing has adverse behavior when mixed with a sprase matrix and the default dropzeros of LinearSolve

@hersle

hersle commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

@ChrisRackauckas If anything, should it not initialize with a nonzero number like ones? Initializing with zeros sounds like it would trigger the dropzeros unconditionally.

Alternatively, would it be better if OrdinaryDiffEq just sets the nonstructural zeros operator assumption to e.g. None instead of Auto when calling LinearSolve? Then the random dropzeros behavior would never be triggered?

@ChrisRackauckas

Copy link
Copy Markdown
Member

There's a lot of cases we found where the dropzeros is actually a major performance improvement, and also a numerical improvement. So we want to have it on and scan for it. But we should try to not do it on many problems, yes. The issue is that it hits init, so we should probably just init to ones.

Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
@ChrisRackauckas-Claude ChrisRackauckas-Claude force-pushed the fix-sparse-jacobian-zero-init branch from d67e68b to 8a4f275 Compare July 8, 2026 09:21
@ChrisRackauckas-Claude ChrisRackauckas-Claude changed the title Zero sparse Jacobian caches before initialization Initialize sparse Jacobian caches with stored values Jul 8, 2026
@ChrisRackauckas ChrisRackauckas marked this pull request as ready for review July 8, 2026 11:20
@ChrisRackauckas ChrisRackauckas merged commit d8cbb9e into SciML:master Jul 8, 2026
141 of 181 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.

Memory use fluctuates wildly with sparse Jacobians due to dropzeros

3 participants