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: static inline int PetscStackGetSize_Private(const PetscStack *stack)
 10: {
 11:   return PetscMin(stack->currentsize, PETSCSTACKSIZE);
 12: }

 14: /* Return non-null diagnostic strings even when the requested frame is unavailable.
 15:    The return value indicates whether the frame was stored. Do not modify the stack here. */
 16: static inline PetscBool PetscStackGetValidFrame_Private(const PetscStack *stack, int index, const char **file, const char **function, int *line)
 17: {
 18:   *file     = "unknown file (check for missing or mismatched PetscFunctionBegin/PetscFunctionReturn)";
 19:   *function = "unknown_function";
 20:   *line     = 0;
 21:   if (index < 0 || index >= stack->currentsize) return PETSC_FALSE;
 22:   if (index >= PETSCSTACKSIZE) {
 23:     *file = "unknown file (stack depth exceeds PETSCSTACKSIZE=" PetscStringize(PETSCSTACKSIZE) ")";
 24:     return PETSC_FALSE;
 25:   }
 26:   if (!stack->function[index]) return PETSC_FALSE;
 27:   *file     = stack->file[index] ? stack->file[index] : "unknown file";
 28:   *function = stack->function[index];
 29:   *line     = stack->line[index];
 30:   return PETSC_TRUE;
 31: }

 33: #if PetscDefined(CLANG_STATIC_ANALYZER)
 34:   #define PetscDisableStaticAnalyzerForExpressionUnderstandingThatThisIsDangerousAndBugprone(...)
 35: #else
 36:   #define PetscDisableStaticAnalyzerForExpressionUnderstandingThatThisIsDangerousAndBugprone(...) __VA_ARGS__
 37: #endif

 39: #if PetscDefined(USE_DEBUG)
 40: PETSC_INTERN PetscErrorCode PetscStackSetCheck(PetscBool);
 41: PETSC_INTERN PetscErrorCode PetscStackReset(void);
 42: PETSC_EXTERN PetscErrorCode PetscStackCopy(PetscStack *, PetscStack *);
 43: PETSC_INTERN PetscErrorCode PetscStackPrint(PetscStack *, FILE *);
 44: #else
 45:   #define PetscStackSetCheck(check)         PETSC_SUCCESS
 46:   #define PetscStackReset()                 PETSC_SUCCESS
 47:   #define PetscStackCopy(stackin, stackout) PETSC_SUCCESS
 48:   #define PetscStackPrint(stack, file)      PETSC_SUCCESS
 49: #endif

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

 55: /*
 56:    All major PETSc data structures have a common core; this is defined
 57:    below by PETSCHEADER.

 59:    PetscHeaderCreate() should be used whenever creating a PETSc structure.
 60: */

 62: /*
 63:    PetscOps: structure of core operations that all PETSc objects support.

 65:       view()            - Is the routine for viewing the entire PETSc object; for
 66:                           example, MatView() is the general matrix viewing routine.
 67:                           This is used by PetscObjectView((PetscObject)obj) to allow
 68:                           viewing any PETSc object.
 69:       destroy()         - Is the routine for destroying the entire PETSc object;
 70:                           for example,MatDestroy() is the general matrix
 71:                           destruction routine.
 72:                           This is used by PetscObjectDestroy((PetscObject*)&obj) to allow
 73:                           destroying any PETSc object.
 74: */

 76: typedef struct {
 77:   PetscErrorCode (*view)(PetscObject, PetscViewer);
 78:   PetscErrorCode (*destroy)(PetscObject *);
 79: } PetscOps;

 81: /*E
 82:    PetscFortranCallbackType  - Indicates if a Fortran callback stored in a `PetscObject` is associated with the class or the current particular type of the object

 84:   Values:
 85: + `PETSC_FORTRAN_CALLBACK_CLASS`   - the callback is associated with the class
 86: - `PETSC_FORTRAN_CALLBACK_SUBTYPE` - the callback is associated with the current particular subtype

 88:   Level: developer

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

 95: .seealso: `PetscFortranCallbackFn`, `PetscObjectSetFortranCallback()`, `PetscObjectGetFortranCallback()`, `PetscObjectChangeTypeName()`
 96: E*/
 97: typedef enum {
 98:   PETSC_FORTRAN_CALLBACK_CLASS,
 99:   PETSC_FORTRAN_CALLBACK_SUBTYPE,
100:   PETSC_FORTRAN_CALLBACK_MAXTYPE
101: } PetscFortranCallbackType;

103: typedef size_t PetscFortranCallbackId;
104: #define PETSC_SMALLEST_FORTRAN_CALLBACK ((PetscFortranCallbackId)1000)
105: PETSC_EXTERN PetscErrorCode PetscFortranCallbackRegister(PetscClassId, const char *, PetscFortranCallbackId *);
106: PETSC_EXTERN PetscErrorCode PetscFortranCallbackGetSizes(PetscClassId, PetscFortranCallbackId *, PetscFortranCallbackId *);

108: /*S
109:   PetscFortranCallbackFn - A prototype of a Fortran function provided as a callback

111:   Level: advanced

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

116: .seealso: `PetscVoidFn`, `PetscErrorCodeFn`
117: S*/
118: PETSC_EXTERN_TYPEDEF typedef void(PetscFortranCallbackFn)(void);

120: typedef struct {
121:   PetscFortranCallbackFn *func;
122:   void                   *ctx;
123: } PetscFortranCallback;

125: /*
126:    All PETSc objects begin with the fields defined in PETSCHEADER.
127:    The PetscObject is a way of examining these fields regardless of
128:    the specific object. In C++ this could be a base abstract class
129:    from which all objects are derived.
130: */
131: #define PETSC_MAX_OPTIONS_HANDLER 5
132: typedef struct _p_PetscObject {
133:   PetscOps      bops[1];
134:   PetscClassId  classid;
135:   MPI_Comm      comm;
136:   PetscObjectId id; /* this is used to compare object for identity that may no longer exist since memory addresses get recycled for new objects */
137:   PetscInt      refct;
138:   PetscErrorCode (*non_cyclic_references)(PetscObject, PetscInt *);
139:   PetscInt64        cidx;
140:   PetscMPIInt       tag;
141:   PetscFunctionList qlist;
142:   PetscObjectList   olist;
143:   char             *class_name; /*  for example, "Vec" */
144:   char             *description;
145:   char             *mansec;
146:   char             *type_name; /*  this is the subclass, for example VECSEQ which equals "seq" */
147:   char             *name;
148:   char             *prefix;
149:   PetscInt          tablevel;
150:   void             *cpp;
151:   PetscObjectState  state;
152:   PetscInt          int_idmax, intstar_idmax;
153:   PetscObjectState *intcomposedstate, *intstarcomposedstate;
154:   PetscInt         *intcomposeddata, **intstarcomposeddata;
155:   PetscInt          real_idmax, realstar_idmax;
156:   PetscObjectState *realcomposedstate, *realstarcomposedstate;
157:   PetscReal        *realcomposeddata, **realstarcomposeddata;
158: #if PetscDefined(USE_COMPLEX)
159:   PetscInt          scalar_idmax, scalarstar_idmax;
160:   PetscObjectState *scalarcomposedstate, *scalarstarcomposedstate;
161:   PetscScalar      *scalarcomposeddata, **scalarstarcomposeddata;
162: #endif
163:   PetscFortranCallbackFn **fortran_func_pointers;     /* used by Fortran interface functions to stash user provided Fortran functions */
164:   PetscFortranCallbackId   num_fortran_func_pointers; /* number of Fortran function pointers allocated */
165:   PetscFortranCallback    *fortrancallback[PETSC_FORTRAN_CALLBACK_MAXTYPE];
166:   PetscFortranCallbackId   num_fortrancallback[PETSC_FORTRAN_CALLBACK_MAXTYPE];
167:   void                    *python_context;
168:   PetscErrorCode (*python_destroy)(void *);

170:   PetscInt noptionhandler;
171:   PetscErrorCode (*optionhandler[PETSC_MAX_OPTIONS_HANDLER])(PetscObject, PetscOptionItems, PetscCtx);
172:   PetscErrorCode (*optiondestroy[PETSC_MAX_OPTIONS_HANDLER])(PetscObject, PetscCtxRt);
173:   void *optionctx[PETSC_MAX_OPTIONS_HANDLER];
174: #if PetscDefined(HAVE_SAWS)
175:   PetscBool amsmem;          /* if PETSC_TRUE then this object is registered with SAWs and visible to clients */
176:   PetscBool amspublishblock; /* if PETSC_TRUE and publishing objects then will block at PetscObjectSAWsBlock() */
177: #endif
178:   PetscOptions options; /* options database used, NULL means default */
179:   PetscBool    optionsprinted;
180:   PetscBool    donotPetscObjectPrintClassNamePrefixType;
181: } _p_PetscObject;

