Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

alg_hmc.C

Go to the documentation of this file.
00001 #include<config.h>
00002 CPS_START_NAMESPACE 
00003 //------------------------------------------------------------------
00009 //------------------------------------------------------------------
00010 //
00011 // alg_hmc.C
00012 //
00013 // AlgHmc is an abstract implementation of the Hybrid Monte Carlo
00014 // Algorithm.
00015 //
00016 //------------------------------------------------------------------
00017 
00018 CPS_END_NAMESPACE
00019 #include<math.h>
00020 #include<alg/alg_hmc.h>
00021 #include<alg/alg_meas.h>
00022 #include<comms/glb.h>
00023 #include <util/checksum.h>
00024 #include<util/data_shift.h>
00025 #include<util/error.h>
00026 #include<util/gjp.h>
00027 #include<util/lattice.h>
00028 #include<util/vector.h>
00029 #include<util/verbose.h>
00030 #include<util/smalloc.h>
00031 #include<util/qcdio.h>
00032 #include<util/wilson.h>
00033 
00034 #ifdef HAVE_STRINGS_H
00035 #include <strings.h>
00036 #endif
00037 #ifdef HAVE_QCDOCOS_SCU_CHECKSUM_H
00038 #include <qcdocos/scu_checksum.h>
00039 #endif
00040 CPS_START_NAMESPACE
00041 
00042 //#if (TARGET==QCDOC) || (TARGET==BGP)
00043 #if (TARGET==QCDOC) 
00044 static const int SHIFT_X = 1;
00045 static const int SHIFT_Y = 1;
00046 static const int SHIFT_Z = 1;
00047 #else
00048 static const int SHIFT_X = 0;
00049 static const int SHIFT_Y = 0;
00050 static const int SHIFT_Z = 0;
00051 #endif
00052 
00053 //------------------------------------------------------------------
00059 //------------------------------------------------------------------
00060 
00061 AlgHmc::AlgHmc(AlgIntAB &Integrator, CommonArg &c_arg, HmcArg &arg)
00062 {
00063   cname = "AlgHmc";
00064   char *fname = "AlgHmc(AlgIntAB*,CommonArg*,HmcArg*)";
00065   VRB.Func(cname,fname);
00066 
00067   integrator = &Integrator;
00068   hmc_arg = &arg;
00069   common_arg = &c_arg;
00070 
00071   {
00072     Lattice &lat = LatticeFactory::Create(F_CLASS_NONE, G_CLASS_NONE);
00073 
00074     g_size = GJP.VolNodeSites() * lat.GsiteSize();
00075 
00077     gauge_field_init = (Matrix *) smalloc(g_size * sizeof(Float), 
00078                                           cname,fname, "gauge_field_init");
00079     
00080     if (hmc_arg->reverse == REVERSE_YES) {
00081       
00083       gauge_field_final = (Matrix *) smalloc(g_size * sizeof(Float), 
00084                                              cname,fname, "gauge_field_final");
00085       
00086     }
00087 
00088     LatticeFactory::Destroy();
00089   }
00090 
00091 } 
00092 
00093 //------------------------------------------------------------------
00094 // Destructor
00095 //------------------------------------------------------------------
00096 AlgHmc::~AlgHmc() {
00097 
00098 //  int i,j;
00099   char *fname = "~AlgHmc()" ;
00100   VRB.Func(cname,fname);
00101 
00102   // Free memory for the initial gauge field.
00103   sfree(gauge_field_init, cname,fname, "gauge_field_init");
00104 
00105   if (hmc_arg->reverse == REVERSE_YES) {
00107     sfree(gauge_field_final, cname, fname, "gauge_field_final");
00108 
00109   }
00110 
00111 }
00112 
00113 
00114 //------------------------------------------------------------------
00115 //
00116 // run(): The Hybrid Monte Carlo algorithm.
00133 //------------------------------------------------------------------
00134 Float AlgHmc::run(void)
00135 {
00136 #if TARGET==cpsMPI
00137   using MPISCU::fprintf;
00138 #endif
00139 //  int step;                            // Trajectory step
00140   int accept;
00141 
00142   char *fname = "run()";
00143   FILE *fp;
00144   VRB.Func(cname,fname);
00145 
00146   Float dev = 0.0;
00147   Float max_diff = 0.0;
00148 
00149   Float acceptance;                            // The acceptance probability
00150   Float efficiency = 0.0;
00151 
00152 #ifdef HAVE_QCDOCOS_SCU_CHECKSUM_H
00153   if(!ScuChecksum::ChecksumsOn())
00154   ScuChecksum::Initialise(true,true);
00155 #endif
00156  
00157   // Set the microcanonical time step
00158 //  Float dt = hmc_arg->step_size;
00159 
00161   int Ntests = saveInitialState();
00162   VRB.Result(cname,fname,"shifts=%d %d %d\n",SHIFT_X,SHIFT_Y,SHIFT_Z);
00163 
00164   // Try attempt_limit times to generate the same final gauge config 
00165   // consecutively
00166   for (int attempt = 0; attempt < hmc_arg->reproduce_attempt_limit; attempt++) {
00167 
00168     for (int test = 0; test < Ntests; test++) {
00169       VRB.Result(cname,fname,"Running test %d of %d, attempt %d of %d\n", 
00170                  test+1, Ntests, attempt+1, hmc_arg->reproduce_attempt_limit);
00171 
00173       integrator->init();
00174 
00176       if ( !(test == 0 && attempt ==0) ){
00177         restoreInitialState();
00178         shiftStates(SHIFT_X,SHIFT_Y,SHIFT_Z,0);
00179         GDS.SetOrigin(SHIFT_X,SHIFT_Y,SHIFT_Z,0);
00180       }
00181 
00183       integrator->heatbath();
00184 
00186       wilson_set_sloppy( false);
00187       h_init = integrator->energy();
00188 //      Float total_h_init =h_init;
00189 //      glb_sum(&total_h_init);
00190 
00191       // Molecular Dynamics Trajectory
00192       if(hmc_arg->wfm_md_sloppy) wilson_set_sloppy(true);
00193       integrator->evolve(hmc_arg->step_size, hmc_arg->steps_per_traj);
00194       wilson_set_sloppy(false);
00195 
00196       // Reunitarize
00197       if(hmc_arg->reunitarize == REUNITARIZE_YES){
00198         Lattice &lat = LatticeFactory::Create(F_CLASS_NONE, G_CLASS_NONE);
00199         lat.Reunitarize(dev, max_diff);
00200         LatticeFactory::Destroy();
00201       }
00202 
00203 #ifdef HAVE_QCDOCOS_SCU_CHECKSUM_H
00204       printf("SCU checksum test\n");
00205   if ( ! ScuChecksum::CsumSwap() )
00206     ERR.Hardware(cname,fname, "SCU Checksum mismatch\n");
00207 #endif
00208 
00210       h_final = integrator->energy();
00211 //      Float total_h_final =h_final;
00212 //      glb_sum(&total_h_final);
00213 
00214       // Calculate Final-Initial Hamiltonian 
00215       delta_h = h_final - h_init;
00216       glb_sum(&delta_h);
00217 //      VRB.Result(cname,fname,"h_init=%0.14e h_final=%0.14e delta_h=%0.14e \n",
00218 //        total_h_init,total_h_final,delta_h);
00219 
00220       // Check that delta_h is the same across all s-slices 
00221       // (relevant only if GJP.Snodes() != 1)
00222       if(GJP.Snodes() != 1) {
00223         Lattice &lat = LatticeFactory::Create(F_CLASS_NONE, G_CLASS_NONE);
00224         VRB.Flow(cname,fname, "Checking Delta H across s-slices\n");
00225         lat.SoCheck(delta_h);
00226         LatticeFactory::Destroy();
00227       }
00228 
00229       if ( !(test == 0 && attempt ==0) ){
00230         shiftStates(-SHIFT_X,-SHIFT_Y,-SHIFT_Z,0);
00231         GDS.SetOrigin(0,0,0,0);
00232       }
00233 
00234       if (hmc_arg->reverse == REVERSE_YES) {
00235         saveFinalState();
00236 
00237         integrator->reverse();
00238       if(hmc_arg->wfm_md_sloppy) wilson_set_sloppy(true);
00239         integrator->evolve(hmc_arg->step_size, hmc_arg->steps_per_traj);
00240       wilson_set_sloppy(false);
00241 
00242 #ifdef HAVE_QCDOCOS_SCU_CHECKSUM_H
00243   printf("SCU checksum test\n");
00244   if ( ! ScuChecksum::CsumSwap() )
00245     ERR.Hardware(cname,fname, "SCU Checksum mismatch\n");
00246 #endif
00247 
00248         h_delta = h_final - integrator->energy();
00249         glb_sum(&h_delta);
00250 
00251         reverseTest();
00252         restoreFinalState();
00253       }
00254 
00255       Lattice &lat = LatticeFactory::Create(F_CLASS_NONE, G_CLASS_NONE);
00256       checksum[test] = global_checksum((Float*)lat.GaugeField(),g_size);
00257       LatticeFactory::Destroy();
00258 
00259     } // end test loop
00260   
00261     if (reproduceTest(attempt)) break;
00262 
00263   } // end attempt loop
00264 
00265   {
00266     Lattice &lat = LatticeFactory::Create(F_CLASS_NONE, G_CLASS_NONE);
00267     
00268         VRB.Result(cname,fname,"hmc_arg->metropolis=%d\n",hmc_arg->metropolis);
00270     if(hmc_arg->metropolis == METROPOLIS_YES){
00271       accept = lat.MetropolisAccept(delta_h,&acceptance);
00272       if( !(accept) ){
00273         // Trajectory rejected
00274         lat.GaugeField(gauge_field_init);
00275         VRB.Result(cname,fname,"Metropolis step -> Rejected\n");
00276       }
00277       else {
00278         // Trajectory accepted. 
00279         // Increment the Gauge Update counter in Lattice.
00280         lat.GupdCntInc(1);
00281         VRB.Result(cname,fname,"Metropolis step -> Accepted\n");
00282       }
00283     } 
00284     else {
00285       accept = 1;
00286       acceptance = 1.0;
00287       lat.GupdCntInc(1);
00288       VRB.Result(cname,fname,"No Metropolis step -> Accepted\n");
00289     }
00290 
00296     if(GJP.Snodes() != 1) {
00297       VRB.Flow(cname,fname, "Checking gauge field across s-slices\n");
00298       lat.GsoCheck();
00299     }
00300 
00301     config_no = lat.GupdCnt();
00302 
00303     LatticeFactory::Destroy();
00304   }
00305 
00306   CgStats cg_stats;
00307   integrator->cost(&cg_stats);
00308 
00310   if (cg_stats.cg_calls > 0)
00311     efficiency = Float(acceptance) / Float(cg_stats.cg_iter_av);
00312 
00314   if(common_arg->results != 0){
00315     if( (fp = Fopen((char *)common_arg->results, "a")) == NULL ) {
00316       ERR.FileA(cname,fname, (char *)common_arg->results);
00317     }
00318     Fprintf(fp,"%d %e %e %d %e %e %e %e %d %d %e %e %e\n",
00319             hmc_arg->steps_per_traj,
00320             IFloat(delta_h), 
00321             acceptance,
00322             accept, 
00323             IFloat(dev),
00324             IFloat(max_diff),
00325             IFloat(cg_stats.cg_iter_total),
00326             IFloat(cg_stats.cg_iter_av),
00327             cg_stats.cg_iter_min,
00328             cg_stats.cg_iter_max,
00329             IFloat(cg_stats.true_rsd_av),
00330             IFloat(cg_stats.true_rsd_min),
00331             IFloat(cg_stats.true_rsd_max));
00332     Fclose(fp);
00333   }
00334 
00335   VRB.Result(cname,fname,
00336              "Hmc steps = %d, Delta_hamilton = %e, accept = %d, dev = %e, max_diff = %e\n",
00337              hmc_arg->steps_per_traj,
00338              IFloat(delta_h), 
00339              accept,
00340              IFloat(dev),
00341              IFloat(max_diff));
00342   VRB.Result(cname,fname,
00343              "CG iterations: average = %e, min = %d, max = %d\n",
00344              IFloat(cg_stats.cg_iter_av),
00345              cg_stats.cg_iter_min,
00346              cg_stats.cg_iter_max);
00347   VRB.Result(cname,fname,
00348              "True Residual / |source|: average = %e, min = %e, max = %e\n",
00349              IFloat(cg_stats.true_rsd_av),
00350              IFloat(cg_stats.true_rsd_min),
00351              IFloat(cg_stats.true_rsd_max));
00352 
00353   VRB.Result(cname,fname,
00354              "Efficiency (acceptance per cg iteration) = %e\n",
00355              efficiency);
00356 
00357   VRB.Result(cname,fname,"Configuration number = %d\n", config_no);
00358 
00359 
00360   return acceptance;
00361 }
00362 
00363 
00364 int AlgHmc::saveInitialState() {
00365 
00366   Lattice &lat = LatticeFactory::Create(F_CLASS_NONE, G_CLASS_NONE);
00367 
00369   if(hmc_arg->metropolis == METROPOLIS_YES ||
00370      hmc_arg->reproduce == REPRODUCE_YES ||
00371      hmc_arg->reverse == REVERSE_YES){
00372     lat.CopyGaugeField(gauge_field_init);
00373   }
00374 
00375   int Ntests;
00376 
00377   if (hmc_arg->reproduce == REPRODUCE_YES) {
00379 //    LRG.GetStates(rng5d_init, FIVE_D);
00380 //    LRG.GetStates(rng4d_init, FOUR_D);
00381       lrg_state.GetStates();
00382     
00383     if (hmc_arg->reproduce_attempt_limit < 1 ||
00384         hmc_arg->reproduce_attempt_limit > 5)
00385       hmc_arg->reproduce_attempt_limit = 3;
00386     Ntests = 2;
00387   } else {
00388     hmc_arg->reproduce_attempt_limit = 1;
00389     Ntests = 1;
00390   }
00391 
00392   LatticeFactory::Destroy();
00393 
00394   return Ntests;
00395 
00396 }
00397 
00399 void AlgHmc::saveFinalState() {
00400   Lattice &lat = LatticeFactory::Create(F_CLASS_NONE, G_CLASS_NONE);
00401   lat.CopyGaugeField(gauge_field_final);
00402   LatticeFactory::Destroy();
00403 }
00404 
00406 void AlgHmc::restoreInitialState() {
00407   Lattice &lat = LatticeFactory::Create(F_CLASS_NONE, G_CLASS_NONE);
00408   lat.GaugeField(gauge_field_init);
00409 //  LRG.SetStates(rng4d_init, FOUR_D);
00410 //  LRG.SetStates(rng5d_init, FIVE_D);
00411   lrg_state.SetStates();
00412   LatticeFactory::Destroy();
00413 }
00414 
00415 void AlgHmc::shiftStates(int x, int y, int z, int t) {
00416   Lattice &lat = LatticeFactory::Create(F_CLASS_NONE, G_CLASS_NONE);
00417   GDS.Set(x,y,z,t);
00418   LRG.Shift();
00419   lat.Shift();
00420   LatticeFactory::Destroy();
00421 }
00422 
00424 void AlgHmc::restoreFinalState() {
00425   Lattice &lat = LatticeFactory::Create(F_CLASS_NONE, G_CLASS_NONE);
00426   lat.GaugeField(gauge_field_final);
00427   LatticeFactory::Destroy();
00428 }
00429 
00431 int AlgHmc::reproduceTest(int attempt) {
00432 
00433   char *fname = "reproduceTest(int)" ;
00434 
00435   if (hmc_arg->reproduce == REPRODUCE_YES) {
00436     Lattice &lat = LatticeFactory::Create(F_CLASS_NONE, G_CLASS_NONE);
00438     if (checksum[0] == checksum[1]) {
00439       VRB.Result(cname,fname,"Passed reproducibility test\n");
00440       LatticeFactory::Destroy();
00441       return 1;
00442     } else {
00443       VRB.Result(cname,fname, 
00444                  "Failed reproducibility first = %p, second = %p\n", 
00445                  checksum[0], checksum[1]);
00446       LatticeFactory::Destroy();
00447     }
00448     
00449     VRB.Result(cname,fname,"Failed reproducibility test %d\n",attempt);
00450     if (attempt == hmc_arg->reproduce_attempt_limit-1) 
00451       ERR.General(cname,fname,"Failed to reproduce\n");
00452     return 0;
00453  } else {
00454    return 1;
00455  }
00456 
00457 }
00458 
00459 void AlgHmc::reverseTest() {
00460 
00461   char *fname = "reverseTest()";
00462 
00464   Float delta_delta_h = delta_h - h_delta;
00465   delta_delta_h = sqrt(delta_delta_h*delta_delta_h);
00466 
00468   Lattice &lat = LatticeFactory::Create(F_CLASS_NONE, G_CLASS_NONE);
00469 
00470   ((Vector*)(lat.GaugeField()))->
00471     VecMinusEquVec((Vector*)gauge_field_init, g_size);
00472   Float delta_delta_U = ((Vector*)(lat.GaugeField()))->NormSqGlbSum4D(g_size);
00473   delta_delta_U = sqrt(delta_delta_U);
00474 
00475   LatticeFactory::Destroy();
00476   
00477   VRB.Result(cname, fname, 
00478              "Reversibility check: delta dH = %e, delta dU = %e\n", 
00479              delta_delta_h, delta_delta_U);
00480 
00481 }
00482 
00483 
00484 CPS_END_NAMESPACE

Generated on Sat Oct 10 14:11:17 2009 for Columbia Physics System by  doxygen 1.3.9.1