1 #ifndef DASH__HALO_HALOSTENCILOPERATOR_H 2 #define DASH__HALO_HALOSTENCILOPERATOR_H 4 #include <dash/halo/iterator/StencilIterator.h> 15 constexpr T operator()(
const T& lhs,
const T& rhs)
const {
return rhs; }
20 using namespace internal;
23 template <
typename HaloBlockT,
typename StencilSpecT>
29 template <
typename StencilOperatorT>
33 static constexpr
auto NumStencilPoints = StencilOperatorT::num_stencil_points();
37 using Element_t =
typename StencilOperatorT::Element_t;
38 using ViewSpec_t =
typename StencilOperatorT::ViewSpec_t;
39 using Coords_t =
typename StencilOperatorT::Coords_t;
40 using iterator =
typename StencilOperatorT::iterator_inner;
41 using const_iterator =
const iterator;
43 using StencilOffsets_t =
typename StencilOperatorT::StencilOffsets_t;
47 : _stencil_op(stencil_op) {}
52 iterator
begin() noexcept {
return _stencil_op->_ibegin; }
57 const_iterator
begin() const noexcept {
return _stencil_op->_ibegin; }
62 iterator
end() noexcept {
return _stencil_op->_iend; }
67 const_iterator
end() const noexcept {
return _stencil_op->_iend; }
72 const ViewSpec_t&
view()
const {
return _stencil_op->_spec_views.inner(); }
86 template <
typename BinaryFunc =
internal::replace<Element_t>>
88 Element_t coefficient_center,
89 BinaryFunc op = BinaryFunc()) {
90 auto* center = _stencil_op->_local_memory + _stencil_op->get_offset(coords);
92 *center = op(*center, coefficient_center * value);
93 for(
auto i = 0; i < NumStencilPoints; ++i) {
94 auto& stencil_point_value = center[_stencil_op->_stencil_offsets[i]];
96 op(stencil_point_value,
97 _stencil_op->_stencil_spec[i].coefficient() * value);
113 template <
typename BinaryFunc = std::plus<Element_t>>
115 Element_t coefficient_center,
116 BinaryFunc op = BinaryFunc())
const {
117 auto* center = _stencil_op->_local_memory + _stencil_op->get_offset(coords);
118 Element_t value = *center * coefficient_center;
120 for(
auto i = 0; i < NumStencilPoints; ++i) {
121 auto& stencil_point_value = center[_stencil_op->_stencil_offsets[i]];
122 value = op(value, _stencil_op->_stencil_spec[i].coefficient()
123 * stencil_point_value);
135 template <
typename Op>
136 void update(Element_t* begin_dst, Op operation) {
137 update(
begin(),
end(), begin_dst, operation);
149 template <
typename Op>
151 if(begin < this->
begin() || end < this->
begin() ||
152 begin > this->
end() || end > this->
end()) {
154 DASH_LOG_ERROR(
"Begin or End iterator located outside of inner view.");
161 const auto& view = this->view();
162 const auto& offsets_view = view.offsets();
163 const auto& extents_view = view.extents();
164 auto end_coords_view = offsets_view;
165 for(
auto d = 0; d < NumDimensions; ++d) {
166 end_coords_view[d] += extents_view[d];
169 auto begin_coords = begin.coords();
170 auto end_coords = end.coords();
172 auto center = _stencil_op->_local_memory;
173 auto offsets = _stencil_op->set_dimension_offsets();
175 for(
dim_t d = 0; d < NumDimensions; ++d) {
176 offset += offsets[d] * begin_coords[d];
179 auto center_dst = begin_dst + offset;
182 if(NumDimensions == 2) {
183 if(begin_coords[0] == end_coords[0]) {
184 auto center_i = center;
185 auto center_dst_i = center_dst;
186 auto offset_i = offset;
187 for(
int j = begin_coords[1]; j <= end_coords[1];
188 ++j, ++center_i, ++center_dst_i, ++offset_i) {
189 operation(center_i, center_dst_i, offset_i,
190 _stencil_op->_stencil_offsets);
196 auto center_i = center;
197 auto center_dst_i = center_dst;
198 auto offset_i = offset;
199 auto align_offset = begin_coords[1] - offsets_view[1];
200 for(
int j = begin_coords[1]; j < end_coords_view[1];
201 ++j, ++center_i, ++center_dst_i, ++offset_i) {
202 operation(center_i, center_dst_i, offset_i,
203 _stencil_op->_stencil_offsets);
206 center += offsets[0] - align_offset;
207 center_dst += offsets[0] - align_offset;
208 offset += offsets[0] - align_offset;
209 for(
int i = begin_coords[0] + 1; i < end_coords[0]; ++i,
210 center += offsets[0], center_dst += offsets[0],
211 offset += offsets[0]) {
213 center_dst_i = center_dst;
215 for(
int j = offsets_view[1]; j < end_coords_view[1];
216 ++j, ++center_i, ++center_dst_i, ++offset_i) {
217 operation(center_i, center_dst_i, offset_i,
218 _stencil_op->_stencil_offsets);
223 center_dst_i = center_dst;
225 for(
int j = offsets_view[1]; j <= end_coords[1];
226 ++j, ++center_i, ++center_dst_i, ++offset_i) {
227 operation(center_i, center_dst_i, offset_i,
228 _stencil_op->_stencil_offsets);
234 if(NumDimensions == 3) {
235 for(
int i = begin_coords[0]; i <= end_coords[0]; ++i,
236 center += offsets[0], center_dst += offsets[0],
237 offset += offsets[0]) {
238 auto center_i = center;
239 auto center_dst_i = center_dst;
240 auto offset_i = offset;
241 for(
int j = begin_coords[1]; j <= end_coords[1]; ++j,
242 center_i += offsets[1], center_dst_i += offsets[1],
243 offset_i += offsets[1]) {
244 auto center_j = center_i;
245 auto center_dst_j = center_dst_i;
246 auto offset_j = offset_i;
247 for(
int k = begin_coords[2]; k <= end_coords[2];
248 ++k, ++center_j, ++center_dst_j, ++offset_j) {
249 operation(center_j, center_dst_j, offset_j,
250 _stencil_op->_stencil_offsets);
259 for(
int i = begin_coords[0]; i <= end_coords[0]; ++i, center += offsets[0],
260 center_dst += offsets[0], offset += offsets[0]) {
261 Loop<1, Op>()(_stencil_op->_stencil_offsets, offsets, begin_coords,
262 end_coords, center, center_dst, offset, operation);
275 template <
typename Op>
276 void update_blocked(
const Coords_t& begin_coords,
const Coords_t& end_coords, Element_t* begin_dst, Op operation) {
277 const auto& view = this->view();
278 const auto& offsets_view = view.offsets();
279 const auto& extents_view = view.extents();
281 for(
auto d = 0; d < NumDimensions; ++d) {
282 auto end_coord = offsets_view[d] + extents_view[d];
283 if(begin_coords[d] < offsets_view[d] ||
284 end_coords[d] < offsets_view[d] ||
285 begin_coords[d] >= end_coord ||
286 end_coords[d] >= end_coord) {
288 DASH_LOG_ERROR(
"Begin or End coordinates located outside of inner view.");
294 auto center = _stencil_op->_local_memory;
295 auto offsets = _stencil_op->set_dimension_offsets();
297 for(
dim_t d = 0; d < NumDimensions; ++d) {
298 offset += offsets[d] * begin_coords[d];
301 auto center_dst = begin_dst + offset;
304 if(NumDimensions == 2) {
305 for(
int i = begin_coords[0]; i <= end_coords[0]; ++i,
306 center += offsets[0], center_dst += offsets[0],
307 offset += offsets[0]) {
308 auto center_i = center;
309 auto center_dst_i = center_dst;
310 auto offset_i = offset;
311 for(
int j = begin_coords[1]; j <= end_coords[1];
312 ++j, ++center_i, ++center_dst_i, ++offset_i) {
313 operation(center_i, center_dst_i, offset_i,
314 _stencil_op->_stencil_offsets);
321 if(NumDimensions == 3) {
322 for(
int i = begin_coords[0]; i <= end_coords[0]; ++i,
323 center += offsets[0], center_dst += offsets[0],
324 offset += offsets[0]) {
325 auto center_i = center;
326 auto center_dst_i = center_dst;
327 auto offset_i = offset;
328 for(
int j = begin_coords[1]; j <= end_coords[1]; ++j,
329 center_i += offsets[1], center_dst_i += offsets[1],
330 offset_i += offsets[1]) {
331 auto center_j = center_i;
332 auto center_dst_j = center_dst_i;
333 auto offset_j = offset_i;
334 for(
int k = begin_coords[2]; k <= end_coords[2];
335 ++k, ++center_j, ++center_dst_j, ++offset_j) {
336 operation(center_j, center_dst_j, offset_j,
337 _stencil_op->_stencil_offsets);
346 for(
int i = begin_coords[0]; i <= end_coords[0]; ++i, center += offsets[0],
347 center_dst += offsets[0], offset += offsets[0]) {
348 Loop<1, Op>()(_stencil_op->_stencil_offsets, offsets, begin_coords,
349 end_coords, center, center_dst, offset, operation);
354 template <dim_t dim,
typename Op>
356 template <
typename OffsetT>
357 constexpr
void operator()(
const StencilOffsets_t& stencil_offs,
358 const StencilOffsets_t& dim_offs,
359 const Coords_t&
begin,
360 const Coords_t&
end, Element_t* center,
361 Element_t* center_dst, OffsetT offset, Op op) {
362 for(
int i = begin[dim]; i <= end[dim]; ++i, center += dim_offs[dim],
363 center_dst += dim_offs[dim], offset += dim_offs[dim]) {
364 Loop<dim + 1, Op>()(stencil_offs, dim_offs, begin, end, center,
365 center_dst, offset, op);
370 template <
typename Op>
371 struct Loop<NumDimensions - 1, Op> {
372 template <
typename OffsetT>
373 constexpr
void operator()(
const StencilOffsets_t& stencil_offs,
374 const StencilOffsets_t& dim_offs,
375 const Coords_t&
begin,
376 const Coords_t&
end, Element_t* center,
377 Element_t* center_dst, OffsetT offset, Op op) {
378 for(
int i = begin[NumDimensions - 1]; i <= end[NumDimensions - 1];
379 ++i, ++center, ++center_dst, ++offset) {
380 op(center, center_dst, offset, stencil_offs);
386 StencilOperatorT* _stencil_op;
392 template <
typename StencilOperatorT>
396 static constexpr
auto NumStencilPoints = StencilOperatorT::num_stencil_points();
399 using StencilSpecViews_t =
typename StencilOperatorT::StencilSpecViews_t;
402 using Element_t =
typename StencilOperatorT::Element_t;
403 using uindex_t =
typename StencilOperatorT::uindex_t;
404 using ViewSpec_t =
typename StencilOperatorT::ViewSpec_t;
405 using Coords_t =
typename StencilOperatorT::Coords_t;
406 using iterator =
typename StencilOperatorT::iterator_bnd;
407 using const_iterator =
const iterator;
408 using BoundaryViews_t =
typename StencilSpecViews_t::BoundaryViews_t;
413 : _stencil_op(stencil_op) {}
418 iterator
begin() noexcept {
return _stencil_op->_bbegin; }
423 const_iterator
begin() const noexcept {
return _stencil_op->_bbegin; }
428 iterator
end() noexcept {
return _stencil_op->_bend; }
433 const_iterator
end() const noexcept {
return _stencil_op->_bend; }
441 const BoundaryViews_t&
view()
const {
442 return _stencil_op->_spec_views.boundary_views();
449 return _stencil_op->_spec_views.boundary_size();
466 template <
typename BinaryFunc =
internal::replace<Element_t>>
468 Element_t coefficient_center,
469 BinaryFunc op = BinaryFunc()) {
470 auto* center = _stencil_op->_local_memory + _stencil_op->get_offset(coords);
472 *center = op(*center, coefficient_center * value);
473 for(
auto i = 0; i < NumStencilPoints; ++i) {
475 for(
auto d = 0; d < NumDimensions; ++d) {
476 auto coord_value = coords[d] + _stencil_op->_stencil_spec[i][d];
478 || coord_value >= _stencil_op->_view_local->extent(d)) {
487 auto& stencil_point_value = center[_stencil_op->_stencil_offsets[i]];
488 stencil_point_value =
489 op(stencil_point_value,
490 _stencil_op->_stencil_spec[i].coefficient() * value);
502 DASH_ASSERT_LT(dim, NumDimensions,
"Given dimension to great");
503 const auto& bnd_views = _stencil_op->_spec_views.boundary_views();
506 for(
dim_t d = 0; d < dim; ++d, ++it_views)
507 offset += it_views->size() + (++it_views)->
size();
509 if(pos == RegionPos::POST) {
510 offset += it_views->size();
514 auto it_begin = _stencil_op->_bbegin + offset;
516 return std::make_pair(it_begin, it_begin + it_views->size());
519 std::pair<iterator, iterator> iterator_at(region_index_t
index) {
520 DASH_ASSERT_LT(index, NumRegionsMax<NumDimensions>,
"Given index out of range");
521 const auto& bnd_views = _stencil_op->_spec_views.boundary_views();
523 for(region_index_t r = 0; r <
index; ++r) {
524 offset += bnd_views[r].size();
527 auto it_begin = _stencil_op->_bbegin + offset;
529 return std::make_pair(it_begin, it_begin + bnd_views[index].
size());
546 template <
typename BinaryFunc = std::plus<Element_t>>
548 Element_t coefficient_center,
549 BinaryFunc op = BinaryFunc())
const {
550 auto* center = _stencil_op->_local_memory + _stencil_op->get_offset(coords);
551 Element_t value = *center * coefficient_center;
552 auto& stencil_spec = _stencil_op->_stencil_spec;
553 for(
auto i = 0; i < NumStencilPoints; ++i) {
555 auto coords_stencil = coords;
557 for(
auto d = 0; d < NumDimensions; ++d) {
558 coords_stencil[d] += stencil_spec[i][d];
559 if(coords_stencil[d] < 0
560 || coords_stencil[d] >= _stencil_op->_view_local->extent(d))
565 auto& halo_memory = *_stencil_op->_halo_memory;
566 auto index = _stencil_op->_halo_block->index_at(
567 *(_stencil_op->_view_local), coords_stencil);
568 auto halomem_pos = halo_memory.first_element_at(index);
570 halo_memory.to_halo_mem_coords(index, coords_stencil);
571 auto offset = halo_memory.offset(index, coords_stencil);
572 value = op(value, stencil_spec[i].coefficient() * halomem_pos[offset]);
574 auto stencil_point_value = center[_stencil_op->_stencil_offsets[i]];
575 value = op(value, stencil_spec[i].coefficient() * stencil_point_value);
588 template <
typename Op>
589 void update(Element_t* begin_dst, Op operation) {
590 update(
begin(),
end(), begin_dst, operation);
603 template <
typename Op>
606 for(
auto it = begin; it !=
end; ++it) {
607 begin_out[it.lpos()] = operation(it);
612 const StencilOperatorT* _stencil_op;
647 template <
typename HaloBlockT,
typename StencilSpecT>
651 using Pattern_t =
typename HaloBlockT::Pattern_t;
659 template <
typename _SO>
662 template <
typename _SO>
670 using Element_t =
typename HaloBlockT::Element_t;
671 using index_t =
typename std::make_signed<typename Pattern_t::index_type>::type;
672 using uindex_t =
typename std::make_unsigned<index_t>::type;
673 using StencilOffsets_t = std::array<index_t, NumStencilPoints>;
674 using HaloBlock_t = HaloBlockT;
676 using ViewSpec_t =
typename HaloBlockT::ViewSpec_t;
677 using Coords_t = std::array<index_t, NumDimensions>;
682 using stencil_index_t =
typename StencilSpecT::stencil_index_t;
686 using const_iterator =
const iterator;
692 using const_iterator_inner =
const iterator;
695 using const_iterator_bnd =
const iterator;
703 const HaloBlockT* haloblock,
704 Element_t* local_memory,
709 , _halo_block(haloblock)
710 , _local_memory(local_memory)
711 , _halo_memory(halomemory)
712 , _stencil_spec(stencil_spec)
713 , _view_local(&haloblock->view_local())
714 , _stencil_offsets(set_stencil_offsets())
715 , _spec_views(*_halo_block, _stencil_spec, _view_local)
722 _spec_views.inner_with_boundaries(),
730 _spec_views.inner_with_boundaries(),
731 _spec_views.inner_with_boundaries().
size())
734 _spec_views.inner().
size()))
737 _spec_views.boundary_size())) {
740 static constexpr decltype(
auto)
ndim() {
return NumDimensions; }
742 static constexpr decltype(
auto) memory_order() {
return MemoryArrange; }
744 static constexpr decltype(
auto) num_stencil_points() {
return NumStencilPoints; }
796 const ViewSpec_t&
view()
const {
return _spec_views.inner_with_boundaries(); }
801 const ViewSpec_t&
view_local()
const {
return *_view_local; }
812 return _stencil_offsets[pos];
821 if(MemoryArrange == ROW_MAJOR) {
823 for(
auto d = 1; d < NumDimensions; ++d)
824 offset = offset * _view_local->extent(d) + coords[d];
826 offset = coords[NumDimensions - 1];
827 for(
auto d = NumDimensions - 1; d > 0;) {
829 offset = offset * _view_local->extent(d) + coords[d];
837 StencilOffsets_t set_stencil_offsets() {
838 StencilOffsets_t stencil_offs;
839 for(
auto i = 0u; i < NumStencilPoints; ++i) {
841 if(MemoryArrange == ROW_MAJOR) {
842 offset = _stencil_spec[i][0];
843 for(
auto d = 1; d < NumDimensions; ++d)
844 offset = _stencil_spec[i][d] + offset * _view_local->extent(d);
846 offset = _stencil_spec[i][NumDimensions - 1];
847 for(
auto d = NumDimensions - 1; d > 0;) {
849 offset = _stencil_spec[i][d] + offset * _view_local->extent(d);
852 stencil_offs[i] = offset;
858 StencilOffsets_t set_dimension_offsets() {
859 StencilOffsets_t dim_offs;
861 if(MemoryArrange == ROW_MAJOR) {
862 dim_offs[NumDimensions - 1] = 1;
863 for(
auto d = NumDimensions - 1; d > 0;) {
865 dim_offs[d] = dim_offs[d + 1] * _view_local->extent(d + 1);
869 for(
auto d = 1; d < NumDimensions; ++d)
870 dim_offs[d] = dim_offs[d - 1] * _view_local->extent(d - 1);
881 const HaloBlock_t* _halo_block;
882 Element_t* _local_memory;
885 const ViewSpec_t* _view_local;
886 StencilOffsets_t _stencil_offsets;
900 #endif // DASH__HALO_HALOSTENCILOPERATOR_H const BoundaryViews_t & view() const
Returns all boundary views including all boundary elements (no dublicates) Unlike the view methods in...
Proxy StencilOperator for inner elements only.
constexpr std::enable_if< std::is_integral< IndexType >::value, IndexType >::type index(IndexType idx)
Defines how a list of global indices is mapped to single units within a Team.
const ViewSpec_t & view() const
Returns a view for all inner elements.
size_t size()
Return the number of units in the global team.
constexpr auto end(RangeType &&range) -> decltype(std::forward< RangeType >(range).end())
This class is a simple memory pool which holds allocates elements of size ValueType.
void set_values_at(const Coords_t &coords, Element_t value, Element_t coefficient_center, BinaryFunc op=BinaryFunc())
Modifies all stencil point elements and the center with halo check.
StencilOperator(const HaloBlockT *haloblock, Element_t *local_memory, HaloMemory_t *halomemory, const StencilSpecT &stencil_spec)
Constructor that takes a HaloBlock, a HaloMemory, a StencilSpec and a local ViewSpec.
void update(const iterator &begin, const iterator &end, Element_t *begin_out, Op operation)
Updates all boundary elements within a user defined range using a userdefined stencil operation...
const StencilSpecViews_t & spec_views() const
Returns the StencilSpecificView.
constexpr auto begin(RangeType &&range) -> decltype(std::forward< RangeType >(range).begin())
int dim_t
Scalar type for a dimension value, with 0 indicating the first dimension.
const_iterator end() const noexcept
Returns the end const iterator for all inner elements.
void set_values_at(const Coords_t &coords, Element_t value, Element_t coefficient_center, BinaryFunc op=BinaryFunc())
Modifies all stencil point elements and the center within the inner view.
void update(Element_t *begin_dst, Op operation)
Updates all inner elements using a user-defined stencil operation.
void update_blocked(const Coords_t &begin_coords, const Coords_t &end_coords, Element_t *begin_dst, Op operation)
Updates all inner elements within a user defined range using a user-defined stencil operation...
std::pair< iterator, iterator > iterator_at(dim_t dim, RegionPos pos)
Returns a pair of boundary iterators (first: begin, second: end) for a given dimension and RegionPos...
const_iterator begin() const noexcept
Returns the begin const iterator for all inner elements.
void update(Element_t *begin_dst, Op operation)
Updates all boundary elements using a user-defined stencil operation.
uindex_t boundary_size() const
Returns the number of all boundary elements (no dublicates)
const ViewSpec_t & view_local() const
Returns the local SpecView.
index_t get_offset(const Coords_t &coords) const
Returns the local memory offset for a given coordinate.
iterator end() noexcept
Returns the end iterator for all inner elements.
N-Dimensional region coordinates and associated indices for all possible Halo/Boundary regions of a H...
static constexpr stencil_size_t num_stencil_points()
static constexpr dim_t ndim() noexcept
Number of dimensions of the cartesian space partitioned by the pattern.
iterator end() noexcept
Returns the end iterator for all relevant elements (inner + boundary)
iterator end() noexcept
Returns the end iterator for all boundary elements.
iterator begin() noexcept
Returns the begin iterator for all inner elements.
constexpr dim_t ndim(const DimensionalType &d)
Proxy StencilOperator for boundary elements only.
const index_t stencil_offset_at(std::size_t pos) const
Returns the offset for specific stencil point.
void update(iterator begin, iterator end, Element_t *begin_dst, Op operation)
Updates all inner elements within a user defined range using a user-defined stencil operation...
const StencilOffsets_t & stencil_offsets() const
Returns the offsets for each stencil point.
const_iterator end() const noexcept
Returns the end const iterator for all relevant elements (inner + boundary)
iterator begin() noexcept
Returns the begin iterator for all relevant elements (inner + boundary)
const ViewSpec_t & view() const
Returns a SpecView including inner and boundary elements.
Element_t * local_memory()
Returns the halo memory management object HaloMemory.
const_iterator end() const noexcept
Returns the end const iterator for all boundary elements.
The StencilOperator provides stencil specific iterator and functions for a given HaloBlock and HaloMe...
HaloMemory_t & halo_memory()
Returns the halo memory management object HaloMemory.
A collection of stencil points (Stencil) e.g.
const HaloBlock_t & halo_block()
Returns the HaloBlock.
const_iterator begin() const noexcept
Returns the begin const iterator for all relevant elements (inner + boundary)
const_iterator begin() const noexcept
Returns the begin const iterator for all boundary elements.
Element_t get_value_at(const Coords_t &coords, Element_t coefficient_center, BinaryFunc op=BinaryFunc()) const
Returns the result of the given operation done on all stencil point elements and the center...
Element_t get_value_at(const Coords_t &coords, Element_t coefficient_center, BinaryFunc op=BinaryFunc()) const
Returns the result of the given operation done on all stencil point elements and the center...
iterator begin() noexcept
Returns the begin iterator for all boundary elements.
const StencilSpecT & stencil_spec() const
Returns the stencil specification StencilSpec.
static constexpr MemArrange memory_order() noexcept
Memory order followed by the pattern.