DASH  0.3.0
StencilIterator.h
1 #ifndef DASH__HALO__ITERATOR__STENCILITERATOR_H
2 #define DASH__HALO__ITERATOR__STENCILITERATOR_H
3 
4 #include <dash/Types.h>
5 
6 #include <dash/halo/Halo.h>
7 #include <dash/halo/HaloMemory.h>
8 
9 #include <vector>
10 
11 namespace dash {
12 
13 namespace halo {
14 
15 using namespace internal;
16 
17 template<typename StencilOpT>
19 private:
21  using StencilSpec_t = typename StencilOpT::StencilSpec_t;
22 
23  static constexpr auto NumDimensions = StencilOpT::ndim();
24  static constexpr auto NumStencilPoints = StencilOpT::num_stencil_points();
25  static constexpr auto MemoryArrange = StencilOpT::memory_order();
26  static constexpr auto FastestDimension =
27  MemoryArrange == ROW_MAJOR ? NumDimensions - 1 : 0;
28 
29 public:
30  using Element_t = typename StencilOpT::Element_t;
31  using ViewSpec_t = typename StencilOpT::ViewSpec_t;
32  using index_t = typename StencilOpT::index_t;
33  using uindex_t = typename StencilOpT::uindex_t;
35  using Coords_t = typename StencilOpT::Coords_t;
36  using stencil_index_t = typename StencilSpec_t::stencil_index_t;
37 
38 private:
39  using RangeDim_t = std::pair<uindex_t, uindex_t>;
40  using Ranges_t = std::array<RangeDim_t, NumDimensions>;
41  using StencilOffsPtrs_t = std::array<Element_t*, NumStencilPoints>;
42  using OffsetsDim_t = std::array<uindex_t, NumDimensions>;
43  using viewspec_index_t = typename ViewSpec_t::index_type;
44  using LocalLayout_t =
46 
47 public:
48 
49  CoordsIdxManagerInner(StencilOpT& stencil_op,
50  uindex_t start_idx = 0, const ViewSpec_t* sub_view = nullptr)
51  : _stencil_op(&stencil_op),
52  _sub_view((sub_view != nullptr) ? sub_view : &(stencil_op.inner.view())),
53  _size(_sub_view->size()),
54  _local_layout(stencil_op.view_local().extents()) {
55  // initializes ranges, coordinates depending on the index, offsets for all dimensions and all stencil pointer
56  init_ranges();
57  set(start_idx);
58  }
59 
60  static constexpr decltype(auto) ndim() { return NumDimensions; }
61 
62  const ViewSpec_t& view() const { return _stencil_op->view_local(); }
63 
64  const ViewSpec_t& sub_view() const { return *_sub_view; }
65 
66  const Coords_t& coords() const { return _coords; }
67 
68  Coords_t coords(uindex_t idx) const { return _local_layout.coords(idx, *_sub_view); }
69 
70  const uindex_t& index() const { return _idx; }
71 
72  const uindex_t& offset() const { return _offset; }
73 
74  Element_t& value() const { return *_current_lmemory_addr; }
75 
76  Element_t& value_at(const stencil_index_t index_stencil ) const { return *_stencil_mem_ptr[index_stencil]; }
77 
78  Element_t& value_at(const StencilP_t& stencil) {
79  const auto index_stencil = _stencil_op->stencil_spec().index(stencil);
80 
81  DASH_ASSERT_MSG(index_stencil.second,
82  "No valid region index for given stencil point found");
83 
84  return value_at(index_stencil.first);
85  }
86 
87  void set(uindex_t idx) {
88  if(idx >=_size) {
89  _idx = _size;
90 
91  return;
92  }
93 
94  _idx = idx;
95  init_coords();
96  init_offset();
97  init_stencil_points();
98  }
99 
100  Element_t operator[](index_t n) const {
101  auto index = _idx + n;
102  auto new_coords = coords(index);
103 
104  return _stencil_op->local_memory()[_local_layout.at(new_coords)];
105  }
106 
107  Element_t& operator[](index_t n) {
108  return operator[](n);
109  }
110 
111  void next_element() {
112  ++_idx;
113  ++_coords[FastestDimension];
114  if(static_cast<uindex_t>(_coords[FastestDimension]) < _ranges[FastestDimension].second) {
115  for(auto i = 0u; i < NumStencilPoints; ++i)
116  ++_stencil_mem_ptr[i];
117 
118  ++_current_lmemory_addr;
119  ++_offset;
120 
121  return;
122  }
123  _coords[FastestDimension] = _sub_view->offset(FastestDimension);
124  uindex_t add = 0;
125  if(MemoryArrange == ROW_MAJOR) {
126  for(dim_t d = NumDimensions-1; d > 0;) {
127  --d;
128  ++_coords[d];
129  if(static_cast<uindex_t>(_coords[d]) < _ranges[d].second) {
130  add = _offsets_dim[d];
131  break;
132  } else {
133  _coords[d] = _ranges[d].first;
134 
135  }
136  }
137  } else {
138  for(dim_t d = 1; d < NumDimensions; ++d) {
139  ++_coords[d];
140  if(static_cast<uindex_t>(_coords[d]) < _ranges[d].second) {
141  add = _offsets_dim[d];
142  break;
143  } else {
144  _coords[d] = _ranges[d].first;
145  }
146  }
147  }
148  _current_lmemory_addr += add;
149  _offset += add;
150  for(auto i = 0u; i < NumStencilPoints; ++i) {
151  _stencil_mem_ptr[i] += add;
152  }
153  }
154 
155 
156 private:
157  void init_ranges() {
158  for(dim_t d = 0; d < NumDimensions; ++d) {
159  _ranges[d] = std::make_pair(_sub_view->offset(d), _sub_view->offset(d) + _sub_view->extent(d));
160  }
161  }
162 
163  void init_coords() {
164  _coords = _local_layout.coords(_idx, *_sub_view);
165  }
166 
167  void init_offset() {
168  if(MemoryArrange == ROW_MAJOR) {
169  _offset = _coords[0];
170  for(dim_t d = 1; d < NumDimensions; ++d)
171  _offset = _offset * _local_layout.extent(d) + _coords[d];
172  } else {
173  _offset = _coords[NumDimensions - 1];
174  for(dim_t d = NumDimensions - 1; d > 0;) {
175  --d;
176  _offset = _offset * _local_layout.extent(d) + _coords[d];
177  }
178  }
179 
180  const auto& view = _stencil_op->view_local();
181  _offsets_dim[FastestDimension] = 1;
182  if(MemoryArrange == ROW_MAJOR) {
183  if(FastestDimension > 0) {
184  _offsets_dim[FastestDimension - 1] = (view.extent(FastestDimension) - _sub_view->extent(FastestDimension)) + 1;
185  }
186  for(dim_t d = FastestDimension - 1; d > 0;) {
187  --d;
188  _offsets_dim[d] = (view.extent(d+1) - _sub_view->extent(d+1)) * view.extent(d+2) + _offsets_dim[d+1];
189  }
190  } else {
191  if(NumDimensions > 1) {
192  _offsets_dim[FastestDimension + 1] = (view.extent(FastestDimension) - _sub_view->extent(FastestDimension)) + 1;
193  }
194  for(dim_t d = 2; d < NumDimensions; ++d) {
195  _offsets_dim[d] = (view.extent(d-1) - _sub_view->extent(d-1)) * view.extent(d-2) + _offsets_dim[d-1];
196  }
197  }
198  }
199 
200  void init_stencil_points() {
201  _current_lmemory_addr = _stencil_op->local_memory() + _offset;
202  for(auto i = 0u; i < NumStencilPoints; ++i) {
203  _stencil_mem_ptr[i] = _current_lmemory_addr + _stencil_op->stencil_offsets()[i];
204  }
205  }
206 
207 private:
208  StencilOpT* _stencil_op;
209  const ViewSpec_t* _sub_view;
210  uindex_t _size;
211  LocalLayout_t _local_layout;
212  uindex_t _idx;
213  Element_t* _current_lmemory_addr;
214  StencilOffsPtrs_t _stencil_mem_ptr;
215  Ranges_t _ranges;
216  Coords_t _coords;
217  uindex_t _offset;
218  OffsetsDim_t _offsets_dim;
219 };
220 
221 template <typename StencilOpT>
222 std::ostream& operator<<(
223  std::ostream& os,
224  const CoordsIdxManagerInner<StencilOpT>& helper) {
225  os << "dash::halo::CoordsHelper"
226  << "(view: " << helper.view()
227  << "; sub_view: " << helper.sub_view()
228  << "; index: " << helper.index()
229  << "; offset: " << helper.offset()
230  << "; coords: { ";
231  for(const auto& elem : helper.coords()) {
232  os << elem << " ";
233  }
234  os << "})";
235 
236  return os;
237 }
238 
239 template<typename StencilOpT>
241 
242 private:
244  using StencilSpec_t = typename StencilOpT::StencilSpec_t;
245  using StencilSpecViews_t = typename StencilOpT::StencilSpecViews_t;
246 
247  static constexpr auto NumDimensions = StencilOpT::ndim();
248  static constexpr auto NumStencilPoints = StencilOpT::num_stencil_points();
249  static constexpr auto MemoryArrange = StencilOpT::memory_order();
250  static constexpr auto FastestDimension =
251  MemoryArrange == ROW_MAJOR ? NumDimensions - 1 : 0;
252 
253 public:
254  using Element_t = typename StencilOpT::Element_t;
255  using ViewSpec_t = typename StencilOpT::ViewSpec_t;
256  using index_t = typename StencilOpT::index_t;
257  using uindex_t = typename StencilOpT::uindex_t;
259  using Coords_t = typename StencilOpT::Coords_t;
260  using stencil_index_t = typename StencilSpec_t::stencil_index_t;
261 
263 private:
264  using BoundaryViews_t = typename StencilSpecViews_t::BoundaryViews_t;
265  using viewspec_index_t = typename ViewSpec_t::index_type;
266  using LocalLayout_t =
268  using ViewIndexPair_t = std::pair<const ViewSpec_t*, uindex_t>;
269  using StencilOffsPtrs_t = std::array<Element_t*, NumStencilPoints>;
270  using OffsetsDim_t = std::array<uindex_t, NumDimensions>;
271 
272  struct RangeDim_t {
273  uindex_t begin = 0;
274  uindex_t end = 0;
275  };
276  using Ranges_t = std::array<RangeDim_t, NumDimensions>;
277 
278  struct HaloPointProp_t {
279  bool possible;
280  bool always;
281  region_index_t index;
282  };
283  using HaloPoints_t = std::array<HaloPointProp_t, NumStencilPoints>;
284 
285 
286 public:
287 
288  CoordsIdxManagerBoundary(StencilOpT& stencil_op, uindex_t start_idx = 0)
289  : _stencil_op(&stencil_op),
290  _size(stencil_op.spec_views().boundary_size()),
291  _region_number(0),
292  _local_layout(stencil_op.view_local().extents()),
293  _idx(0) {
294  const auto& ext_max = stencil_op.stencil_spec().minmax_distances(FastestDimension);
295 
296  _ext_dim_reduced = {static_cast<uindex_t>(std::abs(ext_max.first)),
297  _local_layout.extent(FastestDimension) - static_cast<uindex_t>(ext_max.second)};
298  set(start_idx);
299  }
300 
301  static constexpr decltype(auto) ndim() { return NumDimensions; }
302 
303  const ViewSpec_t& view() const { return _stencil_op->view_local(); }
304 
305  const ViewSpec_t& sub_view() const { return *(_current_view.first); }
306 
307  const Coords_t& coords() const { return _coords; }
308 
309  const uindex_t& index() const { return _idx; }
310 
311  const uindex_t& offset() const { return _offset; }
312 
313  Element_t& value() const { return *_current_lmemory_addr; }
314 
315  Element_t& value_at(const stencil_index_t index_stencil ) const { return *_stencil_mem_ptr[index_stencil]; }
316 
317  Element_t& value_at(const StencilP_t& stencil) {
318  const auto index_stencil = _stencil_op->stencil_spec().index(stencil);
319 
320  DASH_ASSERT_MSG(index_stencil.second,
321  "No valid region index for given stencil point found");
322 
323  return value_at(index_stencil.first);
324  }
325 
326  void set(uindex_t idx) {
327  if(idx >=_size) {
328  _idx = _size;
329 
330  return;
331  }
332 
333  _idx = idx;
334  _current_view = get_current_view(_idx);
335  init_ranges();
336  init_coords();
337  init_offset();
338  init_stencil_points();
339 
340  }
341 
342  Element_t operator[](index_t n) const {
343  auto index = _idx + n;
344  auto new_coords = coords(index);
345 
346  return _stencil_op->local_memory()[_local_layout.at(new_coords)];
347  }
348 
349  Element_t& operator[](index_t n) {
350  return operator[](n);
351  }
352 
353  const region_index_t region_id() const { return _region_number; }
354 
355  const uindex_t& size() const { return _size; }
356 
357  void next_element() {
358  ++_idx;
359  ++_current_view.second;
360  ++_coords[FastestDimension];
361  uindex_t add = 1;
362  if(static_cast<uindex_t>(_coords[FastestDimension]) < _ranges[FastestDimension].end) {
363  if(static_cast<uindex_t>(_coords[FastestDimension]) >= _ext_dim_reduced.begin
364  && static_cast<uindex_t>(_coords[FastestDimension]) < _ext_dim_reduced.end) {
365  ++_current_lmemory_addr;
366  ++_offset;
367  for(auto i = 0u; i < NumStencilPoints; ++i) {
368  ++_stencil_mem_ptr[i];
369  }
370 
371  return;
372  }
373  } else {
374 
375  if(_current_view.second == (*_current_view.first).size()) {
376 
377  auto& bnd_views = _stencil_op->boundary.view();
378 
379  do {
380  ++_region_number;
381  if(_region_number >= bnd_views.size()) {
382  _region_number = bnd_views.size();
383 
384  return;
385  }
386 
387  } while(bnd_views[_region_number].size() == 0);
388 
389  if(_idx < _size) {
390  _current_view = {&bnd_views[_region_number],0};
391  init_ranges();
392  init_coords();
393  init_offset();
394  init_stencil_points();
395  }
396 
397  return;
398  }
399 
400  if(static_cast<uindex_t>(_coords[FastestDimension]) >= _ranges[FastestDimension].end) {
401  _coords[FastestDimension] = _ranges[FastestDimension].begin;
402  if(MemoryArrange == ROW_MAJOR) {
403  for(dim_t d = NumDimensions-1; d > 0;) {
404  --d;
405  ++_coords[d];
406  if(static_cast<uindex_t>(_coords[d]) < _ranges[d].end) {
407  add = _offsets_dim[d];
408  break;
409  } else {
410  _coords[d] = _ranges[d].begin;
411  }
412  }
413  }
414 
415  if(MemoryArrange == COL_MAJOR) {
416  for(dim_t d = 1; d < NumDimensions; ++d) {
417  ++_coords[d];
418  if(static_cast<uindex_t>(_coords[d]) < _ranges[d].end) {
419  add = _offsets_dim[d];
420  break;
421  } else {
422  _coords[d] = _ranges[d].begin;
423  }
424  }
425  }
426  }
427  }
428 
429  _current_lmemory_addr += add;
430  _offset += add;
431  const auto& extents = _local_layout.extents();
432  const auto& specs = _stencil_op->stencil_spec();
433  const auto& stencil_offs = _stencil_op->stencil_offsets();
434  for(auto i = 0u; i < NumStencilPoints; ++i) {
435  if(_spoint_is_halo[i].possible) {
436  auto& stencil = specs[i];
437  auto coords = _coords;
438 
439  if(_spoint_is_halo[i].always) {
440  for(dim_t d = 0; d < NumDimensions; ++d)
441  coords[d] += stencil[d];
442  _stencil_mem_ptr[i] = value_halo_at(_spoint_is_halo[i].index, coords);
443  continue;
444  }
445 
446  bool is_halo = false;
447  region_index_t index = 0;
448  for(dim_t d = 0; d < NumDimensions; ++d) {
449  auto stencil_off = stencil[d];
450  if(stencil_off == 0) {
451  index = 1 + index * REGION_INDEX_BASE;
452  continue;
453  }
454  coords[d] += stencil_off;
455  if(coords[d] < 0) {
456  index *= REGION_INDEX_BASE;
457  is_halo = true;
458  continue;
459  }
460 
461  if(static_cast<uindex_t>(coords[d]) < extents[d]) {
462  index = 1 + index * REGION_INDEX_BASE;
463  continue;
464  }
465 
466  index = 2 + index * REGION_INDEX_BASE;
467  is_halo = true;
468  }
469  if(is_halo) {
470  _stencil_mem_ptr[i] = value_halo_at(index, coords);
471  continue;
472  }
473 
474  _stencil_mem_ptr[i] = _current_lmemory_addr + stencil_offs[i];
475  } else {
476  _stencil_mem_ptr[i] += add;
477  }
478  }
479  }
480 
481 
482 private:
483 
484  void init_ranges() {
485  for(dim_t d = 0; d < NumDimensions; ++d) {
486  auto sub_view = _current_view.first;
487  _ranges[d] = {static_cast<uindex_t>(sub_view->offset(d)),
488  static_cast<uindex_t>(sub_view->offset(d)) + sub_view->extent(d)};
489  }
490  }
491 
492  void init_coords() {
493  _coords = _local_layout.coords(_current_view.second, *_current_view.first);
494  }
495 
496  void init_offset() {
497  if(MemoryArrange == ROW_MAJOR) {
498  _offset = _coords[0];
499  for(dim_t d = 1; d < NumDimensions; ++d)
500  _offset = _offset * _local_layout.extent(d) + _coords[d];
501  } else {
502  _offset = _coords[NumDimensions - 1];
503  for(dim_t d = NumDimensions - 1; d > 0;) {
504  --d;
505  _offset = _offset * _local_layout.extent(d) + _coords[d];
506  }
507  }
508 
509  auto& sub_view = *(_current_view.first);
510  _offsets_dim[FastestDimension] = 1;
511  const auto& view = _stencil_op->view_local();
512  if(MemoryArrange == ROW_MAJOR) {
513  if(FastestDimension > 0) {
514  _offsets_dim[FastestDimension - 1] = (view.extent(FastestDimension) - sub_view.extent(FastestDimension)) + 1;
515  }
516  for(dim_t d = FastestDimension - 1; d > 0;) {
517  --d;
518  _offsets_dim[d] = (view.extent(d+1) - sub_view.extent(d+1)) * view.extent(d+2) + _offsets_dim[d+1];
519  }
520  } else {
521  if(NumDimensions > 1) {
522  _offsets_dim[FastestDimension + 1] = (view.extent(FastestDimension) - sub_view.extent(FastestDimension)) + 1;
523  }
524  for(dim_t d = 2; d < NumDimensions; ++d) {
525  _offsets_dim[d] = (view.extent(d-1) - sub_view.extent(d-1)) * view.extent(d-2) + _offsets_dim[d-1];
526  }
527  }
528  }
529 
530  ViewIndexPair_t get_current_view(uindex_t idx) {
531  _region_number = 0;
532  const auto& bnd_views = _stencil_op->boundary.view();
533  for(const auto& region : bnd_views) {
534  if(idx < region.size()) {
535  return std::make_pair(&region, idx);
536  }
537  ++_region_number;
538  idx -= region.size();
539  }
540 
541  auto& last_region = bnd_views.back();
542  return std::make_pair(&last_region, last_region.size());
543  }
544 
545  void init_stencil_points() {
546  _current_lmemory_addr = _stencil_op->local_memory() + _offset;
547  const auto& specs = _stencil_op->stencil_spec();
548  const auto& stencil_offs = _stencil_op->stencil_offsets();
549  auto minmax = specs.minmax_distances();
550  const auto& extents = _local_layout.extents();
551 
552  for(auto i = 0u; i < NumStencilPoints; ++i) {
553  auto& spoint_halo =_spoint_is_halo[i];
554  spoint_halo = {false, true, 0};
555 
556  auto halo_coord = _coords;
557  bool is_halo = false;
558  for(dim_t d = 0; d < NumDimensions; ++d) {
559  auto stencil_off = specs[i][d];
560  if(stencil_off == 0) {
561  spoint_halo.index = 1 + spoint_halo.index * REGION_INDEX_BASE;
562  continue;
563  }
564 
565  halo_coord[d] += stencil_off;
566  if(halo_coord[d] < 0) {
567  spoint_halo.index *= REGION_INDEX_BASE;
568  spoint_halo.possible = true;
569  is_halo = true;
570  if( halo_coord[d] > minmax[d].first) {
571  spoint_halo.always = false;
572  }
573  continue;
574  }
575 
576  if(static_cast<uindex_t>(halo_coord[d]) < extents[d]) {
577  spoint_halo.index = 1 + spoint_halo.index * REGION_INDEX_BASE;
578  if(_coords[d] < std::abs(minmax[d].first) ||
579  (extents[d] - static_cast<uindex_t>(_coords[d])) <= static_cast<uindex_t>(minmax[d].second)) {
580  spoint_halo.always = false;
581  spoint_halo.possible = true;
582  }
583 
584  continue;
585  }
586 
587  spoint_halo.index = 2 + spoint_halo.index * REGION_INDEX_BASE;
588  spoint_halo.possible = true;
589  is_halo = true;
590  if(minmax[d].second != stencil_off) {
591  spoint_halo.always = false;
592  }
593  }
594 
595  if(is_halo)
596  _stencil_mem_ptr[i] = value_halo_at(spoint_halo.index, halo_coord);
597  else
598  _stencil_mem_ptr[i] = _current_lmemory_addr + stencil_offs[i];
599  }
600  }
601 
602  Element_t* value_halo_at(region_index_t region_index,
603  Coords_t& halo_coords) {
604  auto& halo_memory = _stencil_op->halo_memory();
605  halo_memory.to_halo_mem_coords(region_index, halo_coords);
606 
607  return &*(halo_memory.first_element_at(region_index)
608  + halo_memory.offset(region_index, halo_coords));
609  }
610 
611 private:
612  StencilOpT* _stencil_op;
613  uindex_t _size;
614  region_index_t _region_number{ 0 };
615  LocalLayout_t _local_layout;
616  uindex_t _idx;
617  Coords_t _coords;
618  ViewIndexPair_t _current_view;
619  Element_t* _current_lmemory_addr;
620  StencilOffsPtrs_t _stencil_mem_ptr;
621  HaloPoints_t _spoint_is_halo;
622 
623  uindex_t _offset;
624  OffsetsDim_t _offsets_dim;
625  Ranges_t _ranges;
626  RangeDim_t _ext_dim_reduced;
627 };
628 
629 template <typename StencilOpT>
630 std::ostream& operator<<(
631  std::ostream& os,
632  const CoordsIdxManagerBoundary<StencilOpT>& helper) {
633  os << "dash::halo::CoordsHelper"
634  << "(view: " << helper.view()
635  << "; region id: " << helper.region_id()
636  << "; sub_view: " << helper.sub_view()
637  << "; index: " << helper.index()
638  << "; offset: " << helper.offset()
639  << "; coords: { ";
640  for(const auto& elem : helper.coords()) {
641  os << elem << " ";
642  }
643  os << "})";
644 
645  return os;
646 }
647 
648 
649 /*
650  * Stencil specific iterator to iterate over a given scope of elements.
651  * The iterator provides element access via stencil points and for boundary
652  * elements halo element access.
653  */
654 template <typename CoordsIdxManagerT>
656 private:
657  using Element_t = typename CoordsIdxManagerT::Element_t;
658 
660  using ViewSpec_t = typename CoordsIdxManagerT::ViewSpec_t;
661 
662  static constexpr auto NumDimensions = CoordsIdxManagerT::ndim();
663 
664 public:
665  // Iterator traits
666  using iterator_category = std::random_access_iterator_tag;
667  using value_type = Element_t;
668  using difference_type = typename CoordsIdxManagerT::uindex_t;
669  using pointer = Element_t*;
670  using reference = Element_t&;
671 
672  using index_t = typename CoordsIdxManagerT::index_t;
673  using uindex_t = typename CoordsIdxManagerT::uindex_t;
675  using Coords_t = typename CoordsIdxManagerT::Coords_t;
676  using stencil_index_t = typename CoordsIdxManagerT::stencil_index_t;
677 
678 public:
679  //TODO anpassen
685  StencilIteratorTest(CoordsIdxManagerT coords_mng)
686  : _coords_mng(coords_mng) {
687  }
688 
692  StencilIteratorTest(const Self_t& other) = default;
693 
699  Self_t& operator=(const Self_t& other) = default;
700 
706  static constexpr dim_t ndim() { return NumDimensions; }
707 
713  reference operator*() const { return _coords_mng.value(); }
714 
721  Element_t operator[](index_t n) const {
722  return _coords_mng[n];
723  }
724 
725  reference operator[](index_t n) {
726  return _coords_mng[n];
727  }
728 
729  uindex_t rpos() const { return _coords_mng.index(); }
730 
731  uindex_t lpos() const { return _coords_mng.offset(); }
732 
733  Coords_t coords() const { return _coords_mng.coords(); }
734 
735  CoordsIdxManagerT& helper() {return _coords_mng;}
736 
741  Element_t value_at(const stencil_index_t index_stencil) {
742  return _coords_mng.value_at(index_stencil);
743  }
744 
745  /* returns the value of a given stencil point (not as efficient as
746  * stencil point index )
747  */
748  Element_t value_at(const StencilP_t& stencil) {
749  return _coords_mng.value_at(stencil);
750  }
751 
756  _coords_mng.next_element();
757 
758  return *this;
759  }
760 
765  Self_t result = *this;
766 
767  _coords_mng.next_element();
768 
769  return result;
770  }
771 
776  _coords_mng.set(_coords_mng.index()-1);
777 
778  return *this;
779  }
780 
785  Self_t result = *this;
786 
787  _coords_mng.set(_coords_mng.index()-1);
788 
789  return result;
790  }
791 
792  Self_t& operator+=(index_t n) {
793  auto index = _coords_mng.index() + n;
794  //if(index < _coords_mng.size())
795  _coords_mng.set(index);
796 
797  return *this;
798  }
799 
800  Self_t& operator-=(index_t n) {
801  auto index = _coords_mng.index();
802  if(index >= n)
803  _coords_mng.set(index - n);
804 
805  return *this;
806  }
807 
808  Self_t operator+(index_t n) const {
809  auto res( *this );
810  res += n;
811 
812  return res;
813  }
814 
815  Self_t operator-(index_t n) const {
816  auto res( *this );
817  res -= n;
818 
819  return res;
820  }
821 
822  difference_type operator-(const Self_t& other) const { return _coords_mng.index() - other._coords_mng.index(); }
823 
824  bool operator<(const Self_t& other) const {
825  return compare(other, std::less<index_t>());
826  }
827 
828  bool operator<=(const Self_t& other) const {
829  return compare(other, std::less_equal<index_t>());
830  }
831 
832  bool operator>(const Self_t& other) const {
833  return compare(other, std::greater<index_t>());
834  }
835 
836  bool operator>=(const Self_t& other) const {
837  return compare(other, std::greater_equal<index_t>());
838  }
839 
840  bool operator==(const Self_t& other) const {
841  return compare(other, std::equal_to<index_t>());
842  }
843 
844  bool operator!=(const Self_t& other) const {
845  return compare(other, std::not_equal_to<index_t>());
846  }
847 
848 private:
853  template <typename GlobIndexCmpFunc>
854  bool compare(const Self_t& other, const GlobIndexCmpFunc& gidx_cmp) const {
855 
856  return gidx_cmp(_coords_mng.index(), other._coords_mng.index());
857  }
858 
859 private:
860  CoordsIdxManagerT _coords_mng;
861 }; // class StencilIterator
862 
863 
864 /*
865  * Stencil specific iterator to iterate over a given scope of elements.
866  * The iterator provides element access via stencil points and for boundary
867  * elements halo element access.
868  */
869 template <typename ElementT, typename PatternT, typename GlobMemT, typename StencilSpecT,
870  StencilViewScope Scope>
872 private:
873  static constexpr auto NumDimensions = PatternT::ndim();
874  static constexpr auto NumStencilPoints = StencilSpecT::num_stencil_points();
875  static constexpr auto MemoryArrange = PatternT::memory_order();
876  static constexpr auto FastestDimension =
877  MemoryArrange == ROW_MAJOR ? NumDimensions - 1 : 0;
878 
880  using ViewSpec_t = typename PatternT::viewspec_type;
881  using pattern_size_t = typename PatternT::size_type;
884 
885 public:
886  // Iterator traits
887  using iterator_category = std::random_access_iterator_tag;
888  using value_type = ElementT;
889  using difference_type = typename PatternT::index_type;
890  using pointer = ElementT*;
891  using reference = ElementT&;
892 
894  using pattern_index_t = typename PatternT::index_type;
895  using LocalLayout_t =
898  using ElementCoords_t = std::array<pattern_index_t, NumDimensions>;
899  using signed_pattern_size_t = typename std::make_signed<pattern_size_t>::type;
900  using StencilOffsets_t =
901  std::array<signed_pattern_size_t, NumStencilPoints>;
903  using BoundaryViews_t = typename StencilSpecViews_t::BoundaryViews_t;
904 
905 public:
917  StencilIterator(ElementT* local_memory, HaloMemory_t* halomemory,
918  const StencilSpecT* stencil_spec,
919  const StencilOffsets_t* stencil_offsets,
920  const ViewSpec_t& view_local, const ViewSpec_t& view_scope,
921  pattern_index_t idx)
922  : _halomemory(halomemory), _stencil_spec(stencil_spec),
923  _stencil_offsets(stencil_offsets), _view(view_scope),
924  _local_memory(local_memory),
925  _local_layout(view_local.extents()), _idx(idx) {
926  _size = _view.size();
927  if(_idx < _size)
928  set_coords();
929 
930  const auto ext_max = stencil_spec->minmax_distances(FastestDimension);
931  if(Scope == StencilViewScope::INNER) {
932  _ext_dim_reduced = std::make_pair(
933  _view.offset(FastestDimension),
934  _local_layout.extent(FastestDimension) - ext_max.second - 1);
935  } else {
936  _ext_dim_reduced =
937  std::make_pair(std::abs(ext_max.first),
938  _view.extent(FastestDimension) - ext_max.second - 1);
939  }
940  }
941 
953  StencilIterator(ElementT* local_memory, HaloMemory_t* halomemory,
954  const StencilSpecT* stencil_spec,
955  const StencilOffsets_t* stencil_offsets,
956  const ViewSpec_t& view_local,
957  const BoundaryViews_t& boundary_views, pattern_index_t idx)
958  : _halomemory(halomemory), _stencil_spec(stencil_spec),
959  _stencil_offsets(stencil_offsets),
960  _view(view_local.extents()),
961  _boundary_views(boundary_views),
962  _local_memory(local_memory),
963  _local_layout(view_local.extents()), _idx(idx) {
964  _size = 0;
965  for(const auto& view : boundary_views)
966  _size += view.size();
967 
968  if(_idx < _size)
969  set_coords();
970 
971  const auto ext_max = stencil_spec->minmax_distances(FastestDimension);
972 
973  _ext_dim_reduced =
974  std::make_pair(std::abs(ext_max.first),
975  _view.extent(FastestDimension) - ext_max.second - 1);
976  }
977 
981  StencilIterator(const Self_t& other) = default;
982 
988  Self_t& operator=(const Self_t& other) = default;
989 
995  static constexpr dim_t ndim() { return NumDimensions; }
996 
1002  reference operator*() const { return *_current_lmemory_addr; }
1003 
1010  reference operator[](pattern_index_t n) const {
1011  auto coords = set_coords(_idx + n);
1012  return _local_memory[_local_layout.at(coords)];
1013  }
1014 
1015  pattern_index_t rpos() const { return _idx; }
1016 
1017  pattern_index_t lpos() const { return _offset; }
1018 
1019  ElementCoords_t coords() const { return _coords; };
1020 
1021  bool is_halo_value(const region_index_t index_stencil) {
1022  if(Scope == StencilViewScope::INNER)
1023  return false;
1024 
1025  auto halo_coords = _coords;
1026  const auto& stencil = (*_stencil_spec)[index_stencil];
1027  for(auto d = 0; d < NumDimensions; ++d) {
1028  halo_coords[d] += stencil[d];
1029  if(halo_coords[d] < 0 || halo_coords[d] >= _local_layout.extent(d))
1030  return true;
1031  }
1032 
1033  return false;
1034  }
1035 
1040  ElementT value_at(const region_index_t index_stencil) {
1041  return *(_stencil_mem_ptr[index_stencil]);
1042  }
1043 
1044  /* returns the value of a given stencil point (not as efficient as
1045  * stencil point index )
1046  */
1047  ElementT value_at(const StencilP_t& stencil) {
1048  auto index_stencil = _stencil_spec->index(stencil);
1049 
1050  DASH_ASSERT_MSG(index_stencil.second,
1051  "No valid region index for given stencil point found");
1052 
1053  return value_at(index_stencil.first);
1054  }
1055 
1060  ++_idx;
1061  next_element();
1062 
1063  return *this;
1064  }
1065 
1070  Self_t result = *this;
1071  ++_idx;
1072  next_element();
1073 
1074  return result;
1075  }
1076 
1081  --_idx;
1082  set_coords();
1083 
1084  return *this;
1085  }
1086 
1091  Self_t result = *this;
1092  --_idx;
1093  if(_idx < _size) {
1094  _coords = set_coords(_idx);
1095  set_offsets();
1096  }
1097 
1098  return result;
1099  }
1100 
1101  Self_t& operator+=(pattern_index_t n) {
1102  _idx += n;
1103  if(_idx < _size) {
1104  _coords = set_coords(_idx);
1105  set_offsets();
1106  }
1107 
1108  return *this;
1109  }
1110 
1111  Self_t& operator-=(pattern_index_t n) {
1112  _idx -= n;
1113  if(_idx < _size) {
1114  _coords = set_coords(_idx);
1115  set_offsets();
1116  }
1117 
1118  return *this;
1119  }
1120 
1121  Self_t operator+(pattern_index_t n) const {
1122  auto res( *this );
1123  res += n;
1124 
1125  return res;
1126  }
1127 
1128  Self_t operator-(pattern_index_t n) const {
1129  auto res( *this );
1130  res -= n;
1131 
1132  return res;
1133  }
1134 
1135  difference_type operator-(const Self_t& other) const { return _idx - other._idx; }
1136 
1137  bool operator<(const Self_t& other) const {
1138  return compare(other, std::less<pattern_index_t>());
1139  }
1140 
1141  bool operator<=(const Self_t& other) const {
1142  return compare(other, std::less_equal<pattern_index_t>());
1143  }
1144 
1145  bool operator>(const Self_t& other) const {
1146  return compare(other, std::greater<pattern_index_t>());
1147  }
1148 
1149  bool operator>=(const Self_t& other) const {
1150  return compare(other, std::greater_equal<pattern_index_t>());
1151  }
1152 
1153  bool operator==(const Self_t& other) const {
1154  return compare(other, std::equal_to<pattern_index_t>());
1155  }
1156 
1157  bool operator!=(const Self_t& other) const {
1158  return compare(other, std::not_equal_to<pattern_index_t>());
1159  }
1160 
1161 private:
1166  template <typename GlobIndexCmpFunc>
1167  bool compare(const Self_t& other, const GlobIndexCmpFunc& gidx_cmp) const {
1168 #if __REMARK__
1169  // Usually this is a best practice check, but it's an infrequent case
1170  // so we rather avoid this comparison:
1171  if(this == &other) {
1172  return true;
1173  }
1174 #endif
1175  return gidx_cmp(_idx, other._idx);
1176 
1177  // TODO not the best solution
1178  return false;
1179  }
1180 
1181  void next_element() {
1182  const auto& coord_fastest_dim = _coords[FastestDimension];
1183 
1184  if(coord_fastest_dim >= _ext_dim_reduced.first
1185  && coord_fastest_dim < _ext_dim_reduced.second) {
1186  for(auto it = _stencil_mem_ptr.begin(); it != _stencil_mem_ptr.end();
1187  ++it)
1188  *it += 1;
1189 
1190  ++_coords[FastestDimension];
1191  ++_current_lmemory_addr;
1192  ++_offset;
1193 
1194  return;
1195  }
1196 
1197  if(Scope == StencilViewScope::INNER) {
1198  if(MemoryArrange == ROW_MAJOR) {
1199  for(dim_t d = NumDimensions; d > 0;) {
1200  --d;
1201  if(_coords[d] < _view.extent(d) + _view.offset(d) - 1) {
1202  ++_coords[d];
1203  break;
1204  } else
1205  _coords[d] = _view.offset(d);
1206  }
1207  } else {
1208  for(dim_t d = 0; d < NumDimensions; ++d) {
1209  if(_coords[d] < _view.extent(d) + _view.offset(d) - 1) {
1210  ++_coords[d];
1211  break;
1212  } else
1213  _coords[d] = _view.offset(d);
1214  }
1215  }
1216  if(MemoryArrange == ROW_MAJOR) {
1217  _offset = _coords[0];
1218  for(dim_t d = 1; d < NumDimensions; ++d)
1219  _offset = _offset * _local_layout.extent(d) + _coords[d];
1220  } else {
1221  _offset = _coords[NumDimensions - 1];
1222  for(dim_t d = NumDimensions - 1; d > 0;) {
1223  --d;
1224  _offset = _offset * _local_layout.extent(d) + _coords[d];
1225  }
1226  }
1227  _current_lmemory_addr = _local_memory + _offset;
1228  for(auto i = 0; i < NumStencilPoints; ++i)
1229  _stencil_mem_ptr[i] = _current_lmemory_addr + (*_stencil_offsets)[i];
1230  } else
1231  set_coords();
1232  }
1233 
1234  void set_coords() {
1235  if(Scope == StencilViewScope::BOUNDARY) {
1236  if(_region_bound == 0) {
1237  _coords = set_coords(_idx);
1238  } else {
1239  if(_idx < _region_bound) {
1240  const auto& region = _boundary_views[_region_number];
1241 
1242  if(MemoryArrange == ROW_MAJOR) {
1243  for(dim_t d = NumDimensions; d > 0;) {
1244  --d;
1245  if(_coords[d] < region.extent(d) + region.offset(d) - 1) {
1246  ++_coords[d];
1247  break;
1248  } else {
1249  _coords[d] = region.offset(d);
1250  }
1251  }
1252  } else {
1253  for(dim_t d = 0; d < NumDimensions; ++d) {
1254  if(_coords[d] < region.extent(d) + region.offset(d) - 1) {
1255  ++_coords[d];
1256  break;
1257  } else {
1258  _coords[d] = region.offset(d);
1259  }
1260  }
1261  }
1262  } else {
1263  do {
1264  ++_region_number;
1265  if(_region_number >= _boundary_views.size())
1266  return;
1267 
1268  _region_bound += _boundary_views[_region_number].size();
1269  } while(_idx >= _region_bound);
1270  _coords = _local_layout.coords(0, _boundary_views[_region_number]);
1271  }
1272  }
1273  } else {
1274  if(_idx < _size)
1275  _coords = set_coords(_idx);
1276  }
1277 
1278  set_offsets();
1279  }
1280 
1281  void set_offsets() {// setup center point offset
1282  if(MemoryArrange == ROW_MAJOR) {
1283  _offset = _coords[0];
1284  for(dim_t d = 1; d < NumDimensions; ++d)
1285  _offset = _offset * _local_layout.extent(d) + _coords[d];
1286  } else {
1287  _offset = _coords[NumDimensions - 1];
1288  for(dim_t d = NumDimensions - 1; d > 0;) {
1289  --d;
1290  _offset = _offset * _local_layout.extent(d) + _coords[d];
1291  }
1292  }
1293  _current_lmemory_addr = _local_memory + _offset;
1294 
1295  // setup stencil point offsets
1296  if(Scope == StencilViewScope::INNER) {
1297  for(auto i = 0; i < NumStencilPoints; ++i)
1298  _stencil_mem_ptr[i] = _current_lmemory_addr + (*_stencil_offsets)[i];
1299  } else {
1300  using signed_extent_t = typename std::make_signed<pattern_size_t>::type;
1301  std::array<ElementCoords_t, NumStencilPoints> halo_coords{};
1302  std::array<bool, NumStencilPoints> is_halo{};
1303  std::array<region_index_t, NumStencilPoints> indexes{};
1304  for(auto d = 0; d < NumDimensions; ++d) {
1305  auto extent = _local_layout.extent(d);
1306 
1307  for(auto i = 0; i < NumStencilPoints; ++i) {
1308  auto& halo_coord = halo_coords[i][d];
1309  halo_coord = _coords[d] + (*_stencil_spec)[i][d];
1310  if(halo_coord < 0) {
1311  indexes[i] *= REGION_INDEX_BASE;
1312  is_halo[i] = true;
1313  continue;
1314  }
1315 
1316  if(halo_coord < static_cast<signed_extent_t>(extent)) {
1317  indexes[i] = 1 + indexes[i] * REGION_INDEX_BASE;
1318  continue;
1319  }
1320 
1321  indexes[i] = 2 + indexes[i] * REGION_INDEX_BASE;
1322  is_halo[i] = true;
1323  }
1324  }
1325 
1326  for(auto i = 0; i < NumStencilPoints; ++i) {
1327  if(is_halo[i])
1328  _stencil_mem_ptr[i] = value_halo_at(indexes[i], halo_coords[i]);
1329  else
1330  _stencil_mem_ptr[i] = _current_lmemory_addr + (*_stencil_offsets)[i];
1331  }
1332  }
1333  }
1334 
1335  ElementCoords_t set_coords(pattern_index_t idx) {
1336  if(Scope == StencilViewScope::BOUNDARY) {
1337  _region_bound = 0;
1338  _region_number = 0;
1339  auto local_idx = idx;
1340  for(const auto& region : _boundary_views) {
1341  _region_bound += region.size();
1342  if(local_idx < region.size()) {
1343  return _local_layout.coords(local_idx, region);
1344  }
1345  ++_region_number;
1346  local_idx -= region.size();
1347  }
1348  DASH_ASSERT("idx >= size not implemented yet");
1349  return std::array<pattern_index_t, NumDimensions>{};
1350  } else {
1351  if(_view.size() == 0)
1352  return std::array<pattern_index_t, NumDimensions>{};
1353  else
1354  return _local_layout.coords(idx, _view);
1355  }
1356  }
1357 
1358  ElementT* value_halo_at(region_index_t region_index,
1359  ElementCoords_t& halo_coords) {
1360  _halomemory->to_halo_mem_coords(region_index, halo_coords);
1361 
1362  return &*(_halomemory->first_element_at(region_index)
1363  + _halomemory->offset(region_index, halo_coords));
1364  }
1365 
1366 private:
1367  HaloMemory_t* _halomemory;
1368  const StencilSpecT* _stencil_spec;
1369  const StencilOffsets_t* _stencil_offsets;
1370  ViewSpec_t _view;
1371  BoundaryViews_t _boundary_views{};
1372  ElementT* _local_memory;
1373  std::array<ElementT*, NumStencilPoints> _stencil_mem_ptr;
1374  LocalLayout_t _local_layout;
1375  pattern_index_t _idx{ 0 };
1376  // extension of the fastest index dimension minus the halo extension
1377  std::pair<pattern_index_t, pattern_index_t> _ext_dim_reduced;
1378  signed_pattern_size_t _offset;
1379  pattern_index_t _region_bound{ 0 };
1380  size_t _region_number{ 0 };
1381  ElementCoords_t _coords;
1382  ElementT* _current_lmemory_addr;
1383  pattern_index_t _size;
1384 }; // class StencilIterator
1385 
1386 
1387 } // namespace halo
1388 
1389 } // namespace dash
1390 
1391 #endif // DASH__HALO__ITERATOR__STENCILITERATOR_H
Returns second operand.
Definition: Operation.h:218
constexpr std::enable_if< std::is_integral< IndexType >::value, IndexType >::type index(IndexType idx)
Definition: Iterator.h:60
size_t size()
Return the number of units in the global team.
StencilIteratorTest(CoordsIdxManagerT coords_mng)
Constructor.
constexpr auto end(RangeType &&range) -> decltype(std::forward< RangeType >(range).end())
Definition: Range.h:98
This class is a simple memory pool which holds allocates elements of size ValueType.
Definition: AllOf.h:8
Element_t operator[](index_t n) const
Subscript operator, returns global reference to element at given global index.
reference operator*() const
Dereference operator.
ElementT value_at(const region_index_t index_stencil)
Returns the value for a given stencil point index (index postion in StencilSpec)
StencilIterator(ElementT *local_memory, HaloMemory_t *halomemory, const StencilSpecT *stencil_spec, const StencilOffsets_t *stencil_offsets, const ViewSpec_t &view_local, const ViewSpec_t &view_scope, pattern_index_t idx)
Constructor.
Takes the local part of the NArray and builds halo and boundary regions.
Definition: Halo.h:827
constexpr auto begin(RangeType &&range) -> decltype(std::forward< RangeType >(range).begin())
Definition: Range.h:89
Self_t operator++(int)
Postfix increment operator.
Self_t & operator--()
Prefix decrement operator.
int dim_t
Scalar type for a dimension value, with 0 indicating the first dimension.
Definition: Types.h:39
DASH_CONSTEXPR auto operator-(const GlobIter< ElementType, Pattern, GlobMemType, Pointer, Reference > &lhs, const GlobIter< ElementType, Pattern, GlobMemType, Pointer, Reference > &rhs) DASH_NOEXCEPT
Definition: Iterator.h:147
Returns second operand.
Definition: Operation.h:201
constexpr bool operator<=(const Pair< T1, T2 > &x, const Pair< T1, T2 > &y)
Less-than-or-equal operator implemented in terms of less-than operator.
Definition: Pair.h:172
reference operator*() const
Dereference operator.
reference operator[](pattern_index_t n) const
Subscript operator, returns global reference to element at given global index.
Stencil point with raletive coordinates for N dimensions e.g.
Definition: Stencil.h:19
constexpr bool operator>=(const Pair< T1, T2 > &x, const Pair< T1, T2 > &y)
Greater-than-or-equal operator implemented in terms of less-than operator.
Definition: Pair.h:182
N-Dimensional region coordinates and associated indices for all possible Halo/Boundary regions of a H...
Definition: Region.h:40
static constexpr stencil_size_t num_stencil_points()
Definition: Stencil.h:216
StencilIterator(ElementT *local_memory, HaloMemory_t *halomemory, const StencilSpecT *stencil_spec, const StencilOffsets_t *stencil_offsets, const ViewSpec_t &view_local, const BoundaryViews_t &boundary_views, pattern_index_t idx)
Constructor.
static constexpr dim_t ndim()
The number of dimensions of the iterator&#39;s underlying pattern.
constexpr bool operator>(const Pair< T1, T2 > &x, const Pair< T1, T2 > &y)
Greater-than operator implemented in terms of less-than operator.
Definition: Pair.h:162
Self_t operator--(int)
Postfix decrement operator.
constexpr dim_t ndim(const DimensionalType &d)
Definition: Dimensional.h:56
Self_t operator++(int)
Postfix increment operator.
DistanceAll_t minmax_distances() const
Returns the minimal and maximal distances of all stencil points for all dimensions.
Definition: Stencil.h:267
Self_t & operator++()
Prefix increment operator.
static constexpr dim_t ndim()
The number of dimensions of the iterator&#39;s underlying pattern.
Element_t value_at(const stencil_index_t index_stencil)
Returns the value for a given stencil point index (index postion in StencilSpec)
constexpr DimensionalType::extent_type extent(const DimensionalType &d)
Definition: Dimensional.h:73
A collection of stencil points (Stencil) e.g.
Definition: Stencil.h:167
Definition: main.cpp:123
Self_t operator--(int)
Postfix decrement operator.
Self_t & operator++()
Prefix increment operator.
constexpr bool operator<(const Pair< T1, T2 > &x, const Pair< T1, T2 > &y)
A pair is smaller than another pair if the first member is smaller or the first is equal and the seco...
Definition: Pair.h:140
Self_t & operator--()
Prefix decrement operator.