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:   PetscMPIInt       tag;
104:   PetscFunctionList qlist;
105:   PetscObjectList   olist;
106:   char             *class_name; /*  for example, "Vec" */
107:   char             *description;
108:   char             *mansec;
109:   char             *type_name; /*  this is the subclass, for example VECSEQ which equals "seq" */
110:   char             *name;
111:   char             *prefix;
112:   PetscInt          tablevel;
113:   void             *cpp;
114:   PetscObjectState  state;
115:   PetscInt          int_idmax, intstar_idmax;
116:   PetscObjectState *intcomposedstate, *intstarcomposedstate;
117:   PetscInt         *intcomposeddata, **intstarcomposeddata;
118:   PetscInt          real_idmax, realstar_idmax;
119:   PetscObjectState *realcomposedstate, *realstarcomposedstate;
120:   PetscReal        *realcomposeddata, **realstarcomposeddata;
121:   PetscInt          scalar_idmax, scalarstar_idmax;
122:   PetscObjectState *scalarcomposedstate, *scalarstarcomposedstate;
123:   PetscScalar      *scalarcomposeddata, **scalarstarcomposeddata;
124:   void (**fortran_func_pointers)(void);             /* used by Fortran interface functions to stash user provided Fortran functions */
125:   PetscFortranCallbackId num_fortran_func_pointers; /* number of Fortran function pointers allocated */
126:   PetscFortranCallback  *fortrancallback[PETSC_FORTRAN_CALLBACK_MAXTYPE];
127:   PetscFortranCallbackId num_fortrancallback[PETSC_FORTRAN_CALLBACK_MAXTYPE];
128:   void                  *python_context;
129:   PetscErrorCode (*python_destroy)(void *);

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

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

148: #define PETSCFREEDHEADER -1

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

153: /*@C
154:     PetscHeaderCreate - Creates a PETSc object of a particular class

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

165:     Output Parameter:
166: .   h - the newly created object

168:     Level: developer

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

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

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

180: /*@C
181:     PetscHeaderDestroy - Final step in destroying a PetscObject

183:     Input Parameters:
184: .   h - the header created with `PetscHeaderCreate()`

186:     Level: developer

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

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

198: PETSC_INTERN PetscErrorCode PetscCitationsInitialize(void);
199: PETSC_INTERN PetscErrorCode PetscFreeMPIResources(void);
200: PETSC_INTERN PetscErrorCode PetscOptionsHasHelpIntro_Internal(PetscOptions, PetscBool *);

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

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

217:       do { \
218:         (void)(h); \
219:       } while (0)
221:       do { \
222:         (void)(h); \
223:       } while (0)
225:       do { \
226:         (void)(h); \
227:       } while (0)
229:       do { \
230:         (void)(h); \
231:       } while (0)
233:       do { \
234:         (void)(h); \
235:       } while (0)
237:       do { \
238:         (void)(h); \
239:       } while (0)
241:       do { \
242:         (void)(h); \
243:       } while (0)
245:       do { \
246:         (void)(h); \
247:       } while (0)
249:       do { \
250:         (void)(h); \
251:       } while (0)
253:       do { \
254:         (void)(h); \
255:       } while (0)

257:   #else

259:     /*  This check is for subtype methods such as DMDAGetCorners() that do not use the PetscTryMethod() or PetscUseMethod() paradigm */
261:       do { \
262:         PetscBool _7_same; \
264:         PetscObjectTypeCompare((PetscObject)(h), t, &_7_same); \
266:       } while (0)

269:       do { \
272:       } while (0)

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

284:       do { \
288:       } while (0)


298:       do { \
300:       } while (0)
301:   #endif
302: #else  /* PETSC_CLANG_STATIC_ANALYZER */
303: template <typename T>
305: template <typename T>
307: template <typename T>
309: template <typename T>
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: #endif /* PETSC_CLANG_STATIC_ANALYZER */

327: #define PetscSorted(n, idx, sorted) \
328:   do { \
329:     (sorted) = PETSC_TRUE; \
330:     for (PetscInt _i_ = 1; _i_ < (n); ++_i_) { \
331:       if ((idx)[_i_] < (idx)[_i_ - 1]) { \
332:         (sorted) = PETSC_FALSE; \
333:         break; \
334:       } \
335:     } \
336:   } while (0)

