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

154:     Input Parameters:
155: +   classid - the classid associated with this object (for example VEC_CLASSID)
156: .   class_name - string name of class; should be static (for example "Vec")
157: .   descr - string containing short description; should be static (for example "Vector")
158: .   mansec - string indicating section in manual pages; should be static (for example "Vec")
159: .   comm - the MPI Communicator
160: .   destroy - the destroy routine for this object (for example `VecDestroy()`)
161: -   view - the view routine for this object (for example `VecView()`)

163:     Output Parameter:
164: .   h - the newly created object

166:     Level: developer

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

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

174: PETSC_EXTERN PetscErrorCode PetscComposedQuantitiesDestroy(PetscObject obj);
175: PETSC_EXTERN PetscErrorCode PetscHeaderCreate_Private(PetscObject, PetscClassId, const char[], const char[], const char[], MPI_Comm, PetscObjectDestroyFunction, PetscObjectViewFunction);
176: PETSC_INTERN PetscObjectId  PetscObjectNewId_Internal(void);

178: /*@C
179:     PetscHeaderDestroy - Final step in destroying a PetscObject

181:     Input Parameters:
182: .   h - the header created with `PetscHeaderCreate()`

184:     Level: developer

186: .seealso: `PetscHeaderCreate()`
187: @*/
188: #define PetscHeaderDestroy(h) (PetscHeaderDestroy_Private((PetscObject)(*(h)), PETSC_FALSE) || PetscFree(*(h)))

190: PETSC_EXTERN PetscErrorCode                PetscHeaderDestroy_Private(PetscObject, PetscBool);
191: PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode PetscHeaderReset_Internal(PetscObject);
192: PETSC_EXTERN PetscErrorCode                PetscObjectCopyFortranFunctionPointers(PetscObject, PetscObject);
193: PETSC_EXTERN PetscErrorCode                PetscObjectSetFortranCallback(PetscObject, PetscFortranCallbackType, PetscFortranCallbackId *, void (*)(void), void *ctx);
194: PETSC_EXTERN PetscErrorCode                PetscObjectGetFortranCallback(PetscObject, PetscFortranCallbackType, PetscFortranCallbackId, void (**)(void), void **ctx);

196: PETSC_INTERN PetscErrorCode PetscCitationsInitialize(void);
197: PETSC_INTERN PetscErrorCode PetscFreeMPIResources(void);
198: PETSC_INTERN PetscErrorCode PetscOptionsHasHelpIntro_Internal(PetscOptions, PetscBool *);

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

203: #if PetscDefined(HAVE_SETJMP_H)
205: #else
207: #endif
208: #if !defined(PETSC_CLANG_STATIC_ANALYZER)
209:   /*
210:     Macros to test if a PETSc object is valid and if pointers are valid
211: */
212:   #if !defined(PETSC_USE_DEBUG)

215:       do { \
216:         (void)(h); \
217:       } while (0)
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:   #else

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

275:       do { \
278:       } while (0)

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

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


306:       do { \
308:       } while (0)
309:   #endif
310: #else  /* PETSC_CLANG_STATIC_ANALYZER */
311: template <typename T>
313: template <typename T>
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: #endif /* PETSC_CLANG_STATIC_ANALYZER */

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

350: #if !defined(PETSC_CLANG_STATIC_ANALYZER)
351:   #if !defined(PETSC_USE_DEBUG)

354:       do { \
355:         (void)(a); \
356:         (void)(b); \
357:       } while (0)
359:       do { \
360:         (void)(a); \
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:         (void)(b); \
374:       } while (0)
376:       do { \
377:         (void)(a); \
378:         (void)(b); \
379:       } while (0)
381:       do { \
382:         (void)(a); \
383:         (void)(b); \
384:       } while (0)
386:       do { \
387:         (void)(a); \
388:         (void)(b); \
389:       } while (0)
391:       do { \
392:         (void)(a); \
393:         (void)(b); \
394:       } while (0)
396:       do { \
397:         (void)(a); \
398:         (void)(b); \
399:       } while (0)
401:       do { \
402:         (void)(a); \
403:         (void)(b); \
404:       } while (0)
406:       do { \
407:         (void)(a); \
408:         (void)(b); \
409:       } while (0)
411:       do { \
412:         (void)(n); \
413:         (void)(idx); \
414:       } while (0)