183: #define PETSCHEADER(ObjectOps) \
184:   _p_PetscObject hdr; \
185:   ObjectOps      ops[1]

187: #define PETSCFREEDHEADER -1

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

192:   Calling Sequence:
193: . obj - the `PetscObject` to destroy

195:   Level: beginner

197:   Note:
198:   The deprecated `PetscObjectDestroyFunction` works as a replacement for `PetscObjectDestroyFn` *.

200: .seealso: `PetscObject`, `PetscObjectDestroy()`
201: S*/
202: PETSC_EXTERN_TYPEDEF typedef PetscErrorCode PetscObjectDestroyFn(PetscObject *obj);

204: PETSC_EXTERN_TYPEDEF typedef PetscObjectDestroyFn *PetscObjectDestroyFunction;

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

209:   Calling Sequence:
210: + obj - the `PetscObject` to view
211: - v - the viewer

213:   Level: beginner

215:   Note:
216:   The deprecated `PetscObjectViewFunction` works as a replacement for `PetscObjectViewFn` *.

218: .seealso: `PetscObject`, `PetscObjectDestroy()`, `PetscViewer`, `PetscObjectView()`
219: S*/
220: PETSC_EXTERN_TYPEDEF typedef PetscErrorCode PetscObjectViewFn(PetscObject obj, PetscViewer v);

222: PETSC_EXTERN_TYPEDEF typedef PetscObjectViewFn *PetscObjectViewFunction;

224: /*MC
225:     PetscHeaderCreate - Creates a raw PETSc object of a particular class

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

231:   Collective

233:   Input Parameters:
234: + classid    - The classid associated with this object (for example `VEC_CLASSID`)
235: . class_name - String name of class; should be static (for example "Vec"), may be `PETSC_NULLPTR`
236: . descr      - String containing short description; should be static (for example "Vector"), may be `PETSC_NULLPTR`
237: . mansec     - String indicating section in manual pages; should be static (for example "Vec"), may be `PETSC_NULLPTR`.
238:                It also selects the options blocks this object opens for `-help mansec`; an object with no manual
239:                section has none of its blocks selected
240: . comm       - The MPI Communicator
241: . destroy    - The destroy routine for this object (for example `VecDestroy()`)
242: - view       - The view routine for this object (for example `VecView()`), may be `PETSC_NULLPTR`

244:   Output Parameter:
245: . h - The newly created `PetscObject`

247:   Level: developer

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

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

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

262:   Example Usage:
263:   Existing `PetscObject`s may be easily created as shown. An object of type `Name` has
264:   `destroy` and `view` functions named `NameDestroy()` and `NameView()`.
265: .vb
266:   Vec v;

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

271:   It is possible to create custom `PetscObject`s, note however that they must abide by the
272:   restrictions set forth above.
273: .vb
274:   // OK, first member of C structure is _p_PetscObject
275:   struct MyCPetscObject_s
276:   {
277:     _p_PetscObject header;
278:     int            some_data;
279:   };
280:   typedef struct *MyCPetscObject_s MyCPetscObject;

282:   PetscErrorCode MyObjectDestroy(MyObject *);
283:   PetscErrorCode MyObjectView(MyObject);

285:   MyCPetscObject obj;

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

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

293:   // ERROR must be a single-level pointer
294:   PetscHeaderCreate(&obj, ...);
295: .ve

297:   Illustrating proper construction from C++\:
298: .vb
299:   // ERROR, class is not standard layout, first member must be publicly accessible
300:   class BadCppPetscObject
301:   {
302:     _p_PetscObject header;
303:   };

305:   // ERROR, class is not standard layout, has a virtual function and virtual inheritance
306:   class BadCppPetscObject2 : virtual BaseClass
307:   {
308:   public:
309:     _p_PetscObject header;

311:     virtual void foo();
312:   };

314:   // ERROR, class is not standard layout! Has non-standard layout member
315:   class BadCppPetscObject2
316:   {
317:   public:
318:     _p_PetscObject    header;
319:     BadCppPetscObject non_standard_layout;
320:   };

322:   // OK, class is standard layout!
323:   class GoodCppPetscObject;
324:   using MyCppObject = GoodCppPetscObject *;

326:   // OK, non-virtual inheritance of other standard layout class does not affect layout
327:   class GoodCppPetscObject : StandardLayoutClass
328:   {
329:   public:
330:     // OK, non standard layout member is static, does not affect layout
331:     static BadCppPetscObject non_standard_layout;

333:     // OK, first non-static member is _p_PetscObject
334:     _p_PetscObject header;

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

339:     // OK, may use "member" functions for destroy and view so long as they are static
340:     static PetscErrorCode destroy(MyCppObject *);
341:     static PetscErrorCode view(MyCppObject);
342:   };

344:   // OK, usage via pointer
345:   MyObject obj;

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

350: .seealso: `PetscObject`, `PetscHeaderDestroy()`, `PetscClassIdRegister()`
351: M*/
352: #define PetscHeaderCreate(h, classid, class_name, descr, mansec, comm, destroy, view) \
353:   PetscHeaderCreate_Function(PetscNew(&(h)), (PetscObject *)&(h), (classid), (class_name), (descr), (mansec), (comm), (PetscObjectDestroyFn *)(destroy), (PetscObjectViewFn *)(view))

355: PETSC_EXTERN PetscErrorCode PetscHeaderCreate_Function(PetscErrorCode, PetscObject *, PetscClassId, const char[], const char[], const char[], MPI_Comm, PetscObjectDestroyFn *, PetscObjectViewFn *);
356: PETSC_EXTERN PetscErrorCode PetscHeaderCreate_Private(PetscObject, PetscClassId, const char[], const char[], const char[], MPI_Comm, PetscObjectDestroyFn *, PetscObjectViewFn *);
357: PETSC_EXTERN PetscErrorCode PetscHeaderDestroy_Function(PetscObject *);
358: PETSC_EXTERN PetscErrorCode PetscComposedQuantitiesDestroy(PetscObject obj);
359: PETSC_INTERN PetscObjectId  PetscObjectNewId_Internal(void);

