2017-04-09 15:41:04 +01:00
|
|
|
/*************************************************************************************
|
2016-01-02 14:51:32 +00:00
|
|
|
|
|
|
|
Grid physics library, www.github.com/paboyle/Grid
|
|
|
|
|
|
|
|
Source file: ./lib/lattice/Lattice_transfer.h
|
|
|
|
|
|
|
|
Copyright (C) 2015
|
|
|
|
|
|
|
|
Author: Peter Boyle <paboyle@ph.ed.ac.uk>
|
|
|
|
|
|
|
|
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
|
2018-01-14 23:54:25 +00:00
|
|
|
*************************************************************************************/
|
|
|
|
/* END LEGAL */
|
2015-04-18 20:44:19 +01:00
|
|
|
#ifndef GRID_LATTICE_TRANSFER_H
|
|
|
|
#define GRID_LATTICE_TRANSFER_H
|
|
|
|
|
2018-01-14 23:54:25 +00:00
|
|
|
NAMESPACE_BEGIN(Grid);
|
2015-04-18 20:44:19 +01:00
|
|
|
|
2015-04-24 18:40:44 +01:00
|
|
|
inline void subdivides(GridBase *coarse,GridBase *fine)
|
|
|
|
{
|
|
|
|
assert(coarse->_ndimension == fine->_ndimension);
|
|
|
|
|
|
|
|
int _ndimension = coarse->_ndimension;
|
|
|
|
|
|
|
|
// local and global volumes subdivide cleanly after SIMDization
|
|
|
|
for(int d=0;d<_ndimension;d++){
|
|
|
|
assert(coarse->_processors[d] == fine->_processors[d]);
|
|
|
|
assert(coarse->_simd_layout[d] == fine->_simd_layout[d]);
|
|
|
|
assert((fine->_rdimensions[d] / coarse->_rdimensions[d])* coarse->_rdimensions[d]==fine->_rdimensions[d]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-11 14:12:02 +01:00
|
|
|
|
2018-01-14 23:54:25 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// remove and insert a half checkerboard
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
template<class vobj> inline void pickCheckerboard(int cb,Lattice<vobj> &half,const Lattice<vobj> &full){
|
2018-01-26 23:06:03 +00:00
|
|
|
half.Checkerboard() = cb;
|
2018-01-14 23:54:25 +00:00
|
|
|
|
2018-01-27 00:04:12 +00:00
|
|
|
thread_loop( (int ss=0;ss<full.Grid()->oSites();ss++),{
|
2018-01-14 23:54:25 +00:00
|
|
|
int cbos;
|
2018-02-24 22:26:10 +00:00
|
|
|
Coordinate coor;
|
2018-01-27 00:04:12 +00:00
|
|
|
full.Grid()->oCoorFromOindex(coor,ss);
|
|
|
|
cbos=half.Grid()->CheckerBoard(coor);
|
2015-04-18 20:44:19 +01:00
|
|
|
|
2018-01-14 23:54:25 +00:00
|
|
|
if (cbos==cb) {
|
2018-01-27 00:04:12 +00:00
|
|
|
int ssh=half.Grid()->oIndex(coor);
|
2018-01-26 23:06:03 +00:00
|
|
|
half[ssh] = full[ss];
|
2015-04-18 20:44:19 +01:00
|
|
|
}
|
2018-01-24 13:40:30 +00:00
|
|
|
});
|
2018-01-14 23:54:25 +00:00
|
|
|
}
|
|
|
|
template<class vobj> inline void setCheckerboard(Lattice<vobj> &full,const Lattice<vobj> &half){
|
2018-01-26 23:06:03 +00:00
|
|
|
int cb = half.Checkerboard();
|
2018-01-27 00:04:12 +00:00
|
|
|
thread_loop( (int ss=0;ss<full.Grid()->oSites();ss++), {
|
2018-02-24 22:26:10 +00:00
|
|
|
Coordinate coor;
|
2018-01-14 23:54:25 +00:00
|
|
|
int cbos;
|
|
|
|
|
2018-01-27 00:04:12 +00:00
|
|
|
full.Grid()->oCoorFromOindex(coor,ss);
|
|
|
|
cbos=half.Grid()->CheckerBoard(coor);
|
2015-04-18 20:44:19 +01:00
|
|
|
|
2018-01-14 23:54:25 +00:00
|
|
|
if (cbos==cb) {
|
2018-01-27 00:04:12 +00:00
|
|
|
int ssh=half.Grid()->oIndex(coor);
|
2018-01-26 23:06:03 +00:00
|
|
|
full[ss]=half[ssh];
|
2015-04-18 20:44:19 +01:00
|
|
|
}
|
2018-01-24 13:40:30 +00:00
|
|
|
});
|
2018-01-14 23:54:25 +00:00
|
|
|
}
|
2015-04-18 20:44:19 +01:00
|
|
|
|
2015-04-24 18:40:44 +01:00
|
|
|
|
2015-06-08 12:04:59 +01:00
|
|
|
template<class vobj,class CComplex,int nbasis>
|
|
|
|
inline void blockProject(Lattice<iVector<CComplex,nbasis > > &coarseData,
|
|
|
|
const Lattice<vobj> &fineData,
|
|
|
|
const std::vector<Lattice<vobj> > &Basis)
|
2015-04-24 18:40:44 +01:00
|
|
|
{
|
2018-01-27 00:04:12 +00:00
|
|
|
GridBase * fine = fineData.Grid();
|
|
|
|
GridBase * coarse= coarseData.Grid();
|
2015-04-24 18:40:44 +01:00
|
|
|
int _ndimension = coarse->_ndimension;
|
|
|
|
|
|
|
|
// checks
|
|
|
|
assert( nbasis == Basis.size() );
|
|
|
|
subdivides(coarse,fine);
|
|
|
|
for(int i=0;i<nbasis;i++){
|
2015-06-08 12:04:59 +01:00
|
|
|
conformable(Basis[i],fineData);
|
2015-04-24 18:40:44 +01:00
|
|
|
}
|
|
|
|
|
2018-02-24 22:26:10 +00:00
|
|
|
Coordinate block_r (_ndimension);
|
2015-04-24 18:40:44 +01:00
|
|
|
|
|
|
|
for(int d=0 ; d<_ndimension;d++){
|
|
|
|
block_r[d] = fine->_rdimensions[d] / coarse->_rdimensions[d];
|
2015-06-08 12:04:59 +01:00
|
|
|
assert(block_r[d]*coarse->_rdimensions[d] == fine->_rdimensions[d]);
|
2015-04-24 18:40:44 +01:00
|
|
|
}
|
|
|
|
|
2018-01-27 23:50:17 +00:00
|
|
|
coarseData=Zero();
|
2015-04-24 18:40:44 +01:00
|
|
|
|
2017-10-25 23:51:18 +01:00
|
|
|
// Loop over coars parallel, and then loop over fine associated with coarse.
|
2018-01-24 13:40:30 +00:00
|
|
|
thread_loop( (int sf=0;sf<fine->oSites();sf++),{
|
2015-04-24 18:40:44 +01:00
|
|
|
|
|
|
|
int sc;
|
2018-02-24 22:26:10 +00:00
|
|
|
Coordinate coor_c(_ndimension);
|
|
|
|
Coordinate coor_f(_ndimension);
|
2016-02-11 13:37:39 +00:00
|
|
|
Lexicographic::CoorFromIndex(coor_f,sf,fine->_rdimensions);
|
2015-04-24 18:40:44 +01:00
|
|
|
for(int d=0;d<_ndimension;d++) coor_c[d]=coor_f[d]/block_r[d];
|
2016-02-11 13:37:39 +00:00
|
|
|
Lexicographic::IndexFromCoor(coor_c,sc,coarse->_rdimensions);
|
2015-04-24 18:40:44 +01:00
|
|
|
|
2018-01-24 13:40:30 +00:00
|
|
|
thread_critical {
|
2018-01-14 23:54:25 +00:00
|
|
|
for(int i=0;i<nbasis;i++) {
|
2018-01-26 23:06:03 +00:00
|
|
|
coarseData[sc](i)=coarseData[sc](i)
|
|
|
|
+ innerProduct(Basis[i][sf],fineData[sf]);
|
2015-04-24 18:40:44 +01:00
|
|
|
|
2018-01-14 23:54:25 +00:00
|
|
|
}
|
2018-01-24 13:40:30 +00:00
|
|
|
}
|
|
|
|
});
|
2015-04-24 18:40:44 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-06-08 12:04:59 +01:00
|
|
|
template<class vobj,class CComplex>
|
|
|
|
inline void blockZAXPY(Lattice<vobj> &fineZ,
|
|
|
|
const Lattice<CComplex> &coarseA,
|
|
|
|
const Lattice<vobj> &fineX,
|
|
|
|
const Lattice<vobj> &fineY)
|
2015-04-24 18:40:44 +01:00
|
|
|
{
|
2018-01-27 00:04:12 +00:00
|
|
|
GridBase * fine = fineZ.Grid();
|
|
|
|
GridBase * coarse= coarseA.Grid();
|
2015-04-24 18:40:44 +01:00
|
|
|
|
2018-01-26 23:06:03 +00:00
|
|
|
fineZ.Checkerboard()=fineX.Checkerboard();
|
|
|
|
assert(fineX.Checkerboard()==fineY.Checkerboard());
|
2015-06-08 12:04:59 +01:00
|
|
|
subdivides(coarse,fine); // require they map
|
|
|
|
conformable(fineX,fineY);
|
|
|
|
conformable(fineX,fineZ);
|
2015-04-24 18:40:44 +01:00
|
|
|
|
2015-06-08 12:04:59 +01:00
|
|
|
int _ndimension = coarse->_ndimension;
|
2015-04-24 18:40:44 +01:00
|
|
|
|
2018-02-24 22:26:10 +00:00
|
|
|
Coordinate block_r (_ndimension);
|
2015-06-08 12:04:59 +01:00
|
|
|
|
|
|
|
// FIXME merge with subdivide checking routine as this is redundant
|
2015-04-24 18:40:44 +01:00
|
|
|
for(int d=0 ; d<_ndimension;d++){
|
|
|
|
block_r[d] = fine->_rdimensions[d] / coarse->_rdimensions[d];
|
2015-06-08 12:04:59 +01:00
|
|
|
assert(block_r[d]*coarse->_rdimensions[d]==fine->_rdimensions[d]);
|
2015-04-24 18:40:44 +01:00
|
|
|
}
|
|
|
|
|
2018-01-24 13:40:30 +00:00
|
|
|
thread_loop( (int sf=0;sf<fine->oSites();sf++),{
|
2015-06-08 12:04:59 +01:00
|
|
|
|
2015-04-24 18:40:44 +01:00
|
|
|
int sc;
|
2018-02-24 22:26:10 +00:00
|
|
|
Coordinate coor_c(_ndimension);
|
|
|
|
Coordinate coor_f(_ndimension);
|
2015-04-24 18:40:44 +01:00
|
|
|
|
2016-02-11 13:37:39 +00:00
|
|
|
Lexicographic::CoorFromIndex(coor_f,sf,fine->_rdimensions);
|
2015-04-24 18:40:44 +01:00
|
|
|
for(int d=0;d<_ndimension;d++) coor_c[d]=coor_f[d]/block_r[d];
|
2016-02-11 13:37:39 +00:00
|
|
|
Lexicographic::IndexFromCoor(coor_c,sc,coarse->_rdimensions);
|
2015-04-24 18:40:44 +01:00
|
|
|
|
2015-06-08 12:04:59 +01:00
|
|
|
// z = A x + y
|
2018-01-26 23:06:03 +00:00
|
|
|
fineZ[sf]=coarseA[sc]*fineX[sf]+fineY[sf];
|
2015-04-24 18:40:44 +01:00
|
|
|
|
2018-01-24 13:40:30 +00:00
|
|
|
});
|
2015-06-08 12:04:59 +01:00
|
|
|
|
2015-04-24 18:40:44 +01:00
|
|
|
return;
|
|
|
|
}
|
2015-06-08 12:04:59 +01:00
|
|
|
template<class vobj,class CComplex>
|
2018-01-14 23:54:25 +00:00
|
|
|
inline void blockInnerProduct(Lattice<CComplex> &CoarseInner,
|
|
|
|
const Lattice<vobj> &fineX,
|
|
|
|
const Lattice<vobj> &fineY)
|
2015-06-08 12:04:59 +01:00
|
|
|
{
|
2018-01-26 23:06:03 +00:00
|
|
|
typedef decltype(innerProduct(fineX[0],fineY[0])) dotp;
|
2015-04-24 18:40:44 +01:00
|
|
|
|
2018-01-27 00:04:12 +00:00
|
|
|
GridBase *coarse(CoarseInner.Grid());
|
|
|
|
GridBase *fine (fineX.Grid());
|
2015-06-08 12:04:59 +01:00
|
|
|
|
2018-01-26 23:06:03 +00:00
|
|
|
Lattice<dotp> fine_inner(fine); fine_inner.Checkerboard() = fineX.Checkerboard();
|
2015-06-08 12:04:59 +01:00
|
|
|
Lattice<dotp> coarse_inner(coarse);
|
|
|
|
|
2017-10-25 23:51:18 +01:00
|
|
|
// Precision promotion?
|
2015-06-08 12:04:59 +01:00
|
|
|
fine_inner = localInnerProduct(fineX,fineY);
|
|
|
|
blockSum(coarse_inner,fine_inner);
|
2018-01-24 13:40:30 +00:00
|
|
|
thread_loop( (int ss=0;ss<coarse->oSites();ss++),{
|
2018-01-26 23:06:03 +00:00
|
|
|
CoarseInner[ss] = coarse_inner[ss];
|
2018-01-24 13:40:30 +00:00
|
|
|
});
|
2015-06-08 12:04:59 +01:00
|
|
|
}
|
|
|
|
template<class vobj,class CComplex>
|
|
|
|
inline void blockNormalise(Lattice<CComplex> &ip,Lattice<vobj> &fineX)
|
|
|
|
{
|
2018-01-27 00:04:12 +00:00
|
|
|
GridBase *coarse = ip.Grid();
|
2018-01-27 23:50:17 +00:00
|
|
|
Lattice<vobj> zz(fineX.Grid()); zz=Zero(); zz.Checkerboard()=fineX.Checkerboard();
|
2015-06-08 12:04:59 +01:00
|
|
|
blockInnerProduct(ip,fineX,fineX);
|
2015-06-20 22:22:56 +01:00
|
|
|
ip = pow(ip,-0.5);
|
2015-06-09 10:26:19 +01:00
|
|
|
blockZAXPY(fineX,ip,fineX,zz);
|
2015-06-08 12:04:59 +01:00
|
|
|
}
|
2015-04-24 18:40:44 +01:00
|
|
|
// useful in multigrid project;
|
|
|
|
// Generic name : Coarsen?
|
|
|
|
template<class vobj>
|
2015-06-08 12:04:59 +01:00
|
|
|
inline void blockSum(Lattice<vobj> &coarseData,const Lattice<vobj> &fineData)
|
2015-04-24 18:40:44 +01:00
|
|
|
{
|
2018-01-27 00:04:12 +00:00
|
|
|
GridBase * fine = fineData.Grid();
|
|
|
|
GridBase * coarse= coarseData.Grid();
|
2015-04-24 18:40:44 +01:00
|
|
|
|
|
|
|
subdivides(coarse,fine); // require they map
|
|
|
|
|
|
|
|
int _ndimension = coarse->_ndimension;
|
|
|
|
|
2018-02-24 22:26:10 +00:00
|
|
|
Coordinate block_r (_ndimension);
|
2015-04-24 18:40:44 +01:00
|
|
|
|
|
|
|
for(int d=0 ; d<_ndimension;d++){
|
|
|
|
block_r[d] = fine->_rdimensions[d] / coarse->_rdimensions[d];
|
|
|
|
}
|
|
|
|
|
2017-10-25 23:51:18 +01:00
|
|
|
// Turn this around to loop threaded over sc and interior loop
|
|
|
|
// over sf would thread better
|
2018-01-27 23:50:17 +00:00
|
|
|
coarseData=Zero();
|
2018-01-24 13:40:30 +00:00
|
|
|
thread_region {
|
2017-10-25 23:51:18 +01:00
|
|
|
|
2015-04-24 18:40:44 +01:00
|
|
|
int sc;
|
2018-02-24 22:26:10 +00:00
|
|
|
Coordinate coor_c(_ndimension);
|
|
|
|
Coordinate coor_f(_ndimension);
|
2015-04-24 18:40:44 +01:00
|
|
|
|
2018-01-24 13:40:30 +00:00
|
|
|
thread_loop_in_region( (int sf=0;sf<fine->oSites();sf++),{
|
2017-10-25 23:51:18 +01:00
|
|
|
|
|
|
|
Lexicographic::CoorFromIndex(coor_f,sf,fine->_rdimensions);
|
|
|
|
for(int d=0;d<_ndimension;d++) coor_c[d]=coor_f[d]/block_r[d];
|
|
|
|
Lexicographic::IndexFromCoor(coor_c,sc,coarse->_rdimensions);
|
|
|
|
|
2018-01-24 13:40:30 +00:00
|
|
|
thread_critical {
|
2018-01-26 23:06:03 +00:00
|
|
|
coarseData[sc]=coarseData[sc]+fineData[sf];
|
2018-01-24 13:40:30 +00:00
|
|
|
}
|
2015-04-24 18:40:44 +01:00
|
|
|
|
2018-01-24 13:40:30 +00:00
|
|
|
});
|
2015-04-24 18:40:44 +01:00
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-06-09 10:26:19 +01:00
|
|
|
template<class vobj>
|
2018-02-24 22:26:10 +00:00
|
|
|
inline void blockPick(GridBase *coarse,const Lattice<vobj> &unpicked,Lattice<vobj> &picked,Coordinate coor)
|
2015-06-09 10:26:19 +01:00
|
|
|
{
|
2018-01-27 00:04:12 +00:00
|
|
|
GridBase * fine = unpicked.Grid();
|
2015-06-09 10:26:19 +01:00
|
|
|
|
2018-01-26 23:06:03 +00:00
|
|
|
Lattice<vobj> zz(fine); zz.Checkerboard() = unpicked.Checkerboard();
|
2015-06-09 10:26:19 +01:00
|
|
|
Lattice<iScalar<vInteger> > fcoor(fine);
|
|
|
|
|
2018-01-27 23:50:17 +00:00
|
|
|
zz = Zero();
|
2015-06-09 10:26:19 +01:00
|
|
|
|
|
|
|
picked = unpicked;
|
|
|
|
for(int d=0;d<fine->_ndimension;d++){
|
|
|
|
LatticeCoordinate(fcoor,d);
|
|
|
|
int block= fine->_rdimensions[d] / coarse->_rdimensions[d];
|
|
|
|
int lo = (coor[d])*block;
|
|
|
|
int hi = (coor[d]+1)*block;
|
|
|
|
picked = where( (fcoor<hi) , picked, zz);
|
|
|
|
picked = where( (fcoor>=lo), picked, zz);
|
|
|
|
}
|
|
|
|
}
|
2015-06-08 12:04:59 +01:00
|
|
|
|
|
|
|
template<class vobj,class CComplex>
|
|
|
|
inline void blockOrthogonalise(Lattice<CComplex> &ip,std::vector<Lattice<vobj> > &Basis)
|
|
|
|
{
|
2018-01-27 00:04:12 +00:00
|
|
|
GridBase *coarse = ip.Grid();
|
|
|
|
GridBase *fine = Basis[0].Grid();
|
2015-06-08 12:04:59 +01:00
|
|
|
|
|
|
|
int nbasis = Basis.size() ;
|
|
|
|
|
|
|
|
// checks
|
|
|
|
subdivides(coarse,fine);
|
|
|
|
for(int i=0;i<nbasis;i++){
|
2018-01-27 00:04:12 +00:00
|
|
|
conformable(Basis[i].Grid(),fine);
|
2015-06-08 12:04:59 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
for(int v=0;v<nbasis;v++) {
|
|
|
|
for(int u=0;u<v;u++) {
|
|
|
|
//Inner product & remove component
|
|
|
|
blockInnerProduct(ip,Basis[u],Basis[v]);
|
|
|
|
ip = -ip;
|
|
|
|
blockZAXPY<vobj,CComplex> (Basis[v],ip,Basis[u],Basis[v]);
|
|
|
|
}
|
|
|
|
blockNormalise(ip,Basis[v]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class vobj,class CComplex,int nbasis>
|
|
|
|
inline void blockPromote(const Lattice<iVector<CComplex,nbasis > > &coarseData,
|
|
|
|
Lattice<vobj> &fineData,
|
|
|
|
const std::vector<Lattice<vobj> > &Basis)
|
|
|
|
{
|
2018-01-27 00:04:12 +00:00
|
|
|
GridBase * fine = fineData.Grid();
|
|
|
|
GridBase * coarse= coarseData.Grid();
|
2015-06-08 12:04:59 +01:00
|
|
|
int _ndimension = coarse->_ndimension;
|
|
|
|
|
|
|
|
// checks
|
|
|
|
assert( nbasis == Basis.size() );
|
|
|
|
subdivides(coarse,fine);
|
|
|
|
for(int i=0;i<nbasis;i++){
|
2018-01-27 00:04:12 +00:00
|
|
|
conformable(Basis[i].Grid(),fine);
|
2015-06-08 12:04:59 +01:00
|
|
|
}
|
|
|
|
|
2018-02-24 22:26:10 +00:00
|
|
|
Coordinate block_r (_ndimension);
|
2015-06-08 12:04:59 +01:00
|
|
|
|
|
|
|
for(int d=0 ; d<_ndimension;d++){
|
|
|
|
block_r[d] = fine->_rdimensions[d] / coarse->_rdimensions[d];
|
|
|
|
}
|
|
|
|
|
|
|
|
// Loop with a cache friendly loop ordering
|
2018-01-24 13:40:30 +00:00
|
|
|
thread_region {
|
2015-06-08 12:04:59 +01:00
|
|
|
int sc;
|
2018-02-24 22:26:10 +00:00
|
|
|
Coordinate coor_c(_ndimension);
|
|
|
|
Coordinate coor_f(_ndimension);
|
2015-06-08 12:04:59 +01:00
|
|
|
|
2018-01-24 13:40:30 +00:00
|
|
|
thread_loop_in_region( (int sf=0;sf<fine->oSites();sf++),{
|
2015-06-08 12:04:59 +01:00
|
|
|
|
2017-10-25 23:51:18 +01:00
|
|
|
Lexicographic::CoorFromIndex(coor_f,sf,fine->_rdimensions);
|
|
|
|
for(int d=0;d<_ndimension;d++) coor_c[d]=coor_f[d]/block_r[d];
|
|
|
|
Lexicographic::IndexFromCoor(coor_c,sc,coarse->_rdimensions);
|
|
|
|
|
|
|
|
for(int i=0;i<nbasis;i++) {
|
2018-01-26 23:06:03 +00:00
|
|
|
if(i==0) fineData[sf]=coarseData[sc](i) * Basis[i][sf];
|
|
|
|
else fineData[sf]=fineData[sf]+coarseData[sc](i)*Basis[i][sf];
|
2017-10-25 23:51:18 +01:00
|
|
|
}
|
2018-01-24 13:40:30 +00:00
|
|
|
});
|
2015-06-08 12:04:59 +01:00
|
|
|
}
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2016-05-11 15:18:47 +01:00
|
|
|
// Useful for precision conversion, or indeed anything where an operator= does a conversion on scalars.
|
|
|
|
// Simd layouts need not match since we use peek/poke Local
|
|
|
|
template<class vobj,class vvobj>
|
|
|
|
void localConvert(const Lattice<vobj> &in,Lattice<vvobj> &out)
|
|
|
|
{
|
|
|
|
typedef typename vobj::scalar_object sobj;
|
|
|
|
typedef typename vvobj::scalar_object ssobj;
|
|
|
|
|
2018-01-27 00:04:12 +00:00
|
|
|
GridBase *ig = in.Grid();
|
|
|
|
GridBase *og = out.Grid();
|
2016-05-11 15:18:47 +01:00
|
|
|
|
|
|
|
int ni = ig->_ndimension;
|
|
|
|
int no = og->_ndimension;
|
|
|
|
|
|
|
|
assert(ni == no);
|
|
|
|
|
|
|
|
for(int d=0;d<no;d++){
|
|
|
|
assert(ig->_processors[d] == og->_processors[d]);
|
|
|
|
assert(ig->_ldimensions[d] == og->_ldimensions[d]);
|
2017-02-07 06:16:39 +00:00
|
|
|
assert(ig->lSites() == og->lSites());
|
2016-05-11 15:18:47 +01:00
|
|
|
}
|
|
|
|
|
2018-01-24 13:40:30 +00:00
|
|
|
thread_loop( (int idx=0;idx<ig->lSites();idx++),{
|
2017-02-07 06:16:39 +00:00
|
|
|
sobj s;
|
|
|
|
ssobj ss;
|
|
|
|
|
2018-02-24 22:26:10 +00:00
|
|
|
Coordinate lcoor(ni);
|
2016-05-11 15:18:47 +01:00
|
|
|
ig->LocalIndexToLocalCoor(idx,lcoor);
|
|
|
|
peekLocalSite(s,in,lcoor);
|
|
|
|
ss=s;
|
|
|
|
pokeLocalSite(ss,out,lcoor);
|
2018-01-24 13:40:30 +00:00
|
|
|
});
|
2016-05-11 15:18:47 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-05-11 14:12:02 +01:00
|
|
|
template<class vobj>
|
2017-04-09 15:41:04 +01:00
|
|
|
void InsertSlice(const Lattice<vobj> &lowDim,Lattice<vobj> & higherDim,int slice, int orthog)
|
2016-05-11 14:12:02 +01:00
|
|
|
{
|
|
|
|
typedef typename vobj::scalar_object sobj;
|
|
|
|
|
2018-01-27 00:04:12 +00:00
|
|
|
GridBase *lg = lowDim.Grid();
|
|
|
|
GridBase *hg = higherDim.Grid();
|
2016-05-11 14:12:02 +01:00
|
|
|
int nl = lg->_ndimension;
|
|
|
|
int nh = hg->_ndimension;
|
|
|
|
|
|
|
|
assert(nl+1 == nh);
|
|
|
|
assert(orthog<nh);
|
|
|
|
assert(orthog>=0);
|
2016-05-12 18:35:38 +01:00
|
|
|
assert(hg->_processors[orthog]==1);
|
2016-05-11 14:12:02 +01:00
|
|
|
|
|
|
|
int dl; dl = 0;
|
|
|
|
for(int d=0;d<nh;d++){
|
|
|
|
if ( d != orthog) {
|
|
|
|
assert(lg->_processors[dl] == hg->_processors[d]);
|
|
|
|
assert(lg->_ldimensions[dl] == hg->_ldimensions[d]);
|
|
|
|
dl++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// the above should guarantee that the operations are local
|
2018-01-24 13:40:30 +00:00
|
|
|
thread_loop( (int idx=0;idx<lg->lSites();idx++),{
|
2017-02-07 06:16:39 +00:00
|
|
|
sobj s;
|
2018-02-24 22:26:10 +00:00
|
|
|
Coordinate lcoor(nl);
|
|
|
|
Coordinate hcoor(nh);
|
2016-05-11 14:12:02 +01:00
|
|
|
lg->LocalIndexToLocalCoor(idx,lcoor);
|
2017-02-22 17:19:09 +00:00
|
|
|
int ddl=0;
|
2016-05-11 15:18:47 +01:00
|
|
|
hcoor[orthog] = slice;
|
2016-05-11 14:12:02 +01:00
|
|
|
for(int d=0;d<nh;d++){
|
2016-05-11 15:06:54 +01:00
|
|
|
if ( d!=orthog ) {
|
2017-02-22 17:19:09 +00:00
|
|
|
hcoor[d]=lcoor[ddl++];
|
2016-05-11 14:12:02 +01:00
|
|
|
}
|
|
|
|
}
|
2016-05-12 18:35:38 +01:00
|
|
|
peekLocalSite(s,lowDim,lcoor);
|
|
|
|
pokeLocalSite(s,higherDim,hcoor);
|
2018-01-24 13:40:30 +00:00
|
|
|
});
|
2016-05-11 14:12:02 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
template<class vobj>
|
2017-04-09 15:41:04 +01:00
|
|
|
void ExtractSlice(Lattice<vobj> &lowDim,const Lattice<vobj> & higherDim,int slice, int orthog)
|
2016-05-11 14:12:02 +01:00
|
|
|
{
|
|
|
|
typedef typename vobj::scalar_object sobj;
|
|
|
|
|
2018-01-27 00:04:12 +00:00
|
|
|
GridBase *lg = lowDim.Grid();
|
|
|
|
GridBase *hg = higherDim.Grid();
|
2016-05-11 14:12:02 +01:00
|
|
|
int nl = lg->_ndimension;
|
|
|
|
int nh = hg->_ndimension;
|
|
|
|
|
|
|
|
assert(nl+1 == nh);
|
|
|
|
assert(orthog<nh);
|
|
|
|
assert(orthog>=0);
|
2016-05-12 18:35:38 +01:00
|
|
|
assert(hg->_processors[orthog]==1);
|
2016-05-11 14:12:02 +01:00
|
|
|
|
|
|
|
int dl; dl = 0;
|
2018-01-14 23:54:25 +00:00
|
|
|
for(int d=0;d<nh;d++){
|
|
|
|
if ( d != orthog) {
|
|
|
|
assert(lg->_processors[dl] == hg->_processors[d]);
|
|
|
|
assert(lg->_ldimensions[dl] == hg->_ldimensions[d]);
|
|
|
|
dl++;
|
2016-05-11 14:12:02 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
// the above should guarantee that the operations are local
|
2018-01-24 13:40:30 +00:00
|
|
|
thread_loop((int idx=0;idx<lg->lSites();idx++),{
|
2017-02-07 06:16:39 +00:00
|
|
|
sobj s;
|
2018-02-24 22:26:10 +00:00
|
|
|
Coordinate lcoor(nl);
|
|
|
|
Coordinate hcoor(nh);
|
2016-05-11 14:12:02 +01:00
|
|
|
lg->LocalIndexToLocalCoor(idx,lcoor);
|
2017-02-23 00:25:29 +00:00
|
|
|
int ddl=0;
|
2016-05-11 15:18:47 +01:00
|
|
|
hcoor[orthog] = slice;
|
2016-05-11 14:12:02 +01:00
|
|
|
for(int d=0;d<nh;d++){
|
2016-05-11 15:06:54 +01:00
|
|
|
if ( d!=orthog ) {
|
2017-02-22 17:19:09 +00:00
|
|
|
hcoor[d]=lcoor[ddl++];
|
2016-05-11 14:12:02 +01:00
|
|
|
}
|
|
|
|
}
|
2016-05-12 18:35:38 +01:00
|
|
|
peekLocalSite(s,higherDim,hcoor);
|
|
|
|
pokeLocalSite(s,lowDim,lcoor);
|
2018-01-24 13:40:30 +00:00
|
|
|
});
|
2016-05-11 14:12:02 +01:00
|
|
|
|
|
|
|
}
|
2015-06-08 12:04:59 +01:00
|
|
|
|
2016-08-17 01:33:55 +01:00
|
|
|
|
|
|
|
template<class vobj>
|
2017-04-09 15:41:04 +01:00
|
|
|
void InsertSliceLocal(const Lattice<vobj> &lowDim, Lattice<vobj> & higherDim,int slice_lo,int slice_hi, int orthog)
|
2016-08-17 01:33:55 +01:00
|
|
|
{
|
|
|
|
typedef typename vobj::scalar_object sobj;
|
|
|
|
|
2018-01-27 00:04:12 +00:00
|
|
|
GridBase *lg = lowDim.Grid();
|
|
|
|
GridBase *hg = higherDim.Grid();
|
2016-08-17 01:33:55 +01:00
|
|
|
int nl = lg->_ndimension;
|
|
|
|
int nh = hg->_ndimension;
|
|
|
|
|
|
|
|
assert(nl == nh);
|
|
|
|
assert(orthog<nh);
|
|
|
|
assert(orthog>=0);
|
|
|
|
|
|
|
|
for(int d=0;d<nh;d++){
|
|
|
|
assert(lg->_processors[d] == hg->_processors[d]);
|
|
|
|
assert(lg->_ldimensions[d] == hg->_ldimensions[d]);
|
|
|
|
}
|
|
|
|
|
|
|
|
// the above should guarantee that the operations are local
|
2018-01-24 13:40:30 +00:00
|
|
|
thread_loop( (int idx=0;idx<lg->lSites();idx++),{
|
2017-02-07 06:16:39 +00:00
|
|
|
sobj s;
|
2018-02-24 22:26:10 +00:00
|
|
|
Coordinate lcoor(nl);
|
|
|
|
Coordinate hcoor(nh);
|
2016-08-17 01:33:55 +01:00
|
|
|
lg->LocalIndexToLocalCoor(idx,lcoor);
|
|
|
|
if( lcoor[orthog] == slice_lo ) {
|
|
|
|
hcoor=lcoor;
|
|
|
|
hcoor[orthog] = slice_hi;
|
|
|
|
peekLocalSite(s,lowDim,lcoor);
|
|
|
|
pokeLocalSite(s,higherDim,hcoor);
|
|
|
|
}
|
2018-01-24 13:40:30 +00:00
|
|
|
});
|
2016-08-17 01:33:55 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template<class vobj>
|
|
|
|
void ExtractSliceLocal(Lattice<vobj> &lowDim, Lattice<vobj> & higherDim,int slice_lo,int slice_hi, int orthog)
|
|
|
|
{
|
|
|
|
typedef typename vobj::scalar_object sobj;
|
|
|
|
|
2018-01-27 00:04:12 +00:00
|
|
|
GridBase *lg = lowDim.Grid();
|
|
|
|
GridBase *hg = higherDim.Grid();
|
2016-08-17 01:33:55 +01:00
|
|
|
int nl = lg->_ndimension;
|
|
|
|
int nh = hg->_ndimension;
|
|
|
|
|
|
|
|
assert(nl == nh);
|
|
|
|
assert(orthog<nh);
|
|
|
|
assert(orthog>=0);
|
|
|
|
|
|
|
|
for(int d=0;d<nh;d++){
|
|
|
|
assert(lg->_processors[d] == hg->_processors[d]);
|
|
|
|
assert(lg->_ldimensions[d] == hg->_ldimensions[d]);
|
|
|
|
}
|
|
|
|
|
|
|
|
// the above should guarantee that the operations are local
|
2018-01-24 13:40:30 +00:00
|
|
|
thread_loop( (int idx=0;idx<lg->lSites();idx++),{
|
2017-02-07 06:16:39 +00:00
|
|
|
sobj s;
|
2018-02-24 22:26:10 +00:00
|
|
|
Coordinate lcoor(nl);
|
|
|
|
Coordinate hcoor(nh);
|
2016-08-17 01:33:55 +01:00
|
|
|
lg->LocalIndexToLocalCoor(idx,lcoor);
|
|
|
|
if( lcoor[orthog] == slice_lo ) {
|
|
|
|
hcoor=lcoor;
|
|
|
|
hcoor[orthog] = slice_hi;
|
|
|
|
peekLocalSite(s,higherDim,hcoor);
|
|
|
|
pokeLocalSite(s,lowDim,lcoor);
|
|
|
|
}
|
2018-01-24 13:40:30 +00:00
|
|
|
});
|
2016-08-17 01:33:55 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-08-19 10:26:07 +01:00
|
|
|
template<class vobj>
|
|
|
|
void Replicate(Lattice<vobj> &coarse,Lattice<vobj> & fine)
|
|
|
|
{
|
|
|
|
typedef typename vobj::scalar_object sobj;
|
|
|
|
|
2018-01-27 00:04:12 +00:00
|
|
|
GridBase *cg = coarse.Grid();
|
|
|
|
GridBase *fg = fine.Grid();
|
2015-08-19 10:26:07 +01:00
|
|
|
|
|
|
|
int nd = cg->_ndimension;
|
|
|
|
|
|
|
|
subdivides(cg,fg);
|
|
|
|
|
|
|
|
assert(cg->_ndimension==fg->_ndimension);
|
|
|
|
|
2018-02-24 22:26:10 +00:00
|
|
|
Coordinate ratio(cg->_ndimension);
|
2015-08-19 10:26:07 +01:00
|
|
|
|
|
|
|
for(int d=0;d<cg->_ndimension;d++){
|
|
|
|
ratio[d] = fg->_fdimensions[d]/cg->_fdimensions[d];
|
|
|
|
}
|
|
|
|
|
2018-02-24 22:26:10 +00:00
|
|
|
Coordinate fcoor(nd);
|
|
|
|
Coordinate ccoor(nd);
|
2015-08-19 10:26:07 +01:00
|
|
|
for(int g=0;g<fg->gSites();g++){
|
|
|
|
|
|
|
|
fg->GlobalIndexToGlobalCoor(g,fcoor);
|
|
|
|
for(int d=0;d<nd;d++){
|
|
|
|
ccoor[d] = fcoor[d]%cg->_gdimensions[d];
|
|
|
|
}
|
|
|
|
|
|
|
|
sobj tmp;
|
|
|
|
peekSite(tmp,coarse,ccoor);
|
|
|
|
pokeSite(tmp,fine,fcoor);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2016-07-06 20:57:04 +01:00
|
|
|
//Copy SIMD-vectorized lattice to array of scalar objects in lexicographic order
|
|
|
|
template<typename vobj, typename sobj>
|
2017-05-30 23:38:30 +01:00
|
|
|
typename std::enable_if<isSIMDvectorized<vobj>::value && !isSIMDvectorized<sobj>::value, void>::type
|
|
|
|
unvectorizeToLexOrdArray(std::vector<sobj> &out, const Lattice<vobj> &in)
|
|
|
|
{
|
|
|
|
|
2016-07-06 20:57:04 +01:00
|
|
|
typedef typename vobj::vector_type vtype;
|
|
|
|
|
2018-01-27 00:04:12 +00:00
|
|
|
GridBase* in_grid = in.Grid();
|
2016-07-06 20:57:04 +01:00
|
|
|
out.resize(in_grid->lSites());
|
|
|
|
|
|
|
|
int ndim = in_grid->Nd();
|
|
|
|
int in_nsimd = vtype::Nsimd();
|
|
|
|
|
2018-02-24 22:26:10 +00:00
|
|
|
std::vector<Coordinate > in_icoor(in_nsimd);
|
2016-07-06 20:57:04 +01:00
|
|
|
|
|
|
|
for(int lane=0; lane < in_nsimd; lane++){
|
|
|
|
in_icoor[lane].resize(ndim);
|
|
|
|
in_grid->iCoorFromIindex(in_icoor[lane], lane);
|
|
|
|
}
|
2018-01-24 13:40:30 +00:00
|
|
|
|
|
|
|
//loop over outer index
|
|
|
|
thread_loop( (int in_oidx = 0; in_oidx < in_grid->oSites(); in_oidx++),{
|
2016-07-06 20:57:04 +01:00
|
|
|
//Assemble vector of pointers to output elements
|
2018-02-24 22:26:10 +00:00
|
|
|
ExtractPointerArray<sobj> out_ptrs(in_nsimd);
|
2016-07-06 20:57:04 +01:00
|
|
|
|
2018-02-24 22:26:10 +00:00
|
|
|
Coordinate in_ocoor(ndim);
|
2016-07-06 20:57:04 +01:00
|
|
|
in_grid->oCoorFromOindex(in_ocoor, in_oidx);
|
|
|
|
|
2018-02-24 22:26:10 +00:00
|
|
|
Coordinate lcoor(in_grid->Nd());
|
2016-07-06 20:57:04 +01:00
|
|
|
|
|
|
|
for(int lane=0; lane < in_nsimd; lane++){
|
|
|
|
for(int mu=0;mu<ndim;mu++)
|
|
|
|
lcoor[mu] = in_ocoor[mu] + in_grid->_rdimensions[mu]*in_icoor[lane][mu];
|
|
|
|
|
|
|
|
int lex;
|
|
|
|
Lexicographic::IndexFromCoor(lcoor, lex, in_grid->_ldimensions);
|
|
|
|
out_ptrs[lane] = &out[lex];
|
|
|
|
}
|
|
|
|
|
|
|
|
//Unpack into those ptrs
|
2018-01-26 23:06:03 +00:00
|
|
|
const vobj & in_vobj = in[in_oidx];
|
2018-02-24 22:26:10 +00:00
|
|
|
extract(in_vobj, out_ptrs, 0);
|
2018-01-24 13:40:30 +00:00
|
|
|
});
|
2016-07-06 20:57:04 +01:00
|
|
|
}
|
2017-05-30 23:38:30 +01:00
|
|
|
//Copy SIMD-vectorized lattice to array of scalar objects in lexicographic order
|
|
|
|
template<typename vobj, typename sobj>
|
2017-06-01 22:36:18 +01:00
|
|
|
typename std::enable_if<isSIMDvectorized<vobj>::value
|
2018-01-14 23:54:25 +00:00
|
|
|
&& !isSIMDvectorized<sobj>::value, void>::type
|
2017-06-01 22:36:18 +01:00
|
|
|
vectorizeFromLexOrdArray( std::vector<sobj> &in, Lattice<vobj> &out)
|
2017-05-30 23:38:30 +01:00
|
|
|
{
|
|
|
|
|
|
|
|
typedef typename vobj::vector_type vtype;
|
|
|
|
|
2018-01-27 00:04:12 +00:00
|
|
|
GridBase* grid = out.Grid();
|
2017-05-30 23:38:30 +01:00
|
|
|
assert(in.size()==grid->lSites());
|
|
|
|
|
2018-02-24 22:26:10 +00:00
|
|
|
const int ndim = grid->Nd();
|
|
|
|
constexpr int nsimd = vtype::Nsimd();
|
2017-05-30 23:38:30 +01:00
|
|
|
|
2018-02-24 22:26:10 +00:00
|
|
|
std::vector<Coordinate > icoor(nsimd);
|
2017-05-30 23:38:30 +01:00
|
|
|
|
|
|
|
for(int lane=0; lane < nsimd; lane++){
|
|
|
|
icoor[lane].resize(ndim);
|
|
|
|
grid->iCoorFromIindex(icoor[lane],lane);
|
|
|
|
}
|
|
|
|
|
2018-01-24 13:40:30 +00:00
|
|
|
thread_loop( (uint64_t oidx = 0; oidx < grid->oSites(); oidx++),{
|
2017-05-30 23:38:30 +01:00
|
|
|
//Assemble vector of pointers to output elements
|
2018-02-24 22:26:10 +00:00
|
|
|
ExtractPointerArray<sobj> ptrs(nsimd);
|
2017-05-30 23:38:30 +01:00
|
|
|
|
2018-02-24 22:26:10 +00:00
|
|
|
Coordinate ocoor(ndim);
|
|
|
|
Coordinate lcoor(ndim);
|
2017-05-30 23:38:30 +01:00
|
|
|
grid->oCoorFromOindex(ocoor, oidx);
|
|
|
|
|
|
|
|
for(int lane=0; lane < nsimd; lane++){
|
2017-06-01 22:36:18 +01:00
|
|
|
|
|
|
|
for(int mu=0;mu<ndim;mu++){
|
2017-05-30 23:38:30 +01:00
|
|
|
lcoor[mu] = ocoor[mu] + grid->_rdimensions[mu]*icoor[lane][mu];
|
2017-06-01 22:36:18 +01:00
|
|
|
}
|
2017-05-30 23:38:30 +01:00
|
|
|
|
|
|
|
int lex;
|
|
|
|
Lexicographic::IndexFromCoor(lcoor, lex, grid->_ldimensions);
|
|
|
|
ptrs[lane] = &in[lex];
|
|
|
|
}
|
|
|
|
|
|
|
|
//pack from those ptrs
|
|
|
|
vobj vecobj;
|
2018-02-24 22:26:10 +00:00
|
|
|
merge(vecobj, ptrs, 0);
|
2018-01-26 23:06:03 +00:00
|
|
|
out[oidx] = vecobj;
|
2018-01-24 13:40:30 +00:00
|
|
|
});
|
2017-05-30 23:38:30 +01:00
|
|
|
}
|
2016-07-06 20:57:04 +01:00
|
|
|
|
|
|
|
//Convert a Lattice from one precision to another
|
|
|
|
template<class VobjOut, class VobjIn>
|
|
|
|
void precisionChange(Lattice<VobjOut> &out, const Lattice<VobjIn> &in){
|
2018-01-24 13:40:30 +00:00
|
|
|
|
2018-01-27 00:04:12 +00:00
|
|
|
assert(out.Grid()->Nd() == in.Grid()->Nd());
|
2018-01-26 23:06:03 +00:00
|
|
|
out.Checkerboard() = in.Checkerboard();
|
2018-01-27 00:04:12 +00:00
|
|
|
GridBase *in_grid=in.Grid();
|
|
|
|
GridBase *out_grid = out.Grid();
|
2015-08-19 10:26:07 +01:00
|
|
|
|
2016-07-06 20:57:04 +01:00
|
|
|
typedef typename VobjOut::scalar_object SobjOut;
|
|
|
|
typedef typename VobjIn::scalar_object SobjIn;
|
|
|
|
|
2018-01-27 00:04:12 +00:00
|
|
|
int ndim = out.Grid()->Nd();
|
2016-07-06 20:57:04 +01:00
|
|
|
int out_nsimd = out_grid->Nsimd();
|
|
|
|
|
2018-02-24 22:26:10 +00:00
|
|
|
std::vector<Coordinate > out_icoor(out_nsimd);
|
2016-07-06 20:57:04 +01:00
|
|
|
|
|
|
|
for(int lane=0; lane < out_nsimd; lane++){
|
|
|
|
out_icoor[lane].resize(ndim);
|
|
|
|
out_grid->iCoorFromIindex(out_icoor[lane], lane);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<SobjOut> in_slex_conv(in_grid->lSites());
|
|
|
|
unvectorizeToLexOrdArray(in_slex_conv, in);
|
|
|
|
|
2018-01-24 13:40:30 +00:00
|
|
|
thread_loop( (uint64_t out_oidx=0;out_oidx<out_grid->oSites();out_oidx++),{
|
2018-02-24 22:26:10 +00:00
|
|
|
Coordinate out_ocoor(ndim);
|
2016-07-06 20:57:04 +01:00
|
|
|
out_grid->oCoorFromOindex(out_ocoor, out_oidx);
|
|
|
|
|
2018-02-24 22:26:10 +00:00
|
|
|
ExtractPointerArray<SobjOut> ptrs(out_nsimd);
|
2016-07-06 20:57:04 +01:00
|
|
|
|
2018-02-24 22:26:10 +00:00
|
|
|
Coordinate lcoor(out_grid->Nd());
|
2016-07-06 20:57:04 +01:00
|
|
|
|
|
|
|
for(int lane=0; lane < out_nsimd; lane++){
|
|
|
|
for(int mu=0;mu<ndim;mu++)
|
|
|
|
lcoor[mu] = out_ocoor[mu] + out_grid->_rdimensions[mu]*out_icoor[lane][mu];
|
|
|
|
|
|
|
|
int llex; Lexicographic::IndexFromCoor(lcoor, llex, out_grid->_ldimensions);
|
|
|
|
ptrs[lane] = &in_slex_conv[llex];
|
|
|
|
}
|
2018-01-26 23:06:03 +00:00
|
|
|
merge(out[out_oidx], ptrs, 0);
|
2018-01-24 13:40:30 +00:00
|
|
|
});
|
2016-07-06 20:57:04 +01:00
|
|
|
}
|
2017-10-09 23:19:45 +01:00
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Communicate between grids
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// SIMPLE CASE:
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Mesh of nodes (2x2) ; subdivide to 1x1 subdivisions
|
|
|
|
//
|
|
|
|
// Lex ord:
|
|
|
|
// N0 va0 vb0 vc0 vd0 N1 va1 vb1 vc1 vd1
|
|
|
|
// N2 va2 vb2 vc2 vd2 N3 va3 vb3 vc3 vd3
|
|
|
|
//
|
|
|
|
// Ratio = full[dim] / split[dim]
|
|
|
|
//
|
|
|
|
// For each dimension do an all to all; get Nvec -> Nvec / ratio
|
|
|
|
// Ldim -> Ldim * ratio
|
|
|
|
// LocalVol -> LocalVol * ratio
|
|
|
|
// full AllToAll(0)
|
|
|
|
// N0 va0 vb0 va1 vb1 N1 vc0 vd0 vc1 vd1
|
|
|
|
// N2 va2 vb2 va3 vb3 N3 vc2 vd2 vc3 vd3
|
|
|
|
//
|
|
|
|
// REARRANGE
|
|
|
|
// N0 va01 vb01 N1 vc01 vd01
|
|
|
|
// N2 va23 vb23 N3 vc23 vd23
|
|
|
|
//
|
|
|
|
// full AllToAll(1) // Not what is wanted. FIXME
|
|
|
|
// N0 va01 va23 N1 vc01 vc23
|
|
|
|
// N2 vb01 vb23 N3 vd01 vd23
|
|
|
|
//
|
|
|
|
// REARRANGE
|
|
|
|
// N0 va0123 N1 vc0123
|
|
|
|
// N2 vb0123 N3 vd0123
|
|
|
|
//
|
|
|
|
// Must also rearrange data to get into the NEW lex order of grid at each stage. Some kind of "insert/extract".
|
|
|
|
// NB: Easiest to programme if keep in lex order.
|
2017-11-19 01:39:04 +00:00
|
|
|
/*
|
2017-11-27 15:13:29 +00:00
|
|
|
* Let chunk = (fvol*nvec)/sP be size of a chunk. ( Divide lexico vol * nvec into fP/sP = M chunks )
|
|
|
|
*
|
|
|
|
* 2nd A2A (over sP nodes; subdivide the fP into sP chunks of M)
|
|
|
|
*
|
|
|
|
* node 0 1st chunk of node 0M..(1M-1); 2nd chunk of node 0M..(1M-1).. data chunk x M x sP = fL / sP * M * sP = fL * M growth
|
|
|
|
* node 1 1st chunk of node 1M..(2M-1); 2nd chunk of node 1M..(2M-1)..
|
|
|
|
* node 2 1st chunk of node 2M..(3M-1); 2nd chunk of node 2M..(3M-1)..
|
|
|
|
* node 3 1st chunk of node 3M..(3M-1); 2nd chunk of node 2M..(3M-1)..
|
|
|
|
* etc...
|
2017-11-19 01:39:04 +00:00
|
|
|
*/
|
2017-10-09 23:19:45 +01:00
|
|
|
template<class Vobj>
|
|
|
|
void Grid_split(std::vector<Lattice<Vobj> > & full,Lattice<Vobj> & split)
|
|
|
|
{
|
|
|
|
typedef typename Vobj::scalar_object Sobj;
|
|
|
|
|
|
|
|
int full_vecs = full.size();
|
|
|
|
|
|
|
|
assert(full_vecs>=1);
|
|
|
|
|
2018-01-27 00:04:12 +00:00
|
|
|
GridBase * full_grid = full[0].Grid();
|
|
|
|
GridBase *split_grid = split.Grid();
|
2017-10-09 23:19:45 +01:00
|
|
|
|
|
|
|
int ndim = full_grid->_ndimension;
|
|
|
|
int full_nproc = full_grid->_Nprocessors;
|
|
|
|
int split_nproc =split_grid->_Nprocessors;
|
|
|
|
|
|
|
|
////////////////////////////////
|
|
|
|
// Checkerboard management
|
|
|
|
////////////////////////////////
|
2018-01-26 23:06:03 +00:00
|
|
|
int cb = full[0].Checkerboard();
|
|
|
|
split.Checkerboard() = cb;
|
2017-10-09 23:19:45 +01:00
|
|
|
|
|
|
|
//////////////////////////////
|
|
|
|
// Checks
|
|
|
|
//////////////////////////////
|
|
|
|
assert(full_grid->_ndimension==split_grid->_ndimension);
|
|
|
|
for(int n=0;n<full_vecs;n++){
|
2018-01-26 23:06:03 +00:00
|
|
|
assert(full[n].Checkerboard() == cb);
|
2017-10-09 23:19:45 +01:00
|
|
|
for(int d=0;d<ndim;d++){
|
2018-01-27 00:04:12 +00:00
|
|
|
assert(full[n].Grid()->_gdimensions[d]==split.Grid()->_gdimensions[d]);
|
|
|
|
assert(full[n].Grid()->_fdimensions[d]==split.Grid()->_fdimensions[d]);
|
2017-10-09 23:19:45 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int nvector =full_nproc/split_nproc;
|
|
|
|
assert(nvector*split_nproc==full_nproc);
|
|
|
|
assert(nvector == full_vecs);
|
|
|
|
|
2018-02-24 22:26:10 +00:00
|
|
|
Coordinate ratio(ndim);
|
2017-10-09 23:19:45 +01:00
|
|
|
for(int d=0;d<ndim;d++){
|
|
|
|
ratio[d] = full_grid->_processors[d]/ split_grid->_processors[d];
|
|
|
|
}
|
|
|
|
|
2017-10-27 14:20:35 +01:00
|
|
|
uint64_t lsites = full_grid->lSites();
|
|
|
|
uint64_t sz = lsites * nvector;
|
2017-10-09 23:19:45 +01:00
|
|
|
std::vector<Sobj> tmpdata(sz);
|
|
|
|
std::vector<Sobj> alldata(sz);
|
|
|
|
std::vector<Sobj> scalardata(lsites);
|
2017-10-30 00:22:06 +00:00
|
|
|
|
2017-10-09 23:19:45 +01:00
|
|
|
for(int v=0;v<nvector;v++){
|
|
|
|
unvectorizeToLexOrdArray(scalardata,full[v]);
|
2018-01-24 13:40:30 +00:00
|
|
|
thread_loop( (int site=0;site<lsites;site++),{
|
2017-10-09 23:19:45 +01:00
|
|
|
alldata[v*lsites+site] = scalardata[site];
|
2018-01-24 13:40:30 +00:00
|
|
|
});
|
2017-10-09 23:19:45 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
int nvec = nvector; // Counts down to 1 as we collapse dims
|
2018-02-24 22:26:10 +00:00
|
|
|
Coordinate ldims = full_grid->_ldimensions;
|
2017-10-09 23:19:45 +01:00
|
|
|
|
2017-10-30 00:22:06 +00:00
|
|
|
for(int d=ndim-1;d>=0;d--){
|
2017-10-09 23:19:45 +01:00
|
|
|
|
|
|
|
if ( ratio[d] != 1 ) {
|
|
|
|
|
|
|
|
full_grid ->AllToAll(d,alldata,tmpdata);
|
2017-11-27 12:33:08 +00:00
|
|
|
if ( split_grid->_processors[d] > 1 ) {
|
|
|
|
alldata=tmpdata;
|
|
|
|
split_grid->AllToAll(d,alldata,tmpdata);
|
|
|
|
}
|
|
|
|
|
|
|
|
auto rdims = ldims;
|
2017-11-27 15:13:29 +00:00
|
|
|
auto M = ratio[d];
|
2017-11-27 12:33:08 +00:00
|
|
|
auto rsites= lsites*M;// increases rsites by M
|
2017-11-27 15:13:29 +00:00
|
|
|
nvec /= M; // Reduce nvec by subdivision factor
|
|
|
|
rdims[d] *= M; // increase local dim by same factor
|
2017-11-27 12:33:08 +00:00
|
|
|
|
|
|
|
int sP = split_grid->_processors[d];
|
|
|
|
int fP = full_grid->_processors[d];
|
|
|
|
|
|
|
|
int fvol = lsites;
|
2017-11-27 15:13:29 +00:00
|
|
|
|
|
|
|
int chunk = (nvec*fvol)/sP; assert(chunk*sP == nvec*fvol);
|
2017-11-27 12:33:08 +00:00
|
|
|
|
2017-11-27 15:13:29 +00:00
|
|
|
// Loop over reordered data post A2A
|
2018-01-24 13:40:30 +00:00
|
|
|
thread_loop( (int c=0;c<chunk;c++),{
|
2018-02-24 22:26:10 +00:00
|
|
|
Coordinate coor(ndim);
|
2017-11-27 12:33:08 +00:00
|
|
|
for(int m=0;m<M;m++){
|
|
|
|
for(int s=0;s<sP;s++){
|
2017-11-27 15:13:29 +00:00
|
|
|
|
|
|
|
// addressing; use lexico
|
|
|
|
int lex_r;
|
|
|
|
uint64_t lex_c = c+chunk*m+chunk*M*s;
|
|
|
|
uint64_t lex_fvol_vec = c+chunk*s;
|
|
|
|
uint64_t lex_fvol = lex_fvol_vec%fvol;
|
|
|
|
uint64_t lex_vec = lex_fvol_vec/fvol;
|
|
|
|
|
|
|
|
// which node sets an adder to the coordinate
|
|
|
|
Lexicographic::CoorFromIndex(coor, lex_fvol, ldims);
|
|
|
|
coor[d] += m*ldims[d];
|
|
|
|
Lexicographic::IndexFromCoor(coor, lex_r, rdims);
|
|
|
|
lex_r += lex_vec * rsites;
|
|
|
|
|
|
|
|
// LexicoFind coordinate & vector number within split lattice
|
|
|
|
alldata[lex_r] = tmpdata[lex_c];
|
2017-11-27 12:33:08 +00:00
|
|
|
|
2017-10-09 23:19:45 +01:00
|
|
|
}
|
|
|
|
}
|
2018-01-24 13:40:30 +00:00
|
|
|
});
|
2017-10-09 23:19:45 +01:00
|
|
|
ldims[d]*= ratio[d];
|
|
|
|
lsites *= ratio[d];
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
vectorizeFromLexOrdArray(alldata,split);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class Vobj>
|
|
|
|
void Grid_split(Lattice<Vobj> &full,Lattice<Vobj> & split)
|
|
|
|
{
|
2018-01-27 00:04:12 +00:00
|
|
|
int nvector = full.Grid()->_Nprocessors / split.Grid()->_Nprocessors;
|
|
|
|
std::vector<Lattice<Vobj> > full_v(nvector,full.Grid());
|
2017-10-09 23:19:45 +01:00
|
|
|
for(int n=0;n<nvector;n++){
|
|
|
|
full_v[n] = full;
|
|
|
|
}
|
|
|
|
Grid_split(full_v,split);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class Vobj>
|
|
|
|
void Grid_unsplit(std::vector<Lattice<Vobj> > & full,Lattice<Vobj> & split)
|
|
|
|
{
|
|
|
|
typedef typename Vobj::scalar_object Sobj;
|
|
|
|
|
|
|
|
int full_vecs = full.size();
|
|
|
|
|
|
|
|
assert(full_vecs>=1);
|
|
|
|
|
2018-01-27 00:04:12 +00:00
|
|
|
GridBase * full_grid = full[0].Grid();
|
|
|
|
GridBase *split_grid = split.Grid();
|
2017-10-09 23:19:45 +01:00
|
|
|
|
|
|
|
int ndim = full_grid->_ndimension;
|
|
|
|
int full_nproc = full_grid->_Nprocessors;
|
|
|
|
int split_nproc =split_grid->_Nprocessors;
|
|
|
|
|
|
|
|
////////////////////////////////
|
|
|
|
// Checkerboard management
|
|
|
|
////////////////////////////////
|
2018-01-26 23:06:03 +00:00
|
|
|
int cb = full[0].Checkerboard();
|
|
|
|
split.Checkerboard() = cb;
|
2017-10-09 23:19:45 +01:00
|
|
|
|
|
|
|
//////////////////////////////
|
|
|
|
// Checks
|
|
|
|
//////////////////////////////
|
|
|
|
assert(full_grid->_ndimension==split_grid->_ndimension);
|
|
|
|
for(int n=0;n<full_vecs;n++){
|
2018-01-26 23:06:03 +00:00
|
|
|
assert(full[n].Checkerboard() == cb);
|
2017-10-09 23:19:45 +01:00
|
|
|
for(int d=0;d<ndim;d++){
|
2018-01-27 00:04:12 +00:00
|
|
|
assert(full[n].Grid()->_gdimensions[d]==split.Grid()->_gdimensions[d]);
|
|
|
|
assert(full[n].Grid()->_fdimensions[d]==split.Grid()->_fdimensions[d]);
|
2017-10-09 23:19:45 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int nvector =full_nproc/split_nproc;
|
|
|
|
assert(nvector*split_nproc==full_nproc);
|
|
|
|
assert(nvector == full_vecs);
|
|
|
|
|
2018-02-24 22:26:10 +00:00
|
|
|
Coordinate ratio(ndim);
|
2017-10-09 23:19:45 +01:00
|
|
|
for(int d=0;d<ndim;d++){
|
|
|
|
ratio[d] = full_grid->_processors[d]/ split_grid->_processors[d];
|
|
|
|
}
|
|
|
|
|
2017-10-27 14:20:35 +01:00
|
|
|
uint64_t lsites = full_grid->lSites();
|
|
|
|
uint64_t sz = lsites * nvector;
|
2017-10-09 23:19:45 +01:00
|
|
|
std::vector<Sobj> tmpdata(sz);
|
|
|
|
std::vector<Sobj> alldata(sz);
|
|
|
|
std::vector<Sobj> scalardata(lsites);
|
|
|
|
|
|
|
|
unvectorizeToLexOrdArray(alldata,split);
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
// Start from split grid and work towards full grid
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
int nvec = 1;
|
2017-11-27 12:33:08 +00:00
|
|
|
uint64_t rsites = split_grid->lSites();
|
2018-02-24 22:26:10 +00:00
|
|
|
Coordinate rdims = split_grid->_ldimensions;
|
2017-10-09 23:19:45 +01:00
|
|
|
|
2017-10-30 00:22:06 +00:00
|
|
|
for(int d=0;d<ndim;d++){
|
2017-10-09 23:19:45 +01:00
|
|
|
|
|
|
|
if ( ratio[d] != 1 ) {
|
|
|
|
|
2017-11-27 15:13:29 +00:00
|
|
|
auto M = ratio[d];
|
2017-10-30 00:22:06 +00:00
|
|
|
|
2017-11-27 15:13:29 +00:00
|
|
|
int sP = split_grid->_processors[d];
|
|
|
|
int fP = full_grid->_processors[d];
|
|
|
|
|
|
|
|
auto ldims = rdims; ldims[d] /= M; // Decrease local dims by same factor
|
|
|
|
auto lsites= rsites/M; // Decreases rsites by M
|
|
|
|
|
|
|
|
int fvol = lsites;
|
|
|
|
int chunk = (nvec*fvol)/sP; assert(chunk*sP == nvec*fvol);
|
2017-11-27 12:33:08 +00:00
|
|
|
|
2017-11-27 15:13:29 +00:00
|
|
|
{
|
|
|
|
// Loop over reordered data post A2A
|
2018-01-24 13:40:30 +00:00
|
|
|
thread_loop( (int c=0;c<chunk;c++),{
|
2018-02-24 22:26:10 +00:00
|
|
|
Coordinate coor(ndim);
|
2017-11-27 12:33:08 +00:00
|
|
|
for(int m=0;m<M;m++){
|
|
|
|
for(int s=0;s<sP;s++){
|
2017-12-05 11:39:26 +00:00
|
|
|
|
2017-11-27 15:13:29 +00:00
|
|
|
// addressing; use lexico
|
|
|
|
int lex_r;
|
|
|
|
uint64_t lex_c = c+chunk*m+chunk*M*s;
|
|
|
|
uint64_t lex_fvol_vec = c+chunk*s;
|
|
|
|
uint64_t lex_fvol = lex_fvol_vec%fvol;
|
|
|
|
uint64_t lex_vec = lex_fvol_vec/fvol;
|
2017-11-27 12:33:08 +00:00
|
|
|
|
2017-11-27 15:13:29 +00:00
|
|
|
// which node sets an adder to the coordinate
|
|
|
|
Lexicographic::CoorFromIndex(coor, lex_fvol, ldims);
|
|
|
|
coor[d] += m*ldims[d];
|
|
|
|
Lexicographic::IndexFromCoor(coor, lex_r, rdims);
|
|
|
|
lex_r += lex_vec * rsites;
|
2017-11-27 12:33:08 +00:00
|
|
|
|
2017-11-27 15:13:29 +00:00
|
|
|
// LexicoFind coordinate & vector number within split lattice
|
|
|
|
tmpdata[lex_c] = alldata[lex_r];
|
2017-11-27 12:33:08 +00:00
|
|
|
}
|
2017-10-09 23:19:45 +01:00
|
|
|
}
|
2018-01-24 13:40:30 +00:00
|
|
|
});
|
2017-11-27 15:13:29 +00:00
|
|
|
}
|
2017-10-09 23:19:45 +01:00
|
|
|
|
2017-11-27 15:13:29 +00:00
|
|
|
if ( split_grid->_processors[d] > 1 ) {
|
|
|
|
split_grid->AllToAll(d,tmpdata,alldata);
|
|
|
|
tmpdata=alldata;
|
2017-11-27 12:33:08 +00:00
|
|
|
}
|
2017-11-27 15:13:29 +00:00
|
|
|
full_grid ->AllToAll(d,tmpdata,alldata);
|
|
|
|
rdims[d]/= M;
|
|
|
|
rsites /= M;
|
|
|
|
nvec *= M; // Increase nvec by subdivision factor
|
2017-10-09 23:19:45 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
lsites = full_grid->lSites();
|
|
|
|
for(int v=0;v<nvector;v++){
|
2017-12-05 11:39:26 +00:00
|
|
|
// assert(v<full.size());
|
2018-01-24 13:40:30 +00:00
|
|
|
thread_loop( (int site=0;site<lsites;site++),{
|
2017-12-05 11:39:26 +00:00
|
|
|
// assert(v*lsites+site < alldata.size());
|
2017-10-09 23:19:45 +01:00
|
|
|
scalardata[site] = alldata[v*lsites+site];
|
2018-01-24 13:40:30 +00:00
|
|
|
});
|
2017-10-09 23:19:45 +01:00
|
|
|
vectorizeFromLexOrdArray(scalardata,full[v]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-14 23:54:25 +00:00
|
|
|
NAMESPACE_END(Grid);
|
2015-04-18 20:44:19 +01:00
|
|
|
#endif
|