DASH  0.3.0
CoordinateAccess.h
1 #ifndef DASH__HALO_HALOCOORDINATEACCESS_H
2 #define DASH__HALO_HALOCOORDINATEACCESS_H
3 
4 #include <dash/halo/Halo.h>
5 
6 namespace dash {
7 
8 namespace halo {
9 
10 using namespace internal;
11 
12 // forward declaration
13 template<typename HaloBlockT>
15 
16 template<typename CoordinateAccessT>
18 
19 template<typename CoordinateInnerAccessT, dim_t CurrentDimension>
21 private:
23 
24  static constexpr auto NumDimensions = CoordinateInnerAccessT::ndim();
25 
26 public:
27  using Offsets_t = typename CoordinateInnerAccessT::Offsets_t;
28  using Element_t = typename CoordinateInnerAccessT::Element_t;
29  using index_t = typename CoordinateInnerAccessT::index_t;
30 
31 public:
32 
33  DataInnerAccess(const Offsets_t* offsets, Element_t* mem)
34  : _offsets(offsets), _mem(mem) {
35  }
36 
37  template<dim_t _CurrentDimension = CurrentDimension + 1>
38  std::enable_if_t<(_CurrentDimension != NumDimensions), DataInnerAccess<CoordinateInnerAccessT, CurrentDimension+1>>
39  operator[](index_t pos) {
40 
41  return DataInnerAccess<CoordinateInnerAccessT, CurrentDimension+1>(_offsets, _mem + pos * (*_offsets)[CurrentDimension]);
42  }
43 
44  template<dim_t _CurrentDimension = CurrentDimension + 1>
45  std::enable_if_t<(_CurrentDimension == NumDimensions), Element_t>&
46  operator[](index_t pos) {
47  return _mem[pos];
48  }
49 
50 private:
51  const Offsets_t* _offsets;
52  Element_t* _mem;
53 };
54 
55 template<typename CoordinateAccessT>
57 private:
59 
60  static constexpr auto NumDimensions = CoordinateAccessT::ndim();
61  static constexpr auto MemoryArrange = CoordinateAccessT::memory_order();
62 
63 public:
64  using Element_t = typename CoordinateAccessT::Element_t;
65  using index_t = typename CoordinateAccessT::index_t;
66  using ViewSpec_t = typename CoordinateAccessT::ViewSpec_t;
67  using Offsets_t = typename CoordinateAccessT::Offsets_t;
68  using DataInnerAccess_t = DataInnerAccess<Self_t, 0>;
69  using ViewRange_t = typename CoordinateAccessT::ViewRange_t;
70  using AllViewRanges_t = typename CoordinateAccessT::AllViewRanges_t;
71 
72 public:
73 
74  CoordinateInnerAccess(const AllViewRanges_t& ranges, Element_t* mem, const Offsets_t* offsets)
75  : _ranges(ranges)
76  , _mem(mem)
77  , _offsets(offsets)
78  , _data_access(DataInnerAccess_t(_offsets, _mem)) {
79  }
80 
81  static constexpr decltype(auto) ndim() { return NumDimensions; }
82 
83  static constexpr decltype(auto) memory_order() { return MemoryArrange; }
84 
85  ViewRange_t range_dim(dim_t dim) {
86  return _ranges(dim);
87  }
88 
89  AllViewRanges_t ranges() {
90  return _ranges;
91  }
92 
93  decltype(auto) operator[] (index_t pos) {
94  return _data_access[pos];
95  }
96 
97  decltype(auto) operator[] (index_t pos) const {
98  return _data_access[pos];
99  }
100 
101 private:
102  AllViewRanges_t _ranges;
103  Element_t* _mem;
104  const Offsets_t* _offsets;
105  DataInnerAccess_t _data_access;
106 };
107 
108 
109 template<typename CoordinateAccessT, dim_t CurrentDimension>
110 class DataAccess {
111 private:
113 
114  static constexpr auto NumDimensions = CoordinateAccessT::ndim();
115  static constexpr auto MemoryArrange = CoordinateAccessT::memory_order();
116 
118  static constexpr auto RegIndexCenter = RegCoords_t::center_index();
119 
120 public:
121  using Element_t = typename CoordinateAccessT::Element_t;
122  using index_t = typename CoordinateAccessT::index_t;
123  using Coords_t = typename CoordinateAccessT::Coords_t;
124 
125 public:
126 
127  DataAccess(const CoordinateAccessT* access, Element_t* mem, const Coords_t& coords, region_index_t reg_index, bool halo)
128  : _access(access), _mem(mem), _coords(coords), _reg_index(reg_index), _halo(halo) {
129  }
130 
131  template<dim_t _CurrentDimension = CurrentDimension + 1>
132  std::enable_if_t<(_CurrentDimension != NumDimensions), DataAccess<CoordinateAccessT, CurrentDimension+1>>
133  operator[](index_t pos) {
134  _coords[CurrentDimension] = pos;
135  _reg_index *= REGION_INDEX_BASE;
136  if(_halo || pos < 0 || pos >= static_cast<index_t>(_access->_view_local->extent(CurrentDimension))) {
137  if(pos < 0) {
138  return DataAccess<CoordinateAccessT, CurrentDimension+1>(_access, _mem + pos * _access->_offsets[CurrentDimension], _coords, _reg_index, true);
139  }
140 
141  if(pos >= static_cast<index_t>(_access->_view_local->extent(CurrentDimension))) {
142  return DataAccess<CoordinateAccessT, CurrentDimension+1>(_access, _mem + pos * _access->_offsets[CurrentDimension], _coords, _reg_index + 2, true);
143  }
144 
145  return DataAccess<CoordinateAccessT, CurrentDimension+1>(_access, _mem + pos * _access->_offsets[CurrentDimension], _coords, _reg_index + 1, true);
146  }
147 
148  return DataAccess<CoordinateAccessT, CurrentDimension+1>(_access, _mem + pos * _access->_offsets[CurrentDimension], _coords, _reg_index + 1, false);
149  }
150 
151  template<dim_t _CurrentDimension = CurrentDimension + 1>
152  std::enable_if_t<(_CurrentDimension == NumDimensions), Element_t>&
153  operator[](index_t pos) {
154  if(_halo || pos < 0 || pos >= static_cast<index_t>(_access->_view_local->extent(CurrentDimension))) {
155  _reg_index *= REGION_INDEX_BASE;
156 
157  if(pos >= 0) {
158  ++_reg_index;
159  }
160 
161  if(pos >= static_cast<index_t>(_access->_view_local->extent(CurrentDimension))) {
162  ++_reg_index;
163  }
164 
165  _coords[CurrentDimension] = pos;
166  auto halo_memory = _access->_halo_memory;
167  halo_memory->to_halo_mem_coords(_reg_index, _coords);
168 
169  return *(halo_memory->first_element_at(_reg_index)
170  + halo_memory->offset(_reg_index, _coords));
171  }
172 
173  return _mem[pos];
174  }
175 
176 private:
177  const CoordinateAccessT* _access;
178  Element_t* _mem;
179  Coords_t _coords;
180  region_index_t _reg_index;
181  bool _halo;
182 };
183 
184 template<typename CoordinateAccessT>
186 private:
188 
189  static constexpr auto NumDimensions = CoordinateAccessT::ndim();
190  static constexpr auto MemoryArrange = CoordinateAccessT::memory_order();
191 
192 public:
193  using Element_t = typename CoordinateAccessT::Element_t;
194  using index_t = typename CoordinateAccessT::index_t;
195  using ViewSpec_t = typename CoordinateAccessT::ViewSpec_t;
196  using Offsets_t = typename CoordinateAccessT::Offsets_t;
198  using ViewRange_t = typename CoordinateAccessT::ViewRange_t;
199  using AllViewRanges_t = typename CoordinateAccessT::AllViewRanges_t;
200  using AllBndViewRanges = std::vector<AllViewRanges_t>;
201 
202  using HaloBlock_t = typename CoordinateAccessT::HaloBlock_t;
203  using HaloMemory_t = typename CoordinateAccessT::HaloMemory_t;
204  using Coords_t = typename CoordinateAccessT::Coords_t;
205 
206 public:
207  CoordinateHaloAccess(const CoordinateAccessT* _access)
208  : _access(_access)
209  , _data_access(_access->_data_access)
210  , _ranges(set_ranges(_access->_halo_block)) {
211  }
212 
213  static constexpr decltype(auto) ndim() { return NumDimensions; }
214 
215  static constexpr decltype(auto) memory_order() { return MemoryArrange; }
216 
217  AllBndViewRanges ranges() {
218  return _ranges;
219  }
220 
221  decltype(auto) operator[] (index_t pos) {
222  return _data_access[pos];
223  }
224 
225  decltype(auto) operator[] (index_t pos) const {
226  return _data_access[pos];
227  }
228 
229 private:
230 
231  AllBndViewRanges set_ranges(const HaloBlock_t* halo_block) const {
232  AllBndViewRanges all_ranges;
233  const auto& bnd_views = halo_block->boundary_views();
234  all_ranges.reserve(bnd_views.size());
235 
236  for(const auto& view : bnd_views) {
237  AllViewRanges_t ranges;
238  for(dim_t d = 0; d < NumDimensions; ++d) {
239  ranges[d] = {static_cast<index_t>(view.offset(d)),
240  static_cast<index_t>(view.offset(d) + view.extent(d))};
241  }
242  all_ranges.push_back(ranges);
243  }
244 
245  return all_ranges;
246  }
247 
248 
249 private:
250  const CoordinateAccessT* _access;
251  DataAccess_t _data_access;
252  AllBndViewRanges _ranges;
253 };
254 
255 template<typename HaloBlockT>
256 class CoordinateAccess {
257 private:
259  using Pattern_t = typename HaloBlockT::Pattern_t;
260 
261  static constexpr auto NumDimensions = Pattern_t::ndim();
262  static constexpr auto MemoryArrange = Pattern_t::memory_order();
263 
264  template <typename _CA>
265  friend class CoordinateInnerAccess;
266 
267  template <typename _CA>
268  friend class CoordinateHaloAccess;
269 
270  template <typename _CA, dim_t CurrentDim>
271  friend class DataInnerAccess;
272 
273  template <typename _CA, dim_t CurrentDim>
274  friend class DataAccess;
275 
276 public:
277  using Element_t = typename HaloBlockT::Element_t;
278  using HaloBlock_t = HaloBlockT;
279  using HaloMemory_t = HaloMemory<HaloBlock_t>;
280  using index_t = typename std::make_signed<typename Pattern_t::index_type>::type;
281  using uindex_t = typename std::make_unsigned<index_t>::type;
282  using ViewSpec_t = typename HaloBlockT::ViewSpec_t;
283  using Offsets_t = std::array<index_t, NumDimensions>;
285  using Coords_t = typename HaloMemory_t::ElementCoords_t;
286  using ViewRange_t = ViewRange<index_t>;
287  using AllViewRanges_t = std::array<ViewRange_t, NumDimensions>;
288 
289  using CoordInnerAcc_t = CoordinateInnerAccess<Self_t>;
290  using CoordHaloAcc_t = CoordinateHaloAccess<Self_t>;
291 
292 public:
293  CoordinateAccess(const HaloBlockT* haloblock,
294  Element_t* local_memory,
295  HaloMemory_t* halomemory)
296  : _halo_block(haloblock)
297  , _local_memory(local_memory)
298  , _halo_memory(halomemory)
299  , _view_local(&(haloblock->view_local()))
300  , _offsets(set_offsets())
301  , _data_access(DataAccess_t(this, _local_memory, Coords_t(), 0, false))
302  , _ranges(set_ranges(_halo_block->view_inner_with_boundaries()))
303  , _ranges_local(set_ranges(_halo_block->view_local()))
304  , _ranges_halo(set_ranges_halo(_halo_block->view_inner_with_boundaries()))
305  , inner(set_ranges(_halo_block->view_inner()), _local_memory, &_offsets)
306  , boundary(this) {
307  }
308 
309  static constexpr decltype(auto) ndim() { return NumDimensions; }
310 
311  static constexpr decltype(auto) memory_order() { return MemoryArrange; }
312 
313  ViewRange_t range_dim(dim_t dim) {
314  return _ranges(dim);
315  }
316 
317  AllViewRanges_t ranges() {
318  return _ranges;
319  }
320 
321  ViewRange_t range_local_dim(dim_t dim) {
322  return _ranges_local(dim);
323  }
324 
325  AllViewRanges_t ranges_local() {
326  return _ranges_local;
327  }
328 
329  ViewRange_t range_halo_dim(dim_t dim) {
330  return _ranges_halo(dim);
331  }
332 
333  AllViewRanges_t ranges_halo() {
334  return _ranges_halo;
335  }
336 
337  decltype(auto) operator[] (index_t pos) {
338  return _data_access[pos];
339  }
340 
341  decltype(auto) operator[] (index_t pos) const {
342  return _data_access[pos];
343  }
344 
345 private:
346  Offsets_t set_offsets() {
347  Offsets_t offsets;
348  if(MemoryArrange == ROW_MAJOR) {
349  offsets[NumDimensions - 1] = 1;
350  for(dim_t d = NumDimensions - 1; d > 0;) {
351  --d;
352  offsets[d] = 1;
353  for(dim_t d_tmp = d + 1; d_tmp < NumDimensions; ++d_tmp) {
354  offsets[d] *= _view_local->extent(d_tmp);
355  }
356  }
357  } else {
358  offsets[0] = 1;
359  for(dim_t d = 1; d < NumDimensions; ++d) {
360  offsets[d] = 1;
361  for(dim_t d_tmp = 0; d_tmp < d; ++d_tmp) {
362  offsets[d] *= _view_local->extent(d_tmp);
363  }
364  }
365  }
366 
367  return offsets;
368  }
369 
370  AllViewRanges_t set_ranges(ViewSpec_t view) const {
371  AllViewRanges_t ranges;
372  for(dim_t d = 0; d < NumDimensions; ++d) {
373  ranges[d] = {static_cast<index_t>(view.offset(d)),
374  static_cast<index_t>(view.offset(d) + view.extent(d))};
375  }
376 
377  return ranges;
378  }
379 
380  AllViewRanges_t set_ranges_halo(ViewSpec_t view) const {
381  AllViewRanges_t ranges;
382  for(dim_t d = 0; d < NumDimensions; ++d) {
383  const auto& ext_max = _halo_block->halo_spec().halo_extension_max(d);
384  ranges[d] = {static_cast<index_t>(view.offset(d)) - ext_max.first,
385  static_cast<index_t>(view.offset(d) + view.extent(d)) + ext_max.second};
386  }
387 
388  return ranges;
389  }
390 
391 
392 private:
393  const HaloBlock_t* _halo_block;
394  Element_t* _local_memory;
395  HaloMemory_t* _halo_memory;
396  const ViewSpec_t* _view_local;
397  Offsets_t _offsets;
398  DataAccess_t _data_access;
399  AllViewRanges_t _ranges;
400  AllViewRanges_t _ranges_local;
401  AllViewRanges_t _ranges_halo;
402 
403 public:
404  CoordInnerAcc_t inner;
405  CoordHaloAcc_t boundary;
406 
407 };
408 
409 } // namespace halo
410 
411 } // namespace dash
412 #endif // DASH__HALO_HALOCOORDINATEACCESS_H
Defines how a list of global indices is mapped to single units within a Team.
Definition: BlockPattern.h:42
This class is a simple memory pool which holds allocates elements of size ValueType.
Definition: AllOf.h:8
int dim_t
Scalar type for a dimension value, with 0 indicating the first dimension.
Definition: Types.h:39
N-Dimensional region coordinates and associated indices for all possible Halo/Boundary regions of a H...
Definition: Region.h:40
static constexpr dim_t ndim() noexcept
Number of dimensions of the cartesian space partitioned by the pattern.
constexpr dim_t ndim(const DimensionalType &d)
Definition: Dimensional.h:56
static constexpr MemArrange memory_order() noexcept
Memory order followed by the pattern.