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 PetscStackReset(void);
 18: PETSC_INTERN PetscErrorCode PetscStackCopy(PetscStack *, PetscStack *);
 19: PETSC_INTERN PetscErrorCode PetscStackPrint(PetscStack *, FILE *);
 20: #else
 21:   #define PetscStackSetCheck(check)         PETSC_SUCCESS
 22:   #define PetscStackReset()                 PETSC_SUCCESS
 23:   #define PetscStackCopy(stackin, stackout) PETSC_SUCCESS
 24:   #define PetscStackPrint(stack, file)      PETSC_SUCCESS
 25: #endif

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

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

 35:    PetscHeaderCreate() should be used whenever creating a PETSc structure.
 36: */

 38: /*
 39:    PetscOps: structure of core operations that all PETSc objects support.

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

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

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

 67: /*S
 68:   PetscFortranCallbackFn - A prototype of a Fortran function provided as a callback

 70:   Level: advanced

 72:   Notes:
 73:   `PetscFortranCallbackFn *` plays the role of `void *` for function pointers in the PETSc Fortran API.

 75: .seealso: `PetscVoidFn`, `PetscErrorCodeFn`
 76: S*/
 77: PETSC_EXTERN_TYPEDEF typedef void(PetscFortranCallbackFn)(void);

 79: typedef struct {
 80:   PetscFortranCallbackFn *func;
 81:   void                   *ctx;
 82: } PetscFortranCallback;

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

129:   PetscInt noptionhandler;
130:   PetscErrorCode (*optionhandler[PETSC_MAX_OPTIONS_HANDLER])(PetscObject, PetscOptionItems, void *);
131:   PetscErrorCode (*optiondestroy[PETSC_MAX_OPTIONS_HANDLER])(PetscObject, void *);
132:   void *optionctx[PETSC_MAX_OPTIONS_HANDLER];
133: #if defined(PETSC_HAVE_SAWS)
134:   PetscBool amsmem;          /* if PETSC_TRUE then this object is registered with SAWs and visible to clients */
135:   PetscBool amspublishblock; /* if PETSC_TRUE and publishing objects then will block at PetscObjectSAWsBlock() */
136: #endif
137:   PetscOptions options; /* options database used, NULL means default */
138:   PetscBool    optionsprinted;
139:   PetscBool    donotPetscObjectPrintClassNamePrefixType;
140: } _p_PetscObject;

142: #define PETSCHEADER(ObjectOps) \
143:   _p_PetscObject hdr; \
144:   ObjectOps      ops[1]

146: #define PETSCFREEDHEADER -1

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

151:   Calling Sequence:
152: . obj - the `PetscObject` to destroy

154:   Level: beginner

156:   Note:
157:   The deprecated `PetscObjectDestroyFunction` works as a replacement for `PetscObjectDestroyFn` *.

159: .seealso: `PetscObject`, `PetscObjectDestroy()`
160: S*/
161: PETSC_EXTERN_TYPEDEF typedef PetscErrorCode PetscObjectDestroyFn(PetscObject *obj);

163: PETSC_EXTERN_TYPEDEF typedef PetscObjectDestroyFn *PetscObjectDestroyFunction;

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

168:   Calling Sequence:
169: + obj - the `PetscObject` to view
170: - v - the viewer

172:   Level: beginner

174:   Note:
175:   The deprecated `PetscObjectViewFunction` works as a replacement for `PetscObjectViewFn` *.

177: .seealso: `PetscObject`, `PetscObjectDestroy()`, `PetscViewer`, `PetscObjectView()`
178: S*/
179: PETSC_EXTERN_TYPEDEF typedef PetscErrorCode PetscObjectViewFn(PetscObject obj, PetscViewer v);

181: PETSC_EXTERN_TYPEDEF typedef PetscObjectViewFn *PetscObjectViewFunction;

183: /*MC
184:     PetscHeaderCreate - Creates a raw PETSc object of a particular class

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

190:   Collective

192:   Input Parameters:
193: + classid    - The classid associated with this object (for example `VEC_CLASSID`)
194: . class_name - String name of class; should be static (for example "Vec"), may be `PETSC_NULLPTR`
195: . descr      - String containing short description; should be static (for example "Vector"), may be `PETSC_NULLPTR`
196: . mansec     - String indicating section in manual pages; should be static (for example "Vec"), may be `PETSC_NULLPTR`
197: . comm       - The MPI Communicator
198: . destroy    - The destroy routine for this object (for example `VecDestroy()`)
199: - view       - The view routine for this object (for example `VecView()`), may be `PETSC_NULLPTR`

201:   Output Parameter:
202: . h - The newly created `PetscObject`

204:   Level: developer

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

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

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

219:   Example Usage:
220:   Existing `PetscObject`s may be easily created as shown. Unless otherwise stated, a particular
221:   objects `destroy` and `view` functions are exactly `<OBJECT_TYPE>Destroy()` and
222:   `<OBJECT_TYPE>View()`.
223: .vb
224:   Vec v;

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

229:   It is possible to create custom `PetscObject`s, note however that they must abide by the
230:   restrictions set forth above.
231: .vb
232:   // OK, first member of C structure is _p_PetscObject
233:   struct MyCPetscObject_s
234:   {
235:     _p_PetscObject header;
236:     int            some_data;
237:   };
238:   typedef struct *MyCPetscObject_s MyCPetscObject;

240:   PetscErrorCode MyObjectDestroy(MyObject *);
241:   PetscErrorCode MyObjectView(MyObject);

243:   MyCPetscObject obj;

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

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

251:   // ERROR must be a single-level pointer
252:   PetscHeaderCreate(&obj, ...);
253: .ve

255:   Illustrating proper construction from C++\:
256: .vb
257:   // ERROR, class is not standard layout, first member must be publicly accessible
258:   class BadCppPetscObject
259:   {
260:     _p_PetscObject header;
261:   };

263:   // ERROR, class is not standard layout, has a virtual function and virtual inheritance
264:   class BadCppPetscObject2 : virtual BaseClass
265:   {
266:   public:
267:     _p_PetscObject header;

269:     virtual void foo();
270:   };

272:   // ERROR, class is not standard layout! Has non-standard layout member
273:   class BadCppPetscObject2
274:   {
275:   public:
276:     _p_PetscObject    header;
277:     BadCppPetscObject non_standard_layout;
278:   };

280:   // OK, class is standard layout!
281:   class GoodCppPetscObject;
282:   using MyCppObject = GoodCppPetscObject *;

284:   // OK, non-virtual inheritance of other standard layout class does not affect layout
285:   class GoodCppPetscObject : StandardLayoutClass
286:   {
287:   public:
288:     // OK, non standard layout member is static, does not affect layout
289:     static BadCppPetscObject non_standard_layout;

291:     // OK, first non-static member is _p_PetscObject
292:     _p_PetscObject header;

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

297:     // OK, may use "member" functions for destroy and view so long as they are static
298:     static PetscErrorCode destroy(MyCppObject *);
299:     static PetscErrorCode view(MyCppObject);
300:   };

302:   // OK, usage via pointer
303:   MyObject obj;

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

308: .seealso: `PetscObject`, `PetscHeaderDestroy()`, `PetscClassIdRegister()`
309: M*/
310: #define PetscHeaderCreate(h, classid, class_name, descr, mansec, comm, destroy, view) \
311:   PetscHeaderCreate_Function(PetscNew(&(h)), (PetscObject *)&(h), (classid), (class_name), (descr), (mansec), (comm), (PetscObjectDestroyFn *)(destroy), (PetscObjectViewFn *)(view))

