|
1 | 1 | """
|
2 |
| - SimpleGMRES(; restart::Int = 20, blocksize::Int = 0) |
| 2 | + SimpleGMRES(; restart::Bool = true, blocksize::Int = 0, warm_start::Bool = false, |
| 3 | + memory::Int = 20) |
3 | 4 |
|
4 | 5 | A simple GMRES implementation for square non-Hermitian linear systems.
|
5 | 6 |
|
|
71 | 72 | warm_start::Bool
|
72 | 73 | end
|
73 | 74 |
|
| 75 | +""" |
| 76 | + (c, s, ρ) = _sym_givens(a, b) |
| 77 | +
|
| 78 | +Numerically stable symmetric Givens reflection. |
| 79 | +Given `a` and `b` reals, return `(c, s, ρ)` such that |
| 80 | +
|
| 81 | + [ c s ] [ a ] = [ ρ ] |
| 82 | + [ s -c ] [ b ] = [ 0 ]. |
| 83 | +""" |
| 84 | +function _sym_givens(a::T, b::T) where {T <: AbstractFloat} |
| 85 | + # This has taken from Krylov.jl |
| 86 | + if b == 0 |
| 87 | + c = ifelse(a == 0, one(T), sign(a)) # In Julia, sign(0) = 0. |
| 88 | + s = zero(T) |
| 89 | + ρ = abs(a) |
| 90 | + elseif a == 0 |
| 91 | + c = zero(T) |
| 92 | + s = sign(b) |
| 93 | + ρ = abs(b) |
| 94 | + elseif abs(b) > abs(a) |
| 95 | + t = a / b |
| 96 | + s = sign(b) / sqrt(one(T) + t * t) |
| 97 | + c = s * t |
| 98 | + ρ = b / s # Computationally better than ρ = a / c since |c| ≤ |s|. |
| 99 | + else |
| 100 | + t = b / a |
| 101 | + c = sign(a) / sqrt(one(T) + t * t) |
| 102 | + s = c * t |
| 103 | + ρ = a / c # Computationally better than ρ = b / s since |s| ≤ |c| |
| 104 | + end |
| 105 | + return (c, s, ρ) |
| 106 | +end |
| 107 | + |
74 | 108 | _no_preconditioner(::Nothing) = true
|
75 | 109 | _no_preconditioner(::IdentityOperator) = true
|
76 | 110 | _no_preconditioner(::UniformScaling) = true
|
@@ -162,7 +196,7 @@ function SciMLBase.solve!(cache::SimpleGMRESCache{false}, lincache::LinearCache)
|
162 | 196 | xr = restart ? Δx : x
|
163 | 197 |
|
164 | 198 | if β == 0
|
165 |
| - return SciMLBase.build_linear_solution(nothing, x, r₀, nothing; |
| 199 | + return SciMLBase.build_linear_solution(lincache.alg, x, r₀, lincache; |
166 | 200 | retcode = ReturnCode.Success)
|
167 | 201 | end
|
168 | 202 |
|
@@ -251,7 +285,7 @@ function SciMLBase.solve!(cache::SimpleGMRESCache{false}, lincache::LinearCache)
|
251 | 285 | # Compute and apply current Givens reflection Ωₖ.
|
252 | 286 | # [cₖ sₖ] [ r̄ₖ.ₖ ] = [rₖ.ₖ]
|
253 | 287 | # [s̄ₖ -cₖ] [hₖ₊₁.ₖ] [ 0 ]
|
254 |
| - (c[inner_iter], s[inner_iter], R[nr + inner_iter]) = Krylov.sym_givens(R[nr + inner_iter], |
| 288 | + (c[inner_iter], s[inner_iter], R[nr + inner_iter]) = _sym_givens(R[nr + inner_iter], |
255 | 289 | Hbis)
|
256 | 290 |
|
257 | 291 | # Update zₖ = (Qₖ)ᴴβe₁
|
@@ -402,7 +436,7 @@ function SciMLBase.solve!(cache::SimpleGMRESCache{true}, lincache::LinearCache)
|
402 | 436 | xr = restart ? Δx : x
|
403 | 437 |
|
404 | 438 | if β == 0
|
405 |
| - return SciMLBase.build_linear_solution(nothing, x, r₀, nothing; |
| 439 | + return SciMLBase.build_linear_solution(lincache.alg, x, r₀, lincache; |
406 | 440 | retcode = ReturnCode.Success)
|
407 | 441 | end
|
408 | 442 |
|
@@ -484,7 +518,7 @@ function SciMLBase.solve!(cache::SimpleGMRESCache{true}, lincache::LinearCache)
|
484 | 518 | # [cₖ sₖ] [ r̄ₖ.ₖ ] = [rₖ.ₖ]
|
485 | 519 | # [s̄ₖ -cₖ] [hₖ₊₁.ₖ] [ 0 ]
|
486 | 520 | # FIXME: Write inplace kernel
|
487 |
| - __res = Krylov.sym_givens.(R[nr + inner_iter], Hbis) |
| 521 | + __res = _sym_givens.(R[nr + inner_iter], Hbis) |
488 | 522 | foreach(1:bsize) do i
|
489 | 523 | c[inner_iter][i] = __res[i][1]
|
490 | 524 | s[inner_iter][i] = __res[i][2]
|
|
0 commit comments