1
0
mirror of https://github.com/paboyle/Grid.git synced 2025-04-10 14:10:46 +01:00

Beautification

This commit is contained in:
Michael Marshall 2019-11-02 16:15:48 +00:00
parent 4bcdb4ff95
commit fcd90705bc
6 changed files with 588 additions and 597 deletions

View File

@ -41,33 +41,33 @@ BEGIN_HADRONS_NAMESPACE
BEGIN_MODULE_NAMESPACE(MDistil)
/******************************************************************************
Common elements for distillation
Distillation code that is common across modules
******************************************************************************/
struct DistilParameters: Serializable {
GRID_SERIALIZABLE_CLASS_MEMBERS(DistilParameters,
int, nnoise,
int, tsrc,
std::string, TI,
std::string, LI,
std::string, SI )
DistilParameters() = default;
template <class ReaderClass> DistilParameters(Reader<ReaderClass>& Reader){read(Reader,"Distil",*this);}
GRID_SERIALIZABLE_CLASS_MEMBERS(DistilParameters,
int, nnoise,
int, tsrc,
std::string, TI,
std::string, LI,
std::string, SI )
DistilParameters() = default;
template <class ReaderClass> DistilParameters(Reader<ReaderClass>& Reader){read(Reader,"Distil",*this);}
// Numeric parameter is allowed to be empty (in which case it = Default),
// but assert during setup() if specified but not numeric
// Numeric parameter is allowed to be empty (in which case it = Default),
// but assert during setup() if specified but not numeric
static int ParameterDefault( const std::string & s, int Default, bool bCalledFromSetup )
{
int i = Default;
if( s.length() > 0 ) {
std::istringstream ss( s );
ss >> i;
if( bCalledFromSetup )
assert( !ss.fail() && "Parameter should either be empty or integer" );
static int ParameterDefault( const std::string & s, int Default, bool bCalledFromSetup )
{
int i = Default;
if( s.length() > 0 ) {
std::istringstream ss( s );
ss >> i;
if( bCalledFromSetup )
assert( !ss.fail() && "Parameter should either be empty or integer" );
}
return i;
}
return i;
}
};
#define DISTIL_PARAMETERS_DEFINE( inSetup ) \
@ -88,54 +88,55 @@ const int Nt_inv{ full_tdil ? 1 : TI }
inline GridCartesian * MakeLowerDimGrid( GridCartesian * gridHD )
{
int nd{static_cast<int>(gridHD->_ndimension)};
Coordinate latt_size = gridHD->_gdimensions;
latt_size[nd-1] = 1;
Coordinate simd_layout = GridDefaultSimd(nd-1, vComplex::Nsimd());
simd_layout.push_back( 1 );
Coordinate mpi_layout = gridHD->_processors;
mpi_layout[nd-1] = 1;
GridCartesian * gridLD = new GridCartesian(latt_size,simd_layout,mpi_layout,*gridHD);
return gridLD;
int nd{static_cast<int>(gridHD->_ndimension)};
Coordinate latt_size = gridHD->_gdimensions;
latt_size[nd-1] = 1;
Coordinate simd_layout = GridDefaultSimd(nd-1, vComplex::Nsimd());
simd_layout.push_back( 1 );
Coordinate mpi_layout = gridHD->_processors;
mpi_layout[nd-1] = 1;
GridCartesian * gridLD = new GridCartesian(latt_size,simd_layout,mpi_layout,*gridHD);
return gridLD;
}
/*************************************************************************************
Rotate eigenvectors into our phase convention
First component of first eigenvector is real and positive
TODO: Should this be in Distil.hpp?
*************************************************************************************/
inline void RotateEigen(std::vector<LatticeColourVector> & evec)
{
ColourVector cv0;
auto grid = evec[0].Grid();
Coordinate siteFirst(grid->Nd(),0);
peekSite(cv0, evec[0], siteFirst);
Grid::Complex cplx0 = cv0()()(0);
if( cplx0.imag() == 0 )
std::cout << GridLogMessage << "RotateEigen() : Site 0 : " << cplx0 << " => already meets phase convention" << std::endl;
else {
const Real cplx0_mag = Grid::abs(cplx0);
ColourVector cv0;
auto grid = evec[0].Grid();
Coordinate siteFirst(grid->Nd(),0);
peekSite(cv0, evec[0], siteFirst);
Grid::Complex cplx0 = cv0()()(0);
if( cplx0.imag() == 0 )
std::cout << GridLogMessage << "RotateEigen() : Site 0 : " << cplx0 << " => already meets phase convention" << std::endl;
else {
const Real cplx0_mag = Grid::abs(cplx0);
#ifdef GRID_NVCC
const Grid::Complex phase = thrust::conj(cplx0 / cplx0_mag);
const Real argphase = thrust::arg(phase);
const Grid::Complex phase = thrust::conj(cplx0 / cplx0_mag);
const Real argphase = thrust::arg(phase);
#else
const Grid::Complex phase = std::conj(cplx0 / cplx0_mag);
const Real argphase = std::arg(phase);
const Grid::Complex phase = std::conj(cplx0 / cplx0_mag);
const Real argphase = std::arg(phase);
#endif
std::cout << GridLogMessage << "RotateEigen() : Site 0 : |" << cplx0 << "|=" << cplx0_mag << " => phase=" << (argphase / 3.14159265) << " pi" << std::endl;
{
// TODO: Only really needed on the master slice
for( int k = 0 ; k < evec.size() ; k++ )
evec[k] *= phase;
if(grid->IsBoss()){
for( int c = 0 ; c < Nc ; c++ )
cv0()()(c) *= phase;
cplx0.imag(0); // This assumes phase convention is real, positive (so I get rid of rounding error)
//pokeSite(cv0, evec[0], siteFirst);
pokeLocalSite(cv0, evec[0], siteFirst);
}
std::cout << GridLogMessage << "RotateEigen() : Site 0 : |" << cplx0 << "|=" << cplx0_mag << " => phase=" << (argphase / 3.14159265) << " pi" << std::endl;
{
// TODO: Only really needed on the master slice
for( int k = 0 ; k < evec.size() ; k++ )
evec[k] *= phase;
if(grid->IsBoss()){
for( int c = 0 ; c < Nc ; c++ )
cv0()()(c) *= phase;
cplx0.imag(0); // This assumes phase convention is real, positive (so I get rid of rounding error)
//pokeSite(cv0, evec[0], siteFirst);
pokeLocalSite(cv0, evec[0], siteFirst);
}
}
}
}
}
END_MODULE_NAMESPACE

View File

@ -43,47 +43,47 @@ BEGIN_MODULE_NAMESPACE(MDistil)
class DistilVectorsPar: Serializable
{
public:
GRID_SERIALIZABLE_CLASS_MEMBERS(DistilVectorsPar,
std::string, noise,
std::string, perambulator,
std::string, lapevec,
std::string, source,
std::string, sink,
int, tsrc,
std::string, nvec,
std::string, TI)
GRID_SERIALIZABLE_CLASS_MEMBERS(DistilVectorsPar,
std::string, noise,
std::string, perambulator,
std::string, lapevec,
std::string, source,
std::string, sink,
int, tsrc,
std::string, nvec,
std::string, TI)
};
template <typename FImpl>
class TDistilVectors: public Module<DistilVectorsPar>
{
public:
FERM_TYPE_ALIASES(FImpl,);
// constructor
TDistilVectors(const std::string name);
// destructor
virtual ~TDistilVectors(void);
// dependency relation
virtual std::vector<std::string> getInput(void);
virtual std::vector<std::string> getOutput(void);
// setup
virtual void setup(void);
// execution
virtual void execute(void);
FERM_TYPE_ALIASES(FImpl,);
// constructor
TDistilVectors(const std::string name);
// destructor
virtual ~TDistilVectors(void);
// dependency relation
virtual std::vector<std::string> getInput(void);
virtual std::vector<std::string> getOutput(void);
// setup
virtual void setup(void);
// execution
virtual void execute(void);
protected:
// These variables are created in setup() and freed in Cleanup()
GridCartesian * grid3d; // Owned by me, so I must delete it
GridCartesian * grid4d; // Owned by environment (so I won't delete it)
virtual void Cleanup(void);
// These variables are created in setup() and freed in Cleanup()
GridCartesian * grid3d; // Owned by me, so I must delete it
GridCartesian * grid4d; // Owned by environment (so I won't delete it)
virtual void Cleanup(void);
public:
// These variables contain parameters
std::string PerambulatorName;
std::string NoiseVectorName;
std::string LapEvecName;
bool bMakeSource;
bool bMakeSink;
std::string SourceName;
std::string SinkName;
// These variables contain parameters
std::string PerambulatorName;
std::string NoiseVectorName;
std::string LapEvecName;
bool bMakeSource;
bool bMakeSink;
std::string SourceName;
std::string SinkName;
};
MODULE_REGISTER_TMP(DistilVectors, TDistilVectors<FIMPL>, MDistil);
@ -100,193 +100,196 @@ TDistilVectors<FImpl>::TDistilVectors(const std::string name)
template <typename FImpl>
TDistilVectors<FImpl>::~TDistilVectors(void)
{
Cleanup();
Cleanup();
};
// dependencies/products ///////////////////////////////////////////////////////
template <typename FImpl>
std::vector<std::string> TDistilVectors<FImpl>::getInput(void)
{
PerambulatorName = par().perambulator;
if( PerambulatorName.size() == 0 ) {
PerambulatorName = getName();
PerambulatorName.append( "_peramb" );
}
NoiseVectorName = par().noise;
if( NoiseVectorName.size() == 0 ) {
NoiseVectorName = PerambulatorName;
NoiseVectorName.append( "_noise" );
}
LapEvecName = par().lapevec;
if( LapEvecName.size() == 0 ) {
LapEvecName = PerambulatorName;
LapEvecName.append( "_lapevec" );
}
return { PerambulatorName, NoiseVectorName, LapEvecName };
PerambulatorName = par().perambulator;
if (PerambulatorName.empty())
{
PerambulatorName = getName();
PerambulatorName.append("_peramb");
}
NoiseVectorName = par().noise;
if (NoiseVectorName.empty())
{
NoiseVectorName = PerambulatorName;
NoiseVectorName.append("_noise");
}
LapEvecName = par().lapevec;
if (LapEvecName.empty())
{
LapEvecName = PerambulatorName;
LapEvecName.append("_lapevec");
}
return { PerambulatorName, NoiseVectorName, LapEvecName };
}
template <typename FImpl>
std::vector<std::string> TDistilVectors<FImpl>::getOutput(void)
{
SourceName = par().source;
SinkName = par().sink;
bMakeSource = ( SourceName.size() > 0 );
bMakeSink = ( SinkName.size() > 0 );
if( !bMakeSource && !bMakeSink ) {
SourceName = getName();
SinkName = SourceName;
SourceName.append( "_rho" );
SinkName.append( "_phi" );
bMakeSource = true;
bMakeSink = true;
}
std::vector<std::string> out;
if( bMakeSource )
out.push_back( SourceName );
if( bMakeSink )
out.push_back( SinkName );
return out;
SourceName = par().source;
SinkName = par().sink;
bMakeSource = ( SourceName.size() > 0 );
bMakeSink = ( SinkName.size() > 0 );
if (!bMakeSource && !bMakeSink)
{
SourceName = getName();
SinkName = SourceName;
SourceName.append("_rho");
SinkName.append("_phi");
bMakeSource = true;
bMakeSink = true;
}
std::vector<std::string> out;
if (bMakeSource)
out.push_back(SourceName);
if (bMakeSink)
out.push_back(SinkName);
return out;
}
// setup ///////////////////////////////////////////////////////////////////////
template <typename FImpl>
void TDistilVectors<FImpl>::setup(void)
{
Cleanup();
auto &noise = envGet(NoiseTensor, NoiseVectorName);
auto &perambulator = envGet(PerambTensor, PerambulatorName);
Cleanup();
auto &noise = envGet(NoiseTensor, NoiseVectorName);
auto &perambulator = envGet(PerambTensor, PerambulatorName);
// We expect the perambulator to have been created with these indices
assert( perambulator.ValidateIndexNames() && "Perambulator index names bad" );
// We expect the perambulator to have been created with these indices
assert( perambulator.ValidateIndexNames() && "Perambulator index names bad" );
const int Nt{ env().getDim(Tdir) };
assert( Nt == static_cast<int>( perambulator.tensor.dimension(0) ) && "PerambTensor time dimensionality bad" );
const int TI{ Hadrons::MDistil::DistilParameters::ParameterDefault( par().TI, Nt, true) };
const int LI{ static_cast<int>( perambulator.tensor.dimension(2) ) };
const int SI{ static_cast<int>( perambulator.tensor.dimension(5) ) };
const int Nt_inv{ static_cast<int>( perambulator.tensor.dimension(4) ) };
const int nnoise{ static_cast<int>( perambulator.tensor.dimension(3) ) };
assert( nnoise >= static_cast<int>( noise.dimension(0) ) && "Not enough noise vectors for perambulator" );
// Nvec defaults to what's in the perambulator unless overriden
const int nvec_per{ static_cast<int>( perambulator.tensor.dimension(1) ) };
const int nvec{Hadrons::MDistil::DistilParameters::ParameterDefault(par().nvec, nvec_per, true) };
assert( nvec <= nvec_per && "Not enough distillation sub-space vectors" );
const int Nt{ env().getDim(Tdir) };
assert( Nt == static_cast<int>( perambulator.tensor.dimension(0) ) && "PerambTensor time dimensionality bad" );
const int LI{ static_cast<int>( perambulator.tensor.dimension(2) ) };
const int SI{ static_cast<int>( perambulator.tensor.dimension(5) ) };
const int Nt_inv{ static_cast<int>( perambulator.tensor.dimension(4) ) };
const int nnoise{ static_cast<int>( perambulator.tensor.dimension(3) ) };
assert( nnoise >= static_cast<int>( noise.dimension(0) ) && "Not enough noise vectors for perambulator" );
// Nvec defaults to what's in the perambulator unless overriden
const int nvec_per{ static_cast<int>( perambulator.tensor.dimension(1) ) };
const int nvec{Hadrons::MDistil::DistilParameters::ParameterDefault(par().nvec, nvec_per, true) };
assert( nvec <= nvec_per && "Not enough distillation sub-space vectors" );
if( bMakeSource )
envCreate(std::vector<FermionField>, SourceName, 1, nnoise*LI*SI*Nt_inv, envGetGrid(FermionField));
if( bMakeSink )
envCreate(std::vector<FermionField>, SinkName, 1, nnoise*LI*SI*Nt_inv, envGetGrid(FermionField));
if (bMakeSource)
envCreate(std::vector<FermionField>, SourceName, 1, nnoise*LI*SI*Nt_inv, envGetGrid(FermionField));
if (bMakeSink)
envCreate(std::vector<FermionField>, SinkName, 1, nnoise*LI*SI*Nt_inv, envGetGrid(FermionField));
grid4d = env().getGrid();
Coordinate latt_size = GridDefaultLatt();
Coordinate simd_layout = GridDefaultSimd(Nd, vComplex::Nsimd());
Coordinate mpi_layout = GridDefaultMpi();
Coordinate simd_layout_3 = GridDefaultSimd(Nd-1, vComplex::Nsimd());
latt_size[Nd-1] = 1;
simd_layout_3.push_back( 1 );
mpi_layout[Nd-1] = 1;
grid3d = MakeLowerDimGrid(grid4d);
grid4d = env().getGrid();
Coordinate latt_size = GridDefaultLatt();
Coordinate mpi_layout = GridDefaultMpi();
Coordinate simd_layout_3 = GridDefaultSimd(Nd-1, vComplex::Nsimd());
latt_size[Nd-1] = 1;
simd_layout_3.push_back( 1 );
mpi_layout[Nd-1] = 1;
grid3d = MakeLowerDimGrid(grid4d);
envTmp(LatticeSpinColourVector, "tmp2",1,LatticeSpinColourVector(grid4d));
envTmp(LatticeSpinColourVector, "tmp3d",1,LatticeSpinColourVector(grid3d));
envTmp(LatticeColourVector, "tmp3d_nospin",1,LatticeColourVector(grid3d));
envTmp(LatticeSpinColourVector, "sink_tslice",1,LatticeSpinColourVector(grid3d));
envTmp(LatticeColourVector, "evec3d",1,LatticeColourVector(grid3d));
envTmp(LatticeSpinColourVector, "tmp2",1,LatticeSpinColourVector(grid4d));
envTmp(LatticeSpinColourVector, "tmp3d",1,LatticeSpinColourVector(grid3d));
envTmp(LatticeColourVector, "tmp3d_nospin",1,LatticeColourVector(grid3d));
envTmp(LatticeSpinColourVector, "sink_tslice",1,LatticeSpinColourVector(grid3d));
envTmp(LatticeColourVector, "evec3d",1,LatticeColourVector(grid3d));
}
// clean up any temporaries created by setup (that aren't stored in the environment)
template <typename FImpl>
void TDistilVectors<FImpl>::Cleanup(void)
{
if( grid3d != nullptr ) {
delete grid3d;
grid3d = nullptr;
}
grid4d = nullptr;
if ( grid3d != nullptr)
{
delete grid3d;
grid3d = nullptr;
}
grid4d = nullptr;
}
// execution ///////////////////////////////////////////////////////////////////
template <typename FImpl>
void TDistilVectors<FImpl>::execute(void)
{
auto &noise = envGet(NoiseTensor, NoiseVectorName);
auto &perambulator = envGet(PerambTensor, PerambulatorName);
auto &epack = envGet(Grid::Hadrons::EigenPack<LatticeColourVector>, LapEvecName);
auto &noise = envGet(NoiseTensor, NoiseVectorName);
auto &perambulator = envGet(PerambTensor, PerambulatorName);
auto &epack = envGet(Grid::Hadrons::EigenPack<LatticeColourVector>, LapEvecName);
envGetTmp(LatticeSpinColourVector, tmp2);
envGetTmp(LatticeSpinColourVector, tmp3d);
envGetTmp(LatticeColourVector, tmp3d_nospin);
envGetTmp(LatticeSpinColourVector, sink_tslice);
envGetTmp(LatticeColourVector, evec3d);
envGetTmp(LatticeSpinColourVector, tmp2);
envGetTmp(LatticeSpinColourVector, tmp3d);
envGetTmp(LatticeColourVector, tmp3d_nospin);
envGetTmp(LatticeSpinColourVector, sink_tslice);
envGetTmp(LatticeColourVector, evec3d);
const int Ntlocal{ grid4d->LocalDimensions()[3] };
const int Ntfirst{ grid4d->LocalStarts()[3] };
const int Ntlocal{ grid4d->LocalDimensions()[3] };
const int Ntfirst{ grid4d->LocalStarts()[3] };
const int Nt{ env().getDim(Tdir) };
const int TI{ Hadrons::MDistil::DistilParameters::ParameterDefault( par().TI, Nt, false ) };
const int LI{ static_cast<int>( perambulator.tensor.dimension(2) ) };
const int SI{ static_cast<int>( perambulator.tensor.dimension(5) ) };
const int Nt_inv{ static_cast<int>( perambulator.tensor.dimension(4) ) };
const int nnoise{ static_cast<int>( perambulator.tensor.dimension(3) ) };
// Nvec defaults to what's in the perambulator unless overriden
const int nvec{Hadrons::MDistil::DistilParameters::ParameterDefault(par().nvec, static_cast<int>( perambulator.tensor.dimension(1) ), false)};
const int tsrc{ par().tsrc };
const bool full_tdil{ TI==Nt };
const int Nt{ env().getDim(Tdir) };
const int TI{ Hadrons::MDistil::DistilParameters::ParameterDefault( par().TI, Nt, false ) };
const int LI{ static_cast<int>( perambulator.tensor.dimension(2) ) };
const int SI{ static_cast<int>( perambulator.tensor.dimension(5) ) };
const int Nt_inv{ static_cast<int>( perambulator.tensor.dimension(4) ) };
const int nnoise{ static_cast<int>( perambulator.tensor.dimension(3) ) };
// Nvec defaults to what's in the perambulator unless overriden
const int nvec{Hadrons::MDistil::DistilParameters::ParameterDefault(par().nvec, static_cast<int>( perambulator.tensor.dimension(1) ), false)};
const int tsrc{ par().tsrc };
const bool full_tdil{ TI==Nt };
int vecindex;
int t_inv;
if( bMakeSource ) {
auto &rho = envGet(std::vector<FermionField>, SourceName);
for( int inoise = 0; inoise < nnoise; inoise++ ) {
for( int dk = 0; dk < LI; dk++ ) {
for( int dt = 0; dt < Nt_inv; dt++ ) {
for( int ds = 0; ds < SI; ds++ ) {
vecindex = inoise + nnoise * dk + nnoise * LI * ds + nnoise *LI * SI*dt;
rho[vecindex] = 0;
tmp3d_nospin = 0;
for (int it = dt; it < Nt; it += TI){
if (full_tdil) t_inv = tsrc; else t_inv = it;
if( t_inv >= Ntfirst && t_inv < Ntfirst + Ntlocal ) {
for (int ik = dk; ik < nvec; ik += LI){
for (int is = ds; is < Ns; is += SI){
ExtractSliceLocal(evec3d,epack.evec[ik],0,t_inv-Ntfirst,Tdir);
tmp3d_nospin = evec3d * noise(inoise, t_inv, ik, is);
tmp3d=0;
pokeSpin(tmp3d,tmp3d_nospin,is);
tmp2=0;
InsertSliceLocal(tmp3d,tmp2,0,t_inv-Ntfirst,Tdir);
rho[vecindex] += tmp2;
}
int vecindex;
int t_inv;
if (bMakeSource)
{
auto &rho = envGet(std::vector<FermionField>, SourceName);
for (int inoise = 0; inoise < nnoise; inoise++) {
for (int dk = 0; dk < LI; dk++) {
for (int dt = 0; dt < Nt_inv; dt++) {
for (int ds = 0; ds < SI; ds++) {
vecindex = inoise + nnoise * dk + nnoise * LI * ds + nnoise *LI * SI*dt;
rho[vecindex] = 0;
tmp3d_nospin = 0;
for (int it = dt; it < Nt; it += TI){
if (full_tdil) t_inv = tsrc; else t_inv = it;
if (t_inv >= Ntfirst && t_inv < Ntfirst + Ntlocal) {
for (int ik = dk; ik < nvec; ik += LI){
for (int is = ds; is < Ns; is += SI){
ExtractSliceLocal(evec3d,epack.evec[ik],0,t_inv-Ntfirst,Tdir);
tmp3d_nospin = evec3d * noise(inoise, t_inv, ik, is);
tmp3d=0;
pokeSpin(tmp3d,tmp3d_nospin,is);
tmp2=0;
InsertSliceLocal(tmp3d,tmp2,0,t_inv-Ntfirst,Tdir);
rho[vecindex] += tmp2;
}
}
}
}
}
}
}
}
}
}
}
}
}
if( bMakeSink ) {
auto &phi = envGet(std::vector<FermionField>, SinkName);
for( int inoise = 0; inoise < nnoise; inoise++ ) {
for( int dk = 0; dk < LI; dk++ ) {
for( int dt = 0; dt < Nt_inv; dt++ ) {
for( int ds = 0; ds < SI; ds++ ) {
vecindex = inoise + nnoise * dk + nnoise * LI * ds + nnoise *LI * SI*dt;
phi[vecindex] = 0;
for (int t = Ntfirst; t < Ntfirst + Ntlocal; t++) {
sink_tslice=0;
for (int ivec = 0; ivec < nvec; ivec++) {
ExtractSliceLocal(evec3d,epack.evec[ivec],0,t-Ntfirst,Tdir);
sink_tslice += evec3d * perambulator.tensor(t, ivec, dk, inoise,dt,ds);
}
InsertSliceLocal(sink_tslice,phi[vecindex],0,t-Ntfirst,Tdir);
if (bMakeSink) {
auto &phi = envGet(std::vector<FermionField>, SinkName);
for (int inoise = 0; inoise < nnoise; inoise++) {
for (int dk = 0; dk < LI; dk++) {
for (int dt = 0; dt < Nt_inv; dt++) {
for (int ds = 0; ds < SI; ds++) {
vecindex = inoise + nnoise * dk + nnoise * LI * ds + nnoise *LI * SI*dt;
phi[vecindex] = 0;
for (int t = Ntfirst; t < Ntfirst + Ntlocal; t++) {
sink_tslice=0;
for (int ivec = 0; ivec < nvec; ivec++) {
ExtractSliceLocal(evec3d,epack.evec[ivec],0,t-Ntfirst,Tdir);
sink_tslice += evec3d * perambulator.tensor(t, ivec, dk, inoise,dt,ds);
}
InsertSliceLocal(sink_tslice,phi[vecindex],0,t-Ntfirst,Tdir);
}
}
}
}
}
}
}
}
}
}
END_MODULE_NAMESPACE

View File

@ -42,42 +42,42 @@ BEGIN_MODULE_NAMESPACE(MDistil)
******************************************************************************/
struct StoutParameters: Serializable {
GRID_SERIALIZABLE_CLASS_MEMBERS(StoutParameters,
int, steps,
double, rho)
StoutParameters() = default;
template <class ReaderClass> StoutParameters(Reader<ReaderClass>& Reader){read(Reader,"StoutSmearing",*this);}
GRID_SERIALIZABLE_CLASS_MEMBERS(StoutParameters,
int, steps,
double, rho)
StoutParameters() = default;
template <class ReaderClass> StoutParameters(Reader<ReaderClass>& Reader){read(Reader,"StoutSmearing",*this);}
};
struct ChebyshevParameters: Serializable {
GRID_SERIALIZABLE_CLASS_MEMBERS(ChebyshevParameters,
int, PolyOrder,
double, alpha,
double, beta)
ChebyshevParameters() = default;
template <class ReaderClass> ChebyshevParameters(Reader<ReaderClass>& Reader){read(Reader,"Chebyshev",*this);}
GRID_SERIALIZABLE_CLASS_MEMBERS(ChebyshevParameters,
int, PolyOrder,
double, alpha,
double, beta)
ChebyshevParameters() = default;
template <class ReaderClass> ChebyshevParameters(Reader<ReaderClass>& Reader){read(Reader,"Chebyshev",*this);}
};
struct LanczosParameters: Serializable {
GRID_SERIALIZABLE_CLASS_MEMBERS(LanczosParameters,
int, Nvec,
int, Nk,
int, Np,
int, MaxIt,
double, resid,
int, IRLLog)
LanczosParameters() = default;
template <class ReaderClass> LanczosParameters(Reader<ReaderClass>& Reader){read(Reader,"Lanczos",*this);}
GRID_SERIALIZABLE_CLASS_MEMBERS(LanczosParameters,
int, Nvec,
int, Nk,
int, Np,
int, MaxIt,
double, resid,
int, IRLLog)
LanczosParameters() = default;
template <class ReaderClass> LanczosParameters(Reader<ReaderClass>& Reader){read(Reader,"Lanczos",*this);}
};
// These are the actual parameters passed to the module during construction
struct LapEvecPar: Serializable {
GRID_SERIALIZABLE_CLASS_MEMBERS(LapEvecPar
,std::string, gauge
,StoutParameters, Stout
,ChebyshevParameters, Cheby
,LanczosParameters, Lanczos)
GRID_SERIALIZABLE_CLASS_MEMBERS(LapEvecPar
,std::string, gauge
,StoutParameters, Stout
,ChebyshevParameters, Cheby
,LanczosParameters, Lanczos)
};
/******************************************************************************
@ -90,25 +90,25 @@ template <typename GImpl>
class TLapEvec: public Module<LapEvecPar>
{
public:
GAUGE_TYPE_ALIASES(GImpl,);
// constructor
TLapEvec(const std::string name);
// destructor
virtual ~TLapEvec(void);
// dependency relation
virtual std::vector<std::string> getInput(void);
virtual std::vector<std::string> getOutput(void);
// setup
virtual void setup(void);
// execution
virtual void execute(void);
GAUGE_TYPE_ALIASES(GImpl,);
// constructor
TLapEvec(const std::string name);
// destructor
virtual ~TLapEvec(void);
// dependency relation
virtual std::vector<std::string> getInput(void);
virtual std::vector<std::string> getOutput(void);
// setup
virtual void setup(void);
// execution
virtual void execute(void);
protected:
// These variables are created in setup() and freed in Cleanup()
GridCartesian * gridLD; // Owned by me, so I must delete it
GridCartesian * gridHD; // Owned by environment (so I won't delete it)
std::string sGaugeName;
// These variables are created in setup() and freed in Cleanup()
GridCartesian * gridLD; // Owned by me, so I must delete it
GridCartesian * gridHD; // Owned by environment (so I won't delete it)
std::string sGaugeName;
protected:
virtual void Cleanup(void);
virtual void Cleanup(void);
};
MODULE_REGISTER_TMP(LapEvec, TLapEvec<GIMPL>, MDistil);
@ -127,19 +127,20 @@ TLapEvec<GImpl>::TLapEvec(const std::string name) : gridLD{nullptr}, Module<LapE
template <typename GImpl>
TLapEvec<GImpl>::~TLapEvec()
{
Cleanup();
Cleanup();
}
// dependencies/products ///////////////////////////////////////////////////////
template <typename GImpl>
std::vector<std::string> TLapEvec<GImpl>::getInput(void)
{
sGaugeName = par().gauge;
if( sGaugeName.size() == 0 ) {
sGaugeName = getName();
sGaugeName.append( "_gauge" );
}
return std::vector<std::string>{ sGaugeName };
sGaugeName = par().gauge;
if (sGaugeName.empty())
{
sGaugeName = getName();
sGaugeName.append( "_gauge" );
}
return std::vector<std::string>{ sGaugeName };
}
template <typename GImpl>
@ -153,30 +154,31 @@ std::vector<std::string> TLapEvec<GImpl>::getOutput(void)
template <typename GImpl>
void TLapEvec<GImpl>::setup(void)
{
Cleanup();
Environment & e{env()};
gridHD = e.getGrid();
gridLD = MakeLowerDimGrid( gridHD );
const int Ntlocal{gridHD->LocalDimensions()[Tdir]};
// Temporaries
envTmpLat(GaugeField, "Umu_stout");
envTmpLat(GaugeField, "Umu_smear");
envTmp(LatticeGaugeField, "UmuNoTime",1,LatticeGaugeField(gridLD));
envTmp(LatticeColourVector, "src",1,LatticeColourVector(gridLD));
envTmp(std::vector<LapEvecs>, "eig",1,std::vector<LapEvecs>(Ntlocal));
// Output objects
envCreate(LapEvecs, getName(), 1, par().Lanczos.Nvec, gridHD );
Cleanup();
Environment & e{env()};
gridHD = e.getGrid();
gridLD = MakeLowerDimGrid( gridHD );
const int Ntlocal{gridHD->LocalDimensions()[Tdir]};
// Temporaries
envTmpLat(GaugeField, "Umu_stout");
envTmpLat(GaugeField, "Umu_smear");
envTmp(LatticeGaugeField, "UmuNoTime",1,LatticeGaugeField(gridLD));
envTmp(LatticeColourVector, "src",1,LatticeColourVector(gridLD));
envTmp(std::vector<LapEvecs>, "eig",1,std::vector<LapEvecs>(Ntlocal));
// Output objects
envCreate(LapEvecs, getName(), 1, par().Lanczos.Nvec, gridHD );
}
// clean up any temporaries created by setup (that aren't stored in the environment)
template <typename GImpl>
void TLapEvec<GImpl>::Cleanup(void)
{
if( gridLD != nullptr ) {
delete gridLD;
gridLD = nullptr;
}
gridHD = nullptr;
if (gridLD != nullptr)
{
delete gridLD;
gridLD = nullptr;
}
gridHD = nullptr;
}
/*************************************************************************************
@ -189,55 +191,52 @@ void TLapEvec<GImpl>::Cleanup(void)
template<typename Field, typename GaugeField=LatticeGaugeField>
class Laplacian3D : public LinearOperatorBase<Field>, public LinearFunction<Field> {
typedef typename GaugeField::vector_type vCoeff_t;
protected: // I don't really mind if _gf is messed with ... so make this public?
//GaugeField & _gf;
int nd; // number of spatial dimensions
std::vector<Lattice<iColourMatrix<vCoeff_t> > > U;
public:
// Construct this operator given a gauge field and the number of dimensions it should act on
Laplacian3D( GaugeField& gf, int dimSpatial = Tdir ) : /*_gf(gf),*/ nd{dimSpatial} {
assert(dimSpatial>=1);
for( int mu = 0 ; mu < nd ; mu++ )
U.push_back(PeekIndex<LorentzIndex>(gf,mu));
}
// Apply this operator to "in", return result in "out"
void operator()(const Field& in, Field& out) {
assert( nd <= in.Grid()->Nd() );
conformable( in, out );
out = ( ( Real ) ( 2 * nd ) ) * in;
Field _tmp(in.Grid());
typedef typename GaugeField::vector_type vCoeff_t;
//Lattice<iColourMatrix<vCoeff_t> > U(in.Grid());
for( int mu = 0 ; mu < nd ; mu++ ) {
//U = PeekIndex<LorentzIndex>(_gf,mu);
out -= U[mu] * Cshift( in, mu, 1);
_tmp = adj( U[mu] ) * in;
out -= Cshift(_tmp,mu,-1);
public:
int nd; // number of spatial dimensions
std::vector<Lattice<iColourMatrix<vCoeff_t> > > U;
// Construct this operator given a gauge field and the number of dimensions it should act on
Laplacian3D( GaugeField& gf, int dimSpatial = Tdir ) : nd{dimSpatial}
{
assert(dimSpatial>=1);
for (int mu = 0 ; mu < nd ; mu++)
U.push_back(PeekIndex<LorentzIndex>(gf,mu));
}
}
void OpDiag (const Field &in, Field &out) { assert(0); };
void OpDir (const Field &in, Field &out,int dir,int disp) { assert(0); };
void Op (const Field &in, Field &out) { assert(0); };
void AdjOp (const Field &in, Field &out) { assert(0); };
void HermOpAndNorm(const Field &in, Field &out,RealD &n1,RealD &n2) { assert(0); };
void HermOp(const Field &in, Field &out) { operator()(in,out); };
// Apply this operator to "in", return result in "out"
void operator()(const Field& in, Field& out) {
assert( nd <= in.Grid()->Nd() );
conformable( in, out );
out = ( ( Real ) ( 2 * nd ) ) * in;
Field _tmp(in.Grid());
typedef typename GaugeField::vector_type vCoeff_t;
for (int mu = 0 ; mu < nd ; mu++)
{
out -= U[mu] * Cshift( in, mu, 1);
_tmp = adj( U[mu] ) * in;
out -= Cshift(_tmp,mu,-1);
}
}
void OpDiag (const Field &in, Field &out) { assert(0); };
void OpDir (const Field &in, Field &out,int dir,int disp) { assert(0); };
void Op (const Field &in, Field &out) { assert(0); };
void AdjOp (const Field &in, Field &out) { assert(0); };
void HermOpAndNorm(const Field &in, Field &out,RealD &n1,RealD &n2) { assert(0); };
void HermOp(const Field &in, Field &out) { operator()(in,out); };
};
template<typename Field>
class Laplacian3DHerm : public LinearFunction<Field> {
public:
OperatorFunction<Field> & _poly;
LinearOperatorBase<Field> &_Linop;
Laplacian3DHerm(OperatorFunction<Field> & poly,LinearOperatorBase<Field>& linop)
: _poly{poly}, _Linop{linop} {}
void operator()(const Field& in, Field& out) {
_poly(_Linop,in,out);
}
OperatorFunction<Field> & _poly;
LinearOperatorBase<Field> &_Linop;
Laplacian3DHerm(OperatorFunction<Field> & poly,LinearOperatorBase<Field>& linop)
: _poly{poly}, _Linop{linop} {}
void operator()(const Field& in, Field& out)
{
_poly(_Linop,in,out);
}
};
/******************************************************************************
@ -248,91 +247,93 @@ public:
template <typename GImpl>
void TLapEvec<GImpl>::execute(void)
{
const ChebyshevParameters &ChebPar{par().Cheby};
const LanczosParameters &LPar{par().Lanczos};
const ChebyshevParameters &ChebPar{par().Cheby};
const LanczosParameters &LPar{par().Lanczos};
// Disable IRL logging if requested
LOG(Message) << "IRLLog=" << LPar.IRLLog << std::endl;
const int PreviousIRLLogState{GridLogIRL.isActive()};
GridLogIRL.Active( LPar.IRLLog == 0 ? 0 : 1 );
// Disable IRL logging if requested
LOG(Message) << "IRLLog=" << LPar.IRLLog << std::endl;
const int PreviousIRLLogState{GridLogIRL.isActive()};
GridLogIRL.Active( LPar.IRLLog == 0 ? 0 : 1 );
// Stout smearing
envGetTmp(GaugeField, Umu_smear);
Umu_smear = envGet(GaugeField, sGaugeName); // The smeared field starts off as the Gauge field
LOG(Message) << "Initial plaquette: " << WilsonLoops<PeriodicGimplR>::avgPlaquette(Umu_smear) << std::endl;
const StoutParameters &Stout{par().Stout};
if( Stout.steps )
{
envGetTmp(GaugeField, Umu_stout);
Smear_Stout<PeriodicGimplR> LS(Stout.rho, Tdir); // spatial smearing only
for (int i = 0; i < Stout.steps; i++) {
LS.smear(Umu_stout, Umu_smear);
Umu_smear = Umu_stout;
// Stout smearing
envGetTmp(GaugeField, Umu_smear);
Umu_smear = envGet(GaugeField, sGaugeName); // The smeared field starts off as the Gauge field
LOG(Message) << "Initial plaquette: " << WilsonLoops<PeriodicGimplR>::avgPlaquette(Umu_smear) << std::endl;
const StoutParameters &Stout{par().Stout};
if( Stout.steps )
{
envGetTmp(GaugeField, Umu_stout);
Smear_Stout<PeriodicGimplR> LS(Stout.rho, Tdir); // spatial smearing only
for (int i = 0; i < Stout.steps; i++) {
LS.smear(Umu_stout, Umu_smear);
Umu_smear = Umu_stout;
}
LOG(Message) << "Smeared plaquette: " << WilsonLoops<PeriodicGimplR>::avgPlaquette(Umu_smear) << std::endl;
}
LOG(Message) << "Smeared plaquette: " << WilsonLoops<PeriodicGimplR>::avgPlaquette(Umu_smear) << std::endl;
}
////////////////////////////////////////////////////////////////////////
// Invert nabla operator separately on each time-slice
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
// Invert nabla operator separately on each time-slice
////////////////////////////////////////////////////////////////////////
auto & eig4d = envGet(LapEvecs, getName() );
envGetTmp(std::vector<LapEvecs>, eig); // Eigenpack for each timeslice
envGetTmp(LatticeGaugeField, UmuNoTime); // Gauge field without time dimension
envGetTmp(LatticeColourVector, src);
const int Ntlocal{gridHD->LocalDimensions()[Tdir]};
const int Ntfirst{gridHD->LocalStarts()[Tdir]};
uint32_t ConvergenceErrors{0};
for(int t = 0; t < Ntlocal; t++ ) {
LOG(Message) << "------------------------------------------------------------" << std::endl;
LOG(Message) << " Compute eigenpack, local timeslice = " << t << " / " << Ntlocal << std::endl;
LOG(Message) << "------------------------------------------------------------" << std::endl;
eig[t].resize(LPar.Nk+LPar.Np,gridLD);
auto & eig4d = envGet(LapEvecs, getName() );
envGetTmp(std::vector<LapEvecs>, eig); // Eigenpack for each timeslice
envGetTmp(LatticeGaugeField, UmuNoTime); // Gauge field without time dimension
envGetTmp(LatticeColourVector, src);
const int Ntlocal{gridHD->LocalDimensions()[Tdir]};
const int Ntfirst{gridHD->LocalStarts()[Tdir]};
uint32_t ConvergenceErrors{0};
for (int t = 0; t < Ntlocal; t++ )
{
LOG(Message) << "------------------------------------------------------------" << std::endl;
LOG(Message) << " Compute eigenpack, local timeslice = " << t << " / " << Ntlocal << std::endl;
LOG(Message) << "------------------------------------------------------------" << std::endl;
eig[t].resize(LPar.Nk+LPar.Np,gridLD);
// Construct smearing operator
ExtractSliceLocal(UmuNoTime,Umu_smear,0,t,Tdir); // switch to 3d/4d objects
Laplacian3D<LatticeColourVector> Nabla(UmuNoTime);
LOG(Debug) << "Chebyshev preconditioning to order " << ChebPar.PolyOrder
<< " with parameters (alpha,beta) = (" << ChebPar.alpha << "," << ChebPar.beta << ")" << std::endl;
Chebyshev<LatticeColourVector> Cheb(ChebPar.alpha,ChebPar.beta,ChebPar.PolyOrder);
// Construct smearing operator
ExtractSliceLocal(UmuNoTime,Umu_smear,0,t,Tdir); // switch to 3d/4d objects
Laplacian3D<LatticeColourVector> Nabla(UmuNoTime);
LOG(Message) << "Chebyshev preconditioning to order " << ChebPar.PolyOrder
<< " with parameters (alpha,beta) = (" << ChebPar.alpha << "," << ChebPar.beta << ")" << std::endl;
Chebyshev<LatticeColourVector> Cheb(ChebPar.alpha,ChebPar.beta,ChebPar.PolyOrder);
// Construct source vector according to Test_dwf_compressed_lanczos.cc
src = 11.0; //TODO: Why hard-coded 11?
RealD nn = norm2(src);
nn = Grid::sqrt(nn);
src = src * (1.0/nn);
// Construct source vector according to Test_dwf_compressed_lanczos.cc
src = 11.0; // NB: This is a dummy parameter and just needs to be non-zero
RealD nn = norm2(src);
nn = Grid::sqrt(nn);
src = src * (1.0/nn);
Laplacian3DHerm<LatticeColourVector> NablaCheby(Cheb,Nabla);
ImplicitlyRestartedLanczos<LatticeColourVector>
IRL(NablaCheby,Nabla,LPar.Nvec,LPar.Nk,LPar.Nk+LPar.Np,LPar.resid,LPar.MaxIt);
int Nconv = 0;
IRL.calc(eig[t].eval,eig[t].evec,src,Nconv);
if( Nconv < LPar.Nvec ) {
// NB: Can't assert here since we are processing local slices - i.e. not all nodes would assert
ConvergenceErrors = 1;
LOG(Error) << "MDistil::LapEvec : Not enough eigenvectors converged. If this occurs in practice, we should modify the eigensolver to iterate once more to ensure the second convergence test does not take us below the requested number of eigenvectors" << std::endl;
Laplacian3DHerm<LatticeColourVector> NablaCheby(Cheb,Nabla);
ImplicitlyRestartedLanczos<LatticeColourVector>
IRL(NablaCheby,Nabla,LPar.Nvec,LPar.Nk,LPar.Nk+LPar.Np,LPar.resid,LPar.MaxIt);
int Nconv = 0;
IRL.calc(eig[t].eval,eig[t].evec,src,Nconv);
if (Nconv < LPar.Nvec)
{
// NB: Can't assert here since we are processing local slices - i.e. not all nodes would assert
ConvergenceErrors = 1;
LOG(Error) << "MDistil::LapEvec : Not enough eigenvectors converged. If this occurs in practice, we should modify the eigensolver to iterate once more to ensure the second convergence test does not take us below the requested number of eigenvectors" << std::endl;
}
if( Nconv != LPar.Nvec )
eig[t].resize( LPar.Nvec, gridLD );
RotateEigen( eig[t].evec ); // Rotate the eigenvectors into our phase convention
for (int i=0;i<LPar.Nvec;i++){
InsertSliceLocal(eig[t].evec[i],eig4d.evec[i],0,t,Tdir);
if(t==0 && Ntfirst==0)
eig4d.eval[i] = eig[t].eval[i]; // TODO: Discuss: is this needed? Is there a better way?
}
}
if( Nconv != LPar.Nvec )
eig[t].resize( LPar.Nvec, gridLD );
RotateEigen( eig[t].evec ); // Rotate the eigenvectors into our phase convention
for (int i=0;i<LPar.Nvec;i++){
InsertSliceLocal(eig[t].evec[i],eig4d.evec[i],0,t,Tdir);
if(t==0 && Ntfirst==0)
eig4d.eval[i] = eig[t].eval[i]; // TODO: Discuss: is this needed? Is there a better way?
}
}
GridLogIRL.Active( PreviousIRLLogState );
gridHD->GlobalSum(ConvergenceErrors);
assert(ConvergenceErrors==0 && "The eingensolver failed to find enough eigenvectors on at least one node");
GridLogIRL.Active( PreviousIRLLogState );
gridHD->GlobalSum(ConvergenceErrors);
assert(ConvergenceErrors==0 && "The eingensolver failed to find enough eigenvectors on at least one node");
#if DEBUG
// Now write out the 4d eigenvectors
eig4d.record.operatorXml = "<OPERATOR>Distillation</OPERATOR>";
eig4d.record.solverXml = "<SOLVER>CG</SOLVER>";
std::string sEigenPackName(getName());
sEigenPackName.append(".");
sEigenPackName.append(std::to_string(vm().getTrajectory()));
eig4d.write(sEigenPackName,false);
// Now write out the 4d eigenvectors
eig4d.record.operatorXml = "<OPERATOR>Distillation</OPERATOR>";
eig4d.record.solverXml = "<SOLVER>CG</SOLVER>";
std::string sEigenPackName(getName());
sEigenPackName.append(".");
sEigenPackName.append(std::to_string(vm().getTrajectory()));
eig4d.write(sEigenPackName,false);
#endif
}

View File

@ -82,17 +82,13 @@ TNoises<FImpl>::TNoises(const std::string name)
template <typename FImpl>
std::vector<std::string> TNoises<FImpl>::getInput(void)
{
std::vector<std::string> in;
return in;
return {};
}
template <typename FImpl>
std::vector<std::string> TNoises<FImpl>::getOutput(void)
{
std::vector<std::string> out = {getName()};
return out;
return {getName()};
}
// setup ///////////////////////////////////////////////////////////////////////
@ -100,52 +96,49 @@ std::vector<std::string> TNoises<FImpl>::getOutput(void)
template <typename FImpl>
void TNoises<FImpl>::setup(void)
{
const int Nt{env().getDim(Tdir)};
const int nnoise{par().nnoise};
const int nvec{par().nvec};
const int TI{ Hadrons::MDistil::DistilParameters::ParameterDefault( par().TI, Nt, true) };
const int LI{ Hadrons::MDistil::DistilParameters::ParameterDefault( par().LI, nvec, true) };
envCreate(NoiseTensor, getName(), 1, nnoise, Nt, nvec, Ns);
const int Nt{env().getDim(Tdir)};
const int nnoise{par().nnoise};
const int nvec{par().nvec};
envCreate(NoiseTensor, getName(), 1, nnoise, Nt, nvec, Ns);
}
// execution ///////////////////////////////////////////////////////////////////
template <typename FImpl>
void TNoises<FImpl>::execute(void)
{
const int Nt{env().getDim(Tdir)};
const int nnoise{par().nnoise};
const int nvec{par().nvec};
const int TI{ Hadrons::MDistil::DistilParameters::ParameterDefault( par().TI, Nt, false) };
const int LI{ Hadrons::MDistil::DistilParameters::ParameterDefault( par().LI, nvec, false) };
const bool full_tdil{ TI == Nt }; \
const bool exact_distillation{ full_tdil && LI == nvec }; \
std::string UniqueIdentifier{par().UniqueIdentifier};
if( UniqueIdentifier.length() == 0 ) {
UniqueIdentifier = getName();
}
UniqueIdentifier.append( std::to_string( vm().getTrajectory() ) );
const int Nt{env().getDim(Tdir)};
const int nnoise{par().nnoise};
const int nvec{par().nvec};
const int TI{ Hadrons::MDistil::DistilParameters::ParameterDefault( par().TI, Nt, false) };
const int LI{ Hadrons::MDistil::DistilParameters::ParameterDefault( par().LI, nvec, false) };
const bool full_tdil{ TI == Nt }; \
const bool exact_distillation{ full_tdil && LI == nvec }; \
std::string UniqueIdentifier{par().UniqueIdentifier};
if (UniqueIdentifier.empty())
UniqueIdentifier = getName();
UniqueIdentifier.append( std::to_string( vm().getTrajectory() ) );
// We use our own seeds so we can specify different noises per quark
GridSerialRNG sRNG;
sRNG.SeedUniqueString(UniqueIdentifier);
Real rn;
auto &noise = envGet(NoiseTensor, getName());
for( int inoise = 0; inoise < nnoise; inoise++ ) {
for( int t = 0; t < Nt; t++ ) {
for( int ivec = 0; ivec < nvec; ivec++ ) {
for( int is = 0; is < Ns; is++ ) {
if( exact_distillation )
noise(inoise, t, ivec, is) = 1.;
else{
random(sRNG,rn);
// We could use a greater number of complex roots of unity
// ... but this seems to work well
noise(inoise, t, ivec, is) = (rn > 0.5) ? -1 : 1;
}
// We use our own seeds so we can specify different noises per quark
GridSerialRNG sRNG;
sRNG.SeedUniqueString(UniqueIdentifier);
Real rn;
auto &noise = envGet(NoiseTensor, getName());
for (int inoise = 0; inoise < nnoise; inoise++) {
for (int t = 0; t < Nt; t++) {
for (int ivec = 0; ivec < nvec; ivec++) {
for (int is = 0; is < Ns; is++) {
if (exact_distillation)
noise(inoise, t, ivec, is) = 1.;
else{
random(sRNG,rn);
// We could use a greater number of complex roots of unity
// ... but this seems to work well
noise(inoise, t, ivec, is) = (rn > 0.5) ? -1 : 1;
}
}
}
}
}
}
}
}
END_MODULE_NAMESPACE

View File

@ -69,10 +69,10 @@ public:
// execution
virtual void execute(void);
protected:
GridCartesian * grid3d; // Owned by me, so I must delete it
GridCartesian * grid4d;
GridCartesian * grid3d; // Owned by me, so I must delete it
GridCartesian * grid4d;
protected:
virtual void Cleanup(void);
virtual void Cleanup(void);
};
@ -90,100 +90,98 @@ TPerambFromSolve<FImpl>::TPerambFromSolve(const std::string name)
template <typename FImpl>
TPerambFromSolve<FImpl>::~TPerambFromSolve(void)
{
Cleanup();
Cleanup();
};
// dependencies/products ///////////////////////////////////////////////////////
template <typename FImpl>
std::vector<std::string> TPerambFromSolve<FImpl>::getInput(void)
{
return std::vector<std::string>{ par().solve, par().eigenPack };
return std::vector<std::string>{ par().solve, par().eigenPack };
}
template <typename FImpl>
std::vector<std::string> TPerambFromSolve<FImpl>::getOutput(void)
{
return std::vector<std::string>{ getName() };
return std::vector<std::string>{ getName() };
}
// setup ///////////////////////////////////////////////////////////////////////
template <typename FImpl>
void TPerambFromSolve<FImpl>::setup(void)
{
Cleanup();
DISTIL_PARAMETERS_DEFINE( true );
const int nvec_reduced{ Hadrons::MDistil::DistilParameters::ParameterDefault( par().nvec_reduced, nvec, true) };
const int LI_reduced{ Hadrons::MDistil::DistilParameters::ParameterDefault( par().LI_reduced, LI, true) };
grid4d = env().getGrid();
grid3d = MakeLowerDimGrid(grid4d);
envCreate(PerambTensor, getName(), 1, Nt,nvec_reduced,LI_reduced,nnoise,Nt_inv,SI);
envCreate(NoiseTensor, getName() + "_noise", 1, nnoise, Nt, nvec, Ns );
envTmp(LatticeColourVector, "result_3d",1,LatticeColourVector(grid3d));
envTmp(LatticeColourVector, "evec3d",1,LatticeColourVector(grid3d));
envTmpLat(LatticeColourVector, "result_nospin");
Cleanup();
DISTIL_PARAMETERS_DEFINE( true );
const int nvec_reduced{ Hadrons::MDistil::DistilParameters::ParameterDefault( par().nvec_reduced, nvec, true) };
const int LI_reduced{ Hadrons::MDistil::DistilParameters::ParameterDefault( par().LI_reduced, LI, true) };
grid4d = env().getGrid();
grid3d = MakeLowerDimGrid(grid4d);
envCreate(PerambTensor, getName(), 1, Nt,nvec_reduced,LI_reduced,nnoise,Nt_inv,SI);
envCreate(NoiseTensor, getName() + "_noise", 1, nnoise, Nt, nvec, Ns );
envTmp(LatticeColourVector, "result_3d",1,LatticeColourVector(grid3d));
envTmp(LatticeColourVector, "evec3d",1,LatticeColourVector(grid3d));
envTmpLat(LatticeColourVector, "result_nospin");
}
template <typename FImpl>
void TPerambFromSolve<FImpl>::Cleanup(void)
{
if( grid3d != nullptr ) {
delete grid3d;
grid3d = nullptr;
}
grid4d = nullptr;
if (grid3d != nullptr)
{
delete grid3d;
grid3d = nullptr;
}
grid4d = nullptr;
}
// execution ///////////////////////////////////////////////////////////////////
template <typename FImpl>
void TPerambFromSolve<FImpl>::execute(void)
{
GridCartesian * grid4d = env().getGrid();
const int Ntlocal{grid4d->LocalDimensions()[3]};
const int Ntfirst{grid4d->LocalStarts()[3]};
DISTIL_PARAMETERS_DEFINE( false );
const int nvec_reduced{ Hadrons::MDistil::DistilParameters::ParameterDefault( par().nvec_reduced, nvec, false) };
const int LI_reduced{ Hadrons::MDistil::DistilParameters::ParameterDefault( par().LI_reduced, LI, false) };
auto &perambulator = envGet(PerambTensor, getName());
auto &solve = envGet(std::vector<FermionField>, par().solve);
auto &epack = envGet(Grid::Hadrons::EigenPack<LatticeColourVector>, par().eigenPack);
GridCartesian * grid4d = env().getGrid();
const int Ntlocal{grid4d->LocalDimensions()[3]};
const int Ntfirst{grid4d->LocalStarts()[3]};
DISTIL_PARAMETERS_DEFINE( false );
const int nvec_reduced{ Hadrons::MDistil::DistilParameters::ParameterDefault( par().nvec_reduced, nvec, false) };
const int LI_reduced{ Hadrons::MDistil::DistilParameters::ParameterDefault( par().LI_reduced, LI, false) };
auto &perambulator = envGet(PerambTensor, getName());
auto &solve = envGet(std::vector<FermionField>, par().solve);
auto &epack = envGet(Grid::Hadrons::EigenPack<LatticeColourVector>, par().eigenPack);
envGetTmp(LatticeColourVector, result_nospin);
envGetTmp(LatticeColourVector, result_3d);
envGetTmp(LatticeColourVector, evec3d);
envGetTmp(LatticeColourVector, result_nospin);
envGetTmp(LatticeColourVector, result_3d);
envGetTmp(LatticeColourVector, evec3d);
for (int inoise = 0; inoise < nnoise; inoise++) {
for (int dk = 0; dk < LI_reduced; dk++) {
for (int dt = 0; dt < Nt_inv; dt++) {
for (int ds = 0; ds < SI; ds++) {
for (int is = 0; is < Ns; is++) {
result_nospin = peekSpin(solve[inoise+nnoise*(dk+LI*(dt+Nt_inv*ds))],is);
for (int t = Ntfirst; t < Ntfirst + Ntlocal; t++) {
ExtractSliceLocal(result_3d,result_nospin,0,t-Ntfirst,Tdir);
for (int ivec = 0; ivec < nvec_reduced; ivec++) {
ExtractSliceLocal(evec3d,epack.evec[ivec],0,t-Ntfirst,Tdir);
pokeSpin(perambulator.tensor(t, ivec, dk, inoise,dt,ds),static_cast<Complex>(innerProduct(evec3d, result_3d)),is);
LOG(Message) << "perambulator(t, ivec, dk, inoise,dt,ds)(is) = (" << t << "," << ivec << "," << dk << "," << inoise << "," << dt << "," << ds << ")(" << is << ") = " << perambulator.tensor(t, ivec, dk, inoise,dt,ds)()(is)() << std::endl;
}
for (int inoise = 0; inoise < nnoise; inoise++) {
for (int dk = 0; dk < LI_reduced; dk++) {
for (int dt = 0; dt < Nt_inv; dt++) {
for (int ds = 0; ds < SI; ds++) {
for (int is = 0; is < Ns; is++) {
result_nospin = peekSpin(solve[inoise+nnoise*(dk+LI*(dt+Nt_inv*ds))],is);
for (int t = Ntfirst; t < Ntfirst + Ntlocal; t++) {
ExtractSliceLocal(result_3d,result_nospin,0,t-Ntfirst,Tdir);
for (int ivec = 0; ivec < nvec_reduced; ivec++) {
ExtractSliceLocal(evec3d,epack.evec[ivec],0,t-Ntfirst,Tdir);
pokeSpin(perambulator.tensor(t, ivec, dk, inoise,dt,ds),static_cast<Complex>(innerProduct(evec3d, result_3d)),is);
LOG(Message) << "perambulator(t, ivec, dk, inoise,dt,ds)(is) = (" << t << "," << ivec << "," << dk << "," << inoise << "," << dt << "," << ds << ")(" << is << ") = " << perambulator.tensor(t, ivec, dk, inoise,dt,ds)()(is)() << std::endl;
}
}
}
}
}
}
}
}
}
}
if(grid4d->IsBoss()) {
std::string sPerambName{par().PerambFileName};
if( sPerambName.length() == 0 )
sPerambName = getName();
sPerambName.append( "." );
sPerambName.append( std::to_string(vm().getTrajectory()));
perambulator.write(sPerambName.c_str());
}
if(grid4d->IsBoss())
{
std::string sPerambName{par().PerambFileName};
if (sPerambName.empty())
sPerambName = getName();
sPerambName.append( "." );
sPerambName.append( std::to_string(vm().getTrajectory()));
perambulator.write(sPerambName.c_str());
}
}
END_MODULE_NAMESPACE
END_HADRONS_NAMESPACE
#endif // Hadrons_MDistil_PerambFromSolve_hpp_

View File

@ -126,7 +126,7 @@ void TPerambulator<FImpl>::setup(void)
grid3d = MakeLowerDimGrid(grid4d);
DISTIL_PARAMETERS_DEFINE( true );
const std::string UnsmearedSinkFileName{ par().UnsmearedSinkFileName };
if( !UnsmearedSinkFileName.empty() )
if (!UnsmearedSinkFileName.empty())
bool bMulti = ( Hadrons::MDistil::DistilParameters::ParameterDefault( par().UnsmearedSinkMultiFile, 1, true ) != 0 );
envCreate(PerambTensor, getName(), 1, Nt,nvec,LI,nnoise,Nt_inv,SI);
@ -152,7 +152,7 @@ void TPerambulator<FImpl>::setup(void)
template <typename FImpl>
void TPerambulator<FImpl>::Cleanup(void)
{
if( grid3d != nullptr )
if (grid3d != nullptr)
{
delete grid3d;
grid3d = nullptr;
@ -186,66 +186,61 @@ void TPerambulator<FImpl>::execute(void)
const int Ntfirst{grid4d->LocalStarts()[3]};
const std::string UnsmearedSinkFileName{ par().UnsmearedSinkFileName };
for (int inoise = 0; inoise < nnoise; inoise++)
{
int t_inv;
for (int inoise = 0; inoise < nnoise; inoise++)
for (int dk = 0; dk < LI; dk++)
{
for (int dk = 0; dk < LI; dk++)
for (int dt = 0; dt < Nt_inv; dt++)
{
for (int dt = 0; dt < Nt_inv; dt++)
for (int ds = 0; ds < SI; ds++)
{
for (int ds = 0; ds < SI; ds++)
LOG(Message) << "LapH source vector from noise " << inoise << " and dilution component (d_k,d_t,d_alpha) : (" << dk << ","<< dt << "," << ds << ")" << std::endl;
dist_source = 0;
tmp3d_nospin = 0;
evec3d = 0;
for (int it = dt; it < Nt; it += TI)
{
LOG(Message) << "LapH source vector from noise " << inoise << " and dilution component (d_k,d_t,d_alpha) : (" << dk << ","<< dt << "," << ds << ")" << std::endl;
dist_source = 0;
tmp3d_nospin = 0;
evec3d = 0;
for (int it = dt; it < Nt; it += TI)
const int t_inv{full_tdil ? tsrc : it};
if( t_inv >= Ntfirst && t_inv < Ntfirst + Ntlocal )
{
if (full_tdil) t_inv = tsrc; else t_inv = it;
if( t_inv >= Ntfirst && t_inv < Ntfirst + Ntlocal )
for (int ik = dk; ik < nvec; ik += LI)
{
for (int ik = dk; ik < nvec; ik += LI)
for (int is = ds; is < Ns; is += SI)
{
for (int is = ds; is < Ns; is += SI)
{
ExtractSliceLocal(evec3d,epack.evec[ik],0,t_inv-Ntfirst,Tdir);
tmp3d_nospin = evec3d * noise(inoise, t_inv, ik, is);
tmp3d=0;
pokeSpin(tmp3d,tmp3d_nospin,is);
tmp2=0;
InsertSliceLocal(tmp3d,tmp2,0,t_inv-Ntfirst,Tdir);
dist_source += tmp2;
}
ExtractSliceLocal(evec3d,epack.evec[ik],0,t_inv-Ntfirst,Tdir);
tmp3d_nospin = evec3d * noise(inoise, t_inv, ik, is);
tmp3d=0;
pokeSpin(tmp3d,tmp3d_nospin,is);
tmp2=0;
InsertSliceLocal(tmp3d,tmp2,0,t_inv-Ntfirst,Tdir);
dist_source += tmp2;
}
}
}
result=0;
v4dtmp = dist_source;
if (Ls_ == 1)
}
result=0;
v4dtmp = dist_source;
if (Ls_ == 1)
solver(result, v4dtmp);
else
{
mat.ImportPhysicalFermionSource(v4dtmp, v5dtmp);
solver(v5dtmp_sol, v5dtmp);
mat.ExportPhysicalFermionSolution(v5dtmp_sol, v4dtmp);
result = v4dtmp;
}
if (!UnsmearedSinkFileName.empty())
unsmeared_sink[inoise+nnoise*(dk+LI*(dt+Nt_inv*ds))] = result;
for (int is = 0; is < Ns; is++)
{
result_nospin = peekSpin(result,is);
for (int t = Ntfirst; t < Ntfirst + Ntlocal; t++)
{
solver(result, v4dtmp);
}
else
{
mat.ImportPhysicalFermionSource(v4dtmp, v5dtmp);
solver(v5dtmp_sol, v5dtmp);
mat.ExportPhysicalFermionSolution(v5dtmp_sol, v4dtmp);
result = v4dtmp;
}
if( !UnsmearedSinkFileName.empty() )
unsmeared_sink[inoise+nnoise*(dk+LI*(dt+Nt_inv*ds))] = result;
for (int is = 0; is < Ns; is++)
{
result_nospin = peekSpin(result,is);
for (int t = Ntfirst; t < Ntfirst + Ntlocal; t++)
ExtractSliceLocal(result_3d,result_nospin,0,t-Ntfirst,Tdir);
for (int ivec = 0; ivec < nvec; ivec++)
{
ExtractSliceLocal(result_3d,result_nospin,0,t-Ntfirst,Tdir);
for (int ivec = 0; ivec < nvec; ivec++)
{
ExtractSliceLocal(evec3d,epack.evec[ivec],0,t-Ntfirst,Tdir);
pokeSpin(perambulator.tensor(t, ivec, dk, inoise,dt,ds),static_cast<Complex>(innerProduct(evec3d, result_3d)),is);
}
ExtractSliceLocal(evec3d,epack.evec[ivec],0,t-Ntfirst,Tdir);
pokeSpin(perambulator.tensor(t, ivec, dk, inoise,dt,ds),static_cast<Complex>(innerProduct(evec3d, result_3d)),is);
}
}
}