CHROMA
eoprec_dwf_linop_array_w.cc
Go to the documentation of this file.
1 /*! \file
2  * \brief 4D-style even-odd preconditioned domain-wall linear operator
3  */
4 
6 using namespace QDP::Hints;
7 
8 namespace Chroma
9 {
10  // Check Conventions... Currently I (Kostas) am using Blum et.al.
11 
12 
13  //! Creation routine
14  /*! \ingroup fermact
15  *
16  * \param u_ gauge field (Read)
17  * \param WilsonMass_ DWF height (Read)
18  * \param m_q_ quark mass (Read)
19  * \param N5_ extent of 5D (Read)
20  * \param aniso aniso params (Read)
21  */
22  EvenOddPrecDWLinOpArray::EvenOddPrecDWLinOpArray(
24  const Real& WilsonMass_, const Real& m_q_, int N5_,
25  const AnisoParam_t& aniso)
26  {
27  START_CODE();
28 
29  WilsonMass = WilsonMass_;
30  m_q = m_q_;
31  a5 = 1;
32  N5 = N5_;
33 
34  D.create(fs,N5,aniso); // construct using possibly aniso glue
35 
36  Real ff = where(aniso.anisoP, aniso.nu / aniso.xi_0, Real(1));
37  InvTwoKappa = 1 + a5*(1 + (Nd-1)*ff - WilsonMass);
38  //InvTwoKappa = WilsonMass - 5.0;
39  TwoKappa = 1.0 / InvTwoKappa;
40  Kappa = TwoKappa/2.0;
41 
42  invDfactor =1.0/(1.0 + m_q/pow(InvTwoKappa,N5));
43 
44  END_CODE();
45  }
46 
47 
48  //! Apply the even-even (odd-odd) coupling piece of the domain-wall fermion operator
49  /*!
50  * \ingroup linop
51  *
52  * The operator acts on the entire lattice. Flopcount: (4N5+2)*Nc*Ns*cbsite,
53  * 4 N5 Nc Ns * cbsite in PV mode (m_q = 1)
54  *
55  * \param psi Pseudofermion field (Read)
56  * \param isign Flag ( PLUS | MINUS ) (Read)
57  * \param cb checkerboard ( 0 | 1 ) (Read)
58  */
59  void
60  EvenOddPrecDWLinOpArray::applyDiag(multi1d<LatticeFermion>& chi,
61  const multi1d<LatticeFermion>& psi,
62  enum PlusMinus isign,
63  const int cb) const
64  {
65  START_CODE();
66 
67  if( chi.size() != N5 ) chi.resize(N5);
68 
69  switch ( isign ) {
70 
71  case PLUS:
72  {
73  // Total flopcount: (N5-2)*4 Nc * Ns + 10 (Nc * Ns) cbsite flops
74  // = ( 4 N5 + 2 ) Nc Ns cbsite flops
75  //
76  // = 4 N5 Nc Ns cbsite in PV mode (m_q = 1)
77 
78 
79  // Flopcount for this part:
80  // (N5-2)*4N cNs*cbsite flops
81  for(int s(1);s<N5-1;s++) { // 1/2k psi[s] - P_- * psi[s+1] - P_+ * psi[s-1]
82  //chi[s][rb[cb]] = InvTwoKappa*psi[s] -
83  // 0.5*( psi[s+1] + psi[s-1] + GammaConst<Ns,Ns*Ns-1>()*(psi[s-1] - psi[s+1]) ) ;
84 
85  // Recoded using chiralProject
86 
87  // 3Nc Ns * cbsite flops
88  chi[s][rb[cb]] = InvTwoKappa*psi[s] - chiralProjectPlus(psi[s-1]);
89 
90  // Nc Ns * cbsite flops
91  chi[s][rb[cb]] -= chiralProjectMinus(psi[s+1]);
92  }
93 
94  int N5m1(N5-1) ;
95  //s=0 -- 1/2k psi[0] - P_- * psi[1] + mf* P_+ * psi[N5-1]
96  // chi[0][rb[cb]] = InvTwoKappa*psi[0] -
97  // 0.5*( psi[1] - m_q*psi[N5m1] - GammaConst<Ns,Ns*Ns-1>()*(m_q*psi[N5m1] + psi[1]) ) ;
98 
99  // Recoded using chiralProject
100 
101  // Flopcount for this part: 5 Nc Ns * cbsite flops, 4NcNs *cbsite in PV mode
102 
103  // 3Nc Ns * cbsite flops
104  chi[0][rb[cb]] = InvTwoKappa*psi[0] + m_q*chiralProjectPlus(psi[N5m1]);
105  chi[0][rb[cb]]-= chiralProjectMinus(psi[1]);
106 
107  // 2Nc Ns * cbsite flops, Nc Ns cbsite in PV mode (m_q = 1)
108  // chi[0][rb[cb]] += m_q* chiralProjectPlus(psi[N5m1]);
109 
110  int N5m2(N5-2);
111  //s=N5-1 -- 1/2k psi[N5-1] +mf* P_- * psi[0] - P_+ * psi[N5-2]
112  //chi[N5m1][rb[cb]] = InvTwoKappa*psi[N5m1] -
113  // 0.5*( psi[N5m2] - m_q *psi[0] + GammaConst<Ns,Ns*Ns-1>()*(psi[N5m2] + m_q * psi[0]) );
114 
115  // Recoded using chiralProject
116 
117  // Flopcount for this part: 5Nc Ns cbsite flops
118  // 4Nc Ns cbsite flops in PV Mode (m_q = 1)
119  // 3NcNs cbsite flops
120  chi[N5m1][rb[cb]] = InvTwoKappa*psi[N5m1]+ m_q*chiralProjectMinus(psi[0]);
121  chi[N5m1][rb[cb]] -=chiralProjectPlus(psi[N5m2]);
122 
123  // 2NcNs cbsite flops, Nc Ns in PV mode
124  // chi[N5m1][rb[cb]] += m_q*chiralProjectMinus(psi[0]);
125  }
126  break ;
127 
128  case MINUS:
129  {
130 
131  // Total flopcount: ((N5-2)*4*Nc*Ns + 10 Nc *Ns) * cbsite flops
132  // = (4N5 + 2) Nc Ns cbsite flops
133 
134  // Flopcount for this part: (N5-2)*4 Nc Ns cbsite flops
135  for(int s(1);s<N5-1;s++) { // 1/2k psi[s] - P_+ * psi[s+1] - P_- * psi[s-1]
136  // chi[s][rb[cb]] = InvTwoKappa*psi[s] -
137  // 0.5*( psi[s+1] + psi[s-1] + GammaConst<Ns,Ns*Ns-1>()*(psi[s+1] - psi[s-1]) ) ;
138 
139 
140  // Recoded using chiralProject
141 
142  // 3NcNs cbsite flops
143  chi[s][rb[cb]] = InvTwoKappa*psi[s] - chiralProjectPlus(psi[s+1]);
144 
145  // NcNs cbsite flops
146  chi[s][rb[cb]] -= chiralProjectMinus(psi[s-1]);
147 
148  }
149  int N5m1(N5-1) ;
150  //s=0 -- 1/2k psi[0] - P_+ * psi[1] + mf* P_- * psi[N5-1]
151  // chi[0][rb[cb]] = InvTwoKappa*psi[0] -
152  // 0.5*( psi[1] - m_q*psi[N5m1] + GammaConst<Ns,Ns*Ns-1>()*( psi[1]+m_q*psi[N5m1]) ) ;
153 
154  // Recoded using chiralProject
155  // Flopcount for this part 5NcNs flops:
156 
157  // 3NcNs cbsite flops
158  chi[0][rb[cb]] = InvTwoKappa*psi[0] + m_q*chiralProjectMinus(psi[N5m1]);
159 
160  // 2NcNs cbsite flops, Nc Ns in PV mode (m_q = 1)
161  chi[0][rb[cb]] -= chiralProjectPlus(psi[1]);
162 
163 
164  int N5m2(N5-2);
165  //s=N5-1 -- 1/2k psi[N5-1] + mf* P_+ * psi[0] - P_- * psi[N5-2]
166  // chi[N5m1][rb[cb]] = InvTwoKappa*psi[N5m1] -
167  // 0.5*( psi[N5m2] - m_q *psi[0] - GammaConst<Ns,Ns*Ns-1>()*(psi[N5m2] + m_q * psi[0]) );
168 
169  // Recoded using chiralProject
170  // Flopcount for this part: 5NcNs cbsite flops
171 
172  // 3NcNs cbsite flops
173  chi[N5m1][rb[cb]] = InvTwoKappa*psi[N5m1]+ m_q * chiralProjectPlus(psi[0]);
174  chi[N5m1][rb[cb]] -= chiralProjectMinus(psi[N5m2]);
175  // 2NcNs cbsite flops, Nc Ns in PV mode (m_q = 1)
176  // chi[N5m1][rb[cb]] += m_q * chiralProjectPlus(psi[0]);
177  }
178  break ;
179  }
180 
181  END_CODE();
182  }
183 
184 
185  //! Apply the inverse even-even (odd-odd) coupling piece of the domain-wall fermion operator
186  /*!
187  * \ingroup linop
188  *
189  * The operator acts on the entire lattice: (10 Ns - 8)NcNs flops
190  *
191  * \param psi Pseudofermion field (Read)
192  * \param isign Flag ( PLUS | MINUS ) (Read)
193  * \param cb checkerboard ( 0 | 1 ) (Read)
194  */
195  void
196  EvenOddPrecDWLinOpArray::applyDiagInv(multi1d<LatticeFermion>& chi,
197  const multi1d<LatticeFermion>& psi,
198  enum PlusMinus isign,
199  const int cb) const
200  {
201  START_CODE();
202 
203  if( chi.size() != N5 ) chi.resize(N5);
204 
205  switch ( isign ) {
206 
207  case PLUS:
208  {
209 
210  Real fact = m_q*TwoKappa*TwoKappa*invDfactor;
211  Real invDTwoKappa = invDfactor*TwoKappa;
212 
213  // Optimized it...
214  // I have rolled the scaling by 2Kappa, applying Lm^{-1} forward solving
215  // with L and scaling by invDTwoKappa into 1 loop.
216 
217  // 2 Nc Ns flops/site
218  chi[0][rb[cb]] = TwoKappa*psi[0];
219 
220  // 4 Nc Ns flops/site
221  chi[N5-1][rb[cb]] = invDTwoKappa*psi[N5-1]-fact*chiralProjectMinus(psi[0]);
222  fact *= TwoKappa;
223  for(int s = 1; s < N5-1; s++) {
224  // Nc Ns flops/site
225  chi[s][rb[cb]] = TwoKappa * psi[s] + TwoKappa*chiralProjectPlus(chi[s-1]);
226 
227  // 2Nc Ns flops/site
228  // chi[s][rb[cb]] += TwoKappa*chiralProjectPlus(chi[s-1]);
229 
230  // 2Nc Ns flops/site
231  chi[N5-1][rb[cb]] -= fact*chiralProjectMinus(psi[s]);
232  fact *= TwoKappa;
233 
234  }
235 
236  // 2Nc Ns flops/site
237  chi[N5-1][rb[cb]] += invDTwoKappa*chiralProjectPlus(chi[N5-2]);
238 
239 
240  //The inverse of R. Back substitution...... Getting there!
241  for(int s = N5-2; s >= 0; s--) { // N5-1 iters
242 
243  // 2Nc Ns flops/site
244  chi[s][rb[cb]] += TwoKappa*chiralProjectMinus(chi[s+1]);
245  }
246 
247  //Finally the inverse of Rm
248  fact = m_q*TwoKappa;
249  for(int s = 0; s < N5-1; s++){ // N5-1 iters
250  // 2Nc Ns flops/site
251  chi[s][rb[cb]] -= fact*chiralProjectPlus(chi[N5-1]) ;
252  fact *= TwoKappa ;
253  }
254  }
255  break ;
256 
257  case MINUS:
258  {
259 
260  Real fact = m_q*TwoKappa*TwoKappa*invDfactor;
261  Real invDTwoKappa = invDfactor*TwoKappa;
262 
263 
264  chi[0][rb[cb]] = TwoKappa*psi[0];
265  chi[N5-1][rb[cb]] = invDTwoKappa*psi[N5-1]-fact*chiralProjectPlus(psi[0]);
266  fact *= TwoKappa;
267  for(int s = 1; s < N5-1; s++) {
268  // 2Nc Ns flops
269  chi[s][rb[cb]] = TwoKappa * psi[s] + TwoKappa*chiralProjectMinus(chi[s-1]);
270  // chi[s][rb[cb]] += TwoKappa*chiralProjectMinus(chi[s-1]);
271  chi[N5-1][rb[cb]] -= fact*chiralProjectPlus(psi[s]);
272  fact *= TwoKappa;
273 
274  }
275  chi[N5-1][rb[cb]] += invDTwoKappa*chiralProjectMinus(chi[N5-2]);
276 
277 
278 
279  //The inverse of R. Back substitution...... Getting there!
280  for(int s = N5-2; s >=0; s--) {
281 
282  chi[s][rb[cb]] += TwoKappa*chiralProjectPlus(chi[s+1]);;
283 
284  }
285 
286  //Finally the inverse of Rm
287  fact = m_q*TwoKappa;
288  for(int s = 0; s < N5-1 ;s++){
289  chi[s][rb[cb]] -= fact*chiralProjectMinus(chi[N5-1]);
290  fact *= TwoKappa ;
291  }
292  }
293  break ;
294  }
295 
296  //Done! That was not that bad after all....
297  //See, I told you so...
298  END_CODE();
299  }
300 
301 
302  //! Apply the off diagonal block
303  /*!
304  * \param chi result (Modify)
305  * \param psi source (Read)
306  * \param isign Flag ( PLUS | MINUS ) (Read)
307  * \param cb checkerboard ( 0 | 1 ) (Read)
308  */
309  void
310  EvenOddPrecDWLinOpArray::applyOffDiag(multi1d<LatticeFermion>& chi,
311  const multi1d<LatticeFermion>& psi,
312  enum PlusMinus isign,
313  const int cb) const
314  {
315  if( chi.size() != N5 ) chi.resize(N5);
316 
317 #if 1
318  Real mhalf=-0.5;
319  D.apply(chi,psi,isign,cb);
320  for(int s(0);s<N5;s++)
321  chi[s][rb[cb]] *= mhalf;
322 
323 #else
324  for(int s(0);s<N5;s++)
325  {
326  D.apply(chi[s],psi[s],isign,cb);
327  chi[s][rb[cb]] *= (-0.5);
328  }
329 #endif
330  }
331 
332 
333  //! Apply the Dminus operator on a lattice fermion. See my notes ;-)
334  void
335  EvenOddPrecDWLinOpArray::Dminus(LatticeFermion& chi,
336  const LatticeFermion& psi,
337  enum PlusMinus isign,
338  int s5) const
339  {
340  QDPIO::cerr << "Dminus not implemented" << std::endl;
341  QDP_abort(1);
342  }
343 
344  //! Apply the the even-odd block onto a source std::vector
345  void
346  EvenOddPrecDWLinOpArray::applyDerivOffDiag(multi1d<LatticeColorMatrix>& ds_u,
347  const multi1d<LatticeFermion>& chi,
348  const multi1d<LatticeFermion>& psi,
349  enum PlusMinus isign, int cb) const
350  {
351  START_CODE();
352 
353  D.deriv(ds_u, chi, psi, isign, cb);
354  for(int mu(0);mu<Nd;mu++)
355  ds_u[mu] *= Real(-0.5);
356 
357  END_CODE();
358  }
359 
360 
361 } // End Namespace Chroma
362 
#define END_CODE()
Definition: chromabase.h:65
#define START_CODE()
Definition: chromabase.h:64
Support class for fermion actions and linear operators.
Definition: state.h:94
Class for counted reference semantics.
Definition: handle.h:33
int mu
Definition: cool.cc:24
4D Even Odd preconditioned domain-wall fermion linear operator
unsigned s
Definition: ldumul_w.cc:37
Nd
Definition: meslate.cc:74
Asqtad Staggered-Dirac operator.
Definition: klein_gord.cc:10
@ MINUS
Definition: chromabase.h:45
@ PLUS
Definition: chromabase.h:45
int cb
Definition: invbicg.cc:120
chi
Definition: pade_trln_w.cc:24
psi
Definition: pade_trln_w.cc:191
Parameters for anisotropy.
Definition: aniso_io.h:24