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: } _p_PetscObject;

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

136: #define PETSCFREEDHEADER -1

138: /*S
139:   PetscObjectDestroyFn - A prototype of a function that can destroy a `PetscObject`

141:   Calling Sequence:
142: . obj - the `PetscObject` to destroy

144:   Level: beginner

146:   Note:
147:   The deprecated `PetscObjectDestroyFunction` works as a replacement for `PetscObjectDestroyFn` *.

149: .seealso: `PetscObject`, `PetscObjectDestroy()`
150: S*/
151: PETSC_EXTERN_TYPEDEF typedef PetscErrorCode PetscObjectDestroyFn(PetscObject *obj);

153: PETSC_EXTERN_TYPEDEF typedef PetscObjectDestroyFn *PetscObjectDestroyFunction;

155: /*S
156:   PetscObjectViewFn - A prototype of a function that can view a `PetscObject`

158:   Calling Sequence:
159: + obj - the `PetscObject` to view
160: - v - the viewer

162:   Level: beginner

164:   Note:
165:   The deprecated `PetscObjectViewFunction` works as a replacement for `PetscObjectViewFn` *.

167: .seealso: `PetscObject`, `PetscObjectDestroy()`, `PetscViewer`, `PetscObjectView()`
168: S*/
169: PETSC_EXTERN_TYPEDEF typedef PetscErrorCode PetscObjectViewFn(PetscObject obj, PetscViewer v);

171: PETSC_EXTERN_TYPEDEF typedef PetscObjectViewFn *PetscObjectViewFunction;

173: /*MC
174:     PetscHeaderCreate - Creates a raw PETSc object of a particular class

176:   Synopsis:
177: #include <petsc/private/petscimpl.h>
178:   PetscErrorCode PetscHeaderCreate(PetscObject h, PetscClassId classid, const char class_name[], const char descr[], const char mansec[], MPI_Comm comm, PetscObjectDestroyFn * destroy, PetscObjectViewFn * view)

180:   Collective

182:   Input Parameters:
183: + classid    - The classid associated with this object (for example `VEC_CLASSID`)
184: . class_name - String name of class; should be static (for example "Vec"), may be `PETSC_NULLPTR`
185: . descr      - String containing short description; should be static (for example "Vector"), may be `PETSC_NULLPTR`
186: . mansec     - String indicating section in manual pages; should be static (for example "Vec"), may be `PETSC_NULLPTR`
187: . comm       - The MPI Communicator
188: . destroy    - The destroy routine for this object (for example `VecDestroy()`)
189: - view       - The view routine for this object (for example `VecView()`), may be `PETSC_NULLPTR`

191:   Output Parameter:
192: . h - The newly created `PetscObject`

194:   Level: developer

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

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

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

209:   Example Usage:
210:   Existing `PetscObject`s may be easily created as shown. Unless otherwise stated, a particular
211:   objects `destroy` and `view` functions are exactly `<OBJECT_TYPE>Destroy()` and
212:   `<OBJECT_TYPE>View()`.
213: .vb
214:   Vec v;

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

219:   It is possible to create custom `PetscObject`s, note however that they must abide by the
220:   restrictions set forth above.
221: .vb
222:   // OK, first member of C structure is _p_PetscObject
223:   struct MyCPetscObject_s
224:   {
225:     _p_PetscObject header;
226:     int            some_data;
227:   };
228:   typedef struct *MyCPetscObject_s MyCPetscObject;

230:   PetscErrorCode MyObjectDestroy(MyObject *);
231:   PetscErrorCode MyObjectView(MyObject);

233:   MyCPetscObject obj;

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

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

241:   // ERROR must be a single-level pointer
242:   PetscHeaderCreate(&obj, ...);
243: .ve

245:   Illustrating proper construction from C++\:
246: .vb
247:   // ERROR, class is not standard layout, first member must be publicly accessible
248:   class BadCppPetscObject
249:   {
250:     _p_PetscObject header;
251:   };

253:   // ERROR, class is not standard layout, has a virtual function and virtual inheritance
254:   class BadCppPetscObject2 : virtual BaseClass
255:   {
256:   public:
257:     _p_PetscObject header;

259:     virtual void foo();
260:   };

262:   // ERROR, class is not standard layout! Has non-standard layout member
263:   class BadCppPetscObject2
264:   {
265:   public:
266:     _p_PetscObject    header;
267:     BadCppPetscObject non_standard_layout;
268:   };

270:   // OK, class is standard layout!
271:   class GoodCppPetscObject;
272:   using MyCppObject = GoodCppPetscObject *;

274:   // OK, non-virtual inheritance of other standard layout class does not affect layout
275:   class GoodCppPetscObject : StandardLayoutClass
276:   {
277:   public:
278:     // OK, non standard layout member is static, does not affect layout
279:     static BadCppPetscObject non_standard_layout;

281:     // OK, first non-static member is _p_PetscObject
282:     _p_PetscObject header;

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

287:     // OK, may use "member" functions for destroy and view so long as they are static
288:     static PetscErrorCode destroy(MyCppObject *);
289:     static PetscErrorCode view(MyCppObject);
290:   };

292:   // OK, usage via pointer
293:   MyObject obj;

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

298: .seealso: `PetscObject`, `PetscHeaderDestroy()`, `PetscClassIdRegister()`
299: M*/
300: #define PetscHeaderCreate(h, classid, class_name, descr, mansec, comm, destroy, view) \
301:   PetscHeaderCreate_Function(PetscNew(&(h)), (PetscObject *)&(h), (classid), (class_name), (descr), (mansec), (comm), (PetscObjectDestroyFn *)(destroy), (PetscObjectViewFn *)(view))

303: PETSC_EXTERN PetscErrorCode PetscHeaderCreate_Function(PetscErrorCode, PetscObject *, PetscClassId, const char[], const char[], const char[], MPI_Comm, PetscObjectDestroyFn *, PetscObjectViewFn *);
304: PETSC_EXTERN PetscErrorCode PetscHeaderCreate_Private(PetscObject, PetscClassId, const char[], const char[], const char[], MPI_Comm, PetscObjectDestroyFn *, PetscObjectViewFn *);
305: PETSC_EXTERN PetscErrorCode PetscHeaderDestroy_Function(PetscObject *);
306: PETSC_EXTERN PetscErrorCode PetscComposedQuantitiesDestroy(PetscObject obj);
307: PETSC_INTERN PetscObjectId  PetscObjectNewId_Internal(void);