338: #if !defined(PETSC_CLANG_STATIC_ANALYZER)
339:   #if !defined(PETSC_USE_DEBUG)

342:       do { \
343:         (void)(a); \
344:         (void)(b); \
345:       } while (0)
347:       do { \
348:         (void)(a); \
349:       } while (0)
351:       do { \
352:         (void)(a); \
353:       } while (0)
355:       do { \
356:         (void)(a); \
357:       } while (0)
359:       do { \
360:         (void)(a); \
361:         (void)(b); \
362:       } while (0)
364:       do { \
365:         (void)(a); \
366:         (void)(b); \
367:       } while (0)
369:       do { \
370:         (void)(a); \
371:         (void)(b); \
372:       } while (0)
374:       do { \
375:         (void)(a); \
376:         (void)(b); \
377:       } while (0)
379:       do { \
380:         (void)(a); \
381:         (void)(b); \
382:       } while (0)
384:       do { \
385:         (void)(a); \
386:         (void)(b); \
387:       } while (0)
389:       do { \
390:         (void)(a); \
391:         (void)(b); \
392:       } while (0)
394:       do { \
395:         (void)(a); \
396:         (void)(b); \
397:       } while (0)
399:       do { \
400:         (void)(n); \
401:         (void)(idx); \
402:       } while (0)

404:   #else

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

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

412:   This macro is used incorrectly in the code. Many places that do not need identity of the
413:   types incorrectly call this check and would need to be fixed if this macro is enabled.
414: */
415:     #if 0
417:         do { \
418:           PetscBool pcst_type_eq_ = PETSC_TRUE; \
419:           PetscStrcmp(((PetscObject)(a))->type_name, (((PetscObject)(b)))->type_name, &pcst_type_eq_); \
421:         } while (0)
422:     #else
424:         do { \
425:           (void)(a); \
426:           (void)(b); \
427:         } while (0)
428:     #endif

430:     /*
431:     Check type_name
432: */
434:       do { \
435:         PetscBool _7_match; \
436:         PetscObjectTypeCompare(((PetscObject)(a)), (type), &_7_match); \
438:       } while (0)

441:       do { \
442:         PetscBool _7_match; \
443:         PetscObjectTypeCompareAny(((PetscObject)(a)), &_7_match, (type1), (type2), ""); \
445:       } while (0)

447:     /*
448:    Use this macro to check if the type is set
449: */

452:     /*
453:    Sometimes object must live on same communicator to inter-operate
454: */
456:       do { \
457:         PetscMPIInt _7_flag; \
458:         MPI_Comm_compare(PetscObjectComm((PetscObject)(a)), PetscObjectComm((PetscObject)(b)), &_7_flag); \
460:       } while (0)

463:       do { \
466:       } while (0)

469:       do { \
470:         PetscScalar b0 = (b); \
471:         PetscReal   b1[5], b2[5]; \
472:         if (PetscIsNanScalar(b0)) { \
473:           b1[4] = 1; \
474:         } else { \
475:           b1[4] = 0; \
476:         }; \
477:         b1[0] = -PetscRealPart(b0); \
478:         b1[1] = PetscRealPart(b0); \
479:         b1[2] = -PetscImaginaryPart(b0); \
480:         b1[3] = PetscImaginaryPart(b0); \
481:         MPIU_Allreduce(b1, b2, 5, MPIU_REAL, MPIU_MAX, PetscObjectComm((PetscObject)(a))); \
483:       } while (0)

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

500:       do { \
501:         PetscInt b0 = (b), b1[2], b2[2]; \
502:         b1[0]       = -b0; \
503:         b1[1]       = b0; \
504:         MPIU_Allreduce(b1, b2, 2, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)(a))); \
506:       } while (0)

509:       do { \
510:         PetscMPIInt b0 = (b), b1[2], b2[2]; \
511:         b1[0]          = -b0; \
512:         b1[1]          = b0; \
513:         MPIU_Allreduce(b1, b2, 2, MPI_INT, MPI_MAX, PetscObjectComm((PetscObject)(a))); \
515:       } while (0)

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

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

