Actual source code: petscimpl.h

  1: /*
  2:     Defines the basic header of all PETSc objects.
  3: */
  4: #pragma once
  5: #include <petscsys.h>

  7: /* SUBMANSEC = Sys */

  9: #if defined(PETSC_CLANG_STATIC_ANALYZER)
 10:   #define PetscDisableStaticAnalyzerForExpressionUnderstandingThatThisIsDangerousAndBugprone(...)
 11: #else
 12:   #define PetscDisableStaticAnalyzerForExpressionUnderstandingThatThisIsDangerousAndBugprone(...) __VA_ARGS__
 13: #endif

 15: #if PetscDefined(USE_DEBUG) && !PetscDefined(HAVE_THREADSAFETY)
 16: PETSC_INTERN PetscErrorCode PetscStackSetCheck(PetscBool);
 17: PETSC_INTERN PetscErrorCode PetscStackView(FILE *);
 18: PETSC_INTERN PetscErrorCode PetscStackReset(void);
 19: PETSC_INTERN PetscErrorCode PetscStackCopy(PetscStack *, PetscStack *);
 20: PETSC_INTERN PetscErrorCode PetscStackPrint(PetscStack *, FILE *);
 21: #else
 22:   #define PetscStackSetCheck(check)         PETSC_SUCCESS
 23:   #define PetscStackView(file)              PETSC_SUCCESS
 24:   #define PetscStackReset()                 PETSC_SUCCESS
 25:   #define PetscStackCopy(stackin, stackout) PETSC_SUCCESS
 26:   #define PetscStackPrint(stack, file)      PETSC_SUCCESS
 27: #endif

 29: /* These are used internally by PETSc ASCII IO routines*/
 30: #include <stdarg.h>
 31: PETSC_EXTERN PetscErrorCode PetscVFPrintfDefault(FILE *, const char[], va_list);

 33: /*
 34:    All major PETSc data structures have a common core; this is defined
 35:    below by PETSCHEADER.

 37:    PetscHeaderCreate() should be used whenever creating a PETSc structure.
 38: */

 40: /*
 41:    PetscOps: structure of core operations that all PETSc objects support.

 43:       view()            - Is the routine for viewing the entire PETSc object; for
 44:                           example, MatView() is the general matrix viewing routine.
 45:                           This is used by PetscObjectView((PetscObject)obj) to allow
 46:                           viewing any PETSc object.
 47:       destroy()         - Is the routine for destroying the entire PETSc object;
 48:                           for example,MatDestroy() is the general matrix
 49:                           destruction routine.
 50:                           This is used by PetscObjectDestroy((PetscObject*)&obj) to allow
 51:                           destroying any PETSc object.
 52: */

 54: typedef struct {
 55:   PetscErrorCode (*view)(PetscObject, PetscViewer);
 56:   PetscErrorCode (*destroy)(PetscObject *);
 57: } PetscOps;

 59: typedef enum {
 60:   PETSC_FORTRAN_CALLBACK_CLASS,
 61:   PETSC_FORTRAN_CALLBACK_SUBTYPE,
 62:   PETSC_FORTRAN_CALLBACK_MAXTYPE
 63: } PetscFortranCallbackType;
 64: typedef size_t PetscFortranCallbackId;
 65: #define PETSC_SMALLEST_FORTRAN_CALLBACK ((PetscFortranCallbackId)1000)
 66: PETSC_EXTERN PetscErrorCode PetscFortranCallbackRegister(PetscClassId, const char *, PetscFortranCallbackId *);
 67: PETSC_EXTERN PetscErrorCode PetscFortranCallbackGetSizes(PetscClassId, PetscFortranCallbackId *, PetscFortranCallbackId *);

 69: typedef struct {
 70:   void (*func)(void);
 71:   void *ctx;
 72: } PetscFortranCallback;

 74: /*
 75:    All PETSc objects begin with the fields defined in PETSCHEADER.
 76:    The PetscObject is a way of examining these fields regardless of
 77:    the specific object. In C++ this could be a base abstract class
 78:    from which all objects are derived.
 79: */
 80: #define PETSC_MAX_OPTIONS_HANDLER 5
 81: typedef struct _p_PetscObject {
 82:   PetscOps      bops[1];
 83:   PetscClassId  classid;
 84:   MPI_Comm      comm;
 85:   PetscObjectId id; /* this is used to compare object for identity that may no longer exist since memory addresses get recycled for new objects */
 86:   PetscInt      refct;
 87:   PetscErrorCode (*non_cyclic_references)(PetscObject, PetscInt *);
 88:   PetscInt64        cidx;
 89:   PetscMPIInt       tag;
 90:   PetscFunctionList qlist;
 91:   PetscObjectList   olist;
 92:   char             *class_name; /*  for example, "Vec" */
 93:   char             *description;
 94:   char             *mansec;
 95:   char             *type_name; /*  this is the subclass, for example VECSEQ which equals "seq" */
 96:   char             *name;
 97:   char             *prefix;
 98:   PetscInt          tablevel;
 99:   void             *cpp;
100:   PetscObjectState  state;
101:   PetscInt          int_idmax, intstar_idmax;
102:   PetscObjectState *intcomposedstate, *intstarcomposedstate;
103:   PetscInt         *intcomposeddata, **intstarcomposeddata;
104:   PetscInt          real_idmax, realstar_idmax;
105:   PetscObjectState *realcomposedstate, *realstarcomposedstate;
106:   PetscReal        *realcomposeddata, **realstarcomposeddata;
107: #if PetscDefined(USE_COMPLEX)
108:   PetscInt          scalar_idmax, scalarstar_idmax;
109:   PetscObjectState *scalarcomposedstate, *scalarstarcomposedstate;
110:   PetscScalar      *scalarcomposeddata, **scalarstarcomposeddata;
111: #endif
112:   void (**fortran_func_pointers)(void);             /* used by Fortran interface functions to stash user provided Fortran functions */
113:   PetscFortranCallbackId num_fortran_func_pointers; /* number of Fortran function pointers allocated */
114:   PetscFortranCallback  *fortrancallback[PETSC_FORTRAN_CALLBACK_MAXTYPE];
115:   PetscFortranCallbackId num_fortrancallback[PETSC_FORTRAN_CALLBACK_MAXTYPE];
116:   void                  *python_context;
117:   PetscErrorCode (*python_destroy)(void *);

119:   PetscInt noptionhandler;
120:   PetscErrorCode (*optionhandler[PETSC_MAX_OPTIONS_HANDLER])(PetscObject, PetscOptionItems *, void *);
121:   PetscErrorCode (*optiondestroy[PETSC_MAX_OPTIONS_HANDLER])(PetscObject, void *);
122:   void *optionctx[PETSC_MAX_OPTIONS_HANDLER];
123: #if defined(PETSC_HAVE_SAWS)
124:   PetscBool amsmem;          /* if PETSC_TRUE then this object is registered with SAWs and visible to clients */
125:   PetscBool amspublishblock; /* if PETSC_TRUE and publishing objects then will block at PetscObjectSAWsBlock() */
126: #endif
127:   PetscOptions options; /* options database used, NULL means default */
128:   PetscBool    optionsprinted;
129:   PetscBool    donotPetscObjectPrintClassNamePrefixType;
130:   PetscBool    persistent;
131: } _p_PetscObject;

133: #define PETSCHEADER(ObjectOps) \
134:   _p_PetscObject hdr; \
135:   ObjectOps      ops[1]

137: #define PETSCFREEDHEADER -1

139: PETSC_EXTERN_TYPEDEF typedef PetscErrorCode (*PetscObjectDestroyFunction)(PetscObject *); /* force cast in next macro to NEVER use extern "C" style */
140: PETSC_EXTERN_TYPEDEF typedef PetscErrorCode (*PetscObjectViewFunction)(PetscObject, PetscViewer);

