CHROMA
ovlap_partfrac4d_fermact_w.cc
Go to the documentation of this file.
1 /*! \file
2  * \brief 4D Zolotarev variant of Overlap-Dirac operator
3  */
4 
5 #include <chromabase.h>
6 #include <linearop.h>
7 
8 #include "io/enum_io/enum_io.h" // Read/Write OverlapInnerSolver Type
9 // #include "io/overlap_state_info.h"
10 
11 // For creating auxiliary actions
13 
14 // My defs
16 
17 // the zolo coeffs
19 
20 // Linops I can make
27 #include "meas/eig/ischiral_w.h"
28 
29 
34 
35 #include <iostream>
36 #include <sstream>
37 #include <string>
38 
39 namespace Chroma
40 {
41 
42  //! Hooks to register the class with the fermact factory
43  namespace OvlapPartFrac4DFermActEnv
44  {
45  //! Callback function
46  WilsonTypeFermAct<LatticeFermion,
47  multi1d<LatticeColorMatrix>,
48  multi1d<LatticeColorMatrix> >* createFermAct4D(XMLReader& xml_in,
49  const std::string& path)
50  {
51  return new OvlapPartFrac4DFermAct(WilsonTypeFermBCEnv::reader(xml_in, path),
52  OvlapPartFrac4DFermActParams(xml_in, path));
53  }
54 
55  //! Callback function
56  /*! Differs in return type */
57  FermionAction<LatticeFermion,
58  multi1d<LatticeColorMatrix>,
59  multi1d<LatticeColorMatrix> >* createFermAct(XMLReader& xml_in,
60  const std::string& path)
61  {
62  return createFermAct4D(xml_in, path);
63  }
64 
65  //! Name to be used
66  const std::string name ="OVERLAP_PARTIAL_FRACTION_4D";
67 
68  //! Local registration flag
69  static bool registered = false;
70 
71  //! Register all the factories
72  bool registerAll()
73  {
74  bool success = true;
75  if (! registered)
76  {
77  success &= Chroma::TheFermionActionFactory::Instance().registerObject(name, createFermAct);
79  registered = true;
80  }
81  return success;
82  }
83  }
84 
85 
86 
87  OvlapPartFrac4DFermActParams::OvlapPartFrac4DFermActParams(XMLReader& xml, const std::string& path) : ReorthFreqInner(10), inner_solver_type(OVERLAP_INNER_CG_SINGLE_PASS)
88  {
89  XMLReader in(xml, path);
90 
91  try
92  {
93  if(in.count("AuxFermAct") == 1 )
94  {
95  XMLReader xml_tmp(in, "AuxFermAct");
96  std::ostringstream os;
97  xml_tmp.print(os);
98  AuxFermAct = os.str();
99  }
100  else
101  {
102  throw std::string("No auxilliary action");
103  }
104 
105  read(in, "Mass", Mass);
106  read(in, "RatPolyDeg", RatPolyDeg);
107 
108  if(in.count("RatPolyDegPrecond") == 1 ) {
109  read(in, "RatPolyDegPrecond", RatPolyDegPrecond);
110  }
111  else {
113  }
114 
115  if( in.count("ApproximationType") == 1 ) {
116  read(in, "ApproximationType", approximation_type);
117  }
118  else {
119  // Default coeffs are Zolotarev
121  }
122 
123  read(in, "ApproxMin", approxMin);
124  read(in, "ApproxMax", approxMax);
125 
126  read(in, "InnerSolve/MaxCG", invParamInner.MaxCG);
127  read(in, "InnerSolve/RsdCG", invParamInner.RsdCG);
128  if( in.count("InnerSolve/ReorthFreq") == 1 ) {
129  read(in, "InnerSolve/ReorthFreq", ReorthFreqInner);
130  }
131  else {
132  // ReorthFreqInner = 10; // Some default
133  // This is now set automagically -- constructor initialisation
134  }
135 
136  if( in.count("InnerSolve/SolverType") == 1 ) {
137  read(in, "InnerSolve/SolverType", inner_solver_type);
138  }
139  else {
140  // inner_solver_type = OVERLAP_INNER_CG_SINGLE_PASS;
141  // This is now set automagically -- constructor initialisation
142  }
143 
144  read(in, "IsChiral", isChiralP);
145  }
146  catch( const std::string &e ) {
147  QDPIO::cerr << "Caught Exception reading Zolo4D Fermact params: " << e << std::endl;
148  QDP_abort(1);
149  }
150  }
151 
152  void write(XMLWriter& xml_out, const std::string& path, const OvlapPartFrac4DFermActParams& p)
153  {
154  if ( path != "." ) {
155  push( xml_out, path);
156  }
157 
158  xml_out << p.AuxFermAct;
159  write(xml_out, "Mass", p.Mass);
160  write(xml_out, "RatPolyDeg", p.RatPolyDeg);
161  write(xml_out, "RatPolyDegPrecond", p.RatPolyDegPrecond);
162  push(xml_out, "InnerSolve");
163  write(xml_out, "MaxCG", p.invParamInner.MaxCG);
164  write(xml_out, "RsdCG", p.invParamInner.RsdCG);
165  write(xml_out, "ReorthFreq", p.ReorthFreqInner);
166  write(xml_out, "SolverType", p.inner_solver_type);
167  write(xml_out, "ApproximationType", p.approximation_type);
168  write(xml_out, "ApproxMin", p.approxMin);
169  write(xml_out, "ApproxMax", p.approxMax);
170  write(xml_out, "IsChiral", p.isChiralP);
171  pop(xml_out);
172 
173 // write(xml_out, "StateInfo", p.state_info);
174 
175  if( path != "." ) {
176  pop(xml_out);
177  }
178  }
179 
180  //! Read parameters
181  void read(XMLReader& xml, const std::string& path, OvlapPartFrac4DFermActParams& param)
182  {
184  param = tmp;
185  }
186 
187 
188 
189  //! Constructor
191  const OvlapPartFrac4DFermActParams& params_) :
192  fbc(fbc_), params(params_)
193  {
194  QDPIO::cout << "Constructing OvlapPartFrac4D FermAct from params" << std::endl;
195  std::istringstream xml_s(params.AuxFermAct);
196  XMLReader fermacttop(xml_s);
197  const std::string fermact_path = "/AuxFermAct";
198 
199  // Sanity check
200  if (fbc.operator->() == 0)
201  {
202  QDPIO::cerr << OvlapPartFrac4DFermActEnv::name << ": error: fbc is null" << std::endl;
203  QDP_abort(1);
204  }
205 
206  // Fake a creator. This should be cleaned up
208  cfs = cfs_;
209 
210  struct UnprecCastFailure {
211  UnprecCastFailure(std::string e) : auxfermact(e) {};
212  const std::string auxfermact;
213  };
214 
215  try
216  {
217  std::string auxfermact;
218  read(fermacttop, fermact_path + "/FermAct", auxfermact);
219  QDPIO::cout << "AuxFermAct: " << auxfermact << std::endl;
220 
221  read(fermacttop, fermact_path + "/Mass", params.AuxMass);
222  QDPIO::cout << "AuxFermAct Mass: " << params.AuxMass << std::endl;
223  // Generic Wilson-Type stuff
225  TheFermionActionFactory::Instance().createObject(auxfermact,
226  fermacttop,
227  fermact_path);
228 
230  dynamic_cast<UnprecWilsonTypeFermAct<T,P,Q>*>(S_f);
231 
232  // Dumbass User specifies something that is not UnpreWilsonTypeFermAct
233  // dynamic_cast MUST be checked for 0
234  if( S_aux == 0 ) throw UnprecCastFailure(auxfermact);
235 
236 
237  // Drop AuxFermAct into a Handle immediately.
238  // This should free things up at the end
240  Mact = S_w;
241  }
242  catch( const UnprecCastFailure& e) {
243 
244  // Breakage Scenario
245  QDPIO::cerr << "Unable to upcast auxiliary fermion action to "
246  << "UnprecWilsonTypeFermAct " << std::endl;
247  QDPIO::cerr << OvlapPartFrac4DFermActEnv::name << " does not support even-odd preconditioned "
248  << "auxiliary FermActs" << std::endl;
249  QDPIO::cerr << "You passed : " << std::endl;
250  QDPIO::cerr << e.auxfermact << std::endl;
251  QDP_abort(1);
252  }
253  catch (const std::exception& e) {
254  // General breakage Scenario
255  QDPIO::cerr << "Error reading data: " << e.what() << std::endl;
256  throw;
257  }
258 
259  }
260 
261 
262  //! Creation routine
263  /*! */
264  void
266  Real& coeffP,
267  multi1d<Real>& resP,
268  multi1d<Real>& rootQ,
269  int& NEig,
270  multi1d<Real>& EigValFunc,
271  const EigenConnectState& state ) const
272  {
273  /* A scale factor which should bring the spectrum of the hermitian
274  Wilson Dirac operator H into |H| < 1. */
275  Real scale_fac;
276 
277  /* Contains all the data necessary for Zolotarev partial fraction */
278  /* -------------------------------------------------------------- */
279  zolotarev_data *rdata ;
280  /* The lower (positive) interval bound for the approximation
281  interval [-1,-eps] U [eps,1] */
282 
283  Real eps;
284  /* The type of the approximation R(x):
285  type = 0 -> R(x) = 0 at x = 0
286  type = 1 -> R(x) = infinity at x = 0 */
287 
288  int type;
289  /* The maximal error of the approximation in the interval
290  [-1,-eps] U [eps,1]*/
291 
292  Real maxerr;
293 
294  // The residual for the solutions of the multi-shift linear system
295  // I put this in the class constructor
296 
297  // RsdCGinner = 1.0e-7; // Hardwired the accuracy
298 
299 
300  /* Hermitian 4D overlap operator 1/2 ( 1 + Mass + (1 - Mass) gamma5 * sgn(H))
301  using a partial fraction expansion of the optimal rational function
302  approximation to sgn. Here, H = 1/2 * gamma_5 * (1/kappa - D').
303  The coefficients are computed by Zolotarev's formula. */
304 
305  int NEigVal = state.getNEig();
306 
307  /* The operator gamma_5 * M with the M constructed here has its eigenvalues
308  in the range m/(m + Nd) <= |gamma_5 * M| <= (m + 2*Nd)/(m + Nd) (in the
309  free case) where here m is arbitrary.
310  So if we multiply M by a factor scale_fac = (m + Nd)/(m + 2*Nd) we have
311  |gamma_5 * M| <= 1. */
312 
313  // REmove this evil dublication later please.
314  NEig = NEigVal;
315 
316  switch(params.approximation_type) {
318  scale_fac = Real(1) / params.approxMax;
319  eps = params.approxMin * scale_fac;
320 
321  QDPIO::cout << "Initing Linop with Zolotarev Coefficients" << std::endl;
322  QDPIO::cout << " MaxCGInner = " << params.invParamInner.MaxCG << std::endl;
323  QDPIO::cout << " RsdCGInner = " << params.invParamInner.RsdCG << std::endl;
324  QDPIO::cout << " NEigVal = " << NEigVal << std::endl;
325 
326  /* Below, when we fill in the coefficents for the partial fraction,
327  we include this factor, say t, appropriately, i.e.
328  R(x) = alpha[da] * t * x + sum(alpha[j] * t * x / (t^2 * x^2 - ap[j]),
329  j = 0 .. da-1)
330  = (alpha[da] + + sum(alpha[j] / (x^2 - ap[j] / t^2) ) / t^2 ) * t * x
331  */
332 
333  /* ZOLOTAREV_4D uses Zolotarev's formula for the coefficients.
334  The coefficents produced are for an optimal uniform approximation
335  to the sign-function in the interval [-1,-eps] U [eps,1] and of order n.
336  type can be set to 0 or 1 corresponding to an approximation which is
337  is zero or infinite at x = 0, respectively.
338  Here we are interested in the partial fraction form
339 
340  R(x) = alpha[da] * x + sum(alpha[j] * x / (x^2 - ap[j]), j = 0 .. da-1)
341 
342  where da = dd for type 0 and da = dd + 1 with ap[dd] = 0 for type 1.
343  */
344  type = 0;
345  rdata = zolotarev(toFloat(eps), params.RatPolyDeg, type);
346  if( rdata == 0x0 ) {
347  QDPIO::cerr << "Failed to get Zolo Coeffs" << std::endl;
348  QDP_abort(1);
349  }
350  break;
351 
352  case COEFF_TYPE_TANH:
353  scale_fac = Real(1) / params.approxMax;
354  eps = params.approxMin * scale_fac;
355 
356  QDPIO::cout << "Initing Linop with Higham Rep tanh Coefficients" << std::endl;
357  QDPIO::cout << " MaxCGInner = " << params.invParamInner.MaxCG << std::endl;
358  QDPIO::cout << " RsdCGInner = " << params.invParamInner.RsdCG << std::endl;
359  QDPIO::cout << " NEigVal = " << NEigVal << std::endl;
360 
361  /* Below, when we fill in the coefficents for the partial fraction,
362  we include this factor, say t, appropriately, i.e.
363  R(x) = alpha[da] * t * x + sum(alpha[j] * t * x / (t^2 * x^2 - ap[j]),
364  j = 0 .. da-1)
365  = (alpha[da] + + sum(alpha[j] / (x^2 - ap[j] / t^2) ) / t^2 ) * t * x
366  */
367 
368  /* use the tanh formula (Higham Rep) for the coefficients.
369  The coefficents produced are for the tanh approximation
370  to the sign-function in the interval [-1,-eps] U [eps,1] and of order n. R(x) = alpha[da] * x + sum(alpha[j] * x / (x^2 - ap[j]), j = 0 .. da-1)
371  where da = dd for type 0 and da = dd + 1 with ap[dd] = 0 for type 1.
372  */
373  rdata = higham(toFloat(eps), params.RatPolyDeg);
374  break;
375 
377  scale_fac = Real(1) ;
378  eps = params.approxMin;
379 
380  QDPIO::cout << "Initing Linop with Unscaled Higham Rep tanh Coefficients" << std::endl;
381  QDPIO::cout << " MaxCGInner = " << params.invParamInner.MaxCG << std::endl;
382  QDPIO::cout << " RsdCGInner = " << params.invParamInner.RsdCG << std::endl;
383  QDPIO::cout << " NEigVal = " << NEigVal << std::endl;
384 
385  /* Below, when we fill in the coefficents for the partial fraction,
386  we include this factor, say t, appropriately, i.e.
387  R(x) = alpha[da] * t * x + sum(alpha[j] * t * x / (t^2 * x^2 - ap[j]),
388  j = 0 .. da-1)
389  = (alpha[da] + + sum(alpha[j] / (x^2 - ap[j] / t^2) ) / t^2 ) * t * x
390  */
391 
392  /* use the tanh formula (Higham Rep) for the coefficients.
393  The coefficents produced are for the tanh approximation
394  to the sign-function in the interval [-1,-eps] U [eps,1] and of order n. R(x) = alpha[da] * x + sum(alpha[j] * x / (x^2 - ap[j]), j = 0 .. da-1)
395  where da = dd for type 0 and da = dd + 1 with ap[dd] = 0 for type 1.
396  */
397  rdata = higham(toFloat(eps), params.RatPolyDeg);
398  break;
399 
400  default:
401  // The std::map system should ensure that we never get here but
402  // just for style
403  QDPIO::cerr << "Unknown coefficient type: " << params.approximation_type
404  << std::endl;
405  QDP_abort(1);
406  }
407 
408  maxerr = (Real)(rdata -> Delta);
409  QDPIO::cout << "Maxerr " << maxerr << std::flush << std::endl;
410  /*
411  push(my_writer, "ZolotarevApprox");
412  write(my_writer, "eps", eps);
413  write(my_writer, "scale_fac", scale_fac);
414  write(my_writer, "RatPolyDeg", params.RatPolyDeg);
415  write(my_writer, "type", type);
416  write(my_writer, "maxerr", maxerr);
417  write(my_writer, "InnerSolverType", params.inner_solver_type);
418  pop(my_writer);
419  */
420 
421  /* The number of residuals and poles */
422  /* Allocate the roots and residua */
423  numroot = rdata -> dd;
424  /* The roots, i.e., the shifts in the partial fraction expansion */
425  rootQ.resize(numroot);
426  /* The residuals in the partial fraction expansion */
427  resP.resize(numroot);
428 
429  /* Fill in alpha[0] = alpha[da] if it is not zero*/
430  coeffP = Real(0);
431  coeffP = rdata -> alpha[rdata -> da - 1];
432  /* The coefficients from the partial fraction.
433  Here, we write them out for the sake of bookkeeping. */
434  for(int n=0; n < numroot; ++n) {
435  resP[n] = rdata -> alpha[n];
436  rootQ[n] = rdata -> ap[n];
437  rootQ[n] = -rootQ[n];
438  }
439  /*
440  push(my_writer,"ZolotarevPartFrac");
441  write(my_writer, "scale_fac", scale_fac);
442  write(my_writer, "coeffP", coeffP);
443  write(my_writer, "resP", resP);
444  write(my_writer, "rootQ", rootQ);
445  pop(my_writer);
446  */
447 
448  /* Now fill in the coefficients for real, i.e., taking the rescaling
449  into account */
450  /* Fill in alpha[0] = alpha[da] if it is not zero*/
451  coeffP = rdata -> alpha[rdata -> da - 1] * scale_fac;
452  /* Fill in the coefficients for the roots and the residua */
453  /* Make sure that the smallest shift is in the last value rootQ(numroot-1)*/
454  Real t = Real(1) / (scale_fac * scale_fac);
455  for(int n=0; n < numroot; ++n) {
456 
457  resP[n] = rdata -> alpha[n] / scale_fac;
458  rootQ[n] = rdata -> ap[n];
459  rootQ[n] = -(rootQ[n] * t);
460  }
461 
462  /* Write them out into the namelist */
463  /*
464  push(my_writer,"ZolotarevPartFracResc");
465  write(my_writer, "scale_fac", scale_fac);
466  write(my_writer, "coeffP", coeffP);
467  write(my_writer, "resP", resP);
468  write(my_writer, "rootQ", rootQ);
469  pop(my_writer);
470  */
471 
472  QDPIO::cout << "PartFracApprox 4d n=" << params.RatPolyDeg << " scale=" << scale_fac
473  << " coeff=" << coeffP << " Nwils= " << NEigVal <<" Mass="
474  << params.Mass << " Rsd=" << params.invParamInner.RsdCG << std::endl;
475 
476  QDPIO::cout << "Approximation on [-1,-eps] U [eps,1] with eps = " << eps <<
477  std::endl;
478  QDPIO::cout << "Maximum error |R(x) - sqn(x)| <= " << maxerr << std::endl;
479 
480  switch( params.approximation_type) {
482  QDPIO::cout << "Coefficients from Zolotarev" << std::endl;
483 
484  if(type == 0) {
485  QDPIO::cout << "Approximation type " << type << " with R(0) = 0"
486  << std::endl;
487  }
488  else {
489  QDPIO::cout << "Approximation type " << type << " with R(0) = infinity" << std::endl;
490  }
491 
492  break;
493  case COEFF_TYPE_TANH:
494  QDPIO::cout << "Coefficients from Higham Tanh representation" << std::endl;
495  break;
496 
498  QDPIO::cout << "Coefficients from Unscaled Higham Tanh representation" << std::endl;
499  break;
500 
501  default:
502  QDPIO::cerr << "Unknown coefficient type " << params.approximation_type
503  << std::endl;
504  break;
505  }
506 
507 
508  switch(params.inner_solver_type) {
510  QDPIO::cout << "Using Single Pass Inner Solver" << std::endl;
511  break;
513  QDPIO::cout << "Using Neuberger/Chu Double Pass Inner Solver" << std::endl;
514  break;
515  default:
516  QDPIO::cerr << "Unknown inner solver type " << std::endl;
517  QDP_abort(1);
518  }
519 
520  QDPIO::cout << "Number of poles= " << numroot << std::endl;
521  QDPIO::cout << "Overall Factor= " << coeffP << std::endl;
522  QDPIO::cout << "Numerator coefficients:" << std::endl;
523  for(int n=0; n < numroot; n++) {
524  QDPIO::cout <<" resP[" << n << "]= " << resP[n] << std::endl;
525  }
526  QDPIO::cout << "Denominator roots: " << std::endl;
527  for(int n=0; n < numroot; n++) {
528  QDPIO::cout <<" rootQ[" << n<< "]= " << rootQ[n] << std::endl;
529  }
530 
531  /* We will also compute the 'function' of the eigenvalues */
532  /* for the Wilson vectors to be projected out. */
533  if (NEig > 0)
534  {
535  for(int i = 0; i < NEigVal; i++)
536  {
537  if (toBool(state.getEvalues()[i] > 0.0))
538  EigValFunc[i] = 1.0;
539  else if (toBool(state.getEvalues()[i] < 0.0))
540  EigValFunc[i] = -1.0;
541  else
542  EigValFunc[i] = 0.0;
543  }
544  }
545 
546 
547  // Free the arrays allocate by Tony's zolo
548  zolotarev_free(rdata);
549  }
550 
551  void
553  Real& coeffP,
554  multi1d<Real>& resP,
555  multi1d<Real>& rootQ,
556  int& NEig,
557  multi1d<Real>& EigValFunc,
558  const EigenConnectState& state ) const
559  {
560  /* A scale factor which should bring the spectrum of the hermitian
561  Wilson Dirac operator H into |H| < 1. */
562  Real scale_fac;
563  XMLBufferWriter my_writer;
564 
565  /* Contains all the data necessary for Zolotarev partial fraction */
566  /* -------------------------------------------------------------- */
567  zolotarev_data *rdata ;
568  /* The lower (positive) interval bound for the approximation
569  interval [-1,-eps] U [eps,1] */
570 
571  Real eps;
572  /* The type of the approximation R(x):
573  type = 0 -> R(x) = 0 at x = 0
574  type = 1 -> R(x) = infinity at x = 0 */
575 
576  int type;
577  /* The maximal error of the approximation in the interval
578  [-1,-eps] U [eps,1]*/
579 
580  Real maxerr;
581 
582  // The residual for the solutions of the multi-shift linear system
583  // I put this in the class constructor
584 
585  // RsdCGinner = 1.0e-7; // Hardwired the accuracy
586 
587 
588  /* Hermitian 4D overlap operator 1/2 ( 1 + Mass + (1 - Mass) gamma5 * sgn(H))
589  using a partial fraction expansion of the optimal rational function
590  approximation to sgn. Here, H = 1/2 * gamma_5 * (1/kappa - D').
591  The coefficients are computed by Zolotarev's formula. */
592 
593  int NEigVal = state.getNEig();
594 
595  /* The operator gamma_5 * M with the M constructed here has its eigenvalues
596  in the range m/(m + Nd) <= |gamma_5 * M| <= (m + 2*Nd)/(m + Nd) (in the
597  free case) where here m is arbitrary.
598  So if we multiply M by a factor scale_fac = (m + Nd)/(m + 2*Nd) we have
599  |gamma_5 * M| <= 1. */
600  NEig = NEigVal;
601 
602 
603  switch(params.approximation_type) {
605  scale_fac = Real(1) / params.approxMax;
606  eps = params.approxMin * scale_fac;
607 
608  QDPIO::cout << "Initing Linop with Zolotarev Coefficients" << std::endl;
609 
610  QDPIO::cout << " MaxCGInner = " << params.invParamInner.MaxCG << std::endl;
611  QDPIO::cout << " RsdCGInner = " << params.invParamInner.RsdCG << std::endl;
612  QDPIO::cout << " NEigVal = " << NEigVal << std::endl;
613 
614  /* Below, when we fill in the coefficents for the partial fraction,
615  we include this factor, say t, appropriately, i.e.
616  R(x) = alpha[da] * t * x + sum(alpha[j] * t * x / (t^2 * x^2 - ap[j]),
617  j = 0 .. da-1)
618  = (alpha[da] + + sum(alpha[j] / (x^2 - ap[j] / t^2) ) / t^2 ) * t * x
619  */
620 
621  /* ZOLOTAREV_4D uses Zolotarev's formula for the coefficients.
622  The coefficents produced are for an optimal uniform approximation
623  to the sign-function in the interval [-1,-eps] U [eps,1] and of order n.
624  type can be set to 0 or 1 corresponding to an approximation which is
625  is zero or infinite at x = 0, respectively.
626  Here we are interested in the partial fraction form
627 
628  R(x) = alpha[da] * x + sum(alpha[j] * x / (x^2 - ap[j]), j = 0 .. da-1)
629 
630  where da = dd for type 0 and da = dd + 1 with ap[dd] = 0 for type 1.
631  */
632  type = 0;
633  rdata = zolotarev(toFloat(eps), params.RatPolyDeg, type);
634  maxerr = (Real)(rdata -> Delta);
635  break;
636  case COEFF_TYPE_TANH:
637  scale_fac = Real(1) / params.approxMax;
638  eps = params.approxMin * scale_fac;
639 
640  QDPIO::cout << "Initing Linop with Higham Rep tanh Coefficients" << std::endl;
641 
642  QDPIO::cout << " MaxCGInner = " << params.invParamInner.MaxCG << std::endl;
643  QDPIO::cout << " RsdCGInner = " << params.invParamInner.RsdCG << std::endl;
644  QDPIO::cout << " NEigVal = " << NEigVal << std::endl;
645 
646  /* Below, when we fill in the coefficents for the partial fraction,
647  we include this factor, say t, appropriately, i.e.
648  R(x) = alpha[da] * t * x + sum(alpha[j] * t * x / (t^2 * x^2 - ap[j]),
649  j = 0 .. da-1)
650  = (alpha[da] + + sum(alpha[j] / (x^2 - ap[j] / t^2) ) / t^2 ) * t * x
651  */
652 
653  /* use the tanh formula (Higham Rep) for the coefficients.
654  The coefficents produced are for the tanh approximation
655  to the sign-function in the interval [-1,-eps] U [eps,1] and of order n. R(x) = alpha[da] * x + sum(alpha[j] * x / (x^2 - ap[j]), j = 0 .. da-1)
656  where da = dd for type 0 and da = dd + 1 with ap[dd] = 0 for type 1.
657  */
658  rdata = higham(toFloat(eps), params.RatPolyDeg);
659  maxerr = (Real)(rdata -> Delta);
660  break;
662  scale_fac = Real(1) ;
663  eps = params.approxMin;
664 
665  QDPIO::cout << "Initing Preconditioning Linop with Unscaled Higham Rep tanh Coefficients" << std::endl;
666  QDPIO::cout << " MaxCGInner = " << params.invParamInner.MaxCG << std::endl;
667  QDPIO::cout << " RsdCGInner = " << params.invParamInner.RsdCG << std::endl;
668  QDPIO::cout << " NEigVal = " << NEigVal << std::endl;
669 
670  /* Below, when we fill in the coefficents for the partial fraction,
671  we include this factor, say t, appropriately, i.e.
672  R(x) = alpha[da] * t * x + sum(alpha[j] * t * x / (t^2 * x^2 - ap[j]),
673  j = 0 .. da-1)
674  = (alpha[da] + + sum(alpha[j] / (x^2 - ap[j] / t^2) ) / t^2 ) * t * x
675  */
676 
677  /* use the tanh formula (Higham Rep) for the coefficients.
678  The coefficents produced are for the tanh approximation
679  to the sign-function in the interval [-1,-eps] U [eps,1] and of order n. R(x) = alpha[da] * x + sum(alpha[j] * x / (x^2 - ap[j]), j = 0 .. da-1)
680  where da = dd for type 0 and da = dd + 1 with ap[dd] = 0 for type 1.
681  */
682  rdata = higham(toFloat(eps), params.RatPolyDeg);
683 
684 
685  default:
686  // The std::map system should ensure that we never get here but
687  // just for style
688  QDPIO::cerr << "Unknown coefficient type: " << params.approximation_type
689  << std::endl;
690  QDP_abort(1);
691  }
692 
693  /* The number of residuals and poles */
694  /* Allocate the roots and residua */
695  numroot = rdata -> dd;
696  /* The roots, i.e., the shifts in the partial fraction expansion */
697  rootQ.resize(numroot);
698 
699  /* The residuals in the partial fraction expansion */
700  resP.resize(numroot);
701 
702  /* Fill in alpha[0] = alpha[da] if it is not zero*/
703  coeffP = 0;
704  coeffP = rdata -> alpha[rdata -> da - 1];
705  /* The coefficients from the partial fraction.
706  Here, we write them out for the sake of bookkeeping. */
707  for(int n=0; n < numroot; ++n) {
708  resP[n] = rdata -> alpha[n];
709  rootQ[n] = rdata -> ap[n];
710  rootQ[n] = -rootQ[n];
711  }
712 
713  /*
714  push(my_writer,"ZolotarevPreconditionerPartFrac");
715  write(my_writer, "scale_fac", scale_fac);
716  write(my_writer, "coeffP", coeffP);
717  write(my_writer, "resP", resP);
718  write(my_writer, "rootQ", rootQ);
719  pop(my_writer);
720  */
721 
722  /* Now fill in the coefficients for real, i.e., taking the rescaling
723  into account */
724  /* Fill in alpha[0] = alpha[da] if it is not zero*/
725  coeffP = rdata -> alpha[rdata -> da - 1] * scale_fac;
726  /* Fill in the coefficients for the roots and the residua */
727  /* Make sure that the smallest shift is in the last value rootQ(numroot-1)*/
728  Real t = Real(1) / (scale_fac * scale_fac);
729  for(int n=0; n < numroot; ++n) {
730 
731  resP[n] = rdata -> alpha[n] / scale_fac;
732  rootQ[n] = rdata -> ap[n];
733  rootQ[n] = -(rootQ[n] * t);
734  }
735 
736 
737  /* Write them out into the namelist */
738  /*
739  push(my_writer,"ZolotarevPreconditionerPartFracResc");
740  write(my_writer, "scale_fac", scale_fac);
741  write(my_writer, "coeffP", coeffP);
742  write(my_writer, "resP", resP);
743  write(my_writer, "rootQ", rootQ);
744  pop(my_writer);
745  */
746 
747 
748  QDPIO::cout << "PartFrac Preconditioner 4d n=" << params.RatPolyDegPrecond << " scale=" << scale_fac
749  << " coeff=" << coeffP << " Nwils= " << NEigVal <<" Mass="
750  << params.Mass << " Rsd=" << params.invParamInner.RsdCG << std::endl;
751 
752  QDPIO::cout << "Approximation on [-1,-eps] U [eps,1] with eps = " << eps <<
753  std::endl;
754  QDPIO::cout << "Maximum error |R(x) - sqn(x)| <= " << maxerr << std::endl;
755 
756  switch( params.approximation_type) {
758  QDPIO::cout << "Coefficients from Zolotarev" << std::endl;
759 
760  if(type == 0) {
761  QDPIO::cout << "Approximation type " << type << " with R(0) = 0"
762  << std::endl;
763  }
764  else {
765  QDPIO::cout << "Approximation type " << type << " with R(0) = infinity" << std::endl;
766  }
767  break;
768  case COEFF_TYPE_TANH:
769 
770  QDPIO::cout << "Coefficients from Higham Tanh representation" << std::endl;
771  break;
772 
774 
775  QDPIO::cout << "Coefficients from Higham Tanh representation" << std::endl;
776  break;
777  default:
778  QDPIO::cerr << "Unknown coefficient type " << params.approximation_type
779  << std::endl;
780  break;
781  }
782  QDPIO::cout << std::flush;
783 
784  switch(params.inner_solver_type) {
786  QDPIO::cout << "Using Single Pass Inner Solver" << std::endl;
787  break;
789  QDPIO::cout << "Using Neuberger/Chu Double Pass Inner Solver" << std::endl;
790  break;
791  default:
792  QDPIO::cerr << "Unknown inner solver type " << std::endl;
793  QDP_abort(1);
794  }
795 
796  QDPIO::cout << "Number of poles= " << numroot << std::endl;
797  QDPIO::cout << "Overall Factor= " << coeffP << std::endl;
798  QDPIO::cout << "Numerator coefficients:" << std::endl;
799  for(int n=0; n < numroot; n++) {
800  QDPIO::cout <<" resP[" << n << "]= " << resP[n] << std::endl;
801  }
802  QDPIO::cout << "Denominator roots: " << std::endl;
803  for(int n=0; n < numroot; n++) {
804  QDPIO::cout <<" rootQ[" << n<< "]= " << rootQ[n] << std::endl;
805  }
806 
807 
808  /* We will also compute the 'function' of the eigenvalues */
809  /* for the Wilson vectors to be projected out. */
810  if (NEig > 0)
811  {
812  for(int i = 0; i < NEigVal; i++)
813  {
814  if (toBool(state.getEvalues()[i] > 0.0))
815  EigValFunc[i] = 1.0;
816  else if (toBool(state.getEvalues()[i] < 0.0))
817  EigValFunc[i] = -1.0;
818  else
819  EigValFunc[i] = 0.0;
820  }
821  }
822 
823  // Free the arrays allocate by Tony's zolo
824  zolotarev_free(rdata);
825 
826  QDPIO::cout << "Leaving Init!" << std::endl << std::flush;
827 
828  }
829 
830  //! Produce a linear operator for this action
831  /*!
832  * The operator acts on the entire lattice
833  *
834  * \param state_ gauge field state (Read)
835  * \param m_q mass for this operator (Read)
836  */
837  UnprecLinearOperator<LatticeFermion,
838  multi1d<LatticeColorMatrix>,
839  multi1d<LatticeColorMatrix> >*
841  {
842  START_CODE();
843 
844  try {
845  const EigenConnectState& state = dynamic_cast<EigenConnectState&>(*state_);
846 
847  int NEigVal = state.getNEig();
848 
849  /* The actual number of eigenvectors to project out.
850  The highest of the valid low eigenmodes is not
851  projected out. So we will put NEig = NEigVal - 1 */
852  int NEig = NEigVal;
853 
854  /* The number of residuals and poles */
855  int numroot;
856 
857  /* The roots, i.e., the shifts in the partial fraction expansion */
858  multi1d<Real> rootQ;
859 
860  /* The residuals in the partial fraction expansion */
861  multi1d<Real> resP;
862 
863  /* This will be our alpha(0) which can be 0 depending on type */
864  /* an even- or oddness of RatPolyDeg*/
865  Real coeffP;
866 
867  /* Array of values of the sign function evaluated on the eigenvectors of H */
868  multi1d<Real> EigValFunc(NEigVal);
869 
870  // Common initialization
871  init(numroot, coeffP, resP, rootQ, NEig, EigValFunc, state);
872 
873 
874  /* Finally construct and pack the operator */
875  /* This is the operator of the form (1/2)*[(1+mu) + (1-mu)*gamma_5*eps] */
876  switch( params.inner_solver_type ) {
878  return new lovlapms(*Mact, state_, m_q,
879  numroot, coeffP, resP, rootQ,
880  NEig, EigValFunc, state.getEvectors(),
884  break;
886  return new lovlap_double_pass(*Mact, state_, m_q,
887  numroot, coeffP, resP, rootQ,
888  NEig, EigValFunc, state.getEvectors(),
892  break;
893  default:
894  QDPIO::cerr << "Unknown OverlapInnerSolverType " << params.inner_solver_type << std::flush << std::endl;
895  QDP_abort(1);
896  }
897 
898  }
899  catch(std::bad_cast) {
900  QDPIO::cerr << "OverlapPartFrac4DFermAct::unprecLinOp: "
901  << " Failed to downcast ConnectState to OverlapConnectState"
902  << std::endl;
903  QDP_abort(1);
904  }
905 
906  END_CODE();
907 
908  QDPIO::cout << "DANGER!!! About to return zero! " << std::endl;
909  return 0;
910  }
911 
912  //! Produce a linear operator for this action
913  /*!
914  * The operator acts on the entire lattice
915  *
916  * \param state_ gauge field state (Read)
917  */
920  {
921  START_CODE();
922  try {
923  const EigenConnectState& state = dynamic_cast<const EigenConnectState&>(*state_);
924 
925  int NEigVal = state.getNEig();
926 
927  /* The actual number of eigenvectors to project out.
928  The highest of the valid low eigenmodes is not
929  projected out. So we will put NEig = NEigVal - 1 */
930  int NEig=NEigVal;
931 
932  /* The number of residuals and poles */
933  int numroot;
934 
935  /* The roots, i.e., the shifts in the partial fraction expansion */
936  multi1d<Real> rootQ;
937 
938  /* The residuals in the partial fraction expansion */
939  multi1d<Real> resP;
940 
941  /* This will be our alpha(0) which can be 0 depending on type */
942  /* an even- or oddness of RatPolyDeg*/
943  Real coeffP;
944 
945  /* Array of values of the sign function evaluated on the eigenvectors of H */
946  multi1d<Real> EigValFunc(NEigVal);
947 
948  // Common initialization
949  initPrec(numroot, coeffP, resP, rootQ, NEig, EigValFunc, state);
950 
951 
952  /* Finally construct and pack the operator */
953  /* This is the operator of the form (1/2)*[(1+mu) + (1-mu)*gamma_5*eps] */
954  switch( params.inner_solver_type ) {
956  return new lovlapms(*Mact, state_, params.Mass,
957  numroot, coeffP, resP, rootQ,
958  NEig, EigValFunc, state.getEvectors(),
960  break;
962  return new lovlap_double_pass(*Mact, state_, params.Mass,
963  numroot, coeffP, resP, rootQ,
964  NEig, EigValFunc, state.getEvectors(),
966  break;
967  default:
968  QDPIO::cerr << "Unknown OverlapInnerSolverType " << params.inner_solver_type << std::endl;
969  QDP_abort(1);
970  }
971 
972  }
973  catch(std::bad_cast) {
974  QDPIO::cerr << "OverlapPartFrac4DFermAct::linOpPrecondition: "
975  << " Failed to downcast ConnectState to OverlapConnectState"
976  << std::endl;
977  QDP_abort(1);
978  }
979 
980  END_CODE();
981 
982  return 0;
983  }
984 
985  //! Produce a linear operator for gamma5 epsilon(H) psi
986  /*!
987  * The operator acts on the entire lattice
988  *
989  * \param state_ gauge field state (Read)
990  */
993  {
994  START_CODE();
995 
996  try {
997  const EigenConnectState& state = dynamic_cast<const EigenConnectState&>(*state_);
998 
999  int NEigVal = state.getNEig();
1000 
1001  /* The actual number of eigenvectors to project out.
1002  The highest of the valid low eigenmodes is not
1003  projected out. */
1004  int NEig = NEigVal;
1005 
1006  /* The number of residuals and poles */
1007  int numroot;
1008 
1009  /* The roots, i.e., the shifts in the partial fraction expansion */
1010  multi1d<Real> rootQ;
1011 
1012  /* The residuals in the partial fraction expansion */
1013  multi1d<Real> resP;
1014 
1015  /* This will be our alpha(0) which can be 0 depending on type */
1016  /* an even- or oddness of RatPolyDeg*/
1017  Real coeffP;
1018 
1019  /* Array of values of the sign function evaluated on the eigenvectors of H */
1020  multi1d<Real> EigValFunc(NEigVal);
1021 
1022  // Common initialization
1023  init(numroot, coeffP, resP, rootQ, NEig, EigValFunc, state);
1024 
1025 
1026  /* Finally construct and pack the operator */
1027  /* This is the operator of the form (1/2)*[(1+mu) + (1-mu)*gamma_5*eps] */
1028  switch( params.inner_solver_type ) {
1030  return new lg5eps(*Mact, state_,
1031  numroot, coeffP, resP, rootQ,
1032  NEig, EigValFunc, state.getEvectors(),
1034  break;
1036  return new lg5eps_double_pass(*Mact, state_,
1037  numroot, coeffP, resP, rootQ,
1038  NEig, EigValFunc, state.getEvectors(),
1040  break;
1041  default:
1042  QDPIO::cerr << "Unknown OverlapInnerSolverType " << params.inner_solver_type << std::endl;
1043  QDP_abort(1);
1044  }
1045  }
1046  catch(std::bad_cast) {
1047  QDPIO::cerr << "OverlapPartFrac4DFermAct::lgamma5epsH: "
1048  << " Failed to downcast ConnectState to OverlapConnectState"
1049  << std::endl;
1050  QDP_abort(1);
1051  }
1052 
1053  END_CODE();
1054 
1055  return 0;
1056  }
1057 
1058  //! Produce a linear operator for gamma5 epsilon(H) psi
1059  /*!
1060  * The operator acts on the entire lattice
1061  *
1062  * \param state_ gauge field state (Read)
1063  */
1066  {
1067  START_CODE();
1068 
1069  const EigenConnectState& state = dynamic_cast<EigenConnectState&>(*state_);
1070 
1071  int NEigVal = state.getNEig();
1072 
1073  /* The actual number of eigenvectors to project out.
1074  The highest of the valid low eigenmodes is not
1075  projected out. So we will put NEig = NEigVal - 1 */
1076  int NEig=NEigVal;
1077 
1078  /* The number of residuals and poles */
1079  int numroot;
1080 
1081  /* The roots, i.e., the shifts in the partial fraction expansion */
1082  multi1d<Real> rootQ;
1083 
1084  /* The residuals in the partial fraction expansion */
1085  multi1d<Real> resP;
1086 
1087  /* This will be our alpha(0) which can be 0 depending on type */
1088  /* an even- or oddness of RatPolyDeg*/
1089  Real coeffP;
1090 
1091  /* Array of values of the sign function evaluated on the eigenvectors of H */
1092  multi1d<Real> EigValFunc(NEigVal);
1093 
1094  // Common initialization
1095  initPrec(numroot, coeffP, resP, rootQ, NEig, EigValFunc, state);
1096 
1097 
1098  /* Finally construct and pack the operator */
1099  /* This is the operator of the form (1/2)*[(1+mu) + (1-mu)*gamma_5*eps] */
1100  switch( params.inner_solver_type ) {
1102  return new lg5eps(*Mact, state_,
1103  numroot, coeffP, resP, rootQ,
1104  NEig, EigValFunc, state.getEvectors(),
1106  break;
1108  return new lg5eps_double_pass(*Mact, state_,
1109  numroot, coeffP, resP, rootQ,
1110  NEig, EigValFunc, state.getEvectors(),
1112  break;
1113  default:
1114  QDPIO::cerr << "Unknown OverlapInnerSolverType " << params.inner_solver_type << std::endl;
1115  QDP_abort(1);
1116  }
1117 
1118  END_CODE();
1119 
1120  return 0;
1121  }
1122 
1123  //! Produce a conventional MdagM operator for this action
1124  /*!
1125  * This is the operator which you can always use
1126  * The operator acts on the entire lattice
1127  *
1128  * \param state_ gauge field state (Read)
1129  */
1130  DiffLinearOperator<LatticeFermion,
1131  multi1d<LatticeColorMatrix>,
1132  multi1d<LatticeColorMatrix> >*
1134  {
1135  // linOp news the linear operator and gives back pointer,
1136  // We call lmdagm with this pointer.
1137  // lmdagm is the only owner
1138  // No need to grab linOp with handle at this stage.
1139  return new DiffMdagMLinOp<T,P,Q>( linOp(state_) );
1140  }
1141 
1142  //! Produce a linear operator for this action
1143  /*!
1144  * The operator acts on the entire lattice
1145  *
1146  * \param state_ gauge field state (Read)
1147  */
1148  DiffLinearOperator<LatticeFermion,
1149  multi1d<LatticeColorMatrix>,
1150  multi1d<LatticeColorMatrix> >*
1152  {
1153 
1154  // If chirality is none, return traditional MdagM
1155  if ( ichiral == CH_NONE ) {
1156  return lMdagM(state_);
1157  }
1158  else {
1159  const EigenConnectState& state = dynamic_cast<EigenConnectState&>(*state_);
1160 
1161  int NEigVal = state.getNEig();
1162 
1163  /* The actual number of eigenvectors to project out.
1164  The highest of the valid low eigenmodes is not
1165  projected out. So we will put NEig = NEigVal - 1 */
1166  int NEig=NEigVal;
1167 
1168  /* The number of residuals and poles */
1169  int numroot;
1170 
1171  /* The roots, i.e., the shifts in the partial fraction expansion */
1172  multi1d<Real> rootQ;
1173 
1174  /* The residuals in the partial fraction expansion */
1175  multi1d<Real> resP;
1176 
1177  /* This will be our alpha(0) which can be 0 depending on type */
1178  /* an even- or oddness of RatPolyDeg*/
1179  Real coeffP;
1180 
1181  /* Array of values of the sign function evaluated on the eigenvectors of H */
1182  multi1d<Real> EigValFunc(NEigVal);
1183 
1184  // Common initialization
1185  init(numroot, coeffP, resP, rootQ, NEig, EigValFunc, state);
1186 
1187 
1188  // Finally construct and pack the operator
1189  // This is the operator of the form (1/2)*[(1+mu) + (1-mu)*gamma_5*eps]
1190  switch( params.inner_solver_type ) {
1192  return new lovddag(*Mact, state_, params.Mass,
1193  numroot, coeffP, resP, rootQ,
1194  NEig, EigValFunc, state.getEvectors(),
1196  break;
1198  return new lovddag_double_pass(*Mact, state_, params.Mass,
1199  numroot, coeffP, resP, rootQ,
1200  NEig, EigValFunc, state.getEvectors(),
1202  break;
1203  default:
1204  QDPIO::cerr << "Unknown OverlapInnerSolverType " << params.inner_solver_type << std::endl;
1205  QDP_abort(1);
1206  }
1207 
1208  }
1209  END_CODE();
1210 
1211  return 0;
1212  }
1213 
1214 
1215  //! Produce a linear operator for this action
1216  /*!
1217  * The operator acts on the entire lattice
1218  *
1219  * \param state_ gauge field state (Read)
1220  */
1223  {
1224 
1225  // If chirality is none, return traditional MdagM
1226  if ( ichiral == CH_NONE ) {
1227  return lMdagM(state_);
1228  }
1229  else {
1230  const EigenConnectState& state = dynamic_cast<EigenConnectState&>(*state_);
1231 
1232  int NEigVal = state.getNEig();
1233 
1234  /* The actual number of eigenvectors to project out.
1235  The highest of the valid low eigenmodes is not
1236  projected out. So we will put NEig = NEigVal - 1 */
1237  int NEig=NEigVal;
1238 
1239  /* The number of residuals and poles */
1240  int numroot;
1241 
1242  /* The roots, i.e., the shifts in the partial fraction expansion */
1243  multi1d<Real> rootQ;
1244 
1245  /* The residuals in the partial fraction expansion */
1246  multi1d<Real> resP;
1247 
1248  /* This will be our alpha(0) which can be 0 depending on type */
1249  /* an even- or oddness of RatPolyDeg*/
1250  Real coeffP;
1251 
1252  /* Array of values of the sign function evaluated on the eigenvectors of H */
1253  multi1d<Real> EigValFunc(NEigVal);
1254 
1255  // Common initialization
1256  initPrec(numroot, coeffP, resP, rootQ, NEig, EigValFunc, state);
1257 
1258 
1259  // Finally construct and pack the operator
1260  // This is the operator of the form (1/2)*[(1+mu) + (1-mu)*gamma_5*eps]
1261  switch( params.inner_solver_type ) {
1263  return new lovddag(*Mact, state_, params.Mass,
1264  numroot, coeffP, resP, rootQ,
1265  NEig, EigValFunc, state.getEvectors(),
1267  break;
1269  return new lovddag_double_pass(*Mact, state_, params.Mass,
1270  numroot, coeffP, resP, rootQ,
1271  NEig, EigValFunc, state.getEvectors(),
1273  break;
1274  default:
1275  QDPIO::cerr << "Unknown OverlapInnerSolverType " << params.inner_solver_type << std::endl;
1276  QDP_abort(1);
1277  }
1278 
1279  }
1280  END_CODE();
1281 
1282  return 0;
1283  }
1284 
1285  //! Produce a conventional MdagM operator for this action
1286  /*!
1287  * This is the operator which you can always use
1288  * The operator acts on the entire lattice
1289  *
1290  * \param state_ gauge field state (Read)
1291  */
1294  {
1295  // linOp news the linear operator and gives back pointer,
1296  // We call lmdagm with this pointer.
1297  // lmdagm is the only owner
1298  // No need to grab linOp with handle at this stage.
1299  return new MdagMLinOp<LatticeFermion>( linOpPrecondition(state_) );
1300  }
1301 
1302  //! Create a ConnectState with just the gauge fields
1304  OvlapPartFrac4DFermAct::createState(const multi1d<LatticeColorMatrix>& u_) const
1305  {
1306  return new EigenConnectState(fbc, u_);
1307  }
1308 
1309 
1310  //! Create OverlapConnectState from XML
1312  OvlapPartFrac4DFermAct::createState(const multi1d<LatticeColorMatrix>& u_,
1313  XMLReader& state_info_xml,
1314  const std::string& state_info_path) const
1315  {
1316  XMLFileWriter test("./test");
1317  test << state_info_xml;
1318 
1319  //QDPIO::cout << "Creating State from XML: " << reader_contents.str() << std::endl << std::flush;
1320 
1321  std::string eigen_info_id;
1322  if( state_info_xml.count("/StateInfo/eigen_info_id") == 1 ) {
1323 
1324  read(state_info_xml, "/StateInfo/eigen_info_id", eigen_info_id);
1325  QDPIO::cout << "Using eigen_info_id: " << eigen_info_id << std::endl;
1326 
1327  EigenConnectState *ret_val = new EigenConnectState(fbc, u_, eigen_info_id);
1328 
1329 
1330  // Check the low evs
1331  Handle< FermState<T,P,Q> > state_aux(new SimpleFermState<T,P,Q>(fbc, u_));
1332  Handle< LinearOperator<T> > Maux = Mact->hermitianLinOp(state_aux);
1333 
1334  for(int vec = 0; vec < ret_val->getNEig(); vec++) {
1335 
1336  LatticeFermion lambda_e, H_e;
1337  Real lambda = ret_val->getEvalues()[vec];
1338  LatticeFermion ev = ret_val->getEvectors()[vec];
1339 
1340  (*Maux)(H_e, ev, PLUS);
1341  lambda_e = lambda * ev;
1342 
1343  LatticeFermion diff = H_e - lambda_e;
1344  Double norm_diff = sqrt(norm2(diff));
1345  Double norm_diff_rel = norm_diff/fabs(lambda);
1346 
1347  QDPIO::cout << "EV Check["<< vec<<"]: lambda="<< lambda <<" resid="<<norm_diff<<" rel. resid="<< norm_diff_rel << std::endl;
1348 
1349  }
1350  return ret_val;
1351 
1352  }
1353  else {
1354  QDPIO::cout << "No StateInfo Found: " << std::endl;
1355 
1356  return new EigenConnectState(fbc, u_);
1357  }
1358 
1359 
1360  }
1361 
1362 
1363 }
Primary include file for CHROMA library code.
Create a simple ferm connection state.
Differentiable Linear Operator.
Definition: linearop.h:98
Differentiable M^dag.M linear operator.
Definition: lmdagm.h:160
Eigen-state holder.
Definition: eigen_state.h:23
multi1d< Real > & getEvalues()
Return the eigenvalues.
Definition: eigen_state.h:65
multi1d< LatticeFermion > & getEvectors()
Definition: eigen_state.h:82
Base class for all fermion action boundary conditions.
Definition: fermbc.h:20
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
M^dag.M linear operator.
Definition: lmdagm.h:22
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.
4D Zolotarev variant of Overlap-Dirac operator
UnprecLinearOperator< T, P, Q > * unprecLinOp(Handle< FermState< T, P, Q > > state, const Real &m_q) const
Produce a linear operator for this action.
LinearOperator< T > * lgamma5epsHPrecondition(Handle< FermState< T, P, Q > > state) const
Produce a linear operator that gives back gamma_5 eps(H)
LinearOperator< T > * linOpPrecondition(Handle< FermState< T, P, Q > > state) const
Produce a linear operator for this action.
LinearOperator< T > * lMdagMPrecondition(Handle< FermState< T, P, Q > > state) const
Produce a linear operator M^dag.M for this action.
DiffLinearOperator< T, P, Q > * lMdagM(Handle< FermState< T, P, Q > > state) const
Produce a linear operator M^dag.M for this action.
Handle< UnprecWilsonTypeFermAct< T, P, Q > > Mact
OvlapPartFrac4DFermActParams params
LinearOperator< T > * lgamma5epsH(Handle< FermState< T, P, Q > > state) const
Produce a linear operator that gives back gamma_5 eps(H)
OvlapPartFrac4DFermAct()
Partial constructor not allowed.
Handle< CreateFermState< T, P, Q > > cfs
void init(int &numroot, Real &coeffP, multi1d< Real > &resP, multi1d< Real > &rootQ, int &NEig, multi1d< Real > &EigValFunc, const EigenConnectState &state) const
Helper in construction.
void initPrec(int &numroot, Real &coeffP, multi1d< Real > &resP, multi1d< Real > &rootQ, int &NEig, multi1d< Real > &EigValFunc, const EigenConnectState &state) const
Construct stuff but use RatPolyDegPrec in the polynomial.
EigenConnectState * createState(const multi1d< LatticeColorMatrix > &u, XMLReader &state_info_xml, const std::string &state_info_path) const
Create OverlapFermState<T,P,Q> from XML.
Simple version of FermState.
static T & Instance()
Definition: singleton.h:432
Unpreconditioned linear operator including derivatives.
Definition: linearop.h:185
Unpreconditioned Wilson-like fermion actions with derivatives.
Definition: fermact.orig.h:491
Wilson-like fermion actions.
Definition: fermact.orig.h:344
Internal Overlap-pole operator sign function.
Internal Overlap-pole operator.
Definition: lg5eps_w.h:37
Internal Overlap-pole operator.
Internal Overlap-pole operator.
Definition: lovddag_w.h:36
Internal Overlap-pole operator.
Internal Overlap-pole operator.
Definition: lovlapms_w.h:36
Enums.
All ferm create-state method.
Fermion action factories.
Fermionic boundary condition reader.
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.
Handle< FermBC< LatticeFermion, multi1d< LatticeColorMatrix >, multi1d< LatticeColorMatrix > > > reader(XMLReader &xml_in, const std::string &path)
Helper function for the FermionAction readers.
@ COEFF_TYPE_ZOLOTAREV
@ COEFF_TYPE_TANH
@ COEFF_TYPE_TANH_UNSCALED
Params params
unsigned n
Definition: ldumul_w.cc:36
Internal Overlap-pole operator.
Internal pole epsilon operator. Just the unitary part.
Linear Operators.
Internal Overlap-pole operator.
Internal Overlap-pole operator.
Internal Overlap-pole operator.
Internal Overlap-pole operator.
int t
Definition: meslate.cc:37
static bool registered
Local registration flag.
bool registerAll()
Register all the factories.
FermionAction< LatticeFermion, multi1d< LatticeColorMatrix >, multi1d< LatticeColorMatrix > > * createFermAct(XMLReader &xml_in, const std::string &path)
Callback function.
const std::string name
Name to be used.
WilsonTypeFermAct< LatticeFermion, multi1d< LatticeColorMatrix >, multi1d< LatticeColorMatrix > > * createFermAct4D(XMLReader &xml_in, const std::string &path)
Callback function.
static const LatticeInteger & alpha(const int dim)
Definition: stag_phases_s.h:43
Asqtad Staggered-Dirac operator.
Definition: klein_gord.cc:10
Chirality
Definition: ischiral_w.h:8
@ CH_NONE
Definition: ischiral_w.h:8
LatticeFermion tmp
Definition: mespbg5p_w.cc:36
int ichiral
Definition: mespbp_s.cc:21
push(xml_out,"Condensates")
int i
Definition: pbg5p_w.cc:55
@ PLUS
Definition: chromabase.h:45
pop(xml_out)
START_CODE()
const WilsonTypeFermAct< multi1d< LatticeFermion > > Handle< const ConnectState > state
Definition: pbg5p_w.cc:28
const WilsonTypeFermAct< multi1d< LatticeFermion > > & S_f
Definition: pbg5p_w.cc:27
static QDP_ColorVector * in
FloatingPoint< double > Double
Definition: gtest.h:7351
::std::string string
Definition: gtest.h:1979
4D Zolotarev variant of Overlap-Dirac operator
Simple ferm state and a creator.
CoeffType approximation_type
Type of approximation ZOLOTAREV or TANH.
struct Chroma::OvlapPartFrac4DFermActParams::InvParamInner invParamInner
Unpreconditioned Wilson fermion action.
void zolotarev_free(ZOLOTAREV_DATA *f)
ZOLOTAREV_DATA * higham(PRECISION epsilon, int n)
ZOLOTAREV_DATA * zolotarev(PRECISION epsilon, int n, int type)