Actual source code: inherit.c

petsc-3.11.4 2019-09-28
Report Typos and Errors

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

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

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

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

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

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

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

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

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

 92: PETSC_INTERN PetscBool      PetscMemoryCollectMaximumUsage;
 93: PETSC_INTERN PetscLogDouble PetscMemoryMaximumUsage;

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

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

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

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

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

155: /*@C
156:    PetscObjectCopyFortranFunctionPointers - Copy function pointers to another object

158:    Logically Collective on PetscObject

160:    Input Parameter:
161: +  src - source object
162: -  dest - destination object

164:    Level: developer

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

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

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

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

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

195: /*@C
196:    PetscObjectSetFortranCallback - set fortran callback function pointer and context

198:    Logically Collective

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

207:    Level: developer

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

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

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

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

238:    Logically Collective

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

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

249:    Level: developer

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

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

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

271:    Logically Collective on PetscViewer

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

277:    Options Database:
278: .  -objects_dump <all>

280:    Level: advanced

282:    Concepts: options database^printing

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

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

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

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

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

342: #if defined(PETSC_USE_LOG)

344: /*@C
345:    PetscObjectsView - Prints the currently existing objects.

347:    Logically Collective on PetscViewer

349:    Input Parameter:
350: .  viewer - must be an PETSCVIEWERASCII viewer

352:    Level: advanced

354:    Concepts: options database^printing

356: @*/
357: PetscErrorCode  PetscObjectsView(PetscViewer viewer)
358: {
360:   PetscBool      isascii;
361:   FILE           *fd;

364:   if (!viewer) viewer = PETSC_VIEWER_STDOUT_WORLD;
365:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);
366:   if (!isascii) SETERRQ(PetscObjectComm((PetscObject)viewer),PETSC_ERR_SUP,"Only supports ASCII viewer");
367:   PetscViewerASCIIGetPointer(viewer,&fd);
368:   PetscObjectsDump(fd,PETSC_TRUE);
369:   return(0);
370: }

372: /*@C
373:    PetscObjectsGetObject - Get a pointer to a named object

375:    Not collective

377:    Input Parameter:
378: .  name - the name of an object

380:    Output Parameter:
381: .   obj - the object or null if there is no object

383:    Level: advanced

385:    Concepts: options database^printing

387: @*/
388: PetscErrorCode  PetscObjectsGetObject(const char *name,PetscObject *obj,char **classname)
389: {
391:   PetscInt       i;
392:   PetscObject    h;
393:   PetscBool      flg;

396:   *obj = NULL;
397:   for (i=0; i<PetscObjectsMaxCounts; i++) {
398:     if ((h = PetscObjects[i])) {
399:       PetscObjectName(h);
400:       PetscStrcmp(h->name,name,&flg);
401:       if (flg) {
402:         *obj = h;
403:         if (classname) *classname = h->class_name;
404:         return(0);
405:       }
406:     }
407:   }
408:   return(0);
409: }
410: #endif

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

415:    Input Parameters:
416: .  obj  - the PetscObject

418:    Level: developer

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

424: .seealso: PetscOptionsInsert()
425: @*/
426: PetscErrorCode PetscObjectSetPrintedOptions(PetscObject obj)
427: {
429:   obj->optionsprinted = PETSC_TRUE;
430:   return(0);
431: }

433: /*@
434:    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.

436:    Input Parameters:
437: +  pobj - the parent object
438: -  obj  - the PetscObject

440:    Level: developer

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

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

448: .seealso: PetscOptionsInsert(), PetscObjectSetPrintedOptions()
449: @*/
450: PetscErrorCode PetscObjectInheritPrintedOptions(PetscObject pobj,PetscObject obj)
451: {
453:   PetscMPIInt    prank,size;

456:   MPI_Comm_rank(pobj->comm,&prank);
457:   MPI_Comm_size(obj->comm,&size);
458:   if (size == 1 && prank > 0) obj->optionsprinted = PETSC_TRUE;
459:   return(0);
460: }

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

465:     Not Collective

467:     Input Parameter:
468: +   obj - the PETSc object
469: .   handle - function that checks for options
470: .   destroy - function to destroy context if provided
471: -   ctx - optional context for check function

473:     Level: developer


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

