Actual source code: petscimpl.h

petsc-3.8.4 2018-03-24
Report Typos and Errors

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

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

 10: /* These are used internally by PETSc ASCII IO routines*/
 11: #include <stdarg.h>
 12: PETSC_EXTERN PetscErrorCode PetscVSNPrintf(char*,size_t,const char[],size_t*,va_list);
 13: PETSC_EXTERN PetscErrorCode (*PetscVFPrintf)(FILE*,const char[],va_list);
 14: PETSC_EXTERN PetscErrorCode PetscVFPrintfDefault(FILE*,const char[],va_list);

 16: #if defined(PETSC_HAVE_MATLAB_ENGINE)
 17: PETSC_EXTERN PetscErrorCode PetscVFPrintf_Matlab(FILE*,const char[],va_list);
 18: #endif

 20: #if defined(PETSC_HAVE_CLOSURES)
 21: PETSC_EXTERN PetscErrorCode PetscVFPrintfSetClosure(int (^)(const char*));
 22: #endif


 25: #if defined(PETSC_HAVE_CUDA)
 26: #include <cuda.h>
 27: #include <cublas_v2.h>
 28: #endif

 30: /*
 31:    All major PETSc data structures have a common core; this is defined
 32:    below by PETSCHEADER.

 34:    PetscHeaderCreate() should be used whenever creating a PETSc structure.
 35: */

 37: /*
 38:    PetscOps: structure of core operations that all PETSc objects support.

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

 57: typedef struct {
 58:    PetscErrorCode (*getcomm)(PetscObject,MPI_Comm *);
 59:    PetscErrorCode (*view)(PetscObject,PetscViewer);
 60:    PetscErrorCode (*destroy)(PetscObject*);
 61:    PetscErrorCode (*compose)(PetscObject,const char[],PetscObject);
 62:    PetscErrorCode (*query)(PetscObject,const char[],PetscObject *);
 63:    PetscErrorCode (*composefunction)(PetscObject,const char[],void (*)(void));
 64:    PetscErrorCode (*queryfunction)(PetscObject,const char[],void (**)(void));
 65: } PetscOps;

 67: typedef enum {PETSC_FORTRAN_CALLBACK_CLASS,PETSC_FORTRAN_CALLBACK_SUBTYPE,PETSC_FORTRAN_CALLBACK_MAXTYPE} PetscFortranCallbackType;
 68: typedef int PetscFortranCallbackId;
 69: #define PETSC_SMALLEST_FORTRAN_CALLBACK ((PetscFortranCallbackId)1000)
 70: PETSC_EXTERN PetscErrorCode PetscFortranCallbackRegister(PetscClassId,const char*,PetscFortranCallbackId*);
 71: PETSC_EXTERN PetscErrorCode PetscFortranCallbackGetSizes(PetscClassId,PetscInt*,PetscInt*);

 73: typedef struct {
 74:   void (*func)(void);
 75:   void *ctx;
 76: } PetscFortranCallback;

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

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

135: #define PETSCHEADER(ObjectOps) \
136:   _p_PetscObject hdr;          \
137:   ObjectOps      ops[1]

139: #define  PETSCFREEDHEADER -1

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

144: /*@C
145:     PetscHeaderCreate - Creates a PETSc object of a particular class

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

156:     Output Parameter:
157: .   h - the newly created object

159:     Level: developer

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

163: @*/
164: #define PetscHeaderCreate(h,classid,class_name,descr,mansec,comm,destroy,view) \
165:   (PetscNew(&(h)) || \
166:    PetscHeaderCreate_Private((PetscObject)h,classid,class_name,descr,mansec,comm,(PetscObjectDestroyFunction)destroy,(PetscObjectViewFunction)view) || \
167:    PetscLogObjectCreate(h) || \
168:    PetscLogObjectMemory((PetscObject)h,sizeof(*(h))))

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

173: /*@C
174:     PetscHeaderDestroy - Final step in destroying a PetscObject

176:     Input Parameters:
177: .   h - the header created with PetscHeaderCreate()

179:     Level: developer

181: .seealso: PetscHeaderCreate()
182: @*/
183: #define PetscHeaderDestroy(h) (PetscHeaderDestroy_Private((PetscObject)(*h)) || PetscFree(*h))

