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