Skip to content

Handle matrix-free instability diagnostics - #4310

Merged
ChrisRackauckas merged 1 commit into
SciML:masterfrom
ChrisRackauckas-Claude:fix/matrix-free-diagnostic-jacobian
Aug 20, 2026
Merged

Handle matrix-free instability diagnostics#4310
ChrisRackauckas merged 1 commit into
SciML:masterfrom
ChrisRackauckas-Claude:fix/matrix-free-diagnostic-jacobian

Conversation

@ChrisRackauckas-Claude

Copy link
Copy Markdown
Member

Please ignore this PR until reviewed by @ChrisRackauckas.

What changed and why

Return nothing from the fresh-Jacobian diagnostic hook when an in-place solver cache is matrix-free. The current code calls zero(cache.J) and receives a NullOperator for a Krylov JVPCache, then passes that operator to the matrix-only calc_J! path and errors while trying to report numerical instability. The Core diagnostic caller already treats nothing as “stored Jacobian unavailable.”

The regression is covered with an in-place Rosenbrock23/Krylov cache and verifies both the return value and unchanged solver work counters. OrdinaryDiffEqDifferentiation is bumped to 3.9.1.

An independent runtime bisect identified 0ed2615 as the first bad commit. Its parent returns a dense matrix for the same reproducer; the bad commit errors in jacobian!(::NullOperator, ...).

Failing before / passing after

With the regression test present and the source fix reverted:

Matrix-free diagnostic Jacobian: Error During Test
Expression: get_fresh_jacobian(integrator, integrator.cache) === nothing
MethodError: no method matching jacobian!(::SciMLOperators.NullOperator, ...)

No Jac Tests | Pass 8 Error 1 Total 9

With this patch, the same test and full Core group pass:

No Jac Tests | Pass 9 Total 9
Krylov nf accounting | Pass 21 Total 21
Krylov linear tolerance | Pass 7 Total 7
Testing OrdinaryDiffEqDifferentiation tests passed

A direct after-fix reproduction returned nothing with counters unchanged at (nf, njacs) = (3, 0).

Local verification

  • GROUP=Core julia +1.12 --project=lib/OrdinaryDiffEqDifferentiation --startup-file=no -e 'using Pkg; Pkg.test()': full package group passed. This includes DAE jacobian2W 4/4, scalar-operator mass matrix 9/9, No Jac 9/9, stale W 12/12, nf accounting 21/21, and Krylov tolerance 7/7.
  • GROUP=QA julia +1.12 --project=lib/OrdinaryDiffEqDifferentiation --startup-file=no -e 'using Pkg; Pkg.test()': JET 1/1 and Aqua 19/19; package tests passed.
  • Runic, typos, and git diff --check: passed.

The CUDA job was not run locally because this machine has no GPU. The failure was reproduced through the same matrix-free cache path on CPU; broad CI should verify the GPU path. Docs and prerelease-Julia groups were not run because this adds no public API or documentation.

Failing CI job: https://github.com/SciML/OrdinaryDiffEq.jl/actions/runs/32353535950/job/96379682877

@ChrisRackauckas-Claude

Copy link
Copy Markdown
Member Author

CI triage: all completed failures are the two independently reproduced master Downstream issues. ProbNumDiffEq’s Julia 1.10 resolver failure is addressed by #4320. PositiveIntegrators’ LinearSolve 5 compatibility failure is addressed upstream by NumericalMathematics/PositiveIntegrators.jl#216. No completed red check currently points to this PR’s changed behavior.

Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
@ChrisRackauckas-Claude
ChrisRackauckas-Claude force-pushed the fix/matrix-free-diagnostic-jacobian branch from 72c953e to bfe1e1a Compare August 20, 2026 15:57
@ChrisRackauckas
ChrisRackauckas marked this pull request as ready for review August 20, 2026 15:59
@ChrisRackauckas
ChrisRackauckas merged commit f77ad2b into SciML:master Aug 20, 2026
18 of 22 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