309: /*MC
310:   PetscHeaderDestroy - Final step in destroying a `PetscObject`

312:   Synopsis:
313: #include <petsc/private/petscimpl.h>
314:   PetscErrorCode PetscHeaderDestroy(PetscObject *obj)

316:   Collective

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

321:   Level: developer

323:   Notes:
324:   `h` is freed and set to `PETSC_NULLPTR` when this routine returns.

326:   Example Usage:
327: .vb
328:   PetscObject obj;

330:   PetscHeaderCreate(obj, ...);
331:   // use obj...

333:   // note pointer to obj is used
334:   PetscHeaderDestroy(&obj);
335: .ve

337:   Note that this routine is the _last_ step when destroying higher-level `PetscObject`s as it
338:   deallocates the memory for the structure itself\:
339: .vb
340:   typedef struct MyPetscObject_s *MyPetscObject;
341:   struct MyPetscObject_s
342:   {
343:     _p_PetscObject  hdr;
344:     PetscInt       *foo;
345:     PetscScalar    *bar;
346:   };

348:   // assume obj is created/initialized elsewhere...
349:   MyPetscObject obj;

351:   // OK, should dispose of all dynamically allocated resources before calling
352:   // PetscHeaderDestroy()
353:   PetscFree(obj->foo);

355:   // OK, dispose of obj
356:   PetscHeaderDestroy(&obj);

358:   // ERROR, obj points to NULL here, accessing obj->bar may result in segmentation violation!
359:   // obj->bar is potentially leaked!
360:   PetscFree(obj->bar);
361: .ve

363: .seealso: `PetscObject`, `PetscHeaderCreate()`
364: M*/
365: #define PetscHeaderDestroy(h) PetscHeaderDestroy_Function((PetscObject *)h)

367: PETSC_EXTERN PetscErrorCode                PetscHeaderDestroy_Private(PetscObject, PetscBool);
368: PETSC_INTERN PetscErrorCode                PetscHeaderDestroy_Private_Unlogged(PetscObject, PetscBool);
369: PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode PetscHeaderReset_Internal(PetscObject);
370: PETSC_EXTERN PetscErrorCode                PetscObjectCopyFortranFunctionPointers(PetscObject, PetscObject);
371: PETSC_EXTERN PetscErrorCode                PetscObjectSetFortranCallback(PetscObject, PetscFortranCallbackType, PetscFortranCallbackId *, void (*)(void), void *ctx);
372: PETSC_EXTERN PetscErrorCode                PetscObjectGetFortranCallback(PetscObject, PetscFortranCallbackType, PetscFortranCallbackId, void (**)(void), void **ctx);

374: PETSC_INTERN PetscErrorCode PetscCitationsInitialize(void);
375: PETSC_INTERN PetscErrorCode PetscFreeMPIResources(void);
376: PETSC_INTERN PetscErrorCode PetscOptionsHasHelpIntro_Internal(PetscOptions, PetscBool *);

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

381: #if PetscDefined(HAVE_SETJMP_H)
382: PETSC_EXTERN PetscBool PetscCheckPointer(const void *, PetscDataType);
383: #else
384:   #define PetscCheckPointer(ptr, data_type) (ptr ? PETSC_TRUE : PETSC_FALSE)
385: #endif

387: #if defined(PETSC_CLANG_STATIC_ANALYZER)
388: template <typename T>
390: template <typename T>
392: template <typename T>
394: template <typename T>
395: extern void PetscAssertPointer(T, int)
396: {
397: }
398: template <typename T>
400: #else
401:   // Macros to test if a PETSc object is valid and if pointers are valid
402:   #if PetscDefined(USE_DEBUG)
403:     /*  This check is for subtype methods such as DMDAGetCorners() that do not use the PetscTryMethod() or PetscUseMethod() paradigm */
405:       do { \
406:         PetscBool _7_same; \
408:         PetscCall(PetscObjectTypeCompare((PetscObject)(h), t, &_7_same)); \
409:         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); \
410:       } while (0)

412:     #define PetscAssertPointer_Internal(ptr, arg, ptype, ptrtype) \
413:       do { \
414:         PetscCheck(ptr, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Null Pointer: Parameter # %d", arg); \
415:         PetscCheck(PetscCheckPointer(ptr, ptype), PETSC_COMM_SELF, PETSC_ERR_ARG_BADPTR, "Invalid Pointer to %s: Argument '" PetscStringize(ptr) "' (parameter # %d)", ptrtype, arg); \
416:       } while (0)

419:       do { \
420:         PetscAssertPointer_Internal(h, arg, PETSC_OBJECT, "PetscObject"); \
421:         if (((PetscObject)(h))->classid != ck) { \
422:           PetscCheck(((PetscObject)(h))->classid != PETSCFREEDHEADER, PETSC_COMM_SELF, PETSC_ERR_ARG_CORRUPT, "Object already free: Parameter # %d", arg); \
423:           SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Wrong type of object: Parameter # %d", arg); \
424:         } \
425:       } while (0)

428:       do { \
429:         PetscAssertPointer_Internal(h, arg, PETSC_OBJECT, "PetscObject"); \
430:         PetscCheck(((PetscObject)(h))->classid != PETSCFREEDHEADER, PETSC_COMM_SELF, PETSC_ERR_ARG_CORRUPT, "Object already free: Parameter # %d", arg); \
431:         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); \
432:       } while (0)

434:     #if defined(__cplusplus)
435:       #include <type_traits> // std::decay

437: namespace Petsc
438: {

440: namespace util
441: {

443: template <typename T>
444: struct PetscAssertPointerImpl {
445:   PETSC_NODISCARD static constexpr PetscDataType type() noexcept { return PETSC_CHAR; }
446:   PETSC_NODISCARD static constexpr const char   *string() noexcept { return "memory"; }
447: };

449:       #define PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(T, PETSC_TYPE) \
450:         template <> \
451:         struct PetscAssertPointerImpl<T *> { \
452:           PETSC_NODISCARD static constexpr PetscDataType type() noexcept { return PETSC_TYPE; } \
453:           PETSC_NODISCARD static constexpr const char   *string() noexcept { return PetscStringize(T); } \
454:         }; \
455:         template <> \
456:         struct PetscAssertPointerImpl<const T *> : PetscAssertPointerImpl<T *> { }; \
457:         template <> \
458:         struct PetscAssertPointerImpl<volatile T *> : PetscAssertPointerImpl<T *> { }; \
459:         template <> \
460:         struct PetscAssertPointerImpl<const volatile T *> : PetscAssertPointerImpl<T *> { }

462: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(char, PETSC_CHAR);
463: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(signed char, PETSC_CHAR);
464: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(unsigned char, PETSC_CHAR);
465: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(short, PETSC_SHORT);
466: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(unsigned short, PETSC_SHORT);
467: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(PetscBool, PETSC_BOOL);
468: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(float, PETSC_FLOAT);
469: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(double, PETSC_DOUBLE);
470: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(int32_t, PETSC_INT32);
471: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(uint32_t, PETSC_INT32);
472: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(int64_t, PETSC_INT64);
473: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(uint64_t, PETSC_INT64);
474:       #if defined(PETSC_HAVE_COMPLEX)
475: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(PetscComplex, PETSC_COMPLEX);
476:       #endif

478:       #undef PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION

480: } // namespace util

482: } // namespace Petsc

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

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

