18#include <Kokkos_Core.hpp>
20#include "ddc/detail/dual_discretization.hpp"
21#include "ddc/detail/macros.hpp"
23#if defined(__CUDACC__)
28#define DDC_DETAIL_CUDA_THROW_ON_ERROR(val)
29 ddc::detail::cuda_throw_on_error((val), #val, __FILE__, __LINE__)
34#include <hip/hip_runtime.h>
36#define DDC_DETAIL_HIP_THROW_ON_ERROR(val)
37 ddc::detail::hip_throw_on_error((val), #val, __FILE__, __LINE__)
40#if defined(KOKKOS_ENABLE_CUDA)
41#if !defined(KOKKOS_ENABLE_CUDA_CONSTEXPR)
42static_assert(
false,
"DDC requires option -DKokkos_ENABLE_CUDA_CONSTEXPR=ON");
45#if !defined(KOKKOS_ENABLE_CUDA_RELOCATABLE_DEVICE_CODE)
46static_assert(
false,
"DDC requires option -DKokkos_ENABLE_CUDA_RELOCATABLE_DEVICE_CODE=ON");
50#if defined(KOKKOS_ENABLE_HIP)
51#if !defined(KOKKOS_ENABLE_HIP_RELOCATABLE_DEVICE_CODE)
52static_assert(
false,
"DDC requires option -DKokkos_ENABLE_HIP_RELOCATABLE_DEVICE_CODE=ON");
60#if defined(__CUDACC__)
62void cuda_throw_on_error(
64 const char*
const func,
65 const char*
const file,
68 if (err != cudaSuccess) {
70 ss <<
"CUDA Runtime Error at: " << file <<
":" << line <<
"\n";
71 ss << cudaGetErrorString(err) <<
" " << func <<
"\n";
72 throw std::runtime_error(ss.str());
75#elif defined(__HIPCC__)
77void hip_throw_on_error(T
const err,
const char*
const func,
const char*
const file,
const int line)
79 if (err != hipSuccess) {
81 ss <<
"HIP Runtime Error at: " << file <<
":" << line <<
"\n";
82 ss << hipGetErrorString(err) <<
" " << func <<
"\n";
83 throw std::runtime_error(ss.str());
88template <
class DDim,
class MemorySpace>
89using ddim_impl_t =
typename DDim::
template Impl<DDim, MemorySpace>;
105 alignas(T) Kokkos::Array<std::byte,
sizeof(T)> m_data;
111 return reinterpret_cast<T*>(m_data.data());
117 return *
reinterpret_cast<T*>(m_data.data());
123 return reinterpret_cast<T*>(m_data.data());
128inline std::optional<std::map<std::string, std::function<
void()>>> g_discretization_store;
132inline std::optional<DualDiscretization<DDim>> g_discrete_space_dual;
134#if defined(__CUDACC__)
137__constant__ gpu_proxy<ddim_impl_t<DDim, Kokkos::CudaSpace>> g_discrete_space_device;
138#elif defined(__HIPCC__)
142__constant__ gpu_proxy<ddim_impl_t<DDim, Kokkos::HIPSpace>> g_discrete_space_device;
145inline void display_discretization_store(std::ostream& os)
147 if (g_discretization_store) {
148 os <<
"The host discretization store is initialized:\n";
149 for (
auto const& [key, value] : *g_discretization_store) {
150 os <<
" - " << key <<
"\n";
153 os <<
"The host discretization store is not initialized:\n";
157template <
class Tuple, std::size_t... Ids>
158auto extract_after(Tuple&& t, std::index_sequence<Ids...>)
160 return std::make_tuple(std::move(std::get<Ids + 1>(t))...);
166
167
168
169template <
class DDim,
class... Args>
173 !std::is_same_v<DDim,
typename DDim::discrete_dimension_type>,
174 "Discrete dimensions should inherit from the discretization, not use an alias");
175 if (detail::g_discrete_space_dual<DDim>) {
176 throw std::runtime_error(
"Discrete space function already initialized.");
178 detail::g_discrete_space_dual<DDim>.emplace(std::forward<Args>(args)...);
179 detail::g_discretization_store->emplace(
typeid(DDim).name(), []() {
180 detail::g_discrete_space_dual<DDim>.reset();
182#if defined(__CUDACC__)
183 DDC_DETAIL_CUDA_THROW_ON_ERROR(cudaMemcpyToSymbol(
184 detail::g_discrete_space_device<DDim>,
185 &detail::g_discrete_space_dual<DDim>->get_device(),
186 sizeof(detail::g_discrete_space_dual<DDim>->get_device())));
187#elif defined(__HIPCC__)
188 DDC_DETAIL_HIP_THROW_ON_ERROR(hipMemcpyToSymbol(
189 detail::g_discrete_space_device<DDim>,
190 &detail::g_discrete_space_dual<DDim>->get_device(),
191 sizeof(detail::g_discrete_space_dual<DDim>->get_device())));
196
197
198
199
200template <
class DDim,
class DDimImpl,
class Arg0>
203 init_discrete_space<DDim>(std::move(std::get<0>(a)));
204 return std::get<1>(a);
208
209
210
211
212template <
class DDim,
class DDimImpl,
class Arg0,
class Arg1,
class... Args>
213std::tuple<Arg0, Arg1, Args...>
init_discrete_space(std::tuple<DDimImpl, Arg0, Arg1, Args...>&& a)
215 init_discrete_space<DDim>(std::move(std::get<0>(a)));
216 return detail::extract_after(std::move(a), std::index_sequence_for<Arg0, Arg1, Args...>());
220
221
222
223
224
225template <
class DDim,
class MemorySpace = DDC_CURRENT_KOKKOS_SPACE>
228 if constexpr (std::is_same_v<MemorySpace, Kokkos::HostSpace>) {
229 return detail::g_discrete_space_dual<DDim>->get_host();
231#if defined(__CUDACC__)
232 else if constexpr (std::is_same_v<MemorySpace, Kokkos::CudaSpace>) {
233 return *detail::g_discrete_space_device<DDim>;
235#elif defined(__HIPCC__)
236 else if constexpr (std::is_same_v<MemorySpace, Kokkos::HIPSpace>) {
237 return *detail::g_discrete_space_device<DDim>;
241 static_assert(std::is_same_v<MemorySpace, MemorySpace>,
"Memory space not handled");
248 return detail::g_discrete_space_dual<DDim>.has_value();
254 return detail::g_discrete_space_dual<DDim>->get_host();
259#if defined(__CUDACC__)
260#undef DDC_DETAIL_CUDA_THROW_ON_ERROR
262#if defined(__HIPCC__)
263#undef DDC_DETAIL_HIP_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.