536:       do { \
537:         PetscBool _1_flg; \
538:         PetscSorted(n, idx, _1_flg); \
540:       } while (0)

542:   #endif
543: #else  /* PETSC_CLANG_STATIC_ANALYZER */
544: template <typename Ta, typename Tb>
546: template <typename Ta, typename Tb>
548: template <typename Ta, typename Tb, typename Tc>
550: template <typename T>
552: template <typename Ta, typename Tb>
554: template <typename Ta, typename Tb>
556: template <typename Ta, typename Tb>
558: template <typename Ta, typename Tb>
560: template <typename Ta, typename Tb>
562: template <typename Ta, typename Tb>
564: template <typename Ta, typename Tb>
566: template <typename Ta, typename Tb>
568: template <typename T>
570: #endif /* PETSC_CLANG_STATIC_ANALYZER */

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

575:   Synopsis:
576:    #include "petsc/private/petscimpl.h"
577:    PetscTryMethod(PetscObject obj,const char *name,(arg_types),(arg_value))

579:    Input Parameters:
580: +   obj - the object
581: .   name - the name of the method, for example, "KSPGMRESSetRestart_C" for the function `KSPGMRESSetRestart()`
582: .   arg_types - the argument types for the method, for example, (KSP,PetscInt)
583: -   args - the arguements for the method, for example, (ksp,restart))

585:    Level: developer

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

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

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

596: M*/
597: #define PetscTryMethod(obj, A, B, C) \
598:   do { \
599:     PetscErrorCode(*_7_f) B; \
600:     PetscObjectQueryFunction((PetscObject)(obj), A, &_7_f); \
601:     if (_7_f) (*_7_f)C; \
602:   } while (0)

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

607:   Synopsis:
608:    #include "petsc/private/petscimpl.h"
609:    PetscUseMethod(PetscObject obj,const char *name,(arg_types),(arg_value))

611:    Input Parameters:
612: +   obj - the object
613: .   name - the name of the method, for example, "KSPGMRESSetRestart_C" for the function `KSPGMRESSetRestart()`
614: .   arg_types - the argument types for the method, for example, (KSP,PetscInt)
615: -   args - the arguements for the method, for example, (ksp,restart))

617:    Level: developer

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

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

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

628: M*/
629: #define PetscUseMethod(obj, A, B, C) \
630:   do { \
631:     PetscErrorCode(*_7_f) B; \
632:     PetscObjectQueryFunction((PetscObject)(obj), A, &_7_f); \
634:     (*_7_f)C; \
635:   } while (0)

637: /*
638:   Use Microsoft traditional preprocessor.

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

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

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

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

651:   #define PetscUseTypeMethod(obj, OP, ...) \
652:     do { \
653:       PetscErrorCode ierr_p_; \
654:       PetscStackUpdateLine; \
656:       ierr_p_ = (*(obj)->ops->OP)(obj, __VA_ARGS__); \
657:       ierr_p_; \
658:     } while (0)

660:   #define PetscTryTypeMethod(obj, OP, ...) \
661:     do { \
662:       if ((obj)->ops->OP) { \
663:         PetscErrorCode ierr_p_; \
664:         PetscStackUpdateLine; \
665:         ierr_p_ = (*(obj)->ops->OP)(obj, __VA_ARGS__); \
666:         ierr_p_; \
667:       } \
668:     } while (0)

670: #else

672:   /*MC
673:    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

675:   Synopsis:
676:    #include "petsc/private/petscimpl.h"
677:    PetscUseTypeMethod(obj,method,other_args)

679:    Input Parameters:
680: +   obj - the object the method is called on
681: .   method - the name of the method, for example, mult for the PETSc routine MatMult()
682: -   other_args - the other arguments for the method, obj is the first argument

684:    Level: developer

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

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

692: M*/
693:   #define PetscUseTypeMethod(obj, ...) \
694:     do { \
696:                  PetscStringize(PETSC_FIRST_ARG((__VA_ARGS__,unused))), ((PetscObject)obj)->class_name, ((PetscObject)obj)->type_name); \
697:       (*(obj)->ops->PETSC_FIRST_ARG((__VA_ARGS__, unused)))(obj PETSC_REST_ARG(__VA_ARGS__)); \
698:     } while (0)

