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(expr)
 13: #else
 14:   #define PetscDisableStaticAnalyzerForExpressionUnderstandingThatThisIsDangerousAndBugprone(expr) expr
 15: #endif

 17: #if PetscDefined(USE_DEBUG)
 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)         0
 25:   #define PetscStackView(file)              0
 26:   #define PetscStackReset()                 0
 27:   #define PetscStackCopy(stackin, stackout) 0
 28:   #define PetscStackPrint(stack, file)      0
 29: #endif /* PetscDefined(USE_DEBUG) */

 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: /*MC
152:   PetscHeaderCreate - Creates a PETSc object of a particular class

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

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

171:   Output Parameter:
172: . h - The newly created `PetscObject`

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

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

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

187:   Example Usage:
188:   Existing `PetscObject`s may be easily created as shown. Unless otherwise stated, a particular
189:   objects `destroy` and `view` functions are exactly `<OBJECT_TYPE>Destroy()` and
190:   `<OBJECT_TYPE>View()`.
191: .vb
192:   Vec v;

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

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

208:   PetscErrorCode MyObjectDestroy(MyObject *);
209:   PetscErrorCode MyObjectView(MyObject);

211:   MyCPetscObject obj;

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

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

219:   // ERROR must be a single-level pointer
220:   PetscHeaderCreate(&obj, ...);
221: .ve

223:   Illustrating proper construction from C++\:
224: .vb
225:   // ERROR, class is not standard layout, first member must be publicly accessible
226:   class BadCppPetscObject
227:   {
228:     _p_PetscObject header;
229:   };

231:   // ERROR, class is not standard layout, has a virtual function and virtual inheritance
232:   class BadCppPetscObject2 : virtual BaseClass
233:   {
234:   public:
235:     _p_PetscObject header;

237:     virtual void foo();
238:   };

240:   // ERROR, class is not standard layout! Has non-standard layout member
241:   class BadCppPetscObject2
242:   {
243:   public:
244:     _p_PetscObject    header;
245:     BadCppPetscObject non_standard_layout;
246:   };

248:   // OK, class is standard layout!
249:   class GoodCppPetscObject;
250:   using MyCppObject = GoodCppPetscObject *;

252:   // OK, non-virtual inheritance of other standard layout class does not affect layout
253:   class GoodCppPetscObject : StandardLayoutClass
254:   {
255:   public:
256:     // OK, non standard layout member is static, does not affect layout
257:     static BadCppPetscObject non_standard_layout;

259:     // OK, first non-static member is _p_PetscObject
260:     _p_PetscObject header;

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

265:     // OK, may use "member" functions for destroy and view so long as they are static
266:     static PetscErrorCode destroy(MyCppObject *);
267:     static PetscErrorCode view(MyCppObject);
268:   };

270:   // OK, usage via pointer
271:   MyObject obj;

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

276:   Level: developer

278: .seealso: `PetscHeaderDestroy()`, `PetscClassIdRegister()`
279: M*/
280: #define PetscHeaderCreate(h, classid, class_name, descr, mansec, comm, destroy, view) \
281:   (PetscNew(&(h)) || PetscHeaderCreate_Private((PetscObject)(h), classid, class_name, descr, mansec, comm, (PetscObjectDestroyFunction)(destroy), (PetscObjectViewFunction)(view)) || PetscLogObjectCreate(h))

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

287: /*MC
288:   PetscHeaderDestroy - Final step in destroying a `PetscObject`

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

294:   Input Parameters:
295: . h - A pointer to the header created with `PetscHeaderCreate()`

297:   Notes:
298:   `h` is freed and set to `PETSC_NULLPTR` when this routine returns.

300:   Example Usage:
301: .vb
302:   PetscObject obj;

304:   PetscHeaderCreate(obj, ...);
305:   // use obj...

307:   // note pointer to obj is used
308:   PetscHeaderDestroy(&obj);
309: .ve

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

322:   // assume obj is created/initialized elsewhere...
323:   MyPetscObject obj;

325:   // OK, should dispose of all dynamically allocated resources before calling
326:   // PetscHeaderDestroy()
327:   PetscFree(obj->foo);

329:   // OK, dispose of obj
330:   PetscHeaderDestroy(&obj);

332:   // ERROR, obj points to NULL here, accessing obj->bar may result in segmentation violation!
333:   // obj->bar is potentially leaked!
334:   PetscFree(obj->bar);
335: .ve

337:   Level: developer

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

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

349: PETSC_INTERN PetscErrorCode PetscCitationsInitialize(void);
350: PETSC_INTERN PetscErrorCode PetscFreeMPIResources(void);
351: PETSC_INTERN PetscErrorCode PetscOptionsHasHelpIntro_Internal(PetscOptions, PetscBool *);

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

356: #if PetscDefined(HAVE_SETJMP_H)
358: #else
360: #endif
361: #if !defined(PETSC_CLANG_STATIC_ANALYZER)
362:   /*
363:     Macros to test if a PETSc object is valid and if pointers are valid
364: */
365:   #if !defined(PETSC_USE_DEBUG)