416:   #else

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

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

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

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

453:       do { \
454:         PetscBool _7_match; \
455:         PetscObjectTypeCompareAny(((PetscObject)(a)), &_7_match, (type1), (type2), ""); \
457:       } while (0)

459:     /*
460:    Use this macro to check if the type is set
461: */

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

475:       do { \
478:       } while (0)

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

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

512:       do { \
513:         PetscInt b0 = (b), b1[2], b2[2]; \
514:         b1[0]       = -b0; \
515:         b1[1]       = b0; \
516:         MPIU_Allreduce(b1, b2, 2, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)(a))); \
518:       } while (0)

521:       do { \
522:         PetscMPIInt b0 = (b), b1[2], b2[2]; \
523:         b1[0]          = -b0; \
524:         b1[1]          = b0; \
525:         MPIU_Allreduce(b1, b2, 2, MPI_INT, MPI_MAX, PetscObjectComm((PetscObject)(a))); \
527:       } while (0)

530:       do { \
531:         PetscMPIInt b0 = (PetscMPIInt)(b), b1[2], b2[2]; \
532:         b1[0]          = -b0; \
533:         b1[1]          = b0; \
534:         MPIU_Allreduce(b1, b2, 2, MPI_INT, MPI_MAX, PetscObjectComm((PetscObject)(a))); \
536:       } while (0)

539:       do { \
540:         PetscMPIInt b0 = (PetscMPIInt)(b), b1[2], b2[2]; \
541:         b1[0]          = -b0; \
542:         b1[1]          = b0; \
543:         MPIU_Allreduce(b1, b2, 2, MPI_INT, MPI_MAX, PetscObjectComm((PetscObject)(a))); \
545:       } while (0)

548:       do { \
549:         PetscBool _1_flg; \
550:         PetscSorted(n, idx, _1_flg); \
552:       } while (0)

554:   #endif
555: #else  /* PETSC_CLANG_STATIC_ANALYZER */
556: template <typename Ta, typename Tb>
558: template <typename Ta, typename Tb>
560: template <typename Ta, typename Tb, typename Tc>
562: template <typename T>
564: template <typename Ta, typename Tb>
566: template <typename Ta, typename Tb>
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 T>
582: #endif /* PETSC_CLANG_STATIC_ANALYZER */

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

587:   Synopsis:
588:    #include "petsc/private/petscimpl.h"
589:    PetscTryMethod(PetscObject obj,const char *name,(arg_types),(arg_value))

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

597:    Level: developer

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

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

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

608: M*/
609: #define PetscTryMethod(obj, A, B, C) \
610:   do { \
611:     PetscErrorCode(*_7_f) B; \
612:     PetscObjectQueryFunction((PetscObject)(obj), A, &_7_f); \
613:     if (_7_f) (*_7_f)C; \
614:   } while (0)

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

619:   Synopsis:
620:    #include "petsc/private/petscimpl.h"
621:    PetscUseMethod(PetscObject obj,const char *name,(arg_types),(arg_value))

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

629:    Level: developer

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

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

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

640: M*/
641: #define PetscUseMethod(obj, A, B, C) \
642:   do { \
643:     PetscErrorCode(*_7_f) B; \
644:     PetscObjectQueryFunction((PetscObject)(obj), A, &_7_f); \
646:     (*_7_f)C; \
647:   } while (0)

