DDC 0.5.0
Loading...
Searching...
No Matches
chunk_common.hpp
1// Copyright (C) The DDC development team, see COPYRIGHT.md file
2//
3// SPDX-License-Identifier: MIT
4
5#pragma once
6
7#include <array>
8#include <cassert>
9#include <cstddef>
10#include <type_traits>
11#include <utility>
12
13#include <Kokkos_Core.hpp>
14
15#include "ddc/chunk_traits.hpp"
16#include "ddc/detail/macros.hpp"
17#include "ddc/discrete_domain.hpp"
18
19namespace ddc {
20
21/** Access the domain (or subdomain) of a view
22 * @param[in] chunk the view whose domain to access
23 * @return the domain of view in the queried dimensions
24 */
25template <class... QueryDDims, class ChunkType>
26KOKKOS_FUNCTION auto get_domain(ChunkType const& chunk) noexcept
27{
28 static_assert(is_chunk_v<ChunkType>, "Not a chunk span type");
29 return chunk.template domain<QueryDDims...>();
30}
31
32template <class ElementType, class SupportType, class LayoutStridedPolicy>
33class ChunkCommon;
34
35template <class ElementType, class... DDims, class LayoutStridedPolicy>
36class ChunkCommon<ElementType, DiscreteDomain<DDims...>, LayoutStridedPolicy>
37{
38protected:
39 /// the raw mdspan underlying this, with the same indexing (0 might no be dereferenceable)
40 using internal_mdspan_type = Kokkos::mdspan<
41 ElementType,
42 Kokkos::dextents<std::size_t, sizeof...(DDims)>,
43 Kokkos::layout_stride>;
44
45public:
46 using discrete_domain_type = DiscreteDomain<DDims...>;
47
48 /// The dereferenceable part of the co-domain but with a different domain, starting at 0
49 using allocation_mdspan_type = Kokkos::mdspan<
50 ElementType,
51 Kokkos::dextents<std::size_t, sizeof...(DDims)>,
52 LayoutStridedPolicy>;
53
54 using const_allocation_mdspan_type = Kokkos::mdspan<
55 const ElementType,
56 Kokkos::dextents<std::size_t, sizeof...(DDims)>,
57 LayoutStridedPolicy>;
58
59 using discrete_element_type = typename discrete_domain_type::discrete_element_type;
60
61 using extents_type = typename allocation_mdspan_type::extents_type;
62
63 using layout_type = typename allocation_mdspan_type::layout_type;
64
65 using accessor_type = typename allocation_mdspan_type::accessor_type;
66
67 using mapping_type = typename allocation_mdspan_type::mapping_type;
68
69 using element_type = typename allocation_mdspan_type::element_type;
70
71 using value_type = typename allocation_mdspan_type::value_type;
72
73 using size_type = typename allocation_mdspan_type::size_type;
74
75 using data_handle_type = typename allocation_mdspan_type::data_handle_type;
76
77 using reference = typename allocation_mdspan_type::reference;
78
79 // ChunkCommon, ChunkSpan and Chunk need to access to m_internal_mdspan and m_domain of other template versions
80 template <class, class, class>
81 friend class ChunkCommon;
82
83 template <class, class, class, class>
84 friend class ChunkSpan;
85
86 template <class, class, class>
87 friend class Chunk;
88
89 static_assert(mapping_type::is_always_strided());
90
91protected:
92 /// The raw view of the data
93 internal_mdspan_type m_internal_mdspan;
94
95 /// The mesh on which this chunk is defined
96 discrete_domain_type m_domain;
97
98public:
99 static KOKKOS_FUNCTION constexpr int rank() noexcept
100 {
101 return extents_type::rank();
102 }
103
104 static KOKKOS_FUNCTION constexpr int rank_dynamic() noexcept
105 {
106 return extents_type::rank_dynamic();
107 }
108
109 static KOKKOS_FUNCTION constexpr size_type static_extent(std::size_t r) noexcept
110 {
111 return extents_type::static_extent(r);
112 }
113
114 static KOKKOS_FUNCTION constexpr bool is_always_unique() noexcept
115 {
116 return mapping_type::is_always_unique();
117 }
118
119 static KOKKOS_FUNCTION constexpr bool is_always_exhaustive() noexcept
120 {
121 return mapping_type::is_always_exhaustive();
122 }
123
124 static KOKKOS_FUNCTION constexpr bool is_always_strided() noexcept
125 {
126 return mapping_type::is_always_strided();
127 }
128
129private:
130 template <class Mapping = mapping_type>
131 static KOKKOS_FUNCTION constexpr std::
132 enable_if_t<std::is_constructible_v<Mapping, extents_type>, internal_mdspan_type>
133 make_internal_mdspan(ElementType* ptr, discrete_domain_type const& domain)
134 {
135 if (domain.empty()) {
136 return internal_mdspan_type(ptr, Kokkos::layout_stride::mapping<extents_type>());
137 }
138 extents_type const extents_r(::ddc::extents<DDims>(domain).value()...);
139 mapping_type const mapping_r(extents_r);
140
141 extents_type const extents_s((front<DDims>(domain) + ddc::extents<DDims>(domain)).uid()...);
142 std::array<std::size_t, sizeof...(DDims)> const strides_s {
143 mapping_r.stride(type_seq_rank_v<DDims, detail::TypeSeq<DDims...>>)...};
144 Kokkos::layout_stride::mapping<extents_type> const mapping_s(extents_s, strides_s);
145 return internal_mdspan_type(ptr - mapping_s(front<DDims>(domain).uid()...), mapping_s);
146 }
147
148public:
149 KOKKOS_FUNCTION constexpr accessor_type accessor() const
150 {
151 return m_internal_mdspan.accessor();
152 }
153
154 KOKKOS_FUNCTION constexpr DiscreteVector<DDims...> extents() const noexcept
155 {
156 return m_domain.extents();
157 }
158
159 template <class QueryDDim>
160 KOKKOS_FUNCTION constexpr size_type extent() const noexcept
161 {
162 return m_domain.template extent<QueryDDim>();
163 }
164
165 KOKKOS_FUNCTION constexpr size_type size() const noexcept
166 {
167 return allocation_mdspan().size();
168 }
169
170 KOKKOS_FUNCTION constexpr mapping_type mapping() const noexcept
171 {
172 return allocation_mdspan().mapping();
173 }
174
175 KOKKOS_FUNCTION constexpr bool is_unique() const noexcept
176 {
177 return allocation_mdspan().is_unique();
178 }
179
180 KOKKOS_FUNCTION constexpr bool is_exhaustive() const noexcept
181 {
182 return allocation_mdspan().is_exhaustive();
183 }
184
185 KOKKOS_FUNCTION constexpr bool is_strided() const noexcept
186 {
187 return allocation_mdspan().is_strided();
188 }
189
190 template <class QueryDDim>
191 KOKKOS_FUNCTION constexpr size_type stride() const
192 {
193 return m_internal_mdspan.stride(type_seq_rank_v<QueryDDim, detail::TypeSeq<DDims...>>);
194 }
195
196 /** Provide access to the domain on which this chunk is defined
197 * @return the domain on which this chunk is defined
198 */
199 KOKKOS_FUNCTION constexpr discrete_domain_type domain() const noexcept
200 {
201 return m_domain;
202 }
203
204 /** Provide access to the domain on which this chunk is defined
205 * @return the domain on which this chunk is defined
206 */
207 template <class... QueryDDims>
208 KOKKOS_FUNCTION constexpr DiscreteDomain<QueryDDims...> domain() const noexcept
209 {
210 return DiscreteDomain<QueryDDims...>(domain());
211 }
212
213protected:
214 /// Empty ChunkCommon
215 KOKKOS_DEFAULTED_FUNCTION constexpr ChunkCommon() = default;
216
217 /** Constructs a new ChunkCommon from scratch
218 * @param internal_mdspan
219 * @param domain
220 */
222 internal_mdspan_type internal_mdspan,
223 discrete_domain_type const& domain) noexcept
224 : m_internal_mdspan(std::move(internal_mdspan))
225 , m_domain(domain)
226 {
227 }
228
229 /** Constructs a new ChunkCommon from scratch
230 * @param ptr the allocation pointer to the data
231 * @param domain the domain that sustains the view
232 */
233 template <
234 class Mapping = mapping_type,
235 std::enable_if_t<std::is_constructible_v<Mapping, extents_type>, int> = 0>
236 KOKKOS_FUNCTION constexpr ChunkCommon(ElementType* ptr, discrete_domain_type const& domain)
237 : m_internal_mdspan(make_internal_mdspan(ptr, domain))
238 , m_domain(domain)
239 {
240 // Handle the case where an allocation of size 0 returns a nullptr.
241 assert(domain.empty() || ((ptr != nullptr) && !domain.empty()));
242 }
243
244 /** Constructs a new ChunkCommon by copy, yields a new view to the same data
245 * @param other the ChunkCommon to copy
246 */
247 KOKKOS_DEFAULTED_FUNCTION constexpr ChunkCommon(ChunkCommon const& other) = default;
248
249 /** Constructs a new ChunkCommon by move
250 * @param other the ChunkCommon to move
251 */
252 KOKKOS_DEFAULTED_FUNCTION constexpr ChunkCommon(ChunkCommon&& other) noexcept = default;
253
254 KOKKOS_DEFAULTED_FUNCTION ~ChunkCommon() noexcept = default;
255
256 /** Copy-assigns a new value to this ChunkCommon, yields a new view to the same data
257 * @param other the ChunkCommon to copy
258 * @return *this
259 */
260 KOKKOS_DEFAULTED_FUNCTION constexpr ChunkCommon& operator=(ChunkCommon const& other) = default;
261
262 /** Move-assigns a new value to this ChunkCommon
263 * @param other the ChunkCommon to move
264 * @return *this
265 */
266 KOKKOS_DEFAULTED_FUNCTION constexpr ChunkCommon& operator=(ChunkCommon&& other) noexcept
267 = default;
268
269 /** Access to the underlying allocation pointer
270 * @return allocation pointer
271 */
272 KOKKOS_FUNCTION constexpr ElementType* data_handle() const
273 {
274 ElementType* ptr = m_internal_mdspan.data_handle();
275 if (!m_domain.empty()) {
276 ptr += m_internal_mdspan.mapping()(front<DDims>(m_domain).uid()...);
277 }
278 return ptr;
279 }
280
281 /** Provide a modifiable view of the data
282 * @return a modifiable view of the data
283 */
284 KOKKOS_FUNCTION constexpr internal_mdspan_type internal_mdspan() const
285 {
286 return m_internal_mdspan;
287 }
288
289 /** Provide a modifiable view of the data
290 * @return a modifiable view of the data
291 */
292 KOKKOS_FUNCTION constexpr allocation_mdspan_type allocation_mdspan() const
293 {
294 DDC_IF_NVCC_THEN_PUSH_AND_SUPPRESS(implicit_return_from_non_void_function)
295 extents_type const extents_s(::ddc::extents<DDims>(m_domain).value()...);
296 if constexpr (std::is_same_v<LayoutStridedPolicy, Kokkos::layout_stride>) {
297 mapping_type const map(extents_s, m_internal_mdspan.mapping().strides());
298 return allocation_mdspan_type(data_handle(), map);
299 } else {
300 mapping_type const map(extents_s);
301 return allocation_mdspan_type(data_handle(), map);
302 }
303 DDC_IF_NVCC_THEN_POP
304 }
305};
306
307template <class ElementType, class SupportType, class LayoutStridedPolicy>
308class ChunkCommon
309{
310public:
311 using discrete_domain_type = SupportType;
312
313 /// The dereferenceable part of the co-domain but with a different domain, starting at 0
314 using allocation_mdspan_type = Kokkos::mdspan<
315 ElementType,
316 Kokkos::dextents<std::size_t, SupportType::rank()>,
317 LayoutStridedPolicy>;
318
319 using const_allocation_mdspan_type = Kokkos::mdspan<
320 const ElementType,
321 Kokkos::dextents<std::size_t, SupportType::rank()>,
322 LayoutStridedPolicy>;
323
324 using discrete_element_type = typename discrete_domain_type::discrete_element_type;
325
326 using extents_type = typename allocation_mdspan_type::extents_type;
327
328 using layout_type = typename allocation_mdspan_type::layout_type;
329
330 using accessor_type = typename allocation_mdspan_type::accessor_type;
331
332 using mapping_type = typename allocation_mdspan_type::mapping_type;
333
334 using element_type = typename allocation_mdspan_type::element_type;
335
336 using value_type = typename allocation_mdspan_type::value_type;
337
338 using size_type = typename allocation_mdspan_type::size_type;
339
340 using data_handle_type = typename allocation_mdspan_type::data_handle_type;
341
342 using reference = typename allocation_mdspan_type::reference;
343
344 // ChunkCommon, ChunkSpan and Chunk need to access to m_allocation_mdspan_mdspan and m_domain of other template versions
345 template <class, class, class>
346 friend class ChunkCommon;
347
348 template <class, class, class, class>
349 friend class ChunkSpan;
350
351 template <class, class, class>
352 friend class Chunk;
353
354 static_assert(mapping_type::is_always_strided());
355
356protected:
357 /// The raw view of the data
358 allocation_mdspan_type m_allocation_mdspan;
359
360 /// The mesh on which this chunk is defined
361 SupportType m_domain;
362
363public:
364 static KOKKOS_FUNCTION constexpr int rank() noexcept
365 {
366 return extents_type::rank();
367 }
368
369 static KOKKOS_FUNCTION constexpr int rank_dynamic() noexcept
370 {
371 return extents_type::rank_dynamic();
372 }
373
374 static KOKKOS_FUNCTION constexpr size_type static_extent(std::size_t r) noexcept
375 {
376 return extents_type::static_extent(r);
377 }
378
379 static KOKKOS_FUNCTION constexpr bool is_always_unique() noexcept
380 {
381 return mapping_type::is_always_unique();
382 }
383
384 static KOKKOS_FUNCTION constexpr bool is_always_exhaustive() noexcept
385 {
386 return mapping_type::is_always_exhaustive();
387 }
388
389 static KOKKOS_FUNCTION constexpr bool is_always_strided() noexcept
390 {
391 return mapping_type::is_always_strided();
392 }
393
394private:
395 template <class Mapping = mapping_type>
396 static KOKKOS_FUNCTION constexpr std::
397 enable_if_t<std::is_constructible_v<Mapping, extents_type>, allocation_mdspan_type>
398 make_allocation_mdspan(ElementType* ptr, SupportType const& domain)
399 {
400 return allocation_mdspan_type(ptr, detail::array(domain.extents()));
401 }
402
403public:
404 KOKKOS_FUNCTION constexpr accessor_type accessor() const
405 {
406 return m_allocation_mdspan.accessor();
407 }
408
409 KOKKOS_FUNCTION constexpr typename SupportType::discrete_vector_type extents() const noexcept
410 {
411 return m_domain.extents();
412 }
413
414 template <class QueryDDim>
415 KOKKOS_FUNCTION constexpr size_type extent() const noexcept
416 {
417 return m_domain.template extent<QueryDDim>();
418 }
419
420 KOKKOS_FUNCTION constexpr size_type size() const noexcept
421 {
422 return allocation_mdspan().size();
423 }
424
425 KOKKOS_FUNCTION constexpr mapping_type mapping() const noexcept
426 {
427 return allocation_mdspan().mapping();
428 }
429
430 KOKKOS_FUNCTION constexpr bool is_unique() const noexcept
431 {
432 return allocation_mdspan().is_unique();
433 }
434
435 KOKKOS_FUNCTION constexpr bool is_exhaustive() const noexcept
436 {
437 return allocation_mdspan().is_exhaustive();
438 }
439
440 KOKKOS_FUNCTION constexpr bool is_strided() const noexcept
441 {
442 return allocation_mdspan().is_strided();
443 }
444
445 template <class QueryDDim>
446 KOKKOS_FUNCTION constexpr size_type stride() const
447 {
448 return m_allocation_mdspan.stride(type_seq_rank_v<QueryDDim, to_type_seq_t<SupportType>>);
449 }
450
451 /** Provide access to the domain on which this chunk is defined
452 * @return the domain on which this chunk is defined
453 */
454 KOKKOS_FUNCTION constexpr SupportType domain() const noexcept
455 {
456 return m_domain;
457 }
458
459 /** Provide access to the domain on which this chunk is defined
460 * @return the domain on which this chunk is defined
461 */
462 template <class... QueryDDims>
463 KOKKOS_FUNCTION constexpr DiscreteDomain<QueryDDims...> domain() const noexcept
464 {
465 return DiscreteDomain<QueryDDims...>(domain());
466 }
467
468protected:
469 /// Empty ChunkCommon
470 KOKKOS_DEFAULTED_FUNCTION constexpr ChunkCommon() = default;
471
472 /** Constructs a new ChunkCommon from scratch
473 * @param allocation_mdspan
474 * @param domain
475 */
477 allocation_mdspan_type allocation_mdspan,
478 SupportType const& domain) noexcept
479 : m_allocation_mdspan(std::move(allocation_mdspan))
480 , m_domain(domain)
481 {
482 }
483
484 /** Constructs a new ChunkCommon from scratch
485 * @param ptr the allocation pointer to the data
486 * @param domain the domain that sustains the view
487 */
488 template <
489 class Mapping = mapping_type,
490 std::enable_if_t<std::is_constructible_v<Mapping, extents_type>, int> = 0>
491 KOKKOS_FUNCTION constexpr ChunkCommon(ElementType* ptr, SupportType const& domain)
492 : m_allocation_mdspan(make_allocation_mdspan(ptr, domain))
493 , m_domain(domain)
494 {
495 // Handle the case where an allocation of size 0 returns a nullptr.
496 assert(domain.empty() || ((ptr != nullptr) && !domain.empty()));
497 }
498
499 /** Constructs a new ChunkCommon by copy, yields a new view to the same data
500 * @param other the ChunkCommon to copy
501 */
502 KOKKOS_DEFAULTED_FUNCTION constexpr ChunkCommon(ChunkCommon const& other) = default;
503
504 /** Constructs a new ChunkCommon by move
505 * @param other the ChunkCommon to move
506 */
507 KOKKOS_DEFAULTED_FUNCTION constexpr ChunkCommon(ChunkCommon&& other) noexcept = default;
508
509 KOKKOS_DEFAULTED_FUNCTION ~ChunkCommon() noexcept = default;
510
511 /** Copy-assigns a new value to this ChunkCommon, yields a new view to the same data
512 * @param other the ChunkCommon to copy
513 * @return *this
514 */
515 KOKKOS_DEFAULTED_FUNCTION constexpr ChunkCommon& operator=(ChunkCommon const& other) = default;
516
517 /** Move-assigns a new value to this ChunkCommon
518 * @param other the ChunkCommon to move
519 * @return *this
520 */
521 KOKKOS_DEFAULTED_FUNCTION constexpr ChunkCommon& operator=(ChunkCommon&& other) noexcept
522 = default;
523
524 /** Access to the underlying allocation pointer
525 * @return allocation pointer
526 */
527 KOKKOS_FUNCTION constexpr ElementType* data_handle() const
528 {
529 return m_allocation_mdspan.data_handle();
530 }
531
532 /** Provide a modifiable view of the data
533 * @return a modifiable view of the data
534 */
535 KOKKOS_FUNCTION constexpr allocation_mdspan_type allocation_mdspan() const
536 {
537 return m_allocation_mdspan;
538 }
539};
540
541} // namespace ddc
KOKKOS_FUNCTION constexpr mapping_type mapping() const noexcept
KOKKOS_DEFAULTED_FUNCTION constexpr ChunkCommon & operator=(ChunkCommon const &other)=default
Copy-assigns a new value to this ChunkCommon, yields a new view to the same data.
KOKKOS_FUNCTION constexpr discrete_domain_type domain() const noexcept
Provide access to the domain on which this chunk is defined.
discrete_domain_type m_domain
The mesh on which this chunk is defined.
KOKKOS_DEFAULTED_FUNCTION constexpr ChunkCommon(ChunkCommon const &other)=default
Constructs a new ChunkCommon by copy, yields a new view to the same data.
KOKKOS_FUNCTION constexpr DiscreteVector< DDims... > extents() const noexcept
KOKKOS_DEFAULTED_FUNCTION constexpr ChunkCommon()=default
Empty ChunkCommon.
KOKKOS_FUNCTION constexpr ElementType * data_handle() const
Access to the underlying allocation pointer.
KOKKOS_FUNCTION constexpr allocation_mdspan_type allocation_mdspan() const
Provide a modifiable view of the data.
KOKKOS_FUNCTION constexpr ChunkCommon(internal_mdspan_type internal_mdspan, discrete_domain_type const &domain) noexcept
Constructs a new ChunkCommon from scratch.
KOKKOS_FUNCTION constexpr internal_mdspan_type internal_mdspan() const
Provide a modifiable view of the data.
static KOKKOS_FUNCTION constexpr size_type static_extent(std::size_t r) noexcept
KOKKOS_DEFAULTED_FUNCTION constexpr ChunkCommon(ChunkCommon &&other) noexcept=default
Constructs a new ChunkCommon by move.
KOKKOS_FUNCTION constexpr ChunkCommon(ElementType *ptr, discrete_domain_type const &domain)
Constructs a new ChunkCommon from scratch.
KOKKOS_DEFAULTED_FUNCTION constexpr ChunkCommon & operator=(ChunkCommon &&other) noexcept=default
Move-assigns a new value to this ChunkCommon.
KOKKOS_FUNCTION constexpr DiscreteDomain< QueryDDims... > domain() const noexcept
Provide access to the domain on which this chunk is defined.
KOKKOS_FUNCTION constexpr bool is_strided() const noexcept
KOKKOS_DEFAULTED_FUNCTION ~ChunkCommon() noexcept=default
KOKKOS_FUNCTION constexpr ElementType * data_handle() const
Access to the underlying allocation pointer.
KOKKOS_DEFAULTED_FUNCTION constexpr ChunkCommon()=default
Empty ChunkCommon.
allocation_mdspan_type m_allocation_mdspan
The raw view of the data.
KOKKOS_FUNCTION constexpr SupportType domain() const noexcept
Provide access to the domain on which this chunk is defined.
static KOKKOS_FUNCTION constexpr bool is_always_strided() noexcept
KOKKOS_FUNCTION constexpr allocation_mdspan_type allocation_mdspan() const
Provide a modifiable view of the data.
KOKKOS_FUNCTION constexpr ChunkCommon(allocation_mdspan_type allocation_mdspan, SupportType const &domain) noexcept
Constructs a new ChunkCommon from scratch.
KOKKOS_FUNCTION constexpr ChunkCommon(ElementType *ptr, SupportType const &domain)
Constructs a new ChunkCommon from scratch.
KOKKOS_DEFAULTED_FUNCTION constexpr ChunkCommon(ChunkCommon const &other)=default
Constructs a new ChunkCommon by copy, yields a new view to the same data.
static KOKKOS_FUNCTION constexpr bool is_always_unique() noexcept
KOKKOS_FUNCTION constexpr DiscreteDomain< QueryDDims... > domain() const noexcept
Provide access to the domain on which this chunk is defined.
KOKKOS_DEFAULTED_FUNCTION constexpr ChunkCommon & operator=(ChunkCommon const &other)=default
Copy-assigns a new value to this ChunkCommon, yields a new view to the same data.
KOKKOS_DEFAULTED_FUNCTION constexpr ChunkCommon(ChunkCommon &&other) noexcept=default
Constructs a new ChunkCommon by move.
KOKKOS_DEFAULTED_FUNCTION constexpr ChunkCommon & operator=(ChunkCommon &&other) noexcept=default
Move-assigns a new value to this ChunkCommon.
KOKKOS_FUNCTION constexpr size_type extent() const noexcept
KOKKOS_FUNCTION constexpr size_type stride() const
KOKKOS_FUNCTION constexpr bool is_exhaustive() const noexcept
KOKKOS_FUNCTION constexpr mapping_type mapping() const noexcept
static KOKKOS_FUNCTION constexpr int rank() noexcept
KOKKOS_FUNCTION constexpr bool is_unique() const noexcept
KOKKOS_FUNCTION constexpr accessor_type accessor() const
KOKKOS_FUNCTION constexpr SupportType::discrete_vector_type extents() const noexcept
KOKKOS_FUNCTION constexpr size_type size() const noexcept
SupportType m_domain
The mesh on which this chunk is defined.
static KOKKOS_FUNCTION constexpr int rank_dynamic() noexcept
static KOKKOS_FUNCTION constexpr size_type static_extent(std::size_t r) noexcept
static KOKKOS_FUNCTION constexpr bool is_always_exhaustive() noexcept
friend class DiscreteDomain
KOKKOS_FUNCTION constexpr bool operator!=(DiscreteVector< OTags... > const &rhs) const noexcept
The top-level namespace of DDC.
KOKKOS_FUNCTION auto get_domain(ChunkType const &chunk) noexcept
Access the domain (or subdomain) of a view.