700:   /*MC
701:    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

703:   Synopsis:
704:    #include "petsc/private/petscimpl.h"
705:    PetscTryTtype(obj,method,other_args)

707:    Input Parameters:
708: +   obj - the object the method is called on
709: .   method - the name of the method, for example, mult for the PETSc routine MatMult()
710: -   other_args - the other arguments for the method, obj is the first argument

712:    Level: developer

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

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

720: M*/
721:   #define PetscTryTypeMethod(obj, ...) \
722:     do { \
723:       if ((obj)->ops->PETSC_FIRST_ARG((__VA_ARGS__, unused))) (*(obj)->ops->PETSC_FIRST_ARG((__VA_ARGS__, unused)))(obj PETSC_REST_ARG(__VA_ARGS__)); \
724:     } while (0)

726: #endif

728: /*MC
729:    PetscObjectStateIncrease - Increases the state of any `PetscObject`

731:    Synopsis:
732:    #include "petsc/private/petscimpl.h"
733:    PetscErrorCode PetscObjectStateIncrease(PetscObject obj)

735:    Logically Collective

737:    Input Parameter:
738: .  obj - any PETSc object, for example a `Vec`, `Mat` or `KSP`. This must be
739:          cast with a (PetscObject), for example,
740:          `PetscObjectStateIncrease`((`PetscObject`)mat);

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

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

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

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

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

759:    Level: developer

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

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

766: PETSC_EXTERN PetscErrorCode PetscObjectStateGet(PetscObject, PetscObjectState *);
767: PETSC_EXTERN PetscErrorCode PetscObjectStateSet(PetscObject, PetscObjectState);
768: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataRegister(PetscInt *);
769: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseInt(PetscObject);
770: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseIntstar(PetscObject);
771: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseReal(PetscObject);
772: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseRealstar(PetscObject);
773: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseScalar(PetscObject);
774: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseScalarstar(PetscObject);
775: PETSC_EXTERN PetscInt       PetscObjectComposedDataMax;

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

780:    Synopsis:
781:    #include "petsc/private/petscimpl.h"
782:    PetscErrorCode PetscObjectComposedDataSetInt(PetscObject obj,int id,int data)

784:    Not collective

786:    Input parameters:
787: +  obj - the object to which data is to be attached
788: .  id - the identifier for the data
789: -  data - the data to  be attached

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

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

797:    Level: developer

799: .seealso: `PetscObjectComposedDataGetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetReal()`,
800:           `PetscObjectComposedDataGetIntstar()`, `PetscObjectComposedDataSetIntstar()`, `PetscObject`,
801:           `PetscObjectCompose()`,  `PetscObjectQuery()`
802: M*/
803: #define PetscObjectComposedDataSetInt(obj, id, data) ((((obj)->int_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseInt(obj)) || ((obj)->intcomposeddata[id] = data, (obj)->intcomposedstate[id] = (obj)->state, 0))

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

808:    Synopsis:
809:    #include "petsc/private/petscimpl.h"
810:    PetscErrorCode PetscObjectComposedDataGetInt(PetscObject obj,int id,int data,PetscBool  flag)

812:    Not collective

814:    Input parameters:
815: +  obj - the object from which data is to be retrieved
816: -  id - the identifier for the data

818:    Output parameters:
819: +  data - the data to be retrieved
820: -  flag - `PETSC_TRUE` if the data item exists and is valid, `PETSC_FALSE` otherwise

822:    Level: developer

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

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

