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
28 changes: 24 additions & 4 deletions ext/LinearSolveSparseArraysExt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,11 @@ end
)
end # @static if Base.USE_GPL_LIBS

# UMFPACK's `UmfpackLU` only exists for `Float64`/`ComplexF64` (SuiteSparse's
# `UMFVTypes`). The other BLAS eltypes are not a subset of it, so cachevals for
# UMFPACK-backed algorithms must be bounded by this, not by `BLASELTYPES`.
const UMFPACKELTYPES = Union{Float64, ComplexF64}

function LinearSolve.init_cacheval(
alg::LUFactorization, A::AbstractSparseArray{<:Number, <:Integer}, b, u,
Pl, Pr,
Expand Down Expand Up @@ -169,7 +174,7 @@ end
Pl, Pr,
maxiters::Int, abstol, reltol,
verbose::Union{LinearVerbosity, Bool}, assumptions::OperatorAssumptions
) where {T <: BLASELTYPES}
) where {T <: UMFPACKELTYPES}
if LinearSolve.is_cusparse(A)
LinearSolve.cudss_loaded(A) ? ArrayInterface.lu_instance(A) : nothing
else
Expand All @@ -185,7 +190,7 @@ end
Pl, Pr,
maxiters::Int, abstol, reltol,
verbose::Union{LinearVerbosity, Bool}, assumptions::OperatorAssumptions
) where {T <: BLASELTYPES}
) where {T <: UMFPACKELTYPES}
if LinearSolve.is_cusparse(A)
LinearSolve.cudss_loaded(A) ? ArrayInterface.lu_instance(A) : nothing
else
Expand All @@ -198,6 +203,21 @@ end
end
end # @static if Base.USE_GPL_LIBS

# Single-precision sparse: no UMFPACK cacheval exists, but a cuDSS-backed
# CuSparse matrix still needs its `lu_instance`.
function LinearSolve.init_cacheval(
alg::LUFactorization, A::AbstractSparseArray{T, <:Union{Int32, Int64}}, b, u,
Pl, Pr,
maxiters::Int, abstol, reltol,
verbose::Union{LinearVerbosity, Bool}, assumptions::OperatorAssumptions
) where {T <: BLASELTYPES}
if LinearSolve.is_cusparse(A)
return LinearSolve.cudss_loaded(A) ? ArrayInterface.lu_instance(A) : nothing
else
return nothing
end
end

function LinearSolve.init_cacheval(
alg::LUFactorization, A::LinearSolve.GPUArraysCore.AnyGPUArray, b, u,
Pl, Pr,
Expand Down Expand Up @@ -231,7 +251,7 @@ end
Pl, Pr,
maxiters::Int, abstol, reltol,
verbose::Union{LinearVerbosity, Bool}, assumptions::OperatorAssumptions
) where {T <: BLASELTYPES}
) where {T <: UMFPACKELTYPES}
SparseArrays.UMFPACK.UmfpackLU(
SparseMatrixCSC{T, Int64}(
zero(Int64), zero(Int64), [Int64(1)], Int64[], T[]
Expand All @@ -244,7 +264,7 @@ end
Pl, Pr,
maxiters::Int, abstol, reltol,
verbose::Union{LinearVerbosity, Bool}, assumptions::OperatorAssumptions
) where {T <: BLASELTYPES}
) where {T <: UMFPACKELTYPES}
SparseArrays.UMFPACK.UmfpackLU(
SparseMatrixCSC{T, Int32}(
zero(Int32), zero(Int32), [Int32(1)], Int32[], T[]
Expand Down
19 changes: 19 additions & 0 deletions test/Core/default_algs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,25 @@ let As_bf = sparse(BigFloat.([1 2 3; 2 4 6; 1 1 1])), bs_bf = BigFloat.([1, 2, 3
@test all(isfinite, sol.u)
end

# Single-precision sparse has no UMFPACK/KLU (SuiteSparse) support, so the
# default polyalgorithm — which eagerly builds a cacheval for *every* slot, not
# just the selected one — must not try to allocate an UMFPACK cacheval for it.
@testset "Sparse $T with $Ti indices" for T in (Float32, ComplexF32),
Ti in (Int64, Int32)

n = 20
A32 = sparse(Ti.(1:n), Ti.(1:n), fill(T(n), n), n, n) +
sparse(Ti.(1:(n - 1)), Ti.(2:n), fill(T(1), n - 1), n, n)
b32 = ones(T, n)
@test A32 isa SparseMatrixCSC{T, Ti}
@test LinearSolve.defaultalg(A32, b32, LinearSolve.OperatorAssumptions(true)).alg ===
LinearSolve.DefaultAlgorithmChoice.KLUFactorization
sol32 = solve(LinearProblem(A32, b32))
@test SciMLBase.successful_retcode(sol32.retcode)
@test eltype(sol32.u) === T
@test norm(A32 * sol32.u - b32) / norm(b32) < 1.0f-5
end

@test LinearSolve.defaultalg(sprand(10^4, 10^4, 1.0e-5) + I, zeros(1000)).alg ===
LinearSolve.DefaultAlgorithmChoice.KLUFactorization
prob = LinearProblem(sprand(1000, 1000, 0.5), zeros(1000))
Expand Down
Loading