#include #include #include #include #ifdef PARALLEL #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_BFM #include #endif #define HAVE_DOEXT USING_NAMESPACE_CPS static const char* cname = ""; // global argument structures DoArg do_arg; #ifdef HAVE_DOEXT DoArgExt doext_arg; #endif EvoArg evo_arg; void setup(int argc, char **argv); void load_checkpoint(int traj); #ifdef USE_BFM void init_bfm(int* argc, char ***argv, int nthrds); #endif inline int Chdir(const char* dir) { const char *fname = "Chdir(char*)"; if(chdir(dir)!=0){ ERR.General(cname, fname, "Cannot change directory to %s\n", dir); } return 0; } // link_perturbation_magnitude should be a small number, say 1e-5 // The smaller the perturbation the better the agreement you can // expect between the force and the numerical derivative of the action. void test_force(AlgActionEOFA& integrator, Float link_perturbation_size) { const char* fname = "test_force"; VRB.Result(cname, fname, "Comparing force to numerical derivative of action.\n"); VRB.Result(cname, fname, "link_perturbation_size = %e\n", link_perturbation_size); // integrator.init(); integrator.heatbath(); Float ham_initial = integrator.energy(); glb_sum(&ham_initial); // compute force on each link int num_links = 4*GJP.VolNodeSites(); Matrix *force = (Matrix*) smalloc(num_links*sizeof(Matrix), "force", fname, cname); for(int i=0; iTrLessAntiHermMatrix(); } { GnoneFnone lat; // U_{x,u} = exp(link_perturbation) * U_{x,u} lat.EvolveGfield(link_perturbation, 1.0); } // The force is supposed to be the derivative of the energy with respect // to the links, so we can use it to predict the change in the action // under the given perturbation of the links. // predicted change = -Tr [link_perturbation * T^a d^a_x,u f] Float predicted_change = 0.0; for(int i=0; i nrow(Nd); for(int i=0; i procs = QDP::Layout::logicalSize(); multi1d ncoor = QDP::Layout::nodeCoord(); for(int i=0; i<4; ++i){ bfm_arg.ncoor[i] = ncoor[i]; } bfm_arg.local_comm[0] = procs[0] > 1 ? 0 : 1; bfm_arg.local_comm[1] = procs[1] > 1 ? 0 : 1; bfm_arg.local_comm[2] = procs[2] > 1 ? 0 : 1; bfm_arg.local_comm[3] = procs[3] > 1 ? 0 : 1; if(GJP.Gparity()){ bfm_arg.gparity = 1; if(!UniqueID()){ printf("G-parity directions: "); } for(int d=0; d<3; d++){ if(GJP.Bc(d) == BND_CND_GPARITY){ bfm_arg.gparity_dir[d] = 1; if(!UniqueID()){ printf("%d ", d); } } } for(int d=0; d<4; d++){ bfm_arg.nodes[d] = procs[d]; } if(!UniqueID()){ printf("\n"); } } // mobius scale = b + c in Andrew's notation #ifdef USE_NEW_BFM_GPARITY bfm_arg.mobius_scale = 1.0; #else bfmarg::mobius_scale = 1.0; #endif bfmarg::Threads(nthrds); bfmarg::Reproduce(0); bfmarg::ReproduceChecksum(0); bfmarg::ReproduceMasterCheck(0); bfmarg::Verbose(0); } #endif