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