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