CHROMA
unprec_ht_contfrac5d_fermact_array_w.cc
Go to the documentation of this file.
1 /*! \file
2  * \brief Unpreconditioned H_T kernel continued fraction (5D) action
3  */
4 
5 #include "chromabase.h"
6 
9 
13 
15 #include "zolotarev.h"
16 
19 
20 #include "io/enum_io/enum_io.h"
21 
23 
24 namespace Chroma
25 {
26 
27  //! Hooks to register the class with the fermact factory
28  namespace UnprecHTContFrac5DFermActArrayEnv
29  {
30  //! Callback function
31  WilsonTypeFermAct5D<LatticeFermion,
32  multi1d<LatticeColorMatrix>,
33  multi1d<LatticeColorMatrix> >* createFermAct5D(XMLReader& xml_in,
34  const std::string& path)
35  {
37  UnprecHTContFrac5DFermActParams(xml_in, path));
38  }
39 
40  //! Callback function
41  /*! Differs in return type */
42  FermionAction<LatticeFermion,
43  multi1d<LatticeColorMatrix>,
44  multi1d<LatticeColorMatrix> >* createFermAct(XMLReader& xml_in,
45  const std::string& path)
46  {
47  return createFermAct5D(xml_in, path);
48  }
49 
50  //! Name to be used
51  const std::string name = "UNPRECONDITIONED_HT_CONTINUED_FRACTION_5D";
52 
53  //! Local registration flag
54  static bool registered = false;
55 
56  //! Register all the factories
57  bool registerAll()
58  {
59  bool success = true;
60  if (! registered)
61  {
62  success &= Chroma::TheFermionActionFactory::Instance().registerObject(name, createFermAct);
64  registered = true;
65  }
66  return success;
67  }
68  } // End Namespace UnprecHTContFrac5DFermActArrayEnv
69 
70 
71  //! Read XML
73  {
74  XMLReader in(xml, path);
75 
76  try
77  {
78  read(in, "Mass", Mass);
79  read(in, "RatPolyDeg", RatPolyDeg);
80  read(in, "OverMass", OverMass);
81 
82  if( in.count("ApproximationType") == 1 )
83  {
84  read(in, "ApproximationType", approximation_type);
85  }
86  else
87  {
88  // Default coeffs are unscaled tanh
90  }
91 
93  {
94  read(in, "ApproxMin", ApproxMin);
95  read(in, "ApproxMax", ApproxMax);
96  }
97  else
98  {
99  ApproxMin = ApproxMax = 0.0;
100  }
101 
102  int count_b5 = in.count("b5");
103  int count_c5 = in.count("c5");
104 
105  if( count_b5 == 0 && count_c5 == 0 )
106  {
107  QDPIO::cout << "b5 and c5 not specified. Using Shamir values: b5=1 c5=0" << std::endl;
108  b5 = Real(1);
109  c5 = Real(0);
110  }
111  else {
112  read(in, "b5", b5);
113  read(in, "c5", c5);
114  }
115 
116  }
117  catch( const std::string &e ) {
118  QDPIO::cerr << "Caught Exception reading Unprec HT ContFrac Fermact params: " << e << std::endl;
119  QDP_abort(1);
120  }
121  }
122 
123 
124  void read(XMLReader& xml_in, const std::string& path,
126  {
127  UnprecHTContFrac5DFermActParams tmp(xml_in, path);
128  param = tmp;
129  }
130 
131 
132  void write(XMLWriter& xml_out, const std::string& path, const UnprecHTContFrac5DFermActParams& p)
133  {
134  if ( path != "." ) {
135  push( xml_out, path);
136  }
137 
138  write(xml_out, "OverMass", p.OverMass);
139  write(xml_out, "Mass", p.Mass);
140  write(xml_out, "RatPolyDeg", p.RatPolyDeg);
141  write(xml_out, "ApproximationType", p.approximation_type);
142  write(xml_out, "b5", p.b5);
143  write(xml_out, "c5", p.c5);
144  write(xml_out, "ApproxMin", p.ApproxMin);
145  write(xml_out, "ApproxMax", p.ApproxMax);
146 
147  pop(xml_out);
148 
149 
150  if( path != "." ) {
151  pop(xml_out);
152  }
153  }
154 
155 
156 
157  // Construct the action out of a parameter structure
159  Handle< CreateFermState<T,P,Q> > cfs_a_,
160  const UnprecHTContFrac5DFermActParams& params_) :
161  cfs(cfs_a_), params(params_)
162  {
163  // WHAT IS BELOW ONLY WORKS FOR TYPE=0 approximations
164  // which is what we use. Forget TYPE=1
165  // the Tanh approximation (Higham) is of type TYPE=0
166  // We have two cases.
167  bool isEvenRatPolyDeg = ( params.RatPolyDeg % 2 == 0);
168 
169  if( isEvenRatPolyDeg )
170  {
171  N5 = params.RatPolyDeg+1;
172  isLastZeroP = true;
173  }
174  else
175  {
176  N5 = params.RatPolyDeg;
177  isLastZeroP = false;
178  }
179  }
180 
181 
182  void
184  multi1d<Real>& beta) const
185  {
186  int type = 0;
187 
188  zolotarev_data *rdata;
189  Real epsilon;
190  Real scale_fac;
191 
192  switch(params.approximation_type)
193  {
196  QDPIO::cout << "Initing Linop with Zolotarev Coefficients: epsilon = " << epsilon << std::endl;
197  rdata = zolotarev(toFloat(epsilon), params.RatPolyDeg, type);
198  scale_fac = Real(1) / params.ApproxMax;
199  break;
200 
203  QDPIO::cout << "Initing Linop with Higham Rep tanh Coefficients" << std::endl;
204  rdata = higham(toFloat(epsilon), params.RatPolyDeg);
205  scale_fac = Real(1);
206  break;
207 
208  default:
209  // The std::map system should ensure that we never get here but
210  // just for style
211  QDPIO::cerr << "Unknown coefficient type: " << params.approximation_type
212  << std::endl;
213  QDP_abort(1);
214  }
215 
216  Real maxerr = (Real)(rdata->Delta);
217 
218  // Check N5 is good:
219  if( N5 != rdata->db ) {
220  QDPIO::cerr << "Mismatch between N5 and N5 from Coefficient Code" << std::endl;
221  QDPIO::cerr << "N5 = " << N5 << " rdata->db=" << rdata->db << std::endl;
222  QDP_abort(1);
223  }
224 
225  // The coefficients from the continued fraction
226  beta.resize(N5);
227  for(int i = 0; i < N5; i++) {
228  beta[i] = rdata->beta[i];
229  }
230 
231  alpha.resize(N5-1);
232  for(int i=0; i < N5-1; i++) {
233  alpha[i] = Real(1);
234  }
235 
236  // The gamma's are the equivalence transforms
237  // There are N5-1 of them and they appear in the
238  // diagonal terms as gamma^2
239  // and in the off diagonal terms as gamma_i gamma_i+1
240  // except in the last one which is just gamma
241  //
242  // For the moment choose gamma_i = 1/sqrt(beta_i) */
243 
244  multi1d<Real> gamma(N5-1);
245  for(int i=0; i < N5-1; i++) {
246  gamma[i] = Real(1)/ sqrt( beta[i] );
247  }
248 
249  // Now perform the equivalence transformation
250  //
251  // On the diagonal coefficients
252  // Note that beta[N5-1] is NOT changed
253  for(int i=0; i < N5-1; i++) {
254  beta[i] = beta[i]*gamma[i]*gamma[i];
255  }
256 
257  // and the off diagonal ones
258  // from 0..N5-3 we have gamma_i gamma_i+1
259  // and on N5-2 we have gamma_i
260  for(int i=0; i < N5-2; i++) {
261  alpha[i] *= gamma[i]*gamma[i+1];
262  }
263  alpha[N5-2] *= gamma[N5-2];
264 
265 
266  // Rescale the diagonal terms
267  for(int i=0; i < beta.size(); i++) {
268  beta[i] *= scale_fac;
269  }
270 
271  QDPIO::cout << "UnprecHTContfrac5d:" << std::endl
272  << " Degree=" << params.RatPolyDeg
273  << " N5=" << N5 << " scale=" << scale_fac
274  << " Mass=" << params.Mass << std::endl ;
275  QDPIO::cout << "Approximation on [-1,eps] U [eps,1] with eps = " << epsilon <<std::endl;
276 
277  QDPIO::cout << "Maximum error | R(x) - sgn(x) | <= Delta = " << maxerr << std::endl;
278  /*
279  for(int i=0; i < N5; i++) {
280  QDPIO::cout << "beta["<<i<<"] = " << beta[i] << std::endl;
281  }
282  for(int i=0; i < N5; i++) {
283  QDPIO::cout << "alpha["<<i<<"] = " << alpha[i] << std::endl;
284  }
285  */
286 
287  switch( params.approximation_type) {
289  QDPIO::cout << "Coefficients from Zolotarev" << std::endl;
290 
291  if(type == 0) {
292  QDPIO::cout << "Approximation type " << type << " with R(0) = 0"
293  << std::endl;
294  }
295  else {
296  QDPIO::cout << "Approximation type " << type << " with R(0) = infinity"
297  << std::endl;
298  }
299 
300  break;
301  case COEFF_TYPE_TANH:
302  QDPIO::cout << "Coefficients from Higham Tanh representation" << std::endl;
303  break;
305  QDPIO::cout << "Coefficients from Unscaled Higham Tanh representation" << std::endl;
306  break;
307  default:
308  QDPIO::cerr << "Unknown coefficient type " << params.approximation_type
309  << std::endl;
310  QDP_abort(1);
311  break;
312  }
313 
314  // free the arrays allocated by Tony's Zolo
315  zolotarev_free(rdata);
316  }
317 
318 
319 
320  //! Produce a linear operator for this action
321  /*!
322  * The operator acts on the entire lattice
323  *
324  * \param state gauge field (Read)
325  */
326  UnprecLinearOperatorArray<LatticeFermion,
327  multi1d<LatticeColorMatrix>,
328  multi1d<LatticeColorMatrix> >*
330  {
331  START_CODE();
332 
333  multi1d<Real> alpha;
334  multi1d<Real> beta;
335 
336  init(alpha, beta);
337 
340  params.Mass,
341  N5,
342  params.b5,
343  params.c5,
344  alpha,
345  beta,
346  isLastZeroP);
347  }
348 
349 
350  //! Propagator of unpreconditioned H_T kernel continued fraction (5D) operator
351  /*! \ingroup qprop
352  *
353  * Propagator solver for Extended overlap fermions
354  */
355  template<typename T>
356  class OvHTCFZ5DQprop : public SystemSolver<T>
357  {
358  public:
359  //! Constructor
360  /*!
361  * \param A_ Linear operator ( Read )
362  * \param Mass_ quark mass ( Read )
363  */
365  Handle< LinearOperator<T> > D_denum_,
366  const Real& Mass_,
367  const SysSolverCGParams& invParam_) :
368  A(A_), D_denum(D_denum_), Mass(Mass_), invParam(invParam_) {}
369 
370  //! Destructor is automatic
372 
373  //! Return the subset on which the operator acts
374  const Subset& subset() const {return all;}
375 
376  //! Solver the linear system
377  /*!
378  * \param psi quark propagator ( Modify )
379  * \param chi source ( Read )
380  * \return number of CG iterations
381  */
383  {
384  START_CODE();
385 
387  const int N5 = A->size();
388 
389  int G5 = Ns*Ns - 1;
390 
391  // Initialize the 5D fields
392  multi1d<LatticeFermion> chi5(N5);
393  multi1d<LatticeFermion> psi5(N5);
394 
395  // For reasons I do not appreciate doing the solve as
396  // M^{dag} M psi = M^{dag} chi
397  // seems a few iterations faster and more accurate than
398  // Doing M^{dag} M psi = chi
399  // and then applying M^{dag}
400 
401  // So first get M^{dag} gamma_5 chi into the source.
402 
403 // if( invType == "CG_INVERTER")
404  {
405  multi1d<LatticeFermion> tmp5(N5);
406 
407  // Zero out 5D vectors
408  for(int i=0; i < N5; i++) {
409  psi5[i] = zero;
410  chi5[i] = zero;
411  tmp5[i] = zero;
412  }
413 
414  // Set initial guess
415  psi5[N5-1] = psi;
416 
417  // set up D_denum^dag gamma_5 chi into chi-1
418  {
419  LatticeFermion tmp = Gamma(G5)*chi;
420  (*D_denum)(chi5[N5-1], tmp, MINUS);
421  }
422  (*A)(tmp5, chi5, MINUS);
423 
424  // psi5 = (M^{dag} M)^(-1) M^{dag} * gamma_5 * chi5
425  // psi5[N5] = (1 - m)/2 D^{-1}(m) chi [N5]
426  res = InvCG2(*A, tmp5, psi5, invParam.RsdCG, invParam.MaxCG);
427  }
428 // else
429 // {
430 // QDPIO::cerr << UnprecHTContFrac5DFermActArrayEnv::name
431 // << "Unsupported inverter type =" << invType << std::endl;
432 // QDP_abort(1);
433 // }
434 
435  if ( res.n_count == invParam.MaxCG )
436  QDP_error_exit("no convergence in the inverter", res.n_count);
437 
438  // Compute residual
439  {
440  multi1d<T> r(N5);
441  (*A)(r, psi5, PLUS);
442  r -= chi5;
443  res.resid = sqrt(norm2(r));
444  }
445 
446  // Solution now lives in chi5
447 
448  // Multiply back in factor 2/(1-m) to return to
449  // (1/2)( 1 + m + (1-m) gamma_5 epsilon )
450  // normalisatoin
451  psi5[N5-1] *= Real(2)/(Real(1)-Mass);
452 
453  // Remove contact term
454  psi = psi5[N5-1] - chi;
455 
456  // Overall normalization
457  Real ftmp1 = Real(1) / (Real(1) - Mass);
458  psi *= ftmp1;
459 
460  END_CODE();
461 
462  return res;
463  }
464 
465  private:
466  // Hide default constructor
468 
471  Real Mass;
473  };
474 
475 
476  //! Propagator of unpreconditioned H_T kernel continued fraction (5D) operator
479  const GroupXML_t& invParam) const
480  {
481  Real a5 = params.b5 - params.c5;
482  Real WilsonMass = -params.OverMass;
483 
484  Handle< LinearOperator<T> > D_w(new UnprecWilsonLinOp(state, WilsonMass));
486 
487  std::istringstream is(invParam.xml);
488  XMLReader paramtop(is);
489 
491  D_denum,
492  getQuarkMass(),
493  SysSolverCGParams(paramtop,invParam.path));
494  }
495 
496 
497 } // End namespace Chroma
Primary include file for CHROMA library code.
Create a fermion connection state.
Definition: create_state.h:69
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
Linear Operator to arrays.
Definition: linearop.h:61
Linear Operator.
Definition: linearop.h:27
Propagator of unpreconditioned H_T kernel continued fraction (5D) operator.
SystemSolverResults_t operator()(T &psi, const T &chi) const
Solver the linear system.
OvHTCFZ5DQprop(Handle< LinearOperatorArray< T > > A_, Handle< LinearOperator< T > > D_denum_, const Real &Mass_, const SysSolverCGParams &invParam_)
Constructor.
const Subset & subset() const
Return the subset on which the operator acts.
Handle< LinearOperatorArray< T > > A
static T & Instance()
Definition: singleton.h:432
Linear system solvers.
Definition: syssolver.h:34
Operator to apply the denominator.
5D continued fraction overlap action using H_T kernel
SystemSolver< LatticeFermion > * qprop(Handle< FermState< T, P, Q > > state, const GroupXML_t &invParam) const
Compute quark propagator over base type.
void init(multi1d< Real > &alpha, multi1d< Real > &beta) const
Helper in construction.
UnprecLinearOperatorArray< T, P, Q > * linOp(Handle< FermState< T, P, Q > > state) const
Produce a linear operator for this action.
Unpreconditioned H_T kernel continued fraction (5D) operator.
Unpreconditioned linear operator including derivatives.
Definition: linearop.h:203
Unpreconditioned Wilson-Dirac operator.
Wilson-like fermion actions.
Definition: fermact.orig.h:403
Enums.
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.
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
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.
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
Hold group xml and type id.
Params for CG inverter.
Holds return info from SystemSolver call.
Definition: syssolver.h:17
CoeffType approximation_type
ZOLOTAREV | TANH | Other approximation coeffs.
Solve a CG1 system.
Double ftmp1
Definition: topol.cc:29
Unpreconditioned Wilson fermion linear operator.
Unpreconditioned H_T kernel continued fraction (5D) action.
Unpreconditioned H_T kernel continued fraction (5D) 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)