Actual source code: inherit.c

petsc-3.12.5 2020-03-29
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:     PetscCalloc1(newPetscObjectsMaxCounts,&newPetscObjects);
 80:     PetscArraycpy(newPetscObjects,PetscObjects,PetscObjectsMaxCounts);
 81:     PetscFree(PetscObjects);

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

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

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

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

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

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

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

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

157:    Logically Collective on PetscObject

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

163:    Level: developer

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

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

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

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

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

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

197:    Logically Collective

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

206:    Level: developer

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

217:   if (cbtype == PETSC_FORTRAN_CALLBACK_SUBTYPE) subtype = obj->type_name;
218:   if (!*cid) {PetscFortranCallbackRegister(obj->classid,subtype,cid);}
219:   if (*cid >= PETSC_SMALLEST_FORTRAN_CALLBACK+obj->num_fortrancallback[cbtype]) {
220:     PetscInt             oldnum = obj->num_fortrancallback[cbtype],newnum = PetscMax(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 Arguments:
240: +  obj - object on which to get callback
241: .  cbtype - callback type
242: -  cid - address of callback Id

244:    Output Arguments:
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 Parameter:
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>

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 = 0;
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 Parameter:
376: .   obj - the object or null if there is no object

378:    Level: advanced

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

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

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

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

411:    Level: developer

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

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

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

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

433:    Level: developer

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

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

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

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

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

458:     Not Collective

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

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


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

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

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

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

513:     Not Collective

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

518:     Level: developer


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

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

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


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

546:    Logically Collective on PetscObject

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

552:    Level: advanced

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

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

569:    Not Collective

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

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

578:    Level: advanced

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

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

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

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

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

605:    Level: advanced

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

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

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

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

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

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

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

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

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

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

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

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

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

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

693:    Not Collective

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

702:    Level: advanced

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

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

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

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


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

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

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

737:    Not Collective

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

747:    Level: advanced

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


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

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

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

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

773:    Logically Collective on PetscObject

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

782:    Level: advanced

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

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

790: .seealso: PetscObjectQueryFunction(), PetscContainerCreate()
791: M*/

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

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

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

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

811:    Logically Collective on PetscObject

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

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

821:    Level: advanced

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

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

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

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

845:    Logically Collective on PetscContainer

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

850:    Level: advanced

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

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

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

866:    Not Collective

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

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

874:    Level: advanced

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


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

892:    Logically Collective on PetscContainer

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

898:    Level: advanced

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

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

915:    Collective on PetscContainer

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

920:    Level: advanced

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

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

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

940:    Logically Collective on PetscContainer

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

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

949:    Level: advanced

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

961: PetscClassId PETSC_CONTAINER_CLASSID;

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

969:    Collective

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

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

977:    Level: advanced

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

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

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

997:    Collective on obj

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

1002:    Options Database Keys:

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

1007:    Level: beginner

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

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

1021:    Collective on PetscObject

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

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

1029:    Level: advanced

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