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: /* These are used internally by PETSc ASCII IO routines*/
     11: #include <stdarg.h>
     12: PETSC_EXTERN PetscErrorCode PetscVFPrintfDefault(FILE*,const char[],va_list);

     14: #if defined(PETSC_HAVE_CLOSURE)
     15: PETSC_EXTERN PetscErrorCode PetscVFPrintfSetClosure(int (^)(const char*));
     16: #endif

     18: /*
     19:    All major PETSc data structures have a common core; this is defined
     20:    below by PETSCHEADER.

     22:    PetscHeaderCreate() should be used whenever creating a PETSc structure.
     23: */

     25: /*
     26:    PetscOps: structure of core operations that all PETSc objects support.

     28:       getcomm()         - Gets the object's communicator.
     29:       view()            - Is the routine for viewing the entire PETSc object; for
     30:                           example, MatView() is the general matrix viewing routine.
     31:                           This is used by PetscObjectView((PetscObject)obj) to allow
     32:                           viewing any PETSc object.
     33:       destroy()         - Is the routine for destroying the entire PETSc object;
     34:                           for example,MatDestroy() is the general matrix
     35:                           destruction routine.
     36:                           This is used by PetscObjectDestroy((PetscObject*)&obj) to allow
     37:                           destroying any PETSc object.
     38:       compose()         - Associates a PETSc object with another PETSc object with a name
     39:       query()           - Returns a different PETSc object that has been associated
     40:                           with the first object using a name.
     41:       composefunction() - Attaches an a function to a PETSc object with a name.
     42:       queryfunction()   - Requests a registered function that has been attached to a PETSc object.
     43: */

     45: typedef struct {
     46:    PetscErrorCode (*getcomm)(PetscObject,MPI_Comm *);
     47:    PetscErrorCode (*view)(PetscObject,PetscViewer);
     48:    PetscErrorCode (*destroy)(PetscObject*);
     49:    PetscErrorCode (*compose)(PetscObject,const char[],PetscObject);
     50:    PetscErrorCode (*query)(PetscObject,const char[],PetscObject *);
     51:    PetscErrorCode (*composefunction)(PetscObject,const char[],void (*)(void));
     52:    PetscErrorCode (*queryfunction)(PetscObject,const char[],void (**)(void));
     53: } PetscOps;

     55: typedef enum {PETSC_FORTRAN_CALLBACK_CLASS,PETSC_FORTRAN_CALLBACK_SUBTYPE,PETSC_FORTRAN_CALLBACK_MAXTYPE} PetscFortranCallbackType;
     56: typedef int PetscFortranCallbackId;
     57: #define PETSC_SMALLEST_FORTRAN_CALLBACK ((PetscFortranCallbackId)1000)
     58: PETSC_EXTERN PetscErrorCode PetscFortranCallbackRegister(PetscClassId,const char*,PetscFortranCallbackId*);
     59: PETSC_EXTERN PetscErrorCode PetscFortranCallbackGetSizes(PetscClassId,PetscInt*,PetscInt*);

     61: typedef struct {
     62:   void (*func)(void);
     63:   void *ctx;
     64: } PetscFortranCallback;

     66: /*
     67:    All PETSc objects begin with the fields defined in PETSCHEADER.
     68:    The PetscObject is a way of examining these fields regardless of
     69:    the specific object. In C++ this could be a base abstract class
     70:    from which all objects are derived.
     71: */
     72: #define PETSC_MAX_OPTIONS_HANDLER 5
     73: typedef struct _p_PetscObject {
     74:   PetscClassId         classid;
     75:   PetscOps             bops[1];
     76:   MPI_Comm             comm;
     77:   PetscInt             type;
     78:   PetscLogDouble       flops,time,mem,memchildren;
     79:   PetscObjectId        id;
     80:   PetscInt             refct;
     81:   PetscMPIInt          tag;
     82:   PetscFunctionList    qlist;
     83:   PetscObjectList      olist;
     84:   char                 *class_name;    /*  for example, "Vec" */
     85:   char                 *description;
     86:   char                 *mansec;
     87:   char                 *type_name;     /*  this is the subclass, for example VECSEQ which equals "seq" */
     88:   PetscObject          parent;
     89:   PetscObjectId        parentid;
     90:   char*                name;
     91:   char                 *prefix;
     92:   PetscInt             tablevel;
     93:   void                 *cpp;
     94:   PetscObjectState     state;
     95:   PetscInt             int_idmax,        intstar_idmax;
     96:   PetscObjectState     *intcomposedstate,*intstarcomposedstate;
     97:   PetscInt             *intcomposeddata, **intstarcomposeddata;
     98:   PetscInt             real_idmax,        realstar_idmax;
     99:   PetscObjectState     *realcomposedstate,*realstarcomposedstate;
    100:   PetscReal            *realcomposeddata, **realstarcomposeddata;
    101:   PetscInt             scalar_idmax,        scalarstar_idmax;
    102:   PetscObjectState     *scalarcomposedstate,*scalarstarcomposedstate;
    103:   PetscScalar          *scalarcomposeddata, **scalarstarcomposeddata;
    104:   void                 (**fortran_func_pointers)(void);                  /* used by Fortran interface functions to stash user provided Fortran functions */
    105:   PetscInt             num_fortran_func_pointers;                        /* number of Fortran function pointers allocated */
    106:   PetscFortranCallback *fortrancallback[PETSC_FORTRAN_CALLBACK_MAXTYPE];
    107:   PetscInt             num_fortrancallback[PETSC_FORTRAN_CALLBACK_MAXTYPE];
    108:   void                 *python_context;
    109:   PetscErrorCode       (*python_destroy)(void*);

    111:   PetscInt             noptionhandler;
    112:   PetscErrorCode       (*optionhandler[PETSC_MAX_OPTIONS_HANDLER])(PetscOptionItems*,PetscObject,void*);
    113:   PetscErrorCode       (*optiondestroy[PETSC_MAX_OPTIONS_HANDLER])(PetscObject,void*);
    114:   void                 *optionctx[PETSC_MAX_OPTIONS_HANDLER];
    115:   PetscBool            optionsprinted;
    116: #if defined(PETSC_HAVE_SAWS)
    117:   PetscBool            amsmem;          /* if PETSC_TRUE then this object is registered with SAWs and visible to clients */
    118:   PetscBool            amspublishblock; /* if PETSC_TRUE and publishing objects then will block at PetscObjectSAWsBlock() */
    119: #endif
    120:   PetscOptions         options;         /* options database used, NULL means default */
    121:   PetscBool            donotPetscObjectPrintClassNamePrefixType;
    122: } _p_PetscObject;

    124: #define PETSCHEADER(ObjectOps) \
    125:   _p_PetscObject hdr;          \
    126:   ObjectOps      ops[1]

    128: #define  PETSCFREEDHEADER -1

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

    133: /*@C
    134:     PetscHeaderCreate - Creates a PETSc object of a particular class

    136:     Input Parameters:
    137: +   classid - the classid associated with this object (for example VEC_CLASSID)
    138: .   class_name - string name of class; should be static (for example "Vec")
    139: .   descr - string containing short description; should be static (for example "Vector")
    140: .   mansec - string indicating section in manual pages; should be static (for example "Vec")
    141: .   comm - the MPI Communicator
    142: .   destroy - the destroy routine for this object (for example VecDestroy())
    143: -   view - the view routine for this object (for example VecView())

    145:     Output Parameter:
    146: .   h - the newly created object

    148:     Level: developer

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

    152: @*/
    153: #define PetscHeaderCreate(h,classid,class_name,descr,mansec,comm,destroy,view) \
    154:   (PetscNew(&(h)) || \
    155:    PetscHeaderCreate_Private((PetscObject)(h),classid,class_name,descr,mansec,comm,(PetscObjectDestroyFunction)(destroy),(PetscObjectViewFunction)(view)) || \
    156:    PetscLogObjectCreate(h) || \
    157:    PetscLogObjectMemory((PetscObject)(h),sizeof(*(h))))

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

    162: /*@C
    163:     PetscHeaderDestroy - Final step in destroying a PetscObject

    165:     Input Parameters:
    166: .   h - the header created with PetscHeaderCreate()

    168:     Level: developer

    170: .seealso: PetscHeaderCreate()
    171: @*/
    172: #define PetscHeaderDestroy(h) (PetscHeaderDestroy_Private((PetscObject)(*(h))) || PetscFree(*(h)))

    174: PETSC_EXTERN PetscErrorCode PetscHeaderDestroy_Private(PetscObject);
    175: PETSC_EXTERN PetscErrorCode PetscObjectCopyFortranFunctionPointers(PetscObject,PetscObject);
    176: PETSC_EXTERN PetscErrorCode PetscObjectSetFortranCallback(PetscObject,PetscFortranCallbackType,PetscFortranCallbackId*,void(*)(void),void *ctx);
    177: PETSC_EXTERN PetscErrorCode PetscObjectGetFortranCallback(PetscObject,PetscFortranCallbackType,PetscFortranCallbackId,void(**)(void),void **ctx);

    179: PETSC_INTERN PetscErrorCode PetscCitationsInitialize(void);
    180: PETSC_INTERN PetscErrorCode PetscFreeMPIResources(void);
    181: PETSC_INTERN PetscErrorCode PetscOptionsHasHelpIntro_Internal(PetscOptions,PetscBool*);

    185: /*
    186:     Macros to test if a PETSc object is valid and if pointers are valid
    187: */
    188: #if !defined(PETSC_USE_DEBUG)

    201: #else

    203: /*  This check is for subtype methods such as DMDAGetCorners() that do not use the PetscTryMethod() or PetscUseMethod() paradigm */
    205:   do {   \
    206:     PetscErrorCode _7_ierr; \
    207:     PetscBool      _7_same; \
    209:     _7_PetscObjectTypeCompare((PetscObject)(h),t,&_7_same);CHKERRQ(_7_ierr); \
    210:     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); \
    211:   } while (0)

    214:   do {                                                                  \
    215:     if (!(h)) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Null Object: Parameter # %d",arg); \
    217:     if (((PetscObject)(h))->classid != ck) {                            \
    218:       if (((PetscObject)(h))->classid == PETSCFREEDHEADER) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_CORRUPT,"Object already free: Parameter # %d",arg); \
    219:       else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Wrong type of object: Parameter # %d",arg); \
    220:     }                                                                   \
    221:   } while (0)

    224:   do {                                                                  \
    225:     if (!(h)) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Null Object: Parameter # %d",arg); \
    227:     if (((PetscObject)(h))->classid == PETSCFREEDHEADER) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_CORRUPT,"Object already free: Parameter # %d",arg); \
    228:     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); \
    229:   } while (0)

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

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

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

    250:   do {                                                                  \
    251:     if (!(h)) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_BADPTR,"Null Pointer: 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 (!(f)) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Null Function Pointer: Parameter # %d",arg); \
    270:   } while (0)

    272: #endif

    274: #define PetscSorted(n,idx,sorted)           \
    275:   do {                                      \
    276:     PetscInt _i_;                           \
    277:     (sorted) = PETSC_TRUE;                  \
    278:     for (_i_ = 1; _i_ < (n); _i_++)         \
    279:       if ((idx)[_i_] < (idx)[_i_ - 1])      \
    280:         { (sorted) = PETSC_FALSE; break; }  \
    281:   } while (0)

    283: #if !defined(PETSC_USE_DEBUG)

    299: #else

    301: /*
    302:     For example, in the dot product between two vectors,
    303:   both vectors must be either Seq or MPI, not one of each
    304: */
    306:   do {                                                                  \
    307:     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); \
    308:   } while (0)
    309: /*
    310:     Check type_name
    311: */
    313:   do {                                                                  \
    314:     PetscBool      _7_match;                                            \
    315:     PetscErrorCode _7_ierr;                                             \
    316:     _7_PetscObjectTypeCompare(((PetscObject)(a)),(type),&_7_match);CHKERRQ(_7_ierr); \
    317:     if (!_7_match) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Object (%s) is not %s",(char*)(((PetscObject)(a))->type_name),type); \
    318:   } while (0)

    321:   do {                                                                  \
    322:     PetscBool      _7_match;                                            \
    323:     PetscErrorCode _7_ierr;                                             \
    324:     _7_PetscObjectTypeCompareAny(((PetscObject)(a)),&_7_match,(type1),(type2),"");CHKERRQ(_7_ierr); \
    325:     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); \
    326:   } while (0)
    327: /*
    328:    Use this macro to check if the type is set
    329: */
    331:   do {                                                                  \
    332:     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); \
    333:   } while (0)
    334: /*
    335:    Sometimes object must live on same communicator to inter-operate
    336: */
    338:   do {                                                                  \
    339:     PetscErrorCode _7_ierr;                                             \
    340:     PetscMPIInt    _7_flag;                                             \
    341:     _7_MPI_Comm_compare(PetscObjectComm((PetscObject)(a)),PetscObjectComm((PetscObject)(b)),&_7_flag);CHKERRMPI(_7_ierr); \
    342:     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); \
    343:   } while (0)

    346:   do {                                                  \
    349:   } while (0)

    352:   do {                                                                  \
    353:     PetscErrorCode _7_ierr;                                             \
    354:     PetscScalar b0=(b);                                                 \
    355:     PetscReal b1[5],b2[5];                                              \
    356:     if (PetscIsNanScalar(b0)) {b1[4] = 1;} else {b1[4] = 0;};           \
    357:     b1[0] = -PetscRealPart(b0); b1[1] = PetscRealPart(b0); b1[2] = -PetscImaginaryPart(b0); b1[3] = PetscImaginaryPart(b0); \
    358:     _7_MPI_Allreduce(b1,b2,5,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)(a)));CHKERRMPI(_7_ierr); \
    359:     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); \
    360:   } while (0)

    363:   do {                                                                  \
    364:     PetscErrorCode _7_ierr;                                             \
    365:     PetscReal b0=(b),b1[3],b2[3];                                       \
    366:     if (PetscIsNanReal(b0)) {b1[2] = 1;} else {b1[2] = 0;};             \
    367:     b1[0] = -b0; b1[1] = b0;                                            \
    368:     _7_MPI_Allreduce(b1,b2,3,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)(a)));CHKERRMPI(_7_ierr); \
    369:     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); \
    370:   } while (0)

    373:   do {                                                                  \
    374:     PetscErrorCode _7_ierr;                                             \
    375:     PetscInt b0=(b),b1[2],b2[2];                                        \
    376:     b1[0] = -b0; b1[1] = b0;                                            \
    377:     _7_MPIU_Allreduce(b1,b2,2,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)(a)));CHKERRQ(_7_ierr); \
    378:     if (-b2[0] != b2[1]) SETERRQ1(PetscObjectComm((PetscObject)(a)),PETSC_ERR_ARG_WRONG,"Int value must be same on all processes, argument # %d",arg); \
    379:   } while (0)

    382:   do {                                                                  \
    383:     PetscErrorCode _7_ierr;                                             \
    384:     PetscMPIInt b0=(b),b1[2],b2[2];                                     \
    385:     b1[0] = -b0; b1[1] = b0;                                            \
    386:     _7_MPIU_Allreduce(b1,b2,2,MPI_INT,MPI_MAX,PetscObjectComm((PetscObject)(a)));CHKERRQ(_7_ierr); \
    387:     if (-b2[0] != b2[1]) SETERRQ1(PetscObjectComm((PetscObject)(a)),PETSC_ERR_ARG_WRONG,"PetscMPIInt value must be same on all processes, argument # %d",arg); \
    388:   } while (0)

    391:   do {                                                                  \
    392:     PetscErrorCode _7_ierr;                                             \
    393:     PetscMPIInt b0=(PetscMPIInt)(b),b1[2],b2[2];                        \
    394:     b1[0] = -b0; b1[1] = b0;                                            \
    395:     _7_MPIU_Allreduce(b1,b2,2,MPI_INT,MPI_MAX,PetscObjectComm((PetscObject)(a)));CHKERRQ(_7_ierr); \
    396:     if (-b2[0] != b2[1]) SETERRQ1(PetscObjectComm((PetscObject)(a)),PETSC_ERR_ARG_WRONG,"Bool value must be same on all processes, argument # %d",arg); \
    397:   } while (0)

    400:   do {                                                                  \
    401:     PetscErrorCode _7_ierr;                                             \
    402:     PetscMPIInt b0=(PetscMPIInt)(b),b1[2],b2[2];                        \
    403:     b1[0] = -b0; b1[1] = b0;                                            \
    404:     _7_MPIU_Allreduce(b1,b2,2,MPI_INT,MPI_MAX,PetscObjectComm((PetscObject)(a)));CHKERRQ(_7_ierr); \
    405:     if (-b2[0] != b2[1]) SETERRQ1(PetscObjectComm((PetscObject)(a)),PETSC_ERR_ARG_WRONG,"Enum value must be same on all processes, argument # %d",arg); \
    406:   } while (0)

    409:   do {                                                                                            \
    410:     PetscBool _1_flg;                                                                             \
    411:     PetscSorted(n,idx,_1_flg);                                                                    \
    412:     if (!_1_flg) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Input array needs to be sorted"); \
    413:   } while (0)

    415: #endif

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

    421:    Level: developer

    423: .seealso: PetscUseMethod()
    424: */
    425: #define  PetscTryMethod(obj,A,B,C) \
    426:   0; do { PetscErrorCode (*_7_f)B, _7_ierr; \
    427:     _7_PetscObjectQueryFunction((PetscObject)(obj),A,&_7_f);CHKERRQ(_7_ierr); \
    428:     if (_7_f) {_7_(*_7_f)C;CHKERRQ(_7_ierr);} \
    429:   } while (0)

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

    435:    Level: developer

    437: .seealso: PetscTryMethod()
    438: */
    439: #define  PetscUseMethod(obj,A,B,C) \
    440:   0; do { PetscErrorCode (*_7_f)B, _7_ierr; \
    441:     _7_PetscObjectQueryFunction((PetscObject)(obj),A,&_7_f);CHKERRQ(_7_ierr); \
    442:     if (_7_f) {_7_(*_7_f)C;CHKERRQ(_7_ierr);} \
    443:     else SETERRQ1(PetscObjectComm((PetscObject)(obj)),PETSC_ERR_SUP,"Cannot locate function %s in object",A); \
    444:   } while (0)

    446: /*MC
    447:    PetscObjectStateIncrease - Increases the state of any PetscObject

    449:    Synopsis:
    450:    #include "petsc/private/petscimpl.h"
    451:    PetscErrorCode PetscObjectStateIncrease(PetscObject obj)

    453:    Logically Collective

    455:    Input Parameter:
    456: .  obj - any PETSc object, for example a Vec, Mat or KSP. This must be
    457:          cast with a (PetscObject), for example,
    458:          PetscObjectStateIncrease((PetscObject)mat);

    460:    Notes:
    461:     object state is an integer which gets increased every time
    462:    the object is changed internally. By saving and later querying the object state
    463:    one can determine whether information about the object is still current.
    464:    Currently, state is maintained for Vec and Mat objects.

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

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

    473:    Level: developer

    475:    seealso: PetscObjectStateGet()

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

    480: PETSC_EXTERN PetscErrorCode PetscObjectStateGet(PetscObject,PetscObjectState*);
    481: PETSC_EXTERN PetscErrorCode PetscObjectStateSet(PetscObject,PetscObjectState);
    482: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataRegister(PetscInt*);
    483: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseInt(PetscObject);
    484: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseIntstar(PetscObject);
    485: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseReal(PetscObject);
    486: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseRealstar(PetscObject);
    487: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseScalar(PetscObject);
    488: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseScalarstar(PetscObject);
    489: PETSC_EXTERN PetscInt       PetscObjectComposedDataMax;
    490: /*MC
    491:    PetscObjectComposedDataSetInt - attach integer data to a PetscObject

    493:    Synopsis:
    494:    #include "petsc/private/petscimpl.h"
    495:    PetscErrorCode PetscObjectComposedDataSetInt(PetscObject obj,int id,int data)

    497:    Not collective

    499:    Input parameters:
    500: +  obj - the object to which data is to be attached
    501: .  id - the identifier for the data
    502: -  data - the data to  be attached

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

    507:    Level: developer
    508: M*/
    509: #define PetscObjectComposedDataSetInt(obj,id,data)                                      \
    510:   ((((obj)->int_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseInt(obj)) ||  \
    511:    ((obj)->intcomposeddata[id] = data,(obj)->intcomposedstate[id] = (obj)->state, 0))

    513: /*MC
    514:    PetscObjectComposedDataGetInt - retrieve integer data attached to an object

    516:    Synopsis:
    517:    #include "petsc/private/petscimpl.h"
    518:    PetscErrorCode PetscObjectComposedDataGetInt(PetscObject obj,int id,int data,PetscBool  flag)

    520:    Not collective

    522:    Input parameters:
    523: +  obj - the object from which data is to be retrieved
    524: -  id - the identifier for the data

    526:    Output parameters:
    527: +  data - the data to be retrieved
    528: -  flag - PETSC_TRUE if the data item exists and is valid, PETSC_FALSE otherwise

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

    532:    Level: developer
    533: M*/
    534: #define PetscObjectComposedDataGetInt(obj,id,data,flag)                            \
    535:   ((((obj)->intcomposedstate && ((obj)->intcomposedstate[id] == (obj)->state)) ?   \
    536:    (data = (obj)->intcomposeddata[id],flag = PETSC_TRUE) : (flag = PETSC_FALSE)),0)

    538: /*MC
    539:    PetscObjectComposedDataSetIntstar - attach integer array data to a PetscObject

    541:    Synopsis:
    542:    #include "petsc/private/petscimpl.h"
    543:    PetscErrorCode PetscObjectComposedDataSetIntstar(PetscObject obj,int id,int *data)

    545:    Not collective

    547:    Input parameters:
    548: +  obj - the object to which data is to be attached
    549: .  id - the identifier for the data
    550: -  data - the data to  be attached

    552:    Notes
    553:    The data identifier can best be determined through a call to
    554:    PetscObjectComposedDataRegister()

    556:    Level: developer
    557: M*/
    558: #define PetscObjectComposedDataSetIntstar(obj,id,data)                                          \
    559:   ((((obj)->intstar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseIntstar(obj)) ||  \
    560:    ((obj)->intstarcomposeddata[id] = data,(obj)->intstarcomposedstate[id] = (obj)->state, 0))

    562: /*MC
    563:    PetscObjectComposedDataGetIntstar - retrieve integer array data
    564:    attached to an object

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

    570:    Not collective

    572:    Input parameters:
    573: +  obj - the object from which data is to be retrieved
    574: -  id - the identifier for the data

    576:    Output parameters:
    577: +  data - the data to be retrieved
    578: -  flag - PETSC_TRUE if the data item exists and is valid, PETSC_FALSE otherwise

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

    582:    Level: developer
    583: M*/
    584: #define PetscObjectComposedDataGetIntstar(obj,id,data,flag)                               \
    585:   ((((obj)->intstarcomposedstate && ((obj)->intstarcomposedstate[id] == (obj)->state)) ?  \
    586:    (data = (obj)->intstarcomposeddata[id],flag = PETSC_TRUE) : (flag = PETSC_FALSE)),0)

    588: /*MC
    589:    PetscObjectComposedDataSetReal - attach real data to a PetscObject

    591:    Synopsis:
    592:    #include "petsc/private/petscimpl.h"
    593:    PetscErrorCode PetscObjectComposedDataSetReal(PetscObject obj,int id,PetscReal data)

    595:    Not collective

    597:    Input parameters:
    598: +  obj - the object to which data is to be attached
    599: .  id - the identifier for the data
    600: -  data - the data to  be attached

    602:    Notes
    603:    The data identifier can best be determined through a call to
    604:    PetscObjectComposedDataRegister()

    606:    Level: developer
    607: M*/
    608: #define PetscObjectComposedDataSetReal(obj,id,data)                                       \
    609:   ((((obj)->real_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseReal(obj)) ||  \
    610:    ((obj)->realcomposeddata[id] = data,(obj)->realcomposedstate[id] = (obj)->state, 0))

    612: /*MC
    613:    PetscObjectComposedDataGetReal - retrieve real data attached to an object

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

    619:    Not collective

    621:    Input parameters:
    622: +  obj - the object from which data is to be retrieved
    623: -  id - the identifier for the data

    625:    Output parameters:
    626: +  data - the data to be retrieved
    627: -  flag - PETSC_TRUE if the data item exists and is valid, PETSC_FALSE otherwise

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

    631:    Level: developer
    632: M*/
    633: #define PetscObjectComposedDataGetReal(obj,id,data,flag)                            \
    634:   ((((obj)->realcomposedstate && ((obj)->realcomposedstate[id] == (obj)->state)) ?  \
    635:    (data = (obj)->realcomposeddata[id],flag = PETSC_TRUE) : (flag = PETSC_FALSE)),0)

    637: /*MC
    638:    PetscObjectComposedDataSetRealstar - attach real array data to a PetscObject

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

    644:    Not collective

    646:    Input parameters:
    647: +  obj - the object to which data is to be attached
    648: .  id - the identifier for the data
    649: -  data - the data to  be attached

    651:    Notes
    652:    The data identifier can best be determined through a call to
    653:    PetscObjectComposedDataRegister()

    655:    Level: developer
    656: M*/
    657: #define PetscObjectComposedDataSetRealstar(obj,id,data)                                           \
    658:   ((((obj)->realstar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseRealstar(obj)) ||  \
    659:    ((obj)->realstarcomposeddata[id] = data, (obj)->realstarcomposedstate[id] = (obj)->state, 0))

    661: /*MC
    662:    PetscObjectComposedDataGetRealstar - retrieve real array data
    663:    attached to an object

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

    669:    Not collective

    671:    Input parameters:
    672: +  obj - the object from which data is to be retrieved
    673: -  id - the identifier for the data

    675:    Output parameters:
    676: +  data - the data to be retrieved
    677: -  flag - PETSC_TRUE if the data item exists and is valid, PETSC_FALSE otherwise

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

    681:    Level: developer
    682: M*/
    683: #define PetscObjectComposedDataGetRealstar(obj,id,data,flag)                                \
    684:   ((((obj)->realstarcomposedstate && ((obj)->realstarcomposedstate[id] == (obj)->state)) ?  \
    685:    (data = (obj)->realstarcomposeddata[id],flag = PETSC_TRUE) : (flag = PETSC_FALSE)),0)

    687: /*MC
    688:    PetscObjectComposedDataSetScalar - attach scalar data to a PetscObject

    690:    Synopsis:
    691:    #include "petsc/private/petscimpl.h"
    692:    PetscErrorCode PetscObjectComposedDataSetScalar(PetscObject obj,int id,PetscScalar data)

    694:    Not collective

    696:    Input parameters:
    697: +  obj - the object to which data is to be attached
    698: .  id - the identifier for the data
    699: -  data - the data to  be attached

    701:    Notes
    702:    The data identifier can best be determined through a call to
    703:    PetscObjectComposedDataRegister()

    705:    Level: developer
    706: M*/
    707: #if defined(PETSC_USE_COMPLEX)
    708: #define PetscObjectComposedDataSetScalar(obj,id,data)                                        \
    709:   ((((obj)->scalar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseScalar(obj)) || \
    710:    ((obj)->scalarcomposeddata[id] = data,(obj)->scalarcomposedstate[id] = (obj)->state, 0))
    711: #else
    712: #define PetscObjectComposedDataSetScalar(obj,id,data) \
    713:         PetscObjectComposedDataSetReal(obj,id,data)
    714: #endif
    715: /*MC
    716:    PetscObjectComposedDataGetScalar - retrieve scalar data attached to an object

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

    722:    Not collective

    724:    Input parameters:
    725: +  obj - the object from which data is to be retrieved
    726: -  id - the identifier for the data

    728:    Output parameters:
    729: +  data - the data to be retrieved
    730: -  flag - PETSC_TRUE if the data item exists and is valid, PETSC_FALSE otherwise

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

    734:    Level: developer
    735: M*/
    736: #if defined(PETSC_USE_COMPLEX)
    737: #define PetscObjectComposedDataGetScalar(obj,id,data,flag)                              \
    738:   ((((obj)->scalarcomposedstate && ((obj)->scalarcomposedstate[id] == (obj)->state)) ? \
    739:    (data = (obj)->scalarcomposeddata[id],flag = PETSC_TRUE) : (flag = PETSC_FALSE)),0)
    740: #else
    741: #define PetscObjectComposedDataGetScalar(obj,id,data,flag)                             \
    742:         PetscObjectComposedDataGetReal(obj,id,data,flag)
    743: #endif

    745: /*MC
    746:    PetscObjectComposedDataSetScalarstar - attach scalar array data to a PetscObject

    748:    Synopsis:
    749:    #include "petsc/private/petscimpl.h"
    750:    PetscErrorCode PetscObjectComposedDataSetScalarstar(PetscObject obj,int id,PetscScalar *data)

    752:    Not collective

    754:    Input parameters:
    755: +  obj - the object to which data is to be attached
    756: .  id - the identifier for the data
    757: -  data - the data to  be attached

    759:    Notes
    760:    The data identifier can best be determined through a call to
    761:    PetscObjectComposedDataRegister()

    763:    Level: developer
    764: M*/
    765: #if defined(PETSC_USE_COMPLEX)
    766: #define PetscObjectComposedDataSetScalarstar(obj,id,data)                                             \
    767:   ((((obj)->scalarstar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseScalarstar(obj)) ||  \
    768:    ((obj)->scalarstarcomposeddata[id] = data,(obj)->scalarstarcomposedstate[id] = (obj)->state, 0))
    769: #else
    770: #define PetscObjectComposedDataSetScalarstar(obj,id,data) \
    771:         PetscObjectComposedDataSetRealstar(obj,id,data)
    772: #endif
    773: /*MC
    774:    PetscObjectComposedDataGetScalarstar - retrieve scalar array data
    775:    attached to an object

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

    781:    Not collective

    783:    Input parameters:
    784: +  obj - the object from which data is to be retrieved
    785: -  id - the identifier for the data

    787:    Output parameters:
    788: +  data - the data to be retrieved
    789: -  flag - PETSC_TRUE if the data item exists and is valid, PETSC_FALSE otherwise

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

    793:    Level: developer
    794: M*/
    795: #if defined(PETSC_USE_COMPLEX)
    796: #define PetscObjectComposedDataGetScalarstar(obj,id,data,flag)                                 \
    797:   ((((obj)->scalarstarcomposedstate && ((obj)->scalarstarcomposedstate[id] == (obj)->state)) ? \
    798:        (data = (obj)->scalarstarcomposeddata[id],flag = PETSC_TRUE) : (flag = PETSC_FALSE)),0)
    799: #else
    800: #define PetscObjectComposedDataGetScalarstar(obj,id,data,flag)         \
    801:         PetscObjectComposedDataGetRealstar(obj,id,data,flag)
    802: #endif

    804: PETSC_EXTERN PetscMPIInt Petsc_Counter_keyval;
    805: PETSC_EXTERN PetscMPIInt Petsc_InnerComm_keyval;
    806: PETSC_EXTERN PetscMPIInt Petsc_OuterComm_keyval;
    807: PETSC_EXTERN PetscMPIInt Petsc_Seq_keyval;
    808: PETSC_EXTERN PetscMPIInt Petsc_ShmComm_keyval;

    810: /*
    811:   PETSc communicators have this attribute, see
    812:   PetscCommDuplicate(), PetscCommDestroy(), PetscCommGetNewTag(), PetscObjectGetName()
    813: */
    814: typedef struct {
    815:   PetscMPIInt tag;              /* next free tag value */
    816:   PetscInt    refcount;         /* number of references, communicator can be freed when this reaches 0 */
    817:   PetscInt    namecount;        /* used to generate the next name, as in Vec_0, Mat_1, ... */
    818:   PetscMPIInt *iflags;          /* length of comm size, shared by all calls to PetscCommBuildTwoSided_Allreduce/RedScatter on this comm */
    819: } PetscCommCounter;

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

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

    825: typedef struct {
    826:   MPI_Comm    comm;
    827:   MPI_Request request;
    828:   PetscBool   async;
    829:   PetscScalar *lvalues;     /* this are the reduced values before call to MPI_Allreduce() */
    830:   PetscScalar *gvalues;     /* values after call to MPI_Allreduce() */
    831:   void        **invecs;     /* for debugging only, vector/memory used with each op */
    832:   PetscInt    *reducetype;  /* is particular value to be summed or maxed? */
    833:   SRState     state;        /* are we calling xxxBegin() or xxxEnd()? */
    834:   PetscInt    maxops;       /* total amount of space we have for requests */
    835:   PetscInt    numopsbegin;  /* number of requests that have been queued in */
    836:   PetscInt    numopsend;    /* number of requests that have been gotten by user */
    837: } PetscSplitReduction;

    839: PETSC_EXTERN PetscErrorCode PetscSplitReductionGet(MPI_Comm,PetscSplitReduction**);
    840: PETSC_EXTERN PetscErrorCode PetscSplitReductionEnd(PetscSplitReduction*);
    841: PETSC_EXTERN PetscErrorCode PetscSplitReductionExtend(PetscSplitReduction*);

    843: #if !defined(PETSC_SKIP_SPINLOCK)
    844: #if defined(PETSC_HAVE_THREADSAFETY)
    845: #  if defined(PETSC_HAVE_CONCURRENCYKIT)
    846: #if defined(__cplusplus)
    847: /*  CK does not have extern "C" protection in their include files */
    848: extern "C" {
    849: #endif
    850: #include <ck_spinlock.h>
    851: #if defined(__cplusplus)
    852: }
    853: #endif
    854: typedef ck_spinlock_t PetscSpinlock;
    855: PETSC_STATIC_INLINE PetscErrorCode PetscSpinlockCreate(PetscSpinlock *ck_spinlock)
    856: {
    857:   ck_spinlock_init(ck_spinlock);
    858:   return 0;
    859: }
    860: PETSC_STATIC_INLINE PetscErrorCode PetscSpinlockLock(PetscSpinlock *ck_spinlock)
    861: {
    862:   ck_spinlock_lock(ck_spinlock);
    863:   return 0;
    864: }
    865: PETSC_STATIC_INLINE PetscErrorCode PetscSpinlockUnlock(PetscSpinlock *ck_spinlock)
    866: {
    867:   ck_spinlock_unlock(ck_spinlock);
    868:   return 0;
    869: }
    870: PETSC_STATIC_INLINE PetscErrorCode PetscSpinlockDestroy(PetscSpinlock *ck_spinlock)
    871: {
    872:   return 0;
    873: }
    874: #  elif defined(PETSC_HAVE_OPENMP)

    876: #include <omp.h>
    877: typedef omp_lock_t PetscSpinlock;
    878: PETSC_STATIC_INLINE PetscErrorCode PetscSpinlockCreate(PetscSpinlock *omp_lock)
    879: {
    880:   omp_init_lock(omp_lock);
    881:   return 0;
    882: }
    883: PETSC_STATIC_INLINE PetscErrorCode PetscSpinlockLock(PetscSpinlock *omp_lock)
    884: {
    885:   omp_set_lock(omp_lock);
    886:   return 0;
    887: }
    888: PETSC_STATIC_INLINE PetscErrorCode PetscSpinlockUnlock(PetscSpinlock *omp_lock)
    889: {
    890:   omp_unset_lock(omp_lock);
    891:   return 0;
    892: }
    893: PETSC_STATIC_INLINE PetscErrorCode PetscSpinlockDestroy(PetscSpinlock *omp_lock)
    894: {
    895:   omp_destroy_lock(omp_lock);
    896:   return 0;
    897: }
    898: #else
    899: Thread safety requires either --with-openmp or --download-concurrencykit
    900: #endif

    902: #else
    903: typedef int PetscSpinlock;
    904: #define PetscSpinlockCreate(a)  0
    905: #define PetscSpinlockLock(a)    0
    906: #define PetscSpinlockUnlock(a)  0
    907: #define PetscSpinlockDestroy(a) 0
    908: #endif

    910: #if defined(PETSC_HAVE_THREADSAFETY)
    911: PETSC_INTERN PetscSpinlock PetscViewerASCIISpinLockOpen;
    912: PETSC_INTERN PetscSpinlock PetscViewerASCIISpinLockStdout;
    913: PETSC_INTERN PetscSpinlock PetscViewerASCIISpinLockStderr;
    914: PETSC_INTERN PetscSpinlock PetscCommSpinLock;
    915: #endif
    916: #endif

    918: PETSC_EXTERN PetscLogEvent PETSC_Barrier;
    919: PETSC_EXTERN PetscLogEvent PETSC_BuildTwoSided;
    920: PETSC_EXTERN PetscLogEvent PETSC_BuildTwoSidedF;
    921: PETSC_EXTERN PetscBool     use_gpu_aware_mpi;

    923: #if defined(PETSC_HAVE_ADIOS)
    924: PETSC_EXTERN int64_t Petsc_adios_group;
    925: #endif

    927: #if defined(PETSC_HAVE_KOKKOS)
    928: PETSC_INTERN PetscBool      PetscBeganKokkos;
    929: PETSC_EXTERN PetscBool      PetscKokkosInitialized;
    930: PETSC_INTERN PetscErrorCode PetscKokkosIsInitialized_Private(PetscBool*);
    931: PETSC_INTERN PetscErrorCode PetscKokkosFinalize_Private(void);
    932: #endif

    934: #if defined(PETSC_HAVE_CUDA)
    935: PETSC_EXTERN PetscBool      PetscCUDAInitialized;  /* Is CUDA initialized? One can use this flag to guard CUDA calls. */
    936: PETSC_EXTERN PetscBool      PetscMPICUDAAwarenessCheck(void);
    937: #endif

    939: #if defined(PETSC_HAVE_HIP)
    940: PETSC_EXTERN PetscBool      PetscHIPInitialized;
    941: PETSC_EXTERN PetscBool      PetscMPIHIPAwarenessCheck(void);
    942: #endif

    944: PETSC_EXTERN PetscBool      PetscCreatedGpuObjects;
    945: #endif /* PETSCIMPL_H */