1
+ export bicgstabl, bicgstabl!, bicgstabl_iterator, bicgstabl_iterator!, BiCGStabIterable
2
+
3
+ import Base: start, next, done
4
+
5
+ type BiCGStabIterable{precT, matT, vecT <: AbstractVector , smallMatT <: AbstractMatrix , realT <: Real , scalarT <: Number }
6
+ A:: matT
7
+ b:: vecT
8
+ l:: Int
9
+
10
+ x:: vecT
11
+ r_shadow:: vecT
12
+ rs:: smallMatT
13
+ us:: smallMatT
14
+
15
+ max_mv_products:: Int
16
+ mv_products:: Int
17
+ reltol:: realT
18
+ residual:: realT
19
+
20
+ Pl:: precT
21
+
22
+ γ:: vecT
23
+ ω:: scalarT
24
+ σ:: scalarT
25
+ M:: smallMatT
26
+ end
27
+
28
+ bicgstabl_iterator (A, b, l; kwargs... ) = bicgstabl_iterator! (zerox (A, b), A, b, l; initial_zero = true , kwargs... )
29
+
30
+ function bicgstabl_iterator! (x, A, b, l:: Int = 2 ;
31
+ Pl = Identity (),
32
+ max_mv_products = min (30 , size (A, 1 )),
33
+ initial_zero = false ,
34
+ tol = sqrt (eps (real (eltype (b))))
35
+ )
36
+ T = eltype (b)
37
+ n = size (A, 1 )
38
+ mv_products = 0
39
+
40
+ # Large vectors.
41
+ r_shadow = rand (T, n)
42
+ rs = Matrix {T} (n, l + 1 )
43
+ us = zeros (T, n, l + 1 )
44
+
45
+ residual = view (rs, :, 1 )
46
+
47
+ # Compute the initial residual rs[:, 1] = b - A * x
48
+ # Avoid computing A * 0.
49
+ if initial_zero
50
+ copy! (residual, b)
51
+ else
52
+ A_mul_B! (residual, A, x)
53
+ @blas! residual -= one (T) * b
54
+ @blas! residual *= - one (T)
55
+ mv_products += 1
56
+ end
57
+
58
+ # Apply the left preconditioner
59
+ A_ldiv_B! (Pl, residual)
60
+
61
+ γ = zeros (T, l)
62
+ ω = σ = one (T)
63
+
64
+ nrm = norm (residual)
65
+
66
+ # For the least-squares problem
67
+ M = zeros (T, l + 1 , l + 1 )
68
+
69
+ # Stopping condition based on relative tolerance.
70
+ reltol = nrm * tol
71
+
72
+ BiCGStabIterable (A, b, l, x, r_shadow, rs, us,
73
+ max_mv_products, mv_products, reltol, nrm,
74
+ Pl,
75
+ γ, ω, σ, M
76
+ )
77
+ end
78
+
79
+ @inline converged (it:: BiCGStabIterable ) = it. residual ≤ it. reltol
80
+ @inline start (:: BiCGStabIterable ) = 0
81
+ @inline done (it:: BiCGStabIterable , iteration:: Int ) = it. mv_products ≥ it. max_mv_products || converged (it)
82
+
83
+ function next (it:: BiCGStabIterable , iteration:: Int )
84
+ T = eltype (it. b)
85
+ L = 2 : it. l + 1
86
+
87
+ it. σ = - it. ω * it. σ
88
+
89
+ # # BiCG part
90
+ for j = 1 : it. l
91
+ ρ = dot (it. r_shadow, view (it. rs, :, j))
92
+ β = ρ / it. σ
93
+
94
+ # us[:, 1 : j] .= rs[:, 1 : j] - β * us[:, 1 : j]
95
+ for i = 1 : j
96
+ @blas! view (it. us, :, i) *= - β
97
+ @blas! view (it. us, :, i) += one (T) * view (it. rs, :, i)
98
+ end
99
+
100
+ # us[:, j + 1] = Pl \ (A * us[:, j])
101
+ next_u = view (it. us, :, j + 1 )
102
+ A_mul_B! (next_u, it. A, view (it. us, :, j))
103
+ A_ldiv_B! (it. Pl, next_u)
104
+
105
+ it. σ = dot (it. r_shadow, next_u)
106
+ α = ρ / it. σ
107
+
108
+ # rs[:, 1 : j] .= rs[:, 1 : j] - α * us[:, 2 : j + 1]
109
+ for i = 1 : j
110
+ @blas! view (it. rs, :, i) -= α * view (it. us, :, i + 1 )
111
+ end
112
+
113
+ # rs[:, j + 1] = Pl \ (A * rs[:, j])
114
+ next_r = view (it. rs, :, j + 1 )
115
+ A_mul_B! (next_r, it. A , view (it. rs, :, j))
116
+ A_ldiv_B! (it. Pl, next_r)
117
+
118
+ # x = x + α * us[:, 1]
119
+ @blas! it. x += α * view (it. us, :, 1 )
120
+ end
121
+
122
+ # Bookkeeping
123
+ it. mv_products += 2 * it. l
124
+
125
+ # # MR part
126
+
127
+ # M = rs' * rs
128
+ Ac_mul_B! (it. M, it. rs, it. rs)
129
+
130
+ # γ = M[L, L] \ M[L, 1]
131
+ F = lufact! (view (it. M, L, L))
132
+ A_ldiv_B! (it. γ, F, view (it. M, L, 1 ))
133
+
134
+ # This could even be BLAS 3 when combined.
135
+ BLAS. gemv! (' N' , - one (T), view (it. us, :, L), it. γ, one (T), view (it. us, :, 1 ))
136
+ BLAS. gemv! (' N' , one (T), view (it. rs, :, 1 : it. l), it. γ, one (T), it. x)
137
+ BLAS. gemv! (' N' , - one (T), view (it. rs, :, L), it. γ, one (T), view (it. rs, :, 1 ))
138
+
139
+ it. ω = it. γ[it. l]
140
+ it. residual = norm (view (it. rs, :, 1 ))
141
+
142
+ it. residual, iteration + 1
143
+ end
144
+
145
+ # Classical API
146
+
147
+ bicgstabl (A, b, l = 2 ; kwargs... ) = bicgstabl! (zerox (A, b), A, b, l; initial_zero = true , kwargs... )
148
+
149
+ function bicgstabl! (x, A, b, l = 2 ;
150
+ tol = sqrt (eps (real (eltype (b)))),
151
+ max_mv_products:: Int = min (20 , size (A, 1 )),
152
+ log:: Bool = false ,
153
+ verbose:: Bool = false ,
154
+ Pl = Identity (),
155
+ kwargs...
156
+ )
157
+ history = ConvergenceHistory (partial = ! log)
158
+ history[:tol ] = tol
159
+
160
+ # This doesn't yet make sense: the number of iters is smaller.
161
+ log && reserve! (history, :resnorm , max_mv_products)
162
+
163
+ # Actually perform CG
164
+ iterable = bicgstabl_iterator! (x, A, b, l; Pl = Pl, tol = tol, max_mv_products = max_mv_products, kwargs... )
165
+
166
+ if log
167
+ history. mvps = iterable. mv_products
168
+ end
169
+
170
+ for (iteration, item) = enumerate (iterable)
171
+ if log
172
+ nextiter! (history)
173
+ history. mvps = iterable. mv_products
174
+ push! (history, :resnorm , iterable. residual)
175
+ end
176
+ verbose && @printf (" %3d\t %1.2e\n " , iteration, iterable. residual)
177
+ end
178
+
179
+ verbose && println ()
180
+ log && setconv (history, converged (iterable))
181
+ log && shrink! (history)
182
+
183
+ log ? (iterable. x, history) : iterable. x
184
+ end
185
+
186
+ # ################
187
+ # Documentation #
188
+ # ################
189
+
190
+ let
191
+ doc_call = " bicgstab(A, b, l)"
192
+ doc!_call = " bicgstab!(x, A, b, l)"
193
+
194
+ doc_msg = " Solve A*x = b with the BiCGStab(l)"
195
+ doc!_msg = " Overwrite `x`.\n\n " * doc_msg
196
+
197
+ doc_arg = " "
198
+ doc!_arg = """ `x`: initial guess, overwrite final estimation."""
199
+
200
+ doc_version = (doc_call, doc_msg, doc_arg)
201
+ doc!_version = (doc!_call, doc!_msg, doc!_arg)
202
+
203
+ docstring = String[]
204
+
205
+ # Build docs
206
+ for (call, msg, arg) in (doc_version, doc!_version) # Start
207
+ push! (docstring,
208
+ """
209
+ $call
210
+
211
+ $msg
212
+
213
+ # Arguments
214
+
215
+ $arg
216
+
217
+ `A`: linear operator.
218
+
219
+ `b`: right hand side (vector).
220
+
221
+ `l::Int = 2`: Number of GMRES steps.
222
+
223
+ ## Keywords
224
+
225
+ `Pl = Identity()`: left preconditioner of the method.
226
+
227
+ `tol::Real = sqrt(eps(real(eltype(b))))`: tolerance for stopping condition
228
+ `|r_k| / |r_0| ≤ tol`. Note that:
229
+
230
+ 1. The actual residual is never computed during the iterations; only an
231
+ approximate residual is used.
232
+ 2. If a preconditioner is given, the stopping condition is based on the
233
+ *preconditioned residual*.
234
+
235
+ `max_mv_products::Int = min(30, size(A, 1))`: maximum number of matrix
236
+ vector products. For BiCGStab this is a less dubious criterion than maximum
237
+ number of iterations.
238
+
239
+ # Output
240
+
241
+ `x`: approximated solution.
242
+ `residual`: last approximate residual norm
243
+
244
+ # References
245
+ [1] Sleijpen, Gerard LG, and Diederik R. Fokkema. "BiCGstab(l) for
246
+ linear equations involving unsymmetric matrices with complex spectrum."
247
+ Electronic Transactions on Numerical Analysis 1.11 (1993): 2000.
248
+ """
249
+ )
250
+ end
251
+
252
+ @doc docstring[1 ] -> bicgstabl
253
+ @doc docstring[2 ] -> bicgstabl!
254
+ end
0 commit comments