10#include <sundials/sundials_nvector.h>
11#include <sundials/sundials_core.hpp>
12#include <nvector/nvector_serial.h>
13#include <nvector/nvector_kokkos.hpp>
14#include <arkode/arkode_arkstep.h>
15#include <arkode/arkode_erkstep.h>
46 void* arkodMem =
reinterpret_cast<void*
>(ark);
47 ARKodeFree(&arkodMem);
59 if (key ==
"Forward-Euler")
return ARKODE_FORWARD_EULER_1_1;
62 NF_ERROR_EXIT(
"Currently unsupported until field time step-stage indexing resolved.");
63 return ARKODE_HEUN_EULER_2_1_2;
65 if (key ==
"Midpoint")
67 NF_ERROR_EXIT(
"Currently unsupported until field time step-stage indexing resolved.");
68 return ARKODE_EXPLICIT_MIDPOINT_EULER_2_1_2;
71 "Unsupported Runge-Kutta time integration method selectied: " + key +
".\n"
72 +
"Supported methods are: Forward-Euler, Heun, Midpoint."
74 return ARKODE_ERK_NONE;
85template<
typename SKVectorType,
typename ValueType>
88 auto view = ::sundials::kokkos::GetVec<SKVectorType>(vector)->View();
90 field.
exec(), field.
range(), KOKKOS_LAMBDA(
const size_t i) { view(i) = field[i]; }
101template<
typename ValueType>
105 if (std::holds_alternative<NeoFOAM::GPUExecutor>(field.
exec()))
107 fieldToSunNVectorImpl<::sundials::kokkos::Vector<Kokkos::DefaultExecutionSpace>>(
112 if (std::holds_alternative<NeoFOAM::CPUExecutor>(field.
exec()))
114 fieldToSunNVectorImpl<::sundials::kokkos::Vector<Kokkos::DefaultHostExecutionSpace>>(
119 if (std::holds_alternative<NeoFOAM::SerialExecutor>(field.
exec()))
121 fieldToSunNVectorImpl<::sundials::kokkos::Vector<Kokkos::Serial>>(field, vector);
135template<
typename SKVectorType,
typename ValueType>
138 auto view = ::sundials::kokkos::GetVec<SKVectorType>(vector)->View();
139 ValueType* fieldData = field.
data();
141 field.
exec(), field.
range(), KOKKOS_LAMBDA(
const size_t i) { fieldData[i] = view(i); }
151template<
typename ValueType>
154 if (std::holds_alternative<NeoFOAM::GPUExecutor>(field.
exec()))
156 sunNVectorToFieldImpl<::sundials::kokkos::Vector<Kokkos::DefaultExecutionSpace>>(
161 if (std::holds_alternative<NeoFOAM::CPUExecutor>(field.
exec()))
163 sunNVectorToFieldImpl<::sundials::kokkos::Vector<Kokkos::DefaultHostExecutionSpace>>(
168 if (std::holds_alternative<NeoFOAM::SerialExecutor>(field.
exec()))
170 sunNVectorToFieldImpl<::sundials::kokkos::Vector<Kokkos::Serial>>(vector, field);
190template<
typename SolutionFieldType>
191int explicitRKSolve([[maybe_unused]] sunrealtype t, N_Vector y, N_Vector ydot,
void* userData)
195 sunrealtype* yDotArray = N_VGetArrayPointer(ydot);
196 sunrealtype* yArray = N_VGetArrayPointer(y);
199 yDotArray !=
nullptr && yArray !=
nullptr && pdeExpre !=
nullptr,
200 "Failed to dereference pointers in sundails."
203 size_t size =
static_cast<size_t>(N_VGetLength(y));
207 if (std::holds_alternative<NeoFOAM::GPUExecutor>(pdeExpre->
exec()))
225template<
typename Vector>
228 vec.initNVector(size, context);
237template<
typename Vector>
240 return vec.sunNVector();
249template<
typename Vector>
252 return vec.sunNVector();
261template<
typename ValueType>
269 : kvector_(other.kvector_), svector_(other.kvector_) {};
271 : kvector_(std::move(other.kvector_)), svector_(std::move(other.svector_)) {};
276 using KVector = ::sundials::kokkos::Vector<Kokkos::Serial>;
277 void initNVector(
size_t size, std::shared_ptr<SUNContext> context)
279 kvector_ =
KVector(size, *context);
288 N_Vector svector_ {
nullptr};
296template<
typename ValueType>
301 using KVector = ::sundials::kokkos::Vector<Kokkos::DefaultHostExecutionSpace>;
306 : kvector_(other.kvector_), svector_(other.kvector_) {};
308 : kvector_(std::move(other.kvector_)), svector_(std::move(other.svector_)) {};
312 void initNVector(
size_t size, std::shared_ptr<SUNContext> context)
314 kvector_ =
KVector(size, *context);
323 N_Vector svector_ {
nullptr};
331template<
typename ValueType>
336 using KVector = ::sundials::kokkos::Vector<Kokkos::DefaultExecutionSpace>;
341 : kvector_(other.kvector_), svector_(other.kvector_) {};
343 : kvector_(std::move(other.kvector_)), svector_(std::move(other.svector_)) {};
347 void initNVector(
size_t size, std::shared_ptr<SUNContext> context)
349 kvector_ =
KVector(size, *context);
360 N_Vector svector_ {
nullptr};
369template<
typename ValueType>
377 using SKVectorVariant = std::variant<SKVectorSerialV, SKVectorHostDefaultV, SKDefaultVectorV>;
382 SKVector() { vector_.template emplace<SKVectorHostDefaultV>(); };
417 if (std::holds_alternative<NeoFOAM::GPUExecutor>(exec))
419 vector_.template emplace<SKDefaultVectorV>();
422 if (std::holds_alternative<NeoFOAM::CPUExecutor>(exec))
424 vector_.template emplace<SKVectorHostDefaultV>();
427 if (std::holds_alternative<NeoFOAM::SerialExecutor>(exec))
429 vector_.template emplace<SKVectorSerialV>();
434 "Unsupported NeoFOAM executor: "
435 << std::visit([](
const auto& e) {
return e.name(); }, exec) <<
"."
444 void initNVector(
size_t size, std::shared_ptr<SUNContext> context)
468 return std::visit([](
auto& vec) -> N_Vector& {
return detail::sunNVector(vec); }, vector_);
A class to contain the data and executors for a field and define some basic operations.
std::pair< size_t, size_t > range() const
Gets the range of the field.
const Executor & exec() const
Gets the executor associated with the field.
ValueType * data()
Direct access to the underlying field data.
A class for the representation of a 3D Vector.
Field< scalar > explicitOperation(size_t nCells)
const Executor & exec() const
Default executor SUNDIALS Kokkos vector wrapper.
SKVectorDefault(SKVectorDefault &&other) noexcept
SKVectorDefault & operator=(const SKVectorDefault &other)=delete
SKVectorDefault(const SKVectorDefault &other)
~SKVectorDefault()=default
void initNVector(size_t size, std::shared_ptr< SUNContext > context)
SKVectorDefault & operator=(SKVectorDefault &&other)=delete
::sundials::kokkos::Vector< Kokkos::DefaultExecutionSpace > KVector
SKVectorDefault()=default
const N_Vector & sunNVector() const
Host default executor SUNDIALS Kokkos vector wrapper.
const N_Vector & sunNVector() const
void initNVector(size_t size, std::shared_ptr< SUNContext > context)
SKVectorHostDefault(const SKVectorHostDefault &other)
SKVectorHostDefault()=default
SKVectorHostDefault(SKVectorHostDefault &&other) noexcept
~SKVectorHostDefault()=default
::sundials::kokkos::Vector< Kokkos::DefaultHostExecutionSpace > KVector
SKVectorHostDefault & operator=(SKVectorHostDefault &&other)=delete
SKVectorHostDefault & operator=(const SKVectorHostDefault &other)=delete
Serial executor SUNDIALS Kokkos vector wrapper.
::sundials::kokkos::Vector< Kokkos::Serial > KVector
const N_Vector & sunNVector() const
SKVectorSerial(const SKVectorSerial &other)
SKVectorSerial & operator=(SKVectorSerial &&other)=delete
~SKVectorSerial()=default
void initNVector(size_t size, std::shared_ptr< SUNContext > context)
SKVectorSerial(SKVectorSerial &&other) noexcept
SKVectorSerial & operator=(const SKVectorSerial &other)=delete
Unified interface for SUNDIALS Kokkos vector management.
~SKVector()=default
Default destructor.
const SKVectorVariant & variant() const
Gets const reference to variant storing implementation.
SKVector(SKVector &&) noexcept=default
Move constructor.
void initNVector(size_t size, std::shared_ptr< SUNContext > context)
Initializes underlying vector with given size and context.
SKVector(const SKVector &)=default
Copy constructor.
SKVectorVariant & variant()
Gets mutable reference to variant storing implementation.
void setExecutor(const NeoFOAM::Executor &exec)
Sets appropriate vector implementation based on executor type.
std::variant< SKVectorSerialV, SKVectorHostDefaultV, SKDefaultVectorV > SKVectorVariant
N_Vector & sunNVector()
Gets mutable reference to underlying N_Vector.
SKVector & operator=(const SKVector &)=delete
Copy assignment operator (deleted).
SKVector()
Default constructor. Initializes with host-default vector.
const N_Vector & sunNVector() const
Gets const reference to underlying N_Vector.
#define NF_ERROR_EXIT(message)
Macro for printing an error message and aborting the program.
#define NF_ASSERT(condition, message)
Macro for asserting a condition and printing an error message if the condition is false.
void initNVector(size_t size, std::shared_ptr< SUNContext > context, Vector &vec)
Initializes a vector wrapper with specified size and context.
const N_Vector & sunNVector(const Vector &vec)
Provides const access to underlying N_Vector.
void sunNVectorToField(const N_Vector &vector, NeoFOAM::Field< ValueType > &field)
Dispatcher for N_Vector to field conversion based on executor type.
void fieldToSunNVector(const NeoFOAM::Field< ValueType > &field, N_Vector &vector)
Dispatcher for field to N_Vector conversion based on executor type.
auto SUN_ARK_DELETER
Custom deleter for explicit type RK solvers (ERK, ARK, etc) for the unique pointers.
void sunNVectorToFieldImpl(const N_Vector &vector, NeoFOAM::Field< ValueType > &field)
Converts SUNDIALS N_Vector data back to NeoFOAM Field format.
void fieldToSunNVectorImpl(const NeoFOAM::Field< ValueType > &field, N_Vector &vector)
Converts NeoFOAM Field data to SUNDIALS N_Vector format.
auto SUN_CONTEXT_DELETER
Custom deleter for SUNContext shared pointers.
int explicitRKSolve(sunrealtype t, N_Vector y, N_Vector ydot, void *userData)
Performs a single explicit Runge-Kutta stage evaluation.
ARKODE_ERKTableID stringToERKTable(const std::string &key)
Maps dictionary keywords to SUNDIALS RKButcher tableau identifiers.
std::variant< SerialExecutor, CPUExecutor, GPUExecutor > Executor
void parallelFor(const Executor &exec, std::pair< size_t, size_t > range, Kernel kernel, std::string name="parallelFor")