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 Parameter:
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 Arguments:
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],newnum = PetscMax(1,2*oldnum);
220:     PetscFortranCallback *callback;
221:     PetscMalloc1(newnum,&callback);
222:     PetscMemcpy(callback,obj->fortrancallback[cbtype],oldnum*sizeof(*obj->fortrancallback[cbtype]));
223:     PetscFree(obj->fortrancallback[cbtype]);

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

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

236:    Logically Collective

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

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

247:    Level: developer

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

257:   if (PetscUnlikely(cid < PETSC_SMALLEST_FORTRAN_CALLBACK)) SETERRQ(obj->comm,PETSC_ERR_ARG_CORRUPT,"Fortran callback Id invalid");
258:   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");
259:   cb = &obj->fortrancallback[cbtype][cid-PETSC_SMALLEST_FORTRAN_CALLBACK];
260:   if (func) *func = cb->func;
261:   if (ctx) *ctx = cb->ctx;
262:   return(0);
263: }

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

269:    Logically Collective on PetscViewer

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

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

278:    Level: advanced

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

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

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

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

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

338: #if defined(PETSC_USE_LOG)

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

343:    Logically Collective on PetscViewer

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

348:    Level: advanced

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

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

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

369:    Not collective

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

374:    Output Parameter:
375: .   obj - the object or null if there is no object

377:    Level: advanced

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

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

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

407:    Input Parameters:
408: .  obj  - the PetscObject

410:    Level: developer

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

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

425: /*@
426:    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.

428:    Input Parameters:
429: +  pobj - the parent object
430: -  obj  - the PetscObject

432:    Level: developer

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

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

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

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

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

457:     Not Collective

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

465:     Level: developer


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

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

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

485:     Not Collective

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

490:     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


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

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

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


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

545:    Logically Collective on PetscObject

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

551:    Level: advanced

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

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

568:    Not Collective

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

574:    Output Parameter:
575: .  cnt - the reference count

577:    Level: advanced

579: .seealso: PetscObjectCompose(), PetscObjectDereference(), PetscObjectReference()
580: @*/
581: PetscErrorCode  PetscObjectGetReference(PetscObject obj,PetscInt *cnt)
582: {
586:   *cnt = obj->refct;
587:   return(0);
588: }

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

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

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

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

604:    Level: advanced

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

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

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

