Actual source code: petscimpl.h


  2: /*
  3:     Defines the basic header of all PETSc objects.
  4: */
  5: #ifndef PETSCIMPL_H
  6: #define PETSCIMPL_H
  7: #include <petscsys.h>

  9: /* SUBMANSEC = Sys */

 11: #if defined(PETSC_CLANG_STATIC_ANALYZER)
 12:   #define PetscDisableStaticAnalyzerForExpressionUnderstandingThatThisIsDangerousAndBugprone(...)
 13: #else
 14:   #define PetscDisableStaticAnalyzerForExpressionUnderstandingThatThisIsDangerousAndBugprone(...) __VA_ARGS__
 15: #endif

 17: #if PetscDefined(USE_DEBUG) && !PetscDefined(HAVE_THREADSAFETY)
 18: PETSC_INTERN PetscErrorCode PetscStackSetCheck(PetscBool);
 19: PETSC_INTERN PetscErrorCode PetscStackView(FILE *);
 20: PETSC_INTERN PetscErrorCode PetscStackReset(void);
 21: PETSC_INTERN PetscErrorCode PetscStackCopy(PetscStack *, PetscStack *);
 22: PETSC_INTERN PetscErrorCode PetscStackPrint(PetscStack *, FILE *);
 23: #else
 24:   #define PetscStackSetCheck(check)         PETSC_SUCCESS
 25:   #define PetscStackView(file)              PETSC_SUCCESS
 26:   #define PetscStackReset()                 PETSC_SUCCESS
 27:   #define PetscStackCopy(stackin, stackout) PETSC_SUCCESS
 28:   #define PetscStackPrint(stack, file)      PETSC_SUCCESS
 29: #endif

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

 35: /*
 36:    All major PETSc data structures have a common core; this is defined
 37:    below by PETSCHEADER.

 39:    PetscHeaderCreate() should be used whenever creating a PETSc structure.
 40: */

 42: /*
 43:    PetscOps: structure of core operations that all PETSc objects support.

 45:       getcomm()         - Gets the object's communicator.
 46:       view()            - Is the routine for viewing the entire PETSc object; for
 47:                           example, MatView() is the general matrix viewing routine.
 48:                           This is used by PetscObjectView((PetscObject)obj) to allow
 49:                           viewing any PETSc object.
 50:       destroy()         - Is the routine for destroying the entire PETSc object;
 51:                           for example,MatDestroy() is the general matrix
 52:                           destruction routine.
 53:                           This is used by PetscObjectDestroy((PetscObject*)&obj) to allow
 54:                           destroying any PETSc object.
 55:       compose()         - Associates a PETSc object with another PETSc object with a name
 56:       query()           - Returns a different PETSc object that has been associated
 57:                           with the first object using a name.
 58:       composefunction() - Attaches an a function to a PETSc object with a name.
 59:       queryfunction()   - Requests a registered function that has been attached to a PETSc object.
 60: */

 62: typedef struct {
 63:   PetscErrorCode (*view)(PetscObject, PetscViewer);
 64:   PetscErrorCode (*destroy)(PetscObject *);
 65:   PetscErrorCode (*compose)(PetscObject, const char[], PetscObject);
 66:   PetscErrorCode (*query)(PetscObject, const char[], PetscObject *);
 67:   PetscErrorCode (*composefunction)(PetscObject, const char[], void (*)(void));
 68:   PetscErrorCode (*queryfunction)(PetscObject, const char[], void (**)(void));
 69: } PetscOps;

 71: typedef enum {
 72:   PETSC_FORTRAN_CALLBACK_CLASS,
 73:   PETSC_FORTRAN_CALLBACK_SUBTYPE,
 74:   PETSC_FORTRAN_CALLBACK_MAXTYPE
 75: } PetscFortranCallbackType;
 76: typedef size_t PetscFortranCallbackId;
 77: #define PETSC_SMALLEST_FORTRAN_CALLBACK ((PetscFortranCallbackId)1000)
 78: PETSC_EXTERN PetscErrorCode PetscFortranCallbackRegister(PetscClassId, const char *, PetscFortranCallbackId *);
 79: PETSC_EXTERN PetscErrorCode PetscFortranCallbackGetSizes(PetscClassId, PetscFortranCallbackId *, PetscFortranCallbackId *);

 81: typedef struct {
 82:   void (*func)(void);
 83:   void *ctx;
 84: } PetscFortranCallback;

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

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

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

146: #define PETSCFREEDHEADER -1

148: PETSC_EXTERN_TYPEDEF typedef PetscErrorCode (*PetscObjectDestroyFunction)(PetscObject *); /* force cast in next macro to NEVER use extern "C" style */
149: PETSC_EXTERN_TYPEDEF typedef PetscErrorCode (*PetscObjectViewFunction)(PetscObject, PetscViewer);

151: #define PetscHeaderInitialize_Private(h, classid, class_name, descr, mansec, comm, destroy, view) \
152:   ((PetscErrorCode)(PetscHeaderCreate_Private((PetscObject)(h), classid, class_name, descr, mansec, comm, (PetscObjectDestroyFunction)(destroy), (PetscObjectViewFunction)(view)) || PetscLogObjectCreate(h)))

