Skip to content

Fix the default solver's Krylov adjoint branch - #1227

Merged
ChrisRackauckas merged 1 commit into
SciML:mainfrom
AJ0070:fix/1217-default-krylov-adjoint
Aug 17, 2026
Merged

Fix the default solver's Krylov adjoint branch#1227
ChrisRackauckas merged 1 commit into
SciML:mainfrom
AJ0070:fix/1217-default-krylov-adjoint

Conversation

@AJ0070

@AJ0070 AJ0070 commented Aug 16, 2026

Copy link
Copy Markdown
Contributor

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

Fixes #1217. Three things in the same branch:

  • cache.val.abstol, cache.val.reltol and cache.val.verbose. All three callers (the ChainRulesCore, Enzyme and Mooncake rules) pass a LinearCache, and hasproperty(cache, :val) is false for that type, so the branch throws wherever it is reached.
  • It returned the LinearSolution where the four sibling branches return an array, so the caller's λ .* tu would get a solution object.
  • It used transpose(cache.A) where the rest of the function takes the adjoint, which differ for a complex eltype.

There is no test. Reaching this branch needs the default solver to pick a Krylov method, which happens for a square AbstractSciMLOperator without ldiv!. I confirmed that selection, but could not stand up a working matrix-free operator here: FunctionOperator probes the operator with u === nothing during construction in the version I have, on every keyword combination I tried.

It is worth sending anyway, because the current code cannot run at all rather than merely running badly, and the change only makes the branch agree with its siblings. It also stops being unreachable-in-practice if #1222 lands, since solve!(cache; adjoint = true) routes through here for a default-solver cache. Happy to hold this until someone can add a test with a real operator.

Core passes.

The Krylov branch of `defaultalg_adjoint_eval` reads `cache.val.abstol`, but all
three callers pass a `LinearCache`, which has no `val` field, so the branch throws
wherever it is reached. It also returns the solution object where the sibling
branches return an array, and transposes where they take the adjoint, which
differ for a complex eltype.
@ChrisRackauckas
ChrisRackauckas merged commit 499e543 into SciML:main Aug 17, 2026
60 of 62 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.

Krylov branch of defaultalg_adjoint_eval references a field LinearCache does not have

2 participants