368:       do { \
369:         (void)(h); \
370:       } while (0)
372:       do { \
373:         (void)(h); \
374:       } while (0)
376:       do { \
377:         (void)(h); \
378:       } while (0)
380:       do { \
381:         (void)(h); \
382:       } while (0)
384:       do { \
385:         (void)(h); \
386:       } while (0)
388:       do { \
389:         (void)(h); \
390:       } while (0)
392:       do { \
393:         (void)(h); \
394:       } while (0)
396:       do { \
397:         (void)(h); \
398:       } while (0)
400:       do { \
401:         (void)(h); \
402:       } while (0)
404:       do { \
405:         (void)(h); \
406:       } while (0)
408:       do { \
409:         (void)(h); \
410:       } while (0)
412:       do { \
413:         (void)(h); \
414:       } while (0)

416:   #else

418:     /*  This check is for subtype methods such as DMDAGetCorners() that do not use the PetscTryMethod() or PetscUseMethod() paradigm */
420:       do { \
421:         PetscBool _7_same; \
423:         PetscObjectTypeCompare((PetscObject)(h), t, &_7_same); \
425:       } while (0)

428:       do { \
431:       } while (0)

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

443:       do { \
447:       } while (0)


459:       do { \
461:       } while (0)
462:   #endif
463: #else  /* PETSC_CLANG_STATIC_ANALYZER */
464: template <typename T>
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: #endif /* PETSC_CLANG_STATIC_ANALYZER */

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

503: #if !defined(PETSC_CLANG_STATIC_ANALYZER)
504:   #if !defined(PETSC_USE_DEBUG)

507:       do { \
508:         (void)(a); \
509:         (void)(b); \
510:       } while (0)
512:       do { \
513:         (void)(a); \
514:       } while (0)
516:       do { \
517:         (void)(a); \
518:       } while (0)
520:       do { \
521:         (void)(a); \
522:       } while (0)
524:       do { \
525:         (void)(a); \
526:         (void)(b); \
527:       } while (0)
529:       do { \
530:         (void)(a); \
531:         (void)(b); \
532:       } while (0)
534:       do { \
535:         (void)(a); \
536:         (void)(b); \
537:       } while (0)
539:       do { \
540:         (void)(a); \
541:         (void)(b); \
542:       } while (0)
544:       do { \
545:         (void)(a); \
546:         (void)(b); \
547:       } while (0)
549:       do { \
550:         (void)(a); \
551:         (void)(b); \
552:       } while (0)
554:       do { \
555:         (void)(a); \
556:         (void)(b); \
557:       } while (0)
559:       do { \
560:         (void)(a); \
561:         (void)(b); \
562:       } while (0)
564:       do { \
565:         (void)(n); \
566:         (void)(idx); \
567:       } while (0)

569:   #else

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

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

577:   This macro is used incorrectly in the code. Many places that do not need identity of the
578:   types incorrectly call this check and would need to be fixed if this macro is enabled.
579: */
580:     #if 0
582:         do { \
583:           PetscBool pcst_type_eq_ = PETSC_TRUE; \
584:           PetscStrcmp(((PetscObject)(a))->type_name, (((PetscObject)(b)))->type_name, &pcst_type_eq_); \
586:         } while (0)
587:     #else
589:         do { \
590:           (void)(a); \
591:           (void)(b); \
592:         } while (0)
593:     #endif