185: PETSC_EXTERN PetscErrorCode PetscHeaderDestroy_Private(PetscObject);
186: PETSC_EXTERN PetscErrorCode PetscObjectCopyFortranFunctionPointers(PetscObject,PetscObject);
187: PETSC_EXTERN PetscErrorCode PetscObjectSetFortranCallback(PetscObject,PetscFortranCallbackType,PetscFortranCallbackId*,void(*)(void),void *ctx);
188: PETSC_EXTERN PetscErrorCode PetscObjectGetFortranCallback(PetscObject,PetscFortranCallbackType,PetscFortranCallbackId,void(**)(void),void **ctx);

190: PETSC_INTERN PetscErrorCode PetscCitationsInitialize(void);
191: PETSC_INTERN PetscErrorCode PetscOptionsFindPair_Private(PetscOptions,const char[],const char[],char**,PetscBool*);
192: PETSC_INTERN PetscErrorCode PetscFreeMPIResources(void);




198: /*
199:     Macros to test if a PETSc object is valid and if pointers are valid
200: */
201: #if !defined(PETSC_USE_DEBUG)


212: #else

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

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

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

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

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

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

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

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

267: #endif

269: #if !defined(PETSC_USE_DEBUG)


284: #else

286: /*
287:     For example, in the dot product between two vectors,
288:   both vectors must be either Seq or MPI, not one of each
289: */
291:   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);
292: /*
293:     Check type_name
294: */
296:   do {                                                                  \
297:     PetscBool      __match;                                             \
298:     PetscErrorCode _7_ierr;                                             \
299:     _7_PetscObjectTypeCompare(((PetscObject)a),(type),&__match);CHKERRQ(_7_ierr); \
300:     if (!__match) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Object (%s) is not %s",(char*)(((PetscObject)a)->type_name),type); \
301:   } while (0)

304:   do {                                                                  \
305:     PetscBool       __match;                                            \
306:     PetscErrorCode _7_ierr;                                             \
307:     _7_PetscObjectTypeCompareAny(((PetscObject)a),&__match,(type1),(type2),"");CHKERRQ(_7_ierr); \
308:     if (!__match) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Object (%s) is not %s or %s",(char*)(((PetscObject)a)->type_name),type1,type2); \
309:   } while (0)
310: /*
311:    Use this macro to check if the type is set
312: */
314:   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);
315: /*
316:    Sometimes object must live on same communicator to inter-operate
317: */
319:   do {                                                                  \
320:     PetscErrorCode _6_ierr,__flag;                                      \
321:     _6_MPI_Comm_compare(PetscObjectComm((PetscObject)a),PetscObjectComm((PetscObject)b),&__flag);CHKERRQ(_6_ierr);                                                   \
322:     if (__flag != MPI_CONGRUENT && __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,__flag); \
323:   } while (0)

326:   do {                                                  \
329:   } while (0)

332:   do {                                                                  \
333:     PetscErrorCode _7_ierr;                                             \
334:     PetscReal b1[5],b2[5];                                              \
335:     if (PetscIsNanScalar(b)) {b1[4] = 1;} else {b1[4] = 0;};            \
336:     b1[0] = -PetscRealPart(b); b1[1] = PetscRealPart(b);b1[2] = -PetscImaginaryPart(b); b1[3] = PetscImaginaryPart(b);         \
337:     _7_MPI_Allreduce(b1,b2,5,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)a));CHKERRQ(_7_ierr); \
338:     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",c); \
339:   } while (0)

342:   do {                                                                  \
343:     PetscErrorCode _7_ierr;                                             \
344:     PetscReal b1[3],b2[3];                                              \
345:     if (PetscIsNanReal(b)) {b1[2] = 1;} else {b1[2] = 0;};              \
346:     b1[0] = -b; b1[1] = b;                                              \
347:     _7_MPI_Allreduce(b1,b2,3,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)a));CHKERRQ(_7_ierr); \
348:     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",c); \
349:   } while (0)

