Beispiel #1
0
su3 slow_expon(su3 in, int nterm)  {
  su3 out , out_new , aa , aa_old , aa_scale ;
  int i ; 
  double fact = 1 ; 

  _su3_one(out) ; 
  aa = in ; 
  aa_old = aa ; 

  _su3_plus_su3(out_new,out,aa) ; 
  out = out_new ;  

  for(i=2 ; i < nterm ; ++i) {

    _su3_times_su3(aa,in,aa_old);
    aa_old = aa ; 
    aa_scale = aa ; 
    fact *= i ; 
    scale_su3(&aa_scale, 1.0/fact ) ; 

    _su3_plus_su3(out_new,out,aa_scale) ; 
    out = out_new ;  
  }

  return(out); 
}
Beispiel #2
0
void cayley_hamilton_exponent(su3* expA, su3 const *A)
{
  static double const fac_1_3 = 1 / 3.0;
    
  _Complex double f0,f1,f2;

  /* c0 = det[A] */
  double c0 = I * (A->c00 * (A->c11 * A->c22 - A->c12 * A->c21) + 
                   A->c01 * (A->c12 * A->c20 - A->c10 * A->c22) +
                   A->c02 * (A->c10 * A->c21 - A->c11 * A->c20)  );
  
  /* c1 = 0.5 * Tr[AA] */
  double c1 = -0.5 * (A->c00 * A->c00 + A->c01 * A->c10 + A->c02 * A->c20 +
                      A->c10 * A->c01 + A->c11 * A->c11 + A->c12 * A->c21 +
                      A->c20 * A->c02 + A->c21 * A->c12 + A->c22 * A->c22  );

  /* There is a special, but common (cold start) case where the given matrix is actually 0!
   * We need to account for it. */
  if (c0 == 0 && c1 == 0) 
  {
    _su3_one(*expA);
    f1 = I;
    f2 = -0.5;
    return;
  }
  
  /* P&M give symmetry relations that can be used when c0 < 0, to avoid the numerically problematic c0 -> -c0_max limit.
     We note the sign here for future reference, then continue with c0 as if it were positive. */
  int c0_negative = (c0 < 0);
  c0 = fabs(c0);

  /* The call to fmin below is needed, because for small deviations alpha from zero -- O(10e-12) -- rounding errors can cause c0 > c0max by epsilon.
     In that case, acos(c0/c0max) will produce NaNs, whereas the mathematically correct conclusion would be that theta is zero to machine precision! 
     Note that this approach will *not* produce identity and zero for all output, but rather the correct answer of order (I + alpha) for exp(iQ). */
  
  double c0max = 2.0 * pow(fac_1_3 * c1, 1.5);
  double theta_3 = fac_1_3 * acos(fmin(c0 / c0max, 1.0));

  double u = sqrt(fac_1_3 * c1) * cos(theta_3);
  double w = sqrt(c1) * sin(theta_3);
  
  /* Calculate and cache some repeating factors. *
   * We can fold in the sign immediately -- c.f. f_j(-c0, c1) = -1^j * conj(f_j(c0, c1)) 
   * This should just amount to potentially adding a minus to all imaginary components and an overall phase for f1. */
  _Complex double ma = cexp(2 * I * u);
  _Complex double mb = cexp(-I * u);
  double cw = cos(w);
  double u2 = u * u;
  double w2 = w * w;
  
  /* Modification w.r.t. Peardon & Morningstar:  w is always positive, so |w| =  w */
  double xi0 = (w > 0.05) ? (sin(w) / w) 
                          : 1 - 0.16666666666666667 *  w2 * (1 - 0.05 *  w2 * (1 - 0.023809523809523808 *  w2));
  double divisor = 1.0 / (9.0 * u2 -  w2);

  f0 = divisor * (ma * (u * u -  w * w) + mb * (8 * u * u * cw + 2 * I * u * (3 * u * u +  w * w) * xi0));
  f1 = divisor * (-2 * I * u * ma + mb * (2 * I * u * cw + (3 * u * u -  w * w) * xi0));
  f2 = divisor * (mb * (cw + 3 * I * u * xi0) - ma);

  /* The first point where we use the symmetry relations to calculate the negative c0 possibility */
  if (c0_negative)
  {
    f0 = conj(f0);
    f1 = conj(f1);
    f2 = conj(f2);
  }
  
  exponent_from_coefficients(expA, f0, f1, f2, A);
   
  return;
 }