313: PETSC_EXTERN PetscErrorCode PetscHeaderCreate_Function(PetscErrorCode, PetscObject *, PetscClassId, const char[], const char[], const char[], MPI_Comm, PetscObjectDestroyFn *, PetscObjectViewFn *);
314: PETSC_EXTERN PetscErrorCode PetscHeaderCreate_Private(PetscObject, PetscClassId, const char[], const char[], const char[], MPI_Comm, PetscObjectDestroyFn *, PetscObjectViewFn *);
315: PETSC_EXTERN PetscErrorCode PetscHeaderDestroy_Function(PetscObject *);
316: PETSC_EXTERN PetscErrorCode PetscComposedQuantitiesDestroy(PetscObject obj);
317: PETSC_INTERN PetscObjectId  PetscObjectNewId_Internal(void);

319: /*MC
320:   PetscHeaderDestroy - Final step in destroying a `PetscObject`

322:   Synopsis:
323: #include <petsc/private/petscimpl.h>
324:   PetscErrorCode PetscHeaderDestroy(PetscObject *obj)

326:   Collective

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

331:   Level: developer

333:   Notes:
334:   `h` is freed and set to `PETSC_NULLPTR` when this routine returns.

336:   Example Usage:
337: .vb
338:   PetscObject obj;

340:   PetscHeaderCreate(obj, ...);
341:   // use obj...

343:   // note pointer to obj is used
344:   PetscHeaderDestroy(&obj);
345: .ve

347:   Note that this routine is the _last_ step when destroying higher-level `PetscObject`s as it
348:   deallocates the memory for the structure itself\:
349: .vb
350:   typedef struct MyPetscObject_s *MyPetscObject;
351:   struct MyPetscObject_s
352:   {
353:     _p_PetscObject  hdr;
354:     PetscInt       *foo;
355:     PetscScalar    *bar;
356:   };

358:   // assume obj is created/initialized elsewhere...
359:   MyPetscObject obj;

361:   // OK, should dispose of all dynamically allocated resources before calling
362:   // PetscHeaderDestroy()
363:   PetscFree(obj->foo);

365:   // OK, dispose of obj
366:   PetscHeaderDestroy(&obj);

368:   // ERROR, obj points to NULL here, accessing obj->bar may result in segmentation violation!
369:   // obj->bar is potentially leaked!
370:   PetscFree(obj->bar);
371: .ve

373: .seealso: `PetscObject`, `PetscHeaderCreate()`
374: M*/
375: #define PetscHeaderDestroy(h) PetscHeaderDestroy_Function((PetscObject *)h)

377: PETSC_EXTERN PetscErrorCode                PetscHeaderDestroy_Private(PetscObject, PetscBool);
378: PETSC_INTERN PetscErrorCode                PetscHeaderDestroy_Private_Unlogged(PetscObject, PetscBool);
379: PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode PetscHeaderReset_Internal(PetscObject);
380: PETSC_EXTERN PetscErrorCode                PetscObjectCopyFortranFunctionPointers(PetscObject, PetscObject);
381: PETSC_EXTERN PetscErrorCode                PetscObjectSetFortranCallback(PetscObject, PetscFortranCallbackType, PetscFortranCallbackId *, PetscFortranCallbackFn *, void *ctx);
382: PETSC_EXTERN PetscErrorCode                PetscObjectGetFortranCallback(PetscObject, PetscFortranCallbackType, PetscFortranCallbackId, PetscFortranCallbackFn **, void **ctx);

384: PETSC_INTERN PetscErrorCode PetscCitationsInitialize(void);
385: PETSC_INTERN PetscErrorCode PetscFreeMPIResources(void);
386: PETSC_INTERN PetscErrorCode PetscOptionsHasHelpIntro_Internal(PetscOptions, PetscBool *);

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

391: #if PetscDefined(HAVE_SETJMP_H)
392: PETSC_EXTERN PetscBool PetscCheckPointer(const void *, PetscDataType);
393: #else
394:   #define PetscCheckPointer(ptr, data_type) (ptr ? PETSC_TRUE : PETSC_FALSE)
395: #endif

397: #if defined(PETSC_CLANG_STATIC_ANALYZER)
398: template <typename T>
400: template <typename T>
402: template <typename T>
404: template <typename T>
405: extern void PetscAssertPointer(T, int)
406: {
407: }
408: template <typename T>
410: #else
411:   // Macros to test if a PETSc object is valid and if pointers are valid
412:   #if PetscDefined(USE_DEBUG)
413:     /*  This check is for subtype methods such as DMDAGetCorners() that do not use the PetscTryMethod() or PetscUseMethod() paradigm */
415:       do { \
416:         PetscBool _7_same; \
418:         PetscCall(PetscObjectTypeCompare((PetscObject)(h), t, &_7_same)); \
419:         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); \
420:       } while (0)

