#ifndef _COMPUTE_PION_H #define _COMPUTE_PION_H #include #include #include CPS_START_NAMESPACE //Policy for RequiredMomenta. This is the set of momenta that Daiqian used. class StandardPionMomentaPolicy{ public: void setupMomenta(const int &ngp){ RequiredMomentum *tt = static_cast*>(this); if(ngp == 0){ //p_pi = (0,0,0) tt->addP("(0,0,0) + (0,0,0)",false); }else if(ngp == 1){ //p_pi = (-2,0,0) (units of pi/2L) tt->addPandMinusP("(-1,0,0) + (-1,0,0)",false); tt->addPandMinusP("(1,0,0) + (-3,0,0)",true); //alternative momentum //(In case you're wondering why my first momentum has the opposite sign to Daiqian's, its because mine is for W^dagger, not W) }else if(ngp == 2){ //Along G-parity direction: //p_pi = (-2,-2,0) (units of pi/2L) tt->addPandMinusP("(-1,-1,0) + (-1,-1,0)",false); tt->addPandMinusP("(1,1,0) + (-3,-3,0)",true); //Along off-diagonal direction: //p_pi = (2,-2,0) tt->addPandMinusP("(-1,-1,0) + (3,-1,0)",false); tt->addPandMinusP("(1,1,0) + (1,-3,0)",true); }else if(ngp == 3){ //p_pi = (-2,-2,-2) (units of pi/2L) tt->addPandMinusP("(-1,-1,-1) + (-1,-1,-1)",false); tt->addPandMinusP("(1,1,1) + (-3,-3,-3)",true); //p_pi = (2,-2,-2) tt->addPandMinusP("(-1,-1,-1) + (3,-1,-1)",false); tt->addPandMinusP("(1,1,1) + (1,-3,-3)",true); //p_pi = (-2,2,-2) tt->addPandMinusP("(-1,-1,-1) + (-1,3,-1)",false); tt->addPandMinusP("(1,1,1) + (-3,1,-3)",true); //p_pi = (-2,-2,2) tt->addPandMinusP("(-1,-1,-1) + (-1,-1,3)",false); tt->addPandMinusP("(1,1,1) + (-3,-3,1)",true); }else{ ERR.General("StandardPionMomentaPolicy","setupMomenta","ngp cannot be >3\n"); } } }; //This set of momenta does not include the second momentum combination with which we average to reduce the G-parity rotational symmetry breaking class H4asymmetricMomentaPolicy{ public: void setupMomenta(const int &ngp){ RequiredMomentum *tt = static_cast*>(this); if(ngp == 0){ //p_pi = (0,0,0) tt->addP("(0,0,0) + (0,0,0)",false); }else if(ngp == 1){ //p_pi = (-2,0,0) (units of pi/2L) tt->addPandMinusP("(-1,0,0) + (-1,0,0)",false); //(In case you're wondering why my first momentum has the opposite sign to Daiqian's, its because mine is for W^dagger, not W) }else if(ngp == 2){ //Along G-parity direction: //p_pi = (-2,-2,0) (units of pi/2L) tt->addPandMinusP("(-1,-1,0) + (-1,-1,0)",false); //Along off-diagonal direction: //p_pi = (2,-2,0) tt->addPandMinusP("(-1,-1,0) + (3,-1,0)",false); }else if(ngp == 3){ //p_pi = (-2,-2,-2) (units of pi/2L) tt->addPandMinusP("(-1,-1,-1) + (-1,-1,-1)",false); //p_pi = (2,-2,-2) tt->addPandMinusP("(-1,-1,-1) + (3,-1,-1)",false); //p_pi = (-2,2,-2) tt->addPandMinusP("(-1,-1,-1) + (-1,3,-1)",false); //p_pi = (-2,-2,2) tt->addPandMinusP("(-1,-1,-1) + (-1,-1,3)",false); }else{ ERR.General("H4asymmetricMomentaPolicy","setupMomenta","ngp cannot be >3\n"); } } }; template class ComputePion{ public: typedef typename A2Asource::FieldType::InputParamType FieldParamType; #ifdef USE_DESTRUCTIVE_FFT typedef A2AvectorW Wtype; typedef A2AvectorV Vtype; #else typedef const A2AvectorW Wtype; typedef const A2AvectorV Vtype; #endif typedef A2AmesonField MesonFieldType; typedef std::vector MesonFieldVectorType; typedef typename mf_Policies::ComplexType ComplexType; typedef typename mf_Policies::SourcePolicies SourcePolicies; private: struct GparityComputeTypes{ typedef A2AflavorProjectedExpSource ExpSrcType; typedef A2AflavorProjectedHydrogenSource HydSrcType; typedef Elem > SrcList; typedef A2AmultiSource MultiSrcType; //typedef SCFspinflavorInnerProduct<15,ComplexType,MultiSrcType,true,false> MultiInnerType; //typedef GparityFlavorProjectedMultiSourceStorage StorageType; //Allows for more memory efficient computation algorithm typedef GparitySourceShiftInnerProduct > MultiInnerType; typedef GparityFlavorProjectedShiftSourceStorage StorageType; }; template static typename GparityComputeTypes::StorageType* GparityDoCompute(const RequiredMomentum &pion_mom, const std::vector &Wspecies, const std::vector &Vspecies, const Float &rad, Lattice &lattice, const FieldParamType &src_setup_params){ const int nmom = pion_mom.nMom(); int pbase[3]; //we reset the momentum for each computation so we technically don't need this - however the code demands a valid momentum GparityBaseMomentum(pbase,+1); typename GparityComputeTypes::MultiSrcType src; src.template getSource<0>().setup(rad,pbase,src_setup_params); //1s src.template getSource<1>().setup(2,0,0,rad,pbase,src_setup_params); //2s typename GparityComputeTypes::MultiInnerType g5_s3_inner(sigma3, src); typename GparityComputeTypes::StorageType* mf_store = new typename GparityComputeTypes::StorageType(g5_s3_inner,src); //Base momenta for(int pidx=0;pidxaddCompute(0,0, p_w,p_v); } //Alt momenta for(int pidx=0;pidxaddCompute(0,0, p_w,p_v); } ComputeMesonFields::compute(*mf_store,Wspecies,Vspecies,lattice #ifdef NODE_DISTRIBUTE_MESONFIELDS ,true #endif ); return mf_store; } template static void GparityCombineStore(MesonFieldMomentumContainer &mf_ll_con, const RequiredMomentum &pion_mom, const int src_idx, typename GparityComputeTypes::StorageType* mf_store){ const int Lt = GJP.Tnodes()*GJP.TnodeSites(); const int nmom = pion_mom.nMom(); for(int pidx=0;pidx static void GparityWriteMF(const std::string &work_dir, const int traj, const Float &rad, const RequiredMomentum &pion_mom, typename GparityComputeTypes::StorageType* mf_store){ const int Lt = GJP.Tnodes()*GJP.TnodeSites(); const int nmom = pion_mom.nMom(); std::string src_names[2] = {"1s","2s"}; for(int pidx=0;pidx static void GparityWriteAverageMF(const std::string &work_dir, const int traj, const Float &rad, const RequiredMomentum &pion_mom, typename GparityComputeTypes::StorageType* mf_store){ const int Lt = GJP.Tnodes()*GJP.TnodeSites(); const int nmom = pion_mom.nMom(); std::string src_names[2] = {"1s","2s"}; MesonFieldVectorType tmp(Lt); for(int pidx=0;pidxpipi calculations template static void computeMesonFields(MesonFieldMomentumContainer &mf_ll_con, //container for 1s pion output fields, accessible by ThreeMomentum of pion const std::string &work_dir, const int traj, //all meson fields stored to disk const RequiredMomentum &pion_mom, //object that tells us what quark momenta to use Wtype &W, Vtype &V, const Float &rad, //exponential wavefunction radius Lattice &lattice, const FieldParamType &src_setup_params = NullObject()){ Float time = -dclock(); std::vector Wspecies(1, &W); std::vector Vspecies(1, &V); const int Lt = GJP.Tnodes()*GJP.TnodeSites(); const int nmom = pion_mom.nMom(); if(pion_mom.nAltMom() > 0 && pion_mom.nAltMom() != nmom) ERR.General("ComputePion","computeMesonFields","If alternate momentum combinations are specified there must be one for each pion momentum!\n"); if(GJP.Gparity()){ typename GparityComputeTypes::StorageType* mf_store = GparityDoCompute(pion_mom,Wspecies,Vspecies,rad,lattice,src_setup_params); GparityCombineStore(mf_ll_con, pion_mom, 0, mf_store); //combine and store 1s pion GparityWriteAverageMF(work_dir, traj, rad, pion_mom, mf_store); //write all meson fields to disk delete mf_store; }else{ typedef A2AexpSource SrcType; typedef SCspinInnerProduct<15,ComplexType,SrcType> InnerType; typedef BasicSourceStorage StorageType; SrcType src(rad,src_setup_params); InnerType g5_inner(src); StorageType mf_store(g5_inner); for(int pidx=0;pidx::compute(mf_store,Wspecies,Vspecies,lattice); for(int pidx=0;pidx static void computeGparityMesonFields(MesonFieldMomentumContainer &mf_ll_1s_con, //container for 1s pion output fields, accessible by ThreeMomentum of pion MesonFieldMomentumContainer &mf_ll_2s_con, //same for 2s source const std::string &work_dir, const int traj, //all meson fields stored to disk const RequiredMomentum &pion_mom, //object that tells us what quark momenta to use Wtype &W, Vtype &V, const Float &rad, //exponential wavefunction radius Lattice &lattice, const FieldParamType &src_setup_params = NullObject()){ assert(GJP.Gparity()); Float time = -dclock(); std::vector Wspecies(1, &W); std::vector Vspecies(1, &V); const int Lt = GJP.Tnodes()*GJP.TnodeSites(); const int nmom = pion_mom.nMom(); if(pion_mom.nAltMom() > 0 && pion_mom.nAltMom() != nmom) ERR.General("ComputePion","computeGparityMesonFields","If alternate momentum combinations are specified there must be one for each pion momentum!\n"); typename GparityComputeTypes::StorageType* mf_store = GparityDoCompute(pion_mom,Wspecies,Vspecies,rad,lattice,src_setup_params); GparityCombineStore(mf_ll_1s_con, pion_mom, 0, mf_store); GparityCombineStore(mf_ll_2s_con, pion_mom, 1, mf_store); GparityWriteAverageMF(work_dir, traj, rad, pion_mom, mf_store); //write all meson fields to disk delete mf_store; } //Compute the two-point function using the pre-generated meson fields. //The pion is given the momentum associated with index 'pidx' in the RequiredMomentum //result is indexed by (tsrc, tsep) where tsep is the source-sink separation template static void compute(fMatrix &into, MesonFieldMomentumContainer &mf_ll_con, const RequiredMomentum &pion_mom, const int pidx){ typedef typename mf_Policies::ComplexType ComplexType; typedef typename mf_Policies::ScalarComplexType ScalarComplexType; int Lt = GJP.Tnodes()*GJP.TnodeSites(); into.resize(Lt,Lt); ThreeMomentum p_pi_src = pion_mom.getMesonMomentum(pidx); //exp(-ipx) ThreeMomentum p_pi_snk = -p_pi_src; //exp(+ipx) assert(mf_ll_con.contains(p_pi_src)); assert(mf_ll_con.contains(p_pi_snk)); //Construct the meson fields std::vector > &mf_ll_src = mf_ll_con.get(p_pi_src); std::vector > &mf_ll_snk = mf_ll_con.get(p_pi_snk); #ifdef NODE_DISTRIBUTE_MESONFIELDS if(!UniqueID()){ printf("Gathering meson fields\n"); fflush(stdout); } nodeGetMany(2,&mf_ll_src,&mf_ll_snk); sync(); #endif //Compute the two-point function // \sum_{xsnk,xsrc} exp(ip xsnk)exp(-ipxsrc) tr( S G(xsnk, tsnk; xsrc, tsrc) S G(xsrc,tsrc; xsnk, tsnk) ) //where S is the vertex spin/color/flavor structure //= tr( [[\sum_{xsnk} exp(ip xsnk) w^dag(xsnk,tsnk) S v(xsnk,tsnk)]] [[\sum_{xsrc} exp(-ip xsrc) w^dag(xsrc,tsrc) S v(xsrc,tsrc) ]] ) if(!UniqueID()){ printf("Starting trace\n"); fflush(stdout); } trace(into,mf_ll_snk,mf_ll_src); into *= ScalarComplexType(0.5,0); rearrangeTsrcTsep(into); //rearrange temporal ordering sync(); if(!UniqueID()){ printf("Finished trace\n"); fflush(stdout); } #ifdef NODE_DISTRIBUTE_MESONFIELDS nodeDistributeMany(2,&mf_ll_src,&mf_ll_snk); #endif } }; CPS_END_NAMESPACE #endif