xref: /petsc/src/sys/objects/device/tests/petscdevicetestcommon.h (revision 19a20e4ccaa848451342107d37410bc58500e44e)
1 #ifndef PETSCDEVICE_H
2 #error "included this file before petscdevice.h, this file must be included last to ensure that public petsc headers are well formed"
3 #endif
4 #ifndef PETSCDEVICETESTCOMMON_H
5 #define PETSCDEVICETESTCOMMON_H
6 
7 /* all of the error checking macros are undefined and redefined verbatim so that they are also
8  * defined for optimized builds.
9  */
10 #undef PetscValidDeviceType
11 #undef PetscValidDevice
12 #undef PetscCheckCompatibleDevices
13 #undef PetscValidStreamType
14 #undef PetscValidDeviceContext
15 #undef PetscCheckCompatibleDeviceContexts
16 
17 #define PetscValidDeviceType(_p_dev_type__,_p_arg__) do {               \
18     if (PetscUnlikely(((_p_dev_type__) < PETSC_DEVICE_INVALID) ||       \
19                       ((_p_dev_type__) > PETSC_DEVICE_MAX))) {          \
20       SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,              \
21                "Unknown PetscDeviceType '%d': Argument #%d",            \
22                (_p_dev_type__),(_p_arg__));                             \
23     } else if (PetscUnlikely(!PetscDeviceConfiguredFor_Internal(_p_dev_type__))) { \
24       switch(_p_dev_type__) {                                           \
25       case PETSC_DEVICE_INVALID:                                        \
26         SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,                         \
27                  "Invalid PetscDeviceType '%s': Argument #%d;"          \
28                  " PETSc is not configured with device support",        \
29                  PetscDeviceTypes[_p_dev_type__],(_p_arg__));           \
30         break;                                                          \
31       case PETSC_DEVICE_MAX:                                            \
32         SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,                  \
33                  "Invalid PetscDeviceType '%s': Argument #%d",          \
34                  PetscDeviceTypes[_p_dev_type__],(_p_arg__));           \
35         break;                                                          \
36       default:                                                          \
37         SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_SUP,                         \
38                  "Not configured for PetscDeviceType '%s': Argument #%d;" \
39                  " run configure --help %s for available options",      \
40                  PetscDeviceTypes[_p_dev_type__],(_p_arg__),            \
41                  PetscDeviceTypes[_p_dev_type__]);                      \
42         break;                                                          \
43       }                                                                 \
44     }                                                                   \
45   } while (0)
46 
47 #define PetscValidDevice(_p_dev__,_p_arg__)          do {       \
48     PetscValidPointer(_p_dev__,_p_arg__);                       \
49     PetscValidDeviceType((_p_dev__)->type,_p_arg__);            \
50     if (PetscUnlikely((_p_dev__)->id < 0)) {                    \
51       SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,                  \
52                "Invalid PetscDevice: Argument #%d; id %D < 0",  \
53                (_p_arg__),(_p_dev__)->id);                      \
54     } else if (PetscUnlikely((_p_dev__)->refcnt < 0)) {         \
55       SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,                  \
56                "Invalid PetscDevice: Argument #%d; "            \
57                "negative reference count %D",                   \
58                (_p_arg__),(_p_dev__)->refcnt);                  \
59     }                                                           \
60   } while (0)
61 
62 /* for now just checks strict equality, but this can be changed as some devices
63    (i.e. kokkos and any cupm should be compatible once implemented) */
64 #define PetscCheckCompatibleDevices(_p_dev1__,_p_arg1__,_p_dev2__,_p_arg2__) \
65   do {                                                                  \
66     PetscValidDevice(_p_dev1__,_p_arg1__);                              \
67     PetscValidDevice(_p_dev2__,_p_arg2__);                              \
68     if (PetscUnlikely((_p_dev1__)->type != (_p_dev2__)->type)) {        \
69       SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,                    \
70                "PetscDevices are incompatible: Arguments #%d and #%d",  \
71                (_p_arg1__),(_p_arg2__));                                \
72     }                                                                   \
73  } while (0)
74 
75 #define PetscValidStreamType(_p_strm_type__,_p_arg__)  do {             \
76     if (PetscUnlikely(((_p_strm_type__) < 0) ||                         \
77                       ((_p_strm_type__) > PETSC_STREAM_MAX))) {         \
78       SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,              \
79                "Unknown PetscStreamType '%d': Argument #%d",            \
80                (_p_strm_type__),(_p_arg__));                            \
81     } else if (PetscUnlikely((_p_strm_type__) == PETSC_STREAM_MAX)) {   \
82       SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,                    \
83                "Invalid PetscStreamType '%s': Argument #%d",            \
84                PetscStreamTypes[_p_strm_type__],(_p_arg__));            \
85     }                                                                   \
86   } while (0)
87 
88 #define PetscValidDeviceContext(_p_dev_ctx__,_p_arg__) do {             \
89     PetscValidPointer(_p_dev_ctx__,_p_arg__);                           \
90     PetscValidStreamType((_p_dev_ctx__)->streamType,_p_arg__);          \
91     if ((_p_dev_ctx__)->device) {                                       \
92       PetscValidDevice((_p_dev_ctx__)->device,_p_arg__);                \
93     } else if (PetscUnlikely((_p_dev_ctx__)->setup)) {                  \
94       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,                \
95                "Invalid PetscDeviceContext: Argument #%d; "             \
96                "PetscDeviceContext is setup but has no PetscDevice",    \
97                (_p_arg__));                                             \
98     }                                                                   \
99     if (PetscUnlikely((_p_dev_ctx__)->id < 1)) {                        \
100       SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,                          \
101                "Invalid PetscDeviceContext: Argument #%d; id %D < 1",   \
102                (_p_arg__),(_p_dev_ctx__)->id);                          \
103     } else if (PetscUnlikely((_p_dev_ctx__)->numChildren      >         \
104                              (_p_dev_ctx__)->maxNumChildren)) {         \
105       SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_CORRUPT,                   \
106                "Invalid PetscDeviceContext: Argument #%d; "             \
107                "number of children %D > max number of children %D",     \
108                (_p_arg__),(_p_dev_ctx__)->numChildren,                  \
109                (_p_dev_ctx__)->maxNumChildren);                         \
110     }                                                                   \
111   } while (0)
112 
113 #define PetscCheckCompatibleDeviceContexts(_p_dev_ctx1__,_p_arg1__,_p_dev_ctx2__,_p_arg2__) \
114   do {                                                                  \
115     PetscValidDeviceContext(_p_dev_ctx1__,_p_arg1__);                   \
116     PetscValidDeviceContext(_p_dev_ctx2__,_p_arg2__);                   \
117     PetscCheckCompatibleDevices((_p_dev_ctx1__)->device,_p_arg1__,      \
118                                 (_p_dev_ctx2__)->device,_p_arg2__);     \
119   } while (0)
120 
121 /*  This header file should NEVER #include another file and should be the last thing included
122  *  in the test file. This is to guard against ill-formed PetscDevice header files!
123  */
124 PETSC_STATIC_INLINE PetscErrorCode AssertDeviceExists(PetscDevice device)
125 {
126   PetscFunctionBegin;
127   PetscValidDevice(device,1);
128   PetscFunctionReturn(0);
129 }
130 
131 PETSC_STATIC_INLINE PetscErrorCode AssertDeviceDoesNotExist(PetscDevice device)
132 {
133   PetscFunctionBegin;
134   if (device) {
135     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"PetscDevice was not destroyed for type %s",PetscDeviceTypes[device->type]);
136   }
137   PetscFunctionReturn(0);
138 }
139 
140 PETSC_STATIC_INLINE PetscErrorCode AssertDeviceContextExists(PetscDeviceContext dctx)
141 {
142   PetscFunctionBegin;
143   PetscValidDeviceContext(dctx,1);
144   PetscFunctionReturn(0);
145 }
146 
147 PETSC_STATIC_INLINE PetscErrorCode AssertDeviceContextDoesNotExist(PetscDeviceContext dctx)
148 {
149   PetscFunctionBegin;
150   if (dctx) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"PetscDeviceContext was not destroyed");
151   PetscFunctionReturn(0);
152 }
153 
154 PETSC_STATIC_INLINE PetscErrorCode AssertPetscStreamTypesValidAndEqual(PetscStreamType left, PetscStreamType right, const char *errStr)
155 {
156   PetscFunctionBegin;
157   PetscValidStreamType(left,1);
158   PetscValidStreamType(right,2);
159   if (left != right) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_CORRUPT,errStr,PetscStreamTypes[left],PetscStreamTypes[right]);
160   PetscFunctionReturn(0);
161 }
162 
163 PETSC_STATIC_INLINE PetscErrorCode AssertPetscDevicesValidAndEqual(PetscDevice left, PetscDevice right, const char *errStr)
164 {
165   PetscFunctionBegin;
166   PetscCheckCompatibleDevices(left,1,right,2);
167   if (left != right) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_CORRUPT,errStr);
168   PetscFunctionReturn(0);
169 }
170 
171 PETSC_STATIC_INLINE PetscErrorCode AssertPetscDeviceContextsValidAndEqual(PetscDeviceContext left, PetscDeviceContext right, const char *errStr)
172 {
173   PetscFunctionBegin;
174   PetscCheckCompatibleDeviceContexts(left,1,right,2);
175   if (left != right) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,errStr);
176   PetscFunctionReturn(0);
177 }
178 #endif /* PETSCDEVICETESTCOMMON_H */
179