// residues, roots and order define rational function approximation for // x^(nf/8) void grsource_imp_rhmc( field_offset dest, params_ratfunc *rf, int parity, su3_vector **multi_x, su3_vector *sumvec, Real my_rsqmin, int my_niter, int my_prec, ferm_links_t *fn) { register int i,j; register site *s; Real final_rsq; int order = rf->order; Real *residues = rf->res; Real *roots = rf->pole; /*TEMP*/ double sum; sum=0.0; FORSOMEPARITY(i,s,parity){ for(j=0;j<3;j++){ #ifdef SITERAND s->g_rand.c[j].real = gaussian_rand_no(&(s->site_prn)); s->g_rand.c[j].imag = gaussian_rand_no(&(s->site_prn)); #else s->g_rand.c[j].real = gaussian_rand_no(&node_prn); s->g_rand.c[j].imag = gaussian_rand_no(&node_prn); #endif } /*TEMP*/ sum += (double)magsq_su3vec( &(s->g_rand) ); } /*TEMP*/g_doublesum( &sum); node0_printf("GRSOURCE: sum = %.10e\n",sum); ks_ratinv( F_OFFSET(g_rand), multi_x, roots, order, my_niter, my_rsqmin, my_prec, parity, &final_rsq, fn ); ks_rateval( sumvec, F_OFFSET(g_rand), multi_x, residues, order, parity ); FORSOMEPARITY(i,s,parity){ *(su3_vector *)F_PT(s,dest) = sumvec[i]; }
void eo_fermion_force_rhmc( Real eps, params_ratfunc *rf, su3_vector **multi_x, field_offset phi_off, Real my_rsqmin, int my_niter, int cg_prec, int ff_prec, fermion_links_t *fl) { // at different time steps Real final_rsq; int j; int order = rf->order; Real *residues = rf->res; Real *roots = rf->pole; imp_ferm_links_t **fn; // Compute ( M^\dagger M)^{-1} in xxx_even // Then compute M*xxx in temporary vector xxx_odd /* See long comment at end of file */ /* The diagonal term in M doesn't matter */ // load_ferm_links(fn); restore_fermion_links_from_site(fl, cg_prec); fn = get_fm_links(fl); /* Do the inversion for zero Naik term epsilon */ ks_ratinv( phi_off, multi_x, roots, order, my_niter, my_rsqmin, cg_prec, EVEN, &final_rsq, fn[0], 0, 0. ); /* Do dslash for zero Naik term epsilon */ for(j=0;j<order;j++){ dslash_field( multi_x[j], multi_x[j], ODD, fn[0] ); } eo_fermion_force_multi( eps, &(residues[1]), multi_x, order, ff_prec, fl ); }
// fermion force update grouping pseudofermions with the same path coeffs int update_h_fermion( Real eps, su3_vector **multi_x ){ int iphi,jphi; Real final_rsq; int i,j,n; int order, tmporder; Real *residues,*allresidues; Real *roots; int iters = 0; imp_ferm_links_t **fn; /* Algorithm sketch: assemble multi_x with all |X> fields, then call force routine for each part (so far we have to parts: zero correction to Naik and non-zero correction to Naik */ allresidues = (Real *)malloc(n_order_naik_total*sizeof(Real)); // Group the fermion force calculation according to sets of like // path coefficients. tmporder = 0; iphi = 0; #if ( FERM_ACTION == HISQ || FERM_ACTION == HYPISQ ) n = fermion_links_get_n_naiks(fn_links); #else n = 1; #endif for( i=0; i<n; i++ ) { for( jphi=0; jphi<n_pseudo_naik[i]; jphi++ ) { restore_fermion_links_from_site(fn_links, prec_md[iphi]); fn = get_fm_links(fn_links); // Add the current pseudofermion to the current set order = rparam[iphi].MD.order; residues = rparam[iphi].MD.res; roots = rparam[iphi].MD.pole; // Compute ( M^\dagger M)^{-1} in xxx_even // Then compute M*xxx in temporary vector xxx_odd /* See long comment at end of file */ /* The diagonal term in M doesn't matter */ iters += ks_ratinv( F_OFFSET(phi[iphi]), multi_x+tmporder, roots, order, niter_md[iphi], rsqmin_md[iphi], prec_md[iphi], EVEN, &final_rsq, fn[i], i, rparam[iphi].naik_term_epsilon ); for(j=0;j<order;j++){ dslash_field( multi_x[tmporder+j], multi_x[tmporder+j], ODD, fn[i]); allresidues[tmporder+j] = residues[j+1]; // remember that residues[0] is constant, no force contribution. } tmporder += order; iphi++; } } #ifdef MILC_GLOBAL_DEBUG node0_printf("update_h_rhmc: MULTI_X ASSEMBLED\n");fflush(stdout); node0_printf("update_h_rhmc: n_distinct_Naik=%d\n",n); for(j=0;j<n;j++) node0_printf("update_h_rhmc: orders[%d]=%d\n",j,n_orders_naik[j]); #if ( FERM_ACTION == HISQ || FERM_ACTION == HYPISQ ) for(j=0;j<n;j++) node0_printf("update_h_rhmc: masses_Naik[%d]=%f\n",j,fn_links.hl.eps_naik[j]); #endif fflush(stdout); #endif /* MILC_GLOBAL_DEBUG */ restore_fermion_links_from_site(fn_links, prec_ff); eo_fermion_force_multi( eps, allresidues, multi_x, n_order_naik_total, prec_ff, fn_links ); free(allresidues); return iters; } /* update_h_fermion */