00001 #include<config.h>
00002 CPS_START_NAMESPACE
00003
00009
00010
00011
00012
00013
00014
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
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
00095
00096 AlgHmc::~AlgHmc() {
00097
00098
00099 char *fname = "~AlgHmc()" ;
00100 VRB.Func(cname,fname);
00101
00102
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
00133
00134 Float AlgHmc::run(void)
00135 {
00136 #if TARGET==cpsMPI
00137 using MPISCU::fprintf;
00138 #endif
00139
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;
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
00158
00159
00161 int Ntests = saveInitialState();
00162 VRB.Result(cname,fname,"shifts=%d %d %d\n",SHIFT_X,SHIFT_Y,SHIFT_Z);
00163
00164
00165
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
00189
00190
00191
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
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
00212
00213
00214
00215 delta_h = h_final - h_init;
00216 glb_sum(&delta_h);
00217
00218
00219
00220
00221
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 }
00260
00261 if (reproduceTest(attempt)) break;
00262
00263 }
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
00274 lat.GaugeField(gauge_field_init);
00275 VRB.Result(cname,fname,"Metropolis step -> Rejected\n");
00276 }
00277 else {
00278
00279
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
00380
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
00410
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