490:       #if PetscDefined(HAVE_COMPLEX)
491:         #define PETSC_GENERIC_CV_COMPLEX(result) PETSC_GENERIC_CV(PetscComplex, result)
492:       #else
493:         #define PETSC_GENERIC_CV_COMPLEX(result)
494:       #endif

496:       #define PetscAssertPointer_PetscDataType(h) \
497:         _Generic((h), \
498:           default: PETSC_CHAR, \
499:           PETSC_GENERIC_CV(          char, PETSC_CHAR), \
500:           PETSC_GENERIC_CV(   signed char, PETSC_CHAR), \
501:           PETSC_GENERIC_CV( unsigned char, PETSC_CHAR), \
502:           PETSC_GENERIC_CV(         short, PETSC_SHORT), \
503:           PETSC_GENERIC_CV(unsigned short, PETSC_SHORT), \
504:           PETSC_GENERIC_CV(         float, PETSC_FLOAT), \
505:           PETSC_GENERIC_CV(        double, PETSC_DOUBLE), \
506:           PETSC_GENERIC_CV(       int32_t, PETSC_INT32), \
507:           PETSC_GENERIC_CV(      uint32_t, PETSC_INT32), \
508:           PETSC_GENERIC_CV(       int64_t, PETSC_INT64), \
509:           PETSC_GENERIC_CV(      uint64_t, PETSC_INT64), \
510:           PETSC_GENERIC_CV_COMPLEX(PETSC_COMPLEX))

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

514:       #if PetscDefined(HAVE_COMPLEX)
515:         #define PETSC_GENERIC_CV_STRINGIZE_COMPLEX PETSC_GENERIC_CV_STRINGIZE(PetscComplex)
516:       #else
517:         #define PETSC_GENERIC_CV_STRINGIZE_COMPLEX
518:       #endif

520:       #define PetscAssertPointer_String(h) \
521:         _Generic((h), \
522:           default: "memory", \
523:           PETSC_GENERIC_CV_STRINGIZE(char), \
524:           PETSC_GENERIC_CV_STRINGIZE(signed char), \
525:           PETSC_GENERIC_CV_STRINGIZE(unsigned char), \
526:           PETSC_GENERIC_CV_STRINGIZE(short), \
527:           PETSC_GENERIC_CV_STRINGIZE(unsigned short), \
528:           PETSC_GENERIC_CV_STRINGIZE(float), \
529:           PETSC_GENERIC_CV_STRINGIZE(double), \
530:           PETSC_GENERIC_CV_STRINGIZE(int32_t), \
531:           PETSC_GENERIC_CV_STRINGIZE(uint32_t), \
532:           PETSC_GENERIC_CV_STRINGIZE(int64_t), \
533:           PETSC_GENERIC_CV_STRINGIZE(uint64_t), \
534:           PETSC_GENERIC_CV_STRINGIZE_COMPLEX)
535:     #else // PETSC_C_VERSION >= 11 || defined(__cplusplus)
536:       #define PetscAssertPointer_PetscDataType(h) PETSC_CHAR
537:       #define PetscAssertPointer_String(h)        "memory"
538:     #endif // PETSC_C_VERSION >= 11 || defined(__cplusplus)
539:     #define PetscAssertPointer(h, arg) PetscAssertPointer_Internal(h, arg, PetscAssertPointer_PetscDataType(h), PetscAssertPointer_String(h))
541:   #else // PetscDefined(USE_DEBUG)
543:       do { \
544:         (void)(h); \
545:       } while (0)
547:       do { \
548:         (void)(h); \
549:       } while (0)
551:       do { \
552:         (void)(h); \
553:       } while (0)
554:     #define PetscAssertPointer(h, arg) \
555:       do { \
556:         (void)(h); \
557:       } while (0)
559:       do { \
560:         (void)(h); \
561:       } while (0)
562:   #endif // PetscDefined(USE_DEBUG)
563: #endif   // PETSC_CLANG_STATIC_ANALYZER


574: #define PetscSorted(n, idx, sorted) \
575:   do { \
576:     (sorted) = PETSC_TRUE; \
577:     for (PetscCount _i_ = 1; _i_ < (n); ++_i_) { \
578:       if ((idx)[_i_] < (idx)[_i_ - 1]) { \
579:         (sorted) = PETSC_FALSE; \
580:         break; \
581:       } \
582:     } \
583:   } while (0)

585: #if !defined(PETSC_CLANG_STATIC_ANALYZER)
586:   #if !defined(PETSC_USE_DEBUG)

588:     #define PetscCheckSameType(a, arga, b, argb) \
589:       do { \
590:         (void)(a); \
591:         (void)(b); \
592:       } while (0)
593:     #define PetscCheckTypeName(a, type) \
594:       do { \
595:         (void)(a); \
596:       } while (0)
597:     #define PetscCheckTypeNames(a, type1, type2) \
598:       do { \
599:         (void)(a); \
600:       } while (0)
602:       do { \
603:         (void)(a); \
604:       } while (0)
605:     #define PetscCheckSameComm(a, arga, b, argb) \
606:       do { \
607:         (void)(a); \
608:         (void)(b); \
609:       } while (0)
610:     #define PetscCheckSameTypeAndComm(a, arga, b, argb) \
611:       do { \
612:         (void)(a); \
613:         (void)(b); \
614:       } while (0)
616:       do { \
617:         (void)(a); \
618:         (void)(b); \
619:       } while (0)
621:       do { \
622:         (void)(a); \
623:         (void)(b); \
624:       } while (0)
626:       do { \
627:         (void)(a); \
628:         (void)(b); \
629:       } while (0)
631:       do { \
632:         (void)(a); \
633:         (void)(b); \
634:       } while (0)
636:       do { \
637:         (void)(a); \
638:         (void)(b); \
639:       } while (0)
641:       do { \
642:         (void)(a); \
643:         (void)(b); \
644:       } while (0)
646:       do { \
647:         (void)(a); \
648:         (void)(b); \
649:       } while (0)
651:       do { \
652:         (void)(a); \
653:         (void)(b); \
654:       } while (0)
655:     #define PetscCheckSorted(n, idx) \
656:       do { \
657:         (void)(n); \
658:         (void)(idx); \
659:       } while (0)

