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: #if defined(PETSC_HAVE_CLOSURE)
 36: PETSC_EXTERN PetscErrorCode PetscVFPrintfSetClosure(int (^)(const char *));
 37: #endif

 39: /*
 40:    All major PETSc data structures have a common core; this is defined
 41:    below by PETSCHEADER.

 43:    PetscHeaderCreate() should be used whenever creating a PETSc structure.
 44: */

 46: /*
 47:    PetscOps: structure of core operations that all PETSc objects support.

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

 66: typedef struct {
 67:   PetscErrorCode (*view)(PetscObject, PetscViewer);
 68:   PetscErrorCode (*destroy)(PetscObject *);
 69:   PetscErrorCode (*compose)(PetscObject, const char[], PetscObject);
 70:   PetscErrorCode (*query)(PetscObject, const char[], PetscObject *);
 71:   PetscErrorCode (*composefunction)(PetscObject, const char[], void (*)(void));
 72:   PetscErrorCode (*queryfunction)(PetscObject, const char[], void (**)(void));
 73: } PetscOps;

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

 85: typedef struct {
 86:   void (*func)(void);
 87:   void *ctx;
 88: } PetscFortranCallback;

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

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

146: #define PETSCHEADER(ObjectOps) \
147:   _p_PetscObject hdr; \
148:   ObjectOps      ops[1]

150: #define PETSCFREEDHEADER -1

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

155: /*@C
156:     PetscHeaderCreate - Creates a PETSc object of a particular class

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")
161: .   descr - string containing short description; should be static (for example "Vector")
162: .   mansec - string indicating section in manual pages; should be static (for example "Vec")
163: .   comm - the MPI Communicator
164: .   destroy - the destroy routine for this object (for example `VecDestroy()`)
165: -   view - the view routine for this object (for example `VecView()`)

167:     Output Parameter:
168: .   h - the newly created object

170:     Level: developer

172: .seealso: `PetscHeaderDestroy()`, `PetscClassIdRegister()`

174: @*/
175: #define PetscHeaderCreate(h, classid, class_name, descr, mansec, comm, destroy, view) \
176:   (PetscNew(&(h)) || PetscHeaderCreate_Private((PetscObject)(h), classid, class_name, descr, mansec, comm, (PetscObjectDestroyFunction)(destroy), (PetscObjectViewFunction)(view)) || PetscLogObjectCreate(h))

178: PETSC_EXTERN PetscErrorCode PetscComposedQuantitiesDestroy(PetscObject obj);
179: PETSC_EXTERN PetscErrorCode PetscHeaderCreate_Private(PetscObject, PetscClassId, const char[], const char[], const char[], MPI_Comm, PetscObjectDestroyFunction, PetscObjectViewFunction);
180: PETSC_INTERN PetscObjectId  PetscObjectNewId_Internal(void);

182: /*@C
183:     PetscHeaderDestroy - Final step in destroying a PetscObject

185:     Input Parameters:
186: .   h - the header created with `PetscHeaderCreate()`

188:     Level: developer

190: .seealso: `PetscHeaderCreate()`
191: @*/
192: #define PetscHeaderDestroy(h) (PetscHeaderDestroy_Private((PetscObject)(*(h)), PETSC_FALSE) || PetscFree(*(h)))

194: PETSC_EXTERN PetscErrorCode                PetscHeaderDestroy_Private(PetscObject, PetscBool);
195: PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode PetscHeaderReset_Internal(PetscObject);
196: PETSC_EXTERN PetscErrorCode                PetscObjectCopyFortranFunctionPointers(PetscObject, PetscObject);
197: PETSC_EXTERN PetscErrorCode                PetscObjectSetFortranCallback(PetscObject, PetscFortranCallbackType, PetscFortranCallbackId *, void (*)(void), void *ctx);
198: PETSC_EXTERN PetscErrorCode                PetscObjectGetFortranCallback(PetscObject, PetscFortranCallbackType, PetscFortranCallbackId, void (**)(void), void **ctx);

200: PETSC_INTERN PetscErrorCode PetscCitationsInitialize(void);
201: PETSC_INTERN PetscErrorCode PetscFreeMPIResources(void);
202: PETSC_INTERN PetscErrorCode PetscOptionsHasHelpIntro_Internal(PetscOptions, PetscBool *);

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

207: #if PetscDefined(HAVE_SETJMP_H)
209: #else
211: #endif
212: #if !defined(PETSC_CLANG_STATIC_ANALYZER)
213:   /*
214:     Macros to test if a PETSc object is valid and if pointers are valid
215: */
216:   #if !defined(PETSC_USE_DEBUG)

