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
1
function RS (S:: SparseMatrixCSC )
101
-
2
+
102
3
m,n = size (S)
103
4
104
5
n_nodes = n
@@ -107,17 +8,17 @@ function RS(S::SparseMatrixCSC)
107
8
Tj = S. rowval
108
9
Sp = Tp
109
10
Sj = Tj
110
-
11
+
111
12
# compute lambdas
112
13
for i = 1 : n
113
14
lambda[i] = Tp[i+ 1 ] - Tp[i]
114
15
end
115
-
16
+
116
17
interval_ptr = zeros (Int, n+ 1 )
117
18
interval_count = zeros (Int, n+ 1 )
118
19
index_to_node = zeros (Int,n)
119
20
node_to_index = zeros (Int,n)
120
-
21
+
121
22
for i = 1 : n
122
23
interval_count[lambda[i]+ 1 ] += 1
123
24
end
@@ -135,96 +36,96 @@ function RS(S::SparseMatrixCSC)
135
36
interval_count[lambda_i] += 1
136
37
end
137
38
splitting = fill (2 , n)
138
-
39
+
139
40
# all nodes with no neighbors become F nodes
140
41
for i = 1 : n
141
42
# check if diagonal or check if no neighbors
142
43
if lambda[i] == 0 || (lambda[i] == 1 && Tj[Tp[i]] == i)
143
44
splitting[i] = F_NODE
144
45
end
145
46
end
146
-
47
+
147
48
# Now add elements to C and F, in descending order of lambda
148
49
for top_index = n_nodes: - 1 : 1
149
50
i = index_to_node[top_index]
150
51
lambda_i = lambda[i] + 1
151
-
52
+
152
53
# if (n_nodes == 4)
153
54
# std::cout << "selecting node #" << i << " with lambda " << lambda[i] << std::endl;
154
-
55
+
155
56
# remove i from its interval
156
57
interval_count[lambda_i] -= 1
157
-
58
+
158
59
if splitting[i] == F_NODE
159
60
continue
160
61
else
161
-
62
+
162
63
@assert splitting[i] == U_NODE
163
-
64
+
164
65
splitting[i] = C_NODE
165
-
66
+
166
67
# For each j in S^T_i /\ U
167
68
for jj = Tp[i]: Tp[i+ 1 ]- 1
168
69
169
70
j = Tj[jj]
170
-
71
+
171
72
if splitting[j] == U_NODE
172
73
splitting[j] = F_NODE
173
-
74
+
174
75
# For each k in S_j /\ U
175
76
for kk = Sp[j]: Sp[j+ 1 ]- 1
176
77
k = Sj[kk]
177
-
78
+
178
79
if splitting[k] == U_NODE
179
80
# move k to the end of its current interval
180
81
lambda[k] >= n_nodes - 1 && continue
181
-
82
+
182
83
lambda_k = lambda[k] + 1
183
84
old_pos = node_to_index[k]
184
85
new_pos = interval_ptr[lambda_k] + interval_count[lambda_k]# - 1
185
-
86
+
186
87
node_to_index[index_to_node[old_pos]] = new_pos
187
88
node_to_index[index_to_node[new_pos]] = old_pos
188
89
(index_to_node[old_pos], index_to_node[new_pos]) = (index_to_node[new_pos], index_to_node[old_pos])
189
-
90
+
190
91
# update intervals
191
92
interval_count[lambda_k] -= 1
192
93
interval_count[lambda_k+ 1 ] += 1 # invalid write!
193
94
interval_ptr[lambda_k+ 1 ] = new_pos - 1
194
-
95
+
195
96
# increment lambda_k
196
97
lambda[k] += 1
197
98
end
198
99
end
199
100
end
200
101
end
201
-
102
+
202
103
# For each j in S_i /\ U
203
104
for jj = Sp[i]: Sp[i+ 1 ]- 1
204
105
205
106
j = Sj[jj]
206
107
207
108
if splitting[j] == U_NODE # decrement lambda for node j
208
109
209
- lambda[j] == 0 && continue
210
-
110
+ lambda[j] == 0 && continue
111
+
211
112
# assert(lambda[j] > 0);//this would cause problems!
212
-
113
+
213
114
# move j to the beginning of its current interval
214
115
lambda_j = lambda[j] + 1
215
116
old_pos = node_to_index[j]
216
117
new_pos = interval_ptr[lambda_j]
217
-
118
+
218
119
node_to_index[index_to_node[old_pos]] = new_pos
219
120
node_to_index[index_to_node[new_pos]] = old_pos
220
121
(index_to_node[old_pos],index_to_node[new_pos]) = (index_to_node[new_pos],index_to_node[old_pos])
221
-
122
+
222
123
# update intervals
223
124
interval_count[lambda_j] -= 1
224
125
interval_count[lambda_j- 1 ] += 1
225
126
interval_ptr[lambda_j] += 1
226
127
interval_ptr[lambda_j- 1 ] = interval_ptr[lambda_j] - interval_count[lambda_j- 1 ]
227
-
128
+
228
129
# decrement lambda_j
229
130
lambda[j] -= 1
230
131
end
@@ -233,4 +134,3 @@ function RS(S::SparseMatrixCSC)
233
134
end
234
135
splitting
235
136
end
236
- poisson (n) = sparse (Tridiagonal (fill (- 1 , n- 1 ), fill (2 , n), fill (- 1 , n- 1 )))
0 commit comments