@@ -55,17 +55,29 @@ function SciMLBase.solve!(cache::LinearCache, alg::LinearSolveFunction,
5555end
5656
5757"""
58- DirectLdiv! <: AbstractSolveFunction
58+ DirectLdiv!{cache}() <: AbstractSolveFunction
5959
60- A simple linear solver that directly applies the left-division operator (`\\ `)
60+ A simple linear solver that directly applies the left-division operator (`\\ `)
6161to solve the linear system. This algorithm calls `ldiv!(u, A, b)` which computes
6262`u = A \\ b` in-place.
6363
64+ ## Type Parameter
65+
66+ - `cache::Bool`: Whether to cache a copy of the matrix for use with ldiv!.
67+ When `true`, a copy of the matrix is stored during `init` and used during `solve!`,
68+ preventing mutation of `cache.A`. Default is `true` for matrix types where `ldiv!`
69+ mutates the input (e.g., `Tridiagonal`, `SymTridiagonal`).
70+
6471## Usage
6572
6673```julia
74+ # Default: automatically caches for matrix types that need it
6775alg = DirectLdiv!()
6876sol = solve(prob, alg)
77+
78+ # Explicit caching control
79+ alg = DirectLdiv!(Val(true)) # Always cache
80+ alg = DirectLdiv!(Val(false)) # Never cache (may mutate A)
6981```
7082
7183## Notes
@@ -75,13 +87,27 @@ sol = solve(prob, alg)
7587- Performance depends on the specific matrix type and its `ldiv!` implementation
7688- No preconditioners or advanced numerical techniques are applied
7789- Best used for small to medium problems or when `A` has special structure
90+ - For `Tridiagonal` and `SymTridiagonal`, `ldiv!` performs in-place LU factorization
91+ which mutates the matrix. Use `cache=true` (default) to preserve `cache.A`.
7892"""
79- struct DirectLdiv! <: AbstractSolveFunction end
93+ struct DirectLdiv!{cache} <: AbstractSolveFunction
94+ function DirectLdiv! (:: Val{cache} = Val (true )) where {cache}
95+ new {cache} ()
96+ end
97+ end
8098
81- function SciMLBase. solve! (cache:: LinearCache , alg:: DirectLdiv! , args... ; kwargs... )
99+ # Default solve! for non-caching or matrix types that don't need caching
100+ function SciMLBase. solve! (cache:: LinearCache , alg:: DirectLdiv!{false} , args... ; kwargs... )
82101 (; A, b, u) = cache
83102 ldiv! (u, A, b)
103+ return SciMLBase. build_linear_solution (alg, u, nothing , cache)
104+ end
84105
106+ # For caching DirectLdiv! with general matrices, just use regular ldiv!
107+ # (caching is only needed for specific matrix types like Tridiagonal)
108+ function SciMLBase. solve! (cache:: LinearCache , alg:: DirectLdiv!{true} , args... ; kwargs... )
109+ (; A, b, u) = cache
110+ ldiv! (u, A, b)
85111 return SciMLBase. build_linear_solution (alg, u, nothing , cache)
86112end
87113
90116# We cache a copy of the Tridiagonal matrix and use that for the factorization.
91117# See https://github.com/SciML/LinearSolve.jl/issues/825
92118
93- function init_cacheval (alg:: DirectLdiv! , A:: Tridiagonal , b, u, Pl, Pr, maxiters:: Int ,
119+ function init_cacheval (alg:: DirectLdiv!{true} , A:: Tridiagonal , b, u, Pl, Pr, maxiters:: Int ,
94120 abstol, reltol, verbose:: Union{LinearVerbosity, Bool} ,
95121 assumptions:: OperatorAssumptions )
96122 # Allocate a copy of the Tridiagonal matrix to use as workspace for ldiv!
97123 return copy (A)
98124end
99125
100- function init_cacheval (alg:: DirectLdiv! , A:: SymTridiagonal , b, u, Pl, Pr, maxiters :: Int ,
101- abstol, reltol, verbose:: Union{LinearVerbosity, Bool} ,
126+ function init_cacheval (alg:: DirectLdiv!{true} , A:: SymTridiagonal , b, u, Pl, Pr,
127+ maxiters :: Int , abstol, reltol, verbose:: Union{LinearVerbosity, Bool} ,
102128 assumptions:: OperatorAssumptions )
103129 # SymTridiagonal also gets mutated by ldiv!, cache a copy
104130 return copy (A)
105131end
106132
107- function SciMLBase. solve! (cache:: LinearCache{<:Tridiagonal} , alg:: DirectLdiv! ,
133+ function SciMLBase. solve! (cache:: LinearCache{<:Tridiagonal} , alg:: DirectLdiv!{true} ,
108134 args... ; kwargs... )
109135 (; A, b, u, cacheval) = cache
110136 # Copy current A values into the cached workspace (non-allocating)
@@ -116,7 +142,7 @@ function SciMLBase.solve!(cache::LinearCache{<:Tridiagonal}, alg::DirectLdiv!,
116142 return SciMLBase. build_linear_solution (alg, u, nothing , cache)
117143end
118144
119- function SciMLBase. solve! (cache:: LinearCache{<:SymTridiagonal} , alg:: DirectLdiv! ,
145+ function SciMLBase. solve! (cache:: LinearCache{<:SymTridiagonal} , alg:: DirectLdiv!{true} ,
120146 args... ; kwargs... )
121147 (; A, b, u, cacheval) = cache
122148 # Copy current A values into the cached workspace (non-allocating)
0 commit comments