CHROMA
eoprec_clover_orbifold_linop_w.cc
Go to the documentation of this file.
1 /*! \file
2  * \brief Even-odd preconditioned Clover fermion linear operator with orbifold
3  *
4  * 3D-Orbifold construction follows arXiv:0811.2127
5  */
6 
8 
9 using namespace QDP::Hints;
10 
11 namespace Chroma
12 {
13 
14  //! Creation routine with Anisotropy
15  /*!
16  * \param u_ gauge field (Read)
17  * \param param_ fermion kappa (Read)
18  */
19  void EvenOddPrecCloverOrbifoldLinOp::create(Handle< FermState<T,P,Q> > fs,
20  const CloverFermActParams& param_)
21  {
22  START_CODE();
23 
24  // QDPIO::cout << __PRETTY_FUNCTION__ << ": enter" << std::endl;
25 
26  param = param_;
27 
28  clov.create(fs, param);
29 
30  invclov.create(fs,param,clov); // make a copy
31  invclov.choles(0); // invert the cb=0 part
32 
33  D.create(fs, param.anisoParam);
34 
35  if ( param.twisted_m_usedP )
36  {
37  QDPIO::cerr << "EvenOddPrecCloverOrbifoldLinOp:: no twisted-mass allowed\n";
38  QDP_abort(1);
39  }
40 
41  // Orbifold Sanity checks
42  if (QDP::Layout::subgridLattSize()[0] != QDP::Layout::lattSize()[0])
43  {
44  QDPIO::cerr << "Requires x-dir on-node\n";
45  QDP_abort(1);
46  }
47 
48  if (QDP::Layout::subgridLattSize()[1] != QDP::Layout::lattSize()[1])
49  {
50  QDPIO::cerr << "Requires y-dir on-node\n";
51  QDP_abort(1);
52  }
53 
54  if (QDP::Layout::subgridLattSize()[2] != QDP::Layout::lattSize()[2])
55  {
56  QDPIO::cerr << "Requires z-dir on-node\n";
57  QDP_abort(1);
58  }
59 
60  // QDPIO::cout << __PRETTY_FUNCTION__ << ": exit" << std::endl;
61  END_CODE();
62  }
63 
64  //! Apply the the odd-odd block onto a source std::vector
65  void
66  EvenOddPrecCloverOrbifoldLinOp::oddOddLinOp(LatticeFermion& chi, const LatticeFermion& psi,
67  enum PlusMinus isign) const
68  {
69  START_CODE();
70 
71  clov.apply(chi, psi, isign, 1);
72 
73  END_CODE();
74  }
75 
76 
77  //! Apply the the even-even block onto a source std::vector
78  void
79  EvenOddPrecCloverOrbifoldLinOp::evenEvenLinOp(LatticeFermion& chi, const LatticeFermion& psi,
80  enum PlusMinus isign) const
81  {
82  START_CODE();
83 
84  // Nuke for testing
85  clov.apply(chi, psi, isign, 0);
86 
87  END_CODE();
88  }
89 
90  //! Apply the inverse of the even-even block onto a source std::vector
91  void
92  EvenOddPrecCloverOrbifoldLinOp::evenEvenInvLinOp(LatticeFermion& chi, const LatticeFermion& psi,
93  enum PlusMinus isign) const
94  {
95  START_CODE();
96 
97  invclov.apply(chi, psi, isign, 0);
98 
99  END_CODE();
100  }
101 
102 
103  //! Apply even-odd linop component
104  /*!
105  * The operator acts on the entire even sublattice
106  *
107  * \param chi Pseudofermion field (Write)
108  * \param psi Pseudofermion field (Read)
109  * \param isign Flag ( PLUS | MINUS ) (Read)
110  */
111  void
112  EvenOddPrecCloverOrbifoldLinOp::evenOddLinOp(LatticeFermion& chi,
113  const LatticeFermion& psi,
114  enum PlusMinus isign) const
115  {
116  START_CODE();
117 
118  Real mhalf = -0.5;
119 
120  D.apply(chi, psi, isign, 0);
121  chi[rb[0]] *= mhalf;
122 
123  END_CODE();
124  }
125 
126  //! Apply odd-even linop component
127  /*!
128  * The operator acts on the entire odd sublattice
129  *
130  * \param chi Pseudofermion field (Write)
131  * \param psi Pseudofermion field (Read)
132  * \param isign Flag ( PLUS | MINUS ) (Read)
133  */
134  void
135  EvenOddPrecCloverOrbifoldLinOp::oddEvenLinOp(LatticeFermion& chi,
136  const LatticeFermion& psi,
137  enum PlusMinus isign) const
138  {
139  START_CODE();
140 
141  Real mhalf = -0.5;
142 
143  D.apply(chi, psi, isign, 1);
144  chi[rb[1]] *= mhalf;
145 
146  END_CODE();
147  }
148 
149  // Orbifold term
150  void EvenOddPrecCloverOrbifoldLinOp::orbifold(LatticeFermion& chi,
151  const LatticeFermion& psi,
152  enum PlusMinus isign,
153  int z, int cb) const
154  {
155  LatticeFermion tmp;
156  GammaConst<4,8> g4; // gamma_4
157  GammaConst<4,4> g3; // gamma_3
158 
159  for(int tt=0; tt < QDP::Layout::subgridLattSize()[3]; ++tt)
160  {
161  int t = tt + QDP::Layout::nodeCoord()[3]*QDP::Layout::subgridLattSize()[3];
162 
163  for(int xx=0; xx < QDP::Layout::lattSize()[0] >> 1; ++xx)
164  {
165  for(int y=0; y < QDP::Layout::lattSize()[1]; ++y)
166  {
167  multi1d<int> coord(4);
168  int x = 2*xx + ((cb+y+z+t) & 1);
169 
170  // output sites on z
171  coord[0] = x;
172  coord[1] = y;
173  coord[2] = z;
174  coord[3] = t;
175  int site = QDP::Layout::linearSiteIndex(coord);
176 
177  coord[0] = QDP::Layout::lattSize()[0] - 1 - x;
178  coord[1] = QDP::Layout::lattSize()[1] - 1 - y;
179  int site_n = QDP::Layout::linearSiteIndex(coord);
180 
181  if (isign == PLUS)
182  {
183  tmp.elem(site) = g4 * psi.elem(site_n);
184  chi.elem(site) += tmp.elem(site) + g3 * tmp.elem(site);
185  }
186  else
187  {
188  tmp.elem(site) = g4 * psi.elem(site_n);
189  chi.elem(site) += tmp.elem(site) - g3 * tmp.elem(site);
190  }
191  }
192  }
193  }
194  }
195 
196 
197  // Override inherited one with a few more funkies
199  const LatticeFermion& psi,
200  enum PlusMinus isign) const
201  {
202  START_CODE();
203 
204  LatticeFermion tmp1; moveToFastMemoryHint(tmp1);
205  LatticeFermion tmp2; moveToFastMemoryHint(tmp2);
206  Real mquarter = -0.25;
207 
208  // chi_o = A_oo * psi_o + D_oe A^(-1)_ee D_eo psi_o
209 
210  // tmp1_e = D_eo psi_o
211  D.apply(tmp1, psi, isign, 0);
212 
213  // tmp1_e += (Orbifold term)*psi_o
214  orbifold(tmp1, psi, isign, 0, 0); // z=0, cb=0
215  orbifold(tmp1, psi, isign, QDP::Layout::lattSize()[2]-1, 0); // z=L-1, cb=0
216 
217  // tmp2_e = A_ee^{-1} * tmp1_e
218  invclov.apply(tmp2, tmp1, isign, 0);
219 
220  // tmp1_o = D_oe * tmp2_e
221  D.apply(tmp1, tmp2, isign, 1);
222 
223  // tmp1_o += (Orbifold term)*tmp2_e
224  orbifold(tmp1, tmp2, isign, 0, 1); // z=0, cb=1
225  orbifold(tmp1, tmp2, isign, QDP::Layout::lattSize()[2]-1, 1); // z=L-1, cb=1
226 
227  // chi_o = A_oo psi_o - tmp1_o
228  clov.apply(chi, psi, isign, 1);
229 
230  chi[rb[1]] += mquarter*tmp1;
231 
232 
233  END_CODE();
234  }
235 
236 
237  // Return flops performed by the operator()
238  unsigned long EvenOddPrecCloverOrbifoldLinOp::nFlops() const
239  {
240  unsigned long cbsite_flops = 2*D.nFlops()+2*clov.nFlops()+4*Nc*Ns;
241  return cbsite_flops*(Layout::sitesOnNode()/2);
242  }
243 
244 
245  // Get the log det of the even even part
246  Double EvenOddPrecCloverOrbifoldLinOp::logDetEvenEvenLinOp(void) const
247  {
248  QDPIO::cerr << "EvenOddPrecCloverOrbifoldLinOp::" << __func__ << " not suppported\n";
249  QDP_abort(1);
250  return zero;
251  }
252 
253 } // End Namespace Chroma
#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
Even-odd preconditioned Clover fermion linear operator with orbifold.
Double tmp
Definition: meslate.cc:60
int y
Definition: meslate.cc:35
int z
Definition: meslate.cc:36
multi1d< int > coord(Nd)
int x
Definition: meslate.cc:34
int t
Definition: meslate.cc:37
Double tmp2
Definition: mesq.cc:30
multi1d< Hadron2PtContraction_t > operator()(const multi1d< LatticeColorMatrix > &u)
Asqtad Staggered-Dirac operator.
Definition: klein_gord.cc:10
@ PLUS
Definition: chromabase.h:45
int cb
Definition: invbicg.cc:120
Double zero
Definition: invbicg.cc:106
FloatingPoint< double > Double
Definition: gtest.h:7351
chi
Definition: pade_trln_w.cc:24
psi
Definition: pade_trln_w.cc:191
Params for clover ferm acts.