1 
2 /*
3     Defines the basic header of all PETSc objects.
4 */
5 
6 #if !defined(PETSCIMPL_H)
7 #define PETSCIMPL_H
8 #include <petscsys.h>
9 
10 /* These are used internally by PETSc ASCII IO routines*/
11 #include <stdarg.h>
12 PETSC_EXTERN PetscErrorCode PetscVFPrintfDefault(FILE*,const char[],va_list);
13 
14 #if defined(PETSC_HAVE_CLOSURE)
15 PETSC_EXTERN PetscErrorCode PetscVFPrintfSetClosure(int (^)(const char*));
16 #endif
17 
18 /*
19    All major PETSc data structures have a common core; this is defined
20    below by PETSCHEADER.
21 
22    PetscHeaderCreate() should be used whenever creating a PETSc structure.
23 */
24 
25 /*
26    PetscOps: structure of core operations that all PETSc objects support.
27 
28       getcomm()         - Gets the object's communicator.
29       view()            - Is the routine for viewing the entire PETSc object; for
30                           example, MatView() is the general matrix viewing routine.
31                           This is used by PetscObjectView((PetscObject)obj) to allow
32                           viewing any PETSc object.
33       destroy()         - Is the routine for destroying the entire PETSc object;
34                           for example,MatDestroy() is the general matrix
35                           destruction routine.
36                           This is used by PetscObjectDestroy((PetscObject*)&obj) to allow
37                           destroying any PETSc object.
38       compose()         - Associates a PETSc object with another PETSc object with a name
39       query()           - Returns a different PETSc object that has been associated
40                           with the first object using a name.
41       composefunction() - Attaches an a function to a PETSc object with a name.
42       queryfunction()   - Requests a registered function that has been attached to a PETSc object.
43 */
44 
45 typedef struct {
46    PetscErrorCode (*getcomm)(PetscObject,MPI_Comm *);
47    PetscErrorCode (*view)(PetscObject,PetscViewer);
48    PetscErrorCode (*destroy)(PetscObject*);
49    PetscErrorCode (*compose)(PetscObject,const char[],PetscObject);
50    PetscErrorCode (*query)(PetscObject,const char[],PetscObject *);
51    PetscErrorCode (*composefunction)(PetscObject,const char[],void (*)(void));
52    PetscErrorCode (*queryfunction)(PetscObject,const char[],void (**)(void));
53 } PetscOps;
54 
55 typedef enum {PETSC_FORTRAN_CALLBACK_CLASS,PETSC_FORTRAN_CALLBACK_SUBTYPE,PETSC_FORTRAN_CALLBACK_MAXTYPE} PetscFortranCallbackType;
56 typedef int PetscFortranCallbackId;
57 #define PETSC_SMALLEST_FORTRAN_CALLBACK ((PetscFortranCallbackId)1000)
58 PETSC_EXTERN PetscErrorCode PetscFortranCallbackRegister(PetscClassId,const char*,PetscFortranCallbackId*);
59 PETSC_EXTERN PetscErrorCode PetscFortranCallbackGetSizes(PetscClassId,PetscInt*,PetscInt*);
60 
61 typedef struct {
62   void (*func)(void);
63   void *ctx;
64 } PetscFortranCallback;
65 
66 /*
67    All PETSc objects begin with the fields defined in PETSCHEADER.
68    The PetscObject is a way of examining these fields regardless of
69    the specific object. In C++ this could be a base abstract class
70    from which all objects are derived.
71 */
72 #define PETSC_MAX_OPTIONS_HANDLER 5
73 typedef struct _p_PetscObject {
74   PetscClassId         classid;
75   PetscOps             bops[1];
76   MPI_Comm             comm;
77   PetscInt             type;
78   PetscLogDouble       flops,time,mem,memchildren;
79   PetscObjectId        id;
80   PetscInt             refct;
81   PetscMPIInt          tag;
82   PetscFunctionList    qlist;
83   PetscObjectList      olist;
84   char                 *class_name;    /*  for example, "Vec" */
85   char                 *description;
86   char                 *mansec;
87   char                 *type_name;     /*  this is the subclass, for example VECSEQ which equals "seq" */
88   PetscObject          parent;
89   PetscObjectId        parentid;
90   char*                name;
91   char                 *prefix;
92   PetscInt             tablevel;
93   void                 *cpp;
94   PetscObjectState     state;
95   PetscInt             int_idmax,        intstar_idmax;
96   PetscObjectState     *intcomposedstate,*intstarcomposedstate;
97   PetscInt             *intcomposeddata, **intstarcomposeddata;
98   PetscInt             real_idmax,        realstar_idmax;
99   PetscObjectState     *realcomposedstate,*realstarcomposedstate;
100   PetscReal            *realcomposeddata, **realstarcomposeddata;
101   PetscInt             scalar_idmax,        scalarstar_idmax;
102   PetscObjectState     *scalarcomposedstate,*scalarstarcomposedstate;
103   PetscScalar          *scalarcomposeddata, **scalarstarcomposeddata;
104   void                 (**fortran_func_pointers)(void);                  /* used by Fortran interface functions to stash user provided Fortran functions */
105   PetscInt             num_fortran_func_pointers;                        /* number of Fortran function pointers allocated */
106   PetscFortranCallback *fortrancallback[PETSC_FORTRAN_CALLBACK_MAXTYPE];
107   PetscInt             num_fortrancallback[PETSC_FORTRAN_CALLBACK_MAXTYPE];
108   void                 *python_context;
109   PetscErrorCode       (*python_destroy)(void*);
110 
111   PetscInt             noptionhandler;
112   PetscErrorCode       (*optionhandler[PETSC_MAX_OPTIONS_HANDLER])(PetscOptionItems*,PetscObject,void*);
113   PetscErrorCode       (*optiondestroy[PETSC_MAX_OPTIONS_HANDLER])(PetscObject,void*);
114   void                 *optionctx[PETSC_MAX_OPTIONS_HANDLER];
115   PetscBool            optionsprinted;
116 #if defined(PETSC_HAVE_SAWS)
117   PetscBool            amsmem;          /* if PETSC_TRUE then this object is registered with SAWs and visible to clients */
118   PetscBool            amspublishblock; /* if PETSC_TRUE and publishing objects then will block at PetscObjectSAWsBlock() */
119 #endif
120   PetscOptions         options;         /* options database used, NULL means default */
121   PetscBool            donotPetscObjectPrintClassNamePrefixType;
122 } _p_PetscObject;
123 
124 #define PETSCHEADER(ObjectOps) \
125   _p_PetscObject hdr;          \
126   ObjectOps      ops[1]
127 
128 #define  PETSCFREEDHEADER -1
129 
130 PETSC_EXTERN_TYPEDEF typedef PetscErrorCode (*PetscObjectDestroyFunction)(PetscObject*); /* force cast in next macro to NEVER use extern "C" style */
131 PETSC_EXTERN_TYPEDEF typedef PetscErrorCode (*PetscObjectViewFunction)(PetscObject,PetscViewer);
132 
133 /*@C
134     PetscHeaderCreate - Creates a PETSc object of a particular class
135 
136     Input Parameters:
137 +   classid - the classid associated with this object (for example VEC_CLASSID)
138 .   class_name - string name of class; should be static (for example "Vec")
139 .   descr - string containing short description; should be static (for example "Vector")
140 .   mansec - string indicating section in manual pages; should be static (for example "Vec")
141 .   comm - the MPI Communicator
142 .   destroy - the destroy routine for this object (for example VecDestroy())
143 -   view - the view routine for this object (for example VecView())
144 
145     Output Parameter:
146 .   h - the newly created object
147 
148     Level: developer
149 
150 .seealso: PetscHeaderDestroy(), PetscClassIdRegister()
151 
152 @*/
153 #define PetscHeaderCreate(h,classid,class_name,descr,mansec,comm,destroy,view) \
154   (PetscNew(&(h)) || \
155    PetscHeaderCreate_Private((PetscObject)(h),classid,class_name,descr,mansec,comm,(PetscObjectDestroyFunction)(destroy),(PetscObjectViewFunction)(view)) || \
156    PetscLogObjectCreate(h) || \
157    PetscLogObjectMemory((PetscObject)(h),sizeof(*(h))))
158 
159 PETSC_EXTERN PetscErrorCode PetscComposedQuantitiesDestroy(PetscObject obj);
160 PETSC_EXTERN PetscErrorCode PetscHeaderCreate_Private(PetscObject,PetscClassId,const char[],const char[],const char[],MPI_Comm,PetscObjectDestroyFunction,PetscObjectViewFunction);
161 
162 /*@C
163     PetscHeaderDestroy - Final step in destroying a PetscObject
164 
165     Input Parameters:
166 .   h - the header created with PetscHeaderCreate()
167 
168     Level: developer
169 
170 .seealso: PetscHeaderCreate()
171 @*/
172 #define PetscHeaderDestroy(h) (PetscHeaderDestroy_Private((PetscObject)(*(h))) || PetscFree(*(h)))
173 
174 PETSC_EXTERN PetscErrorCode PetscHeaderDestroy_Private(PetscObject);
175 PETSC_EXTERN PetscErrorCode PetscObjectCopyFortranFunctionPointers(PetscObject,PetscObject);
176 PETSC_EXTERN PetscErrorCode PetscObjectSetFortranCallback(PetscObject,PetscFortranCallbackType,PetscFortranCallbackId*,void(*)(void),void *ctx);
177 PETSC_EXTERN PetscErrorCode PetscObjectGetFortranCallback(PetscObject,PetscFortranCallbackType,PetscFortranCallbackId,void(**)(void),void **ctx);
178 
179 PETSC_INTERN PetscErrorCode PetscCitationsInitialize(void);
180 PETSC_INTERN PetscErrorCode PetscFreeMPIResources(void);
181 PETSC_INTERN PetscErrorCode PetscOptionsHasHelpIntro_Internal(PetscOptions,PetscBool*);
182 
183 
184 PETSC_EXTERN PetscBool PetscCheckPointer(const void*,PetscDataType);
185 /*
186     Macros to test if a PETSc object is valid and if pointers are valid
187 */
188 #if !defined(PETSC_USE_DEBUG)
189 
190 #define PetscValidHeaderSpecific(h,ck,arg) do {(void)(h);} while (0)
191 #define PetscValidHeaderSpecificType(h,ck,arg,t) do {(void)(h);} while (0)
192 #define PetscValidHeader(h,arg) do {(void)(h);} while (0)
193 #define PetscValidPointer(h,arg) do {(void)(h);} while (0)
194 #define PetscValidCharPointer(h,arg) do {(void)(h);} while (0)
195 #define PetscValidIntPointer(h,arg) do {(void)(h);} while (0)
196 #define PetscValidBoolPointer(h,arg) do {(void)(h);} while (0)
197 #define PetscValidScalarPointer(h,arg) do {(void)(h);} while (0)
198 #define PetscValidRealPointer(h,arg) do {(void)(h);} while (0)
199 #define PetscValidFunction(h,arg) do {(void)(h);} while (0)
200 
201 #else
202 
203 /*  This check is for subtype methods such as DMDAGetCorners() that do not use the PetscTryMethod() or PetscUseMethod() paradigm */
204 #define PetscValidHeaderSpecificType(h,ck,arg,t) \
205   do {   \
206     PetscErrorCode _7_ierr; \
207     PetscBool      _7_same; \
208     PetscValidHeaderSpecific(h,ck,arg); \
209     _7_ierr = PetscObjectTypeCompare((PetscObject)(h),t,&_7_same);CHKERRQ(_7_ierr); \
210     if (!_7_same) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Wrong subtype object:Parameter # %d must have implementation %s it is %s",arg,t,((PetscObject)(h))->type_name); \
211   } while (0)
212 
213 #define PetscValidHeaderSpecific(h,ck,arg)                              \
214   do {                                                                  \
215     if (!(h)) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Null Object: Parameter # %d",arg); \
216     if (!PetscCheckPointer(h,PETSC_OBJECT)) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_CORRUPT,"Invalid Pointer to Object: Parameter # %d",arg); \
217     if (((PetscObject)(h))->classid != ck) {                            \
218       if (((PetscObject)(h))->classid == PETSCFREEDHEADER) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_CORRUPT,"Object already free: Parameter # %d",arg); \
219       else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Wrong type of object: Parameter # %d",arg); \
220     }                                                                   \
221   } while (0)
222 
223 #define PetscValidHeader(h,arg)                                         \
224   do {                                                                  \
225     if (!(h)) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Null Object: Parameter # %d",arg); \
226     if (!PetscCheckPointer(h,PETSC_OBJECT)) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_CORRUPT,"Invalid Pointer to Object: Parameter # %d",arg); \
227     if (((PetscObject)(h))->classid == PETSCFREEDHEADER) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_CORRUPT,"Object already free: Parameter # %d",arg); \
228     else if (((PetscObject)(h))->classid < PETSC_SMALLEST_CLASSID || ((PetscObject)(h))->classid > PETSC_LARGEST_CLASSID) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_CORRUPT,"Invalid type of object: Parameter # %d",arg); \
229   } while (0)
230 
231 #define PetscValidPointer(h,arg)                                        \
232   do {                                                                  \
233     if (!(h)) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Null Pointer: Parameter # %d",arg); \
234     if (!PetscCheckPointer(h,PETSC_CHAR)) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_BADPTR,"Invalid Pointer: Parameter # %d",arg); \
235   } while (0)
236 
237 #define PetscValidCharPointer(h,arg)                                    \
238   do {                                                                  \
239     if (!(h)) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Null Pointer: Parameter # %d",arg);\
240     if (!PetscCheckPointer(h,PETSC_CHAR)) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_BADPTR,"Invalid Pointer to char: Parameter # %d",arg); \
241   } while (0)
242 
243 #define PetscValidIntPointer(h,arg)                                     \
244   do {                                                                  \
245     if (!(h)) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_BADPTR,"Null Pointer: Parameter # %d",arg); \
246     if (!PetscCheckPointer(h,PETSC_INT)) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_BADPTR,"Invalid Pointer to PetscInt: Parameter # %d",arg); \
247   } while (0)
248 
249 #define PetscValidBoolPointer(h,arg)                                    \
250   do {                                                                  \
251     if (!(h)) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_BADPTR,"Null Pointer: Parameter # %d",arg); \
252     if (!PetscCheckPointer(h,PETSC_BOOL)) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_BADPTR,"Invalid Pointer to PetscBool: Parameter # %d",arg); \
253   } while (0)
254 
255 #define PetscValidScalarPointer(h,arg)                                  \
256   do {                                                                  \
257     if (!(h)) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Null Pointer: Parameter # %d",arg); \
258     if (!PetscCheckPointer(h,PETSC_SCALAR)) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_BADPTR,"Invalid Pointer to PetscScalar: Parameter # %d",arg); \
259   } while (0)
260 
261 #define PetscValidRealPointer(h,arg)                                    \
262   do {                                                                  \
263     if (!(h)) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Null Pointer: Parameter # %d",arg); \
264     if (!PetscCheckPointer(h,PETSC_REAL)) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_BADPTR,"Invalid Pointer to PetscReal: Parameter # %d",arg); \
265   } while (0)
266 
267 #define PetscValidFunction(f,arg)                                       \
268   do {                                                                  \
269     if (!(f)) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Null Function Pointer: Parameter # %d",arg); \
270   } while (0)
271 
272 #endif
273 
274 #define PetscSorted(n,idx,sorted)           \
275   do {                                      \
276     PetscInt _i_;                           \
277     (sorted) = PETSC_TRUE;                  \
278     for (_i_ = 1; _i_ < (n); _i_++)         \
279       if ((idx)[_i_] < (idx)[_i_ - 1])      \
280         { (sorted) = PETSC_FALSE; break; }  \
281   } while (0)
282 
283 #if !defined(PETSC_USE_DEBUG)
284 
285 #define PetscCheckSameType(a,arga,b,argb) do {(void)(a);(void)(b);} while (0)
286 #define PetscCheckTypeName(a,type) do {(void)(a);} while (0)
287 #define PetscCheckTypeNames(a,type1,type2) do {(void)(a);} while (0)
288 #define PetscValidType(a,arg) do {(void)(a);} while (0)
289 #define PetscCheckSameComm(a,arga,b,argb) do {(void)(a);(void)(b);} while (0)
290 #define PetscCheckSameTypeAndComm(a,arga,b,argb) do {(void)(a);(void)(b);} while (0)
291 #define PetscValidLogicalCollectiveScalar(a,b,arg) do {(void)(a);(void)(b);} while (0)
292 #define PetscValidLogicalCollectiveReal(a,b,arg) do {(void)(a);(void)(b);} while (0)
293 #define PetscValidLogicalCollectiveInt(a,b,arg) do {(void)(a);(void)(b);} while (0)
294 #define PetscValidLogicalCollectiveMPIInt(a,b,arg) do {(void)(a);(void)(b);} while (0)
295 #define PetscValidLogicalCollectiveBool(a,b,arg) do {(void)(a);(void)(b);} while (0)
296 #define PetscValidLogicalCollectiveEnum(a,b,arg) do {(void)(a);(void)(b);} while (0)
297 #define PetscCheckSorted(n,idx) do {(void)(n);(void)(idx);} while (0)
298 
299 #else
300 
301 /*
302     For example, in the dot product between two vectors,
303   both vectors must be either Seq or MPI, not one of each
304 */
305 #define PetscCheckSameType(a,arga,b,argb)                               \
306   do {                                                                  \
307     if (((PetscObject)(a))->type != ((PetscObject)(b))->type) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMETYPE,"Objects not of same type: Argument # %d and %d",arga,argb); \
308   } while (0)
309 /*
310     Check type_name
311 */
312 #define PetscCheckTypeName(a,type)                                      \
313   do {                                                                  \
314     PetscBool      _7_match;                                            \
315     PetscErrorCode _7_ierr;                                             \
316     _7_ierr = PetscObjectTypeCompare(((PetscObject)(a)),(type),&_7_match);CHKERRQ(_7_ierr); \
317     if (!_7_match) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Object (%s) is not %s",(char*)(((PetscObject)(a))->type_name),type); \
318   } while (0)
319 
320 #define PetscCheckTypeNames(a,type1,type2)                              \
321   do {                                                                  \
322     PetscBool      _7_match;                                            \
323     PetscErrorCode _7_ierr;                                             \
324     _7_ierr = PetscObjectTypeCompareAny(((PetscObject)(a)),&_7_match,(type1),(type2),"");CHKERRQ(_7_ierr); \
325     if (!_7_match) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Object (%s) is not %s or %s",(char*)(((PetscObject)(a))->type_name),type1,type2); \
326   } while (0)
327 /*
328    Use this macro to check if the type is set
329 */
330 #define PetscValidType(a,arg)                                           \
331   do {                                                                  \
332     if (!((PetscObject)(a))->type_name) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"%s object's type is not set: Argument # %d",((PetscObject)(a))->class_name,arg); \
333   } while (0)
334 /*
335    Sometimes object must live on same communicator to inter-operate
336 */
337 #define PetscCheckSameComm(a,arga,b,argb)                               \
338   do {                                                                  \
339     PetscErrorCode _7_ierr;                                             \
340     PetscMPIInt    _7_flag;                                             \
341     _7_ierr = MPI_Comm_compare(PetscObjectComm((PetscObject)(a)),PetscObjectComm((PetscObject)(b)),&_7_flag);CHKERRQ(_7_ierr); \
342     if (_7_flag != MPI_CONGRUENT && _7_flag != MPI_IDENT) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"Different communicators in the two objects: Argument # %d and %d flag %d",arga,argb,_7_flag); \
343   } while (0)
344 
345 #define PetscCheckSameTypeAndComm(a,arga,b,argb)        \
346   do {                                                  \
347     PetscCheckSameType(a,arga,b,argb);                  \
348     PetscCheckSameComm(a,arga,b,argb);                  \
349   } while (0)
350 
351 #define PetscValidLogicalCollectiveScalar(a,b,arg)                      \
352   do {                                                                  \
353     PetscErrorCode _7_ierr;                                             \
354     PetscScalar b0=(b);                                                 \
355     PetscReal b1[5],b2[5];                                              \
356     if (PetscIsNanScalar(b0)) {b1[4] = 1;} else {b1[4] = 0;};           \
357     b1[0] = -PetscRealPart(b0); b1[1] = PetscRealPart(b0); b1[2] = -PetscImaginaryPart(b0); b1[3] = PetscImaginaryPart(b0); \
358     _7_ierr = MPI_Allreduce(b1,b2,5,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)(a)));CHKERRQ(_7_ierr); \
359     if (!(b2[4] > 0) && !(PetscEqualReal(-b2[0],b2[1]) && PetscEqualReal(-b2[2],b2[3]))) SETERRQ1(PetscObjectComm((PetscObject)(a)),PETSC_ERR_ARG_WRONG,"Scalar value must be same on all processes, argument # %d",arg); \
360   } while (0)
361 
362 #define PetscValidLogicalCollectiveReal(a,b,arg)                        \
363   do {                                                                  \
364     PetscErrorCode _7_ierr;                                             \
365     PetscReal b0=(b),b1[3],b2[3];                                       \
366     if (PetscIsNanReal(b0)) {b1[2] = 1;} else {b1[2] = 0;};             \
367     b1[0] = -b0; b1[1] = b0;                                            \
368     _7_ierr = MPI_Allreduce(b1,b2,3,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)(a)));CHKERRQ(_7_ierr); \
369     if (!(b2[2] > 0) && !PetscEqualReal(-b2[0],b2[1])) SETERRQ1(PetscObjectComm((PetscObject)(a)),PETSC_ERR_ARG_WRONG,"Real value must be same on all processes, argument # %d",arg); \
370   } while (0)
371 
372 #define PetscValidLogicalCollectiveInt(a,b,arg)                         \
373   do {                                                                  \
374     PetscErrorCode _7_ierr;                                             \
375     PetscInt b0=(b),b1[2],b2[2];                                        \
376     b1[0] = -b0; b1[1] = b0;                                            \
377     _7_ierr = MPIU_Allreduce(b1,b2,2,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)(a)));CHKERRQ(_7_ierr); \
378     if (-b2[0] != b2[1]) SETERRQ1(PetscObjectComm((PetscObject)(a)),PETSC_ERR_ARG_WRONG,"Int value must be same on all processes, argument # %d",arg); \
379   } while (0)
380 
381 #define PetscValidLogicalCollectiveMPIInt(a,b,arg)                      \
382   do {                                                                  \
383     PetscErrorCode _7_ierr;                                             \
384     PetscMPIInt b0=(b),b1[2],b2[2];                                     \
385     b1[0] = -b0; b1[1] = b0;                                            \
386     _7_ierr = MPIU_Allreduce(b1,b2,2,MPI_INT,MPI_MAX,PetscObjectComm((PetscObject)(a)));CHKERRQ(_7_ierr); \
387     if (-b2[0] != b2[1]) SETERRQ1(PetscObjectComm((PetscObject)(a)),PETSC_ERR_ARG_WRONG,"PetscMPIInt value must be same on all processes, argument # %d",arg); \
388   } while (0)
389 
390 #define PetscValidLogicalCollectiveBool(a,b,arg)                        \
391   do {                                                                  \
392     PetscErrorCode _7_ierr;                                             \
393     PetscMPIInt b0=(PetscMPIInt)(b),b1[2],b2[2];                        \
394     b1[0] = -b0; b1[1] = b0;                                            \
395     _7_ierr = MPIU_Allreduce(b1,b2,2,MPI_INT,MPI_MAX,PetscObjectComm((PetscObject)(a)));CHKERRQ(_7_ierr); \
396     if (-b2[0] != b2[1]) SETERRQ1(PetscObjectComm((PetscObject)(a)),PETSC_ERR_ARG_WRONG,"Bool value must be same on all processes, argument # %d",arg); \
397   } while (0)
398 
399 #define PetscValidLogicalCollectiveEnum(a,b,arg)                        \
400   do {                                                                  \
401     PetscErrorCode _7_ierr;                                             \
402     PetscMPIInt b0=(PetscMPIInt)(b),b1[2],b2[2];                        \
403     b1[0] = -b0; b1[1] = b0;                                            \
404     _7_ierr = MPIU_Allreduce(b1,b2,2,MPI_INT,MPI_MAX,PetscObjectComm((PetscObject)(a)));CHKERRQ(_7_ierr); \
405     if (-b2[0] != b2[1]) SETERRQ1(PetscObjectComm((PetscObject)(a)),PETSC_ERR_ARG_WRONG,"Enum value must be same on all processes, argument # %d",arg); \
406   } while (0)
407 
408 #define PetscCheckSorted(n,idx)                                                                   \
409   do {                                                                                            \
410     PetscBool _1_flg;                                                                             \
411     PetscSorted(n,idx,_1_flg);                                                                    \
412     if (!_1_flg) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Input array needs to be sorted"); \
413   } while (0)
414 
415 #endif
416 
417 /*
418    PetscTryMethod - Queries an object for a method, if it exists then calls it.
419               These are intended to be used only inside PETSc functions.
420 
421    Level: developer
422 
423 .seealso: PetscUseMethod()
424 */
425 #define  PetscTryMethod(obj,A,B,C) \
426   0; do { PetscErrorCode (*_7_f)B, _7_ierr; \
427     _7_ierr = PetscObjectQueryFunction((PetscObject)(obj),A,&_7_f);CHKERRQ(_7_ierr); \
428     if (_7_f) {_7_ierr = (*_7_f)C;CHKERRQ(_7_ierr);} \
429   } while (0)
430 
431 /*
432    PetscUseMethod - Queries an object for a method, if it exists then calls it, otherwise generates an error.
433               These are intended to be used only inside PETSc functions.
434 
435    Level: developer
436 
437 .seealso: PetscTryMethod()
438 */
439 #define  PetscUseMethod(obj,A,B,C) \
440   0; do { PetscErrorCode (*_7_f)B, _7_ierr; \
441     _7_ierr = PetscObjectQueryFunction((PetscObject)(obj),A,&_7_f);CHKERRQ(_7_ierr); \
442     if (_7_f) {_7_ierr = (*_7_f)C;CHKERRQ(_7_ierr);} \
443     else SETERRQ1(PetscObjectComm((PetscObject)(obj)),PETSC_ERR_SUP,"Cannot locate function %s in object",A); \
444   } while (0)
445 
446 /*MC
447    PetscObjectStateIncrease - Increases the state of any PetscObject
448 
449    Synopsis:
450    #include "petsc/private/petscimpl.h"
451    PetscErrorCode PetscObjectStateIncrease(PetscObject obj)
452 
453    Logically Collective
454 
455    Input Parameter:
456 .  obj - any PETSc object, for example a Vec, Mat or KSP. This must be
457          cast with a (PetscObject), for example,
458          PetscObjectStateIncrease((PetscObject)mat);
459 
460    Notes:
461     object state is an integer which gets increased every time
462    the object is changed internally. By saving and later querying the object state
463    one can determine whether information about the object is still current.
464    Currently, state is maintained for Vec and Mat objects.
465 
466    This routine is mostly for internal use by PETSc; a developer need only
467    call it after explicit access to an object's internals. Routines such
468    as VecSet() or MatScale() already call this routine. It is also called, as a
469    precaution, in VecRestoreArray(), MatRestoreRow(), MatDenseRestoreArray().
470 
471    This routine is logically collective because state equality comparison needs to be possible without communication.
472 
473    Level: developer
474 
475    seealso: PetscObjectStateGet()
476 
477 M*/
478 #define PetscObjectStateIncrease(obj) ((obj)->state++,0)
479 
480 PETSC_EXTERN PetscErrorCode PetscObjectStateGet(PetscObject,PetscObjectState*);
481 PETSC_EXTERN PetscErrorCode PetscObjectStateSet(PetscObject,PetscObjectState);
482 PETSC_EXTERN PetscErrorCode PetscObjectComposedDataRegister(PetscInt*);
483 PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseInt(PetscObject);
484 PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseIntstar(PetscObject);
485 PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseReal(PetscObject);
486 PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseRealstar(PetscObject);
487 PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseScalar(PetscObject);
488 PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseScalarstar(PetscObject);
489 PETSC_EXTERN PetscInt       PetscObjectComposedDataMax;
490 /*MC
491    PetscObjectComposedDataSetInt - attach integer data to a PetscObject
492 
493    Synopsis:
494    #include "petsc/private/petscimpl.h"
495    PetscErrorCode PetscObjectComposedDataSetInt(PetscObject obj,int id,int data)
496 
497    Not collective
498 
499    Input parameters:
500 +  obj - the object to which data is to be attached
501 .  id - the identifier for the data
502 -  data - the data to  be attached
503 
504    Notes
505    The data identifier can best be created through a call to  PetscObjectComposedDataRegister()
506 
507    Level: developer
508 M*/
509 #define PetscObjectComposedDataSetInt(obj,id,data)                                      \
510   ((((obj)->int_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseInt(obj)) ||  \
511    ((obj)->intcomposeddata[id] = data,(obj)->intcomposedstate[id] = (obj)->state, 0))
512 
513 /*MC
514    PetscObjectComposedDataGetInt - retrieve integer data attached to an object
515 
516    Synopsis:
517    #include "petsc/private/petscimpl.h"
518    PetscErrorCode PetscObjectComposedDataGetInt(PetscObject obj,int id,int data,PetscBool  flag)
519 
520    Not collective
521 
522    Input parameters:
523 +  obj - the object from which data is to be retrieved
524 -  id - the identifier for the data
525 
526    Output parameters:
527 +  data - the data to be retrieved
528 -  flag - PETSC_TRUE if the data item exists and is valid, PETSC_FALSE otherwise
529 
530    The 'data' and 'flag' variables are inlined, so they are not pointers.
531 
532    Level: developer
533 M*/
534 #define PetscObjectComposedDataGetInt(obj,id,data,flag)                            \
535   ((((obj)->intcomposedstate && ((obj)->intcomposedstate[id] == (obj)->state)) ?   \
536    (data = (obj)->intcomposeddata[id],flag = PETSC_TRUE) : (flag = PETSC_FALSE)),0)
537 
538 /*MC
539    PetscObjectComposedDataSetIntstar - attach integer array data to a PetscObject
540 
541    Synopsis:
542    #include "petsc/private/petscimpl.h"
543    PetscErrorCode PetscObjectComposedDataSetIntstar(PetscObject obj,int id,int *data)
544 
545    Not collective
546 
547    Input parameters:
548 +  obj - the object to which data is to be attached
549 .  id - the identifier for the data
550 -  data - the data to  be attached
551 
552    Notes
553    The data identifier can best be determined through a call to
554    PetscObjectComposedDataRegister()
555 
556    Level: developer
557 M*/
558 #define PetscObjectComposedDataSetIntstar(obj,id,data)                                          \
559   ((((obj)->intstar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseIntstar(obj)) ||  \
560    ((obj)->intstarcomposeddata[id] = data,(obj)->intstarcomposedstate[id] = (obj)->state, 0))
561 
562 /*MC
563    PetscObjectComposedDataGetIntstar - retrieve integer array data
564    attached to an object
565 
566    Synopsis:
567    #include "petsc/private/petscimpl.h"
568    PetscErrorCode PetscObjectComposedDataGetIntstar(PetscObject obj,int id,int *data,PetscBool  flag)
569 
570    Not collective
571 
572    Input parameters:
573 +  obj - the object from which data is to be retrieved
574 -  id - the identifier for the data
575 
576    Output parameters:
577 +  data - the data to be retrieved
578 -  flag - PETSC_TRUE if the data item exists and is valid, PETSC_FALSE otherwise
579 
580    The 'data' and 'flag' variables are inlined, so they are not pointers.
581 
582    Level: developer
583 M*/
584 #define PetscObjectComposedDataGetIntstar(obj,id,data,flag)                               \
585   ((((obj)->intstarcomposedstate && ((obj)->intstarcomposedstate[id] == (obj)->state)) ?  \
586    (data = (obj)->intstarcomposeddata[id],flag = PETSC_TRUE) : (flag = PETSC_FALSE)),0)
587 
588 /*MC
589    PetscObjectComposedDataSetReal - attach real data to a PetscObject
590 
591    Synopsis:
592    #include "petsc/private/petscimpl.h"
593    PetscErrorCode PetscObjectComposedDataSetReal(PetscObject obj,int id,PetscReal data)
594 
595    Not collective
596 
597    Input parameters:
598 +  obj - the object to which data is to be attached
599 .  id - the identifier for the data
600 -  data - the data to  be attached
601 
602    Notes
603    The data identifier can best be determined through a call to
604    PetscObjectComposedDataRegister()
605 
606    Level: developer
607 M*/
608 #define PetscObjectComposedDataSetReal(obj,id,data)                                       \
609   ((((obj)->real_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseReal(obj)) ||  \
610    ((obj)->realcomposeddata[id] = data,(obj)->realcomposedstate[id] = (obj)->state, 0))
611 
612 /*MC
613    PetscObjectComposedDataGetReal - retrieve real data attached to an object
614 
615    Synopsis:
616    #include "petsc/private/petscimpl.h"
617    PetscErrorCode PetscObjectComposedDataGetReal(PetscObject obj,int id,PetscReal data,PetscBool  flag)
618 
619    Not collective
620 
621    Input parameters:
622 +  obj - the object from which data is to be retrieved
623 -  id - the identifier for the data
624 
625    Output parameters:
626 +  data - the data to be retrieved
627 -  flag - PETSC_TRUE if the data item exists and is valid, PETSC_FALSE otherwise
628 
629    The 'data' and 'flag' variables are inlined, so they are not pointers.
630 
631    Level: developer
632 M*/
633 #define PetscObjectComposedDataGetReal(obj,id,data,flag)                            \
634   ((((obj)->realcomposedstate && ((obj)->realcomposedstate[id] == (obj)->state)) ?  \
635    (data = (obj)->realcomposeddata[id],flag = PETSC_TRUE) : (flag = PETSC_FALSE)),0)
636 
637 /*MC
638    PetscObjectComposedDataSetRealstar - attach real array data to a PetscObject
639 
640    Synopsis:
641    #include "petsc/private/petscimpl.h"
642    PetscErrorCode PetscObjectComposedDataSetRealstar(PetscObject obj,int id,PetscReal *data)
643 
644    Not collective
645 
646    Input parameters:
647 +  obj - the object to which data is to be attached
648 .  id - the identifier for the data
649 -  data - the data to  be attached
650 
651    Notes
652    The data identifier can best be determined through a call to
653    PetscObjectComposedDataRegister()
654 
655    Level: developer
656 M*/
657 #define PetscObjectComposedDataSetRealstar(obj,id,data)                                           \
658   ((((obj)->realstar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseRealstar(obj)) ||  \
659    ((obj)->realstarcomposeddata[id] = data, (obj)->realstarcomposedstate[id] = (obj)->state, 0))
660 
661 /*MC
662    PetscObjectComposedDataGetRealstar - retrieve real array data
663    attached to an object
664 
665    Synopsis:
666    #include "petsc/private/petscimpl.h"
667    PetscErrorCode PetscObjectComposedDataGetRealstar(PetscObject obj,int id,PetscReal *data,PetscBool  flag)
668 
669    Not collective
670 
671    Input parameters:
672 +  obj - the object from which data is to be retrieved
673 -  id - the identifier for the data
674 
675    Output parameters:
676 +  data - the data to be retrieved
677 -  flag - PETSC_TRUE if the data item exists and is valid, PETSC_FALSE otherwise
678 
679    The 'data' and 'flag' variables are inlined, so they are not pointers.
680 
681    Level: developer
682 M*/
683 #define PetscObjectComposedDataGetRealstar(obj,id,data,flag)                                \
684   ((((obj)->realstarcomposedstate && ((obj)->realstarcomposedstate[id] == (obj)->state)) ?  \
685    (data = (obj)->realstarcomposeddata[id],flag = PETSC_TRUE) : (flag = PETSC_FALSE)),0)
686 
687 /*MC
688    PetscObjectComposedDataSetScalar - attach scalar data to a PetscObject
689 
690    Synopsis:
691    #include "petsc/private/petscimpl.h"
692    PetscErrorCode PetscObjectComposedDataSetScalar(PetscObject obj,int id,PetscScalar data)
693 
694    Not collective
695 
696    Input parameters:
697 +  obj - the object to which data is to be attached
698 .  id - the identifier for the data
699 -  data - the data to  be attached
700 
701    Notes
702    The data identifier can best be determined through a call to
703    PetscObjectComposedDataRegister()
704 
705    Level: developer
706 M*/
707 #if defined(PETSC_USE_COMPLEX)
708 #define PetscObjectComposedDataSetScalar(obj,id,data)                                        \
709   ((((obj)->scalar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseScalar(obj)) || \
710    ((obj)->scalarcomposeddata[id] = data,(obj)->scalarcomposedstate[id] = (obj)->state, 0))
711 #else
712 #define PetscObjectComposedDataSetScalar(obj,id,data) \
713         PetscObjectComposedDataSetReal(obj,id,data)
714 #endif
715 /*MC
716    PetscObjectComposedDataGetScalar - retrieve scalar data attached to an object
717 
718    Synopsis:
719    #include "petsc/private/petscimpl.h"
720    PetscErrorCode PetscObjectComposedDataGetScalar(PetscObject obj,int id,PetscScalar data,PetscBool  flag)
721 
722    Not collective
723 
724    Input parameters:
725 +  obj - the object from which data is to be retrieved
726 -  id - the identifier for the data
727 
728    Output parameters:
729 +  data - the data to be retrieved
730 -  flag - PETSC_TRUE if the data item exists and is valid, PETSC_FALSE otherwise
731 
732    The 'data' and 'flag' variables are inlined, so they are not pointers.
733 
734    Level: developer
735 M*/
736 #if defined(PETSC_USE_COMPLEX)
737 #define PetscObjectComposedDataGetScalar(obj,id,data,flag)                              \
738   ((((obj)->scalarcomposedstate && ((obj)->scalarcomposedstate[id] == (obj)->state)) ? \
739    (data = (obj)->scalarcomposeddata[id],flag = PETSC_TRUE) : (flag = PETSC_FALSE)),0)
740 #else
741 #define PetscObjectComposedDataGetScalar(obj,id,data,flag)                             \
742         PetscObjectComposedDataGetReal(obj,id,data,flag)
743 #endif
744 
745 /*MC
746    PetscObjectComposedDataSetScalarstar - attach scalar array data to a PetscObject
747 
748    Synopsis:
749    #include "petsc/private/petscimpl.h"
750    PetscErrorCode PetscObjectComposedDataSetScalarstar(PetscObject obj,int id,PetscScalar *data)
751 
752    Not collective
753 
754    Input parameters:
755 +  obj - the object to which data is to be attached
756 .  id - the identifier for the data
757 -  data - the data to  be attached
758 
759    Notes
760    The data identifier can best be determined through a call to
761    PetscObjectComposedDataRegister()
762 
763    Level: developer
764 M*/
765 #if defined(PETSC_USE_COMPLEX)
766 #define PetscObjectComposedDataSetScalarstar(obj,id,data)                                             \
767   ((((obj)->scalarstar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseScalarstar(obj)) ||  \
768    ((obj)->scalarstarcomposeddata[id] = data,(obj)->scalarstarcomposedstate[id] = (obj)->state, 0))
769 #else
770 #define PetscObjectComposedDataSetScalarstar(obj,id,data) \
771         PetscObjectComposedDataSetRealstar(obj,id,data)
772 #endif
773 /*MC
774    PetscObjectComposedDataGetScalarstar - retrieve scalar array data
775    attached to an object
776 
777    Synopsis:
778    #include "petsc/private/petscimpl.h"
779    PetscErrorCode PetscObjectComposedDataGetScalarstar(PetscObject obj,int id,PetscScalar *data,PetscBool  flag)
780 
781    Not collective
782 
783    Input parameters:
784 +  obj - the object from which data is to be retrieved
785 -  id - the identifier for the data
786 
787    Output parameters:
788 +  data - the data to be retrieved
789 -  flag - PETSC_TRUE if the data item exists and is valid, PETSC_FALSE otherwise
790 
791    The 'data' and 'flag' variables are inlined, so they are not pointers.
792 
793    Level: developer
794 M*/
795 #if defined(PETSC_USE_COMPLEX)
796 #define PetscObjectComposedDataGetScalarstar(obj,id,data,flag)                                 \
797   ((((obj)->scalarstarcomposedstate && ((obj)->scalarstarcomposedstate[id] == (obj)->state)) ? \
798        (data = (obj)->scalarstarcomposeddata[id],flag = PETSC_TRUE) : (flag = PETSC_FALSE)),0)
799 #else
800 #define PetscObjectComposedDataGetScalarstar(obj,id,data,flag)         \
801         PetscObjectComposedDataGetRealstar(obj,id,data,flag)
802 #endif
803 
804 PETSC_EXTERN PetscMPIInt Petsc_Counter_keyval;
805 PETSC_EXTERN PetscMPIInt Petsc_InnerComm_keyval;
806 PETSC_EXTERN PetscMPIInt Petsc_OuterComm_keyval;
807 PETSC_EXTERN PetscMPIInt Petsc_Seq_keyval;
808 PETSC_EXTERN PetscMPIInt Petsc_ShmComm_keyval;
809 
810 /*
811   PETSc communicators have this attribute, see
812   PetscCommDuplicate(), PetscCommDestroy(), PetscCommGetNewTag(), PetscObjectGetName()
813 */
814 typedef struct {
815   PetscMPIInt tag;              /* next free tag value */
816   PetscInt    refcount;         /* number of references, communicator can be freed when this reaches 0 */
817   PetscInt    namecount;        /* used to generate the next name, as in Vec_0, Mat_1, ... */
818   PetscMPIInt *iflags;          /* length of comm size, shared by all calls to PetscCommBuildTwoSided_Allreduce/RedScatter on this comm */
819 } PetscCommCounter;
820 
821 typedef enum {STATE_BEGIN, STATE_PENDING, STATE_END} SRState;
822 
823 typedef enum {PETSC_SR_REDUCE_SUM=0,PETSC_SR_REDUCE_MAX=1,PETSC_SR_REDUCE_MIN=2} PetscSRReductionType;
824 
825 typedef struct {
826   MPI_Comm    comm;
827   MPI_Request request;
828   PetscBool   async;
829   PetscScalar *lvalues;     /* this are the reduced values before call to MPI_Allreduce() */
830   PetscScalar *gvalues;     /* values after call to MPI_Allreduce() */
831   void        **invecs;     /* for debugging only, vector/memory used with each op */
832   PetscInt    *reducetype;  /* is particular value to be summed or maxed? */
833   SRState     state;        /* are we calling xxxBegin() or xxxEnd()? */
834   PetscInt    maxops;       /* total amount of space we have for requests */
835   PetscInt    numopsbegin;  /* number of requests that have been queued in */
836   PetscInt    numopsend;    /* number of requests that have been gotten by user */
837 } PetscSplitReduction;
838 
839 PETSC_EXTERN PetscErrorCode PetscSplitReductionGet(MPI_Comm,PetscSplitReduction**);
840 PETSC_EXTERN PetscErrorCode PetscSplitReductionEnd(PetscSplitReduction*);
841 PETSC_EXTERN PetscErrorCode PetscSplitReductionExtend(PetscSplitReduction*);
842 
843 #if !defined(PETSC_SKIP_SPINLOCK)
844 #if defined(PETSC_HAVE_THREADSAFETY)
845 #  if defined(PETSC_HAVE_CONCURRENCYKIT)
846 #if defined(__cplusplus)
847 /*  CK does not have extern "C" protection in their include files */
848 extern "C" {
849 #endif
850 #include <ck_spinlock.h>
851 #if defined(__cplusplus)
852 }
853 #endif
854 typedef ck_spinlock_t PetscSpinlock;
PetscSpinlockCreate(PetscSpinlock * ck_spinlock)855 PETSC_STATIC_INLINE PetscErrorCode PetscSpinlockCreate(PetscSpinlock *ck_spinlock)
856 {
857   ck_spinlock_init(ck_spinlock);
858   return 0;
859 }
PetscSpinlockLock(PetscSpinlock * ck_spinlock)860 PETSC_STATIC_INLINE PetscErrorCode PetscSpinlockLock(PetscSpinlock *ck_spinlock)
861 {
862   ck_spinlock_lock(ck_spinlock);
863   return 0;
864 }
PetscSpinlockUnlock(PetscSpinlock * ck_spinlock)865 PETSC_STATIC_INLINE PetscErrorCode PetscSpinlockUnlock(PetscSpinlock *ck_spinlock)
866 {
867   ck_spinlock_unlock(ck_spinlock);
868   return 0;
869 }
PetscSpinlockDestroy(PetscSpinlock * ck_spinlock)870 PETSC_STATIC_INLINE PetscErrorCode PetscSpinlockDestroy(PetscSpinlock *ck_spinlock)
871 {
872   return 0;
873 }
874 #  elif defined(PETSC_HAVE_OPENMP)
875 
876 #include <omp.h>
877 typedef omp_lock_t PetscSpinlock;
PetscSpinlockCreate(PetscSpinlock * omp_lock)878 PETSC_STATIC_INLINE PetscErrorCode PetscSpinlockCreate(PetscSpinlock *omp_lock)
879 {
880   omp_init_lock(omp_lock);
881   return 0;
882 }
PetscSpinlockLock(PetscSpinlock * omp_lock)883 PETSC_STATIC_INLINE PetscErrorCode PetscSpinlockLock(PetscSpinlock *omp_lock)
884 {
885   omp_set_lock(omp_lock);
886   return 0;
887 }
PetscSpinlockUnlock(PetscSpinlock * omp_lock)888 PETSC_STATIC_INLINE PetscErrorCode PetscSpinlockUnlock(PetscSpinlock *omp_lock)
889 {
890   omp_unset_lock(omp_lock);
891   return 0;
892 }
PetscSpinlockDestroy(PetscSpinlock * omp_lock)893 PETSC_STATIC_INLINE PetscErrorCode PetscSpinlockDestroy(PetscSpinlock *omp_lock)
894 {
895   omp_destroy_lock(omp_lock);
896   return 0;
897 }
898 #else
899 Thread safety requires either --with-openmp or --download-concurrencykit
900 #endif
901 
902 #else
903 typedef int PetscSpinlock;
904 #define PetscSpinlockCreate(a)  0
905 #define PetscSpinlockLock(a)    0
906 #define PetscSpinlockUnlock(a)  0
907 #define PetscSpinlockDestroy(a) 0
908 #endif
909 
910 #if defined(PETSC_HAVE_THREADSAFETY)
911 PETSC_INTERN PetscSpinlock PetscViewerASCIISpinLockOpen;
912 PETSC_INTERN PetscSpinlock PetscViewerASCIISpinLockStdout;
913 PETSC_INTERN PetscSpinlock PetscViewerASCIISpinLockStderr;
914 PETSC_INTERN PetscSpinlock PetscCommSpinLock;
915 #endif
916 #endif
917 
918 PETSC_EXTERN PetscLogEvent PETSC_Barrier;
919 PETSC_EXTERN PetscLogEvent PETSC_BuildTwoSided;
920 PETSC_EXTERN PetscLogEvent PETSC_BuildTwoSidedF;
921 PETSC_EXTERN PetscBool     use_gpu_aware_mpi;
922 
923 #if defined(PETSC_HAVE_ADIOS)
924 PETSC_EXTERN int64_t Petsc_adios_group;
925 #endif
926 
927 #if defined(PETSC_HAVE_KOKKOS)
928 PETSC_INTERN PetscBool      PetscBeganKokkos;
929 PETSC_INTERN PetscErrorCode PetscKokkosInitialize_Private(void); /* C bindings for the Kokkos C++ routines */
930 PETSC_INTERN PetscErrorCode PetscKokkosIsInitialized_Private(PetscBool*);
931 PETSC_INTERN PetscErrorCode PetscKokkosFinalize_Private(void);
932 PETSC_EXTERN PetscErrorCode PetscKokkosInitializeCheck(void);  /* Check if CUDA is initialized and init CUDA if not yet. */
933 #endif
934 
935 #if defined(PETSC_HAVE_CUDA)
936 PETSC_EXTERN PetscBool      PetscCUDAInitialized;  /* Has petsc initialized CUDA? One can use this flag to guard CUDA calls. */
937 PETSC_EXTERN PetscBool      PetscMPICUDAAwarenessCheck(void);
938 #endif
939 
940 #if defined(PETSC_HAVE_HIP)
941 PETSC_EXTERN PetscBool      PetscHIPInitialized;
942 PETSC_EXTERN PetscBool      PetscMPIHIPAwarenessCheck(void);
943 #endif
944 
945 PETSC_EXTERN PetscBool      PetscCreatedGpuObjects;
946 #endif /* PETSCIMPL_H */
947