595:     /*
596:     Check type_name
597: */
599:       do { \
600:         PetscBool _7_match; \
601:         PetscObjectTypeCompare(((PetscObject)(a)), (type), &_7_match); \
603:       } while (0)

606:       do { \
607:         PetscBool _7_match; \
608:         PetscObjectTypeCompareAny(((PetscObject)(a)), &_7_match, (type1), (type2), ""); \
610:       } while (0)

612:     /*
613:    Use this macro to check if the type is set
614: */

617:     /*
618:    Sometimes object must live on same communicator to inter-operate
619: */
621:       do { \
622:         PetscMPIInt _7_flag; \
623:         MPI_Comm_compare(PetscObjectComm((PetscObject)(a)), PetscObjectComm((PetscObject)(b)), &_7_flag); \
625:       } while (0)

628:       do { \
631:       } while (0)

634:       do { \
635:         PetscScalar b0 = (b); \
636:         PetscReal   b1[5], b2[5]; \
637:         if (PetscIsNanScalar(b0)) { \
638:           b1[4] = 1; \
639:         } else { \
640:           b1[4] = 0; \
641:         }; \
642:         b1[0] = -PetscRealPart(b0); \
643:         b1[1] = PetscRealPart(b0); \
644:         b1[2] = -PetscImaginaryPart(b0); \
645:         b1[3] = PetscImaginaryPart(b0); \
646:         MPIU_Allreduce(b1, b2, 5, MPIU_REAL, MPIU_MAX, PetscObjectComm((PetscObject)(a))); \
648:       } while (0)

651:       do { \
652:         PetscReal b0 = (b), b1[3], b2[3]; \
653:         if (PetscIsNanReal(b0)) { \
654:           b1[2] = 1; \
655:         } else { \
656:           b1[2] = 0; \
657:         }; \
658:         b1[0] = -b0; \
659:         b1[1] = b0; \
660:         MPIU_Allreduce(b1, b2, 3, MPIU_REAL, MPIU_MAX, PetscObjectComm((PetscObject)(a))); \
662:       } while (0)

665:       do { \
666:         PetscInt b0 = (b), b1[2], b2[2]; \
667:         b1[0]       = -b0; \
668:         b1[1]       = b0; \
669:         MPIU_Allreduce(b1, b2, 2, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)(a))); \
671:       } while (0)

674:       do { \
675:         PetscMPIInt b0 = (b), b1[2], b2[2]; \
676:         b1[0]          = -b0; \
677:         b1[1]          = b0; \
678:         MPIU_Allreduce(b1, b2, 2, MPI_INT, MPI_MAX, PetscObjectComm((PetscObject)(a))); \
680:       } while (0)

683:       do { \
684:         PetscMPIInt b0 = (PetscMPIInt)(b), b1[2], b2[2]; \
685:         b1[0]          = -b0; \
686:         b1[1]          = b0; \
687:         MPIU_Allreduce(b1, b2, 2, MPI_INT, MPI_MAX, PetscObjectComm((PetscObject)(a))); \
689:       } while (0)

692:       do { \
693:         PetscMPIInt b0 = (PetscMPIInt)(b), b1[2], b2[2]; \
694:         b1[0]          = -b0; \
695:         b1[1]          = b0; \
696:         MPIU_Allreduce(b1, b2, 2, MPI_INT, MPI_MAX, PetscObjectComm((PetscObject)(a))); \
698:       } while (0)

701:       do { \
702:         PetscBool _1_flg; \
703:         PetscSorted(n, idx, _1_flg); \
705:       } while (0)

707:   #endif
708: #else  /* PETSC_CLANG_STATIC_ANALYZER */
709: template <typename Ta, typename Tb>
711: template <typename Ta, typename Tb>
713: template <typename Ta, typename Tb, typename Tc>
715: template <typename T>
717: template <typename Ta, typename Tb>
719: template <typename Ta, typename Tb>
721: template <typename Ta, typename Tb>
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 T>
735: #endif /* PETSC_CLANG_STATIC_ANALYZER */

