DDC 0.0.0

a discrete domain computation library

discrete_element.hpp
1// SPDX-License-Identifier: MIT
2
3#pragma once
4
5#include <array>
6#include <cstddef>
7#include <ostream>
8#include <type_traits>
9#include <utility>
10
11#include "ddc/coordinate.hpp"
12#include "ddc/detail/macros.hpp"
13#include "ddc/detail/type_seq.hpp"
14#include "ddc/discrete_vector.hpp"
15
16namespace ddc {
17
18template <class...>
19class DiscreteElement;
20
21template <class T>
22struct IsDiscreteElement : std::false_type
23{
24};
25
26template <class... Tags>
27struct IsDiscreteElement<DiscreteElement<Tags...>> : std::true_type
28{
29};
30
31template <class T>
32inline constexpr bool is_discrete_element_v = IsDiscreteElement<T>::value;
33
34
35namespace detail {
36
37template <class... Tags>
38struct ToTypeSeq<DiscreteElement<Tags...>>
39{
40 using type = TypeSeq<Tags...>;
41};
42
43} // namespace detail
44
45/** A DiscreteCoordElement is a scalar that identifies an element of the discrete dimension
46 */
47using DiscreteElementType = std::size_t;
48
49template <class Tag>
50KOKKOS_FUNCTION constexpr DiscreteElementType const& uid(DiscreteElement<Tag> const& tuple) noexcept
51{
52 return tuple.uid();
53}
54
55template <class Tag>
56KOKKOS_FUNCTION constexpr DiscreteElementType& uid(DiscreteElement<Tag>& tuple) noexcept
57{
58 return tuple.uid();
59}
60
61template <class QueryTag, class... Tags>
62KOKKOS_FUNCTION constexpr DiscreteElementType const& uid(
63 DiscreteElement<Tags...> const& tuple) noexcept
64{
65 return tuple.template uid<QueryTag>();
66}
67
68template <class QueryTag, class... Tags>
69KOKKOS_FUNCTION constexpr DiscreteElementType& uid(DiscreteElement<Tags...>& tuple) noexcept
70{
71 return tuple.template uid<QueryTag>();
72}
73
74template <class QueryTag, class... Tags>
75KOKKOS_FUNCTION constexpr DiscreteElementType const& uid_or(
76 DiscreteElement<Tags...> const& tuple,
77 DiscreteElementType const& default_value) noexcept
78{
79 return tuple.template uid_or<QueryTag>(default_value);
80}
81
82template <class... QueryTags, class... Tags>
83KOKKOS_FUNCTION constexpr DiscreteElement<QueryTags...> select(
84 DiscreteElement<Tags...> const& arr) noexcept
85{
86 return DiscreteElement<QueryTags...>(arr);
87}
88
89template <class... QueryTags, class... Tags>
90KOKKOS_FUNCTION constexpr DiscreteElement<QueryTags...> select(
91 DiscreteElement<Tags...>&& arr) noexcept
92{
93 return DiscreteElement<QueryTags...>(std::move(arr));
94}
95
96/// Returns a reference towards the DiscreteElement that contains the QueryTag
97template <
98 class QueryTag,
99 class HeadDElem,
100 class... TailDElems,
101 std::enable_if_t<
102 is_discrete_element_v<HeadDElem> && (is_discrete_element_v<TailDElems> && ...),
103 int> = 1>
104KOKKOS_FUNCTION constexpr auto const& take(HeadDElem const& head, TailDElems const&... tail)
105{
106 DDC_IF_NVCC_THEN_PUSH_AND_SUPPRESS(implicit_return_from_non_void_function)
107 if constexpr (type_seq_contains_v<detail::TypeSeq<QueryTag>, to_type_seq_t<HeadDElem>>) {
108 static_assert(
109 (!type_seq_contains_v<detail::TypeSeq<QueryTag>, to_type_seq_t<TailDElems>> && ...),
110 "ERROR: tag redundant");
111 return head;
112 } else {
113 static_assert(sizeof...(TailDElems) > 0, "ERROR: tag not found");
114 return take<QueryTag>(tail...);
115 }
116 DDC_IF_NVCC_THEN_POP
117}
118
119namespace detail {
120
121/// Returns a reference to the underlying `std::array`
122template <class... Tags>
123KOKKOS_FUNCTION constexpr std::array<DiscreteElementType, sizeof...(Tags)>& array(
124 DiscreteElement<Tags...>& v) noexcept
125{
126 return v.m_values;
127}
128
129/// Returns a reference to the underlying `std::array`
130template <class... Tags>
131KOKKOS_FUNCTION constexpr std::array<DiscreteElementType, sizeof...(Tags)> const& array(
132 DiscreteElement<Tags...> const& v) noexcept
133{
134 return v.m_values;
135}
136
137} // namespace detail
138
139/** A DiscreteElement identifies an element of the discrete dimension
140 *
141 * Each one is tagged by its associated dimensions.
142 */
143template <class... Tags>
144class DiscreteElement
145{
146 using tags_seq = detail::TypeSeq<Tags...>;
147
148 friend KOKKOS_FUNCTION constexpr std::array<DiscreteElementType, sizeof...(Tags)>& detail::
149 array<Tags...>(DiscreteElement<Tags...>& v) noexcept;
150
151 friend KOKKOS_FUNCTION constexpr std::array<DiscreteElementType, sizeof...(Tags)> const&
152 detail::array<Tags...>(DiscreteElement<Tags...> const& v) noexcept;
153
154private:
155 std::array<DiscreteElementType, sizeof...(Tags)> m_values;
156
157public:
158 using value_type = DiscreteElementType;
159
160 static KOKKOS_FUNCTION constexpr std::size_t size() noexcept
161 {
162 return sizeof...(Tags);
163 }
164
165public:
166 KOKKOS_DEFAULTED_FUNCTION constexpr DiscreteElement() = default;
167
168 KOKKOS_DEFAULTED_FUNCTION constexpr DiscreteElement(DiscreteElement const&) = default;
169
170 KOKKOS_DEFAULTED_FUNCTION constexpr DiscreteElement(DiscreteElement&&) = default;
171
172 template <class... DElems, class = std::enable_if_t<(is_discrete_element_v<DElems> && ...)>>
173 explicit KOKKOS_FUNCTION constexpr DiscreteElement(DElems const&... delems) noexcept
174 : m_values {take<Tags>(delems...).template uid<Tags>()...}
175 {
176 }
177
178 template <
179 class... Params,
180 class = std::enable_if_t<(!is_discrete_element_v<Params> && ...)>,
181 class = std::enable_if_t<(std::is_integral_v<Params> && ...)>,
182 class = std::enable_if_t<sizeof...(Params) == sizeof...(Tags)>>
183 explicit KOKKOS_FUNCTION constexpr DiscreteElement(Params const&... params) noexcept
184 : m_values {static_cast<value_type>(params)...}
185 {
186 }
187
188 KOKKOS_DEFAULTED_FUNCTION ~DiscreteElement() = default;
189
190 KOKKOS_DEFAULTED_FUNCTION DiscreteElement& operator=(DiscreteElement const& other) = default;
191
192 KOKKOS_DEFAULTED_FUNCTION DiscreteElement& operator=(DiscreteElement&& other) = default;
193
194 template <class... OTags>
195 KOKKOS_FUNCTION constexpr DiscreteElement& operator=(
196 DiscreteElement<OTags...> const& other) noexcept
197 {
198 m_values = other.m_values;
199 return *this;
200 }
201
202 template <class... OTags>
203 KOKKOS_FUNCTION constexpr DiscreteElement& operator=(DiscreteElement<OTags...>&& other) noexcept
204 {
205 m_values = std::move(other.m_values);
206 return *this;
207 }
208
209 template <class QueryTag>
210 KOKKOS_FUNCTION constexpr value_type const& uid_or(value_type const& default_value) const&
211 {
212 DDC_IF_NVCC_THEN_PUSH_AND_SUPPRESS(implicit_return_from_non_void_function)
213 if constexpr (in_tags_v<QueryTag, tags_seq>) {
214 return m_values[type_seq_rank_v<QueryTag, tags_seq>];
215 } else {
216 return default_value;
217 }
218 DDC_IF_NVCC_THEN_POP
219 }
220
221 template <class QueryTag>
222 KOKKOS_FUNCTION constexpr value_type& uid() noexcept
223 {
224 using namespace detail;
225 static_assert(in_tags_v<QueryTag, tags_seq>, "requested Tag absent from DiscreteElement");
226 return m_values[type_seq_rank_v<QueryTag, tags_seq>];
227 }
228
229 template <class QueryTag>
230 KOKKOS_FUNCTION constexpr value_type const& uid() const noexcept
231 {
232 using namespace detail;
233 static_assert(in_tags_v<QueryTag, tags_seq>, "requested Tag absent from DiscreteElement");
234 return m_values[type_seq_rank_v<QueryTag, tags_seq>];
235 }
236
237 template <std::size_t N = sizeof...(Tags)>
238 KOKKOS_FUNCTION constexpr std::enable_if_t<N == 1, value_type&> uid() noexcept
239 {
240 return m_values[0];
241 }
242
243 template <std::size_t N = sizeof...(Tags)>
244 KOKKOS_FUNCTION constexpr std::enable_if_t<N == 1, value_type const&> uid() const noexcept
245 {
246 return m_values[0];
247 }
248
249 template <std::size_t N = sizeof...(Tags), class = std::enable_if_t<N == 1>>
250 KOKKOS_FUNCTION constexpr DiscreteElement& operator++()
251 {
252 ++m_values[0];
253 return *this;
254 }
255
256 template <std::size_t N = sizeof...(Tags), class = std::enable_if_t<N == 1>>
257 KOKKOS_FUNCTION constexpr DiscreteElement operator++(int)
258 {
259 DiscreteElement const tmp = *this;
260 ++m_values[0];
261 return tmp;
262 }
263
264 template <std::size_t N = sizeof...(Tags), class = std::enable_if_t<N == 1>>
265 KOKKOS_FUNCTION constexpr DiscreteElement& operator--()
266 {
267 ++m_values[0];
268 return *this;
269 }
270
271 template <std::size_t N = sizeof...(Tags), class = std::enable_if_t<N == 1>>
272 KOKKOS_FUNCTION constexpr DiscreteElement operator--(int)
273 {
274 DiscreteElement const tmp = *this;
275 ++m_values[0];
276 return tmp;
277 }
278
279 template <class... OTags>
280 KOKKOS_FUNCTION constexpr DiscreteElement& operator+=(DiscreteVector<OTags...> const& rhs)
281 {
282 static_assert(((type_seq_contains_v<detail::TypeSeq<OTags>, tags_seq>)&&...));
283 ((m_values[type_seq_rank_v<OTags, tags_seq>] += rhs.template get<OTags>()), ...);
284 return *this;
285 }
286
287 template <
288 class IntegralType,
289 std::size_t N = sizeof...(Tags),
290 class = std::enable_if_t<N == 1>,
291 class = std::enable_if_t<std::is_integral_v<IntegralType>>>
292 KOKKOS_FUNCTION constexpr DiscreteElement& operator+=(IntegralType const& rhs)
293 {
294 m_values[0] += rhs;
295 return *this;
296 }
297
298 template <class... OTags>
299 KOKKOS_FUNCTION constexpr DiscreteElement& operator-=(DiscreteVector<OTags...> const& rhs)
300 {
301 static_assert(((type_seq_contains_v<detail::TypeSeq<OTags>, tags_seq>)&&...));
302 ((m_values[type_seq_rank_v<OTags, tags_seq>] -= rhs.template get<OTags>()), ...);
303 return *this;
304 }
305
306 template <
307 class IntegralType,
308 std::size_t N = sizeof...(Tags),
309 class = std::enable_if_t<N == 1>,
310 class = std::enable_if_t<std::is_integral_v<IntegralType>>>
311 KOKKOS_FUNCTION constexpr DiscreteElement& operator-=(IntegralType const& rhs)
312 {
313 m_values[0] -= rhs;
314 return *this;
315 }
316};
317
318inline std::ostream& operator<<(std::ostream& out, DiscreteElement<> const&)
319{
320 out << "()";
321 return out;
322}
323
324template <class Head, class... Tags>
325std::ostream& operator<<(std::ostream& out, DiscreteElement<Head, Tags...> const& arr)
326{
327 out << "(";
328 out << uid<Head>(arr);
329 ((out << ", " << uid<Tags>(arr)), ...);
330 out << ")";
331 return out;
332}
333
334
335template <class... Tags, class... OTags>
336KOKKOS_FUNCTION constexpr bool operator==(
337 DiscreteElement<Tags...> const& lhs,
338 DiscreteElement<OTags...> const& rhs) noexcept
339{
340 return ((lhs.template uid<Tags>() == rhs.template uid<Tags>()) && ...);
341}
342
343template <class... Tags, class... OTags>
344KOKKOS_FUNCTION constexpr bool operator!=(
345 DiscreteElement<Tags...> const& lhs,
346 DiscreteElement<OTags...> const& rhs) noexcept
347{
348 return !(lhs == rhs);
349}
350
351template <class Tag>
352KOKKOS_FUNCTION constexpr bool operator<(
353 DiscreteElement<Tag> const& lhs,
354 DiscreteElement<Tag> const& rhs)
355{
356 return lhs.uid() < rhs.uid();
357}
358
359template <class Tag>
360KOKKOS_FUNCTION constexpr bool operator<=(
361 DiscreteElement<Tag> const& lhs,
362 DiscreteElement<Tag> const& rhs)
363{
364 return lhs.uid() <= rhs.uid();
365}
366
367template <class Tag>
368KOKKOS_FUNCTION constexpr bool operator>(
369 DiscreteElement<Tag> const& lhs,
370 DiscreteElement<Tag> const& rhs)
371{
372 return lhs.uid() > rhs.uid();
373}
374
375template <class Tag>
376KOKKOS_FUNCTION constexpr bool operator>=(
377 DiscreteElement<Tag> const& lhs,
378 DiscreteElement<Tag> const& rhs)
379{
380 return lhs.uid() >= rhs.uid();
381}
382
383/// right external binary operators: +, -
384
385template <class... Tags, class... OTags>
386KOKKOS_FUNCTION constexpr DiscreteElement<Tags...> operator+(
387 DiscreteElement<Tags...> const& lhs,
388 DiscreteVector<OTags...> const& rhs)
389{
390 using detail::TypeSeq;
391 static_assert(((type_seq_contains_v<TypeSeq<OTags>, TypeSeq<Tags...>>)&&...));
392 DiscreteElement<Tags...> result(lhs);
393 result += rhs;
394 return result;
395}
396
397template <
398 class Tag,
399 class IntegralType,
400 class = std::enable_if_t<std::is_integral_v<IntegralType>>,
401 class = std::enable_if_t<!is_discrete_vector_v<IntegralType>>>
402KOKKOS_FUNCTION constexpr DiscreteElement<Tag> operator+(
403 DiscreteElement<Tag> const& lhs,
404 IntegralType const& rhs)
405{
406 return DiscreteElement<Tag>(uid<Tag>(lhs) + rhs);
407}
408
409template <class... Tags, class... OTags>
410KOKKOS_FUNCTION constexpr DiscreteElement<Tags...> operator-(
411 DiscreteElement<Tags...> const& lhs,
412 DiscreteVector<OTags...> const& rhs)
413{
414 using detail::TypeSeq;
415 static_assert(((type_seq_contains_v<TypeSeq<OTags>, TypeSeq<Tags...>>)&&...));
416 DiscreteElement<Tags...> result(lhs);
417 result -= rhs;
418 return result;
419}
420
421template <
422 class Tag,
423 class IntegralType,
424 class = std::enable_if_t<std::is_integral_v<IntegralType>>,
425 class = std::enable_if_t<!is_discrete_vector_v<IntegralType>>>
426KOKKOS_FUNCTION constexpr DiscreteElement<Tag> operator-(
427 DiscreteElement<Tag> const& lhs,
428 IntegralType const& rhs)
429{
430 return DiscreteElement<Tag>(uid<Tag>(lhs) - rhs);
431}
432
433/// binary operator: -
434
435template <class... Tags, class... OTags>
436KOKKOS_FUNCTION constexpr DiscreteVector<Tags...> operator-(
437 DiscreteElement<Tags...> const& lhs,
438 DiscreteElement<OTags...> const& rhs)
439{
440 static_assert(type_seq_same_v<detail::TypeSeq<Tags...>, detail::TypeSeq<OTags...>>);
441 return DiscreteVector<Tags...>((uid<Tags>(lhs) - uid<Tags>(rhs))...);
442}
443
444// Gives access to the type of the coordinates of a discrete element
445// Example usage : "using Coords = coordinate_of_t<DElem>;"
446template <class... DDims>
447struct coordinate_of<ddc::DiscreteElement<DDims...>>
448{
449 // maybe a static_assert on DDims ?
450 using type = Coordinate<typename DDims::continuous_dimension_type...>;
451};
452
453} // namespace ddc
KOKKOS_FUNCTION constexpr DiscreteElement & operator+=(DiscreteVector< OTags... > const &rhs)
Definition: discrete_element.hpp:280
KOKKOS_FUNCTION constexpr value_type const & uid() const noexcept
Definition: discrete_element.hpp:230
KOKKOS_FUNCTION constexpr value_type & uid() noexcept
Definition: discrete_element.hpp:222
KOKKOS_DEFAULTED_FUNCTION ~DiscreteElement()=default
KOKKOS_FUNCTION constexpr DiscreteElement & operator++()
Definition: discrete_element.hpp:250
KOKKOS_FUNCTION constexpr DiscreteElement & operator=(DiscreteElement< OTags... > const &other) noexcept
Definition: discrete_element.hpp:195
KOKKOS_FUNCTION constexpr DiscreteElement & operator-=(IntegralType const &rhs)
Definition: discrete_element.hpp:311
KOKKOS_DEFAULTED_FUNCTION constexpr DiscreteElement(DiscreteElement const &)=default
KOKKOS_FUNCTION constexpr DiscreteElement(DElems const &... delems) noexcept
Definition: discrete_element.hpp:173
KOKKOS_FUNCTION constexpr value_type const & uid_or(value_type const &default_value) const &
Definition: discrete_element.hpp:210
KOKKOS_FUNCTION constexpr DiscreteElement & operator-=(DiscreteVector< OTags... > const &rhs)
Definition: discrete_element.hpp:299
KOKKOS_FUNCTION constexpr DiscreteElement operator++(int)
Definition: discrete_element.hpp:257
KOKKOS_DEFAULTED_FUNCTION constexpr DiscreteElement()=default
KOKKOS_FUNCTION constexpr DiscreteElement & operator--()
Definition: discrete_element.hpp:265
KOKKOS_DEFAULTED_FUNCTION DiscreteElement & operator=(DiscreteElement const &other)=default
KOKKOS_FUNCTION constexpr DiscreteElement operator--(int)
Definition: discrete_element.hpp:272
KOKKOS_FUNCTION constexpr std::enable_if_t< N==1, value_type & > uid() noexcept
Definition: discrete_element.hpp:238
KOKKOS_FUNCTION constexpr DiscreteElement & operator=(DiscreteElement< OTags... > &&other) noexcept
Definition: discrete_element.hpp:203
static KOKKOS_FUNCTION constexpr std::size_t size() noexcept
Definition: discrete_element.hpp:160
KOKKOS_FUNCTION constexpr std::enable_if_t< N==1, value_type const & > uid() const noexcept
Definition: discrete_element.hpp:244
KOKKOS_FUNCTION constexpr DiscreteElement & operator+=(IntegralType const &rhs)
Definition: discrete_element.hpp:292
KOKKOS_DEFAULTED_FUNCTION DiscreteElement & operator=(DiscreteElement &&other)=default
KOKKOS_FUNCTION constexpr DiscreteElement(Params const &... params) noexcept
Definition: discrete_element.hpp:183
KOKKOS_DEFAULTED_FUNCTION constexpr DiscreteElement(DiscreteElement &&)=default
Definition: aligned_allocator.hpp:9
KOKKOS_FUNCTION constexpr bool operator<(DiscreteElement< Tag > const &lhs, DiscreteElement< Tag > const &rhs)
Definition: discrete_element.hpp:352
KOKKOS_FUNCTION constexpr DiscreteElementType const & uid_or(DiscreteElement< Tags... > const &tuple, DiscreteElementType const &default_value) noexcept
Definition: discrete_element.hpp:75
KOKKOS_FUNCTION constexpr bool operator==(DiscreteElement< Tags... > const &lhs, DiscreteElement< OTags... > const &rhs) noexcept
Definition: discrete_element.hpp:336
KOKKOS_FUNCTION constexpr DiscreteElement< QueryTags... > select(DiscreteElement< Tags... > &&arr) noexcept
Definition: discrete_element.hpp:90
KOKKOS_FUNCTION constexpr DiscreteElement< QueryTags... > select(DiscreteElement< Tags... > const &arr) noexcept
Definition: discrete_element.hpp:83
KOKKOS_FUNCTION constexpr auto const & take(HeadDElem const &head, TailDElems const &... tail)
Returns a reference towards the DiscreteElement that contains the QueryTag.
Definition: discrete_element.hpp:104
KOKKOS_FUNCTION constexpr DiscreteElement< Tag > operator-(DiscreteElement< Tag > const &lhs, IntegralType const &rhs)
Definition: discrete_element.hpp:426
KOKKOS_FUNCTION constexpr DiscreteVector< Tags... > operator-(DiscreteElement< Tags... > const &lhs, DiscreteElement< OTags... > const &rhs)
binary operator: -
Definition: discrete_element.hpp:436
KOKKOS_FUNCTION constexpr DiscreteElementType const & uid(DiscreteElement< Tag > const &tuple) noexcept
Definition: discrete_element.hpp:50
KOKKOS_FUNCTION constexpr DiscreteElement< Tags... > operator+(DiscreteElement< Tags... > const &lhs, DiscreteVector< OTags... > const &rhs)
right external binary operators: +, -
Definition: discrete_element.hpp:386
constexpr bool is_discrete_element_v
Definition: discrete_element.hpp:32
KOKKOS_FUNCTION constexpr bool operator>=(DiscreteElement< Tag > const &lhs, DiscreteElement< Tag > const &rhs)
Definition: discrete_element.hpp:376
KOKKOS_FUNCTION constexpr bool operator<=(DiscreteElement< Tag > const &lhs, DiscreteElement< Tag > const &rhs)
Definition: discrete_element.hpp:360
KOKKOS_FUNCTION constexpr DiscreteElementType & uid(DiscreteElement< Tags... > &tuple) noexcept
Definition: discrete_element.hpp:69
KOKKOS_FUNCTION constexpr bool operator>(DiscreteElement< Tag > const &lhs, DiscreteElement< Tag > const &rhs)
Definition: discrete_element.hpp:368
KOKKOS_FUNCTION constexpr DiscreteElement< Tag > operator+(DiscreteElement< Tag > const &lhs, IntegralType const &rhs)
Definition: discrete_element.hpp:402
KOKKOS_FUNCTION constexpr DiscreteElementType & uid(DiscreteElement< Tag > &tuple) noexcept
Definition: discrete_element.hpp:56
KOKKOS_FUNCTION constexpr DiscreteElement< Tags... > operator-(DiscreteElement< Tags... > const &lhs, DiscreteVector< OTags... > const &rhs)
Definition: discrete_element.hpp:410
KOKKOS_FUNCTION constexpr DiscreteElementType const & uid(DiscreteElement< Tags... > const &tuple) noexcept
Definition: discrete_element.hpp:62
KOKKOS_FUNCTION constexpr bool operator!=(DiscreteElement< Tags... > const &lhs, DiscreteElement< OTags... > const &rhs) noexcept
Definition: discrete_element.hpp:344
Definition: discrete_element.hpp:23