CHROMA
seoprec_clover_linop_w.cc
Go to the documentation of this file.
1 /*! \file
2  * \brief Symmetric even-odd preconditioned clover linear operator
3  */
4 
6 
7 namespace Chroma
8 {
9  using namespace QDP::Hints;
10 
11  //! Creation routine with Anisotropy
12  /*!
13  * \param u_ gauge field (Read)
14  * \param param_ fermion kappa (Read)
15  */
17  const CloverFermActParams& param_)
18  {
19  START_CODE();
20  // QDPIO::cout << __PRETTY_FUNCTION__ << ": enter" << std::endl;
21 
22  param = param_;
23  QDPIO::cout << "Using Twisted Mass: " << param.twisted_m_usedP << std::endl;
24  if( param.twisted_m_usedP) {
25  QDPIO::cout << "Twisted Mass is " << param.twisted_m << std::endl;
26  }
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  invclov.choles(1); // invert the cb=1 part
33 
34  D.create(fs, param.anisoParam);
35 
36  clov_deriv_time = 0;
37  clov_apply_time = 0;
38 
39  // QDPIO::cout << __PRETTY_FUNCTION__ << ": exit" << std::endl;
40  END_CODE();
41  }
42 
43  //! Apply the the odd-odd block onto a source std::vector
44  void
45  SymEvenOddPrecCloverLinOp::unprecOddOddLinOp(LatticeFermion& chi, const LatticeFermion& psi,
46  enum PlusMinus isign) const
47  {
48  START_CODE();
49 
50 
51  clov.apply(chi, psi, isign, 1);
52 
53  END_CODE();
54  }
55 
56 
57  //! Apply the inverse of the odd-odd block onto a source std::vector
58  void
59  SymEvenOddPrecCloverLinOp::unprecOddOddInvLinOp(LatticeFermion& chi, const LatticeFermion& psi,
60  enum PlusMinus isign) const
61  {
62  START_CODE();
63 
64  invclov.apply(chi, psi, isign, 1);
65  END_CODE();
66  }
67 
68 
69  //! Apply the the even-even block onto a source std::vector
70  void
71  SymEvenOddPrecCloverLinOp::unprecEvenEvenLinOp(LatticeFermion& chi, const LatticeFermion& psi,
72  enum PlusMinus isign) const
73  {
74  START_CODE();
75  clov.apply(chi, psi, isign, 0);
76  END_CODE();
77  }
78 
79  //! Apply the inverse of the even-even block onto a source std::vector
80  void
81  SymEvenOddPrecCloverLinOp::unprecEvenEvenInvLinOp(LatticeFermion& chi, const LatticeFermion& psi,
82  enum PlusMinus isign) const
83  {
84  START_CODE();
85 
86  invclov.apply(chi, psi, isign, 0);
87 
88  END_CODE();
89  }
90 
91 
92  //! Apply even-odd linop component
93  /*!
94  * The operator acts on the entire even sublattice
95  *
96  * \param chi Pseudofermion field (Write)
97  * \param psi Pseudofermion field (Read)
98  * \param isign Flag ( PLUS | MINUS ) (Read)
99  */
100  void
102  const LatticeFermion& psi,
103  enum PlusMinus isign) const
104  {
105  START_CODE();
106 
107  Real mhalf = -0.5;
108 
109  D.apply(chi, psi, isign, 0);
110  chi[rb[0]] *= mhalf;
111 
112  END_CODE();
113  }
114 
115  //! Apply odd-even linop component
116  /*!
117  * The operator acts on the entire odd sublattice
118  *
119  * \param chi Pseudofermion field (Write)
120  * \param psi Pseudofermion field (Read)
121  * \param isign Flag ( PLUS | MINUS ) (Read)
122  */
123  void
125  const LatticeFermion& psi,
126  enum PlusMinus isign) const
127  {
128  START_CODE();
129 
130  Real mhalf = -0.5;
131 
132  D.apply(chi, psi, isign, 1);
133  chi[rb[1]] *= mhalf;
134 
135  END_CODE();
136  }
137 
138 
139  //! Apply even-odd preconditioned Clover fermion linear operator
140  /*!
141  * \param chi Pseudofermion field (Write)
142  * \param psi Pseudofermion field (Read)
143  * \param isign Flag ( PLUS | MINUS ) (Read)
144  */
146  const T& psi,
147  enum PlusMinus isign) const
148  {
149  START_CODE();
150 
151  T tmp1; moveToFastMemoryHint(tmp1);
152  T tmp2; moveToFastMemoryHint(tmp2);
153  Real mquarter = -0.25;
154 
155 
156  if( isign == PLUS) {
157  // tmp2_o = A^(-1)_oo D_oe A^(-1)_ee D_eo psi_o
158  D.apply(tmp1, psi, isign, 0);
159  invclov.apply(tmp2, tmp1, isign, 0);
160 
161  D.apply(tmp1, tmp2, isign, 1);
162  invclov.apply(tmp2, tmp1, isign, 1);
163  }
164  else {
165  invclov.apply(tmp1, psi, isign, 1);
166  D.apply(tmp2, tmp1, isign, 0);
167  invclov.apply(tmp1, tmp2, isign, 0);
168  D.apply(tmp2, tmp1, isign, 1);
169  }
170 
171  // chi_o = psi_o - tmp2_o
172  chi[rb[1]] = psi + mquarter*tmp2;
173 #if 1
174  if( param.twisted_m_usedP ){
175  // tmp1 = i mu gamma_5 tmp1
176  tmp1[rb[1]] = (GammaConst<Ns,Ns*Ns-1>() * timesI(psi));
177 
178  if( isign == PLUS ) {
179  chi[rb[1]] += param.twisted_m * tmp1;
180  }
181  else {
182  chi[rb[1]] -= param.twisted_m * tmp1;
183  }
184  }
185 #endif
186  getFermBC().modifyF(chi);
187  END_CODE();
188  }
189 
190 
191  //! Apply the even-even block onto a source std::vector
192  void
193  SymEvenOddPrecCloverLinOp::derivUnprecEvenEvenLinOp(multi1d<LatticeColorMatrix>& ds_u,
194  const LatticeFermion& chi, const LatticeFermion& psi,
195  enum PlusMinus isign) const
196  {
197  START_CODE();
198 
199 
200  clov.deriv(ds_u, chi, psi, isign, 0);
201 
202  END_CODE();
203  }
204 
205  // Inherit this
206  //! Apply the the odd-odd block onto a source std::vector
207  void
208  SymEvenOddPrecCloverLinOp::derivUnprecOddOddLinOp(multi1d<LatticeColorMatrix>& ds_u,
209  const LatticeFermion& chi, const LatticeFermion& psi,
210  enum PlusMinus isign) const
211  {
212  START_CODE();
213 
214  clov.deriv(ds_u, chi, psi, isign, 1);
215 
216  END_CODE();
217  }
218 
219  //! Apply the even-even block onto a source std::vector
220  void
221  SymEvenOddPrecCloverLinOp::derivLogDetEvenEvenLinOp(multi1d<LatticeColorMatrix>& ds_u,
222  enum PlusMinus isign) const
223  {
224  START_CODE();
225 
226  invclov.derivTrLn(ds_u, isign, 0);
227 
228  END_CODE();
229  }
230 
231  //! Apply the even-even block onto a source std::vector
232  void
233  SymEvenOddPrecCloverLinOp::derivLogDetOddOddLinOp(multi1d<LatticeColorMatrix>& ds_u,
234  enum PlusMinus isign) const
235  {
236  START_CODE();
237 
238  invclov.derivTrLn(ds_u, isign, 1);
239 
240  END_CODE();
241  }
242 
243  //! Apply the the even-odd block onto a source std::vector
244  void
245  SymEvenOddPrecCloverLinOp::derivUnprecEvenOddLinOp(multi1d<LatticeColorMatrix>& ds_u,
246  const LatticeFermion& chi, const LatticeFermion& psi,
247  enum PlusMinus isign) const
248  {
249  START_CODE();
250  ds_u.resize(Nd);
251  D.deriv(ds_u, chi, psi, isign, 0);
252  for(int mu=0; mu < Nd; mu++) {
253  ds_u[mu] *= Real(-0.5);
254  }
255  END_CODE();
256  }
257 
258  //! Apply the the odd-even block onto a source std::vector
259  void
260  SymEvenOddPrecCloverLinOp::derivUnprecOddEvenLinOp(multi1d<LatticeColorMatrix>& ds_u,
261  const LatticeFermion& chi, const LatticeFermion& psi,
262  enum PlusMinus isign) const
263  {
264  START_CODE();
265  ds_u.resize(Nd);
266 
267  D.deriv(ds_u, chi, psi, isign, 1);
268  for(int mu=0; mu < Nd; mu++) {
269  ds_u[mu] *= Real(-0.5);
270  }
271  END_CODE();
272  }
273 
274  //! Deriv
275  void SymEvenOddPrecCloverLinOp::deriv(P& ds_u, const T& chi, const T& psi,
276  enum PlusMinus isign) const
277  {
278  T M_eo_psi; moveToFastMemoryHint(M_eo_psi);
279  T M_oe_dag_chi; moveToFastMemoryHint(M_oe_dag_chi);
280  T tmp;
281  T Ainv_left;
282  T Ainv_right;
283 
284  //enum PlusMinus msign = ( isign == PLUS ) ? MINUS : PLUS;
285 
286  if( isign == PLUS ) {
287  D.apply(tmp, psi, PLUS, 0);
288  invclov.apply(M_eo_psi, tmp, PLUS, 0);
289 
290  invclov.apply(tmp, chi, MINUS,1);
291  D.apply(M_oe_dag_chi,tmp,MINUS,0);
292  }
293  else {
294  invclov.apply(tmp,psi,MINUS,1);
295  D.apply(M_eo_psi,tmp,MINUS,0);
296 
297  D.apply(tmp,chi,PLUS,0);
298  invclov.apply(M_oe_dag_chi,tmp,PLUS,0);
299  }
300  M_eo_psi[rb[0]] *= Real(-0.5);
301  M_oe_dag_chi[rb[0]] *= Real(-0.5);
302 
303  ds_u.resize(Nd);
304  ds_u = zero;
305  P ds_tmp;
306  ds_tmp.resize(Nd);
307 
308  //derivOddEvenLinOp(ds_tmp,chi,M_eo_psi,isign);
309  if( isign == PLUS ) {
310 
311  //
312  D.apply(tmp,M_eo_psi, PLUS,1);
313  invclov.apply(Ainv_right,tmp, PLUS,1);
314  invclov.apply(Ainv_left,chi,MINUS,1);
315  clov.deriv(ds_u,Ainv_left,Ainv_right, PLUS, 1);
316 
317 
318  invclov.apply(tmp, chi, MINUS,1);
319  D.deriv(ds_tmp, tmp,M_eo_psi, PLUS,1);
320  ds_u -= ds_tmp;
321 
322 
323  D.apply(tmp,psi, PLUS,0);
324  invclov.apply(Ainv_right,tmp,PLUS,0);
325  invclov.apply(Ainv_left, M_oe_dag_chi,PLUS,0);
326  clov.deriv(ds_tmp,Ainv_left, Ainv_right,PLUS,0);
327  ds_u += ds_tmp;
328 
329 
330  invclov.apply(tmp, M_oe_dag_chi, MINUS,0);
331  D.deriv(ds_tmp, tmp,psi, PLUS,0);
332  ds_u -= ds_tmp;
333  }
334  else {
335  D.apply(tmp,chi,PLUS,0);
336  invclov.apply(Ainv_left,tmp,PLUS,0);
337  invclov.apply(Ainv_right,M_eo_psi,MINUS,0);
338  clov.deriv(ds_u,Ainv_left,Ainv_right,MINUS,0);
339 
340  invclov.apply(tmp, M_eo_psi, MINUS,0);
341  D.deriv(ds_tmp, chi, tmp, MINUS,1);
342  ds_u -= ds_tmp;
343 
344  invclov.apply(tmp, psi, MINUS,1);
345  D.deriv(ds_tmp, M_oe_dag_chi, tmp, MINUS,0);
346  ds_u -= ds_tmp;
347 
348  D.apply(tmp,M_oe_dag_chi,PLUS,1);
349  invclov.apply(Ainv_left,tmp,PLUS,1);
350  invclov.apply(Ainv_right,psi,MINUS,1);
351  clov.deriv(ds_tmp, Ainv_left,Ainv_right, MINUS,1);
352  ds_u += ds_tmp;
353  }
354 
355  for(int mu=0; mu < Nd; ++mu) {
356  ds_u[mu] *= Real(-0.5);
357  }
358  getFermBC().zero(ds_u);
359  }
360 
361 
362  //! Deriv
363  void SymEvenOddPrecCloverLinOp::derivMultipole(P& ds_u, const multi1d<T>& chi,
364  const multi1d<T>& psi,
365  enum PlusMinus isign) const
366  {
367  if( chi.size() != psi.size() ) {
368  QDPIO::cerr << "Incompatible array sizes in SymEvenOddPrecCloverOp::derivMultipole" << std::endl;
369  QDP_abort(1);
370  }
371  int n_poles= psi.size();
372  multi1d<T> M_eo_psi(n_poles);
373  multi1d<T> M_oe_dag_chi(n_poles);
374  T tmp;
375  multi1d<T> Ainv_left(n_poles);
376  multi1d<T> Ainv_right(n_poles);
377 
378  //enum PlusMinus msign = ( isign == PLUS ) ? MINUS : PLUS;
379 
380  if( isign == PLUS ) {
381  for(int i=0; i < n_poles; ++i) {
382  D.apply(tmp, psi[i], PLUS, 0);
383  invclov.apply(M_eo_psi[i], tmp, PLUS, 0);
384 
385  invclov.apply(tmp, chi[i], MINUS,1);
386  D.apply(M_oe_dag_chi[i],tmp,MINUS,0);
387  }
388  }
389  else {
390  for(int i=0; i < n_poles; ++i) {
391  invclov.apply(tmp,psi[i],MINUS,1);
392  D.apply(M_eo_psi[i],tmp,MINUS,0);
393 
394  D.apply(tmp,chi[i],PLUS,0);
395  invclov.apply(M_oe_dag_chi[i],tmp,PLUS,0);
396  }
397  }
398  for(int i=0; i < n_poles; ++i) {
399  (M_eo_psi[i])[rb[0]] *= Real(-0.5);
400  (M_oe_dag_chi[i])[rb[0]] *= Real(-0.5);
401  }
402  ds_u.resize(Nd);
403  ds_u = zero;
404  P ds_tmp;
405  ds_tmp.resize(Nd);
406 
407  //derivOddEvenLinOp(ds_tmp,chi,M_eo_psi,isign);
408  if( isign == PLUS ) {
409 
410  for(int i=0; i < n_poles; ++i) {
411  D.apply(tmp,M_eo_psi[i], PLUS,1);
412  invclov.apply(Ainv_right[i],tmp, PLUS,1);
413  invclov.apply(Ainv_left[i],chi[i],MINUS,1);
414  }
415  clov.derivMultipole(ds_u,Ainv_left,Ainv_right, PLUS, 1);
416 
417  for(int i=0; i < n_poles; ++i) {
418  invclov.apply(tmp, chi[i], MINUS,1);
419  D.deriv(ds_tmp, tmp,M_eo_psi[i], PLUS,1);
420  ds_u -= ds_tmp;
421  }
422 
423  for(int i=0; i < n_poles; ++i) {
424  D.apply(tmp,psi[i], PLUS,0);
425  invclov.apply(Ainv_right[i],tmp,PLUS,0);
426  invclov.apply(Ainv_left[i], M_oe_dag_chi[i],PLUS,0);
427  }
428  clov.derivMultipole(ds_tmp,Ainv_left, Ainv_right,PLUS,0);
429  ds_u += ds_tmp;
430 
431  for(int i=0; i < n_poles; ++i) {
432  invclov.apply(tmp, M_oe_dag_chi[i], MINUS,0);
433  D.deriv(ds_tmp, tmp,psi[i], PLUS,0);
434  ds_u -= ds_tmp;
435  }
436  }
437  else {
438  for(int i=0; i < n_poles; ++i) {
439  D.apply(tmp,chi[i],PLUS,0);
440  invclov.apply(Ainv_left[i],tmp,PLUS,0);
441  invclov.apply(Ainv_right[i],M_eo_psi[i],MINUS,0);
442  }
443  clov.derivMultipole(ds_u,Ainv_left,Ainv_right,MINUS,0);
444 
445  for(int i=0; i < n_poles; ++i) {
446  invclov.apply(tmp, M_eo_psi[i], MINUS,0);
447  D.deriv(ds_tmp, chi[i], tmp, MINUS,1);
448  ds_u -= ds_tmp;
449 
450 
451  invclov.apply(tmp, psi[i], MINUS,1);
452  D.deriv(ds_tmp, M_oe_dag_chi[i], tmp, MINUS,0);
453  ds_u -= ds_tmp;
454  }
455 
456  for(int i=0; i < n_poles; ++i) {
457  D.apply(tmp,M_oe_dag_chi[i],PLUS,1);
458  invclov.apply(Ainv_left[i],tmp,PLUS,1);
459  invclov.apply(Ainv_right[i],psi[i],MINUS,1);
460  }
461  clov.derivMultipole(ds_tmp, Ainv_left,Ainv_right, MINUS,1);
462  ds_u += ds_tmp;
463  }
464 
465  for(int mu=0; mu < Nd; ++mu) {
466  ds_u[mu] *= Real(-0.5);
467  }
468  getFermBC().zero(ds_u);
469  }
470 
471 
472  //! Return flops performed by the operator()
473  unsigned long SymEvenOddPrecCloverLinOp::nFlops() const
474  {
475  unsigned long cbsite_flops = 2*D.nFlops()+2*clov.nFlops()+4*Nc*Ns;
476  if( param.twisted_m_usedP ) {
477  cbsite_flops += 4*Nc*Ns; // a + mu*b : a = chi, b = g_5 I psi
478  }
479  return cbsite_flops*(Layout::sitesOnNode()/2);
480  }
481 
482  //! Get the log det of the even even part
483  // BUt for now, return zero for testing.
485  return invclov.cholesDet(0);
486  }
487 
488  //! Get the log det of the odd odd part
489  // BUt for now, return zero for testing.
491  return invclov.cholesDet(1);
492  }
493 
494 } // End Namespace Chroma
Support class for fermion actions and linear operators.
Definition: state.h:94
Class for counted reference semantics.
Definition: handle.h:33
multi1d< LatticeColorMatrix > P
void operator()(T &chi, const T &psi, enum PlusMinus isign) const override
Apply even-odd preconditioned Clover fermion linear operator.
void unprecEvenEvenLinOp(T &chi, const T &psi, enum PlusMinus isign) const
Apply the the even-even block onto a source std::vector.
void unprecOddEvenLinOp(T &chi, const T &psi, enum PlusMinus isign) const
Apply the the odd-even block onto a source std::vector.
Double logDetEvenEvenLinOp(void) const
Get the log det of the even even part.
void derivMultipole(P &ds_u, const multi1d< T > &chi, const multi1d< T > &psi, enum PlusMinus isign) const override
Deriv.
void create(Handle< FermState< T, P, Q > > fs, const CloverFermActParams &param_)
Creation routine.
void unprecOddOddInvLinOp(T &chi, const T &psi, enum PlusMinus isign) const
Apply the inverse of the odd-odd block onto a source std::vector.
void derivLogDetEvenEvenLinOp(P &ds_u, enum PlusMinus isign) const
Apply the even-even block onto a source std::vector.
virtual void derivUnprecEvenEvenLinOp(P &ds_u, const T &chi, const T &psi, enum PlusMinus isign) const
Apply the even-even block onto a source std::vector.
virtual void derivUnprecEvenOddLinOp(P &ds_u, const T &chi, const T &psi, enum PlusMinus isign) const
Apply the the even-odd block onto a source std::vector.
virtual void derivUnprecOddOddLinOp(P &ds_u, const T &chi, const T &psi, enum PlusMinus isign) const
Apply the the odd-odd block onto a source std::vector.
void derivLogDetOddOddLinOp(P &ds_u, enum PlusMinus isign) const
Apply the odd-odd block onto a source std::vector.
void unprecEvenEvenInvLinOp(T &chi, const T &psi, enum PlusMinus isign) const
Apply the inverse of the even-even block onto a source std::vector.
unsigned long nFlops() const
Return flops performed by the operator()
void unprecOddOddLinOp(T &chi, const T &psi, enum PlusMinus isign) const
Apply the the odd-odd block onto a source std::vector.
void unprecEvenOddLinOp(T &chi, const T &psi, enum PlusMinus isign) const
Apply the the even-odd block onto a source std::vector.
Double logDetOddOddLinOp(void) const
Get the log det of the odd odd part.
void deriv(P &ds_u, const T &chi, const T &psi, enum PlusMinus isign) const override
Deriv.
virtual void derivUnprecOddEvenLinOp(P &ds_u, const T &chi, const T &psi, enum PlusMinus isign) const
Apply the the odd-even block onto a source std::vector.
int mu
Definition: cool.cc:24
Nd
Definition: meslate.cc:74
Double tmp2
Definition: mesq.cc:30
Asqtad Staggered-Dirac operator.
Definition: klein_gord.cc:10
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
START_CODE()
Double zero
Definition: invbicg.cc:106
FloatingPoint< double > Double
Definition: gtest.h:7351
Symmetric even-odd preconditioned Clover fermion linear operator.
Params for clover ferm acts.