Date: 2022-03-04T17:37:08+00:00

Actual source code: inherit.c

      1: /*
      2:      Provides utility routines for manipulating any type of PETSc object.
      3: */
      4: #include <petsc/private/petscimpl.h>
      5: #include <petscviewer.h>

      7: #if defined(PETSC_USE_LOG)
      8: PETSC_INTERN PetscObject *PetscObjects;
      9: PETSC_INTERN PetscInt    PetscObjectsCounts;
     10: PETSC_INTERN PetscInt    PetscObjectsMaxCounts;
     11: PETSC_INTERN PetscBool   PetscObjectsLog;
     12: #endif

     14: #if defined(PETSC_USE_LOG)
     15: PetscObject *PetscObjects      = NULL;
     16: PetscInt    PetscObjectsCounts = 0, PetscObjectsMaxCounts = 0;
     17: PetscBool   PetscObjectsLog    = PETSC_FALSE;
     18: #endif

     20: PETSC_EXTERN PetscErrorCode PetscObjectGetComm_Petsc(PetscObject,MPI_Comm*);
     21: PETSC_EXTERN PetscErrorCode PetscObjectCompose_Petsc(PetscObject,const char[],PetscObject);
     22: PETSC_EXTERN PetscErrorCode PetscObjectQuery_Petsc(PetscObject,const char[],PetscObject*);
     23: PETSC_EXTERN PetscErrorCode PetscObjectComposeFunction_Petsc(PetscObject,const char[],void (*)(void));
     24: PETSC_EXTERN PetscErrorCode PetscObjectQueryFunction_Petsc(PetscObject,const char[],void (**)(void));

     26: /*
     27:    PetscHeaderCreate_Private - Creates a base PETSc object header and fills
     28:    in the default values.  Called by the macro PetscHeaderCreate().
     29: */
     30: PetscErrorCode  PetscHeaderCreate_Private(PetscObject h,PetscClassId classid,const char class_name[],const char descr[],const char mansec[],
     31:                                           MPI_Comm comm,PetscObjectDestroyFunction destroy,PetscObjectViewFunction view)
     32: {
     33:   static PetscInt idcnt = 1;
     34:   PetscErrorCode  ierr;
     35: #if defined(PETSC_USE_LOG)
     36:   PetscObject     *newPetscObjects;
     37:   PetscInt         newPetscObjectsMaxCounts,i;
     38: #endif

     41:   h->classid               = classid;
     42:   h->type                  = 0;
     43:   h->class_name            = (char*)class_name;
     44:   h->description           = (char*)descr;
     45:   h->mansec                = (char*)mansec;
     46:   h->prefix                = NULL;
     47:   h->refct                 = 1;
     48: #if defined(PETSC_HAVE_SAWS)
     49:   h->amsmem                = PETSC_FALSE;
     50: #endif
     51:   h->id                    = idcnt++;
     52:   h->parentid              = 0;
     53:   h->qlist                 = NULL;
     54:   h->olist                 = NULL;
     55:   h->bops->destroy         = destroy;
     56:   h->bops->view            = view;
     57:   h->bops->getcomm         = PetscObjectGetComm_Petsc;
     58:   h->bops->compose         = PetscObjectCompose_Petsc;
     59:   h->bops->query           = PetscObjectQuery_Petsc;
     60:   h->bops->composefunction = PetscObjectComposeFunction_Petsc;
     61:   h->bops->queryfunction   = PetscObjectQueryFunction_Petsc;

     63:   PetscCommDuplicate(comm,&h->comm,&h->tag);

     65: #if defined(PETSC_USE_LOG)
     66:   /* Keep a record of object created */
     67:   if (PetscObjectsLog) {
     68:     PetscObjectsCounts++;
     69:     for (i=0; i<PetscObjectsMaxCounts; i++) {
     70:       if (!PetscObjects[i]) {
     71:         PetscObjects[i] = h;
     72:         return(0);
     73:       }
     74:     }
     75:     /* Need to increase the space for storing PETSc objects */
     76:     if (!PetscObjectsMaxCounts) newPetscObjectsMaxCounts = 100;
     77:     else                        newPetscObjectsMaxCounts = 2*PetscObjectsMaxCounts;
     78:     PetscCalloc1(newPetscObjectsMaxCounts,&newPetscObjects);
     79:     PetscArraycpy(newPetscObjects,PetscObjects,PetscObjectsMaxCounts);
     80:     PetscFree(PetscObjects);

     82:     PetscObjects                        = newPetscObjects;
     83:     PetscObjects[PetscObjectsMaxCounts] = h;
     84:     PetscObjectsMaxCounts               = newPetscObjectsMaxCounts;
     85:   }
     86: #endif
     87:   return(0);
     88: }

     90: PETSC_INTERN PetscBool      PetscMemoryCollectMaximumUsage;
     91: PETSC_INTERN PetscLogDouble PetscMemoryMaximumUsage;

     93: /*
     94:     PetscHeaderDestroy_Private - Destroys a base PETSc object header. Called by
     95:     the macro PetscHeaderDestroy().
     96: */
     97: PetscErrorCode  PetscHeaderDestroy_Private(PetscObject h)
     98: {

    103:   PetscLogObjectDestroy(h);
    104:   PetscComposedQuantitiesDestroy(h);
    105:   if (PetscMemoryCollectMaximumUsage) {
    106:     PetscLogDouble usage;
    107:     PetscMemoryGetCurrentUsage(&usage);
    108:     if (usage > PetscMemoryMaximumUsage) PetscMemoryMaximumUsage = usage;
    109:   }
    110:   /* first destroy things that could execute arbitrary code */
    111:   if (h->python_destroy) {
    112:     void           *python_context = h->python_context;
    113:     PetscErrorCode (*python_destroy)(void*) = h->python_destroy;
    114:     h->python_context = NULL;
    115:     h->python_destroy = NULL;

    117:     (*python_destroy)(python_context);
    118:   }
    119:   PetscObjectDestroyOptionsHandlers(h);
    120:   PetscObjectListDestroy(&h->olist);
    121:   PetscCommDestroy(&h->comm);
    122:   /* next destroy other things */
    123:   h->classid = PETSCFREEDHEADER;

    125:   PetscFunctionListDestroy(&h->qlist);
    126:   PetscFree(h->type_name);
    127:   PetscFree(h->name);
    128:   PetscFree(h->prefix);
    129:   PetscFree(h->fortran_func_pointers);
    130:   PetscFree(h->fortrancallback[PETSC_FORTRAN_CALLBACK_CLASS]);
    131:   PetscFree(h->fortrancallback[PETSC_FORTRAN_CALLBACK_SUBTYPE]);

    133: #if defined(PETSC_USE_LOG)
    134:   if (PetscObjectsLog) {
    135:     PetscInt i;
    136:     /* Record object removal from list of all objects */
    137:     for (i=0; i<PetscObjectsMaxCounts; i++) {
    138:       if (PetscObjects[i] == h) {
    139:         PetscObjects[i] = NULL;
    140:         PetscObjectsCounts--;
    141:         break;
    142:       }
    143:     }
    144:     if (!PetscObjectsCounts) {
    145:       PetscFree(PetscObjects);
    146:       PetscObjectsMaxCounts = 0;
    147:     }
    148:   }
    149: #endif
    150:   return(0);
    151: }

    153: /*@C
    154:    PetscObjectCopyFortranFunctionPointers - Copy function pointers to another object

    156:    Logically Collective on PetscObject

    158:    Input Parameters:
    159: +  src - source object
    160: -  dest - destination object

    162:    Level: developer

    164:    Note:
    165:    Both objects must have the same class.
    166: @*/
    167: PetscErrorCode PetscObjectCopyFortranFunctionPointers(PetscObject src,PetscObject dest)
    168: {
    170:   PetscInt       cbtype,numcb[PETSC_FORTRAN_CALLBACK_MAXTYPE];

    175:   if (src->classid != dest->classid) SETERRQ(src->comm,PETSC_ERR_ARG_INCOMP,"Objects must be of the same class");

    177:   PetscFree(dest->fortran_func_pointers);
    178:   PetscMalloc(src->num_fortran_func_pointers*sizeof(void(*)(void)),&dest->fortran_func_pointers);
    179:   PetscMemcpy(dest->fortran_func_pointers,src->fortran_func_pointers,src->num_fortran_func_pointers*sizeof(void(*)(void)));

    181:   dest->num_fortran_func_pointers = src->num_fortran_func_pointers;

    183:   PetscFortranCallbackGetSizes(src->classid,&numcb[PETSC_FORTRAN_CALLBACK_CLASS],&numcb[PETSC_FORTRAN_CALLBACK_SUBTYPE]);
    184:   for (cbtype=PETSC_FORTRAN_CALLBACK_CLASS; cbtype<PETSC_FORTRAN_CALLBACK_MAXTYPE; cbtype++) {
    185:     PetscFree(dest->fortrancallback[cbtype]);
    186:     PetscCalloc1(numcb[cbtype],&dest->fortrancallback[cbtype]);
    187:     PetscMemcpy(dest->fortrancallback[cbtype],src->fortrancallback[cbtype],src->num_fortrancallback[cbtype]*sizeof(PetscFortranCallback));
    188:     dest->num_fortrancallback[cbtype] = src->num_fortrancallback[cbtype];
    189:   }
    190:   return(0);
    191: }

    193: /*@C
    194:    PetscObjectSetFortranCallback - set fortran callback function pointer and context

    196:    Logically Collective

    198:    Input Parameters:
    199: +  obj - object on which to set callback
    200: .  cbtype - callback type (class or subtype)
    201: .  cid - address of callback Id, updated if not yet initialized (zero)
    202: .  func - Fortran function
    203: -  ctx - Fortran context

    205:    Level: developer

    207: .seealso: PetscObjectGetFortranCallback()
    208: @*/
    209: PetscErrorCode PetscObjectSetFortranCallback(PetscObject obj,PetscFortranCallbackType cbtype,PetscFortranCallbackId *cid,void (*func)(void),void *ctx)
    210: {
    212:   const char     *subtype = NULL;

    216:   if (cbtype == PETSC_FORTRAN_CALLBACK_SUBTYPE) subtype = obj->type_name;
    217:   if (!*cid) {PetscFortranCallbackRegister(obj->classid,subtype,cid);}
    218:   if (*cid >= PETSC_SMALLEST_FORTRAN_CALLBACK+obj->num_fortrancallback[cbtype]) {
    219:     PetscInt             oldnum = obj->num_fortrancallback[cbtype];
    220:     PetscInt             newnum = PetscMax(*cid - PETSC_SMALLEST_FORTRAN_CALLBACK + 1, 2*oldnum);
    221:     PetscFortranCallback *callback;
    222:     PetscMalloc1(newnum,&callback);
    223:     PetscMemcpy(callback,obj->fortrancallback[cbtype],oldnum*sizeof(*obj->fortrancallback[cbtype]));
    224:     PetscFree(obj->fortrancallback[cbtype]);

    226:     obj->fortrancallback[cbtype] = callback;
    227:     obj->num_fortrancallback[cbtype] = newnum;
    228:   }
    229:   obj->fortrancallback[cbtype][*cid-PETSC_SMALLEST_FORTRAN_CALLBACK].func = func;
    230:   obj->fortrancallback[cbtype][*cid-PETSC_SMALLEST_FORTRAN_CALLBACK].ctx = ctx;
    231:   return(0);
    232: }

    234: /*@C
    235:    PetscObjectGetFortranCallback - get fortran callback function pointer and context

    237:    Logically Collective

    239:    Input Parameters:
    240: +  obj - object on which to get callback
    241: .  cbtype - callback type
    242: -  cid - address of callback Id

    244:    Output Parameters:
    245: +  func - Fortran function (or NULL if not needed)
    246: -  ctx - Fortran context (or NULL if not needed)

    248:    Level: developer

    250: .seealso: PetscObjectSetFortranCallback()
    251: @*/
    252: PetscErrorCode PetscObjectGetFortranCallback(PetscObject obj,PetscFortranCallbackType cbtype,PetscFortranCallbackId cid,void (**func)(void),void **ctx)
    253: {
    254:   PetscFortranCallback *cb;

    258:   if (PetscUnlikely(cid < PETSC_SMALLEST_FORTRAN_CALLBACK)) SETERRQ(obj->comm,PETSC_ERR_ARG_CORRUPT,"Fortran callback Id invalid");
    259:   if (PetscUnlikely(cid >= PETSC_SMALLEST_FORTRAN_CALLBACK+obj->num_fortrancallback[cbtype])) SETERRQ(obj->comm,PETSC_ERR_ARG_CORRUPT,"Fortran callback not set on this object");
    260:   cb = &obj->fortrancallback[cbtype][cid-PETSC_SMALLEST_FORTRAN_CALLBACK];
    261:   if (func) *func = cb->func;
    262:   if (ctx) *ctx = cb->ctx;
    263:   return(0);
    264: }

    266: #if defined(PETSC_USE_LOG)
    267: /*@C
    268:    PetscObjectsDump - Prints the currently existing objects.

    270:    Logically Collective on PetscViewer

    272:    Input Parameters:
    273: +  fd - file pointer
    274: -  all - by default only tries to display objects created explicitly by the user, if all is PETSC_TRUE then lists all outstanding objects

    276:    Options Database:
    277: .  -objects_dump <all> - print information about all the objects that exist at the end of the programs run

    279:    Level: advanced

    281: @*/
    282: PetscErrorCode  PetscObjectsDump(FILE *fd,PetscBool all)
    283: {
    285:   PetscInt       i;
    286: #if defined(PETSC_USE_DEBUG)
    287:   PetscInt       j,k=0;
    288: #endif
    289:   PetscObject    h;

    292:   if (PetscObjectsCounts) {
    293:     PetscFPrintf(PETSC_COMM_WORLD,fd,"The following objects were never freed\n");
    294:     PetscFPrintf(PETSC_COMM_WORLD,fd,"-----------------------------------------\n");
    295:     for (i=0; i<PetscObjectsMaxCounts; i++) {
    296:       if ((h = PetscObjects[i])) {
    297:         PetscObjectName(h);
    298:         {
    299: #if defined(PETSC_USE_DEBUG)
    300:         PetscStack *stack = NULL;
    301:         char       *create,*rclass;

    303:         /* if the PETSc function the user calls is not a create then this object was NOT directly created by them */
    304:         PetscMallocGetStack(h,&stack);
    305:         if (stack) {
    306:           k = stack->currentsize-2;
    307:           if (!all) {
    308:             k = 0;
    309:             while (!stack->petscroutine[k]) k++;
    310:             PetscStrstr(stack->function[k],"Create",&create);
    311:             if (!create) {
    312:               PetscStrstr(stack->function[k],"Get",&create);
    313:             }
    314:             PetscStrstr(stack->function[k],h->class_name,&rclass);
    315:             if (!create) continue;
    316:             if (!rclass) continue;
    317:           }
    318:         }
    319: #endif

    321:         PetscFPrintf(PETSC_COMM_WORLD,fd,"[%d] %s %s %s\n",PetscGlobalRank,h->class_name,h->type_name,h->name);

    323: #if defined(PETSC_USE_DEBUG)
    324:         PetscMallocGetStack(h,&stack);
    325:         if (stack) {
    326:           for (j=k; j>=0; j--) {
    327:             fprintf(fd,"      [%d]  %s() in %s\n",PetscGlobalRank,stack->function[j],stack->file[j]);
    328:           }
    329:         }
    330: #endif
    331:         }
    332:       }
    333:     }
    334:   }
    335:   return(0);
    336: }
    337: #endif

    339: #if defined(PETSC_USE_LOG)

    341: /*@C
    342:    PetscObjectsView - Prints the currently existing objects.

    344:    Logically Collective on PetscViewer

    346:    Input Parameter:
    347: .  viewer - must be an PETSCVIEWERASCII viewer

    349:    Level: advanced

    351: @*/
    352: PetscErrorCode  PetscObjectsView(PetscViewer viewer)
    353: {
    355:   PetscBool      isascii;
    356:   FILE           *fd;

    359:   if (!viewer) viewer = PETSC_VIEWER_STDOUT_WORLD;
    360:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);
    361:   if (!isascii) SETERRQ(PetscObjectComm((PetscObject)viewer),PETSC_ERR_SUP,"Only supports ASCII viewer");
    362:   PetscViewerASCIIGetPointer(viewer,&fd);
    363:   PetscObjectsDump(fd,PETSC_TRUE);
    364:   return(0);
    365: }

    367: /*@C
    368:    PetscObjectsGetObject - Get a pointer to a named object

    370:    Not collective

    372:    Input Parameter:
    373: .  name - the name of an object

    375:    Output Parameters:
    376: +  obj - the object or null if there is no object
    377: -  classname - the name of the class

    379:    Level: advanced

    381: @*/
    382: PetscErrorCode  PetscObjectsGetObject(const char *name,PetscObject *obj,char **classname)
    383: {
    385:   PetscInt       i;
    386:   PetscObject    h;
    387:   PetscBool      flg;

    390:   *obj = NULL;
    391:   for (i=0; i<PetscObjectsMaxCounts; i++) {
    392:     if ((h = PetscObjects[i])) {
    393:       PetscObjectName(h);
    394:       PetscStrcmp(h->name,name,&flg);
    395:       if (flg) {
    396:         *obj = h;
    397:         if (classname) *classname = h->class_name;
    398:         return(0);
    399:       }
    400:     }
    401:   }
    402:   return(0);
    403: }
    404: #endif

    406: /*@
    407:    PetscObjectSetPrintedOptions - indicate to an object that it should behave as if it has already printed the help for its options

    409:    Input Parameters:
    410: .  obj  - the PetscObject

    412:    Level: developer

    414:    Developer Notes:
    415:    This is used, for example to prevent sequential objects that are created from a parallel object; such as the KSP created by
    416:    PCBJACOBI from all printing the same help messages to the screen

    418: .seealso: PetscOptionsInsert()
    419: @*/
    420: PetscErrorCode PetscObjectSetPrintedOptions(PetscObject obj)
    421: {
    423:   obj->optionsprinted = PETSC_TRUE;
    424:   return(0);
    425: }

    427: /*@
    428:    PetscObjectInheritPrintedOptions - If the child object is not on the rank 0 process of the parent object and the child is sequential then the child gets it set.

    430:    Input Parameters:
    431: +  pobj - the parent object
    432: -  obj  - the PetscObject

    434:    Level: developer

    436:    Developer Notes:
    437:    This is used, for example to prevent sequential objects that are created from a parallel object; such as the KSP created by
    438:    PCBJACOBI from all printing the same help messages to the screen

    440:    This will not handle more complicated situations like with GASM where children may live on any subset of the parent's processes and overlap

    442: .seealso: PetscOptionsInsert(), PetscObjectSetPrintedOptions()
    443: @*/
    444: PetscErrorCode PetscObjectInheritPrintedOptions(PetscObject pobj,PetscObject obj)
    445: {
    447:   PetscMPIInt    prank,size;

    450:   MPI_Comm_rank(pobj->comm,&prank);
    451:   MPI_Comm_size(obj->comm,&size);
    452:   if (size == 1 && prank > 0) obj->optionsprinted = PETSC_TRUE;
    453:   return(0);
    454: }

    456: /*@C
    457:     PetscObjectAddOptionsHandler - Adds an additional function to check for options when XXXSetFromOptions() is called.

    459:     Not Collective

    461:     Input Parameters:
    462: +   obj - the PETSc object
    463: .   handle - function that checks for options
    464: .   destroy - function to destroy context if provided
    465: -   ctx - optional context for check function

    467:     Level: developer

    469: .seealso: KSPSetFromOptions(), PCSetFromOptions(), SNESSetFromOptions(), PetscObjectProcessOptionsHandlers(), PetscObjectDestroyOptionsHandlers()

    471: @*/
    472: PetscErrorCode PetscObjectAddOptionsHandler(PetscObject obj,PetscErrorCode (*handle)(PetscOptionItems*,PetscObject,void*),PetscErrorCode (*destroy)(PetscObject,void*),void *ctx)
    473: {
    476:   if (obj->noptionhandler >= PETSC_MAX_OPTIONS_HANDLER) SETERRQ(obj->comm,PETSC_ERR_ARG_OUTOFRANGE,"To many options handlers added");
    477:   obj->optionhandler[obj->noptionhandler] = handle;
    478:   obj->optiondestroy[obj->noptionhandler] = destroy;
    479:   obj->optionctx[obj->noptionhandler++]   = ctx;
    480:   return(0);
    481: }

    483: /*@C
    484:     PetscObjectProcessOptionsHandlers - Calls all the options handlers attached to an object

    486:     Not Collective

    488:     Input Parameter:
    489: .   obj - the PETSc object

    491:     Level: developer

    493: .seealso: KSPSetFromOptions(), PCSetFromOptions(), SNESSetFromOptions(), PetscObjectAddOptionsHandler(), PetscObjectDestroyOptionsHandlers()

    495: @*/
    496: PetscErrorCode  PetscObjectProcessOptionsHandlers(PetscOptionItems *PetscOptionsObject,PetscObject obj)
    497: {
    498:   PetscInt       i;

    503:   for (i=0; i<obj->noptionhandler; i++) {
    504:     (*obj->optionhandler[i])(PetscOptionsObject,obj,obj->optionctx[i]);
    505:   }
    506:   return(0);
    507: }

    509: /*@C
    510:     PetscObjectDestroyOptionsHandlers - Destroys all the option handlers attached to an object

    512:     Not Collective

    514:     Input Parameter:
    515: .   obj - the PETSc object

    517:     Level: developer

    519: .seealso: KSPSetFromOptions(), PCSetFromOptions(), SNESSetFromOptions(), PetscObjectAddOptionsHandler(), PetscObjectProcessOptionsHandlers()

    521: @*/
    522: PetscErrorCode  PetscObjectDestroyOptionsHandlers(PetscObject obj)
    523: {
    524:   PetscInt       i;

    529:   for (i=0; i<obj->noptionhandler; i++) {
    530:     if (obj->optiondestroy[i]) {
    531:       (*obj->optiondestroy[i])(obj,obj->optionctx[i]);
    532:     }
    533:   }
    534:   obj->noptionhandler = 0;
    535:   return(0);
    536: }

    538: /*@C
    539:    PetscObjectReference - Indicates to any PetscObject that it is being
    540:    referenced by another PetscObject. This increases the reference
    541:    count for that object by one.

    543:    Logically Collective on PetscObject

    545:    Input Parameter:
    546: .  obj - the PETSc object. This must be cast with (PetscObject), for example,
    547:          PetscObjectReference((PetscObject)mat);

    549:    Level: advanced

    551: .seealso: PetscObjectCompose(), PetscObjectDereference()
    552: @*/
    553: PetscErrorCode  PetscObjectReference(PetscObject obj)
    554: {
    556:   if (!obj) return(0);
    558:   obj->refct++;
    559:   return(0);
    560: }

    562: /*@C
    563:    PetscObjectGetReference - Gets the current reference count for
    564:    any PETSc object.

    566:    Not Collective

    568:    Input Parameter:
    569: .  obj - the PETSc object; this must be cast with (PetscObject), for example,
    570:          PetscObjectGetReference((PetscObject)mat,&cnt);

    572:    Output Parameter:
    573: .  cnt - the reference count

    575:    Level: advanced

    577: .seealso: PetscObjectCompose(), PetscObjectDereference(), PetscObjectReference()
    578: @*/
    579: PetscErrorCode  PetscObjectGetReference(PetscObject obj,PetscInt *cnt)
    580: {
    584:   *cnt = obj->refct;
    585:   return(0);
    586: }

    588: /*@C
    589:    PetscObjectDereference - Indicates to any PetscObject that it is being
    590:    referenced by one less PetscObject. This decreases the reference
    591:    count for that object by one.

    593:    Collective on PetscObject if reference reaches 0 otherwise Logically Collective

    595:    Input Parameter:
    596: .  obj - the PETSc object; this must be cast with (PetscObject), for example,
    597:          PetscObjectDereference((PetscObject)mat);

    599:    Notes:
    600:     PetscObjectDestroy(PetscObject *obj)  sets the obj pointer to null after the call, this routine does not.

    602:    Level: advanced

    604: .seealso: PetscObjectCompose(), PetscObjectReference()
    605: @*/
    606: PetscErrorCode  PetscObjectDereference(PetscObject obj)
    607: {

    611:   if (!obj) return(0);
    613:   if (obj->bops->destroy) {
    614:     (*obj->bops->destroy)(&obj);
    615:   } else if (!--obj->refct) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"This PETSc object does not have a generic destroy routine");
    616:   return(0);
    617: }

    619: /* ----------------------------------------------------------------------- */
    620: /*
    621:      The following routines are the versions private to the PETSc object
    622:      data structures.
    623: */
    624: PetscErrorCode PetscObjectGetComm_Petsc(PetscObject obj,MPI_Comm *comm)
    625: {
    628:   *comm = obj->comm;
    629:   return(0);
    630: }

    632: PetscErrorCode PetscObjectRemoveReference(PetscObject obj,const char name[])
    633: {

    638:   PetscObjectListRemoveReference(&obj->olist,name);
    639:   return(0);
    640: }

    642: PetscErrorCode PetscObjectCompose_Petsc(PetscObject obj,const char name[],PetscObject ptr)
    643: {
    645:   char           *tname;
    646:   PetscBool      skipreference;

    649:   if (ptr) {
    650:     PetscObjectListReverseFind(ptr->olist,obj,&tname,&skipreference);
    651:     if (tname && !skipreference) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"An object cannot be composed with an object that was composed with it");
    652:   }
    653:   PetscObjectListAdd(&obj->olist,name,ptr);
    654:   return(0);
    655: }

    657: PetscErrorCode PetscObjectQuery_Petsc(PetscObject obj,const char name[],PetscObject *ptr)
    658: {

    663:   PetscObjectListFind(obj->olist,name,ptr);
    664:   return(0);
    665: }

    667: PetscErrorCode PetscObjectComposeFunction_Petsc(PetscObject obj,const char name[],void (*ptr)(void))
    668: {

    673:   PetscFunctionListAdd(&obj->qlist,name,ptr);
    674:   return(0);
    675: }

    677: PetscErrorCode PetscObjectQueryFunction_Petsc(PetscObject obj,const char name[],void (**ptr)(void))
    678: {

    683:   PetscFunctionListFind(obj->qlist,name,ptr);
    684:   return(0);
    685: }

    687: /*@C
    688:    PetscObjectCompose - Associates another PETSc object with a given PETSc object.

    690:    Not Collective

    692:    Input Parameters:
    693: +  obj - the PETSc object; this must be cast with (PetscObject), for example,
    694:          PetscObjectCompose((PetscObject)mat,...);
    695: .  name - name associated with the child object
    696: -  ptr - the other PETSc object to associate with the PETSc object; this must also be
    697:          cast with (PetscObject)

    699:    Level: advanced

    701:    Notes:
    702:    The second objects reference count is automatically increased by one when it is
    703:    composed.

    705:    Replaces any previous object that had the same name.

    707:    If ptr is null and name has previously been composed using an object, then that
    708:    entry is removed from the obj.

    710:    PetscObjectCompose() can be used with any PETSc object (such as
    711:    Mat, Vec, KSP, SNES, etc.) or any user-provided object.  See
    712:    PetscContainerCreate() for info on how to create an object from a
    713:    user-provided pointer that may then be composed with PETSc objects.

    715: .seealso: PetscObjectQuery(), PetscContainerCreate(), PetscObjectComposeFunction(), PetscObjectQueryFunction()
    716: @*/
    717: PetscErrorCode  PetscObjectCompose(PetscObject obj,const char name[],PetscObject ptr)
    718: {

    725:   if (obj == ptr) SETERRQ(PetscObjectComm((PetscObject)obj),PETSC_ERR_SUP,"Cannot compose object with itself");
    726:   (*obj->bops->compose)(obj,name,ptr);
    727:   return(0);
    728: }

    730: /*@C
    731:    PetscObjectQuery  - Gets a PETSc object associated with a given object.

    733:    Not Collective

    735:    Input Parameters:
    736: +  obj - the PETSc object
    737:          Thus must be cast with a (PetscObject), for example,
    738:          PetscObjectCompose((PetscObject)mat,...);
    739: .  name - name associated with child object
    740: -  ptr - the other PETSc object associated with the PETSc object, this must be
    741:          cast with (PetscObject*)

    743:    Level: advanced

    745:    The reference count of neither object is increased in this call

    747: .seealso: PetscObjectCompose(), PetscObjectComposeFunction(), PetscObjectQueryFunction()
    748: @*/
    749: PetscErrorCode  PetscObjectQuery(PetscObject obj,const char name[],PetscObject *ptr)
    750: {

    757:   (*obj->bops->query)(obj,name,ptr);
    758:   return(0);
    759: }

    761: /*MC
    762:    PetscObjectComposeFunction - Associates a function with a given PETSc object.

    764:     Synopsis:
    765: #include <petscsys.h>
    766:     PetscErrorCode PetscObjectComposeFunction(PetscObject obj,const char name[],void (*fptr)(void))

    768:    Logically Collective on PetscObject

    770:    Input Parameters:
    771: +  obj - the PETSc object; this must be cast with a (PetscObject), for example,
    772:          PetscObjectCompose((PetscObject)mat,...);
    773: .  name - name associated with the child function
    774: .  fname - name of the function
    775: -  fptr - function pointer

    777:    Level: advanced

    779:    Notes:
    780:    To remove a registered routine, pass in NULL for fptr().

    782:    PetscObjectComposeFunction() can be used with any PETSc object (such as
    783:    Mat, Vec, KSP, SNES, etc.) or any user-provided object.

    785: .seealso: PetscObjectQueryFunction(), PetscContainerCreate() PetscObjectCompose(), PetscObjectQuery()
    786: M*/

    788: PetscErrorCode  PetscObjectComposeFunction_Private(PetscObject obj,const char name[],void (*fptr)(void))
    789: {

    795:   (*obj->bops->composefunction)(obj,name,fptr);
    796:   return(0);
    797: }

    799: /*MC
    800:    PetscObjectQueryFunction - Gets a function associated with a given object.

    802:     Synopsis:
    803: #include <petscsys.h>
    804:     PetscErrorCode PetscObjectQueryFunction(PetscObject obj,const char name[],void (**fptr)(void))

    806:    Logically Collective on PetscObject

    808:    Input Parameters:
    809: +  obj - the PETSc object; this must be cast with (PetscObject), for example,
    810:          PetscObjectQueryFunction((PetscObject)ksp,...);
    811: -  name - name associated with the child function

    813:    Output Parameter:
    814: .  fptr - function pointer

    816:    Level: advanced

    818: .seealso: PetscObjectComposeFunction(), PetscFunctionListFind(), PetscObjectCompose(), PetscObjectQuery()
    819: M*/
    820: PETSC_EXTERN PetscErrorCode PetscObjectQueryFunction_Private(PetscObject obj,const char name[],void (**ptr)(void))
    821: {

    827:   (*obj->bops->queryfunction)(obj,name,ptr);
    828:   return(0);
    829: }

    831: struct _p_PetscContainer {
    832:   PETSCHEADER(int);
    833:   void           *ptr;
    834:   PetscErrorCode (*userdestroy)(void*);
    835: };

    837: /*@C
    838:    PetscContainerUserDestroyDefault - Default destroy routine for user-provided data that simply calls PetscFree().

    840:    Logically Collective on PetscContainer

    842:    Input Parameter:
    843: .  ctx - pointer to user-provided data

    845:    Level: advanced

    847: .seealso: PetscContainerDestroy(), PetscContainerSetUserDestroy()
    848: @*/
    849: PetscErrorCode PetscContainerUserDestroyDefault(void* ctx)
    850: {

    854:   PetscFree(ctx);
    855:   return(0);
    856: }

    858: /*@C
    859:    PetscContainerGetPointer - Gets the pointer value contained in the container.

    861:    Not Collective

    863:    Input Parameter:
    864: .  obj - the object created with PetscContainerCreate()

    866:    Output Parameter:
    867: .  ptr - the pointer value

    869:    Level: advanced

    871: .seealso: PetscContainerCreate(), PetscContainerDestroy(),
    872:           PetscContainerSetPointer()
    873: @*/
    874: PetscErrorCode  PetscContainerGetPointer(PetscContainer obj,void **ptr)
    875: {
    879:   *ptr = obj->ptr;
    880:   return(0);
    881: }

    883: /*@C
    884:    PetscContainerSetPointer - Sets the pointer value contained in the container.

    886:    Logically Collective on PetscContainer

    888:    Input Parameters:
    889: +  obj - the object created with PetscContainerCreate()
    890: -  ptr - the pointer value

    892:    Level: advanced

    894: .seealso: PetscContainerCreate(), PetscContainerDestroy(),
    895:           PetscContainerGetPointer()
    896: @*/
    897: PetscErrorCode  PetscContainerSetPointer(PetscContainer obj,void *ptr)
    898: {
    902:   obj->ptr = ptr;
    903:   return(0);
    904: }

    906: /*@C
    907:    PetscContainerDestroy - Destroys a PETSc container object.

    909:    Collective on PetscContainer

    911:    Input Parameter:
    912: .  obj - an object that was created with PetscContainerCreate()

    914:    Level: advanced

    916: .seealso: PetscContainerCreate(), PetscContainerSetUserDestroy()
    917: @*/
    918: PetscErrorCode  PetscContainerDestroy(PetscContainer *obj)
    919: {

    923:   if (!*obj) return(0);
    925:   if (--((PetscObject)(*obj))->refct > 0) {*obj = NULL; return(0);}
    926:   if ((*obj)->userdestroy) { (*(*obj)->userdestroy)((*obj)->ptr); }
    927:   PetscHeaderDestroy(obj);
    928:   return(0);
    929: }

    931: /*@C
    932:    PetscContainerSetUserDestroy - Sets name of the user destroy function.

    934:    Logically Collective on PetscContainer

    936:    Input Parameters:
    937: +  obj - an object that was created with PetscContainerCreate()
    938: -  des - name of the user destroy function

    940:    Notes:
    941:    Use PetscContainerUserDestroyDefault() if the memory was obtained by calling PetscMalloc or one of its variants for single memory allocation.

    943:    Level: advanced

    945: .seealso: PetscContainerDestroy(), PetscContainerUserDestroyDefault(), PetscMalloc(), PetscMalloc1(), PetscCalloc(), PetscCalloc1()
    946: @*/
    947: PetscErrorCode  PetscContainerSetUserDestroy(PetscContainer obj, PetscErrorCode (*des)(void*))
    948: {
    951:   obj->userdestroy = des;
    952:   return(0);
    953: }

    955: PetscClassId PETSC_CONTAINER_CLASSID;

    957: /*@C
    958:    PetscContainerCreate - Creates a PETSc object that has room to hold
    959:    a single pointer. This allows one to attach any type of data (accessible
    960:    through a pointer) with the PetscObjectCompose() function to a PetscObject.
    961:    The data item itself is attached by a call to PetscContainerSetPointer().

    963:    Collective

    965:    Input Parameters:
    966: .  comm - MPI communicator that shares the object

    968:    Output Parameters:
    969: .  container - the container created

    971:    Level: advanced

    973: .seealso: PetscContainerDestroy(), PetscContainerSetPointer(), PetscContainerGetPointer(), PetscObjectCompose(), PetscObjectQuery()
    974: @*/
    975: PetscErrorCode  PetscContainerCreate(MPI_Comm comm,PetscContainer *container)
    976: {
    978:   PetscContainer contain;

    982:   PetscSysInitializePackage();
    983:   PetscHeaderCreate(contain,PETSC_CONTAINER_CLASSID,"PetscContainer","Container","Sys",comm,PetscContainerDestroy,NULL);
    984:   *container = contain;
    985:   return(0);
    986: }

    988: /*@
    989:    PetscObjectSetFromOptions - Sets generic parameters from user options.

    991:    Collective on obj

    993:    Input Parameter:
    994: .  obj - the PetscObjcet

    996:    Options Database Keys:

    998:    Notes:
    999:    We have no generic options at present, so this does nothing

    1001:    Level: beginner

    1003: .seealso: PetscObjectSetOptionsPrefix(), PetscObjectGetOptionsPrefix()
    1004: @*/
    1005: PetscErrorCode  PetscObjectSetFromOptions(PetscObject obj)
    1006: {
    1009:   return(0);
    1010: }

    1012: /*@
    1013:    PetscObjectSetUp - Sets up the internal data structures for the later use.

    1015:    Collective on PetscObject

    1017:    Input Parameters:
    1018: .  obj - the PetscObject

    1020:    Notes:
    1021:    This does nothing at present.

    1023:    Level: advanced

    1025: .seealso: PetscObjectDestroy()
    1026: @*/
    1027: PetscErrorCode  PetscObjectSetUp(PetscObject obj)
    1028: {
    1031:   return(0);
    1032: }