Actual source code: petscimpl.h

petsc-master 2020-04-04
Report Typos and Errors

  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


 19: #if defined(PETSC_HAVE_CUDA)
 20: #include <cuda.h>
 21: #include <cublas_v2.h>
 22: #endif

 24: /*
 25:    All major PETSc data structures have a common core; this is defined
 26:    below by PETSCHEADER.

 28:    PetscHeaderCreate() should be used whenever creating a PETSc structure.
 29: */

 31: /*
 32:    PetscOps: structure of core operations that all PETSc objects support.

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

 51: typedef struct {
 52:    PetscErrorCode (*getcomm)(PetscObject,MPI_Comm *);
 53:    PetscErrorCode (*view)(PetscObject,PetscViewer);
 54:    PetscErrorCode (*destroy)(PetscObject*);
 55:    PetscErrorCode (*compose)(PetscObject,const char[],PetscObject);
 56:    PetscErrorCode (*query)(PetscObject,const char[],PetscObject *);
 57:    PetscErrorCode (*composefunction)(PetscObject,const char[],void (*)(void));
 58:    PetscErrorCode (*queryfunction)(PetscObject,const char[],void (**)(void));
 59: } PetscOps;

 61: typedef enum {PETSC_FORTRAN_CALLBACK_CLASS,PETSC_FORTRAN_CALLBACK_SUBTYPE,PETSC_FORTRAN_CALLBACK_MAXTYPE} PetscFortranCallbackType;
 62: typedef int PetscFortranCallbackId;
 63: #define PETSC_SMALLEST_FORTRAN_CALLBACK ((PetscFortranCallbackId)1000)
 64: PETSC_EXTERN PetscErrorCode PetscFortranCallbackRegister(PetscClassId,const char*,PetscFortranCallbackId*);
 65: PETSC_EXTERN PetscErrorCode PetscFortranCallbackGetSizes(PetscClassId,PetscInt*,PetscInt*);

 67: typedef struct {
 68:   void (*func)(void);
 69:   void *ctx;
 70: } PetscFortranCallback;

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

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

130: #define PETSCHEADER(ObjectOps) \
131:   _p_PetscObject hdr;          \
132:   ObjectOps      ops[1]

134: #define  PETSCFREEDHEADER -1

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

139: /*@C
140:     PetscHeaderCreate - Creates a PETSc object of a particular class

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

151:     Output Parameter:
152: .   h - the newly created object

154:     Level: developer

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

158: @*/
159: #define PetscHeaderCreate(h,classid,class_name,descr,mansec,comm,destroy,view) \
160:   (PetscNew(&(h)) || \
161:    PetscHeaderCreate_Private((PetscObject)(h),classid,class_name,descr,mansec,comm,(PetscObjectDestroyFunction)(destroy),(PetscObjectViewFunction)(view)) || \
162:    PetscLogObjectCreate(h) || \
163:    PetscLogObjectMemory((PetscObject)(h),sizeof(*(h))))

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

168: /*@C
169:     PetscHeaderDestroy - Final step in destroying a PetscObject

171:     Input Parameters:
172: .   h - the header created with PetscHeaderCreate()

174:     Level: developer

176: .seealso: PetscHeaderCreate()
177: @*/
178: #define PetscHeaderDestroy(h) (PetscHeaderDestroy_Private((PetscObject)(*(h))) || PetscFree(*(h)))

180: PETSC_EXTERN PetscErrorCode PetscHeaderDestroy_Private(PetscObject);
181: PETSC_EXTERN PetscErrorCode PetscObjectCopyFortranFunctionPointers(PetscObject,PetscObject);
182: PETSC_EXTERN PetscErrorCode PetscObjectSetFortranCallback(PetscObject,PetscFortranCallbackType,PetscFortranCallbackId*,void(*)(void),void *ctx);
183: PETSC_EXTERN PetscErrorCode PetscObjectGetFortranCallback(PetscObject,PetscFortranCallbackType,PetscFortranCallbackId,void(**)(void),void **ctx);

185: PETSC_INTERN PetscErrorCode PetscCitationsInitialize(void);
186: PETSC_INTERN PetscErrorCode PetscFreeMPIResources(void);



191: #if defined(PETSC_HAVE_CUDA)
193: #endif
194: /*
195:     Macros to test if a PETSc object is valid and if pointers are valid
196: */
197: #if !defined(PETSC_USE_DEBUG)