219:       do { \
220:         (void)(h); \
221:       } while (0)
223:       do { \
224:         (void)(h); \
225:       } while (0)
227:       do { \
228:         (void)(h); \
229:       } while (0)
231:       do { \
232:         (void)(h); \
233:       } while (0)
235:       do { \
236:         (void)(h); \
237:       } while (0)
239:       do { \
240:         (void)(h); \
241:       } while (0)
243:       do { \
244:         (void)(h); \
245:       } while (0)
247:       do { \
248:         (void)(h); \
249:       } while (0)
251:       do { \
252:         (void)(h); \
253:       } while (0)
255:       do { \
256:         (void)(h); \
257:       } while (0)
259:       do { \
260:         (void)(h); \
261:       } while (0)
263:       do { \
264:         (void)(h); \
265:       } while (0)

267:   #else

269:     /*  This check is for subtype methods such as DMDAGetCorners() that do not use the PetscTryMethod() or PetscUseMethod() paradigm */
271:       do { \
272:         PetscBool _7_same; \
274:         PetscObjectTypeCompare((PetscObject)(h), t, &_7_same); \
276:       } while (0)

279:       do { \
282:       } while (0)

285:       do { \
287:         if (((PetscObject)(h))->classid != ck) { \
289:           SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Wrong type of object: Parameter # %d", arg); \
290:         } \
291:       } while (0)

294:       do { \
298:       } while (0)


310:       do { \
312:       } while (0)
313:   #endif
314: #else  /* PETSC_CLANG_STATIC_ANALYZER */
315: template <typename T>
317: template <typename T>
319: template <typename T>
321: template <typename T>
323: template <typename T>
325: template <typename T>
327: template <typename T>
329: template <typename T>
331: template <typename T>
333: template <typename T>
335: template <typename T>
337: template <typename T>
339: template <typename T>
341: #endif /* PETSC_CLANG_STATIC_ANALYZER */

343: #define PetscSorted(n, idx, sorted) \
344:   do { \
345:     (sorted) = PETSC_TRUE; \
346:     for (PetscInt _i_ = 1; _i_ < (n); ++_i_) { \
347:       if ((idx)[_i_] < (idx)[_i_ - 1]) { \
348:         (sorted) = PETSC_FALSE; \
349:         break; \
350:       } \
351:     } \
352:   } while (0)

354: #if !defined(PETSC_CLANG_STATIC_ANALYZER)
355:   #if !defined(PETSC_USE_DEBUG)

358:       do { \
359:         (void)(a); \
360:         (void)(b); \
361:       } while (0)
363:       do { \
364:         (void)(a); \
365:       } while (0)
367:       do { \
368:         (void)(a); \
369:       } while (0)
371:       do { \
372:         (void)(a); \
373:       } while (0)
375:       do { \
376:         (void)(a); \
377:         (void)(b); \
378:       } while (0)
380:       do { \
381:         (void)(a); \
382:         (void)(b); \
383:       } while (0)
385:       do { \
386:         (void)(a); \
387:         (void)(b); \
388:       } while (0)
390:       do { \
391:         (void)(a); \
392:         (void)(b); \
393:       } while (0)
395:       do { \
396:         (void)(a); \
397:         (void)(b); \
398:       } while (0)
400:       do { \
401:         (void)(a); \
402:         (void)(b); \
403:       } while (0)
405:       do { \
406:         (void)(a); \
407:         (void)(b); \
408:       } while (0)
410:       do { \
411:         (void)(a); \
412:         (void)(b); \
413:       } while (0)
415:       do { \
416:         (void)(n); \
417:         (void)(idx); \
418:       } while (0)

420:   #else

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

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

428:   This macro is used incorrectly in the code. Many places that do not need identity of the
429:   types incorrectly call this check and would need to be fixed if this macro is enabled.
430: */
431:     #if 0
433:         do { \
434:           PetscBool pcst_type_eq_ = PETSC_TRUE; \
435:           PetscStrcmp(((PetscObject)(a))->type_name, (((PetscObject)(b)))->type_name, &pcst_type_eq_); \
437:         } while (0)
438:     #else
440:         do { \
441:           (void)(a); \
442:           (void)(b); \
443:         } while (0)
444:     #endif

446:     /*
447:     Check type_name
448: */
450:       do { \
451:         PetscBool _7_match; \
452:         PetscObjectTypeCompare(((PetscObject)(a)), (type), &_7_match); \
454:       } while (0)

457:       do { \
458:         PetscBool _7_match; \
459:         PetscObjectTypeCompareAny(((PetscObject)(a)), &_7_match, (type1), (type2), ""); \
461:       } while (0)

463:     /*
464:    Use this macro to check if the type is set
465: */