649: /*
650:   Use Microsoft traditional preprocessor.

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

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

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

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

663:   #define PetscUseTypeMethod(obj, OP, ...) \
664:     do { \
665:       PetscErrorCode ierr_p_; \
666:       PetscStackUpdateLine; \
668:       ierr_p_ = (*(obj)->ops->OP)(obj, __VA_ARGS__); \
669:       ierr_p_; \
670:     } while (0)

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

682: #else

684:   /*MC
685:    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

687:   Synopsis:
688:    #include "petsc/private/petscimpl.h"
689:    PetscUseTypeMethod(obj,method,other_args)

691:    Input Parameters:
692: +   obj - the object the method is called on
693: .   method - the name of the method, for example, mult for the PETSc routine MatMult()
694: -   other_args - the other arguments for the method, obj is the first argument

696:    Level: developer

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

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

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

712:   /*MC
713:    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

715:   Synopsis:
716:    #include "petsc/private/petscimpl.h"
717:    PetscTryTtype(obj,method,other_args)

719:    Input Parameters:
720: +   obj - the object the method is called on
721: .   method - the name of the method, for example, mult for the PETSc routine MatMult()
722: -   other_args - the other arguments for the method, obj is the first argument

724:    Level: developer

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

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

732: M*/
733:   #define PetscTryTypeMethod(obj, ...) \
734:     do { \
735:       if ((obj)->ops->PETSC_FIRST_ARG((__VA_ARGS__, unused))) (*(obj)->ops->PETSC_FIRST_ARG((__VA_ARGS__, unused)))(obj PETSC_REST_ARG(__VA_ARGS__)); \
736:     } while (0)

738: #endif