478: @*/
479: PetscErrorCode PetscObjectAddOptionsHandler(PetscObject obj,PetscErrorCode (*handle)(PetscOptionItems*,PetscObject,void*),PetscErrorCode (*destroy)(PetscObject,void*),void *ctx)
480: {
483:   if (obj->noptionhandler >= PETSC_MAX_OPTIONS_HANDLER) SETERRQ(obj->comm,PETSC_ERR_ARG_OUTOFRANGE,"To many options handlers added");
484:   obj->optionhandler[obj->noptionhandler] = handle;
485:   obj->optiondestroy[obj->noptionhandler] = destroy;
486:   obj->optionctx[obj->noptionhandler++]   = ctx;
487:   return(0);
488: }

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

493:     Not Collective

495:     Input Parameter:
496: .   obj - the PETSc object

498:     Level: developer


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

503: @*/
504: PetscErrorCode  PetscObjectProcessOptionsHandlers(PetscOptionItems *PetscOptionsObject,PetscObject obj)
505: {
506:   PetscInt       i;

511:   for (i=0; i<obj->noptionhandler; i++) {
512:     (*obj->optionhandler[i])(PetscOptionsObject,obj,obj->optionctx[i]);
513:   }
514:   return(0);
515: }

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

520:     Not Collective

522:     Input Parameter:
523: .   obj - the PETSc object

525:     Level: developer


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

530: @*/
531: PetscErrorCode  PetscObjectDestroyOptionsHandlers(PetscObject obj)
532: {
533:   PetscInt       i;

538:   for (i=0; i<obj->noptionhandler; i++) {
539:     if (obj->optiondestroy[i]) {
540:       (*obj->optiondestroy[i])(obj,obj->optionctx[i]);
541:     }
542:   }
543:   obj->noptionhandler = 0;
544:   return(0);
545: }


548: /*@C
549:    PetscObjectReference - Indicates to any PetscObject that it is being
550:    referenced by another PetscObject. This increases the reference
551:    count for that object by one.

553:    Logically Collective on PetscObject

555:    Input Parameter:
556: .  obj - the PETSc object. This must be cast with (PetscObject), for example,
557:          PetscObjectReference((PetscObject)mat);

559:    Level: advanced

561: .seealso: PetscObjectCompose(), PetscObjectDereference()
562: @*/
563: PetscErrorCode  PetscObjectReference(PetscObject obj)
564: {
566:   if (!obj) return(0);
568:   obj->refct++;
569:   return(0);
570: }

572: /*@C
573:    PetscObjectGetReference - Gets the current reference count for
574:    any PETSc object.

576:    Not Collective

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

582:    Output Parameter:
583: .  cnt - the reference count

585:    Level: advanced

587: .seealso: PetscObjectCompose(), PetscObjectDereference(), PetscObjectReference()
588: @*/
589: PetscErrorCode  PetscObjectGetReference(PetscObject obj,PetscInt *cnt)
590: {
594:   *cnt = obj->refct;
595:   return(0);
596: }

598: /*@C
599:    PetscObjectDereference - Indicates to any PetscObject that it is being
600:    referenced by one less PetscObject. This decreases the reference
601:    count for that object by one.

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

605:    Input Parameter:
606: .  obj - the PETSc object; this must be cast with (PetscObject), for example,
607:          PetscObjectDereference((PetscObject)mat);

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

612:    Level: advanced

614: .seealso: PetscObjectCompose(), PetscObjectReference()
615: @*/
616: PetscErrorCode  PetscObjectDereference(PetscObject obj)
617: {

621:   if (!obj) return(0);
623:   if (obj->bops->destroy) {
624:     (*obj->bops->destroy)(&obj);
625:   } else if (!--obj->refct) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"This PETSc object does not have a generic destroy routine");
626:   return(0);
627: }

629: /* ----------------------------------------------------------------------- */
630: /*
631:      The following routines are the versions private to the PETSc object
632:      data structures.
633: */
634: PetscErrorCode PetscObjectGetComm_Petsc(PetscObject obj,MPI_Comm *comm)
635: {
638:   *comm = obj->comm;
639:   return(0);
640: }

642: PetscErrorCode PetscObjectRemoveReference(PetscObject obj,const char name[])
643: {

648:   PetscObjectListRemoveReference(&obj->olist,name);
649:   return(0);
650: }

652: PetscErrorCode PetscObjectCompose_Petsc(PetscObject obj,const char name[],PetscObject ptr)
653: {
655:   char           *tname;
656:   PetscBool      skipreference;

659:   if (ptr) {
660:     PetscObjectListReverseFind(ptr->olist,obj,&tname,&skipreference);
661:     if (tname && !skipreference) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"An object cannot be composed with an object that was composed with it");
662:   }
663:   PetscObjectListAdd(&obj->olist,name,ptr);
664:   return(0);
665: }

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