361: /*MC
362:   PetscHeaderDestroy - Final step in destroying a `PetscObject`

364:   Synopsis:
365: #include <petsc/private/petscimpl.h>
366:   PetscErrorCode PetscHeaderDestroy(PetscObject *obj)

368:   Collective

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

373:   Level: developer

375:   Notes:
376:   `h` is freed and set to `PETSC_NULLPTR` when this routine returns.

378:   Example Usage:
379: .vb
380:   PetscObject obj;

382:   PetscHeaderCreate(obj, ...);
383:   // use obj...

385:   // note pointer to obj is used
386:   PetscHeaderDestroy(&obj);
387: .ve

389:   Note that this routine is the _last_ step when destroying higher-level `PetscObject`s as it
390:   deallocates the memory for the structure itself\:
391: .vb
392:   typedef struct MyPetscObject_s *MyPetscObject;
393:   struct MyPetscObject_s
394:   {
395:     _p_PetscObject  hdr;
396:     PetscInt       *foo;
397:     PetscScalar    *bar;
398:   };

400:   // assume obj is created/initialized elsewhere...
401:   MyPetscObject obj;

403:   // OK, should dispose of all dynamically allocated resources before calling
404:   // PetscHeaderDestroy()
405:   PetscFree(obj->foo);

407:   // OK, dispose of obj
408:   PetscHeaderDestroy(&obj);

410:   // ERROR, obj points to NULL here, accessing obj->bar may result in segmentation violation!
411:   // obj->bar is potentially leaked!
412:   PetscFree(obj->bar);
413: .ve

415: .seealso: `PetscObject`, `PetscHeaderCreate()`
416: M*/
417: #define PetscHeaderDestroy(h) PetscHeaderDestroy_Function((PetscObject *)(h))

419: PETSC_EXTERN PetscErrorCode                PetscHeaderDestroy_Private(PetscObject, PetscBool);
420: PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode PetscHeaderReset_Internal(PetscObject);
421: PETSC_EXTERN PetscErrorCode                PetscObjectCopyFortranFunctionPointers(PetscObject, PetscObject);
422: PETSC_EXTERN PetscErrorCode                PetscObjectSetFortranCallback(PetscObject, PetscFortranCallbackType, PetscFortranCallbackId *, PetscFortranCallbackFn *, PetscCtx ctx);
423: PETSC_EXTERN PetscErrorCode                PetscObjectGetFortranCallback(PetscObject, PetscFortranCallbackType, PetscFortranCallbackId, PetscFortranCallbackFn **, void **ctx);

425: PETSC_INTERN PetscErrorCode                PetscCitationsInitialize(void);
426: PETSC_INTERN PetscErrorCode                PetscFreeMPIResources(void);
427: PETSC_INTERN PetscErrorCode                PetscOptionsHasHelpIntro_Internal(PetscOptions, PetscBool *);
428: PETSC_INTERN PetscErrorCode                PetscOptionsHelpManSecs_Internal(PetscOptions, PetscInt *, const char *const *[]);
429: PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode PetscOptionsHelpPrintable_Internal(PetscOptions, const char[], PetscBool *);

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

434: #if PetscDefined(HAVE_SETJMP_H)
435: PETSC_EXTERN PetscBool PetscCheckPointer(const void *, PetscDataType);
436: #else
437:   #define PetscCheckPointer(ptr, data_type) ((ptr) ? PETSC_TRUE : PETSC_FALSE)
438: #endif

440: #if PetscDefined(CLANG_STATIC_ANALYZER)
441: template <typename T>
443: template <typename T>
445: template <typename T>
447: template <typename T>
448: extern void PetscAssertPointer(T, int)
449: {
450: }
451: template <typename T>
453: #else
454:   // Macros to test if a PETSc object is valid and if pointers are valid
455:   #if PetscDefined(USE_DEBUG)
456:     /*  This check is for subtype methods such as DMDAGetCorners() that do not use the PetscTryMethod() or PetscUseMethod() paradigm */
458:       do { \
459:         PetscBool _7_same; \
461:         PetscCall(PetscObjectTypeCompare((PetscObject)(h), t, &_7_same)); \
462:         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); \
463:       } while (0)

465:     #define PetscAssertPointer_Internal(ptr, arg, ptype, ptrtype) \
466:       do { \
467:         PetscCheck(ptr, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Null Pointer: Parameter # %d", arg); \
468:         PetscCheck(PetscCheckPointer(ptr, ptype), PETSC_COMM_SELF, PETSC_ERR_ARG_BADPTR, "Invalid Pointer to %s: Argument '" PetscStringize(ptr) "' (parameter # %d)", ptrtype, arg); \
469:       } while (0)

472:       do { \
473:         PetscAssertPointer_Internal(h, arg, PETSC_OBJECT, "PetscObject"); \
474:         if (((PetscObject)(h))->classid != ck) { \
475:           PetscCheck(((PetscObject)(h))->classid != PETSCFREEDHEADER, PETSC_COMM_SELF, PETSC_ERR_ARG_CORRUPT, "Object already free: Parameter # %d", arg); \
476:           SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Wrong type of object: Parameter # %d", arg); \
477:         } \
478:       } while (0)

481:       do { \
482:         PetscAssertPointer_Internal(h, arg, PETSC_OBJECT, "PetscObject"); \
483:         PetscCheck(((PetscObject)(h))->classid != PETSCFREEDHEADER, PETSC_COMM_SELF, PETSC_ERR_ARG_CORRUPT, "Object already free: Parameter # %d", arg); \
484:         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); \
485:       } while (0)

487:     #if defined(__cplusplus)
488:       #include <type_traits> // std::decay

490: namespace Petsc
491: {

493: namespace util
494: {

496: template <typename T>
497: struct PetscAssertPointerImpl {
498:   PETSC_NODISCARD static constexpr PetscDataType type() noexcept { return PETSC_CHAR; }
499:   PETSC_NODISCARD static constexpr const char   *string() noexcept { return "memory"; }
500: };

502:       #define PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(T, PETSC_TYPE) \
503:         template <> \
504:         struct PetscAssertPointerImpl<T *> { \
505:           PETSC_NODISCARD static constexpr PetscDataType type() noexcept { return PETSC_TYPE; } \
506:           PETSC_NODISCARD static constexpr const char   *string() noexcept { return PetscStringize(T); } \
507:         }; \
508:         template <> \
509:         struct PetscAssertPointerImpl<const T *> : PetscAssertPointerImpl<T *> { }; \
510:         template <> \
511:         struct PetscAssertPointerImpl<volatile T *> : PetscAssertPointerImpl<T *> { }; \
512:         template <> \
513:         struct PetscAssertPointerImpl<const volatile T *> : PetscAssertPointerImpl<T *> { }

515: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(char, PETSC_CHAR);
516: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(signed char, PETSC_CHAR);
517: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(unsigned char, PETSC_CHAR);
518: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(short, PETSC_SHORT);
519: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(unsigned short, PETSC_SHORT);
520: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(PetscBool, PETSC_BOOL);
521: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(float, PETSC_FLOAT);
522: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(double, PETSC_DOUBLE);
523: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(int32_t, PETSC_INT32);
524: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(uint32_t, PETSC_INT32);
525: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(int64_t, PETSC_INT64);
526: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(uint64_t, PETSC_INT64);
527:       #if PetscDefined(HAVE_COMPLEX)
528: PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION(PetscComplex, PETSC_COMPLEX);
529:       #endif

531:       #undef PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION

533: } // namespace util

535: } // namespace Petsc

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

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

543:       #if PetscDefined(HAVE_COMPLEX)
544:         #define PETSC_GENERIC_CV_COMPLEX(result) , PETSC_GENERIC_CV(PetscComplex, result)
545:       #else
546:         #define PETSC_GENERIC_CV_COMPLEX(result)
547:       #endif

