Skip to content

Commit 3d130ad

Browse files
authored
Merge pull request #5 from ranjanan/fix
Fix splitting for strength matrices that aren't symmetric
2 parents 87c0d62 + 291f4da commit 3d130ad

File tree

7 files changed

+124
-35
lines changed

7 files changed

+124
-35
lines changed

.travis.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@ matrix:
1717
- julia: nightly
1818

1919
## uncomment and modify the following lines to manually install system packages
20-
#addons:
21-
# apt: # apt-get for linux
22-
# packages:
23-
# - gfortran
20+
addons:
21+
apt: # apt-get for linux
22+
packages:
23+
- hdf5-tools
2424
#before_script: # homebrew for mac
2525
# - if [ $TRAVIS_OS_NAME = osx ]; then brew install gcc; fi
2626

src/classical.jl

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,12 @@ function direct_interpolation{T,V}(A::T, S::T, splitting::Vector{V})
4242
fill!(S.nzval, 1.)
4343
S = A .* S
4444
Pp = rs_direct_interpolation_pass1(S, A, splitting)
45-
Pp .= Pp .+ 1
45+
Pp = Pp .+ 1
4646

4747
Px, Pj = rs_direct_interpolation_pass2(A, S, splitting, Pp)
4848

4949
# Px .= abs.(Px)
50-
Pj .= Pj .+ 1
50+
Pj = Pj .+ 1
5151

5252
R = SparseMatrixCSC(maximum(Pj), size(A, 1), Pp, Pj, Px)
5353
P = R'
@@ -59,7 +59,7 @@ end
5959
function rs_direct_interpolation_pass1(S, A, splitting)
6060

6161
Bp = zeros(Int, size(A.colptr))
62-
Sp = S.colptr
62+
#=Sp = S.colptr
6363
Sj = S.rowval
6464
n_nodes = size(A, 1)
6565
nnz = 0
@@ -75,6 +75,21 @@ function rs_direct_interpolation_pass1(S, A, splitting)
7575
end
7676
end
7777
Bp[i+1] = nnz
78+
end=#
79+
n = size(A, 1)
80+
nnz = 0
81+
for i = 1:n
82+
if splitting[i] == C_NODE
83+
nnz += 1
84+
else
85+
for j in nzrange(S, i)
86+
row = S.rowval[j]
87+
if splitting[row] == C_NODE && row != i
88+
nnz += 1
89+
end
90+
end
91+
end
92+
Bp[i+1] = nnz
7893
end
7994
Bp
8095
end

src/splitting.jl

Lines changed: 86 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,23 +12,25 @@ function RS_CF_splitting(S::SparseMatrixCSC)
1212

1313
n_nodes = n
1414
lambda = zeros(Int, n)
15-
Tp = S.colptr
16-
Tj = S.rowval
17-
Sp = Tp
18-
Sj = Tj
15+
T = S'
16+
Tp = T.colptr
17+
Tj = T.rowval
18+
Sp = S.colptr
19+
Sj = S.rowval
1920

20-
# compute lambdas
21+
# compute lambdas - number of neighbors
2122
for i = 1:n
22-
lambda[i] = Tp[i+1] - Tp[i]
23+
lambda[i] = Sp[i+1] - Sp[i]
2324
end
2425

2526
interval_ptr = zeros(Int, n+1)
2627
interval_count = zeros(Int, n+1)
2728
index_to_node = zeros(Int,n)
2829
node_to_index = zeros(Int,n)
2930

31+
# Number of nodes with a certain neighbor count
3032
for i = 1:n
31-
interval_count[lambda[i]+1] += 1
33+
interval_count[lambda[i] + 1] += 1
3234
end
3335
csum = 0
3436
for i = 1:n
@@ -37,7 +39,7 @@ function RS_CF_splitting(S::SparseMatrixCSC)
3739
interval_count[i] = 0
3840
end
3941
for i = 1:n
40-
lambda_i = lambda[i]+1
42+
lambda_i = lambda[i] + 1
4143
index = interval_ptr[lambda_i] + interval_count[lambda_i]
4244
index_to_node[index+1] = i
4345
node_to_index[i] = index+1
@@ -53,8 +55,78 @@ function RS_CF_splitting(S::SparseMatrixCSC)
5355
end
5456
end
5557