468:     /*
469:    Sometimes object must live on same communicator to inter-operate
470: */
472:       do { \
473:         PetscMPIInt _7_flag; \
474:         MPI_Comm_compare(PetscObjectComm((PetscObject)(a)), PetscObjectComm((PetscObject)(b)), &_7_flag); \
476:       } while (0)

479:       do { \
482:       } while (0)

485:       do { \
486:         PetscScalar b0 = (b); \
487:         PetscReal   b1[5], b2[5]; \
488:         if (PetscIsNanScalar(b0)) { \
489:           b1[4] = 1; \
490:         } else { \
491:           b1[4] = 0; \
492:         }; \
493:         b1[0] = -PetscRealPart(b0); \
494:         b1[1] = PetscRealPart(b0); \
495:         b1[2] = -PetscImaginaryPart(b0); \
496:         b1[3] = PetscImaginaryPart(b0); \
497:         MPIU_Allreduce(b1, b2, 5, MPIU_REAL, MPIU_MAX, PetscObjectComm((PetscObject)(a))); \
499:       } while (0)

502:       do { \
503:         PetscReal b0 = (b), b1[3], b2[3]; \
504:         if (PetscIsNanReal(b0)) { \
505:           b1[2] = 1; \
506:         } else { \
507:           b1[2] = 0; \
508:         }; \
509:         b1[0] = -b0; \
510:         b1[1] = b0; \
511:         MPIU_Allreduce(b1, b2, 3, MPIU_REAL, MPIU_MAX, PetscObjectComm((PetscObject)(a))); \
513:       } while (0)

516:       do { \
517:         PetscInt b0 = (b), b1[2], b2[2]; \
518:         b1[0]       = -b0; \
519:         b1[1]       = b0; \
520:         MPIU_Allreduce(b1, b2, 2, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)(a))); \
522:       } while (0)

525:       do { \
526:         PetscMPIInt b0 = (b), b1[2], b2[2]; \
527:         b1[0]          = -b0; \
528:         b1[1]          = b0; \
529:         MPIU_Allreduce(b1, b2, 2, MPI_INT, MPI_MAX, PetscObjectComm((PetscObject)(a))); \
531:       } while (0)

534:       do { \
535:         PetscMPIInt b0 = (PetscMPIInt)(b), b1[2], b2[2]; \
536:         b1[0]          = -b0; \
537:         b1[1]          = b0; \
538:         MPIU_Allreduce(b1, b2, 2, MPI_INT, MPI_MAX, PetscObjectComm((PetscObject)(a))); \
540:       } while (0)

543:       do { \
544:         PetscMPIInt b0 = (PetscMPIInt)(b), b1[2], b2[2]; \
545:         b1[0]          = -b0; \
546:         b1[1]          = b0; \
547:         MPIU_Allreduce(b1, b2, 2, MPI_INT, MPI_MAX, PetscObjectComm((PetscObject)(a))); \
549:       } while (0)

552:       do { \
553:         PetscBool _1_flg; \
554:         PetscSorted(n, idx, _1_flg); \
556:       } while (0)

558:   #endif
559: #else  /* PETSC_CLANG_STATIC_ANALYZER */
560: template <typename Ta, typename Tb>
562: template <typename Ta, typename Tb>
564: template <typename Ta, typename Tb, typename Tc>
566: template <typename T>
568: template <typename Ta, typename Tb>
570: template <typename Ta, typename Tb>
572: template <typename Ta, typename Tb>
574: template <typename Ta, typename Tb>
576: template <typename Ta, typename Tb>
578: template <typename Ta, typename Tb>
580: template <typename Ta, typename Tb>
582: template <typename Ta, typename Tb>
584: template <typename T>
586: #endif /* PETSC_CLANG_STATIC_ANALYZER */

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

591:   Synopsis:
592:    #include "petsc/private/petscimpl.h"
593:    PetscTryMethod(PetscObject obj,const char *name,(arg_types),(arg_value))

595:    Input Parameters:
596: +   obj - the object
597: .   name - the name of the method, for example, "KSPGMRESSetRestart_C" for the function `KSPGMRESSetRestart()`
598: .   arg_types - the argument types for the method, for example, (KSP,PetscInt)
599: -   args - the arguements for the method, for example, (ksp,restart))

601:    Level: developer

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

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

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

612: M*/
613: #define PetscTryMethod(obj, A, B, C) \
614:   do { \
615:     PetscErrorCode(*_7_f) B; \
616:     PetscObjectQueryFunction((PetscObject)(obj), A, &_7_f); \
617:     if (_7_f) (*_7_f)C; \
618:   } while (0)

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

623:   Synopsis:
624:    #include "petsc/private/petscimpl.h"
625:    PetscUseMethod(PetscObject obj,const char *name,(arg_types),(arg_value))