737: /*MC
738:    PetscTryMethod - Queries an object for a method added with `PetscObjectComposeFunction()`, if it exists then calls it.

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

744:    Input Parameters:
745: +   obj - the object
746: .   name - the name of the method, for example, "KSPGMRESSetRestart_C" for the function `KSPGMRESSetRestart()`
747: .   arg_types - the argument types for the method, for example, (KSP,PetscInt)
748: -   args - the arguments for the method, for example, (ksp,restart))

750:    Level: developer

752:    Notes:
753:    The object is always the implicit first argument of the method and is not listed in arg_types or args

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.

761: M*/
762: #define PetscTryMethod(obj, A, B, C) \
763:   do { \
764:     PetscErrorCode(*_7_f) B; \
765:     PetscObjectQueryFunction((PetscObject)(obj), A, &_7_f); \
766:     if (_7_f) (*_7_f)C; \
767:   } while (0)

769: /*MC
770:    PetscUseMethod - Queries an object 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
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:    The object is always the implicit first argument of the method and is not listed in arg_types or args

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

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

793: M*/
794: #define PetscUseMethod(obj, A, B, C) \
795:   do { \
796:     PetscErrorCode(*_7_f) B; \
797:     PetscObjectQueryFunction((PetscObject)(obj), A, &_7_f); \
799:     (*_7_f)C; \
800:   } while (0)

802: /*
803:   Use Microsoft traditional preprocessor.

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

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

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

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

816:   #define PetscUseTypeMethod(obj, OP, ...) \
817:     do { \
818:       PetscErrorCode ierr_p_; \
819:       PetscStackUpdateLine; \
821:       ierr_p_ = (*(obj)->ops->OP)(obj, __VA_ARGS__); \
822:       ierr_p_; \
823:     } while (0)

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

835: #else

837:   /*MC
838:    PetscUseTypeMethod - Call a method on a PETSc object, that is a function in the objects function table obj->ops, error if the method does not exist

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

844:    Input Parameters:
845: +   obj - the object the method is called on
846: .   method - the name of the method, for example, mult for the PETSc routine MatMult()
847: -   other_args - the other arguments for the method, obj is the first argument

849:    Level: developer

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

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

857: M*/
858:   #define PetscUseTypeMethod(obj, ...) \
859:     do { \
861:                  PetscStringize(PETSC_FIRST_ARG((__VA_ARGS__,unused))), ((PetscObject)obj)->class_name, ((PetscObject)obj)->type_name); \
862:       (*(obj)->ops->PETSC_FIRST_ARG((__VA_ARGS__, unused)))(obj PETSC_REST_ARG(__VA_ARGS__)); \
863:     } while (0)

865:   /*MC
866:    PetscTryTypeMethod - Call a method on a PETSc object, that is a function in the objects function table obj->ops, skip if the method does not exist

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

872:    Input Parameters:
873: +   obj - the object the method is called on
874: .   method - the name of the method, for example, mult for the PETSc routine MatMult()
875: -   other_args - the other arguments for the method, obj is the first argument

877:    Level: developer

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

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

885: M*/
886:   #define PetscTryTypeMethod(obj, ...) \
887:     do { \
888:       if ((obj)->ops->PETSC_FIRST_ARG((__VA_ARGS__, unused))) (*(obj)->ops->PETSC_FIRST_ARG((__VA_ARGS__, unused)))(obj PETSC_REST_ARG(__VA_ARGS__)); \
889:     } while (0)

891: #endif

893: /*MC
894:    PetscObjectStateIncrease - Increases the state of any `PetscObject`

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

900:    Logically Collective

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

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:    Level: developer

926: .seealso: `PetscObjectStateGet()`, `PetscObject`

928: M*/
929: #define PetscObjectStateIncrease(obj) ((obj)->state++, 0)

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

