1
0
mirror of https://github.com/paboyle/Grid.git synced 2024-11-10 07:55:35 +00:00

Hadrons: overhaul of A2A for production

This commit is contained in:
Antonin Portelli 2018-08-07 18:27:59 +01:00
parent 231cc95be6
commit 0677adb4dd
6 changed files with 558 additions and 531 deletions

View File

@ -0,0 +1,387 @@
#ifndef A2A_Vectors_hpp_
#define A2A_Vectors_hpp_
#include <Grid/Hadrons/Global.hpp>
#include <Grid/Hadrons/Environment.hpp>
#include <Grid/Hadrons/Solver.hpp>
BEGIN_HADRONS_NAMESPACE
////////////////////////////////
// A2A Modes
////////////////////////////////
template <typename FImpl>
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<FMat, FermionField> op_;
};
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);
}
}
// A2AVectorsSchurDiagTwo(const int Nl, const int Nh,
// std::vector<FermionField> &v,
// std::vector<FermionField> &w,
// const bool _return_5d)
// : Nl(_Nl), Nh(_Nh),
// return_5d(_return_5d)
// {
// if (!return_5d)
// {
// init_resize(1, Nl + Nh);
// }
// else
// {
// init_resize(Nl + Nh, Nl + Nh);
// }
// }
// void init_resize(const size_t size_5d, const size_t size_4d,
// GridBase *grid_5d, GridBase *grid_4d)
// {
// w_5d.resize(size_5d, grid_5d);
// v_5d.resize(size_5d, grid_5d);
// w_4d.resize(size_4d, grid_4d);
// v_4d.resize(size_4d, grid_4d);
// }
// int get_Nh(void) const
// {
// return Nh;
// }
// int get_Nl(void) const
// {
// return Nl;
// }
// void low_modes(int il, const Field &evec, const Real &eval, Matrix &action)
// {
// int i5d;
// i5d = 0;
// if (return_5d) i5d = il;
// this->low_mode_v(v_5d[i5d], v_4d[il], evec, eval, action);
// this->low_mode_w(w_5d[i5d], w_4d[il], evec, eval, action);
// }
// void high_modes(int ih, Field &source_5d, Field &w_source_5d,
// Field &source_4d, Solver &solver)
// {
// int i5d;
// i5d = 0;
// if (return_5d) i5d = ih + Nl;
// this->high_mode_v(source_5d, v_5d[i5d], v_4d[ih + Nl], solver);
// this->high_mode_w(w_source_5d, source_4d, w_5d[i5d], w_4d[ih + Nl]);
// }
// void return_v(int i, Field &vout_5d, Field &vout_4d)
// {
// vout_4d = v_4d[i];
// if (!(return_5d)) i = 0;
// vout_5d = v_5d[i];
// }
// void return_w(int i, Field &wout_5d, Field &wout_4d)
// {
// wout_4d = w_4d[i];
// if (!(return_5d)) i = 0;
// wout_5d = w_5d[i];
// }
// void low_mode_v(Field &vout_5d, Field &vout_4d, const Field &evec,
// const Real &eval, Matrix &action)
// {
// GridBase *grid = action.RedBlackGrid();
// Field src_o(grid);
// Field sol_e(grid);
// Field sol_o(grid);
// Field tmp(grid);
// src_o = evec;
// src_o.checkerboard = Odd;
// pickCheckerboard(Even, sol_e, vout_5d);
// pickCheckerboard(Odd, sol_o, vout_5d);
// /////////////////////////////////////////////////////
// // 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_5d, sol_e);
// assert(sol_e.checkerboard == Even);
// setCheckerboard(vout_5d, sol_o);
// assert(sol_o.checkerboard == Odd);
// action.ExportPhysicalFermionSolution(vout_5d, vout_4d);
// }
// void low_mode_w(Field &wout_5d, Field &wout_4d, const Field &evec,
// const Real &eval, Matrix &action)
// {
// GridBase *grid = action.RedBlackGrid();
// SchurDiagTwoOperator<Matrix, Field> _HermOpEO(action);
// Field src_o(grid);
// Field sol_e(grid);
// Field sol_o(grid);
// Field tmp(grid);
// GridBase *fgrid = action.Grid();
// Field tmp_wout(fgrid);
// src_o = evec;
// src_o.checkerboard = Odd;
// pickCheckerboard(Even, sol_e, tmp_wout);
// pickCheckerboard(Odd, sol_o, tmp_wout);
// /////////////////////////////////////////////////////
// // w_ie = - MeeInvDag MoeDag Doo evec_i
// /////////////////////////////////////////////////////
// _HermOpEO.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
// /////////////////////////////////////////////////////
// _HermOpEO.Mpc(src_o, sol_o);
// assert(sol_o.checkerboard == Odd);
// setCheckerboard(tmp_wout, sol_e);
// assert(sol_e.checkerboard == Even);
// setCheckerboard(tmp_wout, sol_o);
// assert(sol_o.checkerboard == Odd);
// action.DminusDag(tmp_wout, wout_5d);
// action.ExportPhysicalFermionSource(wout_5d, wout_4d);
// }
// void high_mode_v(const Field &source, Field &vout_5d, Field &vout_4d,
// Matrix &action, Solver &solver)
// {
// GridBase *fgrid = action.Grid();
// solver(vout_5d, source); // Note: solver is solver(out, in)
// action.ExportPhysicalFermionSolution(vout_5d, vout_4d);
// }
// void high_mode_w(const Field &w_source_5d, const Field &source_4d,
// Field &wout_5d, Field &wout_4d)
// {
// wout_5d = w_source_5d;
// wout_4d = source_4d;
// }
// TODO: A2A for coarse eigenvectors
// template <class FineField, class CoarseField, class Matrix, class Solver>
// class A2ALMSchurDiagTwoCoarse : public A2AModesSchurDiagTwo<FineField, Matrix, Solver>
// {
// private:
// const std::vector<FineField> &subspace;
// const std::vector<CoarseField> &evec_coarse;
// const std::vector<RealD> &eval_coarse;
// Matrix &action;
// public:
// A2ALMSchurDiagTwoCoarse(const std::vector<FineField> &_subspace, const std::vector<CoarseField> &_evec_coarse, const std::vector<RealD> &_eval_coarse, Matrix &_action)
// : subspace(_subspace), evec_coarse(_evec_coarse), eval_coarse(_eval_coarse), action(_action){};
// void operator()(int i, FineField &vout, FineField &wout)
// {
// FineField prom_evec(subspace[0]._grid);
// blockPromote(evec_coarse[i], prom_evec, subspace);
// this->low_mode_v(action, prom_evec, eval_coarse[i], vout);
// this->low_mode_w(action, prom_evec, eval_coarse[i], wout);
// }
// };
END_HADRONS_NAMESPACE
#endif // A2A_Vectors_hpp_