352:   do {                                                                  \
353:     PetscErrorCode _7_ierr;                                             \
354:     PetscInt b1[2],b2[2];                                               \
355:     b1[0] = -b; b1[1] = b;                                              \
356:     _7_MPIU_Allreduce(b1,b2,2,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)a));CHKERRQ(_7_ierr); \
357:     if (-b2[0] != b2[1]) SETERRQ1(PetscObjectComm((PetscObject)a),PETSC_ERR_ARG_WRONG,"Int value must be same on all processes, argument # %d",c); \
358:   } while (0)


363:   do {                                                                  \
364:     PetscErrorCode _7_ierr;                                             \
365:     PetscMPIInt b1[2],b2[2];                                            \
366:     b1[0] = -(PetscMPIInt)b; b1[1] = (PetscMPIInt)b;                    \
367:     _7_MPIU_Allreduce(b1,b2,2,MPI_INT,MPI_MAX,PetscObjectComm((PetscObject)a));CHKERRQ(_7_ierr); \
368:     if (-b2[0] != b2[1]) SETERRQ1(PetscObjectComm((PetscObject)a),PETSC_ERR_ARG_WRONG,"Bool value must be same on all processes, argument # %d",c); \
369:   } while (0)

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

380: #endif

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

386:    Level: developer

388: .seealso: PetscUseMethod()
389: */
390: #define  PetscTryMethod(obj,A,B,C) \
391:   0;{ PetscErrorCode (*f)B, __ierr; \
392:     __PetscObjectQueryFunction((PetscObject)obj,A,&f);CHKERRQ(__ierr); \
393:     if (f) {__(*f)C;CHKERRQ(__ierr);}\
394:   }

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

400:    Level: developer

402: .seealso: PetscTryMethod()
403: */
404: #define  PetscUseMethod(obj,A,B,C) \
405:   0;{ PetscErrorCode (*f)B, __ierr; \
406:     __PetscObjectQueryFunction((PetscObject)obj,A,&f);CHKERRQ(__ierr); \
407:     if (f) {__(*f)C;CHKERRQ(__ierr);}\
408:     else SETERRQ1(PetscObjectComm((PetscObject)obj),PETSC_ERR_SUP,"Cannot locate function %s in object",A); \
409:   }

