Skip to content

Commit bc74893

Browse files
committed
Use a local copy of sym_givens
1 parent 07fc3fa commit bc74893

File tree

1 file changed

+39
-5
lines changed

1 file changed

+39
-5
lines changed

src/simplegmres.jl

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
"""
2-
SimpleGMRES(; restart::Int = 20, blocksize::Int = 0)
2+
SimpleGMRES(; restart::Bool = true, blocksize::Int = 0, warm_start::Bool = false,
3+
memory::Int = 20)
34
45
A simple GMRES implementation for square non-Hermitian linear systems.
56
@@ -71,6 +72,39 @@ end
7172
warm_start::Bool
7273
end
7374

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+
74108
_no_preconditioner(::Nothing) = true
75109
_no_preconditioner(::IdentityOperator) = true
76110
_no_preconditioner(::UniformScaling) = true
@@ -162,7 +196,7 @@ function SciMLBase.solve!(cache::SimpleGMRESCache{false}, lincache::LinearCache)
162196
xr = restart ? Δx : x
163197

164198
if β == 0
165-
return SciMLBase.build_linear_solution(nothing, x, r₀, nothing;
199+
return SciMLBase.build_linear_solution(lincache.alg, x, r₀, lincache;
166200
retcode = ReturnCode.Success)
167201
end
168202

@@ -251,7 +285,7 @@ function SciMLBase.solve!(cache::SimpleGMRESCache{false}, lincache::LinearCache)
251285
# Compute and apply current Givens reflection Ωₖ.
252286
# [cₖ sₖ] [ r̄ₖ.ₖ ] = [rₖ.ₖ]
253287
# [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],
255289
Hbis)
256290

257291
# Update zₖ = (Qₖ)ᴴβe₁
@@ -402,7 +436,7 @@ function SciMLBase.solve!(cache::SimpleGMRESCache{true}, lincache::LinearCache)
402436
xr = restart ? Δx : x
403437

404438
if β == 0
405-
return SciMLBase.build_linear_solution(nothing, x, r₀, nothing;
439+
return SciMLBase.build_linear_solution(lincache.alg, x, r₀, lincache;
406440
retcode = ReturnCode.Success)
407441
end
408442

@@ -484,7 +518,7 @@ function SciMLBase.solve!(cache::SimpleGMRESCache{true}, lincache::LinearCache)
484518
# [cₖ sₖ] [ r̄ₖ.ₖ ] = [rₖ.ₖ]
485519
# [s̄ₖ -cₖ] [hₖ₊₁.ₖ] [ 0 ]
486520
# FIXME: Write inplace kernel
487-
__res = Krylov.sym_givens.(R[nr + inner_iter], Hbis)
521+
__res = _sym_givens.(R[nr + inner_iter], Hbis)
488522
foreach(1:bsize) do i
489523
c[inner_iter][i] = __res[i][1]
490524
s[inner_iter][i] = __res[i][2]

0 commit comments

Comments
 (0)