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*);

184: #if !defined(PETSC_CLANG_STATIC_ANALYZER)
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)
271: #endif
272: #else /* PETSC_CLANG_STATIC_ANALYZER */
273: template <typename T>
275: template <typename T>
277: template <typename T>
279: template <typename T>
281: template <typename T>
283: template <typename T>
285: template <typename T>
287: template <typename T>
289: template <typename T>
291: template <typename T>
294: #endif /* PETSC_CLANG_STATIC_ANALYZER */

296: #define PetscSorted(n,idx,sorted)           \
297:   do {                                      \
298:     PetscInt _i_;                           \
299:     (sorted) = PETSC_TRUE;                  \
300:     for (_i_ = 1; _i_ < (n); _i_++)         \
301:       if ((idx)[_i_] < (idx)[_i_ - 1])      \
302:         { (sorted) = PETSC_FALSE; break; }  \
303:   } while (0)

305: #if !defined(PETSC_CLANG_STATIC_ANALYZER)
306: #if !defined(PETSC_USE_DEBUG)


322: #else

324: /*
325:     For example, in the dot product between two vectors,
326:   both vectors must be either Seq or MPI, not one of each
327: */
329:   do {                                                                  \
330:     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); \
331:   } while (0)

333: /*
334:     Check type_name
335: */
337:   do {                                                                  \
338:     PetscBool      _7_match;                                            \
339:     PetscErrorCode _7_ierr;                                             \
340:     _7_PetscObjectTypeCompare(((PetscObject)(a)),(type),&_7_match);CHKERRQ(_7_ierr); \
341:     if (!_7_match) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Object (%s) is not %s",(char*)(((PetscObject)(a))->type_name),type); \
342:   } while (0)

345:   do {                                                                  \
346:     PetscBool      _7_match;                                            \
347:     PetscErrorCode _7_ierr;                                             \
348:     _7_PetscObjectTypeCompareAny(((PetscObject)(a)),&_7_match,(type1),(type2),"");CHKERRQ(_7_ierr); \
349:     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); \
350:   } while (0)
351: /*
352:    Use this macro to check if the type is set
353: */

356:   do {                                                                  \
357:     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); \
358:   } while (0)
359: /*
360:    Sometimes object must live on same communicator to inter-operate
361: */
363:   do {                                                                  \
364:     PetscErrorCode _7_ierr;                                             \
365:     PetscMPIInt    _7_flag;                                             \
366:     _7_MPI_Comm_compare(PetscObjectComm((PetscObject)(a)),PetscObjectComm((PetscObject)(b)),&_7_flag);CHKERRMPI(_7_ierr); \
367:     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); \
368:   } while (0)

371:   do {                                                  \
374:   } while (0)

377:   do {                                                                  \
378:     PetscErrorCode _7_ierr;                                             \
379:     PetscScalar b0=(b);                                                 \
380:     PetscReal b1[5],b2[5];                                              \
381:     if (PetscIsNanScalar(b0)) {b1[4] = 1;} else {b1[4] = 0;};           \
382:     b1[0] = -PetscRealPart(b0); b1[1] = PetscRealPart(b0); b1[2] = -PetscImaginaryPart(b0); b1[3] = PetscImaginaryPart(b0); \
383:     _7_MPIU_Allreduce(b1,b2,5,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)(a)));CHKERRMPI(_7_ierr); \
384:     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); \
385:   } while (0)

388:   do {                                                                  \
389:     PetscErrorCode _7_ierr;                                             \
390:     PetscReal b0=(b),b1[3],b2[3];                                       \
391:     if (PetscIsNanReal(b0)) {b1[2] = 1;} else {b1[2] = 0;};             \
392:     b1[0] = -b0; b1[1] = b0;                                            \
393:     _7_MPIU_Allreduce(b1,b2,3,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)(a)));CHKERRMPI(_7_ierr); \
394:     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); \
395:   } while (0)

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

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

