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

alg_hmc_rhmc.C

Go to the documentation of this file.
00001 #include<config.h>
00002 CPS_START_NAMESPACE 
00003 //------------------------------------------------------------------
00009 //--------------------------------------------------------------------
00010 /*
00011   $Author: chulwoo $
00012   $Date: 2007/06/25 15:49:20 $
00013   $Header: /space/cvs/cps/cps++/src/alg/alg_hmd/alg_hmc_rhmc.C,v 1.28 2007/06/25 15:49:20 chulwoo Exp $
00014   $Id: alg_hmc_rhmc.C,v 1.28 2007/06/25 15:49:20 chulwoo Exp $
00015   $Name: v5_0_8 $
00016   $Locker:  $
00017   $RCSfile: alg_hmc_rhmc.C,v $
00018   $Revision: 1.28 $
00019   $Source: /space/cvs/cps/cps++/src/alg/alg_hmd/alg_hmc_rhmc.C,v $
00020   $State: Exp $
00021 */
00022 //--------------------------------------------------------------------
00023 
00024 
00025 //------------------------------------------------------------------
00026 //
00027 // alg_hmc_rhmc.C
00028 //
00029 // AlgHmcRHMC is derived from Alg and is relevant to the Rational
00030 // Hybrid Monte Carlo Algorithm.
00031 //
00032 //------------------------------------------------------------------
00033 
00034 CPS_END_NAMESPACE
00035 #include<util/data_shift.h>
00036 #include<util/checksum.h>
00037 #include<util/qcdio.h>
00038 #include<math.h>
00039 #include<alg/alg_hmd.h>
00040 #include<util/lattice.h>
00041 #include<util/vector.h>
00042 #include<util/gjp.h>
00043 #include<util/smalloc.h>
00044 #include<util/verbose.h>
00045 #include<util/error.h>
00046 #include<comms/glb.h>
00047 #include<alg/alg_remez.h>
00048 #include<util/data_shift.h>
00049 #ifdef HAVE_STRINGS_H
00050 #include <strings.h>
00051 #endif
00052 CPS_START_NAMESPACE
00053 
00054 //------------------------------------------------------------------
00060 //------------------------------------------------------------------
00061 
00062 AlgHmcRHMC::AlgHmcRHMC(Lattice& latt, 
00063                        CommonArg *c_arg,
00064                        HmdArg *arg) : 
00065   AlgHmd(latt, c_arg, arg) 
00066 {
00067   cname = "AlgHmcRHMC";
00068   char *fname = "AlgHmcRHMC(L&,CommonArg*,HmdArg*)";
00069   VRB.Func(cname,fname);
00070 
00071   // Approx type must be constant if this constructor is called
00072   //----------------------------------------------------------------
00073   hmd_arg->approx_type = CONSTANT;
00074 
00075   // Currently RHMC force term is not implemented for Asqtad with any
00076   // dimension less than 4
00077   //----------------------------------------------------------------
00078   if( latt.Fclass() == F_CLASS_ASQTAD && 
00079       (GJP.XnodeSites()==2 ||
00080        GJP.YnodeSites()==2 ||
00081        GJP.ZnodeSites()==2 ||
00082        GJP.TnodeSites()==2 ) )
00083     ERR.General(cname,fname," RHMC force term is not implemented for Fasqtad with any dimension less than 4\n");
00084 
00085   // construct approximation if necessary
00086   generateApprox(arg);
00087 
00088   init();
00089 
00090 
00091 }
00092 
00093 //------------------------------------------------------------------
00101 //------------------------------------------------------------------
00102 
00103 AlgHmcRHMC::AlgHmcRHMC(Lattice& latt, CommonArg *c_arg, HmdArg *arg, 
00104                        EigArg *e_arg) : AlgHmd(latt, c_arg, arg)
00105 
00106 {
00107   cname = "AlgHmcRHMC";
00108   char *fname = "AlgHmcRHMC(L&,CommonArg*,HmdArg*)";
00109   VRB.Func(cname,fname);
00110 
00111   // construct approximation if necessary
00112   generateApprox(arg);
00113 
00114   init();
00115 
00116   eig_arg = e_arg;
00117 }
00118 
00119 void AlgHmcRHMC::init()
00120 {
00121   int i,j;
00122   cname = "AlgHmcRHMC";
00123   char *fname = "init()";
00124   VRB.Func(cname,fname);
00125 
00126   // Number of lattice sites
00127   f_sites = GJP.SnodeSites()*GJP.VolNodeSites() / (AlgLattice().FchkbEvl()+1);
00128   // Number of Vectors in a Vector array
00129   f_vec_count = f_sites * AlgLattice().SpinComponents();
00130   // Number of Floats in a Vector array
00131   f_size = f_vec_count * AlgLattice().Colors() * 2;
00132 
00133   // Initialize the number of dynamical fermion masses
00134   //----------------------------------------------------------------
00135   n_frm_masses = hmd_arg->n_frm_masses;
00136   if(n_frm_masses > MAX_HMD_MASSES){
00137     ERR.General(cname,fname,
00138                 "hmd_arg->n_frm_masses = %d is larger than MAX_HMD_MASSES = %d\n",
00139                 n_frm_masses, MAX_HMD_MASSES);
00140   }
00141 
00142   // Initialize the number of dynamical boson masses
00143   //----------------------------------------------------------------
00144   n_bsn_masses = hmd_arg->n_bsn_masses;
00145   if(n_bsn_masses > MAX_HMD_MASSES){
00146     ERR.General(cname,fname,
00147                 "hmd_arg->n_bsn_masses = %d is larger than MAX_HMD_MASSES = %d\n",
00148                 n_bsn_masses, MAX_HMD_MASSES);
00149   }
00150 
00151   // Allocate memory for the fermion CG arguments.
00152   //----------------------------------------------------------------
00153   if(n_frm_masses != 0){
00154     frm_cg_arg = (CgArg **) smalloc (cname,fname, "frm_cg_arg", 
00155                                      n_frm_masses * sizeof(CgArg*));
00156 
00157     for(i=0; i<n_frm_masses; i++) {
00158       frm_cg_arg[i] = (CgArg *) 
00159         smalloc(cname,fname, "frm_cg_arg[i]",sizeof(CgArg));
00160     }
00161 
00162     // Initialize the fermion CG arguments
00163     //----------------------------------------------------------------
00164     for(i=0; i<n_frm_masses; i++){
00165       frm_cg_arg[i]->mass = hmd_arg->frm_mass[i];
00166       frm_cg_arg[i]->max_num_iter = hmd_arg->max_num_iter[i];
00167       frm_cg_arg[i]->stop_rsd = hmd_arg->stop_rsd_mc[i];
00168     }
00169   }
00170   // Allocate memory for the boson CG arguments.
00171   //----------------------------------------------------------------
00172   if(n_bsn_masses != 0){
00173     bsn_cg_arg = (CgArg **) smalloc(n_bsn_masses * sizeof(CgArg*), 
00174                                     cname, fname, "bsn_cg_arg");
00175     
00176     for(i=0; i<n_bsn_masses; i++){
00177       bsn_cg_arg[i] = (CgArg *) 
00178         smalloc(sizeof(CgArg), cname, fname, "bsn_cg_arg[i]");
00179     } 
00180 
00181   }
00182 
00183   // Initialize the boson CG arguments
00184   //----------------------------------------------------------------
00185   //??? Complete this
00186   for(i=0; i<n_bsn_masses; i++){
00187     bsn_cg_arg[i]->mass = hmd_arg->bsn_mass[i];
00188     bsn_cg_arg[i]->max_num_iter = hmd_arg->max_num_iter[i];
00189     bsn_cg_arg[i]->stop_rsd = hmd_arg->stop_rsd_mc[i];
00190   }
00191 
00192   // Allocate memory for the phi pseudo fermion field.
00193   //----------------------------------------------------------------
00194   phi = (Vector **) smalloc(n_frm_masses * sizeof(Vector*),
00195                             cname,fname, "phi");
00196 
00197   for(i=0; i<n_frm_masses; i++) {
00198     phi[i] = (Vector *) smalloc(f_size*sizeof(Float),cname,fname, "phi[i]");
00199   }      
00200   
00201   // Allocate memory for the frmn solution fermion fields.
00202   //----------------------------------------------------------------
00203   total_size = 0;
00204   for (i=0; i<n_frm_masses; i++) total_size += hmd_arg->FRatDeg[i];
00205   
00206   // array holding coefficents used in dwf force, folded into MInv
00207   alpha = (Float**) smalloc(hmd_arg->n_frm_masses*sizeof(Float*),
00208                             cname,fname,"alpha");
00209   for (i=0; i<n_frm_masses; i++)
00210     alpha[i] = (Float*) smalloc(f_size*hmd_arg->FRatDeg[i]*sizeof(Float),
00211                                 cname,fname,"alpha[i]");    
00212 
00213   if (AlgLattice().Fclass() == F_CLASS_DWF) {
00214     // For dwf we need the solution vector contiguous in memory
00215     frmn = (Vector**) smalloc(total_size*sizeof(Vector*), cname, fname, "frmn");
00216     
00217     frmn[0] = (Vector*) smalloc(f_size*total_size*sizeof(Float), 
00218                                 cname, fname, "frmn[0]");
00219     
00220     for (i=1; i<total_size; i++) frmn[i] = frmn[0] + i*f_vec_count;
00221 
00222     frmn_d = 0;
00223   } else {
00224     // For asqtad we need them checkerboarded with dslash applied
00225     frmn = (Vector**) smalloc(total_size*sizeof(Vector*), cname, fname, "frmn");    
00226     frmn_d = (Vector**) smalloc(total_size*sizeof(Vector*), cname, fname, "frmn_d");
00227     
00228     for (i=0; i<total_size; i++) {
00229       frmn[i] = (Vector*) smalloc(2*f_size*sizeof(Float));
00230       frmn_d[i] = frmn[i] + f_vec_count;
00231     }
00232 
00233   }     
00234 
00235   // Allocate memory for the boson field bsn.
00236   //----------------------------------------------------------------
00237   if(n_bsn_masses != 0){
00238     bsn = (Vector **) smalloc(n_bsn_masses * sizeof(Vector*),
00239                               cname,fname, "bsn");
00240     for(i=0; i<n_bsn_masses; i++) {
00241       bsn[i] = (Vector*)smalloc(f_size*sizeof(Float), cname, fname, "bsn[i]");
00242     }
00243 
00244   }
00245 
00246   // Allocate memory for the initial gauge field.
00247   //----------------------------------------------------------------
00248   gauge_field_init = (Matrix *) smalloc(g_size * sizeof(Float), 
00249                                         cname,fname, "gauge_field_init");
00250 
00251   if (hmd_arg->reproduce != 1 && hmd_arg->reproduce != 0)
00252     hmd_arg->reproduce = 0;
00253 
00254   if (hmd_arg->reproduce) {
00255     
00256     // Allocate memory for the final gauge field.
00257     //----------------------------------------------------------------
00258 
00259     gauge_field_final = (Matrix *) smalloc(g_size * sizeof(Float), 
00260                                            cname,fname, "gauge_field_final");
00261         
00262     // Allocate memory for the initial rng state
00263     //----------------------------------------------------------------
00264     rng4d_init = (unsigned int**) smalloc(LRG.NStates(FOUR_D)*sizeof(unsigned int*),
00265                                           cname, fname, "rng4d_init");
00266     rng5d_init = (unsigned int**) smalloc(LRG.NStates()*sizeof(unsigned int*),
00267                                           cname, fname, "rng5d_init");
00268     for (int i=0; i<LRG.NStates(FOUR_D); i++)
00269       rng4d_init[i] = (unsigned int*) smalloc(LRG.StateSize()*sizeof(unsigned int), 
00270                                               cname, fname, "rng4d_init[i]");
00271     for (int i=0; i<LRG.NStates(); i++)
00272       rng5d_init[i] = (unsigned int*) smalloc(LRG.StateSize()*sizeof(unsigned int), 
00273                                               cname, fname, "rng5d_init[i]");
00274 
00275   }
00276 
00277   // Used for storing residue coefficients for staggered optimisation
00278   //----------------------------------------------------------------
00279   if ((AlgLattice().Fclass() == F_CLASS_ASQTAD || AlgLattice().Fclass() == F_CLASS_P4) && total_size > 0) {
00280     all_res = (Float *)smalloc(total_size * sizeof(Float),
00281                                cname,fname, "all_res");
00282     Float *res = all_res;
00283     for (i=0; i<n_frm_masses; i++) 
00284       for (j=0; j<hmd_arg->FRatDeg[i]; j++)
00285         *(res++) = hmd_arg->FRatRes[i][j];
00286   }
00287 
00288 } 
00289 
00290 //------------------------------------------------------------------
00291 // Destructor
00292 //------------------------------------------------------------------
00293 AlgHmcRHMC::~AlgHmcRHMC() {
00294 
00295   int i;
00296   char *fname = "~AlgHmcRHMC()" ;
00297   VRB.Func(cname,fname);
00298 
00299   // Free memory for the residue coefficients
00300   //----------------------------------------------------------------
00301   if ((AlgLattice().Fclass() == F_CLASS_ASQTAD || AlgLattice().Fclass() == F_CLASS_P4) && total_size > 0) 
00302     sfree(all_res, cname,fname, "all_res");
00303 
00304   // Free memory for the initial gauge field.
00305   //----------------------------------------------------------------
00306   sfree(gauge_field_init, cname,fname, "gauge_field_init");
00307 
00308   if (hmd_arg->reproduce) {
00309 
00310     // Free memory for the initial rng state
00311     //----------------------------------------------------------------
00312     for (int i=0; i<LRG.NStates(); i++)
00313       sfree(rng5d_init[i], cname, fname, "rng5d_init[i]");
00314     for (int i=0; i<LRG.NStates(FOUR_D); i++)
00315       sfree(rng4d_init[i], cname, fname, "rng4d_init[i]");
00316     
00317     sfree(rng5d_init, cname, fname, "rng5d_init");
00318     sfree(rng4d_init, cname, fname, "rng4d_init");
00319     // Free memory for the final gauge field.
00320     //----------------------------------------------------------------
00321     sfree(gauge_field_final, cname, fname, "gauge_field_final");
00322 
00323   }
00324 
00325   // Free memory for the boson field bsn.
00326   //----------------------------------------------------------------
00327   if(n_bsn_masses != 0){
00328     for(i=0; i<n_bsn_masses; i++)
00329       sfree(bsn[i], cname,fname, "bsn[i]");
00330     sfree(bsn, cname,fname, "bsn");
00331   }
00332 
00333   // Free memory for the phi (pseudo fermion) fermion field.
00334   //----------------------------------------------------------------
00335   if(n_frm_masses != 0){
00336     for(i=0; i<n_frm_masses; i++)
00337       sfree(phi[i], cname,fname, "phi[i]");
00338     sfree(phi, cname,fname, "phi");
00339 
00340     // Free memory for the frmn (pseudo fermion) solution fields.
00341     //----------------------------------------------------------------
00342     if (AlgLattice().Fclass() == F_CLASS_DWF) {
00343       sfree(frmn[0], cname, fname, "frmn[0]");
00344     } else {
00345       sfree(frmn_d, cname,fname, "frmn_d");    
00346       for (i=0; i<total_size; i++) sfree(frmn[i], cname, fname, "frmn[i]");
00347     }
00348     sfree(frmn, cname, fname, "frmn");
00349   }
00350 
00351   // Free memory for alpha coefficients
00352   //----------------------------------------------------------------
00353   for (i=0; i<n_frm_masses; i++)
00354     sfree(alpha[i],cname,fname,"alpha[i]");
00355   sfree(alpha,cname,fname,"alpha");
00356 
00357   // Free memory for the boson CG arguments
00358   //----------------------------------------------------------------
00359   if(n_bsn_masses != 0){
00360     for(i=0; i<n_bsn_masses; i++) {
00361       sfree(bsn_cg_arg[i], cname,fname, "bsn_cg_arg[i]");
00362     }
00363     sfree(bsn_cg_arg, cname,fname, "bsn_cg_arg");
00364   }
00365 
00366   // Free memory for the fermion CG arguments
00367   //----------------------------------------------------------------
00368   if(n_frm_masses != 0){
00369     for(i=0; i<n_frm_masses; i++){
00370       sfree(frm_cg_arg[i], cname,fname, "frm_cg_arg[i]");
00371     }
00372     sfree(frm_cg_arg, cname,fname, "frm_cg_arg");
00373   }
00374   
00375 }
00376 
00377 
00378 //------------------------------------------------------------------
00379 //
00380 // run(): The Rational Hybrid Monte Carlo algorithm.
00397 //------------------------------------------------------------------
00398 Float AlgHmcRHMC::run(void)
00399 {
00400 #if TARGET==cpsMPI
00401   using MPISCU::fprintf;
00402 #endif
00403   int step;                            // Trajectory step
00404   Float h_init;                        // Initial Hamiltonian
00405   Float h_final;                       // Final Hamiltonian
00406   Float delta_h;                       // Final-Initial Hamiltonian
00407   int accept;
00408 
00409   int cg_iter;
00410   Float cg_iter_av=0;
00411   int cg_iter_min=0;
00412   int cg_iter_max=0;
00413   Float true_res_av=0;
00414   Float true_res_min=0;
00415   Float true_res_max=0;
00416   int cg_calls=0;
00417   int shift;
00418   int i, j;
00419   char *fname = "run()";
00420   char *md_time_str = "MD_time/step_size = ";
00421   FILE *fp;
00422   VRB.Func(cname,fname);
00423   unsigned long step_cnt = 0;
00424   CSM.SaveComment(step_cnt);
00425 
00426   Float dev = 0.0;
00427   Float max_diff = 0.0;
00428 
00429   Float trueMass=0;
00430   Float acceptance;                            // The acceptance probability
00431   Float efficiency;
00432 
00433  
00434   // Get the Lattice object
00435   //----------------------------------------------------------------
00436   Lattice& lat = AlgLattice();
00437 
00438   // Set the microcanonical time step
00439   //----------------------------------------------------------------
00440   Float dt = hmd_arg->step_size;
00441 
00442   if(hmd_arg->metropolis) {
00443     // Save initial gauge field configuration
00444     //--------------------------------------------------------------
00445     lat.CopyGaugeField(gauge_field_init);
00446   }
00447 
00448   Float delta_h0;                       // save first run dH
00449   int Ntests;
00450   LRGState lrg_state;
00451 
00452   if (hmd_arg->reproduce) {
00453     // Save initial rng state
00454     //--------------------------------------------------------------
00455 //    LRG.GetStates(rng5d_init, FIVE_D);
00456 //    LRG.GetStates(rng4d_init, FOUR_D);
00457     lrg_state.GetStates();
00458     
00459     
00460     // Need to save initial lattice if have not already done so
00461     if (!hmd_arg->metropolis)
00462       lat.CopyGaugeField(gauge_field_init);
00463 
00464 
00465     if (hmd_arg->reproduce_attempt_limit < 1 ||
00466         hmd_arg->reproduce_attempt_limit > 5)
00467       hmd_arg->reproduce_attempt_limit = 3;
00468     Ntests = 2;
00469   } else {
00470     hmd_arg->reproduce_attempt_limit = 1;
00471     Ntests = 1;
00472   }
00473 
00474   if (lat.Fclass() == F_CLASS_DWF || lat.Fclass() == F_CLASS_ASQTAD || lat.Fclass() == F_CLASS_P4) {
00475     for (int i=0; i<n_frm_masses; i++)
00476       for (int j=0; j<hmd_arg->FRatDeg[i]; j++)
00477         alpha[i][j] = sqrt(hmd_arg->FRatRes[i][j]);
00478   }
00479 
00480   GDS.Set(0,0,0,0);
00481   GDS.SetOrigin(0,0,0,0);
00482   // Try attempt_limit times to generate the same final gauge config 
00483   // consecutively
00484   for (int attempt = 0; attempt < hmd_arg->reproduce_attempt_limit; attempt++) {
00485 
00486     for (int test = 0; test < Ntests; test++) {
00487       VRB.Result(cname,fname,"Running test %d of %d, attempt %d of %d\n", 
00488                  test+1, Ntests, attempt+1, hmd_arg->reproduce_attempt_limit);
00489 
00490       // Restore the initial gauge field and rng state
00491 
00492       if ( !(test == 0 && attempt ==0) ) {
00493         lat.GaugeField(gauge_field_init);
00494 //      LRG.SetStates(rng4d_init, FOUR_D);
00495 //      LRG.SetStates(rng5d_init, FIVE_D);
00496         lrg_state.SetStates();
00497         GDS.Set(1,1,1,0);
00498         LRG.Shift();
00499         lat.Shift();
00500         GDS.SetOrigin(1,1,1,0);
00501       }
00502 
00503       // Initialize Hamiltonian variables
00504       //----------------------------------------------------------------
00505       h_init=0;                        // Initial Hamiltonian
00506       h_final=0;                       // Final Hamiltonian
00507       delta_h=0;                       // Final-Initial Hamiltonian
00508       
00509       // Initialize monitor variables
00510       //----------------------------------------------------------------
00511       cg_iter_av   = 0.0;
00512       cg_iter_min  = 1000000;
00513       cg_iter_max  = 0;
00514       true_res_av  = 0.0;
00515       true_res_min = 3.4e+38;
00516       true_res_max = 0.0;
00517       cg_calls     = 0;
00518       
00519       // reset MD time in Lattice
00520       //----------------------------------------------------------------
00521       lat.MdTime(0.0);
00522       VRB.Flow(cname,fname,"%s%f\n", md_time_str, IFloat(lat.MdTime()));
00523       
00524       
00525       // Heat Bath for the conjugate momenta
00526       //----------------------------------------------------------------
00527       lat.RandGaussAntiHermMatrix(mom, 1.0);
00528       
00529       // Heat Bath for the boson field bsn
00530       //----------------------------------------------------------------
00531       for(i=0; i<n_bsn_masses; i++){
00532         lat.RandGaussVector(frmn[0], 0.5, Ncb);
00533         lat.RandGaussVector(bsn[i], 0.5, Ncb);
00534         lat.SetPhi(frmn[1], frmn[0], bsn[i], hmd_arg->bsn_mass[i]);
00535         lat.RandGaussVector(bsn[i], 0.5, Ncb);
00536         lat.FmatEvlInv(bsn[i], frmn[1], bsn_cg_arg[i], CNV_FRM_NO);
00537       }
00538       
00539       // Heat Bath for the pseudo-fermions (phi)
00540       // Use the SI approximation since need the inverse of the action
00541       //----------------------------------------------------------------
00542       
00543       h_init = lat.GhamiltonNode() + lat.MomHamiltonNode(mom);
00544       for(i=0; i<n_frm_masses; i++){
00545     
00546         lat.RandGaussVector(frmn[i], 0.5, Ncb);
00547         h_init += lat.FhamiltonNode(frmn[i],frmn[i]);
00548         
00549         massRenormalise(&(frm_cg_arg[i]->mass), &trueMass, hmd_arg->SRatDeg[i], 
00550                         hmd_arg->SIRatPole[i], RENORM_FORWARDS);
00551 
00552         phi[i] -> CopyVec(frmn[i], f_size);
00553         phi[i] -> VecTimesEquFloat(hmd_arg->SIRatNorm[i], f_size);
00554         cg_iter = lat.FmatEvlMInv(phi+i, frmn[i], hmd_arg->SIRatPole[i], hmd_arg->SRatDeg[i],
00555                                   hmd_arg->isz, frm_cg_arg[i], CNV_FRM_NO, SINGLE, 
00556                                   hmd_arg->SIRatRes[i]);
00557         
00558         massRenormalise(&(frm_cg_arg[i]->mass), &trueMass, hmd_arg->SRatDeg[i], 
00559                         hmd_arg->SIRatPole[i], RENORM_BACKWARDS);
00560         
00561         cg_iter_av += cg_iter;
00562         if(cg_iter < cg_iter_min) cg_iter_min = cg_iter;
00563         if(cg_iter > cg_iter_max) cg_iter_max = cg_iter;
00564         true_res_av += frm_cg_arg[i]->true_rsd;
00565         if(frm_cg_arg[i]->true_rsd < true_res_min) true_res_min = frm_cg_arg[i]->true_rsd;
00566         if(frm_cg_arg[i]->true_rsd > true_res_max) true_res_max = frm_cg_arg[i]->true_rsd;
00567         cg_calls++;      
00568 
00569       }
00570 
00571       // Calculate initial boson contribution to the Hamiltonian
00572       //---------------------------------------------------------------
00573       for(i=0; i<n_bsn_masses; i++)
00574         h_init += lat.BhamiltonNode(bsn[i], hmd_arg->bsn_mass[i]);
00575 
00576       //----------------------------------------------------------------
00577       // Molecular Dynamics Trajectory
00578       //----------------------------------------------------------------
00579 
00580       // Reset the residual error for the Molecular Dynamics
00581       //--------------------------------------------------------------
00582       for (i=0; i<n_frm_masses; i++)
00583         frm_cg_arg[i]->stop_rsd = hmd_arg->stop_rsd_md[i];
00584 
00585       // Perform initial QPQ integration
00586       //--------------------------------------------------------------
00587       if (hmd_arg->steps_per_traj > 0) {
00588         lat.EvolveGfield(mom, 0.25*dt/(Float)hmd_arg->sw);
00589         for (i=0; i<hmd_arg->sw; i++) {
00590           for(j=0; j<n_bsn_masses; j++)
00591             lat.EvolveMomFforce(mom, bsn[j], hmd_arg->bsn_mass[j], 
00592                                 -0.5*dt/(Float)hmd_arg->sw);
00593           lat.EvolveMomGforce(mom, 0.5*dt/(Float)hmd_arg->sw);
00594           if (i < hmd_arg->sw-1) lat.EvolveGfield(mom, 0.5*dt/(Float)hmd_arg->sw);
00595           else lat.EvolveGfield(mom, 0.25*dt/(Float)hmd_arg->sw);
00596         }
00597       }
00598 
00599       // First leap frog step has occurred. Increment MD Time clock in
00600       // Lattice one half time step.
00601       //----------------------------------------------------------------
00602       lat.MdTimeInc(0.5) ;
00603       VRB.Flow(cname,fname,"%s%f\n", md_time_str, IFloat(lat.MdTime()));
00604 
00605       // Run through the trajectory
00606       //----------------------------------------------------------------
00607 
00608       for(step=0; step < hmd_arg->steps_per_traj; step++){
00609         CSM.SaveComment(++step_cnt);
00610 
00611 
00612         // Evolve momenta by one step using the fermion force
00613         //--------------------------------------------------------------
00614 
00615         shift = 0;
00616         for(i=0; i<n_frm_masses; i++){
00617 
00618           massRenormalise(&(frm_cg_arg[i]->mass), &trueMass, hmd_arg->FRatDeg[i], 
00619                           hmd_arg->FRatPole[i], RENORM_FORWARDS);
00620       
00621           for (j=0; j<hmd_arg->FRatDeg[i]; j++) 
00622             bzero((char *)frmn[j+shift],f_size*sizeof(Float));
00623 
00624           cg_iter = lat.FmatEvlMInv(frmn + shift, phi[i], hmd_arg->FRatPole[i], 
00625                                     hmd_arg->FRatDeg[i], hmd_arg->isz, frm_cg_arg[i], 
00626                                     CNV_FRM_NO, frmn_d + shift);
00627 
00628           massRenormalise(&(frm_cg_arg[i]->mass), &trueMass, hmd_arg->FRatDeg[i], 
00629                           hmd_arg->FRatPole[i], RENORM_BACKWARDS);
00630       
00631           cg_iter_av += cg_iter;
00632           if(cg_iter < cg_iter_min) cg_iter_min = cg_iter;
00633           if(cg_iter > cg_iter_max) cg_iter_max = cg_iter;
00634           true_res_av += frm_cg_arg[i]->true_rsd;
00635           if(frm_cg_arg[i]->true_rsd < true_res_min) 
00636             true_res_min = frm_cg_arg[i]->true_rsd;
00637           if(frm_cg_arg[i]->true_rsd > true_res_max) 
00638             true_res_max = frm_cg_arg[i]->true_rsd;
00639           cg_calls++;      
00640 
00641           if ((lat.Fclass() != F_CLASS_ASQTAD && lat.Fclass() != F_CLASS_P4))
00642             lat.RHMC_EvolveMomFforce(mom, frmn+shift, hmd_arg->FRatDeg[i], 0,
00643                                      hmd_arg->FRatRes[i], hmd_arg->frm_mass[i],
00644                                      dt, frmn_d+shift, FORCE_MEASURE_NO);
00645 
00646           shift += hmd_arg->FRatDeg[i];
00647         }
00648 
00649         // Only for the case of asqtad fermions do we perform this optimisation
00650         //--------------------------------------------------------------      
00651         if ((lat.Fclass() == F_CLASS_ASQTAD || lat.Fclass() == F_CLASS_P4) && n_frm_masses != 0)
00652           {
00653             VRB.Flow(cname,fname,"start EvolveMomFforce\n");
00654 #if 1
00655 #if 1
00656             lat.RHMC_EvolveMomFforce(mom, frmn, total_size, 0, all_res, 0.0, dt, frmn_d, FORCE_MEASURE_NO);
00657 #else
00658             for(int jj = 0; jj< total_size; jj++)
00659               {
00660                 VRB.Flow(cname,fname,"before shift = %d, **(frmn+jj) = %e, all_res[jj]=%e\n",jj,*((IFloat *) *(frmn+jj)), all_res[jj]);
00661                 lat.RHMC_EvolveMomFforce(mom, frmn+jj, 1, 0, all_res+jj, 0.0, dt, frmn_d+jj, FORCE_MEASURE_NO);
00662                 VRB.Flow(cname,fname,"after shift = %d, **(frmn+jj) = %e, all_res[jj]=%e\n",jj,*((IFloat *) *(frmn+jj)), all_res[jj]);
00663               }
00664 #endif
00665 #else
00666             for(int jj = 0; jj < total_size; jj++)
00667               {
00668                 //VRB.Flow(cname,fname,"before shift = %d, **(frmn+jj) = %e, all_res[jj]=%e\n",jj,*((IFloat *) *(frmn+jj)), all_res[jj]);
00669                 frmn[jj]->VecTimesEquFloat(all_res[jj], GJP.VolNodeSites()*lat.FsiteSize()/2);
00670                 //VRB.Flow(cname,fname,"shift = %d, **(frmn+jj) = %e\n",jj,*((IFloat *) *(frmn+jj)));
00671                 lat.EvolveMomFforce(mom, *(frmn+jj), 0.0, dt);
00672                 //VRB.Flow(cname,fname,"after shift = %d, **(frmn+jj) = %e, all_res[jj]=%e\n",jj,*((IFloat *) *(frmn+jj)), all_res[jj]);
00673               }
00674 #endif
00675             VRB.Flow(cname,fname,"*((IFloat *)mom+777) = %e\n", *((IFloat *) mom+777));
00676           }
00677 
00678         // Increment MD Time clock in Lattice by one half time step.
00679         //--------------------------------------------------------------
00680         lat.MdTimeInc(0.5);
00681         VRB.Flow(cname,fname,"%s%f\n", md_time_str, IFloat(lat.MdTime()));
00682 
00683 
00684         if (step < hmd_arg->steps_per_traj-1) 
00685           {
00686             // Perform QPQ integration (pure gauge, boson and momenta)
00687             //----------------------------------------------------------------
00688             lat.EvolveGfield(mom, 0.5*dt/(Float)hmd_arg->sw);
00689             for (i=0; i<hmd_arg->sw; i++) {
00690               for(j=0; j<n_bsn_masses; j++)
00691                 lat.EvolveMomFforce(mom, bsn[j], hmd_arg->bsn_mass[j], 
00692                                     -dt/(Float)hmd_arg->sw);
00693               lat.EvolveMomGforce(mom, dt/(Float)hmd_arg->sw);
00694               if (i < hmd_arg->sw-1) lat.EvolveGfield(mom, dt/(Float)hmd_arg->sw);
00695               else lat.EvolveGfield(mom, 0.5*dt/(Float)hmd_arg->sw);
00696             }
00697 
00698             // Increment MD Time clock in Lattice by one half time step.
00699             //--------------------------------------------------------------
00700             lat.MdTimeInc(0.5);
00701             VRB.Flow(cname,fname,"%s%f\n", md_time_str, IFloat(lat.MdTime()));
00702           } 
00703         else 
00704           {
00705             // Perform final QPQ integration
00706             //----------------------------------------------------------------
00707             lat.EvolveGfield(mom, 0.25*dt/(Float)hmd_arg->sw);
00708             for (i=0; i<hmd_arg->sw; i++) {
00709               for(j=0; j<n_bsn_masses; j++)
00710                 lat.EvolveMomFforce(mom, bsn[j], hmd_arg->bsn_mass[j], 
00711                                     -0.5*dt/(Float)hmd_arg->sw);
00712               lat.EvolveMomGforce(mom, 0.5*dt/(Float)hmd_arg->sw);
00713               if (i < hmd_arg->sw-1) lat.EvolveGfield(mom, 0.5*dt/(Float)hmd_arg->sw);
00714               else lat.EvolveGfield(mom, 0.25*dt/(Float)hmd_arg->sw);
00715             }
00716 
00717           }
00718       }
00719 
00720       CSM.SaveComment(++step_cnt);
00721       // Reunitarize
00722       //----------------------------------------------------------------
00723       if(hmd_arg->reunitarize == REUNITARIZE_YES){
00724         lat.Reunitarize(dev, max_diff);
00725       }
00726       h_final = lat.GhamiltonNode();
00727       IFloat h_gauge = h_final;
00728 
00729       // Measure bounds and generate new approximations
00730       if (hmd_arg->approx_type == DYNAMIC) {
00731 #ifndef GMP
00732         ERR.General(cname,fname,"Dynamical rational generation not possible without gmp\n");
00733 #else
00734         dynamicalApprox();
00735 #endif
00736       }
00737 
00738       // Calculate final fermion contribution to the Hamiltonian
00739       //---------------------------------------------------------------
00740       shift = 0;
00741       for (i=0; i<n_frm_masses; i++) {
00742         massRenormalise(&(frm_cg_arg[i]->mass), &trueMass, hmd_arg->SRatDeg[i], 
00743                         hmd_arg->SRatPole[i], RENORM_FORWARDS);
00744 
00745         // Reset the residual error to the mc error
00746         frm_cg_arg[i]->stop_rsd = hmd_arg->stop_rsd_mc[i];
00747 
00748         frmn[shift] -> CopyVec(phi[i],f_size);
00749         frmn[shift] -> VecTimesEquFloat(hmd_arg->SRatNorm[i], f_size);
00750 
00751         cg_iter = lat.FmatEvlMInv(frmn+shift, phi[i], hmd_arg->SRatPole[i], 
00752                                   hmd_arg->SRatDeg[i], hmd_arg->isz, frm_cg_arg[i], 
00753                                   CNV_FRM_NO, SINGLE, hmd_arg->SRatRes[i]);
00754 
00755         massRenormalise(&(frm_cg_arg[i]->mass), &trueMass, hmd_arg->SRatDeg[i], 
00756                         hmd_arg->SRatPole[i], RENORM_BACKWARDS);
00757 
00758         cg_iter_av += cg_iter;
00759         if(cg_iter < cg_iter_min) cg_iter_min = cg_iter;
00760         if(cg_iter > cg_iter_max) cg_iter_max = cg_iter;
00761         true_res_av += frm_cg_arg[i]->true_rsd;
00762         if(frm_cg_arg[i]->true_rsd < true_res_min) true_res_min = frm_cg_arg[i]->true_rsd;
00763         if(frm_cg_arg[i]->true_rsd > true_res_max) true_res_max = frm_cg_arg[i]->true_rsd;
00764         cg_calls++;      
00765 
00766         h_final += lat.FhamiltonNode(frmn[shift], frmn[shift]);
00767         shift += hmd_arg->FRatDeg[i];
00768 
00769       }
00770   
00771       IFloat h_fermion = h_final - h_gauge;
00772       h_final += lat.MomHamiltonNode(mom);
00773       IFloat h_mom = h_final - h_gauge - h_fermion;
00774 
00775       // Calculate final boson contribution to the Hamiltonian
00776       //---------------------------------------------------------------
00777       for(i=0; i<n_bsn_masses; i++)
00778         h_final += lat.BhamiltonNode(bsn[i], hmd_arg->bsn_mass[i]);
00779 
00780       // Calculate Final-Initial Hamiltonian 
00781       //---------------------------------------------------------------
00782       delta_h = h_final - h_init;
00783       glb_sum(&h_gauge);
00784       glb_sum(&h_fermion);
00785       glb_sum(&h_mom);
00786       glb_sum(&h_init);
00787       glb_sum(&h_final);
00788       glb_sum(&delta_h);
00789       VRB.Result(cname,fname,"hamilton_gauge = %e\n", h_gauge);
00790       VRB.Result(cname,fname,"hamilton_fermion = %e\n", h_fermion);
00791       VRB.Result(cname,fname,"hamilton_mom = %e\n", h_mom);
00792       VRB.Result(cname,fname,"hamilton_final = %e\n", h_final);
00793       VRB.Result(cname,fname,"hamilton_initial = %e\n", h_init);
00794       VRB.Result(cname,fname,"delta_hamilton = %e\n", delta_h);
00795 
00796       // Check that delta_h is the same accross all s-slices 
00797       // (relevant only if GJP.Snodes() != 1)
00798       //----------------------------------------------------------------
00799       if(GJP.Snodes() != 1) {
00800         VRB.Flow(cname,fname, "Checking Delta H across s-slices\n");
00801         lat.SoCheck(delta_h);
00802       }
00803 
00804       if (hmd_arg->reproduce) {
00805         // Save final gauge field configuration
00806         if ( test != 0) {
00807           GDS.Set(-1,-1,-1,0);
00808           LRG.Shift();
00809           lat.Shift();
00810           GDS.SetOrigin(0,0,0,0);
00811         }
00812         else {
00813           lat.CopyGaugeField(gauge_field_final);
00814           delta_h0 = delta_h;
00815         }
00816       }
00817     } // end test loop
00818   
00819     if (hmd_arg->reproduce) {  
00820       // Compare the final gauge configs generated
00821       // if passed continue, else try again
00822       
00823       if (lat.CompareGaugeField(gauge_field_final)) {
00824         VRB.Result(cname,fname,"Passed reproducibility test\n");
00825         break;
00826       } else {
00827         VRB.Result(cname,fname, 
00828                    "Failed reproducibility dH0 = %18.16e, dH1 = %18.16e, delta dH = %18.16e\n", 
00829                    delta_h0, delta_h, delta_h-delta_h0);
00830       }
00831 
00832       VRB.Result(cname,fname,"Failed reproducibility test %d\n",attempt);
00833       if (attempt == hmd_arg->reproduce_attempt_limit-1) 
00834         ERR.General(cname,fname,"Failed to reproduce\n");
00835     } else {
00836       break;
00837     }
00838 
00839   } // end attempt loop
00840 
00841   // Metropolis step
00842   //---------------------------------------------------------------
00843   if(hmd_arg->metropolis){
00844     // Metropolis accept-reject step
00845     //--------------------------------------------------------------
00846     accept = lat.MetropolisAccept(delta_h,&acceptance);
00847     if( !(accept) ){
00848       // Trajectory rejected
00849       //------------------------------------------------------------
00850       lat.GaugeField(gauge_field_init);
00851       VRB.Result(cname,fname,"Metropolis step -> Rejected\n");
00852     }
00853     else {
00854       // Trajectory accepted. 
00855       // Increment the Gauge Update counter in Lattice.
00856       //-------------------------------------------------------------
00857       lat.GupdCntInc(1);
00858       VRB.Result(cname,fname,"Metropolis step -> Accepted\n");
00859     }
00860   } 
00861   else {
00862     accept = 1;
00863     acceptance = 1.0;
00864     lat.GupdCntInc(1);
00865     VRB.Result(cname,fname,"No Metropolis step -> Accepted\n");
00866   }    
00867 
00868 
00869   // Calculate average of monitor variables
00870   //---------------------------------------------------------------
00871   
00872   efficiency = Float(acceptance) / Float(cg_iter_av);
00873   cg_iter_av = Float(cg_iter_av) / Float(cg_calls);
00874   true_res_av = Float(true_res_av) / Float(cg_calls);
00875 
00876 
00877   // If GJP.Snodes() !=1  the gauge field is spread out
00878   // across s-slices of processors. It must be identical
00879   // on each slice. Check to make sure and exit if it
00880   // is not identical. A case where this is relevant
00881   // is the DWF spread-out case.
00882   //----------------------------------------------------------------
00883   if(GJP.Snodes() != 1) {
00884     VRB.Flow(cname,fname, "Checking gauge field across s-slices\n");
00885     lat.GsoCheck();
00886   }
00887 
00888   // Print out monitor info
00889   //---------------------------------------------------------------
00890   if(common_arg->results != 0){
00891     if( (fp = Fopen((char *)common_arg->results, "a")) == NULL ) {
00892       ERR.FileA(cname,fname, (char *)common_arg->results);
00893     }
00894     Fprintf(fp,"%d %e %e %d %e %e %e %d %d %e %e %e\n",
00895             hmd_arg->steps_per_traj,
00896             IFloat(delta_h), 
00897             acceptance,
00898             accept, 
00899             IFloat(dev),
00900             IFloat(max_diff),
00901             IFloat(cg_iter_av),
00902             cg_iter_min,
00903             cg_iter_max,
00904             IFloat(true_res_av),
00905             IFloat(true_res_min),
00906             IFloat(true_res_max));
00907     Fclose(fp);
00908   }
00909 
00910   VRB.Result(cname,fname,
00911              "Hmc steps = %d, Delta_hamilton = %e, accept = %d, dev = %e, max_diff = %e\n",
00912              hmd_arg->steps_per_traj,
00913              IFloat(delta_h), 
00914              accept,
00915              IFloat(dev),
00916              IFloat(max_diff));
00917   VRB.Result(cname,fname,
00918              "CG iterations: average = %e, min = %d, max = %d\n",
00919              IFloat(cg_iter_av),
00920              cg_iter_min,
00921              cg_iter_max);
00922   VRB.Result(cname,fname,
00923              "True Residual / |source|: average = %e, min = %e, max = %e\n",
00924              IFloat(true_res_av),
00925              IFloat(true_res_min),
00926              IFloat(true_res_max));
00927 
00928   VRB.Result(cname,fname,
00929              "Efficiency (acceptance per cg iteration) = %e\n",
00930              efficiency);
00931 
00932   VRB.Result(cname,fname,"Configuration number = %d\n", lat.GupdCnt());
00933 
00934   for (int i=0; i<n_frm_masses; i++)
00935     VRB.Result(cname,fname,"%d psi_bar psi = %e\n", 
00936                i, lat.FhamiltonNode(phi[i],phi[i]));
00937   
00938 
00939   // Reset Molecular Dynamics time counter
00940   //----------------------------------------------------------------
00941   lat.MdTime(0.0);
00942   VRB.Flow(cname,fname,"%s%f\n", md_time_str, IFloat(lat.MdTime()));
00943 
00944   //  ERR.HdwCheck(cname,fname);
00945 
00946   return acceptance;
00947 }
00948 
00953 void AlgHmcRHMC::massRenormalise(Float *mass, Float *trueMass, int degree, 
00954                                   Float *shift, MassRenormaliseDir direction) {
00955 
00956     // Can only renormalise mass for staggered or asqtad cases
00957   if (AlgLattice().Fclass() == F_CLASS_ASQTAD || AlgLattice().Fclass() == F_CLASS_STAG || AlgLattice().Fclass() == F_CLASS_P4) {
00958     if (direction == RENORM_FORWARDS) {
00959       *trueMass = *mass;
00960       *mass = sqrt((*trueMass)*(*trueMass) + shift[hmd_arg->isz]/4.0);
00961       Float zeroPole = shift[hmd_arg->isz];
00962       for (int j=0; j<degree; j++) shift[j] -= zeroPole;
00963     } else if (direction == RENORM_BACKWARDS) {
00964       Float zeroPole = 4.0*((*mass)*(*mass) - (*trueMass)*(*trueMass));
00965       for (int j=0; j<degree; j++) shift[j] += zeroPole;
00966       *mass = *trueMass;
00967     }
00968   }
00969 
00970 }
00971 
00975 void AlgHmcRHMC::generateApprox(HmdArg *hmd_arg)
00976 {
00977 
00978   // Construct approximations
00979   for (int i=0; i<hmd_arg->n_frm_masses; i++) {
00980     for (int j=0; j<i; j++) {
00981       // no need to recalculate approximation if same mass
00982       if (hmd_arg->frm_mass[j] == hmd_arg->frm_mass[i] &&
00983           hmd_arg->field_type[j] == hmd_arg->field_type[i] &&
00984           hmd_arg->frm_power_num[j] ==hmd_arg-> frm_power_num[i] &&
00985           hmd_arg->frm_power_den[j] ==hmd_arg-> frm_power_den[i] ) {
00986         hmd_arg->FRatDeg[i] = hmd_arg->FRatDeg[j];
00987         hmd_arg->FRatNorm[i] = hmd_arg->FRatNorm[j];
00988         for (int k=0; k<hmd_arg->FRatDeg[i]; k++) {
00989           hmd_arg->FRatRes[i][k] = hmd_arg->FRatRes[j][k];
00990           hmd_arg->FRatPole[i][k] = hmd_arg->FRatPole[j][k];
00991         }
00992         hmd_arg->SRatDeg[i] = hmd_arg->SRatDeg[j];
00993         hmd_arg->SRatNorm[i] = hmd_arg->SRatNorm[j];
00994         hmd_arg->SIRatNorm[i] = hmd_arg->SIRatNorm[j];
00995         for (int k=0; k<hmd_arg->SRatDeg[i]; k++) {
00996           hmd_arg->SRatRes[i][k] = hmd_arg->SRatRes[j][k];
00997           hmd_arg->SRatPole[i][k] = hmd_arg->SRatPole[j][k];
00998           hmd_arg->SIRatRes[i][k] = hmd_arg->SIRatRes[j][k];
00999           hmd_arg->SIRatPole[i][k] = hmd_arg->SIRatPole[j][k];
01000         }
01001         hmd_arg->valid_approx[i] = 1;
01002       }
01003     }
01004 
01005 // CJ: backward compatibility
01006 
01007     if (!hmd_arg->valid_approx[i]) {
01008 //      AlgRemez remez(hmd_arg->lambda_low[i],hmd_arg->lambda_high[i],hmd_arg->precision);
01009 //      hmd_arg->FRatError[i] = remez.generateApprox(hmd_arg->FRatDeg[i],hmd_arg->frm_power_num[i], hmd_arg->frm_power_den[i]);
01010 
01011         RemezArg remez_arg;
01012         //-----------------------------------------------
01013         //Ugly hack to make things work with this deprecated style of RHMC
01014         //michaelc 03/01/06
01015         remez_arg.approx_type = RATIONAL_APPROX_POWER;
01016         //-----------------------------------------------
01017         remez_arg.degree = hmd_arg->FRatDeg[i];
01018         remez_arg.field_type = hmd_arg->field_type[i];
01019         remez_arg.lambda_low = hmd_arg->lambda_low[i];
01020         remez_arg.lambda_high = hmd_arg->lambda_high[i];
01021         remez_arg.power_num = hmd_arg->frm_power_num[i];
01022         remez_arg.power_den = hmd_arg->frm_power_den[i];
01023         remez_arg.precision = hmd_arg->precision;
01024         remez_arg.delta_m = 0.0;
01025         {
01026             AlgRemez remez(remez_arg);
01027             remez.generateApprox();
01028             hmd_arg->FRatError[i] = remez_arg.error;
01029             if (hmd_arg->field_type[i] == BOSON) {
01030                 remez.getPFE(hmd_arg->FRatRes[i],hmd_arg->FRatPole[i],&hmd_arg->FRatNorm[i]);
01031              } else {
01032                 remez.getIPFE(hmd_arg->FRatRes[i],hmd_arg->FRatPole[i],&hmd_arg->FRatNorm[i]);
01033              }
01034         }
01035 
01036    //   hmd_arg->SRatError[i] = remez.generateApprox(hmd_arg->SRatDeg[i],hmd_arg->frm_power_num[i], 2*hmd_arg->frm_power_den[i]);
01037         remez_arg.degree = hmd_arg->SRatDeg[i];
01038         remez_arg.power_num = hmd_arg->frm_power_num[i];
01039         remez_arg.power_den = 2*hmd_arg->frm_power_den[i];
01040         {
01041             AlgRemez remez(remez_arg);
01042             remez.generateApprox();
01043             hmd_arg->SRatError[i] = remez_arg.error;
01044 
01045             if (hmd_arg->field_type[i] == BOSON) {
01046                 remez.getPFE(hmd_arg->SRatRes[i],hmd_arg->SRatPole[i],&hmd_arg->SRatNorm[i]);
01047                 remez.getIPFE(hmd_arg->SIRatRes[i],hmd_arg->SIRatPole[i],&hmd_arg->SIRatNorm[i]);
01048             }else {
01049                 remez.getIPFE(hmd_arg->SRatRes[i],hmd_arg->SRatPole[i],&hmd_arg->SRatNorm[i]);
01050                 remez.getPFE(hmd_arg->SIRatRes[i],hmd_arg->SIRatPole[i],&hmd_arg->SIRatNorm[i]);
01051             }
01052         }
01053         hmd_arg->valid_approx[i] = 1;
01054     }      
01055     
01056   }
01057   
01058 }
01059 
01064 void AlgHmcRHMC::dynamicalApprox()
01065 {
01066 
01067   char *fname = "dynamicalApprox()";
01068   VRB.Func(cname,fname);
01069 
01070   // Get the Lattice object
01071   //----------------------------------------------------------------
01072   Lattice& lat = AlgLattice();
01073 
01074   // First measure highest and lowest eigenvalues
01075   eig_arg->N_eig = 1;
01076 
01077   Vector **psi = (Vector**) smalloc(sizeof(Vector*),
01078                                     cname,fname, "psi");
01079   Float *lambda = (Float*) smalloc(2*sizeof(Float), 
01080                                    cname,fname, "lambda");
01081   Float *chirality = (Float*) smalloc(sizeof(Float),
01082                                       cname,fname, "chirality");
01083   int *valid_eig = (int*) smalloc(sizeof(int), 
01084                                   cname,fname, "valid_eig");
01085   Float **hsum = (Float**) smalloc(sizeof(Float*), 
01086                                    cname,fname, "hsum");
01087 
01088   size_t hsum_size=0;
01089   switch(eig_arg->hsum_dir == 0){
01090   case DIR_X:
01091     hsum_size = GJP.Xnodes()*GJP.XnodeSites() * sizeof(Float);
01092     break;
01093   case DIR_Y:
01094     hsum_size = GJP.Ynodes()*GJP.YnodeSites() * sizeof(Float);
01095     break;
01096   case DIR_Z:
01097     hsum_size = GJP.Znodes()*GJP.ZnodeSites() * sizeof(Float);
01098     break;
01099   case DIR_T:
01100     hsum_size = GJP.Tnodes()*GJP.TnodeSites() * sizeof(Float);
01101     break;
01102   default:
01103     ERR.General(cname, fname, "Bad value %d for eig_arg.hsum_dir\n",
01104                 eig_arg->hsum_dir);
01105   }
01106   hsum[0] = (Float*) smalloc(hsum_size, cname,fname, "hsum[0]");
01107   psi[0] = (Vector*) smalloc(f_size*sizeof(Float), cname,fname, "psi[0]");
01108 
01109   for (int i=0; i<n_frm_masses; i++) {
01110     // Reset the required degree of approximation
01111     if (hmd_arg->FRatDegNew[i] == 0)
01112       hmd_arg->FRatDegNew[i] = hmd_arg->FRatDeg[i];
01113 
01114     if (hmd_arg->SRatDegNew[i] == 0)
01115       hmd_arg->SRatDegNew[i] = hmd_arg->SRatDeg[i];
01116 
01117     eig_arg->mass = hmd_arg->frm_mass[i];
01118 
01119     // Measure lowest e-value
01120     eig_arg->RitzMatOper = MATPCDAG_MATPC;
01121     lat.RandGaussVector(psi[0], 0.5, 1);
01122     lat.FeigSolv(psi, lambda, chirality, valid_eig, hsum, eig_arg, CNV_FRM_NO);
01123       
01124     // Measure highest e-value
01125     eig_arg->RitzMatOper = NEG_MATPCDAG_MATPC;
01126     lat.RandGaussVector(psi[0], 0.5, 1);
01127     lat.FeigSolv(psi, lambda+1, chirality, valid_eig, hsum, eig_arg,CNV_FRM_NO);
01128     lambda[1] *= -1;
01129 
01130     VRB.Result(cname,fname, "Old Spectral Bounds are [%f,%f]\n",
01131                hmd_arg->lambda_low[i],hmd_arg->lambda_high[i]);
01132     VRB.Result(cname,fname, "New Spectral Bounds are [%f,%f]\n",
01133                lambda[0],lambda[1]);
01134 
01135     // Need to reconstruct approximations if either the spectrum leaves the 
01136     // interval or if it moves much inside the interval
01137     
01138     Float delta = eig_arg->Rsdlam + hmd_arg->spread;
01139     
01140     if (lambda[0] < hmd_arg->lambda_low[i]  || // below interval
01141         lambda[1] > hmd_arg->lambda_high[i] || // above interval
01142         lambda[0] > hmd_arg->lambda_low[i]  * (1.0+delta) || //inside from below
01143         lambda[1] < hmd_arg->lambda_high[i] * (1.0-delta) ||
01144         hmd_arg->FRatDeg[i] != hmd_arg->FRatDegNew[i] ||
01145         hmd_arg->SRatDeg[i] != hmd_arg->SRatDegNew[i] ) { // inside from above
01146       VRB.Result(cname,fname,"Reconstructing approximation\n");
01147       
01148       if (hmd_arg->SRatDeg[i] != hmd_arg->SRatDegNew[i])
01149         hmd_arg->SRatDeg[i] = hmd_arg->SRatDegNew[i];
01150       
01151       // If bounded, remain within bounds
01152       if (lambda[0]*(1-delta) > hmd_arg->lambda_min[i]) 
01153         hmd_arg->lambda_low[i] = lambda[0]*(1-delta);
01154       else
01155         hmd_arg->lambda_low[i] = hmd_arg->lambda_min[i];
01156     
01157       if (lambda[1]*(1+delta) < hmd_arg->lambda_max[i]) 
01158         hmd_arg->lambda_high[i] = lambda[1]*(1+delta);
01159       else
01160         hmd_arg->lambda_high[i] = hmd_arg->lambda_max[i];
01161 
01162 //      AlgRemez remez(hmd_arg->lambda_low[i], hmd_arg->lambda_high[i], hmd_arg->precision);
01163       
01164 //      remez.generateApprox(hmd_arg->FRatDeg[i],hmd_arg->frm_power_num[i], hmd_arg->frm_power_den[i]);
01165       RemezArg remez_arg;
01166       remez_arg.degree = hmd_arg->FRatDeg[i];
01167       remez_arg.field_type = hmd_arg->field_type[i];
01168       remez_arg.lambda_low = hmd_arg->lambda_low[i];
01169       remez_arg.lambda_high = hmd_arg->lambda_high[i];
01170       remez_arg.power_num = hmd_arg->frm_power_num[i];
01171       remez_arg.power_den = hmd_arg->frm_power_den[i];
01172       remez_arg.precision = hmd_arg->precision;
01173       {
01174         AlgRemez remez(remez_arg);
01175         remez.generateApprox();
01176         hmd_arg->FRatError[i] = remez_arg.error;
01177         if (hmd_arg->field_type[i] == BOSON) {
01178           remez.getPFE(hmd_arg->FRatRes[i], hmd_arg->FRatPole[i], &hmd_arg->FRatNorm[i]);
01179         } else {
01180           remez.getIPFE(hmd_arg->FRatRes[i], hmd_arg->FRatPole[i], &hmd_arg->FRatNorm[i]);
01181         }
01182       }
01183 
01184 //      remez.generateApprox(hmd_arg->SRatDeg[i],hmd_arg->frm_power_num[i], 2*hmd_arg->frm_power_den[i]);
01185 
01186       remez_arg.degree = hmd_arg->SRatDeg[i];
01187       remez_arg.power_num = hmd_arg->frm_power_num[i];
01188       remez_arg.power_den = 2*hmd_arg->frm_power_den[i];
01189       {
01190         AlgRemez remez(remez_arg);
01191         remez.generateApprox();
01192         hmd_arg->SRatError[i] = remez_arg.error;
01193         if (hmd_arg->field_type[i] == BOSON) {
01194           remez.getPFE(hmd_arg->SRatRes[i],hmd_arg->SRatPole[i], &hmd_arg->SRatNorm[i]);
01195           remez.getIPFE(hmd_arg->SIRatRes[i],hmd_arg->SIRatPole[i], &hmd_arg->SIRatNorm[i]);
01196         } else {
01197           remez.getIPFE(hmd_arg->SRatRes[i],hmd_arg->SRatPole[i], &hmd_arg->SRatNorm[i]);
01198           remez.getPFE(hmd_arg->SIRatRes[i],hmd_arg->SIRatPole[i], &hmd_arg->SIRatNorm[i]);
01199         }
01200       }
01201     } else {
01202       VRB.Result(cname,fname,"Reconstruction not necessary\n");
01203     }
01204     
01205   }
01206 
01207   sfree(hsum[0], cname,fname, "hsum[0]");
01208   sfree(hsum, cname,fname, "hsum");
01209   sfree(psi[0], cname,fname, "psi[0]");
01210   sfree(psi, cname,fname, "psi");
01211   sfree(lambda, cname,fname, "lambda");
01212   sfree(chirality, cname,fname, "chirality");
01213   sfree(valid_eig, cname,fname, "valid_eig");
01214 
01215 }
01216 
01217 
01218 CPS_END_NAMESPACE

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