Skip to content

Wrap Jacobian with both dense and sparse FunctionWrapper signatures#1288

Merged
ChrisRackauckas merged 1 commit intoSciML:masterfrom
ChrisRackauckas-Claude:fix-sparse-jac-functionwrapper
Feb 23, 2026
Merged

Wrap Jacobian with both dense and sparse FunctionWrapper signatures#1288
ChrisRackauckas merged 1 commit intoSciML:masterfrom
ChrisRackauckas-Claude:fix-sparse-jac-functionwrapper

Conversation

@ChrisRackauckas-Claude
Copy link
Contributor

Summary

  • When an ODEFunction has a sparse sparsity pattern (f.sparsity isa AbstractMatrix with non-dense type) but no jac_prototype, the solver's build_J_W may create a SparseMatrixCSC J from the sparsity pattern (when using AutoSparse).
  • Previously, promote_f only wrapped the Jacobian with a dense Matrix{Float64} signature in the FunctionWrappersWrapper, causing "No matching function wrapper was found!" at solve time.
  • This PR detects non-dense sparsity patterns and creates a FunctionWrappersWrapper with both dense and sparse matrix signatures, so the Jacobian call works regardless of which matrix type the solver allocates.

Context

This fixes a failure in ModelingToolkit.jl tests when using AutoSpecialize (the new default) with jac=true, sparsity=true and an implicit solver like Rodas5(). See: SciML/ModelingToolkit.jl#4335

The root cause is that OrdinaryDiffEqDifferentiation's build_J_W creates a sparse J from the sparsity pattern when alg_autodiff(alg) isa AutoSparse, even when jac_prototype is nothing. The FunctionWrapper was only registered for the dense (Matrix{Float64}, Vector{Float64}, Vector{Float64}, Float64) signature, so the call with SparseMatrixCSC failed.

Test plan

  • Reproduced the "No matching function wrapper" error with jac=true, sparsity=true, Rodas5() on AutoSpecialize ODEProblem
  • Verified the fix resolves the error
  • Verified @inferred remake and @inferred solve still pass
  • Verified prob1 (no jac) and prob2 (jac, no sparsity) still work

🤖 Generated with Claude Code

When an ODEFunction has a sparse sparsity pattern but no jac_prototype,
the solver's build_J_W may create a SparseMatrixCSC J from the sparsity
pattern (when using AutoSparse). The previous code only wrapped the
Jacobian with a dense Matrix{Float64} signature, causing "No matching
function wrapper was found!" at solve time.

Now detects non-dense sparsity patterns and creates a FunctionWrappersWrapper
with both dense and sparse matrix signatures so the Jacobian call works
regardless of which matrix type the solver allocates.

All type computations use Base.promote_op to avoid allocating prototype
matrices just for their types.

Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
@ChrisRackauckas-Claude ChrisRackauckas-Claude force-pushed the fix-sparse-jac-functionwrapper branch from 11589a2 to dea4704 Compare February 23, 2026 13:48
@ChrisRackauckas ChrisRackauckas merged commit c8409a9 into SciML:master Feb 23, 2026
37 of 46 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