CHROMA
eoprec_ovlap_contfrac5d_linop_array_w.cc
Go to the documentation of this file.
1 /*! \file
2  * \brief Even-odd prec. 5D continued fraction linop
3  */
4 
7 
8 #if 0
9 
10 namespace Chroma
11 {
13  Handle< FermState<T,P,Q> > state,
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  Handle< DslashLinearOperator<LatticeFermion,
27  multi1d<LatticeColorMatrix>, multi1d<LatticeColorMatrix> > > Ds(new WilsonDslash(state));
28  Dslash = Ds; // Copy Handle -- M now owns dslash
29 
30  // The mass ratio
31  Real mass = ( Real(1) + m_q ) / (Real(1) - m_q);
32 
33  // Now compute some coefficients.
34  // First the beta_tilde_i
35  // Basically this is beta[n]*Hsign*scale_fac
36  // Now N5 is always odd. So the first Hsign is +
37  // and the last one should also be
38  // Hence at the end of this loop Hsign should be flipped from +->-
39  beta_tilde.resize(N5);
40  int Hsign = 1;
41  for(int i=0; i < N5; i++)
42  {
43  // Flip Hsign
44  beta_tilde[i] = beta[i]*Hsign*scale_fac;
45 
46  /*
47  QDPIO::cout << "beta["<<i<<"]=" << beta[i]
48  << " Hsign=" << Hsign
49  << " scale_fac=" << scale_fac
50  << " beta_tilde["<<i<<"]=" << beta_tilde[i] << std::endl;
51 
52  */
53  Hsign = -Hsign;
54  }
55 
56  // Sanity Check
57  if ( Hsign > 0 ) {
58  QDPIO::cerr << "Something is wrong. At the end of this loop"
59  << " Hsign should be -ve" << std::endl;
60  }
61 
62  // Now the a_i's and b_i's
63  a.resize(N5);
64  for(int i=0; i < N5-1; i++) {
65  a[i] = beta_tilde[i]*(Nd - OverMass);
66  }
67  a[N5-1] = mass + (beta_tilde[N5-1]*(Nd - OverMass));
68 
69  /*
70  QDPIO::cout << "Nd - OverMass = " << Nd- OverMass << std::endl;
71  for(int i=0; i < N5; i++) {
72  QDPIO::cout << "a["<<i<<"]= " << a[i] << std::endl;
73  }
74  */
75  // Now the d-s
76  multi1d<Real> d(N5);
77  invd.resize(N5);
78 
79  d[0] = a[0];
80  invd[0] = Real(1)/d[0];
81 
82  for(int i=1; i < N5; i++) {
83  d[i] = a[i] - (alpha[i-1]*alpha[i-1])/d[i-1];
84  invd[i] = Real(1)/d[i];
85  }
86 
87 
88  /*
89  for(int i=0; i < N5; i++) {
90  QDPIO::cout << "d["<<i<<"]=" << d[i] << std::endl;
91  }
92  */
93 
94  // Now the u-s
95  u.resize(N5-1);
96  for(int i=0; i < N5-1; i++) {
97  u[i] = alpha[i]/d[i];
98  }
99 
100  off_diag_coeff.resize(N5);
101  for(int i=0; i < N5; i++) {
102  off_diag_coeff[i] = -Real(0.5)*beta_tilde[i];
103  }
104  /*
105  for(int i=0; i < N5-1; i++) {
106  QDPIO::cout << "u["<<i<<"] = " << u[i] << std::endl;
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  * \param psi Pseudofermion field (Read)
122  * \param isign Flag ( PLUS | MINUS ) (Read)
123  * \param cb checkerboard ( 0 | 1 ) (Read)
124  *
125  *
126  * Flopcount: N5*6NcNs + (N5-2)*4NcNs = NcNs( 6N5 +4(N5-2) ) = (10N5-8) Nc Ns / cb_site
127  */
128  void
129  QDPEvenOddPrecOvlapContFrac5DLinOpArray::applyDiag(multi1d<LatticeFermion>& chi,
130  const multi1d<LatticeFermion>& psi,
131  enum PlusMinus isign,
132  const int cb) const
133  {
134  START_CODE();
135 
136  if( chi.size() != N5 ) chi.resize(N5);
137 
138  // We don't care about the isign because our operator is Hermitian
139  // Apply matrix
140  // [ A_0 B_0 0 ... ] [ psi_0 ]
141  // [ B_0 A_1 B_1 ... ... ] [ psi_1 ]
142  // [ 0 ... ... ... ... ] [ psi_2 ]
143  // [ ... ... 0 B_N5-3 A_N5-2 B_N5-2 ] [ psi_N5-2 ]
144  // [ ... ... ... 0 B_N5-2 A_N5-1 ] [ psi_N5-1 ]
145 
146  // With A_i = gamma_5 a_i = a_i gamma_5
147  // and B_i = b_i I = alpha_i I
148 
149  LatticeFermion tmp; moveToFastMemoryHint(tmp);
150  int G5=Ns*Ns-1;
151 
152  // First 0ne
153  // Operation: chi[0][rb[cb]] = a[0] G5 psi[0] + alpha[0]*psi[1]
154  //
155  // Useful flops: 6Nc Ns / site
156  // tmp[rb[cb]] = Gamma(G5)*psi[0];
157  // chi[0][rb[cb]] = a[0]*tmp;
158 
159  if( N5 > 1 ) {
160  chi[0][rb[cb]] = alpha[0]*psi[1] + a[0]*(GammaConst<Ns,Ns*Ns-1>()*psi[0]);
161  }
162  else {
163  chi[0][rb[cb]] = a[0]*(GammaConst<Ns,Ns*Ns-1>()*psi[0]);
164  }
165 
166  // All the rest
167  for(int i=1; i < N5; i++) {
168 
169  // Operation:
170  // N5 - 1 times:
171  // chi[i] = alpha[i-1]*psi[i-1] + a[i] Gamma_5 *psi[i]
172  // N5 - 2 times:
173  // chi[i] += alpha[i]*psi[i+1];
174  // Useful flops = (N5-1) * 6NcNs + (N5-2)*4Nc*Ns
175 
176  /*
177  // B_{i-1} psi_[i-1]
178  chi[i][rb[cb]] = alpha[i-1]*psi[i-1];
179 
180  // A_{i} psi[i] = a_{i} g_5 psi[i]
181  tmp[rb[cb]] = Gamma(G5)*psi[i];
182  chi[i][rb[cb]] += a[i]*tmp;
183  */
184  chi[i][rb[cb]] = alpha[i-1]*psi[i-1] + a[i]*(GammaConst<Ns,Ns*Ns-1>()*psi[i]);
185 
186  // When i hits N5-1, we don't have the B_N5-1 term
187  if(i < N5-1) {
188  chi[i][rb[cb]] += alpha[i]*psi[i+1];
189  }
190  }
191 
192  END_CODE();
193  }
194 
195 
196  //! Apply the inverse even-even (odd-odd)
197  /*!
198  * \ingroup linop
199  *
200  * Here we apply the LDU decomposition
201  *
202  * \param psi Pseudofermion field (Read)
203  * \param isign Flag ( PLUS | MINUS ) (Read)
204  * \param cb checkerboard ( 0 | 1 ) (Read)
205 
206  *
207  * Total flopcount: (N5-1)*4NcNs + 2NcNs + (N5-1)*6NcNs
208  * = (N5-1)*10NcNs + 2NcNs
209  * = (10N5-8) Nc Ns per_cb_site
210  */
211  void
212  QDPEvenOddPrecOvlapContFrac5DLinOpArray::applyDiagInv(
213  multi1d<LatticeFermion>& chi,
214  const multi1d<LatticeFermion>& psi,
215  enum PlusMinus isign,
216  const int cb) const
217  {
218  START_CODE();
219 
220  if( chi.size() != N5 ) chi.resize(N5);
221 
222  multi1d<LatticeFermion> y(N5); moveToFastMemoryHint(y);
223 
224  LatticeFermion tmp; moveToFastMemoryHint(tmp);
225  Real coeff;
226 
227  const int G5 = Ns*Ns-1;
228 
229  // Solve L y = psi
230  y[0][rb[cb]] = psi[0];
231 
232  // (N5-1)*4NcNs
233  for(int i = 1; i < N5; i++) {
234  // tmp[rb[cb]] = Gamma(G5)*y[i-1];
235  // y[i][rb[cb]] = psi[i] - u[i-1]*tmp;
236  y[i][rb[cb]] = psi[i] - u[i-1]*(GammaConst<Ns,Ns*Ns-1>()*y[i-1]);
237  }
238 
239  // Invert diagonal piece y <- D^{-1} y
240  // N5 times: y = (1/d_i) gamma_5 y[i]
241  // Useful flops: N5 * 2NcNs flops / site
242  // Rolled this into the bottom loop
243 
244  // Backsubstitute U chi = y
245 
246  // 2NcNs
247 
248  chi[N5-1][rb[cb]] = invd[N5-1]*(GammaConst<Ns,Ns*Ns-1>()*y[N5-1]);
249 
250  // N5-1 * 6NcNs
251  for(int i = N5-2; i >= 0; i--) {
252  // tmp[rb[cb]] = Gamma(G5)*chi[i+1]
253  // chi[i][rb[cb]] = y[i] - u[i]*tmp;
254  // y[i][rb[cb]] = invd[i]*(GammaConst<Ns,Ns*Ns-1>()*y[i]);
255  // chi[i][rb[cb]] = y[i] - u[i]*(GammaConst<Ns,Ns*Ns-1>()*chi[i+1]);
256  chi[i][rb[cb]] = GammaConst<Ns,Ns*Ns-1>()*(invd[i]*y[i]-u[i]*chi[i+1]);
257  }
258 
259  //Done! That was not that bad after all....
260  //See, I told you so...
261  END_CODE();
262  }
263 
264  //! Apply the off diagonal block
265  /*!
266  * \param chi result (Modify)
267  * \param psi source (Read)
268  * \param isign Flag ( PLUS | MINUS ) (Read)
269  * \param cb checkerboard ( 0 | 1 ) (Read)
270  *
271  * Total flopcount: (N5-1)*(Dslash_cb_flops + 2NcNs) per cb_site (isLastZeroP==true)
272  * N5*(Dslash_cb_flops+2NcNs) per cb_site (isLastZeroP==false)
273  *
274  *
275  */
276  void QDPEvenOddPrecOvlapContFrac5DLinOpArray::applyOffDiag(
277  multi1d<LatticeFermion>& chi,
278  const multi1d<LatticeFermion>& psi,
279  enum PlusMinus isign,
280  const int cb) const
281  {
282  START_CODE();
283 
284  if( chi.size() != N5 ) chi.resize(N5);
285 
286  LatticeFermion tmp; moveToFastMemoryHint(tmp);
287 
288  int G5 = Ns*Ns-1;
289 
290  // Optimisation... do up to the penultimate block...
291 
292  // (N5-1)( Dslash + 2NcNs) flops/site
293 
294  for(int i=0; i < N5-1; i++) {
295  // CB is CB of TARGET
296  // gamma_5 Dslash is hermitian so I can ignore isign
297 
298  // Apply g5 Dslash
299  Dslash->apply(tmp, psi[i], PLUS, cb);
300 
301  // chi[i][rb[cb]] = Gamma(G5)*tmp;
302 
303  // Chi_i is now -(1/2) beta_tilde_i Dslash
304  chi[i][rb[cb]] = off_diag_coeff[i]*(GammaConst<Ns,Ns*Ns-1>()*tmp);
305  }
306 
307 
308  // Only do last block if beta_tilde[i] is not zero
309  // ( Dslash + 2NcNs) flops per site if done.
310  if( !isLastZeroP ) {
311  Dslash->apply(tmp, psi[N5-1], PLUS, cb);
312  // chi[N5-1][rb[cb]] = Gamma(G5)*tmp;
313 
314  // Chi_i is now -(1/2) beta_tilde_i Dslash
315  chi[N5-1][rb[cb]] = off_diag_coeff[N5-1]*(GammaConst<Ns,Ns*Ns-1>()*tmp);
316  }
317  else {
318  chi[N5-1][rb[cb]] = zero;
319  }
320 
321  END_CODE();
322  }
323 
324 
325  // Derivative of even-odd linop component
326  /*
327  * This is a copy of the above applyOffDiag with the D.apply(...) replaced
328  * by D.deriv(ds_tmp,...) like calls.
329  */
330  void
331  QDPEvenOddPrecOvlapContFrac5DLinOpArray::applyDerivOffDiag(multi1d<LatticeColorMatrix>& ds_u,
332  const multi1d<LatticeFermion>& chi,
333  const multi1d<LatticeFermion>& psi,
334  enum PlusMinus isign,
335  int cb) const
336  {
337  START_CODE();
338 
339  ds_u.resize(Nd);
340  ds_u = zero;
341 
342  multi1d<LatticeColorMatrix> ds_tmp(Nd);
343 
344  LatticeFermion tmp; moveToFastMemoryHint(tmp);
345  Real coeff;
346  int G5 = Ns*Ns-1;
347 
348  switch (isign)
349  {
350  case PLUS:
351  // Optimisation... do up to the penultimate block...
352  for(int i=0; i < N5; i++)
353  {
354  if (i == N5-1 && isLastZeroP) continue;
355 
356  // CB is CB of TARGET
357  // consider case of gamma_5 Dslash
358  tmp[rb[cb]] = Gamma(G5)*chi[i];
359 
360  // Multiply coefficient
361  coeff = -Real(0.5)*beta_tilde[i];
362 
363  // Chi_i is now -(1/2) beta_tilde_i Dslash
364  tmp[rb[cb]] *= coeff;
365 
366  // Apply g5 Dslash
367  Dslash->deriv(ds_tmp, tmp, psi[i], PLUS, cb);
368  ds_u += ds_tmp;
369  }
370  break;
371 
372  case MINUS:
373  // Optimisation... do up to the penultimate block...
374  for(int i=0; i < N5; i++)
375  {
376  if (i == N5-1 && isLastZeroP) continue;
377 
378  // CB is CB of TARGET
379  // consider case of Dslash^dag gamma_5
380  tmp[rb[1-cb]] = Gamma(G5)*psi[i];
381 
382  // Multiply coefficient
383  coeff = -Real(0.5)*beta_tilde[i];
384 
385  // Chi_i is now -(1/2) beta_tilde_i Dslash
386  tmp[rb[1-cb]] *= coeff;
387 
388  // Apply g5 Dslash
389  Dslash->deriv(ds_tmp, chi[i], tmp, MINUS, cb);
390  ds_u += ds_tmp;
391  }
392  break;
393 
394  default:
395  QDP_error_exit("unknown case");
396  }
397 
398  END_CODE();
399  }
400 
401 } // End Namespace Chroma
402 
403 
404 #endif
#define END_CODE()
Definition: chromabase.h:65
#define START_CODE()
Definition: chromabase.h:64
QDPEvenOddPrecOvlapContFrac5DLinOpArray(Handle< FermState< T, P, Q > > state, const Real &_m_q, const Real &_OverMass, int _N5, const Real &_scale_fac, const multi1d< Real > &_alpha, const multi1d< Real > &_beta, const bool _isLastZeroP)
Full constructor.
Include possibly optimized Wilson dslash.
Even-odd prec. 5D continued fraction linop.
unsigned i
Definition: ldumul_w.cc:34
Double tmp
Definition: meslate.cc:60
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
QDPWilsonDslash WilsonDslash
Definition: dslash_w.h:132
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
static multi1d< LatticeColorMatrix > u
Double mass
Definition: pbg5p_w.cc:54
@ MINUS
Definition: chromabase.h:45
@ PLUS
Definition: chromabase.h:45
Complex a
Definition: invbicg.cc:95
DComplex d
Definition: invbicg.cc:99
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
chi
Definition: pade_trln_w.cc:24
psi
Definition: pade_trln_w.cc:191