154: /*MC
155:     PetscHeaderCreate - Creates a raw PETSc object of a particular class

157:   Synopsis:
158: #include <petsc/private/petscimpl.h>
159:   PetscErrorCode PetscHeaderCreate(PetscObject h, PetscClassId classid, const char class_name[], const char descr[], const char mansec[], MPI_Comm comm, PetscObjectDestroyFunction destroy, PetscObjectViewFunction view)

161:   Input Parameters:
162: + classid    - The classid associated with this object (for example `VEC_CLASSID`)
163: . class_name - String name of class; should be static (for example "Vec"), may be
164:                `PETSC_NULLPTR`
165: . descr      - String containing short description; should be static (for example "Vector"),
166:                may be `PETSC_NULLPTR`
167: . mansec     - String indicating section in manual pages; should be static (for example "Vec"),
168:                may be `PETSC_NULLPTR`
169: . comm       - The MPI Communicator
170: . destroy    - The destroy routine for this object (for example `VecDestroy()`)
171: - view       - The view routine for this object (for example `VecView()`), may be
172:                `PETSC_NULLPTR`

174:   Output Parameter:
175: . h - The newly created `PetscObject`

177:   Level: developer

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

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

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

192:   Example Usage:
193:   Existing `PetscObject`s may be easily created as shown. Unless otherwise stated, a particular
194:   objects `destroy` and `view` functions are exactly `<OBJECT_TYPE>Destroy()` and
195:   `<OBJECT_TYPE>View()`.
196: .vb
197:   Vec v;

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

202:   It is possible to create custom `PetscObject`s, note however that they must abide by the
203:   restrictions set forth above.
204: .vb
205:   // OK, first member of C structure is _p_PetscObject
206:   struct MyCPetscObject_s
207:   {
208:     _p_PetscObject header;
209:     int            some_data;
210:   };
211:   typedef struct *MyCPetscObject_s MyCPetscObject;

213:   PetscErrorCode MyObjectDestroy(MyObject *);
214:   PetscErrorCode MyObjectView(MyObject);

216:   MyCPetscObject obj;

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

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

224:   // ERROR must be a single-level pointer
225:   PetscHeaderCreate(&obj, ...);
226: .ve

228:   Illustrating proper construction from C++\:
229: .vb
230:   // ERROR, class is not standard layout, first member must be publicly accessible
231:   class BadCppPetscObject
232:   {
233:     _p_PetscObject header;
234:   };

236:   // ERROR, class is not standard layout, has a virtual function and virtual inheritance
237:   class BadCppPetscObject2 : virtual BaseClass
238:   {
239:   public:
240:     _p_PetscObject header;

242:     virtual void foo();
243:   };

245:   // ERROR, class is not standard layout! Has non-standard layout member
246:   class BadCppPetscObject2
247:   {
248:   public:
249:     _p_PetscObject    header;
250:     BadCppPetscObject non_standard_layout;
251:   };

253:   // OK, class is standard layout!
254:   class GoodCppPetscObject;
255:   using MyCppObject = GoodCppPetscObject *;

257:   // OK, non-virtual inheritance of other standard layout class does not affect layout
258:   class GoodCppPetscObject : StandardLayoutClass
259:   {
260:   public:
261:     // OK, non standard layout member is static, does not affect layout
262:     static BadCppPetscObject non_standard_layout;

264:     // OK, first non-static member is _p_PetscObject
265:     _p_PetscObject header;

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

270:     // OK, may use "member" functions for destroy and view so long as they are static
271:     static PetscErrorCode destroy(MyCppObject *);
272:     static PetscErrorCode view(MyCppObject);
273:   };

275:   // OK, usage via pointer
276:   MyObject obj;

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

281: .seealso: `PetscObject`, `PetscHeaderDestroy()`, `PetscClassIdRegister()`
282: M*/
283: #define PetscHeaderCreate(h, classid, class_name, descr, mansec, comm, destroy, view) ((PetscErrorCode)(PetscNew(&(h)) || PetscHeaderInitialize_Private((h), (classid), (class_name), (descr), (mansec), (comm), (destroy), (view))))

285: PETSC_EXTERN PetscErrorCode PetscComposedQuantitiesDestroy(PetscObject obj);
286: PETSC_EXTERN PetscErrorCode PetscHeaderCreate_Private(PetscObject, PetscClassId, const char[], const char[], const char[], MPI_Comm, PetscObjectDestroyFunction, PetscObjectViewFunction);
287: PETSC_INTERN PetscObjectId  PetscObjectNewId_Internal(void);

289: /*MC
290:   PetscHeaderDestroy - Final step in destroying a `PetscObject`

292:   Synopsis:
293: #include <petsc/private/petscimpl.h>
294:   PetscErrorCode PetscHeaderDestroy(PetscObject *obj)

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

299:   Level: developer

301:   Notes:
302:   `h` is freed and set to `PETSC_NULLPTR` when this routine returns.

304:   Example Usage:
305: .vb
306:   PetscObject obj;

308:   PetscHeaderCreate(obj, ...);
309:   // use obj...

311:   // note pointer to obj is used
312:   PetscHeaderDestroy(&obj);
313: .ve

315:   Note that this routine is the _last_ step when destroying higher-level `PetscObject`s as it
316:   deallocates the memory for the structure itself\:
317: .vb
318:   typedef struct MyPetscObject_s *MyPetscObject;
319:   struct MyPetscObject_s
320:   {
321:     _p_PetscObject  hdr;
322:     PetscInt       *foo;
323:     PetscScalar    *bar;
324:   };

326:   // assume obj is created/initialized elsewhere...
327:   MyPetscObject obj;

329:   // OK, should dispose of all dynamically allocated resources before calling
330:   // PetscHeaderDestroy()
331:   PetscFree(obj->foo);

333:   // OK, dispose of obj
334:   PetscHeaderDestroy(&obj);

336:   // ERROR, obj points to NULL here, accessing obj->bar may result in segmentation violation!
337:   // obj->bar is potentially leaked!
338:   PetscFree(obj->bar);
339: .ve

341: .seealso: `PetscObject`, `PetscHeaderCreate()`
342: M*/
343: #define PetscHeaderDestroy(h) ((PetscErrorCode)(PetscHeaderDestroy_Private((PetscObject)(*(h)), PETSC_FALSE) || PetscFree(*(h))))

345: PETSC_EXTERN PetscErrorCode                PetscHeaderDestroy_Private(PetscObject, PetscBool);
346: PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode PetscHeaderReset_Internal(PetscObject);
347: PETSC_EXTERN PetscErrorCode                PetscObjectCopyFortranFunctionPointers(PetscObject, PetscObject);
348: PETSC_EXTERN PetscErrorCode                PetscObjectSetFortranCallback(PetscObject, PetscFortranCallbackType, PetscFortranCallbackId *, void (*)(void), void *ctx);
349: PETSC_EXTERN PetscErrorCode                PetscObjectGetFortranCallback(PetscObject, PetscFortranCallbackType, PetscFortranCallbackId, void (**)(void), void **ctx);

351: PETSC_INTERN PetscErrorCode PetscCitationsInitialize(void);
352: PETSC_INTERN PetscErrorCode PetscFreeMPIResources(void);
353: PETSC_INTERN PetscErrorCode PetscOptionsHasHelpIntro_Internal(PetscOptions, PetscBool *);

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

358: #if PetscDefined(HAVE_SETJMP_H)
359: PETSC_EXTERN PetscBool PetscCheckPointer(const void *, PetscDataType);
360: #else
361:   #define PetscCheckPointer(ptr, data_type) (ptr ? PETSC_TRUE : PETSC_FALSE)
362: #endif
363: #if !defined(PETSC_CLANG_STATIC_ANALYZER)
364:   /*
365:     Macros to test if a PETSc object is valid and if pointers are valid
366: */
367:   #if !defined(PETSC_USE_DEBUG)

