@@ -7,80 +7,159 @@ function cg!(x, A, b;
7
7
maxiter:: Integer = min (20 , size (A, 1 )),
8
8
plot = false ,
9
9
log:: Bool = false ,
10
+ Pl = Identity (),
10
11
kwargs...
11
12
)
12
13
(plot & ! log) && error (" Can't plot when log keyword is false" )
13
- K = KrylovSubspace (A, length (b), 1 , Vector{Adivtype (A,b)}[])
14
- init! (K, x)
15
14
history = ConvergenceHistory (partial = ! log)
16
15
history[:tol ] = tol
17
- reserve! (history, :resnorm , maxiter)
18
- cg_method! (history, x, K , b; tol = tol, maxiter = maxiter, kwargs... )
19
- (plot || log) && shrink! (history)
16
+ log && reserve! (history, :resnorm , maxiter + 1 )
17
+ cg_method! (history, x, A , b, Pl ; tol = tol, log = log , maxiter = maxiter, kwargs... )
18
+ log && shrink! (history)
20
19
plot && showplot (history)
21
20
log ? (x, history) : x
22
21
end
23
22
24
- function cg_method! (log:: ConvergenceHistory , x, K, b;
25
- Pl = 1 ,
23
+ function cg_method! (history:: ConvergenceHistory , x, A, b, Pl;
26
24
tol = sqrt (eps (real (eltype (b)))),
27
- maxiter:: Integer = min (20 , size (K. A, 1 )),
28
- verbose:: Bool = false
25
+ maxiter:: Integer = min (20 , size (A, 1 )),
26
+ verbose:: Bool = false ,
27
+ log = false
29
28
)
29
+ # Preconditioned CG
30
30
T = eltype (b)
31
- n = size (K . A, 1 )
31
+ n = size (A, 1 )
32
32
33
33
# Initial residual vector
34
34
r = copy (b)
35
- @blas! r -= one (T) * nextvec (K)
36
- c = zeros (T, n)
35
+ c = A * x
36
+ @blas! r -= one (T) * c
37
37
u = zeros (T, n)
38
38
ρ = one (T)
39
-
40
- iter = 0
41
39
42
- last_residual = norm (r)
40
+ if log
41
+ history. mvps += 1
42
+ end
43
+
44
+ iter = 1
43
45
44
46
# Here you could save one inner product if norm(r) is used rather than norm(b)
45
47
reltol = norm (b) * tol
48
+ last_residual = zero (T)
46
49
47
- while last_residual > reltol && iter < maxiter
48
- nextiter! (log, mvps = 1 )
50
+ while true
51
+
52
+ last_residual = norm (r)
53
+
54
+ verbose && @printf (" %3d\t %1.2e\n " , iter, last_residual)
55
+
56
+ if last_residual ≤ reltol || iter > maxiter
57
+ break
58
+ end
59
+
60
+ # Log progress
61
+ if log
62
+ nextiter! (history, mvps = 1 )
63
+ push! (history, :resnorm , last_residual)
64
+ end
49
65
50
66
# Preconditioner: c = Pl \ r
51
67
solve! (c, Pl, r)
52
68
53
69
ρ_prev = ρ
54
70
ρ = dot (c, r)
55
- β = - ρ / ρ_prev
71
+ β = ρ / ρ_prev
56
72
57
- # u := r - βu (almost an axpy)
58
- @blas! u *= - β
73
+ # u := c + βu (almost an axpy)
74
+ @blas! u *= β
59
75
@blas! u += one (T) * c
60
76
61
77
# c = A * u
62
- append! (K, u)
63
- nextvec! (c, K)
78
+ A_mul_B! (c, A, u)
64
79
α = ρ / dot (u, c)
65
80
66
81
# Improve solution and residual
67
82
@blas! x += α * u
68
83
@blas! r -= α * c
69
84
70
85
iter += 1
71
- last_residual = norm (r)
86
+ end
87
+
88
+ verbose && @printf (" \n " )
89
+ log && setconv (history, last_residual < reltol)
90
+
91
+ x
92
+ end
93
+
94
+ function cg_method! (history:: ConvergenceHistory , x, A, b, Pl:: Identity ;
95
+ tol = sqrt (eps (real (eltype (b)))),
96
+ maxiter:: Integer = min (20 , size (A, 1 )),
97
+ verbose:: Bool = false ,
98
+ log = false
99
+ )
100
+ # Unpreconditioned CG
101
+ T = eltype (b)
102
+ n = size (A, 1 )
103
+
104
+ # Initial residual vector
105
+ r = copy (b)
106
+ c = A * x
107
+ @blas! r -= one (T) * c
108
+ u = zeros (T, n)
109
+ ρ = one (T)
110
+
111
+ if log
112
+ history. mvps += 1
113
+ end
114
+
115
+ iter = 1
116
+
117
+ reltol = norm (b) * tol
118
+ last_residual = zero (T)
119
+
120
+ while true
121
+
122
+ ρ_prev = ρ
123
+ ρ = dot (r, r)
124
+ β = ρ / ρ_prev
125
+
126
+ last_residual = sqrt (ρ)
72
127
73
128
# Log progress
74
- push! (log, :resnorm , last_residual)
129
+ if log
130
+ nextiter! (history, mvps = 1 )
131
+ push! (history, :resnorm , last_residual)
132
+ end
133
+
75
134
verbose && @printf (" %3d\t %1.2e\n " , iter, last_residual)
135
+
136
+ # Stopping condition
137
+ if last_residual ≤ reltol || iter > maxiter
138
+ break
139
+ end
140
+
141
+ # u := r + βu (almost an axpy)
142
+ @blas! u *= β
143
+ @blas! u += one (T) * r
144
+
145
+ # c = A * u
146
+ A_mul_B! (c, A, u)
147
+ α = ρ / dot (u, c)
148
+
149
+ # Improve solution and residual
150
+ @blas! x += α * u
151
+ @blas! r -= α * c
152
+
153
+ iter += 1
76
154
end
77
155
78
156
verbose && @printf (" \n " )
79
- setconv (log , last_residual < reltol)
157
+ log && setconv (history , last_residual < reltol)
80
158
81
159
x
82
160
end
83
161
162
+
84
163
# ################
85
164
# Documentation #
86
165
# ################
126
205
127
206
## Keywords
128
207
129
- `Pl = 1 `: left preconditioner of the method.
208
+ `Pl = Identity() `: left preconditioner of the method.
130
209
131
210
`tol::Real = size(A,2)*eps()`: stopping tolerance.
132
211
0 commit comments