634: PetscErrorCode PetscObjectRemoveReference(PetscObject obj,const char name[])
635: {

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

644: PetscErrorCode PetscObjectCompose_Petsc(PetscObject obj,const char name[],PetscObject ptr)
645: {
647:   char           *tname;
648:   PetscBool      skipreference;

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

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

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

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

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

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

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

689: /*@C
690:    PetscObjectCompose - Associates another PETSc object with a given PETSc object.

692:    Not Collective

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

701:    Level: advanced

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

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

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

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


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

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

733: /*@C
734:    PetscObjectQuery  - Gets a PETSc object associated with a given object.

736:    Not Collective

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

746:    Level: advanced

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


751: .seealso: PetscObjectCompose(), PetscObjectComposeFunction(), PetscObjectQueryFunction()
752: @*/
753: PetscErrorCode  PetscObjectQuery(PetscObject obj,const char name[],PetscObject *ptr)
754: {

761:   (*obj->bops->query)(obj,name,ptr);
762:   return(0);
763: }

765: /*MC
766:    PetscObjectComposeFunction - Associates a function with a given PETSc object.

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

772:    Logically Collective on PetscObject

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

781:    Level: advanced

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

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

789: .seealso: PetscObjectQueryFunction(), PetscContainerCreate() PetscObjectCompose(), PetscObjectQuery()
790: M*/

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

799:   (*obj->bops->composefunction)(obj,name,fptr);
800:   return(0);
801: }

803: /*MC
804:    PetscObjectQueryFunction - Gets a function associated with a given object.

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

810:    Logically Collective on PetscObject

812:    Input Parameters:
813: +  obj - the PETSc object; this must be cast with (PetscObject), for example,
814:          PetscObjectQueryFunction((PetscObject)ksp,...);
815: -  name - name associated with the child function

817:    Output Parameter:
818: .  fptr - function pointer

820:    Level: advanced

822: .seealso: PetscObjectComposeFunction(), PetscFunctionListFind(), PetscObjectCompose(), PetscObjectQuery()
823: M*/
824: PETSC_EXTERN PetscErrorCode PetscObjectQueryFunction_Private(PetscObject obj,const char name[],void (**ptr)(void))
825: {

831:   (*obj->bops->queryfunction)(obj,name,ptr);
832:   return(0);
833: }

835: struct _p_PetscContainer {
836:   PETSCHEADER(int);
837:   void           *ptr;
838:   PetscErrorCode (*userdestroy)(void*);
839: };

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

844:    Logically Collective on PetscContainer

846:    Input Parameter:
847: .  ctx - pointer to user-provided data

849:    Level: advanced

851: .seealso: PetscContainerDestroy(), PetscContainerSetUserDestroy()
852: @*/
853: PetscErrorCode PetscContainerUserDestroyDefault(void* ctx)
854: {

858:   PetscFree(ctx);
859:   return(0);
860: }

862: /*@C
863:    PetscContainerGetPointer - Gets the pointer value contained in the container.

865:    Not Collective

867:    Input Parameter:
868: .  obj - the object created with PetscContainerCreate()

870:    Output Parameter:
871: .  ptr - the pointer value

873:    Level: advanced

875: .seealso: PetscContainerCreate(), PetscContainerDestroy(),
876:           PetscContainerSetPointer()
877: @*/
878: PetscErrorCode  PetscContainerGetPointer(PetscContainer obj,void **ptr)
879: {
883:   *ptr = obj->ptr;
884:   return(0);
885: }


888: /*@C
889:    PetscContainerSetPointer - Sets the pointer value contained in the container.

891:    Logically Collective on PetscContainer

893:    Input Parameters:
894: +  obj - the object created with PetscContainerCreate()
895: -  ptr - the pointer value

897:    Level: advanced

899: .seealso: PetscContainerCreate(), PetscContainerDestroy(),
900:           PetscContainerGetPointer()
901: @*/
902: PetscErrorCode  PetscContainerSetPointer(PetscContainer obj,void *ptr)
903: {
907:   obj->ptr = ptr;
908:   return(0);
909: }

911: /*@C
912:    PetscContainerDestroy - Destroys a PETSc container object.

914:    Collective on PetscContainer

916:    Input Parameter:
917: .  obj - an object that was created with PetscContainerCreate()

919:    Level: advanced

921: .seealso: PetscContainerCreate(), PetscContainerSetUserDestroy()
922: @*/
923: PetscErrorCode  PetscContainerDestroy(PetscContainer *obj)
924: {

928:   if (!*obj) return(0);
930:   if (--((PetscObject)(*obj))->refct > 0) {*obj = NULL; return(0);}
931:   if ((*obj)->userdestroy) { (*(*obj)->userdestroy)((*obj)->ptr); }
932:   PetscHeaderDestroy(obj);
933:   return(0);
934: }

936: /*@C
937:    PetscContainerSetUserDestroy - Sets name of the user destroy function.

939:    Logically Collective on PetscContainer

941:    Input Parameter:
942: +  obj - an object that was created with PetscContainerCreate()
943: -  des - name of the user destroy function

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

948:    Level: advanced

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

960: PetscClassId PETSC_CONTAINER_CLASSID;

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

968:    Collective

970:    Input Parameters:
971: .  comm - MPI communicator that shares the object

973:    Output Parameters:
974: .  container - the container created

976:    Level: advanced

978: .seealso: PetscContainerDestroy(), PetscContainerSetPointer(), PetscContainerGetPointer(), PetscObjectCompose(), PetscObjectQuery()
979: @*/
980: PetscErrorCode  PetscContainerCreate(MPI_Comm comm,PetscContainer *container)
981: {
983:   PetscContainer contain;

987:   PetscSysInitializePackage();
988:   PetscHeaderCreate(contain,PETSC_CONTAINER_CLASSID,"PetscContainer","Container","Sys",comm,PetscContainerDestroy,NULL);
989:   *container = contain;
990:   return(0);
991: }

993: /*@
994:    PetscObjectSetFromOptions - Sets generic parameters from user options.

996:    Collective on obj

998:    Input Parameter:
999: .  obj - the PetscObjcet

1001:    Options Database Keys:

1003:    Notes:
1004:    We have no generic options at present, so this does nothing

1006:    Level: beginner

1008: .seealso: PetscObjectSetOptionsPrefix(), PetscObjectGetOptionsPrefix()
1009: @*/
1010: PetscErrorCode  PetscObjectSetFromOptions(PetscObject obj)
1011: {
1014:   return(0);
1015: }

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

1020:    Collective on PetscObject

1022:    Input Parameters:
1023: .  obj - the PetscObject

1025:    Notes:
1026:    This does nothing at present.

1028:    Level: advanced

1030: .seealso: PetscObjectDestroy()
1031: @*/
1032: PetscErrorCode  PetscObjectSetUp(PetscObject obj)
1033: {
1036:   return(0);
1037: }