627:    Input Parameters:
628: +   obj - the object
629: .   name - the name of the method, for example, "KSPGMRESSetRestart_C" for the function `KSPGMRESSetRestart()`
630: .   arg_types - the argument types for the method, for example, (KSP,PetscInt)
631: -   args - the arguements for the method, for example, (ksp,restart))

633:    Level: developer

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

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

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

644: M*/
645: #define PetscUseMethod(obj, A, B, C) \
646:   do { \
647:     PetscErrorCode(*_7_f) B; \
648:     PetscObjectQueryFunction((PetscObject)(obj), A, &_7_f); \
650:     (*_7_f)C; \
651:   } while (0)

653: /*
654:   Use Microsoft traditional preprocessor.

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

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

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

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

667:   #define PetscUseTypeMethod(obj, OP, ...) \
668:     do { \
669:       PetscErrorCode ierr_p_; \
670:       PetscStackUpdateLine; \
672:       ierr_p_ = (*(obj)->ops->OP)(obj, __VA_ARGS__); \
673:       ierr_p_; \
674:     } while (0)

676:   #define PetscTryTypeMethod(obj, OP, ...) \
677:     do { \
678:       if ((obj)->ops->OP) { \
679:         PetscErrorCode ierr_p_; \
680:         PetscStackUpdateLine; \
681:         ierr_p_ = (*(obj)->ops->OP)(obj, __VA_ARGS__); \
682:         ierr_p_; \
683:       } \
684:     } while (0)

686: #else

688:   /*MC
689:    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

691:   Synopsis:
692:    #include "petsc/private/petscimpl.h"
693:    PetscUseTypeMethod(obj,method,other_args)

695:    Input Parameters:
696: +   obj - the object the method is called on
697: .   method - the name of the method, for example, mult for the PETSc routine MatMult()
698: -   other_args - the other arguments for the method, obj is the first argument

700:    Level: developer

702:    Note:
703:    This does not return an error code, it is a macro that returns with an erorr code on error.

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

708: M*/
709:   #define PetscUseTypeMethod(obj, ...) \
710:     do { \
712:                  PetscStringize(PETSC_FIRST_ARG((__VA_ARGS__,unused))), ((PetscObject)obj)->class_name, ((PetscObject)obj)->type_name); \
713:       (*(obj)->ops->PETSC_FIRST_ARG((__VA_ARGS__, unused)))(obj PETSC_REST_ARG(__VA_ARGS__)); \
714:     } while (0)

716:   /*MC
717:    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

719:   Synopsis:
720:    #include "petsc/private/petscimpl.h"
721:    PetscTryTtype(obj,method,other_args)

723:    Input Parameters:
724: +   obj - the object the method is called on
725: .   method - the name of the method, for example, mult for the PETSc routine MatMult()
726: -   other_args - the other arguments for the method, obj is the first argument

728:    Level: developer

730:    Note:
731:    This does not return an error code, it is a macro that returns with an erorr code on error.

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

736: M*/
737:   #define PetscTryTypeMethod(obj, ...) \
738:     do { \
739:       if ((obj)->ops->PETSC_FIRST_ARG((__VA_ARGS__, unused))) (*(obj)->ops->PETSC_FIRST_ARG((__VA_ARGS__, unused)))(obj PETSC_REST_ARG(__VA_ARGS__)); \
740:     } while (0)

742: #endif

744: /*MC
745:    PetscObjectStateIncrease - Increases the state of any `PetscObject`

747:    Synopsis:
748:    #include "petsc/private/petscimpl.h"
749:    PetscErrorCode PetscObjectStateIncrease(PetscObject obj)

751:    Logically Collective

753:    Input Parameter:
754: .  obj - any PETSc object, for example a `Vec`, `Mat` or `KSP`. This must be
755:          cast with a (PetscObject), for example,
756:          `PetscObjectStateIncrease`((`PetscObject`)mat);

758:    Notes:
759:    Object state is a 64 bit integer which gets increased every time
760:    the object is changed internally. By saving and later querying the object state
761:    one can determine whether information about the object is still current.
762:    Currently, state is maintained for `Vec` and `Mat` objects.

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

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

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

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

775:    Level: developer

777: .seealso: `PetscObjectStateGet()`, `MatSetNonzeroState()`, `PetscObject`

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

782: PETSC_EXTERN PetscErrorCode PetscObjectStateGet(PetscObject, PetscObjectState *);
783: PETSC_EXTERN PetscErrorCode PetscObjectStateSet(PetscObject, PetscObjectState);
784: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataRegister(PetscInt *);
785: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseInt(PetscObject);
786: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseIntstar(PetscObject);
787: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseReal(PetscObject);
788: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseRealstar(PetscObject);
789: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseScalar(PetscObject);
790: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseScalarstar(PetscObject);
791: PETSC_EXTERN PetscInt       PetscObjectComposedDataMax;

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

796:    Synopsis:
797:    #include "petsc/private/petscimpl.h"
798:    PetscErrorCode PetscObjectComposedDataSetInt(PetscObject obj,int id,int data)

800:    Not collective

802:    Input parameters:
803: +  obj - the object to which data is to be attached
804: .  id - the identifier for the data
805: -  data - the data to  be attached

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

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

813:    Level: developer

815: .seealso: `PetscObjectComposedDataGetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetReal()`,
816:           `PetscObjectComposedDataGetIntstar()`, `PetscObjectComposedDataSetIntstar()`, `PetscObject`,
817:           `PetscObjectCompose()`, `PetscObjectQuery()`
818: M*/
819: #define PetscObjectComposedDataSetInt(obj, id, data) ((((obj)->int_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseInt(obj)) || ((obj)->intcomposeddata[id] = data, (obj)->intcomposedstate[id] = (obj)->state, 0))

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