942: /*MC
943:    PetscObjectComposedDataSetInt - attach integer data to a `PetscObject` that may be accessed with `PetscObjectComposedDataGetInt()`

945:    Synopsis:
946:    #include "petsc/private/petscimpl.h"
947:    PetscErrorCode PetscObjectComposedDataSetInt(PetscObject obj,int id,int data)

949:    Not collective

951:    Input parameters:
952: +  obj - the object to which data is to be attached
953: .  id - the identifier for the data
954: -  data - the data to  be attached

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

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

962:    Level: developer

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

970: /*MC
971:    PetscObjectComposedDataGetInt - retrieve integer data attached to an object with `PetscObjectComposedDataSetInt()`

973:    Synopsis:
974:    #include "petsc/private/petscimpl.h"
975:    PetscErrorCode PetscObjectComposedDataGetInt(PetscObject obj,int id,int data,PetscBool  flag)

977:    Not collective

979:    Input parameters:
980: +  obj - the object from which data is to be retrieved
981: -  id - the identifier for the data

983:    Output parameters:
984: +  data - the data to be retrieved
985: -  flag - `PETSC_TRUE` if the data item exists and is valid, `PETSC_FALSE` otherwise

987:    Level: developer

989:    Notes:
990:    The 'data' and 'flag' variables are inlined, so they are not pointers.

992:    The length of the array accessed must be known.

994: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetReal()`,
995:           `PetscObjectComposedDataGetIntstar()`, `PetscObjectComposedDataSetIntstar()`, `PetscObject`,
996:           `PetscObjectCompose()`, `PetscObjectQuery()`
997: M*/
998: #define PetscObjectComposedDataGetInt(obj, id, data, flag) (((obj)->intcomposedstate ? (data = (obj)->intcomposeddata[id], flag = (PetscBool)((obj)->intcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), 0)