422:     #define PetscAssertPointer_Internal(ptr, arg, ptype, ptrtype) \
423:       do { \
424:         PetscCheck(ptr, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Null Pointer: Parameter # %d", arg); \
425:         PetscCheck(PetscCheckPointer(ptr, ptype), PETSC_COMM_SELF, PETSC_ERR_ARG_BADPTR, "Invalid Pointer to %s: Argument '" PetscStringize(ptr) "' (parameter # %d)", ptrtype, arg); \
426:       } while (0)

429:       do { \
430:         PetscAssertPointer_Internal(h, arg, PETSC_OBJECT, "PetscObject"); \
431:         if (((PetscObject)(h))->classid != ck) { \
432:           PetscCheck(((PetscObject)(h))->classid != PETSCFREEDHEADER, PETSC_COMM_SELF, PETSC_ERR_ARG_CORRUPT, "Object already free: Parameter # %d", arg); \
433:           SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Wrong type of object: Parameter # %d", arg); \
434:         } \
435:       } while (0)

438:       do { \
439:         PetscAssertPointer_Internal(h, arg, PETSC_OBJECT, "PetscObject"); \
440:         PetscCheck(((PetscObject)(h))->classid != PETSCFREEDHEADER, PETSC_COMM_SELF, PETSC_ERR_ARG_CORRUPT, "Object already free: Parameter # %d", arg); \
441:         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); \
442:       } while (0)

444:     #if defined(__cplusplus)
445:       #include <type_traits> // std::decay

447: namespace Petsc
448: {

450: namespace util
451: {

453: template <typename T>
454: struct PetscAssertPointerImpl {
455:   PETSC_NODISCARD static constexpr PetscDataType type() noexcept { return PETSC_CHAR; }
456:   PETSC_NODISCARD static constexpr const char   *string() noexcept { return "memory"; }
457: };

459:       #define PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(T, PETSC_TYPE) \
460:         template <> \
461:         struct PetscAssertPointerImpl<T *> { \
462:           PETSC_NODISCARD static constexpr PetscDataType type() noexcept { return PETSC_TYPE; } \
463:           PETSC_NODISCARD static constexpr const char   *string() noexcept { return PetscStringize(T); } \
464:         }; \
465:         template <> \
466:         struct PetscAssertPointerImpl<const T *> : PetscAssertPointerImpl<T *> { }; \
467:         template <> \
468:         struct PetscAssertPointerImpl<volatile T *> : PetscAssertPointerImpl<T *> { }; \
469:         template <> \
470:         struct PetscAssertPointerImpl<const volatile T *> : PetscAssertPointerImpl<T *> { }

472: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(char, PETSC_CHAR);
473: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(signed char, PETSC_CHAR);
474: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(unsigned char, PETSC_CHAR);
475: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(short, PETSC_SHORT);
476: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(unsigned short, PETSC_SHORT);
477: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(PetscBool, PETSC_BOOL);
478: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(float, PETSC_FLOAT);
479: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(double, PETSC_DOUBLE);
480: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(int32_t, PETSC_INT32);
481: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(uint32_t, PETSC_INT32);
482: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(int64_t, PETSC_INT64);
483: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(uint64_t, PETSC_INT64);
484:       #if defined(PETSC_HAVE_COMPLEX)
485: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(PetscComplex, PETSC_COMPLEX);
486:       #endif

488:       #undef PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION

490: } // namespace util

492: } // namespace Petsc

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

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

500:       #if PetscDefined(HAVE_COMPLEX)
501:         #define PETSC_GENERIC_CV_COMPLEX(result) PETSC_GENERIC_CV(PetscComplex, result)
502:       #else
503:         #define PETSC_GENERIC_CV_COMPLEX(result)
504:       #endif

506:       #define PetscAssertPointer_PetscDataType(h) \
507:         _Generic((h), \
508:           default: PETSC_CHAR, \
509:           PETSC_GENERIC_CV(          char, PETSC_CHAR), \
510:           PETSC_GENERIC_CV(   signed char, PETSC_CHAR), \
511:           PETSC_GENERIC_CV( unsigned char, PETSC_CHAR), \
512:           PETSC_GENERIC_CV(         short, PETSC_SHORT), \
513:           PETSC_GENERIC_CV(unsigned short, PETSC_SHORT), \
514:           PETSC_GENERIC_CV(         float, PETSC_FLOAT), \
515:           PETSC_GENERIC_CV(        double, PETSC_DOUBLE), \
516:           PETSC_GENERIC_CV(       int32_t, PETSC_INT32), \
517:           PETSC_GENERIC_CV(      uint32_t, PETSC_INT32), \
518:           PETSC_GENERIC_CV(       int64_t, PETSC_INT64), \
519:           PETSC_GENERIC_CV(      uint64_t, PETSC_INT64), \
520:           PETSC_GENERIC_CV_COMPLEX(PETSC_COMPLEX))

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

524:       #if PetscDefined(HAVE_COMPLEX)
525:         #define PETSC_GENERIC_CV_STRINGIZE_COMPLEX PETSC_GENERIC_CV_STRINGIZE(PetscComplex)
526:       #else
527:         #define PETSC_GENERIC_CV_STRINGIZE_COMPLEX
528:       #endif

530:       #define PetscAssertPointer_String(h) \
531:         _Generic((h), \
532:           default: "memory", \
533:           PETSC_GENERIC_CV_STRINGIZE(char), \
534:           PETSC_GENERIC_CV_STRINGIZE(signed char), \
535:           PETSC_GENERIC_CV_STRINGIZE(unsigned char), \
536:           PETSC_GENERIC_CV_STRINGIZE(short), \
537:           PETSC_GENERIC_CV_STRINGIZE(unsigned short), \
538:           PETSC_GENERIC_CV_STRINGIZE(float), \
539:           PETSC_GENERIC_CV_STRINGIZE(double), \
540:           PETSC_GENERIC_CV_STRINGIZE(int32_t), \
541:           PETSC_GENERIC_CV_STRINGIZE(uint32_t), \
542:           PETSC_GENERIC_CV_STRINGIZE(int64_t), \
543:           PETSC_GENERIC_CV_STRINGIZE(uint64_t), \
544:           PETSC_GENERIC_CV_STRINGIZE_COMPLEX)
545:     #else // PETSC_C_VERSION >= 11 || defined(__cplusplus)
546:       #define PetscAssertPointer_PetscDataType(h) PETSC_CHAR
547:       #define PetscAssertPointer_String(h)        "memory"
548:     #endif // PETSC_C_VERSION >= 11 || defined(__cplusplus)
549:     #define PetscAssertPointer(h, arg) PetscAssertPointer_Internal(h, arg, PetscAssertPointer_PetscDataType(h), PetscAssertPointer_String(h))
551:   #else // PetscDefined(USE_DEBUG)
553:       do { \
554:         (void)(h); \
555:       } while (0)
557:       do { \
558:         (void)(h); \
559:       } while (0)
561:       do { \
562:         (void)(h); \
563:       } while (0)
564:     #define PetscAssertPointer(h, arg) \
565:       do { \
566:         (void)(h); \
567:       } while (0)
569:       do { \
570:         (void)(h); \
571:       } while (0)
572:   #endif // PetscDefined(USE_DEBUG)
573: #endif   // PETSC_CLANG_STATIC_ANALYZER


