Ejemplo n.º 1
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);
    }
Ejemplo n.º 2
0
int update()  {
  int step, iters=0;
  int n;
  Real final_rsq;
#ifdef HMC_ALGORITHM
  double startaction,endaction,d_action();
  Real xrandom;
#endif
  imp_ferm_links_t** fn;

    /* refresh the momenta */
    ranmom();

    /* In this application, the number of naik terms is 1 or 2 only */
    n = fermion_links_get_n_naiks(fn_links);

    /* do "steps" microcanonical steps"  */
    for(step=1; step <= steps; step++){
 
#ifdef PHI_ALGORITHM
        /* generate a pseudofermion configuration only at start*/
	/* also clear xxx, since zero is our best guess for the solution
	   with a new random phi field. */
     	if(step==1){
	  restore_fermion_links_from_site(fn_links, PRECISION);
	  fn = get_fm_links(fn_links);
	  clear_latvec( F_OFFSET(xxx1), EVENANDODD );
	  grsource_imp( F_OFFSET(phi1), mass1, EVEN, fn[0]);
	  clear_latvec( F_OFFSET(xxx2), EVENANDODD );
	  grsource_imp( F_OFFSET(phi2), mass2, EVEN, fn[n-1]);
	}

#ifdef HMC_ALGORITHM
        /* find action */
        /* do conjugate gradient to get (Madj M)inverse * phi */
        if(step==1){
            /* do conjugate gradient to get (Madj M)inverse * phi */
	  restore_fermion_links_from_site(fn_links, PRECISION);
	  fn = get_fm_links(fn_links);
	    iters += ks_congrad( F_OFFSET(phi1), F_OFFSET(xxx1), mass1,
				 niter, nrestart, rsqmin, PRECISION, EVEN, 
				 &final_rsq, fn[0]);
	  restore_fermion_links_from_site(fn_links, PRECISION);
	  fn = get_fm_links(fn_links);
	    iters += ks_congrad( F_OFFSET(phi2), F_OFFSET(xxx2), mass2,
				 niter, nrestart, rsqmin, PRECISION, EVEN, 
				 &final_rsq, fn[n-1]);

     	    startaction=d_action();
            /* copy link field to old_link */
	    gauge_field_copy( F_OFFSET(link[0]), F_OFFSET(old_link[0]));
        }
#endif

	/* update U's to middle of interval */
     	update_u(0.5*epsilon);

#else /* "R" algorithm */
       	/* first update the U's to special time interval */
        /* and generate a pseudofermion configuration */
	/* probably makes most sense if nflavors1 >= nflavors2 */

       	update_u(epsilon*(0.5-nflavors1/8.0));
	clear_latvec( F_OFFSET(xxx1), EVENANDODD );
	restore_fermion_links_from_site(fn_links, PRECISION);
	fn = get_fm_links(fn_links);
     	grsource_imp( F_OFFSET(phi1), mass1, EVEN, fn[0]);

       	update_u(epsilon*((nflavors1-nflavors2)/8.0));
	clear_latvec( F_OFFSET(xxx2), EVENANDODD );
	restore_fermion_links_from_site(fn_links, PRECISION);
	fn = get_fm_links(fn_links);
     	grsource_imp( F_OFFSET(phi2), mass2, EVEN, fn[n-1]);

	/* update U's to middle of interval */
     	update_u(epsilon*nflavors2/8.0);
#endif

        /* do conjugate gradient to get (Madj M)inverse * phi */
	restore_fermion_links_from_site(fn_links, PRECISION);
	fn = get_fm_links(fn_links);
	if(n == 2){
	  iters += ks_congrad( F_OFFSET(phi1), F_OFFSET(xxx1), mass1,
		       niter, nrestart, rsqmin, PRECISION, EVEN, &final_rsq, fn[0] );
	  iters += ks_congrad( F_OFFSET(phi2), F_OFFSET(xxx2), mass2,
		       niter, nrestart, rsqmin, PRECISION, EVEN, &final_rsq, fn[1] );
	} else {
	iters += ks_congrad_two_src( F_OFFSET(phi1), F_OFFSET(phi2),
				     F_OFFSET(xxx1), F_OFFSET(xxx2),
				     mass1, mass2, niter, nrestart, rsqmin, 
				     PRECISION, EVEN, &final_rsq,
				     fn[0]);
	}

	dslash_site( F_OFFSET(xxx1), F_OFFSET(xxx1), ODD, fn[0]);
	dslash_site( F_OFFSET(xxx2), F_OFFSET(xxx2), ODD, fn[n-1]);
	/* now update H by full time interval */
    	update_h(epsilon);

#if 0
#ifdef HAVE_QIO
	{
	  char *filexml;
	  char recxml[] = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><title>Test fermion force field</title>";
	  char ansfile[128];
	  char rootname[] = "fermion_force_dump";

	  /* Do this at the specified interval */
	  if(step%3 == 1){
	    
	    /* Construct a file name */
	    sprintf(ansfile,"%s%02d",rootname,step);
	    /* Dump the computed fermion force from the site structure */
	    filexml = create_QCDML();
	    save_color_matrix_scidac_from_site(ansfile, filexml, 
		       recxml, QIO_PARTFILE,  F_OFFSET(mom[0]), 4, PRECISION);
	    free_QCDML(filexml);
	  }
	}
#endif
#endif

    	/* update U's by half time step to get to even time */
    	update_u(epsilon*0.5);

        /* reunitarize the gauge field */
	rephase( OFF );
        reunitarize();
	rephase( ON );

    }	/* end loop over microcanonical steps */

#ifdef HMC_ALGORITHM
    /* find action */
    /* do conjugate gradient to get (Madj M)inverse * phi */
    restore_fermion_links_from_site(fn_links, PRECISION);
    fn = get_fm_links(fn_links);
    iters += ks_congrad( F_OFFSET(phi1), F_OFFSET(xxx1), mass1,
			 niter, nrestart, rsqmin, PRECISION, EVEN, 
			 &final_rsq, fn[0]);
    iters += ks_congrad( F_OFFSET(phi2), F_OFFSET(xxx2), mass2,
			 niter, nrestart, rsqmin, PRECISION, EVEN, 
			 &final_rsq, fn[n-1]);
    endaction=d_action();
    /* decide whether to accept, if not, copy old link field back */
    /* careful - must generate only one random number for whole lattice */
    if(this_node==0)xrandom = myrand(&node_prn);
    broadcast_float(&xrandom);
    if( exp( (double)(startaction-endaction) ) < xrandom ){
	if(steps > 0)
	    gauge_field_copy( F_OFFSET(old_link[0]), F_OFFSET(link[0]) );
#ifdef FN
	invalidate_fermion_links(fn_links);
#endif
	node0_printf("REJECT: delta S = %e\n", (double)(endaction-startaction));
    }
    else {
	node0_printf("ACCEPT: delta S = %e\n", (double)(endaction-startaction));
    }
#endif

    if(steps > 0)return (iters/steps);
    else return(-99);
}