CHROMA
unprec_s_cprec_t_wilson_linop_w.cc
Go to the documentation of this file.
1 /*! \file
2  * \brief Unpreconditioned Wilson linear operator
3  */
4 
5 
6 #include "qdp_config.h"
7 
8 #if QDP_NS == 4
9 #if QDP_NC == 3
10 #if QDP_ND == 4
11 
12 #include "chromabase.h"
15 
16 using namespace QDP::Hints;
17 
18 namespace Chroma
19 {
20 
21 
22  //! Creation routine with Anisotropy
23  /*!
24  * \param u_ gauge field (Read)
25  * \param Mass_ fermion kappa (Read)
26  * \param aniso anisotropy struct (Read)
27  */
28  void UnprecSCprecTWilsonLinOp::create(Handle< FermState<T,P,Q> > fs_,
29  const Real& Mass_,
30  const AnisoParam_t& anisoParam_)
31  {
32 #ifndef QDP_IS_QDPJIT
33  START_CODE();
34 
35  // Check we are in 4D
36  if ( Nd != 4 ) {
37  QDPIO::cout << "This class (UnprecSCprecTWilsonLinOp) only works in 4D" << std::endl;
38  QDP_abort(1);
39  }
40 
41 
42  // Check Aniso Direction -- has to be 3.
43  if ( anisoParam_.t_dir != 3 ) {
44  QDPIO::cout << "This class (UnprecSCprecTWilsonLinOp) is hardwired for t_dir=3"<< std::endl;
45  QDP_abort(1);
46  }
47 
48  // Check that the time direction is local:
49  const multi1d<int>& s_size = QDP::Layout::subgridLattSize(); // Local Lattice
50  const multi1d<int>& t_size = QDP::Layout::lattSize(); // Total Latt Size
51  if( t_size[3] != s_size[3] ) {
52  QDPIO::cout << "This class (UnprecSCprecTWilsonLinOp) needs time to be local" << std::endl;
53  QDP_abort(1);
54  }
55 
56  // Store gauge state etc
57  fs = fs_;
58  aniso = anisoParam_;
59  Mass = Mass_;
60 
61  u = fs->getLinks();
62  if (aniso.anisoP)
63  {
64  // Work out aniso factors
65  Real ff = where(aniso.anisoP, aniso.nu / aniso.xi_0, Real(1));
66  fact = 1 + (Nd-1)*ff + Mass;
67 
68  // Rescale the u fields by the anisotropy
69  for(int mu=0; mu < u.size(); ++mu)
70  {
71  if (mu != aniso.t_dir)
72  u[mu] *= ff;
73  }
74  }
75  else {
76  fact = Nd + Mass;
77  }
78 
79  invfact = Real(1)/fact;
80  // These will be useful for controlling loops.
81  int t_index=3;
82  int Nx = QDP::Layout::subgridLattSize()[0];
83  int Ny = QDP::Layout::subgridLattSize()[1];
84  int Nz = QDP::Layout::subgridLattSize()[2];
85  int Nt = QDP::Layout::subgridLattSize()[3];
86 
87  // Resize lookup table: for spatial site z,y,x we will get back an array of length t giving the site indices
88  // for the t sites, with that spatial index.
89  //
90  int Nspace = Nx*Ny*Nz;
91  tsite.resize(Nspace, Nt);
92 
93  int ssite=0;
94  // Loop over all spatial sites
95  for(int z=0; z < Nz; z++) {
96  for(int y=0; y < Ny; y++) {
97  for(int x=0; x < Nx; x++) {
98  // Assemble the site indices for all timeslices of this coordinate
99  multi1d<int> coords(Nd);
100  coords[0]=x;
101  coords[1]=y;
102  coords[2]=z;
103  for(int t=0; t < Nt; t++) {
104  coords[3] = t;
105  tsite(ssite,t) = QDP::Layout::linearSiteIndex(coords);
106  }
107  ssite++;
108  }
109  }
110  }
111 
112  // Figure out whether we are Schroedinger in time:
113  const FermBC<T,P,Q>& fbc = getFermBC();
114  if( fbc.nontrivialP() ) {
115  try {
116  const SchrFermBC& schr_ref = dynamic_cast<const SchrFermBC&>(fbc);
117  schrTP = ( schr_ref.getDir() == tDir() );
118  }
119  catch(std::bad_cast) {
120  schrTP = false;
121  }
122 
123  }
124  else {
125  // fbc are not nontrivial
126  schrTP = false;
127  }
128 
129  logDetTSq = zero;
130 
131  if( !schrTP ) {
132  // P and P_mat dag are needed for the Woodbury
133  // (P_mat for inverting T, P_mat_dag for inverting T_dag - NB P_mat_dag != (P_mat)^dagger
134  P_mat.resize(Nspace, Nt);
135  P_mat_dag.resize(Nspace, Nt);
136  Q_mat_inv.resize(Nspace);
137  Q_mat_dag_inv.resize(Nspace);
138 
139 
140  for(int site=0; site < Nspace; site++) {
141  Real minvfact = Real(-1)*invfact;
142 
143  // Compute P by backsubsitution - See Balint's notes eq 38-42
144  P_mat(site,Nt-1) = u[t_index].elem( tsite(site,Nt-1) );
145  P_mat(site,Nt-1) *= minvfact.elem();
146 
147 
148  for(int t=Nt-2; t >=0; t--) {
149  P_mat(site,t) = u[t_index].elem( tsite(site,t) ) * P_mat(site,t+1);
150  P_mat(site,t) *= invfact.elem();
151  }
152 
153  // Compute the dagger. Opposite order (forward sub) similara to eq 38-42
154  // in notes
155  P_mat_dag(site,0) = adj( u[t_index].elem( tsite(site,Nt-1) ) );
156  P_mat_dag(site,0) *= minvfact.elem();
157  for(int t=1; t < Nt; t++) {
158  P_mat_dag(site,t) = adj( u[t_index].elem( tsite(site,t-1) ) )*P_mat_dag(site, t-1) ;
159  P_mat_dag(site,t) *= invfact.elem();
160  }
161 
162 
163  // Compute Q = (1 + W^\dag P)^{-1}, W = [1, 0, 0, 0...] => (1 + P_{0})^{-1} eq: 43
164  // NB: This is not necessarily SU(3) now, so we can't just take the dagger to get the inverse
165  Real one=Real(1);
166  CMat one_plus_P0 = one.elem() + P_mat(site,0);
167  CentralTPrecNoSpinUtils::invert3by3( Q_mat_inv(site), one_plus_P0 );
168 
169  // Compute Q_dag = 1 + W^\dag P^\dag, W = [ 0, ..., 1 ] = > Q_dag = P^\dag [Nt-1]
170  // Similar to eq 43
171  // NB: This is not necessarily SU(3) now, so we can't just take the dagger to get the inverse
172  CMat one_plus_P0_dag = one.elem() + P_mat_dag(site,Nt-1);
173  CentralTPrecNoSpinUtils::invert3by3( Q_mat_dag_inv(site), one_plus_P0_dag);
174 
175 
176  CMat prod = one_plus_P0_dag*one_plus_P0;
177  logDetTSq += CentralTPrecNoSpinUtils::logDet(prod);
178  }
179  }
180  else {
181  // Schroedinger Time Case. Matrix(dagger) is strictly upper(lower)
182  // bidiagonal - Determinant is therefore a product of the
183  // diagonal elements which is just a factor independent
184  // of the gauge fields: (Nd + M)^{Nt}. Since this is a
185  // constant it doesn't need to be simulated and we can
186  // happily return logDetTSq=0
187  logDetTSq = 0;
188  }
189  Dw3D.create( fs_, anisoParam_);
190 
191  END_CODE();
192 #endif
193  }
194 
195  //! Apply (C_L)^{-1}
196  //
197  // C_L^{-1} = P_{+} + P_{-} T
198  //
199  void UnprecSCprecTWilsonLinOp::invCLeftLinOp(T& chi,
200  const T& psi,
201  enum PlusMinus isign) const
202 
203  {
204 
205  LatticeHalfFermion tmp_minus;
206  LatticeHalfFermion tmp_plus;
207  LatticeHalfFermion tmp_T=zero;
208 
209 
210  // This is just a way of doing P+ psi - decompose and reconstruct.
211  // It may be more straightforward to just write a projector ... -- later
212  tmp_plus = spinProjectDir3Plus(psi);
213  chi = spinReconstructDir3Plus(tmp_plus);
214 
215  // Here I project - apply TOp to only the halfector - then reco nstruct
216  tmp_minus = spinProjectDir3Minus(psi);
217 
218 
219  // Use shared routine to apply T or T^\dagger.
220  // Pass in u, and tsite for the subset
221  CentralTPrecNoSpinUtils::TOp(tmp_T,
222  tmp_minus,
223  u,
224  tsite,
225  fact,
226  isign,
227  schroedingerTP());
228 
229  chi += spinReconstructDir3Minus(tmp_T);
230  chi *= Real(0.5);
231 
232  getFermBC().modifyF(chi);
233 
234  }
235 
236  //! Apply (C_R)^{-1}
237  //
238  // C_R^{-1} = P_{-} + P_{+} T^{\dagger}
239  //
240  void UnprecSCprecTWilsonLinOp::invCRightLinOp(T& chi,
241  const T& psi,
242  enum PlusMinus isign) const
243  {
244 
245  // Right op is P- + P+ T^{\dagger} so I need the other isign from what I am given
246  enum PlusMinus other_sign = (isign == PLUS ? MINUS : PLUS) ;
247  LatticeHalfFermion tmp_minus;
248  LatticeHalfFermion tmp_plus;
249  LatticeHalfFermion tmp_T=zero;
250 
251 
252  // This does the P- modulo a factor of 1/2
253  // Rather than spooling through 2 half vectors I could just do a
254  // ProjectDir3Minus rather than going through half vectirs
255  tmp_minus = spinProjectDir3Minus(psi);
256  chi = spinReconstructDir3Minus(tmp_minus);
257 
258  // This does the P+ T^\dagger modulo a factor of 1/2
259  tmp_plus = spinProjectDir3Plus(psi);
260 
261 
262  // Use shared routine to apply T or T^\dagger.
263  // Pass in u, and tsite for the subset
264  CentralTPrecNoSpinUtils::TOp(tmp_T,
265  tmp_plus,
266  u,
267  tsite,
268  fact,
269  other_sign,
270  schroedingerTP());
271 
272  chi += spinReconstructDir3Plus(tmp_T);
273 
274  chi *= Real(0.5); //The overall factor of 1/2
275  getFermBC().modifyF(chi);
276  }
277 
278 
279  //! Apply C_L
280  //
281  // C_L = P_{+} + P_{-} T^{-1}
282  //
283  void UnprecSCprecTWilsonLinOp::cLeftLinOp(T& chi, const T& psi, enum PlusMinus isign) const
284  {
285 
286  LatticeHalfFermion tmp_minus;
287  LatticeHalfFermion tmp_plus;
288  LatticeHalfFermion tmp_T=zero;
289 
290  // 2 P_{+} = ( 1 + gamma_3 )
291  tmp_plus = spinProjectDir3Plus(psi);
292  chi = spinReconstructDir3Plus(tmp_plus);
293 
294  // 2 P_{-} = (1 - gamma_3 )
295  tmp_minus = spinProjectDir3Minus(psi);
296 
297  // Use shared routine to apply (T)^{-1} or (T^\dagger)^{-1}.
298  // Pass in u, and tsite, P, P^\dag, Q and Q^\dag for the subset.
299  CentralTPrecNoSpinUtils::invTOp( tmp_T,
300  tmp_minus,
301  u,
302  tsite,
303  P_mat,
304  P_mat_dag,
305  Q_mat_inv,
306  Q_mat_dag_inv,
307  invfact,
308  isign,
309  getTMax(),
310  schroedingerTP());
311 
312  // Reconstruct
313  chi += spinReconstructDir3Minus(tmp_T);
314 
315  // Overall factor of 2 to turn (1 +/- gamma_3) into projector P_{+/-}
316  // No sense to fold it into the half std::vector because it
317  // would also be needed for the half std::vector in the P_{+} piece
318  // so overall cost is still 1 full std::vector of multiply
319  chi *= Real(0.5);
320  getFermBC().modifyF(chi);
321 
322  }
323 
324  //! Apply C_R
325  //
326  // C_L = P_{-} + P_{+} [ T^{\dagger} ]^{-1}
327  //
328  void UnprecSCprecTWilsonLinOp::cRightLinOp(T& chi, const T& psi, enum PlusMinus isign) const
329  {
330 
331  enum PlusMinus other_sign = isign == PLUS ? MINUS : PLUS ;
332  LatticeHalfFermion tmp_minus;
333  LatticeHalfFermion tmp_plus;
334  LatticeHalfFermion tmp_T = zero;
335 
336 
337  // 2*P_{-}
338  tmp_minus = spinProjectDir3Minus(psi);
339  chi = spinReconstructDir3Minus(tmp_minus);
340 
341  // 2*P_{+}
342  tmp_plus = spinProjectDir3Plus(psi);
343 
344  // Use shared routine to apply (T)^{-1} or (T^\dagger)^{-1}.
345  // Pass in u, and tsite, P, P^\dag, Q and Q^\dag for the subset.
346  CentralTPrecNoSpinUtils::invTOp( tmp_T,
347  tmp_plus,
348  u,
349  tsite,
350  P_mat,
351  P_mat_dag,
352  Q_mat_inv,
353  Q_mat_dag_inv,
354  invfact,
355  other_sign,
356  getTMax(),
357  schroedingerTP());
358 
359  // Reconstruct to full std::vector
360  chi += spinReconstructDir3Plus(tmp_T);
361 
362  // Overall factor of 2 to turn (1 +/- gamma_3) into projector P_{+/-}
363  // No sense to fold it into the half std::vector because it
364  // would also be needed for the half std::vector in the P_{+} piece
365  // so overall cost is still 1 full std::vector of multiply
366  chi *= Real(0.5);
367  getFermBC().modifyF(chi);
368 
369  }
370 
371  //! Apply the the space block onto a source std::vector
372  // Call to 3D Dslash. - overall factor of -0.5from -(1/2) Dslash
373  void
374  UnprecSCprecTWilsonLinOp::spaceLinOp(T& chi, const T& psi, enum PlusMinus isign) const
375  {
376  Real mhalf=Real(-0.5);
377  Dw3D.apply(chi, psi, isign,0);
378  Dw3D.apply(chi, psi, isign,1);
379  chi *= mhalf;
380  getFermBC().modifyF(chi);
381  }
382 
383  //! Derivative of the derivCLeft
384  //
385  // X^\dagger dC_l Y
386  // = X^\dagger d [ P_{-} T^{-1} ] Y
387  // = - X^\dagger P{-} T^{-1} dT T^{-1} Y
388  // = - X^\dagger P{-} P_{-} T^{-1} dT T^{-1} Y since P_{-} P_{-} = P_{-}
389  // = - X^\dagger T^{-1} P_{-} dT P_{-} T^{-1} Y since Ps and Ts commute
390  // = - L^\dagger dT R
391  //
392  // with R = P_{-} T^{-1} Y and L = P_{-} T^{-dagger} X
393  //
394  // T contains only U terms (not U-dagger) and dT/dU R = -shift(R, FORWARD, t)
395  // T^\dagger contains no U terms so dT^\dagger / dU = zero
396  //
397  // similarly to how we do dslash-es. dT/dU^\dagger terms contribute only to the
398  // hermitian conjugate terms which are automagically taken care of when we do the
399  // TAProj() later on
400  void
401  UnprecSCprecTWilsonLinOp::derivCLeft(P& ds_u, const T& X, const T& Y, enum PlusMinus isign) const
402  {
403  ds_u.resize(Nd);
404  for(int mu=0; mu < 3; mu++) {
405  ds_u[mu] = zero;
406  }
407 
408  if (isign == PLUS) {
409 
410  LatticeHalfFermion tmp1, tmp2;
411  T T1, T2;
412 
413  tmp1=spinProjectDir3Minus(Y);
414  CentralTPrecNoSpinUtils::invTOp( tmp2,
415  tmp1,
416  u,
417  tsite,
418  P_mat,
419  P_mat_dag,
420  Q_mat_inv,
421  Q_mat_dag_inv,
422  invfact,
423  PLUS,
424  getTMax(),
425  schroedingerTP());
426 
427  T1 = spinReconstructDir3Minus(tmp2);
428 
429  tmp1=spinProjectDir3Minus(X);
430  CentralTPrecNoSpinUtils::invTOp( tmp2,
431  tmp1,
432  u,
433  tsite,
434  P_mat,
435  P_mat_dag,
436  Q_mat_inv,
437  Q_mat_dag_inv,
438  invfact,
439  MINUS,
440  getTMax(),
441  schroedingerTP());
442 
443  // Two factors of 0.5 from the projectors.
444  // Most cost efficient to apply them together to the half std::vector...
445  tmp2 *= Real(0.25);
446 
447  T2 = spinReconstructDir3Minus(tmp2);
448 
449 
450  LatticeFermion T3 = shift(T1, FORWARD, 3);
451 
452  // A minus from the fact that its dT^{-1}
453  // A minus from the fact that the shift has a -
454  // Makes a +
455  ds_u[3] = traceSpin(outerProduct(T3, T2));
456 
457  }
458  else {
459  ds_u[3] = zero;
460  }
461  getFermBC().zero(ds_u);
462 
463  }
464 
465 
466  //! Derivative of the derivCRight
467  //
468  // X^\dagger dC_R Y
469  // = X^\dagger d [ P_{+} T^{-\dagger} ] Y
470  // = - X^\dagger P{+} T^{-\dagger} dT^\dagger T^{-\dagger} Y
471  // = - X^\dagger P{+} P_{+} T^{-\dagger } dT^\dagger T^{-\dagger} Y since P_{+} P_{+} = P_{+}
472  // = - X^\dagger T^{-\dagger} P_{+} dT^\dagger P_{+} T^{-\dagger} Y since Ps and Ts commute
473  // = - L^\dagger dT R
474  //
475  // with R = P_{+} T^{-\dagger} Y and L = P_{+} T^{-1} X
476  //
477  // T^\dagger contains only U-dagger terms and dT^\dagger/dU = 0
478  // T contains only U terms so (dT^\dagger)^\dagger / dU R = dT/dU R = -shift(R, FORWARD, 1)
479  //
480  // similarly to how we do dslash-es.
481  // hermitian conjugate terms which are automagically taken care of when we do the
482  // TAProj() later on
483  //
484  // Actually this is just derivCLeft with PLUS --> MINUS in the Ifs
485  // and P_{-} <-> P_{+}
486  //
487  void
488  UnprecSCprecTWilsonLinOp::derivCRight(P& ds_u, const T& X, const T& Y, enum PlusMinus isign) const
489  {
490  ds_u.resize(Nd);
491  for(int mu=0; mu < 3; mu++) {
492  ds_u[mu] = zero;
493  }
494 
495  if (isign == MINUS) {
496 
497  LatticeHalfFermion tmp1, tmp2;
498  T T1, T2;
499 
500  tmp1=spinProjectDir3Plus(Y);
501  CentralTPrecNoSpinUtils::invTOp( tmp2,
502  tmp1,
503  u,
504  tsite,
505  P_mat,
506  P_mat_dag,
507  Q_mat_inv,
508  Q_mat_dag_inv,
509  invfact,
510  PLUS,
511  getTMax(),
512  schroedingerTP());
513 
514  T1 = spinReconstructDir3Plus(tmp2);
515 
516  tmp1=spinProjectDir3Plus(X);
517  CentralTPrecNoSpinUtils::invTOp( tmp2,
518  tmp1,
519  u,
520  tsite,
521  P_mat,
522  P_mat_dag,
523  Q_mat_inv,
524  Q_mat_dag_inv,
525  invfact,
526  MINUS,
527  getTMax(),
528  schroedingerTP());
529 
530  // Two factors of 0.5 from the projectors.
531  // Most cost efficient to apply them together to the half std::vector...
532  tmp2 *= Real(0.25);
533 
534  T2 = spinReconstructDir3Plus(tmp2);
535 
536  LatticeFermion T3 = shift(T1, FORWARD, 3);
537 
538  // A minus from the fact that its dT^{-1}
539  // A minus from the fact that the shift has a -
540  // Makes a +
541  ds_u[3] = traceSpin(outerProduct(T3, T2));
542 
543  }
544  else {
545  ds_u[3]= zero;
546  }
547  getFermBC().zero(ds_u);
548 
549  }
550 
551  //! derivSpace
552  //
553  // Easy peasy... call the force in the dslash.
554  void
555  UnprecSCprecTWilsonLinOp::derivSpace(P& ds_u, const T& X, const T& Y,
556  enum PlusMinus isign) const
557  {
558  Real mhalf=Real(-0.5);
559  ds_u.resize(Nd);
560 
561  Dw3D.deriv(ds_u, X, Y, isign);
562  for(int mu = 0; mu < 3 ; mu++) {
563  ds_u[mu] *= mhalf;
564  }
565 
566  ds_u[3] = zero;
567  getFermBC().zero(ds_u);
568  }
569 
570  //! Apply the d/dt of the preconditioned linop
571  //
572  // derivative of C_L D_s C_R is evaluated by the chain rule:
573  //
574  // = dC_L D_s C_R
575  // + C_L dD_s C_R
576  // + C_L D_s dC_R
577  //
578  // but we know that dC_R/ dU = 0 since C_R contains only U^\dagger terms
579  // so we can drop that term. Analogously in the daggered case we can drop
580  // the term containing C_L^\dagger...
581  void
582  UnprecSCprecTWilsonLinOp::deriv(P& ds_u, const T& X, const T& Y, enum PlusMinus isign) const
583  {
584  T T1,T2,T3;
585 
586  P ds_tmp;
587  ds_tmp.resize(Nd);
588 
589 
590  if ( isign == PLUS ) {
591 
592  // Derivative
593  cRightLinOp(T3, Y, PLUS); // T3 = C_r Y
594  spaceLinOp(T1, T3, PLUS); // T1 = D_s C_r Y
595  derivCLeft(ds_u, X, T1, PLUS); // X^\dag dC_l T1
596 
597  // X^\dag dC_l D_s C_r Y
598 
599  cLeftLinOp(T2, X, MINUS); // T2 = C_L^\dag X => T2^dag = X^\dag C_L
600  derivSpace(ds_tmp, T2, T3, PLUS); // X^\dag C_l dD_s C_r Y
601  ds_u += ds_tmp;
602  }
603  else {
604 
605 
606  // Derivative of the daggered
607  cLeftLinOp(T3, Y, MINUS); // T3 = C_l^\dag Y
608  spaceLinOp(T1, T3, MINUS); // T1 = D_s^\dag C_l^\dag Y
609  derivCRight(ds_u, X, T1, MINUS); // X^\dag dC_r^\dag D_s^\dag C_l^\dag Y
610 
611  cRightLinOp(T2, X, PLUS); // T2 = C_r X
612  derivSpace(ds_tmp, T2, T3, MINUS); // X^\dag C_r^\dag dD_s^\dag C_l^\dag Y
613  ds_u += ds_tmp;
614 
615  }
616  getFermBC().zero(ds_u);
617  }
618 
619 
620  // Derivative of trace log (T^\dagger T) -- Forward to central tprec utils
621  void
622  UnprecSCprecTWilsonLinOp::derivLogDetTDagT(P& ds_u,
623  enum PlusMinus isign) const
624  {
625 
626  // Derivative of a Hermitian quantity so ignore isign?
627  // Initial development -- set to 0
628  ds_u.resize(Nd);
629  for(int mu=0; mu < Nd; mu++) {
630  ds_u[mu] = zero;
631  }
632 
633  CentralTPrecNoSpinUtils::derivLogDet(ds_u,
634  u,
635  Q_mat_inv,
636  tsite,
637  tDir(),
638  fact,
639  schroedingerTP());
640  getFermBC().zero(ds_u);
641 
642  }
643 
644 } // End Namespace Chroma
645 
646 #endif
647 #endif
648 #endif
Support for time preconditioning.
Primary include file for CHROMA library code.
#define END_CODE()
Definition: chromabase.h:65
#define START_CODE()
Definition: chromabase.h:64
int mu
Definition: cool.cc:24
Real Mass
int y
Definition: meslate.cc:35
int z
Definition: meslate.cc:36
int x
Definition: meslate.cc:34
int t
Definition: meslate.cc:37
Nd
Definition: meslate.cc:74
Double tmp2
Definition: mesq.cc:30
multi1d< int > coords(const int x, const int y, const int z, const int t)
Asqtad Staggered-Dirac operator.
Definition: klein_gord.cc:10
static int tDir()
Definition: coulgauge.cc:14
static multi1d< LatticeColorMatrix > u
Double one
Definition: invbicg.cc:105
@ MINUS
Definition: chromabase.h:45
@ PLUS
Definition: chromabase.h:45
Double zero
Definition: invbicg.cc:106
chi
Definition: pade_trln_w.cc:24
psi
Definition: pade_trln_w.cc:191
#define FORWARD
Definition: primitives.h:82
LatticeFermion T
Definition: t_clover.cc:11
multi1d< LatticeColorMatrix > P
Definition: t_clover.cc:13
multi1d< LatticeColorMatrix > deriv(const EvenOddPrecLinearOperator< LatticeFermion, multi1d< LatticeColorMatrix >, multi1d< LatticeColorMatrix > > &AP, const LatticeFermion &chi, const LatticeFermion &psi, enum PlusMinus isign)
Apply the operator onto a source std::vector.
Unpreconditioned Wilson fermion linear operator.