661:   #else

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

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

669:   This macro is used incorrectly in the code. Many places that do not need identity of the
670:   types incorrectly call this check and would need to be fixed if this macro is enabled.
671: */
672:     #if 0
673:       #define PetscCheckSameType(a, arga, b, argb) \
674:         do { \
675:           PetscBool pcst_type_eq_ = PETSC_TRUE; \
676:           PetscCall(PetscStrcmp(((PetscObject)(a))->type_name, ((PetscObject)(b))->type_name, &pcst_type_eq_)); \
677:           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); \
678:         } while (0)
679:     #else
680:       #define PetscCheckSameType(a, arga, b, argb) \
681:         do { \
682:           (void)(a); \
683:           (void)(b); \
684:         } while (0)
685:     #endif

687:     /*
688:     Check type_name
689: */
690:     #define PetscCheckTypeName(a, type) \
691:       do { \
692:         PetscBool _7_match; \
693:         PetscCall(PetscObjectTypeCompare(((PetscObject)(a)), (type), &_7_match)); \
694:         PetscCheck(_7_match, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Object (%s) is not %s", ((PetscObject)(a))->type_name, type); \
695:       } while (0)

697:     #define PetscCheckTypeNames(a, type1, type2) \
698:       do { \
699:         PetscBool _7_match; \
700:         PetscCall(PetscObjectTypeCompareAny(((PetscObject)(a)), &_7_match, (type1), (type2), "")); \
701:         PetscCheck(_7_match, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Object (%s) is not %s or %s", ((PetscObject)(a))->type_name, type1, type2); \
702:       } while (0)

704:     /*
705:    Use this macro to check if the type is set
706: */

709:     /*
710:    Sometimes object must live on same communicator to inter-operate
711: */
712:     #define PetscCheckSameComm(a, arga, b, argb) \
713:       do { \
714:         PetscMPIInt _7_flag; \
715:         PetscCallMPI(MPI_Comm_compare(PetscObjectComm((PetscObject)(a)), PetscObjectComm((PetscObject)(b)), &_7_flag)); \
716:         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); \
717:       } while (0)

719:     #define PetscCheckSameTypeAndComm(a, arga, b, argb) \
720:       do { \
721:         PetscCheckSameType(a, arga, b, argb); \
722:         PetscCheckSameComm(a, arga, b, argb); \
723:       } while (0)

726:       do { \
727:         PetscScalar b0 = (b); \
728:         PetscReal   b1[5]; \
729:         if (PetscIsNanScalar(b0)) { \
730:           b1[4] = 1; \
731:         } else { \
732:           b1[4] = 0; \
733:         }; \
734:         b1[0] = -PetscRealPart(b0); \
735:         b1[1] = PetscRealPart(b0); \
736:         b1[2] = -PetscImaginaryPart(b0); \
737:         b1[3] = PetscImaginaryPart(b0); \
738:         PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, b1, 5, MPIU_REAL, MPIU_MAX, PetscObjectComm((PetscObject)(a)))); \
739:         PetscCheck(b1[4] > 0 || (PetscEqualReal(-b1[0], b1[1]) && PetscEqualReal(-b1[2], b1[3])), PetscObjectComm((PetscObject)(a)), PETSC_ERR_ARG_WRONG, "Scalar value must be same on all processes, argument # %d", arg); \
740:       } while (0)

743:       do { \
744:         PetscReal b0 = (b), b1[3]; \
745:         if (PetscIsNanReal(b0)) { \
746:           b1[2] = 1; \
747:         } else { \
748:           b1[2] = 0; \
749:         }; \
750:         b1[0] = -b0; \
751:         b1[1] = b0; \
752:         PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, b1, 3, MPIU_REAL, MPIU_MAX, PetscObjectComm((PetscObject)(a)))); \
753:         PetscCheck(b1[2] > 0 || PetscEqualReal(-b1[0], b1[1]), PetscObjectComm((PetscObject)(a)), PETSC_ERR_ARG_WRONG, "Real value must be same on all processes, argument # %d", arg); \
754:       } while (0)

757:       do { \
758:         PetscInt b0 = (b), b1[2]; \
759:         b1[0]       = -b0; \
760:         b1[1]       = b0; \
761:         PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, b1, 2, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)(a)))); \
762:         PetscCheck(-b1[0] == b1[1], PetscObjectComm((PetscObject)(a)), PETSC_ERR_ARG_WRONG, "Int value must be same on all processes, argument # %d", arg); \
763:       } while (0)

766:       do { \
767:         PetscInt b1[2]; \
768:         b1[0] = -b; \
769:         b1[1] = b; \
770:         PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, b1, 2, MPIU_INT, MPI_MAX, a)); \
771:         PetscCheck(-b1[0] == b1[1], a, PETSC_ERR_ARG_WRONG, "Int value must be same on all processes, argument # %d", arg); \
772:       } while (0)

775:       do { \
776:         PetscCount b0 = (b), b1[2]; \
777:         b1[0]         = -b0; \
778:         b1[1]         = b0; \
779:         PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, b1, 2, MPIU_COUNT, MPI_MAX, PetscObjectComm((PetscObject)(a)))); \
780:         PetscCheck(-b1[0] == b1[1], PetscObjectComm((PetscObject)(a)), PETSC_ERR_ARG_WRONG, "Int value must be same on all processes, argument # %d", arg); \
781:       } while (0)

784:       do { \
785:         PetscMPIInt b0 = (b), b1[2]; \
786:         b1[0]          = -b0; \
787:         b1[1]          = b0; \
788:         PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, b1, 2, MPI_INT, MPI_MAX, PetscObjectComm((PetscObject)(a)))); \
789:         PetscCheck(-b1[0] == b1[1], PetscObjectComm((PetscObject)(a)), PETSC_ERR_ARG_WRONG, "PetscMPIInt value must be same on all processes, argument # %d", arg); \
790:       } while (0)

793:       do { \
794:         PetscBool b0 = (PetscBool)(b), b1[2]; \
795:         b1[0]        = !b0; \
796:         b1[1]        = b0; \
797:         PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, b1, 2, MPIU_BOOL, MPI_LAND, PetscObjectComm((PetscObject)(a)))); \
798:         PetscCheck(!b1[0] == b1[1], PetscObjectComm((PetscObject)(a)), PETSC_ERR_ARG_WRONG, "Bool value must be same on all processes, argument # %d", arg); \
799:       } while (0)

