Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name = "LinearSolve"
uuid = "7ed4a6bd-45f5-4d41-b270-4a48e9bafcae"
version = "4.3.0"
version = "5.0.0"
authors = ["SciML"]

[deps]
Expand Down
2 changes: 1 addition & 1 deletion docs/Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ SciMLOperators = "c0aeaf25-5076-4817-a8d5-81caf7dfa961"

[compat]
Documenter = "1"
LinearSolve = "4"
LinearSolve = "5"
LinearSolveAutotune = "1.1"
LinearSolvePyAMG = "1"
SciMLOperators = "1"
Expand Down
4 changes: 2 additions & 2 deletions docs/src/basics/Preconditioners.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,11 +89,11 @@ A = n * LA.I - rand(n, n)
b = rand(n)

prob = LS.LinearProblem(A, b)
sol = LS.solve(prob, LS.KrylovJL_GMRES(precs = WeightedDiagonalPreconBuilder(w = 0.9)))
cache = LS.init(prob, LS.KrylovJL_GMRES(precs = WeightedDiagonalPreconBuilder(w = 0.9)))
sol = LS.solve!(cache)
sol.u

B = A .+ 0.1
cache = sol.cache
LS.reinit!(cache, A = B, reuse_precs = true)
sol = LS.solve!(cache, LS.KrylovJL_GMRES(precs = WeightedDiagonalPreconBuilder(w = 0.9)))
sol.u
Expand Down
10 changes: 6 additions & 4 deletions docs/src/solvers/solvers.md
Original file line number Diff line number Diff line change
Expand Up @@ -275,10 +275,10 @@ ParUFactorization
!!! warning

Call `cleanup_mumps_cache!` explicitly through the extension before
`MPI.Finalize()`:
`MPI.Finalize()`, using the `LinearCache` from an `init`/`solve!` cycle:
```julia
MUMPSExt = Base.get_extension(LinearSolve, :LinearSolveMUMPSExt)
MUMPSExt.cleanup_mumps_cache!(sol)
MUMPSExt.cleanup_mumps_cache!(cache)
```

```@docs
Expand Down Expand Up @@ -768,8 +768,10 @@ PETSc objects live in C-managed memory outside Julia's GC. Call

```julia
PETScExt = Base.get_extension(LinearSolve, :LinearSolvePETScExt)
PETScExt.cleanup_petsc_cache!(sol) # after solve(...)
PETScExt.cleanup_petsc_cache!(cache) # after init/solve! cycle

cache = SciMLBase.init(prob, PETScAlgorithm(:gmres))
sol = solve!(cache)
PETScExt.cleanup_petsc_cache!(cache) # after the init/solve! cycle
```

A GC finalizer is registered as a safety net, but explicit cleanup is strongly preferred.
Expand Down
7 changes: 5 additions & 2 deletions docs/src/tutorials/caching_interface.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,11 @@ sol3.u
```

The factorization occurs on the first solve, and it stores the factorization in
the cache. You can retrieve this cache via `sol.cache`, which is the same object
as the `init`, but updated to know not to re-solve the factorization.
the cache: the `linsolve` object returned by `init` is updated in-place to know
not to re-solve the factorization. Keep the object from `init` around to reuse
it; the solution returned by `solve!` is a lightweight value type that only
carries the answer (`sol.u`, `sol.resid`, `sol.retcode`, ...), so its `cache`
field is `nothing` (as of LinearSolve.jl 5.0).

