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

alg_hmd_r2.C

Go to the documentation of this file.
00001 #include<config.h>
00002 #include<stdlib.h>
00003 #include<math.h>
00004 CPS_START_NAMESPACE
00005 //------------------------------------------------------------------
00006 //
00007 // alg_hmd_r.C
00008 //
00009 // AlgHmdR2 is derived from AlgHmd and is relevant to the Hybrid  
00010 // Molecular Dynamics R2 algorithm. Boson fields are simulated as
00011 // fermion fields with negative flavor number.
00012 //
00013 //------------------------------------------------------------------
00014 
00015 CPS_END_NAMESPACE
00016 #include <stdio.h>
00017 #include <alg/alg_hmd.h>
00018 #include <comms/glb.h>
00019 #include <util/lattice.h>
00020 #include <util/vector.h>
00021 #include <util/gjp.h>
00022 #include <util/smalloc.h>
00023 #include <util/verbose.h>
00024 #include <util/error.h>
00025 CPS_START_NAMESPACE
00026 
00027 
00028 
00029 
00030 //------------------------------------------------------------------
00036 //------------------------------------------------------------------
00037 AlgHmdR2::AlgHmdR2(Lattice& latt, 
00038                    CommonArg *c_arg,
00039                    HmdArg *arg) : 
00040   AlgHmd(latt, c_arg, arg) 
00041 {
00042   cname = "AlgHmdR2";
00043   char *fname = "AlgHmdR2(L&,CommonArg*,HmdArg*)";
00044   VRB.Func(cname,fname);
00045   int i;
00046 
00047   if (latt.Fclass() != F_CLASS_STAG && 
00048       latt.Fclass() != F_CLASS_ASQTAD )
00049     ERR.General(cname,fname,"Cannot use R2 algorithm with non-staggered quarks\n");
00050 
00051   // Initialize the number of dynamical fermion masses
00052   //----------------------------------------------------------------
00053   n_frm_masses = hmd_arg->n_frm_masses;
00054   if(n_frm_masses != 2){
00055     ERR.General(cname,fname,"n_frm_masses must equal 2 for R2 algorithm\n");
00056   }
00057 
00058 
00059   // Allocate memory for the flavor time step array
00060   //----------------------------------------------------------------
00061   if(n_frm_masses != 0){
00062     flavor_time_step = (Float *) 
00063       smalloc((n_frm_masses+1)*sizeof(Float), 
00064               cname, fname, "flavor_time_step");
00065     force_coeff = (Float *) 
00066       smalloc((n_frm_masses)*sizeof(Float), 
00067               cname, fname, "force_coeff");
00068   }
00069 
00070 
00071   // Calculate the fermion field size.
00072   //----------------------------------------------------------------
00073   // Number of lattice sites
00074   f_sites = GJP.SnodeSites()*GJP.VolNodeSites() / (AlgLattice().FchkbEvl()+1);
00075   // Number of Vectors in a Vector array
00076   f_vec_count = f_sites * AlgLattice().SpinComponents();
00077   // Number of Floats in a Vector array
00078   f_size = f_vec_count * AlgLattice().Colors() * 2;
00079 
00080   // Allocate memory for the fermion CG arguments.
00081   //----------------------------------------------------------------
00082   frm_cg_arg = (CgArg **) 
00083     smalloc(sizeof(CgArg*),cname,fname,"frm_cg_arg");
00084   for (i=0; i<n_frm_masses; i++)
00085     frm_cg_arg[i] = (CgArg *) 
00086       smalloc(sizeof(CgArg),cname,fname,"frm_cg_arg[i]");
00087 
00088   light=0;
00089   heavy=1;
00090   if (hmd_arg->frm_mass[0] > hmd_arg->frm_mass[1]) {
00091     Float temp = hmd_arg->frm_mass[0];
00092     hmd_arg->frm_mass[0] = hmd_arg->frm_mass[1];
00093     hmd_arg->frm_mass[1] = temp;
00094   }
00095 
00096   // Initialize the fermion CG argument
00097   //----------------------------------------------------------------
00098   for (i=0; i<n_frm_masses; i++) {
00099     frm_cg_arg[i]->mass = hmd_arg->frm_mass[i];
00100     frm_cg_arg[i]->max_num_iter = hmd_arg->max_num_iter[i];
00101     frm_cg_arg[i]->stop_rsd = hmd_arg->stop_rsd[i];
00102   }
00103 
00104   shift = (Float*) smalloc(n_frm_masses*sizeof(Float), cname, fname, "shift");
00105 
00106   shift[light] = 0.0;
00107   shift[heavy] 
00108     = 4.0*(hmd_arg->frm_mass[heavy]*hmd_arg->frm_mass[heavy] - 
00109            hmd_arg->frm_mass[light]*hmd_arg->frm_mass[light]);
00110 
00111   // Allocate memory for the phi pseudo fermion field.
00112   //----------------------------------------------------------------
00113   if(n_frm_masses != 0){
00114     phi = (Vector **) 
00115       smalloc(n_frm_masses * sizeof(Vector*), cname,fname, "phi");
00116     for(i=0; i<n_frm_masses; i++)
00117       phi[i] = (Vector *) 
00118         smalloc(f_size * sizeof(Float), cname,fname, "phi[i]");
00119   }
00120 
00121 
00122   // Allocate memory for solution vectors.
00123   //----------------------------------------------------------------
00124   frmn = (Vector**) smalloc(n_frm_masses*sizeof(Vector*), cname, fname, "frmn");    
00125   frmn_d = (Vector**) smalloc(n_frm_masses*sizeof(Vector*), cname, fname, "frmn_d");
00126   
00127   for (i=0; i<n_frm_masses; i++) {
00128     frmn[i] = (Vector*) smalloc(2*f_size*sizeof(Float));
00129     frmn_d[i] = frmn[i] + f_vec_count;
00130   }
00131 
00132 
00133 }
00134 
00135 
00136 //------------------------------------------------------------------
00137 // Destructor
00138 //------------------------------------------------------------------
00139 AlgHmdR2::~AlgHmdR2() {
00140   int i;
00141   char *fname = "~AlgHmdR2()" ;
00142   VRB.Func(cname,fname);
00143 
00144   // Free memory for solution vectors
00145   //----------------------------------------------------------------
00146   sfree(frmn_d, cname,fname, "frmn_d");    
00147   for (i=0; i<n_frm_masses; i++) 
00148     sfree(frmn[i], cname, fname, "frmn[i]");
00149 
00150   sfree(frmn, cname, fname, "frmn");
00151 
00152 
00153   // Free memory for the phi (pseudo fermion) fermion field.
00154   //----------------------------------------------------------------
00155   if(n_frm_masses != 0){
00156     for(i=0; i<n_frm_masses; i++){
00157       sfree(phi[i], cname, fname, "phi[i]");
00158     }
00159     sfree(phi, cname, fname, "phi");
00160   }
00161 
00162   // Free memory for the shifted masses
00163   //----------------------------------------------------------------
00164   sfree(shift, cname, fname, "shift");
00165 
00166   // Free memory for the fermion CG arguments
00167   //----------------------------------------------------------------
00168   for (i=0; i<n_frm_masses; i++)
00169     sfree(frm_cg_arg[i], cname,fname, "frm_cg_arg[i]");
00170   sfree(frm_cg_arg, cname,fname, "frm_cg_arg");
00171 
00172   // Free memory for the flavor time step array
00173   //----------------------------------------------------------------
00174   if(n_frm_masses != 0) {
00175     sfree(flavor_time_step, cname, fname, "flavor_time_step");
00176     sfree(force_coeff);
00177   }
00178 
00179 }
00180 
00181 
00182 //------------------------------------------------------------------
00187 //------------------------------------------------------------------
00188 Float AlgHmdR2::run(void)
00189 {
00190 #if TARGET==cpsMPI
00191     using MPISCU::fprintf;
00192 #endif
00193   int i;
00194   int step;                            // Trajectory step
00195   Float frm_time_step;
00196   Float flavor_coeff;
00197   int   cg_iter;
00198   Float cg_iter_av;
00199   int   cg_iter_min;
00200   int   cg_iter_max;
00201   Float true_res=0.;
00202   Float true_res_av;
00203   Float true_res_min;
00204   Float true_res_max;
00205   int cg_calls;
00206   char *fname = "run()";
00207   char *md_time_str = "MD_time/step_size = ";
00208 
00209   FILE *fp;
00210   VRB.Func(cname,fname);
00211 
00212   // Get the Lattice object
00213   //----------------------------------------------------------------
00214   Lattice& lat = AlgLattice();
00215 
00216   // Set exact flavor coefficient = 1/ ExactFlavors
00217   //----------------------------------------------------------------
00218   flavor_coeff = 1.0 / lat.ExactFlavors();
00219 
00220   // Set the microcanonical time step
00221   //----------------------------------------------------------------
00222   Float dt = hmd_arg->step_size;
00223 
00224   // Initialize the flavor time step array
00225   //----------------------------------------------------------------
00226   int flavor_diff = hmd_arg->frm_flavors[0];
00227   flavor_time_step[0]  = -0.5 * dt * flavor_diff * flavor_coeff;
00228   for(i=1; i<n_frm_masses; i++){
00229     flavor_diff = hmd_arg->frm_flavors[i] - hmd_arg->frm_flavors[i-1];
00230     flavor_time_step[i]  = -0.5 * dt * flavor_diff * flavor_coeff;
00231     force_coeff[i] = hmd_arg->frm_flavors[i] * flavor_coeff;
00232   }
00233   flavor_diff = hmd_arg->frm_flavors[n_frm_masses-1];
00234   flavor_time_step[n_frm_masses] = 0.5 * dt * flavor_diff * flavor_coeff;
00235 
00236   // Initialize monitor variables
00237   //----------------------------------------------------------------
00238   cg_iter_av   = 0.0;
00239   cg_iter_min  = 1000000;
00240   cg_iter_max  = 0;
00241   true_res_av  = 0.0;
00242   true_res_min = 3.4e+38;
00243   true_res_max = 0.0;
00244   cg_calls     = 0;
00245 
00246 
00247   // reset MD time in Lattice
00248   //----------------------------------------------------------------
00249   lat.MdTime(0.0);
00250   VRB.Flow(cname,fname,"%s%f\n", md_time_str, IFloat(lat.MdTime()));
00251 
00252 
00253   // generate Gaussian random momentum
00254   //----------------------------------------------------------------
00255   lat.RandGaussAntiHermMatrix(mom, 1.0);
00256   Float mom_sum = lat.MomHamiltonNode(mom);
00257   glb_sum(&mom_sum);
00258   VRB.Flow(cname,fname,"mom_sum = %0.14e\n",mom_sum);
00259   Float *phi_p = (Float *)mom;
00260 
00261 
00262   // Evolve gauge field by dt/2
00263   //--------------------------------------------------------------
00264   lat.EvolveGfield(mom, 0.5*dt);
00265   lat.MdTimeInc(0.5);
00266   VRB.Flow(cname,fname,"%s%f\n", md_time_str, IFloat(lat.MdTime()));
00267 
00268 
00269   // Run through the trajectory
00270   //----------------------------------------------------------------
00271   step = hmd_arg->steps_per_traj;
00272   while(step) {
00273 
00274     // Set the field phi for each mass.
00275     // First evolve gauge field by flavor_time_step.
00276     // Next generate a Gaussian random vector.
00277     // Finally calculate phi using the evolved gauge field
00278     // and gaussian random vector.
00279     //--------------------------------------------------------------
00280     for(i=0; i<n_frm_masses; i++){
00281       lat.EvolveGfield(mom, flavor_time_step[i]);
00282       lat.MdTimeInc(flavor_time_step[i] / dt);
00283       VRB.Flow(cname,fname,"%s%f\n", md_time_str, IFloat(lat.MdTime()));
00284       lat.RandGaussVector(frmn[0], 0.5, Ncb);
00285       lat.RandGaussVector(frmn[1], 0.5, Ncb);   
00286       lat.SetPhi(phi[i], frmn[0], frmn[1], hmd_arg->frm_mass[i]);
00287     }
00288 
00289     // Evolve gauge field to the mid-point N*dt + dt/2
00290     //--------------------------------------------------------------
00291     lat.EvolveGfield(mom, flavor_time_step[n_frm_masses]);
00292     lat.MdTimeInc(flavor_time_step[n_frm_masses] / dt);
00293     VRB.Flow(cname,fname,"%s%f\n", md_time_str, IFloat(lat.MdTime()));
00294 
00295     // Evolve momenta by one step using the pure gauge force
00296     //--------------------------------------------------------------
00297     lat.EvolveMomGforce(mom, dt);
00298 
00299     // Evolve momenta by one step using the fermion force
00300     //--------------------------------------------------------------
00301 
00302     // First set the initial guess for the generalised
00303     // multi-mass solver
00304     frmn[light] -> FTimesV1MinusV2(1.0, phi[heavy], phi[light], f_size);
00305     frmn[light] -> VecTimesEquFloat(1.0/shift[heavy], f_size);
00306     frmn[heavy] -> CopyVec(frmn[light], f_size);
00307 
00308     cg_iter = lat.FmatEvlMInv(frmn, phi[light], shift, n_frm_masses, light, 
00309                               frm_cg_arg, CNV_FRM_NO, GENERAL, 
00310                               frmn_d);
00311 
00312     cg_iter_av = cg_iter_av + cg_iter;
00313     if(cg_iter < cg_iter_min) cg_iter_min = cg_iter;
00314     if(cg_iter > cg_iter_max) cg_iter_max = cg_iter;
00315     true_res_av = true_res_av + true_res;
00316     if(true_res < true_res_min) true_res_min = true_res;
00317     if(true_res > true_res_max) true_res_max = true_res;
00318     true_res_av = true_res_av + true_res;
00319     if(true_res < true_res_min) true_res_min = true_res;
00320     if(true_res > true_res_max) true_res_max = true_res;
00321     cg_calls++;
00322 
00323     // Now calculate the force (currently uses RHMC force)
00324     lat.RHMC_EvolveMomFforce(mom, frmn, 2, 0, force_coeff, 0.0, dt, frmn_d,
00325                              FORCE_MEASURE_NO);
00326     // decrease the loop counter by 1
00327     step--;
00328 
00329     // if not last step, move links forward by dt
00330     // otherwise, exit the loop
00331     if(step > 0) lat.EvolveGfield(mom, dt);
00332 
00333     // Increment MD Time clock in Lattice by one time step.
00334     lat.MdTimeInc(1.0);
00335     VRB.Flow(cname,fname,"%s%f\n", md_time_str, IFloat(lat.MdTime()));
00336   }
00337 
00338 
00339   //--------------------------------------------------------------
00340   // move Links forward half step, finish leap-
00341   // frog integration
00342   //--------------------------------------------------------------
00343   lat.EvolveGfield(mom, 0.5*dt);
00344 
00345 
00346   //----------------------------------------------------------------
00347   // Reunitarize
00348   //----------------------------------------------------------------
00349   Float dev = 0.0;
00350   Float max_diff = 0.0;
00351   if(hmd_arg->reunitarize == REUNITARIZE_YES){
00352     lat.Reunitarize(dev, max_diff);
00353   }
00354 
00355   //----------------------------------------------------------------
00356   // Update gauge field counter
00357   //----------------------------------------------------------------
00358   lat.GupdCntInc(1);
00359 
00360   //----------------------------------------------------------------
00361   // If GJP.Snodes() !=1  the gauge field is spread out
00362   // accross s-slices of processors. It must be identical
00363   // on each slice. Check to make sure and exit if it
00364   // is not identical. A case where this is relevant
00365   // is the DWF spread-out case.
00366   //----------------------------------------------------------------
00367   lat.GsoCheck();
00368 
00369   // Calculate average of monitor variables
00370   //---------------------------------------------------------------
00371   cg_iter_av = Float(cg_iter_av) / Float(cg_calls);
00372   true_res_av = Float(true_res_av) / Float(cg_calls);
00373 
00374 
00375   // Print out monitor info
00376   //---------------------------------------------------------------
00377   if(common_arg->results != 0){
00378     if( (fp = fopen((char *)common_arg->results, "a")) == NULL ) {
00379       ERR.FileA(cname,fname, (char *)common_arg->results);
00380     }
00381     fprintf(fp,"%d %e %e %e %d %d %e %e %e\n",
00382             hmd_arg->steps_per_traj,
00383             IFloat(dev),
00384             IFloat(max_diff),
00385             IFloat(cg_iter_av),
00386             cg_iter_min,
00387             cg_iter_max,
00388             IFloat(true_res_av),
00389             IFloat(true_res_min),
00390             IFloat(true_res_max));
00391     fclose(fp);
00392   }
00393 
00394   VRB.Result(cname,fname,
00395   "Hmd steps = %d, dev = %e, max_diff = %e\n",
00396              hmd_arg->steps_per_traj,
00397              IFloat(dev),
00398              IFloat(max_diff));
00399   VRB.Result(cname,fname,
00400              "CG iterations: average = %e, min = %d, max = %d\n",
00401              IFloat(cg_iter_av),
00402              cg_iter_min,
00403              cg_iter_max);
00404   VRB.Result(cname,fname,
00405              "True Residual / |source|: average = %e, min = %e, max = %e\n",
00406              IFloat(true_res_av),
00407              IFloat(true_res_min),
00408              IFloat(true_res_max));
00409 
00410   VRB.Result(cname,fname,"Configuration number = %d\n", lat.GupdCnt());
00411 
00412   
00413   // Reset Molecular Dynamics time counter
00414   //----------------------------------------------------------------
00415   lat.MdTime(0.0);
00416   VRB.Flow(cname,fname,"%s%f\n", md_time_str, IFloat(lat.MdTime()));
00417 
00418   return (Float)1.0;
00419 
00420 }
00421 
00422 
00423 
00424 
00425 
00426 
00427 CPS_END_NAMESPACE

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