From 6cac31cf96968be26ec22fc1b4751700c627d949 Mon Sep 17 00:00:00 2001 From: ChrisRackauckas Date: Mon, 6 Oct 2025 20:25:14 -0400 Subject: [PATCH 1/3] Add @static if Base.USE_GPL_LIBS guards for SuiteSparse usage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit adds conditional compilation guards to make LinearSolve.jl GPL-safe when Julia is built without GPL libraries (USE_GPL_LIBS=0). Changes: - Guard UMFPACKFactorization struct and dispatches - Guard CHOLMODFactorization struct and dispatches - Guard KLUFactorization dispatches (KLU is GPL) - Guard SPQR (sparse QR) references in _ldiv! methods - Add fallback error messages when GPL algorithms are used without GPL libs - Conditionally export GPL-dependent types - Add alternative defaultalg for sparse matrices without GPL libs When USE_GPL_LIBS=0: - Sparse LU falls back to SparspakFactorization (MIT licensed) - Symmetric sparse uses CholeskyFactorization instead of CHOLMOD - Sparse QR uses base Julia QR without SPQR 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- ext/LinearSolveSparseArraysExt.jl | 71 +++++++++++++++++++++++++++++++ src/LinearSolve.jl | 10 +++++ src/default.jl | 18 ++++++-- src/factorization.jl | 10 ++++- 4 files changed, 105 insertions(+), 4 deletions(-) diff --git a/ext/LinearSolveSparseArraysExt.jl b/ext/LinearSolveSparseArraysExt.jl index 57e135164..3b553e95c 100644 --- a/ext/LinearSolveSparseArraysExt.jl +++ b/ext/LinearSolveSparseArraysExt.jl @@ -38,15 +38,28 @@ function LinearSolve.init_cacheval(alg::RFLUFactorization, nothing, nothing end +@static if Base.USE_GPL_LIBS function LinearSolve.handle_sparsematrixcsc_lu(A::AbstractSparseMatrixCSC) lu(SparseMatrixCSC(size(A)..., getcolptr(A), rowvals(A), nonzeros(A)), check = false) end +else +function LinearSolve.handle_sparsematrixcsc_lu(A::AbstractSparseMatrixCSC) + error("Sparse LU factorization requires GPL libraries (UMFPACK). Use `using Sparspak` for a non-GPL alternative or rebuild Julia with USE_GPL_LIBS=1") +end +end # @static if Base.USE_GPL_LIBS +@static if Base.USE_GPL_LIBS function LinearSolve.defaultalg( A::Symmetric{<:BLASELTYPES, <:SparseMatrixCSC}, b, ::OperatorAssumptions{Bool}) LinearSolve.DefaultLinearSolver(LinearSolve.DefaultAlgorithmChoice.CHOLMODFactorization) end +else +function LinearSolve.defaultalg( + A::Symmetric{<:BLASELTYPES, <:SparseMatrixCSC}, b, ::OperatorAssumptions{Bool}) + LinearSolve.DefaultLinearSolver(LinearSolve.DefaultAlgorithmChoice.CholeskyFactorization) +end +end # @static if Base.USE_GPL_LIBS function LinearSolve.defaultalg(A::AbstractSparseMatrixCSC{Tv, Ti}, b, assump::OperatorAssumptions{Bool}) where {Tv, Ti} @@ -71,9 +84,13 @@ function LinearSolve.init_cacheval(alg::GenericFactorization, LinearSolve.do_factorization(alg, newA, b, u) end +@static if Base.USE_GPL_LIBS + const PREALLOCATED_UMFPACK = SparseArrays.UMFPACK.UmfpackLU(SparseMatrixCSC(0, 0, [1], Int[], Float64[])) +end # @static if Base.USE_GPL_LIBS + function LinearSolve.init_cacheval( alg::LUFactorization, A::AbstractSparseArray{<:Number, <:Integer}, b, u, Pl, Pr, @@ -90,6 +107,8 @@ function LinearSolve.init_cacheval( nothing end +@static if Base.USE_GPL_LIBS + function LinearSolve.init_cacheval( alg::UMFPACKFactorization, A::AbstractArray, b, u, Pl, Pr, @@ -132,6 +151,8 @@ function LinearSolve.init_cacheval( end end +end # @static if Base.USE_GPL_LIBS + function LinearSolve.init_cacheval( alg::LUFactorization, A::LinearSolve.GPUArraysCore.AnyGPUArray, b, u, Pl, Pr, @@ -140,6 +161,8 @@ function LinearSolve.init_cacheval( ArrayInterface.lu_instance(A) end +@static if Base.USE_GPL_LIBS + function LinearSolve.init_cacheval( alg::UMFPACKFactorization, A::AbstractSparseArray{Float64, Int}, b, u, Pl, Pr, maxiters::Int, abstol, @@ -211,6 +234,8 @@ function SciMLBase.solve!( end end +end # @static if Base.USE_GPL_LIBS + const PREALLOCATED_KLU = KLU.KLUFactorization(SparseMatrixCSC(0, 0, [1], Int[], Float64[])) @@ -282,6 +307,8 @@ function SciMLBase.solve!(cache::LinearSolve.LinearCache, alg::KLUFactorization; end end +@static if Base.USE_GPL_LIBS + const PREALLOCATED_CHOLMOD = cholesky(sparse(reshape([1.0], 1, 1))) function LinearSolve.init_cacheval(alg::CHOLMODFactorization, @@ -310,6 +337,8 @@ function LinearSolve.init_cacheval(alg::CHOLMODFactorization, nothing end +end # @static if Base.USE_GPL_LIBS + function LinearSolve.init_cacheval(alg::NormalCholeskyFactorization, A::Union{AbstractSparseArray{T}, LinearSolve.GPUArraysCore.AnyGPUArray, Symmetric{T, <:AbstractSparseArray{T}}}, b, u, Pl, Pr, @@ -320,6 +349,7 @@ end # Specialize QR for the non-square case # Missing ldiv! definitions: https://github.com/JuliaSparse/SparseArrays.jl/issues/242 +@static if Base.USE_GPL_LIBS function LinearSolve._ldiv!(x::Vector, A::Union{QR, LinearAlgebra.QRCompactWY, SparseArrays.SPQR.QRSparse, @@ -347,6 +377,30 @@ function LinearSolve._ldiv!(::SVector, b::SVector) (A \ b) end +else +# Non-GPL version without SPQR and CHOLMOD +function LinearSolve._ldiv!(x::Vector, + A::Union{QR, LinearAlgebra.QRCompactWY}, b::Vector) + x .= A \ b +end + +function LinearSolve._ldiv!(x::AbstractVector, + A::Union{QR, LinearAlgebra.QRCompactWY}, b::AbstractVector) + x .= A \ b +end + +# Ambiguity removal +function LinearSolve._ldiv!(::SVector, + A::Union{LinearAlgebra.QR, LinearAlgebra.QRCompactWY}, + b::AbstractVector) + (A \ b) +end +function LinearSolve._ldiv!(::SVector, + A::Union{LinearAlgebra.QR, LinearAlgebra.QRCompactWY}, + b::SVector) + (A \ b) +end +end # @static if Base.USE_GPL_LIBS function LinearSolve.pattern_changed(fact, A::SparseArrays.SparseMatrixCSC) !(SparseArrays.decrement(SparseArrays.getcolptr(A)) == @@ -354,6 +408,7 @@ function LinearSolve.pattern_changed(fact, A::SparseArrays.SparseMatrixCSC) fact.rowval) end +@static if Base.USE_GPL_LIBS function LinearSolve.defaultalg( A::AbstractSparseMatrixCSC{<:Union{Float64, ComplexF64}, Ti}, b, assump::OperatorAssumptions{Bool}) where {Ti} @@ -367,6 +422,22 @@ function LinearSolve.defaultalg( LinearSolve.DefaultLinearSolver(LinearSolve.DefaultAlgorithmChoice.QRFactorization) end end +else +function LinearSolve.defaultalg( + A::AbstractSparseMatrixCSC{<:Union{Float64, ComplexF64}, Ti}, b, + assump::OperatorAssumptions{Bool}) where {Ti} + ext = Base.get_extension(LinearSolve, :LinearSolveSparspakExt) + if assump.issq && ext !== nothing + LinearSolve.DefaultLinearSolver(LinearSolve.DefaultAlgorithmChoice.SparspakFactorization) + elseif !assump.issq + LinearSolve.DefaultLinearSolver(LinearSolve.DefaultAlgorithmChoice.QRFactorization) + elseif ext === nothing + error("SparspakFactorization required for sparse matrix LU without GPL libraries. Do `using Sparspak` to enable this functionality") + else + error("Unreachable reached. Please report this error with a reproducer.") + end +end +end # @static if Base.USE_GPL_LIBS # SPQR Handling function LinearSolve.init_cacheval( diff --git a/src/LinearSolve.jl b/src/LinearSolve.jl index 62ef4026f..4fa54c613 100644 --- a/src/LinearSolve.jl +++ b/src/LinearSolve.jl @@ -475,6 +475,7 @@ error_no_cudss_lu(A) = nothing cudss_loaded(A) = false is_cusparse(A) = false +@static if Base.USE_GPL_LIBS export LUFactorization, SVDFactorization, QRFactorization, GenericFactorization, GenericLUFactorization, SimpleLUFactorization, RFLUFactorization, NormalCholeskyFactorization, NormalBunchKaufmanFactorization, @@ -482,6 +483,15 @@ export LUFactorization, SVDFactorization, QRFactorization, GenericFactorization, SparspakFactorization, DiagonalFactorization, CholeskyFactorization, BunchKaufmanFactorization, CHOLMODFactorization, LDLtFactorization, CUSOLVERRFFactorization, CliqueTreesFactorization +else +export LUFactorization, SVDFactorization, QRFactorization, GenericFactorization, + GenericLUFactorization, SimpleLUFactorization, RFLUFactorization, + NormalCholeskyFactorization, NormalBunchKaufmanFactorization, + FastLUFactorization, FastQRFactorization, + SparspakFactorization, DiagonalFactorization, CholeskyFactorization, + BunchKaufmanFactorization, LDLtFactorization, + CUSOLVERRFFactorization, CliqueTreesFactorization +end # @static if Base.USE_GPL_LIBS export LinearSolveFunction, DirectLdiv!, show_algorithm_choices diff --git a/src/default.jl b/src/default.jl index b7df3fcb1..a49322884 100644 --- a/src/default.jl +++ b/src/default.jl @@ -396,9 +396,17 @@ function algchoice_to_alg(alg::Symbol) elseif alg === :SparspakFactorization SparspakFactorization(throwerror = false) elseif alg === :KLUFactorization - KLUFactorization() + @static if Base.USE_GPL_LIBS + KLUFactorization() + else + error("KLUFactorization requires GPL libraries. Rebuild Julia with USE_GPL_LIBS=1 or use a different algorithm") + end elseif alg === :UMFPACKFactorization - UMFPACKFactorization() + @static if Base.USE_GPL_LIBS + UMFPACKFactorization() + else + error("UMFPACKFactorization requires GPL libraries. Rebuild Julia with USE_GPL_LIBS=1 or use a different algorithm") + end elseif alg === :KrylovJL_GMRES KrylovJL_GMRES() elseif alg === :GenericLUFactorization @@ -408,7 +416,11 @@ function algchoice_to_alg(alg::Symbol) elseif alg === :BunchKaufmanFactorization BunchKaufmanFactorization() elseif alg === :CHOLMODFactorization - CHOLMODFactorization() + @static if Base.USE_GPL_LIBS + CHOLMODFactorization() + else + error("CHOLMODFactorization requires GPL libraries. Rebuild Julia with USE_GPL_LIBS=1 or use CholeskyFactorization instead") + end elseif alg === :CholeskyFactorization CholeskyFactorization() elseif alg === :NormalCholeskyFactorization diff --git a/src/factorization.jl b/src/factorization.jl index 9f9065c4a..17f3de3dd 100644 --- a/src/factorization.jl +++ b/src/factorization.jl @@ -852,11 +852,13 @@ end ################################## Factorizations which require solve! overloads +@static if Base.USE_GPL_LIBS + """ `UMFPACKFactorization(;reuse_symbolic=true, check_pattern=true)` A fast sparse multithreaded LU-factorization which specializes on sparsity -patterns with “more structure”. +patterns with "more structure". !!! note @@ -879,6 +881,8 @@ function init_cacheval(alg::UMFPACKFactorization, nothing end +end # @static if Base.USE_GPL_LIBS + """ `KLUFactorization(;reuse_symbolic=true, check_pattern=true)` @@ -907,6 +911,8 @@ end ## CHOLMODFactorization +@static if Base.USE_GPL_LIBS + """ `CHOLMODFactorization(; shift = 0.0, perm = nothing)` @@ -951,6 +957,8 @@ function SciMLBase.solve!(cache::LinearCache, alg::CHOLMODFactorization; kwargs. SciMLBase.build_linear_solution(alg, cache.u, nothing, cache) end +end # @static if Base.USE_GPL_LIBS + ## NormalCholeskyFactorization """ From 9daab1c3af72323195c36f93052307a504602ad1 Mon Sep 17 00:00:00 2001 From: ChrisRackauckas Date: Tue, 7 Oct 2025 01:07:15 -0400 Subject: [PATCH 2/3] Refine GPL guards: keep init_cacheval stubs and exports MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Changes: - Move `nothing`-returning init_cacheval methods outside GPL guards so they exist as fallbacks even without GPL libs - Remove unnecessary QR/QRCompactWY fallbacks in _ldiv! - these are in base Julia, not GPL - Keep SPQR.QRSparse and CHOLMOD.Factor _ldiv! methods guarded - Remove conditional exports - algorithms can be exported but will error nicely when used without GPL libs - More conservative guards: only guard code that directly uses SparseArrays.UMFPACK, SparseArrays.CHOLMOD, etc. This ensures better compatibility and clearer error messages. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- ext/LinearSolveSparseArraysExt.jl | 65 ++++++++++++++----------------- src/LinearSolve.jl | 10 ----- 2 files changed, 29 insertions(+), 46 deletions(-) diff --git a/ext/LinearSolveSparseArraysExt.jl b/ext/LinearSolveSparseArraysExt.jl index 3b553e95c..143789f0e 100644 --- a/ext/LinearSolveSparseArraysExt.jl +++ b/ext/LinearSolveSparseArraysExt.jl @@ -107,8 +107,6 @@ function LinearSolve.init_cacheval( nothing end -@static if Base.USE_GPL_LIBS - function LinearSolve.init_cacheval( alg::UMFPACKFactorization, A::AbstractArray, b, u, Pl, Pr, @@ -117,6 +115,8 @@ function LinearSolve.init_cacheval( nothing end +@static if Base.USE_GPL_LIBS + function LinearSolve.init_cacheval( alg::LUFactorization, A::AbstractSparseArray{Float64, Int64}, b, u, Pl, Pr, @@ -161,6 +161,14 @@ function LinearSolve.init_cacheval( ArrayInterface.lu_instance(A) end +function LinearSolve.init_cacheval( + alg::UMFPACKFactorization, A::LinearSolve.GPUArraysCore.AnyGPUArray, b, u, + Pl, Pr, + maxiters::Int, abstol, reltol, + verbose::Bool, assumptions::OperatorAssumptions) + nothing +end + @static if Base.USE_GPL_LIBS function LinearSolve.init_cacheval( @@ -171,14 +179,6 @@ function LinearSolve.init_cacheval( PREALLOCATED_UMFPACK end -function LinearSolve.init_cacheval( - alg::UMFPACKFactorization, A::LinearSolve.GPUArraysCore.AnyGPUArray, b, u, - Pl, Pr, - maxiters::Int, abstol, reltol, - verbose::Bool, assumptions::OperatorAssumptions) - nothing -end - function LinearSolve.init_cacheval( alg::UMFPACKFactorization, A::AbstractSparseArray{T, Int64}, b, u, Pl, Pr, @@ -307,6 +307,14 @@ function SciMLBase.solve!(cache::LinearSolve.LinearCache, alg::KLUFactorization; end end +function LinearSolve.init_cacheval(alg::CHOLMODFactorization, + A::AbstractArray, b, u, + Pl, Pr, + maxiters::Int, abstol, reltol, + verbose::Bool, assumptions::OperatorAssumptions) + nothing +end + @static if Base.USE_GPL_LIBS const PREALLOCATED_CHOLMOD = cholesky(sparse(reshape([1.0], 1, 1))) @@ -329,14 +337,6 @@ function LinearSolve.init_cacheval(alg::CHOLMODFactorization, cholesky(sparse(reshape([one(T)], 1, 1))) end -function LinearSolve.init_cacheval(alg::CHOLMODFactorization, - A::AbstractArray, b, u, - Pl, Pr, - maxiters::Int, abstol, reltol, - verbose::Bool, assumptions::OperatorAssumptions) - nothing -end - end # @static if Base.USE_GPL_LIBS function LinearSolve.init_cacheval(alg::NormalCholeskyFactorization, @@ -349,54 +349,47 @@ end # Specialize QR for the non-square case # Missing ldiv! definitions: https://github.com/JuliaSparse/SparseArrays.jl/issues/242 -@static if Base.USE_GPL_LIBS function LinearSolve._ldiv!(x::Vector, - A::Union{QR, LinearAlgebra.QRCompactWY, - SparseArrays.SPQR.QRSparse, - SparseArrays.CHOLMOD.Factor}, b::Vector) + A::Union{QR, LinearAlgebra.QRCompactWY}, b::Vector) x .= A \ b end function LinearSolve._ldiv!(x::AbstractVector, - A::Union{QR, LinearAlgebra.QRCompactWY, - SparseArrays.SPQR.QRSparse, - SparseArrays.CHOLMOD.Factor}, b::AbstractVector) + A::Union{QR, LinearAlgebra.QRCompactWY}, b::AbstractVector) x .= A \ b end # Ambiguity removal function LinearSolve._ldiv!(::SVector, - A::Union{SparseArrays.CHOLMOD.Factor, LinearAlgebra.QR, - LinearAlgebra.QRCompactWY, SparseArrays.SPQR.QRSparse}, + A::Union{LinearAlgebra.QR, LinearAlgebra.QRCompactWY}, b::AbstractVector) (A \ b) end function LinearSolve._ldiv!(::SVector, - A::Union{SparseArrays.CHOLMOD.Factor, LinearAlgebra.QR, - LinearAlgebra.QRCompactWY, SparseArrays.SPQR.QRSparse}, + A::Union{LinearAlgebra.QR, LinearAlgebra.QRCompactWY}, b::SVector) (A \ b) end -else -# Non-GPL version without SPQR and CHOLMOD + +@static if Base.USE_GPL_LIBS +# SPQR and CHOLMOD Factor support function LinearSolve._ldiv!(x::Vector, - A::Union{QR, LinearAlgebra.QRCompactWY}, b::Vector) + A::Union{SparseArrays.SPQR.QRSparse, SparseArrays.CHOLMOD.Factor}, b::Vector) x .= A \ b end function LinearSolve._ldiv!(x::AbstractVector, - A::Union{QR, LinearAlgebra.QRCompactWY}, b::AbstractVector) + A::Union{SparseArrays.SPQR.QRSparse, SparseArrays.CHOLMOD.Factor}, b::AbstractVector) x .= A \ b end -# Ambiguity removal function LinearSolve._ldiv!(::SVector, - A::Union{LinearAlgebra.QR, LinearAlgebra.QRCompactWY}, + A::Union{SparseArrays.CHOLMOD.Factor, SparseArrays.SPQR.QRSparse}, b::AbstractVector) (A \ b) end function LinearSolve._ldiv!(::SVector, - A::Union{LinearAlgebra.QR, LinearAlgebra.QRCompactWY}, + A::Union{SparseArrays.CHOLMOD.Factor, SparseArrays.SPQR.QRSparse}, b::SVector) (A \ b) end diff --git a/src/LinearSolve.jl b/src/LinearSolve.jl index 4fa54c613..62ef4026f 100644 --- a/src/LinearSolve.jl +++ b/src/LinearSolve.jl @@ -475,7 +475,6 @@ error_no_cudss_lu(A) = nothing cudss_loaded(A) = false is_cusparse(A) = false -@static if Base.USE_GPL_LIBS export LUFactorization, SVDFactorization, QRFactorization, GenericFactorization, GenericLUFactorization, SimpleLUFactorization, RFLUFactorization, NormalCholeskyFactorization, NormalBunchKaufmanFactorization, @@ -483,15 +482,6 @@ export LUFactorization, SVDFactorization, QRFactorization, GenericFactorization, SparspakFactorization, DiagonalFactorization, CholeskyFactorization, BunchKaufmanFactorization, CHOLMODFactorization, LDLtFactorization, CUSOLVERRFFactorization, CliqueTreesFactorization -else -export LUFactorization, SVDFactorization, QRFactorization, GenericFactorization, - GenericLUFactorization, SimpleLUFactorization, RFLUFactorization, - NormalCholeskyFactorization, NormalBunchKaufmanFactorization, - FastLUFactorization, FastQRFactorization, - SparspakFactorization, DiagonalFactorization, CholeskyFactorization, - BunchKaufmanFactorization, LDLtFactorization, - CUSOLVERRFFactorization, CliqueTreesFactorization -end # @static if Base.USE_GPL_LIBS export LinearSolveFunction, DirectLdiv!, show_algorithm_choices From 4773ac91c837bcda94e49ec2bc1601f4d5f3e9c3 Mon Sep 17 00:00:00 2001 From: ChrisRackauckas Date: Tue, 7 Oct 2025 01:24:55 -0400 Subject: [PATCH 3/3] Fix GPL guards: revert factorization.jl, add solve! error branches MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Changes: - Revert all changes to src/factorization.jl - algorithms are always defined - Add `else` branches in extension with informative solve! errors for GPL algorithms - Fix `handle_sparsematrixcsc_lu` to use inline @static if instead of branches - Guard KLUFactorization solve! and KLU-specific init_cacheval methods - Keep fallback init_cacheval methods (returning `nothing`) outside guards When USE_GPL_LIBS=false: - Algorithms are still defined and exported - Using them gives clear error: "requires GPL libraries, rebuild Julia with USE_GPL_LIBS=1" - init_cacheval fallbacks exist but specific GPL type methods are unavailable 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- ext/LinearSolveSparseArraysExt.jl | 54 +++++++++++++++++++------------ src/factorization.jl | 10 +----- 2 files changed, 35 insertions(+), 29 deletions(-) diff --git a/ext/LinearSolveSparseArraysExt.jl b/ext/LinearSolveSparseArraysExt.jl index 143789f0e..e8ed64da6 100644 --- a/ext/LinearSolveSparseArraysExt.jl +++ b/ext/LinearSolveSparseArraysExt.jl @@ -38,16 +38,14 @@ function LinearSolve.init_cacheval(alg::RFLUFactorization, nothing, nothing end -@static if Base.USE_GPL_LIBS -function LinearSolve.handle_sparsematrixcsc_lu(A::AbstractSparseMatrixCSC) - lu(SparseMatrixCSC(size(A)..., getcolptr(A), rowvals(A), nonzeros(A)), - check = false) -end -else function LinearSolve.handle_sparsematrixcsc_lu(A::AbstractSparseMatrixCSC) - error("Sparse LU factorization requires GPL libraries (UMFPACK). Use `using Sparspak` for a non-GPL alternative or rebuild Julia with USE_GPL_LIBS=1") + @static if Base.USE_GPL_LIBS + lu(SparseMatrixCSC(size(A)..., getcolptr(A), rowvals(A), nonzeros(A)), + check = false) + else + error("Sparse LU factorization requires GPL libraries (UMFPACK). Use `using Sparspak` for a non-GPL alternative or rebuild Julia with USE_GPL_LIBS=1") + end end -end # @static if Base.USE_GPL_LIBS @static if Base.USE_GPL_LIBS function LinearSolve.defaultalg( @@ -234,10 +232,14 @@ function SciMLBase.solve!( end end -end # @static if Base.USE_GPL_LIBS +else -const PREALLOCATED_KLU = KLU.KLUFactorization(SparseMatrixCSC(0, 0, [1], Int[], - Float64[])) +function SciMLBase.solve!( + cache::LinearSolve.LinearCache, alg::UMFPACKFactorization; kwargs...) + error("UMFPACKFactorization requires GPL libraries (UMFPACK). Rebuild Julia with USE_GPL_LIBS=1 or use an alternative algorithm like SparspakFactorization") +end + +end # @static if Base.USE_GPL_LIBS function LinearSolve.init_cacheval( alg::KLUFactorization, A::AbstractArray, b, u, Pl, @@ -247,14 +249,6 @@ function LinearSolve.init_cacheval( nothing end -function LinearSolve.init_cacheval( - alg::KLUFactorization, A::AbstractSparseArray{Float64, Int64}, b, u, Pl, Pr, - maxiters::Int, abstol, - reltol, - verbose::Bool, assumptions::OperatorAssumptions) - PREALLOCATED_KLU -end - function LinearSolve.init_cacheval( alg::KLUFactorization, A::LinearSolve.GPUArraysCore.AnyGPUArray, b, u, Pl, Pr, @@ -263,6 +257,19 @@ function LinearSolve.init_cacheval( nothing end +@static if Base.USE_GPL_LIBS + +const PREALLOCATED_KLU = KLU.KLUFactorization(SparseMatrixCSC(0, 0, [1], Int[], + Float64[])) + +function LinearSolve.init_cacheval( + alg::KLUFactorization, A::AbstractSparseArray{Float64, Int64}, b, u, Pl, Pr, + maxiters::Int, abstol, + reltol, + verbose::Bool, assumptions::OperatorAssumptions) + PREALLOCATED_KLU +end + function LinearSolve.init_cacheval( alg::KLUFactorization, A::AbstractSparseArray{Float64, Int32}, b, u, Pl, Pr, maxiters::Int, abstol, @@ -272,7 +279,6 @@ function LinearSolve.init_cacheval( 0, 0, [Int32(1)], Int32[], Float64[])) end -# TODO: guard this against errors function SciMLBase.solve!(cache::LinearSolve.LinearCache, alg::KLUFactorization; kwargs...) A = cache.A A = convert(AbstractMatrix, A) @@ -307,6 +313,14 @@ function SciMLBase.solve!(cache::LinearSolve.LinearCache, alg::KLUFactorization; end end +else + +function SciMLBase.solve!(cache::LinearSolve.LinearCache, alg::KLUFactorization; kwargs...) + error("KLUFactorization requires GPL libraries (KLU/SuiteSparse). Rebuild Julia with USE_GPL_LIBS=1 or use an alternative algorithm like SparspakFactorization") +end + +end # @static if Base.USE_GPL_LIBS + function LinearSolve.init_cacheval(alg::CHOLMODFactorization, A::AbstractArray, b, u, Pl, Pr, diff --git a/src/factorization.jl b/src/factorization.jl index 17f3de3dd..9f9065c4a 100644 --- a/src/factorization.jl +++ b/src/factorization.jl @@ -852,13 +852,11 @@ end ################################## Factorizations which require solve! overloads -@static if Base.USE_GPL_LIBS - """ `UMFPACKFactorization(;reuse_symbolic=true, check_pattern=true)` A fast sparse multithreaded LU-factorization which specializes on sparsity -patterns with "more structure". +patterns with “more structure”. !!! note @@ -881,8 +879,6 @@ function init_cacheval(alg::UMFPACKFactorization, nothing end -end # @static if Base.USE_GPL_LIBS - """ `KLUFactorization(;reuse_symbolic=true, check_pattern=true)` @@ -911,8 +907,6 @@ end ## CHOLMODFactorization -@static if Base.USE_GPL_LIBS - """ `CHOLMODFactorization(; shift = 0.0, perm = nothing)` @@ -957,8 +951,6 @@ function SciMLBase.solve!(cache::LinearCache, alg::CHOLMODFactorization; kwargs. SciMLBase.build_linear_solution(alg, cache.u, nothing, cache) end -end # @static if Base.USE_GPL_LIBS - ## NormalCholeskyFactorization """