20#include <Kokkos_Core.hpp>
22#include "detail/dual_discretization.hpp"
23#include "detail/macros.hpp"
27#if defined(KOKKOS_ENABLE_CUDA)
29#elif defined(KOKKOS_ENABLE_HIP)
30# include <hip/hip_runtime.h>
33#if defined(KOKKOS_ENABLE_CUDA) || defined(KOKKOS_ENABLE_HIP)
34# define DDC_DETAIL_DEVICE_THROW_ON_ERROR(val)
35 ddc::detail::device_throw_on_error((val), #val, __FILE__, __LINE__)
42#if defined(KOKKOS_ENABLE_CUDA)
43void device_throw_on_error(
44 cudaError_t
const err,
45 char const*
const func,
46 char const*
const file,
48#elif defined(KOKKOS_ENABLE_HIP)
49void device_throw_on_error(
51 char const*
const func,
52 char const*
const file,
56template <ddc::concepts::discrete_dimension DDim,
class MemorySpace>
57using ddim_impl_t = DDim::
template Impl<DDim, MemorySpace>;
73 alignas(T) Kokkos::Array<std::byte,
sizeof(T)> m_data;
79 return reinterpret_cast<T*>(m_data.data());
85 return *
reinterpret_cast<T*>(m_data.data());
91 return reinterpret_cast<T*>(m_data.data());
96extern std::optional<std::map<std::string, std::function<
void()>>> g_discretization_store;
99template <ddc::concepts::discrete_dimension DDim>
100inline std::optional<DualDiscretization<DDim>> g_discrete_space_dual;
102#if defined(KOKKOS_ENABLE_CUDA)
104template <ddc::concepts::discrete_dimension DDim>
105__constant__ GpuProxy<ddim_impl_t<DDim, GlobalVariableDeviceSpace>> g_discrete_space_device;
106#elif defined(KOKKOS_ENABLE_HIP)
109template <ddc::concepts::discrete_dimension DDim>
110__constant__ GpuProxy<ddim_impl_t<DDim, GlobalVariableDeviceSpace>> g_discrete_space_device;
111#elif defined(KOKKOS_ENABLE_SYCL)
113template <ddc::concepts::discrete_dimension DDim>
114SYCL_EXTERNAL
inline sycl::ext::oneapi::experimental::device_global<
115 GpuProxy<ddim_impl_t<DDim, GlobalVariableDeviceSpace>>>
116 g_discrete_space_device;
119void display_discretization_store(std::ostream& os);
121template <
class Tuple, std::size_t... Ids>
122auto extract_after(Tuple&& t, std::index_sequence<Ids...>)
124 return std::make_tuple(std::move(std::get<Ids + 1>(t))...);
130
131
132
133template <
concepts::discrete_dimension DDim,
class... Args>
137 !std::is_same_v<DDim,
typename DDim::discrete_dimension_type>,
138 "Discrete dimensions should inherit from the discretization, not use an alias");
139 if (detail::g_discrete_space_dual<DDim>) {
140 throw std::runtime_error(
"Discrete space function already initialized.");
142 detail::g_discrete_space_dual<DDim>.emplace(std::forward<Args>(args)...);
143 detail::g_discretization_store->emplace(
typeid(DDim).name(), []() {
144 detail::g_discrete_space_dual<DDim>.reset();
146#if defined(KOKKOS_ENABLE_CUDA)
147 DDC_DETAIL_DEVICE_THROW_ON_ERROR(cudaMemcpyToSymbol(
148 detail::g_discrete_space_device<DDim>,
149 &detail::g_discrete_space_dual<DDim>->get_device(),
150 sizeof(detail::g_discrete_space_dual<DDim>->get_device())));
151#elif defined(KOKKOS_ENABLE_HIP)
152 DDC_DETAIL_DEVICE_THROW_ON_ERROR(hipMemcpyToSymbol(
153 detail::g_discrete_space_device<DDim>,
154 &detail::g_discrete_space_dual<DDim>->get_device(),
155 sizeof(detail::g_discrete_space_dual<DDim>->get_device())));
156#elif defined(KOKKOS_ENABLE_SYCL)
157 Kokkos::DefaultExecutionSpace exec;
158 sycl::queue q = exec.sycl_queue();
159 q.memcpy(detail::g_discrete_space_device<DDim>,
160 &detail::g_discrete_space_dual<DDim>->get_device())
166
167
168
169
170template <
concepts::discrete_dimension DDim,
class DDimImpl,
class Arg0>
173 init_discrete_space<DDim>(std::move(std::get<0>(a)));
174 return std::get<1>(a);
178
179
180
181
182template <
concepts::discrete_dimension DDim,
class DDimImpl,
class Arg0,
class Arg1,
class... Args>
183std::tuple<Arg0, Arg1, Args...>
init_discrete_space(std::tuple<DDimImpl, Arg0, Arg1, Args...>&& a)
185 init_discrete_space<DDim>(std::move(std::get<0>(a)));
186 return detail::extract_after(std::move(a), std::index_sequence_for<Arg0, Arg1, Args...>());
190
191
192
193
194template <
concepts::discrete_dimension DDim>
197 return detail::g_discrete_space_dual<DDim>.has_value();
201
202
203
204
205
206template <
concepts::discrete_dimension DDim,
class MemorySpace = DDC_CURRENT_KOKKOS_SPACE>
207KOKKOS_FUNCTION detail::ddim_impl_t<DDim, MemorySpace>
const&
discrete_space()
210 if constexpr (std::is_same_v<MemorySpace, Kokkos::HostSpace>) {
211 KOKKOS_ASSERT(is_discrete_space_initialized<DDim>())
212 return detail::g_discrete_space_dual<DDim>->get_host();
214#if defined(KOKKOS_ENABLE_CUDA) || defined(KOKKOS_ENABLE_HIP)
215 else if constexpr (std::is_same_v<MemorySpace, detail::GlobalVariableDeviceSpace>) {
216 return *detail::g_discrete_space_device<DDim>;
218#elif defined(KOKKOS_ENABLE_SYCL)
219 else if constexpr (std::is_same_v<MemorySpace, detail::GlobalVariableDeviceSpace>) {
220 return *detail::g_discrete_space_device<DDim>.get();
224 static_assert(std::is_same_v<MemorySpace, MemorySpace>,
"Memory space not handled");
228template <
concepts::discrete_dimension DDim>
232 assert(is_discrete_space_initialized<DDim>());
233 return detail::g_discrete_space_dual<DDim>->get_host();
238#if defined(KOKKOS_ENABLE_CUDA) || defined(KOKKOS_ENABLE_HIP)
239# undef DDC_DETAIL_DEVICE_THROW_ON_ERROR
ScopeGuard & operator=(ScopeGuard const &x)=delete
ScopeGuard(int argc, char **&argv)
ScopeGuard(ScopeGuard &&x) noexcept=delete
ScopeGuard & operator=(ScopeGuard &&x) noexcept=delete
ScopeGuard(ScopeGuard const &x)=delete
The top-level namespace of DDC.
bool is_discrete_space_initialized() noexcept
void init_discrete_space(Args &&... args)
Initialize (emplace) a global singleton discrete space.
detail::ddim_impl_t< DDim, Kokkos::HostSpace > const & host_discrete_space()
KOKKOS_FUNCTION detail::ddim_impl_t< DDim, MemorySpace > const & discrete_space()
Arg0 init_discrete_space(std::tuple< DDimImpl, Arg0 > &&a)
Move construct a global singleton discrete space and pass through the other argument.
std::tuple< Arg0, Arg1, Args... > init_discrete_space(std::tuple< DDimImpl, Arg0, Arg1, Args... > &&a)
Move construct a global singleton discrete space and pass through remaining arguments.