// if even_odd_flag set void M_full_quda(spinor * const Even_new, spinor * const Odd_new, spinor * const Even, spinor * const Odd) { inv_param.kappa = g_kappa; inv_param.mu = fabs(g_mu); inv_param.epsilon = 0.0; // IMPORTANT: use opposite TM flavor since gamma5 -> -gamma5 (until LXLYLZT prob. resolved) inv_param.twist_flavor = (g_mu < 0.0 ? QUDA_TWIST_PLUS : QUDA_TWIST_MINUS); inv_param.Ls = (inv_param.twist_flavor == QUDA_TWIST_NONDEG_DOUBLET || inv_param.twist_flavor == QUDA_TWIST_DEG_DOUBLET ) ? 2 : 1; void *spinorIn = (void*)g_spinor_field[DUM_DERI]; // source void *spinorOut = (void*)g_spinor_field[DUM_DERI+1]; // solution // reorder spinor convert_eo_to_lexic( spinorIn, Even, Odd ); reorder_spinor_toQuda( (double*)spinorIn, inv_param.cpu_prec, 0, NULL ); // multiply inv_param.solution_type = QUDA_MAT_SOLUTION; MatQuda( spinorOut, spinorIn, &inv_param); // reorder spinor reorder_spinor_fromQuda( (double*)spinorOut, inv_param.cpu_prec, 0, NULL ); convert_lexic_to_eo( Even_new, Odd_new, spinorOut ); }
int tmLQCD_invert(double * const propagator, double * const source, const int op_id, const int write_prop) { unsigned int index_start = 0; g_mu = 0.; if(!tmLQCD_invert_initialised) { fprintf(stderr, "tmLQCD_invert: tmLQCD_inver_init must be called first. Aborting...\n"); return(-1); } if(op_id < 0 || op_id >= no_operators) { fprintf(stderr, "tmLQCD_invert: op_id=%d not in valid range. Aborting...\n", op_id); return(-1); } operator_list[op_id].sr0 = g_spinor_field[0]; operator_list[op_id].sr1 = g_spinor_field[1]; operator_list[op_id].prop0 = g_spinor_field[2]; operator_list[op_id].prop1 = g_spinor_field[3]; zero_spinor_field(operator_list[op_id].prop0, VOLUME / 2); zero_spinor_field(operator_list[op_id].prop1, VOLUME / 2); // convert to even/odd order convert_lexic_to_eo(operator_list[op_id].sr0, operator_list[op_id].sr1, (spinor*) source); // invert operator_list[op_id].inverter(op_id, index_start, write_prop); // convert back to lexicographic order convert_eo_to_lexic((spinor*) propagator, operator_list[op_id].prop0, operator_list[op_id].prop1); return(0); }
void ov_check_operator(int t, int x, int y, int z) { /* 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]); /* Evaluate Dov(psi) */ Dov_psi(g_spinor_field[3], g_spinor_field[2]); ov_print_spinor(&g_spinor_field[3][g_ipt[t][x][y][z]]); }
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 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; }
int main(int argc,char *argv[]) { FILE *parameterfile=NULL; int c, j, is=0, ic=0; int x, X, y, Y, z, Z, t, tt, i, sum; char * filename = NULL; char datafilename[50]; char parameterfilename[50]; char conf_filename[50]; char * input_filename = NULL; double plaquette_energy, nrm; double * norm; struct stout_parameters params_smear; #ifdef _GAUGE_COPY int kb=0; #endif #ifdef MPI double atime=0., etime=0.; #endif #ifdef _KOJAK_INST #pragma pomp inst init #pragma pomp inst begin(main) #endif DUM_DERI = 6; /* DUM_DERI + 2 is enough (not 7) */ DUM_SOLVER = DUM_DERI+2; DUM_MATRIX = DUM_SOLVER+6; /* DUM_MATRIX + 2 is enough (not 6) */ NO_OF_SPINORFIELDS = DUM_MATRIX+2; verbose = 0; g_use_clover_flag = 0; g_nr_of_psf = 1; #ifdef MPI MPI_Init(&argc, &argv); #endif while ((c = getopt(argc, argv, "h?f:o:")) != -1) { switch (c) { case 'f': input_filename = calloc(200, sizeof(char)); strcpy(input_filename,optarg); break; case 'o': filename = calloc(200, sizeof(char)); strcpy(filename,optarg); break; case 'h': case '?': default: usage(); break; } } if(input_filename == NULL){ input_filename = "hmc.input"; } if(filename == NULL){ filename = "output"; } /* Read the input file */ read_input(input_filename); /* here we want no even/odd preconditioning */ even_odd_flag = 0; /* this DBW2 stuff is not needed for the inversion ! */ g_rgi_C1 = 0; if(Nsave == 0){ Nsave = 1; } tmlqcd_mpi_init(argc, argv); g_dbw2rand = 0; #ifndef MPI g_dbw2rand = 0; #endif #ifdef _GAUGE_COPY j = init_gauge_field(VOLUMEPLUSRAND, 1); #else j = init_gauge_field(VOLUMEPLUSRAND, 0); #endif if ( j!= 0) { fprintf(stderr, "Not enough memory for gauge_fields! Aborting...\n"); exit(-1); } j = init_geometry_indices(VOLUMEPLUSRAND); if ( j!= 0) { fprintf(stderr, "Not enough memory for geometry indices! Aborting...\n"); exit(-1); } if(even_odd_flag) { j = init_spinor_field(VOLUMEPLUSRAND/2, NO_OF_SPINORFIELDS); } else { j = init_spinor_field(VOLUMEPLUSRAND, NO_OF_SPINORFIELDS); } if ( j!= 0) { fprintf(stderr, "Not enough memory for spinor fields! Aborting...\n"); exit(-1); } g_mu = g_mu1; if(g_proc_id == 0){ /*construct the filenames for the observables and the parameters*/ strcpy(datafilename,filename); strcat(datafilename,".data"); strcpy(parameterfilename,filename); strcat(parameterfilename,".para"); parameterfile=fopen(parameterfilename, "w"); write_first_messages(parameterfile, 0, 1); } /* define the geometry */ geometry(); /* define the boundary conditions for the fermion fields */ boundary(); #ifdef _USE_HALFSPINOR j = init_dirac_halfspinor(); if ( j!= 0) { fprintf(stderr, "Not enough memory for halffield! Aborting...\n"); exit(-1); } if(g_sloppy_precision_flag == 1) { j = init_dirac_halfspinor32(); if ( j!= 0) { fprintf(stderr, "Not enough memory for 32-Bit halffield! Aborting...\n"); exit(-1); } } # if (defined _PERSISTENT) init_xchange_halffield(); # endif #endif norm = (double*)calloc(3.*LX/2.+T/2., sizeof(double)); for(j=0;j<Nmeas; j++) { sprintf(conf_filename,"%s.%.4d", gauge_input_filename, nstore); if (g_proc_id == 0){ printf("Reading Gauge field from file %s\n", conf_filename); fflush(stdout); } read_lime_gauge_field(conf_filename); if (g_proc_id == 0){ printf("done!\n"); fflush(stdout); } #ifdef MPI xchange_gauge(); #endif #ifdef _GAUGE_COPY update_backward_gauge(); #endif /* Compute minimal eigenvalues, if wanted */ if(compute_evs != 0) { eigenvalues(&no_eigenvalues, 1000, eigenvalue_precision, 0, compute_evs, nstore, even_odd_flag); } /*compute the energy of the gauge field*/ plaquette_energy = measure_gauge_action(); if(g_proc_id == 0) { printf("The plaquette value is %e\n", plaquette_energy/(6.*VOLUME*g_nproc)); fflush(stdout); } if (use_stout_flag == 1){ params_smear.rho = stout_rho; params_smear.iterations = stout_no_iter; if (stout_smear((su3_tuple*)(g_gauge_field[0]), ¶ms_smear, (su3_tuple*)(g_gauge_field[0])) != 0) exit(1) ; g_update_gauge_copy = 1; g_update_gauge_energy = 1; g_update_rectangle_energy = 1; plaquette_energy = measure_gauge_action(); if (g_proc_id == 0) { printf("# The plaquette value after stouting is %e\n", plaquette_energy / (6.*VOLUME*g_nproc)); fflush(stdout); } } source_spinor_field(g_spinor_field[0], g_spinor_field[1], 0, 0); convert_eo_to_lexic(g_spinor_field[DUM_DERI], g_spinor_field[0], g_spinor_field[1]); D_psi(g_spinor_field[DUM_DERI+1], g_spinor_field[DUM_DERI]); if(even_odd_flag) { i = invert_eo(g_spinor_field[2], g_spinor_field[3], g_spinor_field[0], g_spinor_field[1], solver_precision, max_solver_iterations, solver_flag, g_relative_precision_flag, sub_evs_cg_flag, even_odd_flag); convert_eo_to_lexic(g_spinor_field[DUM_DERI+1], g_spinor_field[2], g_spinor_field[3]); } for(i = 0; i < 3*LX/2+T/2; i++){ norm[i] = 0.; } for(x = 0; x < LX; x++){ if(x > LX/2) X = LX-x; else X = x; for(y = 0; y < LY; y++){ if(y > LY/2) Y = LY-y; else Y = y; for(z = 0; z < LZ; z++){ if(z > LZ/2) Z = LZ-z; else Z = z; for(t = 0; t < T; t++){ if(t > T/2) tt = T - t; else tt = t; sum = X + Y + Z + tt; _spinor_norm_sq(nrm, g_spinor_field[DUM_DERI+1][ g_ipt[t][x][y][z] ]); /* _spinor_norm_sq(nrm, qprop[0][0][1][ g_ipt[t][x][y][z] ]); */ printf("%e %e\n", g_spinor_field[DUM_DERI+1][ g_ipt[t][x][y][z] ].s0.c0.re, g_spinor_field[DUM_DERI+1][ g_ipt[t][x][y][z] ].s0.c0.im); nrm = sqrt( nrm ); printf("%1.12e\n", nrm); if(nrm > norm[sum]) norm[sum] = nrm; } } } } for(i = 0; i < 3*L/2+T/2; i++){ printf("%d %1.12e\n", i, norm[i]); } printf("\n"); nstore+=Nsave; } #ifdef MPI MPI_Finalize(); #endif free_gauge_field(); free_geometry_indices(); free_spinor_field(); free_moment_field(); return(0); #ifdef _KOJAK_INST #pragma pomp inst end(main) #endif }
void online_measurement(const int traj, const int id, const int ieo) { int i, j, t, tt, t0; double *Cpp = NULL, *Cpa = NULL, *Cp4 = NULL; double res = 0., respa = 0., resp4 = 0.; double atime, etime; float tmp; operator * optr; #ifdef MPI double mpi_res = 0., mpi_respa = 0., mpi_resp4 = 0.; // send buffer for MPI_Gather double *sCpp = NULL, *sCpa = NULL, *sCp4 = NULL; #endif FILE *ofs; char *filename; char buf[100]; spinor phi; filename=buf; sprintf(filename,"%s%.6d", "onlinemeas." ,traj); init_operators(); if(no_operators < 1 && g_proc_id == 0) { if(g_proc_id == 0) { fprintf(stderr, "Warning! no operators defined in input file, cannot perform online correlator mesurements!\n"); } return; } if(no_operators > 1 && g_proc_id == 0) { fprintf(stderr, "Warning! number of operators defined larger than 1, using only the first!\n"); } optr = &operator_list[0]; // we don't want to do inversion twice for this purpose here optr->DownProp = 0; if(optr->type != TMWILSON && optr->type != WILSON && optr->type != CLOVER) { if(g_proc_id == 0) { fprintf(stderr, "Warning! correlator online measurement currently only implemented for TMWILSON, WILSON and CLOVER\n"); fprintf(stderr, "Cannot perform online measurement!\n"); } return; } /* generate random timeslice */ if(ranlxs_init == 0) { rlxs_init(1, 123456); } ranlxs(&tmp, 1); t0 = (int)(measurement_list[id].max_source_slice*tmp); #ifdef MPI MPI_Bcast(&t0, 1, MPI_INT, 0, MPI_COMM_WORLD); #endif if(g_debug_level > 1 && g_proc_id == 0) { printf("# timeslice set to %d (T=%d) for online measurement\n", t0, g_nproc_t*T); printf("# online measurements parameters: kappa = %g, mu = %g\n", g_kappa, g_mu/2./g_kappa); } atime = gettime(); #ifdef MPI sCpp = (double*) calloc(T, sizeof(double)); sCpa = (double*) calloc(T, sizeof(double)); sCp4 = (double*) calloc(T, sizeof(double)); if(g_mpi_time_rank == 0) { Cpp = (double*) calloc(g_nproc_t*T, sizeof(double)); Cpa = (double*) calloc(g_nproc_t*T, sizeof(double)); Cp4 = (double*) calloc(g_nproc_t*T, sizeof(double)); } #else Cpp = (double*) calloc(T, sizeof(double)); Cpa = (double*) calloc(T, sizeof(double)); Cp4 = (double*) calloc(T, sizeof(double)); #endif source_generation_pion_only(g_spinor_field[0], g_spinor_field[1], t0, 0, traj); optr->sr0 = g_spinor_field[0]; optr->sr1 = g_spinor_field[1]; optr->prop0 = g_spinor_field[2]; optr->prop1 = g_spinor_field[3]; // op_id = 0, index_start = 0, write_prop = 0 optr->inverter(0, 0, 0); /* now we bring it to normal format */ /* here we use implicitly DUM_MATRIX and DUM_MATRIX+1 */ convert_eo_to_lexic(g_spinor_field[DUM_MATRIX], g_spinor_field[2], g_spinor_field[3]); /* now we sum only over local space for every t */ for(t = 0; t < T; t++) { j = g_ipt[t][0][0][0]; res = 0.; respa = 0.; resp4 = 0.; for(i = j; i < j+LX*LY*LZ; i++) { res += _spinor_prod_re(g_spinor_field[DUM_MATRIX][j], g_spinor_field[DUM_MATRIX][j]); _gamma0(phi, g_spinor_field[DUM_MATRIX][j]); respa += _spinor_prod_re(g_spinor_field[DUM_MATRIX][j], phi); _gamma5(phi, phi); resp4 += _spinor_prod_im(g_spinor_field[DUM_MATRIX][j], phi); } #if defined MPI MPI_Reduce(&res, &mpi_res, 1, MPI_DOUBLE, MPI_SUM, 0, g_mpi_time_slices); res = mpi_res; MPI_Reduce(&respa, &mpi_respa, 1, MPI_DOUBLE, MPI_SUM, 0, g_mpi_time_slices); respa = mpi_respa; MPI_Reduce(&resp4, &mpi_resp4, 1, MPI_DOUBLE, MPI_SUM, 0, g_mpi_time_slices); resp4 = mpi_resp4; sCpp[t] = +res/(g_nproc_x*LX)/(g_nproc_y*LY)/(g_nproc_z*LZ)*2.; sCpa[t] = -respa/(g_nproc_x*LX)/(g_nproc_y*LY)/(g_nproc_z*LZ)*2.; sCp4[t] = +resp4/(g_nproc_x*LX)/(g_nproc_y*LY)/(g_nproc_z*LZ)*2.; #else Cpp[t] = +res/(g_nproc_x*LX)/(g_nproc_y*LY)/(g_nproc_z*LZ)*2.; Cpa[t] = -respa/(g_nproc_x*LX)/(g_nproc_y*LY)/(g_nproc_z*LZ)*2.; Cp4[t] = +resp4/(g_nproc_x*LX)/(g_nproc_y*LY)/(g_nproc_z*LZ)*2.; #endif } #ifdef MPI /* some gymnastics needed in case of parallelisation */ if(g_mpi_time_rank == 0) { MPI_Gather(sCpp, T, MPI_DOUBLE, Cpp, T, MPI_DOUBLE, 0, g_mpi_SV_slices); MPI_Gather(sCpa, T, MPI_DOUBLE, Cpa, T, MPI_DOUBLE, 0, g_mpi_SV_slices); MPI_Gather(sCp4, T, MPI_DOUBLE, Cp4, T, MPI_DOUBLE, 0, g_mpi_SV_slices); } #endif /* and write everything into a file */ if(g_mpi_time_rank == 0 && g_proc_coords[0] == 0) { ofs = fopen(filename, "w"); fprintf( ofs, "1 1 0 %e %e\n", Cpp[t0], 0.); for(t = 1; t < g_nproc_t*T/2; t++) { tt = (t0+t)%(g_nproc_t*T); fprintf( ofs, "1 1 %d %e ", t, Cpp[tt]); tt = (t0+g_nproc_t*T-t)%(g_nproc_t*T); fprintf( ofs, "%e\n", Cpp[tt]); } tt = (t0+g_nproc_t*T/2)%(g_nproc_t*T); fprintf( ofs, "1 1 %d %e %e\n", t, Cpp[tt], 0.); fprintf( ofs, "2 1 0 %e %e\n", Cpa[t0], 0.); for(t = 1; t < g_nproc_t*T/2; t++) { tt = (t0+t)%(g_nproc_t*T); fprintf( ofs, "2 1 %d %e ", t, Cpa[tt]); tt = (t0+g_nproc_t*T-t)%(g_nproc_t*T); fprintf( ofs, "%e\n", Cpa[tt]); } tt = (t0+g_nproc_t*T/2)%(g_nproc_t*T); fprintf( ofs, "2 1 %d %e %e\n", t, Cpa[tt], 0.); fprintf( ofs, "6 1 0 %e %e\n", Cp4[t0], 0.); for(t = 1; t < g_nproc_t*T/2; t++) { tt = (t0+t)%(g_nproc_t*T); fprintf( ofs, "6 1 %d %e ", t, Cp4[tt]); tt = (t0+g_nproc_t*T-t)%(g_nproc_t*T); fprintf( ofs, "%e\n", Cp4[tt]); } tt = (t0+g_nproc_t*T/2)%(g_nproc_t*T); fprintf( ofs, "6 1 %d %e %e\n", t, Cp4[tt], 0.); fclose(ofs); } #ifdef MPI if(g_mpi_time_rank == 0) { free(Cpp); free(Cpa); free(Cp4); } free(sCpp); free(sCpa); free(sCp4); #else free(Cpp); free(Cpa); free(Cp4); #endif etime = gettime(); if(g_proc_id == 0 && g_debug_level > 0) { printf("ONLINE: measurement done int t/s = %1.4e\n", etime - atime); } return; }
int invert_doublet_eo_quda(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, const int even_odd_flag, const SloppyPrecision sloppy_precision, CompressionType compression) { spinor ** solver_field = NULL; const int nr_sf = 4; init_solver_field(&solver_field, VOLUMEPLUSRAND, nr_sf); convert_eo_to_lexic(solver_field[0], Even_s, Odd_s); convert_eo_to_lexic(solver_field[1], Even_c, Odd_c); // convert_eo_to_lexic(g_spinor_field[DUM_DERI+1], Even_new, Odd_new); void *spinorIn = (void*)solver_field[0]; // source void *spinorIn_c = (void*)solver_field[1]; // charme source void *spinorOut = (void*)solver_field[2]; // solution void *spinorOut_c = (void*)solver_field[3]; // charme solution if ( rel_prec ) inv_param.residual_type = QUDA_L2_RELATIVE_RESIDUAL; else inv_param.residual_type = QUDA_L2_ABSOLUTE_RESIDUAL; inv_param.kappa = g_kappa; // IMPORTANT: use opposite TM mu-flavor since gamma5 -> -gamma5 inv_param.mu = -g_mubar /2./g_kappa; inv_param.epsilon = g_epsbar/2./g_kappa; // figure out which BC to use (theta, trivial...) set_boundary_conditions(&compression); // set the sloppy precision of the mixed prec solver set_sloppy_prec(sloppy_precision); // load gauge after setting precision _loadGaugeQuda(compression); // choose dslash type if( g_c_sw > 0.0 ) { inv_param.dslash_type = QUDA_TWISTED_CLOVER_DSLASH; inv_param.matpc_type = QUDA_MATPC_EVEN_EVEN; inv_param.solution_type = QUDA_MAT_SOLUTION; inv_param.clover_order = QUDA_PACKED_CLOVER_ORDER; inv_param.clover_coeff = g_c_sw*g_kappa; } else { inv_param.dslash_type = QUDA_TWISTED_MASS_DSLASH; inv_param.matpc_type = QUDA_MATPC_EVEN_EVEN_ASYMMETRIC; inv_param.solution_type = QUDA_MAT_SOLUTION; } // choose solver if(solver_flag == BICGSTAB) { if(g_proc_id == 0) {printf("# QUDA: Using BiCGstab!\n"); fflush(stdout);} inv_param.inv_type = QUDA_BICGSTAB_INVERTER; } else { /* Here we invert the hermitean operator squared */ inv_param.inv_type = QUDA_CG_INVERTER; if(g_proc_id == 0) { printf("# QUDA: Using mixed precision CG!\n"); printf("# QUDA: mu = %f, kappa = %f\n", g_mu/2./g_kappa, g_kappa); fflush(stdout); } } if( even_odd_flag ) { inv_param.solve_type = QUDA_NORMOP_PC_SOLVE; if(g_proc_id == 0) printf("# QUDA: Using preconditioning!\n"); } else { inv_param.solve_type = QUDA_NORMOP_SOLVE; if(g_proc_id == 0) printf("# QUDA: Not using preconditioning!\n"); } inv_param.tol = sqrt(precision)*0.25; inv_param.maxiter = max_iter; inv_param.twist_flavor = QUDA_TWIST_NONDEG_DOUBLET; inv_param.Ls = 2; // NULL pointers to host fields to force // construction instead of download of the clover field: if( g_c_sw > 0.0 ) loadCloverQuda(NULL, NULL, &inv_param); // reorder spinor reorder_spinor_toQuda( (double*)spinorIn, inv_param.cpu_prec, 1, (double*)spinorIn_c ); // perform the inversion invertQuda(spinorOut, spinorIn, &inv_param); if( inv_param.verbosity == QUDA_VERBOSE ) if(g_proc_id == 0) printf("# QUDA: Device memory used: Spinor: %f GiB, Gauge: %f GiB, Clover: %f GiB\n", inv_param.spinorGiB, gauge_param.gaugeGiB, inv_param.cloverGiB); if( inv_param.verbosity > QUDA_SILENT ) if(g_proc_id == 0) printf("# QUDA: Done: %i iter / %g secs = %g Gflops\n", inv_param.iter, inv_param.secs, inv_param.gflops/inv_param.secs); // number of CG iterations int iteration = inv_param.iter; // reorder spinor reorder_spinor_fromQuda( (double*)spinorIn, inv_param.cpu_prec, 1, (double*)spinorIn_c ); reorder_spinor_fromQuda( (double*)spinorOut, inv_param.cpu_prec, 1, (double*)spinorOut_c ); convert_lexic_to_eo(Even_s, Odd_s, solver_field[0]); convert_lexic_to_eo(Even_c, Odd_c, solver_field[1]); convert_lexic_to_eo(Even_new_s, Odd_new_s, solver_field[2]); convert_lexic_to_eo(Even_new_c, Odd_new_c, solver_field[3]); finalize_solver(solver_field, nr_sf); freeGaugeQuda(); if(iteration >= max_iter) return(-1); return(iteration); }
void pion_norm(const int traj, const int id) { int i, j, z, zz, z0; double *Cpp; double res = 0.; double pionnorm; double atime, etime; float tmp; #ifdef MPI double mpi_res = 0.; #endif FILE *ofs, *ofs2; char *filename, *filename2, *sourcefilename; char buf[100]; char buf2[100]; char buf3[100]; filename=buf; filename2=buf2; sourcefilename=buf3; sprintf(filename,"pionnormcorrelator_finiteT.%.6d",traj); sprintf(filename2,"%s", "pion_norm.data"); /* generate random source point */ if(ranlxs_init == 0) { rlxs_init(1, 123456); } ranlxs(&tmp, 1); z0 = (int)(measurement_list[id].max_source_slice*tmp); #ifdef MPI MPI_Bcast(&z0, 1, MPI_INT, 0, MPI_COMM_WORLD); #endif #ifdef MPI atime = MPI_Wtime(); #else atime = (double)clock()/(double)(CLOCKS_PER_SEC); #endif Cpp = (double*) calloc(g_nproc_z*LZ, sizeof(double)); printf("Doing finite Temperature online measurement\n"); /* stochastic source in z-slice */ source_generation_pion_zdir(g_spinor_field[0], g_spinor_field[1], z0, 0, traj); /* invert on the stochastic source */ invert_eo(g_spinor_field[2], g_spinor_field[3], g_spinor_field[0], g_spinor_field[1], 1.e-14, measurement_list[id].max_iter, CG, 1, 0, 1, 0, NULL, -1); /* now we bring it to normal format */ /* here we use implicitly DUM_MATRIX and DUM_MATRIX+1 */ convert_eo_to_lexic(g_spinor_field[DUM_MATRIX], g_spinor_field[2], g_spinor_field[3]); /* now we sums only over local space for every z */ for(z = 0; z < LZ; z++) { res = 0.; /* sum here over all points in one z-slice we have to look up g_ipt*/ j = g_ipt[0][0][0][z]; for(i = 0; i < T*LX*LY ; i++) { res += _spinor_prod_re(g_spinor_field[DUM_MATRIX][j], g_spinor_field[DUM_MATRIX][j]); j += LZ; /* jump LZ sites in array, z ist fastest index */ } #if defined MPI MPI_Reduce(&res, &mpi_res, 1, MPI_DOUBLE, MPI_SUM, 0, g_mpi_z_slices); res = mpi_res; #endif Cpp[z+g_proc_coords[3]*LZ] = +res/(g_nproc_x*LX)/(g_nproc_y*LY)/(g_nproc_t*T)*2.; } #ifdef MPI /* some gymnastics needed in case of parallelisation */ if(g_mpi_z_rank == 0) { MPI_Gather(&Cpp[g_proc_coords[3]*LZ], LZ, MPI_DOUBLE, Cpp, LZ, MPI_DOUBLE, 0, g_mpi_ST_slices); } #endif /* and write everything into a file */ if(g_mpi_z_rank == 0 && g_proc_coords[3] == 0) { ofs = fopen(filename, "w"); fprintf( ofs, "1 1 0 %e %e\n", Cpp[z0], 0.); for(z = 1; z < g_nproc_z*LZ/2; z++) { zz = (z0+z)%(g_nproc_z*LZ); fprintf( ofs, "1 1 %d %e ", z, Cpp[zz]); zz = (z0+g_nproc_z*LZ-z)%(g_nproc_z*LZ); fprintf( ofs, "%e\n", Cpp[zz]); } zz = (z0+g_nproc_z*LZ/2)%(g_nproc_z*LZ); fprintf( ofs, "1 1 %d %e %e\n", z, Cpp[zz], 0.); fclose(ofs); /* sum over all Cpp to get pionnorm*/ ofs2 = fopen(filename2, "a"); pionnorm = 0.; for(z=0; z<g_nproc_z*LZ; z++){ pionnorm += Cpp[z]; } /* normalize */ pionnorm = pionnorm/(g_nproc_z*LZ); fprintf(ofs2,"%d\t %.16e\n",traj,pionnorm); fclose(ofs2); } free(Cpp); #ifdef MPI etime = MPI_Wtime(); #else etime = (double)clock()/(double)(CLOCKS_PER_SEC); #endif if(g_proc_id == 0 && g_debug_level > 0) { printf("PIONNORM : measurement done int t/s = %1.4e\n", etime - atime); } return; }
void online_measurement(const int traj, const int id) { int i, j, t, tt, t0; double *Cpp, *Cpa, *Cp4; double res = 0., respa = 0., resp4 = 0.; double atime, etime; float tmp; #ifdef MPI double mpi_res = 0., mpi_respa = 0., mpi_resp4 = 0.; #endif FILE *ofs; char *filename; char buf[100]; spinor phi; filename=buf; sprintf(filename,"%s%.6d", "onlinemeas." ,traj); /* generate random timeslice */ if(ranlxs_init == 0) { rlxs_init(1, 123456); } ranlxs(&tmp, 1); t0 = (int)(measurement_list[id].max_source_slice*tmp); #ifdef MPI MPI_Bcast(&t0, 1, MPI_INT, 0, MPI_COMM_WORLD); #endif if(g_debug_level > 1 && g_proc_id == 0) { printf("# timeslice set to %d (T=%d) for online measurement\n", t0, g_nproc_t*T); printf("# online measurements parameters: kappa = %g, mu = %g\n", g_kappa, g_mu/2./g_kappa); } #ifdef MPI atime = MPI_Wtime(); #else atime = (double)clock()/(double)(CLOCKS_PER_SEC); #endif Cpp = (double*) calloc(g_nproc_t*T, sizeof(double)); Cpa = (double*) calloc(g_nproc_t*T, sizeof(double)); Cp4 = (double*) calloc(g_nproc_t*T, sizeof(double)); source_generation_pion_only(g_spinor_field[0], g_spinor_field[1], t0, 0, traj); invert_eo(g_spinor_field[2], g_spinor_field[3], g_spinor_field[0], g_spinor_field[1], 1.e-14, measurement_list[id].max_iter, CG, 1, 0, 1, 0, NULL, -1); /* now we bring it to normal format */ /* here we use implicitly DUM_MATRIX and DUM_MATRIX+1 */ convert_eo_to_lexic(g_spinor_field[DUM_MATRIX], g_spinor_field[2], g_spinor_field[3]); /* now we sum only over local space for every t */ for(t = 0; t < T; t++) { j = g_ipt[t][0][0][0]; res = 0.; respa = 0.; resp4 = 0.; for(i = j; i < j+LX*LY*LZ; i++) { res += _spinor_prod_re(g_spinor_field[DUM_MATRIX][j], g_spinor_field[DUM_MATRIX][j]); _gamma0(phi, g_spinor_field[DUM_MATRIX][j]); respa += _spinor_prod_re(g_spinor_field[DUM_MATRIX][j], phi); _gamma5(phi, phi); resp4 += _spinor_prod_im(g_spinor_field[DUM_MATRIX][j], phi); } #if defined MPI MPI_Reduce(&res, &mpi_res, 1, MPI_DOUBLE, MPI_SUM, 0, g_mpi_time_slices); res = mpi_res; MPI_Reduce(&respa, &mpi_respa, 1, MPI_DOUBLE, MPI_SUM, 0, g_mpi_time_slices); respa = mpi_respa; MPI_Reduce(&resp4, &mpi_resp4, 1, MPI_DOUBLE, MPI_SUM, 0, g_mpi_time_slices); resp4 = mpi_resp4; #endif Cpp[t+g_proc_coords[0]*T] = +res/(g_nproc_x*LX)/(g_nproc_y*LY)/(g_nproc_z*LZ)*2.; Cpa[t+g_proc_coords[0]*T] = -respa/(g_nproc_x*LX)/(g_nproc_y*LY)/(g_nproc_z*LZ)*2.; Cp4[t+g_proc_coords[0]*T] = +resp4/(g_nproc_x*LX)/(g_nproc_y*LY)/(g_nproc_z*LZ)*2.; } #ifdef MPI /* some gymnastics needed in case of parallelisation */ if(g_mpi_time_rank == 0) { MPI_Gather(&Cpp[g_proc_coords[0]*T], T, MPI_DOUBLE, Cpp, T, MPI_DOUBLE, 0, g_mpi_SV_slices); MPI_Gather(&Cpa[g_proc_coords[0]*T], T, MPI_DOUBLE, Cpa, T, MPI_DOUBLE, 0, g_mpi_SV_slices); MPI_Gather(&Cp4[g_proc_coords[0]*T], T, MPI_DOUBLE, Cp4, T, MPI_DOUBLE, 0, g_mpi_SV_slices); } #endif /* and write everything into a file */ if(g_mpi_time_rank == 0 && g_proc_coords[0] == 0) { ofs = fopen(filename, "w"); fprintf( ofs, "1 1 0 %e %e\n", Cpp[t0], 0.); for(t = 1; t < g_nproc_t*T/2; t++) { tt = (t0+t)%(g_nproc_t*T); fprintf( ofs, "1 1 %d %e ", t, Cpp[tt]); tt = (t0+g_nproc_t*T-t)%(g_nproc_t*T); fprintf( ofs, "%e\n", Cpp[tt]); } tt = (t0+g_nproc_t*T/2)%(g_nproc_t*T); fprintf( ofs, "1 1 %d %e %e\n", t, Cpp[tt], 0.); fprintf( ofs, "2 1 0 %e %e\n", Cpa[t0], 0.); for(t = 1; t < g_nproc_t*T/2; t++) { tt = (t0+t)%(g_nproc_t*T); fprintf( ofs, "2 1 %d %e ", t, Cpa[tt]); tt = (t0+g_nproc_t*T-t)%(g_nproc_t*T); fprintf( ofs, "%e\n", Cpa[tt]); } tt = (t0+g_nproc_t*T/2)%(g_nproc_t*T); fprintf( ofs, "2 1 %d %e %e\n", t, Cpa[tt], 0.); fprintf( ofs, "6 1 0 %e %e\n", Cp4[t0], 0.); for(t = 1; t < g_nproc_t*T/2; t++) { tt = (t0+t)%(g_nproc_t*T); fprintf( ofs, "6 1 %d %e ", t, Cp4[tt]); tt = (t0+g_nproc_t*T-t)%(g_nproc_t*T); fprintf( ofs, "%e\n", Cp4[tt]); } tt = (t0+g_nproc_t*T/2)%(g_nproc_t*T); fprintf( ofs, "6 1 %d %e %e\n", t, Cp4[tt], 0.); fclose(ofs); } free(Cpp); free(Cpa); free(Cp4); #ifdef MPI etime = MPI_Wtime(); #else etime = (double)clock()/(double)(CLOCKS_PER_SEC); #endif if(g_proc_id == 0 && g_debug_level > 0) { printf("ONLINE: measurement done int t/s = %1.4e\n", etime - atime); } return; }
/* 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); }
/* 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]); } }
/* saves the operator to the given filename */ void ov_save_12x12(const char * pFileName) { int i, j, k, x, y, z, t; spinor *s[4][3]; matrix12x12 mat; FILE * pCompare; /* evaluate Dov(psi) */ for (i=0; i<4; i++) for (j=0; j<3; j++) { /* get memory for the spinor */ s[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]); /* apply Dov */ Dov_psi(s[i][j], g_spinor_field[2]); } /* open file for storing the operator */ pCompare = fopen(pFileName, "w"); if (pCompare == NULL) { fprintf(stderr, "Error: could not open '%s' for writing the operator\n", pFileName); exit(1); } for(t = 0; t < T; t++){ for(x = 0; x < LX; x++){ for(y = 0; y < LY; y++){ for(z=0; z<LZ; z++) { k = g_ipt[t][x][y][z]; for (j=0; j<3; j++) for (i=0; i<4; i++) { mat[0][i+4*j] = s[i][j][k].s0.c0; mat[1][i+4*j] = s[i][j][k].s1.c0; mat[2][i+4*j] = s[i][j][k].s2.c0; mat[3][i+4*j] = s[i][j][k].s3.c0; mat[4][i+4*j] = s[i][j][k].s0.c1; mat[5][i+4*j] = s[i][j][k].s0.c1; mat[6][i+4*j] = s[i][j][k].s1.c1; mat[7][i+4*j] = s[i][j][k].s2.c1; mat[8][i+4*j] = s[i][j][k].s3.c2; mat[9][i+4*j] = s[i][j][k].s1.c2; mat[10][i+4*j] = s[i][j][k].s2.c2; mat[11][i+4*j] = s[i][j][k].s3.c2; } for (i=0;i<12; i++) for (j=0; j<12; j++) fprintf(pCompare, "%.20le %.20le ", creal(mat[i][j]), cimag(mat[i][j])); } } } } /* close file */ fclose(pCompare); /* free memory */ for (i=0; i<4; i++) for (j=0; j<3; j++) ov_free_spinor(s[i][j]); }
/* compares the operator with the one given in pFileName */ void ov_compare_12x12(const char * pFileName) { double norm, rel, *max_rel, *max_abs, Max_rel = 0.0, Max_abs = 0.0; int i, j, k, x, x_taxi, y, y_taxi, z, z_taxi, t, t_taxi, maxtaxi, taxi; spinor *s[4][3]; matrix12x12 mat, mat2, diff; FILE * pCompare; /* evaluate Dov(psi) */ for (i=0; i<4; i++) for (j=0; j<3; j++) { /* get memory for the spinor */ s[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]); /* apply Dov */ Dov_psi(s[i][j], g_spinor_field[2]); } /* init locality table */ maxtaxi = (LX/2)+(LY/2)+(LZ/2)+T/2; max_abs = (double*)calloc(maxtaxi+1, sizeof(double)); max_rel = (double*)calloc(maxtaxi+1, sizeof(double)); for(i = 0; i <= maxtaxi; i++) { max_abs[i] = 0.0; max_rel[i] = 0.0; } /* open file containing operator for comparison */ pCompare = fopen(pFileName, "r"); if (pCompare == NULL) { fprintf(stderr, "Error: could not open '%s' for comparison of operator\n", pFileName); exit(1); } /* fill locality table */ if (g_debug_level > 0) { printf("// beginning comparison\n"); fflush(stdout); } for(t = 0; t < T; t++){ t_taxi = (t > T/2) ? T - t : t; for(x = 0; x < LX; x++){ x_taxi = (x > LX/2) ? LX-x : x; for(y = 0; y < LY; y++){ y_taxi = (y > LY/2) ? LY-y : y; for(z=0; z<LZ; z++) { z_taxi = (z > LZ/2) ? LZ-z : z; taxi = x_taxi + y_taxi + z_taxi + t_taxi; k = g_ipt[t][x][y][z]; for (j=0; j<3; j++) for (i=0; i<4; i++) { mat[0][i+4*j] = s[i][j][k].s0.c0; mat[1][i+4*j] = s[i][j][k].s1.c0; mat[2][i+4*j] = s[i][j][k].s2.c0; mat[3][i+4*j] = s[i][j][k].s3.c0; mat[4][i+4*j] = s[i][j][k].s0.c1; mat[5][i+4*j] = s[i][j][k].s0.c1; mat[6][i+4*j] = s[i][j][k].s1.c1; mat[7][i+4*j] = s[i][j][k].s2.c1; mat[8][i+4*j] = s[i][j][k].s3.c2; mat[9][i+4*j] = s[i][j][k].s1.c2; mat[10][i+4*j] = s[i][j][k].s2.c2; mat[11][i+4*j] = s[i][j][k].s3.c2; } for (i=0;i<12; i++) for (j=0; j<12; j++) fscanf(pCompare, "%le %le", (double*)&mat2[i][j], (double*)&mat2[i][j] + 1); ov_matrix12x12_diff(diff, mat, mat2); /* statistics */ norm = ov_matrix12x12_rowsumnorm(diff); if (norm > max_abs[taxi]) { max_abs[taxi] = norm; if (norm > Max_abs) Max_abs = norm; } rel = (ov_matrix12x12_rowsumnorm(mat) + ov_matrix12x12_rowsumnorm(mat2))/2; if (rel>0.0) { rel = norm/rel; if (rel > max_rel[taxi]) { max_rel[taxi] = rel; if (rel > Max_rel) Max_rel = rel; } } } } } } /* print locality table */ printf("// comparison of overlap operator to %s\n", pFileName); printf(" - maximum absolute deviation: %.4le\n", Max_abs); printf(" - maximum relative deviation: %.4le\n", Max_rel); printf("// taxi | max abs | max rel\n"); for(i = 0; i <= maxtaxi; i++) printf("%7d %10.6le %10.6le\n", i, max_abs[i], max_rel[i]); printf("\n"); /* close file */ fclose(pCompare); /* free memory */ free(max_abs); free(max_rel); for (i=0; i<4; i++) for (j=0; j<3; j++) ov_free_spinor(s[i][j]); }
void ov_check_locality() { double norm, *maxnorm, *minnorm, *avgnorm; int i, j, k, x, x_taxi, y, y_taxi, z, z_taxi, t, t_taxi, maxtaxi, *samples, taxi; spinor *s[4][3]; /* evaluate Dov(psi) */ for (i=0; i<4; i++) for (j=0; j<3; j++) { /* get memory for the spinor */ s[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]); /* apply Dov */ Dov_psi(s[i][j], g_spinor_field[2]); } /* init locality table */ maxtaxi = (LX/2)+(LY/2)+(LZ/2)+T/2; maxnorm = (double*)calloc(maxtaxi+1, sizeof(double)); minnorm = (double*)calloc(maxtaxi+1, sizeof(double)); avgnorm = (double*)calloc(maxtaxi+1, sizeof(double)); samples = (int*)calloc(maxtaxi+1, sizeof(int)); for(i = 0; i <= maxtaxi; i++) { maxnorm[i] = 0.; minnorm[i] = 1.0e100; avgnorm[i] = 0.; samples[i] = 0; } /* fill locality table */ printf("// beginning locality test\n"); for(x=0; x<LX; x++) { x_taxi = (x > LX/2) ? LX-x : x; for(y = 0; y < LY; y++){ y_taxi = (y > LY/2) ? LY-y : y; for(z = 0; z < LZ; z++){ z_taxi = (z > LZ/2) ? LZ-z : z; for(t = 0; t < T; t++){ t_taxi = (t > T/2) ? T - t : t; taxi = x_taxi + y_taxi + z_taxi + t_taxi; k = g_ipt[t][x][y][z]; norm = ov_operator_colsumnorm(s, k); // statistics if (norm > maxnorm[taxi]) maxnorm[taxi] = norm; if (norm < minnorm[taxi]) minnorm[taxi] = norm; avgnorm[taxi] += norm; samples[taxi]++; } } } } /* print locality table */ printf("// locality check of overlap operator\n"); printf("// taxi | max norm | avg norm | min norm | #samples\n"); for(i = 0; i <= maxtaxi; i++) printf("%7d %10.6le %10.6le %10.6le %8d\n", i, maxnorm[i], (double)(avgnorm[i]/samples[i]), minnorm[i], samples[i]); printf("\n"); /* free memory */ free(maxnorm); free(minnorm); free(avgnorm); free(samples); for (i=0; i<4; i++) for (j=0; j<3; j++) ov_free_spinor(s[i][j]); }