210: #else

212: /*  This check is for subtype methods such as DMDAGetCorners() that do not use the PetscTryMethod() or PetscUseMethod() paradigm */
214:   do {   \
215:     PetscErrorCode _7_ierr; \
216:     PetscBool      _7_same; \
218:     _7_PetscObjectTypeCompare((PetscObject)(h),t,&_7_same);CHKERRQ(_7_ierr); \
219:     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); \
220:   } while (0)

223:   do {                                                                  \
224:     if (!(h)) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Null Object: Parameter # %d",arg); \
226:     if (((PetscObject)(h))->classid != ck) {                            \
227:       if (((PetscObject)(h))->classid == PETSCFREEDHEADER) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_CORRUPT,"Object already free: Parameter # %d",arg); \
228:       else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Wrong type of object: Parameter # %d",arg); \
229:     }                                                                   \
230:   } while (0)

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

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

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

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

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

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

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

277:   do {                                                                  \
278:     if (!(f)) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Null Function Pointer: Parameter # %d",arg); \
279:   } while (0)

281: #endif

283: #define PetscSorted(n,idx,sorted)           \
284:   do {                                      \
285:     PetscInt _i_;                           \
286:     (sorted) = PETSC_TRUE;                  \
287:     for (_i_ = 1; _i_ < (n); _i_++)         \
288:       if ((idx)[_i_] < (idx)[_i_ - 1])      \
289:         { (sorted) = PETSC_FALSE; break; }  \
290:   } while(0)

292: #if !defined(PETSC_USE_DEBUG)


308: #else

310: /*
311:     For example, in the dot product between two vectors,
312:   both vectors must be either Seq or MPI, not one of each
313: */
315:   do {                                                                  \
316:     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); \
317:   } while (0)
318: /*
319:     Check type_name
320: */
322:   do {                                                                  \
323:     PetscBool      _7_match;                                            \
324:     PetscErrorCode _7_ierr;                                             \
325:     _7_PetscObjectTypeCompare(((PetscObject)(a)),(type),&_7_match);CHKERRQ(_7_ierr); \
326:     if (!_7_match) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Object (%s) is not %s",(char*)(((PetscObject)(a))->type_name),type); \
327:   } while (0)

330:   do {                                                                  \
331:     PetscBool      _7_match;                                            \
332:     PetscErrorCode _7_ierr;                                             \
333:     _7_PetscObjectTypeCompareAny(((PetscObject)(a)),&_7_match,(type1),(type2),"");CHKERRQ(_7_ierr); \
334:     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); \
335:   } while (0)
336: /*
337:    Use this macro to check if the type is set
338: */
340:   do {                                                                  \
341:     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); \
342:   } while (0)
343: /*
344:    Sometimes object must live on same communicator to inter-operate
345: */
347:   do {                                                                  \
348:     PetscErrorCode _7_ierr;                                             \
349:     PetscMPIInt    _7_flag;                                             \
350:     _7_MPI_Comm_compare(PetscObjectComm((PetscObject)(a)),PetscObjectComm((PetscObject)(b)),&_7_flag);CHKERRQ(_7_ierr); \
351:     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); \
352:   } while (0)

355:   do {                                                  \
358:   } while (0)

361:   do {                                                                  \
362:     PetscErrorCode _7_ierr;                                             \
363:     PetscScalar b0=(b);                                                 \
364:     PetscReal b1[5],b2[5];                                              \
365:     if (PetscIsNanScalar(b0)) {b1[4] = 1;} else {b1[4] = 0;};           \
366:     b1[0] = -PetscRealPart(b0); b1[1] = PetscRealPart(b0); b1[2] = -PetscImaginaryPart(b0); b1[3] = PetscImaginaryPart(b0); \
367:     _7_MPI_Allreduce(b1,b2,5,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)(a)));CHKERRQ(_7_ierr); \
368:     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); \
369:   } while (0)

372:   do {                                                                  \
373:     PetscErrorCode _7_ierr;                                             \
374:     PetscReal b0=(b),b1[3],b2[3];                                       \
375:     if (PetscIsNanReal(b0)) {b1[2] = 1;} else {b1[2] = 0;};             \
376:     b1[0] = -b0; b1[1] = b0;                                            \
377:     _7_MPI_Allreduce(b1,b2,3,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)(a)));CHKERRQ(_7_ierr); \
378:     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); \
379:   } while (0)

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

