Skip to content

Commit a29e7f0

Browse files
authored
Merge pull request #13 from ranjanan/moreopt
Add symmetric Gauss Seidel smoothing, improve smoother
2 parents bdaaa7c + 5dde554 commit a29e7f0

File tree

6 files changed

+97
-17
lines changed

6 files changed

+97
-17
lines changed

src/AMG.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ include("gallery.jl")
1212
export poisson
1313

1414
include("smoother.jl")
15+
export GaussSeidel, SymmetricSweep, ForwardSweep, BackwardSweep
1516

1617
include("multilevel.jl")
1718
export solve

src/classical.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@ function ruge_stuben{Ti,Tv}(A::SparseMatrixCSC{Ti,Tv};
2020

2121
levels = Vector{Level{Ti,Tv}}()
2222

23-
while length(levels) < max_levels
23+
while length(levels) < max_levels #&& size(A, 1) < max_coarse
2424
A = extend_heirarchy!(levels, strength, CF, A)
25-
if size(A, 1) < max_coarse
25+
if size(A, 1) <= max_coarse
2626
break
2727
end
2828
end

src/multilevel.jl

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ abstract type CoarseSolver end
1616
struct Pinv <: CoarseSolver
1717
end
1818

19-
MultiLevel{Ti,Tv}(l::Vector{Level{Ti,Tv}}, A::SparseMatrixCSC{Ti,Tv}, presmoother, postsmoother; coarse_solver = Pinv()) =
20-
MultiLevel(l, A, coarse_solver, presmoother, postsmoother)
19+
MultiLevel{Ti,Tv}(l::Vector{Level{Ti,Tv}}, A::SparseMatrixCSC{Ti,Tv}, presmoother, postsmoother) =
20+
MultiLevel(l, A, Pinv(), presmoother, postsmoother)
2121
Base.length(ml) = length(ml.levels) + 1
2222

2323
function Base.show(io::IO, ml::MultiLevel)
@@ -61,19 +61,20 @@ end
6161
function solve{T}(ml::MultiLevel, b::Vector{T},
6262
maxiter = 100,
6363
cycle = V(),
64-
tol = 1e-5)
64+
tol = 1e-5;
65+
verbose = false)
6566
x = zeros(T, size(b))
6667
residuals = Vector{T}()
6768
A = ml.levels[1].A
6869
normb = norm(b)
6970
if normb != 0
7071
tol *= normb
7172
end
72-
push!(residuals, T(norm(b - A*x)))
73+
push!(residuals, normb)
7374

7475
lvl = 1
7576
while length(residuals) <= maxiter && residuals[end] > tol
76-
if length(ml.levels) == 1
77+
if length(ml) == 1
7778
x = coarse_solver(ml.coarse_solver, A, b)
7879
else
7980
x = __solve(cycle, ml, x, b, lvl)

src/preconditioner.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ end
66

77
aspreconditioner(ml::MultiLevel) = Preconditioner(ml)
88

9-
\(p::Preconditioner, b) = p * b
10-
*(p::Preconditioner, b) = solve(p.ml, b, 1, V(), 1e-12)
9+
\(p::Preconditioner, b) = solve(p.ml, b, 1, V(), 1e-12)
10+
*(p::Preconditioner, b) = p.ml.levels[1].A * x
1111

1212
A_ldiv_B!(x, p::Preconditioner, b) = copy!(x, p \ b)
1313
A_mul_B!(b, p::Preconditioner, x) = A_mul_B!(b, p.ml.levels[1].A, x)

src/smoother.jl

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,46 @@ struct SymmetricSweep <: Sweep
44
end
55
struct ForwardSweep <: Sweep
66
end
7+
struct BackwardSweep <: Sweep
8+
end
79
struct GaussSeidel{S} <: Smoother
810
sweep::S
911
end
10-
GaussSeidel(;sweep = ForwardSweep()) = GaussSeidel(sweep)
12+
GaussSeidel() = GaussSeidel(SymmetricSweep())
13+
14+
presmoother!(s, A, x, b) = smoother!(s, s.sweep, A, x, b)
15+
postsmoother!(s, A, x, b) = smoother!(s, s.sweep, A, x, b)
16+
17+
smoother!(s::GaussSeidel, ::ForwardSweep, A, x, b) =
18+
gs!(A, b, x, 1, 1, size(A, 1))
19+
# gauss_seidel!(x, A, b, maxiter = 1)
20+
function smoother!(s::GaussSeidel, ::SymmetricSweep, A, x, b)
21+
smoother!(s, ForwardSweep(), A, x, b)
22+
smoother!(s, BackwardSweep(), A, x, b)
23+
end
1124

12-
presmoother!(s, A, x, b) = smoother(s, s.sweep, A, x, b)
13-
postsmoother!(s, A, x, b) = smoother(s, s.sweep, A, x, b)
25+
smoother!(s::GaussSeidel, ::BackwardSweep, A, x, b) =
26+
gs!(A, b, x, size(A,1), -1, 1)
1427