829: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetReal()`,
830:           `PetscObjectComposedDataGetIntstar()`, `PetscObjectComposedDataSetIntstar()`, `PetscObject`,
831:           `PetscObjectCompose()`,  `PetscObjectQuery()`
832: M*/
833: #define PetscObjectComposedDataGetInt(obj, id, data, flag) (((obj)->intcomposedstate ? (data = (obj)->intcomposeddata[id], flag = (PetscBool)((obj)->intcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), 0)

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

838:    Synopsis:
839:    #include "petsc/private/petscimpl.h"
840:    PetscErrorCode PetscObjectComposedDataSetIntstar(PetscObject obj,int id,int *data)

842:    Not collective

844:    Input parameters:
845: +  obj - the object to which data is to be attached
846: .  id - the identifier for the data
847: -  data - the data to  be attached

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

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

854:    Level: developer

856: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetReal()`,
857:           `PetscObjectComposedDataGetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
858:           `PetscObjectCompose()`,  `PetscObjectQuery()`
859: M*/
860: #define PetscObjectComposedDataSetIntstar(obj, id, data) \
861:   ((((obj)->intstar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseIntstar(obj)) || ((obj)->intstarcomposeddata[id] = data, (obj)->intstarcomposedstate[id] = (obj)->state, 0))

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

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

870:    Not collective

872:    Input parameters:
873: +  obj - the object from which data is to be retrieved
874: -  id - the identifier for the data

876:    Output parameters:
877: +  data - the data to be retrieved
878: -  flag - `PETSC_TRUE` if the data item exists and is valid, `PETSC_FALSE` otherwise

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

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

885:    Level: developer

887: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetReal()`,
888:           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
889:           `PetscObjectCompose()`,  `PetscObjectQuery()`
890: M*/
891: #define PetscObjectComposedDataGetIntstar(obj, id, data, flag) (((obj)->intstarcomposedstate ? (data = (obj)->intstarcomposeddata[id], flag = (PetscBool)((obj)->intstarcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), 0)

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

896:    Synopsis:
897:    #include "petsc/private/petscimpl.h"
898:    PetscErrorCode PetscObjectComposedDataSetReal(PetscObject obj,int id,PetscReal data)

900:    Not collective

902:    Input parameters:
903: +  obj - the object to which data is to be attached
904: .  id - the identifier for the data
905: -  data - the data to  be attached

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

910:    Level: developer

912: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
913:           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
914:           `PetscObjectCompose()`,  `PetscObjectQuery()`
915: M*/
916: #define PetscObjectComposedDataSetReal(obj, id, data) ((((obj)->real_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseReal(obj)) || ((obj)->realcomposeddata[id] = data, (obj)->realcomposedstate[id] = (obj)->state, 0))

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

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

925:    Not collective

927:    Input parameters:
928: +  obj - the object from which data is to be retrieved
929: -  id - the identifier for the data

931:    Output parameters:
932: +  data - the data to be retrieved
933: -  flag - `PETSC_TRUE` if the data item exists and is valid, `PETSC_FALSE` otherwise

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

938:    Level: developer