391:   do {                                                                  \
392:     PetscErrorCode _7_ierr;                                             \
393:     PetscMPIInt b0=(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,"PetscMPIInt 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,"Bool value must be same on all processes, argument # %d",arg); \
406:   } while (0)

409:   do {                                                                  \
410:     PetscErrorCode _7_ierr;                                             \
411:     PetscMPIInt b0=(PetscMPIInt)(b),b1[2],b2[2];                        \
412:     b1[0] = -b0; b1[1] = b0;                                            \
413:     _7_MPIU_Allreduce(b1,b2,2,MPI_INT,MPI_MAX,PetscObjectComm((PetscObject)(a)));CHKERRQ(_7_ierr); \
414:     if (-b2[0] != b2[1]) SETERRQ1(PetscObjectComm((PetscObject)(a)),PETSC_ERR_ARG_WRONG,"Enum value must be same on all processes, argument # %d",arg); \
415:   } while (0)

418:   do {                                                                                            \
419:     PetscBool _1_flg;                                                                             \
420:     PetscSorted(n,idx,_1_flg);                                                                    \
421:     if (!_1_flg) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Input array needs to be sorted"); \
422:   } while (0)

424: #endif

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

430:    Level: developer

432: .seealso: PetscUseMethod()
433: */
434: #define  PetscTryMethod(obj,A,B,C) \
435:   0; do { PetscErrorCode (*_7_f)B, _7_ierr; \
436:     _7_PetscObjectQueryFunction((PetscObject)(obj),A,&_7_f);CHKERRQ(_7_ierr); \
437:     if (_7_f) {_7_(*_7_f)C;CHKERRQ(_7_ierr);} \
438:   } while(0)

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

444:    Level: developer

446: .seealso: PetscTryMethod()
447: */
448: #define  PetscUseMethod(obj,A,B,C) \
449:   0; do { PetscErrorCode (*_7_f)B, _7_ierr; \
450:     _7_PetscObjectQueryFunction((PetscObject)(obj),A,&_7_f);CHKERRQ(_7_ierr); \
451:     if (_7_f) {_7_(*_7_f)C;CHKERRQ(_7_ierr);} \
452:     else SETERRQ1(PetscObjectComm((PetscObject)(obj)),PETSC_ERR_SUP,"Cannot locate function %s in object",A); \
453:   } while(0)

455: /*MC
456:    PetscObjectStateIncrease - Increases the state of any PetscObject

458:    Synopsis:
459:    #include "petsc/private/petscimpl.h"
460:    PetscErrorCode PetscObjectStateIncrease(PetscObject obj)

462:    Logically Collective

464:    Input Parameter:
465: .  obj - any PETSc object, for example a Vec, Mat or KSP. This must be
466:          cast with a (PetscObject), for example,
467:          PetscObjectStateIncrease((PetscObject)mat);

469:    Notes:
470:     object state is an integer which gets increased every time
471:    the object is changed internally. By saving and later querying the object state
472:    one can determine whether information about the object is still current.
473:    Currently, state is maintained for Vec and Mat objects.

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

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

482:    Level: developer

484:    seealso: PetscObjectStateGet()

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

489: PETSC_EXTERN PetscErrorCode PetscObjectStateGet(PetscObject,PetscObjectState*);
490: PETSC_EXTERN PetscErrorCode PetscObjectStateSet(PetscObject,PetscObjectState);
491: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataRegister(PetscInt*);
492: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseInt(PetscObject);
493: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseIntstar(PetscObject);
494: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseReal(PetscObject);
495: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseRealstar(PetscObject);
496: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseScalar(PetscObject);
497: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseScalarstar(PetscObject);
498: PETSC_EXTERN PetscInt       PetscObjectComposedDataMax;
499: /*MC
500:    PetscObjectComposedDataSetInt - attach integer data to a PetscObject

502:    Synopsis:
503:    #include "petsc/private/petscimpl.h"
504:    PetscErrorCode PetscObjectComposedDataSetInt(PetscObject obj,int id,int data)

506:    Not collective

508:    Input parameters:
509: +  obj - the object to which data is to be attached
510: .  id - the identifier for the data
511: -  data - the data to  be attached

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

516:    Level: developer
517: M*/
518: #define PetscObjectComposedDataSetInt(obj,id,data)                                      \
519:   ((((obj)->int_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseInt(obj)) ||  \
520:    ((obj)->intcomposeddata[id] = data,(obj)->intcomposedstate[id] = (obj)->state, 0))

522: /*MC
523:    PetscObjectComposedDataGetInt - retrieve integer data attached to an object

525:    Synopsis:
526:    #include "petsc/private/petscimpl.h"
527:    PetscErrorCode PetscObjectComposedDataGetInt(PetscObject obj,int id,int data,PetscBool  flag)

529:    Not collective

531:    Input parameters:
532: +  obj - the object from which data is to be retrieved
533: -  id - the identifier for the data

535:    Output parameters:
536: +  data - the data to be retrieved
537: -  flag - PETSC_TRUE if the data item exists and is valid, PETSC_FALSE otherwise

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

541:    Level: developer
542: M*/
543: #define PetscObjectComposedDataGetInt(obj,id,data,flag)                            \
544:   ((((obj)->intcomposedstate && ((obj)->intcomposedstate[id] == (obj)->state)) ?   \
545:    (data = (obj)->intcomposeddata[id],flag = PETSC_TRUE) : (flag = PETSC_FALSE)),0)

547: /*MC
548:    PetscObjectComposedDataSetIntstar - attach integer array data to a PetscObject

550:    Synopsis:
551:    #include "petsc/private/petscimpl.h"
552:    PetscErrorCode PetscObjectComposedDataSetIntstar(PetscObject obj,int id,int *data)

554:    Not collective

556:    Input parameters:
557: +  obj - the object to which data is to be attached
558: .  id - the identifier for the data
559: -  data - the data to  be attached

561:    Notes
562:    The data identifier can best be determined through a call to
563:    PetscObjectComposedDataRegister()

565:    Level: developer
566: M*/
567: #define PetscObjectComposedDataSetIntstar(obj,id,data)                                          \
568:   ((((obj)->intstar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseIntstar(obj)) ||  \
569:    ((obj)->intstarcomposeddata[id] = data,(obj)->intstarcomposedstate[id] = (obj)->state, 0))

571: /*MC
572:    PetscObjectComposedDataGetIntstar - retrieve integer array data
573:    attached to an object

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

579:    Not collective

581:    Input parameters:
582: +  obj - the object from which data is to be retrieved
583: -  id - the identifier for the data

585:    Output parameters:
586: +  data - the data to be retrieved
587: -  flag - PETSC_TRUE if the data item exists and is valid, PETSC_FALSE otherwise

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

591:    Level: developer
592: M*/
593: #define PetscObjectComposedDataGetIntstar(obj,id,data,flag)                               \
594:   ((((obj)->intstarcomposedstate && ((obj)->intstarcomposedstate[id] == (obj)->state)) ?  \
595:    (data = (obj)->intstarcomposeddata[id],flag = PETSC_TRUE) : (flag = PETSC_FALSE)),0)

597: /*MC
598:    PetscObjectComposedDataSetReal - attach real data to a PetscObject

600:    Synopsis:
601:    #include "petsc/private/petscimpl.h"
602:    PetscErrorCode PetscObjectComposedDataSetReal(PetscObject obj,int id,PetscReal data)

604:    Not collective

606:    Input parameters:
607: +  obj - the object to which data is to be attached
608: .  id - the identifier for the data
609: -  data - the data to  be attached

611:    Notes
612:    The data identifier can best be determined through a call to
613:    PetscObjectComposedDataRegister()

615:    Level: developer
616: M*/
617: #define PetscObjectComposedDataSetReal(obj,id,data)                                       \
618:   ((((obj)->real_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseReal(obj)) ||  \
619:    ((obj)->realcomposeddata[id] = data,(obj)->realcomposedstate[id] = (obj)->state, 0))

621: /*MC
622:    PetscObjectComposedDataGetReal - retrieve real data attached to an object

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

628:    Not collective

630:    Input parameters:
631: +  obj - the object from which data is to be retrieved
632: -  id - the identifier for the data

634:    Output parameters:
635: +  data - the data to be retrieved
636: -  flag - PETSC_TRUE if the data item exists and is valid, PETSC_FALSE otherwise

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

640:    Level: developer
641: M*/
642: #define PetscObjectComposedDataGetReal(obj,id,data,flag)                            \
643:   ((((obj)->realcomposedstate && ((obj)->realcomposedstate[id] == (obj)->state)) ?  \
644:    (data = (obj)->realcomposeddata[id],flag = PETSC_TRUE) : (flag = PETSC_FALSE)),0)

646: /*MC
647:    PetscObjectComposedDataSetRealstar - attach real array data to a PetscObject

649:    Synopsis:
650:    #include "petsc/private/petscimpl.h"
651:    PetscErrorCode PetscObjectComposedDataSetRealstar(PetscObject obj,int id,PetscReal *data)

653:    Not collective

655:    Input parameters:
656: +  obj - the object to which data is to be attached
657: .  id - the identifier for the data
658: -  data - the data to  be attached

660:    Notes
661:    The data identifier can best be determined through a call to
662:    PetscObjectComposedDataRegister()

664:    Level: developer
665: M*/
666: #define PetscObjectComposedDataSetRealstar(obj,id,data)                                           \
667:   ((((obj)->realstar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseRealstar(obj)) ||  \
668:    ((obj)->realstarcomposeddata[id] = data, (obj)->realstarcomposedstate[id] = (obj)->state, 0))

670: /*MC
671:    PetscObjectComposedDataGetRealstar - retrieve real array data
672:    attached to an object

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

678:    Not collective

680:    Input parameters:
681: +  obj - the object from which data is to be retrieved
682: -  id - the identifier for the data

684:    Output parameters:
685: +  data - the data to be retrieved
686: -  flag - PETSC_TRUE if the data item exists and is valid, PETSC_FALSE otherwise

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

690:    Level: developer
691: M*/
692: #define PetscObjectComposedDataGetRealstar(obj,id,data,flag)                                \
693:   ((((obj)->realstarcomposedstate && ((obj)->realstarcomposedstate[id] == (obj)->state)) ?  \
694:    (data = (obj)->realstarcomposeddata[id],flag = PETSC_TRUE) : (flag = PETSC_FALSE)),0)

696: /*MC
697:    PetscObjectComposedDataSetScalar - attach scalar data to a PetscObject

699:    Synopsis:
700:    #include "petsc/private/petscimpl.h"
701:    PetscErrorCode PetscObjectComposedDataSetScalar(PetscObject obj,int id,PetscScalar data)

703:    Not collective

705:    Input parameters:
706: +  obj - the object to which data is to be attached
707: .  id - the identifier for the data
708: -  data - the data to  be attached

710:    Notes
711:    The data identifier can best be determined through a call to
712:    PetscObjectComposedDataRegister()

714:    Level: developer
715: M*/
716: #if defined(PETSC_USE_COMPLEX)
717: #define PetscObjectComposedDataSetScalar(obj,id,data)                                        \
718:   ((((obj)->scalar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseScalar(obj)) || \
719:    ((obj)->scalarcomposeddata[id] = data,(obj)->scalarcomposedstate[id] = (obj)->state, 0))
720: #else
721: #define PetscObjectComposedDataSetScalar(obj,id,data) \
722:         PetscObjectComposedDataSetReal(obj,id,data)
723: #endif
724: /*MC
725:    PetscObjectComposedDataGetScalar - retrieve scalar data attached to an object

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

731:    Not collective

733:    Input parameters:
734: +  obj - the object from which data is to be retrieved
735: -  id - the identifier for the data

737:    Output parameters:
738: +  data - the data to be retrieved
739: -  flag - PETSC_TRUE if the data item exists and is valid, PETSC_FALSE otherwise

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

743:    Level: developer
744: M*/
745: #if defined(PETSC_USE_COMPLEX)
746: #define PetscObjectComposedDataGetScalar(obj,id,data,flag)                              \
747:   ((((obj)->scalarcomposedstate && ((obj)->scalarcomposedstate[id] == (obj)->state) ) ? \
748:    (data = (obj)->scalarcomposeddata[id],flag = PETSC_TRUE) : (flag = PETSC_FALSE)),0)
749: #else
750: #define PetscObjectComposedDataGetScalar(obj,id,data,flag)                             \
751:         PetscObjectComposedDataGetReal(obj,id,data,flag)
752: #endif

754: /*MC
755:    PetscObjectComposedDataSetScalarstar - attach scalar array data to a PetscObject

757:    Synopsis:
758:    #include "petsc/private/petscimpl.h"
759:    PetscErrorCode PetscObjectComposedDataSetScalarstar(PetscObject obj,int id,PetscScalar *data)

761:    Not collective

763:    Input parameters:
764: +  obj - the object to which data is to be attached
765: .  id - the identifier for the data
766: -  data - the data to  be attached

768:    Notes
769:    The data identifier can best be determined through a call to
770:    PetscObjectComposedDataRegister()

772:    Level: developer
773: M*/
774: #if defined(PETSC_USE_COMPLEX)
775: #define PetscObjectComposedDataSetScalarstar(obj,id,data)                                             \
776:   ((((obj)->scalarstar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseScalarstar(obj)) ||  \
777:    ((obj)->scalarstarcomposeddata[id] = data,(obj)->scalarstarcomposedstate[id] = (obj)->state, 0))
778: #else
779: #define PetscObjectComposedDataSetScalarstar(obj,id,data) \
780:         PetscObjectComposedDataSetRealstar(obj,id,data)
781: #endif
782: /*MC
783:    PetscObjectComposedDataGetScalarstar - retrieve scalar array data
784:    attached to an object

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

790:    Not collective

792:    Input parameters:
793: +  obj - the object from which data is to be retrieved
794: -  id - the identifier for the data

796:    Output parameters:
797: +  data - the data to be retrieved
798: -  flag - PETSC_TRUE if the data item exists and is valid, PETSC_FALSE otherwise

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

802:    Level: developer
803: M*/
804: #if defined(PETSC_USE_COMPLEX)
805: #define PetscObjectComposedDataGetScalarstar(obj,id,data,flag)                                 \
806:   ((((obj)->scalarstarcomposedstate && ((obj)->scalarstarcomposedstate[id] == (obj)->state)) ? \
807:        (data = (obj)->scalarstarcomposeddata[id],flag = PETSC_TRUE) : (flag = PETSC_FALSE)),0)
808: #else
809: #define PetscObjectComposedDataGetScalarstar(obj,id,data,flag)         \
810:         PetscObjectComposedDataGetRealstar(obj,id,data,flag)
811: #endif

813: PETSC_EXTERN PetscMPIInt Petsc_Counter_keyval;
814: PETSC_EXTERN PetscMPIInt Petsc_InnerComm_keyval;
815: PETSC_EXTERN PetscMPIInt Petsc_OuterComm_keyval;
816: PETSC_EXTERN PetscMPIInt Petsc_Seq_keyval;
817: PETSC_EXTERN PetscMPIInt Petsc_ShmComm_keyval;

819: /*
820:   PETSc communicators have this attribute, see
821:   PetscCommDuplicate(), PetscCommDestroy(), PetscCommGetNewTag(), PetscObjectGetName()
822: */
823: typedef struct {
824:   PetscMPIInt tag;              /* next free tag value */
825:   PetscInt    refcount;         /* number of references, communicator can be freed when this reaches 0 */
826:   PetscInt    namecount;        /* used to generate the next name, as in Vec_0, Mat_1, ... */
827:   PetscMPIInt *iflags;          /* length of comm size, shared by all calls to PetscCommBuildTwoSided_Allreduce/RedScatter on this comm */
828: } PetscCommCounter;

830: /*E
831:     PetscOffloadMask - indicates which memory (CPU, GPU, or none) contains valid data

833:    PETSC_OFFLOAD_UNALLOCATED  - no memory contains valid matrix entries; NEVER used for vectors
834:    PETSC_OFFLOAD_GPU - GPU has valid vector/matrix entries
835:    PETSC_OFFLOAD_CPU - CPU has valid vector/matrix entries
836:    PETSC_OFFLOAD_BOTH - Both GPU and CPU have valid vector/matrix entries and they match

838:    Level: developer
839: E*/
840: typedef enum {PETSC_OFFLOAD_UNALLOCATED=0x0,PETSC_OFFLOAD_CPU=0x1,PETSC_OFFLOAD_GPU=0x2,PETSC_OFFLOAD_BOTH=0x3} PetscOffloadMask;

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

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

846: typedef struct {
847:   MPI_Comm    comm;
848:   MPI_Request request;
849:   PetscBool   async;
850:   PetscScalar *lvalues;     /* this are the reduced values before call to MPI_Allreduce() */
851:   PetscScalar *gvalues;     /* values after call to MPI_Allreduce() */
852:   void        **invecs;     /* for debugging only, vector/memory used with each op */
853:   PetscInt    *reducetype;  /* is particular value to be summed or maxed? */
854:   SRState     state;        /* are we calling xxxBegin() or xxxEnd()? */
855:   PetscInt    maxops;       /* total amount of space we have for requests */
856:   PetscInt    numopsbegin;  /* number of requests that have been queued in */
857:   PetscInt    numopsend;    /* number of requests that have been gotten by user */
858: } PetscSplitReduction;

860: PETSC_EXTERN PetscErrorCode PetscSplitReductionGet(MPI_Comm,PetscSplitReduction**);
861: PETSC_EXTERN PetscErrorCode PetscSplitReductionEnd(PetscSplitReduction*);
862: PETSC_EXTERN PetscErrorCode PetscSplitReductionExtend(PetscSplitReduction*);

864: #if !defined(PETSC_SKIP_SPINLOCK)
865: #if defined(PETSC_HAVE_THREADSAFETY)
866: #  if defined(PETSC_HAVE_CONCURRENCYKIT)
867: #if defined(__cplusplus)
868: /*  CK does not have extern "C" protection in their include files */
869: extern "C" {
870: #endif
871: #include <ck_spinlock.h>
872: #if defined(__cplusplus)
873: }
874: #endif
875: typedef ck_spinlock_t PetscSpinlock;
876: PETSC_STATIC_INLINE PetscErrorCode PetscSpinlockCreate(PetscSpinlock *ck_spinlock)
877: {
878:   ck_spinlock_init(ck_spinlock);
879:   return 0;
880: }
881: PETSC_STATIC_INLINE PetscErrorCode PetscSpinlockLock(PetscSpinlock *ck_spinlock)
882: {
883:   ck_spinlock_lock(ck_spinlock);
884:   return 0;
885: }
886: PETSC_STATIC_INLINE PetscErrorCode PetscSpinlockUnlock(PetscSpinlock *ck_spinlock)
887: {
888:   ck_spinlock_unlock(ck_spinlock);
889:   return 0;
890: }
891: PETSC_STATIC_INLINE PetscErrorCode PetscSpinlockDestroy(PetscSpinlock *ck_spinlock)
892: {
893:   return 0;
894: }
895: #  elif defined(PETSC_HAVE_OPENMP)

897: #include <omp.h>
898: typedef omp_lock_t PetscSpinlock;
899: PETSC_STATIC_INLINE PetscErrorCode PetscSpinlockCreate(PetscSpinlock *omp_lock)
900: {
901:   omp_init_lock(omp_lock);
902:   return 0;
903: }
904: PETSC_STATIC_INLINE PetscErrorCode PetscSpinlockLock(PetscSpinlock *omp_lock)
905: {
906:   omp_set_lock(omp_lock);
907:   return 0;
908: }
909: PETSC_STATIC_INLINE PetscErrorCode PetscSpinlockUnlock(PetscSpinlock *omp_lock)
910: {
911:   omp_unset_lock(omp_lock);
912:   return 0;
913: }
914: PETSC_STATIC_INLINE PetscErrorCode PetscSpinlockDestroy(PetscSpinlock *omp_lock)
915: {
916:   omp_destroy_lock(omp_lock);
917:   return 0;
918: }
919: #else
920: Thread safety requires either --with-openmp or --download-concurrencykit
921: #endif

923: #else
924: typedef int PetscSpinlock;
925: #define PetscSpinlockCreate(a)  0
926: #define PetscSpinlockLock(a)    0
927: #define PetscSpinlockUnlock(a)  0
928: #define PetscSpinlockDestroy(a) 0
929: #endif

931: #if defined(PETSC_HAVE_THREADSAFETY)
932: PETSC_INTERN PetscSpinlock PetscViewerASCIISpinLockOpen;
933: PETSC_INTERN PetscSpinlock PetscViewerASCIISpinLockStdout;
934: PETSC_INTERN PetscSpinlock PetscViewerASCIISpinLockStderr;
935: PETSC_INTERN PetscSpinlock PetscCommSpinLock;
936: #endif
937: #endif

939: PETSC_EXTERN PetscLogEvent PETSC_Barrier;
940: PETSC_EXTERN PetscLogEvent PETSC_BuildTwoSided;
941: PETSC_EXTERN PetscLogEvent PETSC_BuildTwoSidedF;
942: PETSC_EXTERN PetscBool     use_gpu_aware_mpi;

944: #if defined(PETSC_HAVE_ADIOS)
945: PETSC_EXTERN int64_t Petsc_adios_group;
946: #endif

948: #endif /* PETSCIMPL_H */