CHROMA
lovlap_double_pass_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 namespace Chroma
10 {
11 //! Apply the GW operator onto a source std::vector
12 /*! \ingroup linop
13  *
14  * This routine applies the 4D GW operator onto a source
15  * std::vector. The coeffiecients for the approximation get
16  * wired into the class by the constructor and should
17  * come fromt fermion action.
18  *
19  * The operator applied is:
20  * D = (1/2)[ (1+m) + (1-m)gamma_5 sgn(H_w) ] psi
21  * or D^{dag} = (1/2)[ (1+m) + (1-m) sgn(H_w) gamma_5 psi
22  *
23  *
24  * \param chi result std::vector (Write)
25  * \param psi source std::vector (Read)
26  * \param isign Hermitian Conjugation Flag
27  * ( PLUS = no dagger| MINUS = dagger ) (Read)
28  */
29 void lovlap_double_pass::operator() (LatticeFermion& chi,
30  const LatticeFermion& psi,
31  enum PlusMinus isign) const
32 {
34 }
35 
36 
37 //! Apply the GW operator onto a source std::vector
38 /*! \ingroup linop
39  *
40  * This routine applies the 4D GW operator onto a source
41  * std::vector. The coeffiecients for the approximation get
42  * wired into the class by the constructor and should
43  * come fromt fermion action.
44  *
45  * The operator applied is:
46  * D = (1/2)[ (1+m) + (1-m)gamma_5 sgn(H_w) ] psi
47  * or D^{dag} = (1/2)[ (1+m) + (1-m) sgn(H_w) gamma_5 psi
48  *
49  *
50  * \param chi result std::vector (Write)
51  * \param psi source std::vector (Read)
52  * \param isign Hermitian Conjugation Flag
53  * ( PLUS = no dagger| MINUS = dagger ) (Read)
54  */
55 void lovlap_double_pass::operator() (LatticeFermion& chi,
56  const LatticeFermion& psi,
57  enum PlusMinus isign, Real epsilon) const
58 {
59  START_CODE();
60 
61  LatticeFermion tmp1, tmp2;
62 
63  // Gamma_5
64  int G5 = Ns*Ns - 1;
65 
66  // Mass for shifted system
67  Real mass = Real(1 + m_q) / Real(1 - m_q);
68 
69 
70  switch (isign)
71  {
72  case PLUS:
73  // Non-Dagger: psi is source and tmp1
74  // chi := gamma_5 * (gamma_5 * mass + sgn(H)) * Psi
75  tmp1 = psi;
76  break;
77 
78  case MINUS:
79  // Dagger: apply gamma_5 to source psi to make tmp1
80  // chi := (mass + sgn(H) * gamma_5) * Psi
81  tmp1 = Gamma(G5) * psi;
82  break;
83 
84  default:
85  QDP_error_exit("unknown isign value", isign);
86  }
87 
88 
89  chi = zero;
90 
91  // Project out eigenvectors of source if desired
92  // chi += func(lambda) * EigVec * <EigVec, psi>
93  // Usually "func(.)" is sgn(.); it is precomputed in EigValFunc.
94  // for all the eigenvalues
95  if (NEig > 0)
96  {
97  Complex cconsts;
98 
99  for(int i = 0; i < NEig; ++i)
100  {
101  cconsts = innerProduct(EigVec[i], tmp1);
102  tmp1 -= EigVec[i] * cconsts;
103 
104  cconsts *= EigValFunc[i];
105  chi += EigVec[i] * cconsts;
106  }
107  }
108 
109  // tmp1 <- H * Projected psi
110  // <- gamma_5 * M * psi
111  (*M)(tmp2, tmp1, PLUS);
112  tmp1 = Gamma(G5) * tmp2;
113 
114 
115  // Effectively the multi mass solve is on tmp1
116  // *******************************************************************
117  // Solve (MdagM + rootQ_n) chi_n = H * tmp1
118 
119  Double c = norm2(tmp1);
120  Double rsd_sq = norm2(psi) * epsilon*epsilon; // || psi ||^2 * epsilon^2
121 
122  // We are solving 2/(1-m) Q so rescale target residuum by ((1-m)/2)^2
123  rsd_sq *= (Real(1) - m_q)*(Real(1)-m_q)/Real(4);
124  Double cp;
125  Double d; // InnerProduct
126 
127  /* If exactly 0 norm, then solution must be 0 (for pos. def. operator) */
128  if (toBool(c == 0))
129  {
130  chi = zero;
131  END_CODE();
132  return;
133  }
134 
135 
136  LatticeFermion Ap;
137  LatticeFermion r;
138  LatticeFermion p;
139 
140  multi1d<Double> a(MaxCG+1); // Alpha for unshifted (isz) system
141  multi1d<Double> b(MaxCG+1); // Beta for unshifted system
142 
143  bool convP;
144  int iters_taken;
145 
146  // By default, rootQ(isz) is considered the smallest shift
147  int isz = numroot-1; // isz identifies system with smalles shift
148 
149 
150  // chi[0] := mass*psi + c0*H*tmp1 + Eigvecs;
151  if (isign == PLUS)
152  {
153  // chi := gamma_5 * (gamma_5 * mass + eps(H)) * Psi
154  // Final mult by gamma_5 is at end
155  tmp2 = Gamma(G5) * psi;
156 
157  // This will be an axpy
158  chi += tmp2 * mass;
159  }
160  else
161  {
162  // chi := (mass + eps(H) * gamma_5) . Psi
163  chi += psi * mass;
164  }
165 
166  // Multiply in P(0) -- this may well be 0 for type 0 rational approximations
167  chi += tmp1 * constP;
168 
169 
170  // r[0] := p[0] := tmp1
171  r = tmp1;
172  p = tmp1;
173 
174 
175  cp = 0;
176  convP = false;
177 
178 
179  Double alpha_minus_one=1;
180  b[0] = 0; // b[0] -- do we ever use ?
181 
182 
183 
184  int k;
185  multi1d<Double> c_iter(MaxCG+1);
186 
187  c_iter[0] = c;
188  // Do the iterations proper
189  // first pass
190  for(k = 0; k < MaxCG && ! convP ; ++k) {
191 
192  // Keep hold of the residuum
193 
194  (*MdagM)(Ap, p, PLUS);
195  Ap += p * rootQ[isz];
196 
197  // Project out eigenvectors
198  if (k % ReorthFreq == 0) {
199  GramSchm(Ap, EigVec, NEig, all);
200  }
201 
202  // d = < p, A.p >
203  d = innerProductReal(p, Ap); // 2 Nc Ns flops
204 
205 
206  // k+1 because a[0] corresponds to a_{-1}
207  a[k] = c/d;
208  r -= Real(a[k])*Ap;
209 
210  // Project out eigenvectors
211  if (k % ReorthFreq == 0) {
212  GramSchm (r, EigVec, NEig, all);
213  }
214 
215  cp = c;
216  c = norm2(r);
217 
218  c_iter[k+1] = c;
219  b[k+1] = c/cp;
220 
221  p = r + Real(b[k+1])*p;
222 
223  convP = toBool( c < rsd_sq );
224  }
225 
226  int niters = k;
227 
228  // OK First pass done. I now need to compute gamma_j and c_j
229  multi2d<Double> gamma(niters+1, numroot);
230  for(int s = 0; s < numroot; s++) {
231  gamma[0][s] = 1; // Really gamma_0
232  }
233 
234 
235  multi1d<bool> convPs(numroot);
236  multi1d<int> convIter(numroot);
237  convPs = false;
238 
239  for(int j=0; j < niters; j++) {
240  for(int s =0; s < numroot; s++) {
241 
242 
243  if( s != isz && ! convPs[s] ) {
244  Double a_minus;
245 
246  if( j == 0 ) {
247  // alpha_minus_one -- no need to store. Only need alpha_0,...
248  // in second pass
249  a_minus = Double(1);
250  }
251  else {
252  a_minus = a[j-1];
253  }
254 
255  Double ga = gamma[j][s];
256  Double ga_minus;
257  if( j == 0 ) {
258  // gamma[-1][s] -- no need to store. Only need gamma[0][s]...
259  // in second pass
260  ga_minus =Double(1);
261  }
262  else{
263  ga_minus = gamma[j-1][s];
264  }
265 
266  Double tmp_num = ga*ga_minus*a_minus;
267  Double tmp_den = ga_minus*a_minus*(Double(1) + a[j]*(rootQ[s] - rootQ[isz]));
268  tmp_den += a[j]*b[j]*(ga_minus - ga);
269 
270  gamma[j+1][s] = tmp_num/tmp_den;
271 
272  // If this system has converged at iter j+1, then dont update
273  // gamma-s anymore and note the convergence point. Updating
274  // ad infinitum causes underflow.
275  if( toBool( gamma[j+1][s]*gamma[j+1][s]*c_iter[j+1] < rsd_sq ) ) {
276  convPs[s] = true;
277  convIter[s] = j+1;
278  }
279 
280  }
281 
282 
283  }
284 
285 
286  }
287 
288 
289  multi1d<Double> sumC(niters+1);
290 
291  for(int j=0; j<=niters; j++) {
292 
293  sumC[j] = 0;
294 
295  for(int m=0; m < niters-j; m++) {
296 
297  Double qsum=resP[isz];
298 
299  for(int s =0; s < numroot; s++) {
300 
301  if( s != isz ) {
302 
303  // Only add gammas which are unconverged.
304  // Converged gamma-s are not updated beyond convergence
305  // which would cause problems (with underflows)
306  // gamma[convIters[s]] is last valid gamma
307  if( toBool( (j+m+1) <= convIter[s] ) ) {
308  qsum += resP[s]*gamma[m+j+1][s]*gamma[m+j][s]/gamma[j][s];
309  }
310 
311  }
312  }
313 
314 
315  Double delta_m = Double(1);
316 
317  if( m > 0 ) {
318  for(int k=1; k <= m; k++) {
319  delta_m *= b[j+k];
320  }
321  }
322 
323 
324  sumC[j] += a[j+m]*delta_m*qsum;
325  }
326  }
327 
328 
329  // Second pass Lanczos
330 
331  // Initialise r_0, p_0
332  r=tmp1;
333  p=tmp1;
334 
335  convP = false;
336 
337  for(k=0; k < niters && !convP ; k++) {
338  (*MdagM)(Ap, p, PLUS);
339  Ap += p * rootQ[isz];
340 
341  // Project out eigenvectors
342  if (k % ReorthFreq == 0) {
343  GramSchm(Ap, EigVec, NEig, all);
344  }
345 
346 
347  // Update chi
348  chi += Real(sumC[k])*r;
349 
350  // Update r
351  r -= Real(a[k])*Ap;
352 
353  // Project out eigenvectors
354  if (k % ReorthFreq == 0) {
355  GramSchm (r, EigVec, NEig, all);
356  }
357 
358 #if 0
359 
360  // This early termination criterion has to be abandoned when
361  // using relaxed solevers
362  Double chi_norm_new = epsilon*epsilon*norm2(chi);
363 
364  // Convergence criterion for total signum. Might be good enough
365  // without running to full niters
366  convP = toBool( c_iter[k+1]*sumC[k+1]*sumC[k+1] < chi_norm_new );
367 #endif
368  p = r + Real(b[k+1])*p;
369  }
370 
371 
372  QDPIO::cout << "Overlap Inner Solve (lovlap_double_pass): " << k << " iterations " << std::endl;
373  // End of MULTI SHIFTERY
374 
375  // Now fix up the thing. Multiply in gamma5 if needed
376  // and then rescale to correct normalisation.
377 
378  if (isign == PLUS)
379  {
380  // chi := gamma_5 * (gamma_5 * mass + eps(H)) * Psi
381  tmp1 = Gamma(G5) * chi;
382  chi = tmp1;
383  }
384 
385  // Rescale to the correct normalization
386  chi *= 0.5 * (1 - m_q);
387 
388  END_CODE();
389 }
390 
391 
392 } // End Namespace Chroma
393 
394 
Primary include file for CHROMA library code.
const multi1d< LatticeFermion > EigVec
const multi1d< Real > EigValFunc
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.
unsigned j
Definition: ldumul_w.cc:35
Internal Overlap-pole operator.
static int m[4]
Definition: make_seeds.cc:16
Double tmp2
Definition: mesq.cc:30
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
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
@ MINUS
Definition: chromabase.h:45
@ 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