Skip to content

Commit d156439

Browse files
ChrisRackauckas-ClaudeChrisRackauckasclaude
authored
NonlinearSolveBase: add public get_linear_cache accessor (#1065)
Add `get_linear_cache(cache)`, a read-only accessor that returns the `LinearSolve.jl` `LinearCache` the solver holds its Jacobian (and, for a factorization, that factorization) in — the cache-level companion to the existing public `get_linear_solver(alg)`. It lets a caller reuse the solver's current Jacobian for an auxiliary linear solve `J x = b` (e.g. a smoothed error estimate) instead of building and factorizing a second copy. It walks the existing cache chain: `cache.descent_cache.lincache` -> `LinearSolveJLCache.lincache` -> the raw `LinearCache`, and returns `nothing` where there is no single reusable cache (polyalgorithms, and the native `\`/`SMatrix`/`Number`/`Diagonal` paths). Read-only: it does not refactorize; the returned cache is in the state the last `step!`/`solve!` left it, so reuse it through the normal LinearSolve caching interface (set `b`/`u`, `solve!`, no new `A`), which reuses the existing factorization for a direct solver and re-runs the iterative solve for a Krylov cache. Made `@compat public`, documented (docstring + devdocs `@docs` entry). Minor version bump (new public API): NonlinearSolveBase 2.34.1 -> 2.35.0. Claude-Session: https://claude.ai/code/session_01NB3oFTNzGW79UtDt8AyjsM Co-authored-by: Christopher Rackauckas <accounts@chrisrackauckas.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
1 parent 41681c5 commit d156439

4 files changed

Lines changed: 33 additions & 2 deletions

File tree

docs/src/devdocs/linear_solve.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
```@docs
44
NonlinearSolveBase.AbstractLinearSolverCache
55
NonlinearSolveBase.construct_linear_solver
6+
NonlinearSolveBase.get_linear_cache
67
NonlinearSolveBase.needs_square_A
78
NonlinearSolveBase.needs_concrete_A
89
```

lib/NonlinearSolveBase/Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name = "NonlinearSolveBase"
22
uuid = "be0214bd-f91f-a760-ac4e-3421ce2b2da0"
3-
version = "2.34.3"
3+
version = "2.35.0"
44
authors = ["Avik Pal <avikpal@mit.edu> and contributors"]
55

66
[deps]

lib/NonlinearSolveBase/src/NonlinearSolveBase.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ include("forward_diff.jl")
9696

9797
# public for NonlinearSolve.jl and subpackages to use
9898
@compat(public, (InternalAPI, supports_line_search, supports_trust_region, set_du!))
99-
@compat(public, (construct_linear_solver, needs_square_A, needs_concrete_A))
99+
@compat(public, (construct_linear_solver, needs_square_A, needs_concrete_A, get_linear_cache))
100100
@compat(public, (construct_jacobian_cache, reused_jacobian))
101101
@compat(
102102
public,

lib/NonlinearSolveBase/src/linear_solve.jl

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,36 @@ function set_lincache_u!(cache, u::SArray)
161161
return cache.lincache.u = u
162162
end
163163

164+
"""
165+
get_linear_cache(cache) -> Union{Nothing, LinearSolve.LinearCache}
166+
167+
Return the `LinearSolve.jl` `LinearCache` the solver holds its Jacobian (and, for a
168+
factorization, that factorization) in, or `nothing` when there is no single reusable linear
169+
cache.
170+
171+
This is a read-only accessor: it hands back the cache the solver already maintains so a
172+
caller can reuse the current Jacobian for an auxiliary linear solve `J x = b` (for example a
173+
smoothed error estimate) instead of building and factorizing a second copy. It does **not**
174+
refactorize; the returned cache is in exactly the state the last `step!`/`solve!` left it, so
175+
call it after the solve for the current point. Reuse it through the normal LinearSolve caching
176+
interface (set `b`/`u` and `solve!`, passing no new `A`), which reuses the existing
177+
factorization for a direct solver and re-runs the iterative solve for a Krylov cache.
178+
179+
Returns `nothing` for algorithms with no single descent linear solve (e.g. polyalgorithms)
180+
and for the native `\\`/`SMatrix`/`Number`/`Diagonal` paths that hold no reusable
181+
`LinearCache`; callers should fall back accordingly.
182+
"""
183+
get_linear_cache(::Any) = nothing
184+
function get_linear_cache(cache::AbstractNonlinearSolveCache)
185+
return hasproperty(cache, :descent_cache) ? get_linear_cache(cache.descent_cache) :
186+
nothing
187+
end
188+
function get_linear_cache(cache::AbstractDescentCache)
189+
return hasproperty(cache, :lincache) ? get_linear_cache(cache.lincache) : nothing
190+
end
191+
get_linear_cache(cache::LinearSolveJLCache) = cache.lincache
192+
get_linear_cache(::NativeJLLinearSolveCache) = nothing
193+
164194
function wrap_preconditioners(Pl, Pr, u)
165195
Pl = Pl === nothing ? IdentityOperator(length(u)) : Pl
166196
Pr = Pr === nothing ? IdentityOperator(length(u)) : Pr

0 commit comments

Comments
 (0)