Skip to content

Commit 4c9fe5a

Browse files
Merge pull request #73 from SciML/prec
Even further simplify preconditioner interface
2 parents ed61d9d + 5220f98 commit 4c9fe5a

File tree

5 files changed

+37
-96
lines changed

5 files changed

+37
-96
lines changed

docs/src/basics/FAQ.md

+6-4
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@ IterativeSolvers.jl computes the norm after the application of the left precondt
99
hack the system via the following formulation:
1010

1111
```julia
12-
Pl = LinearSolve.InvDiagonalPreconditioner(weights)
13-
Pr = LinearSolve.DiagonalPreconditioner(weights)
12+
using LinearSolve, LinearAlgebra
13+
Pl = LinearSolve.InvPreconditioner(Diagonal(weights))
14+
Pr = Diagonal(weights)
1415

1516
A = rand(n,n)
1617
b = rand(n)
@@ -24,8 +25,9 @@ can use `ComposePreconditioner` to apply the preconditioner after the applicatio
2425
of the weights like as follows:
2526

2627
```julia
27-
Pl = ComposePreconitioner(LinearSolve.InvDiagonalPreconditioner(weights),realprec)
28-
Pr = LinearSolve.DiagonalPreconditioner(weights)
28+
using LinearSolve, LinearAlgebra
29+
Pl = ComposePreconitioner(LinearSolve.InvPreconditioner(Diagonal(weights),realprec))
30+
Pr = Diagonal(weights)
2931

3032
A = rand(n,n)
3133
b = rand(n)

docs/src/basics/Preconditioners.md

+21-15
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,9 @@ multiplies by the same values. This is commonly used in the case where if, inste
4242
of random, `s` is an approximation to the eigenvalues of a system.
4343

4444
```julia
45+
using LinearSolve, LinearAlgebra
4546
s = rand(n)
46-
Pl = LinearSolve.DiagonalPreconditioner(s)
47+
Pl = Diagonal(s)
4748

4849
A = rand(n,n)
4950
b = rand(n)
@@ -52,22 +53,27 @@ prob = LinearProblem(A,b)
5253
sol = solve(prob,IterativeSolvers_GMRES(),Pl=Pl)
5354
```
5455

55-
## Pre-Defined Preconditioners
56-
57-
To simplify the usage of preconditioners, LinearSolve.jl comes with many standard
58-
preconditioners written to match the required interface.
59-
60-
- `DiagonalPreconditioner(s::Union{Number,AbstractVector})`: the diagonal
61-
preconditioner, defined as a diagonal matrix `Diagonal(s)`.
62-
- `InvDiagonalPreconditioner(s::Union{Number,AbstractVector})`: the diagonal
63-
preconditioner, defined as a diagonal matrix `Diagonal(1./s)`.
64-
- `ComposePreconditioner(prec1,prec2)`: composes the preconditioners to apply
65-
`prec1` before `prec2`.
66-
6756
## Preconditioner Interface
6857

6958
To define a new preconditioner you define a Julia type which satisfies the
7059
following interface:
7160

