20#include <Kokkos_Core.hpp>
22#include "detail/dual_discretization.hpp"
23#include "detail/macros.hpp"
25#if defined(KOKKOS_ENABLE_CUDA)
29#elif defined(KOKKOS_ENABLE_HIP)
32# include <hip/hip_runtime.h>
35#if defined(KOKKOS_ENABLE_CUDA) || defined(KOKKOS_ENABLE_HIP)
36# define DDC_DETAIL_DEVICE_THROW_ON_ERROR(val)
37 ddc::detail::device_throw_on_error((val), #val, __FILE__, __LINE__)
44#if defined(KOKKOS_ENABLE_CUDA)
45inline void device_throw_on_error(
46 cudaError_t
const err,
47 const char*
const func,
48 const char*
const file,
51 if (err != cudaSuccess) {
53 ss <<
"CUDA Runtime Error at: " << file <<
":" << line <<
"\n";
54 ss << cudaGetErrorString(err) <<
" " << func <<
"\n";
55 throw std::runtime_error(ss.str());
58#elif defined(KOKKOS_ENABLE_HIP)
59inline void device_throw_on_error(
61 const char*
const func,
62 const char*
const file,
65 if (err != hipSuccess) {
67 ss <<
"HIP Runtime Error at: " << file <<
":" << line <<
"\n";
68 ss << hipGetErrorString(err) <<
" " << func <<
"\n";
69 throw std::runtime_error(ss.str());
74template <
class DDim,
class MemorySpace>
75using ddim_impl_t =
typename DDim::
template Impl<DDim, MemorySpace>;
91 alignas(T) Kokkos::Array<std::byte,
sizeof(T)> m_data;
97 return reinterpret_cast<T*>(m_data.data());
103 return *
reinterpret_cast<T*>(m_data.data());
109 return reinterpret_cast<T*>(m_data.data());
114inline std::optional<std::map<std::string, std::function<
void()>>> g_discretization_store;
118inline std::optional<DualDiscretization<DDim>> g_discrete_space_dual;
120#if defined(KOKKOS_ENABLE_CUDA)
123__constant__ GpuProxy<ddim_impl_t<DDim, GlobalVariableDeviceSpace>> g_discrete_space_device;
124#elif defined(KOKKOS_ENABLE_HIP)
128__constant__ GpuProxy<ddim_impl_t<DDim, GlobalVariableDeviceSpace>> g_discrete_space_device;
129#elif defined(KOKKOS_ENABLE_SYCL)
132SYCL_EXTERNAL
inline sycl::ext::oneapi::experimental::device_global<
133 GpuProxy<ddim_impl_t<DDim, GlobalVariableDeviceSpace>>>
134 g_discrete_space_device;
137inline void display_discretization_store(std::ostream& os)
139 if (g_discretization_store) {
140 os <<
"The host discretization store is initialized:\n";
141 for (
auto const& [key, value] : *g_discretization_store) {
142 os <<
" - " << key <<
"\n";
145 os <<
"The host discretization store is not initialized:\n";
149template <
class Tuple, std::size_t... Ids>
150auto extract_after(Tuple&& t, std::index_sequence<Ids...>)
152 return std::make_tuple(std::move(std::get<Ids + 1>(t))...);
158
159
160
161template <
class DDim,
class... Args>
165 !std::is_same_v<DDim,
typename DDim::discrete_dimension_type>,
166 "Discrete dimensions should inherit from the discretization, not use an alias");
167 if (detail::g_discrete_space_dual<DDim>) {
168 throw std::runtime_error(
"Discrete space function already initialized.");
170 detail::g_discrete_space_dual<DDim>.emplace(std::forward<Args>(args)...);
171 detail::g_discretization_store->emplace(
typeid(DDim).name(), []() {
172 detail::g_discrete_space_dual<DDim>.reset();
174#if defined(KOKKOS_ENABLE_CUDA)
175 DDC_DETAIL_DEVICE_THROW_ON_ERROR(cudaMemcpyToSymbol(
176 detail::g_discrete_space_device<DDim>,
177 &detail::g_discrete_space_dual<DDim>->get_device(),
178 sizeof(detail::g_discrete_space_dual<DDim>->get_device())));
179#elif defined(KOKKOS_ENABLE_HIP)
180 DDC_DETAIL_DEVICE_THROW_ON_ERROR(hipMemcpyToSymbol(
181 detail::g_discrete_space_device<DDim>,
182 &detail::g_discrete_space_dual<DDim>->get_device(),
183 sizeof(detail::g_discrete_space_dual<DDim>->get_device())));
184#elif defined(KOKKOS_ENABLE_SYCL)
185 Kokkos::DefaultExecutionSpace exec;
186 sycl::queue q = exec.sycl_queue();
187 q.memcpy(detail::g_discrete_space_device<DDim>,
188 &detail::g_discrete_space_dual<DDim>->get_device())
194
195
196
197
198template <
class DDim,
class DDimImpl,
class Arg0>
201 init_discrete_space<DDim>(std::move(std::get<0>(a)));
202 return std::get<1>(a);
206
207
208
209
210template <
class DDim,
class DDimImpl,
class Arg0,
class Arg1,
class... Args>
211std::tuple<Arg0, Arg1, Args...>
init_discrete_space(std::tuple<DDimImpl, Arg0, Arg1, Args...>&& a)
213 init_discrete_space<DDim>(std::move(std::get<0>(a)));
214 return detail::extract_after(std::move(a), std::index_sequence_for<Arg0, Arg1, Args...>());
218
219
220
221
225 return detail::g_discrete_space_dual<DDim>.has_value();
229
230
231
232
233
234template <
class DDim,
class MemorySpace = DDC_CURRENT_KOKKOS_SPACE>
238 if constexpr (std::is_same_v<MemorySpace, Kokkos::HostSpace>) {
239 KOKKOS_ASSERT(is_discrete_space_initialized<DDim>())
240 return detail::g_discrete_space_dual<DDim>->get_host();
242#if defined(KOKKOS_ENABLE_CUDA) || defined(KOKKOS_ENABLE_HIP)
243 else if constexpr (std::is_same_v<MemorySpace, detail::GlobalVariableDeviceSpace>) {
244 return *detail::g_discrete_space_device<DDim>;
246#elif defined(KOKKOS_ENABLE_SYCL)
247 else if constexpr (std::is_same_v<MemorySpace, detail::GlobalVariableDeviceSpace>) {
248 return *detail::g_discrete_space_device<DDim>.get();
252 static_assert(std::is_same_v<MemorySpace, MemorySpace>,
"Memory space not handled");
260 assert(is_discrete_space_initialized<DDim>());
261 return detail::g_discrete_space_dual<DDim>->get_host();
266#if defined(KOKKOS_ENABLE_CUDA) || defined(KOKKOS_ENABLE_HIP)
267# undef DDC_DETAIL_DEVICE_THROW_ON_ERROR
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.