//Generate meson contractions with A2A propagators for comparison with Daiqian //NOTE: You will need to link against libfftw3 and libfftw3_threads #include #include #include //bfm headers #include #include #include #include #include //cps headers #include #include #include #include #include //c++ classes #include #include //#include #include #include #include #include #include #include #ifdef PARALLEL #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //some piece of **** defines these elsewhere, so the bfm header gets screwed up #undef ND #undef SPINOR_SIZE #undef HALF_SPINOR_SIZE #undef GAUGE_SIZE #undef Nmu #undef Ncb #undef NMinusPlus #undef Minus #undef Plus #undef DaggerYes #undef DaggerNo #undef SingleToDouble #undef DoubleToSingle #undef Odd #undef Even #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_BFM #include #endif using namespace std; USING_NAMESPACE_CPS void convert_ferm_cpsord_sord(Float *cps, Float* &sord, bfm_evo &bfm){ Fermion_t handle[2] = { bfm.allocFermion(), bfm.allocFermion() }; bfm.cps_impexFermion(cps,handle,1); long f_size = (long)24 * GJP.VolNodeSites() * GJP.SnodeSites(); if(GJP.Gparity()) f_size*=2; sord = (Float *)pmalloc(sizeof(Float) * f_size); bfm.cps_impexFermion_s(sord,handle,0); bfm.freeFermion(handle[0]); bfm.freeFermion(handle[1]); } void convert_ferm_sord_cpsord(Float *sord, Float* &cps, bfm_evo &bfm){ Fermion_t handle[2] = { bfm.allocFermion(), bfm.allocFermion() }; bfm.cps_impexFermion_s(sord,handle,1); long f_size = (long)24 * GJP.VolNodeSites() * GJP.SnodeSites(); if(GJP.Gparity()) f_size*=2; cps = (Float *)pmalloc(sizeof(Float) * f_size); bfm.cps_impexFermion(cps,handle,0); bfm.freeFermion(handle[0]); bfm.freeFermion(handle[1]); } void setup_bfmargs(bfmarg &dwfa, const BfmSolver &solver = DWF){ printf("Setting up bfmargs\n"); int nthreads = 1; #if TARGET == BGQ nthreads = 64; #endif omp_set_num_threads(nthreads); dwfa.node_latt[0] = GJP.XnodeSites(); dwfa.node_latt[1] = GJP.YnodeSites(); dwfa.node_latt[2] = GJP.ZnodeSites(); dwfa.node_latt[3] = GJP.TnodeSites(); multi1d ncoor(4); multi1d procs(4); for(int i=0;i<4;i++){ ncoor[i] = GJP.NodeCoor(i); procs[i] = GJP.Nodes(i); } if(GJP.Gparity()){ dwfa.gparity = 1; printf("G-parity directions: "); for(int d=0;d<3;d++) if(GJP.Bc(d) == BND_CND_GPARITY){ dwfa.gparity_dir[d] = 1; printf("%d ",d); } else dwfa.gparity_dir[d] = 0; for(int d=0;d<4;d++){ dwfa.nodes[d] = procs[d]; dwfa.ncoor[d] = ncoor[d]; } printf("\n"); } dwfa.verbose=1; dwfa.reproduce=0; bfmarg::Threads(nthreads); bfmarg::Reproduce(0); bfmarg::ReproduceChecksum(0); bfmarg::ReproduceMasterCheck(0); bfmarg::Verbose(1); for(int mu=0;mu<4;mu++){ if ( procs[mu]>1 ) { dwfa.local_comm[mu] = 0; printf("Non-local comms in direction %d\n",mu); } else { dwfa.local_comm[mu] = 1; printf("Local comms in direction %d\n",mu); } } dwfa.precon_5d = 1; if(solver == HmCayleyTanh){ dwfa.precon_5d = 0; //mobius uses 4d preconditioning dwfa.mobius_scale = 2.0; //b = 0.5(scale+1) c=0.5(scale-1), hence this corresponds to b=1.5 and c=0.5, the params used for the 48^3 } dwfa.Ls = GJP.SnodeSites(); dwfa.solver = solver; dwfa.M5 = toDouble(GJP.DwfHeight()); dwfa.mass = toDouble(0.5); dwfa.Csw = 0.0; dwfa.max_iter = 6000; dwfa.residual = 1e-10; printf("Finished setting up bfmargs\n"); } Float* rand_5d_canonical_fermion(Lattice &lat){ long f_size = (long)24 * GJP.VolNodeSites() * GJP.SnodeSites(); if(GJP.Gparity()) f_size*=2; Float *v1 = (Float *)pmalloc(sizeof(Float) * f_size); printf("Making random gaussian 5d vector\n"); lat.RandGaussVector((Vector*)v1, 0.5, 2, CANONICAL, FIVE_D); printf("Finished making random gaussian vector\n"); return v1; } void lanczos_arg(LancArg &into, const Float &mass, const bool &precon){ into.mass = mass; into.stop_rsd = 1e-06; into.qr_rsd = 1e-14; ///convergence of intermediate QR solves, defaults to 1e-14 into.EigenOper = DDAGD; into.precon = precon; //also try this with true into.N_get = 4;///Want K converged vectors into.N_use = 11;///Dimension M Krylov space into.N_true_get = 4;//Actually number of eigen vectors you will get into.ch_ord = 3;///Order of Chebyshev polynomial into.ch_alpha = 5.5;///Spectral radius into.ch_beta = 0.5;///Spectral offset (ie. find eigenvalues of magnitude less than this) into.ch_sh = false;///Shifting or not into.ch_mu = 0;///Shift the peak into.lock = false;///Use locking transofrmation or not into.maxits =10000;///maxiterations into.fname = "Lanczos"; } void lanczos_container_arg(LanczosContainerArg &into, const char* tag, const Float &mass,const bool &lanc_precon, const BfmSolver &solver){ into.tag = strdup(tag); into.cg_max_iter = 10000; into.cg_residual = 1e-08; into.cg_precon_5d = 1; if(solver == HmCayleyTanh){ into.cg_precon_5d = 0; //mobius uses 4d preconditioning into.mobius_scale = 2.0; } if(solver == DWF) into.solver = BFM_DWF; else if(solver == HmCayleyTanh) into.solver = BFM_HmCayleyTanh; else{ printf("lanczos_container_arg(): unknown solver\n"); exit(-1); } into.tbc = BND_CND_APRD; lanczos_arg(into.lanc_arg,mass,lanc_precon); } void a2a_arg(A2AArg &into, const char* lanc_tag, const int &flavor_dilution, const RandomType &rand_type, const int &nl, const bool &do_gauge_fix){ into.lanczos_tag = strdup(lanc_tag); into.nl = nl; into.nhits = 1; into.rand_type = rand_type; into.src_width = 1; into.dilute_flavor = flavor_dilution; into.do_gauge_fix = do_gauge_fix; } void setup_gfix_args(FixGaugeArg &r){ r.fix_gauge_kind = FIX_GAUGE_COULOMB_T; r.hyperplane_start = 0; r.hyperplane_step = 1; r.hyperplane_num = GJP.TnodeSites(); r.stop_cond = 1e-06; r.max_iter_num = 6000; } #define SETUP_ARRAY(OBJ,ARRAYNAME,TYPE,SIZE) \ OBJ . ARRAYNAME . ARRAYNAME##_len = SIZE; \ OBJ . ARRAYNAME . ARRAYNAME##_val = new TYPE [SIZE] #define ELEM(OBJ,ARRAYNAME,IDX) OBJ . ARRAYNAME . ARRAYNAME##_val[IDX] void setup_a2a_prop_args(PropagatorArg &p, const char* tag, const Float &mass, const char* lanc_tag, const int &flavor_dilution, const int &nl, const bool &do_gauge_fix){ p.generics.tag = strdup(tag); p.generics.type = A2A_PROP_TYPE; p.generics.mass = mass; for(int i=0;i<4;i++) p.generics.bc[i] = GJP.Bc(i); SETUP_ARRAY(p,attributes,AttributeContainer,1); AttributeContainer &attr = ELEM(p,attributes,0); attr.type = A2A_ATTR; A2AAttrArg & a2a_args = attr.AttributeContainer_u.a2a_attr; a2a_arg(a2a_args,lanc_tag,flavor_dilution,UONE,nl,do_gauge_fix); //UONE random numbers, nl low modes } static void global_coord(const int &site, int *into_vec){ int rem = site; for(int i=0;i<4;i++){ into_vec[i] = rem % GJP.NodeSites(i) + GJP.NodeCoor(i)*GJP.NodeSites(i); rem /= GJP.NodeSites(i); } } inline static bool ratio_diff_match(const Float &a, const Float &b, const Float &tolerance){ Float rat = a/b; if(rat < 0.0) return false; //opposite signs else return fabs(rat-1.0) <= tolerance; } static void set_p(Float into[3], char sgn){ //units of pi/L for(int i=0;i<3;i++){ if(GJP.Bc(i) == BND_CND_GPARITY) into[i] = (sgn == '+' ? 0.5 : -0.5); else into[i] = 0.0; } } static void setup_ktopipi_args(ContractionTypeKtoPiPi &into, const char *prop_L, const char* prop_H, char p_pi1_sign, char p_pi2_sign){ into.prop_L = strdup(prop_L); into.prop_H = strdup(prop_H); set_p(into.p_qpi1.p1,p_pi1_sign); set_p(into.p_qpi1.p2,p_pi1_sign); set_p(into.p_qpi2.p1,p_pi2_sign); set_p(into.p_qpi2.p2,p_pi2_sign); set_p(into.p_qK,'+'); into.gparity_use_transconv_props = 1; into.pion_source.type = BOX_3D_SMEARING; into.pion_source.A2ASmearing_u.box_3d_smearing.side_length = GJP.Xnodes()*GJP.XnodeSites(); into.kaon_source.type = BOX_3D_SMEARING; into.kaon_source.A2ASmearing_u.box_3d_smearing.side_length = GJP.Xnodes()*GJP.XnodeSites(); into.t_sep_pi_k = 2; into.t_sep_pion = 1; into.file = "type1.dat"; } static void set_p(Float into[3], std::vector q){ //input integers in units of pi/2L into[0] = 0.5*q[0]; into[1] = 0.5*q[1]; into[2] = 0.5*q[2]; } static void setup_ktopipi_multimom_args(ContractionTypeKtoPiPi &into, const char *prop_L, const char* prop_H, std::vector p_pi1q1, std::vector p_pi1q2, std::vector p_pi2q1, std::vector p_pi2q2){ into.prop_L = strdup(prop_L); into.prop_H = strdup(prop_H); set_p(into.p_qpi1.p1, p_pi1q1); set_p(into.p_qpi1.p2, p_pi1q2); set_p(into.p_qpi2.p1, p_pi2q1); set_p(into.p_qpi2.p2, p_pi2q2); set_p(into.p_qK,'+'); into.gparity_use_transconv_props = 1; into.pion_source.type = BOX_3D_SMEARING; into.pion_source.A2ASmearing_u.box_3d_smearing.side_length = GJP.Xnodes()*GJP.XnodeSites(); into.kaon_source.type = BOX_3D_SMEARING; into.kaon_source.A2ASmearing_u.box_3d_smearing.side_length = GJP.Xnodes()*GJP.XnodeSites(); into.t_sep_pi_k = 2; into.t_sep_pion = 1; into.file = "type1.dat"; } class Testing{ public: static void test_prod1(Gparity_KtoPiPi &gpcon, const ContractionTypeKtoPiPi &args, Lattice &lat){ if(!gpcon.setup_called) gpcon.setup(args,lat); int x_op_loc = 0; int tpi2 = 1; //Form SpinColorFlavorMatrix prod1 = vL_i(\vec xop, top) [[\sum_{\vec xpi2} wL_i^dag(\vec xpi2, tpi2) S2 vL_j(\vec xpi2, tpi2)]] wL_j^dag(\vec xop,top) SpinColorFlavorMatrix prod1; MesonField2::contract_vleft_wright(prod1, *gpcon.prop_L, x_op_loc, *gpcon.prop_L, x_op_loc, *gpcon.wdagL_S2_vL_pi2, tpi2); printf("Prod1 (0,0,0,0,0,0): %.12le %.12le (1,1,1,1,1,1): %.12le %.12le\n", prod1(0,0,0,0,0,0).real(), prod1(0,0,0,0,0,0).imag(), prod1(1,1,1,1,1,1).real(), prod1(1,1,1,1,1,1).imag() ); } static void test_conLLLH(Gparity_KtoPiPi &gpcon, const ContractionTypeKtoPiPi &args, Lattice &lat){ if(!gpcon.setup_called) gpcon.setup(args,lat); int t_K = 0; int t_pi1 = 1; RangeSpecificT sett2tK(t_K); MesonField2 con_LLLH; MesonField2::combine_mf_wv_ww(con_LLLH, *gpcon.wdagL_S2_vL_pi1, *gpcon.wdagL_wH, sett2tK); FILE *fp = fopen("con_LLLH.ck","w"); for(int i=0;i con = *con_LLLH.mf_val(i,j,t_pi1); fprintf(fp,"%d %d %.12le %.12le\n",i,j,4.0*con.real(),4.0*con.imag()); } } fclose(fp); std::complex con00 = *con_LLLH.mf_val(0,0,t_pi1); std::complex con35 = *con_LLLH.mf_val(3,5,t_pi1); printf("conLLLH (i,j) = (0,0) : %.12le %.12le and (i,j) = (3,5) : %.12le %.12le\n", con00.real(),con00.imag(), con35.real(), con35.imag() ); int x_op_loc = 0; SpinColorFlavorMatrix prod2; Testing::contract_vleft_vright_testcopy(prod2, *gpcon.prop_L, x_op_loc, *gpcon.prop_H, x_op_loc, con_LLLH, t_pi1, t_K); printf("Prod2 pre-g5 (0,0,0,0,0,0): %.12le %.12le (1,1,1,1,1,1): %.12le %.12le\n", prod2(0,0,0,0,0,0).real(), prod2(0,0,0,0,0,0).imag(), prod2(1,1,1,1,1,1).real(), prod2(1,1,1,1,1,1).imag() ); prod2.gr(-5); printf("Prod2 (0,0,0,0,0,0): %.12le %.12le (1,1,1,1,1,1): %.12le %.12le\n", prod2(0,0,0,0,0,0).real(), prod2(0,0,0,0,0,0).imag(), prod2(1,1,1,1,1,1).real(), prod2(1,1,1,1,1,1).imag() ); } static void contract_vleft_vright_testcopy(SpinColorFlavorMatrix &result, A2APropbfm &prop_left, const int &x, A2APropbfm &prop_right, const int &z, MesonField2 & mf, const int &t, const int &t_vright){ result *= 0.0; for(int j=0;j I=%d, J=%d\n", mf.get_size(MesonField2::Left),mf.get_size(MesonField2::Right), i,j,I,J); std::complex* M = mf.mf_val(i,j,t); printf("M(i=%d,j=%d,t=%d) = %.12le , %.12le\n",i,j,t, M->real(), M->imag()); for(int fl = 0; fl<2; fl++){ std::complex* left_v = prop_left.get_v(I, x,fl); printf("left_v(I=%d,x=%d,fl=%d) = %.12le , %.12le\n",I,x,fl, left_v->real(), left_v->imag()); for(int fr = 0; fr<2; fr++){ std::complex* right_v = prop_right.get_v(J, z,fr); printf("right_v(J=%d,z=%d,fr=%d) = %.12le , %.12le\n",J,z,fr, right_v->real(), right_v->imag()); for(int cr=0;cr<3;cr++){ for(int sr=0;sr<4;sr++){ int sc_off_R = cr+3*sr; for(int cl=0;cl<3;cl++){ for(int sl=0;sl<4;sl++){ int sc_off_L = cl+3*sl; result(sl,cl,fl,sr,cr,fr) += left_v[sc_off_L] * (*M) * std::conj(right_v[sc_off_R]); } } } } } } } } } static void type1_propHg5conj_test(Gparity_KtoPiPi &gpcon, const ContractionTypeKtoPiPi &args, Lattice &lat){ if(!gpcon.setup_called) gpcon.setup(args,lat); int t_sep_pi_k = 2; int t_sep_pion = 1; int tkspec = 0; static const int &c_start = 1; static const int &n_con = 6; int t_size = GJP.Tnodes()*GJP.TnodeSites(); std::vector< MesonField2 > con_LLLH(t_size); for(int t_K = 0 ; t_K < t_size; t_K++){ if(t_K != tkspec) continue; RangeSpecificT sett2tK(t_K); MesonField2::combine_mf_wv_ww(con_LLLH[t_K], *gpcon.wdagL_S2_vL_pi1, *gpcon.wdagL_wH, sett2tK); } int x_op_loc = 0; int t_op_loc = x_op_loc / (GJP.VolNodeSites()/GJP.TnodeSites()); int t_op_glob = t_op_loc + GJP.TnodeCoor()*GJP.TnodeSites(); //Average over all tK int tK = tkspec; //We need to average over choices 1) tpi1 = tK + t_sep_pi_k, tpi2 = tpi1 + t_sep_pion and 2) tpi2 = tK + t_sep_pi_k, tpi1 = tpi2 + t_sep_pion int tpi1_c[2] = { (tK + t_sep_pi_k) % t_size , (tK + t_sep_pi_k + t_sep_pion) % t_size }; int tpi2_c[2] = { (tK + t_sep_pi_k + t_sep_pion) % t_size , (tK + t_sep_pi_k) % t_size }; int c = 0; int mumax = 3; printf("t_K = %d, t_pi1 = %d, t_pi2 = %d\n",tK,tpi1_c[c],tpi2_c[c]); //Form SpinColorFlavorMatrix prod1 = vL_i(\vec xop, top ; tpi2) [\sum_{\vec xpi2} wL_i^dag(\vec xpi2, tpi2) S2 vL_j(\vec xpi2, tpi2; top)] wL_j^dag(\vec xop,top) SpinColorFlavorMatrix prod1; MesonField2::contract_vleft_wright(prod1, *gpcon.prop_L, x_op_loc, *gpcon.prop_L, x_op_loc, *gpcon.wdagL_S2_vL_pi2, tpi2_c[c]); printf("Prod1 (0,0,0,0,0,0): %.12le %.12le (1,1,1,1,1,1): %.12le %.12le\n", prod1(0,0,0,0,0,0).real(), prod1(0,0,0,0,0,0).imag(), prod1(1,1,1,1,1,1).real(), prod1(1,1,1,1,1,1).imag() ); //Form SpinColorFlavorMatrix prod2 = vL_i(\vec xop, top ; tpi1) con_LLLH_{ij}(tpi1)[tK] vH_j^dag(\vec xop, top; t_K) \gamma^5 SpinColorFlavorMatrix prod2; MesonField2::contract_vleft_vright(prod2, *gpcon.prop_L, x_op_loc, *gpcon.prop_H, x_op_loc, con_LLLH[tK], tpi1_c[c], tK); prod2.gr(-5); printf("Prod2 (0,0,0,0,0,0): %.12le %.12le (1,1,1,1,1,1): %.12le %.12le\n", prod2(0,0,0,0,0,0).real(), prod2(0,0,0,0,0,0).imag(), prod2(1,1,1,1,1,1).real(), prod2(1,1,1,1,1,1).imag() ); int g1idx = 0; //M(0,V) int g2idx = 1; //M(0,A) #define USE_DAIQIANS_NEW_DEFINITIONS //Note Daiqian renamed some of his C functions such that the type-II and type-I forms look more similar #ifdef USE_DAIQIANS_NEW_DEFINITIONS int dd[6] = {1,3,4,6,2,5}; #else int dd[6] = {1,2,3,4,5,6}; #endif std::complex C[7]; for(int mu=0;mu<=mumax;mu++){ C[dd[0]] += 0.5*Trace( gpcon.Gamma[g1idx][mu], prod1 ) * Trace( gpcon.Gamma[g2idx][mu], prod2 ); C[dd[1]] += 0.5*( SpinFlavorTrace( gpcon.Gamma[g1idx][mu], prod1 ) * SpinFlavorTrace( gpcon.Gamma[g2idx][mu], prod2 ) ).Trace(); C[dd[2]] += 0.5*Trace(gpcon.Gamma[g1idx][mu]*prod1 , gpcon.Gamma[g2idx][mu]*prod2); C[dd[3]] += 0.5*Trace( ColorTrace( gpcon.Gamma[g1idx][mu], prod1 ), ColorTrace( gpcon.Gamma[g2idx][mu], prod2 ) ); C[dd[4]] += 0.5*( SpinFlavorTrace( gpcon.Gamma[g1idx][mu], prod1 ) * Transpose(SpinFlavorTrace( gpcon.Gamma[g2idx][mu], prod2 )) ).Trace(); C[dd[5]] += 0.5*Trace(gpcon.Gamma[g1idx][mu]*prod1 , ColorTranspose(gpcon.Gamma[g2idx][mu]*prod2) ); } printf("C1 %.12le %.12le\n",C[1].real(),C[1].imag()); printf("C2 %.12le %.12le\n",C[2].real(),C[2].imag()); printf("C3 %.12le %.12le\n",C[3].real(),C[3].imag()); printf("C4 %.12le %.12le\n",C[4].real(),C[4].imag()); printf("C5 %.12le %.12le\n",C[5].real(),C[5].imag()); printf("C6 %.12le %.12le\n",C[6].real(),C[6].imag()); } static void type4_test(Gparity_KtoPiPi &gpcon, const ContractionTypeKtoPiPi &args, Lattice &lat){ if(!gpcon.setup_called) gpcon.setup(args,lat); int t_sep_pi_k = 2; int t_sep_pion = 1; int tkspec = 0; std::vector into; static const int &c_start = 23; static const int &n_con = 10; gpcon.setup_resultvec(n_con,c_start,into); int t_size = GJP.Tnodes()*GJP.TnodeSites(); //A separate meson 'blob' //blob = \sum_{\vec x_pi1,\vec x_pi2} -0.5 * Tr( \prop^L(x_pi1,x_pi2) S_2 \prop^L(x_pi2,x_pi1) S_2 ) // = \sum_{\vec x_pi1,\vec x_pi2} -0.5 * Tr( [[ wL^dag(x_pi2) S_2 vL(x_pi2) ]] [[ wL^dag(x_pi1) S_2 vL(x_pi1) ]] ) // = \sum_{\vec x_pi1,\vec x_pi2} -0.5 * Tr( [[ wL^dag(x_pi1) S_2 vL(x_pi1) ]] [[ wL^dag(x_pi2) S_2 vL(x_pi2) ]] ) //we need both t_pi2 = (t_pi1 + sep) % T (index 0 of array) and t_pi2 = (t_pi1 - sep + T) % T (index 1 of array) RangeT1plusDelta fix_tpi2_plus_sep(t_sep_pion); RangeT1plusDelta fix_tpi2_minus_sep(-t_sep_pion); CorrelationFunction blob_tpi1_plus("blob",1,CorrelationFunction::THREADED); MesonField2::contract_specify_t2range( *gpcon.wdagL_S2_vL_pi1, *gpcon.wdagL_S2_vL_pi2, 0, fix_tpi2_plus_sep, blob_tpi1_plus); CorrelationFunction blob_tpi1_minus("blob",1,CorrelationFunction::THREADED); MesonField2::contract_specify_t2range( *gpcon.wdagL_S2_vL_pi1, *gpcon.wdagL_S2_vL_pi2, 0, fix_tpi2_minus_sep, blob_tpi1_minus); //Sum over t_pi1 and average over pion permutations std::complex blob(0.0); for(int t_pi1=0;t_pi1* corrs[n_con]; for(int cc=0;cc three_vec(int i, int j, int k){ std::vector out(3); out[0] = i; out[1] = j; out[2] = k; return out; } std::vector minus_vec(const std::vector &in){ std::vector out(in); for(int i=0;i permute(const std::vector &in, int idx1, int idx2){ //pairwise swap std::vector out(in); out[idx1] = in[idx2]; out[idx2] = in[idx1]; return out; } void compute_type(std::vector &into, const int &type, const int &tk, const int &t_sep_pi_k, const int &tsep_pion, Gparity_KtoPiPi &gpcon){ std::vector tkv(1,tk); if(type == 1){ gpcon.type1(t_sep_pi_k, tsep_pion, into, &tkv); }else if(type == 2){ gpcon.type2(t_sep_pi_k, tsep_pion, into, &tkv); }else if(type == 3){ gpcon.type3(t_sep_pi_k, tsep_pion, into, &tkv); }else if(type == 4){ gpcon.type4(t_sep_pi_k, tsep_pion, into, &tkv); }else if(type == 5){ gpcon.psvertex_type3(t_sep_pi_k, tsep_pion, into, &tkv); }else if(type == 6){ gpcon.psvertex_type4(t_sep_pi_k, tsep_pion, into, &tkv); }else{ printf("compute_type(..) : Invalid contraction type\n"); exit(-1); } } void daiqian_order_result(std::vector< std::vector< std::vector > > &ordered, std::vector &orig_output, const int &type, const int &tk){ //Daiqian prints out // <(t_op-t_K)%T> 4) ncon = 1; ordered.resize(Lt); //[tt][c][gammacomb] //We want the second time index to be tt= (top-tk+Lt) % Lt in order for(int top=0;top 4) size = 2; std::vector &v = ordered[tt][c]; v.resize( size,cps::Complex(0.0,0.0) ); if(type <= 4){ int m[8] = { Gparity_KtoPiPi::result_map(c,_0V,_0A), Gparity_KtoPiPi::result_map(c,_0A,_0V), Gparity_KtoPiPi::result_map(c,_0V,_1A), Gparity_KtoPiPi::result_map(c,_0A,_1V), Gparity_KtoPiPi::result_map(c,_1V,_0A), Gparity_KtoPiPi::result_map(c,_1A,_0V), Gparity_KtoPiPi::result_map(c,_1V,_1A), Gparity_KtoPiPi::result_map(c,_1A,_1V) }; v[0] = orig_output[m[0]](0,top); v[1] = orig_output[m[1]](0,top); v[2] = orig_output[m[2]](0,top); v[3] = orig_output[m[3]](0,top); v[4] = orig_output[m[4]](0,top); v[5] = orig_output[m[5]](0,top); v[6] = orig_output[m[6]](0,top); v[7] = orig_output[m[7]](0,top); }else{ v[0] = orig_output[0](0,top); v[1] = orig_output[1](0,top); } } } } using namespace Chroma; using namespace cps; typedef LatticeFermion T; typedef multi1d T5; typedef multi1d U; int cout_time(char *); void ReadGaugeField(const MeasArg &meas_arg); void bfm_init(bfm_evo &dwf,double mq); #define Printf if(!UniqueID()) printf int main (int argc,char **argv ) { Start(&argc, &argv); #ifdef HAVE_BFM Chroma::initialize(&argc,&argv); #endif CommandLine::is(argc,argv); bool gparity = false; bool gparity_dirs[3] = {false,false,false}; int arg0 = CommandLine::arg_as_int(0); if(arg0<4){ Printf("Number of G-parity directions: %d\n",arg0); for(int i=0;iargc-6){ Printf("Did not specify enough arguments for 'latt' (require 5 dimensions)\n"); exit(-1); } size[0] = CommandLine::arg_as_int(i); //CommandLine ignores zeroth input arg (i.e. executable name) size[1] = CommandLine::arg_as_int(i+1); size[2] = CommandLine::arg_as_int(i+2); size[3] = CommandLine::arg_as_int(i+3); size[4] = CommandLine::arg_as_int(i+4); i+=6; }else if( strncmp(cmd,"-load_lrg",15) == 0){ if(i==argc-1){ Printf("-load_lrg requires an argument\n"); exit(-1); } load_lrg=true; load_lrg_file = argv[i+1]; i+=2; }else if( strncmp(cmd,"-save_lrg",15) == 0){ if(i==argc-1){ Printf("-save_lrg requires an argument\n"); exit(-1); } save_lrg=true; save_lrg_file = argv[i+1]; i+=2; }else if( strncmp(cmd,"-verbose",15) == 0){ verbose=true; i++; }else if( strncmp(cmd,"-dont_dilute_flavor",15) == 0){ Printf("Running without flavor dilution\n"); dilute_flavor = 0; i++; }else if( strncmp(cmd,"-unit_gauge",15) == 0){ unit_gauge=true; i++; }else{ Printf("Unrecognised argument: %s\n",cmd); exit(-1); } } Printf("Lattice size is %d %d %d %d\n",size[0],size[1],size[2],size[3],size[4]); DoArg do_arg; do_arg.x_sites = size[0]; do_arg.y_sites = size[1]; do_arg.z_sites = size[2]; do_arg.t_sites = size[3]; do_arg.s_sites = size[4]; do_arg.x_node_sites = 0; do_arg.y_node_sites = 0; do_arg.z_node_sites = 0; do_arg.t_node_sites = 0; do_arg.s_node_sites = 0; do_arg.x_nodes = 0; do_arg.y_nodes = 0; do_arg.z_nodes = 0; do_arg.t_nodes = 0; do_arg.s_nodes = 0; do_arg.updates = 0; do_arg.measurements = 0; do_arg.measurefreq = 0; do_arg.cg_reprod_freq = 10; do_arg.x_bc = BND_CND_PRD; do_arg.y_bc = BND_CND_PRD; do_arg.z_bc = BND_CND_PRD; do_arg.t_bc = BND_CND_APRD; do_arg.start_conf_kind = START_CONF_ORD; do_arg.start_conf_load_addr = 0x0; do_arg.start_seed_kind = START_SEED_FIXED; do_arg.start_seed_filename = "../rngs/ckpoint_rng.0"; do_arg.start_conf_filename = "../configurations/ckpoint_lat.0"; do_arg.start_conf_alloc_flag = 6; do_arg.wfm_alloc_flag = 2; do_arg.wfm_send_alloc_flag = 2; do_arg.start_seed_value = 83209; do_arg.beta = 2.25; do_arg.c_1 = -3.3100000000000002e-01; do_arg.u0 = 1.0000000000000000e+00; do_arg.dwf_height = 1.8000000000000000e+00; do_arg.dwf_a5_inv = 1.0000000000000000e+00; do_arg.power_plaq_cutoff = 0.0000000000000000e+00; do_arg.power_plaq_exponent = 0; do_arg.power_rect_cutoff = 0.0000000000000000e+00; do_arg.power_rect_exponent = 0; do_arg.verbose_level = -1202; //VERBOSE_DEBUG_LEVEL; //-1202; do_arg.checksum_level = 0; do_arg.exec_task_list = 0; do_arg.xi_bare = 1.0000000000000000e+00; do_arg.xi_dir = 3; do_arg.xi_v = 1.0000000000000000e+00; do_arg.xi_v_xi = 1.0000000000000000e+00; do_arg.clover_coeff = 0.0000000000000000e+00; do_arg.clover_coeff_xi = 0.0000000000000000e+00; do_arg.xi_gfix = 1.0000000000000000e+00; do_arg.gfix_chkb = 1; do_arg.asqtad_KS = 0.0000000000000000e+00; do_arg.asqtad_naik = 0.0000000000000000e+00; do_arg.asqtad_3staple = 0.0000000000000000e+00; do_arg.asqtad_5staple = 0.0000000000000000e+00; do_arg.asqtad_7staple = 0.0000000000000000e+00; do_arg.asqtad_lepage = 0.0000000000000000e+00; do_arg.p4_KS = 0.0000000000000000e+00; do_arg.p4_knight = 0.0000000000000000e+00; do_arg.p4_3staple = 0.0000000000000000e+00; do_arg.p4_5staple = 0.0000000000000000e+00; do_arg.p4_7staple = 0.0000000000000000e+00; do_arg.p4_lepage = 0.0000000000000000e+00; if(verbose) do_arg.verbose_level = VERBOSE_DEBUG_LEVEL; BndCndType* bc[3] = { &do_arg.x_bc, &do_arg.y_bc, &do_arg.z_bc }; for(int i=0;i<3;i++) if(gparity_dirs[i]) *bc[i] = BND_CND_GPARITY; GJP.Initialize(do_arg); LRG.Initialize(); //usually initialised when lattice generated, but I pre-init here so I can load the state from file if(load_lrg){ if(UniqueID()==0) printf("Loading RNG state from %s\n",load_lrg_file); LRG.Read(load_lrg_file,32); } if(save_lrg){ if(UniqueID()==0) printf("Writing RNG state to %s\n",save_lrg_file); LRG.Write(save_lrg_file,32); } GwilsonFdwf* lattice = new GwilsonFdwf; if(!load_config){ LatRanGen LRGbak = LRG; //don't let the gauge generation modify the RNG printf("Creating gauge field\n"); if(!unit_gauge) lattice->SetGfieldDisOrd(); else lattice->SetGfieldOrd(); LRG = LRGbak; }else{ ReadLatticeParallel readLat; if(UniqueID()==0) printf("Reading: %s (NERSC-format)\n",load_config_file); readLat.read(*lattice,load_config_file); if(UniqueID()==0) printf("Config read.\n"); } if(save_config){ if(UniqueID()==0) printf("Saving config to %s\n",save_config_file); QioArg wt_arg(save_config_file,0.001); wt_arg.ConcurIONumber=32; WriteLatticeParallel wl; wl.setHeader("disord_id","disord_label",0); wl.write(*lattice,wt_arg); if(!wl.good()) ERR.General("main","()","Failed write lattice %s",save_config_file); if(UniqueID()==0) printf("Config written.\n"); } lattice->FixGaugeAllocate(FIX_GAUGE_COULOMB_T); lattice->FixGauge(1e-06,2000); cps_qdp_init(&argc,&argv); // LRG.AssignGenerator(0,0); // printf("INIT RAND %f\n",LRG.Urand(FOUR_D)); #if TARGET == BGQ omp_set_num_threads(64); #else omp_set_num_threads(1); #endif //Light quark Float mass = 0.1; #define DO_GAUGE_FIX #ifdef DO_GAUGE_FIX bool do_gauge_fix = true; #else bool do_gauge_fix = false; #endif LanczosContainerArg lanc_arg; lanczos_container_arg(lanc_arg, "lanc", mass, true, HmCayleyTanh); PropManager::addLanczos(lanc_arg); PropagatorArg prop_arg; setup_a2a_prop_args(prop_arg,"a2aprop", mass,"lanc",dilute_flavor,4,do_gauge_fix); //4 low modes PropManager::addProp(prop_arg); //Strange quark (don't need another Lanczos instance; just use 0 low modes) Float mass_s = 0.3; PropagatorArg prop_arg_s; setup_a2a_prop_args(prop_arg_s,"a2aprop_s", mass_s,"lanc",dilute_flavor,0,do_gauge_fix); //0 low modes PropManager::addProp(prop_arg_s); //Calculate the A2A props PropManager::calcProps(*lattice); { LatRanGen LRGbak(LRG); LRG.AssignGenerator(0,0); printf("RAND POST PROP GEN %f\n",LRG.Urand(FOUR_D)); LRG = LRGbak; } //Do the first test with the pion 2-point function A2APropbfm &a2a_prop = PropManager::getProp("a2aprop").convert().getProp(*lattice); //Print the stochastic field for the high modes int whsize = 2 * GJP.VolNodeSites(); Float* wh = (Float*)a2a_prop.get_wh(); { FILE *fp = fopen("wh0.ck","w"); for(int i=0;i _i(0.0,1.0); SpinColorFlavorMatrix lmat = s3g5*0.5 - s1g5*_i*0.5; SpinColorFlavorMatrix rmat = s3g5 + s1g5*_i; MFqdpMatrix mf_mat_left(MFstructure::W, MFstructure::V, true, false, lmat); MFqdpMatrix mf_mat_right(MFstructure::W, MFstructure::V, true, false, rmat); MFBasicSource src(MFBasicSource::BoxSource, (double)(GJP.XnodeSites()*GJP.Xnodes()) ); Float p[3] = {0.0,0.0,0.0}; for(int i=0;i<3;++i) if(GJP.Bc(i) == BND_CND_GPARITY) p[i] = 0.5; //units of pi/L const Float mp[3] = {-p[0],-p[1],-p[2]}; //Note, FT conventions are e^{-ipx} for forwards FFT into p-space with momentum +p //Hence x and x' have momentum +p and likewise y and y' have momentum -p a2a_prop.set_v_momentum(p); a2a_prop.set_wdag_momentum(p); a2a_prop.fft_vw(); MesonField2 mf_left(a2a_prop,a2a_prop,mf_mat_left,src); a2a_prop.set_v_momentum(mp); a2a_prop.set_wdag_momentum(mp); a2a_prop.fft_vw(); MesonField2 mf_right(a2a_prop,a2a_prop,mf_mat_right,src); CorrelationFunction result("result",1); MesonField2::contract(mf_left,mf_right,result); // if(!UniqueID()){ // printf("Result:\n"); // for(int t=0;t twopoint_results[t_size][t_size]; if(0){ //Do contraction using Daiqian's translationally covariant field source. Here we repeat the above but using the inbuilt code that makes the FFT propagators translationially covariant //\sum_{x,x',y,y'} e^{-ipx}e^{ipy}e^{-ipx'}e^{ipy'} 0.5 * 4 * tr{ [ w^dag(x') g5 \sigma_3 v(x) ] [ w^dag(y) g5 \sigma_3 v(y') ] } //Note the extra factor of 4 which arises because previously we measured with \sigma_3 (1 \pm \sigma_2) in each meson field //and now we measure with 1/2(1 \mp \sigma_2)\sigma_3 1/2(1 \pm \sigma_2) = \sigma_3 1/2(1 \pm \sigma_2) in each meson field SpinColorFlavorMatrix s3g5(gamma5,sigma3); SpinColorFlavorMatrix lmat = s3g5*0.5; //*4; SpinColorFlavorMatrix rmat = s3g5; MFqdpMatrix mf_mat_left(MFstructure::W, MFstructure::V, true, false, lmat); MFqdpMatrix mf_mat_right(MFstructure::W, MFstructure::V, true, false, rmat); MFBasicSource src(MFBasicSource::BoxSource, (double)(GJP.XnodeSites()*GJP.Xnodes()) ); Float p[3] = {0.0,0.0,0.0}; for(int i=0;i<3;++i) if(GJP.Bc(i) == BND_CND_GPARITY) p[i] = 0.5; //units of pi/L const Float mp[3] = {-p[0],-p[1],-p[2]}; //Note, FT conventions are e^{-ipx} for forwards FFT into p-space with momentum +p //Hence x and x' have momentum +p and likewise y and y' have momentum -p #ifdef USE_TRANSCONV_FIELDS a2a_prop.gparity_make_fields_transconv(true); #endif #ifdef IMPOSE_MOMENTUM a2a_prop.set_v_momentum(mp); //x momentum a2a_prop.set_wdag_momentum(mp); #endif a2a_prop.fft_vw(); #ifdef USE_TRANSCONV_FIELDS a2a_prop.gparity_make_fields_transconv(false); #endif MesonField2 mf_left(a2a_prop,a2a_prop,mf_mat_left,src); #ifdef USE_TRANSCONV_FIELDS a2a_prop.gparity_make_fields_transconv(true); #endif #ifdef IMPOSE_MOMENTUM a2a_prop.set_v_momentum(p); a2a_prop.set_wdag_momentum(p); #endif a2a_prop.fft_vw(); #ifdef USE_TRANSCONV_FIELDS a2a_prop.gparity_make_fields_transconv(false); #endif MesonField2 mf_right(a2a_prop,a2a_prop,mf_mat_right,src); CorrelationFunction result("result",1); MesonField2::contract(mf_left,mf_right,result); if(!UniqueID()) printf("Result with inbuilt transconv code and source and sink timeslice explicit:\n"); for(int x4=0;x4 results[t_size][t_size]; if(!UniqueID()) printf("\n"); const int NA=-1; for(int y_4 = 0; y_4 < t_size; y_4++){ RangeSpecificT range(y_4); MesonField2 prod; MesonField2::combine_mf_wv_wv(prod, mf_left, mf_right, range); printf("MesonField2::combine_mf_wv_wv y_4=%d combined meson fields of size %d x %d and %d x %d into one of size %d x %d\n",y_4,mf_left.rows(),mf_left.cols(),mf_right.rows(),mf_right.cols(),prod.rows(),prod.cols()); for(int x_4=0;x_4 &result = results[x_4][y_4]; result.real() = 0.0; result.imag() = 0.0; for(int J=0;J _i(0.0,1.0); #ifdef USE_TRANSCONV_FIELDS SpinColorFlavorMatrix lmat = s3g5 - s1g5*_i; #else SpinColorFlavorMatrix lmat = s3g5*2.0; #endif MFqdpMatrix mf_mat_right(MFstructure::W, MFstructure::V, true, false, rmat); MFBasicSource src(MFBasicSource::BoxSource, (double)(GJP.XnodeSites()*GJP.Xnodes()) ); Float p[3] = {0.0,0.0,0.0}; for(int i=0;i<3;++i) if(GJP.Bc(i) == BND_CND_GPARITY) p[i] = 0.5; //units of pi/L const Float mp[3] = {-p[0],-p[1],-p[2]}; #ifdef USE_TRANSCONV_FIELDS a2a_prop.gparity_make_fields_transconv(true); #endif #ifdef IMPOSE_MOMENTUM a2a_prop.set_v_momentum(mp); a2a_prop.set_wdag_momentum(mp); #endif a2a_prop.fft_vw(); #ifdef USE_TRANSCONV_FIELDS a2a_prop.gparity_make_fields_transconv(false); #endif MesonField2 mf_right(a2a_prop,a2a_prop,mf_mat_right,src); //Loop over source timeslice and coords x and x' on that timeslice int loc3vol = GJP.VolNodeSites()/GJP.TnodeSites(); static const Float _mpi = -3.141592654; if(!UniqueID()) printf("Doing 2-pt function for testing MesonField2::contract_vleft_wright\n"); // for(int x_4=0;x_4= 0 && x_4_loc < GJP.TnodeSites() ){ for(int y_4=0;y_4FixGaugeMatrix(x4d_loc,0), lattice->FixGaugeMatrix(x4d_loc,1) }; scf(0,0).LeftTimesEqual(*gfmatx_f[0]); scf(0,1).LeftTimesEqual(*gfmatx_f[0]); scf(1,0).LeftTimesEqual(*gfmatx_f[1]); scf(1,1).LeftTimesEqual(*gfmatx_f[1]); #endif //Multiply by spin-flavor structure scf.LeftTimesEqual(lmat); #ifdef DO_GAUGE_FIX //For wdag we need to left-multiply by V^dag where V is the gauge fixing matrix cps::Matrix gfmatxpr_f[2]; gfmatxpr_f[0].Dagger( *(lattice->FixGaugeMatrix(xpr4d_loc,0)) ); gfmatxpr_f[1].Dagger( *(lattice->FixGaugeMatrix(xpr4d_loc,1)) ); scf(0,0).LeftTimesEqual(gfmatxpr_f[0]); scf(0,1).LeftTimesEqual(gfmatxpr_f[0]); scf(1,0).LeftTimesEqual(gfmatxpr_f[1]); scf(1,1).LeftTimesEqual(gfmatxpr_f[1]); #endif //Now the phases cps::Complex phases[2] = { cps::Complex(1.0,0.0), cps::Complex(1.0,0.0) }; #ifdef IMPOSE_MOMENTUM int pos_loc[2] = { x3d_loc, xpr3d_loc }; for(int pp=0;pp<2;pp++){ Float pdotx = 0.0; int rem(pos_loc[pp]); for(int d=0;d<3;d++){ int szd = GJP.NodeSites(d); int pos_d_loc = rem % szd; rem /= szd; int pos_d = pos_d_loc + GJP.NodeCoor(d)*GJP.NodeSites(d); pdotx += p[d] * pos_d * _mpi / szd; } phases[pp] = cps::Complex( cos(pdotx), sin(pdotx) ); } #endif //Take the trace result(omp_get_thread_num(),0,y_4) += 0.5*2* scf.Trace() * phases[0]*phases[1]; } } } } cps::sync(); //some nodes will be waiting result.sumLattice(); if(!UniqueID()){ for(int y4=0;y4(pipi)_I=0 contractions //setup_ktopipi_args(ContractionTypeKtoPiPi &into, const char *prop_L, const char* prop_H){ ContractionTypeKtoPiPi ktopipi_args; setup_ktopipi_args(ktopipi_args,"a2aprop","a2aprop_s",'+','-'); Gparity_KtoPiPi gpcon; gpcon.setup(ktopipi_args,*lattice); int tsize = GJP.Tnodes()*GJP.TnodeSites(); //Also write out in Daiqian's format FILE *fp = fopen("type1.ck","w"); //Daiqian's output shows different results for each kaon timeslice for(int tk = 0; tk < tsize; ++tk){ std::vector tkv(1,tk); std::vector result; if(!UniqueID()) printf("Calculating type1 diagrams with tk=%d\n",tk); //gpcon.type1(2,1,result,&tkv); gpcon.type1_propHg5conj(2,1,result,&tkv); for(int c=0;c <(t_op-t_K)%T> > > ordered(tsize); //[tt][c][gammacomb] for(int top=0;top tt=%d\n",tk,top,tt); for(int c=0;c &v = ordered[tt][c]; v.resize( 8,cps::Complex(0.0,0.0) ); //if( (top-tk+Lt)%Lt > 0 && (top-tk+Lt)%Lt < delta ){ v[0] = result[gpcon.result_map(c,_0V,_0A)](0,top); v[1] = result[gpcon.result_map(c,_0A,_0V)](0,top); v[2] = result[gpcon.result_map(c,_0V,_1A)](0,top); v[3] = result[gpcon.result_map(c,_0A,_1V)](0,top); v[4] = result[gpcon.result_map(c,_1V,_0A)](0,top); v[5] = result[gpcon.result_map(c,_1A,_0V)](0,top); v[6] = result[gpcon.result_map(c,_1V,_1A)](0,top); v[7] = result[gpcon.result_map(c,_1A,_1V)](0,top); //} } } for(int tt=0;tt &v = ordered[tt][c]; for(int vv=0;vv<8;vv++) fprintf(fp," %.6le %.6le", std::real(v[vv]), std::imag(v[vv]) ); } fprintf(fp,"\n"); } } fclose(fp); } //Original test with Daiqian if(0){ //For the other types we avoid the ambiguity in momentum directions / timeslices for the two pions by summing over all combinations: //pi1(t, +p), pi2(t+delta, -p) + pi1(t+delta, +p), pi2(t, -p) + pi1(t, -p), pi2(t+delta, +p) + pi1(t+delta, -p), pi2(t,+p) ContractionTypeKtoPiPi ktopipi_args_pm, ktopipi_args_mp; setup_ktopipi_args(ktopipi_args_pm,"a2aprop","a2aprop_s",'+','-'); setup_ktopipi_args(ktopipi_args_mp,"a2aprop","a2aprop_s",'-','+'); Gparity_KtoPiPi gpcon_pm; gpcon_pm.setup(ktopipi_args_pm,*lattice); Gparity_KtoPiPi gpcon_mp; gpcon_mp.setup(ktopipi_args_mp,*lattice); int tsize = GJP.Tnodes()*GJP.TnodeSites(); int n_types = 6; bool do_type[] = { false, false, false, false, false, false }; std::string names[] = { "type1.ck", "type2.ck", "type3.ck", "type4.ck", "psvertex_type3.ck", "psvertex_type4.ck" }; do_type[4] = true; //pseudoscalar vertex of type4 form //Also write out in Daiqian's format FILE *fp[n_types]; for(int i=0;i tkv(1,tk); std::vector result_pm, result_mp; for(int type=0; type < n_types; ++type){ if(!do_type[type]) continue; if(type == 0){ gpcon_pm.type1(2,1,result_pm,&tkv); gpcon_mp.type1(2,1,result_mp,&tkv); }else if(type == 1){ gpcon_pm.type2(2,1,result_pm,&tkv); gpcon_mp.type2(2,1,result_mp,&tkv); }else if(type == 2){ gpcon_pm.type3(2,1,result_pm,&tkv); gpcon_mp.type3(2,1,result_mp,&tkv); }else if(type == 3){ gpcon_pm.type4(2,1,result_pm,&tkv); gpcon_mp.type4(2,1,result_mp,&tkv); }else if(type == 4){ gpcon_pm.psvertex_type3(2,1,result_pm,&tkv); gpcon_mp.psvertex_type3(2,1,result_mp,&tkv); }else if(type == 5){ gpcon_pm.psvertex_type4(2,1,result_pm,&tkv); gpcon_mp.psvertex_type4(2,1,result_mp,&tkv); }else{ printf("Invalid contraction type\n"); exit(-1); } //Sum pm and mp std::vector sum(result_pm.size()); for(int ii=0;ii <(t_op-t_K)%T> > > ordered; daiqian_order_result(ordered,sum,type+1,tk); for(int tt=0;tt &v = ordered[tt][c]; for(int vv=0;vv, std::vector > > mom_comb_diag; std::vector< std::pair< std::vector, std::vector > > mom_comb_perp; if(ngp==3){ //Two combinations for pion moving in +++ direction mom_comb_diag.resize(2); mom_comb_diag[0].first = three_vec(1,1,1); mom_comb_diag[0].second = three_vec(1,1,1); mom_comb_diag[1].first = three_vec(-1,-1,-1); mom_comb_diag[1].second = three_vec(3,3,3); //Two combinations for pion moving in -++ mom_comb_perp.resize(2); mom_comb_perp[0].first = three_vec(1,1,1); mom_comb_perp[0].second = three_vec(-3,1,1); mom_comb_perp[1].first = three_vec(-1,-1,-1); mom_comb_perp[1].second = three_vec(-1,3,3); }else{ printf("Momentum combinations for ngp = %d not specified\n",ngp); exit(-1); } int n_types = 7; bool do_type[] = {false, false, false, false, false, false, false }; //first is dummy std::string names[] = {"", "type1", "type2", "type3", "type4", "psvertex_type3", "psvertex_type4" }; int ncon[] = {-1, 6,6,10,10,1,1}; do_type[1] = true; //Because the problem is symmetric under rotations around the diagonal axis, we need only consider the diagonal axis and one off-diagonal //First consider pi1(+++) pi2(---). There are 4 combinations (2x2), which we sum. Then do the parity-flipped version, then similar for the perpendicular momenta std::vector< std::pair< std::vector, std::vector > >* dir_mcomb[2] = { &mom_comb_diag, &mom_comb_perp }; const char* pi1_mom_names[] = { "111", "_1_1_1", "_111", "1_1_1" }; //Daiqian's notation for(int dir = 0; dir < 2; dir++){ //dir=0 -> diag, dir=1 -> perp const std::vector< std::pair< std::vector, std::vector > > &mom_comb = *dir_mcomb[dir]; for(int parity = 0; parity < 2; parity++){ const char* pi1_mom_name = pi1_mom_names[parity + 2*dir]; //for filenames for(int type = 1; type < n_types; type++){ if(!do_type[type]) continue; std::ostringstream fn; fn << "type" << type << "_deltat_2_sep_1_mom" << pi1_mom_name << ".ck"; FILE *fp = fopen(fn.str().c_str(),"w"); for(int tk = 0; tk < tsize; ++tk){ //Sum over the 4 combinations of quark momenta std::vector sum(4*4*ncon[type]); //(4*4 operator pairs) * (number of contractions of type) for(int ii=0;ii, std::vector > & p_pi1 = mom_comb_diag[pcomb1]; const std::pair< std::vector, std::vector > & minus_p_pi2 = mom_comb_diag[pcomb2]; //is in +++ dir, we need --- so apply minus below std::vector p_pi1_q1 = ( parity==0 ? p_pi1.first : minus_vec( p_pi1.first ) ); std::vector p_pi1_q2 = ( parity==0 ? p_pi1.second : minus_vec( p_pi1.second ) ); std::vector p_pi2_q1 = ( parity==0 ? minus_vec( p_pi2.first ) : p_pi1.first ); std::vector p_pi2_q2 = ( parity==0 ? minus_vec( p_pi2.second ) : p_pi1.second ); Gparity_KtoPiPi gpcon; ContractionTypeKtoPiPi gpcon_args; setup_ktopipi_multimom_args(gpcon_args,"a2aprop","a2aprop_s", p_pi1_q1, p_pi1_q1, p_pi2_q1, p_pi2_q2); gpcon.setup(gpcon_args,*lattice); std::vector tmp; compute_type(tmp,type,tk,2,1,gpcon); for(int ii=0;ii > > ordered;//[tt][c][gammacomb] daiqian_order_result(ordered,sum,type,tk); //Write this tk to file for(int tt=0;tt &v = ordered[tt][c]; for(int vv=0;vv > > > reorg(t_size);//T * T * 4 for(int t=0;t x4_rng(1,x4); std::vector result; gpcon.pipi(1,'+',result,&x4_rng); for(int tsep = 0; tsep <(y4-r4)%T> for(int c=0;c<4;c++){ for(int tsep = 0; tsep pi1(+p)pi2(-p) ContractionTypeKtoPiPi ktopipi_args; setup_ktopipi_args(ktopipi_args,"a2aprop","a2aprop_s",'-','+'); Gparity_KtoPiPi gpcon; gpcon.setup(ktopipi_args,*lattice); int tsize = GJP.Tnodes()*GJP.TnodeSites(); //Also write out in Daiqian's format std::string filenames[4] = {"pipi_C_-+.ck", "pipi_D_-+.ck", "pipi_R_-+.ck", "pipi_V_-+.ck"}; FILE *fp[4]; for(int i=0;i<4;i++) fp[i] = fopen(filenames[i].c_str(),"w"); std::vector< std::vector< std::vector< std::complex > > > reorg(t_size);//T * T * 4 for(int t=0;t x4_rng(1,x4); std::vector result; gpcon.pipi(1,'-',result,&x4_rng); //pi1 at sink has opposite momentum to that at source for(int tsep = 0; tsep <(y4-r4)%T> for(int c=0;c<4;c++){ for(int tsep = 0; tsep