673:   PetscObjectListFind(obj->olist,name,ptr);
674:   return(0);
675: }

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

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

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

693:   PetscFunctionListFind(obj->qlist,name,ptr);
694:   return(0);
695: }

697: /*@C
698:    PetscObjectCompose - Associates another PETSc object with a given PETSc object.

700:    Not Collective

702:    Input Parameters:
703: +  obj - the PETSc object; this must be cast with (PetscObject), for example,
704:          PetscObjectCompose((PetscObject)mat,...);
705: .  name - name associated with the child object
706: -  ptr - the other PETSc object to associate with the PETSc object; this must also be
707:          cast with (PetscObject)

709:    Level: advanced

711:    Notes:
712:    The second objects reference count is automatically increased by one when it is
713:    composed.

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

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

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

725:    Concepts: objects^composing
726:    Concepts: composing objects

728: .seealso: PetscObjectQuery(), PetscContainerCreate()
729: @*/
730: PetscErrorCode  PetscObjectCompose(PetscObject obj,const char name[],PetscObject ptr)
731: {

738:   if (obj == ptr) SETERRQ(PetscObjectComm((PetscObject)obj),PETSC_ERR_SUP,"Cannot compose object with itself");
739:   (*obj->bops->compose)(obj,name,ptr);
740:   return(0);
741: }

743: /*@C
744:    PetscObjectQuery  - Gets a PETSc object associated with a given object.

746:    Not Collective

748:    Input Parameters:
749: +  obj - the PETSc object
750:          Thus must be cast with a (PetscObject), for example,
751:          PetscObjectCompose((PetscObject)mat,...);
752: .  name - name associated with child object
753: -  ptr - the other PETSc object associated with the PETSc object, this must be
754:          cast with (PetscObject*)

756:    Level: advanced

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

760:    Concepts: objects^composing
761:    Concepts: composing objects
762:    Concepts: objects^querying
763:    Concepts: querying objects

765: .seealso: PetscObjectCompose()
766: @*/
767: PetscErrorCode  PetscObjectQuery(PetscObject obj,const char name[],PetscObject *ptr)
768: {

775:   (*obj->bops->query)(obj,name,ptr);
776:   return(0);
777: }

779: /*MC
780:    PetscObjectComposeFunction - Associates a function with a given PETSc object.

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

786:    Logically Collective on PetscObject

788:    Input Parameters:
789: +  obj - the PETSc object; this must be cast with a (PetscObject), for example,
790:          PetscObjectCompose((PetscObject)mat,...);
791: .  name - name associated with the child function
792: .  fname - name of the function
793: -  fptr - function pointer

795:    Level: advanced

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

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

803:    Concepts: objects^composing functions
804:    Concepts: composing functions
805:    Concepts: functions^querying
806:    Concepts: objects^querying
807:    Concepts: querying objects

809: .seealso: PetscObjectQueryFunction(), PetscContainerCreate()
810: M*/

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

819:   (*obj->bops->composefunction)(obj,name,fptr);
820:   return(0);
821: }

823: /*MC
824:    PetscObjectQueryFunction - Gets a function associated with a given object.

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

830:    Logically Collective on PetscObject

832:    Input Parameters:
833: +  obj - the PETSc object; this must be cast with (PetscObject), for example,
834:          PetscObjectQueryFunction((PetscObject)ksp,...);
835: -  name - name associated with the child function

837:    Output Parameter:
838: .  fptr - function pointer

840:    Level: advanced

842:    Concepts: objects^composing functions
843:    Concepts: composing functions
844:    Concepts: functions^querying
845:    Concepts: objects^querying
846:    Concepts: querying objects

848: .seealso: PetscObjectComposeFunction(), PetscFunctionListFind()
849: M*/
850: PETSC_EXTERN PetscErrorCode PetscObjectQueryFunction_Private(PetscObject obj,const char name[],void (**ptr)(void))
851: {

857:   (*obj->bops->queryfunction)(obj,name,ptr);
858:   return(0);
859: }

861: struct _p_PetscContainer {
862:   PETSCHEADER(int);
863:   void           *ptr;
864:   PetscErrorCode (*userdestroy)(void*);
865: };

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

870:    Logically Collective on PetscContainer

872:    Input Parameter:
873: .  ctx - pointer to user-provided data

875:    Level: advanced

877: .seealso: PetscContainerDestroy(), PetscContainterSetUserDestroy()
878: @*/
879: PetscErrorCode PetscContainerUserDestroyDefault(void* ctx)
880: {

884:   PetscFree(ctx);
885:   return(0);
886: }

