void fermion_forwardstep(field_offset flow_vec){ Real eps = epsilon; register int i; register site *s; int j, off[4]; for (j = 0; j < 4; j++) off[j] = flow_vec + j*sizeof(su3_vector); // Step ODD sites // Obtain lambda1 fdslash(off[0], F_OFFSET(W0), off[1], EVEN); fdslash(off[1], F_OFFSET(W0), off[1], ODD); scalar_mult_add_latvec(off[0], off[1], eps/4, off[1], ODD); // Obtain lambda2 fdslash(off[1], F_OFFSET(W1), off[2], EVEN); fdslash(off[2], F_OFFSET(W1), off[2], ODD); scalar_mult_latvec(off[2], 8*eps/9, off[2], ODD); scalar_mult_add_latvec(off[2], off[1], -8/9, off[2], ODD); scalar_mult_add_latvec(off[2], off[0], 17/9, off[2], ODD); // Obtain lambda3 fdslash(off[2], F_OFFSET(W2), off[3], EVEN); fdslash(off[3], F_OFFSET(W2), off[3], ODD); scalar_mult_add_latvec(off[1], off[3], 3*eps/4, off[3], ODD); // copy odd sites of lambda3 FORODDSITES(i,s){ su3vec_copy((su3_vector *)F_PT(s,off[3]), &(s->tempvec0)); }
int mat_invert_uml(field_offset src, field_offset dest, field_offset temp, double mass ){ int cgn; double finalrsq; register int i; register site *s; if( src==temp ){ printf("BOTCH\n"); exit(0); } /* multiply by U - even sites only */ dslash( src, F_OFFSET(ttt), EVEN); scalar_mult_add_latvec( F_OFFSET(ttt), src, -2.0*mass, temp, EVEN); scalar_mult_latvec( temp, -1.0, temp, EVEN); /* invert with M_adj M even */ cgn = ks_congrad( temp, dest, mass, niter, rsqprop, EVEN, &finalrsq ); /* multiply by (1/2m)L, does nothing to even sites */ /* fix up odd sites , 1/2m (Dslash_oe*dest_e + phi_odd) */ dslash( dest, F_OFFSET(ttt), ODD ); FORODDSITES(i,s){ sub_su3_vector( (su3_vector *)F_PT(s,src), &(s->ttt), (su3_vector *)F_PT(s,dest) ); scalar_mult_su3_vector( (su3_vector *)F_PT(s,dest), 1.0/(2.0*mass), (su3_vector *)F_PT(s,dest) ); }
// ----------------------------------------------------------------- // dest <-- M^(-1) src int mat_invert_uml(field_offset src, field_offset dest, field_offset temp, Real mass) { register int i; register site *s; int cgn; Real norm = 1.0 / (2.0 * mass); if (src == temp) { printf("MAT_INVERT_UML: src = temp\n"); exit(0); } // "Precondition" both even and odd sites // temp <-- M^dag src dslash(src, F_OFFSET(ttt), EVENANDODD); scalar_mult_add_latvec(F_OFFSET(ttt), src, -2.0 * mass, temp, EVENANDODD); scalar_mult_latvec(temp, -1.0, temp, EVENANDODD); // dest_e <-- (M^dag M)^-1 temp_e (even sites only) cgn = ks_congrad(temp, dest, mass, EVEN); // Reconstruct odd site solution // dest_o <-- 1/2m (Dslash_oe * dest_e + src_o) dslash(dest, F_OFFSET(ttt), ODD); FORODDSITES(i, s) { sub_vector((vector *)F_PT(s, src), &(s->ttt), (vector *)F_PT(s, dest)); scalar_mult_vector((vector *)F_PT(s, dest), norm, (vector *)F_PT(s, dest)); }
/* Compute M^-1 * phi, answer in dest Uses phi, ttt, resid, xxx, and cg_p as workspace */ int mat_invert_cg( field_offset src, field_offset dest, field_offset temp, double mass ){ int cgn; double finalrsq; clear_latvec( dest, EVENANDODD ); cgn = ks_congrad( src, dest, mass, niter,rsqprop,EVENANDODD,&finalrsq); /* Multiply by Madjoint */ dslash( dest, F_OFFSET(ttt), EVENANDODD); scalar_mult_add_latvec( F_OFFSET(ttt), dest, -2.0*mass, F_OFFSET(ttt), EVENANDODD); scalar_mult_latvec( F_OFFSET(ttt), -1.0, dest, EVENANDODD ); return(cgn); }
/* Before calling checkmul() you should call grsource(EVENANDODD) and congrad(...,EVENANDODD) */ void checkmul() { register int i,j; register site *s; dslash( F_OFFSET(xxx), F_OFFSET(ttt), EVENANDODD); scalar_mult_add_latvec( F_OFFSET(ttt), F_OFFSET(xxx), 2.0*mass, F_OFFSET(ttt), EVENANDODD ); FORALLSITESDOMAIN(i,s){ printf("Site %d %d %d %d\n",s->x,s->y,s->z,s->t); for(j=0;j<3;j++){ printf("%d %d\t%e\t%e\t%e\n",i,j,(double)s->g_rand.c[j].real, (double)s->ttt.c[j].real,(double)s->g_rand.c[j].real - (double)s->ttt.c[j].real); printf("%d %d\t%e\t%e\t%e\n",i,j,(double)s->g_rand.c[j].imag, (double)s->ttt.c[j].imag,(double)s->g_rand.c[j].imag - (double)s->ttt.c[j].imag); } printf("\n"); }
// ----------------------------------------------------------------- // For single pseudofermion or inner Hasenbusch pseudofermion // dest = M^dag g_rand void grsource_imp(field_offset dest, Real M, int parity) { register int i, j; register site *s; FORALLSITES(i, s) { 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 } } // Hit g_rand with M^dag dslash(F_OFFSET(g_rand), dest, parity); scalar_mult_latvec(dest, -1.0, dest, parity); scalar_mult_add_latvec(dest, F_OFFSET(g_rand), 2.0 * M, dest, parity); }
/* "parity" is EVEN, ODD, or EVENANDODD. The parity is the parity at which phi is computed. g_rand must always be computed at all sites. */ void grsource(int parity) { register int i,j; register site *s; FORALLSITES(i,s){ #ifdef SCHROED_FUN if(s->t > 0){ #endif 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 } #ifdef SCHROED_FUN } else{ /* Set all fermion vectors to zero at t=0 */ for(j=0;j<3;j++){ s->phi.c[j].real = s->phi.c[j].imag = 0.0; s->resid.c[j].real = s->resid.c[j].imag = 0.0; s->cg_p.c[j].real = s->cg_p.c[j].imag = 0.0; s->xxx.c[j].real = s->xxx.c[j].imag = 0.0; s->ttt.c[j].real = s->ttt.c[j].imag = 0.0; s->g_rand.c[j].real = s->g_rand.c[j].imag = 0.0; } } #endif } clear_latvec( F_OFFSET(xxx), EVENANDODD ); dslash( F_OFFSET(g_rand), F_OFFSET(phi), parity); scalar_mult_latvec( F_OFFSET(phi), -1.0, F_OFFSET(phi), parity ); scalar_mult_add_latvec( F_OFFSET(phi), F_OFFSET(g_rand), 2.0*mass, F_OFFSET(phi), parity ); }/* grsource */