@@ -8,7 +8,7 @@ mutable struct CGIterable{matT, solT, vecT, numT <: Real}
8
8
r:: vecT
9
9
c:: vecT
10
10
u:: vecT
11
- reltol :: numT
11
+ tol :: numT
12
12
residual:: numT
13
13
prev_residual:: numT
14
14
maxiter:: Int
@@ -22,14 +22,14 @@ mutable struct PCGIterable{precT, matT, solT, vecT, numT <: Real, paramT <: Numb
22
22
r:: vecT
23
23
c:: vecT
24
24
u:: vecT
25
- reltol :: numT
25
+ tol :: numT
26
26
residual:: numT
27
27
ρ:: paramT
28
28
maxiter:: Int
29
29
mv_products:: Int
30
30
end
31
31
32
- @inline converged (it:: Union{CGIterable, PCGIterable} ) = it. residual ≤ it. reltol
32
+ @inline converged (it:: Union{CGIterable, PCGIterable} ) = it. residual ≤ it. tol
33
33
34
34
@inline start (it:: Union{CGIterable, PCGIterable} ) = 0
35
35
41
41
# ##############
42
42
43
43
function iterate (it:: CGIterable , iteration:: Int = start (it))
44
- if done (it, iteration) return nothing end
44
+ # Check for termination first
45
+ if done (it, iteration)
46
+ return nothing
47
+ end
45
48
46
49
# u := r + βu (almost an axpy)
47
50
β = it. residual^ 2 / it. prev_residual^ 2
@@ -72,6 +75,7 @@ function iterate(it::PCGIterable, iteration::Int=start(it))
72
75
return nothing
73
76
end
74
77
78
+ # Apply left preconditioner
75
79
ldiv! (it. c, it. Pl, it. r)
76
80
77
81
ρ_prev = it. ρ
@@ -114,40 +118,44 @@ struct CGStateVariables{T,Tx<:AbstractArray{T}}
114
118
end
115
119
116
120
function cg_iterator! (x, A, b, Pl = Identity ();
117
- tol = sqrt (eps (real (eltype (b)))),
118
- maxiter:: Int = size (A, 2 ),
119
- statevars:: CGStateVariables = CGStateVariables (zero (x), similar (x), similar (x)),
120
- initially_zero:: Bool = false
121
- )
121
+ abstol:: Real = zero (real (eltype (b))),
122
+ reltol:: Real = sqrt (eps (real (eltype (b)))),
123
+ tol = nothing , # TODO : Deprecations introduced in v0.8
124
+ maxiter:: Int = size (A, 2 ),
125
+ statevars:: CGStateVariables = CGStateVariables (zero (x), similar (x), similar (x)),
126
+ initially_zero:: Bool = false )
122
127
u = statevars. u
123
128
r = statevars. r
124
129
c = statevars. c
125
130
u .= zero (eltype (x))
126
131
copyto! (r, b)
127
132
133
+ # TODO : Deprecations introduced in v0.8
134
+ if tol != = nothing
135
+ Base. depwarn (" The keyword argument `tol` is deprecated, use `reltol` instead." , :cg_iterator! )
136
+ reltol = tol
137
+ end
138
+
128
139
# Compute r with an MV-product or not.
129
140
if initially_zero
130
141
mv_products = 0
131
- c = similar (x)
132
- residual = norm (b)
133
- reltol = residual * tol # Save one dot product
134
142
else
135
143
mv_products = 1
136
144
mul! (c, A, x)
137
145
r .- = c
138
- residual = norm (r)
139
- reltol = norm (b) * tol
140
146
end
147
+ residual = norm (r)
148
+ tolerance = max (reltol * residual, abstol)
141
149
142
150
# Return the iterable
143
151
if isa (Pl, Identity)
144
152
return CGIterable (A, x, r, c, u,
145
- reltol , residual, one (residual),
153
+ tolerance , residual, one (residual),
146
154
maxiter, mv_products
147
155
)
148
156
else
149
157
return PCGIterable (Pl, A, x, r, c, u,
150
- reltol , residual, one (eltype (x)),
158
+ tolerance , residual, one (eltype (x)),
151
159
maxiter, mv_products
152
160
)
153
161
end
@@ -177,7 +185,11 @@ cg(A, b; kwargs...) = cg!(zerox(A, b), A, b; initially_zero = true, kwargs...)
177
185
residual vector;
178
186
- `Pl = Identity()`: left preconditioner of the method. Should be symmetric,
179
187
positive-definite like `A`;
180
- - `tol::Real = sqrt(eps(real(eltype(b))))`: tolerance for stopping condition `|r_k| / |r_0| ≤ tol`;
188
+ - `abstol::Real = zero(real(eltype(b)))`,
189
+ `reltol::Real = sqrt(eps(real(eltype(b))))`: absolute and relative
190
+ tolerance for the stopping condition
191
+ `|r_k| / |r_0| ≤ max(reltol * resnorm, abstol)`, where `r_k = A * x_k - b`
192
+ is the residual in the `k`th iteration;
181
193
- `maxiter::Int = size(A,2)`: maximum number of iterations;
182
194
- `verbose::Bool = false`: print method information;
183
195
- `log::Bool = false`: keep track of the residual norm in each iteration.
@@ -199,20 +211,29 @@ cg(A, b; kwargs...) = cg!(zerox(A, b), A, b; initially_zero = true, kwargs...)
199
211
- `:resnom` => `::Vector`: residual norm at each iteration.
200
212
"""
201
213
function cg! (x, A, b;
202
- tol = sqrt (eps (real (eltype (b)))),
203
- maxiter:: Int = size (A, 2 ),
204
- log:: Bool = false ,
205
- statevars:: CGStateVariables = CGStateVariables (zero (x), similar (x), similar (x)),
206
- verbose:: Bool = false ,
207
- Pl = Identity (),
208
- kwargs...
209
- )
214
+ abstol:: Real = zero (real (eltype (b))),
215
+ reltol:: Real = sqrt (eps (real (eltype (b)))),
216
+ tol = nothing , # TODO : Deprecations introduced in v0.8
217
+ maxiter:: Int = size (A, 2 ),
218
+ log:: Bool = false ,
219
+ statevars:: CGStateVariables = CGStateVariables (zero (x), similar (x), similar (x)),
220
+ verbose:: Bool = false ,
221
+ Pl = Identity (),
222
+ kwargs... )
210
223
history = ConvergenceHistory (partial = ! log)
211
- history[:tol ] = tol
224
+ history[:abstol ] = abstol
225
+ history[:reltol ] = reltol
212
226
log && reserve! (history, :resnorm , maxiter + 1 )
213
227
228
+ # TODO : Deprecations introduced in v0.8
229
+ if tol != = nothing
230
+ Base. depwarn (" The keyword argument `tol` is deprecated, use `reltol` instead." , :cg! )
231
+ reltol = tol
232
+ end
233
+
214
234
# Actually perform CG
215
- iterable = cg_iterator! (x, A, b, Pl; tol = tol, maxiter = maxiter, statevars = statevars, kwargs... )
235
+ iterable = cg_iterator! (x, A, b, Pl; abstol = abstol, reltol = reltol, maxiter = maxiter,
236
+ statevars = statevars, kwargs... )
216
237
if log
217
238
history. mvps = iterable. mv_products
218
239
end
0 commit comments