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
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
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
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
00062
00063
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
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
00090
00091 if (diff < tolerance) { break; }
00092 }
00093 if ( i == max_iter )
00094 {
00095
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
00134
00135
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
00147
00148
00149 if ( mu != get_orthog() )
00150 {
00151
00152
00153
00154 Matrix& link(*(lat_back + 4*nloop.Index() + mu ));
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164 smear_link(link,nloop.pos(),mu);
00165
00166
00167
00168 if ( bool_su3_proj ) { su3_proj( link , tolerance ); }
00169 }
00170 }
00171 }
00172
00173
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
00193
00194 for ( int v=0; v<8; v++ )
00195 {
00196
00197 if((v&3)==u || (v&3) == orth ) continue;
00198
00199 const int v1((v+4)&7);
00200
00201 dir[0] = v;
00202 dir[1] = u;
00203 dir[2] = v1;
00204
00205 latt.PathOrdProdPlus(acumulate_mp, pos, dir, 3);
00206 }
00207
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
00221 for(v=0; v<8; v++)
00222 {
00223
00224 if((v&3)==u || (v&3) == orth ) { continue; }
00225
00226 const int v1((v+4)&7);
00227
00228
00229 for(int w=0; w<8; w++)
00230 {
00231
00232
00233
00234
00235 if( (w&3) == u || (w&3) == (v&3) || (w&3) == orth ) { continue; }
00236
00237 const int w1((w+4)&7);
00238
00239
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 }
00249
00250
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
00264 for(v=0; v<8; v++)
00265 {
00266
00267 if((v&3)==u || (v&3)==orth ) { continue; }
00268
00269 const int v1((v+4)&7);
00270
00271
00272 for(w=0; w<8; w++)
00273 {
00274
00275
00276
00277
00278 if( (w&3) == u || (w&3) == (v&3) || (w&3) == orth ) { continue; }
00279
00280 const int w1((w+4)&7);
00281
00282
00283 for (x=0;x<8;x++)
00284 {
00285
00286
00287
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);
00295
00296
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 }
00308 }
00309
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
00320 int v;
00321 for ( v=0; v<8; v++ )
00322 {
00323
00324 if((v&3)==u||(v&3)==orth) { continue; }
00325
00326 const int v1((v+4)&7);
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
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
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);
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
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
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
00522
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
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
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
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
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
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
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
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
00630 }
00631
00638 void AlgHypSmear::run()
00639 {
00640
00641
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