Date: 2022-03-04T17:40:03+00:00

Actual source code: petscimpl.h

      2: /*
      3:     Defines the basic header of all PETSc objects.
      4: */

      6: #if !defined(PETSCIMPL_H)
      7: #define PETSCIMPL_H
      8: #include <petscsys.h>

     10: #if defined(PETSC_CLANG_STATIC_ANALYZER)
     11: #define PetscDisableStaticAnalyzerForExpressionUnderstandingThatThisIsDangerousAndBugprone(expr)
     12: #else
     13: #define PetscDisableStaticAnalyzerForExpressionUnderstandingThatThisIsDangerousAndBugprone(expr) \
     14:   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 (*getcomm)(PetscObject,MPI_Comm *);
     68:    PetscErrorCode (*view)(PetscObject,PetscViewer);
     69:    PetscErrorCode (*destroy)(PetscObject*);
     70:    PetscErrorCode (*compose)(PetscObject,const char[],PetscObject);
     71:    PetscErrorCode (*query)(PetscObject,const char[],PetscObject *);
     72:    PetscErrorCode (*composefunction)(PetscObject,const char[],void (*)(void));
     73:    PetscErrorCode (*queryfunction)(PetscObject,const char[],void (**)(void));
     74: } PetscOps;

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

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

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

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

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

    149: #define  PETSCFREEDHEADER -1

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

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

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

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

    169:     Level: developer

    171: .seealso: PetscHeaderDestroy(), PetscClassIdRegister()

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

    180: PETSC_EXTERN PetscErrorCode PetscComposedQuantitiesDestroy(PetscObject obj);
    181: PETSC_EXTERN PetscErrorCode PetscHeaderCreate_Private(PetscObject,PetscClassId,const char[],const char[],const char[],MPI_Comm,PetscObjectDestroyFunction,PetscObjectViewFunction);

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

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

    189:     Level: developer

    191: .seealso: PetscHeaderCreate()
    192: @*/
    193: #define PetscHeaderDestroy(h) (PetscHeaderDestroy_Private((PetscObject)(*(h))) || PetscFree(*(h)))

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

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

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

    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)

    225: #else

    227: /*  This check is for subtype methods such as DMDAGetCorners() that do not use the PetscTryMethod() or PetscUseMethod() paradigm */
    229:   do {   \
    230:     PetscErrorCode _7_ierr; \
    231:     PetscBool      _7_same; \
    233:     _7_PetscObjectTypeCompare((PetscObject)(h),t,&_7_same);CHKERRQ(_7_ierr); \
    234:     if (!_7_same) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Wrong subtype object:Parameter # %d must have implementation %s it is %s",arg,t,((PetscObject)(h))->type_name); \
    235:   } while (0)

    238:   do {                                                                  \
    239:     if (!(h)) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Null Object: Parameter # %d",arg); \
    241:     if (((PetscObject)(h))->classid != ck) {                            \
    242:       if (((PetscObject)(h))->classid == PETSCFREEDHEADER) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_CORRUPT,"Object already free: Parameter # %d",arg); \
    243:       else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Wrong type of object: Parameter # %d",arg); \
    244:     }                                                                   \
    245:   } while (0)

    248:   do {                                                                  \
    249:     if (!(h)) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Null Object: Parameter # %d",arg); \
    251:     if (((PetscObject)(h))->classid == PETSCFREEDHEADER) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_CORRUPT,"Object already free: Parameter # %d",arg); \
    252:     else if (((PetscObject)(h))->classid < PETSC_SMALLEST_CLASSID || ((PetscObject)(h))->classid > PETSC_LARGEST_CLASSID) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_CORRUPT,"Invalid type of object: Parameter # %d",arg); \
    253:   } while (0)

    256:   do {                                                                  \
    257:     if (!(h)) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Null Pointer: Parameter # %d",arg); \
    259:   } while (0)

    262:   do {                                                                  \
    263:     if (!(h)) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Null Pointer: Parameter # %d",arg);\
    265:   } while (0)

    268:   do {                                                                  \
    269:     if (!(h)) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_BADPTR,"Null Pointer: Parameter # %d",arg); \
    271:   } while (0)

    274:   do {                                                                  \
    275:     if (!(h)) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_BADPTR,"Null Pointer: Parameter # %d",arg); \
    277:   } while (0)

    280:   do {                                                                  \
    281:     if (!(h)) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Null Pointer: Parameter # %d",arg); \
    283:   } while (0)

    286:   do {                                                                  \
    287:     if (!(h)) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Null Pointer: Parameter # %d",arg); \
    289:   } while (0)

    292:   do {                                                                  \
    293:     if (!(f)) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Null Function Pointer: Parameter # %d",arg); \
    294:   } while (0)
    295: #endif
    296: #else /* PETSC_CLANG_STATIC_ANALYZER */
    297: template <typename T>
    299: template <typename T>
    301: template <typename T>
    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>
    318: #endif /* PETSC_CLANG_STATIC_ANALYZER */

    320: #define PetscSorted(n,idx,sorted)           \
    321:   do {                                      \
    322:     PetscInt _i_;                           \
    323:     (sorted) = PETSC_TRUE;                  \
    324:     for (_i_ = 1; _i_ < (n); _i_++)         \
    325:       if ((idx)[_i_] < (idx)[_i_ - 1])      \
    326:         { (sorted) = PETSC_FALSE; break; }  \
    327:   } while (0)

    329: #if !defined(PETSC_CLANG_STATIC_ANALYZER)
    330: #if !defined(PETSC_USE_DEBUG)

    346: #else

    348: /*
    349:     For example, in the dot product between two vectors,
    350:   both vectors must be either Seq or MPI, not one of each
    351: */
    353:   do {                                                                  \
    354:     if (((PetscObject)(a))->type != ((PetscObject)(b))->type) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMETYPE,"Objects not of same type: Argument # %d and %d",arga,argb); \
    355:   } while (0)

    357: /*
    358:     Check type_name
    359: */
    361:   do {                                                                  \
    362:     PetscBool      _7_match;                                            \
    363:     PetscErrorCode _7_ierr;                                             \
    364:     _7_PetscObjectTypeCompare(((PetscObject)(a)),(type),&_7_match);CHKERRQ(_7_ierr); \
    365:     if (!_7_match) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Object (%s) is not %s",(char*)(((PetscObject)(a))->type_name),type); \
    366:   } while (0)

    369:   do {                                                                  \
    370:     PetscBool      _7_match;                                            \
    371:     PetscErrorCode _7_ierr;                                             \
    372:     _7_PetscObjectTypeCompareAny(((PetscObject)(a)),&_7_match,(type1),(type2),"");CHKERRQ(_7_ierr); \
    373:     if (!_7_match) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Object (%s) is not %s or %s",(char*)(((PetscObject)(a))->type_name),type1,type2); \
    374:   } while (0)
    375: /*
    376:    Use this macro to check if the type is set
    377: */

    380:   do {                                                                  \
    381:     if (!((PetscObject)(a))->type_name) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"%s object's type is not set: Argument # %d",((PetscObject)(a))->class_name,arg); \
    382:   } while (0)
    383: /*
    384:    Sometimes object must live on same communicator to inter-operate
    385: */
    387:   do {                                                                  \
    388:     PetscErrorCode _7_ierr;                                             \
    389:     PetscMPIInt    _7_flag;                                             \
    390:     _7_MPI_Comm_compare(PetscObjectComm((PetscObject)(a)),PetscObjectComm((PetscObject)(b)),&_7_flag);CHKERRMPI(_7_ierr); \
    391:     if (_7_flag != MPI_CONGRUENT && _7_flag != MPI_IDENT) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"Different communicators in the two objects: Argument # %d and %d flag %d",arga,argb,_7_flag); \
    392:   } while (0)

    395:   do {                                                  \
    398:   } while (0)

    401:   do {                                                                  \
    402:     PetscErrorCode _7_ierr;                                             \
    403:     PetscScalar b0=(b);                                                 \
    404:     PetscReal b1[5],b2[5];                                              \
    405:     if (PetscIsNanScalar(b0)) {b1[4] = 1;} else {b1[4] = 0;};           \
    406:     b1[0] = -PetscRealPart(b0); b1[1] = PetscRealPart(b0); b1[2] = -PetscImaginaryPart(b0); b1[3] = PetscImaginaryPart(b0); \
    407:     _7_MPIU_Allreduce(b1,b2,5,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)(a)));CHKERRMPI(_7_ierr); \
    408:     if (!(b2[4] > 0) && !(PetscEqualReal(-b2[0],b2[1]) && PetscEqualReal(-b2[2],b2[3]))) SETERRQ1(PetscObjectComm((PetscObject)(a)),PETSC_ERR_ARG_WRONG,"Scalar value must be same on all processes, argument # %d",arg); \
    409:   } while (0)

    412:   do {                                                                  \
    413:     PetscErrorCode _7_ierr;                                             \
    414:     PetscReal b0=(b),b1[3],b2[3];                                       \
    415:     if (PetscIsNanReal(b0)) {b1[2] = 1;} else {b1[2] = 0;};             \
    416:     b1[0] = -b0; b1[1] = b0;                                            \
    417:     _7_MPIU_Allreduce(b1,b2,3,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)(a)));CHKERRMPI(_7_ierr); \
    418:     if (!(b2[2] > 0) && !PetscEqualReal(-b2[0],b2[1])) SETERRQ1(PetscObjectComm((PetscObject)(a)),PETSC_ERR_ARG_WRONG,"Real value must be same on all processes, argument # %d",arg); \
    419:   } while (0)

    422:   do {                                                                  \
    423:     PetscErrorCode _7_ierr;                                             \
    424:     PetscInt b0=(b),b1[2],b2[2];                                        \
    425:     b1[0] = -b0; b1[1] = b0;                                            \
    426:     _7_MPIU_Allreduce(b1,b2,2,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)(a)));CHKERRMPI(_7_ierr); \
    427:     if (-b2[0] != b2[1]) SETERRQ1(PetscObjectComm((PetscObject)(a)),PETSC_ERR_ARG_WRONG,"Int value must be same on all processes, argument # %d",arg); \
    428:   } while (0)

    431:   do {                                                                  \
    432:     PetscErrorCode _7_ierr;                                             \
    433:     PetscMPIInt b0=(b),b1[2],b2[2];                                     \
    434:     b1[0] = -b0; b1[1] = b0;                                            \
    435:     _7_MPIU_Allreduce(b1,b2,2,MPI_INT,MPI_MAX,PetscObjectComm((PetscObject)(a)));CHKERRMPI(_7_ierr); \
    436:     if (-b2[0] != b2[1]) SETERRQ1(PetscObjectComm((PetscObject)(a)),PETSC_ERR_ARG_WRONG,"PetscMPIInt value must be same on all processes, argument # %d",arg); \
    437:   } while (0)

    440:   do {                                                                  \
    441:     PetscErrorCode _7_ierr;                                             \
    442:     PetscMPIInt b0=(PetscMPIInt)(b),b1[2],b2[2];                        \
    443:     b1[0] = -b0; b1[1] = b0;                                            \
    444:     _7_MPIU_Allreduce(b1,b2,2,MPI_INT,MPI_MAX,PetscObjectComm((PetscObject)(a)));CHKERRMPI(_7_ierr); \
    445:     if (-b2[0] != b2[1]) SETERRQ1(PetscObjectComm((PetscObject)(a)),PETSC_ERR_ARG_WRONG,"Bool value must be same on all processes, argument # %d",arg); \
    446:   } while (0)

    449:   do {                                                                  \
    450:     PetscErrorCode _7_ierr;                                             \
    451:     PetscMPIInt b0=(PetscMPIInt)(b),b1[2],b2[2];                        \
    452:     b1[0] = -b0; b1[1] = b0;                                            \
    453:     _7_MPIU_Allreduce(b1,b2,2,MPI_INT,MPI_MAX,PetscObjectComm((PetscObject)(a)));CHKERRMPI(_7_ierr); \
    454:     if (-b2[0] != b2[1]) SETERRQ1(PetscObjectComm((PetscObject)(a)),PETSC_ERR_ARG_WRONG,"Enum value must be same on all processes, argument # %d",arg); \
    455:   } while (0)

    458:   do {                                                                                            \
    459:     PetscBool _1_flg;                                                                             \
    460:     PetscSorted(n,idx,_1_flg);                                                                    \
    461:     if (!_1_flg) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Input array needs to be sorted"); \
    462:   } while (0)

    464: #endif
    465: #else /* PETSC_CLANG_STATIC_ANALYZER */
    466: template <typename Ta,typename Tb>
    470: template <typename T>
    472: template <typename Ta,typename Tb>
    474: template <typename Ta,typename Tb>
    476: template <typename Ta,typename Tb>
    478: template <typename Ta,typename Tb>
    480: template <typename Ta,typename Tb>
    482: template <typename Ta,typename Tb>
    484: template <typename Ta,typename Tb>
    486: template <typename Ta,typename Tb>
    489: #endif /* PETSC_CLANG_STATIC_ANALYZER */

    491: /*
    492:    PetscTryMethod - Queries an object for a method, if it exists then calls it.
    493:               These are intended to be used only inside PETSc functions.

    495:    Level: developer

    497: .seealso: PetscUseMethod()
    498: */
    499: #define  PetscTryMethod(obj,A,B,C) \
    500:   0; do { PetscErrorCode (*_7_f)B, _7_ierr; \
    501:     _7_PetscObjectQueryFunction((PetscObject)(obj),A,&_7_f);CHKERRQ(_7_ierr); \
    502:     if (_7_f) {_7_(*_7_f)C;CHKERRQ(_7_ierr);} \
    503:   } while (0)

    505: /*
    506:    PetscUseMethod - Queries an object for a method, if it exists then calls it, otherwise generates an error.
    507:               These are intended to be used only inside PETSc functions.

    509:    Level: developer

    511: .seealso: PetscTryMethod()
    512: */
    513: #define  PetscUseMethod(obj,A,B,C) \
    514:   0; do { PetscErrorCode (*_7_f)B, _7_ierr; \
    515:     _7_PetscObjectQueryFunction((PetscObject)(obj),A,&_7_f);CHKERRQ(_7_ierr); \
    516:     if (_7_f) {_7_(*_7_f)C;CHKERRQ(_7_ierr);} \
    517:     else SETERRQ1(PetscObjectComm((PetscObject)(obj)),PETSC_ERR_SUP,"Cannot locate function %s in object",A); \
    518:   } while (0)

    520: /*MC
    521:    PetscObjectStateIncrease - Increases the state of any PetscObject

    523:    Synopsis:
    524:    #include "petsc/private/petscimpl.h"
    525:    PetscErrorCode PetscObjectStateIncrease(PetscObject obj)

    527:    Logically Collective

    529:    Input Parameter:
    530: .  obj - any PETSc object, for example a Vec, Mat or KSP. This must be
    531:          cast with a (PetscObject), for example,
    532:          PetscObjectStateIncrease((PetscObject)mat);

    534:    Notes:
    535:     object state is an integer which gets increased every time
    536:    the object is changed internally. By saving and later querying the object state
    537:    one can determine whether information about the object is still current.
    538:    Currently, state is maintained for Vec and Mat objects.

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

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

    547:    Level: developer

    549:    seealso: PetscObjectStateGet()

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

    554: PETSC_EXTERN PetscErrorCode PetscObjectStateGet(PetscObject,PetscObjectState*);
    555: PETSC_EXTERN PetscErrorCode PetscObjectStateSet(PetscObject,PetscObjectState);
    556: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataRegister(PetscInt*);
    557: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseInt(PetscObject);
    558: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseIntstar(PetscObject);
    559: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseReal(PetscObject);
    560: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseRealstar(PetscObject);
    561: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseScalar(PetscObject);
    562: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseScalarstar(PetscObject);
    563: PETSC_EXTERN PetscInt       PetscObjectComposedDataMax;
    564: /*MC
    565:    PetscObjectComposedDataSetInt - attach integer data to a PetscObject

    567:    Synopsis:
    568:    #include "petsc/private/petscimpl.h"
    569:    PetscErrorCode PetscObjectComposedDataSetInt(PetscObject obj,int id,int data)

    571:    Not collective

    573:    Input parameters:
    574: +  obj - the object to which data is to be attached
    575: .  id - the identifier for the data
    576: -  data - the data to  be attached

    578:    Notes
    579:    The data identifier can best be created through a call to  PetscObjectComposedDataRegister()

    581:    Level: developer
    582: M*/
    583: #define PetscObjectComposedDataSetInt(obj,id,data)                                      \
    584:   ((((obj)->int_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseInt(obj)) ||  \
    585:    ((obj)->intcomposeddata[id] = data,(obj)->intcomposedstate[id] = (obj)->state, 0))

    587: /*MC
    588:    PetscObjectComposedDataGetInt - retrieve integer data attached to an object

    590:    Synopsis:
    591:    #include "petsc/private/petscimpl.h"
    592:    PetscErrorCode PetscObjectComposedDataGetInt(PetscObject obj,int id,int data,PetscBool  flag)

    594:    Not collective

    596:    Input parameters:
    597: +  obj - the object from which data is to be retrieved
    598: -  id - the identifier for the data

    600:    Output parameters:
    601: +  data - the data to be retrieved
    602: -  flag - PETSC_TRUE if the data item exists and is valid, PETSC_FALSE otherwise

    604:    The 'data' and 'flag' variables are inlined, so they are not pointers.

    606:    Level: developer
    607: M*/
    608: #define PetscObjectComposedDataGetInt(obj,id,data,flag)                            \
    609:   ((((obj)->intcomposedstate && ((obj)->intcomposedstate[id] == (obj)->state)) ?   \
    610:    (data = (obj)->intcomposeddata[id],flag = PETSC_TRUE) : (flag = PETSC_FALSE)),0)

    612: /*MC
    613:    PetscObjectComposedDataSetIntstar - attach integer array data to a PetscObject

    615:    Synopsis:
    616:    #include "petsc/private/petscimpl.h"
    617:    PetscErrorCode PetscObjectComposedDataSetIntstar(PetscObject obj,int id,int *data)

    619:    Not collective

    621:    Input parameters:
    622: +  obj - the object to which data is to be attached
    623: .  id - the identifier for the data
    624: -  data - the data to  be attached

    626:    Notes
    627:    The data identifier can best be determined through a call to
    628:    PetscObjectComposedDataRegister()

    630:    Level: developer
    631: M*/
    632: #define PetscObjectComposedDataSetIntstar(obj,id,data)                                          \
    633:   ((((obj)->intstar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseIntstar(obj)) ||  \
    634:    ((obj)->intstarcomposeddata[id] = data,(obj)->intstarcomposedstate[id] = (obj)->state, 0))

    636: /*MC
    637:    PetscObjectComposedDataGetIntstar - retrieve integer array data
    638:    attached to an object

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

    644:    Not collective

    646:    Input parameters:
    647: +  obj - the object from which data is to be retrieved
    648: -  id - the identifier for the data

    650:    Output parameters:
    651: +  data - the data to be retrieved
    652: -  flag - PETSC_TRUE if the data item exists and is valid, PETSC_FALSE otherwise

    654:    The 'data' and 'flag' variables are inlined, so they are not pointers.

    656:    Level: developer
    657: M*/
    658: #define PetscObjectComposedDataGetIntstar(obj,id,data,flag)                               \
    659:   ((((obj)->intstarcomposedstate && ((obj)->intstarcomposedstate[id] == (obj)->state)) ?  \
    660:    (data = (obj)->intstarcomposeddata[id],flag = PETSC_TRUE) : (flag = PETSC_FALSE)),0)

    662: /*MC
    663:    PetscObjectComposedDataSetReal - attach real data to a PetscObject

    665:    Synopsis:
    666:    #include "petsc/private/petscimpl.h"
    667:    PetscErrorCode PetscObjectComposedDataSetReal(PetscObject obj,int id,PetscReal data)

    669:    Not collective

    671:    Input parameters:
    672: +  obj - the object to which data is to be attached
    673: .  id - the identifier for the data
    674: -  data - the data to  be attached

    676:    Notes
    677:    The data identifier can best be determined through a call to
    678:    PetscObjectComposedDataRegister()

    680:    Level: developer
    681: M*/
    682: #define PetscObjectComposedDataSetReal(obj,id,data)                                       \
    683:   ((((obj)->real_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseReal(obj)) ||  \
    684:    ((obj)->realcomposeddata[id] = data,(obj)->realcomposedstate[id] = (obj)->state, 0))

    686: /*MC
    687:    PetscObjectComposedDataGetReal - retrieve real data attached to an object

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

    693:    Not collective

    695:    Input parameters:
    696: +  obj - the object from which data is to be retrieved
    697: -  id - the identifier for the data

    699:    Output parameters:
    700: +  data - the data to be retrieved
    701: -  flag - PETSC_TRUE if the data item exists and is valid, PETSC_FALSE otherwise

    703:    The 'data' and 'flag' variables are inlined, so they are not pointers.

    705:    Level: developer
    706: M*/
    707: #define PetscObjectComposedDataGetReal(obj,id,data,flag)                            \
    708:   ((((obj)->realcomposedstate && ((obj)->realcomposedstate[id] == (obj)->state)) ?  \
    709:    (data = (obj)->realcomposeddata[id],flag = PETSC_TRUE) : (flag = PETSC_FALSE)),0)

    711: /*MC
    712:    PetscObjectComposedDataSetRealstar - attach real array data to a PetscObject

    714:    Synopsis:
    715:    #include "petsc/private/petscimpl.h"
    716:    PetscErrorCode PetscObjectComposedDataSetRealstar(PetscObject obj,int id,PetscReal *data)

    718:    Not collective

    720:    Input parameters:
    721: +  obj - the object to which data is to be attached
    722: .  id - the identifier for the data
    723: -  data - the data to  be attached

    725:    Notes
    726:    The data identifier can best be determined through a call to
    727:    PetscObjectComposedDataRegister()

    729:    Level: developer
    730: M*/
    731: #define PetscObjectComposedDataSetRealstar(obj,id,data)                                           \
    732:   ((((obj)->realstar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseRealstar(obj)) ||  \
    733:    ((obj)->realstarcomposeddata[id] = data, (obj)->realstarcomposedstate[id] = (obj)->state, 0))

    735: /*MC
    736:    PetscObjectComposedDataGetRealstar - retrieve real array data
    737:    attached to an object

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

    743:    Not collective

    745:    Input parameters:
    746: +  obj - the object from which data is to be retrieved
    747: -  id - the identifier for the data

    749:    Output parameters:
    750: +  data - the data to be retrieved
    751: -  flag - PETSC_TRUE if the data item exists and is valid, PETSC_FALSE otherwise

    753:    The 'data' and 'flag' variables are inlined, so they are not pointers.

    755:    Level: developer
    756: M*/
    757: #define PetscObjectComposedDataGetRealstar(obj,id,data,flag)                                \
    758:   ((((obj)->realstarcomposedstate && ((obj)->realstarcomposedstate[id] == (obj)->state)) ?  \
    759:    (data = (obj)->realstarcomposeddata[id],flag = PETSC_TRUE) : (flag = PETSC_FALSE)),0)

    761: /*MC
    762:    PetscObjectComposedDataSetScalar - attach scalar data to a PetscObject

    764:    Synopsis:
    765:    #include "petsc/private/petscimpl.h"
    766:    PetscErrorCode PetscObjectComposedDataSetScalar(PetscObject obj,int id,PetscScalar data)

    768:    Not collective

    770:    Input parameters:
    771: +  obj - the object to which data is to be attached
    772: .  id - the identifier for the data
    773: -  data - the data to  be attached

    775:    Notes
    776:    The data identifier can best be determined through a call to
    777:    PetscObjectComposedDataRegister()

    779:    Level: developer
    780: M*/
    781: #if defined(PETSC_USE_COMPLEX)
    782: #define PetscObjectComposedDataSetScalar(obj,id,data)                                        \
    783:   ((((obj)->scalar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseScalar(obj)) || \
    784:    ((obj)->scalarcomposeddata[id] = data,(obj)->scalarcomposedstate[id] = (obj)->state, 0))
    785: #else
    786: #define PetscObjectComposedDataSetScalar(obj,id,data) \
    787:         PetscObjectComposedDataSetReal(obj,id,data)
    788: #endif
    789: /*MC
    790:    PetscObjectComposedDataGetScalar - retrieve scalar data attached to an object

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

    796:    Not collective

    798:    Input parameters:
    799: +  obj - the object from which data is to be retrieved
    800: -  id - the identifier for the data

    802:    Output parameters:
    803: +  data - the data to be retrieved
    804: -  flag - PETSC_TRUE if the data item exists and is valid, PETSC_FALSE otherwise

    806:    The 'data' and 'flag' variables are inlined, so they are not pointers.

    808:    Level: developer
    809: M*/
    810: #if defined(PETSC_USE_COMPLEX)
    811: #define PetscObjectComposedDataGetScalar(obj,id,data,flag)                              \
    812:   ((((obj)->scalarcomposedstate && ((obj)->scalarcomposedstate[id] == (obj)->state)) ? \
    813:    (data = (obj)->scalarcomposeddata[id],flag = PETSC_TRUE) : (flag = PETSC_FALSE)),0)
    814: #else
    815: #define PetscObjectComposedDataGetScalar(obj,id,data,flag)                             \
    816:         PetscObjectComposedDataGetReal(obj,id,data,flag)
    817: #endif

    819: /*MC
    820:    PetscObjectComposedDataSetScalarstar - attach scalar array data to a PetscObject

    822:    Synopsis:
    823:    #include "petsc/private/petscimpl.h"
    824:    PetscErrorCode PetscObjectComposedDataSetScalarstar(PetscObject obj,int id,PetscScalar *data)

    826:    Not collective

    828:    Input parameters:
    829: +  obj - the object to which data is to be attached
    830: .  id - the identifier for the data
    831: -  data - the data to  be attached

    833:    Notes
    834:    The data identifier can best be determined through a call to
    835:    PetscObjectComposedDataRegister()

    837:    Level: developer
    838: M*/
    839: #if defined(PETSC_USE_COMPLEX)
    840: #define PetscObjectComposedDataSetScalarstar(obj,id,data)                                             \
    841:   ((((obj)->scalarstar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseScalarstar(obj)) ||  \
    842:    ((obj)->scalarstarcomposeddata[id] = data,(obj)->scalarstarcomposedstate[id] = (obj)->state, 0))
    843: #else
    844: #define PetscObjectComposedDataSetScalarstar(obj,id,data) \
    845:         PetscObjectComposedDataSetRealstar(obj,id,data)
    846: #endif
    847: /*MC
    848:    PetscObjectComposedDataGetScalarstar - retrieve scalar array data
    849:    attached to an object

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

    855:    Not collective

    857:    Input parameters:
    858: +  obj - the object from which data is to be retrieved
    859: -  id - the identifier for the data

    861:    Output parameters:
    862: +  data - the data to be retrieved
    863: -  flag - PETSC_TRUE if the data item exists and is valid, PETSC_FALSE otherwise

    865:    The 'data' and 'flag' variables are inlined, so they are not pointers.

    867:    Level: developer
    868: M*/
    869: #if defined(PETSC_USE_COMPLEX)
    870: #define PetscObjectComposedDataGetScalarstar(obj,id,data,flag)                                 \
    871:   ((((obj)->scalarstarcomposedstate && ((obj)->scalarstarcomposedstate[id] == (obj)->state)) ? \
    872:        (data = (obj)->scalarstarcomposeddata[id],flag = PETSC_TRUE) : (flag = PETSC_FALSE)),0)
    873: #else
    874: #define PetscObjectComposedDataGetScalarstar(obj,id,data,flag)         \
    875:         PetscObjectComposedDataGetRealstar(obj,id,data,flag)
    876: #endif

    878: PETSC_EXTERN PetscMPIInt Petsc_Counter_keyval;
    879: PETSC_EXTERN PetscMPIInt Petsc_InnerComm_keyval;
    880: PETSC_EXTERN PetscMPIInt Petsc_OuterComm_keyval;
    881: PETSC_EXTERN PetscMPIInt Petsc_Seq_keyval;
    882: PETSC_EXTERN PetscMPIInt Petsc_ShmComm_keyval;

    884: /*
    885:   PETSc communicators have this attribute, see
    886:   PetscCommDuplicate(), PetscCommDestroy(), PetscCommGetNewTag(), PetscObjectGetName()
    887: */
    888: typedef struct {
    889:   PetscMPIInt tag;              /* next free tag value */
    890:   PetscInt    refcount;         /* number of references, communicator can be freed when this reaches 0 */
    891:   PetscInt    namecount;        /* used to generate the next name, as in Vec_0, Mat_1, ... */
    892:   PetscMPIInt *iflags;          /* length of comm size, shared by all calls to PetscCommBuildTwoSided_Allreduce/RedScatter on this comm */
    893: } PetscCommCounter;

    895: typedef enum {STATE_BEGIN, STATE_PENDING, STATE_END} SRState;

    897: typedef enum {PETSC_SR_REDUCE_SUM=0,PETSC_SR_REDUCE_MAX=1,PETSC_SR_REDUCE_MIN=2} PetscSRReductionType;

    899: typedef struct {
    900:   MPI_Comm       comm;
    901:   MPI_Request    request;
    902:   PetscBool      mix;
    903:   PetscBool      async;
    904:   PetscScalar    *lvalues;     /* this are the reduced values before call to MPI_Allreduce() */
    905:   PetscScalar    *gvalues;     /* values after call to MPI_Allreduce() */
    906:   void           **invecs;     /* for debugging only, vector/memory used with each op */
    907:   PetscInt       *reducetype;  /* is particular value to be summed or maxed? */
    908:   struct { PetscScalar v; PetscInt i; } *lvalues_mix,*gvalues_mix; /* used when mixing reduce operations */
    909:   SRState        state;        /* are we calling xxxBegin() or xxxEnd()? */
    910:   PetscInt       maxops;       /* total amount of space we have for requests */
    911:   PetscInt       numopsbegin;  /* number of requests that have been queued in */
    912:   PetscInt       numopsend;    /* number of requests that have been gotten by user */
    913: } PetscSplitReduction;

    915: PETSC_EXTERN PetscErrorCode PetscSplitReductionGet(MPI_Comm,PetscSplitReduction**);
    916: PETSC_EXTERN PetscErrorCode PetscSplitReductionEnd(PetscSplitReduction*);
    917: PETSC_EXTERN PetscErrorCode PetscSplitReductionExtend(PetscSplitReduction*);

    919: #if !defined(PETSC_SKIP_SPINLOCK)
    920: #if defined(PETSC_HAVE_THREADSAFETY)
    921: #  if defined(PETSC_HAVE_CONCURRENCYKIT)
    922: #if defined(__cplusplus)
    923: /*  CK does not have extern "C" protection in their include files */
    924: extern "C" {
    925: #endif
    926: #include <ck_spinlock.h>
    927: #if defined(__cplusplus)
    928: }
    929: #endif
    930: typedef ck_spinlock_t PetscSpinlock;
    931: PETSC_STATIC_INLINE PetscErrorCode PetscSpinlockCreate(PetscSpinlock *ck_spinlock)
    932: {
    933:   ck_spinlock_init(ck_spinlock);
    934:   return 0;
    935: }
    936: PETSC_STATIC_INLINE PetscErrorCode PetscSpinlockLock(PetscSpinlock *ck_spinlock)
    937: {
    938:   ck_spinlock_lock(ck_spinlock);
    939:   return 0;
    940: }
    941: PETSC_STATIC_INLINE PetscErrorCode PetscSpinlockUnlock(PetscSpinlock *ck_spinlock)
    942: {
    943:   ck_spinlock_unlock(ck_spinlock);
    944:   return 0;
    945: }
    946: PETSC_STATIC_INLINE PetscErrorCode PetscSpinlockDestroy(PetscSpinlock *ck_spinlock)
    947: {
    948:   return 0;
    949: }
    950: #  elif defined(PETSC_HAVE_OPENMP)

    952: #include <omp.h>
    953: typedef omp_lock_t PetscSpinlock;
    954: PETSC_STATIC_INLINE PetscErrorCode PetscSpinlockCreate(PetscSpinlock *omp_lock)
    955: {
    956:   omp_init_lock(omp_lock);
    957:   return 0;
    958: }
    959: PETSC_STATIC_INLINE PetscErrorCode PetscSpinlockLock(PetscSpinlock *omp_lock)
    960: {
    961:   omp_set_lock(omp_lock);
    962:   return 0;
    963: }
    964: PETSC_STATIC_INLINE PetscErrorCode PetscSpinlockUnlock(PetscSpinlock *omp_lock)
    965: {
    966:   omp_unset_lock(omp_lock);
    967:   return 0;
    968: }
    969: PETSC_STATIC_INLINE PetscErrorCode PetscSpinlockDestroy(PetscSpinlock *omp_lock)
    970: {
    971:   omp_destroy_lock(omp_lock);
    972:   return 0;
    973: }
    974: #else
    975: Thread safety requires either --with-openmp or --download-concurrencykit
    976: #endif

    978: #else
    979: typedef int PetscSpinlock;
    980: #define PetscSpinlockCreate(a)  0
    981: #define PetscSpinlockLock(a)    0
    982: #define PetscSpinlockUnlock(a)  0
    983: #define PetscSpinlockDestroy(a) 0
    984: #endif

    986: #if defined(PETSC_HAVE_THREADSAFETY)
    987: PETSC_INTERN PetscSpinlock PetscViewerASCIISpinLockOpen;
    988: PETSC_INTERN PetscSpinlock PetscViewerASCIISpinLockStdout;
    989: PETSC_INTERN PetscSpinlock PetscViewerASCIISpinLockStderr;
    990: PETSC_INTERN PetscSpinlock PetscCommSpinLock;
    991: #endif
    992: #endif

    994: PETSC_EXTERN PetscLogEvent PETSC_Barrier;
    995: PETSC_EXTERN PetscLogEvent PETSC_BuildTwoSided;
    996: PETSC_EXTERN PetscLogEvent PETSC_BuildTwoSidedF;
    997: PETSC_EXTERN PetscBool     use_gpu_aware_mpi;

    999: #if defined(PETSC_HAVE_ADIOS)
    1000: PETSC_EXTERN int64_t Petsc_adios_group;
    1001: #endif

    1003: #if defined(PETSC_HAVE_KOKKOS)
    1004: PETSC_INTERN PetscBool      PetscBeganKokkos;
    1005: PETSC_EXTERN PetscBool      PetscKokkosInitialized;
    1006: PETSC_INTERN PetscErrorCode PetscKokkosIsInitialized_Private(PetscBool*);
    1007: PETSC_INTERN PetscErrorCode PetscKokkosFinalize_Private(void);
    1008: #endif

    1010: #if defined(PETSC_HAVE_CUDA)
    1011: PETSC_EXTERN PetscBool      PetscCUDAInitialized;  /* Is CUDA initialized? One can use this flag to guard CUDA calls. */
    1012: PETSC_EXTERN PetscBool      PetscMPICUDAAwarenessCheck(void);
    1013: #endif

    1015: #if defined(PETSC_HAVE_HIP)
    1016: PETSC_EXTERN PetscBool      PetscHIPInitialized;
    1017: PETSC_EXTERN PetscBool      PetscMPIHIPAwarenessCheck(void);
    1018: #endif

    1020: #if defined(PETSC_HAVE_OPENMP)
    1021: PETSC_EXTERN PetscInt PetscNumOMPThreads;
    1022: #endif

    1024: PETSC_EXTERN PetscBool      PetscCreatedGpuObjects;
    1025: #endif /* PETSCIMPL_H */