Actual source code: cupmsolverinterface.hpp

  1: #pragma once

  3: #include <petsc/private/cupmblasinterface.hpp>

  5: namespace Petsc
  6: {

  8: namespace device
  9: {

 11: namespace cupm
 12: {

 14: namespace impl
 15: {

 17: #define PetscCallCUPMSOLVER_(__abort_fn__, __comm__, ...) \
 18:   do { \
 19:     PetscStackUpdateLine; \
 20:     const cupmSolverError_t cupmsolver_stat_p_ = __VA_ARGS__; \
 21:     if (PetscUnlikely(cupmsolver_stat_p_ != CUPMSOLVER_STATUS_SUCCESS)) { \
 22:       if ((cupmsolver_stat_p_ == CUPMSOLVER_STATUS_NOT_INITIALIZED || cupmsolver_stat_p_ == CUPMSOLVER_STATUS_ALLOC_FAILED || cupmsolver_stat_p_ == CUPMSOLVER_STATUS_INTERNAL_ERROR) && PetscDeviceInitialized(PETSC_DEVICE_CUPM())) { \
 23:         __abort_fn__(__comm__, PETSC_ERR_GPU_RESOURCE, \
 24:                      "%s error %d (%s). " \
 25:                      "This indicates the GPU may have run out resources", \
 26:                      cupmSolverName(), static_cast<PetscErrorCode>(cupmsolver_stat_p_), cupmSolverGetErrorName(cupmsolver_stat_p_)); \
 27:       } \
 28:       __abort_fn__(__comm__, PETSC_ERR_GPU, "%s error %d (%s)", cupmSolverName(), static_cast<PetscErrorCode>(cupmsolver_stat_p_), cupmSolverGetErrorName(cupmsolver_stat_p_)); \
 29:     } \
 30:   } while (0)

 32: #define PetscCallCUPMSOLVER(...)             PetscCallCUPMSOLVER_(SETERRQ, PETSC_COMM_SELF, __VA_ARGS__)
 33: #define PetscCallCUPMSOLVERAbort(comm_, ...) PetscCallCUPMSOLVER_(SETERRABORT, comm_, __VA_ARGS__)

 35: #if !defined(PetscConcat3)
 36:   #define PetscConcat3(a, b, c) PetscConcat(PetscConcat(a, b), c)
 37: #endif

 39: #if PetscDefined(USE_COMPLEX)
 40:   #define PETSC_CUPMSOLVER_FP_TYPE_SPECIAL un
 41: #else
 42:   #define PETSC_CUPMSOLVER_FP_TYPE_SPECIAL or
 43: #endif // USE_COMPLEX

 45: #define PETSC_CUPMSOLVER_ALIAS_BLAS_FUNCTION(cupm_name, their_prefix, fp_type, suffix) PETSC_CUPM_ALIAS_FUNCTION(cupm_name, PetscConcat3(their_prefix, fp_type, suffix))

 47: template <DeviceType>
 48: struct SolverInterfaceImpl;

 50: #if PetscDefined(HAVE_CUDA)
 51: template <>
 52: struct PETSC_SINGLE_LIBRARY_VISIBILITY_INTERNAL SolverInterfaceImpl<DeviceType::CUDA> : BlasInterface<DeviceType::CUDA> {
 53:   // typedefs
 54:   using cupmSolverHandle_t    = cusolverDnHandle_t;
 55:   using cupmSolverError_t     = cusolverStatus_t;
 56:   using cupmSolverFillMode_t  = cublasFillMode_t;
 57:   using cupmSolverOperation_t = cublasOperation_t;

 59:   // error codes
 60:   static const auto CUPMSOLVER_STATUS_SUCCESS         = CUSOLVER_STATUS_SUCCESS;
 61:   static const auto CUPMSOLVER_STATUS_NOT_INITIALIZED = CUSOLVER_STATUS_NOT_INITIALIZED;
 62:   static const auto CUPMSOLVER_STATUS_ALLOC_FAILED    = CUSOLVER_STATUS_ALLOC_FAILED;
 63:   static const auto CUPMSOLVER_STATUS_INTERNAL_ERROR  = CUSOLVER_STATUS_INTERNAL_ERROR;

 65:   // enums
 66:   // Why do these exist just to alias the CUBLAS versions? Because AMD -- in their boundless
 67:   // wisdom -- decided to do so for hipSOLVER...
 68:   // https://github.com/ROCmSoftwarePlatform/hipSOLVER/blob/develop/library/include/internal/hipsolver-types.h
 69:   static const auto CUPMSOLVER_OP_T            = CUBLAS_OP_T;
 70:   static const auto CUPMSOLVER_OP_N            = CUBLAS_OP_N;
 71:   static const auto CUPMSOLVER_OP_C            = CUBLAS_OP_C;
 72:   static const auto CUPMSOLVER_FILL_MODE_LOWER = CUBLAS_FILL_MODE_LOWER;
 73:   static const auto CUPMSOLVER_FILL_MODE_UPPER = CUBLAS_FILL_MODE_UPPER;
 74:   static const auto CUPMSOLVER_SIDE_LEFT       = CUBLAS_SIDE_LEFT;
 75:   static const auto CUPMSOLVER_SIDE_RIGHT      = CUBLAS_SIDE_RIGHT;

 77:   // utility functions
 78:   PETSC_CUPM_ALIAS_FUNCTION(cupmSolverCreate, cusolverDnCreate)
 79:   PETSC_CUPM_ALIAS_FUNCTION(cupmSolverDestroy, cusolverDnDestroy)
 80:   PETSC_CUPM_ALIAS_FUNCTION(cupmSolverSetStream, cusolverDnSetStream)
 81:   PETSC_CUPM_ALIAS_FUNCTION(cupmSolverGetStream, cusolverDnGetStream)

 83:   PETSC_CUPMSOLVER_ALIAS_BLAS_FUNCTION(cupmSolverXpotrf_bufferSize, cusolverDn, PETSC_CUPMBLAS_FP_TYPE_U, potrf_bufferSize)
 84:   PETSC_CUPMSOLVER_ALIAS_BLAS_FUNCTION(cupmSolverXpotrf, cusolverDn, PETSC_CUPMBLAS_FP_TYPE_U, potrf)

 86:   using cupmBlasInt_t = typename BlasInterface<DeviceType::CUDA>::cupmBlasInt_t;
 87:   using cupmScalar_t  = typename Interface<DeviceType::CUDA>::cupmScalar_t;

 89:   // to match hipSOLVER version (rocm 5.4.3, CUDA 12.0.1):
 90:   //
 91:   // hipsolverStatus_t hipsolverDpotrs_bufferSize(
 92:   //   hipsolverHandle_t handle, hipsolverFillMode_t uplo, int n, int nrhs, double *A, int lda,
 93:   //   double *B, int ldb, int *lwork
 94:   // )
 95:   //
 96:   // hipsolverStatus_t hipsolverDpotrs(
 97:   //   hipsolverHandle_t handle, hipsolverFillMode_t uplo, int n, int nrhs, double *A, int lda,
 98:   //   double *B, int ldb, double *work, int lwork, int *devInfo
 99:   // )
100:   PETSC_NODISCARD static cupmSolverError_t cupmSolverXpotrs_bufferSize(cupmSolverHandle_t /* handle */, cupmSolverFillMode_t /* uplo */, cupmBlasInt_t /* n */, cupmBlasInt_t /* nrhs */, cupmScalar_t * /* A */, cupmBlasInt_t /* lda */, cupmScalar_t * /* B */, cupmBlasInt_t /* ldb */, cupmBlasInt_t *lwork) noexcept
101:   {
102:     *lwork = 0;
103:     return CUPMSOLVER_STATUS_SUCCESS;
104:   }

106:   PETSC_CUPMSOLVER_ALIAS_BLAS_FUNCTION(cupmSolverXpotrs_p, cusolverDn, PETSC_CUPMBLAS_FP_TYPE_U, potrs)

108:   PETSC_NODISCARD static cupmSolverError_t cupmSolverXpotrs(cupmSolverHandle_t handle, cupmSolverFillMode_t uplo, cupmBlasInt_t n, cupmBlasInt_t nrhs, const cupmScalar_t *A, cupmBlasInt_t lda, cupmScalar_t *B, cupmBlasInt_t ldb, cupmScalar_t * /* work */, cupmBlasInt_t /* lwork */, cupmBlasInt_t *dev_info) noexcept
109:   {
110:     return cupmSolverXpotrs_p(handle, uplo, n, nrhs, A, lda, B, ldb, dev_info);
111:   }

113:   PETSC_CUPMSOLVER_ALIAS_BLAS_FUNCTION(cupmSolverXpotri_bufferSize, cusolverDn, PETSC_CUPMBLAS_FP_TYPE_U, potri_bufferSize)
114:   PETSC_CUPMSOLVER_ALIAS_BLAS_FUNCTION(cupmSolverXpotri, cusolverDn, PETSC_CUPMBLAS_FP_TYPE_U, potri)

116:   PETSC_CUPMSOLVER_ALIAS_BLAS_FUNCTION(cupmSolverXsytrf_bufferSize, cusolverDn, PETSC_CUPMBLAS_FP_TYPE_U, sytrf_bufferSize)
117:   PETSC_CUPMSOLVER_ALIAS_BLAS_FUNCTION(cupmSolverXsytrf, cusolverDn, PETSC_CUPMBLAS_FP_TYPE_U, sytrf)

119:   PETSC_CUPMSOLVER_ALIAS_BLAS_FUNCTION(cupmSolverXgetrf_bufferSize, cusolverDn, PETSC_CUPMBLAS_FP_TYPE_U, getrf_bufferSize)
120:   PETSC_CUPMSOLVER_ALIAS_BLAS_FUNCTION(cupmSolverXgetrf_p, cusolverDn, PETSC_CUPMBLAS_FP_TYPE_U, getrf)
121:   // to match hipSOLVER version (rocm 5.4.3, CUDA 12.0.1):
122:   //
123:   // hipsolverStatus_t hipsolverDgetrf(
124:   //   hipsolverHandle_t handle, int m, int n, double *A, int lda, double *work, int lwork,
125:   //   int *devIpiv, int *devInfo
126:   // )
127:   PETSC_NODISCARD static cupmSolverError_t cupmSolverXgetrf(cupmSolverHandle_t handle, cupmBlasInt_t m, cupmBlasInt_t n, cupmScalar_t *A, cupmBlasInt_t lda, cupmScalar_t *work, cupmBlasInt_t /* lwork */, cupmBlasInt_t *dev_ipiv, cupmBlasInt_t *dev_info) noexcept
128:   {
129:     return cupmSolverXgetrf_p(handle, m, n, A, lda, work, dev_ipiv, dev_info);
130:   }

132:   // to match hipSOLVER version (rocm 5.4.3, CUDA 12.0.1):
133:   //
134:   // hipsolverStatus_t hipsolverDgetrs_bufferSize(
135:   //   hipsolverHandle_t handle, hipsolverOperation_t trans, int n, int nrhs, double *A,
136:   //   int lda, int *devIpiv, double *B, int ldb, int *lwork
137:   // )
138:   //
139:   // hipsolverStatus_t hipsolverDgetrs(
140:   //   hipsolverHandle_t handle, hipsolverOperation_t trans, int n, int nrhs, double *A,
141:   //   int lda, int *devIpiv, double *B, int ldb, double *work, int lwork, int *devInfo
142:   // )
143:   PETSC_NODISCARD static cupmSolverError_t cupmSolverXgetrs_bufferSize(cupmSolverHandle_t /* handle */, cupmSolverOperation_t /* op */, cupmBlasInt_t /* n */, cupmBlasInt_t /* nrhs */, cupmScalar_t * /* A */, cupmBlasInt_t /* lda */, cupmBlasInt_t * /* devIpiv */, cupmScalar_t * /* B */, cupmBlasInt_t /* ldb */, cupmBlasInt_t *lwork) noexcept
144:   {
145:     *lwork = 0;
146:     return CUPMSOLVER_STATUS_SUCCESS;
147:   }

149:   PETSC_CUPMSOLVER_ALIAS_BLAS_FUNCTION(cupmSolverXgetrs_p, cusolverDn, PETSC_CUPMBLAS_FP_TYPE_U, getrs)

151:   PETSC_NODISCARD static cupmSolverError_t cupmSolverXgetrs(cupmSolverHandle_t handle, cupmSolverOperation_t op, cupmBlasInt_t n, cupmBlasInt_t nrhs, cupmScalar_t *A, cupmBlasInt_t lda, cupmBlasInt_t *dev_ipiv, cupmScalar_t *B, cupmBlasInt_t ldb, cupmScalar_t * /* work */, cupmBlasInt_t /* lwork */, cupmBlasInt_t *dev_info) noexcept
152:   {
153:     return cupmSolverXgetrs_p(handle, op, n, nrhs, A, lda, dev_ipiv, B, ldb, dev_info);
154:   }

156:   PETSC_CUPMSOLVER_ALIAS_BLAS_FUNCTION(cupmSolverXgeqrf_bufferSize, cusolverDn, PETSC_CUPMBLAS_FP_TYPE_U, geqrf_bufferSize)
157:   PETSC_CUPMSOLVER_ALIAS_BLAS_FUNCTION(cupmSolverXgeqrf, cusolverDn, PETSC_CUPMBLAS_FP_TYPE_U, geqrf)

159:   PETSC_CUPMSOLVER_ALIAS_BLAS_FUNCTION(cupmSolverXormqr_bufferSize, cusolverDn, PetscConcat(PETSC_CUPMBLAS_FP_TYPE_U, PETSC_CUPMSOLVER_FP_TYPE_SPECIAL), mqr_bufferSize)
160:   PETSC_CUPMSOLVER_ALIAS_BLAS_FUNCTION(cupmSolverXormqr, cusolverDn, PetscConcat(PETSC_CUPMBLAS_FP_TYPE_U, PETSC_CUPMSOLVER_FP_TYPE_SPECIAL), mqr)

162:   PETSC_NODISCARD static const char *cupmSolverGetErrorName(cupmSolverError_t status) noexcept { return PetscCUSolverGetErrorName(status); }
163: };
164: #endif

166: #if PetscDefined(HAVE_HIP)
167: template <>
168: struct PETSC_SINGLE_LIBRARY_VISIBILITY_INTERNAL SolverInterfaceImpl<DeviceType::HIP> : BlasInterface<DeviceType::HIP> {
169:   // typedefs
170:   using cupmSolverHandle_t    = hipsolverHandle_t;
171:   using cupmSolverError_t     = hipsolverStatus_t;
172:   using cupmSolverFillMode_t  = hipsolverFillMode_t;
173:   using cupmSolverOperation_t = hipsolverOperation_t;

175:   // error codes
176:   static const auto CUPMSOLVER_STATUS_SUCCESS         = HIPSOLVER_STATUS_SUCCESS;
177:   static const auto CUPMSOLVER_STATUS_NOT_INITIALIZED = HIPSOLVER_STATUS_NOT_INITIALIZED;
178:   static const auto CUPMSOLVER_STATUS_ALLOC_FAILED    = HIPSOLVER_STATUS_ALLOC_FAILED;
179:   static const auto CUPMSOLVER_STATUS_INTERNAL_ERROR  = HIPSOLVER_STATUS_INTERNAL_ERROR;

181:   // enums
182:   static const auto CUPMSOLVER_OP_T            = HIPSOLVER_OP_T;
183:   static const auto CUPMSOLVER_OP_N            = HIPSOLVER_OP_N;
184:   static const auto CUPMSOLVER_OP_C            = HIPSOLVER_OP_C;
185:   static const auto CUPMSOLVER_FILL_MODE_LOWER = HIPSOLVER_FILL_MODE_LOWER;
186:   static const auto CUPMSOLVER_FILL_MODE_UPPER = HIPSOLVER_FILL_MODE_UPPER;
187:   static const auto CUPMSOLVER_SIDE_LEFT       = HIPSOLVER_SIDE_LEFT;
188:   static const auto CUPMSOLVER_SIDE_RIGHT      = HIPSOLVER_SIDE_RIGHT;

190:   PETSC_CUPM_ALIAS_FUNCTION(cupmSolverCreate, hipsolverCreate)
191:   PETSC_CUPM_ALIAS_FUNCTION(cupmSolverDestroy, hipsolverDestroy)
192:   PETSC_CUPM_ALIAS_FUNCTION(cupmSolverSetStream, hipsolverSetStream)
193:   PETSC_CUPM_ALIAS_FUNCTION(cupmSolverGetStream, hipsolverGetStream)

195:   PETSC_CUPMSOLVER_ALIAS_BLAS_FUNCTION(cupmSolverXpotrf_bufferSize, hipsolver, PETSC_CUPMBLAS_FP_TYPE_U, potrf_bufferSize)
196:   PETSC_CUPMSOLVER_ALIAS_BLAS_FUNCTION(cupmSolverXpotrf, hipsolver, PETSC_CUPMBLAS_FP_TYPE_U, potrf)

198:   PETSC_CUPMSOLVER_ALIAS_BLAS_FUNCTION(cupmSolverXpotrs_bufferSize, hipsolver, PETSC_CUPMBLAS_FP_TYPE_U, potrs_bufferSize)
199:   PETSC_CUPMSOLVER_ALIAS_BLAS_FUNCTION(cupmSolverXpotrs, hipsolver, PETSC_CUPMBLAS_FP_TYPE_U, potrs)

201:   PETSC_CUPMSOLVER_ALIAS_BLAS_FUNCTION(cupmSolverXpotri_bufferSize, hipsolver, PETSC_CUPMBLAS_FP_TYPE_U, potri_bufferSize)
202:   PETSC_CUPMSOLVER_ALIAS_BLAS_FUNCTION(cupmSolverXpotri, hipsolver, PETSC_CUPMBLAS_FP_TYPE_U, potri)

204:   PETSC_CUPMSOLVER_ALIAS_BLAS_FUNCTION(cupmSolverXsytrf_bufferSize, hipsolver, PETSC_CUPMBLAS_FP_TYPE_U, sytrf_bufferSize)
205:   PETSC_CUPMSOLVER_ALIAS_BLAS_FUNCTION(cupmSolverXsytrf, hipsolver, PETSC_CUPMBLAS_FP_TYPE_U, sytrf)

207:   PETSC_CUPMSOLVER_ALIAS_BLAS_FUNCTION(cupmSolverXgetrf_bufferSize, hipsolver, PETSC_CUPMBLAS_FP_TYPE_U, getrf_bufferSize)
208:   PETSC_CUPMSOLVER_ALIAS_BLAS_FUNCTION(cupmSolverXgetrf, hipsolver, PETSC_CUPMBLAS_FP_TYPE_U, getrf)

210:   PETSC_CUPMSOLVER_ALIAS_BLAS_FUNCTION(cupmSolverXgetrs_bufferSize, hipsolver, PETSC_CUPMBLAS_FP_TYPE_U, getrs_bufferSize)
211:   PETSC_CUPMSOLVER_ALIAS_BLAS_FUNCTION(cupmSolverXgetrs, hipsolver, PETSC_CUPMBLAS_FP_TYPE_U, getrs)

213:   PETSC_CUPMSOLVER_ALIAS_BLAS_FUNCTION(cupmSolverXgeqrf_bufferSize, hipsolver, PETSC_CUPMBLAS_FP_TYPE_U, geqrf_bufferSize)
214:   PETSC_CUPMSOLVER_ALIAS_BLAS_FUNCTION(cupmSolverXgeqrf, hipsolver, PETSC_CUPMBLAS_FP_TYPE_U, geqrf)

216:   PETSC_CUPMSOLVER_ALIAS_BLAS_FUNCTION(cupmSolverXormqr_bufferSize, hipsolver, PetscConcat(PETSC_CUPMBLAS_FP_TYPE_U, PETSC_CUPMSOLVER_FP_TYPE_SPECIAL), mqr_bufferSize)
217:   PETSC_CUPMSOLVER_ALIAS_BLAS_FUNCTION(cupmSolverXormqr, hipsolver, PetscConcat(PETSC_CUPMBLAS_FP_TYPE_U, PETSC_CUPMSOLVER_FP_TYPE_SPECIAL), mqr)

219:   PETSC_NODISCARD static const char *cupmSolverGetErrorName(cupmSolverError_t status) noexcept { return PetscHIPSolverGetErrorName(status); }
220: };
221: #endif

223: #define PETSC_CUPMSOLVER_IMPL_CLASS_HEADER(T) \
224:   PETSC_CUPMBLAS_INHERIT_INTERFACE_TYPEDEFS_USING(T); \
225:   /* introspection */ \
226:   using ::Petsc::device::cupm::impl::SolverInterfaceImpl<T>::cupmSolverGetErrorName; \
227:   /* types */ \
228:   using cupmSolverHandle_t    = typename ::Petsc::device::cupm::impl::SolverInterfaceImpl<T>::cupmSolverHandle_t; \
229:   using cupmSolverError_t     = typename ::Petsc::device::cupm::impl::SolverInterfaceImpl<T>::cupmSolverError_t; \
230:   using cupmSolverFillMode_t  = typename ::Petsc::device::cupm::impl::SolverInterfaceImpl<T>::cupmSolverFillMode_t; \
231:   using cupmSolverOperation_t = typename ::Petsc::device::cupm::impl::SolverInterfaceImpl<T>::cupmSolverOperation_t; \
232:   /* error codes */ \
233:   using ::Petsc::device::cupm::impl::SolverInterfaceImpl<T>::CUPMSOLVER_STATUS_SUCCESS; \
234:   using ::Petsc::device::cupm::impl::SolverInterfaceImpl<T>::CUPMSOLVER_STATUS_NOT_INITIALIZED; \
235:   using ::Petsc::device::cupm::impl::SolverInterfaceImpl<T>::CUPMSOLVER_STATUS_ALLOC_FAILED; \
236:   using ::Petsc::device::cupm::impl::SolverInterfaceImpl<T>::CUPMSOLVER_STATUS_INTERNAL_ERROR; \
237:   /* values */ \
238:   using ::Petsc::device::cupm::impl::SolverInterfaceImpl<T>::CUPMSOLVER_OP_T; \
239:   using ::Petsc::device::cupm::impl::SolverInterfaceImpl<T>::CUPMSOLVER_OP_N; \
240:   using ::Petsc::device::cupm::impl::SolverInterfaceImpl<T>::CUPMSOLVER_OP_C; \
241:   using ::Petsc::device::cupm::impl::SolverInterfaceImpl<T>::CUPMSOLVER_FILL_MODE_LOWER; \
242:   using ::Petsc::device::cupm::impl::SolverInterfaceImpl<T>::CUPMSOLVER_FILL_MODE_UPPER; \
243:   using ::Petsc::device::cupm::impl::SolverInterfaceImpl<T>::CUPMSOLVER_SIDE_LEFT; \
244:   using ::Petsc::device::cupm::impl::SolverInterfaceImpl<T>::CUPMSOLVER_SIDE_RIGHT; \
245:   /* utility functions */ \
246:   using ::Petsc::device::cupm::impl::SolverInterfaceImpl<T>::cupmSolverCreate; \
247:   using ::Petsc::device::cupm::impl::SolverInterfaceImpl<T>::cupmSolverDestroy; \
248:   using ::Petsc::device::cupm::impl::SolverInterfaceImpl<T>::cupmSolverGetStream; \
249:   using ::Petsc::device::cupm::impl::SolverInterfaceImpl<T>::cupmSolverSetStream; \
250:   /* blas functions */ \
251:   using ::Petsc::device::cupm::impl::SolverInterfaceImpl<T>::cupmSolverXpotrf_bufferSize; \
252:   using ::Petsc::device::cupm::impl::SolverInterfaceImpl<T>::cupmSolverXpotrf; \
253:   using ::Petsc::device::cupm::impl::SolverInterfaceImpl<T>::cupmSolverXpotrs_bufferSize; \
254:   using ::Petsc::device::cupm::impl::SolverInterfaceImpl<T>::cupmSolverXpotrs; \
255:   using ::Petsc::device::cupm::impl::SolverInterfaceImpl<T>::cupmSolverXpotri_bufferSize; \
256:   using ::Petsc::device::cupm::impl::SolverInterfaceImpl<T>::cupmSolverXpotri; \
257:   using ::Petsc::device::cupm::impl::SolverInterfaceImpl<T>::cupmSolverXsytrf_bufferSize; \
258:   using ::Petsc::device::cupm::impl::SolverInterfaceImpl<T>::cupmSolverXsytrf; \
259:   using ::Petsc::device::cupm::impl::SolverInterfaceImpl<T>::cupmSolverXgetrf_bufferSize; \
260:   using ::Petsc::device::cupm::impl::SolverInterfaceImpl<T>::cupmSolverXgetrf; \
261:   using ::Petsc::device::cupm::impl::SolverInterfaceImpl<T>::cupmSolverXgetrs_bufferSize; \
262:   using ::Petsc::device::cupm::impl::SolverInterfaceImpl<T>::cupmSolverXgetrs; \
263:   using ::Petsc::device::cupm::impl::SolverInterfaceImpl<T>::cupmSolverXgeqrf_bufferSize; \
264:   using ::Petsc::device::cupm::impl::SolverInterfaceImpl<T>::cupmSolverXgeqrf; \
265:   using ::Petsc::device::cupm::impl::SolverInterfaceImpl<T>::cupmSolverXormqr_bufferSize; \
266:   using ::Petsc::device::cupm::impl::SolverInterfaceImpl<T>::cupmSolverXormqr

268: template <DeviceType T>
269: struct SolverInterface : SolverInterfaceImpl<T> {
270:   PETSC_NODISCARD static constexpr const char *cupmSolverName() noexcept { return T == DeviceType::CUDA ? "cusolverDn" : "hipsolver"; }
271: };

273: #define PETSC_CUPMSOLVER_INHERIT_INTERFACE_TYPEDEFS_USING(T) \
274:   PETSC_CUPMSOLVER_IMPL_CLASS_HEADER(T); \
275:   using ::Petsc::device::cupm::impl::SolverInterface<T>::cupmSolverName

277: #if PetscDefined(HAVE_CUDA)
278: extern template struct PETSC_SINGLE_LIBRARY_VISIBILITY_INTERNAL SolverInterface<DeviceType::CUDA>;
279: #endif

281: #if PetscDefined(HAVE_HIP)
282: extern template struct PETSC_SINGLE_LIBRARY_VISIBILITY_INTERNAL SolverInterface<DeviceType::HIP>;
283: #endif

285: } // namespace impl

287: } // namespace cupm

289: } // namespace device

291: } // namespace Petsc