1
1
export cg, cg!
2
2
3
- # ###################
4
- # API method calls #
5
- # ###################
6
-
7
- cg (A, b; kwargs... ) = cg! (zerox (A,b), A, b; kwargs... )
3
+ cg (A, b; kwargs... ) = cg! (zerox (A, b), A, b; kwargs... )
8
4
9
5
function cg! (x, A, b;
10
- tol:: Real = size (A,2 )* eps (), maxiter:: Integer = size (A,2 ),
11
- plot= false , log:: Bool = false , kwargs...
12
- )
6
+ tol = sqrt (eps (real (eltype (b)))),
7
+ maxiter:: Integer = min (20 , size (A, 1 )),
8
+ plot = false ,
9
+ log:: Bool = false ,
10
+ kwargs...
11
+ )
13
12
(plot & ! log) && error (" Can't plot when log keyword is false" )
14
13
K = KrylovSubspace (A, length (b), 1 , Vector{Adivtype (A,b)}[])
15
14
init! (K, x)
16
- history = ConvergenceHistory (partial= ! log)
15
+ history = ConvergenceHistory (partial = ! log)
17
16
history[:tol ] = tol
18
- if all (el-> el== 0 , b)
19
- fill! (x, zero (eltype (x)))
20
- return log ? (x, history) : x
21
- end
22
- reserve! (history,:resnorm , maxiter)
23
- cg_method! (history, x, K, b; tol= tol, maxiter= maxiter, kwargs... )
17
+ reserve! (history, :resnorm , maxiter)
18
+ cg_method! (history, x, K, b; tol = tol, maxiter = maxiter, kwargs... )
24
19
(plot || log) && shrink! (history)
25
20
plot && showplot (history)
26
21
log ? (x, history) : x
27
22
end
28
23
29
- # ########################
30
- # Method Implementation #
31
- # ########################
32
-
33
24
function cg_method! (log:: ConvergenceHistory , x, K, b;
34
- Pl= 1 ,tol:: Real = size (K. A,2 )* eps (),maxiter:: Integer = size (K. A,2 ), verbose:: Bool = false
35
- )
36
- verbose && @printf (" === cg ===\n %4s\t %7s\n " ," iter" ," resnorm" )
37
- tol = tol * norm (b)
38
- r = b - nextvec (K)
39
- q = zeros (r)
40
- z = solve (Pl,r)
41
- p = copy (z)
42
- γ = dot (r, z)
43
- for iter= 1 : maxiter
44
- nextiter! (log, mvps= 1 )
45
- append! (K, p)
46
- nextvec! (q, K)
47
- α = γ/ dot (p, q)
48
- # α>=0 || throw(PosSemidefException("α=$α"))
49
- @blas! x += α* p
50
- @blas! r += - α* q
51
- resnorm = norm (r)
52
- push! (log,:resnorm ,resnorm)
53
- verbose && @printf (" %3d\t %1.2e\n " ,iter,resnorm)
54
- resnorm < tol && break
55
- solve! (z,Pl,r)
56
- oldγ = γ
57
- γ = dot (r, z)
58
- β = γ/ oldγ
59
- @blas! p *= β
60
- @blas! p += z
25
+ Pl = 1 ,
26
+ tol = sqrt (eps (real (eltype (b)))),
27
+ maxiter:: Integer = min (20 , size (K. A, 1 )),
28
+ verbose:: Bool = false
29
+ )
30
+ T = eltype (b)
31
+ n = size (K. A, 1 )
32
+
33
+ # Initial residual vector
34
+ r = copy (b)
35
+ @blas! r -= one (T) * nextvec (K)
36
+ c = zeros (T, n)
37
+ u = zeros (T, n)
38
+ ρ = one (T)
39
+
40
+ iter = 0
41
+
42
+ last_residual = norm (r)
43
+
44
+ # Here you could save one inner product if norm(r) is used rather than norm(b)
45
+ reltol = norm (b) * tol
46
+
47
+ while last_residual > reltol && iter < maxiter
48
+ nextiter! (log, mvps = 1 )
49
+
50
+ # Preconditioner: c = Pl \ r
51
+ solve! (c, Pl, r)
52
+
53
+ ρ_prev = ρ
54
+ ρ = dot (c, r)
55
+ β = - ρ / ρ_prev
56
+
57
+ # u := r - βu (almost an axpy)
58
+ @blas! u *= - β
59
+ @blas! u += one (T) * c
60
+
61
+ # c = A * u
62
+ append! (K, u)
63
+ nextvec! (c, K)
64
+ α = ρ / dot (u, c)
65
+
66
+ # Improve solution and residual
67
+ @blas! x += α * u
68
+ @blas! r -= α * c
69
+
70
+ iter += 1
71
+ last_residual = norm (r)
72
+
73
+ # Log progress
74
+ push! (log, :resnorm , last_residual)
75
+ verbose && @printf (" %3d\t %1.2e\n " , iter, last_residual)
61
76
end
77
+
62
78
verbose && @printf (" \n " )
63
- setconv (log, 0 <= norm (r)< tol)
79
+ setconv (log, last_residual < reltol)
80
+
64
81
x
65
82
end
66
83
145
162
146
163
@doc docstring[1 ] -> cg
147
164
@doc docstring[2 ] -> cg!
148
- end
165
+ end
0 commit comments