802:       do { \
803:         PetscMPIInt b0 = (PetscMPIInt)(b), b1[2]; \
804:         b1[0]          = -b0; \
805:         b1[1]          = b0; \
806:         PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, b1, 2, MPI_INT, MPI_MAX, PetscObjectComm((PetscObject)(a)))); \
807:         PetscCheck(-b1[0] == b1[1], PetscObjectComm((PetscObject)(a)), PETSC_ERR_ARG_WRONG, "Enum value must be same on all processes, argument # %d", arg); \
808:       } while (0)

810:     #define PetscCheckSorted(n, idx) \
811:       do { \
812:         PetscBool _1_flg; \
813:         PetscSorted(n, idx, _1_flg); \
814:         PetscCheck(_1_flg, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Input array needs to be sorted"); \
815:       } while (0)

817:   #endif
818: #else  /* PETSC_CLANG_STATIC_ANALYZER */
819: template <typename Ta, typename Tb>
820: extern void PetscCheckSameType(Ta, int, Tb, int);
821: template <typename Ta, typename Tb>
822: extern void PetscCheckTypeName(Ta, Tb);
823: template <typename Ta, typename Tb, typename Tc>
824: extern void PetscCheckTypeNames(Ta, Tb, Tc);
825: template <typename T>
827: template <typename Ta, typename Tb>
828: extern void PetscCheckSameComm(Ta, int, Tb, int);
829: template <typename Ta, typename Tb>
830: extern void PetscCheckSameTypeAndComm(Ta, int, Tb, int);
831: template <typename Ta, typename Tb>
833: template <typename Ta, typename Tb>
835: template <typename Ta, typename Tb>
837: template <typename Ta, typename Tb>
839: template <typename Ta, typename Tb>
841: template <typename Ta, typename Tb>
843: template <typename Ta, typename Tb>
845: template <typename T>
846: extern void PetscCheckSorted(PetscInt, T);
847: #endif /* PETSC_CLANG_STATIC_ANALYZER */

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

852:   Synopsis:
853:    #include "petsc/private/petscimpl.h"
854:    PetscTryMethod(PetscObject obj, const char *name, (arg_types), (arg_value))

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

862:    Level: developer

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

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

870: .seealso: `PetscUseMethod()`, `PetscCall()`, `PetscUseTypeMethod()`, `PetscTryTypeMethod()`, `PetscCheck()`, `PetscObject`
871: M*/
872: #define PetscTryMethod(obj, A, B, C) \
873:   do { \
874:     PetscErrorCode(*_7_f) B; \
875:     PetscCall(PetscObjectQueryFunction((PetscObject)(obj), A, &_7_f)); \
876:     if (_7_f) PetscCall((*_7_f)C); \
877:   } while (0)

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

882:   Synopsis:
883:    #include "petsc/private/petscimpl.h"
884:    PetscUseMethod(PetscObject obj, const char *name, (arg_types), (arg_value))

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

892:    Level: developer

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

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

900: .seealso: `PetscTryMethod()`, `PetscCall()`, `PetscUseTypeMethod()`, `PetscTryTypeMethod()`, `PetscCheck()`, `PetscObject`
901: M*/
902: #define PetscUseMethod(obj, A, B, C) \
903:   do { \
904:     PetscErrorCode(*_7_f) B; \
905:     PetscCall(PetscObjectQueryFunction((PetscObject)(obj), A, &_7_f)); \
906:     PetscCheck(_7_f, PetscObjectComm((PetscObject)(obj)), PETSC_ERR_SUP, "Cannot locate function %s in object", A); \
907:     PetscCall((*_7_f)C); \
908:   } while (0)

910: /*
911:   Use Microsoft traditional preprocessor.

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

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

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

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

924:   #define PetscUseTypeMethod(obj, OP, ...) \
925:     do { \
926:       PetscErrorCode ierr_p_; \
927:       PetscStackUpdateLine; \
928:       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); \
929:       ierr_p_ = (*(obj)->ops->OP)(obj, __VA_ARGS__); \
930:       PetscCall(ierr_p_); \
931:     } while (0)

933:   #define PetscTryTypeMethod(obj, OP, ...) \
934:     do { \
935:       if ((obj)->ops->OP) { \
936:         PetscErrorCode ierr_p_; \
937:         PetscStackUpdateLine; \
938:         ierr_p_ = (*(obj)->ops->OP)(obj, __VA_ARGS__); \
939:         PetscCall(ierr_p_); \
940:       } \
941:     } while (0)

943: #else

945:   /*MC
946:    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

948:   Synopsis:
949:    #include "petsc/private/petscimpl.h"
950:    PetscUseTypeMethod(obj, method, other_args)

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

957:    Level: developer

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

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

964: .seealso: `PetscTryMethod()`, `PetscUseMethod()`, `PetscCall()`, `PetscCheck()`, `PetscTryTypeMethod()`, `PetscCallBack()`
965: M*/
966:   #define PetscUseTypeMethod(obj, ...) \
967:     do { \
968:       PetscCheck((obj)->ops->PETSC_FIRST_ARG((__VA_ARGS__, unused)), PetscObjectComm((PetscObject)obj), PETSC_ERR_SUP, "No method %s for %s of type %s", \
969:                  PetscStringize(PETSC_FIRST_ARG((__VA_ARGS__,unused))), ((PetscObject)obj)->class_name, ((PetscObject)obj)->type_name); \
970:       PetscCall((*(obj)->ops->PETSC_FIRST_ARG((__VA_ARGS__, unused)))(obj PETSC_REST_ARG(__VA_ARGS__))); \
971:     } while (0)

973:   /*MC
974:    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

976:   Synopsis:
977:    #include "petsc/private/petscimpl.h"
978:    PetscTryTypeMethod(obj, method, other_args)

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

985:    Level: developer

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

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

992: .seealso: `PetscTryMethod()`, `PetscUseMethod()`, `PetscCall()`, `PetscCheck()`, `PetscUseTypeMethod()`
993: M*/
994:   #define PetscTryTypeMethod(obj, ...) \
995:     do { \
996:       if ((obj)->ops->PETSC_FIRST_ARG((__VA_ARGS__, unused))) PetscCall((*(obj)->ops->PETSC_FIRST_ARG((__VA_ARGS__, unused)))(obj PETSC_REST_ARG(__VA_ARGS__))); \
997:     } while (0)

999: #endif

1001: /*MC
1002:    PetscObjectStateIncrease - Increases the state of any `PetscObject`

1004:    Synopsis:
1005:    #include "petsc/private/petscimpl.h"
1006:    PetscErrorCode PetscObjectStateIncrease(PetscObject obj)

1008:    Logically Collective

1010:    Input Parameter:
1011: .  obj - any PETSc object, for example a `Vec`, `Mat` or `KSP`. This must be
1012:          cast with a (PetscObject), for example,
1013:          `PetscObjectStateIncrease`((`PetscObject`)mat);

1015:    Level: developer

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

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

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

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

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

1034: .seealso: `PetscObjectStateGet()`, `PetscObject`
1035: M*/
1036: #define PetscObjectStateIncrease(obj) ((PetscErrorCode)((obj)->state++, PETSC_SUCCESS))

1038: PETSC_EXTERN PetscErrorCode PetscObjectStateGet(PetscObject, PetscObjectState *);
1039: PETSC_EXTERN PetscErrorCode PetscObjectStateSet(PetscObject, PetscObjectState);
1040: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataRegister(PetscInt *);
1041: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseInt(PetscObject);
1042: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseIntstar(PetscObject);
1043: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseReal(PetscObject);
1044: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseRealstar(PetscObject);
1045: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseScalar(PetscObject);
1046: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseScalarstar(PetscObject);
1047: PETSC_EXTERN PetscInt       PetscObjectComposedDataMax;

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

1052:    Synopsis:
1053:    #include "petsc/private/petscimpl.h"
1054:    PetscErrorCode PetscObjectComposedDataSetInt(PetscObject obj, PetscInt id, PetscInt data)

1056:    Not Collective

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

1063:    Level: developer

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

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

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

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

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

1085:    Not Collective

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

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

1095:    Level: developer

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

1100: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetReal()`,
1101:           `PetscObjectComposedDataGetIntstar()`, `PetscObjectComposedDataSetIntstar()`, `PetscObject`,
1102:           `PetscObjectCompose()`, `PetscObjectQuery()`
1103: M*/
1104: #define PetscObjectComposedDataGetInt(obj, id, data, flag) ((PetscErrorCode)(((obj)->intcomposedstate ? (data = (obj)->intcomposeddata[id], flag = (PetscBool)((obj)->intcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), PETSC_SUCCESS))

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

1109:    Synopsis:
1110:    #include "petsc/private/petscimpl.h"
1111:    PetscErrorCode PetscObjectComposedDataSetIntstar(PetscObject obj, PetscInt id, PetscInt *data)

1113:    Not Collective

1115:    Input Parameters:
1116: +  obj - the object to which data is to be attached
1117: .  id - the identifier for the data
1118: -  data - the data to  be attached, a `PetscInt` array

1120:    Level: developer

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

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

1127: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetReal()`,
1128:           `PetscObjectComposedDataGetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1129:           `PetscObjectCompose()`, `PetscObjectQuery()`
1130: M*/
1131: #define PetscObjectComposedDataSetIntstar(obj, id, data) \
1132:   ((PetscErrorCode)((((obj)->intstar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseIntstar(obj)) || ((obj)->intstarcomposeddata[id] = data, (obj)->intstarcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))

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

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

1141:    Not Collective

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

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

1151:    Level: developer

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

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

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

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

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

1172:    Not Collective

1174:    Input Parameters:
1175: +  obj - the object to which data is to be attached
1176: .  id - the identifier for the data
1177: -  data - the data to  be attached, a `PetscReal`

1179:    Level: developer

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

1184: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1185:           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1186:           `PetscObjectCompose()`, `PetscObjectQuery()`
1187: M*/
1188: #define PetscObjectComposedDataSetReal(obj, id, data) \
1189:   ((PetscErrorCode)((((obj)->real_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseReal(obj)) || ((obj)->realcomposeddata[id] = data, (obj)->realcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))

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

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

1198:    Not Collective

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

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

1208:    Level: developer

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

1213: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataSetIntstar()`,
1214:           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1215:           `PetscObjectCompose()`, `PetscObjectQuery()`
1216: M*/
1217: #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))

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

1222:    Synopsis:
1223:    #include "petsc/private/petscimpl.h"
1224:    PetscErrorCode PetscObjectComposedDataSetRealstar(PetscObject obj, PetscInt id, PetscReal *data)

1226:    Not Collective

1228:    Input Parameters:
1229: +  obj - the object to which data is to be attached
1230: .  id - the identifier for the data
1231: -  data - the data to  be attached

1233:    Level: developer

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

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

1240: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1241:           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1242:           `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataGetRealstar()`
1243: M*/
1244: #define PetscObjectComposedDataSetRealstar(obj, id, data) \
1245:   ((PetscErrorCode)((((obj)->realstar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseRealstar(obj)) || ((obj)->realstarcomposeddata[id] = data, (obj)->realstarcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))

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

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

1254:    Not Collective

1256:    Input Parameters:
1257: +  obj - the object from which data is to be retrieved
1258: -  id - the identifier for the data

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

1264:    Level: developer

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

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

1271: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1272:           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1273:           `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`
1274: M*/
1275: #define PetscObjectComposedDataGetRealstar(obj, id, data, flag) \
1276:   ((PetscErrorCode)(((obj)->realstarcomposedstate ? (data = (obj)->realstarcomposeddata[id], flag = (PetscBool)((obj)->realstarcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), PETSC_SUCCESS))

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

1281:    Synopsis:
1282:    #include "petsc/private/petscimpl.h"
1283:    PetscErrorCode PetscObjectComposedDataSetScalar(PetscObject obj, PetscInt id, PetscScalar data)

1285:    Not Collective

1287:    Input Parameters:
1288: +  obj - the object to which data is to be attached
1289: .  id - the identifier for the data
1290: -  data - the data to  be attached, a `PetscScalar`

1292:    Level: developer

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

1297: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1298:           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1299:           `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`, `PetscObjectComposedDataGetScalar()`
1300: M*/
1301: #if defined(PETSC_USE_COMPLEX)
1302:   #define PetscObjectComposedDataSetScalar(obj, id, data) \
1303:     ((PetscErrorCode)((((obj)->scalar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseScalar(obj)) || ((obj)->scalarcomposeddata[id] = data, (obj)->scalarcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))
1304: #else
1305:   #define PetscObjectComposedDataSetScalar(obj, id, data) PetscObjectComposedDataSetReal(obj, id, data)
1306: #endif
1307: /*MC
1308:    PetscObjectComposedDataGetScalar - retrieve `PetscScalar` data attached to a `PetscObject` that was set with `PetscObjectComposedDataSetScalar()`

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

1314:    Not Collective

1316:    Input Parameters:
1317: +  obj - the object from which data is to be retrieved
1318: -  id - the identifier for the data

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

1324:    Level: developer

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

1329: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1330:           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1331:           `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`, `PetscObjectComposedDataSetScalar()`
1332: M*/
1333: #if defined(PETSC_USE_COMPLEX)
1334:   #define PetscObjectComposedDataGetScalar(obj, id, data, flag) \
1335:     ((PetscErrorCode)(((obj)->scalarcomposedstate ? (data = (obj)->scalarcomposeddata[id], flag = (PetscBool)((obj)->scalarcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), PETSC_SUCCESS))
1336: #else
1337:   #define PetscObjectComposedDataGetScalar(obj, id, data, flag) PetscObjectComposedDataGetReal(obj, id, data, flag)
1338: #endif

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

1343:    Synopsis:
1344:    #include "petsc/private/petscimpl.h"
1345:    PetscErrorCode PetscObjectComposedDataSetScalarstar(PetscObject obj, PetscInt id, PetscScalar *data)

1347:    Not Collective

1349:    Input Parameters:
1350: +  obj - the object to which data is to be attached
1351: .  id - the identifier for the data
1352: -  data - the data to  be attached, a `PetscScalar` array

1354:    Level: developer

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

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

1361: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1362:           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1363:           `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`, `PetscObjectComposedDataGetScalarstar()`
1364: M*/
1365: #if defined(PETSC_USE_COMPLEX)
1366:   #define PetscObjectComposedDataSetScalarstar(obj, id, data) \
1367:     ((PetscErrorCode)((((obj)->scalarstar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseScalarstar(obj)) || ((obj)->scalarstarcomposeddata[id] = data, (obj)->scalarstarcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))
1368: #else
1369:   #define PetscObjectComposedDataSetScalarstar(obj, id, data) PetscObjectComposedDataSetRealstar(obj, id, data)
1370: #endif
1371: /*MC
1372:    PetscObjectComposedDataGetScalarstar - retrieve `PetscScalar` array data attached to a `PetscObject` that was set with `PetscObjectComposedDataSetScalarstar()`
1373:    attached to an object

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

1379:    Not Collective

1381:    Input Parameters:
1382: +  obj - the object from which data is to be retrieved
1383: -  id - the identifier for the data

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

1389:    Level: developer

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

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

1396: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1397:           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1398:           `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`, `PetscObjectComposedDataSetScalarstar()`
1399: M*/
1400: #if defined(PETSC_USE_COMPLEX)
1401:   #define PetscObjectComposedDataGetScalarstar(obj, id, data, flag) \
1402:     ((PetscErrorCode)(((obj)->scalarstarcomposedstate ? (data = (obj)->scalarstarcomposeddata[id], flag = (PetscBool)((obj)->scalarstarcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), PETSC_SUCCESS))
1403: #else
1404:   #define PetscObjectComposedDataGetScalarstar(obj, id, data, flag) PetscObjectComposedDataGetRealstar(obj, id, data, flag)
1405: #endif

1407: PETSC_INTERN PetscMPIInt Petsc_Counter_keyval;
1408: PETSC_INTERN PetscMPIInt Petsc_InnerComm_keyval;
1409: PETSC_INTERN PetscMPIInt Petsc_OuterComm_keyval;
1410: PETSC_INTERN PetscMPIInt Petsc_Seq_keyval;
1411: PETSC_INTERN PetscMPIInt Petsc_ShmComm_keyval;
1412: PETSC_EXTERN PetscMPIInt Petsc_CreationIdx_keyval;
1413: PETSC_INTERN PetscMPIInt Petsc_Garbage_HMap_keyval;

1415: PETSC_INTERN PetscMPIInt Petsc_SharedWD_keyval;
1416: PETSC_INTERN PetscMPIInt Petsc_SharedTmp_keyval;

1418: struct PetscCommStash {
1419:   struct PetscCommStash *next;
1420:   MPI_Comm               comm;
1421: };

1423: /*
1424:   PETSc communicators have this attribute, see
1425:   PetscCommDuplicate(), PetscCommDestroy(), PetscCommGetNewTag(), PetscObjectGetName()
1426: */
1427: typedef struct {
1428:   PetscMPIInt            tag;       /* next free tag value */
1429:   PetscInt               refcount;  /* number of references, communicator can be freed when this reaches 0 */
1430:   PetscInt               namecount; /* used to generate the next name, as in Vec_0, Mat_1, ... */
1431:   PetscMPIInt           *iflags;    /* length of comm size, shared by all calls to PetscCommBuildTwoSided_Allreduce/RedScatter on this comm */
1432:   struct PetscCommStash *comms;     /* communicators available for PETSc to pass off to other packages */
1433: } PetscCommCounter;

1435: typedef enum {
1436:   STATE_BEGIN,
1437:   STATE_PENDING,
1438:   STATE_END
1439: } SRState;

1441: typedef enum {
1442:   PETSC_SR_REDUCE_SUM = 0,
1443:   PETSC_SR_REDUCE_MAX = 1,
1444:   PETSC_SR_REDUCE_MIN = 2
1445: } PetscSRReductionType;

1447: typedef struct {
1448:   MPI_Comm              comm;
1449:   MPI_Request           request;
1450:   PetscBool             mix;
1451:   PetscBool             async;
1452:   PetscScalar          *lvalues;    /* this are the reduced values before call to MPI_Allreduce() */
1453:   PetscScalar          *gvalues;    /* values after call to MPI_Allreduce() */
1454:   void                **invecs;     /* for debugging only, vector/memory used with each op */
1455:   PetscSRReductionType *reducetype; /* is particular value to be summed or maxed? */
1456:   struct {
1457:     PetscScalar v;
1458:     PetscInt    i;
1459:   }          *lvalues_mix, *gvalues_mix; /* used when mixing reduce operations */
1460:   SRState     state;                     /* are we calling xxxBegin() or xxxEnd()? */
1461:   PetscMPIInt maxops;                    /* total amount of space we have for requests */
1462:   PetscMPIInt numopsbegin;               /* number of requests that have been queued in */
1463:   PetscMPIInt numopsend;                 /* number of requests that have been gotten by user */
1464: } PetscSplitReduction;

1466: PETSC_EXTERN PetscErrorCode PetscSplitReductionGet(MPI_Comm, PetscSplitReduction **);
1467: PETSC_EXTERN PetscErrorCode PetscSplitReductionEnd(PetscSplitReduction *);
1468: PETSC_EXTERN PetscErrorCode PetscSplitReductionExtend(PetscSplitReduction *);

1470: #if defined(PETSC_HAVE_THREADSAFETY)
1471:   #if defined(PETSC_HAVE_CONCURRENCYKIT)
1472:     #if defined(__cplusplus)
1473: /*  CK does not have extern "C" protection in their include files */
1474: extern "C" {
1475:     #endif
1476:     #include <ck_spinlock.h>
1477:     #if defined(__cplusplus)
1478: }
1479:     #endif
1480: typedef ck_spinlock_t PetscSpinlock;

1482: static inline PetscErrorCode PetscSpinlockCreate(PetscSpinlock *ck_spinlock)
1483: {
1484:   ck_spinlock_init(ck_spinlock);
1485:   return PETSC_SUCCESS;
1486: }
1487: static inline PetscErrorCode PetscSpinlockLock(PetscSpinlock *ck_spinlock)
1488: {
1489:   ck_spinlock_lock(ck_spinlock);
1490:   return PETSC_SUCCESS;
1491: }
1492: static inline PetscErrorCode PetscSpinlockUnlock(PetscSpinlock *ck_spinlock)
1493: {
1494:   ck_spinlock_unlock(ck_spinlock);
1495:   return PETSC_SUCCESS;
1496: }
1497: static inline PetscErrorCode PetscSpinlockDestroy(PetscSpinlock *ck_spinlock)
1498: {
1499:   return PETSC_SUCCESS;
1500: }
1501:   #elif (defined(__cplusplus) && defined(PETSC_HAVE_CXX_ATOMIC)) || (!defined(__cplusplus) && defined(PETSC_HAVE_STDATOMIC_H))
1502:     #if defined(__cplusplus)
1503:       // See the example at https://en.cppreference.com/w/cpp/atomic/atomic_flag
1504:       #include <atomic>
1505:       #define petsc_atomic_flag                 std::atomic_flag
1506:       #define petsc_atomic_flag_test_and_set(p) std::atomic_flag_test_and_set_explicit(p, std::memory_order_acquire)
1507:       #define petsc_atomic_flag_clear(p)        std::atomic_flag_clear_explicit(p, std::memory_order_release)
1508:     #else
1509:       #include <stdatomic.h>
1510:       #define petsc_atomic_flag                 atomic_flag
1511:       #define petsc_atomic_flag_test_and_set(p) atomic_flag_test_and_set_explicit(p, memory_order_acquire)
1512:       #define petsc_atomic_flag_clear(p)        atomic_flag_clear_explicit(p, memory_order_release)
1513:     #endif

1515: typedef petsc_atomic_flag PetscSpinlock;

1517: static inline PetscErrorCode PetscSpinlockCreate(PetscSpinlock *spinlock)
1518: {
1519:   petsc_atomic_flag_clear(spinlock);
1520:   return PETSC_SUCCESS;
1521: }
1522: static inline PetscErrorCode PetscSpinlockLock(PetscSpinlock *spinlock)
1523: {
1524:   do {
1525:   } while (petsc_atomic_flag_test_and_set(spinlock));
1526:   return PETSC_SUCCESS;
1527: }
1528: static inline PetscErrorCode PetscSpinlockUnlock(PetscSpinlock *spinlock)
1529: {
1530:   petsc_atomic_flag_clear(spinlock);
1531:   return PETSC_SUCCESS;
1532: }
1533: static inline PetscErrorCode PetscSpinlockDestroy(PETSC_UNUSED PetscSpinlock *spinlock)
1534: {
1535:   return PETSC_SUCCESS;
1536: }
1537:     #undef petsc_atomic_flag_test_and_set
1538:     #undef petsc_atomic_flag_clear
1539:     #undef petsc_atomic_flag

1541:   #elif defined(PETSC_HAVE_OPENMP)

1543:     #include <omp.h>
1544: typedef omp_lock_t PetscSpinlock;

1546: static inline PetscErrorCode PetscSpinlockCreate(PetscSpinlock *omp_lock)
1547: {
1548:   omp_init_lock(omp_lock);
1549:   return PETSC_SUCCESS;
1550: }
1551: static inline PetscErrorCode PetscSpinlockLock(PetscSpinlock *omp_lock)
1552: {
1553:   omp_set_lock(omp_lock);
1554:   return PETSC_SUCCESS;
1555: }
1556: static inline PetscErrorCode PetscSpinlockUnlock(PetscSpinlock *omp_lock)
1557: {
1558:   omp_unset_lock(omp_lock);
1559:   return PETSC_SUCCESS;
1560: }
1561: static inline PetscErrorCode PetscSpinlockDestroy(PetscSpinlock *omp_lock)
1562: {
1563:   omp_destroy_lock(omp_lock);
1564:   return PETSC_SUCCESS;
1565: }
1566:   #else
1567:     #if defined(__cplusplus)
1568:       #error "Thread safety requires either --download-concurrencykit, std::atomic, or --with-openmp"
1569:     #else
1570:       #error "Thread safety requires either --download-concurrencykit, stdatomic.h, or --with-openmp"
1571:     #endif
1572:   #endif

1574: #else
1575: typedef int PetscSpinlock;
1576:   #define PetscSpinlockCreate(a)  PETSC_SUCCESS
1577:   #define PetscSpinlockLock(a)    PETSC_SUCCESS
1578:   #define PetscSpinlockUnlock(a)  PETSC_SUCCESS
1579:   #define PetscSpinlockDestroy(a) PETSC_SUCCESS
1580: #endif

1582: #if defined(PETSC_HAVE_THREADSAFETY)
1583: PETSC_INTERN PetscSpinlock PetscViewerASCIISpinLockOpen;
1584: PETSC_INTERN PetscSpinlock PetscViewerASCIISpinLockStdout;
1585: PETSC_INTERN PetscSpinlock PetscViewerASCIISpinLockStderr;
1586: PETSC_INTERN PetscSpinlock PetscCommSpinLock;
1587: #endif

1589: PETSC_EXTERN PetscLogEvent PETSC_Barrier;
1590: PETSC_EXTERN PetscLogEvent PETSC_BuildTwoSided;
1591: PETSC_EXTERN PetscLogEvent PETSC_BuildTwoSidedF;
1592: PETSC_EXTERN PetscBool     use_gpu_aware_mpi;
1593: PETSC_EXTERN PetscBool     PetscPrintFunctionList;

1595: #if defined(PETSC_HAVE_ADIOS)
1596: PETSC_EXTERN int64_t Petsc_adios_group;
1597: #endif

1599: #if defined(PETSC_HAVE_KOKKOS)
1600: PETSC_INTERN PetscBool      PetscBeganKokkos;
1601: PETSC_EXTERN PetscBool      PetscKokkosInitialized;
1602: PETSC_INTERN PetscErrorCode PetscKokkosIsInitialized_Private(PetscBool *);
1603: PETSC_INTERN PetscErrorCode PetscKokkosFinalize_Private(void);
1604: #endif

1606: #if defined(PETSC_HAVE_OPENMP)
1607: PETSC_EXTERN PetscInt PetscNumOMPThreads;
1608: #endif

1610: struct _n_PetscObjectList {
1611:   char            name[256];
1612:   PetscBool       skipdereference; /* when the PetscObjectList is destroyed do not call PetscObjectDereference() on this object */
1613:   PetscObject     obj;
1614:   PetscObjectList next;
1615: };