Fix the default solver's Krylov adjoint branch - #1227
Merged
ChrisRackauckas merged 1 commit intoAug 17, 2026
Conversation
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Checklist
contributor guidelines, in particular the SciML Style Guide and
COLPRAC.
Additional context
Fixes #1217. Three things in the same branch:
cache.val.abstol,cache.val.reltolandcache.val.verbose. All three callers (the ChainRulesCore, Enzyme and Mooncake rules) pass aLinearCache, andhasproperty(cache, :val)isfalsefor that type, so the branch throws wherever it is reached.LinearSolutionwhere the four sibling branches return an array, so the caller'sλ .* tuwould get a solution object.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
AbstractSciMLOperatorwithoutldiv!. I confirmed that selection, but could not stand up a working matrix-free operator here:FunctionOperatorprobes the operator withu === nothingduring 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.