411: /*MC
412:    PetscObjectStateIncrease - Increases the state of any PetscObject

414:    Synopsis:
415:    #include "petsc/private/petscimpl.h"
416:    PetscErrorCode PetscObjectStateIncrease(PetscObject obj)

418:    Logically Collective

420:    Input Parameter:
421: .  obj - any PETSc object, for example a Vec, Mat or KSP. This must be
422:          cast with a (PetscObject), for example,
423:          PetscObjectStateIncrease((PetscObject)mat);

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

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

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

437:    Level: developer

439:    seealso: PetscObjectStateGet()

441:    Concepts: state

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

446: PETSC_EXTERN PetscErrorCode PetscObjectStateGet(PetscObject,PetscObjectState*);
447: PETSC_EXTERN PetscErrorCode PetscObjectStateSet(PetscObject,PetscObjectState);
448: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataRegister(PetscInt*);
449: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseInt(PetscObject);
450: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseIntstar(PetscObject);
451: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseReal(PetscObject);
452: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseRealstar(PetscObject);
453: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseScalar(PetscObject);
454: PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseScalarstar(PetscObject);
455: PETSC_EXTERN PetscInt         PetscObjectComposedDataMax;
456: /*MC
457:    PetscObjectComposedDataSetInt - attach integer data to a PetscObject

459:    Synopsis:
460:    #include "petsc/private/petscimpl.h"
461:    PetscErrorCode PetscObjectComposedDataSetInt(PetscObject obj,int id,int data)

463:    Not collective

465:    Input parameters:
466: +  obj - the object to which data is to be attached
467: .  id - the identifier for the data
468: -  data - the data to  be attached

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

473:    Level: developer
474: M*/
475: #define PetscObjectComposedDataSetInt(obj,id,data)                                      \
476:   ((((obj)->int_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseInt(obj)) ||  \
477:    ((obj)->intcomposeddata[id] = data,(obj)->intcomposedstate[id] = (obj)->state, 0))

479: /*MC
480:    PetscObjectComposedDataGetInt - retrieve integer data attached to an object

482:    Synopsis:
483:    #include "petsc/private/petscimpl.h"
484:    PetscErrorCode PetscObjectComposedDataGetInt(PetscObject obj,int id,int data,PetscBool  flag)

486:    Not collective

488:    Input parameters:
489: +  obj - the object from which data is to be retrieved
490: -  id - the identifier for the data

492:    Output parameters
493: +  data - the data to be retrieved
494: -  flag - PETSC_TRUE if the data item exists and is valid, PETSC_FALSE otherwise

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

498:    Level: developer
499: M*/
500: #define PetscObjectComposedDataGetInt(obj,id,data,flag)                            \
501:   ((((obj)->intcomposedstate && ((obj)->intcomposedstate[id] == (obj)->state)) ?   \
502:    (data = (obj)->intcomposeddata[id],flag = PETSC_TRUE) : (flag = PETSC_FALSE)),0)

504: /*MC
505:    PetscObjectComposedDataSetIntstar - attach integer array data to a PetscObject

507:    Synopsis:
508:    #include "petsc/private/petscimpl.h"
509:    PetscErrorCode PetscObjectComposedDataSetIntstar(PetscObject obj,int id,int *data)

511:    Not collective

513:    Input parameters:
514: +  obj - the object to which data is to be attached
515: .  id - the identifier for the data
516: -  data - the data to  be attached

518:    Notes
519:    The data identifier can best be determined through a call to
520:    PetscObjectComposedDataRegister()

522:    Level: developer
523: M*/
524: #define PetscObjectComposedDataSetIntstar(obj,id,data)                                          \
525:   ((((obj)->intstar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseIntstar(obj)) ||  \
526:    ((obj)->intstarcomposeddata[id] = data,(obj)->intstarcomposedstate[id] = (obj)->state, 0))

528: /*MC
529:    PetscObjectComposedDataGetIntstar - retrieve integer array data
530:    attached to an object

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

536:    Not collective

538:    Input parameters:
539: +  obj - the object from which data is to be retrieved
540: -  id - the identifier for the data

542:    Output parameters
543: +  data - the data to be retrieved
544: -  flag - PETSC_TRUE if the data item exists and is valid, PETSC_FALSE otherwise

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

548:    Level: developer
549: M*/
550: #define PetscObjectComposedDataGetIntstar(obj,id,data,flag)                               \
551:   ((((obj)->intstarcomposedstate && ((obj)->intstarcomposedstate[id] == (obj)->state)) ?  \
552:    (data = (obj)->intstarcomposeddata[id],flag = PETSC_TRUE) : (flag = PETSC_FALSE)),0)

554: /*MC
555:    PetscObjectComposedDataSetReal - attach real data to a PetscObject

557:    Synopsis:
558:    #include "petsc/private/petscimpl.h"
559:    PetscErrorCode PetscObjectComposedDataSetReal(PetscObject obj,int id,PetscReal data)

561:    Not collective

563:    Input parameters:
564: +  obj - the object to which data is to be attached
565: .  id - the identifier for the data
566: -  data - the data to  be attached

568:    Notes
569:    The data identifier can best be determined through a call to
570:    PetscObjectComposedDataRegister()

572:    Level: developer
573: M*/
574: #define PetscObjectComposedDataSetReal(obj,id,data)                                       \
575:   ((((obj)->real_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseReal(obj)) ||  \
576:    ((obj)->realcomposeddata[id] = data,(obj)->realcomposedstate[id] = (obj)->state, 0))

578: /*MC
579:    PetscObjectComposedDataGetReal - retrieve real data attached to an object

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

585:    Not collective

587:    Input parameters:
588: +  obj - the object from which data is to be retrieved
589: -  id - the identifier for the data

591:    Output parameters
592: +  data - the data to be retrieved
593: -  flag - PETSC_TRUE if the data item exists and is valid, PETSC_FALSE otherwise

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

597:    Level: developer
598: M*/
599: #define PetscObjectComposedDataGetReal(obj,id,data,flag)                            \
600:   ((((obj)->realcomposedstate && ((obj)->realcomposedstate[id] == (obj)->state)) ?  \
601:    (data = (obj)->realcomposeddata[id],flag = PETSC_TRUE) : (flag = PETSC_FALSE)),0)

603: /*MC
604:    PetscObjectComposedDataSetRealstar - attach real array data to a PetscObject

606:    Synopsis:
607:    #include "petsc/private/petscimpl.h"
608:    PetscErrorCode PetscObjectComposedDataSetRealstar(PetscObject obj,int id,PetscReal *data)

610:    Not collective

612:    Input parameters:
613: +  obj - the object to which data is to be attached
614: .  id - the identifier for the data
615: -  data - the data to  be attached

617:    Notes
618:    The data identifier can best be determined through a call to
619:    PetscObjectComposedDataRegister()

621:    Level: developer
622: M*/
623: #define PetscObjectComposedDataSetRealstar(obj,id,data)                                           \
624:   ((((obj)->realstar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseRealstar(obj)) ||  \
625:    ((obj)->realstarcomposeddata[id] = data, (obj)->realstarcomposedstate[id] = (obj)->state, 0))

627: /*MC
628:    PetscObjectComposedDataGetRealstar - retrieve real array data
629:    attached to an object

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

635:    Not collective

637:    Input parameters:
638: +  obj - the object from which data is to be retrieved
639: -  id - the identifier for the data

641:    Output parameters
642: +  data - the data to be retrieved
643: -  flag - PETSC_TRUE if the data item exists and is valid, PETSC_FALSE otherwise

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

647:    Level: developer
648: M*/
649: #define PetscObjectComposedDataGetRealstar(obj,id,data,flag)                                \
650:   ((((obj)->realstarcomposedstate && ((obj)->realstarcomposedstate[id] == (obj)->state)) ?  \
651:    (data = (obj)->realstarcomposeddata[id],flag = PETSC_TRUE) : (flag = PETSC_FALSE)),0)

653: /*MC
654:    PetscObjectComposedDataSetScalar - attach scalar data to a PetscObject

656:    Synopsis:
657:    #include "petsc/private/petscimpl.h"
658:    PetscErrorCode PetscObjectComposedDataSetScalar(PetscObject obj,int id,PetscScalar data)

660:    Not collective

662:    Input parameters:
663: +  obj - the object to which data is to be attached
664: .  id - the identifier for the data
665: -  data - the data to  be attached

667:    Notes
668:    The data identifier can best be determined through a call to
669:    PetscObjectComposedDataRegister()

671:    Level: developer
672: M*/
673: #if defined(PETSC_USE_COMPLEX)
674: #define PetscObjectComposedDataSetScalar(obj,id,data)                                        \
675:   ((((obj)->scalar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseScalar(obj)) || \
676:    ((obj)->scalarcomposeddata[id] = data,(obj)->scalarcomposedstate[id] = (obj)->state, 0))
677: #else
678: #define PetscObjectComposedDataSetScalar(obj,id,data) \
679:         PetscObjectComposedDataSetReal(obj,id,data)
680: #endif
681: /*MC
682:    PetscObjectComposedDataGetScalar - retrieve scalar data attached to an object

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

688:    Not collective

690:    Input parameters:
691: +  obj - the object from which data is to be retrieved
692: -  id - the identifier for the data

694:    Output parameters
695: +  data - the data to be retrieved
696: -  flag - PETSC_TRUE if the data item exists and is valid, PETSC_FALSE otherwise

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

700:    Level: developer
701: M*/
702: #if defined(PETSC_USE_COMPLEX)
703: #define PetscObjectComposedDataGetScalar(obj,id,data,flag)                              \
704:   ((((obj)->scalarcomposedstate && ((obj)->scalarcomposedstate[id] == (obj)->state) ) ? \
705:    (data = (obj)->scalarcomposeddata[id],flag = PETSC_TRUE) : (flag = PETSC_FALSE)),0)
706: #else
707: #define PetscObjectComposedDataGetScalar(obj,id,data,flag)                             \
708:         PetscObjectComposedDataGetReal(obj,id,data,flag)
709: #endif

711: /*MC
712:    PetscObjectComposedDataSetScalarstar - attach scalar array data to a PetscObject

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

718:    Not collective

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

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

729:    Level: developer
730: M*/
731: #if defined(PETSC_USE_COMPLEX)
732: #define PetscObjectComposedDataSetScalarstar(obj,id,data)                                             \
733:   ((((obj)->scalarstar_idmax < PetscObjectComposedDataMax) && PetscObjectComposedDataIncreaseScalarstar(obj)) ||  \
734:    ((obj)->scalarstarcomposeddata[id] = data,(obj)->scalarstarcomposedstate[id] = (obj)->state, 0))
735: #else
736: #define PetscObjectComposedDataSetScalarstar(obj,id,data) \
737:         PetscObjectComposedDataSetRealstar(obj,id,data)
738: #endif
739: /*MC
740:    PetscObjectComposedDataGetScalarstar - retrieve scalar array data
741:    attached to an object

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

747:    Not collective

749:    Input parameters:
750: +  obj - the object from which data is to be retrieved
751: -  id - the identifier for the data

753:    Output parameters
754: +  data - the data to be retrieved
755: -  flag - PETSC_TRUE if the data item exists and is valid, PETSC_FALSE otherwise

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

759:    Level: developer
760: M*/
761: #if defined(PETSC_USE_COMPLEX)
762: #define PetscObjectComposedDataGetScalarstar(obj,id,data,flag)                                 \
763:   ((((obj)->scalarstarcomposedstate && ((obj)->scalarstarcomposedstate[id] == (obj)->state)) ? \
764:        (data = (obj)->scalarstarcomposeddata[id],flag = PETSC_TRUE) : (flag = PETSC_FALSE)),0)
765: #else
766: #define PetscObjectComposedDataGetScalarstar(obj,id,data,flag)         \
767:         PetscObjectComposedDataGetRealstar(obj,id,data,flag)
768: #endif

770: PETSC_EXTERN PetscErrorCode PetscObjectGetId(PetscObject,PetscObjectId*);

772: PETSC_EXTERN PetscErrorCode PetscMonitorCompare(PetscErrorCode (*)(void),void *,PetscErrorCode (*)(void**),PetscErrorCode (*)(void),void *,PetscErrorCode (*)(void**),PetscBool *);

774: PETSC_EXTERN PetscMPIInt Petsc_Counter_keyval;
775: PETSC_EXTERN PetscMPIInt Petsc_InnerComm_keyval;
776: PETSC_EXTERN PetscMPIInt Petsc_OuterComm_keyval;
777: PETSC_EXTERN PetscMPIInt Petsc_Seq_keyval;

779: /*
780:   PETSc communicators have this attribute, see
781:   PetscCommDuplicate(), PetscCommDestroy(), PetscCommGetNewTag(), PetscObjectGetName()
782: */
783: typedef struct {
784:   PetscMPIInt tag;              /* next free tag value */
785:   PetscInt    refcount;         /* number of references, communicator can be freed when this reaches 0 */
786:   PetscInt    namecount;        /* used to generate the next name, as in Vec_0, Mat_1, ... */
787: } PetscCommCounter;

789: #if defined(PETSC_HAVE_CUSP)
790: /*E
791:     PetscCUSPFlag - indicates which memory (CPU, GPU, or none contains valid vector

793:    PETSC_CUSP_UNALLOCATED  - no memory contains valid matrix entries; NEVER used for vectors
794:    PETSC_CUSP_GPU - GPU has valid vector/matrix entries
795:    PETSC_CUSP_CPU - CPU has valid vector/matrix entries
796:    PETSC_CUSP_BOTH - Both GPU and CPU have valid vector/matrix entries and they match

798:    Level: developer
799: E*/
800: typedef enum {PETSC_CUSP_UNALLOCATED,PETSC_CUSP_GPU,PETSC_CUSP_CPU,PETSC_CUSP_BOTH} PetscCUSPFlag;
801: #elif defined(PETSC_HAVE_VIENNACL)
802: /*E
803:     PetscViennaCLFlag - indicates which memory (CPU, GPU, or none contains valid vector

805:    PETSC_VIENNACL_UNALLOCATED  - no memory contains valid matrix entries; NEVER used for vectors
806:    PETSC_VIENNACL_GPU - GPU has valid vector/matrix entries
807:    PETSC_VIENNACL_CPU - CPU has valid vector/matrix entries
808:    PETSC_VIENNACL_BOTH - Both GPU and CPU have valid vector/matrix entries and they match

810:    Level: developer
811: E*/
812: typedef enum {PETSC_VIENNACL_UNALLOCATED,PETSC_VIENNACL_GPU,PETSC_VIENNACL_CPU,PETSC_VIENNACL_BOTH} PetscViennaCLFlag;
813: #elif defined(PETSC_HAVE_VECCUDA)
814: /*E
815:     PetscCUDAFlag - indicates which memory (CPU, GPU, or none contains valid vector

817:    PETSC_CUDA_UNALLOCATED  - no memory contains valid matrix entries; NEVER used for vectors
818:    PETSC_CUDA_GPU - GPU has valid vector/matrix entries
819:    PETSC_CUDA_CPU - CPU has valid vector/matrix entries
820:    PETSC_CUDA_BOTH - Both GPU and CPU have valid vector/matrix entries and they match

822:    Level: developer
823: E*/
824: typedef enum {PETSC_CUDA_UNALLOCATED,PETSC_CUDA_GPU,PETSC_CUDA_CPU,PETSC_CUDA_BOTH} PetscCUDAFlag;
825: #endif

827: #if defined(PETSC_HAVE_CUSP) || defined(PETSC_HAVE_VECCUDA)
828: PETSC_EXTERN cublasHandle_t cublasv2handle;
829: #endif

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

833: #define REDUCE_SUM  0
834: #define REDUCE_MAX  1
835: #define REDUCE_MIN  2

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

851: PETSC_EXTERN PetscErrorCode PetscSplitReductionGet(MPI_Comm,PetscSplitReduction**);
852: PETSC_EXTERN PetscErrorCode PetscSplitReductionEnd(PetscSplitReduction*);
853: PETSC_EXTERN PetscErrorCode PetscSplitReductionExtend(PetscSplitReduction*);

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

888: #include <omp.h>
889: typedef omp_lock_t PetscSpinlock;
890: PETSC_STATIC_INLINE PetscErrorCode PetscSpinlockCreate(PetscSpinlock *omp_lock)
891: {
892:   omp_init_lock(omp_lock);
893:   return 0;
894: }
895: PETSC_STATIC_INLINE PetscErrorCode PetscSpinlockLock(PetscSpinlock *omp_lock)
896: {
897:   omp_set_lock(omp_lock);
898:   return 0;
899: }
900: PETSC_STATIC_INLINE PetscErrorCode PetscSpinlockUnlock(PetscSpinlock *omp_lock)
901: {
902:   omp_unset_lock(omp_lock);
903:   return 0;
904: }
905: PETSC_STATIC_INLINE PetscErrorCode PetscSpinlockDestroy(PetscSpinlock *omp_lock)
906: {
907:   omp_destroy_lock(omp_lock);
908:   return 0;
909: }
910: #else
911: Thread safety requires either --with-openmp or --download-concurrencykit
912: #endif

914: #else
915: typedef int PetscSpinlock;
916: #define PetscSpinlockCreate(a)  0
917: #define PetscSpinlockLock(a)    0
918: #define PetscSpinlockUnlock(a)  0
919: #define PetscSpinlockDestroy(a) 0
920: #endif

922: #if defined(PETSC_HAVE_THREADSAFETY)
923: extern PetscSpinlock PetscViewerASCIISpinLockOpen;
924: extern PetscSpinlock PetscViewerASCIISpinLockStdout;
925: extern PetscSpinlock PetscViewerASCIISpinLockStderr;
926: extern PetscSpinlock PetscCommSpinLock;
927: #endif
928: #endif

930: #endif /* _PETSCHEAD_H */