370:       do { \
371:         (void)(h); \
372:       } while (0)
374:       do { \
375:         (void)(h); \
376:       } while (0)
378:       do { \
379:         (void)(h); \
380:       } while (0)
382:       do { \
383:         (void)(h); \
384:       } while (0)
386:       do { \
387:         (void)(h); \
388:       } while (0)
390:       do { \
391:         (void)(h); \
392:       } while (0)
394:       do { \
395:         (void)(h); \
396:       } while (0)
398:       do { \
399:         (void)(h); \
400:       } while (0)
402:       do { \
403:         (void)(h); \
404:       } while (0)
406:       do { \
407:         (void)(h); \
408:       } while (0)
410:       do { \
411:         (void)(h); \
412:       } while (0)
414:       do { \
415:         (void)(h); \
416:       } while (0)

418:   #else

420:     /*  This check is for subtype methods such as DMDAGetCorners() that do not use the PetscTryMethod() or PetscUseMethod() paradigm */
422:       do { \
423:         PetscBool _7_same; \
425:         PetscCall(PetscObjectTypeCompare((PetscObject)(h), t, &_7_same)); \
426:         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); \
427:       } while (0)

430:       do { \
431:         PetscCheck(ptr, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Null Pointer: Parameter # %d", arg); \
432:         PetscCheck(PetscCheckPointer(ptr, ptype), PETSC_COMM_SELF, PETSC_ERR_ARG_BADPTR, "Invalid Pointer to " PetscStringize(ptrtype) ": Argument '" PetscStringize(ptr) "' (parameter # %d)", arg); \
433:       } while (0)

436:       do { \
438:         if (((PetscObject)(h))->classid != ck) { \
439:           PetscCheck(((PetscObject)(h))->classid != PETSCFREEDHEADER, PETSC_COMM_SELF, PETSC_ERR_ARG_CORRUPT, "Object already free: Parameter # %d", arg); \
440:           SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Wrong type of object: Parameter # %d", arg); \
441:         } \
442:       } while (0)

445:       do { \
447:         PetscCheck(((PetscObject)(h))->classid != PETSCFREEDHEADER, PETSC_COMM_SELF, PETSC_ERR_ARG_CORRUPT, "Object already free: Parameter # %d", arg); \
448:         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); \
449:       } while (0)


461:       do { \
462:         PetscCheck((f), PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Null Function Pointer: Parameter # %d", arg); \
463:       } while (0)
464:   #endif
465: #else  /* PETSC_CLANG_STATIC_ANALYZER */
466: template <typename T>
468: template <typename T>
470: template <typename T>
472: template <typename T>
474: template <typename T>
476: template <typename T>
478: template <typename T>
480: template <typename T>
482: template <typename T>
484: template <typename T>
486: template <typename T>
488: template <typename T>
490: template <typename T>
492: #endif /* PETSC_CLANG_STATIC_ANALYZER */

494: #define PetscSorted(n, idx, sorted) \
495:   do { \
496:     (sorted) = PETSC_TRUE; \
497:     for (PetscInt _i_ = 1; _i_ < (n); ++_i_) { \
498:       if ((idx)[_i_] < (idx)[_i_ - 1]) { \
499:         (sorted) = PETSC_FALSE; \
500:         break; \
501:       } \
502:     } \
503:   } while (0)

505: #if !defined(PETSC_CLANG_STATIC_ANALYZER)
506:   #if !defined(PETSC_USE_DEBUG)

508:     #define PetscCheckSameType(a, arga, b, argb) \
509:       do { \
510:         (void)(a); \
511:         (void)(b); \
512:       } while (0)
513:     #define PetscCheckTypeName(a, type) \
514:       do { \
515:         (void)(a); \
516:       } while (0)
517:     #define PetscCheckTypeNames(a, type1, type2) \
518:       do { \
519:         (void)(a); \
520:       } while (0)
522:       do { \
523:         (void)(a); \
524:       } while (0)
525:     #define PetscCheckSameComm(a, arga, b, argb) \
526:       do { \
527:         (void)(a); \
528:         (void)(b); \
529:       } while (0)
530:     #define PetscCheckSameTypeAndComm(a, arga, b, argb) \
531:       do { \
532:         (void)(a); \
533:         (void)(b); \
534:       } while (0)
536:       do { \
537:         (void)(a); \
538:         (void)(b); \
539:       } while (0)
541:       do { \
542:         (void)(a); \
543:         (void)(b); \
544:       } while (0)
546:       do { \
547:         (void)(a); \
548:         (void)(b); \
549:       } while (0)
551:       do { \
552:         (void)(a); \
553:         (void)(b); \
554:       } while (0)
556:       do { \
557:         (void)(a); \
558:         (void)(b); \
559:       } while (0)
561:       do { \
562:         (void)(a); \
563:         (void)(b); \
564:       } while (0)
565:     #define PetscCheckSorted(n, idx) \
566:       do { \
567:         (void)(n); \
568:         (void)(idx); \
569:       } while (0)

571:   #else

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

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

579:   This macro is used incorrectly in the code. Many places that do not need identity of the
580:   types incorrectly call this check and would need to be fixed if this macro is enabled.
581: */
582:     #if 0
583:       #define PetscCheckSameType(a, arga, b, argb) \
584:         do { \
585:           PetscBool pcst_type_eq_ = PETSC_TRUE; \
586:           PetscCall(PetscStrcmp(((PetscObject)(a))->type_name, (((PetscObject)(b)))->type_name, &pcst_type_eq_)); \
587:           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); \
588:         } while (0)
589:     #else
590:       #define PetscCheckSameType(a, arga, b, argb) \
591:         do { \
592:           (void)(a); \
593:           (void)(b); \
594:         } while (0)
595:     #endif