940: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataSetIntstar()`,
941:           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
942:           `PetscObjectCompose()`,  `PetscObjectQuery()`
943: M*/
944: #define PetscObjectComposedDataGetReal(obj, id, data, flag) (((obj)->realcomposedstate ? (data = (obj)->realcomposeddata[id], flag = (PetscBool)((obj)->realcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), 0)

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

949:    Synopsis:
950:    #include "petsc/private/petscimpl.h"
951:    PetscErrorCode PetscObjectComposedDataSetRealstar(PetscObject obj,int id,PetscReal *data)

953:    Not collective

955:    Input parameters:
956: +  obj - the object to which data is to be attached
957: .  id - the identifier for the data
958: -  data - the data to  be attached

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

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

965:    Level: developer

967: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
968:           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
969:           `PetscObjectCompose()`,  `PetscObjectQuery()`, `PetscObjectComposedDataGetRealstar()`
970: M*/
971: #define PetscObjectComposedDataSetRealstar(obj, id, data) \
972:   ((((obj)->realstar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseRealstar(obj)) || ((obj)->realstarcomposeddata[id] = data, (obj)->realstarcomposedstate[id] = (obj)->state, 0))

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

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

981:    Not collective

983:    Input parameters:
984: +  obj - the object from which data is to be retrieved
985: -  id - the identifier for the data

987:    Output parameters:
988: +  data - the data to be retrieved
989: -  flag - `PETSC_TRUE` if the data item exists and is valid, `PETSC_FALSE` otherwise

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

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

996:    Level: developer

998: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
999:           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1000:           `PetscObjectCompose()`,  `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`
1001: M*/
1002: #define PetscObjectComposedDataGetRealstar(obj, id, data, flag) (((obj)->realstarcomposedstate ? (data = (obj)->realstarcomposeddata[id], flag = (PetscBool)((obj)->realstarcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), 0)

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

1007:    Synopsis:
1008:    #include "petsc/private/petscimpl.h"
1009:    PetscErrorCode PetscObjectComposedDataSetScalar(PetscObject obj,int id,PetscScalar data)

1011:    Not collective

1013:    Input parameters:
1014: +  obj - the object to which data is to be attached
1015: .  id - the identifier for the data
1016: -  data - the data to  be attached

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

1021:    Level: developer

1023: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1024:           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1025:           `PetscObjectCompose()`,  `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`, `PetscObjectComposedDataGetScalar()`
1026: M*/
1027: #if defined(PETSC_USE_COMPLEX)
1028:   #define PetscObjectComposedDataSetScalar(obj, id, data) ((((obj)->scalar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseScalar(obj)) || ((obj)->scalarcomposeddata[id] = data, (obj)->scalarcomposedstate[id] = (obj)->state, 0))
1029: #else
1030:   #define PetscObjectComposedDataSetScalar(obj, id, data) PetscObjectComposedDataSetReal(obj, id, data)
1031: #endif
1032: /*MC
1033:    PetscObjectComposedDataGetScalar - retrieve scalar data attached to an object that was set with `PetscObjectComposedDataSetScalar()`

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

1039:    Not collective

1041:    Input parameters:
1042: +  obj - the object from which data is to be retrieved
1043: -  id - the identifier for the data

1045:    Output parameters:
1046: +  data - the data to be retrieved
1047: -  flag - `PETSC_TRUE` if the data item exists and is valid, `PETSC_FALSE` otherwise

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

1052:    Level: developer

1054: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1055:           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1056:           `PetscObjectCompose()`,  `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`, `PetscObjectComposedDataSetScalar()`
1057: M*/
1058: #if defined(PETSC_USE_COMPLEX)
1059:   #define PetscObjectComposedDataGetScalar(obj, id, data, flag) (((obj)->scalarcomposedstate ? (data = (obj)->scalarcomposeddata[id], flag = (PetscBool)((obj)->scalarcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), 0)
1060: #else
1061:   #define PetscObjectComposedDataGetScalar(obj, id, data, flag) PetscObjectComposedDataGetReal(obj, id, data, flag)
1062: #endif

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

1067:    Synopsis:
1068:    #include "petsc/private/petscimpl.h"
1069:    PetscErrorCode PetscObjectComposedDataSetScalarstar(PetscObject obj,int id,PetscScalar *data)

1071:    Not collective

1073:    Input parameters:
1074: +  obj - the object to which data is to be attached
1075: .  id - the identifier for the data
1076: -  data - the data to  be attached

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

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

1083:    Level: developer

1085: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1086:           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1087:           `PetscObjectCompose()`,  `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`, `PetscObjectComposedDataGetScalarstar()`
1088: M*/
1089: #if defined(PETSC_USE_COMPLEX)
1090:   #define PetscObjectComposedDataSetScalarstar(obj, id, data) \
1091:     ((((obj)->scalarstar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseScalarstar(obj)) || ((obj)->scalarstarcomposeddata[id] = data, (obj)->scalarstarcomposedstate[id] = (obj)->state, 0))
1092: #else
1093:   #define PetscObjectComposedDataSetScalarstar(obj, id, data) PetscObjectComposedDataSetRealstar(obj, id, data)
1094: #endif
1095: /*MC
1096:    PetscObjectComposedDataGetScalarstar - retrieve scalar array data set with `PetscObjectComposedDataSetScalarstar()`
1097:    attached to an object

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

1103:    Not collective

1105:    Input parameters:
1106: +  obj - the object from which data is to be retrieved
1107: -  id - the identifier for the data

1109:    Output parameters:
1110: +  data - the data to be retrieved
1111: -  flag - `PETSC_TRUE` if the data item exists and is valid, `PETSC_FALSE` otherwise

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

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

1118:    Level: developer

1120: .seealso: `PetscObjectComposedDataSetInt()`, `PetscObjectComposedDataSetReal()`, `PetscObjectComposedDataGetReal()`, `PetscObjectComposedDataSetIntstar()`,
1121:           `PetscObjectComposedDataSetIntstar()`, `PetscObjectComposedDataGetInt()`, `PetscObject`,
1122:           `PetscObjectCompose()`,  `PetscObjectQuery()`, `PetscObjectComposedDataSetRealstar()`, `PetscObjectComposedDataSetScalarstar()`
1123: M*/
1124: #if defined(PETSC_USE_COMPLEX)
1125:   #define PetscObjectComposedDataGetScalarstar(obj, id, data, flag) (((obj)->scalarstarcomposedstate ? (data = (obj)->scalarstarcomposeddata[id], flag = (PetscBool)((obj)->scalarstarcomposedstate[id] == (obj)->state)) : (flag = PETSC_FALSE)), 0)
1126: #else
1127:   #define PetscObjectComposedDataGetScalarstar(obj, id, data, flag) PetscObjectComposedDataGetRealstar(obj, id, data, flag)
1128: #endif

1130: PETSC_EXTERN PetscMPIInt Petsc_Counter_keyval;
1131: PETSC_EXTERN PetscMPIInt Petsc_InnerComm_keyval;
1132: PETSC_EXTERN PetscMPIInt Petsc_OuterComm_keyval;
1133: PETSC_EXTERN PetscMPIInt Petsc_Seq_keyval;
1134: PETSC_EXTERN PetscMPIInt Petsc_ShmComm_keyval;

1136: struct PetscCommStash {
1137:   struct PetscCommStash *next;
1138:   MPI_Comm               comm;
1139: };

1141: /*
1142:   PETSc communicators have this attribute, see
1143:   PetscCommDuplicate(), PetscCommDestroy(), PetscCommGetNewTag(), PetscObjectGetName()
1144: */
1145: typedef struct {
1146:   PetscMPIInt            tag;       /* next free tag value */
1147:   PetscInt               refcount;  /* number of references, communicator can be freed when this reaches 0 */
1148:   PetscInt               namecount; /* used to generate the next name, as in Vec_0, Mat_1, ... */
1149:   PetscMPIInt           *iflags;    /* length of comm size, shared by all calls to PetscCommBuildTwoSided_Allreduce/RedScatter on this comm */
1150:   struct PetscCommStash *comms;     /* communicators available for PETSc to pass off to other packages */
1151: } PetscCommCounter;

1153: typedef enum {
1154:   STATE_BEGIN,
1155:   STATE_PENDING,
1156:   STATE_END
1157: } SRState;

1159: typedef enum {
1160:   PETSC_SR_REDUCE_SUM = 0,
1161:   PETSC_SR_REDUCE_MAX = 1,
1162:   PETSC_SR_REDUCE_MIN = 2
1163: } PetscSRReductionType;

1165: typedef struct {
1166:   MPI_Comm     comm;
1167:   MPI_Request  request;
1168:   PetscBool    mix;
1169:   PetscBool    async;
1170:   PetscScalar *lvalues;    /* this are the reduced values before call to MPI_Allreduce() */
1171:   PetscScalar *gvalues;    /* values after call to MPI_Allreduce() */
1172:   void       **invecs;     /* for debugging only, vector/memory used with each op */
1173:   PetscInt    *reducetype; /* is particular value to be summed or maxed? */
1174:   struct {
1175:     PetscScalar v;
1176:     PetscInt    i;
1177:   }       *lvalues_mix, *gvalues_mix; /* used when mixing reduce operations */
1178:   SRState  state;                     /* are we calling xxxBegin() or xxxEnd()? */
1179:   PetscInt maxops;                    /* total amount of space we have for requests */
1180:   PetscInt numopsbegin;               /* number of requests that have been queued in */
1181:   PetscInt numopsend;                 /* number of requests that have been gotten by user */
1182: } PetscSplitReduction;

1184: PETSC_EXTERN PetscErrorCode PetscSplitReductionGet(MPI_Comm, PetscSplitReduction **);
1185: PETSC_EXTERN PetscErrorCode PetscSplitReductionEnd(PetscSplitReduction *);
1186: PETSC_EXTERN PetscErrorCode PetscSplitReductionExtend(PetscSplitReduction *);

1188: #if !defined(PETSC_SKIP_SPINLOCK)
1189:   #if defined(PETSC_HAVE_THREADSAFETY)
1190:     #if defined(PETSC_HAVE_CONCURRENCYKIT)
1191:       #if defined(__cplusplus)
1192: /*  CK does not have extern "C" protection in their include files */
1193: extern "C" {
1194:       #endif
1195:       #include <ck_spinlock.h>
1196:       #if defined(__cplusplus)
1197: }
1198:       #endif
1199: typedef ck_spinlock_t        PetscSpinlock;
1200: static inline PetscErrorCode PetscSpinlockCreate(PetscSpinlock *ck_spinlock)
1201: {
1202:   ck_spinlock_init(ck_spinlock);
1203:   return 0;
1204: }
1205: static inline PetscErrorCode PetscSpinlockLock(PetscSpinlock *ck_spinlock)
1206: {
1207:   ck_spinlock_lock(ck_spinlock);
1208:   return 0;
1209: }
1210: static inline PetscErrorCode PetscSpinlockUnlock(PetscSpinlock *ck_spinlock)
1211: {
1212:   ck_spinlock_unlock(ck_spinlock);
1213:   return 0;
1214: }
1215: static inline PetscErrorCode PetscSpinlockDestroy(PetscSpinlock *ck_spinlock)
1216: {
1217:   return 0;
1218: }
1219:     #elif defined(PETSC_HAVE_OPENMP)

1221:       #include <omp.h>
1222: typedef omp_lock_t           PetscSpinlock;
1223: static inline PetscErrorCode PetscSpinlockCreate(PetscSpinlock *omp_lock)
1224: {
1225:   omp_init_lock(omp_lock);
1226:   return 0;
1227: }
1228: static inline PetscErrorCode PetscSpinlockLock(PetscSpinlock *omp_lock)
1229: {
1230:   omp_set_lock(omp_lock);
1231:   return 0;
1232: }
1233: static inline PetscErrorCode PetscSpinlockUnlock(PetscSpinlock *omp_lock)
1234: {
1235:   omp_unset_lock(omp_lock);
1236:   return 0;
1237: }
1238: static inline PetscErrorCode PetscSpinlockDestroy(PetscSpinlock *omp_lock)
1239: {
1240:   omp_destroy_lock(omp_lock);
1241:   return 0;
1242: }
1243:     #else
1244:       #error "Thread safety requires either --with-openmp or --download-concurrencykit"
1245:     #endif

1247:   #else
1248: typedef int PetscSpinlock;
1249:     #define PetscSpinlockCreate(a)  0
1250:     #define PetscSpinlockLock(a)    0
1251:     #define PetscSpinlockUnlock(a)  0
1252:     #define PetscSpinlockDestroy(a) 0
1253:   #endif

1255:   #if defined(PETSC_HAVE_THREADSAFETY)
1256: PETSC_INTERN PetscSpinlock PetscViewerASCIISpinLockOpen;
1257: PETSC_INTERN PetscSpinlock PetscViewerASCIISpinLockStdout;
1258: PETSC_INTERN PetscSpinlock PetscViewerASCIISpinLockStderr;
1259: PETSC_INTERN PetscSpinlock PetscCommSpinLock;
1260:   #endif
1261: #endif

1263: PETSC_EXTERN PetscLogEvent PETSC_Barrier;
1264: PETSC_EXTERN PetscLogEvent PETSC_BuildTwoSided;
1265: PETSC_EXTERN PetscLogEvent PETSC_BuildTwoSidedF;
1266: PETSC_EXTERN PetscBool     use_gpu_aware_mpi;
1267: PETSC_EXTERN PetscBool     PetscPrintFunctionList;

1269: #if defined(PETSC_HAVE_ADIOS)
1270: PETSC_EXTERN int64_t Petsc_adios_group;
1271: #endif

1273: #if defined(PETSC_HAVE_KOKKOS)
1274: PETSC_INTERN PetscBool      PetscBeganKokkos;
1275: PETSC_EXTERN PetscBool      PetscKokkosInitialized;
1276: PETSC_INTERN PetscErrorCode PetscKokkosIsInitialized_Private(PetscBool *);
1277: PETSC_INTERN PetscErrorCode PetscKokkosFinalize_Private(void);
1278: #endif

1280: #if defined(PETSC_HAVE_OPENMP)
1281: PETSC_EXTERN PetscInt PetscNumOMPThreads;
1282: #endif

1284: #endif /* PETSCIMPL_H */