584: #define PetscSorted(n, idx, sorted) \
585:   do { \
586:     (sorted) = PETSC_TRUE; \
587:     for (PetscCount _i_ = 1; _i_ < (n); ++_i_) { \
588:       if ((idx)[_i_] < (idx)[_i_ - 1]) { \
589:         (sorted) = PETSC_FALSE; \
590:         break; \
591:       } \
592:     } \
593:   } while (0)

595: #if !defined(PETSC_CLANG_STATIC_ANALYZER)
596:   #if !defined(PETSC_USE_DEBUG)

598:     #define PetscCheckSameType(a, arga, b, argb) \
599:       do { \
600:         (void)(a); \
601:         (void)(b); \
602:       } while (0)
603:     #define PetscCheckTypeName(a, type) \
604:       do { \
605:         (void)(a); \
606:       } while (0)
607:     #define PetscCheckTypeNames(a, type1, type2) \
608:       do { \
609:         (void)(a); \
610:       } while (0)
612:       do { \
613:         (void)(a); \
614:       } while (0)
615:     #define PetscCheckSameComm(a, arga, b, argb) \
616:       do { \
617:         (void)(a); \
618:         (void)(b); \
619:       } while (0)
620:     #define PetscCheckSameTypeAndComm(a, arga, b, argb) \
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)
656:       do { \
657:         (void)(a); \
658:         (void)(b); \
659:       } while (0)
661:       do { \
662:         (void)(a); \
663:         (void)(b); \
664:       } while (0)
665:     #define PetscCheckSorted(n, idx) \
666:       do { \
667:         (void)(n); \
668:         (void)(idx); \
669:       } while (0)

671:   #else

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

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

679:   This macro is used incorrectly in the code. Many places that do not need identity of the
680:   types incorrectly call this check and would need to be fixed if this macro is enabled.
681: */
682:     #if 0
683:       #define PetscCheckSameType(a, arga, b, argb) \
684:         do { \
685:           PetscBool pcst_type_eq_ = PETSC_TRUE; \
686:           PetscCall(PetscStrcmp(((PetscObject)(a))->type_name, ((PetscObject)(b))->type_name, &pcst_type_eq_)); \
687:           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); \
688:         } while (0)
689:     #else
690:       #define PetscCheckSameType(a, arga, b, argb) \
691:         do { \
692:           (void)(a); \
693:           (void)(b); \
694:         } while (0)
695:     #endif

697:     /*
698:     Check type_name
699: */
700:     #define PetscCheckTypeName(a, type) \
701:       do { \
702:         PetscBool _7_match; \
703:         PetscCall(PetscObjectTypeCompare(((PetscObject)(a)), (type), &_7_match)); \
704:         PetscCheck(_7_match, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Object (%s) is not %s", ((PetscObject)(a))->type_name, type); \
705:       } while (0)

707:     #define PetscCheckTypeNames(a, type1, type2) \
708:       do { \
709:         PetscBool _7_match; \
710:         PetscCall(PetscObjectTypeCompareAny(((PetscObject)(a)), &_7_match, (type1), (type2), "")); \
711:         PetscCheck(_7_match, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Object (%s) is not %s or %s", ((PetscObject)(a))->type_name, type1, type2); \
712:       } while (0)

714:     /*
715:    Use this macro to check if the type is set
716: */

719:     /*
720:    Sometimes object must live on same communicator to inter-operate
721: */
722:     #define PetscCheckSameComm(a, arga, b, argb) \
723:       do { \
724:         PetscMPIInt _7_flag; \
725:         PetscCallMPI(MPI_Comm_compare(PetscObjectComm((PetscObject)(a)), PetscObjectComm((PetscObject)(b)), &_7_flag)); \
726:         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); \
727:       } while (0)

729:     #define PetscCheckSameTypeAndComm(a, arga, b, argb) \
730:       do { \
731:         PetscCheckSameType(a, arga, b, argb); \
732:         PetscCheckSameComm(a, arga, b, argb); \
733:       } while (0)

736:       do { \
737:         PetscScalar b0 = (b); \
738:         PetscReal   b1[5]; \
739:         if (PetscIsNanScalar(b0)) { \
740:           b1[4] = 1; \
741:         } else { \
742:           b1[4] = 0; \
743:         }; \
744:         b1[0] = -PetscRealPart(b0); \
745:         b1[1] = PetscRealPart(b0); \
746:         b1[2] = -PetscImaginaryPart(b0); \
747:         b1[3] = PetscImaginaryPart(b0); \
748:         PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, b1, 5, MPIU_REAL, MPIU_MAX, PetscObjectComm((PetscObject)(a)))); \
749:         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); \
750:       } while (0)

753:       do { \
754:         PetscReal b0 = (b), b1[3]; \
755:         if (PetscIsNanReal(b0)) { \
756:           b1[2] = 1; \
757:         } else { \
758:           b1[2] = 0; \
759:         }; \
760:         b1[0] = -b0; \
761:         b1[1] = b0; \
762:         PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, b1, 3, MPIU_REAL, MPIU_MAX, PetscObjectComm((PetscObject)(a)))); \
763:         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); \
764:       } while (0)

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

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

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

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

803:       do { \
804:         PetscBool b0 = (PetscBool)(b), b1[2]; \
805:         b1[0]        = !b0; \
806:         b1[1]        = b0; \
807:         PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, b1, 2, MPI_C_BOOL, MPI_LAND, PetscObjectComm((PetscObject)(a)))); \
808:         PetscCheck(!b1[0] == b1[1], PetscObjectComm((PetscObject)(a)), PETSC_ERR_ARG_WRONG, "Bool value must be same on all processes, argument # %d", arg); \
809:       } while (0)