View File

@ -1,146 +0,0 @@
#ifndef A2A_Reduction_hpp_
#define A2A_Reduction_hpp_
#include <Grid/Hadrons/Global.hpp>
#include <Grid/Hadrons/Environment.hpp>
#include <Grid/Hadrons/Solver.hpp>
BEGIN_HADRONS_NAMESPACE
////////////////////////////////////////////
// A2A Meson Field Inner Product
////////////////////////////////////////////
template <class FermionField>
void sliceInnerProductMesonField(std::vector<std::vector<ComplexD>> &mat,
const std::vector<Lattice<FermionField>> &lhs,
const std::vector<Lattice<FermionField>> &rhs,
int orthogdim)
{
typedef typename FermionField::scalar_type scalar_type;
typedef typename FermionField::vector_type vector_type;
int Lblock = lhs.size();
int Rblock = rhs.size();
GridBase *grid = lhs[0]._grid;
const int Nd = grid->_ndimension;
const int Nsimd = grid->Nsimd();
int Nt = grid->GlobalDimensions()[orthogdim];
assert(mat.size() == Lblock * Rblock);
for (int t = 0; t < mat.size(); t++)
{
assert(mat[t].size() == Nt);
}
int fd = grid->_fdimensions[orthogdim];
int ld = grid->_ldimensions[orthogdim];
int rd = grid->_rdimensions[orthogdim];
// will locally sum vectors first
// sum across these down to scalars
// splitting the SIMD
std::vector<vector_type, alignedAllocator<vector_type>> lvSum(rd * Lblock * Rblock);
for(int r=0;r<rd * Lblock * Rblock;r++)
{
lvSum[r]=zero;
}
std::vector<scalar_type> lsSum(ld * Lblock * Rblock, scalar_type(0.0));
int e1 = grid->_slice_nblock[orthogdim];
int e2 = grid->_slice_block[orthogdim];
int stride = grid->_slice_stride[orthogdim];
// std::cout << GridLogMessage << " Entering first parallel loop " << std::endl;
// Parallelise over t-direction doesn't expose as much parallelism as needed for KNL
parallel_for(int r = 0; r < rd; r++)
{
int so = r * grid->_ostride[orthogdim]; // base offset for start of plane
for (int n = 0; n < e1; n++)
{
for (int b = 0; b < e2; b++)
{
int ss = so + n * stride + b;
for (int i = 0; i < Lblock; i++)
{
auto left = conjugate(lhs[i]._odata[ss]);
for (int j = 0; j < Rblock; j++)
{
int idx = i + Lblock * j + Lblock * Rblock * r;
auto right = rhs[j]._odata[ss];
vector_type vv = left()(0)(0) * right()(0)(0)
+ left()(0)(1) * right()(0)(1)
+ left()(0)(2) * right()(0)(2)
+ left()(1)(0) * right()(1)(0)
+ left()(1)(1) * right()(1)(1)
+ left()(1)(2) * right()(1)(2)
+ left()(2)(0) * right()(2)(0)
+ left()(2)(1) * right()(2)(1)
+ left()(2)(2) * right()(2)(2)
+ left()(3)(0) * right()(3)(0)
+ left()(3)(1) * right()(3)(1)
+ left()(3)(2) * right()(3)(2);
lvSum[idx] = lvSum[idx] + vv;
}
}
}
}
}
// std::cout << GridLogMessage << " Entering second parallel loop " << std::endl;
// Sum across simd lanes in the plane, breaking out orthog dir.
parallel_for(int rt = 0; rt < rd; rt++)
{
std::vector<int> icoor(Nd);
for (int i = 0; i < Lblock; i++)
{
for (int j = 0; j < Rblock; j++)
{
iScalar<vector_type> temp;
std::vector<iScalar<scalar_type>> extracted(Nsimd);
temp._internal = lvSum[i + Lblock * j + Lblock * Rblock * rt];
extract(temp, extracted);
for (int idx = 0; idx < Nsimd; idx++)
{
grid->iCoorFromIindex(icoor, idx);
int ldx = rt + icoor[orthogdim] * rd;
int ij_dx = i + Lblock * j + Lblock * Rblock * ldx;
lsSum[ij_dx] = lsSum[ij_dx] + extracted[idx]._internal;
}
}
}
}
// std::cout << GridLogMessage << " Entering non parallel loop " << std::endl;
for (int t = 0; t < fd; t++)
{
int pt = t/ld; // processor plane
int lt = t%ld;
for (int i = 0; i < Lblock; i++)
{
for (int j = 0; j < Rblock; j++)
{
if (pt == grid->_processor_coor[orthogdim])
{
int ij_dx = i + Lblock * j + Lblock * Rblock * lt;
mat[i + j * Lblock][t] = lsSum[ij_dx];
}
else
{
mat[i + j * Lblock][t] = scalar_type(0.0);
}
}
}
}
// std::cout << GridLogMessage << " Done " << std::endl;
// defer sum over nodes.
return;
}
END_HADRONS_NAMESPACE
#endif // A2A_Reduction_hpp_

