Skip to content

Commit bee8bb9

Browse files
authored
Block preconditioning
* Generic block preconditioner * Removed element types from factorization wrapper * Code reorganization
1 parent e2d82c9 commit bee8bb9

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+851
-569
lines changed

Project.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "ExtendableSparse"
22
uuid = "95c220a8-a1cf-11e9-0c77-dbfce5f500b3"
33
authors = ["Juergen Fuhrmann <[email protected]>"]
4-
version = "1.0.1"
4+
version = "1.1.0"
55

66
[deps]
77
DocStringExtensions = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae"

docs/src/changes.md

+6
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
11
# Changes
2+
## v1.1, May 3, 2023
3+
- AbstractFactorization and subtypes are now without element and index type information.
4+
They wrap more concretely typed info. This shall allow to construct a preconditioner
5+
without knowing matrix and element type.
6+
- First steps to block preconditioning
7+
- src directory restructured
28

39
## v1.0.1, Jan 22, 2023
410
- support of AbstractSparseMatrixCSC interface

docs/src/iter.md

+11-3
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ This functionality probably will be reduced in favor of LinearSolve.jl.
55
## Factorizations
66

77
In this package, preconditioners and LU factorizations are both seen
8-
as complete or approximate _factorizations_. Correspondingly we provide a common API for
9-
their creation.
8+
as complete or approximate _factorizations_. Correspondingly we provide a common API for them.
9+
1010

