示例#1
0
/* fermion contribution to the action */
double fermion_action() {
register int i;
register site *s;
register complex cc;
double sum;
    sum=0.0;
    FOREVENSITES(i,s){
	/* phi is defined on even sites only */
        cc = su3_dot( &(s->phi1), &(s->xxx1) );
        sum += (double)cc.real;
        cc = su3_dot( &(s->phi2), &(s->xxx2) );
        sum += (double)cc.real;
    }
示例#2
0
// -----------------------------------------------------------------
// Modified to return total number of iterations
int f_meas_imp(field_offset chi_off, field_offset psi_off, Real mass) {
  register int i;
  register site *s;
  int jpbp_reps, tot_iters = 0, miters, npbp_reps = 1;
  Real r_pbp_even, i_pbp_even, r_pbp_odd, i_pbp_odd, r_ferm_action;
  double rfaction;
  complex tc;
  double_complex pbp_e, pbp_o;

#ifdef NPBP_REPS
  double pbp_pbp;
  npbp_reps = NPBP_REPS;    // Number of stochastic estimations
#endif

  for (jpbp_reps = 0; jpbp_reps < npbp_reps; jpbp_reps++) {
    rfaction = 0;
    pbp_e = dcmplx(0, 0);
    pbp_o = dcmplx(0, 0);

    // Make random source and do inversion
    // Generate (one-mass) g_rand; chi_off = M g_rand
    grsource_imp(chi_off, mass, EVENANDODD);
    // chi_off = M g_rand (still)
    // psi_off = M^{-1} g_rand
    clear_latvec(psi_off, EVENANDODD);
    miters = mat_invert_uml(F_OFFSET(g_rand), psi_off, chi_off, mass);
    tot_iters += miters;

    // Fermion action = chi.psi
    // pbp on even sites = g_rand.psi
    FOREVENSITES(i, s) {
      tc = su3_dot((vector *)F_PT(s, chi_off),
                   (vector *)F_PT(s, psi_off));
      rfaction += tc.real;
      tc = su3_dot(&(s->g_rand), (vector *)F_PT(s, psi_off));
      CSUM(pbp_e, tc);
    }

    // pbp on odd sites
    FORODDSITES(i, s) {
      tc = su3_dot(&(s->g_rand), (vector *)F_PT(s, psi_off));
      CSUM(pbp_o, tc);
    }
示例#3
0
文件: mu.c 项目: erinaldi/milc_qcd
void pbp(field_offset xxx_off, Real mass){
  site *st;
  int i;
  double_complex cc;
  complex cc1;

  /*FORALLSITES(i,st){
    for(j=0;j<3;j++)
      node0_printf("grand %e %e; xxx1 %e %e\n", lattice[i].g_rand.c[j].real,
		   lattice[i].g_rand.c[j].imag, lattice[i].xxx1.c[j].real,
		   lattice[i].xxx1.c[j].imag);
    
		   }*/
  cc.real =0.0; cc.imag=0.0;

  FORALLSITES(i,st){
    cc1 = su3_dot( &(st->g_rand), (su3_vector *)F_PT(st,xxx_off) );
    cc.real += cc1.real; cc.imag += cc1.imag;
    //node0_printf("cc %e %e\n", cc.real, cc.imag);
  }
示例#4
0
void
measure_chirality_qdp(QDP_ColorVector *src, double *chirality,
		      QDP_Subset subset)
{
  complex tmp;
  double cc;
  int i, parity;
  site *s;

  if(subset==QDP_even) parity = EVEN;
  else if(subset==QDP_odd) parity = ODD;
  else parity = EVENANDODD;

  set_site_from_V(F_OFFSET(tempvec[3]), src,EVENANDODD);
  mult_spin_pseudoscalar(F_OFFSET(tempvec[3]),F_OFFSET(ttt));

  cc = 0.0;
  FORSOMEPARITY(i,s,parity) {
    tmp = su3_dot( &(s->tempvec[3]), &(s->ttt) );
    cc += tmp.real;  /* chirality is real since Gamma_5 is hermitian */
  }
示例#5
0
int nl_spectrum( Real vmass, field_offset temp1, field_offset temp2 ) { 
  /* return the C.G. iteration number */
  double *piprop,*pi2prop,*rhoprop,*rho2prop,*barprop;
  double *nlpiprop,*nlpi2prop,*ckpiprop,*ckpi2prop;
  double *delprop,*ckbarprop;
  Real vmass_x2;
  site* s;
  register complex cc;
  Real finalrsq;
  register int i,x,y,z,t,icol,cgn;
  register int t_source,t_off;
  int dir,isrc;

  msg_tag *mtag[16];

  piprop = (double *)malloc( nt*sizeof(double) );
  pi2prop = (double *)malloc( nt*sizeof(double) );
  rhoprop = (double *)malloc( nt*sizeof(double) );
  rho2prop = (double *)malloc( nt*sizeof(double) );
  barprop = (double *)malloc( nt*sizeof(double) );
  nlpiprop = (double *)malloc( nt*sizeof(double) );
  nlpi2prop = (double *)malloc( nt*sizeof(double) );
  ckpiprop = (double *)malloc( nt*sizeof(double) );
  ckpi2prop = (double *)malloc( nt*sizeof(double) );
  delprop = (double *)malloc( nt*sizeof(double) );
  ckbarprop = (double *)malloc( nt*sizeof(double) );

  for( t=0; t<nt; t++ ){
    piprop[t]=0.0; pi2prop[t]=0.0; rhoprop[t]=0.0; rho2prop[t]=0.0;
    nlpiprop[t]=0.0; nlpi2prop[t]=0.0;
    ckpiprop[t]=0.0; ckpi2prop[t]=0.0;
    barprop[t]=0.0; delprop[t]=0.0; ckbarprop[t]=0.0;
  }

  vmass_x2 = 2.*vmass;
  cgn=0;

  /* Fix TUP Coulomb gauge - gauge links only*/
  rephase( OFF );
  gaugefix(TUP,(Real)1.8,500,(Real)GAUGE_FIX_TOL);
  rephase( ON );
#ifdef FN
  invalidate_all_ferm_links(&fn_links);
#endif

  /* Unlike spectrum.c, here we calculate only with wall sources */
  for(t_source=source_start, isrc=0; t_source<2*nt && isrc < n_sources;
        ++isrc, t_source += source_inc ) {
      
      /* Only work for even source slices */
      if( t_source%2 != 0 ){
	printf("DUMMY:  Use even time slices for nl_spectrum()\n");
	terminate(0);
      }

      /* Compute propagator from even wall sites */
      /* Sources are normalized to 1/8 to make them comparable to */
      /* propagators from a wall with ones on the cube origin. */
      /* Put result in propmat */
      
      for(icol=0; icol<3; icol++) {
	  
	  /* initialize temp1 and temp2 */
	  clear_latvec( temp1, EVEN);
	  clear_latvec( temp2, EVEN);
	  
	  for(x=0;x<nx;x++)for(y=0;y<ny;y++)for(z=0;z<nz;z++) {
	      if((x+y+z) % 2 == 0) {
		  if( node_number(x,y,z,t_source) != mynode() )continue;
		  i=node_index(x,y,z,t_source);
		  ((su3_vector *)(F_PT(&lattice[i],temp1)))->c[icol].real = 
		    -0.25;
		}
	    }
	  
	  /* do a C.G. */
	  load_ferm_links(&fn_links);
	  cgn += congrad(niter,rsqprop,EVEN,&finalrsq, &fn_links);
	  /* Multiply by -Madjoint */
	  dslash_site( temp2, temp2, ODD, &fn_links);
	  scalar_mult_latvec( temp2, -vmass_x2, temp2, EVEN);
	  
	  /* fill the hadron matrix */
	  copy_latvec( temp2, F_OFFSET(propmat[icol]), EVENANDODD);
	} /* end loop on icol */
      
      
      /* Compute propagator from odd wall sites */
      /* Put result in propmat2 */
      
      for(icol=0; icol<3; icol++) {
	  
	  /* initialize temp1 and temp2 */
	  clear_latvec( temp1, ODD);
	  clear_latvec( temp2, ODD);
	  for(x=0;x<nx;x++)for(y=0;y<ny;y++)for(z=0;z<nz;z++) {
	      if((x+y+z) % 2 == 1) {
		  if( node_number(x,y,z,t_source) != mynode() )continue;
		  i=node_index(x,y,z,t_source);
		  ((su3_vector *)(F_PT(&lattice[i],temp1)))->c[icol].real = 
		    -0.25;
		}
	    }
	  
	  /* do a C.G. */
	  load_ferm_links(&fn_links);
	  cgn += congrad(niter,rsqprop,ODD,&finalrsq,&fn_links);
	  /* Multiply by -Madjoint */
	  dslash_site( temp2, temp2, EVEN, &fn_links);
	  scalar_mult_latvec( temp2, -vmass_x2, temp2, ODD);
	  
	  /* fill the hadron matrix */
	  copy_latvec( temp2, F_OFFSET(propmat2[icol]), EVENANDODD);
	} /* end loop on icol */
      
      /* cgn now gives the sum for both inversions */
      
      
      /* measure the meson propagator for the E wall source */
      for(t=0; t<nt; t++) {
	  /* define the time value offset t from t_source */
	  t_off = (t+t_source)%nt;
	  
	  for(x=0;x<nx;x++)for(y=0;y<ny;y++)for(z=0;z<nz;z++)
	    for(icol=0;icol<3;icol++) {
		if( node_number(x,y,z,t_off) != mynode() )continue;
		i=node_index(x,y,z,t_off);
		cc = su3_dot( &lattice[i].propmat[icol],
			     &lattice[i].propmat[icol] );
		
		piprop[t] += cc.real;
		/* (rhoprop and rho2prop are not generated by this source) */
		
		if( (x+y+z)%2==0)pi2prop[t] += cc.real;
		else	     pi2prop[t] -= cc.real;
		
	      }
	  
	} /* nt-loop */
      
      /* measure the baryon propagator for the E wall source */
      for(t=0; t<nt; t++) {
	  /* define the time value offset t from t_source */
	  t_off = (t+t_source)%nt;
	  
	  for(x=0;x<nx;x+=2)for(y=0;y<ny;y+=2)for(z=0;z<nz;z+=2) {
	      if( node_number(x,y,z,t_off) != mynode() )continue;
	      i=node_index(x,y,z,t_off);
	      cc = det_su3( (su3_matrix *)(lattice[i].propmat) );
	      barprop[t] += cc.real;
	  }
	  
	  /* must get sign right.  This looks to see if we have
	     wrapped around the lattice.  "t" is the distance
	     from the source to the measurement, so we are
	     trying to find out if t_source+t is greater than
	     or equal to nt. */
	  if( (((t+t_source)/nt-t_source/nt)%2) == 1 )barprop[t] *= -1.0;
	  /* change sign because antiperiodic b.c.  sink point
	     should really be in a copy of the lattice */
	} /* nt-loop */
      
      
      /* Measure nonlocal (and some local for checking) propagators    */
      /* These propagators include the delta and some nonlocal mesons  */
      /* The method for the delta is described in M.F.L. Golterman and */
      /* J. Smit, Nucl. Phys. B 255, 328 (1985)                        */
      /* Equation (6.3) defines the sink operator for the delta        */
      /* The method for the mesons is described in M.F.L. Golterman    */
      /* Nucl. Phys. B 273, 663 (1986)                                 */
      /* The treatment of the source wall is described in Gupta,       */
      /* Guralnik, Kilcup, and Sharpe, (GGKS) NSF-ITP-90-172 (1990)    */
      /* To get the delta propagator, we take the "q" propagator       */
      /* matrices for each of the wall colors and antisymmetrize over  */
      /* wall color as well as s                    */
      
      /* First construct the "q" and "o" propagators                   */
      /* Put q = E + O in propmat and o = E - O in propmat2 */
      
      FORALLSITES(i,s) {
	  for(icol=0; icol<3; icol++) {
	      add_su3_vector (&(s->propmat[icol]), &(s->propmat2[icol]), 
			      (su3_vector *)(s->tempmat1.e[icol]) );
	      sub_su3_vector (&(s->propmat[icol]), &(s->propmat2[icol]), 
			      &(s->propmat2[icol]) );
	      su3vec_copy( (su3_vector *)(s->tempmat1.e[icol]),
		&(s->propmat[icol]) );
	    }
	}
      
      
      
      /* Next gather the propagators in preparation for calculating   */
      /* shifted propagators Dq and Do                                */
      
      FORALLUPDIRBUT(TUP,dir) {
	  /* Start bringing "q" = propmat from forward sites    */
	  
	  mtag[dir] = start_gather_site(F_OFFSET(propmat[0]), 
		   sizeof(su3_matrix), dir, EVENANDODD, gen_pt[dir]);
	  
	  /* Start bringing "q" from backward neighbors       */
	  
	  mtag[dir+4] = start_gather_site(F_OFFSET(propmat[0]), 
		   sizeof(su3_matrix), OPP_DIR(dir), EVENANDODD,
		   gen_pt[dir+4]);
	  wait_gather(mtag[dir]);
	  wait_gather(mtag[dir+4]);
	  
	  /* Start bringing "o" = propmat2 from forward sites   */
	  
	  mtag[8+dir] = start_gather_site(F_OFFSET(propmat2[0]), 
		   sizeof(su3_matrix), dir, EVENANDODD, gen_pt[8+dir]);
	  
	      /* Start bringing "o" from backward neighbors       */
	  
	  mtag[8+dir+4] = start_gather_site(F_OFFSET(propmat2[0]), 
		    sizeof(su3_matrix), OPP_DIR(dir), EVENANDODD,
		    gen_pt[8+dir+4]);
	  wait_gather(mtag[8+dir]);
	  wait_gather(mtag[8+dir+4]);
	  
	}
      
      
      /* Calculate and dump delta propagator */
      for(t=0; t<nt; t++) {
	  /* define the time value offset t from t_source */
	  t_off = (t+t_source)%nt;
	  
	  /* Calculate contribution for each permutation of source color */
	  delta_prop (0,1,2, 1, t_off, &delprop[t]);
	  delta_prop (1,2,0, 1, t_off, &delprop[t]);
	  delta_prop (2,0,1, 1, t_off, &delprop[t]);
	  delta_prop (1,0,2,-1, t_off, &delprop[t]);
	  delta_prop (0,2,1,-1, t_off, &delprop[t]);
	  delta_prop (2,1,0,-1, t_off, &delprop[t]);
	  
	  if( (((t+t_source)/nt-t_source/nt)%2) == 1 ) delprop[t] *= -1;
	} /* nt-loop */
      
      /* Calculate the "q" source nucleon as a check */
      
      /* Calculate and dump nucleon check propagator */
      for(t=0; t<nt; t++) {
	  /* define the time value offset t from t_source */
	  t_off = (t+t_source)%nt;
	  
	  for(x=0;x<nx;x+=2)for(y=0;y<ny;y+=2)for(z=0;z<nz;z+=2) {
	      if( node_number(x,y,z,t_off) != mynode() )continue;
	      i=node_index(x,y,z,t_off);
	      /* The q propagator is in propmat */
	      cc = det_su3( (su3_matrix *)(lattice[i].propmat) );
	      ckbarprop[t] += cc.real;
	    }
	  
	  if( (((t+t_source)/nt-t_source/nt)%2) == 1 )ckbarprop[t]*= -1.0;
	  /* change sign because antiperiodic b.c.  sink point
	     should really be in a copy of the lattice */
	} /* nt-loop */
      
      /* Calculate nonlocal meson propagators and local check */
      for(t=0; t<nt; t++) {
	  /* Calculate two nonlocal pion propagators */
	  /* These are pi_1 and pi_1 tilde of Gupta et al */
	  /* Also calculate two local propagators as a check */
	  
	  /* define the time value offset t from t_source */
	  t_off = (t+t_source)%nt;
	  
	  nl_meson_prop(t_off,&nlpiprop[t],&nlpi2prop[t],&ckpiprop[t],
	     &ckpi2prop[t]);
	  
	} /* nt-loop */
      
      /* Clean up gathers */
      FORALLUPDIRBUT(TUP,dir) {
	  cleanup_gather(mtag[dir]);
	  cleanup_gather(mtag[dir+4]);
	  cleanup_gather(mtag[8+dir]);
	  cleanup_gather(mtag[8+dir+4]);
	}
示例#6
0
void nl_meson_prop (int t,double *nlpiprop,double *nlpi2prop,
		    double *ckpiprop,double *ckpi2prop,
		    field_offset temp1, field_offset temp2)
     /* Calculates non-local pion propagator pi_3 and pi_3 tilde */
     /* and local pion propagators for a check */
     /* temp1 and temp2 are scratch space */
{
  int x,y,z,i,icol;
  int coord;
  register su3_matrix *tmp1, *tmp2;

  complex cc;
  /* Sum over all x,y z              */
  for(x=0;x<nx;x++)for(y=0;y<ny;y++)for(z=0;z<nz;z++) {
    if( node_number(x,y,z,t) != mynode() )continue;
    i=node_index(x,y,z,t);
    
    coord = get_coord(i,NL_PI_DIR);
    if(coord%2 == 0)accum_nl_meson_prop(i,NL_PI_DIR,temp1,temp2);
    
    for(icol=0;icol<3;icol++) {
      
      /* Calculate non-local propagator only on even coordinate */
      
      if(coord%2 ==0) {
	/* propmat contains "q" and temp1 contains "Dq" */
	/* q^adj D q  */
	tmp1 = (su3_matrix *)F_PT(&lattice[i],temp1);
	cc = su3_dot( &lattice[i].propmat[icol],
		      (su3_vector *)(tmp1->e[icol]) );
	*nlpiprop += cc.real;
	
	/* propmat2 contains "o" and temp2 contains "Do" */
	/* q^adj D q - o^adj D o  */
	tmp2 = (su3_matrix *)F_PT(&lattice[i],temp2);
	cc = su3_dot( &(lattice[i].propmat2[icol]),
		      (su3_vector *)(tmp2->e[icol]) );
	*nlpiprop -= cc.real;
	
	/* o^adj D q          */
	cc = su3_dot( &lattice[i].propmat2[icol],
		      (su3_vector *)(tmp1->e[icol]) );
	
	if((x+y+z)%2 == 0)*nlpi2prop += cc.real;
	else              *nlpi2prop -= cc.real;
	
	/* o^adj D q - q^adj D o          */
	cc = su3_dot( &(lattice[i].propmat[icol]),
		      (su3_vector *)(tmp2 ->e[icol]) );
	
	if((x+y+z)%2 == 0)*nlpi2prop -= cc.real;
	else              *nlpi2prop += cc.real;
	
      }
      
      /* Calculate local check for all z */
      
      /* q^adj q  */
      cc = su3_dot( &lattice[i].propmat[icol],
		    &lattice[i].propmat[icol] );
      *ckpiprop += cc.real;
      
      /* q^adj q + o^adj o          */
      cc = su3_dot( &lattice[i].propmat2[icol],
		    &lattice[i].propmat2[icol] );
      *ckpiprop += cc.real;
      
      
      /* q^adj o  */
      cc = su3_dot( &lattice[i].propmat[icol],
		    &lattice[i].propmat2[icol] );
      
      if( (x+y+z)%2==0)*ckpi2prop += cc.real;
      else	           *ckpi2prop -= cc.real;
      
    }
  }
}
示例#7
0
void 
f_meas_current_diff( int nrand, int nwrite, int thinning, 
		     quark_invert_control *qic_precise, quark_invert_control *qic_sloppy,
		     Real mass, int naik_term_epsilon_index, fermion_links_t *fl, 
		     char *filename){
  
  char myname[] = "f_meas_current_diff";

  imp_ferm_links_t* fn = get_fm_links(fl)[naik_term_epsilon_index];

  /* local variables for accumulators */
  int i, jrand, mu;

  /* Offset for staggered phases in the current definition */
  int r_offset[4] = {0, 0, 0, 0};

  /* Current spin-taste list */
  int *spin_taste = get_spin_taste();

  su3_vector *gr0 = create_v_field();
  su3_vector *gr = create_v_field();
  su3_vector *gr_mu = create_v_field();
  su3_vector *M_inv_gr = create_v_field();
  Real *j_mu = create_r_array_field(NMU);
  int ex, ey, ez, et, d = thinning;

  /* Open file for writing */
  QIO_Writer *outfile = open_vector_current_file(filename);
  if(outfile == NULL){
    node0_printf("%s: Failed to open %s\n", myname, filename);
    exit(1);
  }
  
  double wtime = 0.;
  /* Loop over random sources */
  for(jrand = 0; jrand < nrand; jrand++){

	/* Make random source, and do inversion */
#ifndef Z2RSOURCE
    grsource_plain_field( gr0, EVENANDODD );
#else
    z2rsource_plain_field( gr0, EVENANDODD );
#endif
    
    /* Iterate over 8 even displacements within a d^4 cube */
    for(ex=0;ex<d;ex++)for(ey=0;ey<d;ey++)for(ez=0;ez<d;ez++)for(et=0;et<d;et++)if((ex+ey+ez+et)%2==0){

	      //r_offset[0] = ex; r_offset[1] = ey; r_offset[2] = ez; r_offset[3] = et;

	    /* Apply source thinning */
	    copy_v_field(gr, gr0);
	    thin_source( gr, d, ex, ey, ez, et );
	    
	    /* First, sloppy solution */
	    /* M_inv_gr = M^{-1} gr */
	    node0_printf("Solving sloppily for %d %d %d %d\n", ex, ey, ez, et);
	    mat_invert_uml_field( gr, M_inv_gr, qic_sloppy, mass, fn );
	    
	    /* Loop over directions for the current */
	    for(mu = 0; mu < NMU; mu++){
	      
	      /* Apply the appropriate spin_taste operator for
		 a nearly conserved current.  */
	      spin_taste_op_fn(fn, spin_taste[mu], r_offset, gr_mu, M_inv_gr);
	      spin_taste_op_fn(fn, spin_taste_index("pion05"), r_offset, gr_mu, gr_mu);
	      
	      /* J_mu = imag[gr.M_inv_gr] */
	      /* SUBTRACT the sloppy result */
	      FORALLFIELDSITES(i){
		complex cc = su3_dot( gr+i, gr_mu+i );
		j_mu[NMU*i + mu] -= cc.imag;
	      }
	    } /* mu */
	    
	    /* Next, continue to a "precise" solution from the same source */
	    /* M_inv_gr = M^{-1} gr (same random source for each mass) */
	    node0_printf("Solving precisely for %d %d %d %d\n", ex, ey, ez, et);
	    mat_invert_uml_field( gr, M_inv_gr, qic_precise, mass, fn );
	    
	    /* Loop over directions for the current */
	    for(mu = 0; mu < NMU; mu++){
	      
	      /* Apply the appropriate spin_taste operator for
		 a nearly conserved current.  */
	      spin_taste_op_fn(fn, spin_taste[mu], r_offset, gr_mu, M_inv_gr);
	      spin_taste_op_fn(fn, spin_taste_index("pion05"), r_offset, gr_mu, gr_mu);
	      
	      /* J_mu = imag[gr.M_inv_gr] */
	      /* ADD the precise result, which then gives the difference */
	      FORALLFIELDSITES(i){
		complex cc = su3_dot( gr+i, gr_mu+i );
		j_mu[NMU*i + mu] += cc.imag;
	      }
	    } /* mu */
	    
#if 0      
	    /* DEBUG */
	    FOREVENFIELDSITES(i){
	      printf("%d %d %d %d ",lattice[i].x, lattice[i].y, lattice[i].z, lattice[i].t);
	      for(mu = 0; mu < NMU; mu++)
		printf("%g ",j_mu[NMU*i + mu]);
	      printf("\n");
	    }
#endif
	    
	  } /* ex, ey, ez, et */
    
    /* Write at intervals of nwrite random values */
    if((jrand+1) % nwrite == 0){
      wtime -= dclock();
      average_vector_current(nwrite, j_mu);
      int status = write_vector_current_record(outfile, jrand, nwrite, mass, j_mu);
      clear_r_array_field(j_mu, NMU);
      wtime += dclock();
      if(status != QIO_SUCCESS){
	node0_printf("%s: Failed to write record to %s\n", myname, filename);
      }
    }
  } /* jrand */
示例#8
0
int spectrum_nd( Real mass1, Real mass2, Real tol, ferm_links_t *fn ){
  /* arguments are light and heavy quark masses, return C.G. iteration number */

  int cgn;
  register int i,j,x,y,z,t,t_off;
  register site* s;
  register complex cc;
  register int t_source;
  int color;	/* color for source */
  int src_count; /* number of source time slices used */
  complex **props;	/* arrays of propagators */
  su3_matrix tmat;
  Real finalrsq;
  
  cgn=0; /* number of CG iterations */

  /* allocate arrays to accumulate propagators */
  props = (complex **)malloc(nprops*sizeof(complex *));
  props[0] = (complex *)malloc(nprops*nt*sizeof(complex));
  for(i=1;i<nprops;i++)props[i]=props[i-1]+nt;

  /* set propagators to zero */
  for(cc.real=cc.imag=0.0,i=0;i<nprops;i++)for(j=0;j<nt;j++){
    props[i][j]=cc;
  }

  /* allocate light and heavy quark propagators for each color */
  for( color=0; color<3; color++){
    lightprop[color] = (su3_vector *)malloc( sizeof(su3_vector)*sites_on_node );
    heavyprop[color] = (su3_vector *)malloc( sizeof(su3_vector)*sites_on_node );
  }

  /* loop over "source" time slice */
  for(src_count=0,t_source=source_start; t_source<nt && src_count<n_sources;
    t_source += source_inc,src_count++){
    /* Corner wall source */
    /* Use quark_source for quark source */
    if(this_node==0)printf("spectrum_nd(): source time = %d\n",t_source);

    for(color=0;color<3;color++){
      clear_latvec( F_OFFSET(quark_source), EVENANDODD );
      for(x=0;x<nx;x+=2)for(y=0;y<ny;y+=2)for(z=0;z<nz;z+=2) {
        if( node_number(x,y,z,t_source) != mynode() )continue;
        i=node_index(x,y,z,t_source);
        lattice[i].quark_source.c[color].real = -1.0;
      }

      /* do a C.G. (source in quark_source, result in g_rand) */
      if(t_source%2 == 0) {
         cgn += ks_congrad( F_OFFSET(quark_source), F_OFFSET(g_rand),
			    mass1, niter, nrestart, rsqprop, PRECISION, 
			    EVEN, &finalrsq, fn);
         /* Multiply by -Madjoint */
         dslash_site( F_OFFSET(g_rand), F_OFFSET(quark_prop), ODD, fn);
         scalar_mult_latvec( F_OFFSET(g_rand), -2.0*mass1, F_OFFSET(quark_prop),EVEN);
      }
      else {
        cgn += ks_congrad( F_OFFSET(quark_source), F_OFFSET(g_rand),
			   mass1, niter, nrestart, rsqprop, PRECISION, 
			   ODD, &finalrsq, fn);
          /* Multiply by -Madjoint */
          dslash_site( F_OFFSET(g_rand), F_OFFSET(quark_prop), EVEN, fn);
          scalar_mult_latvec( F_OFFSET(g_rand), -2.0*mass1, F_OFFSET(quark_prop),ODD);
      }
      FORALLSITES(i,s){ lightprop[color][i] = lattice[i].quark_prop; }
scalar_mult_latvec( F_OFFSET(quark_prop), -1.0, F_OFFSET(g_rand), EVENANDODD );
 check_invert( F_OFFSET(g_rand), F_OFFSET(quark_source), mass1, tol, fn);

      /* repeat for heavy quark */
      if(t_source%2 == 0) {
         cgn += ks_congrad( F_OFFSET(quark_source), F_OFFSET(g_rand),
			    mass2, niter, nrestart, rsqprop, PRECISION, 
			    EVEN, &finalrsq, fn);
         /* Multiply by -Madjoint */
         dslash_site( F_OFFSET(g_rand), F_OFFSET(quark_prop), ODD, fn);
         scalar_mult_latvec( F_OFFSET(g_rand), -2.0*mass2, F_OFFSET(quark_prop),EVEN);
      }
      else {
        cgn += ks_congrad( F_OFFSET(quark_source), F_OFFSET(g_rand),
			   mass2, niter, nrestart, rsqprop, PRECISION, 
			   ODD, &finalrsq, fn);
          /* Multiply by -Madjoint */
          dslash_site( F_OFFSET(g_rand), F_OFFSET(quark_prop), EVEN, fn);
          scalar_mult_latvec( F_OFFSET(g_rand), -2.0*mass2, F_OFFSET(quark_prop),ODD);
      }
      FORALLSITES(i,s){ heavyprop[color][i] = lattice[i].quark_prop; }

      /* TEMP: test inversion, */
scalar_mult_latvec( F_OFFSET(quark_prop), -1.0, F_OFFSET(g_rand), EVENANDODD );
 check_invert( F_OFFSET(g_rand), F_OFFSET(quark_source), mass2, tol, fn);
    } /* end color loop*/

    /* add contributions into propagators */
    /* measure the meson propagator */
    for(t=0; t<nt; t++){
        /* define the time value offset t from t_source */
        t_off = (t+t_source)%nt;
        
        for(x=0;x<nx;x++)for(y=0;y<ny;y++)for(z=0;z<nz;z++)
  	for(color=0;color<3;color++) {
  	    if( node_number(x,y,z,t_off) != mynode() )continue;
  	    i=node_index(x,y,z,t_off);

	    /* light-light mesons */
  	    cc = su3_dot( &lightprop[color][i],
  			 &lightprop[color][i] );
  	    
  	    CSUM( props[prop_pion5_ll][t], cc )
  	    
  	    if( (x+y)%2==0)CSUM( props[prop_rhoi0_ll][t], cc )
  	    else CSUB( props[prop_rhoi0_ll][t], cc, props[prop_rhoi0_ll][t] )
  	    if( (y+z)%2==0)CSUM( props[prop_rhoi0_ll][t], cc )
  	    else CSUB( props[prop_rhoi0_ll][t], cc,  props[prop_rhoi0_ll][t] )
  	    if( (z+x)%2==0)CSUM( props[prop_rhoi0_ll][t], cc )
  	    else CSUB( props[prop_rhoi0_ll][t], cc, props[prop_rhoi0_ll][t] )
  	    
  	    if( x%2==0)CSUM( props[prop_rhoi_ll][t], cc )
  	    else CSUB( props[prop_rhoi_ll][t], cc,  props[prop_rhoi_ll][t] )
  	    if( y%2==0)CSUM( props[prop_rhoi_ll][t], cc )
  	    else CSUB( props[prop_rhoi_ll][t], cc, props[prop_rhoi_ll][t] )
  	    if( z%2==0)CSUM( props[prop_rhoi_ll][t], cc )
  	    else CSUB( props[prop_rhoi_ll][t], cc, props[prop_rhoi_ll][t] )
  	    
  	    if( (x+y+z)%2==0)CSUM( props[prop_pion05_ll][t], cc )
  	    else CSUB( props[prop_pion05_ll][t], cc, props[prop_pion05_ll][t] )
  	    
	    /* light-heavy mesons */
  	    cc = su3_dot( &lightprop[color][i],
  			 &heavyprop[color][i] );
  	    
  	    CSUM( props[prop_pion5_lh][t], cc )
  	    
  	    if( (x+y)%2==0)CSUM( props[prop_rhoi0_lh][t], cc )
  	    else CSUB( props[prop_rhoi0_lh][t], cc, props[prop_rhoi0_lh][t] )
  	    if( (y+z)%2==0)CSUM( props[prop_rhoi0_lh][t], cc )
  	    else CSUB( props[prop_rhoi0_lh][t], cc,  props[prop_rhoi0_lh][t] )
  	    if( (z+x)%2==0)CSUM( props[prop_rhoi0_lh][t], cc )
  	    else CSUB( props[prop_rhoi0_lh][t], cc, props[prop_rhoi0_lh][t] )
  	    
  	    if( x%2==0)CSUM( props[prop_rhoi_lh][t], cc )
  	    else CSUB( props[prop_rhoi_lh][t], cc,  props[prop_rhoi_lh][t] )
  	    if( y%2==0)CSUM( props[prop_rhoi_lh][t], cc )
  	    else CSUB( props[prop_rhoi_lh][t], cc, props[prop_rhoi_lh][t] )
  	    if( z%2==0)CSUM( props[prop_rhoi_lh][t], cc )
  	    else CSUB( props[prop_rhoi_lh][t], cc, props[prop_rhoi_lh][t] )
  	    
  	    if( (x+y+z)%2==0)CSUM( props[prop_pion05_lh][t], cc )
  	    else CSUB( props[prop_pion05_lh][t], cc, props[prop_pion05_lh][t] )
  	    
	    /* heavy-heavy mesons */
  	    cc = su3_dot( &heavyprop[color][i],
  			 &heavyprop[color][i] );
  	    
  	    CSUM( props[prop_pion5_hh][t], cc )
  	    
  	    if( (x+y)%2==0)CSUM( props[prop_rhoi0_hh][t], cc )
  	    else CSUB( props[prop_rhoi0_hh][t], cc, props[prop_rhoi0_hh][t] )
  	    if( (y+z)%2==0)CSUM( props[prop_rhoi0_hh][t], cc )
  	    else CSUB( props[prop_rhoi0_hh][t], cc,  props[prop_rhoi0_hh][t] )
  	    if( (z+x)%2==0)CSUM( props[prop_rhoi0_hh][t], cc )
  	    else CSUB( props[prop_rhoi0_hh][t], cc, props[prop_rhoi0_hh][t] )
  	    
  	    if( x%2==0)CSUM( props[prop_rhoi_hh][t], cc )
  	    else CSUB( props[prop_rhoi_hh][t], cc,  props[prop_rhoi_hh][t] )
  	    if( y%2==0)CSUM( props[prop_rhoi_hh][t], cc )
  	    else CSUB( props[prop_rhoi_hh][t], cc, props[prop_rhoi_hh][t] )
  	    if( z%2==0)CSUM( props[prop_rhoi_hh][t], cc )
  	    else CSUB( props[prop_rhoi_hh][t], cc, props[prop_rhoi_hh][t] )
  	    
  	    if( (x+y+z)%2==0)CSUM( props[prop_pion05_hh][t], cc )
  	    else CSUB( props[prop_pion05_hh][t], cc, props[prop_pion05_hh][t] )
  	    
  	  } /* color */
        
      } /* nt-loop */
    
    /* measure the baryon propagator */
    for(t=0; t<nt; t++) {
        /* define the time value offset t from t_source */
        t_off = (t+t_source)%nt;
        
        for(x=0;x<nx;x+=2)for(y=0;y<ny;y+=2)for(z=0;z<nz;z+=2) {
  	  if( node_number(x,y,z,t_off) != mynode() )continue;
  	  i=node_index(x,y,z,t_off);

	  /* three light quarks  */
	  for(color=0;color<3;color++){
	    (tmat.e[0][color]) = lightprop[0][i].c[color];
	    (tmat.e[1][color]) = lightprop[1][i].c[color];
	    (tmat.e[2][color]) = lightprop[2][i].c[color];
	  }
  	  cc = det_su3( &tmat );
  	      
  	  /* must get sign right.  This looks to see if we have
  		wrapped around the lattice.  "t" is the distance
  		from the source to the measurement, so we are
  		trying to find out if t_source+t is greater than
  		or equal to nt.  the "-tsource/nt" is in there
  		so that it will work correctly with tsource=nt.  */
  	  if( (((t+t_source)/nt-t_source/nt)%2) == 0 )
  	     CSUM( props[prop_nuc_lll][t], cc )
  	  else  /* change sign because antiperiodic b.c.  sink point
  		should really be in a copy of the lattice */
  	     CSUB( props[prop_nuc_lll][t], cc, props[prop_nuc_lll][t] )

	  /* two lights and one heavy */
	  for(color=0;color<3;color++){
	    (tmat.e[0][color]) = lightprop[0][i].c[color];
	    (tmat.e[1][color]) = lightprop[1][i].c[color];
	    (tmat.e[2][color]) = heavyprop[2][i].c[color];
	  }
  	  cc = det_su3( &tmat );
  	      
  	  if( (((t+t_source)/nt-t_source/nt)%2) == 0 )
  	     CSUM( props[prop_nuc_llh][t], cc )
  	  else CSUB( props[prop_nuc_llh][t], cc, props[prop_nuc_llh][t] )

	  /* now repeat for hhl baryon */
	  for(color=0;color<3;color++){
	    (tmat.e[0][color]) = lightprop[0][i].c[color];
	    (tmat.e[1][color]) = heavyprop[1][i].c[color];
	    (tmat.e[2][color]) = heavyprop[2][i].c[color];
	  }
  	  cc = det_su3( &tmat );
  	  if( (((t+t_source)/nt-t_source/nt)%2) == 0 )
  	     CSUM( props[prop_nuc_lhh][t], cc )
  	  else  CSUB( props[prop_nuc_lhh][t], cc, props[prop_nuc_lhh][t] )

	  /* and hhh baryon (nonexistent particle!!) */
	  for(color=0;color<3;color++){
	    (tmat.e[0][color]) = heavyprop[0][i].c[color];
	    (tmat.e[1][color]) = heavyprop[1][i].c[color];
	    (tmat.e[2][color]) = heavyprop[2][i].c[color];
	  }
  	  cc = det_su3( &tmat );
  	  if( (((t+t_source)/nt-t_source/nt)%2) == 0 )
  	     CSUM( props[prop_nuc_hhh][t], cc )
  	  else  CSUB( props[prop_nuc_hhh][t], cc, props[prop_nuc_hhh][t] )

        }
      } /* nt-loop */

  } /* end loop on t_source */

  /* Sum propagator arrays over nodes */
  /* print out propagators */
  g_veccomplexsum( props[0], nprops*nt );
  for(i=0;i<nprops;i++)for(j=0;j<nt;j++){
    CDIVREAL(props[i][j],n_sources,props[i][j]);
  }
  if(this_node==0){
  
    /*meson propagators*/
    printf("STARTPROP\n");
    printf("MASSES:  %e   %e\n",mass1,mass1 );
    printf("SOURCE: CORNER\n");
    printf("SINKS: PION_5 PION_05 RHO_i RHO_i0 \n");
    for(j=0;j<nt;j++){
      printf("%d %e %e %e %e %e %e %e %e\n",j,
        props[prop_pion5_ll][j].real, props[prop_pion5_ll][j].imag,
        props[prop_pion05_ll][j].real, props[prop_pion05_ll][j].imag,
        props[prop_rhoi_ll][j].real, props[prop_rhoi_ll][j].imag,
        props[prop_rhoi0_ll][j].real, props[prop_rhoi0_ll][j].imag);
    }
    printf("ENDPROP\n");
    printf("STARTPROP\n");
    printf("MASSES:  %e   %e\n",mass1,mass2 );
    printf("SOURCE: CORNER\n");
    printf("SINKS: PION_5 PION_05 RHO_i RHO_i0 \n");
    for(j=0;j<nt;j++){
      printf("%d %e %e %e %e %e %e %e %e\n",j,
        props[prop_pion5_lh][j].real, props[prop_pion5_lh][j].imag,
        props[prop_pion05_lh][j].real, props[prop_pion05_lh][j].imag,
        props[prop_rhoi_lh][j].real, props[prop_rhoi_lh][j].imag,
        props[prop_rhoi0_lh][j].real, props[prop_rhoi0_lh][j].imag);
    }
    printf("ENDPROP\n");
    printf("STARTPROP\n");
    printf("MASSES:  %e   %e\n",mass2,mass2 );
    printf("SOURCE: CORNER\n");
    printf("SINKS: PION_5 PION_05 RHO_i RHO_i0 \n");
    for(j=0;j<nt;j++){
      printf("%d %e %e %e %e %e %e %e %e\n",j,
        props[prop_pion5_hh][j].real, props[prop_pion5_hh][j].imag,
        props[prop_pion05_hh][j].real, props[prop_pion05_hh][j].imag,
        props[prop_rhoi_hh][j].real, props[prop_rhoi_hh][j].imag,
        props[prop_rhoi0_hh][j].real, props[prop_rhoi0_hh][j].imag);
    }
    printf("ENDPROP\n");
  
    /* Baryon propagators */
    printf("STARTPROP\n");
    printf("MASSES:  %e   %e   %e\n",mass1,mass1,mass1);
    printf("SOURCE: CORNER\n"); printf("SINKS: NUCLEON \n");
    for(j=0;j<nt;j++){
      printf("%d %e %e\n",j,
        props[prop_nuc_lll][j].real, props[prop_nuc_lll][j].imag);
    }
    printf("ENDPROP\n");

    printf("STARTPROP\n");
    printf("MASSES:  %e   %e   %e\n",mass1,mass1,mass2);
    printf("SOURCE: CORNER\n"); printf("SINKS: NUCLEON \n");
    for(j=0;j<nt;j++){
      printf("%d %e %e\n",j,
        props[prop_nuc_llh][j].real, props[prop_nuc_llh][j].imag);
    }
    printf("ENDPROP\n");

    printf("STARTPROP\n");
    printf("MASSES:  %e   %e   %e\n",mass1,mass2,mass2);
    printf("SOURCE: CORNER\n"); printf("SINKS: NUCLEON \n");
    for(j=0;j<nt;j++){
      printf("%d %e %e\n",j,
        props[prop_nuc_lhh][j].real, props[prop_nuc_lhh][j].imag);
    }
    printf("ENDPROP\n");

    printf("STARTPROP\n");
    printf("MASSES:  %e   %e   %e\n",mass2,mass2,mass2);
    printf("SOURCE: CORNER\n"); printf("SINKS: NUCLEON \n");
    for(j=0;j<nt;j++){
      printf("%d %e %e\n",j,
        props[prop_nuc_hhh][j].real, props[prop_nuc_hhh][j].imag);
    }
    printf("ENDPROP\n");

    fflush(stdout);
  } /* end if(this_node==0) */

  /* free arrays */
  free(props[0]); free(props);
  for(color=0;color<3;color++){
    free( lightprop[color] );
    free( heavyprop[color] );
  }
  
  return(cgn);
} /* spectrum_nd */
示例#9
0
 FORALLSITES(i, s) {
   tc = su3_dot(&(s->g_rand), (vector *)F_PT(s, psi_off));
   pbp_pbp += tc.real;
 }
示例#10
0
/* dest <- dest + sum_i eigVec[i]*H^{-1}*eigVec[i].resid, 
   resid = src - (-Dslash^2 + 4*mass^2)*dest
*/
static void initCG(su3_vector *src, su3_vector *dest, int Nvecs_curr, int Nvecs_max,
		   su3_vector **eigVec, double_complex *H, Real mass, int parity,
		   imp_ferm_links_t *fn){

  /* Constants */
  int ione = 1;
  int otherparity = (parity == EVEN) ? ODD : EVEN;
  Real msq_x4 = 4.0*mass*mass;
  double dzero = (double)0.0;
  double_complex zzero = dcmplx(dzero, dzero);

  register int i;
  int j, info;
  double_complex cc;
  double_complex *c, *H2;
  su3_vector *resid;

  c = (double_complex *)malloc(Nvecs_curr*sizeof(double_complex));
  resid = (su3_vector *)malloc(sites_on_node*sizeof(su3_vector));

  /* resid <- src - (-Dslash^2 + 4*mass^2)*dest */
  dslash_fn_field(dest, resid, otherparity, fn);
  dslash_fn_field(resid, resid, parity, fn);
  FORSOMEFIELDPARITY_OMP(i, parity, default(shared)){
    scalar_mult_sum_su3_vector(resid+i, dest+i, -msq_x4);
    add_su3_vector(resid+i, src+i, resid+i);
  } END_LOOP_OMP

  /* c[i] = eigVec[i].resid */
  for(j = 0; j < Nvecs_curr; j++){
//    c[j] = zzero;
//    FORSOMEFIELDPARITY_OMP(i, parity, private(cc) reduction(+:c[j])){
//      cc = su3_dot(eigVec[j]+i, resid+i);
//      CSUM(c[j], cc);
//    } END_LOOP_OMP

    double cctotr=0., cctoti=0.;
    FORSOMEFIELDPARITY_OMP(i, parity, private(cc) reduction(+:cctotr,cctoti)){
      cc = su3_dot(eigVec[j]+i, resid+i);
      cctotr += cc.real;
      cctoti += cc.imag;
    } END_LOOP_OMP;
    c[j].real = cctotr;
    c[j].imag = cctoti;

  }
  g_vecdcomplexsum(c, Nvecs_curr);

  free(resid);

  H2 = (double_complex *)malloc(Nvecs_curr*Nvecs_curr*sizeof(double_complex));

  /* H2 = H + 4*mass^2*I */
  for(j = 0; j < Nvecs_curr; j++){
    zcopy_(&Nvecs_curr, H+Nvecs_max*j, &ione, H2+Nvecs_curr*j, &ione);
    CSUM(H2[(Nvecs_curr+1)*j], dcmplx(msq_x4, dzero));
  }

  /* Compute H^{-1}*c = H^{-1}*eigVec.resid with Cholesky decomposition */
  zpotrf_("U", &Nvecs_curr, H2, &Nvecs_curr, &info);
  zpotrs_("U", &Nvecs_curr, &ione, H2, &Nvecs_curr, c, &Nvecs_curr, &info);

  free(H2);

  /* dest <- dest + sum_j c[i]*eigVec[i] = dest + sum_i eigVec[i]*H^{-1}*eigVec[i].resid */ 
  for(j = 0; j < Nvecs_curr; j++){
    FORSOMEFIELDPARITY_OMP(i, parity, default(shared)){
      c_scalar_mult_add_su3vec(dest+i, c+j, eigVec[j]+i);
    } END_LOOP_OMP
  }

  free(c);
}
示例#11
0
/* Assume the first Nvecs_curr eigenvectors have been already orthonormalized.
   If norm of an eigenvector is less than ORTHO_EPS, remove it.
   Rturn the number of new eigenvectors to be added.
*/
static int orthogonalize(int Nvecs, int Nvecs_curr, su3_vector **eigVec, int parity){

  register int i;
  int j, k, Nvecs_add, n;
  double norm;
  double_complex cc;
  double_complex *c;

  j = Nvecs_curr;
  Nvecs_add = Nvecs;
  n = Nvecs_curr + Nvecs_add;

  c = (double_complex *)malloc(n*sizeof(double_complex));

  while(j < n){
    /* Modified Gram-Schmidt
       Orthogonality is better but more communications are needed */
    for(k = 0; k < j; k++){
//      c[k] = dcmplx((double)0.0,(double)0.0);
//      FORSOMEFIELDPARITY_OMP(i, parity, private(cc) reduction(+:c[k])){
//	cc = su3_dot(eigVec[k]+i, eigVec[j]+i);
//	CSUM(c[k], cc);
//      } END_LOOP_OMP;

      double cctotr=0., cctoti=0.;
      FORSOMEFIELDPARITY_OMP(i, parity, private(cc) reduction(+:cctotr,cctoti)){
	cc = su3_dot(eigVec[k]+i, eigVec[j]+i);
	cctotr += cc.real;
	cctoti += cc.imag;
      } END_LOOP_OMP;
      c[k].real = cctotr;
      c[k].imag = cctoti;

      g_dcomplexsum(c+k);
      FORSOMEFIELDPARITY_OMP(i, parity, default(shared)){
	c_scalar_mult_sub_su3vec(eigVec[j]+i, c+k, eigVec[k]+i);
      } END_LOOP_OMP
    }
    /* Gram-Schmidt
       Less communications but
       poor orthogonality might happen if the number of vectors is too large. */
    /*
    for(k = 0; k < j; k++){
      c[k] = dcmplx((double)0.0,(double)0.0);
      FORSOMEFIELDPARITY_OMP(i, parity, private(cc) reduction(+:c[k])){
	cc = su3_dot(eigVec[k]+i, eigVec[j]+i);
	CSUM(c[k], cc);
      } END_LOOP_OMP
    }
    g_vecdcomplexsum(c, j);
    for(k = 0; k < j; k++){
      FORSOMEFIELDPARITY_OMP(i, parity, default(shared)){
	c_scalar_mult_sub_su3vec(eigVec[j]+i, c+k, eigVec[k]+i);
      } END_LOOP_OMP
    }
    */
    norm = (double)0.0;
    FORSOMEFIELDPARITY_OMP(i, parity, reduction(+:norm)){
      norm += magsq_su3vec(eigVec[j]+i);
    } END_LOOP_OMP
    g_doublesum(&norm);
    norm = sqrt(norm);
    if( norm < ORTHO_EPS ){
      Nvecs_add--;
      n--;
      for(k = j; k < n; k++){
	FORSOMEFIELDPARITY_OMP(i, parity, default(shared)){
	  eigVec[k][i] = eigVec[k+1][i];
	} END_LOOP_OMP
      }
    }
    else{
示例#12
0
void f_meas_imp_field( int npbp_reps, quark_invert_control *qic, Real mass,
		       int naik_term_epsilon_index, fermion_links_t *fl){

  imp_ferm_links_t* fn = get_fm_links(fl)[naik_term_epsilon_index];

#ifdef DM_DU0
  imp_ferm_links_t* fn_du0 = get_fm_du0_links(fl)[naik_term_epsilon_index];
#endif

#if ( FERM_ACTION == HISQ || FERM_ACTION == HYPISQ ) & defined(DM_DEPS)
  imp_ferm_links_t *fn_deps = get_fn_deps_links(fl);
#endif

    Real r_psi_bar_psi_even, i_psi_bar_psi_even;
    Real  r_psi_bar_psi_odd, i_psi_bar_psi_odd;
    Real r_ferm_action;
    /* local variables for accumulators */
    register int i;
    double rfaction;
    double_complex pbp_e, pbp_o;
    complex cc;

    int jpbp_reps;
    su3_vector *gr = NULL;
    su3_vector *M_gr = NULL;
    su3_vector *M_inv_gr = NULL;

#ifdef DM_DU0
    double r_pb_dMdu_p_even, r_pb_dMdu_p_odd;
    su3_vector *dMdu_x = NULL;
#endif

#if ( FERM_ACTION == HISQ || FERM_ACTION == HYPISQ ) & defined(DM_DEPS)
    double r_pb_dMdeps_p_even, r_pb_dMdeps_p_odd;
    su3_vector *dMdeps_x = NULL;
#endif

#ifdef CHEM_POT
    double_complex pb_dMdmu_p_e, pb_dMdmu_p_o;
    double_complex pb_d2Mdmu2_p_e, pb_d2Mdmu2_p_o;
    double MidM_MidM;
    su3_vector *dM_M_inv_gr = NULL;
    su3_vector *d2M_M_inv_gr = NULL;
    su3_vector *M_inv_dM_M_inv_gr = NULL;
    su3_vector *dM_M_inv_dM_M_inv_gr = NULL;
#endif

    /* Loop over random sources */
    for(jpbp_reps = 0; jpbp_reps < npbp_reps; jpbp_reps++){

      rfaction = (double)0.0;
      pbp_e = pbp_o = dcmplx((double)0.0,(double)0.0);
      
      /* Make random source, and do inversion */
      /* generate gr random; M_gr = M gr */
      gr = create_v_field();
#ifndef Z2RSOURCE
      grsource_plain_field( gr, EVENANDODD );
#else
      z2rsource_plain_field( gr, EVENANDODD );
#endif
      /* The following operation is done in the prevailing
	 precision.  The algorithm needs to be fixed! */
      M_gr = create_v_field();
      ks_dirac_adj_op( gr, M_gr, mass, EVENANDODD, fn );

      /* M_inv_gr = M^{-1} gr */

      M_inv_gr = create_v_field();
      mat_invert_uml_field( gr, M_inv_gr, qic, mass, fn );
      
#ifdef DM_DU0
      r_pb_dMdu_p_even = r_pb_dMdu_p_odd = (double)0.0;
      /* dMdu_x = dM/du0 M^{-1} gr */
      dMdu_x = create_v_field();
      dslash_fn_field( M_inv_gr, dMdu_x, EVENANDODD, fn_du0 );
#endif

#if ( FERM_ACTION == HISQ || FERM_ACTION == HYPISQ ) & defined(DM_DEPS)
      r_pb_dMdeps_p_even = r_pb_dMdeps_p_odd = (double)0.0;
      /* dMdeps_x = dM/deps0 M^{-1} gr */
      dMdeps_x = create_v_field();
      dslash_fn_field( M_inv_gr, dMdeps_x, EVENANDODD, fn_deps );
#endif

#ifdef CHEM_POT
      pb_dMdmu_p_e = pb_dMdmu_p_o = dcmplx((double)0.0,(double)0.0);
      pb_d2Mdmu2_p_e = pb_d2Mdmu2_p_o = dcmplx((double)0.0,(double)0.0);

      /* dM_M_inv_gr = dM/dmu * M_inv_gr */
      /* d2M_M_inv_gr = d2M/dmu2 * M_inv_gr */
      dM_M_inv_gr = create_v_field();
      chem_pot_tshift(fn, dM_M_inv_gr, M_inv_gr, 3., -1.);
      d2M_M_inv_gr = create_v_field();
      chem_pot_tshift(fn, d2M_M_inv_gr, M_inv_gr, 9., 1.);

#endif

      /* fermion action = M_gr.M_inv_gr */
      /* psi-bar-psi on even sites = gr.M_inv_gr */
      FOREVENFIELDSITES(i){
	rfaction += su3_rdot( M_gr+i, M_inv_gr+i );
	cc = su3_dot( gr+i, M_inv_gr+i );
	CSUM(pbp_e, cc);

#ifdef DM_DU0
	/* r_pb_dMdu_p_even = gr * dM/du0 M^{-1} gr |even*/
	r_pb_dMdu_p_even += su3_rdot( gr+i, dMdu_x+i );
#endif

#if ( FERM_ACTION == HISQ || FERM_ACTION == HYPISQ ) & defined(DM_DEPS)
	/* r_pb_dMdu_p_even = gr * dM/du0 M^{-1} gr |even*/
	r_pb_dMdeps_p_even += su3_rdot( gr+i, dMdeps_x+i );
#endif

#ifdef CHEM_POT
	/* Compute pb_dMdmu_p, pb_d2Mdmu2_p and dM_M_inv on even sites */
	cc = su3_dot( gr+i, dM_M_inv_gr+i);
	CSUM(pb_dMdmu_p_e, cc);
	cc = su3_dot( gr+i, d2M_M_inv_gr+i);
	CSUM(pb_d2Mdmu2_p_e, cc);
#endif
      }

      /* psi-bar-psi on odd sites */
      FORODDFIELDSITES(i){
	cc = su3_dot( gr+i, M_inv_gr+i );
	CSUM(pbp_o, cc);
#ifdef DM_DU0
	/* r_pb_dMdu_p_odd = gr * dM/du0 M^{-1} gr |odd*/
	r_pb_dMdu_p_odd += su3_rdot( gr+i, dMdu_x+i );
#endif

#if ( FERM_ACTION == HISQ || FERM_ACTION == HYPISQ ) & defined(DM_DEPS)
	/* r_pb_dMdu_p_odd = gr * dM/du0 M^{-1} gr |odd*/
	r_pb_dMdeps_p_odd += su3_rdot( gr+i, dMdeps_x+i );
#endif

#ifdef CHEM_POT
	/* Compute pb_dMdmu_P, pb_d2Mdmu2_p and dM_M_inv on odd sites */
	cc = su3_dot( gr+i, dM_M_inv_gr+i);
	CSUM(pb_dMdmu_p_o, cc);
	cc = su3_dot( gr+i, d2M_M_inv_gr+i);
	CSUM(pb_d2Mdmu2_p_o, cc);
#endif
      }

#ifdef CHEM_POT
      destroy_v_field(d2M_M_inv_gr); d2M_M_inv_gr = NULL;
#endif
      destroy_v_field(M_gr); M_gr = NULL;

      g_dcomplexsum( &pbp_o );
      g_dcomplexsum( &pbp_e );
      g_doublesum( &rfaction );
      
#ifdef DM_DU0
      destroy_v_field( dMdu_x ); dMdu_x = NULL;
      g_doublesum( &r_pb_dMdu_p_even );
      g_doublesum( &r_pb_dMdu_p_odd );
      r_pb_dMdu_p_even *= (2.0/(double)volume);
      r_pb_dMdu_p_odd *= (2.0/(double)volume);
      node0_printf("PB_DMDU_P: mass %e  %e  %e ( %d of %d )\n", mass,
		   r_pb_dMdu_p_even, r_pb_dMdu_p_odd, jpbp_reps+1, npbp_reps);
#endif

#if ( FERM_ACTION == HISQ || FERM_ACTION == HYPISQ ) & defined(DM_DEPS)
      destroy_v_field( dMdeps_x ); dMdeps_x = NULL;
      g_doublesum( &r_pb_dMdeps_p_even );
      g_doublesum( &r_pb_dMdeps_p_odd );
      r_pb_dMdeps_p_even *= (2.0/(double)volume);
      r_pb_dMdeps_p_odd *= (2.0/(double)volume);
      node0_printf("PB_DMDEPS_P: mass %e  %e  %e ( %d of %d )\n", mass,
		   r_pb_dMdeps_p_even, r_pb_dMdeps_p_odd, jpbp_reps+1, npbp_reps);
#endif

      r_psi_bar_psi_odd =  pbp_o.real*(2.0/(double)volume) ;
      i_psi_bar_psi_odd =  pbp_o.imag*(2.0/(double)volume) ;
      r_psi_bar_psi_even =  pbp_e.real*(2.0/(double)volume) ;
      i_psi_bar_psi_even =  pbp_e.imag*(2.0/(double)volume) ;
      r_ferm_action =  rfaction*(1.0/(double)volume) ;
      node0_printf("PBP: mass %e     %e  %e  %e  %e ( %d of %d )\n", mass,
		   r_psi_bar_psi_even, r_psi_bar_psi_odd,
		   i_psi_bar_psi_even, i_psi_bar_psi_odd,
		   jpbp_reps+1, npbp_reps);
      node0_printf("FACTION: mass = %e,  %e ( %d of %d )\n", mass,
		   r_ferm_action, jpbp_reps+1, npbp_reps);

#ifdef CHEM_POT
      /* Print results for pb_dMdmu_p and pb_d2Mdmu2_p */
      chem_pot_print1(pb_dMdmu_p_e, pb_dMdmu_p_o, pb_d2Mdmu2_p_e, pb_d2Mdmu2_p_o,
		      mass, jpbp_reps, npbp_reps);
#endif

#ifdef TR_MM_INV
      if(npbp_reps > 1){
	su3_vector *MM_inv_gr = create_v_field();
	double pbp_pbp = 0.0;

	mat_invert_uml_field( M_inv_gr, MM_inv_gr, qic, mass, fn );
	FORALLFIELDSITES(i){
	  pbp_pbp += su3_rdot( gr+i, MM_inv_gr+i );
	}
	g_doublesum( &pbp_pbp );
	pbp_pbp =  pbp_pbp*(1.0/(double)volume) ;
	node0_printf("TR_MM_INV: mass %e,  %e ( %d of %d )\n", mass,
		     pbp_pbp, jpbp_reps+1, npbp_reps);
	destroy_v_field(MM_inv_gr);
      }
#endif
      destroy_v_field(M_inv_gr); M_inv_gr = NULL;

#ifdef CHEM_POT
      /* M_inv_dM_M_inv_gr = M^{-1} dM_M_inv_gr */

      M_inv_dM_M_inv_gr = create_v_field();
      mat_invert_uml_field( dM_M_inv_gr, M_inv_dM_M_inv_gr, qic, mass, fn );
      destroy_v_field(dM_M_inv_gr); dM_M_inv_gr = NULL;

      /* dM_M_inv_dM_M_inv_gr = dM/dmu M_inv_dM_M_inv_gr */

      dM_M_inv_dM_M_inv_gr = create_v_field();
      chem_pot_tshift(fn, dM_M_inv_dM_M_inv_gr, M_inv_dM_M_inv_gr, 3., -1.);
      destroy_v_field(M_inv_dM_M_inv_gr); M_inv_dM_M_inv_gr = NULL;

      /* Compute MidM_MidM */
      MidM_MidM = (double)0.0;
      FORALLFIELDSITES(i){
	MidM_MidM += su3_rdot( gr+i, dM_M_inv_dM_M_inv_gr+i);
      }

      destroy_v_field(dM_M_inv_dM_M_inv_gr); dM_M_inv_dM_M_inv_gr = NULL;

      chem_pot_print2(MidM_MidM, jpbp_reps, npbp_reps, mass);

#endif
      destroy_v_field(gr); gr = NULL;

    } /* jpbp_reps */