CHROMA
eoprec_ovlap_contfrac5d_pv_linop_array_w.cc
Go to the documentation of this file.
1 /*! \file
2  * \brief Even-odd preconditioned Pauli-Villars Continued Fraction 5D
3  */
4 
7 
8 using namespace QDP::Hints;
9 
10 namespace Chroma
11 {
12  EvenOddPrecOvlapContFrac5DPVLinOpArray::EvenOddPrecOvlapContFrac5DPVLinOpArray(
14  const Real& _m_q,
15  const Real& _OverMass,
16  int _N5,
17  const Real& _scale_fac,
18  const multi1d<Real>& _alpha,
19  const multi1d<Real>& _beta,
20  const bool _isLastZeroP ) :
21  m_q(_m_q), OverMass(_OverMass), N5(_N5), scale_fac(_scale_fac),
22  alpha(_alpha), beta(_beta), isLastZeroP(_isLastZeroP)
23  {
24  START_CODE();
25 
26  // It is always N5-1...
27  Dslash.create(state,N5-1);
28 
29  // Now compute some coefficients.
30  // First the beta_tilde_i
31  // Basically this is beta[n]*Hsign*scale_fac
32  // Now N5 is always odd. So the first Hsign is +
33  // and the last one should also be
34  // Hence at the end of this loop Hsign should be flipped from +->-
35  beta_tilde.resize(N5);
36  int Hsign = 1;
37  for(int i=0; i < N5; i++)
38  {
39  // Flip Hsign
40  beta_tilde[i] = beta[i]*Hsign*scale_fac;
41 
42  /*
43  QDPIO::cout << "beta["<<i<<"]=" << beta[i]
44  << " scale_fac=" << scale_fac
45  << " beta_tilde["<<i<<"]=" << beta_tilde[i] << std::endl;
46 
47  */
48  Hsign = -Hsign;
49  }
50 
51  // Sanity Check
52  if ( Hsign > 0 ) {
53  QDPIO::cerr << "Something is wrong. At the end of this loop"
54  << " Hsign should be -ve" << std::endl;
55  }
56 
57  // Now the a_i's and b_i's
58  a.resize(N5);
59  for(int i=0; i < N5-1; i++) {
60  a[i] = beta_tilde[i]*(Nd - OverMass);
61  }
62  a[N5-1] = 1; // CHECK THIS: WHAT IS THE NORM OF THE 1 IN THE PV TERM
63 
64  /*
65  QDPIO::cout << "Nd - OverMass = " << Nd - OverMass << std::endl;
66  for(int i=0; i < N5; i++) {
67  QDPIO::cout << "a["<<i<<"]= " << a[i] << std::endl;
68  }
69  */
70 
71  // Now the d-s
72  multi1d<Real> d(N5);
73  dinv.resize(N5);
74  d[0] = a[0];
75  dinv[0] = Real(1)/d[0];
76 
77  d[N5-1] = a[N5-1];
78  dinv[N5-1] = Real(1)/d[N5-1];
79 
80  for(int i=1; i < N5-1; i++) {
81  d[i] = a[i] - (alpha[i-1]*alpha[i-1])/d[i-1];
82  dinv[i] = Real(1)/d[i];
83  }
84 
85  off_diag_coeff.resize(N5-1);
86  for(int i=0; i < N5-1; i++) {
87  off_diag_coeff[i] = -Real(0.5)*beta_tilde[i];
88  }
89 
90  /*
91  for(int i=0; i < N5; i++) {
92  QDPIO::cout << "d["<<i<<"]=" << d[i] << std::endl;
93  }
94  */
95 
96  // Now the u-s
97  u.resize(N5-1);
98  u[N5-2] = 0.0;
99  for(int i=0; i < N5-2; i++) {
100  u[i] = alpha[i]/d[i];
101  }
102 
103  /*
104  for(int i=0; i < N5-1; i++) {
105  QDPIO::cout << "u["<<i<<"] = " << u[i] << std::endl;
106  }
107  */
108 
109  END_CODE();
110  }
111 
112 
113 
114 
115  //! Apply the even-even (odd-odd) coupling piece of the domain-wall fermion operator
116  /*!
117  * \ingroup linop
118  *
119  * The operator acts on the entire lattice
120  *
121  * 6NcNs + N5-2*[ 6NcNs ] + (N5-3)*4Nc Ns
122  * = N5-1*(6NcNs) + (N5-3)*4NcNs
123  * = 6*N5*NcNs - 6NcNs + 4N5NcNs - 12 NcNs
124  * =10*N5 NcNs - 18NcNs = (10*N5-18) NcNs
125  *
126  * \param psi Pseudofermion field (Read)
127  * \param isign Flag ( PLUS | MINUS ) (Read)
128  * \param cb checkerboard ( 0 | 1 ) (Read)
129  */
130  void
132  const multi1d<LatticeFermion>& psi,
133  enum PlusMinus isign,
134  const int cb) const
135  {
136  START_CODE();
137 
138  if( chi.size() != N5 ) chi.resize(N5);
139 
140  // We don't care about the isign because our operator is Hermitian
141  // Apply matrix
142  // [ A_0 B_0 0 ... ] [ psi_0 ]
143  // [ B_0 A_1 B_1 ... ... ] [ psi_1 ]
144  // [ 0 ... ... ... ... ] [ psi_2 ]
145  // [ ... ... 0 B_N5-3 A_N5-2 B_N5-2 ] [ psi_N5-2 ]
146  // [ ... ... ... 0 B_N5-2 A_N5-1 ] [ psi_N5-1 ]
147 
148  // With A_i = gamma_5 a_i = a_i gamma_5
149  // and B_i = b_i I = alpha_i I
150 
151  LatticeFermion tmp; moveToFastMemoryHint(tmp);
152  int G5=Ns*Ns-1;
153 
154  // First 0ne
155  /*
156  tmp[rb[cb]] = Gamma(G5)*psi[0];
157  chi[0][rb[cb]] = a[0]*tmp;
158  */
159  if( N5 > 1 ) {
160  // 6NcNs flops
161  chi[0][rb[cb]] = alpha[0]*psi[1] + a[0]*(GammaConst<Ns,Ns*Ns-1>()*psi[0]);
162  }
163  else {
164  chi[0][rb[cb]] = a[0]*(GammaConst<Ns,Ns*Ns-1>()*psi[0]);
165  }
166  // All the rest
167 
168  // N5-2*[ 6NcNs ] + (N5-3)*4Nc Ns
169  for(int i=1; i < N5-1; i++)
170  {
171  // B_{i-1} psi_[i-1]
172  /*
173  chi[i][rb[cb]] = alpha[i-1]*psi[i-1];
174 
175  // A_{i} psi[i] = a_{i} g_5 psi[i]
176  tmp[rb[cb]] = Gamma(G5)*psi[i];
177  chi[i][rb[cb]] += a[i]*tmp;
178  */
179  chi[i][rb[cb]] = alpha[i-1]*psi[i-1] + a[i]*(GammaConst<Ns,Ns*Ns-1>()*psi[i]);
180 
181  // When i hits N5-1, we don't have the B_N5-1 term
182  if(i < N5-2)
183  chi[i][rb[cb]] += alpha[i]*psi[i+1];
184  }
185 
186  chi[N5-1][rb[cb]] = psi[N5-1];
187 
188  END_CODE();
189  }
190 
191 
192  //! Apply the inverse even-even (odd-odd)
193  /*!
194  * \ingroup linop
195  *
196  * Here we apply the LDU decomposition
197  *
198  *
199  * 10NcNs(N5-2)+2NcNs
200  * = (10N5 - 18)NcNs flops per cb_site
201  *
202  * \param psi Pseudofermion field (Read)
203  * \param isign Flag ( PLUS | MINUS ) (Read)
204  * \param cb checkerboard ( 0 | 1 ) (Read)
205  */
206  void
208  multi1d<LatticeFermion>& chi,
209  const multi1d<LatticeFermion>& psi,
210  enum PlusMinus isign,
211  const int cb) const
212  {
213  START_CODE();
214 
215  if( chi.size() != N5 ) chi.resize(N5);
216 
217  multi1d<LatticeFermion> y(N5); moveToFastMemoryHint(y);
218 
219  LatticeFermion tmp; moveToFastMemoryHint(tmp);
220  Real coeff;
221 
222  const int G5 = Ns*Ns-1;
223 
224  // Solve L y = psi
225  y[0][rb[cb]] = psi[0];
226 
227  // (N5-2) * 4NcNs flops
228  for(int i = 1; i < N5-1; i++)
229  {
230  /* tmp[rb[cb]] = Gamma(G5)*y[i-1]; */
231  y[i][rb[cb]] = psi[i] - u[i-1]*(GammaConst<Ns,Ns*Ns-1>()*y[i-1]);
232  }
233 
234  // Backsubstitute U chi = y
235 
236  // Special note. chi[N5-1] = y[N5-1] = psi[N5-1] -- lowest
237  // corner is a unit matrix
238  chi[N5-1][rb[cb]] = psi[N5-1];
239 
240 
241  // Real backsubstitutions starts from chi[N5-2]
242  // 2NcNs flops
243  chi[N5-2][rb[cb]] = dinv[N5-2]*(GammaConst<Ns,Ns*Ns-1>()*y[N5-2]);
244 
245  // N5-2 * 6NcNs flops
246  for(int i = N5-3; i >= 0; i--) {
247  //tmp = Gamma(G5)*chi[i+1];
248  // y[i][rb[cb]] = dinv[i]*(GammaConst<Ns,Ns*Ns-1>()*y[i]);
249  chi[i][rb[cb]] = GammaConst<Ns,Ns*Ns-1>()*( dinv[i]*y[i] - u[i]*chi[i+1]);
250  }
251 
252  END_CODE();
253  }
254 
255 
256  //! Apply the off diagonal block
257  /*!
258  * (N5-1)*(Dslash + 2NcNs)
259  *
260  * \param chi result (Modify)
261  * \param psi source (Read)
262  * \param isign Flag ( PLUS | MINUS ) (Read)
263  * \param cb checkerboard ( 0 | 1 ) (Read)
264  */
266  multi1d<LatticeFermion>& chi,
267  const multi1d<LatticeFermion>& psi,
268  enum PlusMinus isign,
269  const int cb) const
270  {
271  START_CODE();
272 
273  if( chi.size() != N5 ) chi.resize(N5);
274 
275  multi1d<LatticeFermion> tmp(N5); moveToFastMemoryHint(tmp);
276  Real coeff;
277  int G5 = Ns*Ns-1;
278 
279  // (N5-1)*(Dslash + 2NcNs)
280  // Now donw with Dslash std::vector...
281  Dslash.apply(tmp, psi, PLUS, cb);
282 
283  for(int i=0; i < N5-1; i++)
284  {
285  // Chi_i is now -(1/2) beta_tilde_i Dslash
286  chi[i][rb[cb]] = off_diag_coeff[i]*(GammaConst<Ns,Ns*Ns-1>()*tmp[i]);
287  }
288 
289  chi[N5-1][rb[cb]] = zero;
290 
291  END_CODE();
292  }
293 
294 
295  // Derivative of even-odd linop component
296  /*
297  * This is a copy of the above applyOffDiag with the D.apply(...) replaced
298  * by D.deriv(ds_tmp,...) like calls.
299  */
300  void
302  const multi1d<LatticeFermion>& chi,
303  const multi1d<LatticeFermion>& psi,
304  enum PlusMinus isign,
305  int cb) const
306  {
307  START_CODE();
308 
309  ds_u.resize(Nd);
310  ds_u = zero;
311 
312  multi1d<LatticeColorMatrix> ds_tmp(Nd);
313 
314  LatticeFermion tmp; moveToFastMemoryHint(tmp);
315  Real coeff;
316  int G5 = Ns*Ns-1;
317 
318  switch (isign)
319  {
320  case PLUS:
321  // Optimisation... do up to the penultimate block...
322  for(int i=0; i < N5-1; i++)
323  {
324  // CB is CB of TARGET
325  // consider gamma_5 Dslash
326  // tmp[rb[cb]] = Gamma(G5)*chi[i];
327 
328  // Multiply coefficient
329  // coeff = -Real(0.5)*beta_tilde[i];
330 
331  // Chi_i is now -(1/2) beta_tilde_i Dslash
332  tmp[rb[cb]] = off_diag_coeff[i]*(GammaConst<Ns,Ns*Ns-1>()*chi[i]);
333 
334  // Apply g5 Dslash
335  Dslash.deriv(ds_tmp, tmp, psi[i], PLUS, cb);
336  ds_u += ds_tmp;
337  }
338  break;
339 
340  case MINUS:
341  // Optimisation... do up to the penultimate block...
342  for(int i=0; i < N5-1; i++)
343  {
344  // CB is CB of TARGET
345  // consider Dslash^dag gamma_5
346  // tmp[rb[1-cb]] = Gamma(G5)*psi[i];
347 
348  // Multiply coefficient
349  // coeff = -Real(0.5)*beta_tilde[i];
350 
351  // Chi_i is now -(1/2) beta_tilde_i Dslash
352  tmp[rb[1-cb]] = off_diag_coeff[i]*(GammaConst<Ns,Ns*Ns-1>()*psi[i]);
353 
354  // Apply g5 Dslash
355  Dslash.deriv(ds_tmp, chi[i], tmp, MINUS, cb);
356  ds_u += ds_tmp;
357  }
358  break;
359 
360  default:
361  QDP_error_exit("unknown case");
362  }
363 
364 
365 // if( !isLastZeroP )
366 // {
367 // // This term does not contribute to PV
368 // }
369 
370 
371  END_CODE();
372  }
373 
374 
375 } // End Namespace Chroma
376 
377 
void applyOffDiag(multi1d< LatticeFermion > &chi, const multi1d< LatticeFermion > &psi, enum PlusMinus isign, const int cb) const
Apply the off diagonal block.
void applyDerivOffDiag(multi1d< LatticeColorMatrix > &ds_u, const multi1d< LatticeFermion > &chi, const multi1d< LatticeFermion > &psi, enum PlusMinus isign, int cb) const
Apply the even-odd (odd-even) coupling piece of the NEF operator.
Support class for fermion actions and linear operators.
Definition: state.h:94
Class for counted reference semantics.
Definition: handle.h:33
virtual void deriv(multi1d< LatticeColorMatrix > &ds_u, const multi1d< LatticeFermion > &chi, const multi1d< LatticeFermion > &psi, enum PlusMinus isign) const
Take deriv of D.
Include possibly optimized Wilson dslash.
Even-odd preconditioned Pauli-Villars Continued Fraction 5D.
void apply(multi1d< LatticeFermion > &chi, const multi1d< LatticeFermion > &psi, enum PlusMinus isign, int cb) const
General Wilson-Dirac dslash.
void create(Handle< FermState< T, P, Q > > state, int N5_)
Creation routine.
void applyDiag(multi1d< LatticeFermion > &chi, const multi1d< LatticeFermion > &psi, enum PlusMinus isign, const int cb) const
Apply the even-even (odd-odd) coupling piece of the domain-wall fermion operator.
void applyDiagInv(multi1d< LatticeFermion > &chi, const multi1d< LatticeFermion > &psi, enum PlusMinus isign, const int cb) const
Apply the inverse even-even (odd-odd) coupling piece of the domain-wall fermion operator.
int y
Definition: meslate.cc:35
Nd
Definition: meslate.cc:74
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
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
DComplex d
Definition: invbicg.cc:99
START_CODE()
int cb
Definition: invbicg.cc:120
const WilsonTypeFermAct< multi1d< LatticeFermion > > Handle< const ConnectState > state
Definition: pbg5p_w.cc:28
Double zero
Definition: invbicg.cc:106