58+
for top_index = n_nodes:-1:1
59+
i = index_to_node[top_index]
60+
lambda_i = lambda[i] + 1
61+
interval_count[lambda_i] -= 1
62+
if splitting[i] == F_NODE
63+
continue
64+
else
65+
@assert splitting[i] == U_NODE
66+
splitting[i] = C_NODE
67+
for j in nzrange(T, i)
68+
row = T.rowval[j]
69+
if splitting[row] == U_NODE
70+
splitting[row] = F_NODE
71+
72+
for k in nzrange(S, row)
73+
rowk = S.rowval[k]
74+
if splitting[rowk] == U_NODE
75+
lambda[rowk] >= n_nodes - 1 && continue
76+
lambda_k = lambda[rowk] + 1
77+
old_pos = node_to_index[rowk]
78+
new_pos = interval_ptr[lambda_k] + interval_count[lambda_k]# - 1
79+
80+
node_to_index[index_to_node[old_pos]] = new_pos
81+
node_to_index[index_to_node[new_pos]] = old_pos
82+
(index_to_node[old_pos], index_to_node[new_pos]) = (index_to_node[new_pos], index_to_node[old_pos])
83+
84+
# update intervals
85+
interval_count[lambda_k] -= 1
86+
interval_count[lambda_k + 1] += 1 # invalid write!
87+
interval_ptr[lambda_k + 1] = new_pos - 1
88+
89+
# increment lambda_k
90+
lambda[rowk] += 1
91+
end
92+
end
93+
end
94+
end
95+
for j in nzrange(S, i)
96+
row = S.rowval[j]
97+
if splitting[row] == U_NODE
98+
99+
lambda[row] == 0 && continue
100+
101+
# assert(lambda[j] > 0);//this would cause problems!
102+
103+
# move j to the beginning of its current interval
104+
lambda_j = lambda[row] + 1
105+
old_pos = node_to_index[row]
106+
new_pos = interval_ptr[lambda_j] + 1
107+
108+
node_to_index[index_to_node[old_pos]] = new_pos
109+
node_to_index[index_to_node[new_pos]] = old_pos
110+
(index_to_node[old_pos],index_to_node[new_pos]) = (index_to_node[new_pos],index_to_node[old_pos])
111+
112+
# update intervals
113+
interval_count[lambda_j] -= 1
114+
interval_count[lambda_j-1] += 1
115+
interval_ptr[lambda_j] += 1
116+
interval_ptr[lambda_j-1] = interval_ptr[lambda_j] - interval_count[lambda_j-1]
117+
118+
# decrement lambda_j
119+
lambda[row] -= 1
120+
end
121+
end
122+
end
123+
end
124+
splitting
125+
end
126+
127+
56128
# Now add elements to C and F, in descending order of lambda
57-
for top_index = n_nodes:-1:1
129+
#=for top_index = n_nodes:-1:1
58130
i = index_to_node[top_index]
59131
lambda_i = lambda[i] + 1
60132
@@ -74,6 +146,7 @@ function RS_CF_splitting(S::SparseMatrixCSC)
74146
75147
# For each j in S^T_i /\ U
76148
for jj = Tp[i]:Tp[i+1]-1
149+
#jj > length(Tp) && continue
77150
78151
j = Tj[jj]
79152
@@ -82,6 +155,7 @@ function RS_CF_splitting(S::SparseMatrixCSC)
82155
83156
# For each k in S_j /\ U
84157
for kk = Sp[j]: Sp[j+1]-1
158+
# kk > length(Sj) && continue
85159
k = Sj[kk]
86160
87161
if splitting[k] == U_NODE
@@ -109,7 +183,8 @@ function RS_CF_splitting(S::SparseMatrixCSC)
109183
end
110184
111185
# For each j in S_i /\ U
112-
for jj = Sp[i]: Sp[i+1]-1
186+
for jj = Sp[i]: Sp[i+1] - 1
187+
# jj > length(Sj) && continue
113188
114189
j = Sj[jj]
115190
@@ -141,4 +216,4 @@ function RS_CF_splitting(S::SparseMatrixCSC)
141216
end
142217
end
143218
splitting
144-
end
219+
end=#

src/strength.jl

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,9 @@ function strength_of_connection{T}(c::Classical{T}, A::SparseMatrixCSC)
2929
end
3030
S = sparse(I, J, V, m, n)
3131

32-
scale_cols_by_largest_entry(S)
32+
scale_cols_by_largest_entry!(S)
33+
34+
S'
3335
end
3436

3537
function find_max_off_diag(neighbors, col)
@@ -40,26 +42,15 @@ function find_max_off_diag(neighbors, col)
4042
return maxval
4143
end
4244

43-
function scale_cols_by_largest_entry(A::SparseMatrixCSC)
44-
45-
m,n = size(A)
46-
47-
I = zeros(Int, size(A.nzval))
48-
J = similar(I)
49-
V = zeros(size(A.nzval))
45+
function scale_cols_by_largest_entry!(A::SparseMatrixCSC)
5046

51-
k = 1
47+
n = size(A, 1)
5248
for i = 1:n
5349
_m = maximum(A[:,i])
5450
for j in nzrange(A, i)
55-
row = A.rowval[j]
56-
val = A.nzval[j]
57-
I[k] = row
58-
J[k] = i
59-
V[k] = val / _m
60-
k += 1
51+
A.nzval[j] /= _m
6152
end
6253
end
6354

64-
sparse(I,J,V,m,n)
55+
A
6556
end

test/REQUIRE

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
JLD

test/runtests.jl

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

45
@testset "Strength of connection" begin
56

@@ -19,11 +20,17 @@ end
1920
# Ruge-Stuben splitting
2021
S = poisson(7)
2122
@test split_nodes(RS(), S) == [0, 1, 0, 1, 0, 1, 0]
22-
23+
@show "buzz"
2324
srand(0)
2425
S = sprand(10,10,0.1); S = S + S'
2526
@test split_nodes(RS(), S) == [0, 1, 1, 0, 0, 0, 0, 0, 1, 1]
2627

28+
a = load("thing.jld")["G"]
29+
S = AMG.strength_of_connection(AMG.Classical(0.25), a)
30+
@test split_nodes(RS(), S) == [0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0,
31+
0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0,
32+
1, 0]
33+
2734
end
2835

2936
@testset "Interpolation" begin

test/thing.jld

10.9 KB
Binary file not shown.

0 commit comments

Comments
 (0)