// ----------------------------------------------------------------- // 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); }
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); }