15-
smoother(s::GaussSeidel, ::ForwardSweep, A, x, b) =
16-
gauss_seidel!(x, A, b, maxiter = 1)
28+
29+
function gs!{T,Ti}(A::SparseMatrixCSC{T,Ti}, b::Vector{T}, x::Vector{T}, start, step, stop)
30+
n = size(A, 1)
31+
z = zero(eltype(A))
32+
for i = start:step:stop
33+
rsum = z
34+
d = z
35+
for j in nzrange(A, i)
36+
row = A.rowval[j]
37+
val = A.nzval[j]
38+
if i == row
39+
d = val
40+
else
41+
rsum += val * x[row]
42+
end
43+
end
44+
45+
if d != 0
46+
x[i] = (b[i] - rsum) / d
47+
end
48+
end
49+
end

test/runtests.jl

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -100,23 +100,39 @@ end
100100
end
101101

102102
@testset "Solver" begin
103+
fsmoother = GaussSeidel(ForwardSweep())
104+
103105
A = poisson(1000)
104106
A = float.(A)
105107
ml = ruge_stuben(A)
106108
x = solve(ml, A * ones(1000))
107-
@test sum(abs2, x - ones(1000)) < 1e-10
109+
@test sum(abs2, x - ones(1000)) < 1e-8
110+
111+
ml = ruge_stuben(A, presmoother = fsmoother,
112+
postsmoother = fsmoother)
113+
x = solve(ml, A * ones(1000))
114+
@test sum(abs2, x - ones(1000)) < 1e-8
115+
108116

109117
A = load("randlap.jld")["G"]
118+
119+
ml = ruge_stuben(A, presmoother = fsmoother,
120+
postsmoother = fsmoother)
121+
x = solve(ml, A * ones(100))
122+
@test sum(abs2, x - zeros(100)) < 1e-8
123+
110124
ml = ruge_stuben(A)
111125
x = solve(ml, A * ones(100))
112-
@test sum(abs2, x - zeros(100)) < 1e-10
126+
@test sum(abs2, x - zeros(100)) < 1e-6
113127

114128
end
115129

116130
@testset "Preconditioning" begin
117131
A = load("thing.jld")["G"]
118132
n = size(A, 1)
119-
ml = ruge_stuben(A)
133+
smoother = GaussSeidel(ForwardSweep())
134+
ml = ruge_stuben(A, presmoother = smoother,
135+
postsmoother = smoother)
120136
p = aspreconditioner(ml)
121137
b = zeros(n)
122138
b[1] = 1
@@ -163,5 +179,34 @@ diff = x - [ 0.82365077, -0.537589 , -0.30632349, -0.19370186, -0.14773294,
163179
0.04968258, 0.04968737, 0.05105749, 0.05009268, 0.04972329,
164180
0.04970173]
165181
@test sum(abs2, diff) < 1e-8
182+
183+
# Symmetric GaussSeidel Smoothing
184+
185+
ml = ruge_stuben(A)
186+
p = aspreconditioner(ml)
187+
188+
x = cg(A, b, Pl = p, maxiter = 100_000, tol = 1e-6)
189+
diff = x - [0.823762, -0.537478, -0.306212, -0.19359, -0.147621, 0.685002,
190+
-0.155389, -0.127703, -0.111867, 0.453735, -0.0856607, -0.0858715,
191+
-0.0846678, 0.129962, 0.0281662, -0.0389642, -0.0593981, -0.0653311,
192+
0.0545782, -0.0474255, -0.0519275, -0.0467483, -0.0448061, 0.056504,
193+
0.0280386, -0.0227138, -0.0405172, -0.0431067, -0.0440778, 0.076042,
194+
0.052232, 0.0447537, 0.05847, 0.0509098, 0.0484189, 0.0528356,
195+
0.0503983, 0.0495933, 0.0497211, 0.0497731, 0.0497942, 0.049799,
196+
0.0511691, 0.0502043, 0.0498349, 0.0498134]
197+
@test sum(abs2, diff) < 1e-8
198+
199+
x = solve(ml, b, 1, V(), 1e-12)
200+
diff = x - [0.775725, -0.571202, -0.290989, -0.157001, -0.106981, 0.622652,
201+
-0.122318, -0.0891874, -0.0709834, 0.392621, -0.055544, -0.0507485,
202+
-0.0466376, 0.107175, 0.0267468, -0.0200843, -0.0282827, -0.0299929,
203+
0.0420468, -0.0175585, -0.0181318, -0.0121591, -0.00902523, 0.0394795,
204+
0.019981, -0.00270916, -0.0106855, -0.0093661, -0.00837619, 0.052532,
205+
0.0301423, 0.0248904, 0.0333098, 0.0262179, 0.0246211, 0.026778,
206+
0.0245746, 0.0238448, 0.0233892, 0.0231593, 0.0230526, 0.0229771,
207+
0.0247913, 0.0238555, 0.0233681, 0.023096]
208+
@test sum(abs2, diff) < 1e-8
209+
210+
166211
end
167212
end

0 commit comments

Comments
 (0)