549:       #define PetscAssertPointer_PetscDataType(h) \
550:         _Generic((h), \
551:           default: PETSC_CHAR, \
552:           PETSC_GENERIC_CV(          char, PETSC_CHAR), \
553:           PETSC_GENERIC_CV(   signed char, PETSC_CHAR), \
554:           PETSC_GENERIC_CV( unsigned char, PETSC_CHAR), \
555:           PETSC_GENERIC_CV(         short, PETSC_SHORT), \
556:           PETSC_GENERIC_CV(unsigned short, PETSC_SHORT), \
557:           PETSC_GENERIC_CV(         float, PETSC_FLOAT), \
558:           PETSC_GENERIC_CV(        double, PETSC_DOUBLE), \
559:           PETSC_GENERIC_CV(       int32_t, PETSC_INT32), \
560:           PETSC_GENERIC_CV(      uint32_t, PETSC_INT32), \
561:           PETSC_GENERIC_CV(       int64_t, PETSC_INT64), \
562:           PETSC_GENERIC_CV(      uint64_t, PETSC_INT64) \
563:           PETSC_GENERIC_CV_COMPLEX(PETSC_COMPLEX))

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

567:       #if PetscDefined(HAVE_COMPLEX)
568:         #define PETSC_GENERIC_CV_STRINGIZE_COMPLEX , PETSC_GENERIC_CV_STRINGIZE(PetscComplex)
569:       #else
570:         #define PETSC_GENERIC_CV_STRINGIZE_COMPLEX
571:       #endif

573:       #define PetscAssertPointer_String(h) \
574:         _Generic((h), \
575:           default: "memory", \
576:           PETSC_GENERIC_CV_STRINGIZE(char), \
577:           PETSC_GENERIC_CV_STRINGIZE(signed char), \
578:           PETSC_GENERIC_CV_STRINGIZE(unsigned char), \
579:           PETSC_GENERIC_CV_STRINGIZE(short), \
580:           PETSC_GENERIC_CV_STRINGIZE(unsigned short), \
581:           PETSC_GENERIC_CV_STRINGIZE(float), \
582:           PETSC_GENERIC_CV_STRINGIZE(double), \
583:           PETSC_GENERIC_CV_STRINGIZE(int32_t), \
584:           PETSC_GENERIC_CV_STRINGIZE(uint32_t), \
585:           PETSC_GENERIC_CV_STRINGIZE(int64_t), \
586:           PETSC_GENERIC_CV_STRINGIZE(uint64_t) \
587:           PETSC_GENERIC_CV_STRINGIZE_COMPLEX)
588:     #else // PETSC_C_VERSION >= 11 || defined(__cplusplus)
589:       #define PetscAssertPointer_PetscDataType(h) PETSC_CHAR
590:       #define PetscAssertPointer_String(h)        "memory"
591:     #endif // PETSC_C_VERSION >= 11 || defined(__cplusplus)
592:     #define PetscAssertPointer(h, arg) PetscAssertPointer_Internal(h, arg, PetscAssertPointer_PetscDataType(h), PetscAssertPointer_String(h))
594:   #else // PetscDefined(USE_DEBUG)
596:       do { \
597:         (void)(h); \
598:       } while (0)
600:       do { \
601:         (void)(h); \
602:       } while (0)
604:       do { \
605:         (void)(h); \
606:       } while (0)
607:     #define PetscAssertPointer(h, arg) \
608:       do { \
609:         (void)(h); \
610:       } while (0)
612:       do { \
613:         (void)(h); \
614:       } while (0)
615:   #endif // PetscDefined(USE_DEBUG)
616: #endif   // PETSC_CLANG_STATIC_ANALYZER


627: #define PetscSorted(n, idx, sorted) \
628:   do { \
629:     (sorted) = PETSC_TRUE; \
630:     for (PetscCount _i_ = 1; _i_ < (n); ++_i_) { \
631:       if ((idx)[_i_] < (idx)[_i_ - 1]) { \
632:         (sorted) = PETSC_FALSE; \
633:         break; \
634:       } \
635:     } \
636:   } while (0)

638: #if !PetscDefined(CLANG_STATIC_ANALYZER)
639:   #if !PetscDefined(USE_DEBUG)

641:     #define PetscCheckSameType(a, arga, b, argb) \
642:       do { \
643:         (void)(a); \
644:         (void)(b); \
645:       } while (0)
646:     #define PetscCheckTypeName(a, type) \
647:       do { \
648:         (void)(a); \
649:       } while (0)
650:     #define PetscCheckTypeNames(a, type1, type2) \
651:       do { \
652:         (void)(a); \
653:       } while (0)
655:       do { \
656:         (void)(a); \
657:       } while (0)
658:     #define PetscCheckSameComm(a, arga, b, argb) \
659:       do { \
660:         (void)(a); \
661:         (void)(b); \
662:       } while (0)
663:     #define PetscCheckSameTypeAndComm(a, arga, b, argb) \
664:       do { \
665:         (void)(a); \
666:         (void)(b); \
667:       } while (0)
669:       do { \
670:         (void)(a); \
671:         (void)(b); \
672:       } while (0)
674:       do { \
675:         (void)(a); \
676:         (void)(b); \
677:       } while (0)
679:       do { \
680:         (void)(a); \
681:         (void)(b); \
682:       } while (0)
684:       do { \
685:         (void)(a); \
686:         (void)(b); \
687:       } while (0)
689:       do { \
690:         (void)(a); \
691:         (void)(b); \
692:       } while (0)
694:       do { \
695:         (void)(a); \
696:         (void)(b); \
697:       } while (0)
699:       do { \
700:         (void)(a); \
701:         (void)(b); \
702:       } while (0)
704:       do { \
705:         (void)(a); \
706:         (void)(b); \
707:       } while (0)
708:     #define PetscCheckSorted(n, idx) \
709:       do { \
710:         (void)(n); \
711:         (void)(idx); \
712:       } while (0)

714:   #else

716:     #define PetscCheckSameType(a, arga, b, argb) \
717:       do { \
718:         PetscBool pcst_type_eq_ = PETSC_TRUE; \
719:         PetscCall(PetscStrcmp(((PetscObject)(a))->type_name, ((PetscObject)(b))->type_name, &pcst_type_eq_)); \
720:         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); \
721:       } while (0)

723:     /*
724:     Check type_name
725: */
726:     #define PetscCheckTypeName(a, type) \
727:       do { \
728:         PetscBool _7_match; \
729:         PetscCall(PetscObjectTypeCompare(((PetscObject)(a)), (type), &_7_match)); \
730:         PetscCheck(_7_match, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Object (%s) is not %s", ((PetscObject)(a))->type_name, type); \
731:       } while (0)

733:     #define PetscCheckTypeNames(a, type1, type2) \
734:       do { \
735:         PetscBool _7_match; \
736:         PetscCall(PetscObjectTypeCompareAny(((PetscObject)(a)), &_7_match, (type1), (type2), "")); \
737:         PetscCheck(_7_match, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Object (%s) is not %s or %s", ((PetscObject)(a))->type_name, type1, type2); \
738:       } while (0)

740:     /*
741:    Use this macro to check if the type is set
742: */

745:     /*
746:    Sometimes object must live on same communicator to inter-operate
747: */
748:     #define PetscCheckSameComm(a, arga, b, argb) \
749:       do { \
750:         PetscMPIInt _7_flag; \
751:         PetscCallMPI(MPI_Comm_compare(PetscObjectComm((PetscObject)(a)), PetscObjectComm((PetscObject)(b)), &_7_flag)); \
752:         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); \
753:       } while (0)

755:     #define PetscCheckSameTypeAndComm(a, arga, b, argb) \
756:       do { \
757:         PetscCheckSameType(a, arga, b, argb); \
758:         PetscCheckSameComm(a, arga, b, argb); \
759:       } while (0)

762:       do { \
763:         PetscScalar b0 = (b); \
764:         PetscReal   b1[5]; \
765:         if (PetscIsNanScalar(b0)) { \
766:           b1[4] = 1; \
767:         } else { \
768:           b1[4] = 0; \
769:         }; \
770:         b1[0] = -PetscRealPart(b0); \
771:         b1[1] = PetscRealPart(b0); \
772:         b1[2] = -PetscImaginaryPart(b0); \
773:         b1[3] = PetscImaginaryPart(b0); \
774:         PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, b1, 5, MPIU_REAL, MPIU_MAX, PetscObjectComm((PetscObject)(a)))); \
775:         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); \
776:       } while (0)

