CHROMA
overlap_fermact_base_w.cc
Go to the documentation of this file.
1 /*! \file
2  * \brief Base class for unpreconditioned overlap-like fermion actions
3  */
4 
5 #include "chromabase.h"
6 //#include "actions/ferm/fermstates/overlap_state.h"
12 
22 #include "meas/eig/ischiral_w.h"
23 
26 
27 namespace Chroma
28 {
29  //! Propagator for unpreconditioned overlap-like fermion actions
30  //! Propagator of an un-preconditioned Extended-Overlap linear operator
31  /*! \ingroup qprop
32  *
33  * Propagator solver for DWF-like fermions
34  */
35  class Ovlap4DQprop : public SystemSolver<LatticeFermion>
36  {
37  public:
38  // Typedefs to save typing
39  typedef LatticeFermion T;
40  typedef multi1d<LatticeColorMatrix> P;
41  typedef multi1d<LatticeColorMatrix> Q;
42 
43  //! Constructor
44  /*!
45  * \param S_f_ Fermion action ( Read )
46  * \param state_ state ( Read )
47  */
49  Handle< FermState<T,P,Q> > state_,
50  const SysSolverCGParams& invParam_) :
51  S_f(S_f_), state(state_), invParam(invParam_) {}
52 
53  //! Destructor is automatic
55 
56  //! Return the subset on which the operator acts
57  const Subset& subset() const {return all;}
58 
59  //! Solver the linear system
60  /*!
61  * \param psi quark propagator ( Modify )
62  * \param chi source ( Read )
63  * \return number of CG iterations
64  */
65  SystemSolverResults_t operator() (LatticeFermion& psi, const LatticeFermion& chi) const
66  {
67  START_CODE();
68 
70  Real mass = S_f->getQuarkMass();
71 
72 // if( invType == "CG_INVERTER")
73  {
74  // We do our solve into tmp, so make sure this is the supplied initial guess
75  LatticeFermion tmp = psi;
76 
77  Handle< LinearOperator<T> > M(S_f->linOp(state));
78 
79  // Check whether the source is chiral.
81  if( ichiral == CH_NONE || ( S_f->isChiral() == false ))
82  {
83  Handle<LinearOperator<T> > MM(S_f->lMdagM(state));
84 
85  // Do this at the end as otherwise it may mix chiralities?
86  (*M)(tmp, chi, MINUS);
87 
88 
89  // Source is not chiral. In this case we should use,
90  // InvCG2 with M
91  res = InvCG2(*M, tmp, psi, invParam.RsdCG, invParam.MaxCG);
92 
93  }
94  else
95  {
96  // If we have a chiral source we have M^{dag} M = M^{2}
97  // but applying M at the front might mix chiralities hurting
98  // convergence so we do it last
100 
101  // Source is chiral. In this case we should use InvCG1
102  // with the special MdagM
103  res = InvCG1(*MM, chi,tmp, invParam.RsdCG, invParam.MaxCG);
104  (*M)(psi,tmp, MINUS);
105  }
106 
107  LatticeFermion Mpsi;
108  (*M)(Mpsi, psi, PLUS);
109  Mpsi -= chi;
110 
111  QDPIO::cout << "OvQprop || chi - D psi ||/||chi|| = "
112  << sqrt(norm2(Mpsi))/sqrt(norm2(chi))
113  << " n_count = " << res.n_count << " iters" << std::endl;
114  }
115 #if 0
116  else if (invType == "REL_CG_INVERTER")
117  {
118  LatticeFermion tmp = psi;
119  Handle<LinearOperator<T> > M(S_f->linOp(state));
120 
121 
122  // Check whether the source is chiral.
124  if( ichiral == CH_NONE || ( S_f->isChiral() == false ))
125  {
126 
127  // Source is not chiral. In this case we should use,
128  // InvCG2 with M
129  (*M)(tmp, chi, MINUS);
131  }
132  else
133  {
134  // Source is chiral. In this case we should use InvCG1
135  // with the special MdagM
136  Handle<LinearOperator<T> > MM( dynamic_cast< LinearOperator<LatticeFermion>* >( S_f->lMdagM(state, ichiral) ) );
137 
138  (*M)(tmp, chi, MINUS);
140  }
141 
142  LatticeFermion Mpsi;
143  (*M)(Mpsi, psi, PLUS);
144  Mpsi -= chi;
145  QDPIO::cout << "OvQprop || chi - D psi ||/||chi|| = "
146  << sqrt(norm2(Mpsi))/sqrt(norm2(chi))
147  << " n_count = " << res.n_count << " iters" << std::endl;
148 
149  }
150 #if 0
151  else if (invType == "MR_INVERTER")
152  {
153  // psi = D^(-1)* chi
155  }
156  else if (invType == "BICG_INVERTER")
157  {
158  // psi = D^(-1) chi
159  InvBiCG (*M, chi, psi, invParam.RsdCG, invParam.MaxCG, res.n_count);
160  }
161 #endif
162  else if (invType == "SUMR_INVERTER")
163  {
164  // Solve by SUMR solver -- for shifted unitary matrices
165  //
166  // Solve zeta I + rho gamma_5 eps(H)
167  // where gamma_5 eps(H) is unitary
168  //
169  // zeta = (1 + mu)/(1-mu)
170  // rho = 1
171  Real rho = Real(1);
172  Real mu = S_f->getQuarkMass();
173  Complex zeta = cmplx(( Real(1) + mu ) / (Real(1) - mu),0);
174  {
175  Handle< LinearOperator<T> > U(S_f->lgamma5epsH(state));
176 
177  // Now solve:
178  InvSUMR(*U, chi, psi, zeta, rho, invParam.RsdCG, invParam.MaxCG, res.n_count);
179 
180  // Restore to normal scaling
181  Real fact = Real(2)/(Real(1) - mu);
182  psi *= fact;
183  }
184 
185  // Check back:
186  // Get a proper operator and compute chi- Dpsi
187  Handle< LinearOperator<T> > D(S_f->linOp(state));
188  LatticeFermion Dpsi;
189  (*D)(Dpsi, psi, PLUS);
190  Dpsi -= chi;
191  QDPIO::cout << "OvQprop || chi - D psi || = "
192  << sqrt(norm2(Dpsi))/sqrt(norm2(chi))
193  << " n_count = " << res.n_count << " iters" << std::endl;
194  }
195  else if (invType == "REL_SUMR_INVERTER")
196  {
197  // Solve by Relaxed SUMR solver -- for shifted unitary matrices
198  //
199  // Solve zeta I + rho gamma_5 eps(H)
200  // where gamma_5 eps(H) is unitary
201  //
202  // zeta = (1 + mu)/(1-mu)
203  // rho = 1
204  Real rho = Real(1);
205  Real mu = S_f->getQuarkMass();
206  Complex zeta = cmplx(( Real(1) + mu ) / (Real(1) - mu),0);
207  {
208  Handle< LinearOperator<T> > U( dynamic_cast< LinearOperator<LatticeFermion>* >(S_f->lgamma5epsH(state)) );
209 
210  Real fact = Real(2)/(Real(1) - mu);
211 
212  // Now solve:
213  InvRelSUMR(*U, chi, psi, zeta, rho, invParam.RsdCG, invParam.MaxCG, res.n_count);
214 
215  // Restore to normal scaling
216  psi *= fact;
217 
218 
219  }
220 
221  // Check back:
222  // Get a proper operator and compute chi- Dpsi
223  Handle< LinearOperator<T> > D(S_f->linOp(state));
224  LatticeFermion Dpsi;
225  (*D)(Dpsi, psi, PLUS);
226  Dpsi -= chi;
227  QDPIO::cout << "OvQprop || chi - D psi || = "
228  << sqrt(norm2(Dpsi)) / sqrt(norm2(chi))
229  << " n_count = " << res.n_count << " iters" << std::endl;
230  }
231  else if (invType == "REL_GMRESR_SUMR_INVERTER")
232  {
233  // Solve by Relaxed SUMR solver -- for shifted unitary matrices
234  //
235  // Solve zeta I + rho gamma_5 eps(H)
236  // where gamma_5 eps(H) is unitary
237  //
238  // zeta = (1 + mu)/(1-mu)
239  // rho = 1
240  Real rho = Real(1);
241  Real mu = S_f->getQuarkMass();
242  Complex zeta = cmplx(( Real(1) + mu ) / (Real(1) - mu),0);
243  {
244  Handle< LinearOperator<T> > UnprecU( dynamic_cast< LinearOperator<T>* >(S_f->lgamma5epsH(state)) );
245 
246  Handle< LinearOperator<T> > PrecU( dynamic_cast< LinearOperator<T>* >(S_f->lgamma5epsHPrecondition(state)) );
247 
248 
249  Real fact = Real(2)/(Real(1) - mu);
250 
251  // Now solve:
252  InvRelGMRESR_SUMR(*PrecU, zeta, rho, *UnprecU, chi, psi, invParam.RsdCG, invParam.RsdCGPrec, invParam.MaxCG, invParam.MaxCGPrec, res.n_count);
253 
254  // Restore to normal scaling
255  psi *= fact;
256 
257 
258  }
259 
260  // Check back:
261  // Get a proper operator and compute chi- Dpsi
262  Handle< LinearOperator<T> > D(S_f->linOp(state));
263  LatticeFermion Dpsi;
264  (*D)(Dpsi, psi, PLUS);
265  Dpsi -= chi;
266 
267  QDPIO::cout << "OvQprop || chi - D psi || = "
268  << sqrt(norm2(Dpsi))/sqrt(norm2(chi))
269  << " n_count = " << res.n_count << " iters" << std::endl;
270  }
271  else if (invType == "REL_GMRESR_GG_INVERTER")
272  {
273 
274  LatticeFermion tmp= psi;
276  LinearOperator<T> *MM_ptr;
277  LinearOperator<T> *MM_prec_ptr;
278 
279  if( ichiral == CH_NONE || ( S_f->isChiral() == false )) {
280 
281  MM_ptr = dynamic_cast< LinearOperator<T>* >( S_f->lMdagM(state));
282  MM_prec_ptr = dynamic_cast< LinearOperator<T>* >( S_f->lMdagMPrecondition(state));
283 
284  }
285  else {
286 
287  // Source is chiral. In this case we should use InvCG1
288  // with the special MdagM
289  MM_ptr = dynamic_cast< LinearOperator<T>* >( S_f->lMdagM(state, ichiral) );
290  MM_prec_ptr = dynamic_cast< LinearOperator<T>* >( S_f->lMdagMPrecondition(state, ichiral) );
291 
292  }
293 
294  Handle< LinearOperator<T> > MM(MM_ptr);
295  Handle< LinearOperator<T> > MM_prec(MM_prec_ptr);
296  Handle< LinearOperator<T> > M(S_f->linOp(state));
297 
298  (*M)(tmp,chi,MINUS);
299  InvRelGMRESR_CG(*MM_prec,*MM, tmp, psi, invParam.RsdCG, invParam.RsdCGPrec, invParam.MaxCG, invParam.MaxCGPrec, res.n_count);
300 
301 
302 
303  T Mpsi;
304  (*M)(Mpsi, psi, PLUS);
305  Mpsi -= chi;
306  QDPIO::cout << "OvQprop || chi - D psi ||/||chi|| = "
307  << sqrt(norm2(Mpsi)) / sqrt(norm2(chi))
308  << " n_count = " << res.n_count << " iters" << std::endl;
309  }
310  else
311  {
312  QDPIO::cerr << "Zolotarev4DFermActBj::qprop Solver Type not implemented" << std::endl;
313  QDP_abort(1);
314  }
315 #endif
316 
317  if ( res.n_count == invParam.MaxCG ) {
318  QDP_error_exit("Zolotarev4DFermAct::qprop: No convergence in solver: n_count = %d\n", res.n_count);
319  }
320 
321  // Compute residual
322  {
323  Handle< LinearOperator<T> > M(S_f->linOp(state));
324 
325  T r;
326  (*M)(r, psi, PLUS);
327  r -= chi;
328  res.resid = sqrt(norm2(r));
329  }
330 
331  // Normalize and remove contact term
332  Real ftmp = Real(1) / ( Real(1) - mass );
333 
334  psi -= chi;
335  psi *= ftmp;
336 
337  END_CODE();
338 
339  return res;
340  }
341 
342  private:
343  // Hide default constructor
345 
349  };
350 
351 
352 // Propagator for unpreconditioned overlap-like fermion actions
353 /* Yuk, just make a clone of the current action and pass it around */
356  const GroupXML_t& invParam) const
357  {
358  std::istringstream is(invParam.xml);
359  XMLReader paramtop(is);
360 
362  SysSolverCGParams(paramtop,invParam.path));
363  }
364 
365 
366 
367 /* This routine is Wilson type Overlap fermions */
368 
369 /* Compute multiple quark mass propagators for an unpreconditioned overla fermion */
370 /* using the single mass source in "chi" - so, the source can */
371 /* be of any desired form. The results will appear in "psi", which is */
372 /* ignored on input (and set to zero initially) */
373 
374 /* This routine can return the solution to the following systems,
375  when using CG */
376 /* D * psi = chi (n_soln = 1) */
377 /* D^dag * psi = chi (n_soln = 2) */
378 /* and all of the above for n_soln = 3 */
379 /* (D * D^dag) * psi = chi (for n_soln = 4) */
380 
381 /* u -- gauge field ( Read ) */
382 /* chi -- source ( Modify ) */
383 /* Mass -- quark masses in lattice units ( Read ) */
384 /* psi -- quark propagators ( Write ) */
385 /* ncg_had -- number of CG iterations ( Modify ) */
386  void
388  const multi1d<Real>& masses,
390  const T& chi,
391  const GroupXML_t& invParam_,
392  const int n_soln,
393  int& n_count) const
394  {
395 
396  if ( toBool( getQuarkMass() != 0 ) ) {
397  QDP_error_exit("Multi Mass Qprop only works if action has mass = 0 (strictly)");
398  }
399 
400  std::istringstream is(invParam_.xml);
401  XMLReader paramtop(is);
402 
403  MultiSysSolverCGParams invParam(paramtop, invParam_.path);
404 
405  int nsets ;
406  int msets ;
407  multi1d<enum PlusMinus> isign_set(2);
408 
409 
410  switch(n_soln) {
411  case 1: // D psi = chi
412  nsets = 1;
413  isign_set[0] = MINUS;
414  break;
415 
416  case 2:
417  nsets = 1; // D^dag psi = chi
418  isign_set[0] = PLUS;
419  break;
420 
421  case 3: // both D psi = chi and D dag psi = chi
422  nsets = 2;
423  isign_set[0] = MINUS;
424  isign_set[1] = PLUS;
425  break;
426 
427  case 4:
428  nsets = 0; // D^dag D psi = chi
429  isign_set[0] = PLUS;
430  break;
431 
432  default:
433  QDP_error_exit("solution type incorrect", n_soln);
434  }
435 
436 
437  const int n_mass = masses.size();
438 
439  // Generic feature of multi mass solvers, initial guesses psi have to be zero
440  for(int n=0; n < n_mass; n++) {
441  psi[n] = zero;
442  }
443 
444 
445  Real ftmp;
446 // switch( invParam.invType ) {
447 
448 // case CG_INVERTER:
449  {
450  // This is M_scaled = 2 D(0).
451  // the fact that D has zero masss is enforced earlier
452  //
454  M_scaled(new lopscl<T, Real>( linOp(state), Real(2) ) );
455 
456  Chirality ischiral;
457  LinearOperator<T>* MdagMPtr;
458  multi1d<Real> shifted_masses(n_mass);
459 
460  for(int i = 0; i < n_mass; i++) {
461  shifted_masses[i] = ( Real(1) + masses[i] )/( Real(1) - masses[i] );
462  shifted_masses[i] += ( Real(1) / shifted_masses[i] );
463  shifted_masses[i] -= Real(2);
464  }
465 
466 
467  // This is icky. I have to new and delete,
468  // and I can't drop in a handle as I
469  // a) Can't declare variables in a case statement
470  // in case it jumps.
471  //
472  // Hence I have to deal directly with the f***ing pointer
473  // using new and delete.
474  //
475  //
476  // MdagMPtr = 4 D^{dag}(0) D(0)
477  //
478  // The Zero is enforced elsewhere
479  ischiral = isChiralVector(chi);
480  if( ischiral == CH_NONE || ( isChiral() == false ) ) {
481 
482  // I have one scaled by 2. The MdagM fixes up the scale
483  // factor of 4. I don't need to recompute coeffs etc here.
484  //
485 
486  MdagMPtr = new MdagMLinOp<T>(M_scaled);
487  }
488  else {
489  // Special lovddag version
490  MdagMPtr = new lopscl<T, Real> ( lMdagM( state, ischiral ), Real(4) );
491  }
492 
493  // Do the solve
494  //
495  // This really solves with Kerel:
496  //
497  // (1/(1-m^2)) 4 D(m)^{dag} D(m)
498  //
499  // = 4 D(0)^{dag} D(0) + shift
500  //
501  // with shift = (1+m)/(1-m) + (1-m)/(1+m) - 2
502  //
503  //
504  // result of solution is:
505  //
506  // psi = [ (1 - m^2 ) / 4 ] [ D^{dag}(m) D(m) ]^{-1} chi
507  //
508  // = [ ( 1 - m^2 ) / 2 ] (2 D^{dag}(m))^{-1} D(m)^{-1} chi
509  //
510  // = [ ( 1 - m^2 ) / 2 ] ( 2 D(m))^{-1} D^{-dag}(m) chi
511  MInvCG(*MdagMPtr, chi, psi, shifted_masses, invParam.RsdCG, invParam.MaxCG, n_count);
512 
513  // Delete MdagMPtr. Do it right away before I forget.
514  delete MdagMPtr;
515 
516  if ( n_count == invParam.MaxCG ) {
517  QDP_error_exit("no convergence in the inverter", n_count);
518  }
519 
520  // Now make the solution(s)
521  switch(n_soln) {
522  case 4:
523 
524  // Compensate for the 4/(1-m^2) factor
525 
526  for(int i = 0; i < n_mass; i++) {
527  psi[i] *= Real(4) / ( Real(1) - masses[i]*masses[i] );
528  }
529  break;
530 
531  case 3:
532  // Copy ofver the solutions of D^{-1} for solutions to D_dag^{-1}
533  for( int i = 0 ; i < n_mass; i++) {
534  psi[n_mass + i] = psi[i];
535  }
536  // Fall through to the case below:
537 
538  case 1:
539  case 2:
540  for(int iset=0; iset < nsets; iset++) {
541  for(int i=0; i < n_mass; i++) {
542  int j = i+iset*n_mass;
543  T tmp1;
544 
545  // Need to multiply:
546  //
547  // (2/(1-m^2)) (2D(m)) or (2/(1-m^2)) (2D^{dag}(m))
548  //
549  // as appropriate. D(m) = m + (1 - m) D(0)
550  //
551  // so 2D(m) = 2m + (1-m) 2D(0)
552  // = [1+m-(1-m)] + (1-m) 2D(0)
553  //
554  // and 2/(1-m^2) = 2/((1+m)(1-m)
555  //
556  // finally:
557  //
558  // (2/(1-m^2)) (2D(m))
559  // = 2/(1+m) * [ (1+m)/(1-m) - 1 + 2D(0) ]
560  // = 2/(1+m) * [ {(1+m)/(1-m) - 1} + M_scaled ]
561  //
562  //
563  (*M_scaled)(tmp1, psi[j], isign_set[iset]);
564 
565  ftmp = (Real(1) + masses[i])/(Real(1) - masses[i]) - Real(1);
566 
567  tmp1 += ftmp*psi[j];
568 
569  tmp1 *= Real(2)/(Real(1) + masses[i]);
570 
571 
572  // Subtract off contact term
573  psi[j] = tmp1 - chi;
574 
575  // overall noramalisation
576  ftmp = Real(1) / ( Real(1) - masses[i] );
577  psi[j] *= ftmp;
578 
579  }
580  }
581  break;
582  default:
583  QDP_error_exit("This value of n_soln is not known about %d\n", n_soln);
584  break;
585  } // End switch over n_soln;
586  }
587 #if 0
588  break; // End of CG case
589 
590  case REL_CG_INVERTER:
591  {
592  // This is M_scaled = 2 D(0).
593  // the fact that D has zero masss is enforced earlier
594  //
596  // This is a really ugly construction but should work
597  M_scaled(new approx_lopscl<T, Real>(dynamic_cast<LinearOperator<T>* >(linOp(state)),Real(2) ) );
598 
599  Chirality ischiral;
600  LinearOperator<T>* MdagMPtr;
601  multi1d<Real> shifted_masses(n_mass);
602 
603  for(int i = 0; i < n_mass; i++) {
604  shifted_masses[i] = ( Real(1) + masses[i] )/( Real(1) - masses[i] );
605  shifted_masses[i] += ( Real(1) / shifted_masses[i] );
606  shifted_masses[i] -= Real(2);
607  }
608 
609 
610  // This is icky. I have to new and delete,
611  // and I can't drop in a handle as I
612  // a) Can't declare variables in a case statement
613  // in case it jumps.
614  //
615  // Hence I have to deal directly with the f***ing pointer
616  // using new and delete.
617  //
618  //
619  // MdagMPtr = 4 D^{dag}(0) D(0)
620  //
621  // The Zero is enforced elsewhere
622  ischiral = isChiralVector(chi);
623  if( ischiral == CH_NONE || ( isChiral() == false ) ) {
624 
625  // I have one scaled by 2. The MdagM fixes up the scale
626  // factor of 4. I don't need to recompute coeffs etc here.
627  //
628  MdagMPtr = new approx_lmdagm<T>(M_scaled);
629  }
630  else {
631  // Special lovddag version
632  // This is yet another ugly cast.
633  MdagMPtr = new approx_lopscl<T, Real> ( dynamic_cast<LinearOperator<T>* >(lMdagM( state, ischiral )), Real(4) );
634  }
635 
636  // Do the solve
637  //
638  // This really solves with Kerel:
639  //
640  // (1/(1-m^2)) 4 D(m)^{dag} D(m)
641  //
642  // = 4 D(0)^{dag} D(0) + shift
643  //
644  // with shift = (1+m)/(1-m) + (1-m)/(1+m) - 2
645  //
646  //
647  // result of solution is:
648  //
649  // psi = [ (1 - m^2 ) / 4 ] [ D^{dag}(m) D(m) ]^{-1} chi
650  //
651  // = [ ( 1 - m^2 ) / 2 ] (2 D^{dag}(m))^{-1} D(m)^{-1} chi
652  //
653  // = [ ( 1 - m^2 ) / 2 ] ( 2 D(m))^{-1} D^{-dag}(m) chi
654 
655 
656  MInvRelCG(*MdagMPtr, chi, psi, shifted_masses, invParam.RsdCG, invParam.MaxCG, n_count);
657 
658  // Delete MdagMPtr. Do it right away before I forget.
659  delete MdagMPtr;
660 
661  if ( n_count == invParam.MaxCG ) {
662  QDP_error_exit("no convergence in the inverter", n_count);
663  }
664 
665  // Now make the solution(s)
666  switch(n_soln) {
667  case 4:
668 
669 
670  // Compensate for the 4/(1-m^2) factor
671 
672  for(int i = 0; i < n_mass; i++) {
673  psi[i] *= Real(4) / ( Real(1) - masses[i]*masses[i] );
674  }
675  break;
676 
677  case 3:
678  // Copy ofver the solutions of D^{-1} for solutions to D_dag^{-1}
679  for( int i = 0 ; i < n_mass; i++) {
680  psi[n_mass + i] = psi[i];
681  }
682  // Fall through to the case below:
683 
684  case 1:
685  case 2:
686  for(int iset=0; iset < nsets; iset++) {
687  for(int i=0; i < n_mass; i++) {
688  int j = i+iset*n_mass;
689  T tmp1;
690 
691  // Need to multiply:
692  //
693  // (2/(1-m^2)) (2D(m)) or (2/(1-m^2)) (2D^{dag}(m))
694  //
695  // as appropriate. D(m) = m + (1 - m) D(0)
696  //
697  // so 2D(m) = 2m + (1-m) 2D(0)
698  // = [1+m-(1-m)] + (1-m) 2D(0)
699  //
700  // and 2/(1-m^2) = 2/((1+m)(1-m)
701  //
702  // finally:
703  //
704  // (2/(1-m^2)) (2D(m))
705  // = 2/(1+m) * [ (1+m)/(1-m) - 1 + 2D(0) ]
706  // = 2/(1+m) * [ {(1+m)/(1-m) - 1} + M_scaled ]
707  //
708  //
709  (*M_scaled)(tmp1, psi[j], isign_set[iset]);
710 
711  ftmp = (Real(1) + masses[i])/(Real(1) - masses[i]) - Real(1);
712 
713  tmp1 += ftmp*psi[j];
714 
715  tmp1 *= Real(2)/(Real(1) + masses[i]);
716 
717 
718  // Subtract off contact term
719  psi[j] = tmp1 - chi;
720 
721  // overall noramalisation
722  ftmp = Real(1) / ( Real(1) - masses[i] );
723  psi[j] *= ftmp;
724 
725  }
726  }
727  break;
728  default:
729  QDP_error_exit("This value of n_soln is not known about %d\n", n_soln);
730  break;
731  } // End switch over n_soln;
732  }
733  break; // End of CG case
734 
735  case SUMR_INVERTER:
736  {
737 
738  /* Only do psi = D^(-1) chi */
739  if (n_soln != 1) {
740  QDP_error_exit("SUMMR inverter does not solve for D_dag");
741  }
742 
744 
745  multi1d<Complex> shifted_masses(n_mass);
746 
747  // This is the code from SZIN. I checked the shifts . Should work ok
748  for(int i=0; i < n_mass; ++i) {
749  shifted_masses[i] = (Real(1) + masses[i]) / ( Real(1) - masses[i] );
750  }
751 
752  // For the case of the overlap rho, is always 1
753  multi1d<Real> rho(n_mass);
754  rho = Real(1);
755 
756  multi1d<Real> scaledRsdCG(n_mass);
757  for(int i=0; i < n_mass; i++) {
758  scaledRsdCG[i] = RsdCG[i]*(Real(1) - masses[i])/Real(2);
759  }
760 
761  // Do the solve
762  MInvSUMR(*U, chi, psi, shifted_masses, rho, scaledRsdCG, invParam.MaxCG,n_count);
763 
764 #if 1
765  for(int s=0; s < n_mass; s++) {
766 
767  // Check back solutions
768  T r;
769  (*U)(r, psi[s], PLUS);
770  r *= rho[s];
771  r += shifted_masses[s]*psi[s];
772 
773 
774  r -= chi;
775  Double r_norm = sqrt(norm2(r))/sqrt(norm2(chi));
776  QDPIO::cout << "Check: shift="<<s<<" || r ||/||b|| = " << r_norm << " RsdCG = " << RsdCG[s] << std::endl;
777 
778  }
779 #endif
780 
781  /* psi <- (D^(-1) - 1) chi */
782  for(int i=0; i < n_mass; ++i) {
783 
784  // Go back to (1/2)( 1 + mu + (1 - mu) normalisation
785  ftmp = Real(2) / ( Real(1) - masses[i] );
786  psi[i] *= ftmp;
787 
788  // Remove conact term
789  psi[i] -= chi;
790 
791  // overall noramalisation
792  ftmp = Real(1) / ( Real(1) - masses[i] );
793  psi[i] *= ftmp;
794 
795  }
796  }
797  break; // End of MR inverter case
798  case REL_SUMR_INVERTER:
799  {
800 
801  /* Only do psi = D^(-1) chi */
802  if (n_soln != 1) {
803  QDP_error_exit("SUMMR inverter does not solve for D_dag");
804  }
805 
807 
808  multi1d<Complex> shifted_masses(n_mass);
809 
810  // This is the code from SZIN. I checked the shifts . Should work ok
811  for(int i=0; i < n_mass; ++i) {
812  shifted_masses[i] = (Real(1) + masses[i]) / ( Real(1) - masses[i] );
813  }
814 
815  // For the case of the overlap rho, is always 1
816  multi1d<Real> rho(n_mass);
817  rho = Real(1);
818 
819  // We are solving with a scaled operator
820  // shifted_masses[i] + gamma_5 eps
821  //
822  // which is the original scaled by 2/(1 - m)
823  //
824  // So I should rescale each desired RsdCG by (1-m)/2
825  // where m is the smallest mass.
826  multi1d<Real> scaledRsdCG(n_mass);
827  for(int i=0; i < n_mass; i++) {
828  scaledRsdCG[i] = RsdCG[i]*(1-masses[i])/Real(2);
829  }
830 
831  // Do the solve
832  MInvRelSUMR(*U, chi, psi, shifted_masses, rho, scaledRsdCG, invParam.MaxCG,n_count);
833 
834 #if 1
835  for(int s=0; s < n_mass; s++) {
836 
837  // Check back solutions
838  T r;
839  (*U)(r, psi[s], PLUS);
840  r *= rho[s];
841  r += shifted_masses[s]*psi[s];
842 
843  r -= chi;
844  Double r_norm = sqrt(norm2(r))/sqrt(norm2(chi));
845  QDPIO::cout << "Check: shift="<<s<<" || r ||/||b|| = " << r_norm << " RsdCG = " << RsdCG[s] << std::endl;
846 
847  }
848 #endif
849 
850 
851  /* psi <- (D^(-1) - 1) chi */
852  for(int i=0; i < n_mass; ++i) {
853 
854  // Go back to (1/2)( 1 + mu + (1 - mu) normalisation
855  ftmp = Real(2) / ( Real(1) - masses[i] );
856  psi[i] *= ftmp;
857 
858  // Remove conact term
859  psi[i] -= chi;
860 
861  // overall noramalisation
862  ftmp = Real(1) / ( Real(1) - masses[i] );
863  psi[i] *= ftmp;
864 
865  }
866  }
867  break; // End of MR inverter case
868 #if 0
869  case MR_INVERTER:
870  {
871 
872  /* psi = D^(-1) chi */
873  if (n_soln != 1) {
874  QDP_error_exit("MR inverter does not solve for D_dag");
875  }
876 
877  // This is the code from SZIN. I checked the shifts . Should work ok
878  multi1d<Real> shifted_masses(n_mass);
879  for(int i=0; i < n_mass; ++i) {
880  shifted_masses[i] = (Real(1) + masses[i]) / ( Real(1) - masses[i] ) - 1;
881  }
882 
883  // Do the solve
884  MInvMR (*M_scaled, chi, psi, shifted_masses, invParam.RsdCG, ncg_had);
885  if ( n_count == invParam.MaxCG ) {
886  QDP_error_exit("no convergence in the inverter", n_count);
887  }
888 
889  /* psi <- (D^(-1) - 1) chi */
890  for(i=0; i < n_mass; ++i) {
891 
892  // Go back to (1/2)( 1 + mu + (1 - mu) normalisation
893  ftmp = Real(2) / ( Real(1) - masses[i] );
894  psi[i] *= ftmp;
895 
896  // Remove conact term
897  psi[i] -= chi;
898 
899  // overall noramalisation
900  ftmp = Real(1) / ( Real(1) - masses[i] );
901  psi[i] *= ftmp;
902 
903  }
904  }
905  break; // End of MR inverter case
906 #endif
907 
908 
909  default:
910  QDP_error_exit("Unknown inverter type %d\n", invParam.invType);
911  }
912 #endif
913 
914 
915  END_CODE();
916  }
917 
918 } // End Namespace Chroma
919 
920 
Primary include file for CHROMA library code.
Support class for fermion actions and linear operators.
Definition: state.h:94
Class for counted reference semantics.
Definition: handle.h:33
M^dag.M linear operator.
Definition: lmdagm.h:22
virtual LinearOperator< T > * lgamma5epsH(Handle< FermState< T, P, Q > > state) const =0
Produce a linear operator that gives back gamma_5 eps(H)
void multiQprop(multi1d< T > &psi, const multi1d< Real > &masses, Handle< FermState< T, P, Q > > state, const T &chi, const GroupXML_t &invParam, const int n_soln, int &ncg_had) const
Define a multi mass qprop.
virtual UnprecLinearOperator< T, P, Q > * linOp(Handle< FermState< T, P, Q > > state) const
Override to produce a DWF-link unprec. linear operator for this action.
virtual DiffLinearOperator< T, P, Q > * lMdagM(Handle< FermState< T, P, Q > > state) const =0
virtual OverlapFermActBase * clone() const =0
Virtual copy constructor.
virtual Real getQuarkMass() const =0
Return the quark mass.
virtual bool isChiral() const =0
Does this object really satisfy the Ginsparg-Wilson relation?
SystemSolver< T > * qprop(Handle< FermState< T, P, Q > > state, const GroupXML_t &invParam) const
Redefine quark propagator routine for 4D fermions.
~Ovlap4DQprop()
Destructor is automatic.
multi1d< LatticeColorMatrix > P
SystemSolverResults_t operator()(LatticeFermion &psi, const LatticeFermion &chi) const
Solver the linear system.
Handle< FermState< T, P, Q > > state
const SysSolverCGParams invParam
const Subset & subset() const
Return the subset on which the operator acts.
Handle< OverlapFermActBase > S_f
Ovlap4DQprop(Handle< OverlapFermActBase > S_f_, Handle< FermState< T, P, Q > > state_, const SysSolverCGParams &invParam_)
Constructor.
multi1d< LatticeColorMatrix > Q
Linear system solvers.
Definition: syssolver.h:34
M^dag.M linear operator.
Definition: lmdagm.h:112
Scaled Linear Operator.
Definition: lopscl.h:61
Scaled Linear Operator.
Definition: lopscl.h:22
Real MRover
int mu
Definition: cool.cc:24
void MInvCG(const LinearOperator< LatticeFermion > &M, const LatticeFermion &chi, multi1d< LatticeFermion > &psi, const multi1d< Real > &shifts, const multi1d< Real > &RsdCG, int MaxCG, int &n_count)
Definition: minvcg.cc:407
SystemSolverResults_t InvCG1(const LinearOperator< LatticeFermion > &A, const LatticeFermion &chi, LatticeFermion &psi, const Real &RsdCG, int MaxCG, int MinCG)
Conjugate-Gradient (CGNE) algorithm for a generic Linear Operator.
Definition: invcg1.cc:215
SystemSolverResults_t InvCG2(const LinearOperator< LatticeFermionF > &M, const LatticeFermionF &chi, LatticeFermionF &psi, const Real &RsdCG, int MaxCG)
Conjugate-Gradient (CGNE) algorithm for a generic Linear Operator.
Definition: invcg2.cc:240
void InvRelCG2(const LinearOperator< LatticeFermion > &M, const LatticeFermion &chi, LatticeFermion &psi, const Real &RsdCG, int MaxCG, int &n_count)
Relaxed Conjugate-Gradient (CGNE) algorithm for a generic Linear Operator.
Definition: inv_rel_cg2.cc:175
void InvRelCG1(const LinearOperator< LatticeFermion > &A, const LatticeFermion &chi, LatticeFermion &psi, const Real &RsdCG, int MaxCG, int &n_count)
Conjugate-Gradient (CGNE) algorithm for a generic Linear Operator.
Definition: inv_rel_cg1.cc:144
SystemSolverResults_t InvMR(const LinearOperator< LatticeFermion > &M, const LatticeFermion &chi, LatticeFermion &psi, const Real &MRovpar, const Real &RsdMR, int MaxMR, enum PlusMinus isign)
Minimal-residual (MR) algorithm for a generic Linear Operator.
Definition: invmr.cc:185
void MInvMR(const LinearOperator< LatticeFermion > &M, const LatticeFermion &chi, multi1d< LatticeFermion > &psi, const multi1d< Real > &shifts, const multi1d< Real > &RsdMR, int MaxMR, int &n_count)
Multishift Conjugate-Gradient (CG1) algorithm for a Linear Operator.
Definition: minvmr.cc:258
Conjugate-Gradient algorithm for a generic Linear Operator.
Conjugate-Gradient algorithm for a generic Linear Operator.
Relaxed GMRESR algorithm of the Wuppertal Group.
Relaxed GMRESR algorithm of the Wuppertal Group.
Conjugate-Gradient algorithm for a generic Linear Operator.
Conjugate-Gradient algorithm for a generic Linear Operator.
Conjugate-Gradient algorithm for a generic Linear Operator.
Conjugate-Gradient algorithm for a generic Linear Operator.
unsigned j
Definition: ldumul_w.cc:35
unsigned n
Definition: ldumul_w.cc:36
Conjugate-Gradient algorithm for a generic Linear Operator.
Multishift Conjugate-Gradient algorithm for a Linear Operator.
Conjugate-Gradient algorithm for a generic Linear Operator.
Params of CG inverter.
Asqtad Staggered-Dirac operator.
Definition: klein_gord.cc:10
const WilsonTypeFermAct< multi1d< LatticeFermion > > Handle< const ConnectState > const multi1d< Real > enum InvType invType const multi1d< Real > & RsdCG
Definition: pbg5p_w.cc:30
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)
Chirality
Definition: ischiral_w.h:8
@ CH_NONE
Definition: ischiral_w.h:8
void MInvSUMR(const LinearOperator< LatticeFermion > &U, const LatticeFermion &b, multi1d< LatticeFermion > &x, const multi1d< Complex > &zeta, const multi1d< Real > &rho, const multi1d< Real > &epsilon, int MaxSUMR, int &n_count)
Definition: minvsumr.cc:359
void InvRelGMRESR_SUMR(const LinearOperator< LatticeFermion > &PrecU, const Complex &zeta, const Real &rho, const LinearOperator< LatticeFermion > &UnprecU, const LatticeFermion &b, LatticeFermion &x, const Real &epsilon, const Real &epsilon_prec, int MaxGMRESR, int MaxGMRESRPrec, int &n_count)
int n_count
Definition: invbicg.cc:78
LatticeFermion tmp
Definition: mespbg5p_w.cc:36
int ichiral
Definition: mespbp_s.cc:21
void InvRelSUMR(const LinearOperator< LatticeFermion > &U, const LatticeFermion &b, LatticeFermion &x, const Complex &zeta, const Real &rho, const Real &epsilon, int MaxSUMR, int &n_count)
int i
Definition: pbg5p_w.cc:55
Double mass
Definition: pbg5p_w.cc:54
@ MINUS
Definition: chromabase.h:45
@ PLUS
Definition: chromabase.h:45
Chirality isChiralVector(const LatticeFermion &chi)
Definition: ischiral_w.cc:6
multi1d< LatticeFermion > chi(Ncb)
void InvRelGMRESR_CG(const LinearOperator< LatticeFermion > &PrecMM, const LinearOperator< LatticeFermion > &UnprecMM, const LatticeFermion &b, LatticeFermion &x, const Real &epsilon, const Real &epsilon_prec, int MaxGMRESR, int MaxGMRESRPrec, int &n_count)
LatticeFermion psi
Definition: mespbg5p_w.cc:35
void MInvRelSUMR(const LinearOperator< LatticeFermion > &U, const LatticeFermion &b, multi1d< LatticeFermion > &x, const multi1d< Complex > &zeta, const multi1d< Real > &rho, const multi1d< Real > &epsilon, int MaxSUMR, int &n_count)
void MInvRelCG(const LinearOperator< LatticeFermion > &M, const LatticeFermion &chi, multi1d< LatticeFermion > &psi, const multi1d< Real > &shifts, const multi1d< Real > &RsdCG, int MaxCG, int &n_count)
Definition: minv_rel_cg.cc:410
void InvSUMR(const LinearOperator< LatticeFermion > &U, const LatticeFermion &b, LatticeFermion &x, const Complex &zeta, const Real &rho, const Real &epsilon, int MaxSUMR, int &n_count)
Definition: invsumr.cc:241
START_CODE()
const WilsonTypeFermAct< multi1d< LatticeFermion > > Handle< const ConnectState > state
Definition: pbg5p_w.cc:28
Double zero
Definition: invbicg.cc:106
multi1d< LatticeFermion > s(Ncb)
FloatingPoint< double > Double
Definition: gtest.h:7351
Base class for unpreconditioned overlap-like fermion actions.
Double r_norm
Definition: pade_trln_w.cc:86
Hold group xml and type id.
Params for CG inverter.
Holds return info from SystemSolver call.
Definition: syssolver.h:17
Solve a CG1 system.
multi1d< LatticeColorMatrix > U