740: /*MC
741:    PetscObjectStateIncrease - Increases the state of any `PetscObject`

743:    Synopsis:
744:    #include "petsc/private/petscimpl.h"
745:    PetscErrorCode PetscObjectStateIncrease(PetscObject obj)

747:    Logically Collective

749:    Input Parameter:
750: .  obj - any PETSc object, for example a `Vec`, `Mat` or `KSP`. This must be
751:          cast with a (PetscObject), for example,
752:          `PetscObjectStateIncrease`((`PetscObject`)mat);

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

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

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

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

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

771:    Level: developer

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

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

778: PETSC_EXTERN PetscErrorCode PetscObjectStateGet(PetscObject, PetscObjectState *);
779: PETSC_EXTERN PetscErrorCode PetscObjectStateSet(PetscObject, PetscObjectState);
780: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataRegister(PetscInt *);
781: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseInt(PetscObject);
782: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseIntstar(PetscObject);
783: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseReal(PetscObject);
784: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseRealstar(PetscObject);
785: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseScalar(PetscObject);
786: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseScalarstar(PetscObject);
787: PETSC_EXTERN PetscInt       PetscObjectComposedDataMax;

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

792:    Synopsis:
793:    #include "petsc/private/petscimpl.h"
794:    PetscErrorCode PetscObjectComposedDataSetInt(PetscObject obj,int id,int data)

796:    Not collective

798:    Input parameters:
799: +  obj - the object to which data is to be attached
800: .  id - the identifier for the data
801: -  data - the data to  be attached

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

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

809:    Level: developer

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

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

820:    Synopsis:
821:    #include "petsc/private/petscimpl.h"
822:    PetscErrorCode PetscObjectComposedDataGetInt(PetscObject obj,int id,int data,PetscBool  flag)

824:    Not collective

826:    Input parameters:
827: +  obj - the object from which data is to be retrieved
828: -  id - the identifier for the data

830:    Output parameters:
831: +  data - the data to be retrieved
832: -  flag - `PETSC_TRUE` if the data item exists and is valid, `PETSC_FALSE` otherwise

834:    Level: developer

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

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

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

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

850:    Synopsis:
851:    #include "petsc/private/petscimpl.h"
852:    PetscErrorCode PetscObjectComposedDataSetIntstar(PetscObject obj,int id,int *data)

854:    Not collective

856:    Input parameters:
857: +  obj - the object to which data is to be attached
858: .  id - the identifier for the data
859: -  data - the data to  be attached

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

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

866:    Level: developer

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

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

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

882:    Not collective

884:    Input parameters:
885: +  obj - the object from which data is to be retrieved
886: -  id - the identifier for the data

888:    Output parameters:
889: +  data - the data to be retrieved
890: -  flag - `PETSC_TRUE` if the data item exists and is valid, `PETSC_FALSE` otherwise

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

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

897:    Level: developer

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

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

908:    Synopsis:
909:    #include "petsc/private/petscimpl.h"
910:    PetscErrorCode PetscObjectComposedDataSetReal(PetscObject obj,int id,PetscReal data)

912:    Not collective

914:    Input parameters:
915: +  obj - the object to which data is to be attached
916: .  id - the identifier for the data
917: -  data - the data to  be attached

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

922:    Level: developer

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

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

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

937:    Not collective

939:    Input parameters:
940: +  obj - the object from which data is to be retrieved
941: -  id - the identifier for the data

943:    Output parameters:
944: +  data - the data to be retrieved
945: -  flag - `PETSC_TRUE` if the data item exists and is valid, `PETSC_FALSE` otherwise

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

950:    Level: developer

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

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

961:    Synopsis:
962:    #include "petsc/private/petscimpl.h"
963:    PetscErrorCode PetscObjectComposedDataSetRealstar(PetscObject obj,int id,PetscReal *data)

965:    Not collective

967:    Input parameters:
968: +  obj - the object to which data is to be attached
969: .  id - the identifier for the data
970: -  data - the data to  be attached

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

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

977:    Level: developer

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

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

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

993:    Not collective

995:    Input parameters:
996: +  obj - the object from which data is to be retrieved
997: -  id - the identifier for the data

999:    Output parameters:
1000: +  data - the data to be retrieved
1001: -  flag - `PETSC_TRUE` if the data item exists and is valid, `PETSC_FALSE` otherwise

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

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

1008:    Level: developer

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

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

1019:    Synopsis:
1020:    #include "petsc/private/petscimpl.h"
1021:    PetscErrorCode PetscObjectComposedDataSetScalar(PetscObject obj,int id,PetscScalar data)

1023:    Not collective

1025:    Input parameters:
1026: +  obj - the object to which data is to be attached
1027: .  id - the identifier for the data
1028: -  data - the data to  be attached

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

1033:    Level: developer

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

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

1051:    Not collective

1053:    Input parameters:
1054: +  obj - the object from which data is to be retrieved
1055: -  id - the identifier for the data

1057:    Output parameters:
1058: +  data - the data to be retrieved
1059: -  flag - `PETSC_TRUE` if the data item exists and is valid, `PETSC_FALSE` otherwise

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

1064:    Level: developer

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

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

1079:    Synopsis:
1080:    #include "petsc/private/petscimpl.h"
1081:    PetscErrorCode PetscObjectComposedDataSetScalarstar(PetscObject obj,int id,PetscScalar *data)

1083:    Not collective

1085:    Input parameters:
1086: +  obj - the object to which data is to be attached
1087: .  id - the identifier for the data
1088: -  data - the data to  be attached

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

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

1095:    Level: developer

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

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

1115:    Not collective

1117:    Input parameters:
1118: +  obj - the object from which data is to be retrieved
1119: -  id - the identifier for the data

1121:    Output parameters:
1122: +  data - the data to be retrieved
1123: -  flag - `PETSC_TRUE` if the data item exists and is valid, `PETSC_FALSE` otherwise

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

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()`, `PetscObjectComposedDataSetRealstar()`, `PetscObjectComposedDataSetScalarstar()`
1135: M*/
1136: #if defined(PETSC_USE_COMPLEX)
1137:   #define PetscObjectComposedDataGetScalarstar(obj, id, data, flag) (((obj)->scalarstarcomposedstate ? (data = (obj)->scalarstarcomposeddata[id], flag = (PetscBool)((obj)->scalarstarcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), 0)
1138: #else
1139:   #define PetscObjectComposedDataGetScalarstar(obj, id, data, flag) PetscObjectComposedDataGetRealstar(obj, id, data, flag)
1140: #endif

