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)); }
void dslashRef() { // FIXME: remove once reference clover is finished if (inv_param.matpc_type == QUDA_MATPC_EVEN_EVEN_ASYMMETRIC) { inv_param.matpc_type = QUDA_MATPC_EVEN_EVEN; } else if (inv_param.matpc_type == QUDA_MATPC_ODD_ODD_ASYMMETRIC) { inv_param.matpc_type = QUDA_MATPC_ODD_ODD; } // compare to dslash reference implementation printf("Calculating reference implementation..."); fflush(stdout); switch (test_type) { case 0: dslash(spinorRef->V(), hostGauge, spinor->V(), parity, dagger, inv_param.cpu_prec, gauge_param.cpu_prec, inv_param.mass); break; case 1: matpc(spinorRef->V(), hostGauge, spinor->V(), kappa5, inv_param.matpc_type, dagger, inv_param.cpu_prec, gauge_param.cpu_prec, inv_param.mass); break; case 2: mat(spinorRef->V(), hostGauge, spinor->V(), kappa5, dagger, inv_param.cpu_prec, gauge_param.cpu_prec, inv_param.mass); break; default: printf("Test type not defined\n"); exit(-1); } printf("done.\n"); }
/* 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 */