824:    Synopsis:
825:    #include "petsc/private/petscimpl.h"
826:    PetscErrorCode PetscObjectComposedDataGetInt(PetscObject obj,int id,int data,PetscBool  flag)

828:    Not collective

830:    Input parameters:
831: +  obj - the object from which data is to be retrieved
832: -  id - the identifier for the data

834:    Output parameters:
835: +  data - the data to be retrieved
836: -  flag - `PETSC_TRUE` if the data item exists and is valid, `PETSC_FALSE` otherwise

838:    Level: developer

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

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

845: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetReal()`,
846:           `PetscObjectComposedDataGetIntstar()`, `PetscObjectComposedDataSetIntstar()`, `PetscObject`,
847:           `PetscObjectCompose()`, `PetscObjectQuery()`
848: M*/
849: #define PetscObjectComposedDataGetInt(obj, id, data, flag) (((obj)->intcomposedstate ? (data = (obj)->intcomposeddata[id], flag = (PetscBool)((obj)->intcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), 0)

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

854:    Synopsis:
855:    #include "petsc/private/petscimpl.h"
856:    PetscErrorCode PetscObjectComposedDataSetIntstar(PetscObject obj,int id,int *data)

858:    Not collective

860:    Input parameters:
861: +  obj - the object to which data is to be attached
862: .  id - the identifier for the data
863: -  data - the data to  be attached

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

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

870:    Level: developer

872: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetReal()`,
873:           `PetscObjectComposedDataGetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
874:           `PetscObjectCompose()`, `PetscObjectQuery()`
875: M*/
876: #define PetscObjectComposedDataSetIntstar(obj, id, data) \
877:   ((((obj)->intstar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseIntstar(obj)) || ((obj)->intstarcomposeddata[id] = data, (obj)->intstarcomposedstate[id] = (obj)->state, 0))

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

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

886:    Not collective

888:    Input parameters:
889: +  obj - the object from which data is to be retrieved
890: -  id - the identifier for the data

892:    Output parameters:
893: +  data - the data to be retrieved
894: -  flag - `PETSC_TRUE` if the data item exists and is valid, `PETSC_FALSE` otherwise

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

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

901:    Level: developer

903: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetReal()`,
904:           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
905:           `PetscObjectCompose()`, `PetscObjectQuery()`
906: M*/
907: #define PetscObjectComposedDataGetIntstar(obj, id, data, flag) (((obj)->intstarcomposedstate ? (data = (obj)->intstarcomposeddata[id], flag = (PetscBool)((obj)->intstarcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), 0)

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

912:    Synopsis:
913:    #include "petsc/private/petscimpl.h"
914:    PetscErrorCode PetscObjectComposedDataSetReal(PetscObject obj,int id,PetscReal data)

916:    Not collective

918:    Input parameters:
919: +  obj - the object to which data is to be attached
920: .  id - the identifier for the data
921: -  data - the data to  be attached

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

926:    Level: developer

928: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
929:           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
930:           `PetscObjectCompose()`, `PetscObjectQuery()`
931: M*/
932: #define PetscObjectComposedDataSetReal(obj, id, data) ((((obj)->real_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseReal(obj)) || ((obj)->realcomposeddata[id] = data, (obj)->realcomposedstate[id] = (obj)->state, 0))

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

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

941:    Not collective

943:    Input parameters:
944: +  obj - the object from which data is to be retrieved
945: -  id - the identifier for the data

947:    Output parameters:
948: +  data - the data to be retrieved
949: -  flag - `PETSC_TRUE` if the data item exists and is valid, `PETSC_FALSE` otherwise

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

954:    Level: developer

