IPPL API Reference
Independent Parallel Particle Layer C++ API
Loading...
Searching...
No Matches
TypeUtils.h
1//
2// Type Utilities
3// Metaprogramming utility functions for type manipulation
4//
5
6#ifndef IPPL_TYPE_UTILS_H
7#define IPPL_TYPE_UTILS_H
8
9#include <Kokkos_Core.hpp>
10
11#include "Types/Variant.h"
12
13#include "Utility/IpplException.h"
14
15namespace ippl {
16 namespace detail {
17
24 template <typename Check, typename... Collection>
25 struct IsUnique {
26 constexpr static bool enable = !std::disjunction_v<std::is_same<Check, Collection>...>;
27 typedef Check type;
28 };
29
38 template <template <typename> class Wrapper>
39 struct WrapUnique {
40 template <typename Check, typename... Collection>
41 struct Verifier {
42 typedef Wrapper<Check> type;
43 constexpr static bool enable =
44 !std::disjunction_v<std::is_same<type, Collection>...>;
45 };
46 };
47
55 template <bool B, typename T>
56 using ConditionalType = std::conditional_t<B, T, void>;
57
65 template <typename Type, typename...>
66 struct IsEnabled {
67 constexpr static bool enable = !std::is_void_v<Type>;
68 typedef Type type;
69 };
70
74 template <typename, typename, template <typename...> class Verifier = IsUnique>
76
80 template <template <typename...> class Verifier>
81 struct ConstructVariant<std::variant<>, std::variant<>, Verifier> {
82 typedef std::variant<> type;
83 };
84
89 template <typename... T, template <typename...> class Verifier>
90 struct ConstructVariant<std::variant<>, std::variant<T...>, Verifier> {
91 typedef std::variant<T...> type;
92 };
93
119 template <typename Next, typename... ToAdd, typename... Added,
120 template <typename...> class Verifier>
121 struct ConstructVariant<std::variant<Next, ToAdd...>, std::variant<Added...>, Verifier> {
122 // Convenience aliases
123 template <bool B, class T, class F>
124 using cond = std::conditional_t<B, T, F>;
125 template <typename... T>
126 using variant = std::variant<T...>;
127
128 using Check = Verifier<Next, Added...>;
129
130 typedef cond<
131 Check::enable,
132 // The verifier has indicated that this type should be added
133 typename ConstructVariant<variant<ToAdd...>,
134 variant<typename Check::type, Added...>, Verifier>::type,
135 // The verifier has indicated that the type should not be added
136 typename ConstructVariant<variant<ToAdd...>, variant<Added...>, Verifier>::type>
137 type;
138 };
139
145 template <typename... Types>
146 using VariantFromConditionalTypes =
147 typename ConstructVariant<std::variant<Types...>, std::variant<>, IsEnabled>::type;
148
153 template <typename... Types>
154 using VariantFromUniqueTypes =
155 typename ConstructVariant<std::variant<Types...>, std::variant<>, IsUnique>::type;
156
166 template <template <typename...> class Verifier, typename... Types>
167 using VariantWithVerifier =
168 typename ConstructVariant<std::variant<Types...>, std::variant<>, Verifier>::type;
169
176 template <template <typename...> class Type, typename Pack>
177 struct Forward;
178
182 template <template <typename...> class Type, typename... Spaces>
183 struct Forward<Type, std::variant<Spaces...>> {
184 using type = Type<Spaces...>;
185 };
186
190 template <template <typename...> class Type, typename T, typename... Properties>
191 struct Forward<Type, Kokkos::View<T, Properties...>> {
192 using type = Type<Properties...>;
193 };
194
202 template <template <typename...> class Type, typename View>
204 using view_type = typename View::uniform_type;
205 using type = typename Forward<Type, view_type>::type;
206 };
207
211 template <template <typename...> class Type>
213 using unique_memory_spaces = VariantFromUniqueTypes<
214 Kokkos::HostSpace, Kokkos::SharedSpace, Kokkos::SharedHostPinnedSpace
215#ifdef KOKKOS_ENABLE_CUDA
216 ,
217 Kokkos::CudaSpace, Kokkos::CudaHostPinnedSpace, Kokkos::CudaUVMSpace
218#endif
219#ifdef KOKKOS_ENABLE_HIP
220 ,
221 Kokkos::HIPSpace, Kokkos::HIPHostPinnedSpace, Kokkos::HIPManagedSpace
222#endif
223#ifdef KOKKOS_ENABLE_SYCL
224 ,
225 Kokkos::Experimental::SYCLDeviceUSMSpace, Kokkos::Experimental::SYCLHostUSMSpace,
226 Kokkos::Experimental::SYCLSharedUSMSpace
227#endif
228 >;
229
230 using unique_exec_spaces = VariantFromUniqueTypes<Kokkos::DefaultExecutionSpace
231#ifdef KOKKOS_ENABLE_OPENMP
232 ,
233 Kokkos::OpenMP
234#endif
235#ifdef KOKKOS_ENABLE_OPENMPTARGET
236 ,
237 Kokkos::OpenMPTarget
238#endif
239#ifdef KOKKOS_ENABLE_THREADS
240 ,
241 Kokkos::Threads
242#endif
243#ifdef KOKKOS_ENABLE_SERIAL
244 ,
245 Kokkos::Serial
246#endif
247#ifdef KOKKOS_ENABLE_CUDA
248 ,
249 Kokkos::Cuda
250#endif
251#ifdef KOKKOS_ENABLE_HIP
252 ,
253 Kokkos::HIP
254#endif
255#ifdef KOKKOS_ENABLE_SYCL
256 ,
257 Kokkos::Experimental::SYCL
258#endif
259#ifdef KOKKOS_ENABLE_HPX
260 ,
261 Kokkos::HPX
262#endif
263 >;
264
265 using memory_spaces_type = typename Forward<Type, unique_memory_spaces>::type;
266 using exec_spaces_type = typename Forward<Type, unique_exec_spaces>::type;
267 };
268
275 template <template <typename> class Type, typename... Spaces>
277 template <typename T, typename... Ts>
278 using Verifier = typename WrapUnique<Type>::template Verifier<T, Ts...>;
279
280 using Types = VariantWithVerifier<Verifier, Spaces...>;
281
282 std::array<Types, sizeof...(Spaces)> elements_m;
283
289 template <typename Space, unsigned Idx = 0>
290 constexpr static unsigned spaceToIndex() {
291 static_assert(Idx < sizeof...(Spaces));
292 if constexpr (std::is_same_v<Space,
293 std::tuple_element_t<Idx, std::tuple<Spaces...>>>) {
294 return Idx;
295 } else {
296 return spaceToIndex<Space, Idx + 1>();
297 }
298 // Silences incorrect nvcc warning: missing return statement at end of non-void
299 // function
300 throw IpplException("detail::MultispaceContainer::spaceToIndex",
301 "Unreachable state");
302 }
303
307 template <typename Space>
308 void initElements() {
309 elements_m[spaceToIndex<Space>()] = Type<Space>{};
310 }
311
316 template <typename MemorySpace, typename Filter,
317 std::enable_if_t<std::is_null_pointer_v<std::decay_t<Filter>>, int> = 0>
318 constexpr bool copyToSpace(Filter&&) {
319 return true;
320 }
321
322 template <typename MemorySpace, typename Filter,
323 std::enable_if_t<!std::is_null_pointer_v<std::decay_t<Filter>>, int> = 0>
324 bool copyToSpace(Filter&& predicate) {
325 return predicate.template operator()<MemorySpace>();
326 }
327
328 public:
329 MultispaceContainer() { (initElements<Spaces>(), ...); }
330
341 template <typename DataType, typename Filter = std::nullptr_t>
342 MultispaceContainer(const DataType& data, Filter&& predicate = nullptr)
344 using space = typename DataType::memory_space;
345 static_assert(std::is_same_v<DataType, Type<space>>);
346
347 elements_m[spaceToIndex<space>()] = data;
348 copyToOtherSpaces<space>(predicate);
349 }
350
358 template <typename Space, typename Filter = std::nullptr_t>
359 void copyToOtherSpaces(Filter&& predicate = nullptr) {
360 forAll([&]<typename DataType>(DataType& dst) {
361 using memory_space = typename DataType::memory_space;
362 if constexpr (!std::is_same_v<Space, memory_space>) {
363 if (copyToSpace<memory_space>(predicate)) {
364 dst = Kokkos::create_mirror_view_and_copy(
365 Kokkos::view_alloc(memory_space{}, Kokkos::WithoutInitializing),
366 get<Space>());
367 }
368 }
369 });
370 }
371
377 template <typename Space>
378 const Type<Space>& get() const {
379 return std::get<Type<Space>>(elements_m[spaceToIndex<Space>()]);
380 }
381
382 template <typename Space>
383 Type<Space>& get() {
384 return std::get<Type<Space>>(elements_m[spaceToIndex<Space>()]);
385 }
386
392 template <typename Functor>
393 void forAll(Functor&& f) const {
394 (f(get<Spaces>()), ...);
395 }
396
397 template <typename Functor>
398 void forAll(Functor&& f) {
399 (f(get<Spaces>()), ...);
400 }
401 };
402
407 template <template <typename> class Type>
409 template <typename... Spaces>
410 using container_type = MultispaceContainer<Type, Spaces...>;
411
412 using type = typename TypeForAllSpaces<container_type>::memory_spaces_type;
413
414 // Static factory function that takes a lambda to initialize each memory space
415 template <typename Functor>
416 static type createContainer(Functor&& initFunc) {
417 return type{std::forward<Functor>(initFunc)};
418 }
419 };
420
427 template <typename Functor>
428 void runForAllSpaces(Functor&& f) {
429 using all_spaces = typename TypeForAllSpaces<std::variant>::memory_spaces_type;
430 auto runner = [&]<typename... Spaces>(const std::variant<Spaces...>&) {
431 (f.template operator()<Spaces>(), ...);
432 };
433 runner(all_spaces{});
434 }
435 } // namespace detail
436} // namespace ippl
437
438#endif
Definition IpplException.h:6
Definition TypeUtils.h:276
MultispaceContainer(const DataType &data, Filter &&predicate=nullptr)
Definition TypeUtils.h:342
void forAll(Functor &&f) const
Definition TypeUtils.h:393
const Type< Space > & get() const
Definition TypeUtils.h:378
void copyToOtherSpaces(Filter &&predicate=nullptr)
Definition TypeUtils.h:359
Definition Archive.h:20
Definition TypeUtils.h:75
Definition TypeUtils.h:408
Definition TypeUtils.h:203
Definition TypeUtils.h:177
Definition TypeUtils.h:66
Definition TypeUtils.h:25
Definition TypeUtils.h:212
Definition TypeUtils.h:41
Definition TypeUtils.h:39