View File

@ -1,227 +0,0 @@
#ifndef A2A_Vectors_hpp_
#define A2A_Vectors_hpp_
#include <Grid/Hadrons/Global.hpp>
#include <Grid/Hadrons/Environment.hpp>
#include <Grid/Hadrons/Solver.hpp>
BEGIN_HADRONS_NAMESPACE
////////////////////////////////
// A2A Modes
////////////////////////////////
template <class Field, class Matrix, class Solver>
class A2AModesSchurDiagTwo
{
private:
const std::vector<Field> *evec;
const std::vector<RealD> *eval;
Matrix &action;
Solver &solver;
const int Nl, Nh;
const bool return_5d;
std::vector<Field> w_high_5d, v_high_5d, w_high_4d, v_high_4d;
public:
A2AModesSchurDiagTwo(const std::vector<Field> *_evec, const std::vector<RealD> *_eval,
Matrix &_action,
Solver &_solver,
const int _Nl, const int _Nh,
const bool _return_5d)
: evec(_evec), eval(_eval),
action(_action),
solver(_solver),
Nl(_Nl), Nh(_Nh),
return_5d(_return_5d)
{
init_resize(1, Nh);
if (return_5d) init_resize(Nh, Nh);
};
void init_resize(const size_t size_5d, const size_t size_4d)
{
GridBase *grid_5d = action.Grid();
GridBase *grid_4d = action.GaugeGrid();
w_high_5d.resize(size_5d, grid_5d);
v_high_5d.resize(size_5d, grid_5d);
w_high_4d.resize(size_4d, grid_4d);
v_high_4d.resize(size_4d, grid_4d);
}
int get_Nh(void) const
{
return Nh;
}
int get_Nl(void) const
{
return Nl;
}
void high_modes(Field &source_5d, Field &w_source_5d, Field &source_4d, int i)
{
int i5d;
LOG(Message) << "A2A high modes for i = " << i << std::endl;
i5d = 0;
if (return_5d) i5d = i;
this->high_mode_v(action, solver, source_5d, v_high_5d[i5d], v_high_4d[i]);
this->high_mode_w(w_source_5d, source_4d, w_high_5d[i5d], w_high_4d[i]);
}
void return_v(int i, Field &vout_5d, Field &vout_4d)
{
if (i < Nl)
{
this->low_mode_v(action, evec->at(i), eval->at(i), vout_5d, vout_4d);
}
else
{
vout_4d = v_high_4d[i - Nl];
if (!(return_5d)) i = Nl;
vout_5d = v_high_5d[i - Nl];
}
}
void return_w(int i, Field &wout_5d, Field &wout_4d)
{
if (i < Nl)
{
this->low_mode_w(action, evec->at(i), eval->at(i), wout_5d, wout_4d);
}
else
{
wout_4d = w_high_4d[i - Nl];
if (!(return_5d)) i = Nl;
wout_5d = w_high_5d[i - Nl];
}
}
void low_mode_v(Matrix &action, const Field &evec, const RealD &eval, Field &vout_5d, Field &vout_4d)
{
GridBase *grid = action.RedBlackGrid();
Field src_o(grid);
Field sol_e(grid);
Field sol_o(grid);
Field tmp(grid);
src_o = evec;
src_o.checkerboard = Odd;
pickCheckerboard(Even, sol_e, vout_5d);
pickCheckerboard(Odd, sol_o, vout_5d);
/////////////////////////////////////////////////////
// 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_5d, sol_e);
assert(sol_e.checkerboard == Even);
setCheckerboard(vout_5d, sol_o);
assert(sol_o.checkerboard == Odd);
action.ExportPhysicalFermionSolution(vout_5d, vout_4d);
}
void low_mode_w(Matrix &action, const Field &evec, const RealD &eval, Field &wout_5d, Field &wout_4d)
{
GridBase *grid = action.RedBlackGrid();
SchurDiagTwoOperator<Matrix, Field> _HermOpEO(action);
Field src_o(grid);
Field sol_e(grid);
Field sol_o(grid);
Field tmp(grid);
GridBase *fgrid = action.Grid();
Field tmp_wout(fgrid);
src_o = evec;
src_o.checkerboard = Odd;
pickCheckerboard(Even, sol_e, tmp_wout);
pickCheckerboard(Odd, sol_o, tmp_wout);
/////////////////////////////////////////////////////
// w_ie = - MeeInvDag MoeDag Doo evec_i
/////////////////////////////////////////////////////
_HermOpEO.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
/////////////////////////////////////////////////////
_HermOpEO.Mpc(src_o, sol_o);
assert(sol_o.checkerboard == Odd);
setCheckerboard(tmp_wout, sol_e);
assert(sol_e.checkerboard == Even);
setCheckerboard(tmp_wout, sol_o);
assert(sol_o.checkerboard == Odd);
action.DminusDag(tmp_wout, wout_5d);
action.ExportPhysicalFermionSource(wout_5d, wout_4d);
}
void high_mode_v(Matrix &action, Solver &solver, const Field &source, Field &vout_5d, Field &vout_4d)
{
GridBase *fgrid = action.Grid();
solver(vout_5d, source); // Note: solver is solver(out, in)
action.ExportPhysicalFermionSolution(vout_5d, vout_4d);
}
void high_mode_w(const Field &w_source_5d, const Field &source_4d, Field &wout_5d, Field &wout_4d)
{
wout_5d = w_source_5d;
wout_4d = source_4d;
}
};
// TODO: A2A for coarse eigenvectors
// template <class FineField, class CoarseField, class Matrix, class Solver>
// class A2ALMSchurDiagTwoCoarse : public A2AModesSchurDiagTwo<FineField, Matrix, Solver>
// {
// private:
// const std::vector<FineField> &subspace;
// const std::vector<CoarseField> &evec_coarse;
// const std::vector<RealD> &eval_coarse;
// Matrix &action;
// public:
// A2ALMSchurDiagTwoCoarse(const std::vector<FineField> &_subspace, const std::vector<CoarseField> &_evec_coarse, const std::vector<RealD> &_eval_coarse, Matrix &_action)
// : subspace(_subspace), evec_coarse(_evec_coarse), eval_coarse(_eval_coarse), action(_action){};
// void operator()(int i, FineField &vout, FineField &wout)
// {
// FineField prom_evec(subspace[0]._grid);
// blockPromote(evec_coarse[i], prom_evec, subspace);
// this->low_mode_v(action, prom_evec, eval_coarse[i], vout);
// this->low_mode_w(action, prom_evec, eval_coarse[i], wout);
// }
// };
END_HADRONS_NAMESPACE
#endif // A2A_Vectors_hpp_

