CHROMA
eoprec_ht_contfrac5d_fermact_array_w.cc
Go to the documentation of this file.
1 /*! \file
2  * \brief Unpreconditioned extended-Overlap (5D) (Naryanan&Neuberger) action
3  */
4 
5 #include "chromabase.h"
6 
12 // #include "actions/ferm/linop/eoprec_ovlap_contfrac5d_pv_linop_array_w.h"
14 #include "zolotarev.h"
15 
18 
20 
21 namespace Chroma
22 {
23 
24  //! Hooks to register the class with the fermact factory
25  namespace EvenOddPrecHtContFrac5DFermActArrayEnv
26  {
27  //! Callback function
28  WilsonTypeFermAct5D<LatticeFermion,
29  multi1d<LatticeColorMatrix>,
30  multi1d<LatticeColorMatrix> >* createFermAct5D(XMLReader& xml_in,
31  const std::string& path)
32  {
35  }
36 
37  //! Callback function
38  /*! Differs in return type */
39  FermionAction<LatticeFermion,
40  multi1d<LatticeColorMatrix>,
41  multi1d<LatticeColorMatrix> >* createFermAct(XMLReader& xml_in,
42  const std::string& path)
43  {
44  return createFermAct5D(xml_in, path);
45  }
46 
47  //! Name to be used
48  const std::string name = "HT_CONTINUED_FRACTION_5D";
49 
50  //! Local registration flag
51  static bool registered = false;
52 
53  //! Register all the factories
54  bool registerAll()
55  {
56  bool success = true;
57  if (! registered)
58  {
59  success &= Chroma::TheFermionActionFactory::Instance().registerObject(name, createFermAct);
61  registered = true;
62  }
63  return success;
64  }
65 
66  } // End Namespace EvenOddPrecHtContFrac5DFermActArrayEnv
67 
68 
69  //! Read XML
71  const std::string& path)
72  {
73  XMLReader in(xml, path);
74 
75  try
76  {
77  read(in, "Mass", Mass);
78  read(in, "RatPolyDeg", RatPolyDeg);
79  read(in, "OverMass", OverMass);
80 
81  if( in.count("ApproximationType") == 1 )
82  {
83  read(in, "ApproximationType", approximation_type);
84  }
85  else
86  {
87  // Default coeffs are unscaled tanh
89  }
90 
92  {
93  read(in, "ApproxMin", ApproxMin);
94  read(in, "ApproxMax", ApproxMax);
95  }
96  else
97  {
98  ApproxMin = ApproxMax = 0.0;
99  }
100 
101  int count_b5 = in.count("b5");
102  int count_c5 = in.count("c5");
103 
104  if( count_b5 == 0 && count_c5 == 0 )
105  {
106  QDPIO::cout << "b5 and c5 not specified. Using Shamir values: b5=1 c5=0" << std::endl;
107  b5 = Real(1);
108  c5 = Real(0);
109  }
110  else {
111  read(in, "b5", b5);
112  read(in, "c5", c5);
113  }
114  }
115  catch( const std::string &e ) {
116  QDPIO::cerr << "Caught Exception reading HT ContFrac Fermact params: " << e << std::endl;
117  QDP_abort(1);
118  }
119  }
120 
121  void read(XMLReader& xml_in, const std::string& path,
123  {
124 
126  param = tmp;
127  }
128 
129  void write(XMLWriter& xml_out, const std::string& path, const EvenOddPrecHtContFrac5DFermActParams& p)
130  {
131  if ( path != "." ) {
132  push( xml_out, path);
133  }
134 
135  write(xml_out, "Mass", p.Mass);
136  write(xml_out, "OverMass", p.OverMass);
137  write(xml_out, "RatPolyDeg", p.RatPolyDeg);
138  write(xml_out, "ApproximationType", p.approximation_type);
139  write(xml_out, "b5", p.b5);
140  write(xml_out, "c5", p.c5);
141  write(xml_out, "ApproxMin", p.ApproxMin);
142  write(xml_out, "ApproxMax", p.ApproxMax);
143 
144  pop(xml_out);
145 
146 
147  if( path != "." ) {
148  pop(xml_out);
149  }
150  }
151 
152 
153 
154  // Construct the action out of a parameter structure
156  Handle< CreateFermState<T,P,Q> > fs_a_,
157  const EvenOddPrecHtContFrac5DFermActParams& params_) :
158  fs(fs_a_), params(params_)
159  {
160 
161  // WHAT IS BELOW ONLY WORKS FOR TYPE=0 approximations
162  // which is what we use. Forget TYPE=1
163  // the Tanh approximation (Higham) is of type TYPE=0
164  // We have two cases.
165  bool isEvenRatPolyDeg = ( params.RatPolyDeg % 2 == 0);
166 
167  if( isEvenRatPolyDeg ) {
168  N5 = params.RatPolyDeg+1;
169  isLastZeroP = true;
170  }
171  else {
172  N5 = params.RatPolyDeg;
173  isLastZeroP = false;
174  }
175  }
176 
177 
178  void
180  multi1d<Real>& alpha,
181  multi1d<Real>& beta) const
182  {
183  int type = 0;
184  zolotarev_data *rdata;
185  Real epsilon;
186 
187  Real approxMin = params.ApproxMin;
188  Real approxMax = params.ApproxMax;
189 
190  switch(params.approximation_type)
191  {
193  epsilon = approxMin / approxMax;
194  QDPIO::cout << "Initing Linop with Zolotarev Coefficients: epsilon = " << epsilon << std::endl;
195  rdata = zolotarev(toFloat(epsilon), params.RatPolyDeg, type);
196  scale_fac = Real(1) / approxMax;
197  break;
198 
200  epsilon = approxMin;
201  QDPIO::cout << "Initing Linop with Higham Rep tanh Coefficients" << std::endl;
202  rdata = higham(toFloat(epsilon), params.RatPolyDeg);
203  scale_fac = Real(1);
204  break;
205 
206  default:
207  // The std::map system should ensure that we never get here but
208  // just for style
209  QDPIO::cerr << "Unknown coefficient type: " << params.approximation_type
210  << std::endl;
211  QDP_abort(1);
212  }
213 
214  Real maxerr = (Real)(rdata->Delta);
215 
216  // Check N5 is good:
217  if( N5 != rdata->db ) {
218  QDPIO::cerr << "Mismatch between N5 and N5 from Coefficient Code" << std::endl;
219  QDPIO::cerr << "N5 = " << N5 << " rdata->db=" << rdata->db << std::endl;
220  QDP_abort(1);
221  }
222 
223  // The coefficients from the continued fraction
224  beta.resize(N5);
225  for(int i = 0; i < N5; i++) {
226  beta[i] = rdata->beta[i];
227  }
228 
229  alpha.resize(N5-1);
230  for(int i=0; i < N5-1; i++) {
231  alpha[i] = Real(1);
232  }
233 
234  // The gamma's are the equivalence transforms
235  // There are N5-1 of them and they appear in the
236  // diagonal terms as gamma^2
237  // and in the off diagonal terms as gamma_i gamma_i+1
238  // except in the last one which is just gamma
239  //
240  // For the moment choose gamma_i = 1/sqrt(beta_i) */
241 
242  multi1d<Real> gamma(N5-1);
243  for(int i=0; i < N5-1; i++) {
244  gamma[i] = Real(1)/ sqrt( beta[i] );
245  }
246 
247  // Now perform the equivalence transformation
248  //
249  // On the diagonal coefficients
250  // Note that beta[N5-1] is NOT changed
251  for(int i=0; i < N5-1; i++) {
252  beta[i] = beta[i]*gamma[i]*gamma[i];
253  }
254 
255  // and the off diagonal ones
256  // from 0..N5-3 we have gamma_i gamma_i+1
257  // and on N5-2 we have gamma_i
258  for(int i=0; i < N5-2; i++) {
259  alpha[i] *= gamma[i]*gamma[i+1];
260  }
261  alpha[N5-2] *= gamma[N5-2];
262 
263  QDPIO::cout << "EvenOddPrecHtContfrac5d: " << std::endl
264  << " Degree="<< params.RatPolyDeg
265  << " N5=" << N5 << " scale=" << scale_fac
266  << " Mass=" << params.Mass << std::endl
267  << " OverMass=" << params.OverMass
268  << " IsLastZeroP=" << isLastZeroP << std::endl;
269 
270  QDPIO::cout << "Approximation on [-1,eps] U [eps,1] with eps = " << epsilon <<std::endl;
271 
272  QDPIO::cout << "Maximum error | R(x) - sgn(x) | <= Delta = " << maxerr << std::endl;
273  /*
274  for(int i=0; i < N5; i++) {
275  QDPIO::cout << "beta["<<i<<"] = " << beta[i] << std::endl;
276  }
277  for(int i=0; i < N5; i++) {
278  QDPIO::cout << "alpha["<<i<<"] = " << alpha[i] << std::endl;
279  }
280  */
281 
282  switch( params.approximation_type) {
284  QDPIO::cout << "Coefficients from Zolotarev" << std::endl;
285 
286  if(type == 0) {
287  QDPIO::cout << "Approximation type " << type << " with R(0) = 0"
288  << std::endl;
289  }
290  else {
291  QDPIO::cout << "Approximation type " << type << " with R(0) = infinity" << std::endl;
292  }
293 
294  break;
295  case COEFF_TYPE_TANH:
296  QDPIO::cout << "Coefficients from Higham Tanh representation" << std::endl;
297  break;
299  QDPIO::cout << "Coefficients from Unscaled Higham Tanh representation" << std::endl;
300  break;
301  default:
302  QDPIO::cerr << "Unknown coefficient type " << params.approximation_type
303  << std::endl;
304  QDP_abort(1);
305  break;
306  }
307 
308  // free the arrays allocated by Tony's Zolo
309  zolotarev_free(rdata);
310  }
311 
312  //! Produce a linear operator for this action
313  /*!
314  * \param state gauge field (Read)
315  */
317  multi1d<LatticeColorMatrix>,
318  multi1d<LatticeColorMatrix> >*
320  {
321  START_CODE();
322 
323  multi1d<Real> alpha;
324  multi1d<Real> beta;
325  Real scale_factor;
326 
327  init(scale_factor, alpha, beta);
328 
329  return new EvenOddPrecHtContFrac5DLinOpArray(state_,
330  params.Mass,
332  N5,
333  scale_factor,
334  alpha,
335  beta,
336  params.b5,
337  params.c5,
338  isLastZeroP);
339  }
340 
341 
342  //! Produce a Pauli-Villars linear operator for this action
343  /*!
344  * \param state gauge field (Read)
345  */
347  multi1d<LatticeColorMatrix>,
348  multi1d<LatticeColorMatrix> >*
350  {
351 #if 0
352  multi1d<Real> alpha;
353  multi1d<Real> beta;
354  Real scale_factor;
355 
356  init(scale_factor, alpha, beta);
357 
358  // Hmm, not sure about what all the rescaling does to the PV....
359  return new EvenOddPrecHtContFrac5DPVLinOpArray(state_,
360  params.Mass,
362  N5,
363  scale_factor,
364  alpha,
365  beta,
366  isLastZeroP);
367 #endif
368 
369  QDPIO::cerr << "Not yet implemented PV stuff for prec_ht_contfrac" << std::endl;
370  QDP_abort(1);
371 
372  // Should never get here... Just to satisfy type system
373  return 0;
374  }
375 
376 
377 
378  //! Propagator of an un-preconditioned Extended-Overlap linear operator
379  /*! \ingroup qprop
380  *
381  * Propagator solver for DWF-like fermions
382  */
383  template<typename T, typename P, typename Q>
384  class HtContFrac5DQprop : public SystemSolver<T>
385  {
386  public:
387  //! Constructor
388  /*!
389  * \param A_ Linear operator ( Read )
390  * \param Mass_ quark mass ( Read )
391  */
393  Handle< LinearOperator<T> > D_denum_,
394  const Real& Mass_,
395  const SysSolverCGParams& invParam_) :
396  A(A_), D_denum(D_denum_), Mass(Mass_), invParam(invParam_) {}
397 
398  //! Destructor is automatic
400 
401  //! Return the subset on which the operator acts
402  const Subset& subset() const {return all;}
403 
404  //! Solver the linear system
405  /*!
406  * \param psi quark propagator ( Modify )
407  * \param chi source ( Read )
408  * \return number of CG iterations
409  */
411  {
412  START_CODE();
413 
415  const int N5 = A->size();
416 
417  int G5 = Ns*Ns - 1;
418 
419  // Initialize the 5D fields
420  multi1d<T> chi5(N5);
421  multi1d<T> psi5(N5);
422 
423 // if( invType == "CG_INVERTER")
424  {
425  multi1d<T> tmp5_1(N5);
426  {
427  multi1d<T> tmp5_2(N5);
428  multi1d<T> tmp5_3(N5);
429 
430  chi5 = zero;
431  psi5 = zero;
432  tmp5_1 = zero;
433 
434  // Need to prepare the source
435  {
436  LatticeFermion tmp4 = Gamma(G5)*chi;
437  (*D_denum)(tmp5_1[N5-1], tmp4, MINUS);
438  }
439 
440  A->evenEvenInvLinOp(tmp5_2, tmp5_1, PLUS);
441  A->oddEvenLinOp(tmp5_3, tmp5_2, PLUS);
442 
443 
444  // chi5_e = S_e
445  // chi5_o = S_o - QoeQee^{-1} S_e
446  for(int i=0; i < N5; i++) {
447  chi5[i][rb[0]] = tmp5_1[i];
448  chi5[i][rb[1]] = tmp5_1[i] - tmp5_3[i];
449  }
450  } // tmp5_2 and tmp5_3 go away
451 
452  psi5[N5-1][rb[1]] = psi;
453  (*A)(tmp5_1, chi5, MINUS);
454 
455  // Solve M^{+}M psi = M^{+} chi
456  res = InvCG2(*A, tmp5_1, psi5, invParam.RsdCG, invParam.MaxCG);
457 
458 
459  // psi[N5-1]_odd now holds the desired piece.
460 
461  // Reconstruct psi[N5-1]_e = Q_ee^{-1} S_e - Q_ee^{-1}Q_eo psi[N5-1]_o
462  // = Q_ee^{-1} ( S_e - Q_eo psi_o )
463  {
464 
465  // Dont need to initialise as the parts I use
466  // will be over written the other parts I ignore
467  multi1d<T> tmp5_2(N5);
468  multi1d<T> tmp5_3(N5);
469 
470  // tmp5_2_e = Qeo psi_o
471  A->evenOddLinOp(tmp5_2, psi5, PLUS);
472  for(int i=0; i < N5; i++) {
473 
474  // tmp5_3_e = S_e - Qeo psi_o
475  // = - tmp5_2_e
476  tmp5_3[i][rb[0]] = chi5[i] - tmp5_2[i];
477 
478  }
479 
480  // tmp5_1_e = Qee^{-1} ( S_e - Qeo psi_o )
481  A->evenEvenInvLinOp(tmp5_1, tmp5_3, PLUS);
482 
483  // psi5_e = tmp5_1
484  for(int i=0; i < N5; i++) {
485  psi5[i][rb[0]] = tmp5_1[i];
486  }
487  } // tmp5_2, tmp5_3 disappear
488  } // tmp5_1 disappears
489 // else
490 // {
491 // QDPIO::cerr << EvenOddPrecHtContFrac5DFermActArrayEnv::name
492 // << "Unsupported inverter type =" << invParam.invType << std::endl;
493 // QDP_abort(1);
494 // }
495 
496  if ( res.n_count == invParam.MaxCG )
497  QDP_error_exit("no convergence in the inverter", res.n_count);
498 
499 #if 0
500  // Compute residual
501  {
502  multi1d<T> r(N5);
503  A->unprecLinOp(r, psi5, PLUS);
504  r -= chi5;
505  res.resid = sqrt(norm2(r));
506  }
507 #else
508  res.resid = zero;
509 #endif
510 
511  // Solution now lives in chi5
512 
513  // Multiply back in factor 2/(1-m) to return to
514  // (1/2)( 1 + m + (1-m) gamma_5 epsilon )
515  // normalisation
516  psi5[N5-1] *= Real(2)/(Real(1)-Mass);
517 
518  // Remove contact term
519  psi = psi5[N5-1] - chi;
520 
521  // Overall normalization
522  Real ftmp1 = Real(1) / (Real(1) - Mass);
523  psi *= ftmp1;
524 
525  END_CODE();
526 
527  return res;
528  }
529 
530  private:
531  // Hide default constructor
533 
536  const Real Mass;
538  };
539 
540 
541  //! Propagator of an un-preconditioned Extended-Overlap linear operator
544  const GroupXML_t& invParam) const
545  {
546  Real a5 = params.b5- params.c5;
547  Real WilsonMass = -params.OverMass ;
548  Handle< LinearOperator<T> > D_w(new UnprecWilsonLinOp(state, WilsonMass));
550 
551  std::istringstream is(invParam.xml);
552  XMLReader paramtop(is);
553 
555  D_denum,
556  getQuarkMass(),
557  SysSolverCGParams(paramtop, invParam.path));
558  }
559 
560 } // End namespace Chroma
Primary include file for CHROMA library code.
Create a fermion connection state.
Definition: create_state.h:69
Even-odd preconditioned linear operator including derivatives for arrays.
5D continued fraction overlap action (Borici,Wenger, Edwards)
SystemSolver< LatticeFermion > * qprop(Handle< FermState< T, P, Q > > state, const GroupXML_t &invParam) const
Compute quark propagator over base type.
EvenOddPrecConstDetLinearOperatorArray< T, P, Q > * linOp(Handle< FermState< T, P, Q > > state) const
Produce a linear operator for this action.
void init(Real &scale_fac, multi1d< Real > &alpha, multi1d< Real > &beta) const
Helper in construction.
EvenOddPrecConstDetLinearOperatorArray< T, P, Q > * linOpPV(Handle< FermState< T, P, Q > > state) const
Produce a Pauli-Villars linear operator for this action.
Even odd preconditioned Continued Fraction with H=H_t (Shamir Kernel)
Support class for fermion actions and linear operators.
Definition: state.h:94
Base class for quadratic matter actions (e.g., fermions)
Definition: fermact.h:53
Class for counted reference semantics.
Definition: handle.h:33
Propagator of an un-preconditioned Extended-Overlap linear operator.
const Subset & subset() const
Return the subset on which the operator acts.
HtContFrac5DQprop(Handle< EvenOddPrecConstDetLinearOperatorArray< T, P, Q > > A_, Handle< LinearOperator< T > > D_denum_, const Real &Mass_, const SysSolverCGParams &invParam_)
Constructor.
Handle< EvenOddPrecConstDetLinearOperatorArray< T, P, Q > > A
SystemSolverResults_t operator()(T &psi, const T &chi) const
Solver the linear system.
Linear Operator.
Definition: linearop.h:27
static T & Instance()
Definition: singleton.h:432
Linear system solvers.
Definition: syssolver.h:34
Operator to apply the denominator.
Unpreconditioned Wilson-Dirac operator.
Wilson-like fermion actions.
Definition: fermact.orig.h:403
Even-odd preconditioned Continued Fraction 5D.
Unpreconditioned extended-Overlap (5D) (Naryanan&Neuberger) linear operator.
All ferm create-state method.
Fermion action factories.
void read(XMLReader &xml, const std::string &path, AsqtadFermActParams &param)
Read parameters.
void write(XMLWriter &xml, const std::string &path, const AsqtadFermActParams &param)
Writer parameters.
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
@ COEFF_TYPE_ZOLOTAREV
@ COEFF_TYPE_TANH
@ COEFF_TYPE_TANH_UNSCALED
Params params
Conjugate-Gradient algorithm for a generic Linear Operator.
Handle< CreateFermState< LatticeFermion, multi1d< LatticeColorMatrix >, multi1d< LatticeColorMatrix > > > reader(XMLReader &xml_in, const std::string &path)
Helper function for the CreateFermState readers.
FermionAction< LatticeFermion, multi1d< LatticeColorMatrix >, multi1d< LatticeColorMatrix > > * createFermAct(XMLReader &xml_in, const std::string &path)
Callback function.
WilsonTypeFermAct5D< LatticeFermion, multi1d< LatticeColorMatrix >, multi1d< LatticeColorMatrix > > * createFermAct5D(XMLReader &xml_in, const std::string &path)
Callback function.
int epsilon(int i, int j, int k)
static const LatticeInteger & beta(const int dim)
Definition: stag_phases_s.h:47
static const LatticeInteger & alpha(const int dim)
Definition: stag_phases_s.h:43
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
LatticeFermion tmp
Definition: mespbg5p_w.cc:36
push(xml_out,"Condensates")
LinOpSysSolverMGProtoClover::T T
int i
Definition: pbg5p_w.cc:55
@ MINUS
Definition: chromabase.h:45
@ PLUS
Definition: chromabase.h:45
multi1d< LatticeFermion > chi(Ncb)
LatticeFermion psi
Definition: mespbg5p_w.cc:35
pop(xml_out)
START_CODE()
const WilsonTypeFermAct< multi1d< LatticeFermion > > Handle< const ConnectState > state
Definition: pbg5p_w.cc:28
Double zero
Definition: invbicg.cc:106
static QDP_ColorVector * in
::std::string string
Definition: gtest.h:1979
CoeffType approximation_type
ZOLOTAREV | TANH | Other approximation coeffs.
Hold group xml and type id.
Params for CG inverter.
Holds return info from SystemSolver call.
Definition: syssolver.h:17
Solve a CG1 system.
Double ftmp1
Definition: topol.cc:29
Unpreconditioned Wilson fermion linear operator.
Unpreconditioned Wilson fermion action.
Unpreconditioned Wilson fermion linear operator.
void zolotarev_free(ZOLOTAREV_DATA *f)
ZOLOTAREV_DATA * higham(PRECISION epsilon, int n)
ZOLOTAREV_DATA * zolotarev(PRECISION epsilon, int n, int type)