xref: /petsc/src/sys/objects/device/impls/impldevicebase.hpp (revision 6d8694c4fbab79f9439f1ad13c0386ba7ee1ca4b)
1a4963045SJacob Faibussowitsch #pragma once
20e6b6b59SJacob Faibussowitsch 
30e6b6b59SJacob Faibussowitsch #include <petsc/private/deviceimpl.h>
40e6b6b59SJacob Faibussowitsch #include <petsc/private/viewerimpl.h>
50e6b6b59SJacob Faibussowitsch 
60e6b6b59SJacob Faibussowitsch #include <petsc/private/cpp/crtp.hpp>
70e6b6b59SJacob Faibussowitsch #include <petsc/private/cpp/type_traits.hpp>
80e6b6b59SJacob Faibussowitsch #include <petsc/private/cpp/utility.hpp>
90e6b6b59SJacob Faibussowitsch #include <petsc/private/cpp/array.hpp>
100e6b6b59SJacob Faibussowitsch 
110e6b6b59SJacob Faibussowitsch #include <cstring> // for std::strlen
120e6b6b59SJacob Faibussowitsch 
13d71ae5a4SJacob Faibussowitsch namespace Petsc
14d71ae5a4SJacob Faibussowitsch {
150e6b6b59SJacob Faibussowitsch 
16d71ae5a4SJacob Faibussowitsch namespace device
17d71ae5a4SJacob Faibussowitsch {
180e6b6b59SJacob Faibussowitsch 
19d71ae5a4SJacob Faibussowitsch namespace impl
20d71ae5a4SJacob Faibussowitsch {
210e6b6b59SJacob Faibussowitsch 
220e6b6b59SJacob Faibussowitsch template <typename Derived> // CRTP
23146a86ebSJacob Faibussowitsch class DeviceBase : public util::crtp<DeviceBase, Derived> {
240e6b6b59SJacob Faibussowitsch public:
250e6b6b59SJacob Faibussowitsch   using derived_type            = Derived;
260e6b6b59SJacob Faibussowitsch   using createContextFunction_t = PetscErrorCode (*)(PetscDeviceContext);
270e6b6b59SJacob Faibussowitsch 
280e6b6b59SJacob Faibussowitsch   // default constructor
DeviceBase(createContextFunction_t f)290e6b6b59SJacob Faibussowitsch   constexpr DeviceBase(createContextFunction_t f) noexcept : create_(f) { }
300e6b6b59SJacob Faibussowitsch 
310e6b6b59SJacob Faibussowitsch   template <typename T = derived_type>
PETSC_DEVICE_IMPL()32d71ae5a4SJacob Faibussowitsch   PETSC_NODISCARD static constexpr PetscDeviceType PETSC_DEVICE_IMPL() noexcept
33d71ae5a4SJacob Faibussowitsch   {
340e6b6b59SJacob Faibussowitsch     return T::PETSC_DEVICE_IMPL_();
350e6b6b59SJacob Faibussowitsch   }
360e6b6b59SJacob Faibussowitsch 
37089fb57cSJacob Faibussowitsch   PetscErrorCode        getDevice(PetscDevice, PetscInt) noexcept;
38089fb57cSJacob Faibussowitsch   static PetscErrorCode configureDevice(PetscDevice) noexcept;
39089fb57cSJacob Faibussowitsch   static PetscErrorCode viewDevice(PetscDevice, PetscViewer) noexcept;
40089fb57cSJacob Faibussowitsch   static PetscErrorCode getAttribute(PetscDevice, PetscDeviceAttribute, void *) noexcept;
410e6b6b59SJacob Faibussowitsch 
420e6b6b59SJacob Faibussowitsch protected:
430e6b6b59SJacob Faibussowitsch   // function to create a PetscDeviceContext (the (*create) function pointer usually set
440e6b6b59SJacob Faibussowitsch   // via XXXSetType() for other PETSc objects)
450e6b6b59SJacob Faibussowitsch   const createContextFunction_t create_;
460e6b6b59SJacob Faibussowitsch 
470e6b6b59SJacob Faibussowitsch   // if you want the base class to handle the entire options query, has the same arguments as
480e6b6b59SJacob Faibussowitsch   // PetscOptionDeviceBasic
49089fb57cSJacob Faibussowitsch   static PetscErrorCode PetscOptionDeviceAll(MPI_Comm, std::pair<PetscDeviceInitType, PetscBool> &, std::pair<PetscInt, PetscBool> &, std::pair<PetscBool, PetscBool> &) noexcept;
500e6b6b59SJacob Faibussowitsch 
510e6b6b59SJacob Faibussowitsch   // if you want to start and end the options query yourself, but still want all the default
520e6b6b59SJacob Faibussowitsch   // options
53*ce78bad3SBarry Smith   static PetscErrorCode PetscOptionDeviceBasic(PetscOptionItems, std::pair<PetscDeviceInitType, PetscBool> &, std::pair<PetscInt, PetscBool> &, std::pair<PetscBool, PetscBool> &) noexcept;
540e6b6b59SJacob Faibussowitsch 
550e6b6b59SJacob Faibussowitsch   // option templates to follow, each one has two forms:
560e6b6b59SJacob Faibussowitsch   // - A simple form returning only the value and flag. This gives no control over the message,
570e6b6b59SJacob Faibussowitsch   //   arguments to the options query or otherwise
580e6b6b59SJacob Faibussowitsch   // - A complex form, which allows you to pass most of the options query arguments *EXCEPT*
590e6b6b59SJacob Faibussowitsch   //   - The options query function called
600e6b6b59SJacob Faibussowitsch   //   - The option string
610e6b6b59SJacob Faibussowitsch 
620e6b6b59SJacob Faibussowitsch   // option template for initializing the device
63*ce78bad3SBarry Smith   static PetscErrorCode PetscOptionDeviceInitialize(PetscOptionItems, PetscDeviceInitType *, PetscBool *) noexcept;
640e6b6b59SJacob Faibussowitsch   template <typename... T, util::enable_if_t<sizeof...(T) >= 3, int> = 0>
65*ce78bad3SBarry Smith   static PetscErrorCode PetscOptionDeviceInitialize(PetscOptionItems, T &&...) noexcept;
660e6b6b59SJacob Faibussowitsch   // option template for selecting the default device
67*ce78bad3SBarry Smith   static PetscErrorCode PetscOptionDeviceSelect(PetscOptionItems, PetscInt *, PetscBool *) noexcept;
680e6b6b59SJacob Faibussowitsch   template <typename... T, util::enable_if_t<sizeof...(T) >= 3, int> = 0>
69*ce78bad3SBarry Smith   static PetscErrorCode PetscOptionDeviceSelect(PetscOptionItems, T &&...) noexcept;
700e6b6b59SJacob Faibussowitsch   // option templates for viewing a device
71*ce78bad3SBarry Smith   static PetscErrorCode PetscOptionDeviceView(PetscOptionItems, PetscBool *, PetscBool *) noexcept;
720e6b6b59SJacob Faibussowitsch   template <typename... T, util::enable_if_t<sizeof...(T) >= 3, int> = 0>
73*ce78bad3SBarry Smith   static PetscErrorCode PetscOptionDeviceView(PetscOptionItems, T &&...) noexcept;
740e6b6b59SJacob Faibussowitsch 
750e6b6b59SJacob Faibussowitsch private:
760e6b6b59SJacob Faibussowitsch   // base function for all options templates above, they basically just reformat the arguments,
770e6b6b59SJacob Faibussowitsch   // create the option string and pass it off to this function
78*ce78bad3SBarry Smith   template <typename... T, typename F = PetscErrorCode (*)(PetscOptionItems, const char *, T &&...)>
79*ce78bad3SBarry Smith   static PetscErrorCode PetscOptionDevice(F &&, PetscOptionItems, const char[], T &&...) noexcept;
800e6b6b59SJacob Faibussowitsch 
810e6b6b59SJacob Faibussowitsch   // default crtp implementations
init_device_id_(PetscInt * id)82089fb57cSJacob Faibussowitsch   static PetscErrorCode init_device_id_(PetscInt *id) noexcept
83d71ae5a4SJacob Faibussowitsch   {
840e6b6b59SJacob Faibussowitsch     PetscFunctionBegin;
850e6b6b59SJacob Faibussowitsch     *id = 0;
863ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
870e6b6b59SJacob Faibussowitsch   }
880e6b6b59SJacob Faibussowitsch 
configure_device_(PetscDevice)89089fb57cSJacob Faibussowitsch   static constexpr PetscErrorCode configure_device_(PetscDevice) noexcept { return PETSC_SUCCESS; }
view_device_(PetscDevice,PetscViewer)90089fb57cSJacob Faibussowitsch   static constexpr PetscErrorCode view_device_(PetscDevice, PetscViewer) noexcept { return PETSC_SUCCESS; }
910e6b6b59SJacob Faibussowitsch };
920e6b6b59SJacob Faibussowitsch 
930e6b6b59SJacob Faibussowitsch template <typename D>
getDevice(PetscDevice device,PetscInt id)94d71ae5a4SJacob Faibussowitsch inline PetscErrorCode DeviceBase<D>::getDevice(PetscDevice device, PetscInt id) noexcept
95d71ae5a4SJacob Faibussowitsch {
960e6b6b59SJacob Faibussowitsch   PetscFunctionBegin;
970e6b6b59SJacob Faibussowitsch   PetscCall(this->underlying().init_device_id_(&id));
980e6b6b59SJacob Faibussowitsch   device->deviceId           = id;
990e6b6b59SJacob Faibussowitsch   device->ops->createcontext = this->underlying().create_;
1000e6b6b59SJacob Faibussowitsch   device->ops->configure     = this->underlying().configureDevice;
1010e6b6b59SJacob Faibussowitsch   device->ops->view          = this->underlying().viewDevice;
1020e6b6b59SJacob Faibussowitsch   device->ops->getattribute  = this->underlying().getAttribute;
1033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1040e6b6b59SJacob Faibussowitsch }
1050e6b6b59SJacob Faibussowitsch 
1060e6b6b59SJacob Faibussowitsch template <typename D>
configureDevice(PetscDevice device)107d71ae5a4SJacob Faibussowitsch inline PetscErrorCode DeviceBase<D>::configureDevice(PetscDevice device) noexcept
108d71ae5a4SJacob Faibussowitsch {
1090e6b6b59SJacob Faibussowitsch   PetscFunctionBegin;
1100e6b6b59SJacob Faibussowitsch   PetscCall(derived_type::configure_device_(device));
1113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1120e6b6b59SJacob Faibussowitsch }
1130e6b6b59SJacob Faibussowitsch 
1140e6b6b59SJacob Faibussowitsch template <typename D>
viewDevice(PetscDevice device,PetscViewer viewer)115d71ae5a4SJacob Faibussowitsch inline PetscErrorCode DeviceBase<D>::viewDevice(PetscDevice device, PetscViewer viewer) noexcept
116d71ae5a4SJacob Faibussowitsch {
1170e6b6b59SJacob Faibussowitsch   PetscFunctionBegin;
1180e6b6b59SJacob Faibussowitsch   PetscCall(derived_type::view_device_(device, viewer));
1193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1200e6b6b59SJacob Faibussowitsch }
1210e6b6b59SJacob Faibussowitsch 
1220e6b6b59SJacob Faibussowitsch template <typename D>
getAttribute(PetscDevice device,PetscDeviceAttribute attr,void * value)123d71ae5a4SJacob Faibussowitsch inline PetscErrorCode DeviceBase<D>::getAttribute(PetscDevice device, PetscDeviceAttribute attr, void *value) noexcept
124d71ae5a4SJacob Faibussowitsch {
1250e6b6b59SJacob Faibussowitsch   PetscFunctionBegin;
1260e6b6b59SJacob Faibussowitsch   PetscCall(derived_type::get_attribute_(device->deviceId, attr, value));
1273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1280e6b6b59SJacob Faibussowitsch }
1290e6b6b59SJacob Faibussowitsch 
1300e6b6b59SJacob Faibussowitsch template <typename D>
1310e6b6b59SJacob Faibussowitsch template <typename... T, typename F>
PetscOptionDevice(F && OptionsFunction,PetscOptionItems PetscOptionsObject,const char optstub[],T &&...args)132*ce78bad3SBarry Smith inline PetscErrorCode DeviceBase<D>::PetscOptionDevice(F &&OptionsFunction, PetscOptionItems PetscOptionsObject, const char optstub[], T &&...args) noexcept
133d71ae5a4SJacob Faibussowitsch {
1340e6b6b59SJacob Faibussowitsch   constexpr auto dtype    = PETSC_DEVICE_IMPL();
1350e6b6b59SJacob Faibussowitsch   const auto     implname = PetscDeviceTypes[dtype];
1360e6b6b59SJacob Faibussowitsch   auto           buf      = std::array<char, 128>{};
1370e6b6b59SJacob Faibussowitsch   constexpr auto buflen   = buf.size() - 1;
1380e6b6b59SJacob Faibussowitsch 
1390e6b6b59SJacob Faibussowitsch   PetscFunctionBegin;
1400e6b6b59SJacob Faibussowitsch   if (PetscDefined(USE_DEBUG)) {
1410e6b6b59SJacob Faibussowitsch     const auto len = std::strlen(optstub) + std::strlen(implname);
1420e6b6b59SJacob Faibussowitsch 
1430e6b6b59SJacob Faibussowitsch     PetscCheck(len < buflen, PetscOptionsObject->comm, PETSC_ERR_PLIB, "char buffer is not large enough to hold '%s%s'; have %zu need %zu", optstub, implname, buflen, len);
1440e6b6b59SJacob Faibussowitsch   }
1450e6b6b59SJacob Faibussowitsch   PetscCall(PetscSNPrintf(buf.data(), buflen, "%s%s", optstub, implname));
1460e6b6b59SJacob Faibussowitsch   PetscCall(OptionsFunction(PetscOptionsObject, buf.data(), std::forward<T>(args)...));
1473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1480e6b6b59SJacob Faibussowitsch }
1490e6b6b59SJacob Faibussowitsch 
1500e6b6b59SJacob Faibussowitsch template <typename D>
1510e6b6b59SJacob Faibussowitsch template <typename... T, util::enable_if_t<sizeof...(T) >= 3, int>>
PetscOptionDeviceInitialize(PetscOptionItems PetscOptionsObject,T &&...args)152*ce78bad3SBarry Smith inline PetscErrorCode DeviceBase<D>::PetscOptionDeviceInitialize(PetscOptionItems PetscOptionsObject, T &&...args) noexcept
153d71ae5a4SJacob Faibussowitsch {
1540e6b6b59SJacob Faibussowitsch   PetscFunctionBegin;
1550e6b6b59SJacob Faibussowitsch   PetscCall(PetscOptionDevice(PetscOptionsEList_Private, PetscOptionsObject, "-device_enable_", std::forward<T>(args)...));
1563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1570e6b6b59SJacob Faibussowitsch }
1580e6b6b59SJacob Faibussowitsch 
1590e6b6b59SJacob Faibussowitsch template <typename D>
PetscOptionDeviceInitialize(PetscOptionItems PetscOptionsObject,PetscDeviceInitType * inittype,PetscBool * flag)160*ce78bad3SBarry Smith inline PetscErrorCode DeviceBase<D>::PetscOptionDeviceInitialize(PetscOptionItems PetscOptionsObject, PetscDeviceInitType *inittype, PetscBool *flag) noexcept
161d71ae5a4SJacob Faibussowitsch {
162bd2fcf0cSJacob Faibussowitsch   auto type = static_cast<PetscInt>(util::to_underlying(*inittype));
1630e6b6b59SJacob Faibussowitsch 
1640e6b6b59SJacob Faibussowitsch   PetscFunctionBegin;
1650e6b6b59SJacob Faibussowitsch   PetscCall(PetscOptionDeviceInitialize(PetscOptionsObject, "How (or whether) to initialize a device", "PetscDeviceInitialize()", PetscDeviceInitTypes, 3, PetscDeviceInitTypes[type], &type, flag));
1660e6b6b59SJacob Faibussowitsch   *inittype = static_cast<PetscDeviceInitType>(type);
1673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1680e6b6b59SJacob Faibussowitsch }
1690e6b6b59SJacob Faibussowitsch 
1700e6b6b59SJacob Faibussowitsch template <typename D>
1710e6b6b59SJacob Faibussowitsch template <typename... T, util::enable_if_t<sizeof...(T) >= 3, int>>
PetscOptionDeviceSelect(PetscOptionItems PetscOptionsObject,T &&...args)172*ce78bad3SBarry Smith inline PetscErrorCode DeviceBase<D>::PetscOptionDeviceSelect(PetscOptionItems PetscOptionsObject, T &&...args) noexcept
173d71ae5a4SJacob Faibussowitsch {
1740e6b6b59SJacob Faibussowitsch   PetscFunctionBegin;
1750e6b6b59SJacob Faibussowitsch   PetscCall(PetscOptionDevice(PetscOptionsInt_Private, PetscOptionsObject, "-device_select_", std::forward<T>(args)...));
1763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1770e6b6b59SJacob Faibussowitsch }
1780e6b6b59SJacob Faibussowitsch 
1790e6b6b59SJacob Faibussowitsch template <typename D>
PetscOptionDeviceSelect(PetscOptionItems PetscOptionsObject,PetscInt * id,PetscBool * flag)180*ce78bad3SBarry Smith inline PetscErrorCode DeviceBase<D>::PetscOptionDeviceSelect(PetscOptionItems PetscOptionsObject, PetscInt *id, PetscBool *flag) noexcept
181d71ae5a4SJacob Faibussowitsch {
1820e6b6b59SJacob Faibussowitsch   PetscFunctionBegin;
1830e6b6b59SJacob Faibussowitsch   PetscCall(PetscOptionDeviceSelect(PetscOptionsObject, "Which device to use. Pass " PetscStringize(PETSC_DECIDE) " to have PETSc decide or (given they exist) [0-" PetscStringize(PETSC_DEVICE_MAX_DEVICES) ") for a specific device", "PetscDeviceCreate()", *id, id, flag, PETSC_DECIDE, PETSC_DEVICE_MAX_DEVICES));
1843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1850e6b6b59SJacob Faibussowitsch }
1860e6b6b59SJacob Faibussowitsch 
1870e6b6b59SJacob Faibussowitsch template <typename D>
1880e6b6b59SJacob Faibussowitsch template <typename... T, util::enable_if_t<sizeof...(T) >= 3, int>>
PetscOptionDeviceView(PetscOptionItems PetscOptionsObject,T &&...args)189*ce78bad3SBarry Smith inline PetscErrorCode DeviceBase<D>::PetscOptionDeviceView(PetscOptionItems PetscOptionsObject, T &&...args) noexcept
190d71ae5a4SJacob Faibussowitsch {
1910e6b6b59SJacob Faibussowitsch   PetscFunctionBegin;
1920e6b6b59SJacob Faibussowitsch   PetscCall(PetscOptionDevice(PetscOptionsBool_Private, PetscOptionsObject, "-device_view_", std::forward<T>(args)...));
1933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1940e6b6b59SJacob Faibussowitsch }
1950e6b6b59SJacob Faibussowitsch 
1960e6b6b59SJacob Faibussowitsch template <typename D>
PetscOptionDeviceView(PetscOptionItems PetscOptionsObject,PetscBool * view,PetscBool * flag)197*ce78bad3SBarry Smith inline PetscErrorCode DeviceBase<D>::PetscOptionDeviceView(PetscOptionItems PetscOptionsObject, PetscBool *view, PetscBool *flag) noexcept
198d71ae5a4SJacob Faibussowitsch {
1990e6b6b59SJacob Faibussowitsch   PetscFunctionBegin;
2000e6b6b59SJacob Faibussowitsch   PetscCall(PetscOptionDeviceView(PetscOptionsObject, "Display device information and assignments (forces eager initialization)", "PetscDeviceView()", *view, view, flag));
2013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2020e6b6b59SJacob Faibussowitsch }
2030e6b6b59SJacob Faibussowitsch 
2040e6b6b59SJacob Faibussowitsch template <typename D>
PetscOptionDeviceBasic(PetscOptionItems PetscOptionsObject,std::pair<PetscDeviceInitType,PetscBool> & initType,std::pair<PetscInt,PetscBool> & initId,std::pair<PetscBool,PetscBool> & initView)205*ce78bad3SBarry Smith inline PetscErrorCode DeviceBase<D>::PetscOptionDeviceBasic(PetscOptionItems PetscOptionsObject, std::pair<PetscDeviceInitType, PetscBool> &initType, std::pair<PetscInt, PetscBool> &initId, std::pair<PetscBool, PetscBool> &initView) noexcept
206d71ae5a4SJacob Faibussowitsch {
2070e6b6b59SJacob Faibussowitsch   PetscFunctionBegin;
2080e6b6b59SJacob Faibussowitsch   PetscCall(PetscOptionDeviceInitialize(PetscOptionsObject, &initType.first, &initType.second));
2090e6b6b59SJacob Faibussowitsch   PetscCall(PetscOptionDeviceSelect(PetscOptionsObject, &initId.first, &initId.second));
2100e6b6b59SJacob Faibussowitsch   PetscCall(PetscOptionDeviceView(PetscOptionsObject, &initView.first, &initView.second));
2113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2120e6b6b59SJacob Faibussowitsch }
2130e6b6b59SJacob Faibussowitsch 
2140e6b6b59SJacob Faibussowitsch template <typename D>
PetscOptionDeviceAll(MPI_Comm comm,std::pair<PetscDeviceInitType,PetscBool> & initType,std::pair<PetscInt,PetscBool> & initId,std::pair<PetscBool,PetscBool> & initView)215d71ae5a4SJacob Faibussowitsch inline PetscErrorCode DeviceBase<D>::PetscOptionDeviceAll(MPI_Comm comm, std::pair<PetscDeviceInitType, PetscBool> &initType, std::pair<PetscInt, PetscBool> &initId, std::pair<PetscBool, PetscBool> &initView) noexcept
216d71ae5a4SJacob Faibussowitsch {
2170e6b6b59SJacob Faibussowitsch   constexpr char optname[] = "PetscDevice %s Options";
2180e6b6b59SJacob Faibussowitsch   constexpr auto dtype     = PETSC_DEVICE_IMPL();
2190e6b6b59SJacob Faibussowitsch   const auto     implname  = PetscDeviceTypes[dtype];
2200e6b6b59SJacob Faibussowitsch   auto           buf       = std::array<char, 128>{};
2210e6b6b59SJacob Faibussowitsch   constexpr auto buflen    = buf.size() - 1; // -1 to leave room for null
2220e6b6b59SJacob Faibussowitsch 
2230e6b6b59SJacob Faibussowitsch   PetscFunctionBegin;
2240e6b6b59SJacob Faibussowitsch   if (PetscDefined(USE_DEBUG)) {
2250e6b6b59SJacob Faibussowitsch     // -3 since '%s' is replaced and dont count null char for optname
2260e6b6b59SJacob Faibussowitsch     const auto len = std::strlen(implname) + PETSC_STATIC_ARRAY_LENGTH(optname) - 3;
2270e6b6b59SJacob Faibussowitsch 
2280e6b6b59SJacob Faibussowitsch     PetscCheck(len < buflen, comm, PETSC_ERR_PLIB, "char buffer is not large enough to hold 'PetscDevice %s Options'; have %zu need %zu", implname, buflen, len);
2290e6b6b59SJacob Faibussowitsch   }
2300e6b6b59SJacob Faibussowitsch   PetscCall(PetscSNPrintf(buf.data(), buflen, optname, implname));
2310e6b6b59SJacob Faibussowitsch   PetscOptionsBegin(comm, nullptr, buf.data(), "Sys");
2320e6b6b59SJacob Faibussowitsch   PetscCall(PetscOptionDeviceBasic(PetscOptionsObject, initType, initId, initView));
2330e6b6b59SJacob Faibussowitsch   PetscOptionsEnd();
2343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2350e6b6b59SJacob Faibussowitsch }
2360e6b6b59SJacob Faibussowitsch 
2370e6b6b59SJacob Faibussowitsch } // namespace impl
2380e6b6b59SJacob Faibussowitsch 
2390e6b6b59SJacob Faibussowitsch } // namespace device
2400e6b6b59SJacob Faibussowitsch 
2410e6b6b59SJacob Faibussowitsch } // namespace Petsc
2420e6b6b59SJacob Faibussowitsch 
2430e6b6b59SJacob Faibussowitsch #define PETSC_DEVICE_IMPL_BASE_CLASS_HEADER(base_name, T) \
2440e6b6b59SJacob Faibussowitsch   using base_name = ::Petsc::device::impl::DeviceBase<T>; \
2450e6b6b59SJacob Faibussowitsch   friend base_name; \
2460e6b6b59SJacob Faibussowitsch   using base_name::base_name
247