xref: /petsc/include/petsc/private/petschypre.h (revision 2c105492db5f6d1499b6276c712f7e1cdf3cdaa3)
1 #pragma once
2 
3 #include <petscsys.h>
4 #include <petscpkg_version.h>
5 #include <HYPRE_config.h>
6 #include <HYPRE_utilities.h>
7 
8 /* from version 2.16 on, HYPRE_BigInt is 64-bit for 64-bit pointer installations
9    and 32-bit for 32-bit installations -> not the best name for a variable */
10 #if PETSC_PKG_HYPRE_VERSION_LT(2, 16, 0)
11 typedef PetscInt HYPRE_BigInt;
12 #endif
13 
14 #if defined(HYPRE_BIGINT) || defined(HYPRE_MIXEDINT)
15   #define PetscHYPRE_BigInt_FMT "lld"
16   #ifdef __cplusplus /* make sure our format specifiers line up */
17     #include <type_traits>
18 static_assert(std::is_same<HYPRE_BigInt, long long int>::value, "");
19   #endif
20 #else
21   #define PetscHYPRE_BigInt_FMT "d"
22   #ifdef __cplusplus /* make sure our format specifiers line up */
23     #include <type_traits>
24 static_assert(std::is_same<HYPRE_BigInt, int>::value, "");
25   #endif
26 #endif
27 
28 #if defined(PETSC_CLANG_STATIC_ANALYZER)
29 void PetscCallHYPRE(HYPRE_Int);
30 #else
31   #if PETSC_PKG_HYPRE_VERSION_GT(2, 0, 0) /* HYPRE_DescribeError() added in 2.0.0 */
32     #define PetscCallHYPRE(...) \
33       do { \
34         if (PetscUnlikelyDebug(HYPRE_GetError() != 0)) { \
35           char err_str[PETSC_MAX_PATH_LEN]; \
36           HYPRE_DescribeError(HYPRE_GetError(), err_str); \
37           SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "HYPRE error from previous HYPRE call, error code %" PetscInt_FMT ": %s", (PetscInt)HYPRE_GetError(), err_str); \
38         } \
39         HYPRE_Int ierr_hypre_ = __VA_ARGS__; \
40         if (PetscUnlikely(ierr_hypre_ != 0)) { \
41           char err_str[PETSC_MAX_PATH_LEN]; \
42           HYPRE_DescribeError(ierr_hypre_, err_str); \
43           SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "HYPRE error code %" PetscInt_FMT ": %s", (PetscInt)ierr_hypre_, err_str); \
44         } \
45       } while (0)
46   #elif PETSC_PKG_HYPRE_VERSION_GE(1, 11, 0) /* HYPRE_GetError() added in 1.11.0b */
47     #define PetscCallHYPRE(...) \
48       do { \
49         PetscAssert(HYPRE_GetError() == 0, PETSC_COMM_SELF, PETSC_ERR_LIB, "HYPRE error from previous HYPRE call, error code %" PetscInt_FMT, (PetscInt)HYPRE_GetError()); \
50         HYPRE_Int ierr_hypre_ = __VA_ARGS__; \
51         PetscCheck(ierr_hypre_ == 0, PETSC_COMM_SELF, PETSC_ERR_LIB, "HYPRE error code %" PetscInt_FMT, (PetscInt)ierr_hypre_); \
52       } while (0)
53   #else /* PETSC_PKG_HYPRE_VERSION_LT(1, 11, 0) */
54     #define PetscCallHYPRE(...) \
55       do { \
56         HYPRE_Int ierr_hypre_ = __VA_ARGS__; \
57         PetscCheck(ierr_hypre_ == 0, PETSC_COMM_SELF, PETSC_ERR_LIB, "HYPRE error code %" PetscInt_FMT, (PetscInt)ierr_hypre_); \
58       } while (0)
59   #endif /* PETSC_PKG_HYPRE_VERSION */
60 #endif   /* PETSC_CLANG_STATIC_ANALYZER */
61 
62 /*
63   With scalar type == real, HYPRE_Complex == PetscScalar;
64   With scalar type == complex,  HYPRE_Complex is double __complex__ while PetscScalar may be std::complex<double>
65 */
PetscHYPREScalarCast(PetscScalar a,HYPRE_Complex * b)66 static inline PetscErrorCode PetscHYPREScalarCast(PetscScalar a, HYPRE_Complex *b)
67 {
68   PetscFunctionBegin;
69 #if defined(HYPRE_COMPLEX)
70   ((PetscReal *)b)[0] = PetscRealPart(a);
71   ((PetscReal *)b)[1] = PetscImaginaryPart(a);
72 #else
73   *b = a;
74 #endif
75   PetscFunctionReturn(PETSC_SUCCESS);
76 }
77 
78 #if PETSC_PKG_HYPRE_VERSION_GT(2, 28, 0) || (PETSC_PKG_HYPRE_VERSION_EQ(2, 28, 0) && defined(HYPRE_DEVELOP_NUMBER) && HYPRE_DEVELOP_NUMBER >= 22)
PetscHYPREFinalize_Private(void)79 static inline PetscErrorCode PetscHYPREFinalize_Private(void)
80 {
81   PetscFunctionBegin;
82   if (HYPRE_Initialized() && !HYPRE_Finalized()) PetscCallHYPRE(HYPRE_Finalize());
83   PetscFunctionReturn(PETSC_SUCCESS);
84 }
85 
86 PETSC_EXTERN PetscBool use_gpu_aware_mpi;
87 /*
88   Options Database Keys:
89 . -hypre_umpire_device_pool_size <n>  - set the Umpire device memory pool size (in MiB). HYPRE uses 4 GiB by default.
90 */
PetscHYPREInitialize(void)91 static inline PetscErrorCode PetscHYPREInitialize(void)
92 {
93   PetscFunctionBegin;
94   if (!HYPRE_Initialized()) {
95     PetscCallHYPRE(HYPRE_Initialize());
96   #if defined(HYPRE_USING_UMPIRE_DEVICE)
97     PetscInt  size = 0;
98     PetscBool set  = PETSC_FALSE;
99 
100     PetscCall(PetscOptionsGetInt(NULL, NULL, "-hypre_umpire_device_pool_size", &size, &set));
101     if (set) {
102       PetscCheck(size >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "-hypre_umpire_device_pool_size must be non-negative");
103       PetscCallHYPRE(HYPRE_SetUmpireDevicePoolSize((size_t)(size << 20))); // converr to size in bytes
104     } else if (PetscCIEnabled) {
105       // Set smaller pool size for CI tests to avoid OOM, but keep the default for users
106       PetscCallHYPRE(HYPRE_SetUmpireDevicePoolSize((size_t)(256 << 20))); // 256 MiB
107     }
108   #endif
109   // hypre-2.31.0 added HYPRE_SetGpuAwareMPI.
110   // HYPRE_USING_GPU_AWARE_MPI indicates hypre is configured with --enable-gpu-aware-mpi.
111   // HYPRE_SetGpuAwareMPI() controls whether to actually use GPU-aware MPI.
112   #if PETSC_PKG_HYPRE_VERSION_GE(2, 31, 0) && defined(HYPRE_USING_GPU_AWARE_MPI)
113     PetscCallHYPRE(HYPRE_SetGpuAwareMPI(use_gpu_aware_mpi ? 1 : 0));
114   #endif
115     PetscCall(PetscRegisterFinalize(PetscHYPREFinalize_Private));
116   }
117   PetscFunctionReturn(PETSC_SUCCESS);
118 }
119 #else
PetscHYPREInitialize(void)120 static inline PetscErrorCode PetscHYPREInitialize(void)
121 {
122   PetscFunctionBegin;
123   PetscFunctionReturn(PETSC_SUCCESS);
124 }
125 #endif
126 
127 #if PETSC_PKG_HYPRE_VERSION_LT(2, 19, 0)
128 typedef int HYPRE_MemoryLocation;
129   #define hypre_IJVectorMemoryLocation(a) 0
130   #define hypre_IJMatrixMemoryLocation(a) 0
131 #endif
132