/************************************************************************************* Grid physics library, www.github.com/paboyle/Grid Source file: Hadrons/Modules/MContraction/A2AMesonField.hpp Copyright (C) 2015-2019 Author: Antonin Portelli Author: Peter Boyle Author: paboyle This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. See the full license in the file "LICENSE" in the top level distribution directory *************************************************************************************/ /* END LEGAL */ #ifndef Hadrons_MContraction_A2AMesonField_hpp_ #define Hadrons_MContraction_A2AMesonField_hpp_ #include #include #include #include BEGIN_HADRONS_NAMESPACE /****************************************************************************** * All-to-all meson field creation * ******************************************************************************/ BEGIN_MODULE_NAMESPACE(MContraction) class A2AMesonFieldPar: Serializable { public: GRID_SERIALIZABLE_CLASS_MEMBERS(A2AMesonFieldPar, int, cacheBlock, int, block, std::string, left, std::string, right, std::string, output, std::string, gammas, std::vector, mom); }; class A2AMesonFieldMetadata: Serializable { public: GRID_SERIALIZABLE_CLASS_MEMBERS(A2AMesonFieldMetadata, std::vector, momentum, Gamma::Algebra, gamma); }; template class MesonFieldKernel: public A2AKernel { public: typedef typename FImpl::FermionField FermionField; public: MesonFieldKernel(const std::vector &gamma, const std::vector &mom, GridBase *grid) : gamma_(gamma), mom_(mom), grid_(grid) { vol_ = 1.; for (auto &d: grid_->GlobalDimensions()) { vol_ *= d; } } virtual ~MesonFieldKernel(void) = default; virtual void operator()(A2AMatrixSet &m, const FermionField *left, const FermionField *right, const unsigned int orthogDim, double &t) { A2Autils::MesonField(m, left, right, gamma_, mom_, orthogDim, &t); } virtual double flops(const unsigned int blockSizei, const unsigned int blockSizej) { return vol_*(2*8.0+6.0+8.0*mom_.size())*blockSizei*blockSizej*gamma_.size(); } virtual double bytes(const unsigned int blockSizei, const unsigned int blockSizej) { return vol_*(12.0*sizeof(T))*blockSizei*blockSizej + vol_*(2.0*sizeof(T)*mom_.size())*blockSizei*blockSizej*gamma_.size(); } private: const std::vector &gamma_; const std::vector &mom_; GridBase *grid_; double vol_; }; template class TA2AMesonField : public Module { public: FERM_TYPE_ALIASES(FImpl,); typedef A2AMatrixBlockComputation Computation; typedef MesonFieldKernel Kernel; public: // constructor TA2AMesonField(const std::string name); // destructor virtual ~TA2AMesonField(void){}; // dependency relation virtual std::vector getInput(void); virtual std::vector getOutput(void); // setup virtual void setup(void); // execution virtual void execute(void); private: bool hasPhase_{false}; std::string momphName_; std::vector gamma_; std::vector> mom_; }; MODULE_REGISTER(A2AMesonField, ARG(TA2AMesonField), MContraction); /****************************************************************************** * TA2AMesonField implementation * ******************************************************************************/ // constructor ///////////////////////////////////////////////////////////////// template TA2AMesonField::TA2AMesonField(const std::string name) : Module(name) , momphName_(name + "_momph") { } // dependencies/products /////////////////////////////////////////////////////// template std::vector TA2AMesonField::getInput(void) { std::vector in = {par().left, par().right}; return in; } template std::vector TA2AMesonField::getOutput(void) { std::vector out = {}; return out; } // setup /////////////////////////////////////////////////////////////////////// template void TA2AMesonField::setup(void) { gamma_.clear(); mom_.clear(); if (par().gammas == "all") { gamma_ = { Gamma::Algebra::Gamma5, Gamma::Algebra::Identity, Gamma::Algebra::GammaX, Gamma::Algebra::GammaY, Gamma::Algebra::GammaZ, Gamma::Algebra::GammaT, Gamma::Algebra::GammaXGamma5, Gamma::Algebra::GammaYGamma5, Gamma::Algebra::GammaZGamma5, Gamma::Algebra::GammaTGamma5, Gamma::Algebra::SigmaXY, Gamma::Algebra::SigmaXZ, Gamma::Algebra::SigmaXT, Gamma::Algebra::SigmaYZ, Gamma::Algebra::SigmaYT, Gamma::Algebra::SigmaZT }; } else { gamma_ = strToVec(par().gammas); } for (auto &pstr: par().mom) { auto p = strToVec(pstr); if (p.size() != env().getNd() - 1) { HADRONS_ERROR(Size, "Momentum has " + std::to_string(p.size()) + " components instead of " + std::to_string(env().getNd() - 1)); } mom_.push_back(p); } envCache(std::vector, momphName_, 1, par().mom.size(), envGetGrid(ComplexField)); envTmpLat(ComplexField, "coor"); envTmp(Computation, "computation", 1, envGetGrid(FermionField), env().getNd() - 1, mom_.size(), gamma_.size(), par().block, par().cacheBlock, this); } // execution /////////////////////////////////////////////////////////////////// template void TA2AMesonField::execute(void) { auto &left = envGet(std::vector, par().left); auto &right = envGet(std::vector, par().right); int nt = env().getDim().back(); int N_i = left.size(); int N_j = right.size(); int ngamma = gamma_.size(); int nmom = mom_.size(); int block = par().block; int cacheBlock = par().cacheBlock; LOG(Message) << "Computing all-to-all meson fields" << std::endl; LOG(Message) << "Left: '" << par().left << "' Right: '" << par().right << "'" << std::endl; LOG(Message) << "Momenta:" << std::endl; for (auto &p: mom_) { LOG(Message) << " " << p << std::endl; } LOG(Message) << "Spin bilinears:" << std::endl; for (auto &g: gamma_) { LOG(Message) << " " << g << std::endl; } LOG(Message) << "Meson field size: " << nt << "*" << N_i << "*" << N_j << " (filesize " << sizeString(nt*N_i*N_j*sizeof(HADRONS_A2AM_IO_TYPE)) << "/momentum/bilinear)" << std::endl; auto &ph = envGet(std::vector, momphName_); if (!hasPhase_) { startTimer("Momentum phases"); for (unsigned int j = 0; j < nmom; ++j) { Complex i(0.0,1.0); std::vector p; envGetTmp(ComplexField, coor); ph[j] = zero; for(unsigned int mu = 0; mu < mom_[j].size(); mu++) { LatticeCoordinate(coor, mu); ph[j] = ph[j] + (mom_[j][mu]/env().getDim(mu))*coor; } ph[j] = exp((Real)(2*M_PI)*i*ph[j]); } hasPhase_ = true; stopTimer("Momentum phases"); } auto ionameFn = [this](const unsigned int m, const unsigned int g) { std::stringstream ss; ss << gamma_[g] << "_"; for (unsigned int mu = 0; mu < mom_[m].size(); ++mu) { ss << mom_[m][mu] << ((mu == mom_[m].size() - 1) ? "" : "_"); } return ss.str(); }; auto filenameFn = [this, &ionameFn](const unsigned int m, const unsigned int g) { return par().output + "." + std::to_string(vm().getTrajectory()) + "/" + ionameFn(m, g) + ".h5"; }; auto metadataFn = [this](const unsigned int m, const unsigned int g) { A2AMesonFieldMetadata md; for (auto pmu: mom_[m]) { md.momentum.push_back(pmu); } md.gamma = gamma_[g]; return md; }; Kernel kernel(gamma_, ph, envGetGrid(FermionField)); envGetTmp(Computation, computation); computation.execute(left, right, kernel, ionameFn, filenameFn, metadataFn); } END_MODULE_NAMESPACE END_HADRONS_NAMESPACE #endif // Hadrons_MContraction_A2AMesonField_hpp_