Skip to content

Commit 46e41d5

Browse files
Merge pull request #188 from SciML/nonsquare_operators
Default non-square operators to LSMR
2 parents 79eea00 + ef07182 commit 46e41d5

File tree

6 files changed

+40
-2
lines changed

6 files changed

+40
-2
lines changed

src/LinearSolve.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,6 @@ export LinearSolveFunction
5858
export KrylovJL, KrylovJL_CG, KrylovJL_GMRES, KrylovJL_BICGSTAB, KrylovJL_MINRES,
5959
IterativeSolversJL, IterativeSolversJL_CG, IterativeSolversJL_GMRES,
6060
IterativeSolversJL_BICGSTAB, IterativeSolversJL_MINRES,
61-
KrylovKitJL, KrylovKitJL_CG, KrylovKitJL_GMRES
61+
KrylovKitJL, KrylovKitJL_CG, KrylovKitJL_GMRES, KrylovJL_LSMR
6262

6363
end

src/default.jl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,11 @@ function defaultalg(A::SciMLBase.AbstractDiffEqOperator, b,
6969
KrylovJL_GMRES()
7070
end
7171

72+
function defaultalg(A::SciMLBase.AbstractDiffEqOperator, b,
73+
assumptions::OperatorAssumptions{false})
74+
KrylovJL_LSMR()
75+
end
76+
7277
# Handle ambiguity
7378
function defaultalg(A::GPUArraysCore.AbstractGPUArray, b::GPUArraysCore.AbstractGPUArray,
7479
::OperatorAssumptions{true})

src/factorization.jl

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,14 @@ function _ldiv!(x::Vector, A::Factorization, b::Vector)
55
ldiv!(A, x)
66
end
77

8+
# Specialize QR for the non-square case
9+
# Missing ldiv! definitions: https://github.com/JuliaSparse/SparseArrays.jl/issues/242
10+
function _ldiv!(x::Vector,
11+
A::Union{SparseArrays.QR, LinearAlgebra.QRCompactWY,
12+
SuiteSparse.SPQR.QRSparse}, b::Vector)
13+
x .= A \ b
14+
end
15+
816
function SciMLBase.solve(cache::LinearCache, alg::AbstractFactorization; kwargs...)
917
if cache.isfresh
1018
fact = do_factorization(alg, cache.A, cache.b, cache.u)
@@ -90,7 +98,7 @@ end
9098

9199
function do_factorization(alg::QRFactorization, A, b, u)
92100
A = convert(AbstractMatrix, A)
93-
if alg.inplace
101+
if alg.inplace && (!(A isa SparseMatrixCSC) || VERSION >= v"1.8-")
94102
fact = qr!(A, alg.pivot)
95103
else
96104
fact = qr(A) # CUDA.jl does not allow other args!

src/iterative_wrappers.jl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ function KrylovJL_MINRES(args...; kwargs...)
2424
KrylovJL(args...; KrylovAlg = Krylov.minres!, kwargs...)
2525
end
2626

27+
function KrylovJL_LSMR(args...; kwargs...)
28+
KrylovJL(args...; KrylovAlg = Krylov.lsmr!, kwargs...)
29+
end
30+
2731
function get_KrylovJL_solver(KrylovAlg)
2832
KS = if (KrylovAlg === Krylov.lsmr!)
2933
Krylov.LsmrSolver

test/nonsquare.jl

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
using LinearSolve, Test
2+
using SparseArrays, LinearAlgebra
3+
4+
m, n = 13, 3
5+
6+
A = rand(m, n);
7+
b = rand(m);
8+
prob = LinearProblem(A, b)
9+
res = A \ b
10+
@test solve(prob).u res
11+
@test solve(prob, QRFactorization()) res
12+
@test solve(prob, KrylovJL_LSMR()) res
13+
14+
A = sprand(m, n, 0.5);
15+
b = rand(m);
16+
prob = LinearProblem(A, b)
17+
res = A \ b
18+
@test solve(prob).u res
19+
@test solve(prob, QRFactorization()) res
20+
@test solve(prob, KrylovJL_LSMR()) res

test/runtests.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ end
2121
if GROUP == "All" || GROUP == "Core"
2222
@time @safetestset "Basic Tests" begin include("basictests.jl") end
2323
@time @safetestset "Zero Initialization Tests" begin include("zeroinittests.jl") end
24+
@time @safetestset "Non-Square Tests" begin include("nonsquare.jl") end
2425
end
2526

2627
if GROUP == "LinearSolveCUDA"

0 commit comments

Comments
 (0)