Beispiel #3
0
static su3 unit_su3 (void)
{
   su3 u;
   _su3_one(u);
   return(u);
}
Beispiel #4
0
/* Method based on Givens' rotations, as used by Urs Wenger */
void reunitarize(su3 *omega)
{
  static su3 w, rot, tmp;
  static double trace_old, trace_new;
  static _Complex double s0, s1;
  static double scale;

  _su3_one(w);
  trace_old = omega->c00 + omega->c11 + omega->c22;

  for (int iter = 0; iter < 200; ++iter)
  {
    /* Givens' rotation 01 */
      s0 = omega->c00 + conj(omega->c11);
      s1 = omega->c01 - conj(omega->c10);
      scale = 1.0 / sqrt(conj(s0) * s0 + conj(s1) * s1);
      s0 *= scale;
      s1 *= scale;
      
      /* Projecting */
      _su3_one(rot);
      rot.c00 = s0;
      rot.c11 = conj(s0);
      rot.c01 = s1;
      rot.c10 = -conj(s1);

      _su3_times_su3(tmp, rot, w);
      _su3_assign(w, tmp);
      _su3_times_su3d(tmp, *omega, rot);
      _su3_assign(*omega, tmp);

    /* Givens' rotation 12 */
      s0 = omega->c11 + conj(omega->c22);
      s1 = omega->c12 - conj(omega->c21);
      scale = 1.0 / sqrt(conj(s0) * s0 + conj(s1) * s1);
      s0 *= scale;
      s1 *= scale;

      /* Projecting */
      _su3_one(rot);
      rot.c11 = s0;
      rot.c22 = conj(s0);
      rot.c12 = s1;
      rot.c21 = -conj(s1);

      _su3_times_su3(tmp, rot, w);
      _su3_assign(w, tmp);
      _su3_times_su3d(tmp, *omega, rot);
      _su3_assign(*omega, tmp);

    /* Givens' rotation 20 */
      s0 = omega->c22 + conj(omega->c00);
      s1 = omega->c20 - conj(omega->c02);
      scale = 1.0 / sqrt(conj(s0) * s0 + conj(s1) * s1);
      s0 *= scale;
      s1 *= scale;

      /* Projecting */
      _su3_one(rot);
      rot.c22 = s0;
      rot.c00 = conj(s0);
      rot.c20 = s1;
      rot.c02 = -conj(s1);

      _su3_times_su3(tmp, rot, w);
      _su3_assign(w, tmp);
      _su3_times_su3d(tmp, *omega, rot);
      _su3_assign(*omega, tmp);

    trace_new = omega->c00 + omega->c11 + omega->c22;

    if (trace_new - trace_old < 1e-15)
      break;
    trace_old = trace_new;
  }
  _su3_assign(*omega, w);
}
Beispiel #5
0
void sw_term(su3 ** const gf, const double kappa, const double c_sw) {
  int k,l;
  int x,xpk,xpl,xmk,xml,xpkml,xplmk,xmkml;
  su3 *w1,*w2,*w3,*w4;
  double ka_csw_8 = kappa*c_sw/8.;
  static su3 v1,v2,plaq;
  static su3 fkl[4][4];
  static su3 magnetic[4],electric[4];
  static su3 aux;
  
  /*  compute the clover-leave */
  /*  l  __   __
        |  | |  |
        |__| |__|
         __   __
        |  | |  |
        |__| |__| k  */
  
  for(x = 0; x < VOLUME; x++) {
    for(k = 0; k < 4; k++) {
      for(l = k+1; l < 4; l++) {
	xpk=g_iup[x][k];
	xpl=g_iup[x][l];
	xmk=g_idn[x][k];
	xml=g_idn[x][l];
	xpkml=g_idn[xpk][l];
	xplmk=g_idn[xpl][k];
	xmkml=g_idn[xml][k];
	w1=&gf[x][k];
	w2=&gf[xpk][l];
	w3=&gf[xpl][k];
	w4=&gf[x][l];
	_su3_times_su3(v1,*w1,*w2);
	_su3_times_su3(v2,*w4,*w3);
	_su3_times_su3d(plaq,v1,v2);
	w1=&gf[x][l];
	w2=&gf[xplmk][k];
	w3=&gf[xmk][l];
	w4=&gf[xmk][k];
	_su3_times_su3d(v1,*w1,*w2);
	_su3d_times_su3(v2,*w3,*w4);
	_su3_times_su3_acc(plaq,v1,v2);
	w1=&gf[xmk][k];
	w2=&gf[xmkml][l];
	w3=&gf[xmkml][k];
	w4=&gf[xml][l];
	_su3_times_su3(v1,*w2,*w1);
	_su3_times_su3(v2,*w3,*w4);
	_su3d_times_su3_acc(plaq,v1,v2);
	w1=&gf[xml][l];
	w2=&gf[xml][k];
	w3=&gf[xpkml][l];
	w4=&gf[x][k];
	_su3d_times_su3(v1,*w1,*w2);
	_su3_times_su3d(v2,*w3,*w4);
	_su3_times_su3_acc(plaq,v1,v2);
	_su3_dagger(v2,plaq); 
	_su3_minus_su3(fkl[k][l],plaq,v2);
      }
    }

    // this is the one in flavour and colour space
    // twisted mass term is treated in clover, sw_inv and
    // clover_gamma5
    _su3_one(sw[x][0][0]);
    _su3_one(sw[x][2][0]);
    _su3_one(sw[x][0][1]);
    _su3_one(sw[x][2][1]);
    
    for(k = 1; k < 4; k++)
    {
      _su3_assign(electric[k], fkl[0][k]);
    }
    _su3_assign(magnetic[1], fkl[2][3]);
    _su3_minus_assign(magnetic[2], fkl[1][3]);
    _su3_assign(magnetic[3], fkl[1][2]);
    
    /*  upper left block 6x6 matrix  */
    
    _itimes_su3_minus_su3(aux,electric[3],magnetic[3]);
    _su3_refac_acc(sw[x][0][0],ka_csw_8,aux);
    
    _itimes_su3_minus_su3(aux,electric[1],magnetic[1]);
    _su3_minus_su3(v2,electric[2],magnetic[2]); 
    _su3_acc(aux,v2);
    _real_times_su3(sw[x][1][0],ka_csw_8,aux);
    
    _itimes_su3_minus_su3(aux,magnetic[3],electric[3]);
    _su3_refac_acc(sw[x][2][0],ka_csw_8,aux);

    /*  lower right block 6x6 matrix */
    
    _itimes_su3_plus_su3(aux,electric[3],magnetic[3]);
    _su3_refac_acc(sw[x][0][1],(-ka_csw_8),aux);

    _itimes_su3_plus_su3(aux,electric[1],magnetic[1]);
    _su3_plus_su3(v2,electric[2],magnetic[2]); 
    _su3_acc(aux,v2);
    _real_times_su3(sw[x][1][1],(-ka_csw_8),aux);

    _itimes_su3_plus_su3(aux,magnetic[3],electric[3]);
    _su3_refac_acc(sw[x][2][1],ka_csw_8,aux);
  }
  return;
}
Beispiel #6
0
void flip_subgroup(int ix, int mu, su3 vv, int i){
  static double vv0,vv1,vv2,vv3,aa0,aa1,aa2,aa3;
  static double aux,norm_vv_sq; 
  
  static su3 a,w,v;
  su3 *z;
  _su3_assign(v,vv);
  _su3_one(a);
  z=&g_gauge_field[ix][mu];     
  _su3_times_su3d(w,*z,v);

  /*
    According to Peter's notes ``A Cabibbo-Marinari SU(3)....", eqs. (A.14-A.17)
    we have */
  if(i==1)
  {
    vv0 =  creal(w.c00) + creal(w.c11);   
    vv3 = -cimag(w.c00) + cimag(w.c11);
    vv1 = -cimag(w.c01) - cimag(w.c10);
    vv2 = -creal(w.c01) + creal(w.c10);
  }
  else if(i==2)
  {
    vv0 =  creal(w.c00) + creal(w.c22);   
    vv3 = -cimag(w.c00) + cimag(w.c22);
    vv1 = -cimag(w.c02) - cimag(w.c20);
    vv2 = -creal(w.c02) + creal(w.c20);
  }
  else
  {
    vv0 =  creal(w.c11) + creal(w.c22);   
    vv3 = -cimag(w.c11) + cimag(w.c22);
    vv1 = -cimag(w.c12) - cimag(w.c21);
    vv2 = -creal(w.c12) + creal(w.c21);
  }

  norm_vv_sq= vv0 * vv0 + vv1 * vv1 + vv2 * vv2 + vv3 * vv3;

  aux= 2.0 * vv0 / norm_vv_sq;
  aa0 = aux * vv0-1.0;
  aa1 = aux * vv1;
  aa2 = aux * vv2;
  aa3 = aux * vv3;

  /*  aa is embedded in the SU(3) matrix (a) which can be multiplied on
      the link variable using the su3_type operator * . */
      
  if(i==1)
  {
    a.c00 = aa0 + aa3 * I;
    a.c11 = conj(a.c00);
    a.c01 = aa2 + aa1 * I;
    a.c10 = -conj(a.c01);
  }
  else if(i==2)
  {
    a.c00 = aa0 + aa3 * I;
    a.c22 = conj(a.c00);
    a.c02 = aa2 + aa1 * I;
    a.c20 = -conj(a.c02);
  }
  else
  {
    a.c11 = aa0 + aa3 * I;
    a.c22 = conj(a.c11);
    a.c12 = aa2 + aa1 * I;
    a.c21 = -conj(a.c12);
  }

  _su3_times_su3(w,a,*z);
  *z=w;
}