The advantage of course with import LinearSolve.jl in this form is that it is
efficient while being agnostic to the linear solver. One can easily swap in
Expand Down
4 changes: 2 additions & 2 deletions ext/LinearSolveAMDGPUExt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ function SciMLBase.solve!(

y = Array(b_gpu)
cache.u .= y
return SciMLBase.build_linear_solution(alg, y, nothing, cache)
return SciMLBase.build_linear_solution(alg, y, nothing, nothing)
end

function LinearSolve.init_cacheval(
Expand Down Expand Up @@ -59,7 +59,7 @@ function SciMLBase.solve!(

y = Array(b_gpu[1:n])
cache.u .= y
return SciMLBase.build_linear_solution(alg, y, nothing, cache)
return SciMLBase.build_linear_solution(alg, y, nothing, nothing)
end

function LinearSolve.init_cacheval(
Expand Down
2 changes: 1 addition & 1 deletion ext/LinearSolveAlgebraicMultigridExt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ function SciMLBase.solve!(cache::LinearCache, alg::AlgebraicMultigridJL; kwargs.
copyto!(cache.u, x)

return SciMLBase.build_linear_solution(
alg, cache.u, nothing, cache; retcode = ReturnCode.Success
alg, cache.u, nothing, nothing; retcode = ReturnCode.Success
)
end

Expand Down
4 changes: 2 additions & 2 deletions ext/LinearSolveBLISExt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,7 @@ function SciMLBase.solve!(
if !LinearAlgebra.issuccess(fact[1])
@SciMLMessage("Solver failed", cache.verbose, :solver_failure)
return SciMLBase.build_linear_solution(
alg, cache.u, nothing, cache; retcode = ReturnCode.Failure
alg, cache.u, nothing, nothing; retcode = ReturnCode.Failure
)
end
cache.isfresh = false
Expand All @@ -342,7 +342,7 @@ function SciMLBase.solve!(
getrs!('N', A.factors, A.ipiv, cache.u; info)
end

return SciMLBase.build_linear_solution(alg, cache.u, nothing, cache; retcode = ReturnCode.Success)
return SciMLBase.build_linear_solution(alg, cache.u, nothing, nothing; retcode = ReturnCode.Success)
end

end
8 changes: 4 additions & 4 deletions ext/LinearSolveCUDAExt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ function SciMLBase.solve!(
fact = LinearSolve.@get_cacheval(cache, :CudaOffloadLUFactorization)
y = Array(ldiv!(CUDACore.CuArray(cache.u), fact, CUDACore.CuArray(cache.b)))
cache.u .= y
return SciMLBase.build_linear_solution(alg, y, nothing, cache)
return SciMLBase.build_linear_solution(alg, y, nothing, nothing)
end

function LinearSolve.init_cacheval(
Expand Down Expand Up @@ -105,7 +105,7 @@ function SciMLBase.solve!(
end
y = Array(ldiv!(CUDACore.CuArray(cache.u), cache.cacheval, CUDACore.CuArray(cache.b)))
cache.u .= y
return SciMLBase.build_linear_solution(alg, y, nothing, cache)
return SciMLBase.build_linear_solution(alg, y, nothing, nothing)
end

function LinearSolve.init_cacheval(
Expand Down Expand Up @@ -133,7 +133,7 @@ function SciMLBase.solve!(
end
y = Array(ldiv!(CUDACore.CuArray(cache.u), cache.cacheval, CUDACore.CuArray(cache.b)))
cache.u .= y
return SciMLBase.build_linear_solution(alg, y, nothing, cache)
return SciMLBase.build_linear_solution(alg, y, nothing, nothing)
end

function LinearSolve.init_cacheval(
Expand Down Expand Up @@ -206,7 +206,7 @@ function SciMLBase.solve!(
# Convert back to original precision
y = Array(u_gpu_f32)
cache.u .= Torig.(y)
return SciMLBase.build_linear_solution(alg, cache.u, nothing, cache)
return SciMLBase.build_linear_solution(alg, cache.u, nothing, nothing)
end

function LinearSolve.init_cacheval(
Expand Down
2 changes: 1 addition & 1 deletion ext/LinearSolveCUSOLVERRFExt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ function SciMLBase.solve!(cache::LinearSolve.LinearCache, alg::LinearSolve.CUSOL
copyto!(cache.u, u_gpu)
end

return SciMLBase.build_linear_solution(alg, cache.u, nothing, cache; retcode = ReturnCode.Success)
return SciMLBase.build_linear_solution(alg, cache.u, nothing, nothing; retcode = ReturnCode.Success)
end

# Helper function for pattern checking
Expand Down
2 changes: 1 addition & 1 deletion ext/LinearSolveCliqueTreesExt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ function SciMLBase.solve!(cache::LinearSolve.LinearCache, alg::CliqueTreesFactor
end

ldiv!(u, cache.cacheval, b)
return SciMLBase.build_linear_solution(alg, u, nothing, cache)
return SciMLBase.build_linear_solution(alg, u, nothing, nothing)
end

LinearSolve.PrecompileTools.@compile_workload begin
Expand Down
2 changes: 1 addition & 1 deletion ext/LinearSolveElementalExt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ function SciMLBase.solve!(cache::LinearCache, alg::ElementalJL; kwargs...)
x_jl = convert(Base.Matrix{T}, fact \ _b_to_elemental(cache.b, T))
copyto!(cache.u, vec(x_jl))

return SciMLBase.build_linear_solution(alg, cache.u, nothing, cache; retcode = ReturnCode.Success)
return SciMLBase.build_linear_solution(alg, cache.u, nothing, nothing; retcode = ReturnCode.Success)
end

end # module
4 changes: 2 additions & 2 deletions ext/LinearSolveFastLapackInterfaceExt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ function SciMLBase.solve!(
cache.isfresh = false
end
y = ldiv!(cache.u, cache.cacheval.factors, cache.b)
return SciMLBase.build_linear_solution(alg, y, nothing, cache)
return SciMLBase.build_linear_solution(alg, y, nothing, nothing)
end

function LinearSolve.init_cacheval(
Expand Down Expand Up @@ -106,7 +106,7 @@ function SciMLBase.solve!(
cache.isfresh = false
end
y = ldiv!(cache.u, cache.cacheval.factors, cache.b)
return SciMLBase.build_linear_solution(alg, y, nothing, cache)
return SciMLBase.build_linear_solution(alg, y, nothing, nothing)
end

end
4 changes: 2 additions & 2 deletions ext/LinearSolveForwardDiffExt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -471,7 +471,7 @@ function SciMLBase.solve!(
end

return SciMLBase.build_linear_solution(
getfield(cache, :linear_cache).alg, getfield(cache, :dual_u), primal_sol.resid, cache;
getfield(cache, :linear_cache).alg, getfield(cache, :dual_u), primal_sol.resid, nothing;
primal_sol.retcode, primal_sol.iters, primal_sol.stats
)
end
Expand Down Expand Up @@ -522,7 +522,7 @@ function _solve_direct_dual!(
end

return SciMLBase.build_linear_solution(
linear_cache.alg, getfield(cache, :dual_u), dual_sol.resid, cache;
linear_cache.alg, getfield(cache, :dual_u), dual_sol.resid, nothing;
dual_sol.retcode, dual_sol.iters, dual_sol.stats
)
end
Expand Down
2 changes: 1 addition & 1 deletion ext/LinearSolveGinkgoExt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ function SciMLBase.solve!(cache::LinearCache, alg::GinkgoJL; kwargs...)
end

resid = norm(cache.A * cache.u - cache.b)
return SciMLBase.build_linear_solution(alg, cache.u, resid, cache)
return SciMLBase.build_linear_solution(alg, cache.u, resid, nothing)
end

LinearSolve.update_tolerances_internal!(cache, alg::GinkgoJL, atol, rtol) = nothing
Expand Down
8 changes: 4 additions & 4 deletions ext/LinearSolveHSLExt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ function SciMLBase.solve!(
HSL.ma57_solve!(hcache.ma57, cache.u, hcache.work)

return SciMLBase.build_linear_solution(
alg, cache.u, nothing, cache; retcode = ReturnCode.Success
alg, cache.u, nothing, nothing; retcode = ReturnCode.Success
)
catch err
if err isa HSL.Ma57Exception
Expand All @@ -131,7 +131,7 @@ function SciMLBase.solve!(
)
cache.isfresh = true
return SciMLBase.build_linear_solution(
alg, cache.u, nothing, cache; retcode = ReturnCode.Failure
alg, cache.u, nothing, nothing; retcode = ReturnCode.Failure
)
end
rethrow(err)
Expand Down Expand Up @@ -169,7 +169,7 @@ function SciMLBase.solve!(
HSL.ma97_solve!(hcache.ma97, cache.u)

return SciMLBase.build_linear_solution(
alg, cache.u, nothing, cache; retcode = ReturnCode.Success
alg, cache.u, nothing, nothing; retcode = ReturnCode.Success
)
catch err
if err isa HSL.Ma97Exception
Expand All @@ -180,7 +180,7 @@ function SciMLBase.solve!(
)
cache.isfresh = true
return SciMLBase.build_linear_solution(
alg, cache.u, nothing, cache; retcode = ReturnCode.Failure
alg, cache.u, nothing, nothing; retcode = ReturnCode.Failure
)
end
rethrow(err)
Expand Down
6 changes: 3 additions & 3 deletions ext/LinearSolveHYPREExt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,7 @@ function SciMLBase.solve!(cache::LinearCache, alg::HYPREAlgorithm, args...; kwar
copy!(cache.u, hcache.u)
end

# Note: Inlining SciMLBase.build_linear_solution(alg, u, resid, cache; retcode, iters)
# Note: Inlining SciMLBase.build_linear_solution(alg, u, resid, nothing; retcode, iters)
# since some of the functions used in there does not play well with HYPREVector.

T = cache.u isa HYPREVector ? HYPRE_Complex : eltype(cache.u) # eltype(u)
Expand All @@ -354,10 +354,10 @@ function SciMLBase.solve!(cache::LinearCache, alg::HYPREAlgorithm, args...; kwar

ret = SciMLBase.LinearSolution{
T, N, typeof(cache.u), typeof(resid), typeof(alg),
typeof(cache), typeof(stats),
Nothing, typeof(stats),
}(
cache.u, resid, alg, retc,
iters, cache, stats
iters, nothing, stats
)

return ret
Expand Down
2 changes: 1 addition & 1 deletion ext/LinearSolveIterativeSolversExt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ function SciMLBase.solve!(cache::LinearCache, alg::IterativeSolversJL; kwargs...
resid = resid.current
end

return SciMLBase.build_linear_solution(alg, cache.u, resid, cache; iters = i)
return SciMLBase.build_linear_solution(alg, cache.u, resid, nothing; iters = i)
end

purge_history!(iter, x, b) = nothing
Expand Down
2 changes: 1 addition & 1 deletion ext/LinearSolveKrylovKitExt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ function SciMLBase.solve!(cache::LinearCache, alg::KrylovKitJL; kwargs...)

iters = info.numiter
return SciMLBase.build_linear_solution(
alg, cache.u, resid, cache; retcode = retcode,
alg, cache.u, resid, nothing; retcode = retcode,
iters = iters
)
end
Expand Down
7 changes: 2 additions & 5 deletions ext/LinearSolveMUMPSExt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,9 @@ end

cleanup_mumps_cache!(cache::MUMPSCache) = _finalize_mumps_cache!(cache)
cleanup_mumps_cache!(cache::LinearSolve.LinearCache) = cleanup_mumps_cache!(cache.cacheval)
cleanup_mumps_cache!(sol::LinearSolution) = cleanup_mumps_cache!(sol.cache.cacheval)

"""
cleanup_mumps_cache!(cache::MUMPSCache)
cleanup_mumps_cache!(cache::LinearCache)
cleanup_mumps_cache!(sol::LinearSolution)

Destroy the live `MUMPS.Mumps` object owned by a LinearSolve cache and reset the
cache to an empty state. Safe to call multiple times.
Expand Down Expand Up @@ -107,7 +104,7 @@ function _solve_failed_solution(
)
@SciMLMessage(msg, cache.verbose, :solver_failure)
return SciMLBase.build_linear_solution(
alg, cache.u, nothing, cache; retcode = ReturnCode.Failure
alg, cache.u, nothing, nothing; retcode = ReturnCode.Failure
)
end

Expand Down Expand Up @@ -172,7 +169,7 @@ function SciMLBase.solve!(
end

return SciMLBase.build_linear_solution(
alg, cache.u, nothing, cache; retcode = ReturnCode.Success
alg, cache.u, nothing, nothing; retcode = ReturnCode.Success
)
end

Expand Down
4 changes: 2 additions & 2 deletions ext/LinearSolveMetalExt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ function SciMLBase.solve!(
cache.isfresh = false
end
y = ldiv!(cache.u, @get_cacheval(cache, :MetalLUFactorization), cache.b)
return SciMLBase.build_linear_solution(alg, y, nothing, cache)
return SciMLBase.build_linear_solution(alg, y, nothing, nothing)
end

# Mixed precision Metal LU implementation
Expand Down Expand Up @@ -96,7 +96,7 @@ function SciMLBase.solve!(

# Convert back to original precision
cache.u .= Torig.(u_f32)
return SciMLBase.build_linear_solution(alg, cache.u, nothing, cache)
return SciMLBase.build_linear_solution(alg, cache.u, nothing, nothing)
end

end
4 changes: 1 addition & 3 deletions ext/LinearSolvePETScExt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,6 @@ end
"""
cleanup_petsc_cache!(pcache::PETScCache)
cleanup_petsc_cache!(cache::LinearCache)
cleanup_petsc_cache!(sol::LinearSolution)

Destroy all PETSc objects owned by `pcache` and reset its state to empty.
Safe to call multiple times — subsequent calls after the first are no-ops.
Expand Down Expand Up @@ -144,7 +143,6 @@ function cleanup_petsc_cache!(pcache::PETScCache)
end

cleanup_petsc_cache!(cache::LinearCache) = cleanup_petsc_cache!(cache.cacheval)
cleanup_petsc_cache!(sol::LinearSolution) = cleanup_petsc_cache!(sol.cache.cacheval)

# ── Cache initialisation ──────────────────────────────────────────────────────

Expand Down Expand Up @@ -836,7 +834,7 @@ function SciMLBase.solve!(cache::LinearCache, alg::PETScAlgorithm; kwargs...)
failed !== nothing && return failed
end

return build_linear_solution(alg, cache.u, resid, cache; retcode, iters)
return build_linear_solution(alg, cache.u, resid, nothing; retcode, iters)
end

end
2 changes: 1 addition & 1 deletion ext/LinearSolvePETScMPIExt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,7 @@ function PETScExt.postsolve_solution_check(cache, alg, pcache, A::PSparseMatrix,

if res_norm > tol
return SciMLBase.build_linear_solution(
alg, u, nothing, cache; retcode = ReturnCode.APosterioriSafetyFailure
alg, u, nothing, nothing; retcode = ReturnCode.APosterioriSafetyFailure
)
end
return nothing
Expand Down
Loading
Loading