DDC 0.7.0
Loading...
Searching...
No Matches
chunk.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 <cassert>
8#include <string>
9#include <type_traits>
10#include <utility>
11
12#include <Kokkos_Core.hpp>
13
14#include "detail/kokkos.hpp"
15#include "detail/type_traits.hpp"
16
17#include "chunk_common.hpp"
18#include "chunk_span.hpp"
19#include "chunk_traits.hpp"
20#include "kokkos_allocator.hpp"
21
22namespace ddc {
23
24template <class ElementType, class, class Allocator = HostAllocator<ElementType>>
25class Chunk;
26
27template <class ElementType, class SupportType, class Allocator>
28inline constexpr bool enable_chunk<Chunk<ElementType, SupportType, Allocator>> = true;
29
30template <class ElementType, class SupportType, class Allocator>
31class Chunk : public ChunkCommon<ElementType, SupportType, Kokkos::layout_right>
32{
33protected:
34 using base_type = ChunkCommon<ElementType, SupportType, Kokkos::layout_right>;
35
36public:
37 /// type of a span of this full chunk
38 using span_type = ChunkSpan<
39 ElementType,
40 SupportType,
41 Kokkos::layout_right,
42 typename Allocator::memory_space>;
43
44 /// type of a view of this full chunk
45 using view_type = ChunkSpan<
46 ElementType const,
47 SupportType,
48 Kokkos::layout_right,
49 typename Allocator::memory_space>;
50
51 /// The dereferenceable part of the co-domain but with indexing starting at 0
52 using allocation_mdspan_type = typename base_type::allocation_mdspan_type;
53
54 using const_allocation_mdspan_type = typename base_type::const_allocation_mdspan_type;
55
56 using discrete_domain_type = typename base_type::discrete_domain_type;
57
58 using memory_space = typename Allocator::memory_space;
59
60 using discrete_element_type = typename base_type::discrete_element_type;
61
62 using discrete_vector_type = typename base_type::discrete_vector_type;
63
64 using extents_type = typename base_type::extents_type;
65
66 using layout_type = typename base_type::layout_type;
67
68 using mapping_type = typename base_type::mapping_type;
69
70 using element_type = typename base_type::element_type;
71
72 using value_type = typename base_type::value_type;
73
74 using size_type = typename base_type::size_type;
75
76 using data_handle_type = typename base_type::data_handle_type;
77
78 using reference = typename base_type::reference;
79
80 template <class, class, class>
81 friend class Chunk;
82
83private:
84 Allocator m_allocator;
85
86 std::string m_label;
87
88public:
89 /// Empty Chunk
90 Chunk() = default;
91
92 /// Construct a labeled Chunk on a domain with uninitialized values
93 explicit Chunk(
94 std::string const& label,
95 SupportType const& domain,
96 Allocator allocator = Allocator())
97 : base_type(allocator.allocate(label, domain.size()), domain)
98 , m_allocator(std::move(allocator))
99 , m_label(label)
100 {
101 }
102
103 /// Construct a Chunk on a domain with uninitialized values
104 explicit Chunk(SupportType const& domain, Allocator allocator = Allocator())
105 : Chunk("no-label", domain, std::move(allocator))
106 {
107 }
108
109 /// Deleted: use deepcopy instead
110 Chunk(Chunk const& other) = delete;
111
112 /** Constructs a new Chunk by move
113 * @param other the Chunk to move
114 */
115 Chunk(Chunk&& other) noexcept
116 : base_type(std::move(static_cast<base_type&>(other)))
117 , m_allocator(std::move(other.m_allocator))
118 , m_label(std::move(other.m_label))
119 {
120 other.m_allocation_mdspan
121 = allocation_mdspan_type(nullptr, other.m_allocation_mdspan.mapping());
122 }
123
124 ~Chunk() noexcept
125 {
126 if (this->m_allocation_mdspan.data_handle()) {
127 m_allocator.deallocate(this->data_handle(), this->size());
128 }
129 }
130
131 /// Deleted: use deepcopy instead
132 Chunk& operator=(Chunk const& other) = delete;
133
134 /** Move-assigns a new value to this field
135 * @param other the Chunk to move
136 * @return *this
137 */
138 Chunk& operator=(Chunk&& other) noexcept
139 {
140 if (this == &other) {
141 return *this;
142 }
143 if (this->m_allocation_mdspan.data_handle()) {
144 m_allocator.deallocate(this->data_handle(), this->size());
145 }
146 static_cast<base_type&>(*this) = std::move(static_cast<base_type&>(other));
147 m_allocator = std::move(other.m_allocator);
148 m_label = std::move(other.m_label);
149 other.m_allocation_mdspan
150 = allocation_mdspan_type(nullptr, other.m_allocation_mdspan.mapping());
151
152 return *this;
153 }
154
155 /// Slice out some dimensions
156 template <class... QueryDDims>
157 auto operator[](DiscreteElement<QueryDDims...> const& slice_spec) const
158 {
159 return view_type(*this)[slice_spec];
160 }
161
162 /// Slice out some dimensions
163 template <class... QueryDDims>
164 auto operator[](DiscreteElement<QueryDDims...> const& slice_spec)
165 {
166 return span_view()[slice_spec];
167 }
168
169 /// Slice out some dimensions
170 template <class... QueryDDims>
171 auto operator[](DiscreteDomain<QueryDDims...> const& odomain) const
172 {
173 return span_view()[odomain];
174 }
175
176 /// Slice out some dimensions
177 template <class... QueryDDims>
178 auto operator[](DiscreteDomain<QueryDDims...> const& odomain)
179 {
180 return span_view()[odomain];
181 }
182
183 /** Element access using a list of DiscreteElement
184 * @param delems discrete coordinates
185 * @return const-reference to this element
186 */
187 template <
188 class... DElems,
189 std::enable_if_t<detail::all_of_v<is_discrete_element_v<DElems>...>, int> = 0>
190 element_type const& operator()(DElems const&... delems) const noexcept
191 {
192 static_assert(
193 SupportType::rank() == (0 + ... + DElems::size()),
194 "Invalid number of dimensions");
195 assert(this->m_domain.contains(delems...));
196 return DDC_MDSPAN_ACCESS_OP(
197 this->m_allocation_mdspan,
198 detail::array(this->m_domain.distance_from_front(delems...)));
199 }
200
201 /** Element access using a list of DiscreteVector
202 * @param dvects discrete vectors
203 * @return reference to this element
204 */
205 template <
206 class... DVects,
207 std::enable_if_t<detail::all_of_v<is_discrete_vector_v<DVects>...>, int> = 0,
208 std::enable_if_t<sizeof...(DVects) != 0, int> = 0>
209 element_type const& operator()(DVects const&... dvects) const noexcept
210 {
211 static_assert(
212 SupportType::rank() == (0 + ... + DVects::size()),
213 "Invalid number of dimensions");
214 return DDC_MDSPAN_ACCESS_OP(
215 this->m_allocation_mdspan,
216 detail::array(discrete_vector_type(dvects...)));
217 }
218
219 /** Element access using a list of DiscreteElement
220 * @param delems discrete coordinates
221 * @return reference to this element
222 */
223 template <
224 class... DElems,
225 std::enable_if_t<detail::all_of_v<is_discrete_element_v<DElems>...>, int> = 0>
226 element_type& operator()(DElems const&... delems) noexcept
227 {
228 static_assert(
229 SupportType::rank() == (0 + ... + DElems::size()),
230 "Invalid number of dimensions");
231 assert(this->m_domain.contains(delems...));
232 return DDC_MDSPAN_ACCESS_OP(
233 this->m_allocation_mdspan,
234 detail::array(this->m_domain.distance_from_front(delems...)));
235 }
236
237 /** Element access using a list of DiscreteVector
238 * @param dvects discrete vectors
239 * @return reference to this element
240 */
241 template <
242 class... DVects,
243 std::enable_if_t<detail::all_of_v<is_discrete_vector_v<DVects>...>, int> = 0,
244 std::enable_if_t<sizeof...(DVects) != 0, int> = 0>
245 element_type& operator()(DVects const&... dvects) noexcept
246 {
247 static_assert(
248 SupportType::rank() == (0 + ... + DVects::size()),
249 "Invalid number of dimensions");
250 return DDC_MDSPAN_ACCESS_OP(
251 this->m_allocation_mdspan,
252 detail::array(discrete_vector_type(dvects...)));
253 }
254
255 /** Returns the label of the Chunk
256 * @return c-string
257 */
258 char const* label() const
259 {
260 return m_label.c_str();
261 }
262
263 /** Access to the underlying allocation pointer
264 * @return read-only allocation pointer
265 */
266 ElementType const* data_handle() const
267 {
268 return base_type::data_handle();
269 }
270
271 /** Access to the underlying allocation pointer
272 * @return allocation pointer
273 */
274 ElementType* data_handle()
275 {
276 return base_type::data_handle();
277 }
278
279 /** Provide a mdspan on the memory allocation
280 * @return read-only allocation mdspan
281 */
282 const_allocation_mdspan_type allocation_mdspan() const
283 {
284 return base_type::allocation_mdspan();
285 }
286
287 /** Provide a mdspan on the memory allocation
288 * @return allocation mdspan
289 */
290 allocation_mdspan_type allocation_mdspan()
291 {
292 return base_type::allocation_mdspan();
293 }
294
295 /** Provide an unmanaged `Kokkos::View` on the memory allocation
296 * @return allocation `Kokkos::View`
297 */
299 {
300 auto s = this->allocation_mdspan();
301 auto kokkos_layout = detail::build_kokkos_layout(
302 s.extents(),
303 s.mapping(),
304 std::make_index_sequence<SupportType::rank()> {});
305 return Kokkos::View<
306 detail::mdspan_to_kokkos_element_t<ElementType, SupportType::rank()>,
307 decltype(kokkos_layout),
308 typename Allocator::memory_space>(s.data_handle(), kokkos_layout);
309 }
310
311 /** Provide an unmanaged `Kokkos::View` on the memory allocation
312 * @return read-only allocation `Kokkos::View`
313 */
314 auto allocation_kokkos_view() const
315 {
316 auto s = this->allocation_mdspan();
317 auto kokkos_layout = detail::build_kokkos_layout(
318 s.extents(),
319 s.mapping(),
320 std::make_index_sequence<SupportType::rank()> {});
321 return Kokkos::View<
322 detail::mdspan_to_kokkos_element_t<ElementType const, SupportType::rank()>,
323 decltype(kokkos_layout),
324 typename Allocator::memory_space>(s.data_handle(), kokkos_layout);
325 }
326
327 view_type span_cview() const
328 {
329 return view_type(*this);
330 }
331
332 view_type span_view() const
333 {
334 return view_type(*this);
335 }
336
337 span_type span_view()
338 {
339 return span_type(*this);
340 }
341};
342
343template <class SupportType, class Allocator>
344Chunk(std::string const&, SupportType const&, Allocator)
345 -> Chunk<typename Allocator::value_type, SupportType, Allocator>;
346
347template <class SupportType, class Allocator>
348Chunk(SupportType const&, Allocator)
349 -> Chunk<typename Allocator::value_type, SupportType, Allocator>;
350
351} // namespace ddc
friend class ChunkSpan
auto operator[](DiscreteElement< QueryDDims... > const &slice_spec) const
Slice out some dimensions.
Definition chunk.hpp:157
char const * label() const
Returns the label of the Chunk.
Definition chunk.hpp:258
auto operator[](DiscreteDomain< QueryDDims... > const &odomain) const
Slice out some dimensions.
Definition chunk.hpp:171
const_allocation_mdspan_type allocation_mdspan() const
Provide a mdspan on the memory allocation.
Definition chunk.hpp:282
element_type & operator()(DVects const &... dvects) noexcept
Element access using a list of DiscreteVector.
Definition chunk.hpp:245
ElementType const * data_handle() const
Access to the underlying allocation pointer.
Definition chunk.hpp:266
auto allocation_kokkos_view()
Provide an unmanaged Kokkos::View on the memory allocation.
Definition chunk.hpp:298
auto allocation_kokkos_view() const
Provide an unmanaged Kokkos::View on the memory allocation.
Definition chunk.hpp:314
Chunk(SupportType const &domain, Allocator allocator=Allocator())
Construct a Chunk on a domain with uninitialized values.
Definition chunk.hpp:104
Chunk & operator=(Chunk const &other)=delete
Deleted: use deepcopy instead.
allocation_mdspan_type allocation_mdspan()
Provide a mdspan on the memory allocation.
Definition chunk.hpp:290
ElementType * data_handle()
Access to the underlying allocation pointer.
Definition chunk.hpp:274
element_type const & operator()(DVects const &... dvects) const noexcept
Element access using a list of DiscreteVector.
Definition chunk.hpp:209
view_type span_cview() const
Definition chunk.hpp:327
Chunk(Chunk const &other)=delete
Deleted: use deepcopy instead.
~Chunk() noexcept
Definition chunk.hpp:124
Chunk(std::string const &label, SupportType const &domain, Allocator allocator=Allocator())
Construct a labeled Chunk on a domain with uninitialized values.
Definition chunk.hpp:93
element_type & operator()(DElems const &... delems) noexcept
Element access using a list of DiscreteElement.
Definition chunk.hpp:226
Chunk()=default
Empty Chunk.
Chunk & operator=(Chunk &&other) noexcept
Move-assigns a new value to this field.
Definition chunk.hpp:138
Chunk(Chunk &&other) noexcept
Constructs a new Chunk by move.
Definition chunk.hpp:115
friend class Chunk
Definition chunk.hpp:81
span_type span_view()
Definition chunk.hpp:337
view_type span_view() const
Definition chunk.hpp:332
element_type const & operator()(DElems const &... delems) const noexcept
Element access using a list of DiscreteElement.
Definition chunk.hpp:190
auto operator[](DiscreteDomain< QueryDDims... > const &odomain)
Slice out some dimensions.
Definition chunk.hpp:178
auto operator[](DiscreteElement< QueryDDims... > const &slice_spec)
Slice out some dimensions.
Definition chunk.hpp:164
friend class DiscreteDomain
The top-level namespace of DDC.
constexpr bool enable_chunk< Chunk< ElementType, SupportType, Allocator > >
Definition chunk.hpp:28
Chunk(SupportType const &, Allocator) -> Chunk< typename Allocator::value_type, SupportType, Allocator >
Chunk(std::string const &, SupportType const &, Allocator) -> Chunk< typename Allocator::value_type, SupportType, Allocator >