Skip to content

Hand BrownFullBasicInit the dense AD backend for a DAEProblem - #4544

Draft
ChrisRackauckas wants to merge 1 commit into
masterfrom
fix-brown-init-dense-ad
Draft

ChrisRackauckas wants to merge 1 commit into
masterfrom
fix-brown-init-dense-ad

Conversation

@ChrisRackauckas

Copy link
Copy Markdown
Member

🚧 UNREVIEWED — awaiting review by @ChrisRackauckas. Filed by an AI agent running as @ChrisRackauckas; Chris has not reviewed this change. Please ignore this draft until he reviews it.
Harness: Claude Code 2.1.270 · Model: claude-fable-5-1
Conversation: local Claude Code session 9b5c3ae5-6a0f-41b8-bd69-03bf3b5e7083 (no shareable URL available)

What changed and why

prepare_alg wraps the solver's autodiff choice in AutoSparse whenever the problem function carries a sparse jac_prototype. The in-place BrownFullBasicInit path for a DAEProblem (lib/OrdinaryDiffEqNonlinearSolve/src/initialize_dae.jl) then built

nlsolve = NewtonRaphson(autodiff = alg_autodiff(integrator.alg))

and NonlinearSolve v4 refuses an AutoSparse autodiff outright, so every fully implicit DAE with a sparse jac_prototype and inconsistent initial conditions errored inside initialization before the first step. The fix unwraps the backend with ADTypes.dense_ad, exactly as DAEResidualJacobianWrapper in utils.jl and _isforwarddiff_alg already do. ADTypes was already a dependency and already imported in the module; no Project.toml change. The out-of-place DAEProblem path goes through default_nlsolve and was not affected.

The regression test is appended to test/sparse_dae_initialization_tests.jl, which runtests.jl already runs in the Core group.

Relation to #4479

This is the next failure after #4479. A DAEFunction with a sparse jac_prototype and no user jac first dies in prepare_user_sparsity (FieldError: type DAEFunction has no field mass_matrix), which #4479 fixes via mass_matrix_or_I. That PR's own test uses consistent initial conditions, so it never reaches the NewtonRaphson construction here. Once both are merged, the jac = nothing variant of the test below also passes through this path; today the test supplies a user jac so it is independent of #4479 and discriminates on origin/master alone. Local !(f isa DAEFunction) guards for the sparsity-seeding sites were dropped from this PR because #4479 already covers all three sites (and seeding the diagonal, as #4479 does, is the better semantics than skipping it).

Evidence

Environment: Julia 1.12.6, aarch64 Linux, a scratch env Pkg.developing lib/OrdinaryDiffEqCore, lib/OrdinaryDiffEqDifferentiation, lib/OrdinaryDiffEqNonlinearSolve, lib/OrdinaryDiffEqSDIRK, lib/OrdinaryDiffEqBDF from this branch; NonlinearSolve v4.29.2.

Before (test added, source change not applied) — julia -e 'using Test; @testset "Sparse DAE Initialization" begin include("lib/OrdinaryDiffEqNonlinearSolve/test/sparse_dae_initialization_tests.jl") end':

DAEProblem BrownFullBasicInit with sparse jac_prototype: Error During Test at .../test/sparse_dae_initialization_tests.jl:312
  Got exception outside of a @test
  Specifying a sparse AD type for Nonlinear Problems was removed in v4. \
             Instead use the `sparsity`, `jac_prototype`, and `colorvec` to specify \
             the right sparsity pattern and coloring algorithm. Ignoring the sparsity \
             detection algorithm and coloring algorithm present in AutoSparse(dense_ad=ADTypes.AutoForwardDiff(tag=ForwardDiff.Tag{DiffEqBase.OrdinaryDiffEqTag, Float64}()), sparsity_detector=ADTypes.KnownJacobianSparsityDetector{SparseMatrixCSC{Float64, Int64}}(sparse([1, 2, 1, 2], [1, 1, 2, 2], [1.0, 1.0, 1.0, 1.0], 2, 2)), coloring_algorithm=SparseMatrixColorings.GreedyColoringAlgorithm{:direct...
  Stacktrace:
    [2] construct_concrete_adtype(::NonlinearFunction{true, ..., OrdinaryDiffEqNonlinearSolve.var"#_initialize_dae!##22#_initialize_dae!##23"{...}}, ad::AutoSparse{...})
    [3] construct_jacobian_cache(...)
    ...
Test Summary:                                             | Pass  Error  Total     Time
Sparse DAE Initialization                                 |   33      1     34  2m24.3s
  Sparse jac_prototype in BrownFullBasicInit              |   33            33  2m07.8s
  DAEProblem BrownFullBasicInit with sparse jac_prototype |           1      1     9.4s
ERROR: Some tests did not pass: 33 passed, 0 failed, 1 errored, 0 broken.

After (same command, fix applied):

Test Summary:             | Pass  Total     Time
Sparse DAE Initialization |   39     39  6m37.6s

What was run

  • The changed test file before/after, as above.
  • Runic 1.10.0 (--check --diff) on both changed files: clean. typos 1.50.1 with the repo's .typos.toml over the diff and both files: clean.
  • The four Core-group testsets that exercise DAE initialization, run from the same env against this branch: Sparse DAE Initialization 39/39, DAE Initialization Tests 19/19, CheckInit Tests 4/4, NonlinearSolveAlg DAEProblem Tests 32/32.
  • Pkg.test() of lib/OrdinaryDiffEqNonlinearSolve with GROUP=Core is running under a 4-hour timeout as this is filed; whatever completes will be posted as a follow-up comment.

Not verified

  • The full OrdinaryDiffEqNonlinearSolve Core group does not fit in a session here: a previous run on this machine passed 13 of its 27 testsets (including "Sparse DAE Initialization" with an earlier version of this test) and hit an 8-hour timeout inside the remaining ones (Mass Matrix Tests alone took 152 min). CI is the authority for the rest of the group.
  • The QA and ModelingToolkit test groups were not run.
  • Nothing GPU- or downstream-related was run.

🤖 Posted by an AI agent — harness: Claude Code 2.1.270 · model: claude-fable-5-1
Conversation: local Claude Code session 9b5c3ae5-6a0f-41b8-bd69-03bf3b5e7083 (no shareable URL available)

`prepare_alg` wraps the solver's autodiff in `AutoSparse` when the
`DAEFunction` carries a sparse `jac_prototype`. The in-place
`BrownFullBasicInit` path for a `DAEProblem` then built
`NewtonRaphson(autodiff = alg_autodiff(integrator.alg))`, and NonlinearSolve
v4 rejects an `AutoSparse` autodiff outright ("Specifying a sparse AD type
for Nonlinear Problems was removed in v4"), so every sparse-Jacobian DAE with
inconsistent initial conditions errored before the first step. Unwrap with
`ADTypes.dense_ad`, as the mass-matrix `ODEProblem` path already does.

Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Agent-Harness: Claude Code 2.1.270
Agent-Model: claude-fable-5-1
Agent-Session: local Claude Code session 9b5c3ae5-6a0f-41b8-bd69-03bf3b5e7083
@ChrisRackauckas ChrisRackauckas added bot-generated Opened by an AI agent needs-chris-review Filed by an agent; not yet reviewed by @ChrisRackauckas labels Sep 12, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bot-generated Opened by an AI agent needs-chris-review Filed by an agent; not yet reviewed by @ChrisRackauckas

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant