Date: 2025-03-28T21:10:42+00:00

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, 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 \
    453:           { \
    454:             return PETSC_TYPE; \
    455:           } \
    456:           PETSC_NODISCARD static constexpr const char *string() noexcept \
    457:           { \
    458:             return PetscStringize(T); \
    459:           } \
    460:         }; \
    461:         template <> \
    462:         struct PetscAssertPointerImpl<const T *> : PetscAssertPointerImpl<T *> { }; \
    463:         template <> \
    464:         struct PetscAssertPointerImpl<volatile T *> : PetscAssertPointerImpl<T *> { }; \
    465:         template <> \
    466:         struct PetscAssertPointerImpl<const volatile T *> : PetscAssertPointerImpl<T *> { }

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

    484:       #undef PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION

    486: } // namespace util

    488: } // namespace Petsc

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

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

    496:       #if PetscDefined(HAVE_COMPLEX)
    497:         #define PETSC_GENERIC_CV_COMPLEX(result) PETSC_GENERIC_CV(PetscComplex, result)
    498:       #else
    499:         #define PETSC_GENERIC_CV_COMPLEX(result)
    500:       #endif

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

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

    520:       #if PetscDefined(HAVE_COMPLEX)
    521:         #define PETSC_GENERIC_CV_STRINGIZE_COMPLEX PETSC_GENERIC_CV_STRINGIZE(PetscComplex)
    522:       #else
    523:         #define PETSC_GENERIC_CV_STRINGIZE_COMPLEX
    524:       #endif

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

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

    591: #if !defined(PETSC_CLANG_STATIC_ANALYZER)
    592:   #if !defined(PETSC_USE_DEBUG)

    594:     #define PetscCheckSameType(a, arga, b, argb) \
    595:       do { \
    596:         (void)(a); \
    597:         (void)(b); \
    598:       } while (0)
    599:     #define PetscCheckTypeName(a, type) \
    600:       do { \
    601:         (void)(a); \
    602:       } while (0)
    603:     #define PetscCheckTypeNames(a, type1, type2) \
    604:       do { \
    605:         (void)(a); \
    606:       } while (0)
    608:       do { \
    609:         (void)(a); \
    610:       } while (0)
    611:     #define PetscCheckSameComm(a, arga, b, argb) \
    612:       do { \
    613:         (void)(a); \
    614:         (void)(b); \
    615:       } while (0)
    616:     #define PetscCheckSameTypeAndComm(a, arga, b, argb) \
    617:       do { \
    618:         (void)(a); \
    619:         (void)(b); \
    620:       } while (0)
    622:       do { \
    623:         (void)(a); \
    624:         (void)(b); \
    625:       } while (0)
    627:       do { \
    628:         (void)(a); \
    629:         (void)(b); \
    630:       } while (0)
    632:       do { \
    633:         (void)(a); \
    634:         (void)(b); \
    635:       } while (0)
    637:       do { \
    638:         (void)(a); \
    639:         (void)(b); \
    640:       } while (0)
    642:       do { \
    643:         (void)(a); \
    644:         (void)(b); \
    645:       } while (0)
    647:       do { \
    648:         (void)(a); \
    649:         (void)(b); \
    650:       } while (0)
    652:       do { \
    653:         (void)(a); \
    654:         (void)(b); \
    655:       } while (0)
    656:     #define PetscCheckSorted(n, idx) \
    657:       do { \
    658:         (void)(n); \
    659:         (void)(idx); \
    660:       } while (0)

    662:   #else

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

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

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

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

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

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

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

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

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

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

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

    767:       do { \
    768:         PetscCount b0 = (b), b1[2], b2[2]; \
    769:         b1[0]         = -b0; \
    770:         b1[1]         = b0; \
    771:         PetscCallMPI(MPIU_Allreduce(b1, b2, 2, MPIU_COUNT, MPI_MAX, PetscObjectComm((PetscObject)(a)))); \
    772:         PetscCheck(-b2[0] == b2[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:         PetscMPIInt b0 = (b), b1[2], b2[2]; \
    778:         b1[0]          = -b0; \
    779:         b1[1]          = b0; \
    780:         PetscCallMPI(MPIU_Allreduce(b1, b2, 2, MPI_INT, MPI_MAX, PetscObjectComm((PetscObject)(a)))); \
    781:         PetscCheck(-b2[0] == b2[1], PetscObjectComm((PetscObject)(a)), PETSC_ERR_ARG_WRONG, "PetscMPIInt value must be same on all processes, argument # %d", arg); \
    782:       } while (0)

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

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

    802:     #define PetscCheckSorted(n, idx) \
    803:       do { \
    804:         PetscBool _1_flg; \
    805:         PetscSorted(n, idx, _1_flg); \
    806:         PetscCheck(_1_flg, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Input array needs to be sorted"); \
    807:       } while (0)

    809:   #endif
    810: #else  /* PETSC_CLANG_STATIC_ANALYZER */
    811: template <typename Ta, typename Tb>
    812: extern void PetscCheckSameType(Ta, int, Tb, int);
    813: template <typename Ta, typename Tb>
    814: extern void PetscCheckTypeName(Ta, Tb);
    815: template <typename Ta, typename Tb, typename Tc>
    816: extern void PetscCheckTypeNames(Ta, Tb, Tc);
    817: template <typename T>
    819: template <typename Ta, typename Tb>
    820: extern void PetscCheckSameComm(Ta, int, Tb, int);
    821: template <typename Ta, typename Tb>
    822: extern void PetscCheckSameTypeAndComm(Ta, int, Tb, int);
    823: template <typename Ta, typename Tb>
    825: template <typename Ta, typename Tb>
    827: template <typename Ta, typename Tb>
    829: template <typename Ta, typename Tb>
    831: template <typename Ta, typename Tb>
    833: template <typename Ta, typename Tb>
    835: template <typename Ta, typename Tb>
    837: template <typename T>
    838: extern void PetscCheckSorted(PetscInt, T);
    839: #endif /* PETSC_CLANG_STATIC_ANALYZER */

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

    844:   Synopsis:
    845:    #include "petsc/private/petscimpl.h"
    846:    PetscTryMethod(PetscObject obj, const char *name, (arg_types), (arg_value))

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

    854:    Level: developer

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

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

    862: .seealso: `PetscUseMethod()`, `PetscCall()`, `PetscUseTypeMethod()`, `PetscTryTypeMethod()`, `PetscCheck()`, `PetscObject`
    863: M*/
    864: #define PetscTryMethod(obj, A, B, C) \
    865:   do { \
    866:     PetscErrorCode(*_7_f) B; \
    867:     PetscCall(PetscObjectQueryFunction((PetscObject)(obj), A, &_7_f)); \
    868:     if (_7_f) PetscCall((*_7_f)C); \
    869:   } while (0)

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

    874:   Synopsis:
    875:    #include "petsc/private/petscimpl.h"
    876:    PetscUseMethod(PetscObject obj, const char *name, (arg_types), (arg_value))

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

    884:    Level: developer

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

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

    892: .seealso: `PetscTryMethod()`, `PetscCall()`, `PetscUseTypeMethod()`, `PetscTryTypeMethod()`, `PetscCheck()`, `PetscObject`
    893: M*/
    894: #define PetscUseMethod(obj, A, B, C) \
    895:   do { \
    896:     PetscErrorCode(*_7_f) B; \
    897:     PetscCall(PetscObjectQueryFunction((PetscObject)(obj), A, &_7_f)); \
    898:     PetscCheck(_7_f, PetscObjectComm((PetscObject)(obj)), PETSC_ERR_SUP, "Cannot locate function %s in object", A); \
    899:     PetscCall((*_7_f)C); \
    900:   } while (0)

    902: /*
    903:   Use Microsoft traditional preprocessor.

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

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

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

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

    916:   #define PetscUseTypeMethod(obj, OP, ...) \
    917:     do { \
    918:       PetscErrorCode ierr_p_; \
    919:       PetscStackUpdateLine; \
    920:       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); \
    921:       ierr_p_ = (*(obj)->ops->OP)(obj, __VA_ARGS__); \
    922:       PetscCall(ierr_p_); \
    923:     } while (0)

    925:   #define PetscTryTypeMethod(obj, OP, ...) \
    926:     do { \
    927:       if ((obj)->ops->OP) { \
    928:         PetscErrorCode ierr_p_; \
    929:         PetscStackUpdateLine; \
    930:         ierr_p_ = (*(obj)->ops->OP)(obj, __VA_ARGS__); \
    931:         PetscCall(ierr_p_); \
    932:       } \
    933:     } while (0)

    935: #else

    937:   /*MC
    938:    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

    940:   Synopsis:
    941:    #include "petsc/private/petscimpl.h"
    942:    PetscUseTypeMethod(obj, method, other_args)

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

    949:    Level: developer

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

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

    956: .seealso: `PetscTryMethod()`, `PetscUseMethod()`, `PetscCall()`, `PetscCheck()`, `PetscTryTypeMethod()`, `PetscCallBack()`
    957: M*/
    958:   #define PetscUseTypeMethod(obj, ...) \
    959:     do { \
    960:       PetscCheck((obj)->ops->PETSC_FIRST_ARG((__VA_ARGS__, unused)), PetscObjectComm((PetscObject)obj), PETSC_ERR_SUP, "No method %s for %s of type %s", \
    961:                  PetscStringize(PETSC_FIRST_ARG((__VA_ARGS__,unused))), ((PetscObject)obj)->class_name, ((PetscObject)obj)->type_name); \
    962:       PetscCall((*(obj)->ops->PETSC_FIRST_ARG((__VA_ARGS__, unused)))(obj PETSC_REST_ARG(__VA_ARGS__))); \
    963:     } while (0)

    965:   /*MC
    966:    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

    968:   Synopsis:
    969:    #include "petsc/private/petscimpl.h"
    970:    PetscTryTypeMethod(obj, method, other_args)

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

    977:    Level: developer

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

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

    984: .seealso: `PetscTryMethod()`, `PetscUseMethod()`, `PetscCall()`, `PetscCheck()`, `PetscUseTypeMethod()`
    985: M*/
    986:   #define PetscTryTypeMethod(obj, ...) \
    987:     do { \
    988:       if ((obj)->ops->PETSC_FIRST_ARG((__VA_ARGS__, unused))) PetscCall((*(obj)->ops->PETSC_FIRST_ARG((__VA_ARGS__, unused)))(obj PETSC_REST_ARG(__VA_ARGS__))); \
    989:     } while (0)

    991: #endif

    993: /*MC
    994:    PetscObjectStateIncrease - Increases the state of any `PetscObject`

    996:    Synopsis:
    997:    #include "petsc/private/petscimpl.h"
    998:    PetscErrorCode PetscObjectStateIncrease(PetscObject obj)

    1000:    Logically Collective

    1002:    Input Parameter:
    1003: .  obj - any PETSc object, for example a `Vec`, `Mat` or `KSP`. This must be
    1004:          cast with a (PetscObject), for example,
    1005:          `PetscObjectStateIncrease`((`PetscObject`)mat);

    1007:    Level: developer

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

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

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

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

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

    1026: .seealso: `PetscObjectStateGet()`, `PetscObject`
    1027: M*/
    1028: #define PetscObjectStateIncrease(obj) ((obj)->state++, PETSC_SUCCESS)

    1030: PETSC_EXTERN PetscErrorCode PetscObjectStateGet(PetscObject, PetscObjectState *);
    1031: PETSC_EXTERN PetscErrorCode PetscObjectStateSet(PetscObject, PetscObjectState);
    1032: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataRegister(PetscInt *);
    1033: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseInt(PetscObject);
    1034: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseIntstar(PetscObject);
    1035: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseReal(PetscObject);
    1036: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseRealstar(PetscObject);
    1037: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseScalar(PetscObject);
    1038: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseScalarstar(PetscObject);
    1039: PETSC_EXTERN PetscInt       PetscObjectComposedDataMax;

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

    1044:    Synopsis:
    1045:    #include "petsc/private/petscimpl.h"
    1046:    PetscErrorCode PetscObjectComposedDataSetInt(PetscObject obj, PetscInt id, PetscInt data)

    1048:    Not Collective

    1050:    Input Parameters:
    1051: +  obj - the object to which data is to be attached
    1052: .  id - the identifier for the data
    1053: -  data - the data to  be attached, a `PetscInt`

    1055:    Level: developer

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

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

    1063: .seealso: `PetscObjectComposedDataGetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetReal()`,
    1064:           `PetscObjectComposedDataGetIntstar()`, `PetscObjectComposedDataSetIntstar()`, `PetscObject`,
    1065:           `PetscObjectCompose()`, `PetscObjectQuery()`
    1066: M*/
    1067: #define PetscObjectComposedDataSetInt(obj, id, data) \
    1068:   ((PetscErrorCode)((((obj)->int_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseInt(obj)) || ((obj)->intcomposeddata[id] = data, (obj)->intcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))

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

    1073:    Synopsis:
    1074:    #include "petsc/private/petscimpl.h"
    1075:    PetscErrorCode PetscObjectComposedDataGetInt(PetscObject obj, PetscInt id, PetscInt data, PetscBool flag)

    1077:    Not Collective

    1079:    Input Parameters:
    1080: +  obj - the object from which data is to be retrieved
    1081: -  id - the identifier for the data

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

    1087:    Level: developer

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

    1092: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetReal()`,
    1093:           `PetscObjectComposedDataGetIntstar()`, `PetscObjectComposedDataSetIntstar()`, `PetscObject`,
    1094:           `PetscObjectCompose()`, `PetscObjectQuery()`
    1095: M*/
    1096: #define PetscObjectComposedDataGetInt(obj, id, data, flag) (((obj)->intcomposedstate ? (data = (obj)->intcomposeddata[id], flag = (PetscBool)((obj)->intcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), PETSC_SUCCESS)

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

    1101:    Synopsis:
    1102:    #include "petsc/private/petscimpl.h"
    1103:    PetscErrorCode PetscObjectComposedDataSetIntstar(PetscObject obj, PetscInt id, PetscInt *data)

    1105:    Not Collective

    1107:    Input Parameters:
    1108: +  obj - the object to which data is to be attached
    1109: .  id - the identifier for the data
    1110: -  data - the data to  be attached, a `PetscInt` array

    1112:    Level: developer

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

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

    1119: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetReal()`,
    1120:           `PetscObjectComposedDataGetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
    1121:           `PetscObjectCompose()`, `PetscObjectQuery()`
    1122: M*/
    1123: #define PetscObjectComposedDataSetIntstar(obj, id, data) \
    1124:   ((PetscErrorCode)((((obj)->intstar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseIntstar(obj)) || ((obj)->intstarcomposeddata[id] = data, (obj)->intstarcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))

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

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

    1133:    Not Collective

    1135:    Input Parameters:
    1136: +  obj - the object from which data is to be retrieved
    1137: -  id - the identifier for the data

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

    1143:    Level: developer

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

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

    1150: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetReal()`,
    1151:           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
    1152:           `PetscObjectCompose()`, `PetscObjectQuery()`
    1153: M*/
    1154: #define PetscObjectComposedDataGetIntstar(obj, id, data, flag) \
    1155:   ((PetscErrorCode)(((obj)->intstarcomposedstate ? (data = (obj)->intstarcomposeddata[id], flag = (PetscBool)((obj)->intstarcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), PETSC_SUCCESS))

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

    1160:    Synopsis:
    1161:    #include "petsc/private/petscimpl.h"
    1162:    PetscErrorCode PetscObjectComposedDataSetReal(PetscObject obj, PetscInt id, PetscReal data)

    1164:    Not Collective

    1166:    Input Parameters:
    1167: +  obj - the object to which data is to be attached
    1168: .  id - the identifier for the data
    1169: -  data - the data to  be attached, a `PetscReal`

    1171:    Level: developer

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

    1176: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
    1177:           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
    1178:           `PetscObjectCompose()`, `PetscObjectQuery()`
    1179: M*/
    1180: #define PetscObjectComposedDataSetReal(obj, id, data) \
    1181:   ((PetscErrorCode)((((obj)->real_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseReal(obj)) || ((obj)->realcomposeddata[id] = data, (obj)->realcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))

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

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

    1190:    Not Collective

    1192:    Input Parameters:
    1193: +  obj - the object from which data is to be retrieved
    1194: -  id - the identifier for the data

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

    1200:    Level: developer

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

    1205: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataSetIntstar()`,
    1206:           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
    1207:           `PetscObjectCompose()`, `PetscObjectQuery()`
    1208: M*/
    1209: #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))

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

    1214:    Synopsis:
    1215:    #include "petsc/private/petscimpl.h"
    1216:    PetscErrorCode PetscObjectComposedDataSetRealstar(PetscObject obj, PetscInt id, PetscReal *data)

    1218:    Not Collective

    1220:    Input Parameters:
    1221: +  obj - the object to which data is to be attached
    1222: .  id - the identifier for the data
    1223: -  data - the data to  be attached

    1225:    Level: developer

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

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

    1232: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
    1233:           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
    1234:           `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataGetRealstar()`
    1235: M*/
    1236: #define PetscObjectComposedDataSetRealstar(obj, id, data) \
    1237:   ((PetscErrorCode)((((obj)->realstar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseRealstar(obj)) || ((obj)->realstarcomposeddata[id] = data, (obj)->realstarcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))

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

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

    1246:    Not Collective

    1248:    Input Parameters:
    1249: +  obj - the object from which data is to be retrieved
    1250: -  id - the identifier for the data

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

    1256:    Level: developer

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

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

    1263: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
    1264:           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
    1265:           `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`
    1266: M*/
    1267: #define PetscObjectComposedDataGetRealstar(obj, id, data, flag) \
    1268:   ((PetscErrorCode)(((obj)->realstarcomposedstate ? (data = (obj)->realstarcomposeddata[id], flag = (PetscBool)((obj)->realstarcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), PETSC_SUCCESS))

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

    1273:    Synopsis:
    1274:    #include "petsc/private/petscimpl.h"
    1275:    PetscErrorCode PetscObjectComposedDataSetScalar(PetscObject obj, PetscInt id, PetscScalar data)

    1277:    Not Collective

    1279:    Input Parameters:
    1280: +  obj - the object to which data is to be attached
    1281: .  id - the identifier for the data
    1282: -  data - the data to  be attached, a `PetscScalar`

    1284:    Level: developer

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

    1289: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
    1290:           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
    1291:           `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`, `PetscObjectComposedDataGetScalar()`
    1292: M*/
    1293: #if defined(PETSC_USE_COMPLEX)
    1294:   #define PetscObjectComposedDataSetScalar(obj, id, data) \
    1295:     ((PetscErrorCode)((((obj)->scalar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseScalar(obj)) || ((obj)->scalarcomposeddata[id] = data, (obj)->scalarcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))
    1296: #else
    1297:   #define PetscObjectComposedDataSetScalar(obj, id, data) PetscObjectComposedDataSetReal(obj, id, data)
    1298: #endif
    1299: /*MC
    1300:    PetscObjectComposedDataGetScalar - retrieve `PetscScalar` data attached to a `PetscObject` that was set with `PetscObjectComposedDataSetScalar()`

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

    1306:    Not Collective

    1308:    Input Parameters:
    1309: +  obj - the object from which data is to be retrieved
    1310: -  id - the identifier for the data

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

    1316:    Level: developer

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

    1321: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
    1322:           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
    1323:           `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`, `PetscObjectComposedDataSetScalar()`
    1324: M*/
    1325: #if defined(PETSC_USE_COMPLEX)
    1326:   #define PetscObjectComposedDataGetScalar(obj, id, data, flag) \
    1327:     ((PetscErrorCode)(((obj)->scalarcomposedstate ? (data = (obj)->scalarcomposeddata[id], flag = (PetscBool)((obj)->scalarcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), PETSC_SUCCESS))
    1328: #else
    1329:   #define PetscObjectComposedDataGetScalar(obj, id, data, flag) PetscObjectComposedDataGetReal(obj, id, data, flag)
    1330: #endif

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

    1335:    Synopsis:
    1336:    #include "petsc/private/petscimpl.h"
    1337:    PetscErrorCode PetscObjectComposedDataSetScalarstar(PetscObject obj, PetscInt id, PetscScalar *data)

    1339:    Not Collective

    1341:    Input Parameters:
    1342: +  obj - the object to which data is to be attached
    1343: .  id - the identifier for the data
    1344: -  data - the data to  be attached, a `PetscScalar` array

    1346:    Level: developer

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

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

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

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

    1371:    Not Collective

    1373:    Input Parameters:
    1374: +  obj - the object from which data is to be retrieved
    1375: -  id - the identifier for the data

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

    1381:    Level: developer

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

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

    1388: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
    1389:           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
    1390:           `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`, `PetscObjectComposedDataSetScalarstar()`
    1391: M*/
    1392: #if defined(PETSC_USE_COMPLEX)
    1393:   #define PetscObjectComposedDataGetScalarstar(obj, id, data, flag) \
    1394:     ((PetscErrorCode)(((obj)->scalarstarcomposedstate ? (data = (obj)->scalarstarcomposeddata[id], flag = (PetscBool)((obj)->scalarstarcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), PETSC_SUCCESS))
    1395: #else
    1396:   #define PetscObjectComposedDataGetScalarstar(obj, id, data, flag) PetscObjectComposedDataGetRealstar(obj, id, data, flag)
    1397: #endif

    1399: PETSC_EXTERN PetscMPIInt Petsc_Counter_keyval;
    1400: PETSC_EXTERN PetscMPIInt Petsc_InnerComm_keyval;
    1401: PETSC_EXTERN PetscMPIInt Petsc_OuterComm_keyval;
    1402: PETSC_EXTERN PetscMPIInt Petsc_Seq_keyval;
    1403: PETSC_EXTERN PetscMPIInt Petsc_ShmComm_keyval;
    1404: PETSC_EXTERN PetscMPIInt Petsc_CreationIdx_keyval;
    1405: PETSC_EXTERN PetscMPIInt Petsc_Garbage_HMap_keyval;

    1407: PETSC_EXTERN PetscMPIInt Petsc_SharedWD_keyval;
    1408: PETSC_EXTERN PetscMPIInt Petsc_SharedTmp_keyval;

    1410: struct PetscCommStash {
    1411:   struct PetscCommStash *next;
    1412:   MPI_Comm               comm;
    1413: };

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

    1427: typedef enum {
    1428:   STATE_BEGIN,
    1429:   STATE_PENDING,
    1430:   STATE_END
    1431: } SRState;

    1433: typedef enum {
    1434:   PETSC_SR_REDUCE_SUM = 0,
    1435:   PETSC_SR_REDUCE_MAX = 1,
    1436:   PETSC_SR_REDUCE_MIN = 2
    1437: } PetscSRReductionType;

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

    1458: PETSC_EXTERN PetscErrorCode PetscSplitReductionGet(MPI_Comm, PetscSplitReduction **);
    1459: PETSC_EXTERN PetscErrorCode PetscSplitReductionEnd(PetscSplitReduction *);
    1460: PETSC_EXTERN PetscErrorCode PetscSplitReductionExtend(PetscSplitReduction *);

    1462: #if defined(PETSC_HAVE_THREADSAFETY)
    1463:   #if defined(PETSC_HAVE_CONCURRENCYKIT)
    1464:     #if defined(__cplusplus)
    1465: /*  CK does not have extern "C" protection in their include files */
    1466: extern "C" {
    1467:     #endif
    1468:     #include <ck_spinlock.h>
    1469:     #if defined(__cplusplus)
    1470: }
    1471:     #endif
    1472: typedef ck_spinlock_t PetscSpinlock;

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

    1507: typedef petsc_atomic_flag PetscSpinlock;

    1509: static inline PetscErrorCode PetscSpinlockCreate(PetscSpinlock *spinlock)
    1510: {
    1511:   petsc_atomic_flag_clear(spinlock);
    1512:   return PETSC_SUCCESS;
    1513: }
    1514: static inline PetscErrorCode PetscSpinlockLock(PetscSpinlock *spinlock)
    1515: {
    1516:   do {
    1517:   } while (petsc_atomic_flag_test_and_set(spinlock));
    1518:   return PETSC_SUCCESS;
    1519: }
    1520: static inline PetscErrorCode PetscSpinlockUnlock(PetscSpinlock *spinlock)
    1521: {
    1522:   petsc_atomic_flag_clear(spinlock);
    1523:   return PETSC_SUCCESS;
    1524: }
    1525: static inline PetscErrorCode PetscSpinlockDestroy(PETSC_UNUSED PetscSpinlock *spinlock)
    1526: {
    1527:   return PETSC_SUCCESS;
    1528: }
    1529:     #undef petsc_atomic_flag_test_and_set
    1530:     #undef petsc_atomic_flag_clear
    1531:     #undef petsc_atomic_flag

    1533:   #elif defined(PETSC_HAVE_OPENMP)

    1535:     #include <omp.h>
    1536: typedef omp_lock_t PetscSpinlock;

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

    1566: #else
    1567: typedef int PetscSpinlock;
    1568:   #define PetscSpinlockCreate(a)  PETSC_SUCCESS
    1569:   #define PetscSpinlockLock(a)    PETSC_SUCCESS
    1570:   #define PetscSpinlockUnlock(a)  PETSC_SUCCESS
    1571:   #define PetscSpinlockDestroy(a) PETSC_SUCCESS
    1572: #endif

    1574: #if defined(PETSC_HAVE_THREADSAFETY)
    1575: PETSC_INTERN PetscSpinlock PetscViewerASCIISpinLockOpen;
    1576: PETSC_INTERN PetscSpinlock PetscViewerASCIISpinLockStdout;
    1577: PETSC_INTERN PetscSpinlock PetscViewerASCIISpinLockStderr;
    1578: PETSC_INTERN PetscSpinlock PetscCommSpinLock;
    1579: #endif

    1581: PETSC_EXTERN PetscLogEvent PETSC_Barrier;
    1582: PETSC_EXTERN PetscLogEvent PETSC_BuildTwoSided;
    1583: PETSC_EXTERN PetscLogEvent PETSC_BuildTwoSidedF;
    1584: PETSC_EXTERN PetscBool     use_gpu_aware_mpi;
    1585: PETSC_EXTERN PetscBool     PetscPrintFunctionList;

    1587: #if defined(PETSC_HAVE_ADIOS)
    1588: PETSC_EXTERN int64_t Petsc_adios_group;
    1589: #endif

    1591: #if defined(PETSC_HAVE_KOKKOS)
    1592: PETSC_INTERN PetscBool      PetscBeganKokkos;
    1593: PETSC_EXTERN PetscBool      PetscKokkosInitialized;
    1594: PETSC_INTERN PetscErrorCode PetscKokkosIsInitialized_Private(PetscBool *);
    1595: PETSC_INTERN PetscErrorCode PetscKokkosFinalize_Private(void);
    1596: #endif

    1598: #if defined(PETSC_HAVE_OPENMP)
    1599: PETSC_EXTERN PetscInt PetscNumOMPThreads;
    1600: #endif

    1602: struct _n_PetscObjectList {
    1603:   char            name[256];
    1604:   PetscBool       skipdereference; /* when the PetscObjectList is destroyed do not call PetscObjectDereference() on this object */
    1605:   PetscObject     obj;
    1606:   PetscObjectList next;
    1607: };