416:   do {                                                                  \
417:     PetscErrorCode _7_ierr;                                             \
418:     PetscMPIInt b0=(PetscMPIInt)(b),b1[2],b2[2];                        \
419:     b1[0] = -b0; b1[1] = b0;                                            \
420:     _7_MPIU_Allreduce(b1,b2,2,MPI_INT,MPI_MAX,PetscObjectComm((PetscObject)(a)));CHKERRMPI(_7_ierr); \
421:     if (-b2[0] != b2[1]) SETERRQ1(PetscObjectComm((PetscObject)(a)),PETSC_ERR_ARG_WRONG,"Bool value must be same on all processes, argument # %d",arg); \
422:   } while (0)

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

434:   do {                                                                                            \
435:     PetscBool _1_flg;                                                                             \
436:     PetscSorted(n,idx,_1_flg);                                                                    \
437:     if (!_1_flg) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Input array needs to be sorted"); \
438:   } while (0)

440: #endif
441: #else /* PETSC_CLANG_STATIC_ANALYZER */
442: template <typename Ta,typename Tb>
446: template <typename T>
448: template <typename Ta,typename Tb>
450: template <typename Ta,typename Tb>
452: template <typename Ta,typename Tb>
454: template <typename Ta,typename Tb>
456: template <typename Ta,typename Tb>
458: template <typename Ta,typename Tb>
460: template <typename Ta,typename Tb>
462: template <typename Ta,typename Tb>
465: #endif /* PETSC_CLANG_STATIC_ANALYZER */

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

471:    Level: developer

473: .seealso: PetscUseMethod()
474: */
475: #define  PetscTryMethod(obj,A,B,C) \
476:   0; do { PetscErrorCode (*_7_f)B, _7_ierr; \
477:     _7_PetscObjectQueryFunction((PetscObject)(obj),A,&_7_f);CHKERRQ(_7_ierr); \
478:     if (_7_f) {_7_(*_7_f)C;CHKERRQ(_7_ierr);} \
479:   } while (0)

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

485:    Level: developer

487: .seealso: PetscTryMethod()
488: */
489: #define  PetscUseMethod(obj,A,B,C) \
490:   0; do { PetscErrorCode (*_7_f)B, _7_ierr; \
491:     _7_PetscObjectQueryFunction((PetscObject)(obj),A,&_7_f);CHKERRQ(_7_ierr); \
492:     if (_7_f) {_7_(*_7_f)C;CHKERRQ(_7_ierr);} \
493:     else SETERRQ1(PetscObjectComm((PetscObject)(obj)),PETSC_ERR_SUP,"Cannot locate function %s in object",A); \
494:   } while (0)

496: /*MC
497:    PetscObjectStateIncrease - Increases the state of any PetscObject

499:    Synopsis:
500:    #include "petsc/private/petscimpl.h"
501:    PetscErrorCode PetscObjectStateIncrease(PetscObject obj)

503:    Logically Collective

505:    Input Parameter:
506: .  obj - any PETSc object, for example a Vec, Mat or KSP. This must be
507:          cast with a (PetscObject), for example,
508:          PetscObjectStateIncrease((PetscObject)mat);

510:    Notes:
511:     object state is an integer which gets increased every time
512:    the object is changed internally. By saving and later querying the object state
513:    one can determine whether information about the object is still current.
514:    Currently, state is maintained for Vec and Mat objects.

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

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

523:    Level: developer

525:    seealso: PetscObjectStateGet()

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

530: PETSC_EXTERN PetscErrorCode PetscObjectStateGet(PetscObject,PetscObjectState*);
531: PETSC_EXTERN PetscErrorCode PetscObjectStateSet(PetscObject,PetscObjectState);
532: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataRegister(PetscInt*);
533: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseInt(PetscObject);
534: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseIntstar(PetscObject);
535: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseReal(PetscObject);
536: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseRealstar(PetscObject);
537: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseScalar(PetscObject);
538: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseScalarstar(PetscObject);
539: PETSC_EXTERN PetscInt       PetscObjectComposedDataMax;
540: /*MC
541:    PetscObjectComposedDataSetInt - attach integer data to a PetscObject

543:    Synopsis:
544:    #include "petsc/private/petscimpl.h"
545:    PetscErrorCode PetscObjectComposedDataSetInt(PetscObject obj,int id,int data)

547:    Not collective

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

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

557:    Level: developer
558: M*/
559: #define PetscObjectComposedDataSetInt(obj,id,data)                                      \
560:   ((((obj)->int_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseInt(obj)) ||  \
561:    ((obj)->intcomposeddata[id] = data,(obj)->intcomposedstate[id] = (obj)->state, 0))

563: /*MC
564:    PetscObjectComposedDataGetInt - retrieve integer data attached to an object

566:    Synopsis:
567:    #include "petsc/private/petscimpl.h"
568:    PetscErrorCode PetscObjectComposedDataGetInt(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 PetscObjectComposedDataGetInt(obj,id,data,flag)                            \
585:   ((((obj)->intcomposedstate && ((obj)->intcomposedstate[id] == (obj)->state)) ?   \
586:    (data = (obj)->intcomposeddata[id],flag = PETSC_TRUE) : (flag = PETSC_FALSE)),0)

588: /*MC
589:    PetscObjectComposedDataSetIntstar - attach integer array data to a PetscObject

591:    Synopsis:
592:    #include "petsc/private/petscimpl.h"
593:    PetscErrorCode PetscObjectComposedDataSetIntstar(PetscObject obj,int id,int *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 PetscObjectComposedDataSetIntstar(obj,id,data)                                          \
609:   ((((obj)->intstar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseIntstar(obj)) ||  \
610:    ((obj)->intstarcomposeddata[id] = data,(obj)->intstarcomposedstate[id] = (obj)->state, 0))

612: /*MC
613:    PetscObjectComposedDataGetIntstar - retrieve integer array data
614:    attached to an object

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

620:    Not collective

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

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

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

632:    Level: developer
633: M*/
634: #define PetscObjectComposedDataGetIntstar(obj,id,data,flag)                               \
635:   ((((obj)->intstarcomposedstate && ((obj)->intstarcomposedstate[id] == (obj)->state)) ?  \
636:    (data = (obj)->intstarcomposeddata[id],flag = PETSC_TRUE) : (flag = PETSC_FALSE)),0)

638: /*MC
639:    PetscObjectComposedDataSetReal - attach real data to a PetscObject

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

645:    Not collective

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

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

656:    Level: developer
657: M*/
658: #define PetscObjectComposedDataSetReal(obj,id,data)                                       \
659:   ((((obj)->real_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseReal(obj)) ||  \
660:    ((obj)->realcomposeddata[id] = data,(obj)->realcomposedstate[id] = (obj)->state, 0))

662: /*MC
663:    PetscObjectComposedDataGetReal - retrieve real data attached to an object

665:    Synopsis:
666:    #include "petsc/private/petscimpl.h"
667:    PetscErrorCode PetscObjectComposedDataGetReal(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 PetscObjectComposedDataGetReal(obj,id,data,flag)                            \
684:   ((((obj)->realcomposedstate && ((obj)->realcomposedstate[id] == (obj)->state)) ?  \
685:    (data = (obj)->realcomposeddata[id],flag = PETSC_TRUE) : (flag = PETSC_FALSE)),0)

687: /*MC
688:    PetscObjectComposedDataSetRealstar - attach real array data to a PetscObject

690:    Synopsis:
691:    #include "petsc/private/petscimpl.h"
692:    PetscErrorCode PetscObjectComposedDataSetRealstar(PetscObject obj,int id,PetscReal *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: #define PetscObjectComposedDataSetRealstar(obj,id,data)                                           \
708:   ((((obj)->realstar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseRealstar(obj)) ||  \
709:    ((obj)->realstarcomposeddata[id] = data, (obj)->realstarcomposedstate[id] = (obj)->state, 0))

711: /*MC
712:    PetscObjectComposedDataGetRealstar - retrieve real array data
713:    attached to an object

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

719:    Not collective

721:    Input parameters:
722: +  obj - the object from which data is to be retrieved
723: -  id - the identifier for the data

725:    Output parameters:
726: +  data - the data to be retrieved
727: -  flag - PETSC_TRUE if the data item exists and is valid, PETSC_FALSE otherwise

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

731:    Level: developer
732: M*/
733: #define PetscObjectComposedDataGetRealstar(obj,id,data,flag)                                \
734:   ((((obj)->realstarcomposedstate && ((obj)->realstarcomposedstate[id] == (obj)->state)) ?  \
735:    (data = (obj)->realstarcomposeddata[id],flag = PETSC_TRUE) : (flag = PETSC_FALSE)),0)

737: /*MC
738:    PetscObjectComposedDataSetScalar - attach scalar data to a PetscObject

740:    Synopsis:
741:    #include "petsc/private/petscimpl.h"
742:    PetscErrorCode PetscObjectComposedDataSetScalar(PetscObject obj,int id,PetscScalar data)

744:    Not collective

746:    Input parameters:
747: +  obj - the object to which data is to be attached
748: .  id - the identifier for the data
749: -  data - the data to  be attached

751:    Notes
752:    The data identifier can best be determined through a call to
753:    PetscObjectComposedDataRegister()

755:    Level: developer
756: M*/
757: #if defined(PETSC_USE_COMPLEX)
758: #define PetscObjectComposedDataSetScalar(obj,id,data)                                        \
759:   ((((obj)->scalar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseScalar(obj)) || \
760:    ((obj)->scalarcomposeddata[id] = data,(obj)->scalarcomposedstate[id] = (obj)->state, 0))
761: #else
762: #define PetscObjectComposedDataSetScalar(obj,id,data) \
763:         PetscObjectComposedDataSetReal(obj,id,data)
764: #endif
765: /*MC
766:    PetscObjectComposedDataGetScalar - retrieve scalar data attached to an object

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

772:    Not collective

774:    Input parameters:
775: +  obj - the object from which data is to be retrieved
776: -  id - the identifier for the data

778:    Output parameters:
779: +  data - the data to be retrieved
780: -  flag - PETSC_TRUE if the data item exists and is valid, PETSC_FALSE otherwise

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

784:    Level: developer
785: M*/
786: #if defined(PETSC_USE_COMPLEX)
787: #define PetscObjectComposedDataGetScalar(obj,id,data,flag)                              \
788:   ((((obj)->scalarcomposedstate && ((obj)->scalarcomposedstate[id] == (obj)->state)) ? \
789:    (data = (obj)->scalarcomposeddata[id],flag = PETSC_TRUE) : (flag = PETSC_FALSE)),0)
790: #else
791: #define PetscObjectComposedDataGetScalar(obj,id,data,flag)                             \
792:         PetscObjectComposedDataGetReal(obj,id,data,flag)
793: #endif

795: /*MC
796:    PetscObjectComposedDataSetScalarstar - attach scalar array data to a PetscObject

798:    Synopsis:
799:    #include "petsc/private/petscimpl.h"
800:    PetscErrorCode PetscObjectComposedDataSetScalarstar(PetscObject obj,int id,PetscScalar *data)

802:    Not collective

804:    Input parameters:
805: +  obj - the object to which data is to be attached
806: .  id - the identifier for the data
807: -  data - the data to  be attached

809:    Notes
810:    The data identifier can best be determined through a call to
811:    PetscObjectComposedDataRegister()

813:    Level: developer
814: M*/
815: #if defined(PETSC_USE_COMPLEX)
816: #define PetscObjectComposedDataSetScalarstar(obj,id,data)                                             \
817:   ((((obj)->scalarstar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseScalarstar(obj)) ||  \
818:    ((obj)->scalarstarcomposeddata[id] = data,(obj)->scalarstarcomposedstate[id] = (obj)->state, 0))
819: #else
820: #define PetscObjectComposedDataSetScalarstar(obj,id,data) \
821:         PetscObjectComposedDataSetRealstar(obj,id,data)
822: #endif
823: /*MC
824:    PetscObjectComposedDataGetScalarstar - retrieve scalar array data
825:    attached to an object

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

831:    Not collective

833:    Input parameters:
834: +  obj - the object from which data is to be retrieved
835: -  id - the identifier for the data

837:    Output parameters:
838: +  data - the data to be retrieved
839: -  flag - PETSC_TRUE if the data item exists and is valid, PETSC_FALSE otherwise

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

843:    Level: developer
844: M*/
845: #if defined(PETSC_USE_COMPLEX)
846: #define PetscObjectComposedDataGetScalarstar(obj,id,data,flag)                                 \
847:   ((((obj)->scalarstarcomposedstate && ((obj)->scalarstarcomposedstate[id] == (obj)->state)) ? \
848:        (data = (obj)->scalarstarcomposeddata[id],flag = PETSC_TRUE) : (flag = PETSC_FALSE)),0)
849: #else
850: #define PetscObjectComposedDataGetScalarstar(obj,id,data,flag)         \
851:         PetscObjectComposedDataGetRealstar(obj,id,data,flag)
852: #endif

854: PETSC_EXTERN PetscMPIInt Petsc_Counter_keyval;
855: PETSC_EXTERN PetscMPIInt Petsc_InnerComm_keyval;
856: PETSC_EXTERN PetscMPIInt Petsc_OuterComm_keyval;
857: PETSC_EXTERN PetscMPIInt Petsc_Seq_keyval;
858: PETSC_EXTERN PetscMPIInt Petsc_ShmComm_keyval;

860: /*
861:   PETSc communicators have this attribute, see
862:   PetscCommDuplicate(), PetscCommDestroy(), PetscCommGetNewTag(), PetscObjectGetName()
863: */
864: typedef struct {
865:   PetscMPIInt tag;              /* next free tag value */
866:   PetscInt    refcount;         /* number of references, communicator can be freed when this reaches 0 */
867:   PetscInt    namecount;        /* used to generate the next name, as in Vec_0, Mat_1, ... */
868:   PetscMPIInt *iflags;          /* length of comm size, shared by all calls to PetscCommBuildTwoSided_Allreduce/RedScatter on this comm */
869: } PetscCommCounter;

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

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

875: typedef struct {
876:   MPI_Comm       comm;
877:   MPI_Request    request;
878:   PetscBool      mix;
879:   PetscBool      async;
880:   PetscScalar    *lvalues;     /* this are the reduced values before call to MPI_Allreduce() */
881:   PetscScalar    *gvalues;     /* values after call to MPI_Allreduce() */
882:   void           **invecs;     /* for debugging only, vector/memory used with each op */
883:   PetscInt       *reducetype;  /* is particular value to be summed or maxed? */
884:   struct { PetscScalar v; PetscInt i; } *lvalues_mix,*gvalues_mix; /* used when mixing reduce operations */
885:   SRState        state;        /* are we calling xxxBegin() or xxxEnd()? */
886:   PetscInt       maxops;       /* total amount of space we have for requests */
887:   PetscInt       numopsbegin;  /* number of requests that have been queued in */
888:   PetscInt       numopsend;    /* number of requests that have been gotten by user */
889: } PetscSplitReduction;

891: PETSC_EXTERN PetscErrorCode PetscSplitReductionGet(MPI_Comm,PetscSplitReduction**);
892: PETSC_EXTERN PetscErrorCode PetscSplitReductionEnd(PetscSplitReduction*);
893: PETSC_EXTERN PetscErrorCode PetscSplitReductionExtend(PetscSplitReduction*);

895: #if !defined(PETSC_SKIP_SPINLOCK)
896: #if defined(PETSC_HAVE_THREADSAFETY)
897: #  if defined(PETSC_HAVE_CONCURRENCYKIT)
898: #if defined(__cplusplus)
899: /*  CK does not have extern "C" protection in their include files */
900: extern "C" {
901: #endif
902: #include <ck_spinlock.h>
903: #if defined(__cplusplus)
904: }
905: #endif
906: typedef ck_spinlock_t PetscSpinlock;
907: PETSC_STATIC_INLINE PetscErrorCode PetscSpinlockCreate(PetscSpinlock *ck_spinlock)
908: {
909:   ck_spinlock_init(ck_spinlock);
910:   return 0;
911: }
912: PETSC_STATIC_INLINE PetscErrorCode PetscSpinlockLock(PetscSpinlock *ck_spinlock)
913: {
914:   ck_spinlock_lock(ck_spinlock);
915:   return 0;
916: }
917: PETSC_STATIC_INLINE PetscErrorCode PetscSpinlockUnlock(PetscSpinlock *ck_spinlock)
918: {
919:   ck_spinlock_unlock(ck_spinlock);
920:   return 0;
921: }
922: PETSC_STATIC_INLINE PetscErrorCode PetscSpinlockDestroy(PetscSpinlock *ck_spinlock)
923: {
924:   return 0;
925: }
926: #  elif defined(PETSC_HAVE_OPENMP)

928: #include <omp.h>
929: typedef omp_lock_t PetscSpinlock;
930: PETSC_STATIC_INLINE PetscErrorCode PetscSpinlockCreate(PetscSpinlock *omp_lock)
931: {
932:   omp_init_lock(omp_lock);
933:   return 0;
934: }
935: PETSC_STATIC_INLINE PetscErrorCode PetscSpinlockLock(PetscSpinlock *omp_lock)
936: {
937:   omp_set_lock(omp_lock);
938:   return 0;
939: }
940: PETSC_STATIC_INLINE PetscErrorCode PetscSpinlockUnlock(PetscSpinlock *omp_lock)
941: {
942:   omp_unset_lock(omp_lock);
943:   return 0;
944: }
945: PETSC_STATIC_INLINE PetscErrorCode PetscSpinlockDestroy(PetscSpinlock *omp_lock)
946: {
947:   omp_destroy_lock(omp_lock);
948:   return 0;
949: }
950: #else
951: Thread safety requires either --with-openmp or --download-concurrencykit
952: #endif

954: #else
955: typedef int PetscSpinlock;
956: #define PetscSpinlockCreate(a)  0
957: #define PetscSpinlockLock(a)    0
958: #define PetscSpinlockUnlock(a)  0
959: #define PetscSpinlockDestroy(a) 0
960: #endif

962: #if defined(PETSC_HAVE_THREADSAFETY)
963: PETSC_INTERN PetscSpinlock PetscViewerASCIISpinLockOpen;
964: PETSC_INTERN PetscSpinlock PetscViewerASCIISpinLockStdout;
965: PETSC_INTERN PetscSpinlock PetscViewerASCIISpinLockStderr;
966: PETSC_INTERN PetscSpinlock PetscCommSpinLock;
967: #endif
968: #endif

970: PETSC_EXTERN PetscLogEvent PETSC_Barrier;
971: PETSC_EXTERN PetscLogEvent PETSC_BuildTwoSided;
972: PETSC_EXTERN PetscLogEvent PETSC_BuildTwoSidedF;
973: PETSC_EXTERN PetscBool     use_gpu_aware_mpi;

975: #if defined(PETSC_HAVE_ADIOS)
976: PETSC_EXTERN int64_t Petsc_adios_group;
977: #endif

979: #if defined(PETSC_HAVE_KOKKOS)
980: PETSC_INTERN PetscBool      PetscBeganKokkos;
981: PETSC_EXTERN PetscBool      PetscKokkosInitialized;
982: PETSC_INTERN PetscErrorCode PetscKokkosIsInitialized_Private(PetscBool*);
983: PETSC_INTERN PetscErrorCode PetscKokkosFinalize_Private(void);
984: #endif

986: #if defined(PETSC_HAVE_CUDA)
987: PETSC_EXTERN PetscBool      PetscCUDAInitialized;  /* Is CUDA initialized? One can use this flag to guard CUDA calls. */
988: PETSC_EXTERN PetscBool      PetscMPICUDAAwarenessCheck(void);
989: #endif

991: #if defined(PETSC_HAVE_HIP)
992: PETSC_EXTERN PetscBool      PetscHIPInitialized;
993: PETSC_EXTERN PetscBool      PetscMPIHIPAwarenessCheck(void);
994: #endif

996: PETSC_EXTERN PetscBool      PetscCreatedGpuObjects;
997: #endif /* PETSCIMPL_H */