1142: PETSC_EXTERN PetscMPIInt Petsc_Counter_keyval;
1143: PETSC_EXTERN PetscMPIInt Petsc_InnerComm_keyval;
1144: PETSC_EXTERN PetscMPIInt Petsc_OuterComm_keyval;
1145: PETSC_EXTERN PetscMPIInt Petsc_Seq_keyval;
1146: PETSC_EXTERN PetscMPIInt Petsc_ShmComm_keyval;
1147: PETSC_EXTERN PetscMPIInt Petsc_CreationIdx_keyval;
1148: PETSC_EXTERN PetscMPIInt Petsc_Garbage_HMap_keyval;

1150: struct PetscCommStash {
1151:   struct PetscCommStash *next;
1152:   MPI_Comm               comm;
1153: };

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

1167: typedef enum {
1168:   STATE_BEGIN,
1169:   STATE_PENDING,
1170:   STATE_END
1171: } SRState;

1173: typedef enum {
1174:   PETSC_SR_REDUCE_SUM = 0,
1175:   PETSC_SR_REDUCE_MAX = 1,
1176:   PETSC_SR_REDUCE_MIN = 2
1177: } PetscSRReductionType;

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

1198: PETSC_EXTERN PetscErrorCode PetscSplitReductionGet(MPI_Comm, PetscSplitReduction **);
1199: PETSC_EXTERN PetscErrorCode PetscSplitReductionEnd(PetscSplitReduction *);
1200: PETSC_EXTERN PetscErrorCode PetscSplitReductionExtend(PetscSplitReduction *);

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

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

1261:   #else
1262: typedef int PetscSpinlock;
1263:     #define PetscSpinlockCreate(a)  0
1264:     #define PetscSpinlockLock(a)    0
1265:     #define PetscSpinlockUnlock(a)  0
1266:     #define PetscSpinlockDestroy(a) 0
1267:   #endif

1269:   #if defined(PETSC_HAVE_THREADSAFETY)
1270: PETSC_INTERN PetscSpinlock PetscViewerASCIISpinLockOpen;
1271: PETSC_INTERN PetscSpinlock PetscViewerASCIISpinLockStdout;
1272: PETSC_INTERN PetscSpinlock PetscViewerASCIISpinLockStderr;
1273: PETSC_INTERN PetscSpinlock PetscCommSpinLock;
1274:   #endif
1275: #endif

1277: PETSC_EXTERN PetscLogEvent PETSC_Barrier;
1278: PETSC_EXTERN PetscLogEvent PETSC_BuildTwoSided;
1279: PETSC_EXTERN PetscLogEvent PETSC_BuildTwoSidedF;
1280: PETSC_EXTERN PetscBool     use_gpu_aware_mpi;
1281: PETSC_EXTERN PetscBool     PetscPrintFunctionList;

1283: #if defined(PETSC_HAVE_ADIOS)
1284: PETSC_EXTERN int64_t Petsc_adios_group;
1285: #endif

1287: #if defined(PETSC_HAVE_KOKKOS)
1288: PETSC_INTERN PetscBool      PetscBeganKokkos;
1289: PETSC_EXTERN PetscBool      PetscKokkosInitialized;
1290: PETSC_INTERN PetscErrorCode PetscKokkosIsInitialized_Private(PetscBool *);
1291: PETSC_INTERN PetscErrorCode PetscKokkosFinalize_Private(void);
1292: #endif

1294: #if defined(PETSC_HAVE_OPENMP)
1295: PETSC_EXTERN PetscInt PetscNumOMPThreads;
1296: #endif

1298: #endif /* PETSCIMPL_H */