142: /*MC
143:     PetscHeaderCreate - Creates a raw PETSc object of a particular class

145:   Synopsis:
146: #include <petsc/private/petscimpl.h>
147:   PetscErrorCode PetscHeaderCreate(PetscObject h, PetscClassId classid, const char class_name[], const char descr[], const char mansec[], MPI_Comm comm, PetscObjectDestroyFunction destroy, PetscObjectViewFunction view)

149:   Input Parameters:
150: + classid    - The classid associated with this object (for example `VEC_CLASSID`)
151: . class_name - String name of class; should be static (for example "Vec"), may be
152:                `PETSC_NULLPTR`
153: . descr      - String containing short description; should be static (for example "Vector"),
154:                may be `PETSC_NULLPTR`
155: . mansec     - String indicating section in manual pages; should be static (for example "Vec"),
156:                may be `PETSC_NULLPTR`
157: . comm       - The MPI Communicator
158: . destroy    - The destroy routine for this object (for example `VecDestroy()`)
159: - view       - The view routine for this object (for example `VecView()`), may be
160:                `PETSC_NULLPTR`

162:   Output Parameter:
163: . h - The newly created `PetscObject`

165:   Level: developer

167:   Notes:
168:   Can only be used to create a `PetscObject`. A `PetscObject` is defined as a pointer to a
169:   C/C++ structure which satisfies all of the following\:

171:   1. The first member of the structure must be a `_p_PetscObject`.
172:   2. C++ structures must be "Standard Layout". Generally speaking a standard layout class\:
173:      - Has no virtual functions or base classes.
174:      - Has only standard layout non-static members (if any).
175:      - Has only standard layout base classes (if any).

177:      See https://en.cppreference.com/w/cpp/language/classes#Standard-layout_class for further
178:      information.

180:   Example Usage:
181:   Existing `PetscObject`s may be easily created as shown. Unless otherwise stated, a particular
182:   objects `destroy` and `view` functions are exactly `<OBJECT_TYPE>Destroy()` and
183:   `<OBJECT_TYPE>View()`.
184: .vb
185:   Vec v;

187:   PetscHeaderCreate(v, VEC_CLASSID, "Vec", "A distributed vector class", "Vec", PETSC_COMM_WORLD, VecDestroy, VecView);
188: .ve

190:   It is possible to create custom `PetscObject`s, note however that they must abide by the
191:   restrictions set forth above.
192: .vb
193:   // OK, first member of C structure is _p_PetscObject
194:   struct MyCPetscObject_s
195:   {
196:     _p_PetscObject header;
197:     int            some_data;
198:   };
199:   typedef struct *MyCPetscObject_s MyCPetscObject;

201:   PetscErrorCode MyObjectDestroy(MyObject *);
202:   PetscErrorCode MyObjectView(MyObject);

204:   MyCPetscObject obj;

206:   // assume MY_PETSC_CLASSID is already registered
207:   PetscHeaderCreate(obj, MY_PETSC_CLASSID, "MyObject", "A custom PetscObject", PETSC_NULLPTR, PETSC_COMM_SELF, MyObjectDestroy, MyObjectView);

209:   // OK, only destroy function must be given, all others may be NULL
210:   PetscHeaderCreate(obj, MY_PETSC_CLASSID, PETSC_NULLPTR, PETSC_NULLPTR, PETSC_NULLPTR, PETSC_COMM_SELF, MyObjectDestroy, PETSC_NULLPTR);

212:   // ERROR must be a single-level pointer
213:   PetscHeaderCreate(&obj, ...);
214: .ve

216:   Illustrating proper construction from C++\:
217: .vb
218:   // ERROR, class is not standard layout, first member must be publicly accessible
219:   class BadCppPetscObject
220:   {
221:     _p_PetscObject header;
222:   };

224:   // ERROR, class is not standard layout, has a virtual function and virtual inheritance
225:   class BadCppPetscObject2 : virtual BaseClass
226:   {
227:   public:
228:     _p_PetscObject header;

230:     virtual void foo();
231:   };

233:   // ERROR, class is not standard layout! Has non-standard layout member
234:   class BadCppPetscObject2
235:   {
236:   public:
237:     _p_PetscObject    header;
238:     BadCppPetscObject non_standard_layout;
239:   };

241:   // OK, class is standard layout!
242:   class GoodCppPetscObject;
243:   using MyCppObject = GoodCppPetscObject *;

245:   // OK, non-virtual inheritance of other standard layout class does not affect layout
246:   class GoodCppPetscObject : StandardLayoutClass
247:   {
248:   public:
249:     // OK, non standard layout member is static, does not affect layout
250:     static BadCppPetscObject non_standard_layout;

252:     // OK, first non-static member is _p_PetscObject
253:     _p_PetscObject header;

255:      // OK, non-virtual member functions do not affect class layout
256:     void foo();

258:     // OK, may use "member" functions for destroy and view so long as they are static
259:     static PetscErrorCode destroy(MyCppObject *);
260:     static PetscErrorCode view(MyCppObject);
261:   };

263:   // OK, usage via pointer
264:   MyObject obj;

266:   PetscHeaderCreate(obj, MY_PETSC_CLASSID, "MyObject", "A custom C++ PetscObject", nullptr, PETSC_COMM_SELF, GoodCppPetscObject::destroy, GoodCppPetscObject::view);
267: .ve

269: .seealso: `PetscObject`, `PetscHeaderDestroy()`, `PetscClassIdRegister()`
270: M*/
271: #define PetscHeaderCreate(h, classid, class_name, descr, mansec, comm, destroy, view) \
272:   PetscHeaderCreate_Function(PetscNew(&(h)), (PetscObject *)&(h), (classid), (class_name), (descr), (mansec), (comm), (PetscObjectDestroyFunction)(destroy), (PetscObjectViewFunction)(view))

274: PETSC_EXTERN PetscErrorCode PetscHeaderCreate_Function(PetscErrorCode, PetscObject *, PetscClassId, const char[], const char[], const char[], MPI_Comm, PetscObjectDestroyFunction, PetscObjectViewFunction);
275: PETSC_EXTERN PetscErrorCode PetscHeaderCreate_Private(PetscObject, PetscClassId, const char[], const char[], const char[], MPI_Comm, PetscObjectDestroyFunction, PetscObjectViewFunction);
276: PETSC_EXTERN PetscErrorCode PetscHeaderDestroy_Function(PetscObject *);
277: PETSC_EXTERN PetscErrorCode PetscComposedQuantitiesDestroy(PetscObject obj);
278: PETSC_INTERN PetscObjectId  PetscObjectNewId_Internal(void);

280: /*MC
281:   PetscHeaderDestroy - Final step in destroying a `PetscObject`

283:   Synopsis:
284: #include <petsc/private/petscimpl.h>
285:   PetscErrorCode PetscHeaderDestroy(PetscObject *obj)

287:   Input Parameter:
288: . h - A pointer to the header created with `PetscHeaderCreate()`

290:   Level: developer

292:   Notes:
293:   `h` is freed and set to `PETSC_NULLPTR` when this routine returns.

295:   Example Usage:
296: .vb
297:   PetscObject obj;

299:   PetscHeaderCreate(obj, ...);
300:   // use obj...

302:   // note pointer to obj is used
303:   PetscHeaderDestroy(&obj);
304: .ve

306:   Note that this routine is the _last_ step when destroying higher-level `PetscObject`s as it
307:   deallocates the memory for the structure itself\:
308: .vb
309:   typedef struct MyPetscObject_s *MyPetscObject;
310:   struct MyPetscObject_s
311:   {
312:     _p_PetscObject  hdr;
313:     PetscInt       *foo;
314:     PetscScalar    *bar;
315:   };

317:   // assume obj is created/initialized elsewhere...
318:   MyPetscObject obj;

320:   // OK, should dispose of all dynamically allocated resources before calling
321:   // PetscHeaderDestroy()
322:   PetscFree(obj->foo);

324:   // OK, dispose of obj
325:   PetscHeaderDestroy(&obj);

327:   // ERROR, obj points to NULL here, accessing obj->bar may result in segmentation violation!
328:   // obj->bar is potentially leaked!
329:   PetscFree(obj->bar);
330: .ve

332: .seealso: `PetscObject`, `PetscHeaderCreate()`
333: M*/
334: #define PetscHeaderDestroy(h) PetscHeaderDestroy_Function((PetscObject *)h)

336: PETSC_EXTERN PetscErrorCode                PetscHeaderDestroy_Private(PetscObject, PetscBool);
337: PETSC_INTERN PetscErrorCode                PetscHeaderDestroy_Private_Unlogged(PetscObject, PetscBool);
338: PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode PetscHeaderReset_Internal(PetscObject);
339: PETSC_EXTERN PetscErrorCode                PetscObjectCopyFortranFunctionPointers(PetscObject, PetscObject);
340: PETSC_EXTERN PetscErrorCode                PetscObjectSetFortranCallback(PetscObject, PetscFortranCallbackType, PetscFortranCallbackId *, void (*)(void), void *ctx);
341: PETSC_EXTERN PetscErrorCode                PetscObjectGetFortranCallback(PetscObject, PetscFortranCallbackType, PetscFortranCallbackId, void (**)(void), void **ctx);

343: PETSC_INTERN PetscErrorCode PetscCitationsInitialize(void);
344: PETSC_INTERN PetscErrorCode PetscFreeMPIResources(void);
345: PETSC_INTERN PetscErrorCode PetscOptionsHasHelpIntro_Internal(PetscOptions, PetscBool *);

347: /* Code shared between C and Fortran */
348: PETSC_INTERN PetscErrorCode PetscInitialize_Common(const char *, const char *, const char *, PetscBool, PetscBool, PetscInt);

350: #if PetscDefined(HAVE_SETJMP_H)
351: PETSC_EXTERN PetscBool PetscCheckPointer(const void *, PetscDataType);
352: #else
353:   #define PetscCheckPointer(ptr, data_type) (ptr ? PETSC_TRUE : PETSC_FALSE)
354: #endif

356: #if defined(PETSC_CLANG_STATIC_ANALYZER)
357: template <typename T>
359: template <typename T>
361: template <typename T>
363: template <typename T>
364: extern void PetscAssertPointer(T, int)
365: {
366: }
367: template <typename T>
369: #else
370:   // Macros to test if a PETSc object is valid and if pointers are valid
371:   #if PetscDefined(USE_DEBUG)
372:     /*  This check is for subtype methods such as DMDAGetCorners() that do not use the PetscTryMethod() or PetscUseMethod() paradigm */
374:       do { \
375:         PetscBool _7_same; \
377:         PetscCall(PetscObjectTypeCompare((PetscObject)(h), t, &_7_same)); \
378:         PetscCheck(_7_same, 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); \
379:       } while (0)

