mirror of
https://github.com/paboyle/Grid.git
synced 2025-11-06 14:49:32 +00:00
Now have ability to do Vertex AND Edge grids Should now have no barriers to a) Double Storing links for fermion operators / laplacian b) Laplace or Wilson operators
989 lines
33 KiB
C++
989 lines
33 KiB
C++
/*************************************************************************************
|
|
|
|
Grid physics library, www.github.com/paboyle/Grid
|
|
|
|
Source file: ./lib/GeneralLocalStencil.h
|
|
|
|
Copyright (C) 2019
|
|
|
|
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
|
|
*************************************************************************************/
|
|
/* END LEGAL */
|
|
#pragma once
|
|
NAMESPACE_BEGIN(Grid);
|
|
|
|
// Share with Cartesian Stencil
|
|
struct IcosahedralStencilEntry {
|
|
uint64_t _offset; // 8 bytes
|
|
uint8_t _is_local; // is this with our lattice array (else in a comms buf)
|
|
uint8_t _adjoint; // is this with our lattice array (else in a comms buf)
|
|
uint8_t _polarisation; // which lorentz index on the neighbours patch
|
|
uint8_t _missing_link; //
|
|
};
|
|
|
|
enum IcoshedralDirections {
|
|
IcosahedronPatchX = 0,
|
|
IcosahedronPatchY = 1,
|
|
IcosahedronPatchDiagonal=2,
|
|
IcosahedronTime=3
|
|
};
|
|
|
|
inline int periAdd(int A,int inc,int L) { return (A+inc+L)%L ; }
|
|
|
|
class IcosahedralStencilView {
|
|
public:
|
|
////////////////////////////////////////
|
|
// Basic Grid and stencil info
|
|
////////////////////////////////////////
|
|
int _npoints; // Move to template param?
|
|
IcosahedralStencilEntry* _entries_p;
|
|
|
|
accelerator_inline IcosahedralStencilEntry * GetEntry(int point,int osite) const {
|
|
return & this->_entries_p[point+this->_npoints*osite];
|
|
}
|
|
void ViewClose(void){};
|
|
};
|
|
|
|
////////////////////////////////////////
|
|
// The Stencil Class itself
|
|
////////////////////////////////////////
|
|
class IcosahedralStencil : public IcosahedralStencilView {
|
|
public:
|
|
typedef IcosahedralStencilView View_type;
|
|
|
|
protected:
|
|
GridBase * _grid;
|
|
|
|
public:
|
|
GridBase *Grid(void) const { return _grid; }
|
|
|
|
View_type View(int mode) const {
|
|
View_type accessor(*( (View_type *) this));
|
|
return accessor;
|
|
}
|
|
// NB x+, y+ is ALWAYS present, as are the forward 3 directions for links owned by each site
|
|
//
|
|
// These are VERTEX mesh neigbours being returned, with isPole indicating we need N/S pole according to
|
|
// hemisphere.
|
|
//
|
|
// If needing edge mesh "neigbours" to assemble loops we must find the mapping of a forward link
|
|
// to a corresponding "backward link" on the pole
|
|
deviceVector<IcosahedralStencilEntry> _entries;
|
|
|
|
void GetNbrForPlusX(GridBase *grid,Coordinate &Coor,Coordinate &NbrCoor, int &isPole)
|
|
{
|
|
int nd = grid->Nd();
|
|
int L = grid->LocalDimensions()[0];
|
|
assert (grid->LocalDimensions()[0] == grid->LocalDimensions()[1]);
|
|
int patch = Coor[nd-1];
|
|
int north = patch/HemiPatches;
|
|
int south = 1-north;
|
|
int HemiPatch = patch%HemiPatches;
|
|
int NbrPatch;
|
|
|
|
NbrCoor = Coor;
|
|
isPole = 0;
|
|
if ( Coor[0]<(L-1) ) {
|
|
NbrCoor[0]=Coor[0]+1;
|
|
// Nbr is inside THIS patch
|
|
return;
|
|
}
|
|
if ( north ) {
|
|
assert(Coor[0]==(L-1));
|
|
// Simple connect to southern neighbour tile
|
|
NbrCoor[0]=0;
|
|
NbrCoor[nd-1]=periAdd(HemiPatch,+1,HemiPatches) + SouthernHemisphere;
|
|
return;
|
|
}
|
|
////////////////////////////////////////////////////////////
|
|
// FIXME:
|
|
// Can store the rotation of polarisation here: get xdir instead of ydir and must take adjoint
|
|
////////////////////////////////////////////////////////////
|
|
if ( south ) {
|
|
assert(Coor[0]==(L-1));
|
|
if ( Coor[1] == 0 ) {
|
|
isPole = 1;
|
|
NbrCoor[0] = (L-1); // Coordinate of the edge graph site holding the edge for other vertex in pole triangle
|
|
NbrCoor[1] = 0;
|
|
NbrCoor[nd-1]=periAdd(HemiPatch,+1,HemiPatches) + SouthernHemisphere;
|
|
return;
|
|
} else {
|
|
NbrCoor[1] = 0;
|
|
NbrCoor[0] = L-Coor[1];
|
|
NbrCoor[nd-1]=periAdd(HemiPatch,+1,HemiPatches) + SouthernHemisphere;
|
|
return;
|
|
}
|
|
}
|
|
assert(0);
|
|
}
|
|
void GetNbrForPlusY(GridBase *grid,Coordinate &Coor,Coordinate &NbrCoor, int &isPole)
|
|
{
|
|
int nd = grid->Nd();
|
|
int L = grid->LocalDimensions()[0];
|
|
assert (grid->LocalDimensions()[0] == grid->LocalDimensions()[1]);
|
|
int patch = Coor[nd-1];
|
|
int north = patch/HemiPatches;
|
|
int south = 1-north;
|
|
int HemiPatch = patch%HemiPatches;
|
|
int NbrPatch;
|
|
|
|
NbrCoor = Coor;
|
|
isPole = 0;
|
|
if ( Coor[1]<(L-1) ) {
|
|
NbrCoor[1]=Coor[1]+1;
|
|
// Nbr is inside THIS patch
|
|
return;
|
|
}
|
|
if ( south ) {
|
|
// Simple connect to northern neighbour tile
|
|
assert(Coor[1]==(L-1));
|
|
NbrCoor[1]=0;
|
|
NbrCoor[nd-1]=HemiPatch + NorthernHemisphere;
|
|
return;
|
|
}
|
|
////////////////////////////////////////////////////////////
|
|
// FIXME:
|
|
// Could store the rotation of polarisation here: get xdir instead of ydir and must take adjoint
|
|
// But probaby just write "getLinkPropertiesToCloseTriangleA" "getLinkPropertiesToCloseTriangleB"
|
|
// Or write a 'double store' method to move edge graph to a vertex graph with all fermion transports
|
|
////////////////////////////////////////////////////////////
|
|
if ( north ) {
|
|
assert(Coor[1]==(L-1));
|
|
if ( Coor[0] == 0 ) {
|
|
isPole = 1;
|
|
NbrCoor[1] = (L-1); // Coordinate of the edge graph site holding the edge for other vertex in pole triangle
|
|
NbrCoor[0] = 0;
|
|
NbrCoor[nd-1]=periAdd(HemiPatch,+1,HemiPatches) + NorthernHemisphere;
|
|
return;
|
|
} else {
|
|
NbrCoor[0] = 0;
|
|
NbrCoor[1] = L-Coor[0]; // x=1 --> y=L-1 for y+
|
|
NbrCoor[nd-1]=periAdd(HemiPatch,+1,HemiPatches) + NorthernHemisphere;
|
|
return;
|
|
}
|
|
}
|
|
assert(0);
|
|
}
|
|
// Missing links are at (0,0) on local patch coordinates in -diagonal direction
|
|
// We are here returning VERTEX grid coordinates.
|
|
void GetNbrForMinusX(GridBase *grid,Coordinate &Coor,Coordinate &NbrCoor)
|
|
{
|
|
int nd = grid->Nd();
|
|
int L = grid->LocalDimensions()[0];
|
|
assert (grid->LocalDimensions()[0] == grid->LocalDimensions()[1]);
|
|
int patch = Coor[nd-1];
|
|
int north = patch/HemiPatches;
|
|
int south = 1-north;
|
|
int HemiPatch = patch%HemiPatches;
|
|
int NbrPatch;
|
|
|
|
NbrCoor = Coor;
|
|
if ( Coor[0]>0 ) {
|
|
NbrCoor[0]=Coor[0]-1;
|
|
return;
|
|
}
|
|
if ( south ) {
|
|
assert(Coor[0]==0);
|
|
// Simple connect to northern neighbour tile
|
|
NbrCoor[0]=L-1;
|
|
NbrCoor[nd-1]=periAdd(HemiPatch,-1,HemiPatches) + NorthernHemisphere;
|
|
return;
|
|
}
|
|
if ( north ) {
|
|
NbrCoor[0] = L-1-Coor[1];
|
|
NbrCoor[1] = L-1;
|
|
NbrCoor[nd-1]=periAdd(HemiPatch,-1,HemiPatches) + NorthernHemisphere;
|
|
return;
|
|
}
|
|
assert(0);
|
|
}
|
|
|
|
void GetNbrForMinusY(GridBase *grid,Coordinate &Coor,Coordinate &NbrCoor)
|
|
{
|
|
int nd = grid->Nd();
|
|
int L = grid->LocalDimensions()[0];
|
|
assert (grid->LocalDimensions()[0] == grid->LocalDimensions()[1]);
|
|
int patch = Coor[nd-1];
|
|
int north = patch/HemiPatches;
|
|
int south = 1-north;
|
|
int HemiPatch = patch%HemiPatches;
|
|
int NbrPatch;
|
|
|
|
NbrCoor = Coor;
|
|
if ( Coor[1]>0 ) {
|
|
NbrCoor[1]=Coor[1]-1;
|
|
return;
|
|
}
|
|
if ( north ) {
|
|
assert(Coor[1]==0);
|
|
// Simple connect to northern neighbour tile
|
|
NbrCoor[1]=L-1;
|
|
NbrCoor[nd-1]=HemiPatch + SouthernHemisphere;
|
|
return;
|
|
}
|
|
if ( south ) {
|
|
NbrCoor[1] = L-1-Coor[0];
|
|
NbrCoor[0] = L-1;
|
|
NbrCoor[nd-1]=periAdd(HemiPatch,-1,HemiPatches) + SouthernHemisphere;
|
|
return;
|
|
}
|
|
assert(0);
|
|
}
|
|
void GetNbrForMinusDiagonal(GridBase *grid,Coordinate &Coor,Coordinate &NbrCoor,int &missingLink)
|
|
{
|
|
int nd = grid->Nd();
|
|
int L = grid->LocalDimensions()[0];
|
|
assert (grid->LocalDimensions()[0] == grid->LocalDimensions()[1]);
|
|
int patch = Coor[nd-1];
|
|
int north = patch/HemiPatches;
|
|
int south = 1-north;
|
|
int HemiPatch = patch%HemiPatches;
|
|
int NbrPatch;
|
|
|
|
NbrCoor = Coor;
|
|
|
|
missingLink = 0;
|
|
if( Coor[0]==0 && Coor[1]==0) {
|
|
missingLink=1;
|
|
return;
|
|
}
|
|
if ( (Coor[0]>0) && (Coor[1]>0) ) {
|
|
// Nbr is inside THIS patch
|
|
NbrCoor[0]=Coor[0]-1;
|
|
NbrCoor[1]=Coor[1]-1;
|
|
return;
|
|
}
|
|
if ( north ) {
|
|
if ( Coor[0]==0 ) {
|
|
// We are on -x edge
|
|
// Maps to +y edge of hemipatch to the left
|
|
NbrCoor[nd-1] = periAdd(HemiPatch,-1,HemiPatches) + NorthernHemisphere;
|
|
NbrCoor[0]=(L-Coor[1]);
|
|
NbrCoor[1]=(L-1);
|
|
return;
|
|
} else {
|
|
// We are on the -y edge and NOT bottom left corner; Nbr is in the patch LEFT
|
|
assert( (Coor[0]>0) && (Coor[1]==0) );
|
|
NbrCoor[nd-1] = HemiPatch + SouthernHemisphere; // Map from north to south
|
|
NbrCoor[0]=Coor[0]-1;
|
|
NbrCoor[1]=(L-1);
|
|
return;
|
|
}
|
|
assert(0);
|
|
}
|
|
if ( south ) {
|
|
// We are on the -y edge
|
|
if ( Coor[1]==0 ) {
|
|
NbrCoor[nd-1] = periAdd(HemiPatch,-1,HemiPatches) + SouthernHemisphere;
|
|
NbrCoor[0]=(L-1);
|
|
NbrCoor[1]=(L-Coor[0]);
|
|
return;
|
|
} else {
|
|
// We are on the -x edge and NOT bottom left corner; Nbr is in the patch LEFT
|
|
assert( (Coor[0]==0) && (Coor[1]>0) );
|
|
NbrCoor[nd-1] = periAdd(HemiPatch,-1,HemiPatches) + NorthernHemisphere; // south to north
|
|
NbrCoor[0]=(L-1);
|
|
NbrCoor[1]= Coor[1]-1;
|
|
return;
|
|
}
|
|
assert(0);
|
|
}
|
|
assert(0);
|
|
}
|
|
void GetNbrForPlusDiagonal(GridBase *grid,Coordinate &Coor,Coordinate &NbrCoor)
|
|
{
|
|
int nd = grid->Nd();
|
|
int L = grid->LocalDimensions()[0];
|
|
assert (grid->LocalDimensions()[0] == grid->LocalDimensions()[1]);
|
|
int patch = Coor[nd-1];
|
|
int north = patch/HemiPatches;
|
|
int south = 1-north;
|
|
int HemiPatch = patch%HemiPatches;
|
|
int NbrPatch;
|
|
|
|
NbrCoor = Coor;
|
|
|
|
if ( (Coor[0]<L-1) && (Coor[1]<L-1) ) {
|
|
// Nbr is inside THIS patch
|
|
NbrCoor[0]=Coor[0]+1;
|
|
NbrCoor[1]=Coor[1]+1;
|
|
return;
|
|
}
|
|
|
|
if ( north ) {
|
|
// We are on +y edge
|
|
if ( Coor[1]==(L-1) ) {
|
|
NbrCoor[nd-1] = periAdd(HemiPatch,+1,HemiPatches) + NorthernHemisphere;
|
|
NbrCoor[0]=0;
|
|
NbrCoor[1]=(L-1)-Coor[0];
|
|
return;
|
|
} else {
|
|
// Else we are on the +x edge, not top right corner
|
|
assert( Coor[0]==(L-1) && Coor[1]<(L-1) );
|
|
NbrCoor[nd-1] = periAdd(HemiPatch,+1,HemiPatches) + SouthernHemisphere;
|
|
NbrCoor[0]=0;
|
|
NbrCoor[1]=Coor[1]+1;
|
|
return;
|
|
}
|
|
assert(0);
|
|
}
|
|
|
|
if ( south ) {
|
|
// We are on the +x edge
|
|
if ( Coor[0]==(L-1) ) {
|
|
NbrCoor[nd-1] = periAdd(HemiPatch,+1,HemiPatches) + SouthernHemisphere;
|
|
NbrCoor[0]=(L-1)-Coor[1]; //y=(L-1) <-> x=0 ; y=0<->x=(L-1) [ Sanity check ]
|
|
NbrCoor[1]=0;
|
|
return;
|
|
} else {
|
|
// We are on the +y edge and NOT top right corner; Nbr is in the patch UP
|
|
assert( (Coor[1]==L-1) && (Coor[0]<(L-1)) );
|
|
NbrCoor[nd-1] = HemiPatch + NorthernHemisphere;
|
|
NbrCoor[0]=Coor[0]+1;
|
|
NbrCoor[1]=0;
|
|
return;
|
|
}
|
|
assert(0);
|
|
}
|
|
assert(0);
|
|
}
|
|
|
|
void TestGeometry(void)
|
|
{
|
|
GridBase *grid = this->_grid;
|
|
uint64_t cart_sites = grid->CartesianOsites();
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////
|
|
// Loop over cart sites.
|
|
// Find two triangles per site.
|
|
// Check going forward in X, Up and forward in Diag match
|
|
// Check going Up, forward in X and forward Diag match; subtleties at poles and rotation in cross patch
|
|
//////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
std::cout << GridLogMessage<< "*************************************"<<std::endl;
|
|
std::cout << GridLogMessage<< " Icosahedral Stencil Geometry Test !"<<std::endl;
|
|
std::cout << GridLogMessage<< "*************************************"<<std::endl;
|
|
|
|
const int triangle_ref = cart_sites;
|
|
std::cout << GridLogMessage<< " Base triangle count for each type " <<triangle_ref;
|
|
|
|
std::cout << GridLogMessage<< "------------------------------------"<<std::endl;
|
|
std::cout << GridLogMessage<< "testing +x+y vs +diag"<<std::endl;
|
|
std::cout << GridLogMessage<< "testing +y+x vs +diag"<<std::endl;
|
|
std::cout << GridLogMessage<< "------------------------------------"<<std::endl;
|
|
int xyd_pole_count=0;
|
|
int xyd_count=0;
|
|
int yxd_pole_count=0;
|
|
int yxd_count=0;
|
|
for(uint64_t site=0;site<cart_sites; site ++) {
|
|
|
|
Coordinate Coor;
|
|
Coordinate DiagCoor;
|
|
|
|
int nd = grid->Nd();
|
|
int L = grid->LocalDimensions()[0];
|
|
|
|
grid->oCoorFromOindex(Coor,site);
|
|
|
|
int patch = Coor[nd-1];
|
|
int north = patch/HemiPatches;
|
|
int south = 1-north;
|
|
int isPole = 0;
|
|
int discard;
|
|
int missingLink = 0;
|
|
|
|
int HemiPatch = patch%HemiPatches;
|
|
|
|
//////////////////////////////
|
|
// First test of triangle
|
|
//////////////////////////////
|
|
// Compare +x, +y to +diag
|
|
Coordinate XpCoor;
|
|
Coordinate YpXpCoor;
|
|
GetNbrForPlusDiagonal(grid,Coor,DiagCoor);
|
|
GetNbrForPlusX(grid,Coor,XpCoor,isPole);
|
|
|
|
int XpHemiPatch = XpCoor[nd-1]%HemiPatches;
|
|
int XpHemisphere = XpCoor[nd-1]/HemiPatches;
|
|
|
|
if (isPole) {
|
|
YpXpCoor = XpCoor;
|
|
} else if ( XpHemiPatch != HemiPatch && south ) {
|
|
GetNbrForMinusX(grid,XpCoor,YpXpCoor);
|
|
} else {
|
|
GetNbrForPlusY(grid,XpCoor,YpXpCoor,discard);
|
|
}
|
|
|
|
if(isPole) {
|
|
std::cout << GridLogDebug<<"Forward xyd triangle "<<Coor<<"-Pole["<<XpCoor[2]<<"]-"<<YpXpCoor<<" should be " <<DiagCoor<<std::endl;
|
|
xyd_pole_count++;
|
|
} else {
|
|
std::cout << GridLogDebug<<"Forward xyd triangle "<<Coor<<"-"<<XpCoor<<"-"<<YpXpCoor<<" should be " <<DiagCoor<<std::endl;
|
|
xyd_count++;
|
|
}
|
|
for(int d=0;d<DiagCoor.size();d++) {
|
|
assert(DiagCoor[d]==YpXpCoor[d]);
|
|
}
|
|
|
|
Coordinate YpCoor;
|
|
Coordinate XpYpCoor;
|
|
GetNbrForPlusDiagonal(grid,Coor,DiagCoor);
|
|
GetNbrForPlusY(grid,Coor,YpCoor,isPole);
|
|
|
|
int YpHemiPatch = YpCoor[nd-1]%HemiPatches;
|
|
int YpHemisphere = YpCoor[nd-1]/HemiPatches;
|
|
|
|
if(isPole) {
|
|
XpYpCoor = YpCoor;
|
|
} else if ( YpHemiPatch != HemiPatch && north ) {
|
|
GetNbrForMinusY(grid,YpCoor,XpYpCoor); // we hopped - this rotates the directions
|
|
} else {
|
|
GetNbrForPlusX(grid,YpCoor,XpYpCoor,discard);
|
|
}
|
|
|
|
if(isPole) {
|
|
yxd_pole_count++;
|
|
std::cout << GridLogDebug<<"Forward yxd triangle "<<Coor<<"-Pole["<<YpCoor[2]<<"]-"<<XpYpCoor<<" should be " <<DiagCoor<<std::endl;
|
|
} else {
|
|
yxd_count++;
|
|
std::cout <<GridLogDebug << "Forward yxd triangle "<<Coor<<"-"<<YpCoor<<"-"<<XpYpCoor<<" should be " <<DiagCoor<<std::endl;
|
|
}
|
|
for(int d=0;d<DiagCoor.size();d++) {
|
|
assert(DiagCoor[d]==XpYpCoor[d]);
|
|
}
|
|
}
|
|
std::cout << GridLogMessage<< " xyd_count "<<xyd_count<<" + poles_count "<<xyd_pole_count<<" expect "<<triangle_ref<<" triangles "<<std::endl;
|
|
std::cout << GridLogMessage<<" yxd_count "<<yxd_count<<" + poles_count "<<yxd_pole_count<<" expect "<<triangle_ref<<" triangles "<<std::endl;
|
|
assert(xyd_count+xyd_pole_count == triangle_ref);
|
|
assert(yxd_count+yxd_pole_count == triangle_ref);
|
|
std::cout << GridLogMessage<< "------------------------------------"<<std::endl;
|
|
std::cout << GridLogMessage<< "testing -diag +x+y = identity"<<std::endl;
|
|
std::cout << GridLogMessage<< "testing -diag +y+x = identity"<<std::endl;
|
|
std::cout << GridLogMessage<< "------------------------------------"<<std::endl;
|
|
|
|
int dmxy_count=0;
|
|
int dmyx_count=0;
|
|
int dmxy_count_special=0;
|
|
int dmyx_count_special=0;
|
|
int num_missing=0;
|
|
|
|
for(uint64_t site=0;site<cart_sites; site ++) {
|
|
|
|
Coordinate Coor;
|
|
|
|
int nd = grid->Nd();
|
|
int L = grid->LocalDimensions()[0];
|
|
|
|
grid->oCoorFromOindex(Coor,site);
|
|
|
|
int patch = Coor[nd-1];
|
|
int north = patch/HemiPatches;
|
|
int south = 1-north;
|
|
int isPole = 0;
|
|
int discard;
|
|
int missingLink = 0;
|
|
int HemiPatch = patch%HemiPatches;
|
|
|
|
Coordinate DmCoor;
|
|
GetNbrForMinusDiagonal(grid,Coor,DmCoor,missingLink);
|
|
if ( missingLink ) {
|
|
std::cout << GridLogDebug<< Coor << " has no backwards diagonal link "<<std::endl;
|
|
num_missing++;
|
|
} else {
|
|
|
|
int DmPatch = DmCoor[nd-1];
|
|
int DmHemiPatch = DmCoor[nd-1]%HemiPatches;
|
|
int DmHemisphere = DmCoor[nd-1]/HemiPatches;
|
|
|
|
Coordinate XpDmCoor;
|
|
Coordinate YpXpDmCoor;
|
|
|
|
Coordinate YpDmCoor;
|
|
Coordinate XpYpDmCoor;
|
|
|
|
if ( DmHemiPatch != HemiPatch && north ) {
|
|
GetNbrForPlusDiagonal(grid,DmCoor,XpDmCoor);
|
|
GetNbrForPlusY(grid,XpDmCoor,YpXpDmCoor,isPole); assert(!isPole);
|
|
|
|
GetNbrForMinusX(grid,DmCoor,YpDmCoor);
|
|
GetNbrForPlusDiagonal(grid,YpDmCoor,XpYpDmCoor);
|
|
dmxy_count_special++;
|
|
dmyx_count_special++;
|
|
} else if ( DmPatch == periAdd(HemiPatch,-1,HemiPatches) && south ) {
|
|
GetNbrForPlusDiagonal(grid,DmCoor,YpDmCoor);
|
|
GetNbrForPlusX(grid,YpDmCoor,XpYpDmCoor,isPole); assert(!isPole);
|
|
|
|
GetNbrForMinusY(grid,DmCoor,XpDmCoor);
|
|
GetNbrForPlusDiagonal(grid,XpDmCoor,YpXpDmCoor);
|
|
dmxy_count_special++;
|
|
dmyx_count_special++;
|
|
} else {
|
|
GetNbrForPlusX(grid,DmCoor,XpDmCoor,isPole); assert(!isPole);
|
|
GetNbrForPlusY(grid,XpDmCoor,YpXpDmCoor,isPole); assert(!isPole);
|
|
|
|
GetNbrForPlusY(grid,DmCoor,YpDmCoor,isPole); assert(!isPole);
|
|
GetNbrForPlusX(grid,YpDmCoor,XpYpDmCoor,isPole); assert(!isPole);
|
|
dmxy_count++;
|
|
dmyx_count++;
|
|
}
|
|
std::cout<< GridLogDebug << Coor<<" DmXpYp triangle YpXpDm"<<YpXpDmCoor<<"-XpDm"<<XpDmCoor<<"-Dm"<<DmCoor<<" should be " <<Coor<<std::endl;
|
|
for(int d=0;d<Coor.size();d++) {
|
|
assert(Coor[d]==YpXpDmCoor[d]);
|
|
}
|
|
|
|
std::cout << GridLogDebug<< Coor<<"DmXpYp triangle XpYpDm"<<XpYpDmCoor<<"-YpDm"<<YpDmCoor<<"-Dm"<<DmCoor<<" should be " <<Coor<<std::endl;
|
|
for(int d=0;d<Coor.size();d++) {
|
|
assert(Coor[d]==XpYpDmCoor[d]);
|
|
}
|
|
}
|
|
}
|
|
std::cout <<GridLogMessage<<" dmxy_count "<<dmxy_count<<" + special "<<dmxy_count_special<<" + missing "<<num_missing<<" expect "<<triangle_ref<<" triangles "<<std::endl;
|
|
std::cout <<GridLogMessage<<" dmyx_count "<<dmyx_count<<" + special "<<dmyx_count_special<<" + missing "<<num_missing<<" expect "<<triangle_ref<<" triangles "<<std::endl;
|
|
assert(dmxy_count + dmxy_count_special + num_missing == triangle_ref);
|
|
assert(dmyx_count + dmyx_count_special + num_missing == triangle_ref);
|
|
|
|
std::cout << GridLogMessage<< "------------------------------------"<<std::endl;
|
|
std::cout << GridLogMessage<< "NOT testing diag -x-y = identity "<<std::endl;
|
|
std::cout << GridLogMessage<< "NOT testing diag -y-x = identity"<<std::endl;
|
|
std::cout << GridLogMessage<< "------------------------------------"<<std::endl;
|
|
|
|
std::cout << GridLogMessage<< "------------------------------------"<<std::endl;
|
|
std::cout << GridLogMessage<< "NOT testing -diag = -x-y "<<std::endl;
|
|
std::cout << GridLogMessage<< "NOT testing -diag = -y-x "<<std::endl;
|
|
std::cout << GridLogMessage<< "------------------------------------"<<std::endl;
|
|
|
|
std::cout << GridLogMessage<< "*************************************"<<std::endl;
|
|
std::cout << GridLogMessage<< " Icosahedral Stencil Geometry Test Complete"<<std::endl;
|
|
std::cout << GridLogMessage<< "*************************************"<<std::endl;
|
|
}
|
|
IcosahedralStencil(GridBase *grid) // Must be +1 or -1
|
|
{
|
|
this->_grid = grid;
|
|
// Loop over L^2 x T x npatch and the
|
|
assert(grid->isIcosahedral());
|
|
}
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// VertexInputs = true implies the neighbour has vertex support
|
|
// VertexInputs = false implies the neighbout has edge support
|
|
//
|
|
// isVertex implies must generate stencil entries to evaluate result on north/south pole
|
|
//
|
|
// These are independent:
|
|
// can apply a vertex support gauge transform to edge supported gauge field
|
|
// can apply a vertex supported link double store to edge supported gauge field
|
|
// can apply a vertex supported laplace or dirac operator vertex supported matter field
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
void NearestNeighbourStencil(int vertexOutputs)
|
|
{
|
|
GridBase * grid = this->_grid;
|
|
|
|
int vertexInputs = grid->isIcosahedralVertex();
|
|
|
|
int osites = grid->oSites();
|
|
|
|
uint64_t cart_sites = grid->CartesianOsites();
|
|
uint64_t Npole_sites = grid->NorthPoleOsites();
|
|
uint64_t Spole_sites = grid->SouthPoleOsites();
|
|
Coordinate pcoor = grid->ThisProcessorCoor();
|
|
Coordinate pgrid = grid->ProcessorGrid();
|
|
/*
|
|
* resize the stencil entries array and set npoints
|
|
*/
|
|
const int np=6;
|
|
this->_npoints=np; // Move to template param?
|
|
this->_entries.resize(this->_npoints * cart_sites);
|
|
this->_entries_p = &_entries[0];
|
|
|
|
int nd = grid->Nd();
|
|
int L = grid->LocalDimensions()[0];
|
|
|
|
for(uint64_t site=0;site<cart_sites; site ++) {
|
|
|
|
Coordinate Coor;
|
|
Coordinate NbrCoor;
|
|
|
|
|
|
Integer lexXp = site*np ;
|
|
Integer lexYp = site*np+1;
|
|
Integer lexDp = site*np+2;
|
|
Integer lexXm = site*np+3;
|
|
Integer lexYm = site*np+4;
|
|
Integer lexDm = site*np+5;
|
|
|
|
IcosahedralStencilEntry SE;
|
|
|
|
////////////////////////////////////////////////
|
|
// Outer index of neighbour Offset calculation
|
|
////////////////////////////////////////////////
|
|
grid->oCoorFromOindex(Coor,site);
|
|
NbrCoor = Coor;
|
|
assert( grid->LocalDimensions()[1]==grid->LocalDimensions()[0]);
|
|
assert( grid->_simd_layout[0]==1); // Cannot vectorise in these dims
|
|
assert( grid->_simd_layout[1]==1);
|
|
assert( grid->_processors[0]==1); // Cannot mpi distribute in these dims
|
|
assert( grid->_processors[1]==1);
|
|
|
|
int Patch = Coor[nd-1];
|
|
int HemiPatch = Patch%HemiPatches;
|
|
int north = Patch/HemiPatches;
|
|
int south = 1-north;
|
|
int isPoleY;
|
|
int isPoleX;
|
|
int missingLink;
|
|
assert(Patch<IcosahedralPatches);
|
|
assert((north==1)||(south==1));
|
|
|
|
/*
|
|
* Just get all six neighbours (if present).
|
|
*/
|
|
Coordinate XpCoor;
|
|
Coordinate YpCoor;
|
|
Coordinate DpCoor;
|
|
Coordinate XmCoor;
|
|
Coordinate YmCoor;
|
|
Coordinate DmCoor;
|
|
|
|
GetNbrForPlusDiagonal(grid,Coor,DpCoor);
|
|
GetNbrForPlusX(grid,Coor,XpCoor,isPoleX);
|
|
GetNbrForPlusY(grid,Coor,YpCoor,isPoleY);
|
|
|
|
GetNbrForMinusDiagonal(grid,Coor,DmCoor,missingLink);
|
|
GetNbrForMinusX(grid,Coor,XmCoor);
|
|
GetNbrForMinusY(grid,Coor,YmCoor);
|
|
|
|
int DpPatch = DpCoor[nd-1];
|
|
int DpHemiPatch = DpCoor[nd-1]%HemiPatches;
|
|
int DpHemisphere = DpCoor[nd-1]/HemiPatches;
|
|
|
|
int YpHemiPatch = YpCoor[nd-1]%HemiPatches;
|
|
int XpHemiPatch = XpCoor[nd-1]%HemiPatches;
|
|
// For negative direction cannot use the Diagonal link
|
|
// as this may not be present on the 5-points
|
|
// Makes for a hemisphere dependent behaviour
|
|
int XmHemiPatch = XmCoor[nd-1]%HemiPatches;
|
|
int XmHemisphere = XmCoor[nd-1]/HemiPatches;
|
|
int YmHemiPatch = YmCoor[nd-1]%HemiPatches;
|
|
int YmHemisphere = YmCoor[nd-1]/HemiPatches;
|
|
|
|
if ( vertexInputs ) {
|
|
////////////////////////////////////////////////
|
|
// XpCoor stencil entry; consider isPole case
|
|
////////////////////////////////////////////////
|
|
SE._is_local = true;
|
|
SE._missing_link = false;
|
|
SE._offset = grid->oIndex(XpCoor);
|
|
if ( isPoleX ) {
|
|
SE._offset = grid->PoleSiteForOcoor(Coor);
|
|
}
|
|
SE._polarisation = IcosahedronPatchY;
|
|
SE._adjoint = false;
|
|
acceleratorPut(this->_entries[lexXp],SE);
|
|
////////////////////////////////////////////////
|
|
// for YpCoor
|
|
////////////////////////////////////////////////
|
|
SE._is_local = true;
|
|
SE._missing_link = false;
|
|
SE._offset = grid->oIndex(YpCoor);
|
|
if ( isPoleY ) {
|
|
SE._offset = grid->PoleSiteForOcoor(Coor);
|
|
}
|
|
SE._polarisation = IcosahedronPatchX;
|
|
SE._adjoint = false;
|
|
acceleratorPut(this->_entries[lexYp],SE);
|
|
} else {
|
|
////////////////////////////////////////////////
|
|
// XpCoor stencil entry
|
|
// Store in look up table
|
|
////////////////////////////////////////////////
|
|
// Basis rotates dictates BOTH adjoint and polarisation
|
|
// Could reduce the amount of information stored here
|
|
SE._is_local = true;
|
|
SE._missing_link = false;
|
|
SE._offset = grid->oIndex(XpCoor);
|
|
SE._polarisation = IcosahedronPatchY;
|
|
SE._adjoint = false;
|
|
if ( DpHemiPatch != HemiPatch && south ) {
|
|
SE._offset = grid->oIndex(DpCoor);
|
|
SE._polarisation = IcosahedronPatchX;
|
|
SE._adjoint = true;
|
|
}
|
|
acceleratorPut(this->_entries[lexXp],SE);
|
|
////////////////////////////////////////////////
|
|
// for YpCoor
|
|
////////////////////////////////////////////////
|
|
SE._is_local = true;
|
|
SE._missing_link = false;
|
|
SE._offset = grid->oIndex(YpCoor);
|
|
SE._polarisation = IcosahedronPatchX;
|
|
SE._adjoint = false;
|
|
if ( YpHemiPatch != HemiPatch && north ) {
|
|
SE._offset = grid->oIndex(DpCoor);
|
|
SE._polarisation = IcosahedronPatchY;
|
|
SE._adjoint = true;
|
|
}
|
|
acceleratorPut(this->_entries[lexYp],SE);
|
|
}
|
|
|
|
SE._adjoint = false;
|
|
SE._is_local = true;
|
|
SE._missing_link = false;
|
|
////////////////////////////////////////////////
|
|
// XmCoor stencil entry
|
|
// Store in look up table
|
|
////////////////////////////////////////////////
|
|
SE._offset = grid->oIndex(XmCoor);
|
|
SE._polarisation = IcosahedronPatchDiagonal;
|
|
if ( XmHemiPatch != HemiPatch && north ) {
|
|
SE._polarisation = IcosahedronPatchY; // nbrs Y instead of diagonal in North hemisphere exceptional case
|
|
}
|
|
acceleratorPut(this->_entries[lexXm],SE);
|
|
|
|
////////////////////////////////////////////////
|
|
// for YmCoor
|
|
////////////////////////////////////////////////
|
|
SE._offset = grid->oIndex(YmCoor);
|
|
SE._polarisation = IcosahedronPatchDiagonal;
|
|
if ( YmHemiPatch != HemiPatch && south ) {
|
|
SE._polarisation = IcosahedronPatchX; // Basis rotates
|
|
}
|
|
acceleratorPut(this->_entries[lexYm],SE);
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
// for DpCoor ; never needed for staples, only for vertex diff ops
|
|
// no polarisation rotation
|
|
/////////////////////////////////////////////////////////////////////
|
|
SE._offset = grid->oIndex(DpCoor);
|
|
SE._polarisation = IcosahedronPatchDiagonal; // should ignore
|
|
acceleratorPut(this->_entries[lexDp],SE);
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
// for DmCoor ; never needed for staples, only for vertex diff ops
|
|
// no polarisation rotation
|
|
/////////////////////////////////////////////////////////////////////
|
|
SE._offset = grid->oIndex(DmCoor);
|
|
SE._polarisation = IcosahedronPatchDiagonal; // should ignore
|
|
SE._missing_link = missingLink;
|
|
acceleratorPut(this->_entries[lexDm],SE);
|
|
}
|
|
if ( vertexOutputs ) {
|
|
int ndm1 = grid->Nd()-1;
|
|
if ( grid->ownsSouthPole() ) {
|
|
IcosahedralStencilEntry SE;
|
|
for(uint64_t site=0;site<cart_sites; site ++) {
|
|
Coordinate Coor;
|
|
grid->oCoorFromOindex(Coor,site);
|
|
if( (Coor[0]==L)&&(Coor[1]==0) ) {
|
|
int64_t pole_site = grid->PoleSiteForOcoor(Coor);
|
|
int64_t lex = pole_site*np+Coor[ndm1];
|
|
SE._offset = site;
|
|
SE._is_local = true;
|
|
SE._polarisation = IcosahedronPatchX; // ignored
|
|
SE._adjoint = false; // ignored
|
|
SE._missing_link = false;
|
|
acceleratorPut(this->_entries[lex],SE);
|
|
|
|
int64_t lex5 = pole_site*np+5; // We miss the backwards link
|
|
SE._missing_link = true;
|
|
acceleratorPut(this->_entries[lex5],SE);
|
|
}
|
|
}
|
|
}
|
|
if ( grid->ownsNorthPole() ) {
|
|
IcosahedralStencilEntry SE;
|
|
for(uint64_t site=0;site<cart_sites; site ++) {
|
|
Coordinate Coor;
|
|
grid->oCoorFromOindex(Coor,site);
|
|
if( (Coor[0]==0)&&(Coor[1]==L) ) {
|
|
int64_t pole_site = grid->PoleSiteForOcoor(Coor);
|
|
int64_t lex = pole_site*np+Coor[ndm1];
|
|
SE._offset = site;
|
|
SE._is_local = true;
|
|
SE._polarisation = IcosahedronPatchX; // ignored
|
|
SE._adjoint = false; // ignored
|
|
SE._missing_link = false;
|
|
acceleratorPut(this->_entries[lex],SE);
|
|
|
|
int64_t lex5 = pole_site*np+5; // We miss the backwards link
|
|
SE._missing_link = true;
|
|
acceleratorPut(this->_entries[lex5],SE);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
/*************************************************************
|
|
* For gauge action implementation
|
|
*************************************************************
|
|
*/
|
|
void FaceStencil(void)
|
|
{
|
|
GridBase * grid = this->_grid;
|
|
|
|
int osites = grid->oSites();
|
|
|
|
uint64_t cart_sites = grid->CartesianOsites();
|
|
uint64_t Npole_sites = grid->NorthPoleOsites();
|
|
uint64_t Spole_sites = grid->SouthPoleOsites();
|
|
Coordinate pcoor = grid->ThisProcessorCoor();
|
|
Coordinate pgrid = grid->ProcessorGrid();
|
|
|
|
/*
|
|
* resize the stencil entries array and set npoints
|
|
*/
|
|
this->_npoints=2; // Move to template param?
|
|
this->_entries.resize(this->_npoints * cart_sites);
|
|
this->_entries_p = &_entries[0];
|
|
|
|
for(uint64_t site=0;site<cart_sites; site ++) {
|
|
|
|
Coordinate Coor;
|
|
Coordinate NbrCoor;
|
|
|
|
int nd = grid->Nd();
|
|
int L = grid->LocalDimensions()[0];
|
|
|
|
Integer lexXY = site*2;
|
|
Integer lexYX = site*2+1;
|
|
|
|
IcosahedralStencilEntry SE;
|
|
|
|
////////////////////////////////////////////////
|
|
// Outer index of neighbour Offset calculation
|
|
////////////////////////////////////////////////
|
|
grid->oCoorFromOindex(Coor,site);
|
|
NbrCoor = Coor;
|
|
assert( grid->LocalDimensions()[1]==grid->LocalDimensions()[0]);
|
|
assert( grid->_simd_layout[0]==1); // Cannot vectorise in these dims
|
|
assert( grid->_simd_layout[1]==1);
|
|
assert( grid->_processors[0]==1); // Cannot mpi distribute in these dims
|
|
assert( grid->_processors[1]==1);
|
|
|
|
int Patch = Coor[nd-1];
|
|
int HemiPatch = Patch%HemiPatches;
|
|
int north = Patch/HemiPatches;
|
|
int south = 1-north;
|
|
int isPoleY;
|
|
int isPoleX;
|
|
|
|
assert(Patch<IcosahedralPatches);
|
|
assert((north==1)||(south==1));
|
|
/*
|
|
* Minimal stencil for edge -> face triangle evaluation
|
|
*
|
|
* On each edge grid site, hold +x,+y,+diag links
|
|
* Must locate the closing link to form the two forward triangles
|
|
*
|
|
* case: +x,+d
|
|
*
|
|
* north: +x neighbours ydir link always
|
|
* south: +x neighbours ydir link except
|
|
* cross into a different patch in south
|
|
* then
|
|
* +d neighbours xdir link
|
|
*
|
|
* case: +y,+d
|
|
* south: +y neighbours xdir link always
|
|
* north: +y neighbours xdir link unless
|
|
* cross into a different patch in north
|
|
* then
|
|
* +d neighbours ydir link
|
|
*
|
|
*/
|
|
Coordinate XpCoor;
|
|
Coordinate YpCoor;
|
|
Coordinate DpCoor;
|
|
|
|
GetNbrForPlusDiagonal(grid,Coor,DpCoor);
|
|
GetNbrForPlusX(grid,Coor,XpCoor,isPoleX);
|
|
GetNbrForPlusY(grid,Coor,YpCoor,isPoleY);
|
|
|
|
// int XpHemiPatch = XpCoor[nd-1]%HemiPatches;
|
|
// int XpHemisphere = XpCoor[nd-1]/HemiPatches;
|
|
|
|
int DpPatch = DpCoor[nd-1];
|
|
int DpHemiPatch = DpCoor[nd-1]%HemiPatches;
|
|
int DpHemisphere = DpCoor[nd-1]/HemiPatches;
|
|
|
|
////////////////////////////////////////////////
|
|
// for trace [ U_x(z) U_y(z+\hat x) adj(U_d(z)) ]
|
|
////////////////////////////////////////////////
|
|
if ( DpHemiPatch != HemiPatch && south ) {
|
|
SE._offset = grid->oIndex(DpCoor);
|
|
SE._is_local = true;
|
|
SE._polarisation = IcosahedronPatchX;
|
|
SE._adjoint = true;
|
|
SE._missing_link = false;
|
|
} else {
|
|
SE._offset = grid->oIndex(XpCoor);
|
|
SE._is_local = true;
|
|
SE._polarisation = IcosahedronPatchY;
|
|
SE._adjoint = false;
|
|
SE._missing_link = false;
|
|
}
|
|
|
|
////////////////////////////////////////////////
|
|
// Store in look up table
|
|
////////////////////////////////////////////////
|
|
acceleratorPut(this->_entries[lexXY],SE);
|
|
|
|
// failed in the if case here
|
|
////////////////////////////////////////////////
|
|
// for trace [ U_y(z) U_x(z+\hat y) adj(U_d(z)) ]
|
|
////////////////////////////////////////////////
|
|
int YpHemiPatch = YpCoor[nd-1]%HemiPatches;
|
|
if ( YpHemiPatch != HemiPatch && north ) {
|
|
SE._offset = grid->oIndex(DpCoor);
|
|
SE._is_local = true;
|
|
SE._polarisation = IcosahedronPatchY;
|
|
SE._adjoint = true;
|
|
SE._missing_link = false;
|
|
} else {
|
|
SE._offset = grid->oIndex(YpCoor);
|
|
SE._is_local = true;
|
|
SE._polarisation = IcosahedronPatchX;
|
|
SE._adjoint = false;
|
|
SE._missing_link = false;
|
|
}
|
|
////////////////////////////////////////////////
|
|
// Store in look up table
|
|
////////////////////////////////////////////////
|
|
acceleratorPut(this->_entries[lexYX],SE);
|
|
};
|
|
}
|
|
/*
|
|
* For gauge action derivative implementation
|
|
* Staple
|
|
*
|
|
* Case1: I x T loops
|
|
*
|
|
* Need: DirP this site; no entry
|
|
* Tp @ dir++
|
|
* DirP @ t++
|
|
* Tp @ t--
|
|
* DirP @ t--
|
|
* Tp @ t--, dir++
|
|
*
|
|
* There is no complex rotation of links on other site
|
|
*
|
|
* Case2: I x I loops
|
|
* Just use a general 6 point stencil and cherry pick terms
|
|
*/
|
|
};
|
|
NAMESPACE_END(Grid);
|