/* the "full" operators */ void Q_pm_psi_prec(spinor * const l, spinor * const k) { spinorPrecWS *ws=(spinorPrecWS*)g_precWS; _Complex double ALIGN alpha= -1.0; if(g_prec_sequence_d_dagger_d[0]!=0.0) { alpha = g_prec_sequence_d_dagger_d[0]; spinorPrecondition(l,k,ws,T,L,alpha,0,1); } else assign(l,k,VOLUME); g_mu = -g_mu; D_psi(g_spinor_field[DUM_MATRIX], l); gamma5(l, g_spinor_field[DUM_MATRIX], VOLUME); g_mu = -g_mu; if(g_prec_sequence_d_dagger_d[1]!=0.0) { alpha = g_prec_sequence_d_dagger_d[1]; spinorPrecondition(l,l,ws,T,L,alpha,0,1); } D_psi(g_spinor_field[DUM_MATRIX], l); gamma5(l, g_spinor_field[DUM_MATRIX], VOLUME); if(g_prec_sequence_d_dagger_d[2]!=0.0) { alpha = g_prec_sequence_d_dagger_d[2]; spinorPrecondition(l,l,ws,T,L,alpha,0,1); } }
void Qov_sq_psi(spinor * const P, spinor * const S) { Dov_psi(g_spinor_field[DUM_MATRIX], S); gamma5(g_spinor_field[DUM_MATRIX], g_spinor_field[DUM_MATRIX], VOLUME); Dov_psi(P,g_spinor_field[DUM_MATRIX]); gamma5(P,P, VOLUME); return; }
/* This is the version for the gpu (Florian Burger)*/ void Q_minus_psi_gpu(spinor * const l, spinor * const k) { gamma5(k,k,VOLUME); g_mu = -g_mu; D_psi(l, k); g_mu = -g_mu; gamma5(l, l, VOLUME); }
/* the "full" operators */ void Q_pm_psi2(spinor * const l, spinor * const k) { g_mu = -10.*g_mu; D_psi(l, k); gamma5(g_spinor_field[DUM_MATRIX], l, VOLUME); g_mu = -g_mu/10.; D_psi(l, g_spinor_field[DUM_MATRIX]); gamma5(l, l, VOLUME); }
/* This is the version for the gpu with interchanged order of gamma5 and D_psi (Florian Burger)*/ void Q_pm_psi_gpu(spinor * const l, spinor * const k) { gamma5(k, k, VOLUME); g_mu = -g_mu; D_psi(l, k); gamma5(g_spinor_field[DUM_MATRIX], l, VOLUME); g_mu = -g_mu; D_psi(l, g_spinor_field[DUM_MATRIX]); }
int invert_cloverdoublet_eo(spinor * const Even_new_s, spinor * const Odd_new_s, spinor * const Even_new_c, spinor * const Odd_new_c, spinor * const Even_s, spinor * const Odd_s, spinor * const Even_c, spinor * const Odd_c, const double precision, const int max_iter, const int solver_flag, const int rel_prec) { int iter = 0; /* here comes the inversion using even/odd preconditioning */ if(g_proc_id == 0) {printf("# Using even/odd preconditioning!\n"); fflush(stdout);} Msw_ee_inv_ndpsi(Even_new_s, Even_new_c, Even_s, Even_c); Hopping_Matrix(OE, g_spinor_field[DUM_DERI], Even_new_s); Hopping_Matrix(OE, g_spinor_field[DUM_DERI+1], Even_new_c); /* The sign is plus, since in Hopping_Matrix */ /* the minus is missing */ assign_mul_add_r(g_spinor_field[DUM_DERI], +1., Odd_s, VOLUME/2); assign_mul_add_r(g_spinor_field[DUM_DERI+1], +1., Odd_c, VOLUME/2); /* Do the inversion with the preconditioned */ /* matrix to get the odd sites */ /* Here we invert the hermitean operator squared */ if(g_proc_id == 0) { printf("# Using CG for TMWILSON flavour doublet!\n"); fflush(stdout); } gamma5(g_spinor_field[DUM_DERI], g_spinor_field[DUM_DERI], VOLUME/2); gamma5(g_spinor_field[DUM_DERI+1], g_spinor_field[DUM_DERI+1], VOLUME/2); iter = cg_her_nd(Odd_new_s, Odd_new_c, g_spinor_field[DUM_DERI], g_spinor_field[DUM_DERI+1], max_iter, precision, rel_prec, VOLUME/2, &Qsw_pm_ndpsi); Qsw_dagger_ndpsi(Odd_new_s, Odd_new_c, Odd_new_s, Odd_new_c); /* Reconstruct the even sites */ Hopping_Matrix(EO, g_spinor_field[DUM_DERI], Odd_new_s); Hopping_Matrix(EO, g_spinor_field[DUM_DERI+1], Odd_new_c); Msw_ee_inv_ndpsi(g_spinor_field[DUM_DERI+2], g_spinor_field[DUM_DERI+3], g_spinor_field[DUM_DERI], g_spinor_field[DUM_DERI+1]); /* The sign is plus, since in Hopping_Matrix */ /* the minus is missing */ assign_add_mul_r(Even_new_s, g_spinor_field[DUM_DERI+2], +1., VOLUME/2); assign_add_mul_r(Even_new_c, g_spinor_field[DUM_DERI+3], +1., VOLUME/2); return(iter); }
void Q_full(spinor * const Even_new, spinor * const Odd_new, spinor * const Even, spinor * const Odd) { /* Even sites */ Hopping_Matrix(EO, g_spinor_field[DUM_DERI], Odd); assign_mul_one_pm_imu(Even_new, Even, 1., VOLUME/2); assign_add_mul_r(Even_new, g_spinor_field[DUM_DERI], -1., VOLUME/2); gamma5(Even_new, Even_new, VOLUME/2); /* Odd sites */ Hopping_Matrix(OE, g_spinor_field[DUM_DERI], Even); assign_mul_one_pm_imu(Odd_new, Odd, 1., VOLUME/2); assign_add_mul_r(Odd_new, g_spinor_field[DUM_DERI], -1., VOLUME/2); gamma5(Odd_new, Odd_new, VOLUME/2); }
void Qtm_pm_sym_psi(spinor * const l, spinor * const k){ /* Q_{-} */ Hopping_Matrix(EO, g_spinor_field[DUM_MATRIX+1], k); mul_one_pm_imu_inv(g_spinor_field[DUM_MATRIX+1], -1., VOLUME/2); Hopping_Matrix(OE, g_spinor_field[DUM_MATRIX], g_spinor_field[DUM_MATRIX+1]); mul_one_pm_imu_inv(g_spinor_field[DUM_MATRIX], -1., VOLUME/2); diff(l, k, g_spinor_field[DUM_MATRIX], VOLUME/2); gamma5(l, l, VOLUME/2); /* Q_{+} */ Hopping_Matrix(EO, l, g_spinor_field[DUM_MATRIX]); mul_one_pm_imu_inv(l, +1., VOLUME/2); Hopping_Matrix(OE, g_spinor_field[DUM_MATRIX+1], l); mul_one_pm_imu_inv(g_spinor_field[DUM_MATRIX], +1., VOLUME/2); diff(l, k, g_spinor_field[DUM_MATRIX], VOLUME/2); gamma5(l, l, VOLUME/2); }
/* |R>=rnorm^2 Q^2 |S> */ void norm_Q_sqr_psi(spinor * const R, spinor * const S, const double rnorm) { spinor *aux; aux=lock_Dov_WS_spinor(1); /* Term -1-s is done in D_psi! does this comment make sense for HMC? */ /* no, it doesn't, we do have to work on this */ /* here we need to set kappa = 1./(2 (-1-s) + 8) */ D_psi(R, S); gamma5(aux, R, VOLUME); D_psi(R, aux); gamma5(R, R, VOLUME); mul_r(R, rnorm*rnorm, R, VOLUME); unlock_Dov_WS_spinor(1); return; }
void Qov_sq_psi_prec(spinor * const P, spinor * const S) { spinorPrecWS *ws=(spinorPrecWS*)g_precWS; static complex alpha={0,0}; alpha.re=ws->precExpo[0]; spinorPrecondition(P,S,ws,T,L,alpha,0,1); Dov_psi(g_spinor_field[DUM_MATRIX], P); gamma5(P, g_spinor_field[DUM_MATRIX], VOLUME); alpha.re=ws->precExpo[1]; spinorPrecondition(P,P,ws,T,L,alpha,0,1); Dov_psi(g_spinor_field[DUM_MATRIX], P); gamma5(P, g_spinor_field[DUM_MATRIX], VOLUME); alpha.re=ws->precExpo[2]; spinorPrecondition(P,P,ws,T,L,alpha,0,1); return; }
void addproj_q_invsqrt(spinor * const Q, spinor * const P, const int n, const int N) { int j; spinor *aux; complex cnorm, lambda; static double save_ev[2]={-1.,-1.}; static int * ev_sign = NULL; if(eigenvls[0] != save_ev[0] && eigenvls[1] != save_ev[1] ) { if(g_proc_id == 0 && g_debug_level > 1) { printf("# Recomputing eigenvalue signs!\n"); fflush(stdout); } for(j = 0; j < 2; j++) { save_ev[j] = eigenvls[j]; } free(ev_sign); ev_sign = (int*) malloc(n * sizeof(int)); aux=lock_Dov_WS_spinor(1); for(j=0; j < n; j++) { D_psi(aux, &(eigenvectors[j*evlength])); gamma5(aux, aux, N); lambda = scalar_prod(&(eigenvectors[j*evlength]), aux, N, 1); if (lambda.re < 0) { ev_sign[j] = -1; } else { ev_sign[j] = 1; } } unlock_Dov_WS_spinor(1); /* free(aux_); */ } for(j = 0; j < n; j++) { cnorm = scalar_prod(&(eigenvectors[j*evlength]), P, N, 1); cnorm.re *= (double)ev_sign[j]; cnorm.im *= (double)ev_sign[j]; assign_add_mul(Q, &(eigenvectors[j*evlength]), cnorm, N); } return; }
void CGeoSmoother(spinor * const P, spinor * const Q, const int Ncy, const int dummy) { spinor ** solver_field = NULL; const int nr_sf = 5; double musave = g_mu; g_mu = g_mu1; init_solver_field(&solver_field, VOLUMEPLUSRAND/2, nr_sf); convert_lexic_to_eo(solver_field[0], solver_field[1], Q); if(g_c_sw > 0) assign_mul_one_sw_pm_imu_inv(EE,solver_field[2], solver_field[0], g_mu); else assign_mul_one_pm_imu_inv(solver_field[2], solver_field[0], +1., VOLUME/2); Hopping_Matrix(OE, solver_field[4], solver_field[2]); /* The sign is plus, since in Hopping_Matrix */ /* the minus is missing */ assign_mul_add_r(solver_field[4], +1., solver_field[1], VOLUME/2); /* Do the inversion with the preconditioned */ /* matrix to get the odd sites */ gamma5(solver_field[4], solver_field[4], VOLUME/2); if(g_c_sw > 0) { cg_her(solver_field[3], solver_field[4], Ncy, 1.e-8, 1, VOLUME/2, &Qsw_pm_psi); Qsw_minus_psi(solver_field[3], solver_field[3]); /* Reconstruct the even sites */ Hopping_Matrix(EO, solver_field[2], solver_field[3]); assign_mul_one_sw_pm_imu_inv(EE,solver_field[4],solver_field[2], g_mu); } else { cg_her(solver_field[3], solver_field[4], Ncy, 1.e-8, 1, VOLUME/2, &Qtm_pm_psi); Qtm_minus_psi(solver_field[3], solver_field[3]); /* Reconstruct the even sites */ Hopping_Matrix(EO, solver_field[4], solver_field[3]); mul_one_pm_imu_inv(solver_field[4], +1., VOLUME/2); } /* The sign is plus, since in Hopping_Matrix */ /* the minus is missing */ assign_add_mul_r(solver_field[2], solver_field[4], +1., VOLUME/2); convert_eo_to_lexic(P, solver_field[2], solver_field[3]); g_mu = musave; finalize_solver(solver_field, nr_sf); return; }
void Dov_psi(spinor * const P, spinor * const S) { double c0,c1; spinor *s; static int n_cheby = 0; static int rec_coefs = 1; ov_s = 0.5*(1./g_kappa - 8.) - 1.; /* printf("Degree of Polynomial set to %d\n", ov_n_cheby); */ if(n_cheby != ov_n_cheby || rec_coefs) { calculateOverlapPolynomial(); n_cheby = ov_n_cheby; rec_coefs = 0; } if(dov_ws==NULL){ init_Dov_WS(); } /* s_ = calloc(VOLUMEPLUSRAND+1, sizeof(spinor)); */ /* #if (defined SSE3 || defined SSE2 || defined SSE) */ /* s = (spinor*)(((unsigned long int)(s_)+ALIGN_BASE)&~ALIGN_BASE); */ /* #else */ /* s = s_; */ /* #endif */ s=lock_Dov_WS_spinor(0); /* here we do with M = 1 + s */ /* M + m_ov/2 + (M - m_ov/2) \gamma_5 sign(Q(-M)) */ c0 = -(1.0 + ov_s - 0.5*m_ov); c1 = -(1.0 + ov_s + 0.5*m_ov); Q_over_sqrt_Q_sqr(s, ov_cheby_coef, ov_n_cheby, S, ev_qnorm, ev_minev); gamma5(s, s, VOLUME); assign_mul_add_mul_r(s, S, c0, c1, VOLUME); assign(P, s, VOLUME); /* free(s_); */ unlock_Dov_WS_spinor(0); return; }
int bicg(spinor * const k, spinor * const l, double eps_sq) { int iteration; double xxx; xxx=0.0; gamma5(g_spinor_field[DUM_SOLVER+1], l, VOLUME/2); /* main loop */ for(iteration=1;iteration<=ITER_MAX_BCG;iteration++) { /* compute the residual*/ M_psi(DUM_SOLVER,k,q_off); xxx=diff_and_square_norm(g_spinor_field[DUM_SOLVER], g_spinor_field[DUM_SOLVER+1], VOLUME/2); /*apply the solver step for the residual*/ M_psi(DUM_SOLVER+2,DUM_SOLVER,q_off-(2.+2.*q_off)); assign_add_mul_r(k,-1./((1.+q_off)*(1.+q_off)),g_spinor_field[DUM_SOLVER+2], VOLUME/2); if(xxx <= eps_sq) break; } if(g_proc_id==0) { sout = fopen(solvout, "a"); fprintf(sout, "%d %e %f\n",iteration,xxx, g_mu); fclose(sout); } /* if the geometric series fails, redo with conjugate gradient */ if(iteration>=ITER_MAX_BCG) { if(ITER_MAX_BCG == 0) { iteration = 0; } zero_spinor_field(k,VOLUME/2); iteration += solve_cg(k,l,q_off,eps_sq); Q_psi(k,k,q_off); if(ITER_MAX_BCG != 0) { iteration -= 1000000; } if(g_proc_id == 0) { sout = fopen(solvout, "a"); fprintf(sout, "%d %e\n",iteration, g_mu); fclose(sout); } } return iteration; }
/* |R>=rnorm^n Q^n |S> */ void norm_Q_n_psi(spinor * const R, spinor * const S, const int n, const double rnorm) { int i; double npar = 1.; spinor *aux; aux=lock_Dov_WS_spinor(1); assign(aux, S, VOLUME); for(i=0; i < n; i++){ D_psi(R, aux); /* Term -1-s is done in D_psi! does this comment make sense for HMC? */ gamma5(aux, R, VOLUME); npar *= rnorm; } mul_r(R, npar, aux, VOLUME); unlock_Dov_WS_spinor(1); return; }
void cloverdet_derivative(const int id, hamiltonian_field_t * const hf) { monomial * mnl = &monomial_list[id]; /* This factor 2 a missing factor 2 in trace_lambda */ (*mnl).forcefactor = 2.; /********************************************************************* * * even/odd version * * This a term is det(\hat Q^2(\mu)) * *********************************************************************/ g_mu = mnl->mu; g_mu3 = mnl->rho; boundary(mnl->kappa); // we compute the clover term (1 + T_ee(oo)) for all sites x sw_term(hf->gaugefield, mnl->kappa, mnl->c_sw); // we invert it for the even sites only sw_invert(EE, mnl->mu); if(mnl->solver != CG && g_proc_id == 0) { fprintf(stderr, "Bicgstab currently not implemented, using CG instead! (cloverdet_monomial.c)\n"); } // Invert Q_{+} Q_{-} // X_o -> DUM_DERI+1 chrono_guess(g_spinor_field[DUM_DERI+1], mnl->pf, mnl->csg_field, mnl->csg_index_array, mnl->csg_N, mnl->csg_n, VOLUME/2, mnl->Qsq); mnl->iter1 += cg_her(g_spinor_field[DUM_DERI+1], mnl->pf, mnl->maxiter, mnl->forceprec, g_relative_precision_flag, VOLUME/2, mnl->Qsq); chrono_add_solution(g_spinor_field[DUM_DERI+1], mnl->csg_field, mnl->csg_index_array, mnl->csg_N, &mnl->csg_n, VOLUME/2); // Y_o -> DUM_DERI mnl->Qm(g_spinor_field[DUM_DERI], g_spinor_field[DUM_DERI+1]); // apply Hopping Matrix M_{eo} // to get the even sites of X_e H_eo_sw_inv_psi(g_spinor_field[DUM_DERI+2], g_spinor_field[DUM_DERI+1], EE, -mnl->mu); // \delta Q sandwitched by Y_o^\dagger and X_e deriv_Sb(OE, g_spinor_field[DUM_DERI], g_spinor_field[DUM_DERI+2], hf); // to get the even sites of Y_e H_eo_sw_inv_psi(g_spinor_field[DUM_DERI+3], g_spinor_field[DUM_DERI], EE, mnl->mu); // \delta Q sandwitched by Y_e^\dagger and X_o // uses the gauge field in hf and changes the derivative fields in hf deriv_Sb(EO, g_spinor_field[DUM_DERI+3], g_spinor_field[DUM_DERI+1], hf); // here comes the clover term... // computes the insertion matrices for S_eff // result is written to swp and swm // even/even sites sandwiched by gamma_5 Y_e and gamma_5 X_e gamma5(g_spinor_field[DUM_DERI+2], g_spinor_field[DUM_DERI+2], VOLUME/2); sw_spinor(EO, g_spinor_field[DUM_DERI+2], g_spinor_field[DUM_DERI+3]); // odd/odd sites sandwiched by gamma_5 Y_o and gamma_5 X_o gamma5(g_spinor_field[DUM_DERI], g_spinor_field[DUM_DERI], VOLUME/2); sw_spinor(OE, g_spinor_field[DUM_DERI], g_spinor_field[DUM_DERI+1]); // compute the contribution for the det-part // we again compute only the insertion matrices for S_det // the result is added to swp and swm // even sites only! sw_deriv(EE, mnl->mu); // now we compute // finally, using the insertion matrices stored in swm and swp // we compute the terms F^{det} and F^{sw} at once // uses the gaugefields in hf and changes the derivative field in hf sw_all(hf, mnl->kappa, mnl->c_sw); g_mu = g_mu1; g_mu3 = 0.; boundary(g_kappa); return; }
/* k output , l input */ int bicg(spinor * const k, spinor * const l, double eps_sq, const int rel_prec) { double err, d1, squarenorm=0.; complex rho0, rho1, omega, alpha, beta, nom, denom; int iteration, N=VOLUME/2; spinor * r, * p, * v, *hatr, * s, * t, * P, * Q; if(ITER_MAX_BCG > 0) { hatr = g_spinor_field[DUM_SOLVER]; r = g_spinor_field[DUM_SOLVER+1]; v = g_spinor_field[DUM_SOLVER+2]; p = g_spinor_field[DUM_SOLVER+3]; s = g_spinor_field[DUM_SOLVER+4]; t = g_spinor_field[DUM_SOLVER+5]; P = k; Q = l; squarenorm = square_norm(Q, VOLUME/2, 1); Mtm_plus_psi(r, P); gamma5(g_spinor_field[DUM_SOLVER], l, VOLUME/2); diff(p, hatr, r, N); assign(r, p, N); assign(hatr, p, N); rho0 = scalar_prod(hatr, r, N, 1); for(iteration = 0; iteration < ITER_MAX_BCG; iteration++){ err = square_norm(r, N, 1); if(g_proc_id == g_stdio_proc && g_debug_level > 1) { printf("BiCGstab: iterations: %d res^2 %e\n", iteration, err); fflush(stdout); } if (((err <= eps_sq) && (rel_prec == 0)) || ((err <= eps_sq*squarenorm) && (rel_prec == 1))){ break; } Mtm_plus_psi(v, p); denom = scalar_prod(hatr, v, N, 1); _div_complex(alpha, rho0, denom); assign(s, r, N); assign_diff_mul(s, v, alpha, N); Mtm_plus_psi(t, s); omega = scalar_prod(t,s, N, 1); d1 = square_norm(t, N, 1); omega.re/=d1; omega.im/=d1; assign_add_mul_add_mul(P, p, s, alpha, omega, N); assign(r, s, N); assign_diff_mul(r, t, omega, N); rho1 = scalar_prod(hatr, r, N, 1); _mult_assign_complex(nom, alpha, rho1); _mult_assign_complex(denom, omega, rho0); _div_complex(beta, nom, denom); omega.re=-omega.re; omega.im=-omega.im; assign_mul_bra_add_mul_ket_add(p, v, r, omega, beta, N); rho0.re = rho1.re; rho0.im = rho1.im; } if(g_proc_id==0 && g_debug_level > 0) { printf("BiCGstab: iterations: %d eps_sq: %1.4e\n", iteration, eps_sq); } } else{ iteration = ITER_MAX_BCG; gamma5(k, l, VOLUME/2); } /* if bicg fails, redo with conjugate gradient */ if(iteration>=ITER_MAX_BCG){ iteration = solve_cg(k,l,eps_sq, rel_prec); /* Save the solution for reuse! not needed since Chronological inverter is there */ /* assign(g_spinor_field[DUM_DERI+6], k, VOLUME/2); */ Qtm_minus_psi(k, k);; } return iteration; }
void Q_plus_psi(spinor * const l, spinor * const k) { D_psi(l, k); gamma5(l, l, VOLUME); }
/* Checks GW relation only by applying Dov to delta(0,0) */ void ov_check_ginsparg_wilson_relation(void) { double norm_diff, norm_left, norm_right, norm, max_rel = 0.0, min_left = 1.0e100, min_right = 1.0e100, max_diff = 0.0, min_norm = 1.0e100; int x, y, z, t, i; spinor *S_left, *S_right, *S_diff; /* get memory for the spinor fields */ S_left = ov_alloc_spinor(); S_right = ov_alloc_spinor(); S_diff = ov_alloc_spinor(); /* Create delta source at origin */ source_spinor_field(g_spinor_field[1], g_spinor_field[0], 0, 0); convert_eo_to_lexic(g_spinor_field[2], g_spinor_field[1], g_spinor_field[0]); /* S_right = D gamma_5 D */ Dov_psi(g_spinor_field[3], g_spinor_field[2]); gamma5(S_left, g_spinor_field[3], VOLUME); Dov_psi(S_right, S_left); /* S_left = {gamma_5, D} */ gamma5(g_spinor_field[3], g_spinor_field[2], VOLUME); Dov_psi(g_spinor_field[4], g_spinor_field[3]); add(S_left, S_left, g_spinor_field[4], VOLUME); /* S_diff = S_left-S_right */ diff(S_diff, S_left, S_right, VOLUME); /* scan the whole lattice */ printf("// test of the Ginsparg-Wilson relation\n"); for(x=0; x<LX; x++) for(y = 0; y < LY; y++) for(z = 0; z < LZ; z++) for(t = 0; t < T; t++) { i = g_ipt[t][x][y][z]; _spinor_norm_sq(norm_diff, S_diff[i]); _spinor_norm_sq(norm_left, S_left[i]); _spinor_norm_sq(norm_right, S_right[i]); norm_diff = sqrt(norm_diff); norm_left = sqrt(norm_left); norm_right = sqrt(norm_right); norm = norm_left+norm_right; if (norm < min_norm) min_norm = norm; if (norm > 0.0) { norm = 2.*norm_diff/norm; if (norm > max_rel) max_rel = norm; } if (norm_left < min_left) min_left = norm_left; if (norm_right < min_right) min_right = norm_right; if (norm_diff > max_diff) max_diff = norm_diff; } /* print results */ printf(" - maximum absoulte deviation: %.4le\n", max_diff); printf(" - maximum relative deviation: %.4le\n", max_rel); printf(" - minimum mean norm: %4.le\n", min_norm); printf(" - minimum norm {gamma_5, D}: %.4le\n", min_left); printf(" - minimum norm D gamma_5 D: %.4le\n", min_right); /* free memory */ ov_free_spinor(S_left); ov_free_spinor(S_right); ov_free_spinor(S_diff); }
void Qov_psi(spinor * const P, spinor * const S) { Dov_psi(P, S); gamma5(P, P, VOLUME); return; }
int invert_doublet_eo(spinor * const Even_new_s, spinor * const Odd_new_s, spinor * const Even_new_c, spinor * const Odd_new_c, spinor * const Even_s, spinor * const Odd_s, spinor * const Even_c, spinor * const Odd_c, const double precision, const int max_iter, const int solver_flag, const int rel_prec) { int iter = 0; #ifdef HAVE_GPU # ifdef TEMPORALGAUGE /* initialize temporal gauge here */ int retval; double dret1, dret2; double plaquette1 = 0.0; double plaquette2 = 0.0; if (usegpu_flag) { /* need VOLUME here (not N=VOLUME/2)*/ if ((retval = init_temporalgauge_trafo(VOLUME, g_gauge_field)) != 0 ) { // initializes the transformation matrices if (g_proc_id == 0) printf("Error while gauge fixing to temporal gauge. Aborting...\n"); // g_tempgauge_field as a copy of g_gauge_field exit(200); } /* do trafo */ plaquette1 = measure_plaquette(g_gauge_field); apply_gtrafo(g_gauge_field, g_trafo); // transformation of the gauge field plaquette2 = measure_plaquette(g_gauge_field); if (g_proc_id == 0) printf("\tPlaquette before gauge fixing: %.16e\n", plaquette1/6./VOLUME); if (g_proc_id == 0) printf("\tPlaquette after gauge fixing: %.16e\n", plaquette2/6./VOLUME); /* do trafo to odd_s part of source */ dret1 = square_norm(Odd_s, VOLUME/2 , 1); apply_gtrafo_spinor_odd(Odd_s, g_trafo); // odd spinor transformation, strange dret2 = square_norm(Odd_s, VOLUME/2, 1); if (g_proc_id == 0) printf("\tsquare norm before gauge fixing: %.16e\n", dret1); if (g_proc_id == 0) printf("\tsquare norm after gauge fixing: %.16e\n", dret2); /* do trafo to odd_c part of source */ dret1 = square_norm(Odd_c, VOLUME/2 , 1); apply_gtrafo_spinor_odd(Odd_c, g_trafo); // odd spinor transformation, charm dret2 = square_norm(Odd_c, VOLUME/2, 1); if (g_proc_id == 0) printf("\tsquare norm before gauge fixing: %.16e\n", dret1); if (g_proc_id == 0) printf("\tsquare norm after gauge fixing: %.16e\n", dret2); /* do trafo to even_s part of source */ dret1 = square_norm(Even_s, VOLUME/2 , 1); apply_gtrafo_spinor_even(Even_s, g_trafo); // even spinor transformation, strange dret2 = square_norm(Even_s, VOLUME/2, 1); if (g_proc_id == 0) printf("\tsquare norm before gauge fixing: %.16e\n", dret1); if (g_proc_id == 0) printf("\tsquare norm after gauge fixing: %.16e\n", dret2); /* do trafo to even_c part of source */ dret1 = square_norm(Even_c, VOLUME/2 , 1); apply_gtrafo_spinor_even(Even_c, g_trafo); // even spinor transformation, charm dret2 = square_norm(Even_c, VOLUME/2, 1); if (g_proc_id == 0) printf("\tsquare norm before gauge fixing: %.16e\n", dret1); if (g_proc_id == 0) printf("\tsquare norm after gauge fixing: %.16e\n", dret2); # ifdef MPI xchange_gauge(g_gauge_field); # endif } # endif #endif /* HAVE_GPU*/ /* here comes the inversion using even/odd preconditioning */ if(g_proc_id == 0) {printf("# Using even/odd preconditioning!\n"); fflush(stdout);} M_ee_inv_ndpsi(Even_new_s, Even_new_c, Even_s, Even_c, g_mubar, g_epsbar); Hopping_Matrix(OE, g_spinor_field[DUM_DERI], Even_new_s); Hopping_Matrix(OE, g_spinor_field[DUM_DERI+1], Even_new_c); /* The sign is plus, since in Hopping_Matrix */ /* the minus is missing */ assign_mul_add_r(g_spinor_field[DUM_DERI], +1., Odd_s, VOLUME/2); assign_mul_add_r(g_spinor_field[DUM_DERI+1], +1., Odd_c, VOLUME/2); /* Do the inversion with the preconditioned */ /* matrix to get the odd sites */ /* Here we invert the hermitean operator squared */ if(g_proc_id == 0) { printf("# Using CG for TMWILSON flavour doublet!\n"); fflush(stdout); } gamma5(g_spinor_field[DUM_DERI], g_spinor_field[DUM_DERI], VOLUME/2); gamma5(g_spinor_field[DUM_DERI+1], g_spinor_field[DUM_DERI+1], VOLUME/2); #ifdef HAVE_GPU if (usegpu_flag) { // GPU, mixed precision solver # if defined(MPI) && defined(PARALLELT) iter = mixedsolve_eo_nd(Odd_new_s, Odd_new_c, g_spinor_field[DUM_DERI], g_spinor_field[DUM_DERI+1], max_iter, precision, rel_prec); # elif !defined(MPI) && !defined(PARALLELT) iter = mixedsolve_eo_nd(Odd_new_s, Odd_new_c, g_spinor_field[DUM_DERI], g_spinor_field[DUM_DERI+1], max_iter, precision, rel_prec); # else printf("MPI and/or PARALLELT are not appropriately set for the GPU implementation. Aborting...\n"); exit(-1); # endif } else { // CPU, conjugate gradient iter = cg_her_nd(Odd_new_s, Odd_new_c, g_spinor_field[DUM_DERI], g_spinor_field[DUM_DERI+1], max_iter, precision, rel_prec, VOLUME/2, &Qtm_pm_ndpsi); } #else // CPU, conjugate gradient iter = cg_her_nd(Odd_new_s, Odd_new_c, g_spinor_field[DUM_DERI], g_spinor_field[DUM_DERI+1], max_iter, precision, rel_prec, VOLUME/2, &Qtm_pm_ndpsi); #endif Qtm_dagger_ndpsi(Odd_new_s, Odd_new_c, Odd_new_s, Odd_new_c); /* Reconstruct the even sites */ Hopping_Matrix(EO, g_spinor_field[DUM_DERI], Odd_new_s); Hopping_Matrix(EO, g_spinor_field[DUM_DERI+1], Odd_new_c); M_ee_inv_ndpsi(g_spinor_field[DUM_DERI+2], g_spinor_field[DUM_DERI+3], g_spinor_field[DUM_DERI], g_spinor_field[DUM_DERI+1], g_mubar, g_epsbar); /* The sign is plus, since in Hopping_Matrix */ /* the minus is missing */ assign_add_mul_r(Even_new_s, g_spinor_field[DUM_DERI+2], +1., VOLUME/2); assign_add_mul_r(Even_new_c, g_spinor_field[DUM_DERI+3], +1., VOLUME/2); #ifdef HAVE_GPU /* return from temporal gauge again */ # ifdef TEMPORALGAUGE if (usegpu_flag) { /* undo trafo */ /* apply_inv_gtrafo(g_gauge_field, g_trafo);*/ /* copy back the saved original field located in g_tempgauge_field -> update necessary*/ plaquette1 = measure_plaquette(g_gauge_field); copy_gauge_field(g_gauge_field, g_tempgauge_field); g_update_gauge_copy = 1; plaquette2 = measure_plaquette(g_gauge_field); if (g_proc_id == 0) printf("\tPlaquette before inverse gauge fixing: %.16e\n", plaquette1/6./VOLUME); if (g_proc_id == 0) printf("\tPlaquette after inverse gauge fixing: %.16e\n", plaquette2/6./VOLUME); /* undo trafo to source Even_s */ dret1 = square_norm(Even_s, VOLUME/2 , 1); apply_inv_gtrafo_spinor_even(Even_s, g_trafo); dret2 = square_norm(Even_s, VOLUME/2, 1); if (g_proc_id == 0) printf("\tsquare norm before gauge fixing: %.16e\n", dret1); if (g_proc_id == 0) printf("\tsquare norm after gauge fixing: %.16e\n", dret2); /* undo trafo to source Even_c */ dret1 = square_norm(Even_c, VOLUME/2 , 1); apply_inv_gtrafo_spinor_even(Even_c, g_trafo); dret2 = square_norm(Even_c, VOLUME/2, 1); if (g_proc_id == 0) printf("\tsquare norm before gauge fixing: %.16e\n", dret1); if (g_proc_id == 0) printf("\tsquare norm after gauge fixing: %.16e\n", dret2); /* undo trafo to source Odd_s */ dret1 = square_norm(Odd_s, VOLUME/2 , 1); apply_inv_gtrafo_spinor_odd(Odd_s, g_trafo); dret2 = square_norm(Odd_s, VOLUME/2, 1); if (g_proc_id == 0) printf("\tsquare norm before gauge fixing: %.16e\n", dret1); if (g_proc_id == 0) printf("\tsquare norm after gauge fixing: %.16e\n", dret2); /* undo trafo to source Odd_c */ dret1 = square_norm(Odd_c, VOLUME/2 , 1); apply_inv_gtrafo_spinor_odd(Odd_c, g_trafo); dret2 = square_norm(Odd_c, VOLUME/2, 1); if (g_proc_id == 0) printf("\tsquare norm before gauge fixing: %.16e\n", dret1); if (g_proc_id == 0) printf("\tsquare norm after gauge fixing: %.16e\n", dret2); // Even_new_s dret1 = square_norm(Even_new_s, VOLUME/2 , 1); apply_inv_gtrafo_spinor_even(Even_new_s, g_trafo); dret2 = square_norm(Even_new_s, VOLUME/2, 1); if (g_proc_id == 0) printf("\tsquare norm before gauge fixing: %.16e\n", dret1); if (g_proc_id == 0) printf("\tsquare norm after gauge fixing: %.16e\n", dret2); // Even_new_c dret1 = square_norm(Even_new_c, VOLUME/2 , 1); apply_inv_gtrafo_spinor_even(Even_new_c, g_trafo); dret2 = square_norm(Even_new_c, VOLUME/2, 1); if (g_proc_id == 0) printf("\tsquare norm before gauge fixing: %.16e\n", dret1); if (g_proc_id == 0) printf("\tsquare norm after gauge fixing: %.16e\n", dret2); // Odd_new_s dret1 = square_norm(Odd_new_s, VOLUME/2 , 1); apply_inv_gtrafo_spinor_odd(Odd_new_s, g_trafo); dret2 = square_norm(Odd_new_s, VOLUME/2, 1); if (g_proc_id == 0) printf("\tsquare norm before gauge fixing: %.16e\n", dret1); if (g_proc_id == 0) printf("\tsquare norm after gauge fixing: %.16e\n", dret2); // Odd_new_c dret1 = square_norm(Odd_new_c, VOLUME/2 , 1); apply_inv_gtrafo_spinor_odd(Odd_new_c, g_trafo); dret2 = square_norm(Odd_new_c, VOLUME/2, 1); if (g_proc_id == 0) printf("\tsquare norm before gauge fixing: %.16e\n", dret1); if (g_proc_id == 0) printf("\tsquare norm after gauge fixing: %.16e\n", dret2); finalize_temporalgauge(); # ifdef MPI xchange_gauge(g_gauge_field); # endif } # endif #endif return(iter); }
const Field Dirac_LowModeDeflation_ExactEigen::mult_dag(const Field& f)const{ return gamma5(mult(gamma5(f))); }
int invert_clover_eo(spinor * const Even_new, spinor * const Odd_new, spinor * const Even, spinor * const Odd, const double precision, const int max_iter, const int solver_flag, const int rel_prec,solver_params_t solver_params, su3 *** gf, matrix_mult Qsq, matrix_mult Qm) { int iter; if(g_proc_id == 0 && g_debug_level > 0) { printf("# Using even/odd preconditioning!\n"); fflush(stdout); } assign_mul_one_sw_pm_imu_inv(EE, Even_new, Even, +g_mu); Hopping_Matrix(OE, g_spinor_field[DUM_DERI], Even_new); /* The sign is plus, since in Hopping_Matrix */ /* the minus is missing */ assign_mul_add_r(g_spinor_field[DUM_DERI], +1., Odd, VOLUME/2); /* Do the inversion with the preconditioned */ /* matrix to get the odd sites */ /* Here we invert the hermitean operator squared */ gamma5(g_spinor_field[DUM_DERI], g_spinor_field[DUM_DERI], VOLUME/2); if(g_proc_id == 0) { //printf("# Using CG!\n"); printf("# mu = %f, kappa = %f, csw = %f\n", g_mu/2./g_kappa, g_kappa, g_c_sw); fflush(stdout); } if(solver_flag == CG) { if(g_proc_id == 0) { printf("# Using CG!\n"); fflush(stdout); } iter = cg_her(Odd_new, g_spinor_field[DUM_DERI], max_iter, precision, rel_prec, VOLUME/2, Qsq); Qm(Odd_new, Odd_new); } else if(solver_flag == INCREIGCG) { if(g_proc_id == 0) { printf("# Using Incremental Eig-CG!\n"); fflush(stdout); } iter = incr_eigcg(VOLUME/2,solver_params.eigcg_nrhs, solver_params.eigcg_nrhs1, Odd_new, g_spinor_field[DUM_DERI], solver_params.eigcg_ldh, Qsq, solver_params.eigcg_tolsq1, solver_params.eigcg_tolsq, solver_params.eigcg_restolsq , solver_params.eigcg_rand_guess_opt, rel_prec, max_iter, solver_params.eigcg_nev, solver_params.eigcg_vmax); Qm(Odd_new, Odd_new); } else { if(g_proc_id == 0) { printf("# This solver is not available for this operator. Exisiting!\n"); fflush(stdout); } return 0; } /* Reconstruct the even sites */ Hopping_Matrix(EO, g_spinor_field[DUM_DERI], Odd_new); clover_inv(g_spinor_field[DUM_DERI], +1, g_mu); /* The sign is plus, since in Hopping_Matrix */ /* the minus is missing */ assign_add_mul_r(Even_new, g_spinor_field[DUM_DERI], +1., VOLUME/2); return(iter); }
void invert_overlap(const int op_id, const int index_start) { operator * optr; void (*op)(spinor*,spinor*); static complex alpha={0,0}; spinorPrecWS *ws; optr = &operator_list[op_id]; op=&Dov_psi; /* here we need to (re)compute the kernel eigenvectors */ /* for new gauge fields */ if(g_proc_id == 0) {printf("# Not using even/odd preconditioning!\n"); fflush(stdout);} convert_eo_to_lexic(g_spinor_field[DUM_DERI], optr->sr0, optr->sr1); convert_eo_to_lexic(g_spinor_field[DUM_DERI+1], optr->prop0, optr->prop1); if(optr->solver == 13 ){ optr->iterations = sumr(g_spinor_field[DUM_DERI+1],g_spinor_field[DUM_DERI] , optr->maxiter, optr->eps_sq); } else if(optr->solver == 1 /* CG */) { gamma5(g_spinor_field[DUM_DERI+1], g_spinor_field[DUM_DERI], VOLUME); if(use_preconditioning==1 && g_precWS!=NULL){ ws=(spinorPrecWS*)g_precWS; printf("# Using preconditioning (which one?)!\n"); alpha.re=ws->precExpo[2]; spinorPrecondition(g_spinor_field[DUM_DERI+1],g_spinor_field[DUM_DERI+1],ws,T,L,alpha,0,1); /* iter = cg_her(g_spinor_field[DUM_DERI], g_spinor_field[DUM_DERI+1], max_iter, precision, */ /* rel_prec, VOLUME, &Q_pm_psi_prec); */ optr->iterations = cg_her(g_spinor_field[DUM_DERI], g_spinor_field[DUM_DERI+1], optr->maxiter, optr->eps_sq, optr->rel_prec, VOLUME, &Qov_sq_psi_prec); alpha.re=ws->precExpo[0]; spinorPrecondition(g_spinor_field[DUM_DERI],g_spinor_field[DUM_DERI],ws,T,L,alpha,0,1); } else { printf("# Not using preconditioning (which one?)!\n"); /* iter = cg_her(g_spinor_field[DUM_DERI], g_spinor_field[DUM_DERI+1], max_iter, precision, */ /* rel_prec, VOLUME, &Q_pm_psi); */ optr->iterations = cg_her(g_spinor_field[DUM_DERI], g_spinor_field[DUM_DERI+1], optr->maxiter, optr->eps_sq, optr->rel_prec, VOLUME, &Qov_sq_psi); } Qov_psi(g_spinor_field[DUM_DERI+1], g_spinor_field[DUM_DERI]); if(use_preconditioning == 1 && g_precWS!=NULL){ ws=(spinorPrecWS*)g_precWS; alpha.re=ws->precExpo[1]; spinorPrecondition(g_spinor_field[DUM_DERI+1],g_spinor_field[DUM_DERI+1],ws,T,L,alpha,0,1); } } op(g_spinor_field[4],g_spinor_field[DUM_DERI+1]); convert_eo_to_lexic(g_spinor_field[DUM_DERI], optr->sr0, optr->sr1); optr->reached_prec=diff_and_square_norm(g_spinor_field[4],g_spinor_field[DUM_DERI],VOLUME); convert_lexic_to_eo(optr->prop0, optr->prop1 , g_spinor_field[DUM_DERI+1]); return; }
void cloverdetratio_derivative_orig(const int no, hamiltonian_field_t * const hf) { monomial * mnl = &monomial_list[no]; /* This factor 2* a missing factor 2 in trace_lambda */ mnl->forcefactor = 1.; /********************************************************************* * * this is being run in case there is even/odd preconditioning * * This term is det((Q^2 + \mu_1^2)/(Q^2 + \mu_2^2)) * mu1 and mu2 are set according to the monomial * *********************************************************************/ /* First term coming from the second field */ /* Multiply with W_+ */ g_mu = mnl->mu; g_mu3 = mnl->rho2; //rho2 boundary(mnl->kappa); // we compute the clover term (1 + T_ee(oo)) for all sites x sw_term( (const su3**) hf->gaugefield, mnl->kappa, mnl->c_sw); // we invert it for the even sites only including mu sw_invert(EE, mnl->mu); if(mnl->solver != CG) { fprintf(stderr, "Bicgstab currently not implemented, using CG instead! (detratio_monomial.c)\n"); } mnl->Qp(g_spinor_field[DUM_DERI+2], mnl->pf); g_mu3 = mnl->rho; // rho1 /* Invert Q_{+} Q_{-} */ /* X_W -> DUM_DERI+1 */ chrono_guess(g_spinor_field[DUM_DERI+1], g_spinor_field[DUM_DERI+2], mnl->csg_field, mnl->csg_index_array, mnl->csg_N, mnl->csg_n, VOLUME/2, mnl->Qsq); mnl->iter1 += cg_her(g_spinor_field[DUM_DERI+1], g_spinor_field[DUM_DERI+2], mnl->maxiter, mnl->forceprec, g_relative_precision_flag, VOLUME/2, mnl->Qsq); chrono_add_solution(g_spinor_field[DUM_DERI+1], mnl->csg_field, mnl->csg_index_array, mnl->csg_N, &mnl->csg_n, VOLUME/2); /* Y_W -> DUM_DERI */ mnl->Qm(g_spinor_field[DUM_DERI], g_spinor_field[DUM_DERI+1]); /* apply Hopping Matrix M_{eo} */ /* to get the even sites of X */ H_eo_sw_inv_psi(g_spinor_field[DUM_DERI+2], g_spinor_field[DUM_DERI+1], EE, -mnl->mu); /* \delta Q sandwitched by Y_o^\dagger and X_e */ deriv_Sb(OE, g_spinor_field[DUM_DERI], g_spinor_field[DUM_DERI+2], hf, mnl->forcefactor); /* to get the even sites of Y */ H_eo_sw_inv_psi(g_spinor_field[DUM_DERI+3], g_spinor_field[DUM_DERI], EE, mnl->mu); /* \delta Q sandwitched by Y_e^\dagger and X_o */ deriv_Sb(EO, g_spinor_field[DUM_DERI+3], g_spinor_field[DUM_DERI+1], hf, mnl->forcefactor); // here comes the clover term... // computes the insertion matrices for S_eff // result is written to swp and swm // even/even sites sandwiched by gamma_5 Y_e and gamma_5 X_e gamma5(g_spinor_field[DUM_DERI+2], g_spinor_field[DUM_DERI+2], VOLUME/2); sw_spinor(EO, g_spinor_field[DUM_DERI+2], g_spinor_field[DUM_DERI+3]); // odd/odd sites sandwiched by gamma_5 Y_o and gamma_5 X_o gamma5(g_spinor_field[DUM_DERI], g_spinor_field[DUM_DERI], VOLUME/2); sw_spinor(OE, g_spinor_field[DUM_DERI], g_spinor_field[DUM_DERI+1]); g_mu3 = mnl->rho2; // rho2 /* Second term coming from the second field */ /* The sign is opposite!! */ mul_r(g_spinor_field[DUM_DERI], -1., mnl->pf, VOLUME/2); /* apply Hopping Matrix M_{eo} */ /* to get the even sites of X */ H_eo_sw_inv_psi(g_spinor_field[DUM_DERI+2], g_spinor_field[DUM_DERI+1], EE, -mnl->mu); /* \delta Q sandwitched by Y_o^\dagger and X_e */ deriv_Sb(OE, g_spinor_field[DUM_DERI], g_spinor_field[DUM_DERI+2], hf, mnl->forcefactor); /* to get the even sites of Y */ H_eo_sw_inv_psi(g_spinor_field[DUM_DERI+3], g_spinor_field[DUM_DERI], EE, mnl->mu); /* \delta Q sandwitched by Y_e^\dagger and X_o */ deriv_Sb(EO, g_spinor_field[DUM_DERI+3], g_spinor_field[DUM_DERI+1], hf, mnl->forcefactor); // here comes the clover term... // computes the insertion matrices for S_eff // result is written to swp and swm // even/even sites sandwiched by gamma_5 Y_e and gamma_5 X_e gamma5(g_spinor_field[DUM_DERI+2], g_spinor_field[DUM_DERI+2], VOLUME/2); sw_spinor(EO, g_spinor_field[DUM_DERI+2], g_spinor_field[DUM_DERI+3]); // odd/odd sites sandwiched by gamma_5 Y_o and gamma_5 X_o gamma5(g_spinor_field[DUM_DERI], g_spinor_field[DUM_DERI], VOLUME/2); sw_spinor(OE, g_spinor_field[DUM_DERI], g_spinor_field[DUM_DERI+1]); sw_all(hf, mnl->kappa*mnl->forcefactor, mnl->c_sw); g_mu = g_mu1; g_mu3 = 0.; boundary(g_kappa); return; }
int invert_doublet_eo(spinor * const Even_new_s, spinor * const Odd_new_s, spinor * const Even_new_c, spinor * const Odd_new_c, spinor * const Even_s, spinor * const Odd_s, spinor * const Even_c, spinor * const Odd_c, const double precision, const int max_iter, const int solver_flag, const int rel_prec, solver_params_t solver_params, const ExternalInverter external_inverter, const SloppyPrecision sloppy, const CompressionType compression) { int iter = 0; #ifdef TM_USE_QUDA if( external_inverter==QUDA_INVERTER ) { return invert_doublet_eo_quda( Even_new_s, Odd_new_s, Even_new_c, Odd_new_c, Even_s, Odd_s, Even_c, Odd_c, precision, max_iter, solver_flag, rel_prec, 1, sloppy, compression ); } #endif #ifdef HAVE_GPU # ifdef TEMPORALGAUGE if (usegpu_flag) { gtrafo_eo_nd(Even_s, Odd_s, Even_c, Odd_c, (spinor*const)NULL, (spinor*const)NULL, (spinor*const)NULL, (spinor*const)NULL, GTRAFO_APPLY); } # endif #endif /* HAVE_GPU*/ /* here comes the inversion using even/odd preconditioning */ if(g_proc_id == 0) {printf("# Using even/odd preconditioning!\n"); fflush(stdout);} M_ee_inv_ndpsi(Even_new_s, Even_new_c, Even_s, Even_c, g_mubar, g_epsbar); Hopping_Matrix(OE, g_spinor_field[DUM_DERI], Even_new_s); Hopping_Matrix(OE, g_spinor_field[DUM_DERI+1], Even_new_c); /* The sign is plus, since in Hopping_Matrix */ /* the minus is missing */ assign_mul_add_r(g_spinor_field[DUM_DERI], +1., Odd_s, VOLUME/2); assign_mul_add_r(g_spinor_field[DUM_DERI+1], +1., Odd_c, VOLUME/2); /* Do the inversion with the preconditioned */ /* matrix to get the odd sites */ /* Here we invert the hermitean operator squared */ if(g_proc_id == 0) { printf("# Using CG for TMWILSON flavour doublet!\n"); fflush(stdout); } if ( external_inverter == NO_EXT_INV ){ gamma5(g_spinor_field[DUM_DERI], g_spinor_field[DUM_DERI], VOLUME/2); gamma5(g_spinor_field[DUM_DERI+1], g_spinor_field[DUM_DERI+1], VOLUME/2); #ifdef HAVE_GPU if (usegpu_flag) { // GPU, mixed precision solver # if ( defined TM_USE_MPI && defined PARALLELT ) iter = mixedsolve_eo_nd(Odd_new_s, Odd_new_c, g_spinor_field[DUM_DERI], g_spinor_field[DUM_DERI+1], max_iter, precision, rel_prec); # elif ( !defined TM_USE_MPI && !defined PARALLELT ) iter = mixedsolve_eo_nd(Odd_new_s, Odd_new_c, g_spinor_field[DUM_DERI], g_spinor_field[DUM_DERI+1], max_iter, precision, rel_prec); # else printf("MPI and/or PARALLELT are not appropriately set for the GPU implementation. Aborting...\n"); exit(-1); # endif } else { // CPU, conjugate gradient iter = cg_her_nd(Odd_new_s, Odd_new_c, g_spinor_field[DUM_DERI], g_spinor_field[DUM_DERI+1], max_iter, precision, rel_prec, VOLUME/2, &Qtm_pm_ndpsi); } #else // CPU, conjugate gradient if(solver_flag == RGMIXEDCG){ iter = rg_mixed_cg_her_nd(Odd_new_s, Odd_new_c, g_spinor_field[DUM_DERI], g_spinor_field[DUM_DERI+1], solver_params, max_iter, precision, rel_prec, VOLUME/2, &Qtm_pm_ndpsi, &Qtm_pm_ndpsi_32); } else { iter = cg_her_nd(Odd_new_s, Odd_new_c, g_spinor_field[DUM_DERI], g_spinor_field[DUM_DERI+1], max_iter, precision, rel_prec, VOLUME/2, &Qtm_pm_ndpsi); } #endif Qtm_dagger_ndpsi(Odd_new_s, Odd_new_c, Odd_new_s, Odd_new_c); } // if(NO_EXT_INV) #ifdef TM_USE_QPHIX else if (external_inverter == QPHIX_INVERTER ) { // using QPhiX, we invert M M^dagger y = b, so we don't need gamma_5 multiplications iter = invert_eo_qphix_twoflavour(Odd_new_s, Odd_new_c, g_spinor_field[DUM_DERI], g_spinor_field[DUM_DERI+1], max_iter, precision, solver_flag, rel_prec, solver_params, sloppy, compression); // and it multiplies y internally by M^dagger, returning M^{-1} b as required } #endif // TM_USE_QPHIX /* Reconstruct the even sites */ Hopping_Matrix(EO, g_spinor_field[DUM_DERI], Odd_new_s); Hopping_Matrix(EO, g_spinor_field[DUM_DERI+1], Odd_new_c); M_ee_inv_ndpsi(g_spinor_field[DUM_DERI+2], g_spinor_field[DUM_DERI+3], g_spinor_field[DUM_DERI], g_spinor_field[DUM_DERI+1], g_mubar, g_epsbar); /* The sign is plus, since in Hopping_Matrix */ /* the minus is missing */ assign_add_mul_r(Even_new_s, g_spinor_field[DUM_DERI+2], +1., VOLUME/2); assign_add_mul_r(Even_new_c, g_spinor_field[DUM_DERI+3], +1., VOLUME/2); #ifdef HAVE_GPU /* return from temporal gauge again */ # ifdef TEMPORALGAUGE if (usegpu_flag) { gtrafo_eo_nd(Even_s, Odd_s, Even_c, Odd_c, Even_new_s, Odd_new_s, Even_new_c, Odd_new_c, GTRAFO_REVERT); } # endif #endif return(iter); }
int invert_cloverdoublet_eo(spinor * const Even_new_s, spinor * const Odd_new_s, spinor * const Even_new_c, spinor * const Odd_new_c, spinor * const Even_s, spinor * const Odd_s, spinor * const Even_c, spinor * const Odd_c, const double precision, const int max_iter, const int solver_flag, const int rel_prec, solver_params_t solver_params, const ExternalInverter external_inverter, const SloppyPrecision sloppy, const CompressionType compression) { int iter = 0; #ifdef TM_USE_QUDA if( external_inverter==QUDA_INVERTER ) { return invert_doublet_eo_quda( Even_new_s, Odd_new_s, Even_new_c, Odd_new_c, Even_s, Odd_s, Even_c, Odd_c, precision, max_iter, solver_flag, rel_prec, 1, sloppy, compression ); } #endif /* here comes the inversion using even/odd preconditioning */ if(g_proc_id == 0) {printf("# Using even/odd preconditioning!\n"); fflush(stdout);} Msw_ee_inv_ndpsi(Even_new_s, Even_new_c, Even_s, Even_c); Hopping_Matrix(OE, g_spinor_field[DUM_DERI], Even_new_s); Hopping_Matrix(OE, g_spinor_field[DUM_DERI+1], Even_new_c); /* The sign is plus, since in Hopping_Matrix */ /* the minus is missing */ assign_mul_add_r(g_spinor_field[DUM_DERI], +1., Odd_s, VOLUME/2); assign_mul_add_r(g_spinor_field[DUM_DERI+1], +1., Odd_c, VOLUME/2); if( external_inverter == NO_EXT_INV ){ /* Do the inversion with the preconditioned */ /* matrix to get the odd sites */ /* Here we invert the hermitean operator squared */ if(g_proc_id == 0) { printf("# Using CG for TMWILSON flavour doublet!\n"); fflush(stdout); } gamma5(g_spinor_field[DUM_DERI], g_spinor_field[DUM_DERI], VOLUME/2); gamma5(g_spinor_field[DUM_DERI+1], g_spinor_field[DUM_DERI+1], VOLUME/2); if(solver_flag == RGMIXEDCG){ iter = rg_mixed_cg_her_nd(Odd_new_s, Odd_new_c, g_spinor_field[DUM_DERI], g_spinor_field[DUM_DERI+1], solver_params, max_iter, precision, rel_prec, VOLUME/2, &Qsw_pm_ndpsi, &Qsw_pm_ndpsi_32); } else { iter = cg_her_nd(Odd_new_s, Odd_new_c, g_spinor_field[DUM_DERI], g_spinor_field[DUM_DERI+1], max_iter, precision, rel_prec, VOLUME/2, &Qsw_pm_ndpsi); } Qsw_dagger_ndpsi(Odd_new_s, Odd_new_c, Odd_new_s, Odd_new_c); } // if(NO_EXT_INV) #ifdef TM_USE_QPHIX else if (external_inverter == QPHIX_INVERTER ) { // using QPhiX, we invert M M^dagger y = b, so we don't need gamma_5 multiplications iter = invert_eo_qphix_twoflavour(Odd_new_s, Odd_new_c, g_spinor_field[DUM_DERI], g_spinor_field[DUM_DERI+1], max_iter, precision, solver_flag, rel_prec, solver_params, sloppy, compression); // and it multiplies y internally by M^dagger, returning M^{-1} b as required } #endif // TM_USE_QPHIX /* Reconstruct the even sites */ Hopping_Matrix(EO, g_spinor_field[DUM_DERI], Odd_new_s); Hopping_Matrix(EO, g_spinor_field[DUM_DERI+1], Odd_new_c); Msw_ee_inv_ndpsi(g_spinor_field[DUM_DERI+2], g_spinor_field[DUM_DERI+3], g_spinor_field[DUM_DERI], g_spinor_field[DUM_DERI+1]); /* The sign is plus, since in Hopping_Matrix */ /* the minus is missing */ assign_add_mul_r(Even_new_s, g_spinor_field[DUM_DERI+2], +1., VOLUME/2); assign_add_mul_r(Even_new_c, g_spinor_field[DUM_DERI+3], +1., VOLUME/2); return(iter); }
/* Check GW relation with operator norm over the full lattice */ void ov_check_ginsparg_wilson_relation_strong(void) { double norm_diff, norm_left, norm_right, norm, max_rel = 0.0, min_left = 1.0e100, min_right = 1.0e100, max_diff = 0.0, min_norm = 1.0e100; int x, y, z, t, i, j, k; spinor *S_left[4][3], *S_right[4][3], *S_diff[4][3]; if (g_debug_level>0) { printf("// creating spinor fields and calculating {gamma_5,D} psi and a D gamma_5 D psi\n"); fflush(stdout); } for (i=0; i<4; i++) for (j=0; j<3; j++) { if (g_debug_level>1) { printf("// spinor field: delta_dirac at %d, delta_color at %d\n", i, j); fflush(stdout); } /* get memory for the spinor */ S_left[i][j] = ov_alloc_spinor(); S_right[i][j] = ov_alloc_spinor(); S_diff[i][j] = ov_alloc_spinor(); /* Create delta source at origin */ source_spinor_field(g_spinor_field[1], g_spinor_field[0], i, j); convert_eo_to_lexic(g_spinor_field[2], g_spinor_field[1], g_spinor_field[0]); /* S_right = D gamma_5 D psi */ Dov_psi(g_spinor_field[3], g_spinor_field[2]); gamma5(S_left[i][j], g_spinor_field[3], VOLUME); Dov_psi(S_right[i][j], S_left[i][j]); /* S_left = {gamma_5, D} psi */ gamma5(g_spinor_field[3], g_spinor_field[2], VOLUME); Dov_psi(g_spinor_field[4], g_spinor_field[3]); add(S_left[i][j], S_left[i][j], g_spinor_field[4], VOLUME); /* S_diff = (S_left-S_right) psi, should be zero (GW relation) */ diff(S_diff[i][j], S_left[i][j], S_right[i][j], VOLUME); } /* scan the whole lattice and check GW relation */ printf("// test of the Ginsparg-Wilson relation:\n"); if (g_debug_level>0) fflush(stdout); for(x=0; x<LX; x++) for(y = 0; y < LY; y++) for(z = 0; z < LZ; z++) for(t = 0; t < T; t++) { k = g_ipt[t][x][y][z]; norm_diff = ov_operator_colsumnorm(S_diff, k); norm_left = ov_operator_colsumnorm(S_left, k); norm_right = ov_operator_colsumnorm(S_right, k); norm = (norm_left+norm_right)/2.; if (norm < min_norm) min_norm = norm; if (norm > 0.0) { norm = norm_diff/norm; if (norm > max_rel) max_rel = norm; if ((norm > 1.8) && (g_debug_level)>=5) { printf("(%d,%d,%d,%d): taxi = %d, rel = %.20le, lr = [%.4le, %.4le], diff = %.4le\n", t, x, y, z, ((x>LX/2) ? LX-x : x)+((y>LY/2) ? LY-y : y)+((z>LZ/2) ? LZ-z : z)+((t>T/2) ? T-t : t), norm, norm_left, norm_right, norm_diff); printf("// left[0][0]:\n"); ov_print_spinor(&S_left[0][0][k]); printf("// right[0][0]:\n"); ov_print_spinor(&S_right[0][0][k]); printf("// diff[0][0]:\n"); ov_print_spinor(&S_diff[0][0][k]); } } if (norm_left < min_left) min_left = norm_left; if (norm_right < min_right) min_right = norm_right; if (norm_diff > max_diff) max_diff = norm_diff; } /* print results */ printf(" - maximum absolute deviation: %.4le\n", max_diff); printf(" - maximum relative deviation: %.4le\n", max_rel); printf(" - minimum mean norm: %.4le\n", min_norm); printf(" - minimum norm {gamma_5, D}: %.4le\n", min_left); printf(" - minimum norm D gamma_5 D: %.4le\n", min_right); /* free memory */ for (i=0; i<4; i++) for (j=0; j<3; j++) { ov_free_spinor(S_left[i][j]); ov_free_spinor(S_right[i][j]); ov_free_spinor(S_diff[i][j]); } }