1111
```@autodocs
1212
Modules = [ExtendableSparse]
@@ -122,7 +122,15 @@ nm1, nm2
122122

123123
### API
124124

125+
#### Recommended
126+
```@autodocs
127+
Modules = [ExtendableSparse]
128+
Pages = ["iluzero.jl","ilut.jl","amg.jl","blockpreconditioner.jl"]
129+
```
130+
131+
132+
#### Experimental
125133
```@autodocs
126134
Modules = [ExtendableSparse]
127-
Pages = ["jacobi.jl","parallel_jacobi.jl","iluzero.jl","ilu0.jl","ilut.jl","amg.jl"]
135+
Pages = ["jacobi.jl","parallel_jacobi.jl","ilu0.jl",]
128136
```

docs/src/linearsolve.md

+16-1
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,26 @@ Also, the iterative method interface works with ExtendableSparse.
3838
```@example
3939
using ExtendableSparse # hide
4040
using LinearSolve # hide
41+
using SparseArrays # hide
4142
using ILUZero # hide
4243
A = fdrand(10, 10, 10; matrixtype = ExtendableSparseMatrix)
4344
x = ones(1000)
4445
b = A * x
4546
y = LinearSolve.solve(LinearProblem(A, b), KrylovJL_CG();
46-
Pl = ILUZero.ilu0(sparse(A))).u
47+
Pl = ILUZero.ilu0(SparseMatrixCSC(A))).u
48+
sum(y)
49+
```
50+
51+
However, ExtendableSparse provides a number of wrappers around preconditioners
52+
from various Julia packages.
53+
```@example
54+
using ExtendableSparse # hide
55+
using LinearSolve # hide
56+
using ILUZero # hide
57+
A = fdrand(10, 10, 10; matrixtype = ExtendableSparseMatrix)
58+
x = ones(1000)
59+
b = A * x
60+
y = LinearSolve.solve(LinearProblem(A, b), KrylovJL_CG();
61+
Pl = ILUZeroPreconditioner(A)).u
4762
sum(y)
4863
```

src/ExtendableSparse.jl

+17-14
Original file line numberDiff line numberDiff line change
@@ -18,38 +18,41 @@ using DocStringExtensions
1818

1919
import SparseArrays: AbstractSparseMatrixCSC, rowvals, getcolptr, nonzeros
2020

21-
include("sparsematrixcsc.jl")
22-
include("sparsematrixlnk.jl")
23-
include("extendable.jl")
21+
include("matrix/sparsematrixcsc.jl")
22+
include("matrix/sparsematrixlnk.jl")
23+
include("matrix/extendable.jl")
2424

2525
export SparseMatrixLNK,
2626
ExtendableSparseMatrix, flush!, nnz, updateindex!, rawupdateindex!, colptrs, sparse
2727

28-
include("factorizations.jl")
28+
include("factorizations/factorizations.jl")
2929

3030
export JacobiPreconditioner,
31-
ILU0Preconditioner,
32-
ILUZeroPreconditioner,
33-
ParallelJacobiPreconditioner,
34-
ParallelILU0Preconditioner,
35-
reorderlinsys
31+
ILU0Preconditioner,
32+
ILUZeroPreconditioner,
33+
ParallelJacobiPreconditioner,
34+
ParallelILU0Preconditioner,
35+
BlockPreconditioner,allow_views,
36+
reorderlinsys
37+
3638
export AbstractFactorization, LUFactorization, CholeskyFactorization
3739
export issolver
3840
export factorize!, update!
3941

40-
include("simple_iteration.jl")
42+
include("factorizations/simple_iteration.jl")
4143
export simple, simple!
4244

43-
include("sprand.jl")
45+
include("matrix/sprand.jl")
4446
export sprand!, sprand_sdd!, fdrand, fdrand!, fdrand_coo, solverbenchmark
4547

4648
function __init__()
47-
@require Pardiso="46dd5b70-b6fb-5a00-ae2d-e8fea33afaf2" include("pardiso_lu.jl")
48-
@require IncompleteLU="40713840-3770-5561-ab4c-a76e7d0d7895" include("ilut.jl")
49-
@require AlgebraicMultigrid="2169fc97-5a83-5252-b627-83903c6c433c" include("amg.jl")
49+
@require Pardiso="46dd5b70-b6fb-5a00-ae2d-e8fea33afaf2" include("factorizations/pardiso_lu.jl")
50+
@require IncompleteLU="40713840-3770-5561-ab4c-a76e7d0d7895" include("factorizations/ilut.jl")
51+
@require AlgebraicMultigrid="2169fc97-5a83-5252-b627-83903c6c433c" include("factorizations/amg.jl")
5052
end
5153

5254
export ILUTPreconditioner, AMGPreconditioner
5355
export PardisoLU, MKLPardisoLU, SparspakLU
5456

57+
5558
end # module

src/amg.jl

-33
This file was deleted.

src/factorizations/amg.jl

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
mutable struct AMGPreconditioner <: AbstractPreconditioner
2+
A::ExtendableSparseMatrix
3+
factorization::AlgebraicMultigrid.Preconditioner
4+
max_levels::Int
5+
max_coarse::Int
6+
function AMGPreconditioner(; max_levels = 10, max_coarse = 10)
7+
precon = new()
8+
precon.max_levels = max_levels
9+
precon.max_coarse = max_coarse
10+
precon
11+
end
12+
end
13+
14+
"""
15+
```
16+
AMGPreconditioner(;max_levels=10, max_coarse=10)
17+
AMGPreconditioner(matrix;max_levels=10, max_coarse=10)
18+
```
19+
20+
Create the [`AMGPreconditioner`](@ref) wrapping the Ruge-Stüben AMG preconditioner from [AlgebraicMultigrid.jl](https://github.com/JuliaLinearAlgebra/AlgebraicMultigrid.jl)
21+
"""
22+
function AMGPreconditioner end
23+
24+
@eval begin
25+
@makefrommatrix AMGPreconditioner
26+
end
27+
28+
function update!(precon::AMGPreconditioner)
29+
@inbounds flush!(precon.A)
30+
precon.factorization = AlgebraicMultigrid.aspreconditioner(AlgebraicMultigrid.ruge_stuben(precon.A.cscmatrix))
31+
end
32+
33+
allow_views(::AMGPreconditioner)=true
34+
allow_views(::Type{AMGPreconditioner})=true
+101
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
mutable struct BlockPreconditioner <: AbstractPreconditioner
2+
A::ExtendableSparseMatrix
3+
factorization
4+
phash::UInt64
5+
partitioning::Union{Nothing,Vector{AbstractVector}}
6+
facts::Vector
7+
function BlockPreconditioner(;partitioning=nothing, factorization=ExtendableSparse.LUFactorization)
8+
p = new()
9+
p.phash = 0
10+
p.partitioning=partitioning
11+
p.factorization=factorization
12+
p
13+
end
14+
end
15+
16+
17+
18+
"""
19+
BlockPreconditioner(;partitioning, factorization=LUFactorization)
20+
21+
Create a block preconditioner from partition of unknowns given by `partitioning`, a vector of AbstractVectors describing the
22+
indices of the partitions of the matrix. For a matrix of size `n x n`, e.g. partitioning could be `[ 1:n÷2, (n÷2+1):n]`
23+
or [ 1:2:n, 2:2:n].
24+
Factorization is a callable (Function or struct) which allows to create a factorization (with `ldiv!` methods) from a submatrix of A.
25+
"""
26+
function BlockPreconditioner end
27+
28+
"""
29+
allow_views(::preconditioner_type)
30+
31+
Factorizations on matrix partitions within a block preconditioner may or may not work with array views.
32+
E.g. the umfpack factorization cannot work with views, while ILUZeroPreconditioner can.
33+
Implementing a method for `allow_views` returning `false` resp. `true` allows to dispatch to the proper case.
34+
"""
35+
allow_views(::Any)=false
36+
37+
38+
function update!(precon::BlockPreconditioner)
39+
flush!(precon.A)
40+
nall=sum(length,precon.partitioning)
41+
n=size(precon.A,1)
42+
if nall!=n
43+
@warn "sum(length,partitioning)=$(nall) but n=$(n)"
44+
end
45+
46+
if isnothing(precon.partitioning)
47+
partitioning=[1:n]
48+
end
49+
50+
np=length(precon.partitioning)
51+
precon.facts=Vector{Any}(undef,np)
52+
Threads.@threads for ipart=1:np
53+
factorization=deepcopy(precon.factorization)
54+
AP=precon.A[precon.partitioning[ipart],precon.partitioning[ipart]]
55+
FP=factorization(AP)
56+
precon.facts[ipart]=FP
57+
end
58+
end
59+
60+
61+
62+
63+
function LinearAlgebra.ldiv!(p::BlockPreconditioner,v)
64+
partitioning=p.partitioning
65+
facts=p.facts
66+
np=length(partitioning)
67+
68+
if allow_views(p.factorization)
69+
Threads.@threads for ipart=1:np
70+
ldiv!(facts[ipart],view(v,partitioning[ipart]))
71+
end
72+
else
73+
Threads.@threads for ipart=1:np
74+
vv=v[partitioning[ipart]]
75+
ldiv!(facts[ipart],vv)
76+
view(v,partitioning[ipart]).=vv
77+
end
78+
end
79+
v
80+
end
81+
82+
function LinearAlgebra.ldiv!(u,p::BlockPreconditioner,v)
83+
partitioning=p.partitioning
84+
facts=p.facts
85+
np=length(partitioning)
86+
87+
if allow_views(p.factorization)
88+
Threads.@threads for ipart=1:np
89+
ldiv!(view(u,partitioning[ipart]),facts[ipart],view(v,partitioning[ipart]))
90+
end
91+
else
92+
Threads.@threads for ipart=1:np
93+
uu=u[partitioning[ipart]]
94+
ldiv!(uu,facts[ipart],v[partitioning[ipart]])
95+
view(u,partitioning[ipart]).=uu
96+
end
97+
end
98+
u
99+
end
100+
101+
Base.eltype(p::BlockPreconditioner)=eltype(p.facts[1])

src/cholmod_cholesky.jl renamed to src/factorizations/cholmod_cholesky.jl

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
mutable struct CholeskyFactorization{Tv, Ti} <: AbstractLUFactorization{Tv, Ti}
2-
A::Union{ExtendableSparseMatrix{Tv, Ti}, Nothing}
3-
fact::Union{SuiteSparse.CHOLMOD.Factor{Tv}, Nothing}
1+
mutable struct CholeskyFactorization <: AbstractLUFactorization
2+
A::Union{ExtendableSparseMatrix, Nothing}
3+
fact::Union{SuiteSparse.CHOLMOD.Factor, Nothing}
44
phash::UInt64
55
A64::Any
66
end
@@ -11,15 +11,15 @@ CholeskyFactorization(matrix)
1111
1212
Default Cholesky factorization via cholmod.
1313
"""
14-
function CholeskyFactorization(; valuetype::Type = Float64, indextype::Type = Int64)
15-
CholeskyFactorization{valuetype, indextype}(nothing, nothing, 0, nothing)
14+
function CholeskyFactorization()
15+
CholeskyFactorization(nothing, nothing, 0, nothing)
1616
end
1717

1818
function update!(cholfact::CholeskyFactorization)
1919
A = cholfact.A
2020
flush!(A)
2121
if A.phash != cholfact.phash
22-
cholfact.A64 = Symmetric(SparseMatrixCSC{Float64, Int64}(A.cscmatrix))
22+
cholfact.A64 = Symmetric(A.cscmatrix)
2323
cholfact.fact = cholesky(cholfact.A64)
2424
cholfact.phash = A.phash
2525
else

0 commit comments

Comments
 (0)