/************************************************************************************* Grid physics library, www.github.com/paboyle/Grid Source file: Hadrons/A2AVectors.hpp Copyright (C) 2015-2018 Author: Antonin Portelli Author: fionnoh 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 A2A_Vectors_hpp_ #define A2A_Vectors_hpp_ #include #include #include BEGIN_HADRONS_NAMESPACE /****************************************************************************** * Class to generate V & W all-to-all vectors * ******************************************************************************/ template class A2AVectorsSchurDiagTwo { public: FERM_TYPE_ALIASES(FImpl,); SOLVER_TYPE_ALIASES(FImpl,); public: A2AVectorsSchurDiagTwo(FMat &action, Solver &solver); virtual ~A2AVectorsSchurDiagTwo(void) = default; void makeLowModeV(FermionField &vout, const FermionField &evec, const Real &eval); void makeLowModeV5D(FermionField &vout_4d, FermionField &vout_5d, const FermionField &evec, const Real &eval); void makeLowModeW(FermionField &wout, const FermionField &evec, const Real &eval); void makeLowModeW5D(FermionField &wout_4d, FermionField &wout_5d, const FermionField &evec, const Real &eval); void makeHighModeV(FermionField &vout, const FermionField &noise); void makeHighModeV5D(FermionField &vout_4d, FermionField &vout_5d, const FermionField &noise_5d); void makeHighModeW(FermionField &wout, const FermionField &noise); void makeHighModeW5D(FermionField &vout_5d, FermionField &wout_5d, const FermionField &noise_5d); private: FMat &action_; Solver &solver_; GridBase *fGrid_, *frbGrid_, *gGrid_; bool is5d_; FermionField src_o_, sol_e_, sol_o_, tmp_, tmp5_; SchurDiagTwoOperator op_; }; /****************************************************************************** * Methods for V & W all-to-all vectors I/O * ******************************************************************************/ class A2AVectorsIo { public: struct Record: Serializable { GRID_SERIALIZABLE_CLASS_MEMBERS(Record, unsigned int, index); Record(void): index(0) {} }; public: template static void write(const std::string fileStem, std::vector &vec, const bool multiFile, const int trajectory = -1); template static void read(std::vector &vec, const std::string fileStem, const bool multiFile, const int trajectory = -1); private: static inline std::string vecFilename(const std::string stem, const int traj, const bool multiFile) { std::string t = (traj < 0) ? "" : ("." + std::to_string(traj)); if (multiFile) { return stem + t; } else { return stem + t + ".bin"; } } }; /****************************************************************************** * A2AVectorsSchurDiagTwo template implementation * ******************************************************************************/ template A2AVectorsSchurDiagTwo::A2AVectorsSchurDiagTwo(FMat &action, Solver &solver) : action_(action) , solver_(solver) , fGrid_(action_.FermionGrid()) , frbGrid_(action_.FermionRedBlackGrid()) , gGrid_(action_.GaugeGrid()) , src_o_(frbGrid_) , sol_e_(frbGrid_) , sol_o_(frbGrid_) , tmp_(frbGrid_) , tmp5_(fGrid_) , op_(action_) {} template void A2AVectorsSchurDiagTwo::makeLowModeV(FermionField &vout, const FermionField &evec, const Real &eval) { src_o_ = evec; src_o_.checkerboard = Odd; pickCheckerboard(Even, sol_e_, vout); pickCheckerboard(Odd, sol_o_, vout); ///////////////////////////////////////////////////// // v_ie = -(1/eval_i) * MeeInv Meo MooInv evec_i ///////////////////////////////////////////////////// action_.MooeeInv(src_o_, tmp_); assert(tmp_.checkerboard == Odd); action_.Meooe(tmp_, sol_e_); assert(sol_e_.checkerboard == Even); action_.MooeeInv(sol_e_, tmp_); assert(tmp_.checkerboard == Even); sol_e_ = (-1.0 / eval) * tmp_; assert(sol_e_.checkerboard == Even); ///////////////////////////////////////////////////// // v_io = (1/eval_i) * MooInv evec_i ///////////////////////////////////////////////////// action_.MooeeInv(src_o_, tmp_); assert(tmp_.checkerboard == Odd); sol_o_ = (1.0 / eval) * tmp_; assert(sol_o_.checkerboard == Odd); setCheckerboard(vout, sol_e_); assert(sol_e_.checkerboard == Even); setCheckerboard(vout, sol_o_); assert(sol_o_.checkerboard == Odd); } template void A2AVectorsSchurDiagTwo::makeLowModeV5D(FermionField &vout_4d, FermionField &vout_5d, const FermionField &evec, const Real &eval) { makeLowModeV(vout_5d, evec, eval); action_.ExportPhysicalFermionSolution(vout_5d, vout_4d); } template void A2AVectorsSchurDiagTwo::makeLowModeW(FermionField &wout, const FermionField &evec, const Real &eval) { src_o_ = evec; src_o_.checkerboard = Odd; pickCheckerboard(Even, sol_e_, wout); pickCheckerboard(Odd, sol_o_, wout); ///////////////////////////////////////////////////// // w_ie = - MeeInvDag MoeDag Doo evec_i ///////////////////////////////////////////////////// op_.Mpc(src_o_, tmp_); assert(tmp_.checkerboard == Odd); action_.MeooeDag(tmp_, sol_e_); assert(sol_e_.checkerboard == Even); action_.MooeeInvDag(sol_e_, tmp_); assert(tmp_.checkerboard == Even); sol_e_ = (-1.0) * tmp_; ///////////////////////////////////////////////////// // w_io = Doo evec_i ///////////////////////////////////////////////////// op_.Mpc(src_o_, sol_o_); assert(sol_o_.checkerboard == Odd); setCheckerboard(wout, sol_e_); assert(sol_e_.checkerboard == Even); setCheckerboard(wout, sol_o_); assert(sol_o_.checkerboard == Odd); } template void A2AVectorsSchurDiagTwo::makeLowModeW5D(FermionField &wout_4d, FermionField &wout_5d, const FermionField &evec, const Real &eval) { makeLowModeW(tmp5_, evec, eval); action_.DminusDag(tmp5_, wout_5d); action_.ExportPhysicalFermionSource(wout_5d, wout_4d); } template void A2AVectorsSchurDiagTwo::makeHighModeV(FermionField &vout, const FermionField &noise) { solver_(vout, noise); } template void A2AVectorsSchurDiagTwo::makeHighModeV5D(FermionField &vout_4d, FermionField &vout_5d, const FermionField &noise) { if (noise._grid->Dimensions() == fGrid_->Dimensions() - 1) { action_.ImportPhysicalFermionSource(noise, tmp5_); } else { tmp5_ = noise; } makeHighModeV(vout_5d, tmp5_); action_.ExportPhysicalFermionSolution(vout_5d, vout_4d); } template void A2AVectorsSchurDiagTwo::makeHighModeW(FermionField &wout, const FermionField &noise) { wout = noise; } template void A2AVectorsSchurDiagTwo::makeHighModeW5D(FermionField &wout_4d, FermionField &wout_5d, const FermionField &noise) { if (noise._grid->Dimensions() == fGrid_->Dimensions() - 1) { action_.ImportUnphysicalFermion(noise, wout_5d); wout_4d = noise; } else { wout_5d = noise; action_.ExportPhysicalFermionSource(wout_5d, wout_4d); } } /****************************************************************************** * all-to-all vectors I/O template implementation * ******************************************************************************/ template void A2AVectorsIo::write(const std::string fileStem, std::vector &vec, const bool multiFile, const int trajectory) { Record record; GridBase *grid = vec[0]._grid; ScidacWriter binWriter(grid->IsBoss()); std::string filename = vecFilename(fileStem, multiFile, trajectory); if (multiFile) { std::string fullFilename; for (unsigned int i = 0; i < vec.size(); ++i) { fullFilename = filename + "/elem" + std::to_string(i) + ".bin"; LOG(Message) << "Writing vector " << i << std::endl; makeFileDir(fullFilename, grid); binWriter.open(fullFilename); record.index = i; binWriter.writeScidacFieldRecord(vec[i], record); binWriter.close(); } } else { makeFileDir(filename, grid); binWriter.open(filename); for (unsigned int i = 0; i < vec.size(); ++i) { LOG(Message) << "Writing vector " << i << std::endl; record.index = i; binWriter.writeScidacFieldRecord(vec[i], record); } binWriter.close(); } } template void A2AVectorsIo::read(std::vector &vec, const std::string fileStem, const bool multiFile, const int trajectory) { Record record; ScidacReader binReader; std::string filename = vecFilename(fileStem, multiFile, trajectory); if (multiFile) { std::string fullFilename; for (unsigned int i = 0; i < vec.size(); ++i) { fullFilename = filename + "/elem" + std::to_string(i) + ".bin"; LOG(Message) << "Reading vector " << i << std::endl; binReader.open(fullFilename); binReader.readScidacFieldRecord(vec[i], record); binReader.close(); if (record.index != i) { HADRONS_ERROR(Io, "vector index mismatch"); } } } else { binReader.open(filename); for (unsigned int i = 0; i < vec.size(); ++i) { LOG(Message) << "Reading vector " << i << std::endl; binReader.readScidacFieldRecord(vec[i], record); if (record.index != i) { HADRONS_ERROR(Io, "vector index mismatch"); } } binReader.close(); } } END_HADRONS_NAMESPACE #endif // A2A_Vectors_hpp_