@@ -77,7 +77,6 @@ function inexact_gmres!(x, A, b::AbstractVector{T};
77
77
residual_norm= β, maxiter, tol, s, residual= r,
78
78
restart_history, stage= :restart , krylovdim, k, Axinfo)
79
79
80
-
81
80
while (n_iter < maxiter && k < m) # Arnoldi loop
82
81
n_iter += 1
83
82
@@ -145,263 +144,3 @@ end
145
144
function inexact_gmres (A, b; kwargs... )
146
145
inexact_gmres! (zeros_like (b, eltype (b), size (A, 2 )), A, b; kwargs... )
147
146
end
148
-
149
-
150
-
151
-
152
-
153
-
154
-
155
-
156
-
157
-
158
- function gmres (operators:: Function , b:: AbstractVector{T} ;
159
- x₀= nothing ,
160
- maxiter= min (100 , size (operators (0 ), 1 )),
161
- restart= min (20 , size (operators (0 ), 1 )),
162
- tol= 1e-6 , s_guess= 0.8 , verbose= 1 , debug= false ) where {T}
163
- # pass s/3m 1/\|r_tilde\| tol to operators()
164
- normb = norm (b)
165
- b = b ./ normb
166
- tol = tol / normb
167
- if tol < 0.5 * eps (T)
168
- # throw a warning
169
- @warn " The effective tolerance is smaller than half of the machine epsilon, the requested accuracy may not be achieved."
170
- end
171
-
172
- n_size = length (b)
173
-
174
- # counters
175
- numrestarts:: Int64 = 0
176
- restart_inds = Int64[]
177
- MvTime = Float64[]
178
-
179
- # initialization: Arnoldi basis and Hessenberg matrix
180
- V = zeros (n_size, restart + 1 )
181
- H = zeros (restart + 1 , restart)
182
-
183
- # residual history
184
- residuals = zeros (maxiter)
185
- denominatorvec = zeros (restart)
186
- denominator2 = 1.0
187
- # record min singular values
188
- minsvdvals = zeros (maxiter)
189
-
190
- # solution history
191
- if debug
192
- X = zeros (n_size, maxiter)
193
- end
194
-
195
- # if x0 is zero, set r0 = b
196
- x0iszero = isnothing (x₀)
197
- if x0iszero
198
- β₀ = 1.0
199
- V[:, 1 ] = b # / β₀
200
- tol_new = tol / 2
201
- lm = s_guess / restart / 2 * tol
202
- else
203
- # assert x₀ is a vector of the right size
204
- @assert length (x₀) == n_size
205
- x₀ ./= normb
206
- x0iszero = false
207
- tol_new = tol / 3
208
- A0_tol = tol / 3
209
- lm = s_guess / restart / 3 * tol
210
- push! (MvTime, @elapsed r₀ = operators (A0_tol) * x₀)
211
- r₀ = b - r₀
212
- β₀ = norm (r₀)
213
- V[:, 1 ] = r₀ / β₀
214
- end
215
-
216
- Ai_tol = lm / β₀
217
- i = 0 # iteration counter, set to 0 when restarted
218
- for j = 1 : maxiter
219
- i += 1
220
-
221
- # Arnoldi iteration using MGS
222
- push! (MvTime, @elapsed w = operators (Ai_tol) * V[:, i])
223
- for j = 1 : i
224
- H[j, i] = dot (V[:, j], w)
225
- w .- = H[j, i] * V[:, j]
226
- end
227
- H[i+ 1 , i] = norm (w)
228
- V[:, i+ 1 ] = w / H[i+ 1 , i]
229
-
230
- # compute the min singular value of the upper Hessenberg matrix
231
- minsvdvals[j] = svdvals (H[1 : i+ 1 , 1 : i])[end ]
232
-
233
- # update residual history
234
- if i == 1
235
- denominatorvec[1 ] = conj (- H[1 , 1 ] / H[2 , 1 ])
236
- else
237
- denominatorvec[i] = conj (- (H[1 , i] + dot (denominatorvec[1 : i- 1 ], H[2 : i, i])) / H[i+ 1 , i])
238
- end
239
- denominator2 += abs2 (denominatorvec[i])
240
- residuals[j] = β₀ / sqrt (denominator2)
241
- Ai_tol = lm / residuals[j]
242
-
243
- (verbose > 0 ) && println (" restart = " , numrestarts + 1 , " , iteration = " , i, " , res = " , residuals[j]* normb, " \n " )
244
-
245
- # when converged without updating the s_guess, restart once
246
- converged = residuals[j] < tol_new
247
- happy = converged && ((numrestarts > 0 ) || (s_guess <= minsvdvals[j]))
248
- needrestart = (i == restart) || (converged && ! happy) # equal to converged && (numrestarts == 0) && (s_guess > minsvdvals[j])
249
- reachmaxiter = (j == maxiter)
250
- exitloop = (happy || reachmaxiter)
251
-
252
- solvels = (exitloop || needrestart || debug)
253
- if solvels
254
- # solve the Hessenberg least squares problem
255
- rhs = (UpperTriangular (H[2 : i+ 1 , 1 : i]) \ denominatorvec[1 : i]) * (- β₀ / denominator2)
256
- if x0iszero
257
- xᵢ = V[:, 1 : i] * rhs
258
- else
259
- xᵢ = x₀ + V[:, 1 : i] * rhs
260
- end
261
-
262
- debug && (X[:, j] = xᵢ)
263
-
264
- if exitloop
265
- if debug
266
- return (; x= X[:, 1 : j]. * normb, residuals= residuals[1 : j]. * normb, MvTime= MvTime, restart_inds= restart_inds, minsvdvals= minsvdvals[1 : j])
267
- else
268
- return (; x= xᵢ.* normb, residuals= residuals[1 : j]. * normb, MvTime= MvTime, restart_inds= restart_inds)
269
- end
270
- end
271
-
272
- if needrestart
273
- i = 0
274
- x0iszero = false
275
- # whenever restart, update the guess of the smallest singular value
276
- min_s = minimum (minsvdvals[1 : j])
277
- if s_guess > min_s
278
- verbose > 0 && println (" current s_guess = " , s_guess, " > minsvdval = " , min_s, " , restart with s_guess = minsvdval" )
279
- else
280
- verbose > 0 && println (" current s_guess = " , s_guess, " ≤ minsvdval = " , min_s, " , restart with s_guess = minsvdval" )
281
- end
282
- s_guess = min_s
283
- lm = s_guess / restart / 3 * tol
284
- tol_new = tol / 3
285
- A0_tol = tol / 3
286
-
287
- x₀ = xᵢ
288
- push! (MvTime, @elapsed r₀ = operators (A0_tol) * x₀)
289
- r₀ = b - r₀
290
- β₀ = norm (r₀)
291
- V[:, 1 ] = r₀ / β₀
292
- numrestarts += 1
293
- denominatorvec = zeros (maxiter)
294
- denominator2 = 1.0
295
- push! (restart_inds, j)
296
- (verbose > - 1 ) && println (" restarting: " , " iteration = " , j, " , r₀ = " , β₀, " \n " )
297
- Ai_tol = lm / β₀
298
- end
299
- end
300
- end
301
- end
302
-
303
-
304
- function gmres (operator:: LinearMap{T} , b:: AbstractVector{T} ;
305
- x₀ = nothing ,
306
- maxiter= min (100 , size (operator, 1 )),
307
- restart= min (20 , size (operator, 1 )),
308
- tol= 1e-6 , verbose= 0 , debug= false ) where {T}
309
-
310
- n_size = length (b)
311
-
312
- # counters
313
- numrestarts:: Int64 = 0
314
- restart_inds = Int64[]
315
- MvTime = Float64[]
316
-
317
- # initialization: Arnoldi basis and Hessenberg matrix
318
- V = zeros (n_size, restart + 1 )
319
- H = zeros (restart + 1 , restart)
320
-
321
- # residual history
322
- residuals = zeros (maxiter)
323
- denominatorvec = zeros (restart)
324
- denominator2 = 1.0
325
-
326
- # solution history
327
- if debug
328
- X = zeros (n_size, maxiter)
329
- end
330
-
331
- # if x0 is zero, set r0 = b
332
- if isnothing (x₀)
333
- β₀ = norm (b)
334
- V[:, 1 ] = b / β₀
335
- else
336
- # assert x₀ is a vector of the right size
337
- @assert length (x₀) == n_size
338
- push! (MvTime, @elapsed r₀ = operator * x₀)
339
- r₀ = b - r₀
340
- β₀ = norm (r₀)
341
- V[:, 1 ] = r₀ / β₀
342
- end
343
-
344
- i = 0 # iteration counter, set to 0 when restarted
345
- for j = 1 : maxiter
346
- i += 1
347
- # Arnoldi iteration using MGS
348
- push! (MvTime, @elapsed w = operator * V[:, i])
349
- for j = 1 : i
350
- H[j, i] = dot (V[:, j], w)
351
- w .- = H[j, i] * V[:, j]
352
- end
353
- H[i+ 1 , i] = norm (w)
354
- V[:, i+ 1 ] = w / H[i+ 1 , i]
355
-
356
- # update residual history
357
- if i == 1
358
- denominatorvec[1 ] = conj (- H[1 , 1 ] / H[2 , 1 ])
359
- else
360
- denominatorvec[i] = conj (- (H[1 , i] + dot (denominatorvec[1 : i- 1 ], H[2 : i, i])) / H[i+ 1 , i])
361
- end
362
- denominator2 += abs2 (denominatorvec[i])
363
- residuals[j] = β₀ / sqrt (denominator2)
364
-
365
- (verbose > 0 ) && println (" restart = " , numrestarts + 1 , " , iteration = " , i, " , res = " , residuals[j], " \n " )
366
-
367
- happy = residuals[j] < tol
368
- needrestart = (i == restart)
369
- reachmaxiter = (j == maxiter)
370
- exitloop = (happy || reachmaxiter)
371
-
372
- solvels = (exitloop || needrestart || debug)
373
- if solvels
374
- # solve the Hessenberg least squares problem
375
- rhs = (UpperTriangular (H[2 : i+ 1 , 1 : i]) \ denominatorvec[1 : i]) * (- β₀ / denominator2)
376
- if isnothing (x₀)
377
- xᵢ = V[:, 1 : i] * rhs
378
- else
379
- xᵢ = x₀ + V[:, 1 : i] * rhs
380
- end
381
-
382
- debug && (X[:, j] = xᵢ)
383
-
384
- if exitloop
385
- if debug
386
- return (; x= X[:, 1 : j], residuals= residuals[1 : j], MvTime= MvTime, restart_inds= restart_inds)
387
- else
388
- return (; x= xᵢ, residuals= residuals[1 : j], MvTime= MvTime, restart_inds= restart_inds)
389
- end
390
- end
391
-
392
- if needrestart
393
- i = 0
394
- x₀ = xᵢ
395
- push! (MvTime, @elapsed r₀ = operator * x₀)
396
- r₀ = b - r₀
397
- β₀ = norm (r₀)
398
- V[:, 1 ] = r₀ / β₀
399
- numrestarts += 1
400
- denominatorvec = zeros (maxiter)
401
- denominator2 = 1.0
402
- push! (restart_inds, j)
403
- (verbose > 0 ) && println (" restarting: " , " iteration = " , j, " , r₀ = " , β₀, " \n " )
404
- end
405
- end
406
- end
407
- end
0 commit comments