CHROMA
lovddag_w.cc
Go to the documentation of this file.
1 /*! \file
2  * \brief Overlap-pole operator
3  */
4 #include "chromabase.h"
6 #include "meas/eig/gramschm.h"
7 
8 
9 #undef LOVDDAG_RSD_CHK
10 
11 
12 namespace Chroma
13 {
14  //! Apply the GW operator onto a source std::vector
15  /*! \ingroup linop
16  *
17  */
18  void lovddag::operator() (LatticeFermion& chi, const LatticeFermion& psi,
19  enum PlusMinus isign) const
20  {
22  }
23 
24  //! Apply the GW operator onto a source std::vector
25  // epsilon specifies desired precision (absolute)
26  /*! \ingroup linop
27  *
28  */
29  void lovddag::operator() (LatticeFermion& chi, const LatticeFermion& psi,
30  enum PlusMinus isign, Real epsilon) const
31  {
32  START_CODE();
33 
34  LatticeFermion ltmp;
35  LatticeFermion tmp1;
36  Real ftmp;
37 
38  const int G5 = Ns * Ns - 1;
39  int n;
40 
41  Real mass = ( Real(1) + m_q ) / ( Real(1) - m_q );
42  Real init_fac = (Real(1)/mass) + mass;
43 
44  LatticeFermion psi_proj = psi;
45  chi = init_fac * psi;
46 
47 
48  // Project out eigenvectors of source if desired
49  // chi += eps(lambda) * (gamma_5 + ichiral) * EigVec
50  // Usually "func(.)" is eps(.); it is precomputed in EigValFunc.
51  if (NEig > 0)
52  {
53  Complex cconsts;
54 
55  for(int i = 0; i < NEig; ++i)
56  {
57 
58  cconsts = innerProduct(EigVec[i], psi);
59 
60  psi_proj -= cconsts * EigVec[i];
61 
62 
63  // Construct tmp1 = (gamma_5 +/- 1) * EigVec
64  tmp1 = Gamma(G5)*EigVec[i];
65 
66  switch (ichiral) {
67  case CH_PLUS:
68  tmp1 += EigVec[i];
69  break;
70  case CH_MINUS:
71  tmp1 -= EigVec[i];
72  break;
73  case CH_NONE:
74  {
75  std::ostringstream error_message;
76  error_message << "Should not use lovddag unless the chirality is either CH_PLUS or CH_MINUS" << std::endl;
77  throw error_message.str();
78  }
79  break;
80  default:
81  QDP_error_exit("ichiral is outside allowed range: %d\n", ichiral);
82  break;
83  }
84 
85  /* chi += "eps(lambda)" * (gamma_5 + ichiral) * EigVec */
86  cconsts *= EigValFunc[i];
87  chi += cconsts * tmp1;
88 
89  }
90 
91  }
92 
93  /* First part of application of D.psi */
94  /* tmp1 <- H * psi */
95  /* <- gamma_5 * M * psi */
96  (*M)( ltmp, psi_proj, PLUS);
97  tmp1 = Gamma(G5)*ltmp;
98 
99  Double c = norm2(tmp1);
100 
101  /* If exactly 0 norm, then solution must be 0 (for pos. def. operator) */
102  if ( toBool(c == Real(0)) ) {
103  chi = zero;
104  END_CODE();
105  return;
106  }
107 
108 
109  /* chi += constP*(gamma_5 +/-1) * H * Psi */
110  switch (ichiral) {
111  case CH_PLUS:
112  ltmp += tmp1;
113  break;
114 
115  case CH_MINUS:
116  ltmp -= tmp1;
117  break;
118 
119  default:
120  QDP_error_exit("unsupported chirality", ichiral);
121  }
122 
123 
124  chi += constP * ltmp;
125 
126 
127  /********************************************************************/
128  /* Solve (MdagM + rootQ_n) chi_n = H * tmp1 */
129 #ifdef LOVDDAG_RSD_CHK
130  // DEBUG
131  LatticeFermion b_vec=tmp1;
132  LatticeFermion x = zero;
133 #endif
134  LatticeFermion Ap;
135  LatticeFermion r;
136  multi1d<LatticeFermion> p(numroot);
137 
138  Real a; // Alpha for unshifted (isz) system
139  Real as; // alpha for current shifted system
140  Real b; // Beta for unshifted system
141  Real bp; // Beta previous for unshifted system
142 
143  Double ztmp; // Assorted reals (shifted residues)
144  Double cp;
145  Double d;
146  Real z0; // temporary value for zeta previous
147  Real z1; // temporary value for zeta current
148 
149 
150  multi1d<Real> bs(numroot); // beta for shifted system
151  multi2d<Real> z(2,numroot); // zeta for shifted system
152 
153 
154  Double chi_sq_new; // sgn() convergence criterion
155  Double chi_sq_diff;
156  multi1d<bool> convsP(numroot); // convergence mask for shifted system
157  bool convP; // overall convergence mask
158 
159  int iz; // Temporary index for getting at
160  // zeta values in z array
161 
162  int s; // Counter for loops over shifts
163 
164 
165  // We are dealing with 4/(1-m_q)^2
166  // so I should readjust the residua by that squared
167  Real epsilon_normalise = epsilon*(Real(1)-m_q*m_q)/Real(4);
168 
169  // Now get the desired residuum to terminated the CG
170  //
171  // Which is epsilon/(2+epsilon) according to the wuppertal paper
172  Real epsilon_target = epsilon_normalise/(Real(2)+epsilon_normalise);
173 
174  // Now square that up
175  Real rsdcg_sq = epsilon_target*epsilon_target;
176 
177  Real rsd_sq = norm2(psi)*rsdcg_sq; // Used for relative residue comparisons
178  // r_t^2 * || r ||^2
179 
180  /* By default (could change), rootQ(isz) is considered the smallest shift */
181  int isz = numroot-1;
182 
183 
184  /* r[0] := p[0] := tmp1 */
185  r = tmp1;
186 
187  for(s = 0; s < numroot; ++s) {
188  p[s] = tmp1;
189  }
190 
191  // Set convergence masks to fals
192  convsP = false;
193  convP = false;
194 
195  iz = 1; // z_index z[ iz , s ] holds zeta(s)
196  // z[ 1-iz, s ] holds zeta_minus(s)
197 
198  z = 1; // This fills both zeta and zeta_minus
199 
200  a = 0; // Alpha for unshifted
201  b = 1; // beta for unshifted
202 
203  int k;
204  for(k = 0; k <= MaxCG && ! convP ; ++k)
205  {
206 
207  // Unshifted beta value: b[k] -- k is iteration index
208  // b[k] := | r[k] |**2 / < p[k], Ap[k] > ;
209  // First compute d = < p, A.p >
210  // Ap = A . p
211 
212  // This bit computes
213  // Ap = [ M^dag M + rootQ(isz) ] p_isz
214  (*MdagM)(Ap, p[isz], PLUS);
215  Ap += p[isz] * rootQ[isz];
216 
217 
218  /* Project out eigenvectors */
219  if (k % ReorthFreq == 0){
220  GramSchm(Ap, EigVec, NEig, all);
221  }
222 
223  /* d = < p, A.p > */
224  d = innerProductReal(p[isz], Ap); /* 2 Nc Ns flops */
225 
226  bp = b; // Store previous unshifted beta
227  b = -Real(c/d); // New unshifted beta
228 
229  /* Compute the shifted bs and z */
230  bs[isz] = b;
231 
232  // iz now points to previous z's
233  iz = 1 - iz;
234 
235  // Compute new shifted beta and zeta values
236  // as per Beat Jegerlehner's paper: hep-lat/9612014
237  // eqns 2.42, 2.44 on page 7
238  for(s = 0; s < numroot; s++) {
239 
240  // Do this to avoid mitsmp compiler bug !!
241  z0 = z[1-iz][s]; // The current z for the system under considerstion
242  z1 = z[iz][s] ; // The previous z for the system under consideration
243 
244  // We only compute beta and z factors if
245  // i) The system is not yet converged
246  // ii) The system is shifted
247  if (s != isz && !convsP[s]) {
248 
249 
250  // We write the new z-s in the place of the previous ones.
251  // Our ones will become previous next time around
252  z[iz][s] = z0*z1*bp ;
253  z[iz][s] /= b*a*(z1 - z0) + z1*bp*(1 - (rootQ[s] - rootQ[isz])*b);
254  bs[s] = b * z[iz][s] / z0;
255 
256  }
257  }
258 
259  // New residual of system with smallest shift
260  // r[k+1] += b[k] A . p[k] ;
261  r += b * Ap; // 2 Nc Ns flops
262 
263 
264  /* Project out eigenvectors */
265  if (k % ReorthFreq == 0) {
266  GramSchm (r, EigVec, NEig, all);
267  }
268 
269  // Work out new iterate for sgn(H).
270  //
271  // This in effect updates all x vectors and performs
272  // immediately the linear sum.
273  // However, the x's are never explicitly computed. Rather
274  // the changes they would get get rolled onto the chi immediately
275  //
276  // chi[k+1] -= sum_{shifts} resP_{shift} b_{shift}[k] p_{shift}[k] ;
277  //
278  // since we are doing the linear combinations we multiply in the
279  // constant in the numerator too.
280 
281  // smallest shift first
282  Real(rtmp);
283  rtmp = resP[isz] * b;
284  ltmp = p[isz] * rtmp; // 2 Nc Ns flops
285 
286  // Now the other shifts.
287  // Converged systems haven' changed, so we only add results
288  // from the unconverged systems
289  for(s = 0; s < numroot; ++s) {
290  if(s != isz && !convsP[s]) {
291 
292  rtmp = bs[s] * resP[s];
293  ltmp += p[s] * rtmp; // 2 Nc Ns flops
294  }
295  }
296 
297 
298 
299  /* diff := (gamma_5 + ichiral) * tmp1 */
300  tmp1 = Gamma(G5)*ltmp;
301 
302  switch( ichiral ) {
303  case CH_PLUS:
304  tmp1 += ltmp;
305  break;
306  case CH_MINUS:
307  tmp1 -= ltmp;
308  break;
309  default :
310  QDP_error_exit("lovddag: isign must be CH_PLUS or CH_MINUS\n");
311  break;
312  }
313 
314 
315  /* chi += diff . The minus comes from the CG method. */
316  chi -= tmp1; /* 2 Nc Ns flops */
317 
318 #ifdef LOVDDAG_RSD_CHK
319  /* diff := (gamma_5 + ichiral) * tmp1 */
320  x -= b*p[isz];
321 #endif
322 
323  // Store in cp the previous value of c
324  // cp = | r[k] |**2
325  cp = c;
326 
327  // And compute the current norm of r into the (now saved) c
328  // c = | r[k] |**2
329  c = norm2(r); // 2 Nc Ns flops
330 
331  // Work out the alpha factor for the system with smallest shift.
332  // a[k+1] := |r[k]|**2 / |r[k-1]|**2 ;
333  a = Real(c/cp);
334 
335  /* p[k+1] := r[k+1] + a[k+1] p[k]; */
336  /* Compute the shifted as */
337  /* ps[k+1] := zs[k+1] r[k+1] + a[k+1] ps[k]; */
338  for(s = 0; s < numroot; ++s) {
339  if (s == isz) {
340 
341  p[s] *= a; // Nc Ns flops
342  p[s] += r; // Nc Ns flops
343 
344 
345  }
346  else {
347  if (! convsP[s]) {
348  as = a * z[iz][s]*bs[s] / (z[1-iz][s]*b);
349 
350  p[s] *= as; /* Nc Ns flops */
351  p[s] += r * z[iz][s]; /* Nc Ns flops */
352 
353  }
354  }
355  }
356 
357 #if 0
358  /* Project out eigenvectors */
359  if (k % ReorthFreq == 0)
360  GramSchm (p, numroot, EigVec, NEig, all);
361 #endif
362 
363  // Convergence tests start here.
364  //
365  // These are two steps:
366  //
367  // i) Check that the shifted vectors have converged
368  // by checking their accumulated residues
369  //
370  // ii) Check that the sign function itself has converged
371  //
372  //
373  // We set the global convergence flag to true, and then if
374  // any vectors are unconverged this will flip the global flag back
375  // to false
376  convP = true; // Assume convergence and prove
377  // otherwise
378 
379  for(s = 0; s < numroot; ++s) {
380 
381  // Only deal with unconverged systems
382  if (! convsP[s]) {
383 
384  // Compute the shifted residuum squared
385  //
386  // r_{shift} = || r || * zeta(shift)
387  //
388  // hence || r_shift ||^2 = || r ||^2 * zeta_shift^2
389  //
390  // || r^2 || is already computed in c
391  //
392  // Store || r_shift ||^2 in ztmp
393  ztmp = Real(c) * z[iz][s]*z[iz][s];
394 
395  // Check ztmp is smaller than the target residuum
396  bool btmp = toBool(ztmp < rsd_sq);
397  convP = convP & btmp;
398  convsP[s] = btmp;
399  }
400  }
401 
402 #ifdef LOVDDAG_RSD_CHK
403  if(convP) {
404  LatticeFermion tmp_normcheck;
405  (*MdagM)(tmp_normcheck, x, PLUS);
406  tmp_normcheck += rootQ[isz]*x;
407  tmp_normcheck -= b_vec;
408  Double norm2check = norm2(tmp_normcheck);
409  Double check_ztmp = Real(c) * z[iz][isz]*z[iz][isz];
410  QDPIO::cout << "|| b - (Q_isz + MM)x || = " << norm2check << " accum = " << check_ztmp << std::endl;
411  }
412 #endif
413 
414  // Now check convergence of the sgn() itself.
415  // It was updated with
416  // sum resP(shift) beta(shift) p_shift
417  // and this quantity is still in tmp1.
418  //
419  // So norm tmp1 is like an abolute error in sgn() aka: Delta sgn()
420  //
421  // Here we ensure Delta sgn() < target r^2 || sgn H[k-1] ||
422  //
423  // ie that the relative error in sgn() is smaller than the target.
424  // sgn H is kept in chi
425  //
426  // Only converge if chi is converged. If vectors converge first, then error
427 
428 #if 0
429  if (k > 0 && !convP) {
430 
431  // Get target r^2 * || sgn (H) ||^2
432  chi_sq_new = rsd_sq;
433 
434  // Get || Delta sgn() ||^2
435  chi_sq_diff = norm2(tmp1); // the diff of old and new soln
436 
437  // Check convergence
438  bool btmp = toBool(chi_sq_diff < chi_sq_new);
439 
440  // If we havent converged globally but the vectors have then error
441  if (! btmp && convP) {
442  QDP_error_exit("vectors converged but not final chi");
443  }
444 
445  // cnvP = convP & btmp;
446  convP = btmp;
447  }
448 #endif
449  }
450 
451  int n_count = k;
452 
453  /* Rescale to the correct normalization */
454  /* chi <- (1/4)*(1-m_q^2) * chi */
455  ftmp = Real(0.25) * (Real(1) - m_q*m_q);
456  chi *= ftmp; /* 2 Nc Ns flops */
457  QDPIO::cout << "Overlap Inner Solve (lovddag(" << ichiral << ")) = " << n_count << " iterations" << std::endl;
458 
459  END_CODE();
460  }
461 
462 } // End Namespace Chroma
463 
Primary include file for CHROMA library code.
const Real m_q
Definition: lovddag_w.h:100
Chirality ichiral
Definition: lovddag_w.h:111
const multi1d< LatticeFermion > EigVec
Definition: lovddag_w.h:105
const int ReorthFreq
Definition: lovddag_w.h:110
const Real constP
Definition: lovddag_w.h:102
const Real RsdCG
Definition: lovddag_w.h:109
const multi1d< Real > rootQ
Definition: lovddag_w.h:103
const multi1d< Real > resP
Definition: lovddag_w.h:104
const multi1d< Real > EigValFunc
Definition: lovddag_w.h:106
Gramm-Schmidt orthogonolization.
void GramSchm(multi1d< LatticeFermion > &psi, const int Npsi, const multi1d< LatticeFermion > &vec, const int Nvec, const Subset &sub)
Gramm-Schmidt orthogonolization.
Definition: gramschm.cc:127
void operator()(LatticeFermion &chi, const LatticeFermion &psi, enum PlusMinus isign) const
Apply the operator onto a source std::vector.
Definition: lovddag_w.cc:18
unsigned n
Definition: ldumul_w.cc:36
Internal Overlap-pole operator.
int z
Definition: meslate.cc:36
int x
Definition: meslate.cc:34
int iz
Definition: meslate.cc:32
Real rtmp
Definition: meslate.cc:59
int epsilon(int i, int j, int k)
BinaryReturn< C1, C2, FnInnerProduct >::Type_t innerProduct(const QDPSubType< T1, C1 > &s1, const QDPType< T2, C2 > &s2)
Asqtad Staggered-Dirac operator.
Definition: klein_gord.cc:10
QDP_error_exit("too many BiCG iterations", n_count, rsd_sq, cp, c, re_rvr, im_rvr, re_a, im_a, re_b, im_b)
int G5
Definition: pbg5p_w.cc:57
@ CH_NONE
Definition: ischiral_w.h:8
@ CH_PLUS
Definition: ischiral_w.h:8
@ CH_MINUS
Definition: ischiral_w.h:8
int n_count
Definition: invbicg.cc:78
Double c
Definition: invbicg.cc:108
Real rsd_sq
Definition: invbicg.cc:121
int i
Definition: pbg5p_w.cc:55
Double mass
Definition: pbg5p_w.cc:54
@ PLUS
Definition: chromabase.h:45
Double cp
Definition: invbicg.cc:107
multi1d< LatticeFermion > chi(Ncb)
Complex a
Definition: invbicg.cc:95
LatticeFermion psi
Definition: mespbg5p_w.cc:35
DComplex d
Definition: invbicg.cc:99
START_CODE()
Complex b
Definition: invbicg.cc:96
Double zero
Definition: invbicg.cc:106
int k
Definition: invbicg.cc:119
multi1d< LatticeFermion > s(Ncb)
FloatingPoint< double > Double
Definition: gtest.h:7351
int isz
Definition: pade_trln_w.cc:151