Skip to content

Commit 9ac252c

Browse files
committed
Add direct interpolation with simple test
1 parent cf8e6af commit 9ac252c

File tree

3 files changed

+160
-3
lines changed

3 files changed

+160
-3
lines changed

src/AMG.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,6 @@ export split_nodes, RS
99
include("gallery.jl")
1010
export poisson
1111

12+
include("classical.jl")
13+
1214
end # module

src/classical.jl

Lines changed: 135 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ struct Solver{S,T,P,PS}
77
max_coarse::Int64
88
end
99

10+
struct Level{T}
11+
A::T
12+
end
13+
1014
function ruge_stuben(A::SparseMatrixCSC;
1115
strength = Classical(),
1216
CF = RS(),
@@ -26,8 +30,137 @@ function ruge_stuben(A::SparseMatrixCSC;
2630
end
2731

2832
function extend_heirarchy!(levels::Vector{Level}, strength, CF, A)
29-
3033
S = strength_of_connection(strength, A)
3134
splitting = split_nodes(CF, S)
32-
P = direct_interpolation(A, S, splitting)
35+
P, R = direct_interpolation(A, S, splitting)
36+
end
37+
38+
function direct_interpolation{T,V}(A::T, S::T, splitting::Vector{V})
39+
40+
fill!(S.nzval, 1.)
41+
S = A .* S
42+
Pp = rs_direct_interpolation_pass1(S, A, splitting)
43+
Pp .= Pp .+ 1
44+
45+
Px, Pj = rs_direct_interpolation_pass2(A, S, splitting, Pp)
46+
47+
Px .= abs.(Px)
48+
Pj .= Pj .+ 1
49+
50+
R = SparseMatrixCSC(maximum(Pj), size(A, 1), Pp, Pj, Px)
51+
P = R'
52+
53+
P, R
54+
end
55+
56+
57+
function rs_direct_interpolation_pass1(S, A, splitting)
58+
59+
Bp = zeros(Int, size(A.colptr))
60+
Sp = S.colptr
61+
Sj = S.rowval
62+
n_nodes = size(A, 1)
63+
nnz = 0
64+
for i = 1:n_nodes
65+
if splitting[i] == C_NODE
66+
nnz += 1
67+
else
68+
for jj = Sp[i]:Sp[i+1]-1
69+
if splitting[Sj[jj]] == C_NODE && Sj[jj] != i
70+
nnz += 1
71+
end
72+
end
73+
end
74+
Bp[i+1] = nnz
75+
end
76+
Bp
77+
end
78+
79+
80+
function rs_direct_interpolation_pass2{Tv, Ti}(A::SparseMatrixCSC{Tv,Ti},
81+
S::SparseMatrixCSC{Tv,Ti},
82+
splitting::Vector{Ti},
83+
Bp::Vector{Ti})
84+
85+
86+
Ap = A.colptr
87+
Aj = A.rowval
88+
Ax = A.nzval
89+
Sp = S.colptr
90+
Sj = S.rowval
91+
Sx = S.nzval
92+
Bj = zeros(Ti, Bp[end])
93+
Bx = zeros(Float64, Bp[end])
94+
n_nodes = size(A, 1)
95+
#Bp += 1
96+
97+
for i = 1:n_nodes
98+
if splitting[i] == C_NODE
99+
Bj[Bp[i]] = i
100+
Bx[Bp[i]] = 1
101+
else
102+
sum_strong_pos = 0
103+
sum_strong_neg = 0
104+
for jj = Sp[i]: Sp[i+1]-1
105+
if splitting[Sj[jj]] == C_NODE && Sj[jj] != i
106+
if Sx[jj] < 0
107+
sum_strong_neg += Sx[jj]
108+
else
109+
sum_strong_pos += Sx[jj]
110+
end
111+
end
112+
end
113+
114+
sum_all_pos = 0
115+
sum_all_neg = 0
116+
diag = 0;
117+
for jj = Ap[i]:Ap[i+1]
118+
if Aj[jj] == i
119+
diag += Ax[jj]
120+
else
121+
if Ax[jj] < 0
122+
sum_all_neg += Ax[jj];
123+
else
124+
sum_all_pos += Ax[jj];
125+
end
126+
end
127+
end
128+
129+
alpha = sum_all_neg / sum_strong_neg
130+
beta = sum_all_pos / sum_strong_pos
131+
132+
if sum_strong_pos == 0
133+
diag += sum_all_pos
134+
beta = 0
135+
end
136+
137+
neg_coeff = -alpha/diag;
138+
pos_coeff = -beta/diag;
139+
140+
nnz = Bp[i]
141+
for jj = Sp[i]:Sp[i+1]
142+
if splitting[Sj[jj]] == C_NODE && Sj[jj] != i
143+
Bj[nnz] = Sj[jj]
144+
if Sx[jj] < 0
145+
Bx[nnz] = neg_coeff * Sx[jj]
146+
else
147+
Bx[nnz] = pos_coeff * Sx[jj]
148+
nnz += 1
149+
end
150+
end
151+
end
152+
end
153+
end
154+
155+
m = zeros(Ti, n_nodes)
156+
sum = 0
157+
for i = 1:n_nodes
158+
m[i] = sum
159+
sum += splitting[i]
160+
end
161+
for i = 1:Bp[n_nodes]
162+
Bj[i] = m[Bj[i]]
163+
end
164+
165+
Bx, Bj, Bp
33166
end

test/runtests.jl

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
using AMG
22
using Base.Test
33

4+
@testset "Strength of connection" begin
5+
46
# classical strength of connection
57
A = poisson(5)
68
X = strength_of_connection(Classical(0.2), A)
@@ -10,11 +12,31 @@ X = strength_of_connection(Classical(0.2), A)
1012
0.0 0.0 0.5 1.0 0.5
1113
0.0 0.0 0.0 0.5 1.0 ]
1214

15+
end
16+
17+
@testset "Splitting" begin
18+
1319
# Ruge-Stuben splitting
1420
S = poisson(7)
15-
# S = S - spdiagm(diag(S)) #FIXME
1621
@test split_nodes(RS(), S) == [0, 1, 0, 1, 0, 1, 0]
1722

1823
srand(0)
1924
S = sprand(10,10,0.1); S = S + S'
2025
@test split_nodes(RS(), S) == [0, 1, 1, 0, 0, 0, 0, 0, 1, 1]
26+
27+
end
28+
29+
@testset "Interpolation" begin
30+
31+
# Direct Interpolation
32+
using AMG
33+
A = poisson(5)
34+
splitting = [1,0,1,0,1]
35+
P, R = AMG.direct_interpolation(A, A, splitting)
36+
@test P == [ 1.0 0.0 0.0
37+
0.5 0.5 0.0
38+
0.0 1.0 0.0
39+
0.0 0.5 0.5
40+
0.0 0.0 1.0 ]
41+
42+
end

0 commit comments

Comments
 (0)