812:       do { \
813:         PetscMPIInt b0 = (PetscMPIInt)(b), b1[2]; \
814:         b1[0]          = -b0; \
815:         b1[1]          = b0; \
816:         PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, b1, 2, MPI_INT, MPI_MAX, PetscObjectComm((PetscObject)(a)))); \
817:         PetscCheck(-b1[0] == b1[1], PetscObjectComm((PetscObject)(a)), PETSC_ERR_ARG_WRONG, "Enum value must be same on all processes, argument # %d", arg); \
818:       } while (0)

820:     #define PetscCheckSorted(n, idx) \
821:       do { \
822:         PetscBool _1_flg; \
823:         PetscSorted(n, idx, _1_flg); \
824:         PetscCheck(_1_flg, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Input array needs to be sorted"); \
825:       } while (0)

827:   #endif
828: #else  /* PETSC_CLANG_STATIC_ANALYZER */
829: template <typename Ta, typename Tb>
830: extern void PetscCheckSameType(Ta, int, Tb, int);
831: template <typename Ta, typename Tb>
832: extern void PetscCheckTypeName(Ta, Tb);
833: template <typename Ta, typename Tb, typename Tc>
834: extern void PetscCheckTypeNames(Ta, Tb, Tc);
835: template <typename T>
837: template <typename Ta, typename Tb>
838: extern void PetscCheckSameComm(Ta, int, Tb, int);
839: template <typename Ta, typename Tb>
840: extern void PetscCheckSameTypeAndComm(Ta, int, Tb, int);
841: template <typename Ta, typename Tb>
843: template <typename Ta, typename Tb>
845: template <typename Ta, typename Tb>
847: template <typename Ta, typename Tb>
849: template <typename Ta, typename Tb>
851: template <typename Ta, typename Tb>
853: template <typename Ta, typename Tb>
855: template <typename T>
856: extern void PetscCheckSorted(PetscInt, T);
857: #endif /* PETSC_CLANG_STATIC_ANALYZER */

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

862:   Synopsis:
863:    #include "petsc/private/petscimpl.h"
864:    PetscTryMethod(PetscObject obj, const char *name, (arg_types), (arg_value))

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

872:    Level: developer

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

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

880: .seealso: `PetscUseMethod()`, `PetscCall()`, `PetscUseTypeMethod()`, `PetscTryTypeMethod()`, `PetscCheck()`, `PetscObject`
881: M*/
882: #define PetscTryMethod(obj, A, B, C) \
883:   do { \
884:     PetscErrorCode(*_7_f) B; \
885:     PetscCall(PetscObjectQueryFunction((PetscObject)(obj), A, &_7_f)); \
886:     if (_7_f) PetscCall((*_7_f)C); \
887:   } while (0)

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

892:   Synopsis:
893:    #include "petsc/private/petscimpl.h"
894:    PetscUseMethod(PetscObject obj, const char *name, (arg_types), (arg_value))

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

902:    Level: developer

904:    Notes:
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 `PetscUseTypeMethod()` or `PetscTryTypeMethod()` to call functions that are included in the object's function table, the `ops` array
908:    in the object.

910: .seealso: `PetscTryMethod()`, `PetscCall()`, `PetscUseTypeMethod()`, `PetscTryTypeMethod()`, `PetscCheck()`, `PetscObject`
911: M*/
912: #define PetscUseMethod(obj, A, B, C) \
913:   do { \
914:     PetscErrorCode(*_7_f) B; \
915:     PetscCall(PetscObjectQueryFunction((PetscObject)(obj), A, &_7_f)); \
916:     PetscCheck(_7_f, PetscObjectComm((PetscObject)(obj)), PETSC_ERR_SUP, "Cannot locate function %s in object", A); \
917:     PetscCall((*_7_f)C); \
918:   } while (0)

920: /*
921:   Use Microsoft traditional preprocessor.

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

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

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

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

934:   #define PetscUseTypeMethod(obj, OP, ...) \
935:     do { \
936:       PetscErrorCode ierr_p_; \
937:       PetscStackUpdateLine; \
938:       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); \
939:       ierr_p_ = (*(obj)->ops->OP)(obj, __VA_ARGS__); \
940:       PetscCall(ierr_p_); \
941:     } while (0)

943:   #define PetscTryTypeMethod(obj, OP, ...) \
944:     do { \
945:       if ((obj)->ops->OP) { \
946:         PetscErrorCode ierr_p_; \
947:         PetscStackUpdateLine; \
948:         ierr_p_ = (*(obj)->ops->OP)(obj, __VA_ARGS__); \
949:         PetscCall(ierr_p_); \
950:       } \
951:     } while (0)

953: #else

955:   /*MC
956:    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

958:   Synopsis:
959:    #include "petsc/private/petscimpl.h"
960:    PetscUseTypeMethod(obj, method, other_args)

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

967:    Level: developer

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

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

974: .seealso: `PetscTryMethod()`, `PetscUseMethod()`, `PetscCall()`, `PetscCheck()`, `PetscTryTypeMethod()`, `PetscCallBack()`
975: M*/
976:   #define PetscUseTypeMethod(obj, ...) \
977:     do { \
978:       PetscCheck((obj)->ops->PETSC_FIRST_ARG((__VA_ARGS__, unused)), PetscObjectComm((PetscObject)obj), PETSC_ERR_SUP, "No method %s for %s of type %s", \
979:                  PetscStringize(PETSC_FIRST_ARG((__VA_ARGS__,unused))), ((PetscObject)obj)->class_name, ((PetscObject)obj)->type_name); \
980:       PetscCall((*(obj)->ops->PETSC_FIRST_ARG((__VA_ARGS__, unused)))(obj PETSC_REST_ARG(__VA_ARGS__))); \
981:     } while (0)

983:   /*MC
984:    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

986:   Synopsis:
987:    #include "petsc/private/petscimpl.h"
988:    PetscTryTypeMethod(obj, method, other_args)

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

995:    Level: developer

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

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

1002: .seealso: `PetscTryMethod()`, `PetscUseMethod()`, `PetscCall()`, `PetscCheck()`, `PetscUseTypeMethod()`
1003: M*/
1004:   #define PetscTryTypeMethod(obj, ...) \
1005:     do { \
1006:       if ((obj)->ops->PETSC_FIRST_ARG((__VA_ARGS__, unused))) PetscCall((*(obj)->ops->PETSC_FIRST_ARG((__VA_ARGS__, unused)))(obj PETSC_REST_ARG(__VA_ARGS__))); \
1007:     } while (0)

1009: #endif

1011: /*MC
1012:    PetscObjectStateIncrease - Increases the state of any `PetscObject`

1014:    Synopsis:
1015:    #include "petsc/private/petscimpl.h"
1016:    PetscErrorCode PetscObjectStateIncrease(PetscObject obj)

1018:    Logically Collective

1020:    Input Parameter:
1021: .  obj - any PETSc object, for example a `Vec`, `Mat` or `KSP`. This must be
1022:          cast with a (PetscObject), for example,
1023:          `PetscObjectStateIncrease`((`PetscObject`)mat);

1025:    Level: developer

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

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

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

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

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

1044: .seealso: `PetscObjectStateGet()`, `PetscObject`
1045: M*/
1046: #define PetscObjectStateIncrease(obj) ((PetscErrorCode)((obj)->state++, PETSC_SUCCESS))

1048: PETSC_EXTERN PetscErrorCode PetscObjectStateGet(PetscObject, PetscObjectState *);
1049: PETSC_EXTERN PetscErrorCode PetscObjectStateSet(PetscObject, PetscObjectState);
1050: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataRegister(PetscInt *);
1051: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseInt(PetscObject);
1052: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseIntstar(PetscObject);
1053: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseReal(PetscObject);
1054: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseRealstar(PetscObject);
1055: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseScalar(PetscObject);
1056: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseScalarstar(PetscObject);
1057: PETSC_EXTERN PetscInt       PetscObjectComposedDataMax;

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

1062:    Synopsis:
1063:    #include "petsc/private/petscimpl.h"
1064:    PetscErrorCode PetscObjectComposedDataSetInt(PetscObject obj, PetscInt id, PetscInt data)

1066:    Not Collective

1068:    Input Parameters:
1069: +  obj - the object to which data is to be attached
1070: .  id - the identifier for the data
1071: -  data - the data to  be attached, a `PetscInt`

1073:    Level: developer

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

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

1081: .seealso: `PetscObjectComposedDataGetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetReal()`,
1082:           `PetscObjectComposedDataGetIntstar()`, `PetscObjectComposedDataSetIntstar()`, `PetscObject`,
1083:           `PetscObjectCompose()`, `PetscObjectQuery()`
1084: M*/
1085: #define PetscObjectComposedDataSetInt(obj, id, data) \
1086:   ((PetscErrorCode)((((obj)->int_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseInt(obj)) || ((obj)->intcomposeddata[id] = data, (obj)->intcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))

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

1091:    Synopsis:
1092:    #include "petsc/private/petscimpl.h"
1093:    PetscErrorCode PetscObjectComposedDataGetInt(PetscObject obj, PetscInt id, PetscInt data, PetscBool flag)

1095:    Not Collective

1097:    Input Parameters:
1098: +  obj - the object from which data is to be retrieved
1099: -  id - the identifier for the data

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

1105:    Level: developer

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

1110: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetReal()`,
1111:           `PetscObjectComposedDataGetIntstar()`, `PetscObjectComposedDataSetIntstar()`, `PetscObject`,
1112:           `PetscObjectCompose()`, `PetscObjectQuery()`
1113: M*/
1114: #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))

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

1119:    Synopsis:
1120:    #include "petsc/private/petscimpl.h"
1121:    PetscErrorCode PetscObjectComposedDataSetIntstar(PetscObject obj, PetscInt id, PetscInt *data)

1123:    Not Collective

1125:    Input Parameters:
1126: +  obj - the object to which data is to be attached
1127: .  id - the identifier for the data
1128: -  data - the data to  be attached, a `PetscInt` array

1130:    Level: developer

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

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

1137: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetReal()`,
1138:           `PetscObjectComposedDataGetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1139:           `PetscObjectCompose()`, `PetscObjectQuery()`
1140: M*/
1141: #define PetscObjectComposedDataSetIntstar(obj, id, data) \
1142:   ((PetscErrorCode)((((obj)->intstar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseIntstar(obj)) || ((obj)->intstarcomposeddata[id] = data, (obj)->intstarcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))

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

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

1151:    Not Collective

1153:    Input Parameters:
1154: +  obj - the object from which data is to be retrieved
1155: -  id - the identifier for the data

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

1161:    Level: developer

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

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

1168: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetReal()`,
1169:           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1170:           `PetscObjectCompose()`, `PetscObjectQuery()`
1171: M*/
1172: #define PetscObjectComposedDataGetIntstar(obj, id, data, flag) \
1173:   ((PetscErrorCode)(((obj)->intstarcomposedstate ? (data = (obj)->intstarcomposeddata[id], flag = (PetscBool)((obj)->intstarcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), PETSC_SUCCESS))

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

1178:    Synopsis:
1179:    #include "petsc/private/petscimpl.h"
1180:    PetscErrorCode PetscObjectComposedDataSetReal(PetscObject obj, PetscInt id, PetscReal data)

1182:    Not Collective

1184:    Input Parameters:
1185: +  obj - the object to which data is to be attached
1186: .  id - the identifier for the data
1187: -  data - the data to  be attached, a `PetscReal`

1189:    Level: developer

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

1194: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1195:           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1196:           `PetscObjectCompose()`, `PetscObjectQuery()`
1197: M*/
1198: #define PetscObjectComposedDataSetReal(obj, id, data) \
1199:   ((PetscErrorCode)((((obj)->real_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseReal(obj)) || ((obj)->realcomposeddata[id] = data, (obj)->realcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))

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

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

1208:    Not Collective

1210:    Input Parameters:
1211: +  obj - the object from which data is to be retrieved
1212: -  id - the identifier for the data

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

1218:    Level: developer

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

1223: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataSetIntstar()`,
1224:           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1225:           `PetscObjectCompose()`, `PetscObjectQuery()`
1226: M*/
1227: #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))

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

1232:    Synopsis:
1233:    #include "petsc/private/petscimpl.h"
1234:    PetscErrorCode PetscObjectComposedDataSetRealstar(PetscObject obj, PetscInt id, PetscReal *data)

1236:    Not Collective

1238:    Input Parameters:
1239: +  obj - the object to which data is to be attached
1240: .  id - the identifier for the data
1241: -  data - the data to  be attached

1243:    Level: developer

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

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

1250: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1251:           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1252:           `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataGetRealstar()`
1253: M*/
1254: #define PetscObjectComposedDataSetRealstar(obj, id, data) \
1255:   ((PetscErrorCode)((((obj)->realstar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseRealstar(obj)) || ((obj)->realstarcomposeddata[id] = data, (obj)->realstarcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))

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

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

1264:    Not Collective

1266:    Input Parameters:
1267: +  obj - the object from which data is to be retrieved
1268: -  id - the identifier for the data

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

1274:    Level: developer

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

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

1281: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1282:           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1283:           `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`
1284: M*/
1285: #define PetscObjectComposedDataGetRealstar(obj, id, data, flag) \
1286:   ((PetscErrorCode)(((obj)->realstarcomposedstate ? (data = (obj)->realstarcomposeddata[id], flag = (PetscBool)((obj)->realstarcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), PETSC_SUCCESS))

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

1291:    Synopsis:
1292:    #include "petsc/private/petscimpl.h"
1293:    PetscErrorCode PetscObjectComposedDataSetScalar(PetscObject obj, PetscInt id, PetscScalar data)

1295:    Not Collective

1297:    Input Parameters:
1298: +  obj - the object to which data is to be attached
1299: .  id - the identifier for the data
1300: -  data - the data to  be attached, a `PetscScalar`

1302:    Level: developer

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

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

1320:    Synopsis:
1321:    #include "petsc/private/petscimpl.h"
1322:    PetscErrorCode PetscObjectComposedDataGetScalar(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`
1332: -  flag - `PETSC_TRUE` if the data item exists and is valid, `PETSC_FALSE` otherwise

1334:    Level: developer

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

1339: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1340:           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1341:           `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`, `PetscObjectComposedDataSetScalar()`
1342: M*/
1343: #if defined(PETSC_USE_COMPLEX)
1344:   #define PetscObjectComposedDataGetScalar(obj, id, data, flag) \
1345:     ((PetscErrorCode)(((obj)->scalarcomposedstate ? (data = (obj)->scalarcomposeddata[id], flag = (PetscBool)((obj)->scalarcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), PETSC_SUCCESS))
1346: #else
1347:   #define PetscObjectComposedDataGetScalar(obj, id, data, flag) PetscObjectComposedDataGetReal(obj, id, data, flag)
1348: #endif

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

1353:    Synopsis:
1354:    #include "petsc/private/petscimpl.h"
1355:    PetscErrorCode PetscObjectComposedDataSetScalarstar(PetscObject obj, PetscInt id, PetscScalar *data)

1357:    Not Collective

1359:    Input Parameters:
1360: +  obj - the object to which data is to be attached
1361: .  id - the identifier for the data
1362: -  data - the data to  be attached, a `PetscScalar` array

1364:    Level: developer

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

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

1371: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1372:           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1373:           `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`, `PetscObjectComposedDataGetScalarstar()`
1374: M*/
1375: #if defined(PETSC_USE_COMPLEX)
1376:   #define PetscObjectComposedDataSetScalarstar(obj, id, data) \
1377:     ((PetscErrorCode)((((obj)->scalarstar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseScalarstar(obj)) || ((obj)->scalarstarcomposeddata[id] = data, (obj)->scalarstarcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))
1378: #else
1379:   #define PetscObjectComposedDataSetScalarstar(obj, id, data) PetscObjectComposedDataSetRealstar(obj, id, data)
1380: #endif
1381: /*MC
1382:    PetscObjectComposedDataGetScalarstar - retrieve `PetscScalar` array data attached to a `PetscObject` that was set with `PetscObjectComposedDataSetScalarstar()`
1383:    attached to an object

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

1389:    Not Collective

1391:    Input Parameters:
1392: +  obj - the object from which data is to be retrieved
1393: -  id - the identifier for the data

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

1399:    Level: developer

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

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

1406: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1407:           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1408:           `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`, `PetscObjectComposedDataSetScalarstar()`
1409: M*/
1410: #if defined(PETSC_USE_COMPLEX)
1411:   #define PetscObjectComposedDataGetScalarstar(obj, id, data, flag) \
1412:     ((PetscErrorCode)(((obj)->scalarstarcomposedstate ? (data = (obj)->scalarstarcomposeddata[id], flag = (PetscBool)((obj)->scalarstarcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), PETSC_SUCCESS))
1413: #else
1414:   #define PetscObjectComposedDataGetScalarstar(obj, id, data, flag) PetscObjectComposedDataGetRealstar(obj, id, data, flag)
1415: #endif

1417: PETSC_INTERN PetscMPIInt Petsc_Counter_keyval;
1418: PETSC_INTERN PetscMPIInt Petsc_InnerComm_keyval;
1419: PETSC_INTERN PetscMPIInt Petsc_OuterComm_keyval;
1420: PETSC_INTERN PetscMPIInt Petsc_Seq_keyval;
1421: PETSC_INTERN PetscMPIInt Petsc_ShmComm_keyval;
1422: PETSC_EXTERN PetscMPIInt Petsc_CreationIdx_keyval;
1423: PETSC_INTERN PetscMPIInt Petsc_Garbage_HMap_keyval;

1425: PETSC_INTERN PetscMPIInt Petsc_SharedWD_keyval;
1426: PETSC_INTERN PetscMPIInt Petsc_SharedTmp_keyval;

1428: struct PetscCommStash {
1429:   struct PetscCommStash *next;
1430:   MPI_Comm               comm;
1431: };

1433: /*
1434:   PETSc communicators have this attribute, see
1435:   PetscCommDuplicate(), PetscCommDestroy(), PetscCommGetNewTag(), PetscObjectGetName()
1436: */
1437: typedef struct {
1438:   PetscMPIInt            tag;       /* next free tag value */
1439:   PetscInt               refcount;  /* number of references, communicator can be freed when this reaches 0 */
1440:   PetscInt               namecount; /* used to generate the next name, as in Vec_0, Mat_1, ... */
1441:   PetscMPIInt           *iflags;    /* length of comm size, shared by all calls to PetscCommBuildTwoSided_Allreduce/RedScatter on this comm */
1442:   struct PetscCommStash *comms;     /* communicators available for PETSc to pass off to other packages */
1443: } PetscCommCounter;

1445: typedef enum {
1446:   STATE_BEGIN,
1447:   STATE_PENDING,
1448:   STATE_END
1449: } SRState;

1451: typedef enum {
1452:   PETSC_SR_REDUCE_SUM = 0,
1453:   PETSC_SR_REDUCE_MAX = 1,
1454:   PETSC_SR_REDUCE_MIN = 2
1455: } PetscSRReductionType;

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

1476: PETSC_EXTERN PetscErrorCode PetscSplitReductionGet(MPI_Comm, PetscSplitReduction **);
1477: PETSC_EXTERN PetscErrorCode PetscSplitReductionEnd(PetscSplitReduction *);
1478: PETSC_EXTERN PetscErrorCode PetscSplitReductionExtend(PetscSplitReduction *);

1480: #if defined(PETSC_HAVE_THREADSAFETY)
1481:   #if defined(PETSC_HAVE_CONCURRENCYKIT)
1482:     #if defined(__cplusplus)
1483: /*  CK does not have extern "C" protection in their include files */
1484: extern "C" {
1485:     #endif
1486:     #include <ck_spinlock.h>
1487:     #if defined(__cplusplus)
1488: }
1489:     #endif
1490: typedef ck_spinlock_t PetscSpinlock;

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

1525: typedef petsc_atomic_flag PetscSpinlock;

1527: static inline PetscErrorCode PetscSpinlockCreate(PetscSpinlock *spinlock)
1528: {
1529:   petsc_atomic_flag_clear(spinlock);
1530:   return PETSC_SUCCESS;
1531: }
1532: static inline PetscErrorCode PetscSpinlockLock(PetscSpinlock *spinlock)
1533: {
1534:   do {
1535:   } while (petsc_atomic_flag_test_and_set(spinlock));
1536:   return PETSC_SUCCESS;
1537: }
1538: static inline PetscErrorCode PetscSpinlockUnlock(PetscSpinlock *spinlock)
1539: {
1540:   petsc_atomic_flag_clear(spinlock);
1541:   return PETSC_SUCCESS;
1542: }
1543: static inline PetscErrorCode PetscSpinlockDestroy(PETSC_UNUSED PetscSpinlock *spinlock)
1544: {
1545:   return PETSC_SUCCESS;
1546: }
1547:     #undef petsc_atomic_flag_test_and_set
1548:     #undef petsc_atomic_flag_clear
1549:     #undef petsc_atomic_flag

1551:   #elif defined(PETSC_HAVE_OPENMP)

1553:     #include <omp.h>
1554: typedef omp_lock_t PetscSpinlock;

1556: static inline PetscErrorCode PetscSpinlockCreate(PetscSpinlock *omp_lock)
1557: {
1558:   omp_init_lock(omp_lock);
1559:   return PETSC_SUCCESS;
1560: }
1561: static inline PetscErrorCode PetscSpinlockLock(PetscSpinlock *omp_lock)
1562: {
1563:   omp_set_lock(omp_lock);
1564:   return PETSC_SUCCESS;
1565: }
1566: static inline PetscErrorCode PetscSpinlockUnlock(PetscSpinlock *omp_lock)
1567: {
1568:   omp_unset_lock(omp_lock);
1569:   return PETSC_SUCCESS;
1570: }
1571: static inline PetscErrorCode PetscSpinlockDestroy(PetscSpinlock *omp_lock)
1572: {
1573:   omp_destroy_lock(omp_lock);
1574:   return PETSC_SUCCESS;
1575: }
1576:   #else
1577:     #if defined(__cplusplus)
1578:       #error "Thread safety requires either --download-concurrencykit, std::atomic, or --with-openmp"
1579:     #else
1580:       #error "Thread safety requires either --download-concurrencykit, stdatomic.h, or --with-openmp"
1581:     #endif
1582:   #endif

1584: #else
1585: typedef int PetscSpinlock;
1586:   #define PetscSpinlockCreate(a)  PETSC_SUCCESS
1587:   #define PetscSpinlockLock(a)    PETSC_SUCCESS
1588:   #define PetscSpinlockUnlock(a)  PETSC_SUCCESS
1589:   #define PetscSpinlockDestroy(a) PETSC_SUCCESS
1590: #endif

1592: #if defined(PETSC_HAVE_THREADSAFETY)
1593: PETSC_INTERN PetscSpinlock PetscViewerASCIISpinLockOpen;
1594: PETSC_INTERN PetscSpinlock PetscViewerASCIISpinLockStdout;
1595: PETSC_INTERN PetscSpinlock PetscViewerASCIISpinLockStderr;
1596: PETSC_INTERN PetscSpinlock PetscCommSpinLock;
1597: #endif

1599: PETSC_EXTERN PetscLogEvent PETSC_Barrier;
1600: PETSC_EXTERN PetscLogEvent PETSC_BuildTwoSided;
1601: PETSC_EXTERN PetscLogEvent PETSC_BuildTwoSidedF;
1602: PETSC_EXTERN PetscBool     use_gpu_aware_mpi;
1603: PETSC_EXTERN PetscBool     PetscPrintFunctionList;

1605: #if defined(PETSC_HAVE_ADIOS)
1606: PETSC_EXTERN int64_t Petsc_adios_group;
1607: #endif

1609: #if defined(PETSC_HAVE_KOKKOS)
1610: PETSC_INTERN PetscBool      PetscBeganKokkos;
1611: PETSC_EXTERN PetscBool      PetscKokkosInitialized;
1612: PETSC_INTERN PetscErrorCode PetscKokkosIsInitialized_Private(PetscBool *);
1613: PETSC_INTERN PetscErrorCode PetscKokkosFinalize_Private(void);
1614: #endif

1616: #if defined(PETSC_HAVE_OPENMP)
1617: PETSC_EXTERN PetscInt PetscNumOMPThreads;
1618: #endif

1620: struct _n_PetscObjectList {
1621:   char            name[256];
1622:   PetscBool       skipdereference; /* when the PetscObjectList is destroyed do not call PetscObjectDereference() on this object */
1623:   PetscObject     obj;
1624:   PetscObjectList next;
1625: };