void qopWilsonSolve(Layout *l, real *x, real *u[8], real mass, real *y, double rsq, char *sub) { QDP_ColorMatrix *qu[4]; QDP_DiracFermion *out, *in; in = QDP_create_D(); out = QDP_create_D(); unpackD(l, in, y); unpackD(l, out, x); for(int i=0; i<4; i++) { qu[i] = QDP_create_M(); unpackM(l, qu[i], u[2*i]); QLA_Real two = 2; QDP_M_eq_r_times_M(qu[i], &two, qu[i], QDP_all); } QOP_FermionLinksWilson *fla; fla = QOP_wilson_create_L_from_qdp(qu, NULL); QOP_evenodd_t eo=QOP_EVENODD; if(sub[0]=='e') { eo = QOP_EVEN; } if(sub[0]=='o') { eo = QOP_ODD; } QOP_info_t info = QOP_INFO_ZERO; QOP_invert_arg_t inv_arg = QOP_INVERT_ARG_DEFAULT; QOP_resid_arg_t res_arg = QOP_RESID_ARG_DEFAULT; res_arg.rsqmin = rsq; inv_arg.max_iter = 1000; inv_arg.restart = 500; inv_arg.max_restarts = 5; inv_arg.evenodd = eo; inv_arg.mixed_rsq = 0; QDP_D_eq_zero(out, QDP_even); //QOP_verbose(3); QOP_wilson_invert_qdp(&info, fla, &inv_arg, &res_arg, mass, out, in); //QLA_Real n2; //QDP_r_eq_norm2_D(&n2, (QDP_DiracFermion*)out, QDP_all); printf0("QOP its: %i\n", res_arg.final_iter); packD(l, x, out); QDP_destroy_D(in); QDP_destroy_D(out); for(int i=0; i<4; i++) { QDP_destroy_M(qu[i]); } }
double bench_inv(QOP_info_t *info, QOP_invert_arg_t *inv_arg, QOP_resid_arg_t *res_arg, QDP_DiracFermion *out, QDP_DiracFermion *in) { static QLA_Real r2s=-1, r2; double sec=0, flop=0, mf=0; int i, iter=0; QOP_DiracFermion *qopout, *qopin; QDP_D_eq_zero(out, QDP_all); qopout = QOP_create_D_from_qdp(out); qopin = QOP_create_D_from_qdp(in); for(i=0; i<=nit; i++) { QMP_barrier(); QOP_wilson_invert(info, flw, inv_arg, res_arg, kappa, qopout, qopin); QMP_barrier(); printf("%i\t%i\t%g\t%i\n", i, res_arg->final_iter, info->final_sec, (int)info->final_flop); if(i>0) { iter += res_arg->final_iter; sec += info->final_sec; flop += info->final_flop; //mf += info->final_flop/(1e6*info->final_sec); } } QOP_destroy_D(qopout); QOP_destroy_D(qopin); QDP_r_eq_norm2_D(&r2, out, QDP_even); if(r2s<0) r2s = r2; if(fabs(1-r2/r2s)>1e-3) { printf0("first norm = %g this norn = %g\n", r2s, r2); } mf = 1; QMP_sum_double(&mf); QMP_sum_double(&sec); QMP_sum_double(&flop); res_arg->final_iter = iter/nit; info->final_sec = sec/(mf*nit); info->final_flop = flop/(mf*nit); mf = info->final_flop/(1e6*info->final_sec); return mf; }
void qopWilsonSolveMulti(Layout *l, real *x[], real *u[8], double masses[], real *y, int nmasses, double rsq, char *sub) { QDP_ColorMatrix *qu[4]; QDP_DiracFermion *out[nmasses], *in, **outp; outp = out; in = QDP_create_D(); unpackD(l, in, y); for(int i=0; i<nmasses; i++) { out[i] = QDP_create_D(); unpackD(l, out[i], x[i]); QDP_D_eq_zero(out[i], QDP_even); } for(int i=0; i<4; i++) { qu[i] = QDP_create_M(); unpackM(l, qu[i], u[2*i]); QLA_Real two = 2; QDP_M_eq_r_times_M(qu[i], &two, qu[i], QDP_all); } QOP_FermionLinksWilson *fla; fla = QOP_wilson_create_L_from_qdp(qu, NULL); #if 0 QOP_evenodd_t eo = QOP_EVENODD; if(sub[0]=='e') { eo = QOP_EVEN; } if(sub[0]=='o') { eo = QOP_ODD; } #endif QOP_evenodd_t eo = QOP_EVEN; QOP_info_t info = QOP_INFO_ZERO; QOP_invert_arg_t inv_arg = QOP_INVERT_ARG_DEFAULT; inv_arg.max_iter = 1000; inv_arg.restart = 500; inv_arg.max_restarts = 5; inv_arg.evenodd = eo; inv_arg.mixed_rsq = 0; QOP_resid_arg_t res_arg = QOP_RESID_ARG_DEFAULT; res_arg.rsqmin = rsq; QOP_resid_arg_t *ra[nmasses]; QOP_resid_arg_t **rap = ra; real mf[nmasses], *mfp; mfp = mf; for(int i=0; i<nmasses; i++) { ra[i] = &res_arg; mf[i] = masses[i]; } //QOP_verbose(3); QOP_wilson_invert_multi_qdp(&info, fla, &inv_arg, &rap, &mfp, &nmasses, &outp, &in, 1); //QLA_Real n2; //QDP_r_eq_norm2_D(&n2, (QDP_DiracFermion*)out, QDP_all); printf0("QOP its: %i\n", res_arg.final_iter); QDP_destroy_D(in); for(int i=0; i<nmasses; i++) { packD(l, x[i], out[i]); QDP_destroy_D(out[i]); } for(int i=0; i<4; i++) { QDP_destroy_M(qu[i]); } }
/* Special dslash for use by congrad. Uses restart_gather_site() when possible. Last argument is an integer, which will tell if gathers have been started. If is_started=0,use start_gather_site, otherwise use restart_gather_site. Argument "tag" is a vector of a msg_tag *'s to use for the gathers. The calling program must clean up the gathers! */ void dslash_special_qdp(QDP_DiracFermion *dest, QDP_DiracFermion *src, int sign, QDP_Subset subset, QDP_HalfFermion *temp[]) { int mu; QDP_DiracFermion *vsrc[4]; QDP_DiracFermion *vdest[4]; QDP_ShiftDir fwd[4], bck[4]; int dir[4], sgn[4], msgn[4]; QDP_Subset othersubset; for(mu=0; mu<4; mu++) { vsrc[mu] = src; vdest[mu] = dest; fwd[mu] = QDP_forward; bck[mu] = QDP_backward; dir[mu] = mu; sgn[mu] = sign; msgn[mu] = -sign; } if(subset==QDP_even) othersubset = QDP_odd; else if(subset==QDP_odd) othersubset = QDP_even; else othersubset = QDP_all; /* Take Wilson projection for src displaced in up direction, gather it to "our site" */ for(mu=0; mu<4; mu++) { QDP_H_eq_spproj_D(dtemp1[mu], src, mu, sign, othersubset); QDP_H_eq_sH(temp[mu], dtemp1[mu], QDP_neighbor[mu], QDP_forward, subset); } /* Take Wilson projection for src displaced in down direction, multiply it by adjoint link matrix, gather it "up" */ for(mu=0; mu<4; mu++) { QDP_H_eq_spproj_D(dtemp0, src, mu, -sign, othersubset); QDP_H_eq_Ma_times_H(dtemp1[4+mu], gaugelink[mu], dtemp0, othersubset); QDP_H_eq_sH(temp[4+mu], dtemp1[4+mu], QDP_neighbor[mu], QDP_backward, subset); } /* Set dest to zero */ /* Take Wilson projection for src displaced in up direction, gathered, multiply it by link matrix, expand it, and add. to dest */ QDP_D_eq_zero(dest, subset); QDP_D_vpeq_sprecon_M_times_H(vdest, gaugelink, temp, dir, sgn, subset, 4); for(mu=0; mu<4; mu++) { //QDP_D_peq_sprecon_M_times_H(dest, gaugelink[mu], temp[mu], mu, sign, subset); QDP_discard_H(temp[mu]); } /* Take Wilson projection for src displaced in down direction, expand it, and add to dest */ for(mu=0; mu<4; mu++) { QDP_D_peq_sprecon_H(dest, temp[4+mu], mu, -sign, subset); QDP_discard_H(temp[4+mu]); } } /* end of dslash_special_qdp() */
/* Special dslash for use by congrad. Uses restart_gather_site() when possible. Last argument is an integer, which will tell if gathers have been started. If is_started=0,use start_gather_site, otherwise use restart_gather_site. Argument "tag" is a vector of a msg_tag *'s to use for the gathers. The calling program must clean up the gathers! */ void dslash_special_qdp(QDP_DiracFermion *dest, QDP_DiracFermion *src, int sign, QDP_Subset subset, QDP_DiracFermion *temp[]) { int mu; QDP_DiracFermion *vsrc[8]; QDP_DiracFermion *vdest[8]; QDP_Shift sh[8]; QDP_ShiftDir sd[8]; int dir[8], sgn[8]; #ifndef SHIFT_D QDP_Subset othersubset; if(subset==QDP_even) othersubset = QDP_odd; else if(subset==QDP_odd) othersubset = QDP_even; else othersubset = QDP_all; #endif for(mu=0; mu<4; mu++) { vsrc[mu] = src; vsrc[mu+4] = src; vdest[mu] = dest; vdest[mu+4] = dest; dir[mu] = mu; dir[mu+4] = mu; sgn[mu] = sign; sgn[mu+4] = -sign; sh[mu] = QDP_neighbor[mu]; sh[mu+4] = QDP_neighbor[mu]; sd[mu] = QDP_forward; sd[mu+4] = QDP_backward; } /* Take Wilson projection for src displaced in up direction, gather it to "our site" */ #ifdef SHIFT_D QDP_D_veq_sD(temp, vsrc, sh, sd, subset, 8); #else for(mu=0; mu<8; mu++) { QDP_H_eq_spproj_D(dtemp1[mu], vsrc[mu], dir[mu], sgn[mu], othersubset); QDP_H_eq_sH(temp[mu], dtemp1[mu], sh[mu], sd[mu], subset); } #endif //QDP_H_veq_spproj_D(dtemp1, vsrc, dir, sgn, othersubset, 8); //QDP_H_veq_sH(temp, dtemp1, sh, sd, subset, 8); //QDP_H_veq_spproj_D(dtemp1, vsrc, dir, sgn, othersubset, 4); //QDP_H_veq_sH(temp, dtemp1, QDP_neighbor, sd, subset, 4); //for(mu=0; mu<4; mu++) { //QDP_H_eq_spproj_D(dtemp1[mu], src, mu, sign, othersubset); //QDP_H_eq_sH(temp[mu], dtemp1[mu], QDP_neighbor[mu], QDP_forward, subset); //} //QDP_H_veq_spproj_D(dtemp1+4, vsrc, dir, sgn+4, othersubset, 4); //QDP_H_veq_sH(temp+4, dtemp1+4, QDP_neighbor, sd+4, subset, 4); //for(mu=0; mu<4; mu++) { //QDP_H_eq_spproj_D(dtemp1[mu+4], src, mu, -sign, othersubset); //QDP_H_eq_sH(temp[mu+4], dtemp1[mu+4], QDP_neighbor[mu], QDP_backward, subset); //} /* Set dest to zero */ /* Take Wilson projection for src displaced in up direction, gathered, multiply it by link matrix, expand it, and add. to dest */ QDP_D_eq_zero(dest, subset); //QDP_D_vpeq_sprecon_M_times_H(vdest, gaugelink, temp, dir, sgn, subset, 8); QDP_D_vpeq_wilsonspin_M_times_D(vdest, gaugelink, temp, dir, sgn, subset, 8); #if 0 for(mu=0; mu<8; mu++) { QDP_D_peq_wilsonspin_M_times_D(dest, gaugelink[mu], temp[mu], dir[mu], sgn[mu], subset); } #endif #if 0 { QDP_HalfFermion *hf; hf = QDP_create_H(); for(mu=0; mu<8; mu++) { QDP_D_peq_wilsonspin_M_times_D(dest, gaugelink[mu], temp[mu], dir[mu], sgn[mu], subset); } for( ; mu<8; mu++) { QDP_H_eq_spproj_D(hf, temp[mu], dir[mu], sgn[mu], subset); QDP_D_peq_sprecon_M_times_H(dest, gaugelink[mu], hf, dir[mu], sgn[mu], subset); } QDP_destroy_H(hf); } #endif for(mu=0; mu<8; mu++) { QDP_discard_D(temp[mu]); } } /* end of dslash_special_qdp() */