Grid 0.7.0
Cartesian_red_black.h
Go to the documentation of this file.
1/*************************************************************************************
2
3 Grid physics library, www.github.com/paboyle/Grid
4
5 Source file: ./lib/cartesian/Cartesian_red_black.h
6
7 Copyright (C) 2015
8
9Author: Azusa Yamaguchi <ayamaguc@staffmail.ed.ac.uk>
10Author: Peter Boyle <paboyle@ph.ed.ac.uk>
11
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2 of the License, or
15 (at your option) any later version.
16
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
21
22 You should have received a copy of the GNU General Public License along
23 with this program; if not, write to the Free Software Foundation, Inc.,
24 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25
26 See the full license in the file "LICENSE" in the top level distribution directory
27*************************************************************************************/
28/* END LEGAL */
29#ifndef GRID_CARTESIAN_RED_BLACK_H
30#define GRID_CARTESIAN_RED_BLACK_H
31
33
34static const int CbRed =0;
35static const int CbBlack=1;
36static const int Even =CbRed;
37static const int Odd =CbBlack;
38
39accelerator_inline int RedBlackCheckerBoardFromOindex (int oindex,const Coordinate &rdim,const Coordinate &chk_dim_msk)
40{
41 int nd=rdim.size();
42 Coordinate coor(nd);
43
44 Lexicographic::CoorFromIndex(coor,oindex,rdim);
45
46 int linear=0;
47 for(int d=0;d<nd;d++){
48 if(chk_dim_msk[d])
49 linear=linear+coor[d];
50 }
51 return (linear&0x1);
52}
53
54
55// Specialise this for red black grids storing half the data like a chess board.
57{
58public:
59 // Coordinate _checker_dim_mask;
60 // int _checker_dim;
61 std::vector<int> _checker_board;
62
63 virtual int isCheckerBoarded(void) const { return 1; };
64 virtual int CheckerBoarded(int dim){
65 if( dim==_checker_dim) return 1;
66 else return 0;
67 }
68 virtual int CheckerBoard(const Coordinate &site){
69 int linear=0;
70 assert(site.size()==_ndimension);
71 for(int d=0;d<_ndimension;d++){
73 linear=linear+site[d];
74 }
75 return (linear&0x1);
76 }
77
78 // Depending on the cb of site, we toggle source cb.
79 // for block #b, element #e = (b, e)
80 // we need
81 virtual int CheckerBoardShiftForCB(int source_cb,int dim,int shift,int ocb){
82 if(dim != _checker_dim) return shift;
83
84 int fulldim =_fdimensions[dim];
85 shift = (shift+fulldim)%fulldim;
86
87 // Probably faster with table lookup;
88 // or by looping over x,y,z and multiply rather than computing checkerboard.
89
90 if ( (source_cb+ocb)&1 ) {
91 return (shift)/2;
92 } else {
93 return (shift+1)/2;
94 }
95 }
96 virtual int CheckerBoardFromOindexTable (int Oindex) {
97 return _checker_board[Oindex];
98 }
99 virtual int CheckerBoardFromOindex (int Oindex)
100 {
101 Coordinate ocoor;
102 oCoorFromOindex(ocoor,Oindex);
103 return CheckerBoard(ocoor);
104 }
105 virtual int CheckerBoardShift(int source_cb,int dim,int shift,int osite){
106
107 if(dim != _checker_dim) return shift;
108
109 int ocb=CheckerBoardFromOindex(osite);
110
111 return CheckerBoardShiftForCB(source_cb,dim,shift,ocb);
112 }
113
114 virtual int CheckerBoardDestination(int source_cb,int shift,int dim){
115 if ( _checker_dim_mask[dim] ) {
116 // If _fdimensions[checker_dim] is odd, then shifting by 1 in other dims
117 // does NOT cause a parity hop.
118 int add=(dim==_checker_dim) ? 0 : _fdimensions[_checker_dim];
119 if ( (shift+add) &0x1) {
120 return 1-source_cb;
121 } else {
122 return source_cb;
123 }
124 } else {
125 return source_cb;
126
127 }
128 };
129
131 // Create Redblack from original grid; require full grid pointer ?
134 {
135 int dims = base->_ndimension;
136 Coordinate checker_dim_mask(dims,1);
137 int checker_dim = 0;
138 Init(base->_fdimensions,base->_simd_layout,base->_processors,checker_dim_mask,checker_dim);
139 };
140
142 // Create redblack from original grid, with non-trivial checker dim mask
145 const Coordinate &checker_dim_mask,
146 int checker_dim
148 {
149 Init(base->_fdimensions,base->_simd_layout,base->_processors,checker_dim_mask,checker_dim) ;
150 }
151
152 virtual ~GridRedBlackCartesian() = default;
153
154 void Init(const Coordinate &dimensions,
155 const Coordinate &simd_layout,
156 const Coordinate &processor_grid,
157 const Coordinate &checker_dim_mask,
158 int checker_dim)
159 {
160
161 _isCheckerBoarded = true;
162 _checker_dim = checker_dim;
163 assert(checker_dim_mask[checker_dim] == 1);
164 _ndimension = dimensions.size();
165 assert(checker_dim_mask.size() == _ndimension);
166 assert(processor_grid.size() == _ndimension);
167 assert(simd_layout.size() == _ndimension);
168
174 _lstart.resize(_ndimension);
175 _lend.resize(_ndimension);
176
177 _ostride.resize(_ndimension);
178 _istride.resize(_ndimension);
179
180 _fsites = _gsites = _osites = _isites = 1;
181
182 _checker_dim_mask = checker_dim_mask;
183
184 for (int d = 0; d < _ndimension; d++)
185 {
186 _fdimensions[d] = dimensions[d];
190
191 if (d == _checker_dim)
192 {
193 assert((_gdimensions[d] & 0x1) == 0);
194 _gdimensions[d] = _gdimensions[d] / 2; // Remove a checkerboard
195 _gsites /= 2;
196 }
198 assert(_ldimensions[d] * _processors[d] == _gdimensions[d]);
200 _lend[d] = _processor_coor[d] * _ldimensions[d] + _ldimensions[d] - 1;
201
202 // Use a reduced simd grid
203 _simd_layout[d] = simd_layout[d];
204 _rdimensions[d] = _ldimensions[d] / _simd_layout[d]; // this is not checking if this is integer
205 assert(_rdimensions[d] * _simd_layout[d] == _ldimensions[d]);
206 assert(_rdimensions[d] > 0);
207
208 // all elements of a simd vector must have same checkerboard.
209 // If Ls vectorised, this must still be the case; e.g. dwf rb5d
210 if (_simd_layout[d] > 1)
211 {
212 if (checker_dim_mask[d])
213 {
214 assert((_rdimensions[d] & 0x1) == 0);
215 }
216 }
217
218 _osites *= _rdimensions[d];
219 _isites *= _simd_layout[d];
220
221 // Addressing support
222 if (d == 0)
223 {
224 _ostride[d] = 1;
225 _istride[d] = 1;
226 }
227 else
228 {
229 _ostride[d] = _ostride[d - 1] * _rdimensions[d - 1];
230 _istride[d] = _istride[d - 1] * _simd_layout[d - 1];
231 }
232 }
233
235 // subplane information
240
241 int block = 1;
242 int nblock = 1;
243 for (int d = 0; d < _ndimension; d++)
244 nblock *= _rdimensions[d];
245
246 for (int d = 0; d < _ndimension; d++)
247 {
248 nblock /= _rdimensions[d];
249 _slice_block[d] = block;
251 _slice_nblock[d] = nblock;
252 block = block * _rdimensions[d];
253 }
254
256 // Create a checkerboard lookup table
258 int rvol = 1;
259 for (int d = 0; d < _ndimension; d++)
260 {
261 rvol = rvol * _rdimensions[d];
262 }
263 _checker_board.resize(rvol);
264 for (int osite = 0; osite < _osites; osite++)
265 {
267 }
268 };
269
270protected:
271 virtual int oIndex(Coordinate &coor)
272 {
273 int idx = 0;
274 for (int d = 0; d < _ndimension; d++)
275 {
276 if (d == _checker_dim)
277 {
278 idx += _ostride[d] * ((coor[d] / 2) % _rdimensions[d]);
279 }
280 else
281 {
282 idx += _ostride[d] * (coor[d] % _rdimensions[d]);
283 }
284 }
285 return idx;
286 };
287
288 virtual int iIndex(Coordinate &lcoor)
289 {
290 int idx = 0;
291 for (int d = 0; d < _ndimension; d++)
292 {
293 if (d == _checker_dim)
294 {
295 idx += _istride[d] * (lcoor[d] / (2 * _rdimensions[d]));
296 }
297 else
298 {
299 idx += _istride[d] * (lcoor[d] / _rdimensions[d]);
300 }
301 }
302 return idx;
303 }
304};
306#endif
#define accelerator_inline
static const int Even
static const int Odd
static const int CbRed
accelerator_inline int RedBlackCheckerBoardFromOindex(int oindex, const Coordinate &rdim, const Coordinate &chk_dim_msk)
static const int CbBlack
AcceleratorVector< int, MaxDims > Coordinate
Definition Coordinate.h:95
void add(Lattice< obj1 > &ret, const Lattice< obj2 > &lhs, const Lattice< obj3 > &rhs)
#define NAMESPACE_BEGIN(A)
Definition Namespace.h:35
#define NAMESPACE_END(A)
Definition Namespace.h:36
uint64_t base
accelerator_inline size_type size(void) const
Definition Coordinate.h:52
Coordinate _lstart
Coordinate _slice_stride
Coordinate _fdimensions
Coordinate _lend
Coordinate _istride
Coordinate _slice_nblock
Coordinate _slice_block
Coordinate _checker_dim_mask
bool _isCheckerBoarded
int64_t _fsites
GridBase(const Coordinate &processor_grid)
void oCoorFromOindex(Coordinate &coor, int Oindex)
Coordinate _rdimensions
Coordinate _simd_layout
Coordinate _ostride
Coordinate _ldimensions
Coordinate _gdimensions
int64_t _gsites
virtual ~GridRedBlackCartesian()=default
virtual int CheckerBoardFromOindexTable(int Oindex)
virtual int oIndex(Coordinate &coor)
virtual int CheckerBoardDestination(int source_cb, int shift, int dim)
GridRedBlackCartesian(const GridBase *base)
void Init(const Coordinate &dimensions, const Coordinate &simd_layout, const Coordinate &processor_grid, const Coordinate &checker_dim_mask, int checker_dim)
virtual int CheckerBoardShiftForCB(int source_cb, int dim, int shift, int ocb)
virtual int CheckerBoarded(int dim)
std::vector< int > _checker_board
virtual int CheckerBoardShift(int source_cb, int dim, int shift, int osite)
virtual int CheckerBoardFromOindex(int Oindex)
GridRedBlackCartesian(const GridBase *base, const Coordinate &checker_dim_mask, int checker_dim)
virtual int isCheckerBoarded(void) const
virtual int CheckerBoard(const Coordinate &site)
virtual int iIndex(Coordinate &lcoor)