Grid 0.7.0
PrecGeneralisedConjugateResidualNonHermitian.h
Go to the documentation of this file.
1/*************************************************************************************
2
3 Grid physics library, www.github.com/paboyle/Grid
4
5 Source file: ./lib/algorithms/iterative/PrecGeneralisedConjugateResidual.h
6
7 Copyright (C) 2015
8
9Author: Azusa Yamaguchi <ayamaguc@staffmail.ed.ac.uk>
10Author: Peter Boyle <paboyle@ph.ed.ac.uk>
11
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2 of the License, or
15 (at your option) any later version.
16
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
21
22 You should have received a copy of the GNU General Public License along
23 with this program; if not, write to the Free Software Foundation, Inc.,
24 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25
26 See the full license in the file "LICENSE" in the top level distribution directory
27*************************************************************************************/
28/* END LEGAL */
29#ifndef GRID_PREC_GCR_NON_HERM_H
30#define GRID_PREC_GCR_NON_HERM_H
31
33//VPGCR Abe and Zhang, 2005.
34//INTERNATIONAL JOURNAL OF NUMERICAL ANALYSIS AND MODELING
35//Computing and Information Volume 2, Number 2, Pages 147-161
36//NB. Likely not original reference since they are focussing on a preconditioner variant.
37// but VPGCR was nicely written up in their paper
40
41#define GCRLogLevel std::cout << GridLogMessage <<std::string(level,'\t')<< " Level "<<level<<" "
42
43template<class Field>
45public:
46 using LinearFunction<Field>::operator();
50 int mmax;
51 int nstep;
52 int steps;
53 int level;
57
60
61 void Level(int lv) { level=lv; };
62
64 Tolerance(tol),
65 MaxIterations(maxit),
66 Linop(_Linop),
67 Preconditioner(Prec),
68 mmax(_mmax),
69 nstep(_nstep)
70 {
71 level=1;
72 verbose=1;
73 };
74
75 void operator() (const Field &src, Field &psi){
76
77 // psi=Zero();
78 RealD cp, ssq,rsq;
79 ssq=norm2(src);
80 rsq=Tolerance*Tolerance*ssq;
81
82 Field r(src.Grid());
83
84 PrecTimer.Reset();
85 MatTimer.Reset();
86 LinalgTimer.Reset();
87
88 GridStopWatch SolverTimer;
89 SolverTimer.Start();
90
91 steps=0;
92 for(int k=0;k<MaxIterations;k++){
93
94 cp=GCRnStep(src,psi,rsq);
95
96 GCRLogLevel <<"PGCR("<<mmax<<","<<nstep<<") "<< steps <<" steps cp = "<<cp<<" target "<<rsq <<std::endl;
97
98 if(cp<rsq) {
99
100 SolverTimer.Stop();
101
102 Linop.Op(psi,r);
103 axpy(r,-1.0,src,r);
104 RealD tr = norm2(r);
105 GCRLogLevel<<"PGCR: Converged on iteration " <<steps
106 << " computed residual "<<sqrt(cp/ssq)
107 << " true residual " <<sqrt(tr/ssq)
108 << " target " <<Tolerance <<std::endl;
109
110 GCRLogLevel<<"PGCR Time elapsed: Total "<< SolverTimer.Elapsed() <<std::endl;
111 return;
112 }
113
114 }
115 GCRLogLevel<<"Variable Preconditioned GCR did not converge"<<std::endl;
116 // assert(0);
117 }
118
119 RealD GCRnStep(const Field &src, Field &psi,RealD rsq){
120
121 RealD cp;
122 ComplexD a, b;
123 // ComplexD zAz;
124 RealD zAAz;
125 ComplexD rq;
126
127 GridBase *grid = src.Grid();
128
129 Field r(grid);
130 Field z(grid);
131 Field tmp(grid);
132 Field ttmp(grid);
133 Field Az(grid);
134
136 // history for flexible orthog
138 std::vector<Field> q(mmax,grid);
139 std::vector<Field> p(mmax,grid);
140 std::vector<RealD> qq(mmax);
141
142 GCRLogLevel<< "PGCR nStep("<<nstep<<")"<<std::endl;
143
145 // initial guess x0 is taken as nonzero.
146 // r0=src-A x0 = src
148 MatTimer.Start();
149 Linop.Op(psi,Az);
150 // zAz = innerProduct(Az,psi);
151 zAAz= norm2(Az);
152 MatTimer.Stop();
153
154
155 LinalgTimer.Start();
156 r=src-Az;
157 LinalgTimer.Stop();
158 GCRLogLevel<< "PGCR true residual r = src - A psi "<<norm2(r) <<std::endl;
159
161 // p = Prec(r)
163
164 PrecTimer.Start();
165 Preconditioner(r,z);
166 PrecTimer.Stop();
167
168 MatTimer.Start();
169 Linop.Op(z,Az);
170 MatTimer.Stop();
171
172 LinalgTimer.Start();
173
174 // zAz = innerProduct(Az,psi);
175 zAAz= norm2(Az);
176
177 //p[0],q[0],qq[0]
178 p[0]= z;
179 q[0]= Az;
180 qq[0]= zAAz;
181
182 cp =norm2(r);
183 LinalgTimer.Stop();
184
185 for(int k=0;k<nstep;k++){
186
187 steps++;
188
189 int kp = k+1;
190 int peri_k = k %mmax;
191 int peri_kp= kp%mmax;
192
193 LinalgTimer.Start();
194 rq= innerProduct(q[peri_k],r); // what if rAr not real?
195 a = rq/qq[peri_k];
196
197 axpy(psi,a,p[peri_k],psi);
198
199 cp = axpy_norm(r,-a,q[peri_k],r);
200 LinalgTimer.Stop();
201
202 GCRLogLevel<< "PGCR step["<<steps<<"] resid " << cp << " target " <<rsq<<std::endl;
203
204 if((k==nstep-1)||(cp<rsq)){
205 return cp;
206 }
207
208
209 PrecTimer.Start();
210 Preconditioner(r,z);// solve Az = r
211 PrecTimer.Stop();
212
213 MatTimer.Start();
214 Linop.Op(z,Az);
215 MatTimer.Stop();
216 // zAz = innerProduct(Az,psi);
217 zAAz= norm2(Az);
218
219 LinalgTimer.Start();
220
221 q[peri_kp]=Az;
222 p[peri_kp]=z;
223
224 int northog = ((kp)>(mmax-1))?(mmax-1):(kp); // if more than mmax done, we orthog all mmax history.
225 for(int back=0;back<northog;back++){
226
227 int peri_back=(k-back)%mmax; assert((k-back)>=0);
228
229 b=-real(innerProduct(q[peri_back],Az))/qq[peri_back];
230 p[peri_kp]=p[peri_kp]+b*p[peri_back];
231 q[peri_kp]=q[peri_kp]+b*q[peri_back];
232
233 }
234 qq[peri_kp]=norm2(q[peri_kp]); // could use axpy_norm
235 LinalgTimer.Stop();
236 }
237 assert(0); // never reached
238 return cp;
239 }
240};
242#endif
accelerator_inline Grid_simd< S, V > sqrt(const Grid_simd< S, V > &r)
RealD axpy_norm(Lattice< vobj > &ret, sobj a, const Lattice< vobj > &x, const Lattice< vobj > &y)
void axpy(Lattice< vobj > &ret, sobj a, const Lattice< vobj > &x, const Lattice< vobj > &y)
Lattice< vobj > real(const Lattice< vobj > &lhs)
ComplexD innerProduct(const Lattice< vobj > &left, const Lattice< vobj > &right)
RealD norm2(const Lattice< vobj > &arg)
#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
void Start(void)
Definition Timer.h:92
GridTime Elapsed(void) const
Definition Timer.h:113
void Stop(void)
Definition Timer.h:99
PrecGeneralisedConjugateResidualNonHermitian(RealD tol, Integer maxit, LinearOperatorBase< Field > &_Linop, LinearFunction< Field > &Prec, int _mmax, int _nstep)