72-
- `Base.eltype(::Preconditioner)`
73-
- `LinearAlgebra.ldiv!(::AbstractVector,::Preconditioner,::AbstractVector)`
61+
- `Base.eltype(::Preconditioner)` (Required only for Krylov.jl)
62+
- `LinearAlgebra.ldiv!(::AbstractVector,::Preconditioner,::AbstractVector)` and
63+
`LinearAlgebra.ldiv!(::Preconditioner,::AbstractVector)`
64+
65+
## Curated List of Pre-Defined Preconditioners
66+
67+
The following preconditioners are tested to match the interface of LinearSolve.jl.
68+
69+
- `ComposePreconditioner(prec1,prec2)`: composes the preconditioners to apply
70+
`prec1` before `prec2`.
71+
- `InvPreconditioner(prec)`: inverts `mul!` and `ldiv!` in a preconditioner
72+
definition as a lazy inverse.
73+
- `LinearAlgera.Diagonal(s::Union{Number,AbstractVector})`: the lazy Diagonal
74+
matrix type of Base.LinearAlgebra. Used for efficient construction of a
75+
diagonal preconditioner.
76+
- Other `Base.LinearAlgera` types: all define the full Preconditioner interface.
77+
- [IncompleteLU.ilu](https://github.com/haampie/IncompleteLU.jl): an implementation
78+
of the incomplete LU-factorization preconditioner. This requires `A` as a
79+
`SparseMatrixCSC`.

docs/src/tutorials/caching_interface.md

+2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ means of solving and resolving linear systems. To do this with LinearSolve.jl,
2121
you simply `init` a cache, `solve`, replace `b`, and solve again. This looks like:
2222

2323
```julia
24+
using LinearSolve
25+
2426
n = 4
2527
A = rand(n,n)
2628
b1 = rand(n); b2 = rand(n)

src/preconditioners.jl

+3-53
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,4 @@
1-
## Diagonal Preconditioners
2-
3-
struct DiagonalPreconditioner{D}
4-
diag::D
5-
end
6-
struct InvDiagonalPreconditioner{D}
7-
diag::D
8-
end
9-
10-
Base.eltype(A::Union{DiagonalPreconditioner,InvDiagonalPreconditioner}) = eltype(A.diag)
11-
12-
function LinearAlgebra.ldiv!(A::DiagonalPreconditioner, x)
13-
x .= x ./ A.diag
14-
end
15-
16-
function LinearAlgebra.ldiv!(y, A::DiagonalPreconditioner, x)
17-
y .= x ./ A.diag
18-
end
19-
20-
#=
21-
function LinearAlgebra.ldiv!(y::Matrix, A::DiagonalPreconditioner, b::Matrix)
22-
@inbounds @simd for j ∈ 1:size(y, 2)
23-
for i ∈ 1:length(A.diag)
24-
y[i,j] = b[i,j] / A.diag[i]
25-
end
26-
end
27-
return y
28-
end
29-
=#
30-
31-
function LinearAlgebra.ldiv!(A::InvDiagonalPreconditioner, x)
32-
x .= x .* A.diag
33-
end
34-
35-
function LinearAlgebra.ldiv!(y, A::InvDiagonalPreconditioner, x)
36-
y .= x .* A.diag
37-
end
38-
39-
#=
40-
function LinearAlgebra.ldiv!(y::Matrix, A::InvDiagonalPreconditioner, b::Matrix)
41-
@inbounds @simd for j ∈ 1:size(y, 2)
42-
for i ∈ 1:length(A.diag)
43-
y[i,j] = b[i,j] * A.diag[i]
44-
end
45-
end
46-
return y
47-
end
48-
=#
49-
50-
LinearAlgebra.mul!(y, A::DiagonalPreconditioner, x) = LinearAlgebra.ldiv!(y, InvDiagonalPreconditioner(A.diag), x)
51-
LinearAlgebra.mul!(y, A::InvDiagonalPreconditioner, x) = LinearAlgebra.ldiv!(y, DiagonalPreconditioner(A.diag), x)
52-
53-
## Compose Preconditioner
1+
# Tooling Preconditioners
542

553
struct ComposePreconditioner{Ti,To}
564
inner::Ti
@@ -78,4 +26,6 @@ struct InvPreconditioner{T}
7826
end
7927

8028
Base.eltype(A::InvPreconditioner) = Base.eltype(A.P)
29+
LinearAlgebra.ldiv!(A::InvPreconditioner, x) = mul!(x, A.P, x)
30+
LinearAlgebra.ldiv!(y, A::InvPreconditioner, x) = mul!(y, A.P, x)
8131
LinearAlgebra.mul!(y, A::InvPreconditioner, x) = ldiv!(y, A.P, x)

test/runtests.jl

+5-24
Original file line numberDiff line numberDiff line change
@@ -201,27 +201,9 @@ end
201201
end
202202

203203
@testset "Preconditioners" begin
204-
@testset "Scalar Diagonal Preconditioner" begin
205-
s = rand()
206-
207-
x = rand(n,n)
208-
y = rand(n,n)
209-
210-
Pl, Pr = LinearSolve.DiagonalPreconditioner(s),LinearSolve.InvDiagonalPreconditioner(s)
211-
212-
mul!(y, Pl, x); @test y s * x
213-
mul!(y, Pr, x); @test y s \ x
214-
215-
y .= x; ldiv!(Pl, x); @test x s \ y
216-
y .= x; ldiv!(Pr, x); @test x s * y
217-
218-
ldiv!(y, Pl, x); @test y s \ x
219-
ldiv!(y, Pr, x); @test y s * x
220-
end
221-
222204
@testset "Vector Diagonal Preconditioner" begin
223205
s = rand(n)
224-
Pl, Pr = LinearSolve.DiagonalPreconditioner(s),LinearSolve.InvDiagonalPreconditioner(s)
206+
Pl, Pr = Diagonal(s),LinearSolve.InvPreconditioner(Diagonal(s))
225207

226208
x = rand(n,n)
227209
y = rand(n,n)
@@ -237,21 +219,20 @@ end
237219
end
238220

239221
@testset "ComposePreconditioenr" begin
240-
s1 = rand()
241-
s2 = rand()
222+
s1 = rand(n)
223+
s2 = rand(n)
242224

243225
x = rand(n,n)
244226
y = rand(n,n)
245227

246-
P1 = LinearSolve.DiagonalPreconditioner(s1)
247-
P2 = LinearSolve.DiagonalPreconditioner(s2)
228+
P1 = Diagonal(s1)
229+
P2 = Diagonal(s2)
248230

249231
P = LinearSolve.ComposePreconditioner(P1,P2)
250232

251233
# ComposePreconditioner
252234
ldiv!(y, P, x); @test y ldiv!(P2, ldiv!(P1, x))
253235
y .= x; ldiv!(P, x); @test x ldiv!(P2, ldiv!(P1, y))
254-
255236
end
256237
end
257238

0 commit comments

Comments
 (0)