779:       do { \
780:         PetscReal b0 = (b), b1[3]; \
781:         if (PetscIsNanReal(b0)) { \
782:           b1[2] = 1; \
783:         } else { \
784:           b1[2] = 0; \
785:         }; \
786:         b1[0] = -b0; \
787:         b1[1] = b0; \
788:         PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, b1, 3, MPIU_REAL, MPIU_MAX, PetscObjectComm((PetscObject)(a)))); \
789:         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); \
790:       } while (0)

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

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

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

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

829:       do { \
830:         PetscBool b0 = (PetscBool)(b), b1[2]; \
831:         b1[0]        = !b0; \
832:         b1[1]        = b0; \
833:         PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, b1, 2, MPI_C_BOOL, MPI_LAND, PetscObjectComm((PetscObject)(a)))); \
834:         PetscCheck(!b1[0] == b1[1], PetscObjectComm((PetscObject)(a)), PETSC_ERR_ARG_WRONG, "Bool value must be same on all processes, argument # %d", arg); \
835:       } while (0)

838:       do { \
839:         PetscMPIInt b0 = (PetscMPIInt)(b), b1[2]; \
840:         b1[0]          = -b0; \
841:         b1[1]          = b0; \
842:         PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, b1, 2, MPI_INT, MPI_MAX, PetscObjectComm((PetscObject)(a)))); \
843:         PetscCheck(-b1[0] == b1[1], PetscObjectComm((PetscObject)(a)), PETSC_ERR_ARG_WRONG, "Enum value must be same on all processes, argument # %d", arg); \
844:       } while (0)

