Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

alg_smear.C

Go to the documentation of this file.
00001 //--------------------------------------------------------------------
00009 //--------------------------------------------------------------------
00010 #include <config.h>
00011 #include <math.h>
00012 #include <util/qcdio.h>
00013 #include <alg/alg_smear.h>
00014 #include <util/lattice.h>
00015 #include <util/gjp.h>
00016 #include <util/error.h>
00017 #include <util/site.h>
00018 #include <util/link_buffer.h>
00019 #include <util/smalloc.h>
00020 
00021 CPS_START_NAMESPACE
00022 
00027 void sub( Matrix& x, Matrix& y , int ind )
00028 {
00029 
00030   const int su2_index[][3]= { {0,1,2},
00031                               {0,2,1},
00032                               {1,2,0} };
00033   y=x;
00034   const int zero_rc(su2_index[ind][2]);
00035   const int i1     (su2_index[ind][0]);
00036   const int i2     (su2_index[ind][1]);
00037   // zero out the row and column not used
00038   int i;
00039   for (i=0;i<3;i++) { y(zero_rc,i)=Complex(0,0); }
00040   for (i=0;i<3;i++) { y(i,zero_rc)=Complex(0,0); }
00041   y(zero_rc,zero_rc)=Complex(1,0);
00042   // project onto SU(2)
00043   Float p0(x(i1,i1).real() + x(i2,i2).real());
00044   Float p1(x(i1,i2).imag() + x(i2,i1).imag());
00045   Float p2(x(i1,i2).real() - x(i2,i1).real());
00046   Float p3(x(i1,i1).imag() - x(i2,i2).imag());
00047   const Float psqr( sqrt(p0*p0 + p1*p1 + p2*p2 + p3*p3) ); 
00048   Float ipsqr;
00049   if ( psqr == 0. ) { ipsqr=1;     }
00050   else              { ipsqr=1/psqr;} 
00051   p0*=ipsqr; p1*=ipsqr; p2*=ipsqr; p3*=ipsqr;
00052   // fill with inverse
00053   y(i1,i1) = Complex( p0,-p3);
00054   y(i2,i2) = Complex( p0, p3);
00055   y(i1,i2) = Complex(-p2,-p1);
00056   y(i2,i1) = Complex( p2,-p1);
00057 }
00058 
00059 int su3_proj( Matrix& x , Float tolerance )
00060 {
00061   // usually takes ~5 hits, so just exit
00062   // if hits the max, as something is 
00063   // probably very wrong.
00064   const int max_iter(10000);
00065   Matrix tmp  ;
00066   Matrix inv  ;
00067   Matrix y    ;
00068   Matrix ycopy;
00069   Matrix xdag ; xdag.Dagger(x);
00070   y.UnitMatrix();
00071   tmp = xdag;
00072   Float old_tr( xdag.ReTr() );
00073   int i,j;
00074   for (i=0;i<max_iter;i++)
00075     {
00076       // loop over su2 subgroups
00077       Float diff(-1);
00078       for (j=0;j<3;j++)
00079         {
00080           sub(tmp,inv,j);
00081           ycopy = y ; 
00082           y  .DotMEqual( inv, ycopy );
00083           tmp.DotMEqual( y, xdag );
00084           const Float tr (tmp.ReTr());
00085           const Float dtr(tr-old_tr );
00086           if ( dtr > diff ) { diff = dtr ; }
00087           old_tr = tr;
00088         } 
00089       // for single precision the difference seems
00090       // to never get below 1e-7 (not too suprising)
00091       if (diff < tolerance) { break; }
00092     }
00093   if ( i == max_iter )
00094     {
00095       // hit the max iterations
00096       ERR.General("","su3_proj","Max iterations");
00097     }
00098   x=y; 
00099   return i;
00100 } 
00101  
00109 AlgSmear::AlgSmear( Lattice&   lat,
00110                     CommonArg* ca ,
00111                     int su3_proj ):
00112   Alg(lat,ca),
00113   bool_su3_proj(su3_proj),
00114   tolerance    (1e-6),
00115   orthog       (-1)
00116 {
00117   cname = "AlgSmear";
00118   lat_back = new Matrix[GJP.VolNodeSites()*4];
00119   if ( lat_back == 0x0 ) { ERR.Pointer(cname, cname,"lat_back"); }
00120 }
00121 
00122 AlgSmear::~AlgSmear()
00123 {
00124   delete[] lat_back;
00125 }
00126 
00127 
00128 void AlgSmear::run()
00129 {
00130   Lattice& lattice(AlgLattice());
00131   
00132   //-----------------------------------------------------
00133   // Make a copy of the lattice. This will be the one
00134   // that is smeared. It will be swapped with the one in
00135   // the lattice class at the end of run()
00136   
00137   lattice.CopyGaugeField(lat_back);
00138   
00139   Site nloop;
00140   
00141   while ( nloop.LoopsOverNode() )
00142     {
00143       int mu;
00144       for (mu=0;mu<4;++mu)
00145         {
00146           // check that this isn't along a direction we are not
00147           // smearing in
00148 
00149           if ( mu != get_orthog() )
00150             {
00151 
00152               // link to be smeared
00153               
00154               Matrix& link(*(lat_back + 4*nloop.Index() + mu ));
00155               
00156               /*
00157                 the matrix to be added to this link, take
00158                 this from the gauge field the lattice
00159                 class knows about. This allows the link
00160                 buffer to be used and also means that smearing
00161                 a link will not change the staple of the
00162                 neighbouring links
00163               */
00164               smear_link(link,nloop.pos(),mu);
00165               
00166               // project the matrix back down to SU(3) (if needed)
00167               
00168               if ( bool_su3_proj )  { su3_proj( link , tolerance ); }
00169             } // smear in this direction ?
00170         } // direction
00171     } // spatial position
00172   
00173   // copy smeared configuration to the lattice
00174 
00175   lattice.GaugeField(lat_back);
00176   lattice.ClearAllBufferedLink();
00177 
00178 }
00179 
00187 void three_staple( Lattice& latt,  Matrix& link , 
00188                    int *pos, int u, int orth )
00189 {
00190   Matrix acumulate_mp; acumulate_mp.ZeroMatrix();
00191   int dir[3];
00192   //loop over all directions (+ve and -ve)
00193 
00194   for ( int v=0; v<8; v++ )
00195     {      
00196       // except the ones the link is aligned with 
00197       if((v&3)==u || (v&3) == orth )  continue; 
00198       
00199       const int v1((v+4)&7); // direction opposite to v
00200       
00201       dir[0] = v;
00202       dir[1] = u;
00203       dir[2] = v1;
00204       
00205       latt.PathOrdProdPlus(acumulate_mp, pos, dir, 3); 
00206     }
00207   // 18 is the matrix size
00208   moveMem((Float *) &link, (Float*)&acumulate_mp, 18*sizeof(Float));
00209 }
00210 
00211 
00212 
00213 void five_staple ( Lattice& latt,  Matrix& link ,
00214                    int *pos, int u , int orth )
00215 {
00216   Matrix acumulate_mp; acumulate_mp.ZeroMatrix();
00217 
00218   int v;
00219   int dir[5];
00220   // loop over all directions (+ve and -ve)
00221   for(v=0; v<8; v++)
00222     {
00223       // except the ones the link is aligned with 
00224       if((v&3)==u || (v&3) == orth ) { continue; }
00225       
00226       const int v1((v+4)&7); // direction opposite to v
00227       
00228       // loop over all directions (+ve and -ve)
00229       for(int w=0; w<8; w++)
00230         {
00231           /*
00232             except the ones aligned with either
00233             the link or the v direction
00234           */
00235           if( (w&3) == u || (w&3) == (v&3) || (w&3) == orth ) { continue; }
00236         
00237           const int w1((w+4)&7); // direction opposite to w
00238           
00239           // the chair (but not by Guofengs definition).
00240           dir[0] = v; 
00241           dir[1] = w;
00242           dir[2] = u;
00243           dir[3] = w1;
00244           dir[4] = v1;
00245           
00246           latt.PathOrdProdPlus(acumulate_mp, pos, dir, 5); 
00247         }
00248     }// all directions 
00249 
00250   // 18 is the matrix size
00251   moveMem((Float *) &link, (Float*)&acumulate_mp, 18*sizeof(Float));
00252 }
00253 
00254 
00255 void seven_staple( Lattice& latt,  Matrix& link ,
00256                    int *pos, int u , int orth )
00257 {
00258   Matrix acumulate_mp; acumulate_mp.ZeroMatrix();
00259   int v;
00260   int w;
00261   int x;
00262   int dir[7];
00263   // loop over all directions (+ve and -ve)
00264   for(v=0; v<8; v++)
00265     {
00266       // except the ones the link is aligned with 
00267       if((v&3)==u || (v&3)==orth ) { continue; }
00268       
00269       const int v1((v+4)&7); // direction opposite to v
00270       
00271       // loop over all directions (+ve and -ve)
00272       for(w=0; w<8; w++)
00273         {
00274           /*
00275             except the ones aligned with either
00276             the link or the v direction
00277           */
00278           if( (w&3) == u || (w&3) == (v&3) || (w&3) == orth ) { continue; }
00279           
00280           const int w1((w+4)&7); // direction opposite to w
00281           
00282           // loop over all directions (+ve and -ve)
00283           for (x=0;x<8;x++)
00284             {
00285               /*
00286                 except the ones aligned with
00287                 either the link, v or w
00288               */
00289               if( (x&3) == u     || 
00290                   (x&3) == (v&3) ||
00291                   (x&3) == (w&3) ||
00292                   (x&3) == orth    ) { continue; }
00293               
00294               const int x1((x+4)&7); // direction opposite to x
00295               
00296               // the chair (or at least a subset of)
00297               dir[0] = v; 
00298               dir[1] = w;
00299               dir[2] = x;
00300               dir[3] = u;
00301               dir[4] = x1;
00302               dir[5] = w1; 
00303               dir[6] = v1;
00304                                           
00305               latt.PathOrdProdPlus(acumulate_mp, pos, dir, 7); 
00306             }
00307         }// all directions 
00308     } // all directions
00309   // 18 is the matrix size
00310   moveMem((Float *) &link, (Float*)&acumulate_mp, 18*sizeof(Float));
00311 }
00312 
00313 
00314 void lepage_staple( Lattice& latt,  Matrix& link ,
00315                     int *pos, int u , int orth )
00316 {
00317   Matrix acumulate_mp; acumulate_mp.ZeroMatrix();
00318   int dir[5];
00319   //loop over all directions (+ve and -ve)
00320   int v;
00321   for ( v=0; v<8; v++ )
00322     {      
00323       // except the ones the link is aligned with 
00324       if((v&3)==u||(v&3)==orth) { continue; }
00325       
00326       const int v1((v+4)&7); // direction opposite to v
00327       
00328       dir[0] = v;
00329       dir[1] = v;
00330       dir[2] = u;
00331       dir[3] = v1;
00332       dir[4] = v1;
00333       
00334       latt.PathOrdProdPlus(acumulate_mp, pos, dir, 5); 
00335     }
00336   // 18 is the matrix size
00337   moveMem((Float *) &link, (Float*)&acumulate_mp, 18*sizeof(Float));
00338 }
00339 
00340 
00341 AlgApeSmear::AlgApeSmear(Lattice&     lat,
00342             CommonArg*   ca ,
00343             ApeSmearArg* asa,
00344             int          in_bool_su3_proj):
00345   AlgSmear(lat,ca,in_bool_su3_proj),
00346   cname("AlgApeSmear")
00347 {
00348   c = asa->coef;
00349   set_tol   (asa->tolerance);
00350   set_orthog(asa->orthog);
00351 }
00352   
00358 void AlgApeSmear::run()
00359 {
00360   if(common_arg->filename != 0){
00361     FILE* f = Fopen(common_arg->filename, "a");
00362     if(!f) ERR.FileA(cname, "run", common_arg->filename);
00363     Fprintf(f,"AlgApeSmear: coef = %e ",c);
00364     // YA changed AlgApeSmear being able for no projection, print in that case
00365     if( ! ifSu3Proj() )
00366       Fprintf(f,"with NO SU(3) projection");
00367     Fprintf(f,"\n");
00368     Fclose(f);
00369   }
00370   AlgSmear::run();
00371 }
00372 
00373 
00374 
00375 void AlgApeSmear::smear_link(Matrix& link,
00376                              int*     pos,
00377                              int       mu)
00378 {
00379   Lattice& lattice(AlgLattice());
00380   Matrix stap;
00381   three_staple(lattice,stap,pos,mu,get_orthog());
00382   link*=(1.0-c);
00383   stap*=c/6.0;
00384   link+=stap;
00385 }
00386 
00387 
00388 AlgKineticSmear::AlgKineticSmear(Lattice&   lat,
00389                                  CommonArg* ca ,
00390                                  KineticSmearArg* ksa ):
00391   AlgSmear(lat,ca,0),
00392   cname("AlgKineticSmear")
00393 {
00394   set_orthog(ksa->orthog);
00395   _coef[0] = ksa->single_link;
00396   _coef[1] = ksa->three_link;
00397   _coef[2] = ksa->five_link;
00398   _coef[3] = ksa->seven_link;
00399   _coef[4] = ksa->lepage;
00400 }
00401 
00402 
00408 void AlgKineticSmear::run()
00409 {
00410   if(common_arg->filename != 0){
00411     FILE* f = Fopen(common_arg->filename, "a");
00412     if(!f) ERR.FileA(cname, "run", common_arg->filename);
00413     for (int i=0;i<5;++i) Fprintf(f,"coef %2i : %e \n",i,(Float)_coef[i]);
00414     Fclose(f);
00415   }
00416   AlgSmear::run();
00417 }
00418 
00419 
00420 void AlgKineticSmear::smear_link( Matrix& link,
00421                                   int*    pos,
00422                                   int      mu )
00423 {
00424 
00425   typedef void (*staple_func)(Lattice&,Matrix&,int*,int,int);
00426     
00427   Lattice& lattice(AlgLattice());
00428   staple_func funcs[]={ &three_staple,
00429                         &five_staple ,
00430                         &seven_staple,
00431                         &lepage_staple };
00432   link*=_coef[0];
00433   Matrix stap; 
00434 
00435   for (int i=1;i<5;++i)
00436     {
00437       if ( _coef[i] != 0 ) continue;
00438       
00439       (*(funcs[i-1]))(lattice,stap,pos,mu,get_orthog());
00440       stap*=_coef[i];
00441       link+=stap;
00442       
00443     }
00444 }
00445 
00446 
00447 AlgHypSmear::AlgHypSmear( Lattice&     lat, 
00448                           CommonArg*   ca ,
00449                           HypSmearArg* hsa ): 
00450   AlgSmear(lat,ca,1),
00451   cname("AlgHypSmear")
00452 {
00453   set_tol   (hsa->tolerance);
00454   set_orthog(hsa->orthog);
00455   c1 = hsa->c1;
00456   c2 = hsa->c2;
00457   c3 = hsa->c3;
00458 }
00459   
00460 const Matrix AlgHypSmear::GetLink( Lattice& lat, const int* x, int mu )
00461 {
00462   int link_site[4];
00463   int i;
00464   for (i=0;i<4;i++){ link_site[i] = x[i]; }
00465   const int abs_dir ( mu & 3  );
00466   const int dir_sign( mu >> 2  );
00467   link_site[abs_dir] -=dir_sign;
00468 
00469   if( dir_sign){
00470     Matrix tmp;
00471     tmp.Dagger( *(lat.GetBufferedLink( link_site, abs_dir )) );
00472     return tmp;
00473   } else
00474     return *(lat.GetBufferedLink( link_site, abs_dir ));
00475 }
00476 
00477 
00478 void AlgHypSmear::get_vbar( Matrix& link, int *pos, int mu, int nu, int rho )
00479 {
00480   Lattice& lat(AlgLattice());
00481   Matrix accum; accum.ZeroMatrix();
00482   int v;
00483   int dir[3];
00484   for ( v=0;v<8;v++)
00485     {
00486       const int mv(v&3);
00487       if (mv==(mu&3)||mv==(nu&3)||mv==(rho&3)) { continue; }
00488       const int v1((v+4)&7); // direction opposite to v
00489       dir[0] = v;
00490       dir[1] = mu;
00491       dir[2] = v1;
00492       lat.PathOrdProdPlus(accum, pos, dir, 3);
00493     }
00494   link =  GetLink(lat,pos,mu);
00495   link *= (1-c3);
00496   accum*= c3/2;
00497   link+=accum;
00498   // project down to su3
00499   su3_proj( link , get_tol());
00500 }
00501 
00502 void AlgHypSmear::get_vtilde( Matrix& link , int *pos_in, int mu_in, int nu )
00503 {
00504   Lattice& latt(AlgLattice());
00505   link.ZeroMatrix();
00506   Matrix tmp1,tmp2,tmp3,tmp4;
00507   Matrix stap;
00508   
00509   const int sign_mu_in( mu_in >> 2  );
00510   const int mu ( mu_in & 3  );
00511 
00512   int pos[4] = { pos_in[0],pos_in[1],pos_in[2],pos_in[3] };
00513   if(sign_mu_in) pos[mu]--;
00514 
00515   // +1 in mu direction
00516   int pos_mu[4] = { pos[0],pos[1],pos[2],pos[3] };
00517   pos_mu[mu]++;
00518 
00519   int dir[2]; dir[0]=-1;
00520   int i;
00521   // dir1 and dir2 should be the two directions orthogonal to
00522   // mu and nu 
00523   for ( i=0;i<4;i++) 
00524     { 
00525       if ( i==(mu&3) || i==(nu&3) ) { continue; }
00526       if ( dir[0] < 0 ) { dir[0] = i ; }
00527       else { dir[1] = i; }
00528     }
00529 
00530   stap.ZeroMatrix();
00531   for(i=0;i<2;i++)
00532     {
00533       // forward 
00534       get_vbar(tmp1,pos   ,dir[i],nu    ,mu); pos[dir[i]]++;
00535       get_vbar(tmp2,pos   ,mu    ,dir[i],nu); pos[dir[i]]--;
00536       get_vbar(tmp3,pos_mu,dir[i],nu    ,mu);
00537      
00538       tmp4.DotMEqual( tmp1, tmp2 );
00539       tmp1.Dagger   ( tmp3 );
00540       stap.DotMPlus ( tmp4, tmp1 );
00541     
00542       // backwards 
00543       get_vbar(tmp1,pos   ,(dir[i]+4)&7,nu,mu); pos[dir[i]]--;
00544       get_vbar(tmp2,pos   ,mu,(dir[i]+4)&7,nu); pos[dir[i]]++;
00545       get_vbar(tmp3,pos_mu,(dir[i]+4)&7,nu,mu);
00546       
00547       tmp4.DotMEqual( tmp1, tmp2 );
00548       tmp1.Dagger   ( tmp3 );
00549       stap.DotMPlus ( tmp4, tmp1 );
00550     }
00551   
00552   link = GetLink(latt,pos,mu);
00553   link*=(1-c2);
00554   stap*=c2/4;
00555   link+=stap;
00556   // project down to su3
00557   su3_proj( link, get_tol() );
00558 
00559   if( sign_mu_in ){
00560     tmp1.Dagger( link );
00561     link = tmp1;
00562   }
00563 }
00564 
00565 
00566 
00567 void AlgHypSmear::smear_link(Matrix& link,
00568                              int*     pos,
00569                              int       mu)
00570 {
00571   Lattice& latt(AlgLattice());
00572   link.ZeroMatrix();
00573   Matrix tmp1,tmp2,tmp3,tmp4;
00574   Matrix stap;
00575   
00576   // +1 in mu direction
00577   int pos_mu[4];
00578   pos_mu[0] = pos[0];
00579   pos_mu[1] = pos[1];
00580   pos_mu[2] = pos[2];
00581   pos_mu[3] = pos[3];
00582   pos_mu[mu]++;
00583 
00584   int dir[3]; dir[0]=-1; dir[1]=-1;
00585   int i;
00586   // dir1-3 should be orthogonal to mu
00587   for ( i=0;i<4;i++) 
00588     { 
00589       if ( i==(mu&3) ) { continue; }
00590       if      ( dir[0] < 0 ) { dir[0] = i; }
00591       else if ( dir[1] < 0 ) { dir[1] = i; } 
00592       else                   { dir[2] = i; }
00593     }
00594 
00595   stap.ZeroMatrix();
00596   for ( i=0;i<3;i++)
00597     {
00598       // forward 
00599       get_vtilde(tmp1,pos,dir[i],mu);
00600 
00601       pos[dir[i]]++;
00602       get_vtilde(tmp2,pos,mu,dir[i]);
00603 
00604       pos[dir[i]]--;
00605       get_vtilde(tmp3,pos_mu,dir[i],mu);
00606       
00607       tmp4.DotMEqual( tmp1, tmp2 );
00608       tmp1.Dagger   ( tmp3 );
00609       stap.DotMPlus ( tmp4, tmp1 );
00610       
00611       // backwards 
00612       get_vtilde(tmp1,pos,(dir[i]+4)&7,mu);
00613 
00614       pos[dir[i]]--;
00615       get_vtilde(tmp2,pos,mu,(dir[i]+4)&7);
00616 
00617       pos[dir[i]]++;
00618       get_vtilde(tmp3,pos_mu,(dir[i]+4)&7,mu);
00619       
00620       tmp4.DotMEqual( tmp1, tmp2 );
00621       tmp1.Dagger   ( tmp3 );
00622       stap.DotMPlus ( tmp4, tmp1 );
00623     }
00624   link = GetLink(latt,pos,mu);
00625   link*=(1-c1);
00626   stap*=c1/6;
00627   link+=stap;
00628   
00629   // don't su3 project here because we'll do it in run()
00630 }
00631 
00638 void AlgHypSmear::run()
00639 {
00640   //  if ( get_orthog() >=0 || get_orthog() <4 )
00641   //   ^ YA: this will bring anything to ERR
00642   if ( get_orthog() >=0 && get_orthog() <4 )
00643       ERR.General(cname, "run",
00644                   "Bad value %d for orthogonal direction", get_orthog());
00645    
00646 
00647   if(common_arg->filename != 0){
00648       FILE* f = Fopen(common_arg->filename, "a");
00649       if(!f) ERR.FileA(cname, "run", common_arg->filename);
00650       Fprintf(f,"AlgHypSmear hit: c1=%e  c2=%e  c3=%e \n",c1,c2,c3);
00651       Fclose(f);
00652   }
00653 
00654   AlgSmear::run();
00655 }  
00656 CPS_END_NAMESPACE

Generated on Sat Oct 10 14:11:20 2009 for Columbia Physics System by  doxygen 1.3.9.1