1000: /*MC
1001:    PetscObjectComposedDataSetIntstar - attach an integer array data to a `PetscObject` that may be accessed with `PetscObjectComposedDataGetIntstar()`

1003:    Synopsis:
1004:    #include "petsc/private/petscimpl.h"
1005:    PetscErrorCode PetscObjectComposedDataSetIntstar(PetscObject obj,int id,int *data)

1007:    Not collective

1009:    Input parameters:
1010: +  obj - the object to which data is to be attached
1011: .  id - the identifier for the data
1012: -  data - the data to  be attached

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

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

1019:    Level: developer

1021: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetReal()`,
1022:           `PetscObjectComposedDataGetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1023:           `PetscObjectCompose()`, `PetscObjectQuery()`
1024: M*/
1025: #define PetscObjectComposedDataSetIntstar(obj, id, data) \
1026:   ((((obj)->intstar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseIntstar(obj)) || ((obj)->intstarcomposeddata[id] = data, (obj)->intstarcomposedstate[id] = (obj)->state, 0))

1028: /*MC
1029:    PetscObjectComposedDataGetIntstar - retrieve integer array data attached to an object with `PetscObjectComposedDataSetIntstar()`

1031:    Synopsis:
1032:    #include "petsc/private/petscimpl.h"
1033:    PetscErrorCode PetscObjectComposedDataGetIntstar(PetscObject obj,int id,int *data,PetscBool  flag)

1035:    Not collective

1037:    Input parameters:
1038: +  obj - the object from which data is to be retrieved
1039: -  id - the identifier for the data

1041:    Output parameters:
1042: +  data - the data to be retrieved
1043: -  flag - `PETSC_TRUE` if the data item exists and is valid, `PETSC_FALSE` otherwise

1045:    Notes:
1046:    The 'data' and 'flag' variables are inlined, so they are not pointers.

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

1050:    Level: developer

1052: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetReal()`,
1053:           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1054:           `PetscObjectCompose()`, `PetscObjectQuery()`
1055: M*/
1056: #define PetscObjectComposedDataGetIntstar(obj, id, data, flag) (((obj)->intstarcomposedstate ? (data = (obj)->intstarcomposeddata[id], flag = (PetscBool)((obj)->intstarcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), 0)

1058: /*MC
1059:    PetscObjectComposedDataSetReal - attach real data to a `PetscObject` that may be accessed with `PetscObjectComposedDataGetReal()`

1061:    Synopsis:
1062:    #include "petsc/private/petscimpl.h"
1063:    PetscErrorCode PetscObjectComposedDataSetReal(PetscObject obj,int id,PetscReal data)

1065:    Not collective

1067:    Input parameters:
1068: +  obj - the object to which data is to be attached
1069: .  id - the identifier for the data
1070: -  data - the data to  be attached

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

1075:    Level: developer

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

1083: /*MC
1084:    PetscObjectComposedDataGetReal - retrieve real data attached to an object set with `PetscObjectComposedDataSetReal()`

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

1090:    Not collective

1092:    Input parameters:
1093: +  obj - the object from which data is to be retrieved
1094: -  id - the identifier for the data

1096:    Output parameters:
1097: +  data - the data to be retrieved
1098: -  flag - `PETSC_TRUE` if the data item exists and is valid, `PETSC_FALSE` otherwise

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

1103:    Level: developer

1105: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataSetIntstar()`,
1106:           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1107:           `PetscObjectCompose()`, `PetscObjectQuery()`
1108: M*/
1109: #define PetscObjectComposedDataGetReal(obj, id, data, flag) (((obj)->realcomposedstate ? (data = (obj)->realcomposeddata[id], flag = (PetscBool)((obj)->realcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), 0)

1111: /*MC
1112:    PetscObjectComposedDataSetRealstar - attach real array data to a `PetscObject` that may be retrieved with `PetscObjectComposedDataGetRealstar()`

1114:    Synopsis:
1115:    #include "petsc/private/petscimpl.h"
1116:    PetscErrorCode PetscObjectComposedDataSetRealstar(PetscObject obj,int id,PetscReal *data)

1118:    Not collective

1120:    Input parameters:
1121: +  obj - the object to which data is to be attached
1122: .  id - the identifier for the data
1123: -  data - the data to  be attached

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:    Level: developer

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

1139: /*MC
1140:    PetscObjectComposedDataGetRealstar - retrieve real array data attached to an object with `PetscObjectComposedDataSetRealstar()`

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

1146:    Not collective

1148:    Input parameters:
1149: +  obj - the object from which data is to be retrieved
1150: -  id - the identifier for the data

1152:    Output parameters:
1153: +  data - the data to be retrieved
1154: -  flag - `PETSC_TRUE` if the data item exists and is valid, `PETSC_FALSE` otherwise

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:    Level: developer

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

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

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

1176:    Not collective

1178:    Input parameters:
1179: +  obj - the object to which data is to be attached
1180: .  id - the identifier for the data
1181: -  data - the data to  be attached

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

1186:    Level: developer

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

1200:    Synopsis:
1201:    #include "petsc/private/petscimpl.h"
1202:    PetscErrorCode PetscObjectComposedDataGetScalar(PetscObject obj,int 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
1212: -  flag - `PETSC_TRUE` if the data item exists and is valid, `PETSC_FALSE` otherwise

1214:    Note:
1215:    The 'data' and 'flag' variables are inlined, so they are not pointers.

1217:    Level: developer

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) (((obj)->scalarcomposedstate ? (data = (obj)->scalarcomposeddata[id], flag = (PetscBool)((obj)->scalarcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), 0)
1225: #else
1226:   #define PetscObjectComposedDataGetScalar(obj, id, data, flag) PetscObjectComposedDataGetReal(obj, id, data, flag)
1227: #endif

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

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

1236:    Not collective

1238:    Input parameters:
1239: +  obj - the object to which data is to be attached
1240: .  id - the identifier for the data
1241: -  data - the data to  be attached

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

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

1248:    Level: developer

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

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

1268:    Not collective

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

1274:    Output parameters:
1275: +  data - the data to be retrieved
1276: -  flag - `PETSC_TRUE` if the data item exists and is valid, `PETSC_FALSE` otherwise

1278:    Notes:
1279:    The 'data' and 'flag' variables are inlined, so they are not pointers.

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

1283:    Level: developer

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

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

1303: struct PetscCommStash {
1304:   struct PetscCommStash *next;
1305:   MPI_Comm               comm;
1306: };

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

1320: typedef enum {
1321:   STATE_BEGIN,
1322:   STATE_PENDING,
1323:   STATE_END
1324: } SRState;

1326: typedef enum {
1327:   PETSC_SR_REDUCE_SUM = 0,
1328:   PETSC_SR_REDUCE_MAX = 1,
1329:   PETSC_SR_REDUCE_MIN = 2
1330: } PetscSRReductionType;

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

1351: PETSC_EXTERN PetscErrorCode PetscSplitReductionGet(MPI_Comm, PetscSplitReduction **);
1352: PETSC_EXTERN PetscErrorCode PetscSplitReductionEnd(PetscSplitReduction *);
1353: PETSC_EXTERN PetscErrorCode PetscSplitReductionExtend(PetscSplitReduction *);

1355: #if !defined(PETSC_SKIP_SPINLOCK)
1356:   #if defined(PETSC_HAVE_THREADSAFETY)
1357:     #if defined(PETSC_HAVE_CONCURRENCYKIT)
1358:       #if defined(__cplusplus)
1359: /*  CK does not have extern "C" protection in their include files */
1360: extern "C" {
1361:       #endif
1362:       #include <ck_spinlock.h>
1363:       #if defined(__cplusplus)
1364: }
1365:       #endif
1366: typedef ck_spinlock_t        PetscSpinlock;
1367: static inline PetscErrorCode PetscSpinlockCreate(PetscSpinlock *ck_spinlock)
1368: {
1369:   ck_spinlock_init(ck_spinlock);
1370:   return 0;
1371: }
1372: static inline PetscErrorCode PetscSpinlockLock(PetscSpinlock *ck_spinlock)
1373: {
1374:   ck_spinlock_lock(ck_spinlock);
1375:   return 0;
1376: }
1377: static inline PetscErrorCode PetscSpinlockUnlock(PetscSpinlock *ck_spinlock)
1378: {
1379:   ck_spinlock_unlock(ck_spinlock);
1380:   return 0;
1381: }
1382: static inline PetscErrorCode PetscSpinlockDestroy(PetscSpinlock *ck_spinlock)
1383: {
1384:   return 0;
1385: }
1386:     #elif defined(PETSC_HAVE_OPENMP)

1388:       #include <omp.h>
1389: typedef omp_lock_t           PetscSpinlock;
1390: static inline PetscErrorCode PetscSpinlockCreate(PetscSpinlock *omp_lock)
1391: {
1392:   omp_init_lock(omp_lock);
1393:   return 0;
1394: }
1395: static inline PetscErrorCode PetscSpinlockLock(PetscSpinlock *omp_lock)
1396: {
1397:   omp_set_lock(omp_lock);
1398:   return 0;
1399: }
1400: static inline PetscErrorCode PetscSpinlockUnlock(PetscSpinlock *omp_lock)
1401: {
1402:   omp_unset_lock(omp_lock);
1403:   return 0;
1404: }
1405: static inline PetscErrorCode PetscSpinlockDestroy(PetscSpinlock *omp_lock)
1406: {
1407:   omp_destroy_lock(omp_lock);
1408:   return 0;
1409: }
1410:     #else
1411:       #error "Thread safety requires either --with-openmp or --download-concurrencykit"
1412:     #endif

1414:   #else
1415: typedef int PetscSpinlock;
1416:     #define PetscSpinlockCreate(a)  0
1417:     #define PetscSpinlockLock(a)    0
1418:     #define PetscSpinlockUnlock(a)  0
1419:     #define PetscSpinlockDestroy(a) 0
1420:   #endif

1422:   #if defined(PETSC_HAVE_THREADSAFETY)
1423: PETSC_INTERN PetscSpinlock PetscViewerASCIISpinLockOpen;
1424: PETSC_INTERN PetscSpinlock PetscViewerASCIISpinLockStdout;
1425: PETSC_INTERN PetscSpinlock PetscViewerASCIISpinLockStderr;
1426: PETSC_INTERN PetscSpinlock PetscCommSpinLock;
1427:   #endif
1428: #endif

1430: PETSC_EXTERN PetscLogEvent PETSC_Barrier;
1431: PETSC_EXTERN PetscLogEvent PETSC_BuildTwoSided;
1432: PETSC_EXTERN PetscLogEvent PETSC_BuildTwoSidedF;
1433: PETSC_EXTERN PetscBool     use_gpu_aware_mpi;
1434: PETSC_EXTERN PetscBool     PetscPrintFunctionList;

1436: #if defined(PETSC_HAVE_ADIOS)
1437: PETSC_EXTERN int64_t Petsc_adios_group;
1438: #endif

1440: #if defined(PETSC_HAVE_KOKKOS)
1441: PETSC_INTERN PetscBool      PetscBeganKokkos;
1442: PETSC_EXTERN PetscBool      PetscKokkosInitialized;
1443: PETSC_INTERN PetscErrorCode PetscKokkosIsInitialized_Private(PetscBool *);
1444: PETSC_INTERN PetscErrorCode PetscKokkosFinalize_Private(void);
1445: #endif

1447: #if defined(PETSC_HAVE_OPENMP)
1448: PETSC_EXTERN PetscInt PetscNumOMPThreads;
1449: #endif

1451: #endif /* PETSCIMPL_H */