597:     /*
598:     Check type_name
599: */
600:     #define PetscCheckTypeName(a, type) \
601:       do { \
602:         PetscBool _7_match; \
603:         PetscCall(PetscObjectTypeCompare(((PetscObject)(a)), (type), &_7_match)); \
604:         PetscCheck(_7_match, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Object (%s) is not %s", (char *)(((PetscObject)(a))->type_name), type); \
605:       } while (0)

607:     #define PetscCheckTypeNames(a, type1, type2) \
608:       do { \
609:         PetscBool _7_match; \
610:         PetscCall(PetscObjectTypeCompareAny(((PetscObject)(a)), &_7_match, (type1), (type2), "")); \
611:         PetscCheck(_7_match, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Object (%s) is not %s or %s", (char *)(((PetscObject)(a))->type_name), type1, type2); \
612:       } while (0)

614:     /*
615:    Use this macro to check if the type is set
616: */

619:     /*
620:    Sometimes object must live on same communicator to inter-operate
621: */
622:     #define PetscCheckSameComm(a, arga, b, argb) \
623:       do { \
624:         PetscMPIInt _7_flag; \
625:         PetscCallMPI(MPI_Comm_compare(PetscObjectComm((PetscObject)(a)), PetscObjectComm((PetscObject)(b)), &_7_flag)); \
626:         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); \
627:       } while (0)

629:     #define PetscCheckSameTypeAndComm(a, arga, b, argb) \
630:       do { \
631:         PetscCheckSameType(a, arga, b, argb); \
632:         PetscCheckSameComm(a, arga, b, argb); \
633:       } while (0)

636:       do { \
637:         PetscScalar b0 = (b); \
638:         PetscReal   b1[5], b2[5]; \
639:         if (PetscIsNanScalar(b0)) { \
640:           b1[4] = 1; \
641:         } else { \
642:           b1[4] = 0; \
643:         }; \
644:         b1[0] = -PetscRealPart(b0); \
645:         b1[1] = PetscRealPart(b0); \
646:         b1[2] = -PetscImaginaryPart(b0); \
647:         b1[3] = PetscImaginaryPart(b0); \
648:         PetscCall(MPIU_Allreduce(b1, b2, 5, MPIU_REAL, MPIU_MAX, PetscObjectComm((PetscObject)(a)))); \
649:         PetscCheck(b2[4] > 0 || (PetscEqualReal(-b2[0], b2[1]) && PetscEqualReal(-b2[2], b2[3])), PetscObjectComm((PetscObject)(a)), PETSC_ERR_ARG_WRONG, "Scalar value must be same on all processes, argument # %d", arg); \
650:       } while (0)

653:       do { \
654:         PetscReal b0 = (b), b1[3], b2[3]; \
655:         if (PetscIsNanReal(b0)) { \
656:           b1[2] = 1; \
657:         } else { \
658:           b1[2] = 0; \
659:         }; \
660:         b1[0] = -b0; \
661:         b1[1] = b0; \
662:         PetscCall(MPIU_Allreduce(b1, b2, 3, MPIU_REAL, MPIU_MAX, PetscObjectComm((PetscObject)(a)))); \
663:         PetscCheck(b2[2] > 0 || PetscEqualReal(-b2[0], b2[1]), PetscObjectComm((PetscObject)(a)), PETSC_ERR_ARG_WRONG, "Real value must be same on all processes, argument # %d", arg); \
664:       } while (0)

667:       do { \
668:         PetscInt b0 = (b), b1[2], b2[2]; \
669:         b1[0]       = -b0; \
670:         b1[1]       = b0; \
671:         PetscCall(MPIU_Allreduce(b1, b2, 2, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)(a)))); \
672:         PetscCheck(-b2[0] == b2[1], PetscObjectComm((PetscObject)(a)), PETSC_ERR_ARG_WRONG, "Int value must be same on all processes, argument # %d", arg); \
673:       } while (0)

676:       do { \
677:         PetscMPIInt b0 = (b), b1[2], b2[2]; \
678:         b1[0]          = -b0; \
679:         b1[1]          = b0; \
680:         PetscCall(MPIU_Allreduce(b1, b2, 2, MPI_INT, MPI_MAX, PetscObjectComm((PetscObject)(a)))); \
681:         PetscCheck(-b2[0] == b2[1], PetscObjectComm((PetscObject)(a)), PETSC_ERR_ARG_WRONG, "PetscMPIInt value must be same on all processes, argument # %d", arg); \
682:       } while (0)

685:       do { \
686:         PetscMPIInt b0 = (PetscMPIInt)(b), b1[2], b2[2]; \
687:         b1[0]          = -b0; \
688:         b1[1]          = b0; \
689:         PetscCall(MPIU_Allreduce(b1, b2, 2, MPI_INT, MPI_MAX, PetscObjectComm((PetscObject)(a)))); \
690:         PetscCheck(-b2[0] == b2[1], PetscObjectComm((PetscObject)(a)), PETSC_ERR_ARG_WRONG, "Bool value must be same on all processes, argument # %d", arg); \
691:       } while (0)

694:       do { \
695:         PetscMPIInt b0 = (PetscMPIInt)(b), b1[2], b2[2]; \
696:         b1[0]          = -b0; \
697:         b1[1]          = b0; \
698:         PetscCall(MPIU_Allreduce(b1, b2, 2, MPI_INT, MPI_MAX, PetscObjectComm((PetscObject)(a)))); \
699:         PetscCheck(-b2[0] == b2[1], PetscObjectComm((PetscObject)(a)), PETSC_ERR_ARG_WRONG, "Enum value must be same on all processes, argument # %d", arg); \
700:       } while (0)

702:     #define PetscCheckSorted(n, idx) \
703:       do { \
704:         PetscBool _1_flg; \
705:         PetscSorted(n, idx, _1_flg); \
706:         PetscCheck(_1_flg, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Input array needs to be sorted"); \
707:       } while (0)

709:   #endif
710: #else  /* PETSC_CLANG_STATIC_ANALYZER */
711: template <typename Ta, typename Tb>
712: void PetscCheckSameType(Ta, int, Tb, int);
713: template <typename Ta, typename Tb>
714: void PetscCheckTypeName(Ta, Tb);
715: template <typename Ta, typename Tb, typename Tc>
716: void PetscCheckTypeName(Ta, Tb, Tc);
717: template <typename T>
719: template <typename Ta, typename Tb>
720: void PetscCheckSameComm(Ta, int, Tb, int);
721: template <typename Ta, typename Tb>
722: void PetscCheckSameTypeAndComm(Ta, int, Tb, int);
723: template <typename Ta, typename Tb>
725: template <typename Ta, typename Tb>
727: template <typename Ta, typename Tb>
729: template <typename Ta, typename Tb>
731: template <typename Ta, typename Tb>
733: template <typename Ta, typename Tb>
735: template <typename T>
736: void PetscCheckSorted(PetscInt, T);
737: #endif /* PETSC_CLANG_STATIC_ANALYZER */

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

742:   Synopsis:
743:    #include "petsc/private/petscimpl.h"
744:    PetscTryMethod(PetscObject obj, const char *name, (arg_types), (arg_value))

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

752:    Level: developer

754:    Notes:
755:    This does not return an error code, it is a macro that returns with an error code on error.

757:    Use `PetscUseTypeMethod()` or `PetscTryTypeMethod()` to call functions that are included in the objects function table, the `ops` array
758:    in the object.

760: .seealso: `PetscUseMethod()`, `PetscCall()`, `PetscUseTypeMethod()`, `PetscTryTypeMethod()`, `PetscCheck()`, `PetscObject`
761: M*/
762: #define PetscTryMethod(obj, A, B, C) \
763:   do { \
764:     PetscErrorCode(*_7_f) B; \
765:     PetscCall(PetscObjectQueryFunction((PetscObject)(obj), A, &_7_f)); \
766:     if (_7_f) PetscCall((*_7_f)C); \
767:   } while (0)

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

772:   Synopsis:
773:    #include "petsc/private/petscimpl.h"
774:    PetscUseMethod(PetscObject obj, const char *name, (arg_types), (arg_value))

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

782:    Level: developer

784:    Notes:
785:    This does not return an error code, it is a macro that returns with an error code on error.

787:    Use `PetscUseTypeMethod()` or `PetscTryTypeMethod()` to call functions that are included in the objects function table, the `ops` array
788:    in the object.

790: .seealso: `PetscTryMethod()`, `PetscCall()`, `PetscUseTypeMethod()`, `PetscTryTypeMethod()`, `PetscCheck()`, `PetscObject`
791: M*/
792: #define PetscUseMethod(obj, A, B, C) \
793:   do { \
794:     PetscErrorCode(*_7_f) B; \
795:     PetscCall(PetscObjectQueryFunction((PetscObject)(obj), A, &_7_f)); \
796:     PetscCheck(_7_f, PetscObjectComm((PetscObject)(obj)), PETSC_ERR_SUP, "Cannot locate function %s in object", A); \
797:     PetscCall((*_7_f)C); \
798:   } while (0)

800: /*
801:   Use Microsoft traditional preprocessor.

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

806:   It appears the Intel Windows compiler icl does not have an equaivalent of  -Zc:preprocessor

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

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

814:   #define PetscUseTypeMethod(obj, OP, ...) \
815:     do { \
816:       PetscErrorCode ierr_p_; \
817:       PetscStackUpdateLine; \
818:       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); \
819:       ierr_p_ = (*(obj)->ops->OP)(obj, __VA_ARGS__); \
820:       PetscCall(ierr_p_); \
821:     } while (0)

823:   #define PetscTryTypeMethod(obj, OP, ...) \
824:     do { \
825:       if ((obj)->ops->OP) { \
826:         PetscErrorCode ierr_p_; \
827:         PetscStackUpdateLine; \
828:         ierr_p_ = (*(obj)->ops->OP)(obj, __VA_ARGS__); \
829:         PetscCall(ierr_p_); \
830:       } \
831:     } while (0)

833: #else

835:   /*MC
836:    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

838:   Synopsis:
839:    #include "petsc/private/petscimpl.h"
840:    PetscUseTypeMethod(obj, method, other_args)

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

847:    Level: developer

849:    Note:
850:    This does not return an error code, it is a macro that returns with an error code on error.

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

854: .seealso: `PetscTryMethod()`, `PetscUseMethod()`, `PetscCall()`, `PetscCheck()`, `PetscTryTypeMethod()`
855: M*/
856:   #define PetscUseTypeMethod(obj, ...) \
857:     do { \
858:       PetscCheck((obj)->ops->PETSC_FIRST_ARG((__VA_ARGS__, unused)), PetscObjectComm((PetscObject)obj), PETSC_ERR_SUP, "No method %s for %s of type %s", \
859:                  PetscStringize(PETSC_FIRST_ARG((__VA_ARGS__,unused))), ((PetscObject)obj)->class_name, ((PetscObject)obj)->type_name); \
860:       PetscCall((*(obj)->ops->PETSC_FIRST_ARG((__VA_ARGS__, unused)))(obj PETSC_REST_ARG(__VA_ARGS__))); \
861:     } while (0)

863:   /*MC
864:    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

866:   Synopsis:
867:    #include "petsc/private/petscimpl.h"
868:    PetscTryTtype(obj, method, other_args)

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

875:    Level: developer

877:    Note:
878:    This does not return an error code, it is a macro that returns with an error code on error.

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

882: .seealso: `PetscTryMethod()`, `PetscUseMethod()`, `PetscCall()`, `PetscCheck()`, `PetscUseTypeMethod()`
883: M*/
884:   #define PetscTryTypeMethod(obj, ...) \
885:     do { \
886:       if ((obj)->ops->PETSC_FIRST_ARG((__VA_ARGS__, unused))) PetscCall((*(obj)->ops->PETSC_FIRST_ARG((__VA_ARGS__, unused)))(obj PETSC_REST_ARG(__VA_ARGS__))); \
887:     } while (0)

889: #endif

891: /*MC
892:    PetscObjectStateIncrease - Increases the state of any `PetscObject`

894:    Synopsis:
895:    #include "petsc/private/petscimpl.h"
896:    PetscErrorCode PetscObjectStateIncrease(PetscObject obj)

898:    Logically Collective

900:    Input Parameter:
901: .  obj - any PETSc object, for example a `Vec`, `Mat` or `KSP`. This must be
902:          cast with a (PetscObject), for example,
903:          `PetscObjectStateIncrease`((`PetscObject`)mat);

905:    Level: developer

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

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

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

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

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

924: .seealso: `PetscObjectStateGet()`, `PetscObject`
925: M*/
926: #define PetscObjectStateIncrease(obj) ((obj)->state++, PETSC_SUCCESS)

928: PETSC_EXTERN PetscErrorCode PetscObjectStateGet(PetscObject, PetscObjectState *);
929: PETSC_EXTERN PetscErrorCode PetscObjectStateSet(PetscObject, PetscObjectState);
930: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataRegister(PetscInt *);
931: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseInt(PetscObject);
932: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseIntstar(PetscObject);
933: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseReal(PetscObject);
934: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseRealstar(PetscObject);
935: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseScalar(PetscObject);
936: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseScalarstar(PetscObject);
937: PETSC_EXTERN PetscInt       PetscObjectComposedDataMax;

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

942:    Synopsis:
943:    #include "petsc/private/petscimpl.h"
944:    PetscErrorCode PetscObjectComposedDataSetInt(PetscObject obj, PetscInt id, PetscInt data)

946:    Not Collective

948:    Input Parameters:
949: +  obj - the object to which data is to be attached
950: .  id - the identifier for the data
951: -  data - the data to  be attached, a `PetscInt`

953:    Level: developer

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

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

961: .seealso: `PetscObjectComposedDataGetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetReal()`,
962:           `PetscObjectComposedDataGetIntstar()`, `PetscObjectComposedDataSetIntstar()`, `PetscObject`,
963:           `PetscObjectCompose()`, `PetscObjectQuery()`
964: M*/
965: #define PetscObjectComposedDataSetInt(obj, id, data) \
966:   ((PetscErrorCode)((((obj)->int_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseInt(obj)) || ((obj)->intcomposeddata[id] = data, (obj)->intcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))

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

971:    Synopsis:
972:    #include "petsc/private/petscimpl.h"
973:    PetscErrorCode PetscObjectComposedDataGetInt(PetscObject obj, PetscInt id, PetscInt data, PetscBool flag)

975:    Not Collective

977:    Input Parameters:
978: +  obj - the object from which data is to be retrieved
979: -  id - the identifier for the data

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

985:    Level: developer

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

990: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetReal()`,
991:           `PetscObjectComposedDataGetIntstar()`, `PetscObjectComposedDataSetIntstar()`, `PetscObject`,
992:           `PetscObjectCompose()`, `PetscObjectQuery()`
993: M*/
994: #define PetscObjectComposedDataGetInt(obj, id, data, flag) (((obj)->intcomposedstate ? (data = (obj)->intcomposeddata[id], flag = (PetscBool)((obj)->intcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), PETSC_SUCCESS)

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

999:    Synopsis:
1000:    #include "petsc/private/petscimpl.h"
1001:    PetscErrorCode PetscObjectComposedDataSetIntstar(PetscObject obj, PetscInt id, PetscInt *data)

1003:    Not Collective

1005:    Input Parameters:
1006: +  obj - the object to which data is to be attached
1007: .  id - the identifier for the data
1008: -  data - the data to  be attached, a `PetscInt` array

1010:    Level: developer

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

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

1017: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetReal()`,
1018:           `PetscObjectComposedDataGetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1019:           `PetscObjectCompose()`, `PetscObjectQuery()`
1020: M*/
1021: #define PetscObjectComposedDataSetIntstar(obj, id, data) \
1022:   ((PetscErrorCode)((((obj)->intstar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseIntstar(obj)) || ((obj)->intstarcomposeddata[id] = data, (obj)->intstarcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))

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

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

1031:    Not Collective

1033:    Input Parameters:
1034: +  obj - the object from which data is to be retrieved
1035: -  id - the identifier for the data

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

1041:    Level: developer

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

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

1048: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetReal()`,
1049:           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1050:           `PetscObjectCompose()`, `PetscObjectQuery()`
1051: M*/
1052: #define PetscObjectComposedDataGetIntstar(obj, id, data, flag) \
1053:   ((PetscErrorCode)(((obj)->intstarcomposedstate ? (data = (obj)->intstarcomposeddata[id], flag = (PetscBool)((obj)->intstarcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), PETSC_SUCCESS))

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

1058:    Synopsis:
1059:    #include "petsc/private/petscimpl.h"
1060:    PetscErrorCode PetscObjectComposedDataSetReal(PetscObject obj, PetscInt id, PetscReal data)

1062:    Not Collective

1064:    Input Parameters:
1065: +  obj - the object to which data is to be attached
1066: .  id - the identifier for the data
1067: -  data - the data to  be attached, a `PetscReal`

1069:    Level: developer

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

1074: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1075:           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1076:           `PetscObjectCompose()`, `PetscObjectQuery()`
1077: M*/
1078: #define PetscObjectComposedDataSetReal(obj, id, data) \
1079:   ((PetscErrorCode)((((obj)->real_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseReal(obj)) || ((obj)->realcomposeddata[id] = data, (obj)->realcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))

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

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

1088:    Not Collective

1090:    Input Parameters:
1091: +  obj - the object from which data is to be retrieved
1092: -  id - the identifier for the data

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

1098:    Level: developer

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

1103: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataSetIntstar()`,
1104:           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1105:           `PetscObjectCompose()`, `PetscObjectQuery()`
1106: M*/
1107: #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))

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

1112:    Synopsis:
1113:    #include "petsc/private/petscimpl.h"
1114:    PetscErrorCode PetscObjectComposedDataSetRealstar(PetscObject obj, PetscInt id, PetscReal *data)

1116:    Not Collective

1118:    Input Parameters:
1119: +  obj - the object to which data is to be attached
1120: .  id - the identifier for the data
1121: -  data - the data to  be attached

1123:    Level: developer

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

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

1130: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1131:           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1132:           `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataGetRealstar()`
1133: M*/
1134: #define PetscObjectComposedDataSetRealstar(obj, id, data) \
1135:   ((PetscErrorCode)((((obj)->realstar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseRealstar(obj)) || ((obj)->realstarcomposeddata[id] = data, (obj)->realstarcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))

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

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

1144:    Not Collective

1146:    Input Parameters:
1147: +  obj - the object from which data is to be retrieved
1148: -  id - the identifier for the data

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

1154:    Level: developer

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

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

1161: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1162:           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1163:           `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`
1164: M*/
1165: #define PetscObjectComposedDataGetRealstar(obj, id, data, flag) \
1166:   ((PetscErrorCode)(((obj)->realstarcomposedstate ? (data = (obj)->realstarcomposeddata[id], flag = (PetscBool)((obj)->realstarcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), PETSC_SUCCESS))

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

1171:    Synopsis:
1172:    #include "petsc/private/petscimpl.h"
1173:    PetscErrorCode PetscObjectComposedDataSetScalar(PetscObject obj, PetscInt id, PetscScalar data)

1175:    Not Collective

1177:    Input Parameters:
1178: +  obj - the object to which data is to be attached
1179: .  id - the identifier for the data
1180: -  data - the data to  be attached, a `PetscScalar`

1182:    Level: developer

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

1187: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1188:           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1189:           `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`, `PetscObjectComposedDataGetScalar()`
1190: M*/
1191: #if defined(PETSC_USE_COMPLEX)
1192:   #define PetscObjectComposedDataSetScalar(obj, id, data) \
1193:     ((PetscErrorCode)((((obj)->scalar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseScalar(obj)) || ((obj)->scalarcomposeddata[id] = data, (obj)->scalarcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))
1194: #else
1195:   #define PetscObjectComposedDataSetScalar(obj, id, data) PetscObjectComposedDataSetReal(obj, id, data)
1196: #endif
1197: /*MC
1198:    PetscObjectComposedDataGetScalar - retrieve `PetscScalar` data attached to a `PetscObject` that was set with `PetscObjectComposedDataSetScalar()`

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

1204:    Not Collective

1206:    Input Parameters:
1207: +  obj - the object from which data is to be retrieved
1208: -  id - the identifier for the data

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

1214:    Level: developer

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

1219: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1220:           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1221:           `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`, `PetscObjectComposedDataSetScalar()`
1222: M*/
1223: #if defined(PETSC_USE_COMPLEX)
1224:   #define PetscObjectComposedDataGetScalar(obj, id, data, flag) \
1225:     ((PetscErrorCode)(((obj)->scalarcomposedstate ? (data = (obj)->scalarcomposeddata[id], flag = (PetscBool)((obj)->scalarcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), PETSC_SUCCESS))
1226: #else
1227:   #define PetscObjectComposedDataGetScalar(obj, id, data, flag) PetscObjectComposedDataGetReal(obj, id, data, flag)
1228: #endif

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

1233:    Synopsis:
1234:    #include "petsc/private/petscimpl.h"
1235:    PetscErrorCode PetscObjectComposedDataSetScalarstar(PetscObject obj, PetscInt id, PetscScalar *data)

1237:    Not Collective

1239:    Input Parameters:
1240: +  obj - the object to which data is to be attached
1241: .  id - the identifier for the data
1242: -  data - the data to  be attached, a `PetscScalar` array

1244:    Level: developer

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

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

1251: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1252:           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1253:           `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`, `PetscObjectComposedDataGetScalarstar()`
1254: M*/
1255: #if defined(PETSC_USE_COMPLEX)
1256:   #define PetscObjectComposedDataSetScalarstar(obj, id, data) \
1257:     ((PetscErrorCode)((((obj)->scalarstar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseScalarstar(obj)) || ((obj)->scalarstarcomposeddata[id] = data, (obj)->scalarstarcomposedstate[id] = (obj)->state, PETSC_SUCCESS)))
1258: #else
1259:   #define PetscObjectComposedDataSetScalarstar(obj, id, data) PetscObjectComposedDataSetRealstar(obj, id, data)
1260: #endif
1261: /*MC
1262:    PetscObjectComposedDataGetScalarstar - retrieve `PetscScalar` array data attached to a `PetscObject` that was set with `PetscObjectComposedDataSetScalarstar()`
1263:    attached to an object

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

1269:    Not Collective

1271:    Input Parameters:
1272: +  obj - the object from which data is to be retrieved
1273: -  id - the identifier for the data

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

1279:    Level: developer

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

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

1286: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1287:           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1288:           `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`, `PetscObjectComposedDataSetScalarstar()`
1289: M*/
1290: #if defined(PETSC_USE_COMPLEX)
1291:   #define PetscObjectComposedDataGetScalarstar(obj, id, data, flag) \
1292:     ((PetscErrorCode)(((obj)->scalarstarcomposedstate ? (data = (obj)->scalarstarcomposeddata[id], flag = (PetscBool)((obj)->scalarstarcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), PETSC_SUCCESS))
1293: #else
1294:   #define PetscObjectComposedDataGetScalarstar(obj, id, data, flag) PetscObjectComposedDataGetRealstar(obj, id, data, flag)
1295: #endif

1297: PETSC_EXTERN PetscMPIInt Petsc_Counter_keyval;
1298: PETSC_EXTERN PetscMPIInt Petsc_InnerComm_keyval;
1299: PETSC_EXTERN PetscMPIInt Petsc_OuterComm_keyval;
1300: PETSC_EXTERN PetscMPIInt Petsc_Seq_keyval;
1301: PETSC_EXTERN PetscMPIInt Petsc_ShmComm_keyval;
1302: PETSC_EXTERN PetscMPIInt Petsc_CreationIdx_keyval;
1303: PETSC_EXTERN PetscMPIInt Petsc_Garbage_HMap_keyval;

1305: PETSC_EXTERN PetscMPIInt Petsc_SharedWD_keyval;
1306: PETSC_EXTERN PetscMPIInt Petsc_SharedTmp_keyval;

1308: struct PetscCommStash {
1309:   struct PetscCommStash *next;
1310:   MPI_Comm               comm;
1311: };

1313: /*
1314:   PETSc communicators have this attribute, see
1315:   PetscCommDuplicate(), PetscCommDestroy(), PetscCommGetNewTag(), PetscObjectGetName()
1316: */
1317: typedef struct {
1318:   PetscMPIInt            tag;       /* next free tag value */
1319:   PetscInt               refcount;  /* number of references, communicator can be freed when this reaches 0 */
1320:   PetscInt               namecount; /* used to generate the next name, as in Vec_0, Mat_1, ... */
1321:   PetscMPIInt           *iflags;    /* length of comm size, shared by all calls to PetscCommBuildTwoSided_Allreduce/RedScatter on this comm */
1322:   struct PetscCommStash *comms;     /* communicators available for PETSc to pass off to other packages */
1323: } PetscCommCounter;

1325: typedef enum {
1326:   STATE_BEGIN,
1327:   STATE_PENDING,
1328:   STATE_END
1329: } SRState;

1331: typedef enum {
1332:   PETSC_SR_REDUCE_SUM = 0,
1333:   PETSC_SR_REDUCE_MAX = 1,
1334:   PETSC_SR_REDUCE_MIN = 2
1335: } PetscSRReductionType;

1337: typedef struct {
1338:   MPI_Comm     comm;
1339:   MPI_Request  request;
1340:   PetscBool    mix;
1341:   PetscBool    async;
1342:   PetscScalar *lvalues;    /* this are the reduced values before call to MPI_Allreduce() */
1343:   PetscScalar *gvalues;    /* values after call to MPI_Allreduce() */
1344:   void       **invecs;     /* for debugging only, vector/memory used with each op */
1345:   PetscInt    *reducetype; /* is particular value to be summed or maxed? */
1346:   struct {
1347:     PetscScalar v;
1348:     PetscInt    i;
1349:   }       *lvalues_mix, *gvalues_mix; /* used when mixing reduce operations */
1350:   SRState  state;                     /* are we calling xxxBegin() or xxxEnd()? */
1351:   PetscInt maxops;                    /* total amount of space we have for requests */
1352:   PetscInt numopsbegin;               /* number of requests that have been queued in */
1353:   PetscInt numopsend;                 /* number of requests that have been gotten by user */
1354: } PetscSplitReduction;

1356: PETSC_EXTERN PetscErrorCode PetscSplitReductionGet(MPI_Comm, PetscSplitReduction **);
1357: PETSC_EXTERN PetscErrorCode PetscSplitReductionEnd(PetscSplitReduction *);
1358: PETSC_EXTERN PetscErrorCode PetscSplitReductionExtend(PetscSplitReduction *);

1360: #if defined(PETSC_HAVE_THREADSAFETY)
1361:   #if defined(PETSC_HAVE_CONCURRENCYKIT)
1362:     #if defined(__cplusplus)
1363: /*  CK does not have extern "C" protection in their include files */
1364: extern "C" {
1365:     #endif
1366:     #include <ck_spinlock.h>
1367:     #if defined(__cplusplus)
1368: }
1369:     #endif
1370: typedef ck_spinlock_t PetscSpinlock;

1372: static inline PetscErrorCode PetscSpinlockCreate(PetscSpinlock *ck_spinlock)
1373: {
1374:   ck_spinlock_init(ck_spinlock);
1375:   return PETSC_SUCCESS;
1376: }
1377: static inline PetscErrorCode PetscSpinlockLock(PetscSpinlock *ck_spinlock)
1378: {
1379:   ck_spinlock_lock(ck_spinlock);
1380:   return PETSC_SUCCESS;
1381: }
1382: static inline PetscErrorCode PetscSpinlockUnlock(PetscSpinlock *ck_spinlock)
1383: {
1384:   ck_spinlock_unlock(ck_spinlock);
1385:   return PETSC_SUCCESS;
1386: }
1387: static inline PetscErrorCode PetscSpinlockDestroy(PetscSpinlock *ck_spinlock)
1388: {
1389:   return PETSC_SUCCESS;
1390: }
1391:   #elif (defined(__cplusplus) && defined(PETSC_HAVE_CXX_ATOMIC)) || (!defined(__cplusplus) && defined(PETSC_HAVE_STDATOMIC_H))
1392:     #if defined(__cplusplus)
1393:       #include <atomic>
1394:       #define petsc_atomic_flag                 std::atomic_flag
1395:       #define petsc_atomic_flag_test_and_set(p) std::atomic_flag_test_and_set_explicit(p, std::memory_order_relaxed)
1396:       #define petsc_atomic_flag_clear(p)        std::atomic_flag_clear_explicit(p, std::memory_order_relaxed)
1397:     #else
1398:       #include <stdatomic.h>
1399:       #define petsc_atomic_flag                 atomic_flag
1400:       #define petsc_atomic_flag_test_and_set(p) atomic_flag_test_and_set_explicit(p, memory_order_relaxed)
1401:       #define petsc_atomic_flag_clear(p)        atomic_flag_clear_explicit(p, memory_order_relaxed)
1402:     #endif

1404: typedef petsc_atomic_flag PetscSpinlock;

1406: static inline PetscErrorCode PetscSpinlockCreate(PetscSpinlock *spinlock)
1407: {
1408:   petsc_atomic_flag_clear(spinlock);
1409:   return PETSC_SUCCESS;
1410: }
1411: static inline PetscErrorCode PetscSpinlockLock(PetscSpinlock *spinlock)
1412: {
1413:   do {
1414:   } while (petsc_atomic_flag_test_and_set(spinlock));
1415:   return PETSC_SUCCESS;
1416: }
1417: static inline PetscErrorCode PetscSpinlockUnlock(PetscSpinlock *spinlock)
1418: {
1419:   petsc_atomic_flag_clear(spinlock);
1420:   return PETSC_SUCCESS;
1421: }
1422: static inline PetscErrorCode PetscSpinlockDestroy(PetscSpinlock *spinlock)
1423: {
1424:   return PETSC_SUCCESS;
1425: }
1426:     #undef petsc_atomic_flag_test_and_set
1427:     #undef petsc_atomic_flag_clear
1428:     #undef petsc_atomic_flag

1430:   #elif defined(PETSC_HAVE_OPENMP)

1432:     #include <omp.h>
1433: typedef omp_lock_t PetscSpinlock;

1435: static inline PetscErrorCode PetscSpinlockCreate(PetscSpinlock *omp_lock)
1436: {
1437:   omp_init_lock(omp_lock);
1438:   return PETSC_SUCCESS;
1439: }
1440: static inline PetscErrorCode PetscSpinlockLock(PetscSpinlock *omp_lock)
1441: {
1442:   omp_set_lock(omp_lock);
1443:   return PETSC_SUCCESS;
1444: }
1445: static inline PetscErrorCode PetscSpinlockUnlock(PetscSpinlock *omp_lock)
1446: {
1447:   omp_unset_lock(omp_lock);
1448:   return PETSC_SUCCESS;
1449: }
1450: static inline PetscErrorCode PetscSpinlockDestroy(PetscSpinlock *omp_lock)
1451: {
1452:   omp_destroy_lock(omp_lock);
1453:   return PETSC_SUCCESS;
1454: }
1455:   #else
1456:     #if defined(__cplusplus)
1457:       #error "Thread safety requires either --download-concurrencykit, std::atomic, or --with-openmp"
1458:     #else
1459:       #error "Thread safety requires either --download-concurrencykit, stdatomic.h, or --with-openmp"
1460:     #endif
1461:   #endif

1463: #else
1464: typedef int PetscSpinlock;
1465:   #define PetscSpinlockCreate(a)  PETSC_SUCCESS
1466:   #define PetscSpinlockLock(a)    PETSC_SUCCESS
1467:   #define PetscSpinlockUnlock(a)  PETSC_SUCCESS
1468:   #define PetscSpinlockDestroy(a) PETSC_SUCCESS
1469: #endif

1471: #if defined(PETSC_HAVE_THREADSAFETY)
1472: PETSC_INTERN PetscSpinlock PetscViewerASCIISpinLockOpen;
1473: PETSC_INTERN PetscSpinlock PetscViewerASCIISpinLockStdout;
1474: PETSC_INTERN PetscSpinlock PetscViewerASCIISpinLockStderr;
1475: PETSC_INTERN PetscSpinlock PetscCommSpinLock;
1476: #endif

1478: PETSC_EXTERN PetscLogEvent PETSC_Barrier;
1479: PETSC_EXTERN PetscLogEvent PETSC_BuildTwoSided;
1480: PETSC_EXTERN PetscLogEvent PETSC_BuildTwoSidedF;
1481: PETSC_EXTERN PetscBool     use_gpu_aware_mpi;
1482: PETSC_EXTERN PetscBool     PetscPrintFunctionList;

1484: #if defined(PETSC_HAVE_ADIOS)
1485: PETSC_EXTERN int64_t Petsc_adios_group;
1486: #endif

1488: #if defined(PETSC_HAVE_KOKKOS)
1489: PETSC_INTERN PetscBool      PetscBeganKokkos;
1490: PETSC_EXTERN PetscBool      PetscKokkosInitialized;
1491: PETSC_INTERN PetscErrorCode PetscKokkosIsInitialized_Private(PetscBool *);
1492: PETSC_INTERN PetscErrorCode PetscKokkosFinalize_Private(void);
1493: #endif

1495: #if defined(PETSC_HAVE_OPENMP)
1496: PETSC_EXTERN PetscInt PetscNumOMPThreads;
1497: #endif

1499: #endif /* PETSCIMPL_H */