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

alg_smear2.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_smear2.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 AlgSmear2::AlgSmear2( 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 = "AlgSmear2";
00118   lat_back = new Matrix[GJP.VolNodeSites()*4];
00119   if ( lat_back == 0x0 ) { ERR.Pointer(cname, cname,"lat_back"); }
00120 }
00121 
00122 AlgSmear2::~AlgSmear2()
00123 {
00124   delete[] lat_back;
00125 }
00126 
00127 
00128 void AlgSmear2::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       for (mu=0;mu<3;++mu)
00146         {
00147           // check that this isn't along a direction we are not
00148           // smearing in
00149 
00150           if ( mu != get_orthog() )
00151             {
00152 
00153               // link to be smeared
00154               
00155               Matrix& link(*(lat_back + 4*nloop.Index() + mu ));
00156               
00157               /*
00158                 the matrix to be added to this link, take
00159                 this from the gauge field the lattice
00160                 class knows about. This allows the link
00161                 buffer to be used and also means that smearing
00162                 a link will not change the staple of the
00163                 neighbouring links
00164               */
00165               smear_link2(link,nloop.pos(),mu);
00166               
00167               // project the matrix back down to SU(3) (if needed)
00168               
00169               if ( bool_su3_proj )  { su3_proj( link , tolerance ); }
00170             } // smear in this direction ?
00171         } // direction
00172     } // spatial position
00173   
00174   // copy smeared configuration to the lattice
00175 
00176   lattice.GaugeField(lat_back);
00177   lattice.ClearAllBufferedLink();
00178 
00179 }
00180 
00188 void three_staple2( Lattice& latt,  Matrix& link , 
00189                    int *pos, int u, int orth )
00190 {
00191   Matrix acumulate_mp; acumulate_mp.ZeroMatrix();
00192   int dir[3];
00193   //loop over all directions (+ve and -ve)
00194 
00195   for ( int v=0; v<8; v++ )
00196     {      
00197       // except the ones the link is aligned with 
00198       //      if((v&3)==u || (v&3) == orth)  continue; 
00199       if((v&3) == u)  continue; 
00200       if((v&3) == orth)  continue; 
00201       if((v&3) == 3)  continue; 
00202       
00203       const int v1((v+4)&7); // direction opposite to v
00204       
00205       dir[0] = v;
00206       dir[1] = u;
00207       dir[2] = v1;
00208       
00209       latt.PathOrdProdPlus(acumulate_mp, pos, dir, 3); 
00210     }
00211   // 18 is the matrix size
00212   moveMem((Float *) &link, (Float*)&acumulate_mp, 18*sizeof(Float));
00213 }
00214 
00215 AlgApeSmear2::AlgApeSmear2(Lattice&     lat,
00216             CommonArg*   ca ,
00217             ApeSmearArg* asa ):
00218   AlgSmear2(lat,ca,1),
00219   cname("AlgApeSmear2")
00220 {
00221   c = asa->coef;
00222   set_tol   (asa->tolerance);
00223   set_orthog(asa->orthog);
00224 }
00225   
00231 void AlgApeSmear2::run()
00232 {
00233   if(common_arg->filename != 0){
00234     FILE* f = Fopen(common_arg->filename, "a");
00235     if(!f) ERR.FileA(cname, "run", common_arg->filename);
00236     Fprintf(f,"AlgApeSmear2: coef = %e \n",c);
00237     Fclose(f);
00238   }
00239   AlgSmear2::run();
00240 }
00241 
00242 
00243 
00244 void AlgApeSmear2::smear_link2(Matrix& link,
00245                              int*     pos,
00246                              int       mu)
00247 {
00248   Lattice& lattice(AlgLattice());
00249   Matrix stap;
00250   three_staple2(lattice,stap,pos,mu,get_orthog());
00251   link*=(1.0-c);
00252   stap*=c/6.0;
00253   link+=stap;
00254 }
00255 
00256 CPS_END_NAMESPACE

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