2018-08-07 18:40:48 +01:00
|
|
|
/*************************************************************************************
|
|
|
|
|
|
|
|
Grid physics library, www.github.com/paboyle/Grid
|
|
|
|
|
2018-09-01 21:30:30 +01:00
|
|
|
Source file: Hadrons/A2AVectors.hpp
|
2018-08-07 18:40:48 +01:00
|
|
|
|
|
|
|
Copyright (C) 2015-2018
|
|
|
|
|
|
|
|
Author: Antonin Portelli <antonin.portelli@me.com>
|
2018-08-07 18:42:52 +01:00
|
|
|
Author: fionnoh <fionnoh@gmail.com>
|
2018-08-07 18:40:48 +01:00
|
|
|
|
|
|
|
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 */
|
2018-08-07 18:27:59 +01:00
|
|
|
#ifndef A2A_Vectors_hpp_
|
|
|
|
#define A2A_Vectors_hpp_
|
|
|
|
|
2018-08-28 15:00:40 +01:00
|
|
|
#include <Hadrons/Global.hpp>
|
|
|
|
#include <Hadrons/Environment.hpp>
|
|
|
|
#include <Hadrons/Solver.hpp>
|
2018-08-07 18:27:59 +01:00
|
|
|
|
|
|
|
BEGIN_HADRONS_NAMESPACE
|
|
|
|
|
2018-08-09 00:38:17 +01:00
|
|
|
/******************************************************************************
|
2018-10-18 19:44:58 +01:00
|
|
|
* Class to generate V & W all-to-all vectors *
|
2018-08-09 00:38:17 +01:00
|
|
|
******************************************************************************/
|
2018-08-07 18:27:59 +01:00
|
|
|
template <typename FImpl>
|
|
|
|
class A2AVectorsSchurDiagTwo
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
FERM_TYPE_ALIASES(FImpl,);
|
|
|
|
SOLVER_TYPE_ALIASES(FImpl,);
|
|
|
|
public:
|
|
|
|
A2AVectorsSchurDiagTwo(FMat &action, Solver &solver);
|
|
|
|
virtual ~A2AVectorsSchurDiagTwo(void) = default;
|
2018-08-09 00:38:17 +01:00
|
|
|
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);
|
2018-08-07 18:27:59 +01:00
|
|
|
void makeHighModeV(FermionField &vout, const FermionField &noise);
|
2018-08-09 00:38:17 +01:00
|
|
|
void makeHighModeV5D(FermionField &vout_4d, FermionField &vout_5d,
|
|
|
|
const FermionField &noise_5d);
|
2018-08-07 18:27:59 +01:00
|
|
|
void makeHighModeW(FermionField &wout, const FermionField &noise);
|
2018-08-09 00:38:17 +01:00
|
|
|
void makeHighModeW5D(FermionField &vout_5d, FermionField &wout_5d,
|
|
|
|
const FermionField &noise_5d);
|
2018-08-07 18:27:59 +01:00
|
|
|
private:
|
|
|
|
FMat &action_;
|
|
|
|
Solver &solver_;
|
|
|
|
GridBase *fGrid_, *frbGrid_, *gGrid_;
|
|
|
|
bool is5d_;
|
|
|
|
FermionField src_o_, sol_e_, sol_o_, tmp_, tmp5_;
|
|
|
|
SchurDiagTwoOperator<FMat, FermionField> op_;
|
|
|
|
};
|
|
|
|
|
2018-10-18 19:44:58 +01:00
|
|
|
/******************************************************************************
|
|
|
|
* 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 <typename Field>
|
|
|
|
static void write(const std::string fileStem, std::vector<Field> &vec,
|
|
|
|
const bool multiFile, const int trajectory = -1);
|
|
|
|
template <typename Field>
|
|
|
|
static void read(std::vector<Field> &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";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2018-08-09 00:38:17 +01:00
|
|
|
/******************************************************************************
|
|
|
|
* A2AVectorsSchurDiagTwo template implementation *
|
|
|
|
******************************************************************************/
|
2018-08-07 18:27:59 +01:00
|
|
|
template <typename FImpl>
|
|
|
|
A2AVectorsSchurDiagTwo<FImpl>::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 <typename FImpl>
|
|
|
|
void A2AVectorsSchurDiagTwo<FImpl>::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 <typename FImpl>
|
|
|
|
void A2AVectorsSchurDiagTwo<FImpl>::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 <typename FImpl>
|
|
|
|
void A2AVectorsSchurDiagTwo<FImpl>::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 <typename FImpl>
|
|
|
|
void A2AVectorsSchurDiagTwo<FImpl>::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 <typename FImpl>
|
|
|
|
void A2AVectorsSchurDiagTwo<FImpl>::makeHighModeV(FermionField &vout,
|
|
|
|
const FermionField &noise)
|
|
|
|
{
|
|
|
|
solver_(vout, noise);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename FImpl>
|
|
|
|
void A2AVectorsSchurDiagTwo<FImpl>::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 <typename FImpl>
|
|
|
|
void A2AVectorsSchurDiagTwo<FImpl>::makeHighModeW(FermionField &wout,
|
|
|
|
const FermionField &noise)
|
|
|
|
{
|
|
|
|
wout = noise;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename FImpl>
|
|
|
|
void A2AVectorsSchurDiagTwo<FImpl>::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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-10-18 19:44:58 +01:00
|
|
|
/******************************************************************************
|
|
|
|
* all-to-all vectors I/O template implementation *
|
|
|
|
******************************************************************************/
|
|
|
|
template <typename Field>
|
|
|
|
void A2AVectorsIo::write(const std::string fileStem, std::vector<Field> &vec,
|
|
|
|
const bool multiFile, const int trajectory)
|
|
|
|
{
|
|
|
|
Record record;
|
|
|
|
GridBase *grid = vec[0]._grid;
|
|
|
|
ScidacWriter binWriter(grid->IsBoss());
|
2018-10-21 01:20:05 +01:00
|
|
|
std::string filename = vecFilename(fileStem, trajectory, multiFile);
|
2018-10-18 19:44:58 +01:00
|
|
|
|
|
|
|
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 <typename Field>
|
|
|
|
void A2AVectorsIo::read(std::vector<Field> &vec, const std::string fileStem,
|
|
|
|
const bool multiFile, const int trajectory)
|
|
|
|
{
|
|
|
|
Record record;
|
|
|
|
ScidacReader binReader;
|
2018-10-21 01:20:05 +01:00
|
|
|
std::string filename = vecFilename(fileStem, trajectory, multiFile);
|
2018-10-18 19:44:58 +01:00
|
|
|
|
|
|
|
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();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-07 18:27:59 +01:00
|
|
|
END_HADRONS_NAMESPACE
|
|
|
|
|
2018-08-14 12:15:24 +01:00
|
|
|
#endif // A2A_Vectors_hpp_
|