CHROMA
eo3dprec_s_cprec_t_clover_linop_w.cc
Go to the documentation of this file.
1 /*! \file
2  * \brief Unpreconditioned Clover linear operator
3  */
4 #include "qdp_config.h"
5 #if QDP_NS == 4
6 #if QDP_ND == 4
7 #if QDP_NC == 3
8 
9 #include "chromabase.h"
12 
13 using namespace QDP::Hints;
14 
15 namespace Chroma
16 {
17 
18 
19  //! Creation routine with Anisotropy
20  /*!
21  * \param u_ gauge field (Read)
22  * \param Mass_ fermion kappa (Read)
23  * \param aniso anisotropy struct (Read)
24  */
25  void EO3DPrecSCprecTCloverLinOp::create(Handle< FermState<T,P,Q> > fs_,
26  const CloverFermActParams& param_)
27 
28  {
29 #ifndef QDP_IS_QDPJIT
30  START_CODE();
31 
32  param = param_;
33 
34  // Check we are in 4D
35  if ( Nd != 4 ) {
36  QDPIO::cout << "This class (EO3DPrecSCprecTCloverLinOp) only works in 4D" << std::endl;
37  QDP_abort(1);
38  }
39 
40  // Check Aniso Direction -- has to be 3.
41  if ( param.anisoParam.t_dir != 3 ) {
42  QDPIO::cout << "This class (EO3DPrecSCprecTCloverLinOp) is hardwired for t_dir=3"<< std::endl;
43  QDP_abort(1);
44  }
45 
46  // Check that the time direction is local:
47  const multi1d<int>& s_size = QDP::Layout::subgridLattSize(); // Local Lattice
48  const multi1d<int>& t_size = QDP::Layout::lattSize(); // Total Latt Size
49  if( t_size[3] != s_size[3] ) {
50  QDPIO::cout << "This class (EO3DPrecSCprecTCloverLinOp) needs time to be local" << std::endl;
51  QDP_abort(1);
52  }
53 
54  // Store gauge state etc
55  fs = fs_;
56 
57  // Work out aniso factors
58  Real ff = where(param.anisoParam.anisoP, param.anisoParam.nu / param.anisoParam.xi_0, Real(1));
59  fact = 1 + (Nd-1)*ff + param.Mass;
60  invfact = Real(1)/fact;
61  u = fs->getLinks();
62 
63  // Incorporate into links
64  if (param.anisoParam.anisoP)
65  {
66  // Rescale the u fields by the anisotropy
67  for(int mu=0; mu < u.size(); ++mu)
68  {
69  if (mu != aniso.t_dir)
70  u[mu] *= ff;
71  }
72  }
73 
74  // These will be useful for controlling loops.
75  int t_index=3;
76  int Nx = QDP::Layout::subgridLattSize()[0];
77  int Ny = QDP::Layout::subgridLattSize()[1];
78  int Nz = QDP::Layout::subgridLattSize()[2];
79  int Nt = QDP::Layout::subgridLattSize()[3];
80 
81  // Resize lookup table: for spatial site z,y,x we will get back an array of length t giving the site indices
82  // for the t sites, with that spatial index.
83  //
84  int Nspaceby2 = Nx*Ny*Nz/2; // This always works because Nx has to be even...
85 
86  tsite.resize(2, Nspaceby2, Nt);
87 
88 
89  int ssite_even=0;
90  int ssite_odd=0;
91 
92  int color;
93  int site;
94 
95  // Loop over all spatial sites
96  for(int z=0; z < Nz; z++) {
97  for(int y=0; y < Ny; y++) {
98  for(int x=0; x < Nx; x++) {
99  // Assemble the site indices for all timeslices of this coordinate
100 
101  multi1d<int> coords(Nd);
102  coords[0]=x;
103  coords[1]=y;
104  coords[2]=z;
105  color = (x + y + z) & 1;
106 
107  if ( color == 0 ) {
108  for(int t=0; t < Nt; t++) {
109  coords[3] = t;
110  tsite(0,ssite_even, t) = QDP::Layout::linearSiteIndex(coords);
111  }
112  ssite_even++;
113 
114  }
115  else {
116  for(int t=0; t < Nt; t++) {
117  coords[3] = t;
118  tsite(1,ssite_odd, t) = QDP::Layout::linearSiteIndex(coords);
119  }
120  ssite_odd++;
121  }
122  }
123  }
124  }
125 
126  // P and P_mat dag are needed for the Woodbury
127  // (P_mat for inverting T, P_mat_dag for inverting T_dag - NB P_mat_dag != (P_mat)^dagger
128  P_mat.resize(2, Nspaceby2, Nt);
129  P_mat_dag.resize(2, Nspaceby2, Nt);
130 
131  Q_mat_inv.resize(2,Nspaceby2);
132  Q_mat_dag_inv.resize(2,Nspaceby2);
133 
134  for(int cb3=0; cb3 < 2; cb3++) {
135  for(int site=0; site < Nspaceby2; site++) {
136 
137 
138  Real minvfact = Real(-1)*invfact;
139 
140  // Compute P by backsubsitution - See Balint's notes eq 38-42
141  P_mat(cb3, site, Nt-1) = u[t_index].elem( tsite(cb3,site,Nt-1) );
142  P_mat(cb3, site, Nt-1) *= minvfact.elem();
143 
144 
145  for(int t=Nt-2; t >=0; t--) {
146  P_mat(cb3, site, t) = u[t_index].elem( tsite(cb3, site,t) ) * P_mat(cb3, site,t+1);
147  P_mat(cb3, site, t) *= invfact.elem();
148  }
149 
150  // Compute the dagger. Opposite order (forward sub) similara to eq 38-42
151  // in notes
152  P_mat_dag(cb3, site, 0) = adj( u[t_index].elem( tsite(cb3, site, Nt-1) ) );
153  P_mat_dag(cb3, site, 0) *= minvfact.elem();
154 
155  for(int t=1; t < Nt; t++) {
156  P_mat_dag(cb3, site,t) = adj( u[t_index].elem( tsite(cb3, site, t-1) ) )*P_mat_dag(cb3,site, t-1) ;
157  P_mat_dag(cb3, site,t) *= invfact.elem();
158  }
159 
160 
161  // Compute Q = (1 + W^\dag P)^{-1}, W = [1, 0, 0, 0...] => (1 + P_{0})^{-1} eq: 43
162  // NB: This is not necessarily SU(3) now, so we can't just take the dagger to get the inverse
163  Real one=Real(1);
164  CMat tmp = one.elem() + P_mat(cb3, site,0);
165  CentralTPrecNoSpinUtils::invert3by3( Q_mat_inv(cb3, site), tmp );
166 
167  // Compute Q_dag = 1 + W^\dag P^\dag, W = [ 0, ..., 1 ] = > Q_dag = P^\dag [Nt-1]
168  // Similar to eq 43
169  // NB: This is not necessarily SU(3) now, so we can't just take the dagger to get the inverse
170  tmp = one.elem() + P_mat_dag(cb3, site,Nt-1);
171  CentralTPrecNoSpinUtils::invert3by3( Q_mat_dag_inv(cb3, site), tmp);
172  }
173  }
174 
175  // Create Clover term = A + factor (we don't want the diag mass bit)
176  APlusFact.create(fs, param);
177 
178  Dw3D.create(fs_, param_.anisoParam);
179 
180  END_CODE();
181 #endif
182  }
183 
184  //! Apply (C_L)^{-1}
185  void EO3DPrecSCprecTCloverLinOp::invCLeftLinOp(T& chi,
186  const T& psi,
187  enum PlusMinus isign,
188  int cb3d) const
189 
190  {
191  LatticeHalfFermion tmp_minus;
192  LatticeHalfFermion tmp_plus;
193  LatticeHalfFermion tmp_T;
194 
195  // This is just a way of doing P+ psi - decompose and reconstruct.
196  // It may be more straightforward to just write a projector ... -- later
197  tmp_plus[ rb3[ cb3d ] ] = spinProjectDir3Plus(psi);
198  chi[ rb3[ cb3d ] ] = spinReconstructDir3Plus(tmp_plus);
199 
200  // Here I project - apply TOp to only the halfector - then reco nstruct
201  tmp_minus[ rb3[ cb3d ] ] = spinProjectDir3Minus(psi);
202 
203 
204  // Use shared routine to apply T or T^\dagger.
205  // Pass in u, and tsite for the subset
206  CentralTPrecNoSpinUtils::TOp(tmp_T,
207  tmp_minus,
208  u,
209  tsite[cb3d],
210  fact,
211  isign);
212 
213  chi[rb3[ cb3d ]] += spinReconstructDir3Minus(tmp_T);
214  chi[rb3[ cb3d ]] *= Real(0.5);
215  }
216 
217  //! Apply (C_R)^{-1}
218  void EO3DPrecSCprecTCloverLinOp::invCRightLinOp(T& chi,
219  const T& psi,
220  enum PlusMinus isign,
221  int cb3d) const
222  {
223  // Right op is P- + P+ T^{\dagger} so I need the other isign from what I am given
224  enum PlusMinus other_sign = (isign == PLUS ? MINUS : PLUS) ;
225  LatticeHalfFermion tmp_minus;
226  LatticeHalfFermion tmp_plus;
227  LatticeHalfFermion tmp_T;
228 
229  // This does the P- modulo a factor of 1/2
230  // Rather than spooling through 2 half vectors I could just do a
231  // ProjectDir3Minus rather than going through half vectirs
232  tmp_minus[rb3[cb3d]] = spinProjectDir3Minus(psi);
233  chi[rb3[cb3d]] = spinReconstructDir3Minus(tmp_minus);
234 
235  // This does the P+ T^\dagger modulo a factor of 1/2
236  tmp_plus[rb3[cb3d]] = spinProjectDir3Plus(psi);
237 
238 
239  // Use shared routine to apply T or T^\dagger.
240  // Pass in u, and tsite for the subset
241  CentralTPrecNoSpinUtils::TOp(tmp_T,
242  tmp_plus,
243  u,
244  tsite[cb3d],
245  fact,
246  other_sign);
247 
248  chi[rb3[cb3d]] += spinReconstructDir3Plus(tmp_T);
249 
250  chi[rb3[cb3d]] *= Real(0.5); //The overall factor of 1/2
251  }
252 
253 
254  //! Apply C_L
255  void EO3DPrecSCprecTCloverLinOp::cLeftLinOp(T& chi, const T& psi, enum PlusMinus isign,
256  int cb3d) const
257  {
258  LatticeHalfFermion tmp_minus;
259  LatticeHalfFermion tmp_plus;
260  LatticeHalfFermion tmp_T;
261 
262  tmp_plus[rb3[cb3d]] = spinProjectDir3Plus(psi);
263  chi[rb3[cb3d]] = spinReconstructDir3Plus(tmp_plus);
264 
265  tmp_minus[rb3[cb3d]] = spinProjectDir3Minus(psi);
266 
267  // Use shared routine to apply (T)^{-1} or (T^\dagger)^{-1}.
268  // Pass in u, and tsite, P, P^\dag, Q and Q^\dag for the subset.
269  CentralTPrecNoSpinUtils::invTOp( tmp_T,
270  tmp_minus,
271  u,
272  tsite[cb3d],
273  P_mat[cb3d],
274  P_mat_dag[cb3d],
275  Q_mat_inv[cb3d],
276  Q_mat_dag_inv[cb3d],
277  invfact,
278  isign,
279  getTMax());
280 
281 
282  chi[rb3[cb3d]] += spinReconstructDir3Minus(tmp_T);
283  chi[rb3[cb3d]] *= Real(0.5);
284  }
285 
286  //! Apply C_R
287  void EO3DPrecSCprecTCloverLinOp::cRightLinOp(T& chi, const T& psi, enum PlusMinus isign,
288  int cb3d) const
289  {
290  enum PlusMinus other_sign = isign == PLUS ? MINUS : PLUS ;
291  LatticeHalfFermion tmp_minus;
292  LatticeHalfFermion tmp_plus;
293  LatticeHalfFermion tmp_T;
294 
295  tmp_minus[rb3[cb3d]] = spinProjectDir3Minus(psi);
296  chi[rb3[cb3d]] = spinReconstructDir3Minus(tmp_minus);
297 
298  tmp_plus[rb3[cb3d]] = spinProjectDir3Plus(psi);
299 
300  // Use shared routine to apply (T)^{-1} or (T^\dagger)^{-1}.
301  // Pass in u, and tsite, P, P^\dag, Q and Q^\dag for the subset.
302  CentralTPrecNoSpinUtils::invTOp( tmp_T,
303  tmp_plus,
304  u,
305  tsite[cb3d],
306  P_mat[cb3d],
307  P_mat_dag[cb3d],
308  Q_mat_inv[cb3d],
309  Q_mat_dag_inv[cb3d],
310  invfact,
311  other_sign,
312  getTMax());
313 
314 
315  chi[rb3[cb3d]] += spinReconstructDir3Plus(tmp_T);
316  chi[rb3[cb3d]] *= Real(0.5);
317  }
318 
319 } // End Namespace Chroma
320 
321 #endif
322 #endif
323 #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
Double tmp
Definition: meslate.cc:60
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
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 multi1d< LatticeColorMatrix > u
Double one
Definition: invbicg.cc:105
@ MINUS
Definition: chromabase.h:45
@ PLUS
Definition: chromabase.h:45
chi
Definition: pade_trln_w.cc:24
psi
Definition: pade_trln_w.cc:191
LatticeFermion T
Definition: t_clover.cc:11