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_EXTERN 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: /*E
     58:    PetscFortranCallbackType  - Indicates if a Fortran callback stored in a `PetscObject` is associated with the class or the current particular type of the object

     60:   Values:
     61: + `PETSC_FORTRAN_CALLBACK_CLASS`   - the callback is associated with the class
     62: - `PETSC_FORTRAN_CALLBACK_SUBTYPE` - the callback is associated with the current particular subtype

     64:   Level: developer

     66:   Developer Note:
     67:   The two sets of callbacks are stored in different arrays in the `PetscObject` because the `PETSC_FORTRAN_CALLBACK_SUBTYPE` callbacks must
     68:   be removed whenever the type of the object is changed (because they are not appropriate for other types). The removal is done in
     69:   `PetscObjectChangeTypeName()`.

     71: .seealso: `PetscFortranCallbackFn`, `PetscObjectSetFortranCallback()`, `PetscObjectGetFortranCallback()`, `PetscObjectChangeTypeName()`
     72: E*/
     73: typedef enum {
     74:   PETSC_FORTRAN_CALLBACK_CLASS,
     75:   PETSC_FORTRAN_CALLBACK_SUBTYPE,
     76:   PETSC_FORTRAN_CALLBACK_MAXTYPE
     77: } PetscFortranCallbackType;

     79: typedef size_t PetscFortranCallbackId;
     80: #define PETSC_SMALLEST_FORTRAN_CALLBACK ((PetscFortranCallbackId)1000)
     81: PETSC_EXTERN PetscErrorCode PetscFortranCallbackRegister(PetscClassId, const char *, PetscFortranCallbackId *);
     82: PETSC_EXTERN PetscErrorCode PetscFortranCallbackGetSizes(PetscClassId, PetscFortranCallbackId *, PetscFortranCallbackId *);

     84: /*S
     85:   PetscFortranCallbackFn - A prototype of a Fortran function provided as a callback

     87:   Level: advanced

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

     92: .seealso: `PetscVoidFn`, `PetscErrorCodeFn`
     93: S*/
     94: PETSC_EXTERN_TYPEDEF typedef void(PetscFortranCallbackFn)(void);

     96: typedef struct {
     97:   PetscFortranCallbackFn *func;
     98:   void                   *ctx;
     99: } PetscFortranCallback;

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

    146:   PetscInt noptionhandler;
    147:   PetscErrorCode (*optionhandler[PETSC_MAX_OPTIONS_HANDLER])(PetscObject, PetscOptionItems, PetscCtx);
    148:   PetscErrorCode (*optiondestroy[PETSC_MAX_OPTIONS_HANDLER])(PetscObject, PetscCtxRt);
    149:   void *optionctx[PETSC_MAX_OPTIONS_HANDLER];
    150: #if defined(PETSC_HAVE_SAWS)
    151:   PetscBool amsmem;          /* if PETSC_TRUE then this object is registered with SAWs and visible to clients */
    152:   PetscBool amspublishblock; /* if PETSC_TRUE and publishing objects then will block at PetscObjectSAWsBlock() */
    153: #endif
    154:   PetscOptions options; /* options database used, NULL means default */
    155:   PetscBool    optionsprinted;
    156:   PetscBool    donotPetscObjectPrintClassNamePrefixType;
    157: } _p_PetscObject;

    159: #define PETSCHEADER(ObjectOps) \
    160:   _p_PetscObject hdr; \
    161:   ObjectOps      ops[1]

    163: #define PETSCFREEDHEADER -1

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

    168:   Calling Sequence:
    169: . obj - the `PetscObject` to destroy

    171:   Level: beginner

    173:   Note:
    174:   The deprecated `PetscObjectDestroyFunction` works as a replacement for `PetscObjectDestroyFn` *.

    176: .seealso: `PetscObject`, `PetscObjectDestroy()`
    177: S*/
    178: PETSC_EXTERN_TYPEDEF typedef PetscErrorCode PetscObjectDestroyFn(PetscObject *obj);

    180: PETSC_EXTERN_TYPEDEF typedef PetscObjectDestroyFn *PetscObjectDestroyFunction;

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

    185:   Calling Sequence:
    186: + obj - the `PetscObject` to view
    187: - v - the viewer

    189:   Level: beginner

    191:   Note:
    192:   The deprecated `PetscObjectViewFunction` works as a replacement for `PetscObjectViewFn` *.

    194: .seealso: `PetscObject`, `PetscObjectDestroy()`, `PetscViewer`, `PetscObjectView()`
    195: S*/
    196: PETSC_EXTERN_TYPEDEF typedef PetscErrorCode PetscObjectViewFn(PetscObject obj, PetscViewer v);

    198: PETSC_EXTERN_TYPEDEF typedef PetscObjectViewFn *PetscObjectViewFunction;

    200: /*MC
    201:     PetscHeaderCreate - Creates a raw PETSc object of a particular class

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

    207:   Collective

    209:   Input Parameters:
    210: + classid    - The classid associated with this object (for example `VEC_CLASSID`)
    211: . class_name - String name of class; should be static (for example "Vec"), may be `PETSC_NULLPTR`
    212: . descr      - String containing short description; should be static (for example "Vector"), may be `PETSC_NULLPTR`
    213: . mansec     - String indicating section in manual pages; should be static (for example "Vec"), may be `PETSC_NULLPTR`
    214: . comm       - The MPI Communicator
    215: . destroy    - The destroy routine for this object (for example `VecDestroy()`)
    216: - view       - The view routine for this object (for example `VecView()`), may be `PETSC_NULLPTR`

    218:   Output Parameter:
    219: . h - The newly created `PetscObject`

    221:   Level: developer

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

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

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

    236:   Example Usage:
    237:   Existing `PetscObject`s may be easily created as shown. An object of type `Name` has
    238:   `destroy` and `view` functions named `NameDestroy()` and `NameView()`.
    239: .vb
    240:   Vec v;

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

    245:   It is possible to create custom `PetscObject`s, note however that they must abide by the
    246:   restrictions set forth above.
    247: .vb
    248:   // OK, first member of C structure is _p_PetscObject
    249:   struct MyCPetscObject_s
    250:   {
    251:     _p_PetscObject header;
    252:     int            some_data;
    253:   };
    254:   typedef struct *MyCPetscObject_s MyCPetscObject;

    256:   PetscErrorCode MyObjectDestroy(MyObject *);
    257:   PetscErrorCode MyObjectView(MyObject);

    259:   MyCPetscObject obj;

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

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

    267:   // ERROR must be a single-level pointer
    268:   PetscHeaderCreate(&obj, ...);
    269: .ve

    271:   Illustrating proper construction from C++\:
    272: .vb
    273:   // ERROR, class is not standard layout, first member must be publicly accessible
    274:   class BadCppPetscObject
    275:   {
    276:     _p_PetscObject header;
    277:   };

    279:   // ERROR, class is not standard layout, has a virtual function and virtual inheritance
    280:   class BadCppPetscObject2 : virtual BaseClass
    281:   {
    282:   public:
    283:     _p_PetscObject header;

    285:     virtual void foo();
    286:   };

    288:   // ERROR, class is not standard layout! Has non-standard layout member
    289:   class BadCppPetscObject2
    290:   {
    291:   public:
    292:     _p_PetscObject    header;
    293:     BadCppPetscObject non_standard_layout;
    294:   };

    296:   // OK, class is standard layout!
    297:   class GoodCppPetscObject;
    298:   using MyCppObject = GoodCppPetscObject *;

    300:   // OK, non-virtual inheritance of other standard layout class does not affect layout
    301:   class GoodCppPetscObject : StandardLayoutClass
    302:   {
    303:   public:
    304:     // OK, non standard layout member is static, does not affect layout
    305:     static BadCppPetscObject non_standard_layout;

    307:     // OK, first non-static member is _p_PetscObject
    308:     _p_PetscObject header;

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

    313:     // OK, may use "member" functions for destroy and view so long as they are static
    314:     static PetscErrorCode destroy(MyCppObject *);
    315:     static PetscErrorCode view(MyCppObject);
    316:   };

    318:   // OK, usage via pointer
    319:   MyObject obj;

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

    324: .seealso: `PetscObject`, `PetscHeaderDestroy()`, `PetscClassIdRegister()`
    325: M*/
    326: #define PetscHeaderCreate(h, classid, class_name, descr, mansec, comm, destroy, view) \
    327:   PetscHeaderCreate_Function(PetscNew(&(h)), (PetscObject *)&(h), (classid), (class_name), (descr), (mansec), (comm), (PetscObjectDestroyFn *)(destroy), (PetscObjectViewFn *)(view))

    329: PETSC_EXTERN PetscErrorCode PetscHeaderCreate_Function(PetscErrorCode, PetscObject *, PetscClassId, const char[], const char[], const char[], MPI_Comm, PetscObjectDestroyFn *, PetscObjectViewFn *);
    330: PETSC_EXTERN PetscErrorCode PetscHeaderCreate_Private(PetscObject, PetscClassId, const char[], const char[], const char[], MPI_Comm, PetscObjectDestroyFn *, PetscObjectViewFn *);
    331: PETSC_EXTERN PetscErrorCode PetscHeaderDestroy_Function(PetscObject *);
    332: PETSC_EXTERN PetscErrorCode PetscComposedQuantitiesDestroy(PetscObject obj);
    333: PETSC_INTERN PetscObjectId  PetscObjectNewId_Internal(void);

    335: /*MC
    336:   PetscHeaderDestroy - Final step in destroying a `PetscObject`

    338:   Synopsis:
    339: #include <petsc/private/petscimpl.h>
    340:   PetscErrorCode PetscHeaderDestroy(PetscObject *obj)

    342:   Collective

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

    347:   Level: developer

    349:   Notes:
    350:   `h` is freed and set to `PETSC_NULLPTR` when this routine returns.

    352:   Example Usage:
    353: .vb
    354:   PetscObject obj;

    356:   PetscHeaderCreate(obj, ...);
    357:   // use obj...

    359:   // note pointer to obj is used
    360:   PetscHeaderDestroy(&obj);
    361: .ve

    363:   Note that this routine is the _last_ step when destroying higher-level `PetscObject`s as it
    364:   deallocates the memory for the structure itself\:
    365: .vb
    366:   typedef struct MyPetscObject_s *MyPetscObject;
    367:   struct MyPetscObject_s
    368:   {
    369:     _p_PetscObject  hdr;
    370:     PetscInt       *foo;
    371:     PetscScalar    *bar;
    372:   };

    374:   // assume obj is created/initialized elsewhere...
    375:   MyPetscObject obj;

    377:   // OK, should dispose of all dynamically allocated resources before calling
    378:   // PetscHeaderDestroy()
    379:   PetscFree(obj->foo);

    381:   // OK, dispose of obj
    382:   PetscHeaderDestroy(&obj);

    384:   // ERROR, obj points to NULL here, accessing obj->bar may result in segmentation violation!
    385:   // obj->bar is potentially leaked!
    386:   PetscFree(obj->bar);
    387: .ve

    389: .seealso: `PetscObject`, `PetscHeaderCreate()`
    390: M*/
    391: #define PetscHeaderDestroy(h) PetscHeaderDestroy_Function((PetscObject *)h)

    393: PETSC_EXTERN PetscErrorCode                PetscHeaderDestroy_Private(PetscObject, PetscBool);
    394: PETSC_INTERN PetscErrorCode                PetscHeaderDestroy_Private_Unlogged(PetscObject, PetscBool);
    395: PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode PetscHeaderReset_Internal(PetscObject);
    396: PETSC_EXTERN PetscErrorCode                PetscObjectCopyFortranFunctionPointers(PetscObject, PetscObject);
    397: PETSC_EXTERN PetscErrorCode                PetscObjectSetFortranCallback(PetscObject, PetscFortranCallbackType, PetscFortranCallbackId *, PetscFortranCallbackFn *, PetscCtx ctx);
    398: PETSC_EXTERN PetscErrorCode                PetscObjectGetFortranCallback(PetscObject, PetscFortranCallbackType, PetscFortranCallbackId, PetscFortranCallbackFn **, void **ctx);

    400: PETSC_INTERN PetscErrorCode PetscCitationsInitialize(void);
    401: PETSC_INTERN PetscErrorCode PetscFreeMPIResources(void);
    402: PETSC_INTERN PetscErrorCode PetscOptionsHasHelpIntro_Internal(PetscOptions, PetscBool *);

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

    407: #if PetscDefined(HAVE_SETJMP_H)
    408: PETSC_EXTERN PetscBool PetscCheckPointer(const void *, PetscDataType);
    409: #else
    410:   #define PetscCheckPointer(ptr, data_type) (ptr ? PETSC_TRUE : PETSC_FALSE)
    411: #endif

    413: #if defined(PETSC_CLANG_STATIC_ANALYZER)
    414: template <typename T>
    416: template <typename T>
    418: template <typename T>
    420: template <typename T>
    421: extern void PetscAssertPointer(T, int)
    422: {
    423: }
    424: template <typename T>
    426: #else
    427:   // Macros to test if a PETSc object is valid and if pointers are valid
    428:   #if PetscDefined(USE_DEBUG)
    429:     /*  This check is for subtype methods such as DMDAGetCorners() that do not use the PetscTryMethod() or PetscUseMethod() paradigm */
    431:       do { \
    432:         PetscBool _7_same; \
    434:         PetscCall(PetscObjectTypeCompare((PetscObject)(h), t, &_7_same)); \
    435:         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); \
    436:       } while (0)

    438:     #define PetscAssertPointer_Internal(ptr, arg, ptype, ptrtype) \
    439:       do { \
    440:         PetscCheck(ptr, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Null Pointer: Parameter # %d", arg); \
    441:         PetscCheck(PetscCheckPointer(ptr, ptype), PETSC_COMM_SELF, PETSC_ERR_ARG_BADPTR, "Invalid Pointer to %s: Argument '" PetscStringize(ptr) "' (parameter # %d)", ptrtype, arg); \
    442:       } while (0)

    445:       do { \
    446:         PetscAssertPointer_Internal(h, arg, PETSC_OBJECT, "PetscObject"); \
    447:         if (((PetscObject)(h))->classid != ck) { \
    448:           PetscCheck(((PetscObject)(h))->classid != PETSCFREEDHEADER, PETSC_COMM_SELF, PETSC_ERR_ARG_CORRUPT, "Object already free: Parameter # %d", arg); \
    449:           SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Wrong type of object: Parameter # %d", arg); \
    450:         } \
    451:       } while (0)

    454:       do { \
    455:         PetscAssertPointer_Internal(h, arg, PETSC_OBJECT, "PetscObject"); \
    456:         PetscCheck(((PetscObject)(h))->classid != PETSCFREEDHEADER, PETSC_COMM_SELF, PETSC_ERR_ARG_CORRUPT, "Object already free: Parameter # %d", arg); \
    457:         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); \
    458:       } while (0)

    460:     #if defined(__cplusplus)
    461:       #include <type_traits> // std::decay

    463: namespace Petsc
    464: {

    466: namespace util
    467: {

    469: template <typename T>
    470: struct PetscAssertPointerImpl {
    471:   PETSC_NODISCARD static constexpr PetscDataType type() noexcept { return PETSC_CHAR; }
    472:   PETSC_NODISCARD static constexpr const char   *string() noexcept { return "memory"; }
    473: };

    475:       #define PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(T, PETSC_TYPE) \
    476:         template <> \
    477:         struct PetscAssertPointerImpl<T *> { \
    478:           PETSC_NODISCARD static constexpr PetscDataType type() noexcept { return PETSC_TYPE; } \
    479:           PETSC_NODISCARD static constexpr const char   *string() noexcept { return PetscStringize(T); } \
    480:         }; \
    481:         template <> \
    482:         struct PetscAssertPointerImpl<const T *> : PetscAssertPointerImpl<T *> { }; \
    483:         template <> \
    484:         struct PetscAssertPointerImpl<volatile T *> : PetscAssertPointerImpl<T *> { }; \
    485:         template <> \
    486:         struct PetscAssertPointerImpl<const volatile T *> : PetscAssertPointerImpl<T *> { }

    488: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(char, PETSC_CHAR);
    489: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(signed char, PETSC_CHAR);
    490: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(unsigned char, PETSC_CHAR);
    491: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(short, PETSC_SHORT);
    492: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(unsigned short, PETSC_SHORT);
    493: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(PetscBool, PETSC_BOOL);
    494: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(float, PETSC_FLOAT);
    495: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(double, PETSC_DOUBLE);
    496: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(int32_t, PETSC_INT32);
    497: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(uint32_t, PETSC_INT32);
    498: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(int64_t, PETSC_INT64);
    499: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(uint64_t, PETSC_INT64);
    500:       #if defined(PETSC_HAVE_COMPLEX)
    501: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(PetscComplex, PETSC_COMPLEX);
    502:       #endif

    504:       #undef PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION

    506: } // namespace util

    508: } // namespace Petsc

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

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

    516:       #if PetscDefined(HAVE_COMPLEX)
    517:         #define PETSC_GENERIC_CV_COMPLEX(result) , PETSC_GENERIC_CV(PetscComplex, result)
    518:       #else
    519:         #define PETSC_GENERIC_CV_COMPLEX(result)
    520:       #endif

    522:       #define PetscAssertPointer_PetscDataType(h) \
    523:         _Generic((h), \
    524:           default: PETSC_CHAR, \
    525:           PETSC_GENERIC_CV(          char, PETSC_CHAR), \
    526:           PETSC_GENERIC_CV(   signed char, PETSC_CHAR), \
    527:           PETSC_GENERIC_CV( unsigned char, PETSC_CHAR), \
    528:           PETSC_GENERIC_CV(         short, PETSC_SHORT), \
    529:           PETSC_GENERIC_CV(unsigned short, PETSC_SHORT), \
    530:           PETSC_GENERIC_CV(         float, PETSC_FLOAT), \
    531:           PETSC_GENERIC_CV(        double, PETSC_DOUBLE), \
    532:           PETSC_GENERIC_CV(       int32_t, PETSC_INT32), \
    533:           PETSC_GENERIC_CV(      uint32_t, PETSC_INT32), \
    534:           PETSC_GENERIC_CV(       int64_t, PETSC_INT64), \
    535:           PETSC_GENERIC_CV(      uint64_t, PETSC_INT64) \
    536:           PETSC_GENERIC_CV_COMPLEX(PETSC_COMPLEX))

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

    540:       #if PetscDefined(HAVE_COMPLEX)
    541:         #define PETSC_GENERIC_CV_STRINGIZE_COMPLEX , PETSC_GENERIC_CV_STRINGIZE(PetscComplex)
    542:       #else
    543:         #define PETSC_GENERIC_CV_STRINGIZE_COMPLEX
    544:       #endif

    546:       #define PetscAssertPointer_String(h) \
    547:         _Generic((h), \
    548:           default: "memory", \
    549:           PETSC_GENERIC_CV_STRINGIZE(char), \
    550:           PETSC_GENERIC_CV_STRINGIZE(signed char), \
    551:           PETSC_GENERIC_CV_STRINGIZE(unsigned char), \
    552:           PETSC_GENERIC_CV_STRINGIZE(short), \
    553:           PETSC_GENERIC_CV_STRINGIZE(unsigned short), \
    554:           PETSC_GENERIC_CV_STRINGIZE(float), \
    555:           PETSC_GENERIC_CV_STRINGIZE(double), \
    556:           PETSC_GENERIC_CV_STRINGIZE(int32_t), \
    557:           PETSC_GENERIC_CV_STRINGIZE(uint32_t), \
    558:           PETSC_GENERIC_CV_STRINGIZE(int64_t), \
    559:           PETSC_GENERIC_CV_STRINGIZE(uint64_t) \
    560:           PETSC_GENERIC_CV_STRINGIZE_COMPLEX)
    561:     #else // PETSC_C_VERSION >= 11 || defined(__cplusplus)
    562:       #define PetscAssertPointer_PetscDataType(h) PETSC_CHAR
    563:       #define PetscAssertPointer_String(h)        "memory"
    564:     #endif // PETSC_C_VERSION >= 11 || defined(__cplusplus)
    565:     #define PetscAssertPointer(h, arg) PetscAssertPointer_Internal(h, arg, PetscAssertPointer_PetscDataType(h), PetscAssertPointer_String(h))
    567:   #else // PetscDefined(USE_DEBUG)
    569:       do { \
    570:         (void)(h); \
    571:       } while (0)
    573:       do { \
    574:         (void)(h); \
    575:       } while (0)
    577:       do { \
    578:         (void)(h); \
    579:       } while (0)
    580:     #define PetscAssertPointer(h, arg) \
    581:       do { \
    582:         (void)(h); \
    583:       } while (0)
    585:       do { \
    586:         (void)(h); \
    587:       } while (0)
    588:   #endif // PetscDefined(USE_DEBUG)
    589: #endif   // PETSC_CLANG_STATIC_ANALYZER

    600: #define PetscSorted(n, idx, sorted) \
    601:   do { \
    602:     (sorted) = PETSC_TRUE; \
    603:     for (PetscCount _i_ = 1; _i_ < (n); ++_i_) { \
    604:       if ((idx)[_i_] < (idx)[_i_ - 1]) { \
    605:         (sorted) = PETSC_FALSE; \
    606:         break; \
    607:       } \
    608:     } \
    609:   } while (0)

    611: #if !defined(PETSC_CLANG_STATIC_ANALYZER)
    612:   #if !defined(PETSC_USE_DEBUG)

    614:     #define PetscCheckSameType(a, arga, b, argb) \
    615:       do { \
    616:         (void)(a); \
    617:         (void)(b); \
    618:       } while (0)
    619:     #define PetscCheckTypeName(a, type) \
    620:       do { \
    621:         (void)(a); \
    622:       } while (0)
    623:     #define PetscCheckTypeNames(a, type1, type2) \
    624:       do { \
    625:         (void)(a); \
    626:       } while (0)
    628:       do { \
    629:         (void)(a); \
    630:       } while (0)
    631:     #define PetscCheckSameComm(a, arga, b, argb) \
    632:       do { \
    633:         (void)(a); \
    634:         (void)(b); \
    635:       } while (0)
    636:     #define PetscCheckSameTypeAndComm(a, arga, b, argb) \
    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)
    657:       do { \
    658:         (void)(a); \
    659:         (void)(b); \
    660:       } while (0)
    662:       do { \
    663:         (void)(a); \
    664:         (void)(b); \
    665:       } while (0)
    667:       do { \
    668:         (void)(a); \
    669:         (void)(b); \
    670:       } while (0)
    672:       do { \
    673:         (void)(a); \
    674:         (void)(b); \
    675:       } while (0)
    677:       do { \
    678:         (void)(a); \
    679:         (void)(b); \
    680:       } while (0)
    681:     #define PetscCheckSorted(n, idx) \
    682:       do { \
    683:         (void)(n); \
    684:         (void)(idx); \
    685:       } while (0)

    687:   #else

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

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

    695:   This macro is used incorrectly in the code. Many places that do not need identity of the
    696:   types incorrectly call this check and would need to be fixed if this macro is enabled.
    697: */
    698:     #if 0
    699:       #define PetscCheckSameType(a, arga, b, argb) \
    700:         do { \
    701:           PetscBool pcst_type_eq_ = PETSC_TRUE; \
    702:           PetscCall(PetscStrcmp(((PetscObject)(a))->type_name, ((PetscObject)(b))->type_name, &pcst_type_eq_)); \
    703:           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); \
    704:         } while (0)
    705:     #else
    706:       #define PetscCheckSameType(a, arga, b, argb) \
    707:         do { \
    708:           (void)(a); \
    709:           (void)(b); \
    710:         } while (0)
    711:     #endif

    713:     /*
    714:     Check type_name
    715: */
    716:     #define PetscCheckTypeName(a, type) \
    717:       do { \
    718:         PetscBool _7_match; \
    719:         PetscCall(PetscObjectTypeCompare(((PetscObject)(a)), (type), &_7_match)); \
    720:         PetscCheck(_7_match, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Object (%s) is not %s", ((PetscObject)(a))->type_name, type); \
    721:       } while (0)

    723:     #define PetscCheckTypeNames(a, type1, type2) \
    724:       do { \
    725:         PetscBool _7_match; \
    726:         PetscCall(PetscObjectTypeCompareAny(((PetscObject)(a)), &_7_match, (type1), (type2), "")); \
    727:         PetscCheck(_7_match, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Object (%s) is not %s or %s", ((PetscObject)(a))->type_name, type1, type2); \
    728:       } while (0)

    730:     /*
    731:    Use this macro to check if the type is set
    732: */

    735:     /*
    736:    Sometimes object must live on same communicator to inter-operate
    737: */
    738:     #define PetscCheckSameComm(a, arga, b, argb) \
    739:       do { \
    740:         PetscMPIInt _7_flag; \
    741:         PetscCallMPI(MPI_Comm_compare(PetscObjectComm((PetscObject)(a)), PetscObjectComm((PetscObject)(b)), &_7_flag)); \
    742:         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); \
    743:       } while (0)

    745:     #define PetscCheckSameTypeAndComm(a, arga, b, argb) \
    746:       do { \
    747:         PetscCheckSameType(a, arga, b, argb); \
    748:         PetscCheckSameComm(a, arga, b, argb); \
    749:       } while (0)

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

    769:       do { \
    770:         PetscReal b0 = (b), b1[3]; \
    771:         if (PetscIsNanReal(b0)) { \
    772:           b1[2] = 1; \
    773:         } else { \
    774:           b1[2] = 0; \
    775:         }; \
    776:         b1[0] = -b0; \
    777:         b1[1] = b0; \
    778:         PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, b1, 3, MPIU_REAL, MPIU_MAX, PetscObjectComm((PetscObject)(a)))); \
    779:         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); \
    780:       } while (0)

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

    792:       do { \
    793:         PetscInt b1[2]; \
    794:         b1[0] = -b; \
    795:         b1[1] = b; \
    796:         PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, b1, 2, MPIU_INT, MPI_MAX, a)); \
    797:         PetscCheck(-b1[0] == b1[1], a, PETSC_ERR_ARG_WRONG, "Int value must be same on all processes, argument # %d", arg); \
    798:       } while (0)

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

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

    819:       do { \
    820:         PetscBool b0 = (PetscBool)(b), b1[2]; \
    821:         b1[0]        = !b0; \
    822:         b1[1]        = b0; \
    823:         PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, b1, 2, MPI_C_BOOL, MPI_LAND, PetscObjectComm((PetscObject)(a)))); \
    824:         PetscCheck(!b1[0] == b1[1], PetscObjectComm((PetscObject)(a)), PETSC_ERR_ARG_WRONG, "Bool value must be same on all processes, argument # %d", arg); \
    825:       } while (0)

    828:       do { \
    829:         PetscMPIInt b0 = (PetscMPIInt)(b), b1[2]; \
    830:         b1[0]          = -b0; \
    831:         b1[1]          = b0; \
    832:         PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, b1, 2, MPI_INT, MPI_MAX, PetscObjectComm((PetscObject)(a)))); \
    833:         PetscCheck(-b1[0] == b1[1], PetscObjectComm((PetscObject)(a)), PETSC_ERR_ARG_WRONG, "Enum value must be same on all processes, argument # %d", arg); \
    834:       } while (0)

    836:     #define PetscCheckSorted(n, idx) \
    837:       do { \
    838:         PetscBool _1_flg; \
    839:         PetscSorted(n, idx, _1_flg); \
    840:         PetscCheck(_1_flg, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Input array needs to be sorted"); \
    841:       } while (0)

    843:   #endif
    844: #else  /* PETSC_CLANG_STATIC_ANALYZER */
    845: template <typename Ta, typename Tb>
    846: extern void PetscCheckSameType(Ta, int, Tb, int);
    847: template <typename Ta, typename Tb>
    848: extern void PetscCheckTypeName(Ta, Tb);
    849: template <typename Ta, typename Tb, typename Tc>
    850: extern void PetscCheckTypeNames(Ta, Tb, Tc);
    851: template <typename T>
    853: template <typename Ta, typename Tb>
    854: extern void PetscCheckSameComm(Ta, int, Tb, int);
    855: template <typename Ta, typename Tb>
    856: extern void PetscCheckSameTypeAndComm(Ta, int, Tb, int);
    857: template <typename Ta, typename Tb>
    859: template <typename Ta, typename Tb>
    861: template <typename Ta, typename Tb>
    863: template <typename Ta, typename Tb>
    865: template <typename Ta, typename Tb>
    867: template <typename Ta, typename Tb>
    869: template <typename Ta, typename Tb>
    871: template <typename T>
    872: extern void PetscCheckSorted(PetscInt, T);
    873: #endif /* PETSC_CLANG_STATIC_ANALYZER */

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

    878:   Synopsis:
    879:    #include "petsc/private/petscimpl.h"
    880:    PetscTryMethod(PetscObject obj, const char *name, (arg_types), (arg_value))

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

    888:    Level: developer

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

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

    896: .seealso: `PetscUseMethod()`, `PetscCall()`, `PetscUseTypeMethod()`, `PetscTryTypeMethod()`, `PetscCheck()`, `PetscObject`
    897: M*/
    898: #define PetscTryMethod(obj, A, B, C) \
    899:   do { \
    900:     PetscErrorCode(*_7_f) B; \
    901:     PetscCall(PetscObjectQueryFunction((PetscObject)(obj), A, &_7_f)); \
    902:     if (_7_f) PetscCall((*_7_f)C); \
    903:   } while (0)

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

    908:   Synopsis:
    909:    #include "petsc/private/petscimpl.h"
    910:    PetscUseMethod(PetscObject obj, const char *name, (arg_types), (arg_value))

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

    918:    Level: developer

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

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

    926: .seealso: `PetscTryMethod()`, `PetscCall()`, `PetscUseTypeMethod()`, `PetscTryTypeMethod()`, `PetscCheck()`, `PetscObject`
    927: M*/
    928: #define PetscUseMethod(obj, A, B, C) \
    929:   do { \
    930:     PetscErrorCode(*_7_f) B; \
    931:     PetscCall(PetscObjectQueryFunction((PetscObject)(obj), A, &_7_f)); \
    932:     PetscCheck(_7_f, PetscObjectComm((PetscObject)(obj)), PETSC_ERR_SUP, "Cannot locate function %s in object", A); \
    933:     PetscCall((*_7_f)C); \
    934:   } while (0)

    936: /*
    937:   Use Microsoft traditional preprocessor.

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

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

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

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

    950:   #define PetscUseTypeMethod(obj, OP, ...) \
    951:     do { \
    952:       PetscErrorCode ierr_p_; \
    953:       PetscStackUpdateLine; \
    954:       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); \
    955:       ierr_p_ = (*(obj)->ops->OP)(obj, __VA_ARGS__); \
    956:       PetscCall(ierr_p_); \
    957:     } while (0)

    959:   #define PetscTryTypeMethod(obj, OP, ...) \
    960:     do { \
    961:       if ((obj)->ops->OP) { \
    962:         PetscErrorCode ierr_p_; \
    963:         PetscStackUpdateLine; \
    964:         ierr_p_ = (*(obj)->ops->OP)(obj, __VA_ARGS__); \
    965:         PetscCall(ierr_p_); \
    966:       } \
    967:     } while (0)

    969: #else

    971:   /*MC
    972:    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

    974:   Synopsis:
    975:    #include "petsc/private/petscimpl.h"
    976:    PetscUseTypeMethod(obj, method, other_args)

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

    983:    Level: developer

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

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

    990: .seealso: `PetscTryMethod()`, `PetscUseMethod()`, `PetscCall()`, `PetscCheck()`, `PetscTryTypeMethod()`, `PetscCallBack()`
    991: M*/
    992:   #define PetscUseTypeMethod(obj, ...) \
    993:     do { \
    994:       PetscCheck((obj)->ops->PETSC_FIRST_ARG((__VA_ARGS__, unused)), PetscObjectComm((PetscObject)obj), PETSC_ERR_SUP, "No method %s for %s of type %s", \
    995:                  PetscStringize(PETSC_FIRST_ARG((__VA_ARGS__,unused))), ((PetscObject)obj)->class_name, ((PetscObject)obj)->type_name); \
    996:       PetscCall((*(obj)->ops->PETSC_FIRST_ARG((__VA_ARGS__, unused)))(obj PETSC_REST_ARG(__VA_ARGS__))); \
    997:     } while (0)

    999:   /*MC
    1000:    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

    1002:   Synopsis:
    1003:    #include "petsc/private/petscimpl.h"
    1004:    PetscTryTypeMethod(obj, method, other_args)

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

    1011:    Level: developer

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

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

    1018: .seealso: `PetscTryMethod()`, `PetscUseMethod()`, `PetscCall()`, `PetscCheck()`, `PetscUseTypeMethod()`
    1019: M*/
    1020:   #define PetscTryTypeMethod(obj, ...) \
    1021:     do { \
    1022:       if ((obj)->ops->PETSC_FIRST_ARG((__VA_ARGS__, unused))) PetscCall((*(obj)->ops->PETSC_FIRST_ARG((__VA_ARGS__, unused)))(obj PETSC_REST_ARG(__VA_ARGS__))); \
    1023:     } while (0)

    1025: #endif

    1027: /*MC
    1028:    PetscObjectStateIncrease - Increases the state of any `PetscObject`

    1030:    Synopsis:
    1031:    #include "petsc/private/petscimpl.h"
    1032:    PetscErrorCode PetscObjectStateIncrease(PetscObject obj)

    1034:    Logically Collective

    1036:    Input Parameter:
    1037: .  obj - any PETSc object, for example a `Vec`, `Mat` or `KSP`. This must be
    1038:          cast with a (PetscObject), for example,
    1039:          `PetscObjectStateIncrease`((`PetscObject`)mat);

    1041:    Level: developer

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

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

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

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

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

    1060: .seealso: `PetscObjectStateGet()`, `PetscObject`
    1061: M*/
    1062: #define PetscObjectStateIncrease(obj) ((PetscErrorCode)((obj)->state++, PETSC_SUCCESS))

    1064: PETSC_EXTERN PetscErrorCode PetscObjectStateGet(PetscObject, PetscObjectState *);
    1065: PETSC_EXTERN PetscErrorCode PetscObjectStateSet(PetscObject, PetscObjectState);
    1066: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataRegister(PetscInt *);
    1067: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseInt(PetscObject);
    1068: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseIntstar(PetscObject);
    1069: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseReal(PetscObject);
    1070: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseRealstar(PetscObject);
    1071: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseScalar(PetscObject);
    1072: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseScalarstar(PetscObject);
    1073: PETSC_EXTERN PetscInt       PetscObjectComposedDataMax;

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

    1078:    Synopsis:
    1079:    #include "petsc/private/petscimpl.h"
    1080:    PetscErrorCode PetscObjectComposedDataSetInt(PetscObject obj, PetscInt id, PetscInt data)

    1082:    Not Collective

    1084:    Input Parameters:
    1085: +  obj - the object to which data is to be attached
    1086: .  id - the identifier for the data
    1087: -  data - the data to  be attached, a `PetscInt`

    1089:    Level: developer

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

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

    1097: .seealso: `PetscObjectComposedDataGetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetReal()`,
    1098:           `PetscObjectComposedDataGetIntstar()`, `PetscObjectComposedDataSetIntstar()`, `PetscObject`,
    1099:           `PetscObjectCompose()`, `PetscObjectQuery()`
    1100: M*/
    1101: #define PetscObjectComposedDataSetInt(obj, id, data) \
    1102:   ((PetscErrorCode)((((obj)->int_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseInt(obj)) || ((obj)->intcomposeddata[id] = data, (obj)->intcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))

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

    1107:    Synopsis:
    1108:    #include "petsc/private/petscimpl.h"
    1109:    PetscErrorCode PetscObjectComposedDataGetInt(PetscObject obj, PetscInt id, PetscInt data, PetscBool flag)

    1111:    Not Collective

    1113:    Input Parameters:
    1114: +  obj - the object from which data is to be retrieved
    1115: -  id - the identifier for the data

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

    1121:    Level: developer

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

    1126: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetReal()`,
    1127:           `PetscObjectComposedDataGetIntstar()`, `PetscObjectComposedDataSetIntstar()`, `PetscObject`,
    1128:           `PetscObjectCompose()`, `PetscObjectQuery()`
    1129: M*/
    1130: #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))

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

    1135:    Synopsis:
    1136:    #include "petsc/private/petscimpl.h"
    1137:    PetscErrorCode PetscObjectComposedDataSetIntstar(PetscObject obj, PetscInt id, PetscInt *data)

    1139:    Not Collective

    1141:    Input Parameters:
    1142: +  obj - the object to which data is to be attached
    1143: .  id - the identifier for the data
    1144: -  data - the data to  be attached, a `PetscInt` array

    1146:    Level: developer

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

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

    1153: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetReal()`,
    1154:           `PetscObjectComposedDataGetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
    1155:           `PetscObjectCompose()`, `PetscObjectQuery()`
    1156: M*/
    1157: #define PetscObjectComposedDataSetIntstar(obj, id, data) \
    1158:   ((PetscErrorCode)((((obj)->intstar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseIntstar(obj)) || ((obj)->intstarcomposeddata[id] = data, (obj)->intstarcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))

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

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

    1167:    Not Collective

    1169:    Input Parameters:
    1170: +  obj - the object from which data is to be retrieved
    1171: -  id - the identifier for the data

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

    1177:    Level: developer

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

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

    1184: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetReal()`,
    1185:           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
    1186:           `PetscObjectCompose()`, `PetscObjectQuery()`
    1187: M*/
    1188: #define PetscObjectComposedDataGetIntstar(obj, id, data, flag) \
    1189:   ((PetscErrorCode)(((obj)->intstarcomposedstate ? (data = (obj)->intstarcomposeddata[id], flag = (PetscBool)((obj)->intstarcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), PETSC_SUCCESS))

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

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

    1198:    Not Collective

    1200:    Input Parameters:
    1201: +  obj - the object to which data is to be attached
    1202: .  id - the identifier for the data
    1203: -  data - the data to  be attached, a `PetscReal`

    1205:    Level: developer

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

    1210: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
    1211:           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
    1212:           `PetscObjectCompose()`, `PetscObjectQuery()`
    1213: M*/
    1214: #define PetscObjectComposedDataSetReal(obj, id, data) \
    1215:   ((PetscErrorCode)((((obj)->real_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseReal(obj)) || ((obj)->realcomposeddata[id] = data, (obj)->realcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))

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

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

    1224:    Not Collective

    1226:    Input Parameters:
    1227: +  obj - the object from which data is to be retrieved
    1228: -  id - the identifier for the data

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

    1234:    Level: developer

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

    1239: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataSetIntstar()`,
    1240:           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
    1241:           `PetscObjectCompose()`, `PetscObjectQuery()`
    1242: M*/
    1243: #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))

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

    1248:    Synopsis:
    1249:    #include "petsc/private/petscimpl.h"
    1250:    PetscErrorCode PetscObjectComposedDataSetRealstar(PetscObject obj, PetscInt id, PetscReal *data)

    1252:    Not Collective

    1254:    Input Parameters:
    1255: +  obj - the object to which data is to be attached
    1256: .  id - the identifier for the data
    1257: -  data - the data to  be attached

    1259:    Level: developer

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

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

    1266: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
    1267:           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
    1268:           `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataGetRealstar()`
    1269: M*/
    1270: #define PetscObjectComposedDataSetRealstar(obj, id, data) \
    1271:   ((PetscErrorCode)((((obj)->realstar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseRealstar(obj)) || ((obj)->realstarcomposeddata[id] = data, (obj)->realstarcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))

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

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

    1280:    Not Collective

    1282:    Input Parameters:
    1283: +  obj - the object from which data is to be retrieved
    1284: -  id - the identifier for the data

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

    1290:    Level: developer

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

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

    1297: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
    1298:           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
    1299:           `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`
    1300: M*/
    1301: #define PetscObjectComposedDataGetRealstar(obj, id, data, flag) \
    1302:   ((PetscErrorCode)(((obj)->realstarcomposedstate ? (data = (obj)->realstarcomposeddata[id], flag = (PetscBool)((obj)->realstarcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), PETSC_SUCCESS))

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

    1307:    Synopsis:
    1308:    #include "petsc/private/petscimpl.h"
    1309:    PetscErrorCode PetscObjectComposedDataSetScalar(PetscObject obj, PetscInt id, PetscScalar data)

    1311:    Not Collective

    1313:    Input Parameters:
    1314: +  obj - the object to which data is to be attached
    1315: .  id - the identifier for the data
    1316: -  data - the data to  be attached, a `PetscScalar`

    1318:    Level: developer

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

    1323: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
    1324:           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
    1325:           `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`, `PetscObjectComposedDataGetScalar()`
    1326: M*/
    1327: #if defined(PETSC_USE_COMPLEX)
    1328:   #define PetscObjectComposedDataSetScalar(obj, id, data) \
    1329:     ((PetscErrorCode)((((obj)->scalar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseScalar(obj)) || ((obj)->scalarcomposeddata[id] = data, (obj)->scalarcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))
    1330: #else
    1331:   #define PetscObjectComposedDataSetScalar(obj, id, data) PetscObjectComposedDataSetReal(obj, id, data)
    1332: #endif
    1333: /*MC
    1334:    PetscObjectComposedDataGetScalar - retrieve `PetscScalar` data attached to a `PetscObject` that was set with `PetscObjectComposedDataSetScalar()`

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

    1340:    Not Collective

    1342:    Input Parameters:
    1343: +  obj - the object from which data is to be retrieved
    1344: -  id - the identifier for the data

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

    1350:    Level: developer

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

    1355: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
    1356:           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
    1357:           `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`, `PetscObjectComposedDataSetScalar()`
    1358: M*/
    1359: #if defined(PETSC_USE_COMPLEX)
    1360:   #define PetscObjectComposedDataGetScalar(obj, id, data, flag) \
    1361:     ((PetscErrorCode)(((obj)->scalarcomposedstate ? (data = (obj)->scalarcomposeddata[id], flag = (PetscBool)((obj)->scalarcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), PETSC_SUCCESS))
    1362: #else
    1363:   #define PetscObjectComposedDataGetScalar(obj, id, data, flag) PetscObjectComposedDataGetReal(obj, id, data, flag)
    1364: #endif

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

    1369:    Synopsis:
    1370:    #include "petsc/private/petscimpl.h"
    1371:    PetscErrorCode PetscObjectComposedDataSetScalarstar(PetscObject obj, PetscInt id, PetscScalar *data)

    1373:    Not Collective

    1375:    Input Parameters:
    1376: +  obj - the object to which data is to be attached
    1377: .  id - the identifier for the data
    1378: -  data - the data to  be attached, a `PetscScalar` array

    1380:    Level: developer

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

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

    1387: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
    1388:           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
    1389:           `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`, `PetscObjectComposedDataGetScalarstar()`
    1390: M*/
    1391: #if defined(PETSC_USE_COMPLEX)
    1392:   #define PetscObjectComposedDataSetScalarstar(obj, id, data) \
    1393:     ((PetscErrorCode)((((obj)->scalarstar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseScalarstar(obj)) || ((obj)->scalarstarcomposeddata[id] = data, (obj)->scalarstarcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))
    1394: #else
    1395:   #define PetscObjectComposedDataSetScalarstar(obj, id, data) PetscObjectComposedDataSetRealstar(obj, id, data)
    1396: #endif
    1397: /*MC
    1398:    PetscObjectComposedDataGetScalarstar - retrieve `PetscScalar` array data attached to a `PetscObject` that was set with `PetscObjectComposedDataSetScalarstar()`
    1399:    attached to an object

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

    1405:    Not Collective

    1407:    Input Parameters:
    1408: +  obj - the object from which data is to be retrieved
    1409: -  id - the identifier for the data

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

    1415:    Level: developer

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

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

    1422: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
    1423:           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
    1424:           `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`, `PetscObjectComposedDataSetScalarstar()`
    1425: M*/
    1426: #if defined(PETSC_USE_COMPLEX)
    1427:   #define PetscObjectComposedDataGetScalarstar(obj, id, data, flag) \
    1428:     ((PetscErrorCode)(((obj)->scalarstarcomposedstate ? (data = (obj)->scalarstarcomposeddata[id], flag = (PetscBool)((obj)->scalarstarcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), PETSC_SUCCESS))
    1429: #else
    1430:   #define PetscObjectComposedDataGetScalarstar(obj, id, data, flag) PetscObjectComposedDataGetRealstar(obj, id, data, flag)
    1431: #endif

    1433: PETSC_INTERN PetscMPIInt Petsc_Counter_keyval;
    1434: PETSC_INTERN PetscMPIInt Petsc_InnerComm_keyval;
    1435: PETSC_INTERN PetscMPIInt Petsc_OuterComm_keyval;
    1436: PETSC_INTERN PetscMPIInt Petsc_Seq_keyval;
    1437: PETSC_INTERN PetscMPIInt Petsc_ShmComm_keyval;
    1438: PETSC_EXTERN PetscMPIInt Petsc_CreationIdx_keyval;
    1439: PETSC_INTERN PetscMPIInt Petsc_Garbage_HMap_keyval;

    1441: PETSC_INTERN PetscMPIInt Petsc_SharedWD_keyval;
    1442: PETSC_INTERN PetscMPIInt Petsc_SharedTmp_keyval;

    1444: struct PetscCommStash {
    1445:   struct PetscCommStash *next;
    1446:   MPI_Comm               comm;
    1447: };

    1449: /*
    1450:   PETSc communicators have this attribute, see
    1451:   PetscCommDuplicate(), PetscCommDestroy(), PetscCommGetNewTag(), PetscObjectGetName()
    1452: */
    1453: typedef struct {
    1454:   PetscMPIInt            tag;       /* next free tag value */
    1455:   PetscInt               refcount;  /* number of references, communicator can be freed when this reaches 0 */
    1456:   PetscInt               namecount; /* used to generate the next name, as in Vec_0, Mat_1, ... */
    1457:   PetscMPIInt           *iflags;    /* length of comm size, shared by all calls to PetscCommBuildTwoSided_Allreduce/RedScatter on this comm */
    1458:   struct PetscCommStash *comms;     /* communicators available for PETSc to pass off to other packages */
    1459: } PetscCommCounter;

    1461: typedef enum {
    1462:   STATE_BEGIN,
    1463:   STATE_PENDING,
    1464:   STATE_END
    1465: } SRState;

    1467: typedef enum {
    1468:   PETSC_SR_REDUCE_SUM = 0,
    1469:   PETSC_SR_REDUCE_MAX = 1,
    1470:   PETSC_SR_REDUCE_MIN = 2
    1471: } PetscSRReductionType;

    1473: typedef struct {
    1474:   MPI_Comm              comm;
    1475:   MPI_Request           request;
    1476:   PetscBool             mix;
    1477:   PetscBool             async;
    1478:   PetscScalar          *lvalues;    /* this are the reduced values before call to MPI_Allreduce() */
    1479:   PetscScalar          *gvalues;    /* values after call to MPI_Allreduce() */
    1480:   void                **invecs;     /* for debugging only, vector/memory used with each op */
    1481:   PetscSRReductionType *reducetype; /* is particular value to be summed or maxed? */
    1482:   struct {
    1483:     PetscScalar v;
    1484:     PetscInt    i;
    1485:   }          *lvalues_mix, *gvalues_mix; /* used when mixing reduce operations */
    1486:   SRState     state;                     /* are we calling xxxBegin() or xxxEnd()? */
    1487:   PetscMPIInt maxops;                    /* total amount of space we have for requests */
    1488:   PetscMPIInt numopsbegin;               /* number of requests that have been queued in */
    1489:   PetscMPIInt numopsend;                 /* number of requests that have been gotten by user */
    1490: } PetscSplitReduction;

    1492: PETSC_EXTERN PetscErrorCode PetscSplitReductionGet(MPI_Comm, PetscSplitReduction **);
    1493: PETSC_EXTERN PetscErrorCode PetscSplitReductionEnd(PetscSplitReduction *);
    1494: PETSC_EXTERN PetscErrorCode PetscSplitReductionExtend(PetscSplitReduction *);

    1496: #if defined(PETSC_HAVE_THREADSAFETY)
    1497:   #if defined(PETSC_HAVE_CONCURRENCYKIT)
    1498:     #if defined(__cplusplus)
    1499: /*  CK does not have extern "C" protection in their include files */
    1500: extern "C" {
    1501:     #endif
    1502:     #include <ck_spinlock.h>
    1503:     #if defined(__cplusplus)
    1504: }
    1505:     #endif
    1506: typedef ck_spinlock_t PetscSpinlock;

    1508: static inline PetscErrorCode PetscSpinlockCreate(PetscSpinlock *ck_spinlock)
    1509: {
    1510:   ck_spinlock_init(ck_spinlock);
    1511:   return PETSC_SUCCESS;
    1512: }
    1513: static inline PetscErrorCode PetscSpinlockLock(PetscSpinlock *ck_spinlock)
    1514: {
    1515:   ck_spinlock_lock(ck_spinlock);
    1516:   return PETSC_SUCCESS;
    1517: }
    1518: static inline PetscErrorCode PetscSpinlockUnlock(PetscSpinlock *ck_spinlock)
    1519: {
    1520:   ck_spinlock_unlock(ck_spinlock);
    1521:   return PETSC_SUCCESS;
    1522: }
    1523: static inline PetscErrorCode PetscSpinlockDestroy(PetscSpinlock *ck_spinlock)
    1524: {
    1525:   return PETSC_SUCCESS;
    1526: }
    1527:   #elif (defined(__cplusplus) && defined(PETSC_HAVE_CXX_ATOMIC)) || (!defined(__cplusplus) && defined(PETSC_HAVE_STDATOMIC_H))
    1528:     #if defined(__cplusplus)
    1529:       // See the example at https://en.cppreference.com/w/cpp/atomic/atomic_flag
    1530:       #include <atomic>
    1531:       #define petsc_atomic_flag                 std::atomic_flag
    1532:       #define petsc_atomic_flag_test_and_set(p) std::atomic_flag_test_and_set_explicit(p, std::memory_order_acquire)
    1533:       #define petsc_atomic_flag_clear(p)        std::atomic_flag_clear_explicit(p, std::memory_order_release)
    1534:     #else
    1535:       #include <stdatomic.h>
    1536:       #define petsc_atomic_flag                 atomic_flag
    1537:       #define petsc_atomic_flag_test_and_set(p) atomic_flag_test_and_set_explicit(p, memory_order_acquire)
    1538:       #define petsc_atomic_flag_clear(p)        atomic_flag_clear_explicit(p, memory_order_release)
    1539:     #endif

    1541: typedef petsc_atomic_flag PetscSpinlock;

    1543: static inline PetscErrorCode PetscSpinlockCreate(PetscSpinlock *spinlock)
    1544: {
    1545:   petsc_atomic_flag_clear(spinlock);
    1546:   return PETSC_SUCCESS;
    1547: }
    1548: static inline PetscErrorCode PetscSpinlockLock(PetscSpinlock *spinlock)
    1549: {
    1550:   do {
    1551:   } while (petsc_atomic_flag_test_and_set(spinlock));
    1552:   return PETSC_SUCCESS;
    1553: }
    1554: static inline PetscErrorCode PetscSpinlockUnlock(PetscSpinlock *spinlock)
    1555: {
    1556:   petsc_atomic_flag_clear(spinlock);
    1557:   return PETSC_SUCCESS;
    1558: }
    1559: static inline PetscErrorCode PetscSpinlockDestroy(PETSC_UNUSED PetscSpinlock *spinlock)
    1560: {
    1561:   return PETSC_SUCCESS;
    1562: }
    1563:     #undef petsc_atomic_flag_test_and_set
    1564:     #undef petsc_atomic_flag_clear
    1565:     #undef petsc_atomic_flag

    1567:   #elif defined(PETSC_HAVE_OPENMP)

    1569:     #include <omp.h>
    1570: typedef omp_lock_t PetscSpinlock;

    1572: static inline PetscErrorCode PetscSpinlockCreate(PetscSpinlock *omp_lock)
    1573: {
    1574:   omp_init_lock(omp_lock);
    1575:   return PETSC_SUCCESS;
    1576: }
    1577: static inline PetscErrorCode PetscSpinlockLock(PetscSpinlock *omp_lock)
    1578: {
    1579:   omp_set_lock(omp_lock);
    1580:   return PETSC_SUCCESS;
    1581: }
    1582: static inline PetscErrorCode PetscSpinlockUnlock(PetscSpinlock *omp_lock)
    1583: {
    1584:   omp_unset_lock(omp_lock);
    1585:   return PETSC_SUCCESS;
    1586: }
    1587: static inline PetscErrorCode PetscSpinlockDestroy(PetscSpinlock *omp_lock)
    1588: {
    1589:   omp_destroy_lock(omp_lock);
    1590:   return PETSC_SUCCESS;
    1591: }
    1592:   #else
    1593:     #if defined(__cplusplus)
    1594:       #error "Thread safety requires either --download-concurrencykit, std::atomic, or --with-openmp"
    1595:     #else
    1596:       #error "Thread safety requires either --download-concurrencykit, stdatomic.h, or --with-openmp"
    1597:     #endif
    1598:   #endif

    1600: #else
    1601: typedef int PetscSpinlock;
    1602:   #define PetscSpinlockCreate(a)  PETSC_SUCCESS
    1603:   #define PetscSpinlockLock(a)    PETSC_SUCCESS
    1604:   #define PetscSpinlockUnlock(a)  PETSC_SUCCESS
    1605:   #define PetscSpinlockDestroy(a) PETSC_SUCCESS
    1606: #endif

    1608: #if defined(PETSC_HAVE_THREADSAFETY)
    1609: PETSC_INTERN PetscSpinlock PetscViewerASCIISpinLockOpen;
    1610: PETSC_INTERN PetscSpinlock PetscViewerASCIISpinLockStdout;
    1611: PETSC_INTERN PetscSpinlock PetscViewerASCIISpinLockStderr;
    1612: PETSC_INTERN PetscSpinlock PetscCommSpinLock;
    1613: #endif

    1615: PETSC_EXTERN PetscLogEvent PETSC_Barrier;
    1616: PETSC_EXTERN PetscLogEvent PETSC_BuildTwoSided;
    1617: PETSC_EXTERN PetscLogEvent PETSC_BuildTwoSidedF;
    1618: PETSC_EXTERN PetscBool     use_gpu_aware_mpi;
    1619: PETSC_EXTERN PetscBool     PetscPrintFunctionList;

    1621: #if defined(PETSC_HAVE_ADIOS)
    1622: PETSC_EXTERN int64_t Petsc_adios_group;
    1623: #endif

    1625: #if defined(PETSC_HAVE_KOKKOS)
    1626: PETSC_INTERN PetscBool      PetscBeganKokkos;
    1627: PETSC_EXTERN PetscBool      PetscKokkosInitialized;
    1628: PETSC_INTERN PetscErrorCode PetscKokkosIsInitialized_Private(PetscBool *);
    1629: PETSC_INTERN PetscErrorCode PetscKokkosFinalize_Private(void);
    1630: #endif

    1632: #if defined(PETSC_HAVE_OPENMP)
    1633: PETSC_EXTERN PetscInt PetscNumOMPThreads;
    1634: #endif

    1636: struct _n_PetscObjectList {
    1637:   char            name[256];
    1638:   PetscBool       skipdereference; /* when the PetscObjectList is destroyed do not call PetscObjectDereference() on this object */
    1639:   PetscObject     obj;
    1640:   PetscObjectList next;
    1641: };

    1643: /*E
    1644:     PetscPrecision - Precision of a real number

    1646:     Values:
    1647: +   `PETSC_PRECISION_INVALID`     - an invalid value
    1648: .   `PETSC_PRECISION_BFLOAT16`    - half precision (Google Brain bfloat16)
    1649: .   `PETSC_PRECISION___FP16`      - half precison (IEEE FP16)
    1650: .   `PETSC_PRECISION_SINGLE`      - single precision
    1651: .   `PETSC_PRECISION_DOUBLE`      - double precision
    1652: -   `PETSC_PRECISION___FLOAT128`  - quadruple precision (__float128)

    1654:     Level: intermediate
    1655: E*/

    1657: typedef enum {
    1658:   PETSC_PRECISION_INVALID = 0,
    1659:   PETSC_PRECISION_BFLOAT16,
    1660:   PETSC_PRECISION___FP16,
    1661:   PETSC_PRECISION_SINGLE,
    1662:   PETSC_PRECISION_DOUBLE,
    1663:   PETSC_PRECISION___FLOAT128
    1664: } PetscPrecision;

    1666: // The precision of PetscScalar and PetscReal
    1667: #if defined(PETSC_USE_REAL___FP16)
    1668:   #define PETSC_SCALAR_PRECISION PETSC_PRECISION___FP16
    1669: #elif defined(PETSC_USE_REAL_SINGLE)
    1670:   #define PETSC_SCALAR_PRECISION PETSC_PRECISION_SINGLE
    1671: #elif defined(PETSC_USE_REAL_DOUBLE)
    1672:   #define PETSC_SCALAR_PRECISION PETSC_PRECISION_DOUBLE
    1673: #elif defined(PETSC_USE_REAL___FLOAT128)
    1674:   #define PETSC_SCALAR_PRECISION PETSC_PRECISION___FLOAT128
    1675: #endif

    1677: PETSC_EXTERN const char *const PetscPrecisionTypes[];