#ifndef _MULT_VMV_IMPL #define _MULT_VMV_IMPL //Vector mesonfield outer product implementation template class lA2AfieldL, template class lA2AfieldR, template class rA2AfieldL, template class rA2AfieldR, typename ComplexClass> class _mult_vMv_impl_v{}; template class lA2AfieldL, template class lA2AfieldR, template class rA2AfieldL, template class rA2AfieldR > class _mult_vMv_impl_v{ //necessary to avoid an annoying ambigous overload when mesonfield friends mult public: typedef typename mf_Policies::ScalarComplexType ScalarComplexType; //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) // l^i(xop,top) M^ij(tl,tr) r^j(xop,top) //argument xop is the *local* 3d site index in canonical ordering, top is the *local* time coordinate // Node local and unthreaded static void mult(CPSspinColorFlavorMatrix &out, const lA2AfieldL &l, const A2AmesonField &M, const rA2AfieldR &r, const int &xop, const int &top, const bool &conj_l, const bool &conj_r){ typedef typename lA2AfieldL::DilutionType iLeftDilutionType; typedef typename A2AmesonField::LeftDilutionType iRightDilutionType; typedef typename A2AmesonField::RightDilutionType jLeftDilutionType; typedef typename rA2AfieldR::DilutionType jRightDilutionType; out.zero(); int top_glb = top+GJP.TnodeSites()*GJP.TnodeCoor(); //Precompute index mappings ModeContractionIndices i_ind(l); ModeContractionIndices j_ind(r); modeIndexSet ilp, irp, jlp, jrp; ilp.time = top_glb; irp.time = M.getRowTimeslice(); jlp.time = M.getColTimeslice(); jrp.time = top_glb; int site4dop = xop + GJP.VolNodeSites()/GJP.TnodeSites()*top; const static int nscf = 2*3*4; const static int complex_scf_vect_size = nscf*2; int ni[nscf], nj[nscf]; //mapping f+2*(c+3*s) std::vector ilmap[nscf], irmap[nscf], jlmap[nscf], jrmap[nscf]; //Reorder rows and columns such that they can be accessed sequentially std::vector lreord[nscf]; std::vector rreord[nscf]; int Mrows = M.getNrows(); int Mcols = M.getNcols(); //Are particular row and column indices of M actually used? bool rowidx_used[Mrows]; for(int i=0;i &ilmap_this = ilmap[scf]; ilmap_this.resize(ni_this); std::vector &irmap_this = irmap[scf]; irmap_this.resize(ni_this); for(int i = 0; i < ni_this; i++){ i_ind.getBothIndices(ilmap_this[i],irmap_this[i],i,ilp,irp); rowidx_used[ irmap_this[i] ] = true; //this row index is used } //M.rowReorder(rowreord[scf], &irmap_this.front(), ni_this); lreord[scf].resize(ni_this); for(int i = 0; i < ni_this; i++){ const ScalarComplexType &lval_tmp = l.nativeElem(ilmap_this[i], site4dop, sc, f); lreord[scf][i] = conj_l ? std::conj(lval_tmp) : lval_tmp; } //j index int nj_this = j_ind.getNindices(jlp,jrp); nj[scf] = nj_this; std::vector &jlmap_this = jlmap[scf]; jlmap_this.resize(nj_this); std::vector &jrmap_this = jrmap[scf]; jrmap_this.resize(nj_this); for(int j = 0; j < nj_this; j++){ j_ind.getBothIndices(jlmap_this[j],jrmap_this[j],j,jlp,jrp); colidx_used[ jlmap_this[j] ] = true; } //M.colReorder(colreord[scf], &jlmap_this.front(), nj_this); rreord[scf].resize(nj_this); for(int j = 0; j < nj_this; j++){ const ScalarComplexType &rval_tmp = r.nativeElem(jrmap_this[j], site4dop, sc, f); rreord[scf][j] = conj_r ? std::conj(rval_tmp) : rval_tmp; } } } } //Matrix vector multiplication M*r ScalarComplexType Mr[Mrows][nscf]; //Use GSL BLAS typedef gsl_wrapper gw; assert(sizeof(typename gw::complex) == sizeof(ScalarComplexType) ); typename gw::complex tmp; //Not all rows or columns of M are used, so lets use a packed matrix int nrows_used = 0; for(int i_full=0;i_full &jlmap_this = jlmap[scf]; typename gw::matrix_complex * M_packed = M.GSLpackedColReorder(&jlmap_this.front(), nj_this, rowidx_used, M_packed_buffer); //packs the GSL matrix int i_packed = 0; int i_packed_unmap[nrows_used]; for(int i_full=0;i_full &out, const lA2AfieldL &l, const A2AmesonField &M, const rA2AfieldR &r, const int &xop, const int &top, const bool &conj_l, const bool &conj_r){ int site4dop = xop + GJP.VolNodeSites()/GJP.TnodeSites()*top; A2Aparams i_params(l), j_params(r); StandardIndexDilution idil(i_params), jdil(j_params); int ni = idil.getNmodes(); int nj = jdil.getNmodes(); out.zero(); for(int sl=0;sl<4;sl++){ for(int sr=0;sr<4;sr++){ for(int cl=0;cl<3;cl++){ for(int cr=0;cr<3;cr++){ for(int fl=0;fl<2;fl++){ for(int fr=0;fr<2;fr++){ for(int i=0;i class lA2AfieldL, template class lA2AfieldR, template class rA2AfieldL, template class rA2AfieldR> class _mult_vMv_impl_v{ //for SIMD vectorized W and V vectors public: typedef typename mf_Policies::ComplexType VectorComplexType; typedef typename mf_Policies::ScalarComplexType ScalarComplexType; //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) // l^i(xop,top) M^ij(tl,tr) r^j(xop,top) //argument xop is the *local* 3d site index of the reduced (logical) lattice in canonical ordering, top is the *local* time coordinate //it is assumed that the lattice is not SIMD vectorized in the time direction // Node local and unthreaded static void mult(CPSspinColorFlavorMatrix &out, const lA2AfieldL &l, const A2AmesonField &M, const rA2AfieldR &r, const int &xop, const int &top, const bool &conj_l, const bool &conj_r){ typedef typename lA2AfieldL::DilutionType iLeftDilutionType; typedef typename A2AmesonField::LeftDilutionType iRightDilutionType; typedef typename A2AmesonField::RightDilutionType jLeftDilutionType; typedef typename rA2AfieldR::DilutionType jRightDilutionType; assert(l.getMode(0).SIMDlogicalNodes(3) == 1); out.zero(); int top_glb = top+GJP.TnodeSites()*GJP.TnodeCoor(); //Precompute index mappings ModeContractionIndices i_ind(l); ModeContractionIndices j_ind(r); modeIndexSet ilp, irp, jlp, jrp; ilp.time = top_glb; irp.time = M.getRowTimeslice(); jlp.time = M.getColTimeslice(); jrp.time = top_glb; int site4dop = l.getMode(0).threeToFour(xop, top); const static int nscf = 2*3*4; int ni[nscf], nj[nscf]; //mapping f+2*(c+3*s) std::vector ilmap[nscf], irmap[nscf], jlmap[nscf], jrmap[nscf]; const int Mrows = M.getNrows(); //Are particular row indices of M actually used? bool rowidx_used[Mrows]; for(int i=0;i lreord[nscf]; Grid::Vector rreord[nscf]; //Note: //il is the index of l, //ir is the row index of M, //jl is the column index of M and //jr is the index of r for(int s=0;s<4;s++){ for(int c=0;c<3;c++){ int sc = c + 3*s; ilp.spin_color = jrp.spin_color = sc; for(int f=0;f<2;f++){ ilp.flavor = jrp.flavor = f; int scf = f + 2*ilp.spin_color; //i index int ni_this = i_ind.getNindices(ilp,irp); ni[scf] = ni_this; std::vector &ilmap_this = ilmap[scf]; ilmap_this.resize(ni_this); std::vector &irmap_this = irmap[scf]; irmap_this.resize(ni_this); lreord[scf].resize(ni_this); for(int i = 0; i < ni_this; i++){ i_ind.getBothIndices(ilmap_this[i],irmap_this[i],i,ilp,irp); rowidx_used[ irmap_this[i] ] = true; //this row index of Mr is used const VectorComplexType &lval_tmp = l.nativeElem(ilmap_this[i], site4dop, sc, f); lreord[scf][i] = conj_l ? Grid::conjugate(lval_tmp) : lval_tmp; } //j index int nj_this = j_ind.getNindices(jlp,jrp); nj[scf] = nj_this; std::vector &jlmap_this = jlmap[scf]; jlmap_this.resize(nj_this); std::vector &jrmap_this = jrmap[scf]; jrmap_this.resize(nj_this); rreord[scf].resize(nj_this); for(int j = 0; j < nj_this; j++){ j_ind.getBothIndices(jlmap_this[j],jrmap_this[j],j,jlp,jrp); const VectorComplexType &rval_tmp = r.nativeElem(jrmap_this[j], site4dop, sc, f); rreord[scf][j] = conj_r ? Grid::conjugate(rval_tmp) : rval_tmp; } } } } //Matrix vector multiplication M*r contracted on mode index j. Only do it for rows that are actually used VectorComplexType Mr[Mrows][nscf]; VectorComplexType tmp_v; for(int i=0;i &out, const lA2AfieldL &l, const A2AmesonField &M, const rA2AfieldR &r, const int &xop, const int &top, const bool &conj_l, const bool &conj_r){ assert(l.getMode(0).SIMDlogicalNodes(3) == 1); int site4dop = l.getMode(0).threeToFour(xop,top); A2Aparams i_params(l), j_params(r); StandardIndexDilution idil(i_params), jdil(j_params); int ni = idil.getNmodes(); int nj = jdil.getNmodes(); out.zero(); VectorComplexType tmp; for(int sl=0;sl<4;sl++){ for(int cl=0;cl<3;cl++){ for(int fl=0;fl<2;fl++){ for(int sr=0;sr<4;sr++){ for(int cr=0;cr<3;cr++){ for(int fr=0;fr<2;fr++){ for(int i=0;i class lA2Afield, template class MA2AfieldL, template class MA2AfieldR, template class rA2Afield > void mult(CPSspinColorFlavorMatrix &out, const lA2Afield &l, const A2AmesonField &M, const rA2Afield &r, const int &xop, const int &top, const bool &conj_l, const bool &conj_r){ _mult_vMv_impl_v::type >::mult(out,l,M,r,xop,top,conj_l,conj_r); } template class lA2Afield, template class MA2AfieldL, template class MA2AfieldR, template class rA2Afield > void mult_slow(CPSspinColorFlavorMatrix &out, const lA2Afield &l, const A2AmesonField &M, const rA2Afield &r, const int &xop, const int &top, const bool &conj_l, const bool &conj_r){ _mult_vMv_impl_v::type >::mult_slow(out,l,M,r,xop,top,conj_l,conj_r); } #endif #endif