OpenFPM_pdata  4.1.0
Project that contain the implementation of distributed structures
grid_smb.hpp
1 //
2 // Created by tommaso on 17/06/19.
3 //
4 
5 #ifndef OPENFPM_PDATA_BLOCKGEOMETRY_HPP
6 #define OPENFPM_PDATA_BLOCKGEOMETRY_HPP
7 
8 #include <boost/mpl/size_t.hpp>
9 #include <cstring>
10 #include <Grid/grid_sm.hpp>
11 #include "SparseGridGpu/TemplateUtils/mathUtils.hpp"
12 
18 template<unsigned int dim, unsigned int blockEdgeSize, typename indexT = long int>
19 class grid_smb
20 {
21 private:
22 
25 
26  indexT blockSz[dim];
27  indexT sz[dim];
28 
29 protected:
30 
31  constexpr static indexT blockSize = IntPow<blockEdgeSize, dim>::value;
32 
33 public:
34 
35  grid_smb() {}
36 
42  inline Box<dim,size_t> getBox() const
43  {
44  return box;
45  }
46 
47  __host__ __device__ grid_smb(const size_t (& sz)[dim])
48  {
49  for (int d=0; d<dim; ++d)
50  {
51  this->sz[d] = sz[d];
52  blockSz[d] = sz[d] / blockEdgeSize + ((sz[d] % blockEdgeSize) != 0);
53 
54  box.setHigh(d,sz[d]);
55  box.setLow(d,0);
56  }
57  }
58 
59  __host__ __device__ grid_smb(const indexT (& sz)[dim])
60  {
61  for (int d=0; d<dim; ++d)
62  {
63  this->sz[d] = sz[d];
64  blockSz[d] = sz[d] / blockEdgeSize + ((sz[d] % blockEdgeSize) != 0);
65 
66  box.setHigh(d,sz[d]);
67  box.setLow(d,0);
68  }
69  }
70 
71  __host__ __device__ grid_smb(const size_t domainBlockEdgeSize)
72  {
73  for (int i = 0; i < dim; ++i)
74  {
75  blockSz[i] = (indexT)domainBlockEdgeSize;
76  sz[i] = (indexT)domainBlockEdgeSize * blockEdgeSize;
77 
78  box.setHigh(i,domainBlockEdgeSize);
79  box.setLow(i,0);
80  }
81  }
82 
83  template<typename T>
84  __host__ __device__ grid_smb(const grid_sm<dim, T> blockGrid)
85  {
86  for (int i = 0; i < dim; ++i)
87  {
88  blockSz[i] = blockGrid.size(i);
89  sz[i] = blockGrid.size(i) * blockEdgeSize;
90 
91  box.setHigh(i,sz[i]);
92  box.setLow(i,0);
93  }
94  }
95 
96  static bool noPointers() {return true;}
97 
98 #ifdef __NVCC__
99  //Constructors from dim3 and uint3 objects
100  __host__ __device__ grid_smb(const dim3 blockDimensions)
101  {
102  unsigned int i = 0;
103  assert(dim <= 3);
104  blockSz[i] = blockDimensions.x;
105  sz[i] = blockSz[i] * blockEdgeSize;
106 
107  box.setHigh(i,sz[i]);
108  box.setLow(i,0);
109 
110  if (dim > 1)
111  {
112  ++i;
113  blockSz[i] = blockDimensions.y;
114  sz[i] = blockSz[i] * blockEdgeSize;
115 
116  box.setHigh(i,sz[i]);
117  box.setLow(i,0);
118 
119  if (dim > 2)
120  {
121  ++i;
122  blockSz[i] = blockDimensions.z;
123  sz[i] = blockSz[i] * blockEdgeSize;
124 
125  box.setHigh(i,sz[i]);
126  box.setLow(i,0);
127  }
128  }
129  }
130 
131 
132 #endif // __NVCC__
133 
134  __host__ __device__ grid_smb(const grid_smb<dim, blockEdgeSize> &other)
135  {
136  for (indexT i = 0 ; i < dim ; i++)
137  {
138  blockSz[i] = other.blockSz[i];
139  sz[i] = other.sz[i];
140  }
141  }
142 
143  __host__ __device__ grid_smb &operator=(const grid_smb<dim, blockEdgeSize> &other)
144  {
145  for (indexT i = 0 ; i < dim ; i++)
146  {
147  blockSz[i] = other.blockSz[i];
148  sz[i] = other.sz[i];
149  }
150  return *this;
151  }
152 
153  __host__ __device__ const indexT (& getSize() const)[dim]
154  {
155  return sz;
156  }
157 
158  __host__ __device__ const indexT & size(int i) const
159  {
160  return sz[i];
161  }
162 
175  template<typename indexT_>
176  inline __host__ __device__ indexT LinId(const grid_key_dx<dim, indexT_> coord) const
177  {
178  //todo: Check (in debug mode only) that the coordinates passed here are valid and not overflowing dimensions (???)
179  indexT blockLinId = coord.get(dim - 1) / blockEdgeSize;
180  indexT localLinId = coord.get(dim - 1) % blockEdgeSize;
181  for (int d = dim - 2; d >= 0; --d)
182  {
183  blockLinId *= blockSz[d];
184  localLinId *= blockEdgeSize;
185  blockLinId += coord.get(d) / blockEdgeSize;
186  localLinId += coord.get(d) % blockEdgeSize;
187  }
188  return blockLinId * blockSize + localLinId;
189  }
190 
203  template<typename indexT_>
204  inline __host__ __device__ void LinId(const grid_key_dx<dim, indexT_> coord, indexT & blockLinId, int & localLinId) const
205  {
206  //todo: Check (in debug mode only) that the coordinates passed here are valid and not overflowing dimensions (???)
207  blockLinId = coord.get(dim - 1) / blockEdgeSize;
208  localLinId = coord.get(dim - 1) % blockEdgeSize;
209  for (int d = dim - 2; d >= 0; --d)
210  {
211  blockLinId *= blockSz[d];
212  localLinId *= blockEdgeSize;
213  blockLinId += coord.get(d) / blockEdgeSize;
214  localLinId += coord.get(d) % blockEdgeSize;
215  }
216  }
217 
218  inline __host__ __device__ grid_key_dx<dim, int> InvLinId(const indexT linId) const
219  {
220  indexT blockLinId = linId / blockSize;
221  indexT localLinId = linId % blockSize;
222  return InvLinId(blockLinId, localLinId);
223  }
224 
232  inline __host__ __device__ grid_key_dx<dim, int> LocalInvLinId(unsigned int localLinId) const
233  {
234  grid_key_dx<dim, int> coord;
235  for (int d = 0; d < dim; ++d)
236  {
237  auto c = localLinId % blockEdgeSize;
238  coord.set_d(d, c);
239  localLinId /= blockEdgeSize;
240  }
241  return coord;
242  }
243 
263  inline __host__ __device__ grid_key_dx<dim, int> InvLinId(indexT blockLinId, indexT localLinId) const
264  {
265  grid_key_dx<dim, int> coord;
266  for (int d = 0; d < dim; ++d)
267  {
268  auto c = blockLinId % blockSz[d];
269  c *= blockEdgeSize;
270  c += localLinId % blockEdgeSize;
271  coord.set_d(d, c);
272  blockLinId /= blockSz[d];
273  localLinId /= blockEdgeSize;
274  }
275  return coord;
276  }
277 
278  // Now methods to handle blockGrid coordinates (e.g. to load neighbouring blocks)
279  template<typename indexT_>
280  inline __host__ __device__ indexT BlockLinId(const grid_key_dx<dim, indexT_> & blockCoord) const
281  {
282  indexT blockLinId = blockCoord.get(dim - 1);
283  if (blockLinId >= blockSz[dim-1])
284  {return -1;}
285 
286  for (int d = dim - 2; d >= 0; --d)
287  {
288  blockLinId *= blockSz[d];
289  indexT cur = blockCoord.get(d);
290  if (cur >= blockSz[d])
291  {
292  return -1;
293  }
294  blockLinId += cur;
295  }
296  return blockLinId;
297  }
298 
299  // Now methods to handle blockGrid coordinates (e.g. to load neighbouring blocks)
300  template<typename indexT_>
301  inline __host__ __device__ grid_key_dx<dim,indexT> getGlobalCoord(const grid_key_dx<dim, indexT_> & blockCoord, unsigned int offset) const
302  {
304 
305  for (unsigned int i = 0 ; i < dim ; i++)
306  {
307  k.set_d(i,blockCoord.get(i)*blockEdgeSize + offset%blockEdgeSize);
308  offset /= blockEdgeSize;
309  }
310  return k;
311  }
312 
313  inline __host__ __device__ grid_key_dx<dim, int> BlockInvLinId(indexT blockLinId) const
314  {
315  grid_key_dx<dim, int> blockCoord;
316  for (int d = 0; d < dim; ++d)
317  {
318  auto c = blockLinId % blockSz[d];
319  blockCoord.set_d(d, c);
320  blockLinId /= blockSz[d];
321  }
322  return blockCoord;
323  }
324 
325  inline indexT size_blocks() const
326  {
327  indexT sz = 1;
328 
329  for (indexT i = 0 ; i < dim ; i++)
330  {sz *= blockSz[i];}
331 
332  return sz;
333  }
334 
335  inline indexT size() const
336  {
337  indexT sz = 1;
338 
339  for (indexT i = 0 ; i < dim ; i++)
340  {sz *= this->sz[i];}
341 
342  return sz;
343  }
344 
345  __host__ __device__ inline indexT getBlockSize() const
346  {
347  return blockSize;
348  }
349 
350  __host__ __device__ inline void swap(grid_smb<dim, blockEdgeSize, indexT> &other)
351  {
352  indexT blockSz_tmp[dim];
353  indexT sz_tmp[dim];
354 
355  for (indexT i = 0 ; i < dim ; i++)
356  {
357  blockSz_tmp[i] = blockSz[i];
358  blockSz[i] = other.blockSz[i];
359  other.blockSz[i] = blockSz_tmp[i];
360 
361  sz_tmp[i] = sz[i];
362  sz[i] = other.sz[i];
363  other.sz[i] = sz_tmp[i];
364  }
365  }
366 };
367 
368 #endif //OPENFPM_PDATA_BLOCKGEOMETRY_HPP
__host__ __device__ grid_key_dx< dim, int > LocalInvLinId(unsigned int localLinId) const
Definition: grid_smb.hpp:232
grid_key_dx is the key to access any element in the grid
Definition: grid_key.hpp:18
__device__ __host__ size_t size() const
Return the size of the grid.
Definition: grid_sm.hpp:637
__device__ __host__ index_type get(index_type i) const
Get the i index.
Definition: grid_key.hpp:503
__device__ __host__ void setHigh(int i, T val)
set the high interval of the box
Definition: Box.hpp:544
Box< dim, size_t > getBox() const
Return the box enclosing the grid.
Definition: grid_smb.hpp:42
__device__ __host__ void setLow(int i, T val)
set the low interval of the box
Definition: Box.hpp:533
__host__ __device__ grid_key_dx< dim, int > InvLinId(indexT blockLinId, indexT localLinId) const
Invert from the linearized block id + local id to the position of the point in coordinates.
Definition: grid_smb.hpp:263
Box< dim, size_t > box
Box enclosing the grid.
Definition: grid_smb.hpp:24
__host__ __device__ indexT LinId(const grid_key_dx< dim, indexT_ > coord) const
Linearize the coordinate index.
Definition: grid_smb.hpp:176
__device__ __host__ void set_d(index_type i, index_type id)
Set the i index.
Definition: grid_key.hpp:516
__host__ __device__ void LinId(const grid_key_dx< dim, indexT_ > coord, indexT &blockLinId, int &localLinId) const
Linearize the coordinate index.
Definition: grid_smb.hpp:204