Grid 0.7.0
BiCGSTAB.h
Go to the documentation of this file.
1/*************************************************************************************
2
3Grid physics library, www.github.com/paboyle/Grid
4
5Source file: ./lib/algorithms/iterative/BiCGSTAB.h
6
7Copyright (C) 2015
8
9Author: Azusa Yamaguchi <ayamaguc@staffmail.ed.ac.uk>
10Author: Peter Boyle <paboyle@ph.ed.ac.uk>
11Author: paboyle <paboyle@ph.ed.ac.uk>
12Author: juettner <juettner@soton.ac.uk>
13Author: David Murphy <djmurphy@mit.edu>
14
15This program is free software; you can redistribute it and/or modify
16it under the terms of the GNU General Public License as published by
17the Free Software Foundation; either version 2 of the License, or
18(at your option) any later version.
19
20This program is distributed in the hope that it will be useful,
21but WITHOUT ANY WARRANTY; without even the implied warranty of
22MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23GNU General Public License for more details.
24
25You should have received a copy of the GNU General Public License along
26with this program; if not, write to the Free Software Foundation, Inc.,
2751 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
28
29See the full license in the file "LICENSE" in the top level distribution
30directory
31*************************************************************************************/
32/* END LEGAL */
33
34#ifndef GRID_BICGSTAB_H
35#define GRID_BICGSTAB_H
36
38
40// Base classes for iterative processes based on operators
41// single input vec, single output vec.
43
44template <class Field>
45class BiCGSTAB : public OperatorFunction<Field>
46{
47 public:
48 using OperatorFunction<Field>::operator();
49
50 bool ErrorOnNoConverge; // throw an assert when the CG fails to converge.
51 // Defaults true.
54 Integer IterationsToComplete; //Number of iterations the CG took to finish. Filled in upon completion
55
56 BiCGSTAB(RealD tol, Integer maxit, bool err_on_no_conv = true) :
57 Tolerance(tol), MaxIterations(maxit), ErrorOnNoConverge(err_on_no_conv){};
58
59 void operator()(LinearOperatorBase<Field>& Linop, const Field& src, Field& psi)
60 {
61 psi.Checkerboard() = src.Checkerboard();
62 conformable(psi, src);
63
64 RealD cp(0), rho(1), rho_prev(0), alpha(1), beta(0), omega(1);
65 RealD a(0), bo(0), b(0), ssq(0);
66
67 Field p(src);
68 Field r(src);
69 Field rhat(src);
70 Field v(src);
71 Field s(src);
72 Field t(src);
73 Field h(src);
74
75 v = Zero();
76 p = Zero();
77
78 // Initial residual computation & set up
79 RealD guess = norm2(psi);
80 assert(std::isnan(guess) == 0);
81
82 Linop.Op(psi, v);
83 b = norm2(v);
84
85 r = src - v;
86 rhat = r;
87 a = norm2(r);
88 ssq = norm2(src);
89
90 std::cout << GridLogIterative << std::setprecision(8) << "BiCGSTAB: guess " << guess << std::endl;
91 std::cout << GridLogIterative << std::setprecision(8) << "BiCGSTAB: src " << ssq << std::endl;
92 std::cout << GridLogIterative << std::setprecision(8) << "BiCGSTAB: mp " << b << std::endl;
93 std::cout << GridLogIterative << std::setprecision(8) << "BiCGSTAB: r " << a << std::endl;
94
95 RealD rsq = Tolerance * Tolerance * ssq;
96
97 // Check if guess is really REALLY good :)
98 if(a <= rsq){ return; }
99
100 std::cout << GridLogIterative << std::setprecision(8) << "BiCGSTAB: k=0 residual " << a << " target " << rsq << std::endl;
101
102 GridStopWatch LinalgTimer;
103 GridStopWatch InnerTimer;
104 GridStopWatch AxpyNormTimer;
105 GridStopWatch LinearCombTimer;
106 GridStopWatch MatrixTimer;
107 GridStopWatch SolverTimer;
108
109 SolverTimer.Start();
110 int k;
111 for (k = 1; k <= MaxIterations; k++)
112 {
113 rho_prev = rho;
114
115 LinalgTimer.Start();
116 InnerTimer.Start();
117 ComplexD Crho = innerProduct(rhat,r);
118 InnerTimer.Stop();
119 rho = Crho.real();
120
121 beta = (rho / rho_prev) * (alpha / omega);
122
123 LinearCombTimer.Start();
124 bo = beta * omega;
125 {
126 autoView( p_v , p, AcceleratorWrite);
127 autoView( r_v , r, AcceleratorRead);
128 autoView( v_v , v, AcceleratorRead);
129 accelerator_for(ss, p_v.size(), Field::vector_object::Nsimd(),{
130 coalescedWrite(p_v[ss], beta*p_v(ss) - bo*v_v(ss) + r_v(ss));
131 });
132 }
133 LinearCombTimer.Stop();
134 LinalgTimer.Stop();
135
136 MatrixTimer.Start();
137 Linop.Op(p,v);
138 MatrixTimer.Stop();
139
140 LinalgTimer.Start();
141 InnerTimer.Start();
142 ComplexD Calpha = innerProduct(rhat,v);
143 InnerTimer.Stop();
144 alpha = rho / Calpha.real();
145
146 LinearCombTimer.Start();
147 {
148 autoView( p_v , p, AcceleratorRead);
149 autoView( r_v , r, AcceleratorRead);
150 autoView( v_v , v, AcceleratorRead);
151 autoView( psi_v,psi, AcceleratorRead);
152 autoView( h_v , h, AcceleratorWrite);
153 autoView( s_v , s, AcceleratorWrite);
154 accelerator_for(ss, h_v.size(), Field::vector_object::Nsimd(),{
155 coalescedWrite(h_v[ss], alpha*p_v(ss) + psi_v(ss));
156 });
157 accelerator_for(ss, s_v.size(), Field::vector_object::Nsimd(),{
158 coalescedWrite(s_v[ss], -alpha*v_v(ss) + r_v(ss));
159 });
160 }
161 LinearCombTimer.Stop();
162 LinalgTimer.Stop();
163
164 MatrixTimer.Start();
165 Linop.Op(s,t);
166 MatrixTimer.Stop();
167
168 LinalgTimer.Start();
169 InnerTimer.Start();
170 ComplexD Comega = innerProduct(t,s);
171 InnerTimer.Stop();
172 omega = Comega.real() / norm2(t);
173
174 LinearCombTimer.Start();
175 {
176 autoView( psi_v,psi, AcceleratorWrite);
177 autoView( r_v , r, AcceleratorWrite);
178 autoView( h_v , h, AcceleratorRead);
179 autoView( s_v , s, AcceleratorRead);
180 autoView( t_v , t, AcceleratorRead);
181 accelerator_for(ss, psi_v.size(), Field::vector_object::Nsimd(),{
182 coalescedWrite(psi_v[ss], h_v(ss) + omega * s_v(ss));
183 coalescedWrite(r_v[ss], -omega * t_v(ss) + s_v(ss));
184 });
185 }
186 LinearCombTimer.Stop();
187
188 cp = norm2(r);
189 LinalgTimer.Stop();
190
191 std::cout << GridLogIterative << "BiCGSTAB: Iteration " << k << " residual " << sqrt(cp/ssq) << " target " << Tolerance << std::endl;
192
193 // Stopping condition
194 if(cp <= rsq)
195 {
196 SolverTimer.Stop();
197 Linop.Op(psi, v);
198 p = v - src;
199
200 RealD srcnorm = sqrt(norm2(src));
201 RealD resnorm = sqrt(norm2(p));
202 RealD true_residual = resnorm / srcnorm;
203
204 std::cout << GridLogMessage << "BiCGSTAB Converged on iteration " << k << std::endl;
205 std::cout << GridLogMessage << "\tComputed residual " << sqrt(cp/ssq) << std::endl;
206 std::cout << GridLogMessage << "\tTrue residual " << true_residual << std::endl;
207 std::cout << GridLogMessage << "\tTarget " << Tolerance << std::endl;
208
209 std::cout << GridLogMessage << "Time breakdown " << std::endl;
210 std::cout << GridLogMessage << "\tElapsed " << SolverTimer.Elapsed() << std::endl;
211 std::cout << GridLogMessage << "\tMatrix " << MatrixTimer.Elapsed() << std::endl;
212 std::cout << GridLogMessage << "\tLinalg " << LinalgTimer.Elapsed() << std::endl;
213 std::cout << GridLogMessage << "\tInner " << InnerTimer.Elapsed() << std::endl;
214 std::cout << GridLogMessage << "\tAxpyNorm " << AxpyNormTimer.Elapsed() << std::endl;
215 std::cout << GridLogMessage << "\tLinearComb " << LinearCombTimer.Elapsed() << std::endl;
216
217 if(ErrorOnNoConverge){ assert(true_residual / Tolerance < 10000.0); }
218
220
221 return;
222 }
223 }
224
225 std::cout << GridLogMessage << "BiCGSTAB did NOT converge" << std::endl;
226
227 if(ErrorOnNoConverge){ assert(0); }
229 }
230};
231
233
234#endif
#define accelerator_for(iterator, num, nsimd,...)
accelerator_inline Grid_simd< S, V > sqrt(const Grid_simd< S, V > &r)
void conformable(const Lattice< obj1 > &lhs, const Lattice< obj2 > &rhs)
ComplexD innerProduct(const Lattice< vobj > &left, const Lattice< vobj > &right)
RealD norm2(const Lattice< vobj > &arg)
#define autoView(l_v, l, mode)
GridLogger GridLogIterative(1, "Iterative", GridLogColours, "BLUE")
GridLogger GridLogMessage(1, "Message", GridLogColours, "NORMAL")
@ AcceleratorRead
@ AcceleratorWrite
#define NAMESPACE_BEGIN(A)
Definition Namespace.h:35
#define NAMESPACE_END(A)
Definition Namespace.h:36
uint32_t Integer
Definition Simd.h:58
std::complex< RealD > ComplexD
Definition Simd.h:79
double RealD
Definition Simd.h:61
bool ErrorOnNoConverge
Definition BiCGSTAB.h:50
Integer MaxIterations
Definition BiCGSTAB.h:53
BiCGSTAB(RealD tol, Integer maxit, bool err_on_no_conv=true)
Definition BiCGSTAB.h:56
void operator()(LinearOperatorBase< Field > &Linop, const Field &src, Field &psi)
Definition BiCGSTAB.h:59
RealD Tolerance
Definition BiCGSTAB.h:52
Integer IterationsToComplete
Definition BiCGSTAB.h:54
void Start(void)
Definition Timer.h:92
GridTime Elapsed(void) const
Definition Timer.h:113
void Stop(void)
Definition Timer.h:99
virtual void Op(const Field &in, Field &out)=0
Definition Simd.h:194