#include CPS_START_NAMESPACE /*!\file \brief Implementation of Fclover class. $Id: f_clover.C,v 1.21 2007/06/06 16:06:23 chulwoo Exp $ */ //-------------------------------------------------------------------- // CVS keywords // // $Author: chulwoo $ // $Date: 2007/06/06 16:06:23 $ // $Header: /space/cvs/cps/cps++/src/util/lattice/f_clover/f_clover.C,v 1.21 2007/06/06 16:06:23 chulwoo Exp $ // $Id: f_clover.C,v 1.21 2007/06/06 16:06:23 chulwoo Exp $ // $Name: v5_0_16_hantao_io_test_v7 $ // $Locker: $ // $RCSfile: f_clover.C,v $ // $Revision: 1.21 $ // $Source: /space/cvs/cps/cps++/src/util/lattice/f_clover/f_clover.C,v $ // $State: Exp $ // //-------------------------------------------------------------------- //------------------------------------------------------------------ // // f_clover.C // // Fclover is derived from FwilsonTypes and is relevant to // clover Wilson fermions // //------------------------------------------------------------------ CPS_END_NAMESPACE #include #include #include #include #include #include #include #include #include #include #include CPS_START_NAMESPACE //------------------------------------------------------------------ // local constansts //------------------------------------------------------------------ enum { CLOVER_MAT_SIZE = 72, // COLORS^2 * lat.SpinComponents()^2 / 2; HALF_CLOVER_MAT_SIZE = 36 }; //------------------------------------------------------------------ // Constructor //------------------------------------------------------------------ Fclover::Fclover() { cname = "Fclover"; char *fname = "Fclover()"; VRB.Func(cname,fname); //---------------------------------------------------------------- // Allocate memory for the two clover matrices (one for each // checkerboard). Set the pointers to be the aux0_ptr and aux1_ptr // pointers of the base class. // ???Ping??? //---------------------------------------------------------------- int size = CLOVER_MAT_SIZE * GJP.VolNodeSites()*sizeof(Float) / 2; aux0_ptr = (void *) smalloc(size); if(aux0_ptr == 0) ERR.Pointer(cname,fname, "aux0_ptr"); VRB.Smalloc(cname,fname, "aux0_ptr",aux0_ptr, size); aux1_ptr = (void *) smalloc(size); if(aux1_ptr == 0) ERR.Pointer(cname,fname, "aux1_ptr"); VRB.Smalloc(cname,fname, "aux1_ptr",aux1_ptr, size); //---------------------------------------------------------------- // Do initializations before the clover library can be used //---------------------------------------------------------------- static Clover clover_struct; f_dirac_op_init_ptr = &clover_struct; clover_init(&clover_struct); } //------------------------------------------------------------------ // Destructor //------------------------------------------------------------------ Fclover::~Fclover() { char *fname = "~Fclover()"; VRB.Func(cname,fname); //---------------------------------------------------------------- // Un-initialize the clover library. Memory is set free here. //---------------------------------------------------------------- clover_end((Clover *) f_dirac_op_init_ptr); // Free memory for the clover matrices // ???Ping??? //---------------------------------------------------------------- VRB.Sfree(cname,fname, "aux1_ptr",aux1_ptr); sfree(aux1_ptr); VRB.Sfree(cname,fname, "aux0_ptr",aux0_ptr); sfree(aux0_ptr); } //------------------------------------------------------------------ // FclassType Fclass(): // It returns the type of fermion class. //------------------------------------------------------------------ FclassType Fclover::Fclass() const{ return F_CLASS_CLOVER; } //------------------------------------------------------------------ // int FchkbEvl() : // returns 0 => The fermion fields in the evolution // are defined on ODD-EVEN checkerboard (whole // lattice). //------------------------------------------------------------------ int Fclover::FchkbEvl() const { return 0; } //------------------------------------------------------------------ // int FmatEvlInv(Vector *f_out, Vector *f_in, // CgArg *cg_arg, // Float *true_res, // CnvFrmType cnv_frm = CNV_FRM_YES): // It calculates f_out where A * f_out = f_in and // A is the preconditioned fermion matrix that appears // in the HMC evolution (even/odd preconditioning // of [Dirac^dag Dirac]. The inversion of the odd checkerboard // piece is done with the conjugate gradient algorithm // while the inversion of the even checkerboard is done // using standard explicit hermitian matrix inversion of the // clover matrix. cg_arg is the structure that contains // all the control parameters for the CG, f_in is the // fermion field source vector, f_out should be set to be // the initial guess and on return is the solution. // f_in and f_out are defined on the whole latice. // If true_res !=0 the value of the true residual of the CG and // is returned in true_res. // *true_res = |src - MatPcDagMatPc * sol| / |src| // The function returns the total number of CG iterations. //------------------------------------------------------------------ int Fclover::FmatEvlInv(Vector *f_out, Vector *f_in, CgArg *cg_arg, Float *true_res, CnvFrmType cnv_frm) { int iter; char *fname = "FmatEvlInv(CgArg*,V*,V*,F*,CnvFrmType)"; VRB.Func(cname,fname); DiracOpClover clover(*this, f_out, f_in, cg_arg, cnv_frm); // iter = clover.InvCg(&(cg_arg->true_rsd)); iter = clover.MatEvlInv(&(cg_arg->true_rsd)); if (true_res) *true_res = cg_arg ->true_rsd; // Return the number of CG iterations return iter; } int Fclover::FmatEvlMInv(Vector **f_out, Vector *f_in, Float *shift, int Nshift, int isz, CgArg **cg_arg, CnvFrmType cnv_frm, MultiShiftSolveType type, Float *alpha, Vector **f_out_d) { char *fname = "MatMInv(Vector **out, Vector *in, Float *shift,..."; VRB.Func(cname, fname); ERR.NotImplemented(cname,fname); return -1; } void Fclover::FminResExt(Vector *sol, Vector *source, Vector **sol_old, Vector **vm, int degree, CgArg *cg_arg, CnvFrmType cnv_frm) { char *fname = "FminResExt(V*, V*, V**, V**, int, CgArg *, CnvFrmType)"; VRB.Func(cname,fname); DiracOpClover clover(*this, sol, source, cg_arg, cnv_frm); clover.MinResExt(sol,source,sol_old,vm,degree); } //------------------------------------------------------------------ // int FmatInv(Vector *f_out, Vector *f_in, // CgArg *cg_arg, // Float *true_res, // CnvFrmType cnv_frm = CNV_FRM_YES, // PreserveType prs_f_in = PRESERVE_YES): // It calculates f_out where A * f_out = f_in and // A is the fermion matrix (Dirac operator) with no // preconditioning. The preconditioned matrix is inverted // and from the result the non-preconditioned f_out is // calculated . The inversion of the odd checkerboard // piece is done with the conjugate gradient algorithm // while the inversion of the even checkerboard is done // using standard explicit hermitian matrix inversion of the // clover matrix. cg_arg is the structure that contains // all the control parameters for the CG, f_in is the // fermion field source vector, f_out should be set to be // the initial guess and on return is the solution. // f_in and f_out are defined on the whole latice. // If true_res !=0 the value of the true residual of the CG and // is returned in true_res. // *true_res = |src - MatPcDagMatPc * sol| / |src| // cnv_frm is used to specify if f_in should be converted // from canonical to fermion order and f_out from fermion // to canonical. // prs_f_in is used to specify if the source // f_in should be preserved or not. If not the memory usage // is less by the size of one fermion vector. // The function returns the total number of CG iterations. //------------------------------------------------------------------ int Fclover::FmatInv(Vector *f_out, Vector *f_in, CgArg *cg_arg, Float *true_res, CnvFrmType cnv_frm, PreserveType prs_f_in) { int iter; char *fname = "FmatInv(CgArg*,V*,V*,F*,CnvFrmType)"; VRB.Func(cname,fname); DiracOpClover clover(*this, f_out, f_in, cg_arg, cnv_frm); iter = clover.MatInv(true_res, prs_f_in); // Return the number of iterations return iter; } //------------------------------------------------------------------ // int FeigSolv(Vector **f_eigenv, Float *lambda, int *valid_eig, // EigArg *eig_arg, // CnvFrmType cnv_frm = CNV_FRM_YES): //------------------------------------------------------------------ int Fclover::FeigSolv(Vector **f_eigenv, Float *lambda, Float *chirality, int *valid_eig, Float **hsum, EigArg *eig_arg, CnvFrmType cnv_frm) { int iter; char *fname = "FeigSolv(EigArg*,V*,F*,CnvFrmType)"; VRB.Func(cname,fname); CgArg cg_arg; cg_arg.mass = eig_arg->mass; cg_arg.RitzMatOper = eig_arg->RitzMatOper; if(cnv_frm == CNV_FRM_YES) for(int i=0; i < eig_arg->N_eig; ++i) Fconvert(f_eigenv[i], WILSON, StrOrd()); // Call constructor and solve for eigenvectors. // Use null pointers to fake out constructor. Vector *v1 = (Vector *)0; Vector *v2 = (Vector *)0; DiracOpClover clover(*this, v1, v2, &cg_arg, CNV_FRM_NO); iter = clover.RitzEig(f_eigenv, lambda, valid_eig, eig_arg); if(cnv_frm == CNV_FRM_YES) for(int i=0; i < eig_arg->N_eig; ++i) Fconvert(f_eigenv[i], CANONICAL, StrOrd()); // Compute chirality size_t f_size = (GJP.VolNodeSites() * FsiteSize()); Float factor = 4.0 + eig_arg->mass; v1 = (Vector *)smalloc(f_size*sizeof(Float)); if (v1 == 0) ERR.Pointer(cname, fname, "v1"); VRB.Smalloc(cname, fname, "v1", v1, f_size*sizeof(Float)); for(int i=0; i < eig_arg->N_eig; ++i) { Gamma5(v1, f_eigenv[i], GJP.VolNodeSites()); chirality[i] = f_eigenv[i]->ReDotProductGlbSum4D(v1, f_size); lambda[i] *= factor; } VRB.Sfree(cname, fname, "v1", v1); sfree(v1); // Return the number of iterations return iter; } //------------------------------------------------------------------ // SetPhi(Vector *phi, Vector *frm1, Vector *frm2, Float mass, // DagType dag): // It sets the pseudofermion field phi from frm1, frm2. // Modified - now returns the (trivial) value of the action //------------------------------------------------------------------ Float Fclover::SetPhi(Vector *phi, Vector *frm1, Vector *frm2, Float mass, DagType dag){ char *fname = "SetPhi(V*,V*,V*,F)"; VRB.Func(cname,fname); CgArg cg_arg; cg_arg.mass = mass; if (phi == 0) ERR.Pointer(cname,fname,"phi") ; if (frm1 == 0) ERR.Pointer(cname,fname,"frm1") ; Fconvert(frm1,WILSON,CANONICAL); DiracOpClover clover(*this, frm1, frm2, &cg_arg, CNV_FRM_NO); const int half_sites = GJP.VolNodeSites()/2; int vec_size = FsiteSize() * half_sites; IFloat *frm1_even = (IFloat *)frm1 + vec_size; IFloat *phi_even = (IFloat *)phi + vec_size; IFloat *A_even = (IFloat *)Aux0Ptr(); // phi_odd = (Aoo - kappa*kappa*Doe Aee^inv Deo)^dagger frm1_odd if (dag == DAG_YES) clover.MatPcDag(phi, frm1); else clover.MatPc(phi, frm1); // Calculate the clover matrices for the EVEN checkerboard IFloat *Ap = A_even; for (int i = 0; i < GJP.VolNodeSites(); ++i) { mat_inv(Ap, Ap, 6, MAT_INV_ALG_LDL_CMPR, 0); Ap += HALF_CLOVER_MAT_SIZE; } // phi_even = Aee frm1_even clover_mat_mlt((IFloat *)phi_even, (const IFloat *)(A_even), (const IFloat *)frm1_even, half_sites); return FhamiltonNode(frm1, frm1); } //------------------------------------------------------------------ // EvolveMomFforce(Matrix *mom, Vector *frm, Float mass, // Float dt): // It evolves the canonical momentum mom by dt // using the fermion force. //------------------------------------------------------------------ ForceArg Fclover::EvolveMomFforce(Matrix *mom, Vector *frm, Float mass, Float dt) { char *fname = "EvolveMomFforce(M*,V*,F,F,F)"; VRB.Func(cname,fname); Matrix *gauge = GaugeField() ; if (Colors() != 3) ERR.General(cname,fname,"Wrong nbr of colors.") ; if (SpinComponents() != 4) ERR.General(cname,fname,"Wrong nbr of spin comp.") ; if (mom == 0) ERR.Pointer(cname,fname,"mom") ; if (frm == 0) ERR.Pointer(cname,fname,"frm") ; //------------------------------------------------------------------ // allocate space for four CANONICAL fermion fields. //------------------------------------------------------------------ size_t f_size = FsiteSize() * GJP.VolNodeSites() ; char *str_v1 = "v1" ; Vector *v1 = (Vector *)smalloc(f_size*sizeof(Float)) ; if (v1 == 0) ERR.Pointer(cname, fname, str_v1) ; VRB.Smalloc(cname, fname, str_v1, v1, f_size*sizeof(Float)) ; char *str_v2 = "v2" ; Vector *v2 = (Vector *)smalloc(f_size*sizeof(Float)) ; if (v2 == 0) ERR.Pointer(cname, fname, str_v2) ; VRB.Smalloc(cname, fname, str_v2, v2, f_size*sizeof(Float)) ; char *str_v3 = "v3" ; Vector *v3 = (Vector *)smalloc(f_size*sizeof(Float)) ; if (v3 == 0) ERR.Pointer(cname, fname, str_v3) ; VRB.Smalloc(cname, fname, str_v3, v3, f_size*sizeof(Float)) ; char *str_v4 = "v4" ; Vector *v4 = (Vector *)smalloc(f_size*sizeof(Float)) ; if (v4 == 0) ERR.Pointer(cname, fname, str_v4) ; VRB.Smalloc(cname, fname, str_v4, v4, f_size*sizeof(Float)) ; //------------------------------------------------------------------ // allocate space for two CANONICAL fermion field on a site. //------------------------------------------------------------------ char *str_site_v1 = "site_v1"; Float *site_v1 = (Float *)smalloc(FsiteSize()*sizeof(Float)); if (site_v1 == 0) ERR.Pointer(cname, fname, str_site_v1) ; VRB.Smalloc(cname, fname, str_site_v1, site_v1, FsiteSize()*sizeof(Float)) ; char *str_site_v2 = "site_v2"; Float *site_v2 = (Float *)smalloc(FsiteSize()*sizeof(Float)); if (site_v2 == 0) ERR.Pointer(cname, fname, str_site_v2) ; VRB.Smalloc(cname, fname, str_site_v2, site_v2, FsiteSize()*sizeof(Float)) ; Float L1 = 0.0; Float L2 = 0.0; Float Linf = 0.0; //------------------------------------------------------------------ // Calculate the force vectors for the ODD checkerboard //------------------------------------------------------------------ { CgArg cg_arg ; cg_arg.mass = mass ; DiracOpClover clover(*this, v1, v2, &cg_arg, CNV_FRM_YES) ; clover.CalcHmdForceVecs(frm) ; } //------------------------------------------------------------------ // Calculate the force vectors for the EVEN checkerboard //------------------------------------------------------------------ { CgArg cg_arg ; cg_arg.mass = mass ; DiracOpClover clover(*this, v3, v4, &cg_arg, CNV_FRM_YES) ; const int half_sites = GJP.VolNodeSites()/2; int vec_size = FsiteSize() * half_sites; IFloat *frm_even = (IFloat *)frm + vec_size; IFloat *v3_even = (IFloat *)v3 + vec_size; IFloat *v4_even = (IFloat *)v4 + vec_size; IFloat *A_even = (IFloat *)Aux0Ptr(); // v3_even = frm_even ((Vector *) v3_even)->CopyVec((Vector *)frm_even, vec_size) ; //-------------------------------------------------------------------- // Calculate the clover matrices for the EVEN checkerboard IFloat *Ap = A_even; for (int i = 0; i < GJP.VolNodeSites(); ++i) { mat_inv(Ap, Ap, 6, MAT_INV_ALG_LDL_CMPR, 0); Ap += HALF_CLOVER_MAT_SIZE; } // v4_even = Aee v3_even clover_mat_mlt((IFloat *)v4_even, (const IFloat *)(A_even), (const IFloat *)v3_even, half_sites); } int x, y, z, t, lx, ly, lz, lt ; lx = GJP.XnodeSites() ; ly = GJP.YnodeSites() ; lz = GJP.ZnodeSites() ; lt = GJP.TnodeSites() ; //------------------------------------------------------------------ // Evolves the canonical momentum mom by dt // using fermion force without the clover contribution. // Start by summing first over direction (mu) and then over site // to allow SCU transfers to happen face-by-face in the outermost // loop. //------------------------------------------------------------------ int mu ; Matrix tmp, f; for (mu=0; mu<4; mu++) { for (t=0; tLinf ? tmp : Linf); } } //------------------------------------------------------------------ // Evolves the canonical momentum mom by dt // using the clover contribution of fermion force //------------------------------------------------------------------ EvolveMomFforceSupp(mom, v1, v2, v3, v4, mass, dt); //------------------------------------------------------------------ // deallocate space for two CANONICAL fermion fields on a site. //------------------------------------------------------------------ VRB.Sfree(cname, fname, str_site_v2, site_v2) ; sfree(site_v2) ; VRB.Sfree(cname, fname, str_site_v1, site_v1) ; sfree(site_v1) ; //------------------------------------------------------------------ // deallocate space for four CANONICAL fermion fields. //------------------------------------------------------------------ VRB.Sfree(cname, fname, str_v4, v4) ; sfree(v4) ; VRB.Sfree(cname, fname, str_v3, v3) ; sfree(v3) ; VRB.Sfree(cname, fname, str_v2, v2) ; sfree(v2) ; VRB.Sfree(cname, fname, str_v1, v1) ; sfree(v1) ; glb_sum(&L1); glb_sum(&L2); glb_max(&Linf); L1 /= 4.0*GJP.VolSites(); L2 /= 4.0*GJP.VolSites(); return ForceArg(L1, sqrt(L2), Linf); } ForceArg Fclover::RHMC_EvolveMomFforce(Matrix *mom, Vector **sol, int degree, int isz, Float *alpha, Float mass, Float dt, Vector **sol_d, ForceMeasure force_measure) { char *fname = "RHMC_EvolveMomFforce"; ERR.General(cname,fname,"Not implemented\n"); return ForceArg(0.0,0.0,0.0); } //------------------------------------------------------------------ // Float BhamiltonNode(Vector *boson, Float mass): // The boson Hamiltonian of the node sublattice. //------------------------------------------------------------------ Float Fclover::BhamiltonNode(Vector *boson, Float mass){ char *fname = "BhamiltonNode(V*,F)"; VRB.Func(cname,fname); CgArg cg_arg; cg_arg.mass = mass; if (boson == 0) ERR.Pointer(cname,fname,"boson"); const int half_sites = GJP.VolNodeSites()/2; int vec_size = FsiteSize() * half_sites; size_t f_size = vec_size *2; Vector *bsn_tmp = (Vector *) smalloc(f_size*sizeof(Float)); char *str_tmp = "bsn_tmp" ; if (bsn_tmp == 0) ERR.Pointer(cname,fname,str_tmp) ; VRB.Smalloc(cname,fname,str_tmp,bsn_tmp,f_size*sizeof(Float)); DiracOpClover clover(*this, boson, bsn_tmp, &cg_arg, CNV_FRM_NO) ; IFloat *boson_even = (IFloat *)boson + vec_size; IFloat *bsn_tmp_even = (IFloat *)bsn_tmp + vec_size; IFloat *A_even = (IFloat *)Aux0Ptr(); // bsn_tmp_odd = (Aoo - kappa*kappa*Doe Aee^inv Deo) boson_odd clover.MatPc(bsn_tmp, boson); //-------------------------------------------------------------------- // Calculate the clover matrices for the EVEN checkerboard IFloat *Ap = A_even; for (int i = 0; i < GJP.VolNodeSites(); ++i) { mat_inv(Ap, Ap, 6, MAT_INV_ALG_LDL_CMPR, 0); Ap += HALF_CLOVER_MAT_SIZE; } // bsn_tmp_even = Aee boson_even clover_mat_mlt((IFloat *)bsn_tmp_even, (const IFloat *)(A_even), (const IFloat *)boson_even, half_sites); Float ret_val = bsn_tmp->NormSqNode(f_size) ; VRB.Sfree(cname,fname,str_tmp,bsn_tmp); sfree(bsn_tmp) ; return ret_val; } //------------------------------------------------------------------ // EvolveMomFforceSupp(Matrix *mom, Vector *v1, Vector *v2, // Float mass, Float dt): // It evolves the canonical momentum mom by dt // using the clover contribution of fermion force //------------------------------------------------------------------ void Fclover::EvolveMomFforceSupp(Matrix *mom, Vector *v1, Vector *v2, Vector *v3, Vector *v4, Float mass, Float dt){ char *fname = "EvolveMomFforceSupp(M*,V*,F,F,F)"; VRB.Func(cname,fname); Matrix *gauge = GaugeField() ; char *str_gt = "g_tmp" ; Matrix *g_tmp = (Matrix *)smalloc(6*sizeof(Matrix)) ; if (g_tmp == 0) ERR.Pointer(cname, fname, str_gt) ; VRB.Smalloc(cname, fname, str_gt, g_tmp, 6*sizeof(Matrix)) ; char *str_g1t = "g1_tmp" ; Matrix *g1_tmp = (Matrix *)smalloc(6*sizeof(Matrix)) ; if (g1_tmp == 0) ERR.Pointer(cname, fname, str_g1t) ; VRB.Smalloc(cname, fname, str_g1t, g1_tmp, 6*sizeof(Matrix)) ; char *str_g2t = "g2_tmp" ; Matrix *g2_tmp = (Matrix *)smalloc(6*sizeof(Matrix)) ; if (g2_tmp == 0) ERR.Pointer(cname, fname, str_g2t) ; VRB.Smalloc(cname, fname, str_g2t, g2_tmp, 6*sizeof(Matrix)) ; int mu, nu, loc[4], loc_sites[4]; int size_Matrix = 2 * Colors() * Colors(); loc_sites[0] = GJP.XnodeSites() ; loc_sites[1] = GJP.YnodeSites() ; loc_sites[2] = GJP.ZnodeSites() ; loc_sites[3] = GJP.TnodeSites() ; Matrix tmp, f, f1, f2, f3; //------------------------------------------------------------------ // Suppose g1_{mu, nu}(m)=1/2 Tr_spin[ Sigma_{mu,nu} (v1 v2^dag + v2 v1^dag) ] // and g2_{mu, nu}(m)=1/2 Tr_spin[ Sigma_{mu,nu} (v3 v4^dag + v4 v3^dag) ], // G1* and G2* is used to store the matix for g1 and g2 at different site Matrix G1, G1_plus_mu, G1_plus_mu_plus_nu, G1_plus_mu_minus_nu, G1_plus_nu, G1_minus_nu; Matrix G2, G2_plus_mu, G2_plus_mu_plus_nu, G2_plus_mu_minus_nu, G2_plus_nu, G2_minus_nu; Float kappa = 1.0 / (2.0 * (mass + 4.0)); Float coeff = 0.25 * dt * kappa * GJP.CloverCoeff(); // start by summing first over direction (mu) and then over site // to allow SCU transfers to happen face-by-face in the outermost // loop. //------------------------------------------------------------------ for (mu=0; mu<4; mu++) { for (loc[3]=0; loc[3]