956: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataSetIntstar()`,
957:           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
958:           `PetscObjectCompose()`, `PetscObjectQuery()`
959: M*/
960: #define PetscObjectComposedDataGetReal(obj, id, data, flag) (((obj)->realcomposedstate ? (data = (obj)->realcomposeddata[id], flag = (PetscBool)((obj)->realcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), 0)

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

965:    Synopsis:
966:    #include "petsc/private/petscimpl.h"
967:    PetscErrorCode PetscObjectComposedDataSetRealstar(PetscObject obj,int id,PetscReal *data)

969:    Not collective

971:    Input parameters:
972: +  obj - the object to which data is to be attached
973: .  id - the identifier for the data
974: -  data - the data to  be attached

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

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

981:    Level: developer

983: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
984:           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
985:           `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataGetRealstar()`
986: M*/
987: #define PetscObjectComposedDataSetRealstar(obj, id, data) \
988:   ((((obj)->realstar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseRealstar(obj)) || ((obj)->realstarcomposeddata[id] = data, (obj)->realstarcomposedstate[id] = (obj)->state, 0))

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

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

997:    Not collective

999:    Input parameters:
1000: +  obj - the object from which data is to be retrieved
1001: -  id - the identifier for the data

1003:    Output parameters:
1004: +  data - the data to be retrieved
1005: -  flag - `PETSC_TRUE` if the data item exists and is valid, `PETSC_FALSE` otherwise

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

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

1012:    Level: developer

1014: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1015:           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1016:           `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`
1017: M*/
1018: #define PetscObjectComposedDataGetRealstar(obj, id, data, flag) (((obj)->realstarcomposedstate ? (data = (obj)->realstarcomposeddata[id], flag = (PetscBool)((obj)->realstarcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), 0)

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

1023:    Synopsis:
1024:    #include "petsc/private/petscimpl.h"
1025:    PetscErrorCode PetscObjectComposedDataSetScalar(PetscObject obj,int id,PetscScalar data)

1027:    Not collective

1029:    Input parameters:
1030: +  obj - the object to which data is to be attached
1031: .  id - the identifier for the data
1032: -  data - the data to  be attached

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

1037:    Level: developer

1039: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1040:           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1041:           `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`, `PetscObjectComposedDataGetScalar()`
1042: M*/
1043: #if defined(PETSC_USE_COMPLEX)
1044:   #define PetscObjectComposedDataSetScalar(obj, id, data) ((((obj)->scalar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseScalar(obj)) || ((obj)->scalarcomposeddata[id] = data, (obj)->scalarcomposedstate[id] = (obj)->state, 0))
1045: #else
1046:   #define PetscObjectComposedDataSetScalar(obj, id, data) PetscObjectComposedDataSetReal(obj, id, data)
1047: #endif
1048: /*MC
1049:    PetscObjectComposedDataGetScalar - retrieve scalar data attached to an object that was set with `PetscObjectComposedDataSetScalar()`

1051:    Synopsis:
1052:    #include "petsc/private/petscimpl.h"
1053:    PetscErrorCode PetscObjectComposedDataGetScalar(PetscObject obj,int id,PetscScalar data,PetscBool  flag)

1055:    Not collective

1057:    Input parameters:
1058: +  obj - the object from which data is to be retrieved
1059: -  id - the identifier for the data

1061:    Output parameters:
1062: +  data - the data to be retrieved
1063: -  flag - `PETSC_TRUE` if the data item exists and is valid, `PETSC_FALSE` otherwise

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

1068:    Level: developer

1070: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1071:           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1072:           `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`, `PetscObjectComposedDataSetScalar()`
1073: M*/
1074: #if defined(PETSC_USE_COMPLEX)
1075:   #define PetscObjectComposedDataGetScalar(obj, id, data, flag) (((obj)->scalarcomposedstate ? (data = (obj)->scalarcomposeddata[id], flag = (PetscBool)((obj)->scalarcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), 0)
1076: #else
1077:   #define PetscObjectComposedDataGetScalar(obj, id, data, flag) PetscObjectComposedDataGetReal(obj, id, data, flag)
1078: #endif

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

1083:    Synopsis:
1084:    #include "petsc/private/petscimpl.h"
1085:    PetscErrorCode PetscObjectComposedDataSetScalarstar(PetscObject obj,int id,PetscScalar *data)

1087:    Not collective

1089:    Input parameters:
1090: +  obj - the object to which data is to be attached
1091: .  id - the identifier for the data
1092: -  data - the data to  be attached

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

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

1099:    Level: developer

1101: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1102:           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1103:           `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`, `PetscObjectComposedDataGetScalarstar()`
1104: M*/
1105: #if defined(PETSC_USE_COMPLEX)
1106:   #define PetscObjectComposedDataSetScalarstar(obj, id, data) \
1107:     ((((obj)->scalarstar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseScalarstar(obj)) || ((obj)->scalarstarcomposeddata[id] = data, (obj)->scalarstarcomposedstate[id] = (obj)->state, 0))
1108: #else
1109:   #define PetscObjectComposedDataSetScalarstar(obj, id, data) PetscObjectComposedDataSetRealstar(obj, id, data)
1110: #endif
1111: /*MC
1112:    PetscObjectComposedDataGetScalarstar - retrieve scalar array data set with `PetscObjectComposedDataSetScalarstar()`
1113:    attached to an object

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

1119:    Not collective

1121:    Input parameters:
1122: +  obj - the object from which data is to be retrieved
1123: -  id - the identifier for the data

1125:    Output parameters:
1126: +  data - the data to be retrieved
1127: -  flag - `PETSC_TRUE` if the data item exists and is valid, `PETSC_FALSE` otherwise

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

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

1134:    Level: developer

1136: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1137:           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1138:           `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`, `PetscObjectComposedDataSetScalarstar()`
1139: M*/
1140: #if defined(PETSC_USE_COMPLEX)
1141:   #define PetscObjectComposedDataGetScalarstar(obj, id, data, flag) (((obj)->scalarstarcomposedstate ? (data = (obj)->scalarstarcomposeddata[id], flag = (PetscBool)((obj)->scalarstarcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), 0)
1142: #else
1143:   #define PetscObjectComposedDataGetScalarstar(obj, id, data, flag) PetscObjectComposedDataGetRealstar(obj, id, data, flag)
1144: #endif

1146: PETSC_EXTERN PetscMPIInt Petsc_Counter_keyval;
1147: PETSC_EXTERN PetscMPIInt Petsc_InnerComm_keyval;
1148: PETSC_EXTERN PetscMPIInt Petsc_OuterComm_keyval;
1149: PETSC_EXTERN PetscMPIInt Petsc_Seq_keyval;
1150: PETSC_EXTERN PetscMPIInt Petsc_ShmComm_keyval;
1151: PETSC_EXTERN PetscMPIInt Petsc_CreationIdx_keyval;
1152: PETSC_EXTERN PetscMPIInt Petsc_Garbage_HMap_keyval;

1154: struct PetscCommStash {
1155:   struct PetscCommStash *next;
1156:   MPI_Comm               comm;
1157: };

1159: /*
1160:   PETSc communicators have this attribute, see
1161:   PetscCommDuplicate(), PetscCommDestroy(), PetscCommGetNewTag(), PetscObjectGetName()
1162: */
1163: typedef struct {
1164:   PetscMPIInt            tag;       /* next free tag value */
1165:   PetscInt               refcount;  /* number of references, communicator can be freed when this reaches 0 */
1166:   PetscInt               namecount; /* used to generate the next name, as in Vec_0, Mat_1, ... */
1167:   PetscMPIInt           *iflags;    /* length of comm size, shared by all calls to PetscCommBuildTwoSided_Allreduce/RedScatter on this comm */
1168:   struct PetscCommStash *comms;     /* communicators available for PETSc to pass off to other packages */
1169: } PetscCommCounter;

1171: typedef enum {
1172:   STATE_BEGIN,
1173:   STATE_PENDING,
1174:   STATE_END
1175: } SRState;

1177: typedef enum {
1178:   PETSC_SR_REDUCE_SUM = 0,
1179:   PETSC_SR_REDUCE_MAX = 1,
1180:   PETSC_SR_REDUCE_MIN = 2
1181: } PetscSRReductionType;

1183: typedef struct {
1184:   MPI_Comm     comm;
1185:   MPI_Request  request;
1186:   PetscBool    mix;
1187:   PetscBool    async;
1188:   PetscScalar *lvalues;    /* this are the reduced values before call to MPI_Allreduce() */
1189:   PetscScalar *gvalues;    /* values after call to MPI_Allreduce() */
1190:   void       **invecs;     /* for debugging only, vector/memory used with each op */
1191:   PetscInt    *reducetype; /* is particular value to be summed or maxed? */
1192:   struct {
1193:     PetscScalar v;
1194:     PetscInt    i;
1195:   }       *lvalues_mix, *gvalues_mix; /* used when mixing reduce operations */
1196:   SRState  state;                     /* are we calling xxxBegin() or xxxEnd()? */
1197:   PetscInt maxops;                    /* total amount of space we have for requests */
1198:   PetscInt numopsbegin;               /* number of requests that have been queued in */
1199:   PetscInt numopsend;                 /* number of requests that have been gotten by user */
1200: } PetscSplitReduction;

1202: PETSC_EXTERN PetscErrorCode PetscSplitReductionGet(MPI_Comm, PetscSplitReduction **);
1203: PETSC_EXTERN PetscErrorCode PetscSplitReductionEnd(PetscSplitReduction *);
1204: PETSC_EXTERN PetscErrorCode PetscSplitReductionExtend(PetscSplitReduction *);

1206: #if !defined(PETSC_SKIP_SPINLOCK)
1207:   #if defined(PETSC_HAVE_THREADSAFETY)
1208:     #if defined(PETSC_HAVE_CONCURRENCYKIT)
1209:       #if defined(__cplusplus)
1210: /*  CK does not have extern "C" protection in their include files */
1211: extern "C" {
1212:       #endif
1213:       #include <ck_spinlock.h>
1214:       #if defined(__cplusplus)
1215: }
1216:       #endif
1217: typedef ck_spinlock_t        PetscSpinlock;
1218: static inline PetscErrorCode PetscSpinlockCreate(PetscSpinlock *ck_spinlock)
1219: {
1220:   ck_spinlock_init(ck_spinlock);
1221:   return 0;
1222: }
1223: static inline PetscErrorCode PetscSpinlockLock(PetscSpinlock *ck_spinlock)
1224: {
1225:   ck_spinlock_lock(ck_spinlock);
1226:   return 0;
1227: }
1228: static inline PetscErrorCode PetscSpinlockUnlock(PetscSpinlock *ck_spinlock)
1229: {
1230:   ck_spinlock_unlock(ck_spinlock);
1231:   return 0;
1232: }
1233: static inline PetscErrorCode PetscSpinlockDestroy(PetscSpinlock *ck_spinlock)
1234: {
1235:   return 0;
1236: }
1237:     #elif defined(PETSC_HAVE_OPENMP)

1239:       #include <omp.h>
1240: typedef omp_lock_t           PetscSpinlock;
1241: static inline PetscErrorCode PetscSpinlockCreate(PetscSpinlock *omp_lock)
1242: {
1243:   omp_init_lock(omp_lock);
1244:   return 0;
1245: }
1246: static inline PetscErrorCode PetscSpinlockLock(PetscSpinlock *omp_lock)
1247: {
1248:   omp_set_lock(omp_lock);
1249:   return 0;
1250: }
1251: static inline PetscErrorCode PetscSpinlockUnlock(PetscSpinlock *omp_lock)
1252: {
1253:   omp_unset_lock(omp_lock);
1254:   return 0;
1255: }
1256: static inline PetscErrorCode PetscSpinlockDestroy(PetscSpinlock *omp_lock)
1257: {
1258:   omp_destroy_lock(omp_lock);
1259:   return 0;
1260: }
1261:     #else
1262:       #error "Thread safety requires either --with-openmp or --download-concurrencykit"
1263:     #endif

1265:   #else
1266: typedef int PetscSpinlock;
1267:     #define PetscSpinlockCreate(a)  0
1268:     #define PetscSpinlockLock(a)    0
1269:     #define PetscSpinlockUnlock(a)  0
1270:     #define PetscSpinlockDestroy(a) 0
1271:   #endif

1273:   #if defined(PETSC_HAVE_THREADSAFETY)
1274: PETSC_INTERN PetscSpinlock PetscViewerASCIISpinLockOpen;
1275: PETSC_INTERN PetscSpinlock PetscViewerASCIISpinLockStdout;
1276: PETSC_INTERN PetscSpinlock PetscViewerASCIISpinLockStderr;
1277: PETSC_INTERN PetscSpinlock PetscCommSpinLock;
1278:   #endif
1279: #endif

1281: PETSC_EXTERN PetscLogEvent PETSC_Barrier;
1282: PETSC_EXTERN PetscLogEvent PETSC_BuildTwoSided;
1283: PETSC_EXTERN PetscLogEvent PETSC_BuildTwoSidedF;
1284: PETSC_EXTERN PetscBool     use_gpu_aware_mpi;
1285: PETSC_EXTERN PetscBool     PetscPrintFunctionList;

1287: #if defined(PETSC_HAVE_ADIOS)
1288: PETSC_EXTERN int64_t Petsc_adios_group;
1289: #endif

1291: #if defined(PETSC_HAVE_KOKKOS)
1292: PETSC_INTERN PetscBool      PetscBeganKokkos;
1293: PETSC_EXTERN PetscBool      PetscKokkosInitialized;
1294: PETSC_INTERN PetscErrorCode PetscKokkosIsInitialized_Private(PetscBool *);
1295: PETSC_INTERN PetscErrorCode PetscKokkosFinalize_Private(void);
1296: #endif

1298: #if defined(PETSC_HAVE_OPENMP)
1299: PETSC_EXTERN PetscInt PetscNumOMPThreads;
1300: #endif

1302: #endif /* PETSCIMPL_H */