Skip to content

Commit 1a39841

Browse files
committed
Add some code
1 parent 56f5bab commit 1a39841

File tree

3 files changed

+238
-3
lines changed

3 files changed

+238
-3
lines changed

src/AMG.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
module AMG
22

3-
# package code goes here
3+
include("mg.jl")
4+
export RS
45

56
end # module

src/mg.jl

Lines changed: 236 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,236 @@
1+
#=function mg(a::SparseMatrixCSC, b::Vector, x = zeros(size(b)))
2+
3+
r = a*x - b
4+
5+
# Smoothing steps
6+
smooth!(x, A, b)
7+
8+
# Coarsening steps
9+
while level < nlevels
10+
Ac[level] = coarsen(A[level-1])
11+
f[level] = coarse(f[level-1])
12+
end
13+
x = solve(A[end], f[end])
14+
15+
# Interpolation step
16+
interpolate!(x, nlevels)
17+
18+
if norm(r) < tol
19+
break
20+
end
21+
22+
x
23+
end
24+
25+
struct Level
26+
A::SparseMatrixCSC
27+
R::RestrictionMatrix
28+
P::ProlongationMatrix
29+
end
30+
31+
struct RestrictionMatrix
32+
r::SparseMatrixCSC
33+
end
34+
35+
struct ProlongationMatrix
36+
p::SparseMatrixCSC
37+
end=#
38+
39+
function classical(A::SparseMatrixCSC, θ::Float64)
40+
41+
I = Int[]
42+
J = Int[]
43+
V = Float64[]
44+
45+
m, n = size(A)
46+
47+
for i = 1:n
48+
neighbors = A[:,i]
49+
m = find_max_off_diag(neighbors, i)
50+
threshold = θ * m
51+
for j in nzrange(A, i)
52+
row = A.rowval[j]
53+
val = A.nzval[j]
54+
if abs(val) >= threshold
55+
push!(I, row)
56+
push!(J, i)
57+
push!(V, abs(val))
58+
end
59+
end
60+
end
61+
S = sparse(I, J, V)
62+
63+
scale_cols_by_largest_entry(S)
64+
end
65+
66+
function find_max_off_diag(neighbors, col)
67+
max_offdiag = 0
68+
for (i,v) in enumerate(neighbors)
69+
if col != i
70+
max_offdiag = max(max_offdiag, abs(v))
71+
end
72+
end
73+
max_offdiag
74+
end
75+
76+
function scale_cols_by_largest_entry(A::SparseMatrixCSC)
77+
78+
m,n = size(A)
79+
80+
I = zeros(Int, size(A.nzval))
81+
J = similar(I)
82+
V = zeros(size(A.nzval))
83+
84+
k = 1
85+
for i = 1:n
86+
m = maximum(A[:,i])
87+
for j in nzrange(A, i)
88+
row = A.rowval[j]
89+
val = A.nzval[j]
90+
I[k] = row
91+
J[k] = i
92+
V[k] = val / m
93+
k += 1
94+
end
95+
end
96+
97+
sparse(I,J,V)
98+
end
99+
100+
function RS(S::SparseMatrixCSC)
101+
102+
m,n = size(S)
103+
104+
n_nodes = n
105+
lambda = zeros(Int, n)
106+
Tp = S.colptr
107+
Tj = S.rowval
108+
Sp = Tp
109+
Sj = Tj
110+
111+
# compute lambdas
112+
for i = 1:n
113+
lambda[i] = Tp[i+1] - Tp[i]
114+
end
115+
116+
interval_ptr = zeros(Int, n+1)
117+
interval_count = zeros(Int, n+1)
118+
index_to_node = zeros(Int,n)
119+
node_to_index = zeros(Int,n)
120+
121+
for i = 1:n
122+
interval_count[lambda[i]+1] += 1
123+
end
124+
csum = 0
125+
for i = 1:n
126+
interval_ptr[i] = csum
127+
csum += interval_count[i]
128+
interval_count[i] = 0
129+
end
130+
for i = 1:n
131+
lambda_i = lambda[i]+1
132+
index = interval_ptr[lambda_i] + interval_count[lambda_i]
133+
index_to_node[index+1] = i
134+
node_to_index[i] = index+1
135+
interval_count[lambda_i] += 1
136+
end
137+
splitting = fill(2, n)
138+
139+
# all nodes with no neighbors become F nodes
140+
for i = 1:n
141+
# check if diagonal or check if no neighbors
142+
if lambda[i] == 0 || (lambda[i] == 1 && Tj[Tp[i]] == i)
143+
splitting[i] = F_NODE
144+
end
145+
end
146+
147+
# Now add elements to C and F, in descending order of lambda
148+
for top_index = n_nodes:-1:1
149+
i = index_to_node[top_index]
150+
lambda_i = lambda[i] + 1
151+
152+
# if (n_nodes == 4)
153+
# std::cout << "selecting node #" << i << " with lambda " << lambda[i] << std::endl;
154+
155+
# remove i from its interval
156+
interval_count[lambda_i] -= 1
157+
158+
if splitting[i] == F_NODE
159+
continue
160+
else
161+
162+
@assert splitting[i] == U_NODE
163+
164+
splitting[i] = C_NODE
165+
166+
# For each j in S^T_i /\ U
167+
for jj = Tp[i]:Tp[i+1]-1
168+
169+
j = Tj[jj]
170+
171+
if splitting[j] == U_NODE
172+
splitting[j] = F_NODE
173+
174+
# For each k in S_j /\ U
175+
for kk = Sp[j]: Sp[j+1]-1
176+
k = Sj[kk]
177+
178+
if splitting[k] == U_NODE
179+
# move k to the end of its current interval
180+
lambda[k] >= n_nodes - 1 && continue
181+
182+
lambda_k = lambda[k] + 1
183+
old_pos = node_to_index[k]
184+
new_pos = interval_ptr[lambda_k] + interval_count[lambda_k]# - 1
185+
186+
node_to_index[index_to_node[old_pos]] = new_pos
187+
node_to_index[index_to_node[new_pos]] = old_pos
188+
(index_to_node[old_pos], index_to_node[new_pos]) = (index_to_node[new_pos], index_to_node[old_pos])
189+
190+
# update intervals
191+
interval_count[lambda_k] -= 1
192+
interval_count[lambda_k+1] += 1 # invalid write!
193+
interval_ptr[lambda_k+1] = new_pos - 1
194+
195+
# increment lambda_k
196+
lambda[k] += 1
197+
end
198+
end
199+
end
200+
end
201+
202+
# For each j in S_i /\ U
203+
for jj = Sp[i]: Sp[i+1]-1
204+
205+
j = Sj[jj]
206+
207+
if splitting[j] == U_NODE # decrement lambda for node j
208+
209+
lambda[j] == 0 && continue
210+
211+
# assert(lambda[j] > 0);//this would cause problems!
212+
213+
# move j to the beginning of its current interval
214+
lambda_j = lambda[j] + 1
215+
old_pos = node_to_index[j]
216+
new_pos = interval_ptr[lambda_j]
217+
218+
node_to_index[index_to_node[old_pos]] = new_pos
219+
node_to_index[index_to_node[new_pos]] = old_pos
220+
(index_to_node[old_pos],index_to_node[new_pos]) = (index_to_node[new_pos],index_to_node[old_pos])
221+
222+
# update intervals
223+
interval_count[lambda_j] -= 1
224+
interval_count[lambda_j-1] += 1
225+
interval_ptr[lambda_j] += 1
226+
interval_ptr[lambda_j-1] = interval_ptr[lambda_j] - interval_count[lambda_j-1]
227+
228+
# decrement lambda_j
229+
lambda[j] -= 1
230+
end
231+
end
232+
end
233+
end
234+
splitting
235+
end
236+
poisson(n) = sparse(Tridiagonal(fill(-1, n-1), fill(2, n), fill(-1, n-1)))

test/runtests.jl

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
11
using AMG
22
using Base.Test
33

4-
# write your own tests here
5-
@test 1 == 2

0 commit comments

Comments
 (0)