Gyselalib++
 
Loading...
Searching...
No Matches
derivative_field_common.hpp
1// SPDX-License-Identifier: MIT
2
3#pragma once
4#include <array>
5
6#include <ddc/ddc.hpp>
7#include <ddc/kernels/splines.hpp> // Needed for ddc::Deriv
8
9#include <sll/math_tools.hpp>
10
11#include "ddc_aliases.hpp"
12#include "deriv_details.hpp"
13#include "idx_range_slice.hpp"
14
15template <class T>
16inline constexpr bool enable_deriv_field = false;
17
18template <class T>
19inline constexpr bool enable_borrowed_deriv_field = false;
20
21template <class T>
22inline constexpr bool is_deriv_field_v
23 = enable_deriv_field<std::remove_const_t<std::remove_reference_t<T>>>;
24
25template <class T>
26inline constexpr bool is_borrowed_deriv_field_v
27 = (std::is_lvalue_reference_v<T>)
28 || (enable_borrowed_deriv_field<std::remove_cv_t<std::remove_reference_t<T>>>);
29
30template <class FieldType, class SupportType>
32
42template <class FieldType, class... DDims>
43class DerivFieldCommon<FieldType, IdxRange<DDims...>>
44{
45public:
53 using chunk_type = FieldType;
54
56 using deriv_tags = detail::deriv_sub_set_t<ddc::detail::TypeSeq<DDims...>>;
57
59 using physical_deriv_grids = typename detail::strip_deriv_t<deriv_tags>;
60
62 using physical_grids = ddc::type_seq_remove_t<ddc::detail::TypeSeq<DDims...>, deriv_tags>;
63
65 using element_type = typename chunk_type::element_type;
66
73 using discrete_domain_type = IdxRange<DDims...>;
76
83 using discrete_element_type = Idx<DDims...>;
86
87protected:
89 using internal_mdspan_type = Kokkos::mdspan<
91 Kokkos::dextents<std::size_t, sizeof...(DDims)>,
92 Kokkos::layout_stride>;
93
95 using internal_mdview_type = Kokkos::mdspan<
96 const element_type,
97 Kokkos::dextents<std::size_t, sizeof...(DDims)>,
98 Kokkos::layout_stride>;
99
101 using chunk_span = typename FieldType::span_type;
102
104 using chunk_view = typename FieldType::view_type;
105
108 typename ddc::detail::convert_type_seq_to_discrete_domain_t<physical_grids>;
109
111 using physical_index_type = typename physical_idx_range_type::discrete_element_type;
112
115 typename ddc::detail::convert_type_seq_to_discrete_domain_t<deriv_tags>;
116
120 using discrete_deriv_index_type = typename discrete_deriv_idx_range_type::discrete_element_type;
121
125 using discrete_deriv_vector_type = typename discrete_deriv_idx_range_type::discrete_vector_type;
126
128 static constexpr int n_fields = 1 << ddc::type_seq_size_v<deriv_tags>;
129
130 template <class, class, int, class>
131 friend class DerivFieldMem;
132
133 template <class, class, class, class>
134 friend class DerivField;
135
136protected:
149 std::array<internal_mdspan_type, n_fields> internal_fields;
150
153
156
158 to_subidx_range_collection<physical_deriv_grids> m_cross_derivative_idx_range;
159
160protected:
171 template <class DElem>
172 KOKKOS_FUNCTION std::pair<int, index_type> get_index(DElem elem) const
173 {
174 discrete_deriv_index_type default_derivatives = detail::no_derivative_element<deriv_tags>();
175 discrete_deriv_index_type deriv_index(detail::select_default(elem, default_derivatives));
176 physical_index_type physical_index(elem);
177 index_type index(physical_index, deriv_index);
178 return std::pair<int, index_type>(get_array_index(deriv_index), index);
179 }
180
196 template <class... Tag>
197 KOKKOS_FUNCTION int get_array_index(Idx<Tag...> idx) const
198 {
199 static_assert(std::is_same_v<Idx<Tag...>, discrete_deriv_index_type>);
200 return (0 + ...
201 + (int(ddc::select<Tag>(idx) != Idx<Tag>(0))
202 << ddc::type_seq_rank_v<Tag, deriv_tags>));
203 }
204
215 template <class QueryDDim, class... ODDims>
216 KOKKOS_FUNCTION constexpr auto get_slicer_for(Idx<ODDims...> const& slice_idx, int array_idx)
217 const
218 {
219 if constexpr (!ddc::in_tags_v<QueryDDim, ddc::detail::TypeSeq<ODDims...>>) {
220 return Kokkos::full_extent;
221 } else {
222 if constexpr (ddc::in_tags_v<QueryDDim, physical_deriv_grids>) {
223 // Physical dimension along which derivatives are known
224 // If information is available about the physical index range
225 if (array_idx & (1 << ddc::type_seq_rank_v<ddc::Deriv<QueryDDim>, deriv_tags>)) {
226 // If the derivative is being requested
227 return m_cross_derivative_idx_range.get_index(
228 ddc::select<QueryDDim>(slice_idx));
229 }
230 }
231 if constexpr (ddc::in_tags_v<QueryDDim, physical_grids>) {
232 // Physical dimension along which derivatives are not known
233 return std::size_t(
234 (ddc::select<QueryDDim>(slice_idx)
235 - ddc::select<QueryDDim>(m_physical_idx_range).front()));
236 }
237 if constexpr (ddc::in_tags_v<QueryDDim, deriv_tags>) {
238 // Derivative dimension
239 if (array_idx & (1 << ddc::type_seq_rank_v<QueryDDim, deriv_tags>)) {
240 // If array contains derivatives
241 return std::size_t((ddc::select<QueryDDim>(slice_idx) - Idx<QueryDDim>(1)));
242 } else {
243 // If array doesn't contain derivatives
244 assert(ddc::select<QueryDDim>(slice_idx) == Idx<QueryDDim>(0));
245 return std::size_t(0);
246 }
247 }
248 }
249 }
250
261 template <class QueryDDim, class... ODDims>
262 KOKKOS_FUNCTION constexpr auto get_slicer_for(
263 IdxRange<ODDims...> const& slice_idx_range,
264 int array_idx) const
265 {
266 if constexpr (!ddc::in_tags_v<QueryDDim, ddc::detail::TypeSeq<ODDims...>>) {
267 return Kokkos::full_extent;
268 } else {
269 if constexpr (ddc::in_tags_v<QueryDDim, physical_deriv_grids>) {
270 // Physical dimension along which derivatives are known
271 // If information is available about the physical index range
272 IdxRange<QueryDDim> idx_range_requested(slice_idx_range);
273 if (array_idx & (1 << ddc::type_seq_rank_v<ddc::Deriv<QueryDDim>, deriv_tags>)) {
274 // If the derivative is being requested
275 assert(m_cross_derivative_idx_range.contains(idx_range_requested));
276 return std::pair<std::size_t, std::size_t>(
277 m_cross_derivative_idx_range.get_index(idx_range_requested.front()),
278 m_cross_derivative_idx_range.get_index(idx_range_requested.back()) + 1);
279 }
280 }
281 if constexpr (ddc::in_tags_v<QueryDDim, physical_grids>) {
282 // Physical dimension along which derivatives are not known
283 return std::pair<std::size_t, std::size_t>(
284 ddc::select<QueryDDim>(slice_idx_range).front()
285 - ddc::select<QueryDDim>(m_physical_idx_range).front(),
286 ddc::select<QueryDDim>(slice_idx_range).back() + 1
287 - ddc::select<QueryDDim>(m_physical_idx_range).front());
288 }
289 if constexpr (ddc::in_tags_v<QueryDDim, deriv_tags>) {
290 // Derivative dimension
291 if (array_idx & (1 << ddc::type_seq_rank_v<QueryDDim, deriv_tags>)) {
292 // If array contains derivatives
293 return std::pair<std::size_t, std::size_t>(
294 ddc::select<QueryDDim>(slice_idx_range).front() - Idx<QueryDDim>(1),
295 ddc::select<QueryDDim>(slice_idx_range).back() + 1 - Idx<QueryDDim>(1));
296 } else {
297 // If array doesn't contain derivatives
298 assert(ddc::select<QueryDDim>(slice_idx_range).front() == Idx<QueryDDim>(0));
299 assert(ddc::select<QueryDDim>(slice_idx_range).back()
300 == ddc::select<QueryDDim>(slice_idx_range).front());
301 return std::pair<std::size_t, std::size_t>(0, 1);
302 }
303 }
304 }
305 }
306
318 template <class... ODims>
319 KOKKOS_FUNCTION auto get_internal_field(IdxRange<ODims...> idx_range) const
320 {
321 // Get the types related to the provided information
322 using provided_tags = ddc::detail::TypeSeq<ODims...>;
323 using provided_deriv_tags = detail::deriv_sub_set_t<provided_tags>;
324
325 // Get the types related to the implicit information
326 using remaining_deriv_tags = ddc::type_seq_remove_t<deriv_tags, provided_deriv_tags>;
327 using remaining_deriv_idx_range_type =
328 typename ddc::detail::convert_type_seq_to_discrete_domain_t<remaining_deriv_tags>;
329
330 // Find the index range of the derivatives (either provided or an index range containing only the 0-th derivative)
331 remaining_deriv_idx_range_type no_deriv_idx_range = detail::get_idx_range_from_element(
332 detail::no_derivative_element<remaining_deriv_tags>());
333 discrete_deriv_idx_range_type deriv_idx_range(idx_range, no_deriv_idx_range);
334
335 // Find the physical index range of the field
336 physical_idx_range_type local_physical_idx_range(
337 detail::select_default(idx_range, m_physical_idx_range));
338
339 // Find the discrete index range of the field
340 index_range_type full_idx_range(local_physical_idx_range, deriv_idx_range);
341
342 // Find the index of the internal field
343 int const array_idx = get_array_index(deriv_idx_range.front());
344
345 // Get the relevant internal field
346 internal_mdspan_type internal_view = internal_fields[array_idx];
347 // Slice the relevant section of the internal field
348 auto subview = Kokkos::
349 submdspan(internal_view, get_slicer_for<DDims>(full_idx_range, array_idx)...);
350 // Create a Field with the expected index range
351 Field<element_type,
353 typename chunk_type::memory_space,
354 typename decltype(subview)::layout_type>
355 local_field(subview, full_idx_range);
356
357 // If necessary, slice off the derivative dimensions deduced implicitly
358 if constexpr (ddc::type_seq_size_v<remaining_deriv_tags> == 0) {
359 return local_field;
360 } else {
361 return local_field[no_deriv_idx_range.front()];
362 }
363 }
364
376 template <class... ODims>
377 KOKKOS_FUNCTION auto get_internal_field(Idx<ODims...> elem) const
378 {
379 // Get the types related to the provided information
380 using provided_tags = ddc::detail::TypeSeq<ODims...>;
381 using provided_deriv_tags = detail::deriv_sub_set_t<provided_tags>;
382 using provided_physical_tags = ddc::type_seq_remove_t<provided_tags, provided_deriv_tags>;
383 using provided_deriv_idx_range_type
384 = ddc::detail::convert_type_seq_to_discrete_domain_t<provided_deriv_tags>;
385 using provided_deriv_index_type =
386 typename provided_deriv_idx_range_type::discrete_element_type;
387
388 // Get the types related to the implicit information
389 using remaining_deriv_tags = ddc::type_seq_remove_t<deriv_tags, provided_deriv_tags>;
390 using remaining_deriv_idx_range_type =
391 typename ddc::detail::convert_type_seq_to_discrete_domain_t<remaining_deriv_tags>;
392 using remaining_deriv_index_type =
393 typename remaining_deriv_idx_range_type::discrete_element_type;
394
395 // Get the types related to the final field type
396 using sliced_tags = ddc::type_seq_merge_t<provided_physical_tags, deriv_tags>;
397 using sliced_idx_range_type =
398 typename ddc::detail::convert_type_seq_to_discrete_domain_t<sliced_tags>;
399 using sliced_index_type = typename sliced_idx_range_type::discrete_element_type;
400 using final_tags = ddc::type_seq_remove_t<ddc::detail::TypeSeq<DDims...>, sliced_tags>;
401 using final_idx_range_type =
402 typename ddc::detail::convert_type_seq_to_discrete_domain_t<final_tags>;
403
404 // Get the index of the relevant derivatives
405 provided_deriv_index_type requested_derivs(elem);
406 remaining_deriv_index_type no_deriv_elements(
407 detail::no_derivative_element<remaining_deriv_tags>());
408 discrete_deriv_index_type deriv_index(requested_derivs, no_deriv_elements);
409
410 // Get the element which will slice the mdspan
411 sliced_index_type slice_idx(elem, no_deriv_elements);
412
413 // Find the index of the internal field
414 int const array_idx = get_array_index(deriv_index);
415
416 // Get the final index range
417 final_idx_range_type final_idx_range(m_physical_idx_range);
418
419 // Get the relevant internal field
420 internal_mdspan_type internal_view = internal_fields[array_idx];
421 // Slice the relevant section of the internal field
422 auto subview
423 = Kokkos::submdspan(internal_view, get_slicer_for<DDims>(slice_idx, array_idx)...);
424 // Create a Field with the expected index range
425 Field<element_type,
426 final_idx_range_type,
427 typename chunk_type::memory_space,
428 typename decltype(subview)::layout_type>
429 local_field(subview, final_idx_range);
430
431 return local_field;
432 }
433
442 KOKKOS_FUNCTION DerivFieldCommon(
443 physical_idx_range_type physical_idx_range,
444 discrete_deriv_idx_range_type deriv_idx_range,
445 to_subidx_range_collection<physical_deriv_grids> cross_derivative_idx_range)
446 : m_physical_idx_range(physical_idx_range)
447 , m_deriv_idx_range(deriv_idx_range)
448 , m_cross_derivative_idx_range(cross_derivative_idx_range)
449 {
450 }
451
452public:
453 KOKKOS_DEFAULTED_FUNCTION ~DerivFieldCommon() = default;
454
464 template <class... QueryDDims>
465 constexpr auto operator[](Idx<QueryDDims...> const& slice_spec) const
466 {
467 return get_internal_field(slice_spec).span_cview();
468 }
469
479 template <class... QueryDDims>
480 constexpr auto operator[](Idx<QueryDDims...> const& slice_spec)
481 {
482 return get_internal_field(slice_spec);
483 }
484
496 template <class... QueryDDims>
497 KOKKOS_FUNCTION constexpr auto operator[](IdxRange<QueryDDims...> const& oidx_range)
498 {
499 return get_internal_field(oidx_range);
500 }
501
513 template <class... QueryDDims>
514 KOKKOS_FUNCTION constexpr auto operator[](IdxRange<QueryDDims...> const& oidx_range) const
515 {
516 return get_internal_field(oidx_range).span_cview();
517 }
518
530 template <class... ODims>
531 auto get_mdspan(IdxRange<ODims...> provided_deriv_idx_range)
532 {
533 static_assert(((ddc::in_tags_v<ODims, deriv_tags>)&&...));
534 using provided_deriv_tags = ddc::detail::TypeSeq<ODims...>;
535 using remaining_deriv_tags = ddc::type_seq_remove_t<deriv_tags, provided_deriv_tags>;
536 using remaining_deriv_idx_range_type =
537 typename ddc::detail::convert_type_seq_to_discrete_domain_t<remaining_deriv_tags>;
538 using remaining_deriv_index_type =
539 typename remaining_deriv_idx_range_type::discrete_element_type;
540
541 discrete_deriv_index_type default_derivatives = detail::no_derivative_element<deriv_tags>();
542
543 remaining_deriv_index_type deriv_elements(default_derivatives);
544 discrete_deriv_index_type deriv_index(
545 detail::select_default(provided_deriv_idx_range.front(), default_derivatives));
546
547 int const array_idx = get_array_index(deriv_index);
548
549 internal_mdspan_type internal_view = internal_fields[array_idx];
550 auto subview_all_dims = Kokkos::submdspan(
551 internal_view,
552 get_slicer_for<DDims>(provided_deriv_idx_range, array_idx)...);
553 auto subview = Kokkos::
554 submdspan(subview_all_dims, get_slicer_for<DDims>(deriv_elements, array_idx)...);
555 return subview;
556 }
557
564 {
565 IdxRange<> no_specified_dims;
566 return get_mdspan(no_specified_dims);
567 }
568
577 {
578 IdxRange<> no_specified_dims;
579 return get_internal_field(no_specified_dims);
580 }
581
589 auto get_values_field() const
590 {
591 IdxRange<> no_specified_dims;
592 return get_internal_field(no_specified_dims).span_cview();
593 }
594};
KOKKOS_FUNCTION constexpr auto operator[](IdxRange< QueryDDims... > const &oidx_range)
Get a Field describing a subset of the data.
Definition derivative_field_common.hpp:497
ddc::type_seq_remove_t< ddc::detail::TypeSeq< DDims... >, deriv_tags > physical_grids
A type sequence containing all the physical dimensions on which the fields are defined.
Definition derivative_field_common.hpp:62
std::array< internal_mdspan_type, n_fields > internal_fields
The internal fields describing the values and derivatives.
Definition derivative_field_common.hpp:149
typename FieldType::view_type chunk_view
The type of a constant view of this field. This is a DDC keyword used to make this class interchangea...
Definition derivative_field_common.hpp:104
auto get_mdspan()
Get the mdspan holding the values of the function from the internal array internal_fields.
Definition derivative_field_common.hpp:563
IdxRange< DDims... > discrete_domain_type
The IdxRange on which the fields in this object are defined.
Definition derivative_field_common.hpp:73
detail::deriv_sub_set_t< ddc::detail::TypeSeq< DDims... > > deriv_tags
A type sequence containing all derivatives present in this object.
Definition derivative_field_common.hpp:56
typename ddc::detail::convert_type_seq_to_discrete_domain_t< deriv_tags > discrete_deriv_idx_range_type
The IdxRange which describes the derivatives present on each field.
Definition derivative_field_common.hpp:115
to_subidx_range_collection< physical_deriv_grids > m_cross_derivative_idx_range
The physical index ranges on which the derivatives are defined.
Definition derivative_field_common.hpp:158
Kokkos::mdspan< element_type, Kokkos::dextents< std::size_t, sizeof...(DDims)>, Kokkos::layout_stride > internal_mdspan_type
The type of the memory block stored in the array internal_fields.
Definition derivative_field_common.hpp:92
Kokkos::mdspan< const element_type, Kokkos::dextents< std::size_t, sizeof...(DDims)>, Kokkos::layout_stride > internal_mdview_type
The type of a constant view on the memory block stored in the array internal_fields.
Definition derivative_field_common.hpp:98
KOKKOS_FUNCTION int get_array_index(Idx< Tag... > idx) const
An internal function which provides the index of a field inside the internal_fields array.
Definition derivative_field_common.hpp:197
discrete_element_type index_type
The Idx which can be used to index this object.
Definition derivative_field_common.hpp:85
discrete_deriv_idx_range_type m_deriv_idx_range
The index range of available derivatives.
Definition derivative_field_common.hpp:155
typename discrete_deriv_idx_range_type::discrete_vector_type discrete_deriv_vector_type
The Idx which describes the order of the derivatives in each dimension.
Definition derivative_field_common.hpp:125
typename detail::strip_deriv_t< deriv_tags > physical_deriv_grids
A type sequence containing all physical dimensions for which derivatives are present in this object.
Definition derivative_field_common.hpp:59
physical_idx_range_type m_physical_idx_range
The physical index range on which the values are defined.
Definition derivative_field_common.hpp:152
Idx< DDims... > discrete_element_type
The Idx which can be used to index this object.
Definition derivative_field_common.hpp:83
KOKKOS_FUNCTION constexpr auto get_slicer_for(Idx< ODDims... > const &slice_idx, int array_idx) const
Get an object which can be used to slice an mdspan.
Definition derivative_field_common.hpp:216
FieldType chunk_type
The type of the field stored in the array.
Definition derivative_field_common.hpp:53
KOKKOS_FUNCTION constexpr auto get_slicer_for(IdxRange< ODDims... > const &slice_idx_range, int array_idx) const
Get an object which can be used to slice an mdspan.
Definition derivative_field_common.hpp:262
typename chunk_type::element_type element_type
The type of the elements in the fields.
Definition derivative_field_common.hpp:65
typename FieldType::span_type chunk_span
The type of a modifiable span of this field. This is a DDC keyword used to make this class interchang...
Definition derivative_field_common.hpp:101
typename physical_idx_range_type::discrete_element_type physical_index_type
The Idx which describes the physical position where values are defined.
Definition derivative_field_common.hpp:111
discrete_domain_type index_range_type
The IdxRange on which the fields in this object are defined.
Definition derivative_field_common.hpp:75
typename discrete_deriv_idx_range_type::discrete_element_type discrete_deriv_index_type
The Idx which describes the order of the derivatives in each dimension.
Definition derivative_field_common.hpp:120
KOKKOS_FUNCTION auto get_internal_field(IdxRange< ODims... > idx_range) const
Get a Field from a subset of one of the mdspans in internal_fields.
Definition derivative_field_common.hpp:319
KOKKOS_FUNCTION constexpr auto operator[](IdxRange< QueryDDims... > const &oidx_range) const
Get a ConstField describing a subset of the data.
Definition derivative_field_common.hpp:514
KOKKOS_FUNCTION auto get_internal_field(Idx< ODims... > elem) const
Get a Field from a subset of one of the mdspans in internal_fields.
Definition derivative_field_common.hpp:377
KOKKOS_FUNCTION std::pair< int, index_type > get_index(DElem elem) const
An internal function which provides the index of an element inside the internal_fields.
Definition derivative_field_common.hpp:172
typename ddc::detail::convert_type_seq_to_discrete_domain_t< physical_grids > physical_idx_range_type
The index range for the field excluding derivatives.
Definition derivative_field_common.hpp:108
auto get_values_field() const
Get the Field which holds the values of the function.
Definition derivative_field_common.hpp:589
KOKKOS_FUNCTION DerivFieldCommon(physical_idx_range_type physical_idx_range, discrete_deriv_idx_range_type deriv_idx_range, to_subidx_range_collection< physical_deriv_grids > cross_derivative_idx_range)
Protected constructor to be used by subclasses to initialise index ranges.
Definition derivative_field_common.hpp:442
constexpr auto operator[](Idx< QueryDDims... > const &slice_spec) const
Get a ConstField describing a subset of the data.
Definition derivative_field_common.hpp:465
auto get_values_field()
Get the Field which holds the values of the function.
Definition derivative_field_common.hpp:576
constexpr auto operator[](Idx< QueryDDims... > const &slice_spec)
Get a Field describing a subset of the data.
Definition derivative_field_common.hpp:480
auto get_mdspan(IdxRange< ODims... > provided_deriv_idx_range)
Get one of the mdspans from the internal array internal_fields.
Definition derivative_field_common.hpp:531
Definition derivative_field_common.hpp:31
See DerivFieldMemImplementation.
Definition derivative_field.hpp:10
See DerivFieldImplementation.
Definition derivative_field.hpp:20