381:     #define PetscAssertPointer_Internal(ptr, arg, ptype, ptrtype) \
382:       do { \
383:         PetscCheck(ptr, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Null Pointer: Parameter # %d", arg); \
384:         PetscCheck(PetscCheckPointer(ptr, ptype), PETSC_COMM_SELF, PETSC_ERR_ARG_BADPTR, "Invalid Pointer to %s: Argument '" PetscStringize(ptr) "' (parameter # %d)", ptrtype, arg); \
385:       } while (0)

388:       do { \
389:         PetscAssertPointer_Internal(h, arg, PETSC_OBJECT, "PetscObject"); \
390:         if (((PetscObject)(h))->classid != ck) { \
391:           PetscCheck(((PetscObject)(h))->classid != PETSCFREEDHEADER, PETSC_COMM_SELF, PETSC_ERR_ARG_CORRUPT, "Object already free: Parameter # %d", arg); \
392:           SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Wrong type of object: Parameter # %d", arg); \
393:         } \
394:       } while (0)

397:       do { \
398:         PetscAssertPointer_Internal(h, arg, PETSC_OBJECT, "PetscObject"); \
399:         PetscCheck(((PetscObject)(h))->classid != PETSCFREEDHEADER, PETSC_COMM_SELF, PETSC_ERR_ARG_CORRUPT, "Object already free: Parameter # %d", arg); \
400:         PetscCheck(((PetscObject)(h))->classid >= PETSC_SMALLEST_CLASSID && ((PetscObject)(h))->classid <= PETSC_LARGEST_CLASSID, PETSC_COMM_SELF, PETSC_ERR_ARG_CORRUPT, "Invalid type of object: Parameter # %d", arg); \
401:       } while (0)

403:     #if defined(__cplusplus)
404:       #include <type_traits> // std::decay

406: namespace Petsc
407: {

409: namespace util
410: {

412: template <typename T>
413: struct PetscAssertPointerImpl {
414:   PETSC_NODISCARD static constexpr PetscDataType type() noexcept { return PETSC_CHAR; }
415:   PETSC_NODISCARD static constexpr const char   *string() noexcept { return "memory"; }
416: };

418:       #define PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(T, PETSC_TYPE) \
419:         template <> \
420:         struct PetscAssertPointerImpl<T *> { \
421:           PETSC_NODISCARD static constexpr PetscDataType type() noexcept \
422:           { \
423:             return PETSC_TYPE; \
424:           } \
425:           PETSC_NODISCARD static constexpr const char *string() noexcept \
426:           { \
427:             return PetscStringize(T); \
428:           } \
429:         }; \
430:         template <> \
431:         struct PetscAssertPointerImpl<const T *> : PetscAssertPointerImpl<T *> { }; \
432:         template <> \
433:         struct PetscAssertPointerImpl<volatile T *> : PetscAssertPointerImpl<T *> { }; \
434:         template <> \
435:         struct PetscAssertPointerImpl<const volatile T *> : PetscAssertPointerImpl<T *> { }

437: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(char, PETSC_CHAR);
438: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(signed char, PETSC_CHAR);
439: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(unsigned char, PETSC_CHAR);
440: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(short, PETSC_SHORT);
441: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(unsigned short, PETSC_SHORT);
442: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(PetscBool, PETSC_BOOL);
443: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(float, PETSC_FLOAT);
444: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(double, PETSC_DOUBLE);
445: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(int32_t, PETSC_INT32);
446: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(uint32_t, PETSC_INT32);
447: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(int64_t, PETSC_INT64);
448: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(uint64_t, PETSC_INT64);
449:       #if !defined(PETSC_SKIP_COMPLEX)
450: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(PetscComplex, PETSC_COMPLEX);
451:       #endif

453:       #undef PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION

455: } // namespace util

457: } // namespace Petsc

459:       #define PetscAssertPointer_PetscDataType(h) ::Petsc::util::PetscAssertPointerImpl<typename std::decay<decltype(h)>::type>::type()
460:       #define PetscAssertPointer_String(h)        ::Petsc::util::PetscAssertPointerImpl<typename std::decay<decltype(h)>::type>::string()

462:     #elif PETSC_C_VERSION >= 11
463:       #define PETSC_GENERIC_CV(type, result) type * : result, const type * : result, volatile type * : result, const volatile type * : result

465:       #if !PetscDefined(SKIP_COMPLEX)
466:         #define PETSC_GENERIC_CV_COMPLEX(result) PETSC_GENERIC_CV(PetscComplex, result)
467:       #else
468:         #define PETSC_GENERIC_CV_COMPLEX(result)
469:       #endif

471:       #define PetscAssertPointer_PetscDataType(h) \
472:         _Generic((h), \
473:           default: PETSC_CHAR, \
474:           PETSC_GENERIC_CV(          char, PETSC_CHAR), \
475:           PETSC_GENERIC_CV(   signed char, PETSC_CHAR), \
476:           PETSC_GENERIC_CV( unsigned char, PETSC_CHAR), \
477:           PETSC_GENERIC_CV(         short, PETSC_SHORT), \
478:           PETSC_GENERIC_CV(unsigned short, PETSC_SHORT), \
479:           PETSC_GENERIC_CV(         float, PETSC_FLOAT), \
480:           PETSC_GENERIC_CV(        double, PETSC_DOUBLE), \
481:           PETSC_GENERIC_CV(       int32_t, PETSC_INT32), \
482:           PETSC_GENERIC_CV(      uint32_t, PETSC_INT32), \
483:           PETSC_GENERIC_CV(       int64_t, PETSC_INT64), \
484:           PETSC_GENERIC_CV(      uint64_t, PETSC_INT64), \
485:           PETSC_GENERIC_CV_COMPLEX(PETSC_COMPLEX))

487:       #define PETSC_GENERIC_CV_STRINGIZE(type) PETSC_GENERIC_CV(type, PetscStringize(type))

489:       #if !PetscDefined(SKIP_COMPLEX)
490:         #define PETSC_GENERIC_CV_STRINGIZE_COMPLEX PETSC_GENERIC_CV_STRINGIZE(PetscComplex)
491:       #else
492:         #define PETSC_GENERIC_CV_STRINGIZE_COMPLEX
493:       #endif

495:       #define PetscAssertPointer_String(h) \
496:         _Generic((h), \
497:           default: "memory", \
498:           PETSC_GENERIC_CV_STRINGIZE(char), \
499:           PETSC_GENERIC_CV_STRINGIZE(signed char), \
500:           PETSC_GENERIC_CV_STRINGIZE(unsigned char), \
501:           PETSC_GENERIC_CV_STRINGIZE(short), \
502:           PETSC_GENERIC_CV_STRINGIZE(unsigned short), \
503:           PETSC_GENERIC_CV_STRINGIZE(float), \
504:           PETSC_GENERIC_CV_STRINGIZE(double), \
505:           PETSC_GENERIC_CV_STRINGIZE(int32_t), \
506:           PETSC_GENERIC_CV_STRINGIZE(uint32_t), \
507:           PETSC_GENERIC_CV_STRINGIZE(int64_t), \
508:           PETSC_GENERIC_CV_STRINGIZE(uint64_t), \
509:           PETSC_GENERIC_CV_STRINGIZE_COMPLEX)
510:     #else // PETSC_C_VERSION >= 11 || defined(__cplusplus)
511:       #define PetscAssertPointer_PetscDataType(h) PETSC_CHAR
512:       #define PetscAssertPointer_String(h)        "memory"
513:     #endif // PETSC_C_VERSION >= 11 || defined(__cplusplus)
514:     #define PetscAssertPointer(h, arg) PetscAssertPointer_Internal(h, arg, PetscAssertPointer_PetscDataType(h), PetscAssertPointer_String(h))
516:   #else // PetscDefined(USE_DEBUG)
518:       do { \
519:         (void)(h); \
520:       } while (0)
522:       do { \
523:         (void)(h); \
524:       } while (0)
526:       do { \
527:         (void)(h); \
528:       } while (0)
529:     #define PetscAssertPointer(h, arg) \
530:       do { \
531:         (void)(h); \
532:       } while (0)
534:       do { \
535:         (void)(h); \
536:       } while (0)
537:   #endif // PetscDefined(USE_DEBUG)
538: #endif   // PETSC_CLANG_STATIC_ANALYZER


549: #define PetscSorted(n, idx, sorted) \
550:   do { \
551:     (sorted) = PETSC_TRUE; \
552:     for (PetscInt _i_ = 1; _i_ < (n); ++_i_) { \
553:       if ((idx)[_i_] < (idx)[_i_ - 1]) { \
554:         (sorted) = PETSC_FALSE; \
555:         break; \
556:       } \
557:     } \
558:   } while (0)

560: #if !defined(PETSC_CLANG_STATIC_ANALYZER)
561:   #if !defined(PETSC_USE_DEBUG)

563:     #define PetscCheckSameType(a, arga, b, argb) \
564:       do { \
565:         (void)(a); \
566:         (void)(b); \
567:       } while (0)
568:     #define PetscCheckTypeName(a, type) \
569:       do { \
570:         (void)(a); \
571:       } while (0)
572:     #define PetscCheckTypeNames(a, type1, type2) \
573:       do { \
574:         (void)(a); \
575:       } while (0)
577:       do { \
578:         (void)(a); \
579:       } while (0)
580:     #define PetscCheckSameComm(a, arga, b, argb) \
581:       do { \
582:         (void)(a); \
583:         (void)(b); \
584:       } while (0)
585:     #define PetscCheckSameTypeAndComm(a, arga, b, argb) \
586:       do { \
587:         (void)(a); \
588:         (void)(b); \
589:       } while (0)
591:       do { \
592:         (void)(a); \
593:         (void)(b); \
594:       } while (0)
596:       do { \
597:         (void)(a); \
598:         (void)(b); \
599:       } while (0)
601:       do { \
602:         (void)(a); \
603:         (void)(b); \
604:       } while (0)
606:       do { \
607:         (void)(a); \
608:         (void)(b); \
609:       } while (0)
611:       do { \
612:         (void)(a); \
613:         (void)(b); \
614:       } while (0)
616:       do { \
617:         (void)(a); \
618:         (void)(b); \
619:       } while (0)
620:     #define PetscCheckSorted(n, idx) \
621:       do { \
622:         (void)(n); \
623:         (void)(idx); \
624:       } while (0)

626:   #else

628:     /*
629:   This macro currently does nothing, the plan is for each PetscObject to have a PetscInt "type"
630:   member associated with the string type_name that can be quickly compared.

632:   **Do not swap this macro to compare string type_name!**

634:   This macro is used incorrectly in the code. Many places that do not need identity of the
635:   types incorrectly call this check and would need to be fixed if this macro is enabled.
636: */
637:     #if 0
638:       #define PetscCheckSameType(a, arga, b, argb) \
639:         do { \
640:           PetscBool pcst_type_eq_ = PETSC_TRUE; \
641:           PetscCall(PetscStrcmp(((PetscObject)(a))->type_name, (((PetscObject)(b)))->type_name, &pcst_type_eq_)); \
642:           PetscCheck(pcst_type_eq_, PETSC_COMM_SELF, PETSC_ERR_ARG_NOTSAMETYPE, "Objects not of same type : Argument # % d and % d, % s != % s ", arga, argb, ((PetscObject)(a))->type_name, ((PetscObject)(b))->type_name); \
643:         } while (0)
644:     #else
645:       #define PetscCheckSameType(a, arga, b, argb) \
646:         do { \
647:           (void)(a); \
648:           (void)(b); \
649:         } while (0)
650:     #endif

652:     /*
653:     Check type_name
654: */
655:     #define PetscCheckTypeName(a, type) \
656:       do { \
657:         PetscBool _7_match; \
658:         PetscCall(PetscObjectTypeCompare(((PetscObject)(a)), (type), &_7_match)); \
659:         PetscCheck(_7_match, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Object (%s) is not %s", (char *)(((PetscObject)(a))->type_name), type); \
660:       } while (0)

662:     #define PetscCheckTypeNames(a, type1, type2) \
663:       do { \
664:         PetscBool _7_match; \
665:         PetscCall(PetscObjectTypeCompareAny(((PetscObject)(a)), &_7_match, (type1), (type2), "")); \
666:         PetscCheck(_7_match, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Object (%s) is not %s or %s", (char *)(((PetscObject)(a))->type_name), type1, type2); \
667:       } while (0)

669:     /*
670:    Use this macro to check if the type is set
671: */

674:     /*
675:    Sometimes object must live on same communicator to inter-operate
676: */
677:     #define PetscCheckSameComm(a, arga, b, argb) \
678:       do { \
679:         PetscMPIInt _7_flag; \
680:         PetscCallMPI(MPI_Comm_compare(PetscObjectComm((PetscObject)(a)), PetscObjectComm((PetscObject)(b)), &_7_flag)); \
681:         PetscCheck(_7_flag == MPI_CONGRUENT || _7_flag == MPI_IDENT, PETSC_COMM_SELF, PETSC_ERR_ARG_NOTSAMECOMM, "Different communicators in the two objects: Argument # %d and %d flag %d", arga, argb, _7_flag); \
682:       } while (0)

684:     #define PetscCheckSameTypeAndComm(a, arga, b, argb) \
685:       do { \
686:         PetscCheckSameType(a, arga, b, argb); \
687:         PetscCheckSameComm(a, arga, b, argb); \
688:       } while (0)

691:       do { \
692:         PetscScalar b0 = (b); \
693:         PetscReal   b1[5], b2[5]; \
694:         if (PetscIsNanScalar(b0)) { \
695:           b1[4] = 1; \
696:         } else { \
697:           b1[4] = 0; \
698:         }; \
699:         b1[0] = -PetscRealPart(b0); \
700:         b1[1] = PetscRealPart(b0); \
701:         b1[2] = -PetscImaginaryPart(b0); \
702:         b1[3] = PetscImaginaryPart(b0); \
703:         PetscCall(MPIU_Allreduce(b1, b2, 5, MPIU_REAL, MPIU_MAX, PetscObjectComm((PetscObject)(a)))); \
704:         PetscCheck(b2[4] > 0 || (PetscEqualReal(-b2[0], b2[1]) && PetscEqualReal(-b2[2], b2[3])), PetscObjectComm((PetscObject)(a)), PETSC_ERR_ARG_WRONG, "Scalar value must be same on all processes, argument # %d", arg); \
705:       } while (0)

708:       do { \
709:         PetscReal b0 = (b), b1[3], b2[3]; \
710:         if (PetscIsNanReal(b0)) { \
711:           b1[2] = 1; \
712:         } else { \
713:           b1[2] = 0; \
714:         }; \
715:         b1[0] = -b0; \
716:         b1[1] = b0; \
717:         PetscCall(MPIU_Allreduce(b1, b2, 3, MPIU_REAL, MPIU_MAX, PetscObjectComm((PetscObject)(a)))); \
718:         PetscCheck(b2[2] > 0 || PetscEqualReal(-b2[0], b2[1]), PetscObjectComm((PetscObject)(a)), PETSC_ERR_ARG_WRONG, "Real value must be same on all processes, argument # %d", arg); \
719:       } while (0)

722:       do { \
723:         PetscInt b0 = (b), b1[2], b2[2]; \
724:         b1[0]       = -b0; \
725:         b1[1]       = b0; \
726:         PetscCall(MPIU_Allreduce(b1, b2, 2, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)(a)))); \
727:         PetscCheck(-b2[0] == b2[1], PetscObjectComm((PetscObject)(a)), PETSC_ERR_ARG_WRONG, "Int value must be same on all processes, argument # %d", arg); \
728:       } while (0)

731:       do { \
732:         PetscMPIInt b0 = (b), b1[2], b2[2]; \
733:         b1[0]          = -b0; \
734:         b1[1]          = b0; \
735:         PetscCall(MPIU_Allreduce(b1, b2, 2, MPI_INT, MPI_MAX, PetscObjectComm((PetscObject)(a)))); \
736:         PetscCheck(-b2[0] == b2[1], PetscObjectComm((PetscObject)(a)), PETSC_ERR_ARG_WRONG, "PetscMPIInt value must be same on all processes, argument # %d", arg); \
737:       } while (0)

740:       do { \
741:         PetscMPIInt b0 = (PetscMPIInt)(b), b1[2], b2[2]; \
742:         b1[0]          = -b0; \
743:         b1[1]          = b0; \
744:         PetscCall(MPIU_Allreduce(b1, b2, 2, MPI_INT, MPI_MAX, PetscObjectComm((PetscObject)(a)))); \
745:         PetscCheck(-b2[0] == b2[1], PetscObjectComm((PetscObject)(a)), PETSC_ERR_ARG_WRONG, "Bool value must be same on all processes, argument # %d", arg); \
746:       } while (0)

749:       do { \
750:         PetscMPIInt b0 = (PetscMPIInt)(b), b1[2], b2[2]; \
751:         b1[0]          = -b0; \
752:         b1[1]          = b0; \
753:         PetscCall(MPIU_Allreduce(b1, b2, 2, MPI_INT, MPI_MAX, PetscObjectComm((PetscObject)(a)))); \
754:         PetscCheck(-b2[0] == b2[1], PetscObjectComm((PetscObject)(a)), PETSC_ERR_ARG_WRONG, "Enum value must be same on all processes, argument # %d", arg); \
755:       } while (0)

757:     #define PetscCheckSorted(n, idx) \
758:       do { \
759:         PetscBool _1_flg; \
760:         PetscSorted(n, idx, _1_flg); \
761:         PetscCheck(_1_flg, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Input array needs to be sorted"); \
762:       } while (0)

764:   #endif
765: #else  /* PETSC_CLANG_STATIC_ANALYZER */
766: template <typename Ta, typename Tb>
767: extern void PetscCheckSameType(Ta, int, Tb, int);
768: template <typename Ta, typename Tb>
769: extern void PetscCheckTypeName(Ta, Tb);
770: template <typename Ta, typename Tb, typename Tc>
771: extern void PetscCheckTypeNames(Ta, Tb, Tc);
772: template <typename T>
774: template <typename Ta, typename Tb>
775: extern void PetscCheckSameComm(Ta, int, Tb, int);
776: template <typename Ta, typename Tb>
777: extern void PetscCheckSameTypeAndComm(Ta, int, Tb, int);
778: template <typename Ta, typename Tb>
780: template <typename Ta, typename Tb>
782: template <typename Ta, typename Tb>
784: template <typename Ta, typename Tb>
786: template <typename Ta, typename Tb>
788: template <typename Ta, typename Tb>
790: template <typename T>
791: extern void PetscCheckSorted(PetscInt, T);
792: #endif /* PETSC_CLANG_STATIC_ANALYZER */

794: /*MC
795:    PetscTryMethod - Queries a `PetscObject` for a method added with `PetscObjectComposeFunction()`, if it exists then calls it.

797:   Synopsis:
798:    #include "petsc/private/petscimpl.h"
799:    PetscTryMethod(PetscObject obj, const char *name, (arg_types), (arg_value))

801:    Input Parameters:
802: +   obj - the object, for example a `Mat`, that does not need to be cast to `PetscObject`
803: .   name - the name of the method, for example, "KSPGMRESSetRestart_C" for the function `KSPGMRESSetRestart()`
804: .   arg_types - the argument types for the method, for example, (KSP,PetscInt)
805: -   args - the arguments for the method, for example, (ksp,restart))

807:    Level: developer

809:    Notes:
810:    This does not return an error code, it is a macro that returns from the subroutine with an error code on error.

812:    Use `PetscUseTypeMethod()` or `PetscTryTypeMethod()` to call functions that are included in the object's function table, the `ops` array
813:    in the object.

815: .seealso: `PetscUseMethod()`, `PetscCall()`, `PetscUseTypeMethod()`, `PetscTryTypeMethod()`, `PetscCheck()`, `PetscObject`
816: M*/
817: #define PetscTryMethod(obj, A, B, C) \
818:   do { \
819:     PetscErrorCode(*_7_f) B; \
820:     PetscCall(PetscObjectQueryFunction((PetscObject)(obj), A, &_7_f)); \
821:     if (_7_f) PetscCall((*_7_f)C); \
822:   } while (0)

824: /*MC
825:    PetscUseMethod - Queries a `PetscObject` for a method added with `PetscObjectComposeFunction()`, if it exists then calls it, otherwise generates an error.

827:   Synopsis:
828:    #include "petsc/private/petscimpl.h"
829:    PetscUseMethod(PetscObject obj, const char *name, (arg_types), (arg_value))

831:    Input Parameters:
832: +   obj - the object, for example a `Mat`, that does not need to be cast to `PetscObject`
833: .   name - the name of the method, for example, "KSPGMRESSetRestart_C" for the function `KSPGMRESSetRestart()`
834: .   arg_types - the argument types for the method, for example, (KSP,PetscInt)
835: -   args - the arguments for the method, for example, (ksp,restart))

837:    Level: developer

839:    Notes:
840:    This does not return an error code, it is a macro that returns from the subroutine with an error code on error.

842:    Use `PetscUseTypeMethod()` or `PetscTryTypeMethod()` to call functions that are included in the object's function table, the `ops` array
843:    in the object.

845: .seealso: `PetscTryMethod()`, `PetscCall()`, `PetscUseTypeMethod()`, `PetscTryTypeMethod()`, `PetscCheck()`, `PetscObject`
846: M*/
847: #define PetscUseMethod(obj, A, B, C) \
848:   do { \
849:     PetscErrorCode(*_7_f) B; \
850:     PetscCall(PetscObjectQueryFunction((PetscObject)(obj), A, &_7_f)); \
851:     PetscCheck(_7_f, PetscObjectComm((PetscObject)(obj)), PETSC_ERR_SUP, "Cannot locate function %s in object", A); \
852:     PetscCall((*_7_f)C); \
853:   } while (0)

855: /*
856:   Use Microsoft traditional preprocessor.

858:   The Microsoft compiler option -Zc:preprocessor available in recent versions of the compiler
859:   sets  _MSVC_TRADITIONAL to zero so this code path is not used.

861:   It appears the Intel Microsoft Windows compiler icl does not have an equivalent of -Zc:preprocessor

863:   These macros use the trick that Windows compilers remove the , before the __VA_ARGS__ if __VA_ARGS__ does not exist

865:   PetscCall() cannot be used in the macros because the remove the , trick does not work in a macro in a macro
866: */
867: #if (defined(_MSC_VER) && (!defined(_MSVC_TRADITIONAL) || _MSVC_TRADITIONAL)) || defined(__ICL)

869:   #define PetscUseTypeMethod(obj, OP, ...) \
870:     do { \
871:       PetscErrorCode ierr_p_; \
872:       PetscStackUpdateLine; \
873:       PetscCheck((obj)->ops->OP, PetscObjectComm((PetscObject)obj), PETSC_ERR_SUP, "No method %s for %s of type %s", PetscStringize(OP), ((PetscObject)obj)->class_name, ((PetscObject)obj)->type_name); \
874:       ierr_p_ = (*(obj)->ops->OP)(obj, __VA_ARGS__); \
875:       PetscCall(ierr_p_); \
876:     } while (0)

878:   #define PetscTryTypeMethod(obj, OP, ...) \
879:     do { \
880:       if ((obj)->ops->OP) { \
881:         PetscErrorCode ierr_p_; \
882:         PetscStackUpdateLine; \
883:         ierr_p_ = (*(obj)->ops->OP)(obj, __VA_ARGS__); \
884:         PetscCall(ierr_p_); \
885:       } \
886:     } while (0)

888: #else

890:   /*MC
891:    PetscUseTypeMethod - Call a method on a `PetscObject`, that is a function in the objects function table `obj->ops`, error if the method does not exist

893:   Synopsis:
894:    #include "petsc/private/petscimpl.h"
895:    PetscUseTypeMethod(obj, method, other_args)

897:    Input Parameters:
898: +   obj - the object, for example a `Mat`, that does not need to be cast to `PetscObject`
899: .   method - the name of the method, for example, mult for the PETSc routine `MatMult()`
900: -   other_args - the other arguments for the method, `obj` is the first argument

902:    Level: developer

904:    Note:
905:    This does not return an error code, it is a macro that returns from the subroutine with an error code on error.

907:    Use `PetscUseMethod()` or `PetscTryMethod()` to call functions that have been composed to an object with `PetscObjectComposeFunction()`

909: .seealso: `PetscTryMethod()`, `PetscUseMethod()`, `PetscCall()`, `PetscCheck()`, `PetscTryTypeMethod()`
910: M*/
911:   #define PetscUseTypeMethod(obj, ...) \
912:     do { \
913:       PetscCheck((obj)->ops->PETSC_FIRST_ARG((__VA_ARGS__, unused)), PetscObjectComm((PetscObject)obj), PETSC_ERR_SUP, "No method %s for %s of type %s", \
914:                  PetscStringize(PETSC_FIRST_ARG((__VA_ARGS__,unused))), ((PetscObject)obj)->class_name, ((PetscObject)obj)->type_name); \
915:       PetscCall((*(obj)->ops->PETSC_FIRST_ARG((__VA_ARGS__, unused)))(obj PETSC_REST_ARG(__VA_ARGS__))); \
916:     } while (0)

918:   /*MC
919:    PetscTryTypeMethod - Call a method on a `PetscObject`, that is a function in the objects function table `obj->ops`, skip if the method does not exist

921:   Synopsis:
922:    #include "petsc/private/petscimpl.h"
923:    PetscTryTypeMethod(obj, method, other_args)

925:    Input Parameters:
926: +   obj - the object, for example a `Mat`, that does not need to be cast to `PetscObject`
927: .   method - the name of the method, for example, mult for the PETSc routine `MatMult()`
928: -   other_args - the other arguments for the method, `obj` is the first argument

930:    Level: developer

932:    Note:
933:    This does not return an error code, it is a macro that returns from the subroutine with an error code on error.

935:    Use `PetscUseMethod()` or `PetscTryMethod()` to call functions that have been composed to an object with `PetscObjectComposeFunction()`

937: .seealso: `PetscTryMethod()`, `PetscUseMethod()`, `PetscCall()`, `PetscCheck()`, `PetscUseTypeMethod()`
938: M*/
939:   #define PetscTryTypeMethod(obj, ...) \
940:     do { \
941:       if ((obj)->ops->PETSC_FIRST_ARG((__VA_ARGS__, unused))) PetscCall((*(obj)->ops->PETSC_FIRST_ARG((__VA_ARGS__, unused)))(obj PETSC_REST_ARG(__VA_ARGS__))); \
942:     } while (0)

944: #endif

946: /*MC
947:    PetscObjectStateIncrease - Increases the state of any `PetscObject`

949:    Synopsis:
950:    #include "petsc/private/petscimpl.h"
951:    PetscErrorCode PetscObjectStateIncrease(PetscObject obj)

953:    Logically Collective

955:    Input Parameter:
956: .  obj - any PETSc object, for example a `Vec`, `Mat` or `KSP`. This must be
957:          cast with a (PetscObject), for example,
958:          `PetscObjectStateIncrease`((`PetscObject`)mat);

960:    Level: developer

962:    Notes:
963:    Object state is a 64-bit integer which gets increased every time
964:    the object is changed internally. By saving and later querying the object state
965:    one can determine whether information about the object is still current.
966:    Currently, state is maintained for `Vec` and `Mat` objects.

968:    This routine is mostly for internal use by PETSc; a developer need only
969:    call it after explicit access to an object's internals. Routines such
970:    as `VecSet()` or `MatScale()` already call this routine. It is also called, as a
971:    precaution, in `VecRestoreArray()`, `MatRestoreRow()`, `MatDenseRestoreArray()`.

973:    Routines such as `VecNorm()` can by-pass the computation if the norm has already been computed and the vector's state has not changed.

975:    This routine is logically collective because state equality comparison needs to be possible without communication.

977:    `Mat` also has `MatGetNonzeroState()` for tracking changes to the nonzero structure.

979: .seealso: `PetscObjectStateGet()`, `PetscObject`
980: M*/
981: #define PetscObjectStateIncrease(obj) ((obj)->state++, PETSC_SUCCESS)

983: PETSC_EXTERN PetscErrorCode PetscObjectStateGet(PetscObject, PetscObjectState *);
984: PETSC_EXTERN PetscErrorCode PetscObjectStateSet(PetscObject, PetscObjectState);
985: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataRegister(PetscInt *);
986: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseInt(PetscObject);
987: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseIntstar(PetscObject);
988: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseReal(PetscObject);
989: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseRealstar(PetscObject);
990: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseScalar(PetscObject);
991: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseScalarstar(PetscObject);
992: PETSC_EXTERN PetscInt       PetscObjectComposedDataMax;

994: /*MC
995:    PetscObjectComposedDataSetInt - attach `PetscInt` data to a `PetscObject` that may be later accessed with `PetscObjectComposedDataGetInt()`

997:    Synopsis:
998:    #include "petsc/private/petscimpl.h"
999:    PetscErrorCode PetscObjectComposedDataSetInt(PetscObject obj, PetscInt id, PetscInt data)

1001:    Not Collective

1003:    Input Parameters:
1004: +  obj - the object to which data is to be attached
1005: .  id - the identifier for the data
1006: -  data - the data to  be attached, a `PetscInt`

1008:    Level: developer

1010:    Notes:
1011:    The `data` identifier can be created through a call to `PetscObjectComposedDataRegister()`

1013:    This allows the efficient composition of a single integer value with a `PetscObject`. Complex data may be
1014:    attached with `PetscObjectCompose()`

1016: .seealso: `PetscObjectComposedDataGetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetReal()`,
1017:           `PetscObjectComposedDataGetIntstar()`, `PetscObjectComposedDataSetIntstar()`, `PetscObject`,
1018:           `PetscObjectCompose()`, `PetscObjectQuery()`
1019: M*/
1020: #define PetscObjectComposedDataSetInt(obj, id, data) \
1021:   ((PetscErrorCode)((((obj)->int_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseInt(obj)) || ((obj)->intcomposeddata[id] = data, (obj)->intcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))

1023: /*MC
1024:    PetscObjectComposedDataGetInt - retrieve `PetscInt` data attached to a `PetscObject` `PetscObjectComposedDataSetInt()`

1026:    Synopsis:
1027:    #include "petsc/private/petscimpl.h"
1028:    PetscErrorCode PetscObjectComposedDataGetInt(PetscObject obj, PetscInt id, PetscInt data, PetscBool flag)

1030:    Not Collective

1032:    Input Parameters:
1033: +  obj - the object from which data is to be retrieved
1034: -  id - the identifier for the data

1036:    Output Parameters:
1037: +  data - the data to be retrieved, a `PetscInt`
1038: -  flag - `PETSC_TRUE` if the data item exists and is valid, `PETSC_FALSE` otherwise

1040:    Level: developer

1042:    Notes:
1043:    The `data` and `flag` variables are inlined, so they are not pointers.

1045: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetReal()`,
1046:           `PetscObjectComposedDataGetIntstar()`, `PetscObjectComposedDataSetIntstar()`, `PetscObject`,
1047:           `PetscObjectCompose()`, `PetscObjectQuery()`
1048: M*/
1049: #define PetscObjectComposedDataGetInt(obj, id, data, flag) (((obj)->intcomposedstate ? (data = (obj)->intcomposeddata[id], flag = (PetscBool)((obj)->intcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), PETSC_SUCCESS)

1051: /*MC
1052:    PetscObjectComposedDataSetIntstar - attach `PetscInt` array data to a `PetscObject` that may be accessed later with `PetscObjectComposedDataGetIntstar()`

1054:    Synopsis:
1055:    #include "petsc/private/petscimpl.h"
1056:    PetscErrorCode PetscObjectComposedDataSetIntstar(PetscObject obj, PetscInt id, PetscInt *data)

1058:    Not Collective

1060:    Input Parameters:
1061: +  obj - the object to which data is to be attached
1062: .  id - the identifier for the data
1063: -  data - the data to  be attached, a `PetscInt` array

1065:    Level: developer

1067:    Notes:
1068:    The `data` identifier can be determined through a call to `PetscObjectComposedDataRegister()`

1070:    The length of the array accessed must be known, it is not available through this API.

1072: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetReal()`,
1073:           `PetscObjectComposedDataGetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1074:           `PetscObjectCompose()`, `PetscObjectQuery()`
1075: M*/
1076: #define PetscObjectComposedDataSetIntstar(obj, id, data) \
1077:   ((PetscErrorCode)((((obj)->intstar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseIntstar(obj)) || ((obj)->intstarcomposeddata[id] = data, (obj)->intstarcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))

1079: /*MC
1080:    PetscObjectComposedDataGetIntstar - retrieve `PetscInt` array data attached to a `PetscObject` with `PetscObjectComposedDataSetIntstar()`

1082:    Synopsis:
1083:    #include "petsc/private/petscimpl.h"
1084:    PetscErrorCode PetscObjectComposedDataGetIntstar(PetscObject obj, PetscInt id, PetscInt *data, PetscBool flag)

1086:    Not Collective

1088:    Input Parameters:
1089: +  obj - the object from which data is to be retrieved
1090: -  id - the identifier for the data

1092:    Output Parameters:
1093: +  data - the data to be retrieved, a `PetscInt` array
1094: -  flag - `PETSC_TRUE` if the data item exists and is valid, `PETSC_FALSE` otherwise

1096:    Level: developer

1098:    Notes:
1099:    The `data` and `flag` variables are inlined, so they are not pointers.

1101:    The length of the array accessed must be known, it is not available through this API.

1103: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetReal()`,
1104:           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1105:           `PetscObjectCompose()`, `PetscObjectQuery()`
1106: M*/
1107: #define PetscObjectComposedDataGetIntstar(obj, id, data, flag) \
1108:   ((PetscErrorCode)(((obj)->intstarcomposedstate ? (data = (obj)->intstarcomposeddata[id], flag = (PetscBool)((obj)->intstarcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), PETSC_SUCCESS))

1110: /*MC
1111:    PetscObjectComposedDataSetReal - attach `PetscReal` data to a `PetscObject` that may be later accessed with `PetscObjectComposedDataGetReal()`

1113:    Synopsis:
1114:    #include "petsc/private/petscimpl.h"
1115:    PetscErrorCode PetscObjectComposedDataSetReal(PetscObject obj, PetscInt id, PetscReal data)

1117:    Not Collective

1119:    Input Parameters:
1120: +  obj - the object to which data is to be attached
1121: .  id - the identifier for the data
1122: -  data - the data to  be attached, a `PetscReal`

1124:    Level: developer

1126:    Note:
1127:    The `data` identifier can be determined through a call to  `PetscObjectComposedDataRegister()`

1129: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1130:           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1131:           `PetscObjectCompose()`, `PetscObjectQuery()`
1132: M*/
1133: #define PetscObjectComposedDataSetReal(obj, id, data) \
1134:   ((PetscErrorCode)((((obj)->real_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseReal(obj)) || ((obj)->realcomposeddata[id] = data, (obj)->realcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))

1136: /*MC
1137:    PetscObjectComposedDataGetReal - retrieve `PetscReal` data attached to a `PetscObject` set with `PetscObjectComposedDataSetReal()`

1139:    Synopsis:
1140:    #include "petsc/private/petscimpl.h"
1141:    PetscErrorCode PetscObjectComposedDataGetReal(PetscObject obj, PetscInt id, PetscReal data, PetscBool flag)

1143:    Not Collective

1145:    Input Parameters:
1146: +  obj - the object from which data is to be retrieved
1147: -  id - the identifier for the data

1149:    Output Parameters:
1150: +  data - the data to be retrieved, a `PetscReal`
1151: -  flag - `PETSC_TRUE` if the data item exists and is valid, `PETSC_FALSE` otherwise

1153:    Level: developer

1155:    Note:
1156:    The `data` and `flag` variables are inlined, so they are not pointers.

1158: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataSetIntstar()`,
1159:           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1160:           `PetscObjectCompose()`, `PetscObjectQuery()`
1161: M*/
1162: #define PetscObjectComposedDataGetReal(obj, id, data, flag) ((PetscErrorCode)(((obj)->realcomposedstate ? (data = (obj)->realcomposeddata[id], flag = (PetscBool)((obj)->realcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), PETSC_SUCCESS))

1164: /*MC
1165:    PetscObjectComposedDataSetRealstar - attach `PetscReal` array data to a `PetscObject` that may be retrieved with `PetscObjectComposedDataGetRealstar()`

1167:    Synopsis:
1168:    #include "petsc/private/petscimpl.h"
1169:    PetscErrorCode PetscObjectComposedDataSetRealstar(PetscObject obj, PetscInt id, PetscReal *data)

1171:    Not Collective

1173:    Input Parameters:
1174: +  obj - the object to which data is to be attached
1175: .  id - the identifier for the data
1176: -  data - the data to  be attached

1178:    Level: developer

1180:    Notes:
1181:    The `data` identifier can be determined through a call to `PetscObjectComposedDataRegister()`

1183:    The length of the array accessed must be known, it is not available through this API.

1185: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1186:           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1187:           `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataGetRealstar()`
1188: M*/
1189: #define PetscObjectComposedDataSetRealstar(obj, id, data) \
1190:   ((PetscErrorCode)((((obj)->realstar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseRealstar(obj)) || ((obj)->realstarcomposeddata[id] = data, (obj)->realstarcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))

1192: /*MC
1193:    PetscObjectComposedDataGetRealstar - retrieve `PetscReal` array data attached to a `PetscObject` with `PetscObjectComposedDataSetRealstar()`

1195:    Synopsis:
1196:    #include "petsc/private/petscimpl.h"
1197:    PetscErrorCode PetscObjectComposedDataGetRealstar(PetscObject obj, PetscInt id, PetscReal *data, PetscBool flag)

1199:    Not Collective

1201:    Input Parameters:
1202: +  obj - the object from which data is to be retrieved
1203: -  id - the identifier for the data

1205:    Output Parameters:
1206: +  data - the data to be retrieved, a `PetscReal` array
1207: -  flag - `PETSC_TRUE` if the data item exists and is valid, `PETSC_FALSE` otherwise

1209:    Level: developer

1211:    Notes:
1212:    The `data` and `flag` variables are inlined, so they are not pointers.

1214:    The length of the array accessed must be known, it is not available through this API.

1216: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1217:           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1218:           `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`
1219: M*/
1220: #define PetscObjectComposedDataGetRealstar(obj, id, data, flag) \
1221:   ((PetscErrorCode)(((obj)->realstarcomposedstate ? (data = (obj)->realstarcomposeddata[id], flag = (PetscBool)((obj)->realstarcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), PETSC_SUCCESS))

1223: /*MC
1224:    PetscObjectComposedDataSetScalar - attach `PetscScalar` data to a `PetscObject` that may be later retrieved with `PetscObjectComposedDataGetScalar()`

1226:    Synopsis:
1227:    #include "petsc/private/petscimpl.h"
1228:    PetscErrorCode PetscObjectComposedDataSetScalar(PetscObject obj, PetscInt id, PetscScalar data)

1230:    Not Collective

1232:    Input Parameters:
1233: +  obj - the object to which data is to be attached
1234: .  id - the identifier for the data
1235: -  data - the data to  be attached, a `PetscScalar`

1237:    Level: developer

1239:    Note:
1240:    The `data` identifier can be determined through a call to `PetscObjectComposedDataRegister()`

1242: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1243:           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1244:           `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`, `PetscObjectComposedDataGetScalar()`
1245: M*/
1246: #if defined(PETSC_USE_COMPLEX)
1247:   #define PetscObjectComposedDataSetScalar(obj, id, data) \
1248:     ((PetscErrorCode)((((obj)->scalar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseScalar(obj)) || ((obj)->scalarcomposeddata[id] = data, (obj)->scalarcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))
1249: #else
1250:   #define PetscObjectComposedDataSetScalar(obj, id, data) PetscObjectComposedDataSetReal(obj, id, data)
1251: #endif
1252: /*MC
1253:    PetscObjectComposedDataGetScalar - retrieve `PetscScalar` data attached to a `PetscObject` that was set with `PetscObjectComposedDataSetScalar()`

1255:    Synopsis:
1256:    #include "petsc/private/petscimpl.h"
1257:    PetscErrorCode PetscObjectComposedDataGetScalar(PetscObject obj, PetscInt id, PetscScalar data, PetscBool flag)

1259:    Not Collective

1261:    Input Parameters:
1262: +  obj - the object from which data is to be retrieved
1263: -  id - the identifier for the data

1265:    Output Parameters:
1266: +  data - the data to be retrieved, a `PetscScalar`
1267: -  flag - `PETSC_TRUE` if the data item exists and is valid, `PETSC_FALSE` otherwise

1269:    Level: developer

1271:    Note:
1272:    The `data` and `flag` variables are inlined, so they are not pointers.

1274: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1275:           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1276:           `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`, `PetscObjectComposedDataSetScalar()`
1277: M*/
1278: #if defined(PETSC_USE_COMPLEX)
1279:   #define PetscObjectComposedDataGetScalar(obj, id, data, flag) \
1280:     ((PetscErrorCode)(((obj)->scalarcomposedstate ? (data = (obj)->scalarcomposeddata[id], flag = (PetscBool)((obj)->scalarcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), PETSC_SUCCESS))
1281: #else
1282:   #define PetscObjectComposedDataGetScalar(obj, id, data, flag) PetscObjectComposedDataGetReal(obj, id, data, flag)
1283: #endif

1285: /*MC
1286:    PetscObjectComposedDataSetScalarstar - attach `PetscScalar` array data to a `PetscObject` that may be later retrieved with `PetscObjectComposedDataSetScalarstar()`

1288:    Synopsis:
1289:    #include "petsc/private/petscimpl.h"
1290:    PetscErrorCode PetscObjectComposedDataSetScalarstar(PetscObject obj, PetscInt id, PetscScalar *data)

1292:    Not Collective

1294:    Input Parameters:
1295: +  obj - the object to which data is to be attached
1296: .  id - the identifier for the data
1297: -  data - the data to  be attached, a `PetscScalar` array

1299:    Level: developer

1301:    Notes:
1302:    The `data` identifier can be determined through a call to `PetscObjectComposedDataRegister()`

1304:    The length of the array accessed must be known, it is not available through this API.

1306: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1307:           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1308:           `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`, `PetscObjectComposedDataGetScalarstar()`
1309: M*/
1310: #if defined(PETSC_USE_COMPLEX)
1311:   #define PetscObjectComposedDataSetScalarstar(obj, id, data) \
1312:     ((PetscErrorCode)((((obj)->scalarstar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseScalarstar(obj)) || ((obj)->scalarstarcomposeddata[id] = data, (obj)->scalarstarcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))
1313: #else
1314:   #define PetscObjectComposedDataSetScalarstar(obj, id, data) PetscObjectComposedDataSetRealstar(obj, id, data)
1315: #endif
1316: /*MC
1317:    PetscObjectComposedDataGetScalarstar - retrieve `PetscScalar` array data attached to a `PetscObject` that was set with `PetscObjectComposedDataSetScalarstar()`
1318:    attached to an object

1320:    Synopsis:
1321:    #include "petsc/private/petscimpl.h"
1322:    PetscErrorCode PetscObjectComposedDataGetScalarstar(PetscObject obj, PetscInt id, PetscScalar *data, PetscBool flag)

1324:    Not Collective

1326:    Input Parameters:
1327: +  obj - the object from which data is to be retrieved
1328: -  id - the identifier for the data

1330:    Output Parameters:
1331: +  data - the data to be retrieved, a `PetscScalar` array
1332: -  flag - `PETSC_TRUE` if the data item exists and is valid, `PETSC_FALSE` otherwise

1334:    Level: developer

1336:    Notes:
1337:    The `data` and `flag` variables are inlined, so they are not pointers.

1339:    The length of the array accessed must be known, it is not available through this API.

1341: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1342:           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1343:           `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`, `PetscObjectComposedDataSetScalarstar()`
1344: M*/
1345: #if defined(PETSC_USE_COMPLEX)
1346:   #define PetscObjectComposedDataGetScalarstar(obj, id, data, flag) \
1347:     ((PetscErrorCode)(((obj)->scalarstarcomposedstate ? (data = (obj)->scalarstarcomposeddata[id], flag = (PetscBool)((obj)->scalarstarcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), PETSC_SUCCESS))
1348: #else
1349:   #define PetscObjectComposedDataGetScalarstar(obj, id, data, flag) PetscObjectComposedDataGetRealstar(obj, id, data, flag)
1350: #endif

1352: PETSC_EXTERN PetscMPIInt Petsc_Counter_keyval;
1353: PETSC_EXTERN PetscMPIInt Petsc_InnerComm_keyval;
1354: PETSC_EXTERN PetscMPIInt Petsc_OuterComm_keyval;
1355: PETSC_EXTERN PetscMPIInt Petsc_Seq_keyval;
1356: PETSC_EXTERN PetscMPIInt Petsc_ShmComm_keyval;
1357: PETSC_EXTERN PetscMPIInt Petsc_CreationIdx_keyval;
1358: PETSC_EXTERN PetscMPIInt Petsc_Garbage_HMap_keyval;

1360: PETSC_EXTERN PetscMPIInt Petsc_SharedWD_keyval;
1361: PETSC_EXTERN PetscMPIInt Petsc_SharedTmp_keyval;

1363: struct PetscCommStash {
1364:   struct PetscCommStash *next;
1365:   MPI_Comm               comm;
1366: };

1368: /*
1369:   PETSc communicators have this attribute, see
1370:   PetscCommDuplicate(), PetscCommDestroy(), PetscCommGetNewTag(), PetscObjectGetName()
1371: */
1372: typedef struct {
1373:   PetscMPIInt            tag;       /* next free tag value */
1374:   PetscInt               refcount;  /* number of references, communicator can be freed when this reaches 0 */
1375:   PetscInt               namecount; /* used to generate the next name, as in Vec_0, Mat_1, ... */
1376:   PetscMPIInt           *iflags;    /* length of comm size, shared by all calls to PetscCommBuildTwoSided_Allreduce/RedScatter on this comm */
1377:   struct PetscCommStash *comms;     /* communicators available for PETSc to pass off to other packages */
1378: } PetscCommCounter;

1380: typedef enum {
1381:   STATE_BEGIN,
1382:   STATE_PENDING,
1383:   STATE_END
1384: } SRState;

1386: typedef enum {
1387:   PETSC_SR_REDUCE_SUM = 0,
1388:   PETSC_SR_REDUCE_MAX = 1,
1389:   PETSC_SR_REDUCE_MIN = 2
1390: } PetscSRReductionType;

1392: typedef struct {
1393:   MPI_Comm     comm;
1394:   MPI_Request  request;
1395:   PetscBool    mix;
1396:   PetscBool    async;
1397:   PetscScalar *lvalues;    /* this are the reduced values before call to MPI_Allreduce() */
1398:   PetscScalar *gvalues;    /* values after call to MPI_Allreduce() */
1399:   void       **invecs;     /* for debugging only, vector/memory used with each op */
1400:   PetscInt    *reducetype; /* is particular value to be summed or maxed? */
1401:   struct {
1402:     PetscScalar v;
1403:     PetscInt    i;
1404:   }       *lvalues_mix, *gvalues_mix; /* used when mixing reduce operations */
1405:   SRState  state;                     /* are we calling xxxBegin() or xxxEnd()? */
1406:   PetscInt maxops;                    /* total amount of space we have for requests */
1407:   PetscInt numopsbegin;               /* number of requests that have been queued in */
1408:   PetscInt numopsend;                 /* number of requests that have been gotten by user */
1409: } PetscSplitReduction;

1411: PETSC_EXTERN PetscErrorCode PetscSplitReductionGet(MPI_Comm, PetscSplitReduction **);
1412: PETSC_EXTERN PetscErrorCode PetscSplitReductionEnd(PetscSplitReduction *);
1413: PETSC_EXTERN PetscErrorCode PetscSplitReductionExtend(PetscSplitReduction *);

1415: #if defined(PETSC_HAVE_THREADSAFETY)
1416:   #if defined(PETSC_HAVE_CONCURRENCYKIT)
1417:     #if defined(__cplusplus)
1418: /*  CK does not have extern "C" protection in their include files */
1419: extern "C" {
1420:     #endif
1421:     #include <ck_spinlock.h>
1422:     #if defined(__cplusplus)
1423: }
1424:     #endif
1425: typedef ck_spinlock_t PetscSpinlock;

1427: static inline PetscErrorCode PetscSpinlockCreate(PetscSpinlock *ck_spinlock)
1428: {
1429:   ck_spinlock_init(ck_spinlock);
1430:   return PETSC_SUCCESS;
1431: }
1432: static inline PetscErrorCode PetscSpinlockLock(PetscSpinlock *ck_spinlock)
1433: {
1434:   ck_spinlock_lock(ck_spinlock);
1435:   return PETSC_SUCCESS;
1436: }
1437: static inline PetscErrorCode PetscSpinlockUnlock(PetscSpinlock *ck_spinlock)
1438: {
1439:   ck_spinlock_unlock(ck_spinlock);
1440:   return PETSC_SUCCESS;
1441: }
1442: static inline PetscErrorCode PetscSpinlockDestroy(PetscSpinlock *ck_spinlock)
1443: {
1444:   return PETSC_SUCCESS;
1445: }
1446:   #elif (defined(__cplusplus) && defined(PETSC_HAVE_CXX_ATOMIC)) || (!defined(__cplusplus) && defined(PETSC_HAVE_STDATOMIC_H))
1447:     #if defined(__cplusplus)
1448:       #include <atomic>
1449:       #define petsc_atomic_flag                 std::atomic_flag
1450:       #define petsc_atomic_flag_test_and_set(p) std::atomic_flag_test_and_set_explicit(p, std::memory_order_relaxed)
1451:       #define petsc_atomic_flag_clear(p)        std::atomic_flag_clear_explicit(p, std::memory_order_relaxed)
1452:     #else
1453:       #include <stdatomic.h>
1454:       #define petsc_atomic_flag                 atomic_flag
1455:       #define petsc_atomic_flag_test_and_set(p) atomic_flag_test_and_set_explicit(p, memory_order_relaxed)
1456:       #define petsc_atomic_flag_clear(p)        atomic_flag_clear_explicit(p, memory_order_relaxed)
1457:     #endif

1459: typedef petsc_atomic_flag PetscSpinlock;

1461: static inline PetscErrorCode PetscSpinlockCreate(PetscSpinlock *spinlock)
1462: {
1463:   petsc_atomic_flag_clear(spinlock);
1464:   return PETSC_SUCCESS;
1465: }
1466: static inline PetscErrorCode PetscSpinlockLock(PetscSpinlock *spinlock)
1467: {
1468:   do {
1469:   } while (petsc_atomic_flag_test_and_set(spinlock));
1470:   return PETSC_SUCCESS;
1471: }
1472: static inline PetscErrorCode PetscSpinlockUnlock(PetscSpinlock *spinlock)
1473: {
1474:   petsc_atomic_flag_clear(spinlock);
1475:   return PETSC_SUCCESS;
1476: }
1477: static inline PetscErrorCode PetscSpinlockDestroy(PETSC_UNUSED PetscSpinlock *spinlock)
1478: {
1479:   return PETSC_SUCCESS;
1480: }
1481:     #undef petsc_atomic_flag_test_and_set
1482:     #undef petsc_atomic_flag_clear
1483:     #undef petsc_atomic_flag

1485:   #elif defined(PETSC_HAVE_OPENMP)

1487:     #include <omp.h>
1488: typedef omp_lock_t PetscSpinlock;

1490: static inline PetscErrorCode PetscSpinlockCreate(PetscSpinlock *omp_lock)
1491: {
1492:   omp_init_lock(omp_lock);
1493:   return PETSC_SUCCESS;
1494: }
1495: static inline PetscErrorCode PetscSpinlockLock(PetscSpinlock *omp_lock)
1496: {
1497:   omp_set_lock(omp_lock);
1498:   return PETSC_SUCCESS;
1499: }
1500: static inline PetscErrorCode PetscSpinlockUnlock(PetscSpinlock *omp_lock)
1501: {
1502:   omp_unset_lock(omp_lock);
1503:   return PETSC_SUCCESS;
1504: }
1505: static inline PetscErrorCode PetscSpinlockDestroy(PetscSpinlock *omp_lock)
1506: {
1507:   omp_destroy_lock(omp_lock);
1508:   return PETSC_SUCCESS;
1509: }
1510:   #else
1511:     #if defined(__cplusplus)
1512:       #error "Thread safety requires either --download-concurrencykit, std::atomic, or --with-openmp"
1513:     #else
1514:       #error "Thread safety requires either --download-concurrencykit, stdatomic.h, or --with-openmp"
1515:     #endif
1516:   #endif

1518: #else
1519: typedef int PetscSpinlock;
1520:   #define PetscSpinlockCreate(a)  PETSC_SUCCESS
1521:   #define PetscSpinlockLock(a)    PETSC_SUCCESS
1522:   #define PetscSpinlockUnlock(a)  PETSC_SUCCESS
1523:   #define PetscSpinlockDestroy(a) PETSC_SUCCESS
1524: #endif

1526: #if defined(PETSC_HAVE_THREADSAFETY)
1527: PETSC_INTERN PetscSpinlock PetscViewerASCIISpinLockOpen;
1528: PETSC_INTERN PetscSpinlock PetscViewerASCIISpinLockStdout;
1529: PETSC_INTERN PetscSpinlock PetscViewerASCIISpinLockStderr;
1530: PETSC_INTERN PetscSpinlock PetscCommSpinLock;
1531: #endif

1533: PETSC_EXTERN PetscLogEvent PETSC_Barrier;
1534: PETSC_EXTERN PetscLogEvent PETSC_BuildTwoSided;
1535: PETSC_EXTERN PetscLogEvent PETSC_BuildTwoSidedF;
1536: PETSC_EXTERN PetscBool     use_gpu_aware_mpi;
1537: PETSC_EXTERN PetscBool     PetscPrintFunctionList;

1539: #if defined(PETSC_HAVE_ADIOS)
1540: PETSC_EXTERN int64_t Petsc_adios_group;
1541: #endif

1543: #if defined(PETSC_HAVE_KOKKOS)
1544: PETSC_INTERN PetscBool      PetscBeganKokkos;
1545: PETSC_EXTERN PetscBool      PetscKokkosInitialized;
1546: PETSC_INTERN PetscErrorCode PetscKokkosIsInitialized_Private(PetscBool *);
1547: PETSC_INTERN PetscErrorCode PetscKokkosFinalize_Private(void);
1548: #endif

1550: #if defined(PETSC_HAVE_OPENMP)
1551: PETSC_EXTERN PetscInt PetscNumOMPThreads;
1552: #endif

1554: struct _n_PetscObjectList {
1555:   char            name[256];
1556:   PetscBool       skipdereference; /* when the PetscObjectList is destroyed do not call PetscObjectDereference() on this object */
1557:   PetscObject     obj;
1558:   PetscObjectList next;
1559: };