CHROMA
ilu2prec_s_cprec_t_clover_linop_w.cc
Go to the documentation of this file.
1 /*! \file
2  * \brief Unpreconditioned Clover linear operator
3  */
4 
5 
6 #include "qdp_config.h"
7 #if QDP_NS == 4
8 #if QDP_ND == 4
9 #if QDP_NC == 3
10 
11 #include "chromabase.h"
14 
15 using namespace QDP::Hints;
16 
17 namespace Chroma
18 {
19 
20 
21  //! Creation routine with Anisotropy
22  /*!
23  * \param u_ gauge field (Read)
24  * \param Mass_ fermion kappa (Read)
25  * \param aniso anisotropy struct (Read)
26  */
27  void ILU2PrecSCprecTCloverLinOp::create(Handle< FermState<T,P,Q> > fs_,
28  const CloverFermActParams& param_)
29  {
30 #ifndef QDP_IS_QDPJIT
31  START_CODE();
32 
33  // Copy Params
34  param = param_;
35 
36  // Check we are in 4D
37  if ( Nd != 4 ) {
38  QDPIO::cout << "This class (ILU2PrecSCprecTCloverLinOp) only works in 4D" << std::endl;
39  QDP_abort(1);
40  }
41 
42  // Check Aniso Direction -- has to be 3.
43  if ( param.anisoParam.anisoP== true && param.anisoParam.t_dir != 3 ) {
44  QDPIO::cout << "This class (ILU2PrecSCprecTCloverLinOp) 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 (ILU2PrecSCprecTCloverLinOp) needs time to be local" << std::endl;
53  QDP_abort(1);
54  }
55 
56  // Store gauge state etc
57  fs = fs_;
58 
59  // Work out aniso factors
60  Real ff = where(param.anisoParam.anisoP, param.anisoParam.nu / param.anisoParam.xi_0, Real(1));
61  fact = 1 + (Nd-1)*ff + param.Mass;
62  QDPIO::cout << "Factor=" << fact << " log10(Factor)="<< log10(fact) << std::endl;
63 
64  invfact = Real(1)/fact;
65  u = fs->getLinks();
66 
67  // Incorporate into links
68  if (param.anisoParam.anisoP)
69  {
70  // Rescale the u fields by the anisotropy
71  for(int mu=0; mu < u.size(); ++mu)
72  {
73  if (mu != param.anisoParam.t_dir)
74  u[mu] *= ff;
75  }
76  }
77 
78  // These will be useful for controlling loops.
79  int t_index=3;
80  int Nx = QDP::Layout::subgridLattSize()[0];
81  int Ny = QDP::Layout::subgridLattSize()[1];
82  int Nz = QDP::Layout::subgridLattSize()[2];
83  int Nt = QDP::Layout::subgridLattSize()[3];
84 
85  // Resize lookup table: for spatial site z,y,x we will get back an array of length t giving the site indices
86  // for the t sites, with that spatial index.
87  //
88  int Nspaceby2 = Nx*Ny*Nz/2; // This always works because Nx has to be even...
89 
90  tsite.resize(2, Nspaceby2, Nt);
91 
92 
93  int ssite_even=0;
94  int ssite_odd=0;
95 
96  int color;
97  int site;
98 
99  // Loop over all spatial sites
100  for(int z=0; z < Nz; z++) {
101  for(int y=0; y < Ny; y++) {
102  for(int x=0; x < Nx; x++) {
103  // Assemble the site indices for all timeslices of this coordinate
104 
105  multi1d<int> coords(Nd);
106  coords[0]=x;
107  coords[1]=y;
108  coords[2]=z;
109  color = (x + y + z) & 1;
110 
111  if ( color == 0 ) {
112  for(int t=0; t < Nt; t++) {
113  coords[3] = t;
114  tsite(0,ssite_even, t) = QDP::Layout::linearSiteIndex(coords);
115  }
116  ssite_even++;
117 
118  }
119  else {
120  for(int t=0; t < Nt; t++) {
121  coords[3] = t;
122  tsite(1,ssite_odd, t) = QDP::Layout::linearSiteIndex(coords);
123  }
124  ssite_odd++;
125  }
126  }
127  }
128  }
129 
130 
131 
132  // Figure out whether we are Schroedinger in time:
133  const FermBC<T,P,Q>& fbc = getFermBC();
134  if( fbc.nontrivialP() ) {
135  try {
136  const SchrFermBC& schr_ref = dynamic_cast<const SchrFermBC&>(fbc);
137  schrTP = ( schr_ref.getDir() == tDir() );
138  }
139  catch(std::bad_cast) {
140  schrTP = false;
141  }
142  }
143  else {
144  // fbc are not nontrivial
145  schrTP = false;
146  }
147 
148  logDetTSq = zero;
149  QDPIO::cout << "Got here " << std::endl << std::flush;
150  if( !schrTP ) {
151  // If we are using the max_norm tric. Compute the t_needed
152 
153  if( param.max_norm_usedP) {
154  Real tmp1=param.max_norm/sqrt(Real(3));
155  Real t = -( log(tmp1)/log(fact));
156  QDPIO::cout << "Cutoff t is " << t<< std::endl;
157  t_max=(int)toDouble(ceil(t));
158  QDPIO::cout << "T_max="<<t_max << std::endl;
159  }
160  else {
161  t_max=Nt;
162  QDPIO::cout << "Not using cutoff trick. Setting T_max="<<t_max<<std::endl;
163  }
164  // P and P_mat dag are needed for the Woodbury
165  // (P_mat for inverting T, P_mat_dag for inverting T_dag - NB P_mat_dag != (P_mat)^dagger
166  P_mat.resize(2, Nspaceby2, Nt);
167  P_mat_dag.resize(2, Nspaceby2, Nt);
168 
169  Q_mat_inv.resize(2,Nspaceby2);
170  Q_mat_dag_inv.resize(2,Nspaceby2);
171 
172 
173  for(int cb3=0; cb3 < 2; cb3++) {
174  for(int site=0; site < Nspaceby2; site++) {
175 
176 
177  Real minvfact = Real(-1)*invfact;
178 
179  // Compute P by backsubsitution - See Balint's notes eq 38-42
180  P_mat(cb3, site, Nt-1) = u[t_index].elem( tsite(cb3,site,Nt-1) );
181  P_mat(cb3, site, Nt-1) *= minvfact.elem();
182 
183 
184  for(int t=Nt-2; t >=0; t--) {
185  if( t > Nt-1-t_max) {
186  P_mat(cb3, site, t) = u[t_index].elem( tsite(cb3, site,t) ) * P_mat(cb3, site,t+1);
187  P_mat(cb3, site, t) *= invfact.elem();
188  }
189  else {
190  zero_rep(P_mat(cb3, site, t));
191  }
192  }
193  // Compute the dagger. Opposite order (forward sub) similara to eq 38-42
194  // in notes
195  P_mat_dag(cb3, site, 0) = adj( u[t_index].elem( tsite(cb3, site, Nt-1) ) );
196  P_mat_dag(cb3, site, 0) *= minvfact.elem();
197 
198  for(int t=1; t < Nt; t++) {
199  if( t < t_max ) {
200  P_mat_dag(cb3, site,t) = adj( u[t_index].elem( tsite(cb3, site, t-1) ) )*P_mat_dag(cb3,site, t-1) ;
201  P_mat_dag(cb3, site,t) *= invfact.elem();
202  }
203  else {
204  zero_rep(P_mat_dag(cb3, site,t));
205  }
206 
207  }
208 
209 
210  // Compute Q = (1 + W^\dag P)^{-1}, W = [1, 0, 0, 0...] => (1 + P_{0})^{-1} eq: 43
211  // NB: This is not necessarily SU(3) now, so we can't just take the dagger to get the inverse
212  Real one=Real(1);
213  CMat one_plus_P0 = one.elem() + P_mat(cb3, site,0);
214  CentralTPrecNoSpinUtils::invert3by3( Q_mat_inv(cb3, site), one_plus_P0 );
215 
216  // Compute Q_dag = 1 + W^\dag P^\dag, W = [ 0, ..., 1 ] = > Q_dag = P^\dag [Nt-1]
217  // Similar to eq 43
218  // NB: This is not necessarily SU(3) now, so we can't just take the dagger to get the inverse
219  CMat one_plus_P0_dag = one.elem() + P_mat_dag(cb3, site,Nt-1);
220  CentralTPrecNoSpinUtils::invert3by3( Q_mat_dag_inv(cb3, site), one_plus_P0_dag);
221 
222  CMat prod = one_plus_P0_dag*one_plus_P0;
223  logDetTSq += CentralTPrecNoSpinUtils::logDet(prod);
224  }
225  }
226  }
227  else {
228  t_max = Nt;
229  }
230 
231  // Create Clover term = A + factor (we don't want the diag mass bit)
232  APlusFact.create(fs, param);
233  Dw3D.create(fs_, param_.anisoParam);
234 
235 #if 1
236  QDPIO::cout << "schrTP is " << schrTP << std::endl;
237  if(schrTP==false) {
238  // Numerical experiments
239  for(int i=0; i < Nt; i++) {
240  Double fnorm=Double(0);
241  Double fnorm2=Double(0);
242 
243  OScalar<CMat> f; f.elem() = P_mat(0,0,i);
244  fnorm=sqrt(norm2(f));
245  OScalar<CMat> f2; f2.elem() = P_mat_dag(0,0,i);
246  fnorm2=sqrt(norm2(f2));
247 
248  QDPIO::cout << "cb=0 x=0 t="<<i<<" normP="<<fnorm<<" normPdag="<<fnorm2 << std::endl;
249  }
250  }
251 #endif
252 
253 #endif
254  END_CODE();
255  }
256 
257 
258 } // End Namespace Chroma
259 
260 #endif
261 #endif
262 #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
unsigned i
Definition: ldumul_w.cc:34
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 int tDir()
Definition: coulgauge.cc:14
static multi1d< LatticeColorMatrix > u
Double one
Definition: invbicg.cc:105
Double zero
Definition: invbicg.cc:106
const T1 const T2 & f2
Definition: gtest.h:1321
FloatingPoint< double > Double
Definition: gtest.h:7351