888: /*@C
889:    PetscContainerGetPointer - Gets the pointer value contained in the container.

891:    Not Collective

893:    Input Parameter:
894: .  obj - the object created with PetscContainerCreate()

896:    Output Parameter:
897: .  ptr - the pointer value

899:    Level: advanced

901: .seealso: PetscContainerCreate(), PetscContainerDestroy(),
902:           PetscContainerSetPointer()
903: @*/
904: PetscErrorCode  PetscContainerGetPointer(PetscContainer obj,void **ptr)
905: {
909:   *ptr = obj->ptr;
910:   return(0);
911: }


914: /*@C
915:    PetscContainerSetPointer - Sets the pointer value contained in the container.

917:    Logically Collective on PetscContainer

919:    Input Parameters:
920: +  obj - the object created with PetscContainerCreate()
921: -  ptr - the pointer value

923:    Level: advanced

925: .seealso: PetscContainerCreate(), PetscContainerDestroy(),
926:           PetscContainerGetPointer()
927: @*/
928: PetscErrorCode  PetscContainerSetPointer(PetscContainer obj,void *ptr)
929: {
933:   obj->ptr = ptr;
934:   return(0);
935: }

937: /*@C
938:    PetscContainerDestroy - Destroys a PETSc container object.

940:    Collective on PetscContainer

942:    Input Parameter:
943: .  obj - an object that was created with PetscContainerCreate()

945:    Level: advanced

947: .seealso: PetscContainerCreate(), PetscContainerSetUserDestroy()
948: @*/
949: PetscErrorCode  PetscContainerDestroy(PetscContainer *obj)
950: {

954:   if (!*obj) return(0);
956:   if (--((PetscObject)(*obj))->refct > 0) {*obj = 0; return(0);}
957:   if ((*obj)->userdestroy) { (*(*obj)->userdestroy)((*obj)->ptr); }
958:   PetscHeaderDestroy(obj);
959:   return(0);
960: }

962: /*@C
963:    PetscContainerSetUserDestroy - Sets name of the user destroy function.

965:    Logically Collective on PetscContainer

967:    Input Parameter:
968: +  obj - an object that was created with PetscContainerCreate()
969: -  des - name of the user destroy function

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

974:    Level: advanced

976: .seealso: PetscContainerDestroy(), PetscContainerUserDestroyDefault(), PetscMalloc(), PetscMalloc1(), PetscCalloc(), PetscCalloc1()
977: @*/
978: PetscErrorCode  PetscContainerSetUserDestroy(PetscContainer obj, PetscErrorCode (*des)(void*))
979: {
982:   obj->userdestroy = des;
983:   return(0);
984: }

986: PetscClassId PETSC_CONTAINER_CLASSID;

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

994:    Collective on MPI_Comm

996:    Input Parameters:
997: .  comm - MPI communicator that shares the object

999:    Output Parameters:
1000: .  container - the container created

1002:    Level: advanced

1004: .seealso: PetscContainerDestroy(), PetscContainerSetPointer(), PetscContainerGetPointer()
1005: @*/
1006: PetscErrorCode  PetscContainerCreate(MPI_Comm comm,PetscContainer *container)
1007: {
1009:   PetscContainer contain;

1013:   PetscSysInitializePackage();
1014:   PetscHeaderCreate(contain,PETSC_CONTAINER_CLASSID,"PetscContainer","Container","Sys",comm,PetscContainerDestroy,NULL);
1015:   *container = contain;
1016:   return(0);
1017: }

1019: /*@
1020:    PetscObjectSetFromOptions - Sets generic parameters from user options.

1022:    Collective on obj

1024:    Input Parameter:
1025: .  obj - the PetscObjcet

1027:    Options Database Keys:

1029:    Notes:
1030:    We have no generic options at present, so this does nothing

1032:    Level: beginner

1034: .keywords: set, options, database
1035: .seealso: PetscObjectSetOptionsPrefix(), PetscObjectGetOptionsPrefix()
1036: @*/
1037: PetscErrorCode  PetscObjectSetFromOptions(PetscObject obj)
1038: {
1041:   return(0);
1042: }

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

1047:    Collective on PetscObject

1049:    Input Parameters:
1050: .  obj - the PetscObject

1052:    Notes:
1053:    This does nothing at present.

1055:    Level: advanced

1057: .keywords: setup
1058: .seealso: PetscObjectDestroy()
1059: @*/
1060: PetscErrorCode  PetscObjectSetUp(PetscObject obj)
1061: {
1064:   return(0);
1065: }