846:     #define PetscCheckSorted(n, idx) \
847:       do { \
848:         PetscBool _1_flg; \
849:         PetscSorted(n, idx, _1_flg); \
850:         PetscCheck(_1_flg, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Input array needs to be sorted"); \
851:       } while (0)

853:   #endif
854: #else  /* PETSC_CLANG_STATIC_ANALYZER */
855: template <typename Ta, typename Tb>
856: extern void PetscCheckSameType(Ta, int, Tb, int);
857: template <typename Ta, typename Tb>
858: extern void PetscCheckTypeName(Ta, Tb);
859: template <typename Ta, typename Tb, typename Tc>
860: extern void PetscCheckTypeNames(Ta, Tb, Tc);
861: template <typename T>
863: template <typename Ta, typename Tb>
864: extern void PetscCheckSameComm(Ta, int, Tb, int);
865: template <typename Ta, typename Tb>
866: extern void PetscCheckSameTypeAndComm(Ta, int, Tb, int);
867: template <typename Ta, typename Tb>
869: template <typename Ta, typename Tb>
871: template <typename Ta, typename Tb>
873: template <typename Ta, typename Tb>
875: template <typename Ta, typename Tb>
877: template <typename Ta, typename Tb>
879: template <typename Ta, typename Tb>
881: template <typename T>
882: extern void PetscCheckSorted(PetscInt, T);
883: #endif /* PETSC_CLANG_STATIC_ANALYZER */

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

888:   Synopsis:
889:    #include "petsc/private/petscimpl.h"
890:    PetscTryMethod(PetscObject obj, const char *name, (arg_types), (arg_value))

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

898:    Level: developer

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

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

906: .seealso: `PetscUseMethod()`, `PetscCall()`, `PetscUseTypeMethod()`, `PetscTryTypeMethod()`, `PetscCheck()`, `PetscObject`
907: M*/
908: #define PetscTryMethod(obj, A, B, C) \
909:   do { \
910:     PetscErrorCode(*_7_f) B; \
911:     PetscCall(PetscObjectQueryFunction((PetscObject)(obj), A, &_7_f)); \
912:     if (_7_f) PetscCall((*_7_f)C); \
913:   } while (0)

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

918:   Synopsis:
919:    #include "petsc/private/petscimpl.h"
920:    PetscUseMethod(PetscObject obj, const char *name, (arg_types), (arg_value))

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

928:    Level: developer

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

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

936: .seealso: `PetscTryMethod()`, `PetscCall()`, `PetscUseTypeMethod()`, `PetscTryTypeMethod()`, `PetscCheck()`, `PetscObject`
937: M*/
938: #define PetscUseMethod(obj, A, B, C) \
939:   do { \
940:     PetscErrorCode(*_7_f) B; \
941:     PetscCall(PetscObjectQueryFunction((PetscObject)(obj), A, &_7_f)); \
942:     PetscCheck(_7_f, PetscObjectComm((PetscObject)(obj)), PETSC_ERR_SUP, "Cannot locate function %s in object", A); \
943:     PetscCall((*_7_f)C); \
944:   } while (0)

946: /*
947:   Use Microsoft traditional preprocessor.

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

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

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

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

960:   #define PetscUseTypeMethod(obj, OP, ...) \
961:     do { \
962:       PetscErrorCode ierr_p_; \
963:       PetscStackUpdateLine; \
964:       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); \
965:       ierr_p_ = (*(obj)->ops->OP)(obj, __VA_ARGS__); \
966:       PetscCall(ierr_p_); \
967:     } while (0)

969:   #define PetscTryTypeMethod(obj, OP, ...) \
970:     do { \
971:       if ((obj)->ops->OP) { \
972:         PetscErrorCode ierr_p_; \
973:         PetscStackUpdateLine; \
974:         ierr_p_ = (*(obj)->ops->OP)(obj, __VA_ARGS__); \
975:         PetscCall(ierr_p_); \
976:       } \
977:     } while (0)

979: #else

981:   /*MC
982:    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

984:   Synopsis:
985:    #include "petsc/private/petscimpl.h"
986:    PetscUseTypeMethod(obj, method, ...)

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

993:    Level: developer

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

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

1000: .seealso: `PetscTryMethod()`, `PetscUseMethod()`, `PetscCall()`, `PetscCheck()`, `PetscTryTypeMethod()`, `PetscCallBack()`
1001: M*/
1002:   #define PetscUseTypeMethod(obj, ...) \
1003:     do { \
1004:       PetscCheck((obj)->ops->PETSC_FIRST_ARG((__VA_ARGS__, unused)), PetscObjectComm((PetscObject)(obj)), PETSC_ERR_SUP, "No method %s for %s of type %s", \
1005:                  PetscStringize(PETSC_FIRST_ARG((__VA_ARGS__,unused))), ((PetscObject)(obj))->class_name, ((PetscObject)(obj))->type_name); \
1006:       PetscCall((*(obj)->ops->PETSC_FIRST_ARG((__VA_ARGS__, unused)))(obj PETSC_REST_ARG(__VA_ARGS__))); \
1007:     } while (0)

1009:   /*MC
1010:    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

1012:   Synopsis:
1013:    #include "petsc/private/petscimpl.h"
1014:    PetscTryTypeMethod(obj, method, ...)

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

1021:    Level: developer

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

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

1028: .seealso: `PetscTryMethod()`, `PetscUseMethod()`, `PetscCall()`, `PetscCheck()`, `PetscUseTypeMethod()`
1029: M*/
1030:   #define PetscTryTypeMethod(obj, ...) \
1031:     do { \
1032:       if ((obj)->ops->PETSC_FIRST_ARG((__VA_ARGS__, unused))) PetscCall((*(obj)->ops->PETSC_FIRST_ARG((__VA_ARGS__, unused)))(obj PETSC_REST_ARG(__VA_ARGS__))); \
1033:     } while (0)

1035: #endif

1037: /*MC
1038:    PetscObjectStateIncrease - Increases the state of any `PetscObject`

1040:    Synopsis:
1041:    #include "petsc/private/petscimpl.h"
1042:    PetscErrorCode PetscObjectStateIncrease(PetscObject obj)

1044:    Logically Collective

1046:    Input Parameter:
1047: .  obj - any PETSc object, for example a `Vec`, `Mat` or `KSP`. This must be
1048:          cast with a (PetscObject), for example,
1049:          `PetscObjectStateIncrease`((`PetscObject`)mat);

1051:    Level: developer

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

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

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

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

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

1070: .seealso: `PetscObjectStateGet()`, `PetscObject`
1071: M*/
1072: #define PetscObjectStateIncrease(obj) ((PetscErrorCode)((obj)->state++, PETSC_SUCCESS))

1074: PETSC_EXTERN PetscErrorCode PetscObjectStateGet(PetscObject, PetscObjectState *);
1075: PETSC_EXTERN PetscErrorCode PetscObjectStateSet(PetscObject, PetscObjectState);
1076: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataRegister(PetscInt *);
1077: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseInt(PetscObject);
1078: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseIntstar(PetscObject);
1079: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseReal(PetscObject);
1080: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseRealstar(PetscObject);
1081: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseScalar(PetscObject);
1082: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseScalarstar(PetscObject);
1083: PETSC_EXTERN PetscInt       PetscObjectComposedDataMax;

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

1088:    Synopsis:
1089:    #include "petsc/private/petscimpl.h"
1090:    PetscErrorCode PetscObjectComposedDataSetInt(PetscObject obj, PetscInt id, PetscInt data)

1092:    Not Collective

1094:    Input Parameters:
1095: +  obj - the object to which data is to be attached
1096: .  id - the identifier for the data
1097: -  data - the data to  be attached, a `PetscInt`

1099:    Level: developer

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

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

1107: .seealso: `PetscObjectComposedDataGetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetReal()`,
1108:           `PetscObjectComposedDataGetIntstar()`, `PetscObjectComposedDataSetIntstar()`, `PetscObject`,
1109:           `PetscObjectCompose()`, `PetscObjectQuery()`
1110: M*/
1111: #define PetscObjectComposedDataSetInt(obj, id, data) \
1112:   ((PetscErrorCode)((((obj)->int_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseInt(obj)) || ((obj)->intcomposeddata[id] = data, (obj)->intcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))

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

1117:    Synopsis:
1118:    #include "petsc/private/petscimpl.h"
1119:    PetscErrorCode PetscObjectComposedDataGetInt(PetscObject obj, PetscInt id, PetscInt data, PetscBool flag)

1121:    Not Collective

1123:    Input Parameters:
1124: +  obj - the object from which data is to be retrieved
1125: -  id - the identifier for the data

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

1131:    Level: developer

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

1136: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetReal()`,
1137:           `PetscObjectComposedDataGetIntstar()`, `PetscObjectComposedDataSetIntstar()`, `PetscObject`,
1138:           `PetscObjectCompose()`, `PetscObjectQuery()`
1139: M*/
1140: #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))

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

1145:    Synopsis:
1146:    #include "petsc/private/petscimpl.h"
1147:    PetscErrorCode PetscObjectComposedDataSetIntstar(PetscObject obj, PetscInt id, PetscInt *data)

1149:    Not Collective

1151:    Input Parameters:
1152: +  obj - the object to which data is to be attached
1153: .  id - the identifier for the data
1154: -  data - the data to  be attached, a `PetscInt` array

1156:    Level: developer

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

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

1163: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetReal()`,
1164:           `PetscObjectComposedDataGetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1165:           `PetscObjectCompose()`, `PetscObjectQuery()`
1166: M*/
1167: #define PetscObjectComposedDataSetIntstar(obj, id, data) \
1168:   ((PetscErrorCode)((((obj)->intstar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseIntstar(obj)) || ((obj)->intstarcomposeddata[id] = data, (obj)->intstarcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))

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

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

1177:    Not Collective

1179:    Input Parameters:
1180: +  obj - the object from which data is to be retrieved
1181: -  id - the identifier for the data

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

1187:    Level: developer

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

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

1194: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetReal()`,
1195:           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1196:           `PetscObjectCompose()`, `PetscObjectQuery()`
1197: M*/
1198: #define PetscObjectComposedDataGetIntstar(obj, id, data, flag) \
1199:   ((PetscErrorCode)(((obj)->intstarcomposedstate ? (data = (obj)->intstarcomposeddata[id], flag = (PetscBool)((obj)->intstarcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), PETSC_SUCCESS))

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

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

1208:    Not Collective

1210:    Input Parameters:
1211: +  obj - the object to which data is to be attached
1212: .  id - the identifier for the data
1213: -  data - the data to  be attached, a `PetscReal`

1215:    Level: developer

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

1220: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1221:           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1222:           `PetscObjectCompose()`, `PetscObjectQuery()`
1223: M*/
1224: #define PetscObjectComposedDataSetReal(obj, id, data) \
1225:   ((PetscErrorCode)((((obj)->real_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseReal(obj)) || ((obj)->realcomposeddata[id] = data, (obj)->realcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))

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

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

1234:    Not Collective

1236:    Input Parameters:
1237: +  obj - the object from which data is to be retrieved
1238: -  id - the identifier for the data

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

1244:    Level: developer

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

1249: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataSetIntstar()`,
1250:           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1251:           `PetscObjectCompose()`, `PetscObjectQuery()`
1252: M*/
1253: #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))

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

1258:    Synopsis:
1259:    #include "petsc/private/petscimpl.h"
1260:    PetscErrorCode PetscObjectComposedDataSetRealstar(PetscObject obj, PetscInt id, PetscReal *data)

1262:    Not Collective

1264:    Input Parameters:
1265: +  obj - the object to which data is to be attached
1266: .  id - the identifier for the data
1267: -  data - the data to  be attached

1269:    Level: developer

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

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

1276: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1277:           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1278:           `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataGetRealstar()`
1279: M*/
1280: #define PetscObjectComposedDataSetRealstar(obj, id, data) \
1281:   ((PetscErrorCode)((((obj)->realstar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseRealstar(obj)) || ((obj)->realstarcomposeddata[id] = data, (obj)->realstarcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))

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

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

1290:    Not Collective

1292:    Input Parameters:
1293: +  obj - the object from which data is to be retrieved
1294: -  id - the identifier for the data

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

1300:    Level: developer

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

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

1307: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1308:           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1309:           `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`
1310: M*/
1311: #define PetscObjectComposedDataGetRealstar(obj, id, data, flag) \
1312:   ((PetscErrorCode)(((obj)->realstarcomposedstate ? (data = (obj)->realstarcomposeddata[id], flag = (PetscBool)((obj)->realstarcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), PETSC_SUCCESS))

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

1317:    Synopsis:
1318:    #include "petsc/private/petscimpl.h"
1319:    PetscErrorCode PetscObjectComposedDataSetScalar(PetscObject obj, PetscInt id, PetscScalar data)

1321:    Not Collective

1323:    Input Parameters:
1324: +  obj - the object to which data is to be attached
1325: .  id - the identifier for the data
1326: -  data - the data to  be attached, a `PetscScalar`

1328:    Level: developer

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

1333: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1334:           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1335:           `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`, `PetscObjectComposedDataGetScalar()`
1336: M*/
1337: #if PetscDefined(USE_COMPLEX)
1338:   #define PetscObjectComposedDataSetScalar(obj, id, data) \
1339:     ((PetscErrorCode)((((obj)->scalar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseScalar(obj)) || ((obj)->scalarcomposeddata[id] = data, (obj)->scalarcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))
1340: #else
1341:   #define PetscObjectComposedDataSetScalar(obj, id, data) PetscObjectComposedDataSetReal(obj, id, data)
1342: #endif
1343: /*MC
1344:    PetscObjectComposedDataGetScalar - retrieve `PetscScalar` data attached to a `PetscObject` that was set with `PetscObjectComposedDataSetScalar()`

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

1350:    Not Collective

1352:    Input Parameters:
1353: +  obj - the object from which data is to be retrieved
1354: -  id - the identifier for the data

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

1360:    Level: developer

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

1365: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1366:           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1367:           `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`, `PetscObjectComposedDataSetScalar()`
1368: M*/
1369: #if PetscDefined(USE_COMPLEX)
1370:   #define PetscObjectComposedDataGetScalar(obj, id, data, flag) \
1371:     ((PetscErrorCode)(((obj)->scalarcomposedstate ? (data = (obj)->scalarcomposeddata[id], flag = (PetscBool)((obj)->scalarcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), PETSC_SUCCESS))
1372: #else
1373:   #define PetscObjectComposedDataGetScalar(obj, id, data, flag) PetscObjectComposedDataGetReal(obj, id, data, flag)
1374: #endif

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

1379:    Synopsis:
1380:    #include "petsc/private/petscimpl.h"
1381:    PetscErrorCode PetscObjectComposedDataSetScalarstar(PetscObject obj, PetscInt id, PetscScalar *data)

1383:    Not Collective

1385:    Input Parameters:
1386: +  obj - the object to which data is to be attached
1387: .  id - the identifier for the data
1388: -  data - the data to  be attached, a `PetscScalar` array

1390:    Level: developer

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

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

1397: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1398:           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1399:           `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`, `PetscObjectComposedDataGetScalarstar()`
1400: M*/
1401: #if PetscDefined(USE_COMPLEX)
1402:   #define PetscObjectComposedDataSetScalarstar(obj, id, data) \
1403:     ((PetscErrorCode)((((obj)->scalarstar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseScalarstar(obj)) || ((obj)->scalarstarcomposeddata[id] = data, (obj)->scalarstarcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))
1404: #else
1405:   #define PetscObjectComposedDataSetScalarstar(obj, id, data) PetscObjectComposedDataSetRealstar(obj, id, data)
1406: #endif
1407: /*MC
1408:    PetscObjectComposedDataGetScalarstar - retrieve `PetscScalar` array data attached to a `PetscObject` that was set with `PetscObjectComposedDataSetScalarstar()`
1409:    attached to an object

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

1415:    Not Collective

1417:    Input Parameters:
1418: +  obj - the object from which data is to be retrieved
1419: -  id - the identifier for the data

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

1425:    Level: developer

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

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

1432: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1433:           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1434:           `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`, `PetscObjectComposedDataSetScalarstar()`
1435: M*/
1436: #if PetscDefined(USE_COMPLEX)
1437:   #define PetscObjectComposedDataGetScalarstar(obj, id, data, flag) \
1438:     ((PetscErrorCode)(((obj)->scalarstarcomposedstate ? (data = (obj)->scalarstarcomposeddata[id], flag = (PetscBool)((obj)->scalarstarcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), PETSC_SUCCESS))
1439: #else
1440:   #define PetscObjectComposedDataGetScalarstar(obj, id, data, flag) PetscObjectComposedDataGetRealstar(obj, id, data, flag)
1441: #endif

1443: PETSC_INTERN PetscMPIInt Petsc_Counter_keyval;
1444: PETSC_INTERN PetscMPIInt Petsc_InnerComm_keyval;
1445: PETSC_INTERN PetscMPIInt Petsc_OuterComm_keyval;
1446: PETSC_INTERN PetscMPIInt Petsc_Seq_keyval;
1447: PETSC_INTERN PetscMPIInt Petsc_ShmComm_keyval;
1448: PETSC_EXTERN PetscMPIInt Petsc_CreationIdx_keyval;
1449: PETSC_INTERN PetscMPIInt Petsc_Garbage_HMap_keyval;

1451: PETSC_INTERN PetscMPIInt Petsc_SharedWD_keyval;
1452: PETSC_INTERN PetscMPIInt Petsc_SharedTmp_keyval;

1454: struct PetscCommStash {
1455:   struct PetscCommStash *next;
1456:   MPI_Comm               comm;
1457: };

1459: /*
1460:   PETSc communicators have this attribute, see
1461:   PetscCommDuplicate(), PetscCommDestroy(), PetscCommGetNewTag(), PetscObjectGetName()
1462: */
1463: typedef struct {
1464:   PetscMPIInt            tag;       /* next free tag value */
1465:   PetscInt               refcount;  /* number of references, communicator can be freed when this reaches 0 */
1466:   PetscInt               namecount; /* used to generate the next name, as in Vec_0, Mat_1, ... */
1467:   PetscMPIInt           *iflags;    /* length of comm size, shared by all calls to PetscCommBuildTwoSided_Allreduce/RedScatter on this comm */
1468:   struct PetscCommStash *comms;     /* communicators available for PETSc to pass off to other packages */
1469: } PetscCommCounter;

1471: typedef enum {
1472:   STATE_BEGIN,
1473:   STATE_PENDING,
1474:   STATE_END
1475: } SRState;

1477: typedef enum {
1478:   PETSC_SR_REDUCE_SUM = 0,
1479:   PETSC_SR_REDUCE_MAX = 1,
1480:   PETSC_SR_REDUCE_MIN = 2
1481: } PetscSRReductionType;

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

1502: PETSC_EXTERN PetscErrorCode PetscSplitReductionGet(MPI_Comm, PetscSplitReduction **);
1503: PETSC_EXTERN PetscErrorCode PetscSplitReductionEnd(PetscSplitReduction *);
1504: PETSC_EXTERN PetscErrorCode PetscSplitReductionExtend(PetscSplitReduction *);

1506: #if PetscDefined(HAVE_THREADSAFETY)
1507:   #if PetscDefined(HAVE_CONCURRENCYKIT)
1508:     #if defined(__cplusplus)
1509: /*  CK does not have extern "C" protection in their include files */
1510: extern "C" {
1511:     #endif
1512:     #include <ck_spinlock.h>
1513:     #if defined(__cplusplus)
1514: }
1515:     #endif
1516: typedef ck_spinlock_t PetscSpinlock;

1518: static inline PetscErrorCode PetscSpinlockCreate(PetscSpinlock *ck_spinlock)
1519: {
1520:   ck_spinlock_init(ck_spinlock);
1521:   return PETSC_SUCCESS;
1522: }
1523: static inline PetscErrorCode PetscSpinlockLock(PetscSpinlock *ck_spinlock)
1524: {
1525:   ck_spinlock_lock(ck_spinlock);
1526:   return PETSC_SUCCESS;
1527: }
1528: static inline PetscErrorCode PetscSpinlockUnlock(PetscSpinlock *ck_spinlock)
1529: {
1530:   ck_spinlock_unlock(ck_spinlock);
1531:   return PETSC_SUCCESS;
1532: }
1533: static inline PetscErrorCode PetscSpinlockDestroy(PetscSpinlock *ck_spinlock)
1534: {
1535:   return PETSC_SUCCESS;
1536: }
1537:   #elif (defined(__cplusplus) && PetscDefined(HAVE_CXX_ATOMIC)) || (!defined(__cplusplus) && PetscDefined(HAVE_STDATOMIC_H))
1538:     #if defined(__cplusplus)
1539:       // See the example at https://en.cppreference.com/w/cpp/atomic/atomic_flag
1540:       #include <atomic>
1541:       #define petsc_atomic_flag                 std::atomic_flag
1542:       #define petsc_atomic_flag_test_and_set(p) std::atomic_flag_test_and_set_explicit(p, std::memory_order_acquire)
1543:       #define petsc_atomic_flag_clear(p)        std::atomic_flag_clear_explicit(p, std::memory_order_release)
1544:     #else
1545:       #include <stdatomic.h>
1546:       #define petsc_atomic_flag                 atomic_flag
1547:       #define petsc_atomic_flag_test_and_set(p) atomic_flag_test_and_set_explicit(p, memory_order_acquire)
1548:       #define petsc_atomic_flag_clear(p)        atomic_flag_clear_explicit(p, memory_order_release)
1549:     #endif

1551: typedef petsc_atomic_flag PetscSpinlock;

1553: static inline PetscErrorCode PetscSpinlockCreate(PetscSpinlock *spinlock)
1554: {
1555:   petsc_atomic_flag_clear(spinlock);
1556:   return PETSC_SUCCESS;
1557: }
1558: static inline PetscErrorCode PetscSpinlockLock(PetscSpinlock *spinlock)
1559: {
1560:   do {
1561:   } while (petsc_atomic_flag_test_and_set(spinlock));
1562:   return PETSC_SUCCESS;
1563: }
1564: static inline PetscErrorCode PetscSpinlockUnlock(PetscSpinlock *spinlock)
1565: {
1566:   petsc_atomic_flag_clear(spinlock);
1567:   return PETSC_SUCCESS;
1568: }
1569: static inline PetscErrorCode PetscSpinlockDestroy(PETSC_UNUSED PetscSpinlock *spinlock)
1570: {
1571:   return PETSC_SUCCESS;
1572: }
1573:     #undef petsc_atomic_flag_test_and_set
1574:     #undef petsc_atomic_flag_clear
1575:     #undef petsc_atomic_flag

1577:   #elif PetscDefined(HAVE_OPENMP)

1579:     #include <omp.h>
1580: typedef omp_lock_t PetscSpinlock;

1582: static inline PetscErrorCode PetscSpinlockCreate(PetscSpinlock *omp_lock)
1583: {
1584:   omp_init_lock(omp_lock);
1585:   return PETSC_SUCCESS;
1586: }
1587: static inline PetscErrorCode PetscSpinlockLock(PetscSpinlock *omp_lock)
1588: {
1589:   omp_set_lock(omp_lock);
1590:   return PETSC_SUCCESS;
1591: }
1592: static inline PetscErrorCode PetscSpinlockUnlock(PetscSpinlock *omp_lock)
1593: {
1594:   omp_unset_lock(omp_lock);
1595:   return PETSC_SUCCESS;
1596: }
1597: static inline PetscErrorCode PetscSpinlockDestroy(PetscSpinlock *omp_lock)
1598: {
1599:   omp_destroy_lock(omp_lock);
1600:   return PETSC_SUCCESS;
1601: }
1602:   #else
1603:     #if defined(__cplusplus)
1604:       #error "Thread safety requires either --download-concurrencykit, std::atomic, or --with-openmp"
1605:     #else
1606:       #error "Thread safety requires either --download-concurrencykit, stdatomic.h, or --with-openmp"
1607:     #endif
1608:   #endif

1610: #else
1611: typedef int PetscSpinlock;
1612:   #define PetscSpinlockCreate(a)  PETSC_SUCCESS
1613:   #define PetscSpinlockLock(a)    PETSC_SUCCESS
1614:   #define PetscSpinlockUnlock(a)  PETSC_SUCCESS
1615:   #define PetscSpinlockDestroy(a) PETSC_SUCCESS
1616: #endif

1618: #if PetscDefined(HAVE_THREADSAFETY)
1619: PETSC_INTERN PetscSpinlock PetscViewerASCIISpinLockOpen;
1620: PETSC_INTERN PetscSpinlock PetscViewerASCIISpinLockStdout;
1621: PETSC_INTERN PetscSpinlock PetscViewerASCIISpinLockStderr;
1622: PETSC_INTERN PetscSpinlock PetscCommSpinLock;
1623: #endif

1625: PETSC_EXTERN PetscLogEvent PETSC_Barrier;
1626: PETSC_EXTERN PetscLogEvent PETSC_BuildTwoSided;
1627: PETSC_EXTERN PetscLogEvent PETSC_BuildTwoSidedF;
1628: PETSC_EXTERN PetscBool     use_gpu_aware_mpi;
1629: PETSC_EXTERN PetscBool     PetscPrintFunctionList;

1631: #if PetscDefined(HAVE_ADIOS)
1632: PETSC_EXTERN int64_t Petsc_adios_group;
1633: #endif

1635: #if PetscDefined(HAVE_KOKKOS)
1636: PETSC_INTERN PetscBool      PetscBeganKokkos;
1637: PETSC_EXTERN PetscBool      PetscKokkosInitialized;
1638: PETSC_INTERN PetscErrorCode PetscKokkosIsInitialized_Private(PetscBool *);
1639: PETSC_INTERN PetscErrorCode PetscKokkosFinalize_Private(void);
1640: #endif

1642: #if PetscDefined(HAVE_OPENMP)
1643: PETSC_EXTERN PetscInt PetscNumOMPThreads;
1644: #endif

1646: struct _n_PetscObjectList {
1647:   char            name[256];
1648:   PetscBool       skipdereference; /* when the PetscObjectList is destroyed do not call PetscObjectDereference() on this object */
1649:   PetscObject     obj;
1650:   PetscObjectList next;
1651: };

1653: /*E
1654:     PetscPrecision - Precision of a real number

1656:     Values:
1657: +   `PETSC_PRECISION_INVALID`     - an invalid value
1658: .   `PETSC_PRECISION_BFLOAT16`    - half precision (Google Brain bfloat16)
1659: .   `PETSC_PRECISION___FP16`      - half precision (IEEE FP16)
1660: .   `PETSC_PRECISION_SINGLE`      - single precision
1661: .   `PETSC_PRECISION_DOUBLE`      - double precision
1662: -   `PETSC_PRECISION___FLOAT128`  - quadruple precision (__float128)

1664:     Level: intermediate
1665: E*/

1667: typedef enum {
1668:   PETSC_PRECISION_INVALID = 0,
1669:   PETSC_PRECISION_BFLOAT16,
1670:   PETSC_PRECISION___FP16,
1671:   PETSC_PRECISION_SINGLE,
1672:   PETSC_PRECISION_DOUBLE,
1673:   PETSC_PRECISION___FLOAT128
1674: } PetscPrecision;

1676: // The precision of PetscScalar and PetscReal
1677: #if PetscDefined(USE_REAL___FP16)
1678:   #define PETSC_SCALAR_PRECISION PETSC_PRECISION___FP16
1679: #elif PetscDefined(USE_REAL_SINGLE)
1680:   #define PETSC_SCALAR_PRECISION PETSC_PRECISION_SINGLE
1681: #elif PetscDefined(USE_REAL_DOUBLE)
1682:   #define PETSC_SCALAR_PRECISION PETSC_PRECISION_DOUBLE
1683: #elif PetscDefined(USE_REAL___FLOAT128)
1684:   #define PETSC_SCALAR_PRECISION PETSC_PRECISION___FLOAT128
1685: #endif

1687: PETSC_EXTERN const char *const PetscPrecisionTypes[];