Gyselalib++
derivative_field.hpp
1 // SPDX-License-Identifier: MIT
2 
3 #pragma once
4 #include <ddc/ddc.hpp>
5 
6 #include "ddc_aliases.hpp"
7 #include "derivative_field_common.hpp"
8 
9 template <class, class, int, class>
11 
15 template <
16  class ElementType,
17  class SupportType,
18  class MemorySpace = Kokkos::HostSpace,
19  class LayoutStridedPolicy = std::experimental::layout_right>
20 class DerivField;
21 
22 template <class ElementType, class SupportType, class MemorySpace, class LayoutStridedPolicy>
23 inline constexpr bool enable_deriv_field<
25 
26 template <class ElementType, class SupportType, class MemorySpace, class LayoutStridedPolicy>
27 inline constexpr bool enable_borrowed_deriv_field<
29 
30 template <class ElementType, class SupportType, class MemorySpace, class LayoutStridedPolicy>
31 inline constexpr bool enable_data_access_methods<
33 
34 namespace ddcHelper {
35 
42 template <
43  class FieldDst,
44  class FieldSrc,
45  std::enable_if_t<
46  is_borrowed_deriv_field_v<FieldDst> && is_borrowed_deriv_field_v<FieldSrc>,
47  bool> = true>
48 auto deepcopy(FieldDst&& dst, FieldSrc&& src)
49 {
50  assert(dst.get_values_field().domain().extents() == src.get_values_field().domain().extents());
51 
52  DerivField dst_field = dst.span_view();
53  DerivField src_field = src.span_view();
54 
55  dst_field.deepcopy(src_field);
56 
57  return dst_field;
58 }
59 
67 template <class ExecSpace, class FieldDst, class FieldSrc>
68 auto deepcopy(ExecSpace const& execution_space, FieldDst&& dst, FieldSrc&& src)
69 {
70  static_assert(is_borrowed_deriv_field_v<FieldDst>);
71  static_assert(is_borrowed_deriv_field_v<FieldSrc>);
72 
73  assert(dst.get_values_field().idx_range().extents()
74  == src.get_values_field().idx_range().extents());
75 
76  DerivField dst_field = get_field(dst);
77  DerivField src_field = get_field(src);
78 
79  dst_field.deepcopy(execution_space, src_field);
80 
81  return dst_field;
82 }
83 
84 } // namespace ddcHelper
85 
102 template <class ElementType, class... DDims, class MemorySpace, class LayoutStridedPolicy>
103 class DerivField<ElementType, IdxRange<DDims...>, MemorySpace, LayoutStridedPolicy>
104  : public DerivFieldCommon<
105  Field<ElementType, IdxRange<DDims...>, MemorySpace, LayoutStridedPolicy>,
106  IdxRange<DDims...>>
107 {
108 private:
110  using base_type = DerivFieldCommon<
111  Field<ElementType, IdxRange<DDims...>, MemorySpace, LayoutStridedPolicy>,
112  IdxRange<DDims...>>;
113 
114 public:
116  using element_type = typename base_type::element_type;
117 
124  using discrete_domain_type = typename base_type::discrete_domain_type;
126  using index_range_type = typename base_type::index_range_type;
127 
134  using discrete_element_type = typename base_type::discrete_element_type;
135 
137  using deriv_tags = typename base_type::deriv_tags;
138 
140  using physical_deriv_grids = typename detail::strip_deriv_t<deriv_tags>;
141 
143  using physical_grids = typename base_type::physical_grids;
144 
146  using physical_idx_range_type = typename base_type::physical_idx_range_type;
147 
155  using chunk_type = typename base_type::chunk_type;
156 
158  using span_type = DerivField<ElementType, IdxRange<DDims...>, MemorySpace, LayoutStridedPolicy>;
159 
161  using view_type
162  = DerivField<ElementType const, IdxRange<DDims...>, MemorySpace, LayoutStridedPolicy>;
163 
164 private:
166  using discrete_deriv_idx_range_type = typename base_type::discrete_deriv_idx_range_type;
167 
171  using discrete_deriv_index_type = typename base_type::discrete_deriv_index_type;
172 
174  using reference = typename chunk_type::reference;
175 
177  using base_type::n_fields;
178 
179 private:
183  template <std::size_t ArrayIndex, class Tag>
184  KOKKOS_FUNCTION constexpr Idx<Tag> get_chunk_subidx_range_1d_idx()
185  {
186  // The Tag describes a dimension for which a derivative is defined
187  if constexpr (ddc::in_tags_v<Tag, deriv_tags>) {
188  // If the Field at this index contains the derivatives of this dimension
189  if constexpr (ArrayIndex & (1 << ddc::type_seq_rank_v<Tag, deriv_tags>)) {
190  return Idx<Tag>(1);
191  }
192  // If the Field at this index doesn't contain derivatives of this dimension
193  else {
194  return Idx<Tag>(0);
195  }
196  } else {
197  // Empty IdxRange to be discarded
198  return Idx<Tag>();
199  }
200  }
201 
203  template <std::size_t ArrayIndex>
204  KOKKOS_FUNCTION constexpr discrete_deriv_index_type get_chunk_subidx_range_idx()
205  {
206  return discrete_deriv_index_type(get_chunk_subidx_range_1d_idx<ArrayIndex, DDims>()...);
207  }
208 
210  template <class Field, std::size_t... ArrayIndex>
211  KOKKOS_FUNCTION constexpr void initialise_fields(
212  Field const& chunks,
213  std::index_sequence<ArrayIndex...>)
214  {
215  ((base_type::internal_fields[ArrayIndex] = chunks.internal_fields[chunks.get_array_index(
216  get_chunk_subidx_range_idx<ArrayIndex>())]),
217  ...);
218  }
219 
220  auto get_kokkos_view_from_internal_chunk(int index)
221  {
222  typename base_type::internal_mdspan_type field = base_type::internal_fields[index];
223  auto kokkos_layout = ddc::detail::build_kokkos_layout(
224  field.extents(),
225  field.mapping(),
226  std::make_index_sequence<sizeof...(DDims)> {});
227  return Kokkos::View<
228  ddc::detail::mdspan_to_kokkos_element_t<ElementType, sizeof...(DDims)>,
229  decltype(kokkos_layout),
230  MemorySpace>(field.data_handle(), kokkos_layout);
231  }
232 
233 public:
239  KOKKOS_DEFAULTED_FUNCTION constexpr DerivField(DerivField const& other) = default;
240 
246  KOKKOS_DEFAULTED_FUNCTION constexpr DerivField(DerivField&& other) = default;
247 
253  template <
254  class OElementType,
255  int NDerivs,
256  class Allocator,
257  class = std::enable_if_t<std::is_same_v<typename Allocator::memory_space, MemorySpace>>>
258  explicit constexpr DerivField(
260  : base_type(
261  field.m_physical_idx_range,
262  field.m_deriv_idx_range,
263  field.m_cross_derivative_idx_range)
264  {
265  initialise_fields(field, std::make_integer_sequence<std::size_t, n_fields> {});
266  }
267 
273  // Disabled by SFINAE if `ElementType` is not `const` to avoid write access
274  template <
275  class OElementType,
276  class SFINAEElementType = ElementType,
277  class = std::enable_if_t<std::is_const_v<SFINAEElementType>>,
278  int NDerivs,
279  class Allocator,
280  class = std::enable_if_t<std::is_same_v<typename Allocator::memory_space, MemorySpace>>>
281  explicit constexpr DerivField(
283  : base_type(
284  field.m_physical_idx_range,
285  field.m_deriv_idx_range,
286  field.m_cross_derivative_idx_range)
287  {
288  initialise_fields(field, std::make_integer_sequence<std::size_t, n_fields> {});
289  }
290 
297  template <class OElementType>
298  KOKKOS_FUNCTION constexpr DerivField(
300  field)
301  : base_type(
302  field.m_physical_idx_range,
303  field.m_deriv_idx_range,
304  field.m_cross_derivative_idx_range)
305  {
306  initialise_fields(field, std::make_integer_sequence<std::size_t, n_fields> {});
307  }
308 
309  KOKKOS_DEFAULTED_FUNCTION ~DerivField() = default;
310 
315  KOKKOS_DEFAULTED_FUNCTION constexpr DerivField& operator=(DerivField const& other) = default;
316 
321  KOKKOS_DEFAULTED_FUNCTION constexpr DerivField& operator=(DerivField&& other) = default;
322 
328  template <class OElementType, class OLayoutStridedPolicy, class OMemorySpace>
329  void deepcopy(
331  {
332  for (int i(0); i < n_fields; ++i) {
333  auto kokkos_span = get_kokkos_view_from_internal_chunk(i);
334  auto src_kokkos_span = src.get_kokkos_view_from_internal_chunk(i);
335  Kokkos::deep_copy(kokkos_span, src_kokkos_span);
336  }
337  }
338 
345  template <class ExecSpace, class OElementType, class OMemorySpace, class OLayoutStridedPolicy>
346  void deepcopy(
347  ExecSpace const& execution_space,
349  {
350  for (int i(0); i < n_fields; ++i) {
351  auto kokkos_span = get_kokkos_view_from_internal_chunk(i);
352  auto src_kokkos_span = src.get_kokkos_view_from_internal_chunk(i);
353  Kokkos::deep_copy(execution_space, kokkos_span, src_kokkos_span);
354  }
355  }
356 
366  template <class... DElem>
367  KOKKOS_FUNCTION constexpr reference operator()(DElem... elems) const noexcept
368  {
369  static_assert((ddc::is_discrete_element_v<DElem> && ...));
370  using full_index_type = detail::combine_t<DElem...>;
371  full_index_type elem(elems...);
372  return base_type::get_internal_field(elem)();
373  }
374 
383  KOKKOS_FUNCTION constexpr view_type span_cview() const
384  {
385  return view_type(*this);
386  }
387 
396  KOKKOS_FUNCTION constexpr span_type span_view() const
397  {
398  return *this;
399  }
400 };
401 
402 template <
403  class ElementType,
404  class SupportType,
405  class MemorySpace = Kokkos::HostSpace,
406  class LayoutStridedPolicy = std::experimental::layout_right>
407 using DerivConstField
409 
410 namespace detail {
411 template <
412  class NewMemorySpace,
413  class ElementType,
414  class SupportType,
415  class MemorySpace,
416  class Layout>
417 struct OnMemorySpace<NewMemorySpace, DerivField<ElementType, SupportType, MemorySpace, Layout>>
418 {
420 };
421 }; // namespace detail
Definition: derivative_field_common.hpp:31
See DerivFieldMemImplementation.
Definition: derivative_field.hpp:10
A class which holds references to chunks of memory describing a field and its derivatives.
Definition: derivative_field.hpp:107
typename base_type::element_type element_type
The type of the elements in the chunks.
Definition: derivative_field.hpp:116
constexpr KOKKOS_DEFAULTED_FUNCTION DerivField & operator=(DerivField &&other)=default
Move-assigns a new value to this DerivField.
typename detail::strip_deriv_t< deriv_tags > physical_deriv_grids
A type sequence containing all grid types for which derivatives are present in this object.
Definition: derivative_field.hpp:140
constexpr KOKKOS_DEFAULTED_FUNCTION DerivField(DerivField const &other)=default
Copy-construct a DerivField.
constexpr KOKKOS_FUNCTION reference operator()(DElem... elems) const noexcept
Get an element from a constant field.
Definition: derivative_field.hpp:367
typename base_type::deriv_tags deriv_tags
A type sequence containing all derivatives present in this object.
Definition: derivative_field.hpp:137
constexpr KOKKOS_DEFAULTED_FUNCTION DerivField & operator=(DerivField const &other)=default
Copy-assigns a new value to this DerivField, yields a new view to the same data.
constexpr KOKKOS_DEFAULTED_FUNCTION DerivField(DerivField &&other)=default
Move-construct a DerivField.
void deepcopy(ExecSpace const &execution_space, DerivField< OElementType, index_range_type, OMemorySpace, OLayoutStridedPolicy > src)
Copy the source DerivField into this DerivField using Kokkos::deep_copy.
Definition: derivative_field.hpp:346
void deepcopy(DerivField< OElementType, index_range_type, OMemorySpace, OLayoutStridedPolicy > src)
Copy the source DerivField into this DerivField using Kokkos::deep_copy.
Definition: derivative_field.hpp:329
typename base_type::chunk_type chunk_type
The type of the field stored in the array.
Definition: derivative_field.hpp:155
typename base_type::index_range_type index_range_type
The IdxRange on which the fields in this object are defined.
Definition: derivative_field.hpp:126
typename base_type::discrete_domain_type discrete_domain_type
The IdxRange on which the chunks in this object are defined.
Definition: derivative_field.hpp:124
typename base_type::physical_idx_range_type physical_idx_range_type
The physical index range on which the field is defined.
Definition: derivative_field.hpp:146
constexpr KOKKOS_FUNCTION view_type span_cview() const
Get a constant DerivField of this field.
Definition: derivative_field.hpp:383
typename base_type::discrete_element_type discrete_element_type
The Idx which can be used to index this object.
Definition: derivative_field.hpp:134
constexpr DerivField(DerivFieldMem< OElementType, index_range_type, NDerivs, Allocator > &field)
Constructs a new DerivField containing a modifiable view on the data in a DerivFieldMem.
Definition: derivative_field.hpp:258
typename base_type::physical_grids physical_grids
A type sequence containing all the grids on which the fields are defined.
Definition: derivative_field.hpp:143
constexpr DerivField(DerivFieldMem< OElementType, index_range_type, NDerivs, Allocator > const &field)
Constructs a new DerivField containing a constant view on the data in a DerivFieldMem.
Definition: derivative_field.hpp:281
constexpr KOKKOS_FUNCTION DerivField(DerivField< OElementType, index_range_type, MemorySpace, LayoutStridedPolicy > const &field)
Copy construct a DerivField.
Definition: derivative_field.hpp:298
constexpr KOKKOS_FUNCTION span_type span_view() const
Get a modifiable DerivField of this field.
Definition: derivative_field.hpp:396
See DerivFieldImplementation.
Definition: derivative_field.hpp:20