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 PetscDefined(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 PetscDefined(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_SINGLE_LIBRARY_INTERN PetscErrorCode PetscHeaderReset_Internal(PetscObject);
395: PETSC_EXTERN PetscErrorCode                PetscObjectCopyFortranFunctionPointers(PetscObject, PetscObject);
396: PETSC_EXTERN PetscErrorCode                PetscObjectSetFortranCallback(PetscObject, PetscFortranCallbackType, PetscFortranCallbackId *, PetscFortranCallbackFn *, PetscCtx ctx);
397: PETSC_EXTERN PetscErrorCode                PetscObjectGetFortranCallback(PetscObject, PetscFortranCallbackType, PetscFortranCallbackId, PetscFortranCallbackFn **, void **ctx);

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

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

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

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

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

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

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

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

462: namespace Petsc
463: {

465: namespace util
466: {

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

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

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

503:       #undef PETSC_ASSERT_POINTER_IMPL_SPECIALIZATION

505: } // namespace util

507: } // namespace Petsc

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

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

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

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

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

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

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


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

610: #if !PetscDefined(CLANG_STATIC_ANALYZER)
611:   #if !PetscDefined(USE_DEBUG)

613:     #define PetscCheckSameType(a, arga, b, argb) \
614:       do { \
615:         (void)(a); \
616:         (void)(b); \
617:       } while (0)
618:     #define PetscCheckTypeName(a, type) \
619:       do { \
620:         (void)(a); \
621:       } while (0)
622:     #define PetscCheckTypeNames(a, type1, type2) \
623:       do { \
624:         (void)(a); \
625:       } while (0)
627:       do { \
628:         (void)(a); \
629:       } while (0)
630:     #define PetscCheckSameComm(a, arga, b, argb) \
631:       do { \
632:         (void)(a); \
633:         (void)(b); \
634:       } while (0)
635:     #define PetscCheckSameTypeAndComm(a, arga, b, argb) \
636:       do { \
637:         (void)(a); \
638:         (void)(b); \
639:       } while (0)
641:       do { \
642:         (void)(a); \
643:         (void)(b); \
644:       } while (0)
646:       do { \
647:         (void)(a); \
648:         (void)(b); \
649:       } while (0)
651:       do { \
652:         (void)(a); \
653:         (void)(b); \
654:       } while (0)
656:       do { \
657:         (void)(a); \
658:         (void)(b); \
659:       } while (0)
661:       do { \
662:         (void)(a); \
663:         (void)(b); \
664:       } while (0)
666:       do { \
667:         (void)(a); \
668:         (void)(b); \
669:       } while (0)
671:       do { \
672:         (void)(a); \
673:         (void)(b); \
674:       } while (0)
676:       do { \
677:         (void)(a); \
678:         (void)(b); \
679:       } while (0)
680:     #define PetscCheckSorted(n, idx) \
681:       do { \
682:         (void)(n); \
683:         (void)(idx); \
684:       } while (0)

686:   #else

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

842:   #endif
843: #else  /* PETSC_CLANG_STATIC_ANALYZER */
844: template <typename Ta, typename Tb>
845: extern void PetscCheckSameType(Ta, int, Tb, int);
846: template <typename Ta, typename Tb>
847: extern void PetscCheckTypeName(Ta, Tb);
848: template <typename Ta, typename Tb, typename Tc>
849: extern void PetscCheckTypeNames(Ta, Tb, Tc);
850: template <typename T>
852: template <typename Ta, typename Tb>
853: extern void PetscCheckSameComm(Ta, int, Tb, int);
854: template <typename Ta, typename Tb>
855: extern void PetscCheckSameTypeAndComm(Ta, int, Tb, int);
856: template <typename Ta, typename Tb>
858: template <typename Ta, typename Tb>
860: template <typename Ta, typename Tb>
862: template <typename Ta, typename Tb>
864: template <typename Ta, typename Tb>
866: template <typename Ta, typename Tb>
868: template <typename Ta, typename Tb>
870: template <typename T>
871: extern void PetscCheckSorted(PetscInt, T);
872: #endif /* PETSC_CLANG_STATIC_ANALYZER */

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

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

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

887:    Level: developer

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

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

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

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

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

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

917:    Level: developer

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

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

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

935: /*
936:   Use Microsoft traditional preprocessor.

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

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

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

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

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

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

968: #else

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

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

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

982:    Level: developer

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

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

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

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

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

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

1010:    Level: developer

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

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

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

1024: #endif

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

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

1033:    Logically Collective

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

1040:    Level: developer

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

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

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

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

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

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

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

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

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

1081:    Not Collective

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

1088:    Level: developer

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

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

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

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

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

1110:    Not Collective

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

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

1120:    Level: developer

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

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

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

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

1138:    Not Collective

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

1145:    Level: developer

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

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

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

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

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

1166:    Not Collective

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

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

1176:    Level: developer

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

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

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

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

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

1197:    Not Collective

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

1204:    Level: developer

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

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

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

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

1223:    Not Collective

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

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

1233:    Level: developer

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

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

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

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

1251:    Not Collective

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

1258:    Level: developer

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

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

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

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

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

1279:    Not Collective

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

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

1289:    Level: developer

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

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

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

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

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

1310:    Not Collective

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

1317:    Level: developer

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

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

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

1339:    Not Collective

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

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

1349:    Level: developer

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

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

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

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

1372:    Not Collective

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

1379:    Level: developer

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

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

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

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

1404:    Not Collective

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

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

1414:    Level: developer

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

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

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

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

1440: PETSC_INTERN PetscMPIInt Petsc_SharedWD_keyval;
1441: PETSC_INTERN PetscMPIInt Petsc_SharedTmp_keyval;

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

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

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

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

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

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

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

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

1540: typedef petsc_atomic_flag PetscSpinlock;

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

1566:   #elif PetscDefined(HAVE_OPENMP)

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

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

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

1607: #if PetscDefined(HAVE_THREADSAFETY)
1608: PETSC_INTERN PetscSpinlock PetscViewerASCIISpinLockOpen;
1609: PETSC_INTERN PetscSpinlock PetscViewerASCIISpinLockStdout;
1610: PETSC_INTERN PetscSpinlock PetscViewerASCIISpinLockStderr;
1611: PETSC_INTERN PetscSpinlock PetscCommSpinLock;
1612: #endif

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

1620: #if PetscDefined(HAVE_ADIOS)
1621: PETSC_EXTERN int64_t Petsc_adios_group;
1622: #endif

1624: #if PetscDefined(HAVE_KOKKOS)
1625: PETSC_INTERN PetscBool      PetscBeganKokkos;
1626: PETSC_EXTERN PetscBool      PetscKokkosInitialized;
1627: PETSC_INTERN PetscErrorCode PetscKokkosIsInitialized_Private(PetscBool *);
1628: PETSC_INTERN PetscErrorCode PetscKokkosFinalize_Private(void);
1629: #endif

1631: #if PetscDefined(HAVE_OPENMP)
1632: PETSC_EXTERN PetscInt PetscNumOMPThreads;
1633: #endif

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

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

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

1653:     Level: intermediate
1654: E*/

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

1665: // The precision of PetscScalar and PetscReal
1666: #if PetscDefined(USE_REAL___FP16)
1667:   #define PETSC_SCALAR_PRECISION PETSC_PRECISION___FP16
1668: #elif PetscDefined(USE_REAL_SINGLE)
1669:   #define PETSC_SCALAR_PRECISION PETSC_PRECISION_SINGLE
1670: #elif PetscDefined(USE_REAL_DOUBLE)
1671:   #define PETSC_SCALAR_PRECISION PETSC_PRECISION_DOUBLE
1672: #elif PetscDefined(USE_REAL___FLOAT128)
1673:   #define PETSC_SCALAR_PRECISION PETSC_PRECISION___FLOAT128
1674: #endif

1676: PETSC_EXTERN const char *const PetscPrecisionTypes[];