View File

@ -14,7 +14,7 @@ libHadrons_a_SOURCES = \
libHadrons_adir = $(pkgincludedir)/Hadrons
nobase_libHadrons_a_HEADERS = \
$(modules_hpp) \
AllToAllVectors.hpp \
A2AVectors.hpp \
Application.hpp \
EigenPack.hpp \
Environment.hpp \

View File

@ -4,7 +4,7 @@
#include <Grid/Hadrons/Global.hpp>
#include <Grid/Hadrons/Module.hpp>
#include <Grid/Hadrons/ModuleFactory.hpp>
#include <Grid/Hadrons/AllToAllVectors.hpp>
#include <Grid/Hadrons/A2AVectors.hpp>
#include <Grid/Eigen/unsupported/CXX11/Tensor>
BEGIN_HADRONS_NAMESPACE
@ -24,7 +24,8 @@ class A2AMesonFieldPar : Serializable
int, cacheBlock,
int, schurBlock,
int, Nmom,
std::string, A2A,
std::string, v,
std::string, w,
std::string, output);
};
@ -34,9 +35,6 @@ class TA2AMesonField : public Module<A2AMesonFieldPar>
public:
FERM_TYPE_ALIASES(FImpl, );
SOLVER_TYPE_ALIASES(FImpl, );
typedef A2AModesSchurDiagTwo<typename FImpl::FermionField, FMat, Solver> A2ABase;
public:
// constructor
TA2AMesonField(const std::string name);
@ -80,7 +78,7 @@ TA2AMesonField<FImpl>::TA2AMesonField(const std::string name)
template <typename FImpl>
std::vector<std::string> TA2AMesonField<FImpl>::getInput(void)
{
std::vector<std::string> in = {par().A2A};
std::vector<std::string> in = {par().v, par().w};
return in;
}
@ -97,20 +95,7 @@ std::vector<std::string> TA2AMesonField<FImpl>::getOutput(void)
// setup ///////////////////////////////////////////////////////////////////////
template <typename FImpl>
void TA2AMesonField<FImpl>::setup(void)
{
auto &a2a = envGet(A2ABase, par().A2A);
int Ls = env().getObjectLs(par().A2A);
// Four D fields
envTmp(std::vector<FermionField>, "w", 1, par().schurBlock,
FermionField(env().getGrid()));
envTmp(std::vector<FermionField>, "v", 1, par().schurBlock,
FermionField(env().getGrid()));
// 5D tmp
envTmpLat(FermionField, "tmp_5d", Ls);
}
{}
//////////////////////////////////////////////////////////////////////////////////
// Cache blocked arithmetic routine
@ -304,7 +289,8 @@ void TA2AMesonField<FImpl>::execute(void)
{
LOG(Message) << "Computing A2A meson field" << std::endl;
auto &a2a = envGet(A2ABase, par().A2A);
auto &v = envGet(std::vector<FermionField>, par().v);
auto &w = envGet(std::vector<FermionField>, par().w);
// 2+6+4+4 = 16 gammas
// Ordering defined here
@ -330,15 +316,13 @@ void TA2AMesonField<FImpl>::execute(void)
///////////////////////////////////////////////
// Square assumption for now Nl = Nr = N
///////////////////////////////////////////////
int nt = env().getDim(Tp);
int nx = env().getDim(Xp);
int ny = env().getDim(Yp);
int nz = env().getDim(Zp);
int Nl = a2a.get_Nl();
int N = Nl + a2a.get_Nh();
int nt = env().getDim(Tp);
int nx = env().getDim(Xp);
int ny = env().getDim(Yp);
int nz = env().getDim(Zp);
int N_i = w.size();
int N_j = v.size();
int ngamma = gammas.size();
int schurBlock = par().schurBlock;
int cacheBlock = par().cacheBlock;
int nmom = par().Nmom;
@ -353,14 +337,8 @@ void TA2AMesonField<FImpl>::execute(void)
phases[m] = Complex(1.0); // All zero momentum for now
}
Eigen::Tensor<ComplexD,5> mesonField (nmom,ngamma,nt,N,N);
LOG(Message) << "N = Nh+Nl for A2A MesonField is " << N << std::endl;
envGetTmp(std::vector<FermionField>, w);
envGetTmp(std::vector<FermionField>, v);
envGetTmp(FermionField, tmp_5d);
LOG(Message) << "Finding v and w vectors for N = " << N << std::endl;
Eigen::Tensor<ComplexD,5> mesonField(nmom,ngamma,nt,N_i,N_j);
LOG(Message) << "MesonField size " << N_i << "x" << N_j << "x" << nt << std::endl;
//////////////////////////////////////////////////////////////////////////
// i,j is first loop over SchurBlock factors reusing 5D matrices
@ -379,10 +357,10 @@ void TA2AMesonField<FImpl>::execute(void)
double t_int_2=0;
double t_int_3=0;
double t0 = usecond();
int N_i = N;
int N_j = N;
double t0 = usecond();
int NBlock_i = N_i/schurBlock + (((N_i % schurBlock) != 0) ? 1 : 0);
int NBlock_j = N_j/schurBlock + (((N_j % schurBlock) != 0) ? 1 : 0);
for(int i=0;i<N_i;i+=schurBlock) //loop over SchurBlocking to suppress 5D matrix overhead
for(int j=0;j<N_j;j+=schurBlock)
{
@ -393,12 +371,13 @@ void TA2AMesonField<FImpl>::execute(void)
int N_jj = MIN(N_j-j,schurBlock);
t_schur-=usecond();
for(int ii =0;ii < N_ii;ii++) a2a.return_w(i+ii, tmp_5d, w[ii]);
for(int jj =0;jj < N_jj;jj++) a2a.return_v(j+jj, tmp_5d, v[jj]);
t_schur+=usecond();
LOG(Message) << "Found w vectors " << i <<" .. " << i+N_ii-1 << std::endl;
LOG(Message) << "Found v vectors " << j <<" .. " << j+N_jj-1 << std::endl;
LOG(Message) << "Meson field block "
<< j/schurBlock + NBlock_j*i/schurBlock + 1
<< "/" << NBlock_i*NBlock_j << " [" << i <<" .. "
<< i+N_ii-1 << ", " << j <<" .. " << j+N_jj-1 << "]"
<< std::endl;
///////////////////////////////////////////////////////////////
// Series of cache blocked chunks of the contractions within this SchurBlock
@ -411,11 +390,11 @@ void TA2AMesonField<FImpl>::execute(void)
Eigen::Tensor<ComplexD,5> mesonFieldBlocked(nmom,ngamma,nt,N_iii,N_jjj);
t_contr-=usecond();
MesonField(mesonFieldBlocked, &w[ii], &v[jj], gammas, phases,Tp,
t_int_0,t_int_1,t_int_2,t_int_3);
MesonField(mesonFieldBlocked, &w[i+ii], &v[j+jj], gammas, phases,Tp,
t_int_0,t_int_1,t_int_2,t_int_3);
t_contr+=usecond();
// flops for general N_c & N_s
flops += vol * ( 2 * 8.0 + 6.0 + 8.0*nmom) * N_iii*N_jjj*ngamma;
bytes += vol * (12.0 * sizeof(Complex) ) * N_iii*N_jjj
+ vol * ( 2.0 * sizeof(Complex) *nmom ) * N_iii*N_jjj* ngamma;
@ -435,17 +414,17 @@ void TA2AMesonField<FImpl>::execute(void)
double nodes=grid->NodeCount();
double t1 = usecond();
LOG(Message) << " Contraction of MesonFields took "<<(t1-t0)/1.0e6<< " seconds " << std::endl;
LOG(Message) << " Schur "<<(t_schur)/1.0e6<< " seconds " << std::endl;
LOG(Message) << " Contr "<<(t_contr)/1.0e6<< " seconds " << std::endl;
LOG(Message) << " Intern0 "<<(t_int_0)/1.0e6<< " seconds " << std::endl;
LOG(Message) << " Intern1 "<<(t_int_1)/1.0e6<< " seconds " << std::endl;
LOG(Message) << " Intern2 "<<(t_int_2)/1.0e6<< " seconds " << std::endl;
LOG(Message) << " Intern3 "<<(t_int_3)/1.0e6<< " seconds " << std::endl;
LOG(Message) << "Contraction of MesonFields took "<<(t1-t0)/1.0e6<< " s" << std::endl;
LOG(Message) << " Schur " << (t_schur)/1.0e6 << " s" << std::endl;
LOG(Message) << " Contr " << (t_contr)/1.0e6 << " s" << std::endl;
LOG(Message) << " Intern0 " << (t_int_0)/1.0e6 << " s" << std::endl;
LOG(Message) << " Intern1 " << (t_int_1)/1.0e6 << " s" << std::endl;
LOG(Message) << " Intern2 " << (t_int_2)/1.0e6 << " s" << std::endl;
LOG(Message) << " Intern3 " << (t_int_3)/1.0e6 << " s" << std::endl;
double t_kernel = t_int_0 + t_int_1;
LOG(Message) << " Arith "<<flops/(t_kernel)/1.0e3/nodes<< " Gflop/s / node " << std::endl;
LOG(Message) << " Arith "<<bytes/(t_kernel)/1.0e3/nodes<< " GB/s /node " << std::endl;
LOG(Message) << " Arith " << flops/(t_kernel)/1.0e3/nodes << " Gflop/s/ node " << std::endl;
LOG(Message) << " Arith " << bytes/(t_kernel)/1.0e3/nodes << " GB/s/node " << std::endl;
/////////////////////////////////////////////////////////////////////////
// Test: Build the pion correlator (two end)
@ -453,8 +432,8 @@ void TA2AMesonField<FImpl>::execute(void)
/////////////////////////////////////////////////////////////////////////
std::vector<ComplexD> corr(nt,ComplexD(0.0));
for(int i=0;i<N;i++)
for(int j=0;j<N;j++)
for(int i=0;i<N_i;i++)
for(int j=0;j<N_j;j++)
{
int m=0; // first momentum
int g=0; // first gamma in above ordering is gamma5 for pion

View File

@ -6,13 +6,13 @@
#include <Grid/Hadrons/ModuleFactory.hpp>
#include <Grid/Hadrons/Solver.hpp>
#include <Grid/Hadrons/EigenPack.hpp>
#include <Grid/Hadrons/AllToAllVectors.hpp>
#include <Grid/Hadrons/A2AVectors.hpp>
#include <Grid/Hadrons/DilutedNoise.hpp>
BEGIN_HADRONS_NAMESPACE
/******************************************************************************
* A2AVectors *
* Create all-to-all vector class *
******************************************************************************/
BEGIN_MODULE_NAMESPACE(MSolver)
@ -21,7 +21,6 @@ class A2AVectorsPar: Serializable
public:
GRID_SERIALIZABLE_CLASS_MEMBERS(A2AVectorsPar,
bool, return_5d,
int, Nl,
std::string, noise,
std::string, action,
std::string, eigenPack,
@ -34,7 +33,7 @@ class TA2AVectors : public Module<A2AVectorsPar>
public:
FERM_TYPE_ALIASES(FImpl,);
SOLVER_TYPE_ALIASES(FImpl,);
typedef A2AModesSchurDiagTwo<FermionField, FMat, Solver> A2ABase;
typedef A2AVectorsSchurDiagTwo<FImpl> A2A;
public:
// constructor
TA2AVectors(const std::string name);
@ -42,12 +41,14 @@ public:
virtual ~TA2AVectors(void) {};
// dependency relation
virtual std::vector<std::string> getInput(void);
virtual std::vector<std::string> getReference(void);
virtual std::vector<std::string> getOutput(void);
// setup
virtual void setup(void);
// execution
virtual void execute(void);
private:
std::string solverName_;
unsigned int Nl_{0};
};
MODULE_REGISTER_TMP(A2AVectors,
@ -68,32 +69,24 @@ TA2AVectors<FImpl, Pack>::TA2AVectors(const std::string name)
template <typename FImpl, typename Pack>
std::vector<std::string> TA2AVectors<FImpl, Pack>::getInput(void)
{
int Nl = par().Nl;
std::string sub_string = "";
if (Nl > 0) sub_string = "_subtract";
std::string sub_string;
std::vector<std::string> in;
std::vector<std::string> in = {par().solver + sub_string, par().noise};
if (!par().eigenPack.empty())
{
in.push_back(par().eigenPack);
sub_string = (!par().eigenPack.empty()) ? "_subtract" : "";
}
in.push_back(par().solver + sub_string);
in.push_back(par().noise);
return in;
}
template <typename FImpl, typename Pack>
std::vector<std::string> TA2AVectors<FImpl, Pack>::getReference(void)
{
std::vector<std::string> ref = {par().action};
if (!par().eigenPack.empty())
{
ref.push_back(par().eigenPack);
}
return ref;
}
template <typename FImpl, typename Pack>
std::vector<std::string> TA2AVectors<FImpl, Pack>::getOutput(void)
{
std::vector<std::string> out = {getName()};
std::vector<std::string> out = {getName() + "_v", getName() + "_w"};
return out;
}
@ -102,102 +95,143 @@ std::vector<std::string> TA2AVectors<FImpl, Pack>::getOutput(void)
template <typename FImpl, typename Pack>
void TA2AVectors<FImpl, Pack>::setup(void)
{
int Nl = par().Nl;
bool return_5d = par().return_5d;
auto &noise = envGet(DilutedNoise<FImpl>, par().noise);
int Ls;
bool hasLowModes = (!par().eigenPack.empty());
std::string sub_string = (hasLowModes) ? "_subtract" : "";
bool return_5d = par().return_5d;
auto &noise = envGet(DilutedNoise<FImpl>, par().noise);
auto &action = envGet(FMat, par().action);
auto &solver = envGet(Solver, par().solver + sub_string);
int Ls = env().getObjectLs(par().action);
std::string sub_string = "";
if (Nl > 0) sub_string = "_subtract";
auto &solver = envGet(Solver, par().solver + sub_string);
Ls = env().getObjectLs(par().solver + sub_string);
auto &action = envGet(FMat, par().action);
envTmpLat(FermionField, "ferm_src", Ls);
envTmpLat(FermionField, "unphys_ferm", Ls);
envTmpLat(FermionField, "tmp");
std::vector<FermionField> *evec;
const std::vector<RealD> *eval;
if (Nl > 0)
LOG(Message) << "Creating all-to-all vectors ";
if (hasLowModes)
{
// Low modes
auto &epack = envGet(Pack, par().eigenPack);
LOG(Message) << "Creating a2a vectors " << getName() <<
" using eigenpack '" << par().eigenPack << "' ("
<< epack.evec.size() << " modes)" <<
" and " << noise.size() << " high modes." << std::endl;
evec = &epack.evec;
eval = &epack.eval;
Nl_ = epack.evec.size();
std::cout << " using eigenpack '" << par().eigenPack << "' ("
<< Nl_ << " low modes) and noise '"
<< par().noise << "' (" << noise.size()
<< " noise vectors)" << std::endl;
}
else
{
LOG(Message) << "Creating a2a vectors " << getName() <<
" using " << noise.size() << " high modes only." << std::endl;
std::cout << " using noise '" << par().noise << "' (" << noise.size()
<< " noise vectors)" << std::endl;
}
envCreate(A2ABase, getName(), Ls, evec, eval, action, solver, Nl, noise.size(),
return_5d);
envCreate(std::vector<FermionField>, getName() + "_v", 1,
Nl_ + noise.size(), FermionField(env().getGrid()));
envCreate(std::vector<FermionField>, getName() + "_w", 1,
Nl_ + noise.size(), FermionField(env().getGrid()));
if (Ls > 1)
{
envTmpLat(FermionField, "f5", Ls);
}
envTmp(A2A, "a2a", 1, action, solver);
}
// execution ///////////////////////////////////////////////////////////////////
template <typename FImpl, typename Pack>
void TA2AVectors<FImpl, Pack>::execute(void)
{
auto &action = envGet(FMat, par().action);
auto &noise = envGet(DilutedNoise<FImpl>, par().noise);
std::string sub_string = (Nl_ > 0) ? "_subtract" : "";
auto &action = envGet(FMat, par().action);
auto &solver = envGet(Solver, par().solver + sub_string);
auto &noise = envGet(DilutedNoise<FImpl>, par().noise);
auto &v = envGet(std::vector<FermionField>, getName() + "_v");
auto &w = envGet(std::vector<FermionField>, getName() + "_w");
int Ls = env().getObjectLs(par().action);
int Ls;
int Nl = par().Nl;
std::string sub_string = "";
if (Nl > 0) sub_string = "_subtract";
Ls = env().getObjectLs(par().solver + sub_string);
auto &a2areturn = envGet(A2ABase, getName());
// High modes
envGetTmp(FermionField, ferm_src);
envGetTmp(FermionField, unphys_ferm);
envGetTmp(FermionField, tmp);
for (unsigned int i = 0; i < noise.size(); i++)
envGetTmp(A2A, a2a);
// Low modes
for (unsigned int il = 0; il < Nl_; il++)
{
LOG(Message) << "A2A src for noise vector " << i << std::endl;
// source conversion for 4D sources
if (!env().isObject5d(par().noise))
auto &epack = envGet(Pack, par().eigenPack);
LOG(Message) << "V vector i = " << il << " (low mode)" << std::endl;
if (Ls == 1)
{
if (Ls == 1)
{
ferm_src = noise[i];
tmp = ferm_src;
}
else
{
tmp = noise[i];
action.ImportPhysicalFermionSource(noise[i], ferm_src);
action.ImportUnphysicalFermion(noise[i], unphys_ferm);
}
a2a.makeLowModeV(v[il], epack.evec[il], epack.eval[il]);
}
// source conversion for 5D sources
else
{
if (Ls != env().getObjectLs(par().noise))
{
HADRONS_ERROR(Size, "Ls mismatch between quark action and source");
}
else
{
ferm_src = noise[i];
action.ExportPhysicalFermionSolution(ferm_src, tmp);
unphys_ferm = ferm_src;
}
envGetTmp(FermionField, f5);
a2a.makeLowModeV5D(v[il], f5, epack.evec[il], epack.eval[il]);
}
LOG(Message) << "solveHighMode i = " << i << std::endl;
a2areturn.high_modes(ferm_src, unphys_ferm, tmp, i);
LOG(Message) << "W vector i = " << il << " (low mode)" << std::endl;
if (Ls == 1)
{
a2a.makeLowModeW(w[il], epack.evec[il], epack.eval[il]);
}
else
{
envGetTmp(FermionField, f5);
a2a.makeLowModeW5D(w[il], f5, epack.evec[il], epack.eval[il]);
}
}
// High modes
for (unsigned int ih = 0; ih < noise.size(); ih++)
{
LOG(Message) << "V vector i = " << Nl_ + ih
<< " (" << ((Nl_ > 0) ? "high " : "")
<< "stochastic mode)" << std::endl;
if (Ls == 1)
{
a2a.makeHighModeV(v[Nl_ + ih], noise[ih]);
}
else
{
envGetTmp(FermionField, f5);
a2a.makeHighModeV5D(v[Nl_ + ih], f5, noise[ih]);
std::cout << norm2(v[Nl_ + ih]) << std::endl;
}
LOG(Message) << "W vector i = " << Nl_ + ih
<< " (" << ((Nl_ > 0) ? "high " : "")
<< "stochastic mode)" << std::endl;
if (Ls == 1)
{
a2a.makeHighModeW(w[Nl_ + ih], noise[ih]);
}
else
{
envGetTmp(FermionField, f5);
a2a.makeHighModeW5D(w[Nl_ + ih], f5, noise[ih]);
std::cout << norm2(w[Nl_ + ih]) << std::endl;
}
}
// // source conversion for 4D sources
// if (!env().isObject5d(par().noise))
// {
// if (Ls == 1)
// {
// ferm_src = noise[ih];
// tmp = ferm_src;
// }
// else
// {
// tmp = noise[ih];
// action.ImportPhysicalFermionSource(noise[ih], ferm_src);
// action.ImportUnphysicalFermion(noise[ih], unphys_ferm);
// }
// }
// // source conversion for 5D sources
// else
// {
// if (Ls != env().getObjectLs(par().noise))
// {
// HADRONS_ERROR(Size, "Ls mismatch between quark action and source");
// }
// else
// {
// ferm_src = noise[ih];
// action.ExportPhysicalFermionSolution(ferm_src, tmp);
// unphys_ferm = ferm_src;
// }
// }
// a2a.high_modes(ih, ferm_src, unphys_ferm, tmp, solver);
}
END_MODULE_NAMESPACE