Exemple #1
0
/*!
  Non-Zero Momentum nucleon  from wall sources
*/
void Nuc2pt::calcWallMomNucleon(QPropW& quark, QPropWMomSrc& mom_quark)
{
  char *fname = "Nuc2pt()";
  ThreeMom sink_mom(mom_quark.Mom()) ;
  sink_mom.conj();
  //The momentum on the sink has to be complex conjugated!!
  // p --> - p 
  
  srcdesc[0]=srcdesc[1]=srcdesc[2]=srcdesc[3]=-1 ;
  srcdesc[4]=srcdesc[5]=-1 ; // TIZB
  switch (quark.SrcType())
    {
    case WALL:
      srcdesc[0] = quark.SourceTime() ;
      source="WALL" ;
      break ;
    default:
      ERR.General(cname,fname,"Bad source type\n") ;
    }
  
  quark_mass = quark.Mass() ;
    
  WilsonMatrix Q1;  
  WilsonMatrix Q2;
  WilsonMatrix Q3;  
  
  SnkType=POINT;
  sprintf(mom,"%i %i %i", mom_quark.Mom().cmp(0), 
	  mom_quark.Mom().cmp(1), mom_quark.Mom().cmp(2) );
  Site s ;
  for(s.Begin();s.End();s.nextSite())
    {
      int t = s.physT() ;
      Q1 =  quark[s.Index()] ;  
      if(HalfFerm) Q1.PParProjectSink() ;
      Q2 = Q1 ;
      // here is the sink so I need exp(ipx) 
      // I did conjugate the momentum at the construction
      Q3 = sink_mom.Fact(s)*mom_quark[s.Index()]  ; 
      if(HalfFerm) Q3.PParProjectSink() ;
      calc_nuc_(Q1, Q2, Q3,t) ;	  
    }
  plus_parity.GlobalSum() ;
  minus_parity.GlobalSum() ;
}
Exemple #2
0
/*! 
  Computes
  \f[
   Trace(seqQ \, 
     \gamma_{\mu_1} \, \gamma_{\mu_2} \, \gamma_{\mu_3}\, 
     e^{-i mom . x}\, Quark)
  \f]
  where \f$\mu\f$ is the member int gamma and ThreeMom mom is
  the momentum injected at the operator. 
**/
void Nuc3ptGamma::InsertOp(CorrFunc& tmp,QPropW& seqQ, QPropW& Quark)
{
  char *fname = "InsertOp()";

  VRB.Func(cname, fname);

  Site s ;
  for(s.Begin();s.End();s.nextSite())
    {
      int t(s.physT()) ;
      WilsonMatrix sq(seqQ[s.Index()]) ;
      for(int mu(0);mu<G.N();mu++)
	sq.gr(G[mu]) ; // Multiply by gamma_mu 
      Complex cc(mom.Fact(s)) ; // The momentum factor exp(-ipx)
      cc *= Trace(sq,Quark[s.Index()]) ;
      tmp[t] += cc ;
    }
}
void AlgFourierProp::calcmom(const FourMom& p)
{
  char *fname="calcmom(const FourMom&)";
  VRB.Func(cname,fname);

  Float   p1( p.x() + 0.5*bc[0] );
  Float   p2( p.y() + 0.5*bc[1] );
  Float   p3( p.z() + 0.5*bc[2] );
  Float   p4( p.t() + 0.5*bc[3] );
 
  const Float PI(3.141592654);
 
  p1 *= 2.0*PI/(GJP.XnodeSites()*GJP.Xnodes());
  p2 *= 2.0*PI/(GJP.YnodeSites()*GJP.Ynodes());
  p3 *= 2.0*PI/(GJP.ZnodeSites()*GJP.Znodes());
  p4 *= 2.0*PI/(GJP.TnodeSites()*GJP.Tnodes());

  Site site;

  while ( site.LoopsOverNode() )
    {
      const Float px( site.physX()*p1 );
      const Float py( site.physY()*p2 );
      const Float pz( site.physZ()*p3 );
      const Float pt( site.physT()*p4 );
      
      const Float pdotx( px + py + pz + pt );


      Rcomplex fact( cos(pdotx), -sin(pdotx) );

      //--------------------------------------------
      //  Using AddMult is logically equivalent to
      //     momprop += fact * (*prop)[i]; ,
      //  but cuts down on the number of loops over
      //  the data. The time taken is reduced by
      //  a factor of two.
      //--------------------------------------------
      
      momprop.AddMult(fact,(*prop)[site.Index()]);
      
    }
}
Exemple #4
0
/*!
  Non-Zero Momentum nucleon from box sources or point
*/
void Nuc2pt::calcMomNucleon(QPropW& quark, ThreeMom& Mom, int dohalf)
{
  char *fname = "Nuc2pt()";
  ThreeMom sink_mom(Mom) ;
  sink_mom.conj();
  //The momentum on the sink has to be complex conjugated!!
  // p --> - p 

  HalfFerm=dohalf;
  
  srcdesc[0]=srcdesc[1]=srcdesc[2]=srcdesc[3]=-1 ;
  srcdesc[4]=srcdesc[5]=-1 ; // TIZB
  switch (quark.SrcType())
    {
    case BOX:
      srcdesc[0] = quark.BoxSrcStart() ; 
      srcdesc[1] = quark.BoxSrcEnd() ;
      srcdesc[2] = quark.SourceTime() ;
      if( quark. BoxSrcUseXYZOffset() ){ // use QPropWArg.{x,y,z} as offset
	srcdesc[3] = quark.PointSrcX() ; 
	srcdesc[4] = quark.PointSrcX() ; 
	srcdesc[5] = quark.PointSrcX() ; 
      }
      source="BOX" ;
      break ;
    case POINT:
      srcdesc[0] = quark.PointSrcX() ; 
      srcdesc[1] = quark.PointSrcY() ;
      srcdesc[2] = quark.PointSrcZ() ;
      srcdesc[3] = quark.SourceTime() ;
      source="POINT" ;
      break ;
    case GAUSS_GAUGE_INV:
      srcdesc[0] = quark.Gauss_N() ; 
      srcdesc[1] = int(100*quark.Gauss_W()) ;
      srcdesc[2] = quark.SourceTime() ;
      source = "GAUSS" ;
      break ;
    default:
      ERR.General(cname,fname,"Bad source type\n") ;
    }
  
  quark_mass = quark.Mass() ;
  
  WilsonMatrix Q1;  
  WilsonMatrix Q2;
  WilsonMatrix Q3;  
  WilsonMatrix Q4;
  WilsonMatrix Q5;  
  
  //SnkType=POINT;
  sprintf(mom,"%i %i %i", Mom.cmp(0), Mom.cmp(1), Mom.cmp(2) );

  Site s ;

  for(s.Begin();s.End();s.nextSite())
    {
      int t = s.physT() ;
      Q1 = quark[s.Index()] ;
      if(HalfFerm) Q1.PParProjectSink() ;
      Q2 = Q1 ; 
      Q3 = Q1 ; 
      Q4 = Q1 ; 
      // here is the sink so I need exp(ipx) 
      // I did conjugate the momentum at the construction
      Q5 = Mom.Fact(s)*Q2 ;
      calc_nuc_(Q1, Q2, Q3, Q4, Q5, t, dohalf) ;
    }
  plus_parity.GlobalSum() ;
  minus_parity.GlobalSum() ;
}
Exemple #5
0
/*!
  Calculate zero momentum nucleon two point functions
*/
void Nuc2pt::calcNucleon(QPropW& quark, int dohalf){
  char *cname = "Nuc2pt" ;
  char *fname = "calcNucleon(QPropW&)" ;

  strcpy(mom,"0 0 0");  

  HalfFerm=dohalf;

  srcdesc[0]=srcdesc[1]=srcdesc[2]=srcdesc[3]=-1 ;
  srcdesc[4]=srcdesc[5]=-1 ; // TIZB
  switch (quark.SrcType())
    {
    case WALL:
      srcdesc[0] = quark.SourceTime() ;
      source="WALL" ;
      break ;
    case BOX:
      srcdesc[0] = quark.BoxSrcStart() ; 
      srcdesc[1] = quark.BoxSrcEnd() ;
      srcdesc[2] = quark.SourceTime() ;
      if( quark. BoxSrcUseXYZOffset() ){ // use QPropWArg.{x,y,z} as offset
	srcdesc[3] = quark.PointSrcX() ; 
	srcdesc[4] = quark.PointSrcX() ; 
	srcdesc[5] = quark.PointSrcX() ; 
      }
      source="BOX" ;
      break ;
    case POINT:
      srcdesc[0] = quark.PointSrcX() ; 
      srcdesc[1] = quark.PointSrcY() ;
      srcdesc[2] = quark.PointSrcZ() ;
      srcdesc[3] = quark.SourceTime() ;
      source = "POINT" ;
      break ;
    case GAUSS_GAUGE_INV:
      srcdesc[0] = quark.Gauss_N() ; 
      srcdesc[1] = int(100*quark.Gauss_W()) ;
      srcdesc[2] = quark.SourceTime() ;
      source = "GAUSS" ;
      break ;
    default:
      ERR.General(cname,fname,"Bad source type\n") ;
    }
  quark_mass = quark.Mass() ;
    
  WilsonMatrix Q1;  
  WilsonMatrix Q2;
  WilsonMatrix Q3;
  WilsonMatrix Q4;
  WilsonMatrix Q5;
  
    switch (SnkType)
      {
      case POINT:
      case GAUSS_GAUGE_INV:	
	{
	  if(SnkType==GAUSS_GAUGE_INV)
	    sink="GAUSS" ;
	  else
	    sink="POINT" ;
	  Site s ;
	  for(s.Begin();s.End();s.nextSite())
	    {
	      int t = s.physT() ;
	      Q1 = quark[s.Index()] ;
	      if(HalfFerm) Q1.PParProjectSink() ;
	      Q2 = Q1 ; 
	      Q3 = Q1 ; 
	      Q4 = Q1 ; 
	      Q5 = Q1 ; 
	      calc_nuc_(Q1, Q2, Q3, Q4, Q5, t, dohalf) ;
	    }
	  plus_parity.GlobalSum() ;
	  minus_parity.GlobalSum() ;
	}
	break ;
      case WALL:
	{
	  sink="WALL" ;

	  if(!quark.GFixedSnk())
	    ERR.General(cname,fname,"Wall sink needs gauge fixing\n") ;

	  for(int t = 0 ; t<plus_parity.TimeSize();t++)
	    {
	      Q1 =  quark.WallSinkProp(t) ;
	      if(HalfFerm) Q1.PParProjectSink() ;
	      Q2 = Q1 ;
	      calc_nuc_(Q1, Q2, Q1, t) ;
	    }
	}
	break ;
      default:
	ERR.General(cname,fname,"Unknown Sink Type\n") ;
      } 
}
Exemple #6
0
/*!
  Calculate zero momentum nucleon two point functions
  for non-degenerate quarks.
*/
void Nuc2pt::calcNucleon(QPropW& upquark, QPropW& downquark){
  char *cname = "Nuc2pt" ;
  char *fname = "calcNucleon(QPropW&, QPropW&)" ;

  strcpy(mom,"0 0 0");

  if(upquark.DoHalfFermion())
    HalfFerm=1;

  srcdesc[0]=srcdesc[1]=srcdesc[2]=srcdesc[3]=-1 ;
  srcdesc[4]=srcdesc[5]=-1 ; // TIZB
  switch (downquark.SrcType())
    {
    case WALL:
      srcdesc[0] = downquark.SourceTime() ;
      source="WALL" ;
      break ;
    case BOX:
      srcdesc[0] = downquark.BoxSrcStart() ; 
      srcdesc[1] = downquark.BoxSrcEnd() ;
      srcdesc[2] = downquark.SourceTime() ;
      if( downquark. BoxSrcUseXYZOffset() ){ // use QPropWArg.{x,y,z} as offset
	srcdesc[3] = downquark.PointSrcX() ; 
	srcdesc[4] = downquark.PointSrcX() ; 
	srcdesc[5] = downquark.PointSrcX() ; 
      }
      source="BOX" ;
      break ;
    case POINT:
      srcdesc[0] = downquark.PointSrcX() ; 
      srcdesc[1] = downquark.PointSrcY() ;
      srcdesc[2] = downquark.PointSrcZ() ;
      srcdesc[3] = downquark.SourceTime() ;
      source = "POINT" ;
      break ;
    case GAUSS_GAUGE_INV:
      srcdesc[0] = downquark.Gauss_N() ; 
      srcdesc[1] = int(100*downquark.Gauss_W()) ;
      srcdesc[2] = downquark.SourceTime() ;
      source = "GAUSS" ;
      break ;
    default:
      ERR.General(cname,fname,"Bad source type\n") ;
    }

  quark_mass = downquark.Mass() ;
  int tsrc = downquark.SourceTime();

  if(downquark.SrcType() != upquark.SrcType())
    ERR.General(cname,fname,"Up and down source types differ\n") ;
  if(upquark.SourceTime() != downquark.SourceTime())
    ERR.General(cname,fname,"Up and down source times differ\n") ;

  WilsonMatrix Q1;  
  WilsonMatrix Q2;
  
    switch (SnkType)
      {
      case POINT:
        {
          sink="POINT" ;
          Site s ;
          for(s.Begin();s.End();s.nextSite())
            {
              int t = s.physT() ;
              Q1 = upquark[s.Index()] ;
              if(HalfFerm) Q1.PParProjectSink() ;
              Q2 = downquark[s.Index()] ;
              if(HalfFerm) Q2.PParProjectSink() ;
              calc_nuc_(Q1, Q2, Q1, t, tsrc) ;    
            } 
          plus_parity.GlobalSum() ;
          minus_parity.GlobalSum() ;
        }
        break ;
      case WALL:
        {
          sink="WALL" ;

          if(!upquark.GFixedSnk() || !downquark.GFixedSnk())
            ERR.General(cname,fname,"Wall sink needs gauge fixing\n") ;

          for(int t = 0 ; t<plus_parity.TimeSize();t++)
            {
              Q1 =  upquark.WallSinkProp(t) ;
              if(HalfFerm) Q1.PParProjectSink() ;
              Q2 =  downquark.WallSinkProp(t) ;
              if(HalfFerm) Q2.PParProjectSink() ;
              calc_nuc_(Q1, Q2, Q1, t, tsrc) ;
            }
        }
        break ;
      default:
        ERR.General(cname,fname,"Unknown Sink Type\n") ;
      } 
}
Exemple #7
0
/*! 
  Computes
  \f[
   Trace(seqQ \, 
     \gamma_{\mu_1} \, \gamma_{\mu_2} \, \gamma_{\mu_3}\, 
     e^{-i mom . x}\, Quark)
  \f]
  where \f$\mu\f$ is the member int gamma and ThreeMom mom is
  the momentum injected at the operator. 
**/
void Nuc3ptCons::InsertOp(CorrFunc* tmp,QPropW& seqQ, QPropW& Quark, int Nmom, ThreeMom* momo)
{
  char *fname = "InsertOp()";

  VRB.Func(cname, fname);

  WilsonMatrix v0, v1, v0_next, v1_next;
  WilsonMatrix temp_v0D, temp_v0D_next;
  WilsonMatrix temp_v0_1pD, temp_v0_1mD_next;
  WilsonMatrix temp_v1_u;
  WilsonMatrix temp_v1_next_u;


  int shift_t=GJP.TnodeCoor()*GJP.TnodeSites();
  int vol= (GJP.VolNodeSites()/GJP.TnodeSites());

  int dir = G[G.N()-1];


  const int LORENTZs(4); 
  int lcl_sites[LORENTZs]; 
  lcl_sites[0] = GJP.XnodeSites();
  lcl_sites[1] = GJP.YnodeSites();
  lcl_sites[2] = GJP.ZnodeSites();
  lcl_sites[3] = GJP.TnodeSites();

  int lcl_node[LORENTZs];
  lcl_node[0] = GJP.XnodeCoor();
  lcl_node[1] = GJP.YnodeCoor();
  lcl_node[2] = GJP.ZnodeCoor();
  lcl_node[3] = GJP.TnodeCoor();

  int lcl2glb_offset[LORENTZs];
  for (int i = 0; i < LORENTZs; ++i) 
    lcl2glb_offset[i] = lcl_sites[i] * lcl_node[i];

 
  Lattice& lat = seqQ.AlgLattice();
  Matrix *gauge_field = lat.GaugeField();  

  int ls_glb = GJP.SnodeSites() * GJP.Snodes();
  int ls_ini = 0;
  int ls_end = ls_glb;
  if(GJP.Snodes()==2) {
    ls_ini = GJP.SnodeCoor() * GJP.SnodeSites();
    ls_end = ( GJP.SnodeCoor() + 1 ) * GJP.SnodeSites();
  }

  char dummy[50];
  Site site;

  for(int s=ls_ini;s<ls_end;s++){ 
    //for(int s=0;s<ls_glb;s++){ 
    Quark.RestoreQPropLs(dummy, s);
    if(GJP.Snodes()==2) {
    seqQ.RestoreQPropLs(dummy, ls_end-1-s+ls_ini);
    } else {
    seqQ.RestoreQPropLs(dummy, ls_end-1-s);
    }
    //seqQ.RestoreQPropLs(dummy, ls_glb-1-s);

    // This operations are included in QPropWSeqProtU(D)Src.
    // When we restore 5d prop the operations are nessesary.
    //Multiply by gamma5 and take the dagger to make it in to quark.
    for (site.Begin();site.End();site.nextSite()) {
      seqQ[site.Index()].gl(-5);
      seqQ[site.Index()].hconj();
    }


    int lcl[LORENTZs];
    int lcl_next[LORENTZs]; // Next site along propagation direction


    VRB.Clock(cname,fname,"RO\n");
    for(lcl[3]=0; lcl[3]<=GJP.TnodeSites()-1; lcl[3]++) {
    int t=lcl[3]+shift_t;

    for(lcl[0]=0; lcl[0]<=GJP.XnodeSites()-1; lcl[0]++) 
    for(lcl[1]=0; lcl[1]<=GJP.YnodeSites()-1; lcl[1]++) 
    for(lcl[2]=0; lcl[2]<=GJP.ZnodeSites()-1; lcl[2]++) {

      Float coeff = 1.0;
      if( G.N() == 2 ) {
      coeff = -1.0;
      if(GJP.Snodes()==2) {
	if(GJP.SnodeCoor()==1) coeff = -coeff;
      } else {
	if( s > ls_glb/2 - 1 ) coeff = -coeff;
      }
      }

      int lcl_offset = siteOffset(lcl,lcl_sites);

      // coordinates and offset for lcl_next
      for (int i  = 0; i < LORENTZs; i++ ) 
	lcl_next[i] = ( (i == dir) ? (lcl[i]+1)%lcl_sites[i]
			  : lcl[i] );

      int lcl_next_offset = siteOffset(lcl_next,lcl_sites);

      // U_mu(x) where mu = dir
      Matrix * link = gauge_field + siteOffset(lcl,lcl_sites) * 4 + dir ;



      // S_F(x, s)
      v0=Quark[lcl_offset];
      // S_F^+(x, ls_glb-1-s)
      v1=seqQ[lcl_offset];


      // v0_next = S_F(x+dir, s)
      // v1_next = S_F^+(x+dir, ls_glb-1-s)
      if ((lcl[dir]+1) == lcl_sites[dir]) {
	getPlusData( (IFloat *)&v0_next,
		     (IFloat *)(&Quark[lcl_next_offset]), sizeof(WilsonMatrix)/sizeof(Float),
		     dir) ;
	getPlusData( (IFloat *)&v1_next,
		     (IFloat *)(&seqQ[lcl_next_offset]), sizeof(WilsonMatrix)/sizeof(Float), 
		     dir) ;
	
	// fix boundary condition
	switch( dir ) {
	case 0:
	  if (GJP.XnodeBc()==BND_CND_APRD) coeff = -coeff ;
	  break;
	case 1:
	  if (GJP.YnodeBc()==BND_CND_APRD) coeff = -coeff ;
	  break;
	case 2:
	  if (GJP.ZnodeBc()==BND_CND_APRD) coeff = -coeff ;
	  break;
	case 3:
	  if (GJP.TnodeBc()==BND_CND_APRD) coeff = -coeff ;
	  break;
	} // end switch

      } else {
	v0_next = Quark[lcl_next_offset] ;
	v1_next = seqQ[lcl_next_offset] ;
      }

      // Gamma^{dir} S_F(x, s)
      temp_v0D = v0; temp_v0D.gl(dir);
      // Gamma^{dir} S_F(x+dir, s)
      temp_v0D_next = v0_next; temp_v0D_next.gl(dir);

      // ( 1 + Gamma^{dir} ) S_F(x, s)
      temp_v0_1pD = v0 + temp_v0D;
      // ( 1 - Gamma^{dir} ) S_F(x+dir, s)
      temp_v0_1mD_next = v0_next - temp_v0D_next;

      // S_F^+(x, ls_glb-1-s) U
      temp_v1_u.UMultSource(*link, v1);

      // S_F^+(x+dir, ls_glb-1-s) U^+
      temp_v1_next_u.UdagMultSource(*link, v1_next);

      Complex cc(0);
      //-Tr( ( 1 - Gamma^{dir} ) S_F(x+dir, s) S_F^+(x, ls_glb-1-s) U )
      cc-=coeff*( Trace( temp_v0_1mD_next, temp_v1_u ) );
      //+Tr( ( 1 + Gamma^{dir} ) S_F(x, s) S_F^+(x+dir, ls_glb-1-s) U^+ )
      cc+=coeff*( Trace( temp_v0_1pD, temp_v1_next_u ) );
      Site st(lcl[0],lcl[1],lcl[2],lcl[3]);
      for(int ip=0;ip<Nmom;ip++) {
      Complex cd = cc * momo[ip].Fact(st); // The momentum factor exp(-ipx)
      tmp[ip][t] += cd ;
      } // ip loop
    } // xyz loop

    } // t loop

  } // ls loop

  for(int ip=0;ip<Nmom;ip++) {
    for(int tt=0; tt<=GJP.TnodeSites()-1; tt++) {
      int t=tt+shift_t;
      if(GJP.Snodes()==2) {
	Float rsum, isum;
	rsum = tmp[ip][t].real();
	glb_sum_dir(&rsum, 4);
	isum = tmp[ip][t].imag();
	glb_sum_dir(&isum, 4);
	tmp[ip][t] = Complex( rsum, isum );
      }
      tmp[ip][t]=tmp[ip][t]/2;
    }
  }

}
Exemple #8
0
/*! 
  Computes
  \f[
   \mbox{Trace}(\mbox{seqQ} \, 
     \gamma_{\mu_1} \, \gamma_{\mu_2} \, \gamma_{\mu_3}\, 
     \stackrel{\displaystyle \leftrightarrow}{D}_\nu 
     \stackrel{\displaystyle \leftrightarrow}{D}_\rho ...
     e^{-i mom . x}\, \mbox{Quark})
  \f]
  where \f$\mu\f$ is the member int gamma and ThreeMom mom is
  the momentum injected at the operator.

  The string of derivatives gets broken up in strings of forward
  and backward hops. For each term the quark and anti-quark are sitting
  on different sites and they are connected with the gauge connection U.
  The gauge connection U is calculated using the PathOrdPlus routine
  given the location of the anti-quark (starting point) and a list
  of hops. The Derivative class is used not only  to do the break-up
  of the string of derivatives in strings of hops, but also to 
  compute the locations of the quark and the anti-quark and 
  provide the list of links needed to compute the gauge connection U
  for each term.

  In order to speed up the code first we compute for all sites
  all derivative terms with the derivatives applied on the quark i.e
  the anti-quark is not displaced. 
  These terms are not summed up but they are stored individually in the
  DTerms Terms class. 
  Then I we go again through the all sites and construct the derivatives.
  If for a given term the anti-quark is displaced we just have to communicate
  a single Complex number from that site. The DTerms class handles all that.
  The routine Derivative :: DTermIndx() is the mapping of the derivative
  terms to a particular storage order. The DTerm class does not have
  to know the storage order. Only the Derivative class knows about it.
 
 NOTE: The quark is at the sink of the Quark propagator
        while the anti-quark is at to source of the sequential propagator.
	
**/
void Nuc3ptStru::InsertOp(CorrFunc& tmp,QPropW& seqQ, QPropW& Quark)
{
  char *fname = "InsertOp()";

  VRB.Func(cname, fname);
  
  if(seqQ.GFixedSnk() || Quark.GFixedSnk())
    ERR.General(cname,fname,"Gauge Fixed sinks!\n") ;

  Lattice& lat=seqQ.AlgLattice() ; // The lattice

#ifdef DEBUG  
printf("%s:: NDTerms= %i\n",cname,D.NDTerms());
#endif

  DTerms Terms(D.NDTerms()); // The derivative terms
  Matrix U ;
  WilsonMatrix aQ ; // the anti-quark
  WilsonMatrix  Q ; // quark
  WilsonMatrix aQU ; // anti-quark times Gauge path
  WilsonMatrix buff ; // Buffer needed for communication 
  int aq_vec[4]; // Anti-quark location
  int q_vec[4] ; // quark location
  int *dirs = new int[D.N()];
  if(dirs == 0) ERR.Pointer(cname, fname, "dirs");

  Site s ;
  //first compute all derivatives terms on quarks
  for(s.Begin();s.End();s.nextSite()) // Loop over sites
    {
      aQ=seqQ[s.Index()] ;
      // Apply the gamma matrices on the sequential  propagator
      // We multiply the source indices of the sequential propagator
      // which are the anti-quark
      for(int mu(0);mu<G.N();mu++)
	aQ.gr(G[mu]) ; // Multiply by gamma_mu 

      // Loop over all derivative terms on the Quark
      for(D.Start();D.NotEnd();D.NextQuark()) 
	{
	  // Calculate the endpoints of the shift
	  D.CalcEndPoints(aq_vec,q_vec,s);
	  // The sink indices of the quark propagator are the quark
	  Q=Quark.GetMatrix(q_vec,buff) ;
	  
	 
	  D.CalcListOfLinks(dirs);

#ifdef DEBUG
printf("\n%s:: dirs ",cname);
for(int i(0);i<D.N();i++) printf("%i ",dirs[i]);
printf(" aq_vec: ");
for(int i(0);i<4;i++) printf("%i ",aq_vec[i]);
printf(" q_vec: ") ; 
for(int i(0);i<4;i++) printf("%i ",q_vec[i]);
#endif

	  // Start from the anti-quark and move along the path described
	  // by the list of dirs multiplying all the encountered links
	  // at the end of the day you should be at the position of the quark
          if(D.N()>1)  
	    {
	      U.ZeroMatrix();
	      lat.PathOrdProdPlus(U,aq_vec,dirs,D.N()) ;
	      //lat.PathOrdProd(U,aq_vec,dirs,D.N()) ;
	    }
	  else //if D.N()==1 PathOrdPlus does not work
	    {
	      int abs_dir = dirs[0]&3; //abs_dir is {0,1,2,3}
	      if(abs_dir == dirs[0]) // dir is forward
		U = *(lat.GetBufferedLink(aq_vec, abs_dir));
	      else // dir is backward. q_vec is now the site where the link is
		U.Dagger(*(lat.GetBufferedLink(q_vec, abs_dir)));
	    }

#ifdef DEBUG
Complex cboo(U.Tr()) ; 
printf("  TrU= (%g %g)\n",cboo.real(),cboo.imag());       
#endif

	  //Now that the gauge connection is constructed multiply it on
	  //the quark i.e the source indices of the anti-quark propagator
	  aQU.UMultSource(U,aQ) ;

	  Terms(D.DTermIndx(),s.Index()) = Trace(aQU,Q) ;

#ifdef DEBUG
printf("   (anti-Q, Q) aQU = (%6.3f %6.3f), (%6.3f %6.3f) (%6.3f %6.3f)\n",
       aQ.Trace().real(),aQ.Trace().imag(),
       Q.Trace().real(),Q.Trace().imag(),
       aQU.Trace().real(),aQU.Trace().imag());
printf("%s:: DTermIndx(): %i site: %i Value: ( %6.3f %6.3f ) \n",
       cname,D.DTermIndx(),s.Index(),
       Terms(D.DTermIndx(),s.Index()).real(), 
       Terms(D.DTermIndx(),s.Index()).imag());
#endif


	}
    }

  Complex tt ;
  // Loop over sites and construct the operator
  for(s.Begin();s.End();s.nextSite()) 
    {
      int t(s.physT()) ;
      for(D.Start();D.NotEnd();D.Next()) // Loop over all derivative terms
	{
	  //Calculate the endpoints of the shift
	  //aq_vec : anti quark location
	  // q_vec :      quark location
	  D.CalcEndPoints(aq_vec,q_vec,s);
	  Complex cc(Terms.GetTerm(D.DTermIndx(),aq_vec,tt)) ;

	  //Finaly the momentum factors
	  cc *= mom.Fact(s) ; // The momentum factor exp(-ipx)	
	  cc *= D.Fact()    ; /* The sign and the normalization factor 
				 for the current derivative term         */

	  tmp[t] += cc ;

#ifdef DEBUG
printf("%s:: DTermIndx(): %i site: %i Fact: %9.6f Value: ( %6.3f %6.3f ) \n",
       cname, D.DTermIndx(),s.Index(),D.Fact(),cc.real(),cc.imag());
#endif
	
	}
    }
  delete [] dirs ;
}