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 PetscObjectCompose_Petsc(PetscObject, const char[], PetscObject);
 21: PETSC_EXTERN PetscErrorCode PetscObjectQuery_Petsc(PetscObject, const char[], PetscObject *);
 22: PETSC_EXTERN PetscErrorCode PetscObjectComposeFunction_Petsc(PetscObject, const char[], void (*)(void));
 23: PETSC_EXTERN PetscErrorCode PetscObjectQueryFunction_Petsc(PetscObject, const char[], void (**)(void));

 25: PetscObjectId PetscObjectNewId_Internal(void)
 26: {
 27:   static PetscObjectId idcnt = 1;
 28:   return idcnt++;
 29: }

 31: /*
 32:    PetscHeaderCreate_Private - Creates a base PETSc object header and fills
 33:    in the default values.  Called by the macro PetscHeaderCreate().
 34: */
 35: PetscErrorCode PetscHeaderCreate_Private(PetscObject h, PetscClassId classid, const char class_name[], const char descr[], const char mansec[], MPI_Comm comm, PetscObjectDestroyFunction destroy, PetscObjectViewFunction view)
 36: {
 37:   h->classid               = classid;
 38:   h->class_name            = (char *)class_name;
 39:   h->description           = (char *)descr;
 40:   h->mansec                = (char *)mansec;
 41:   h->refct                 = 1;
 42:   h->id                    = PetscObjectNewId_Internal();
 43:   h->bops->destroy         = destroy;
 44:   h->bops->view            = view;
 45:   h->bops->compose         = PetscObjectCompose_Petsc;
 46:   h->bops->query           = PetscObjectQuery_Petsc;
 47:   h->bops->composefunction = PetscObjectComposeFunction_Petsc;
 48:   h->bops->queryfunction   = PetscObjectQueryFunction_Petsc;

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

 52: #if defined(PETSC_USE_LOG)
 53:   /* Keep a record of object created */
 54:   if (PetscObjectsLog) {
 55:     PetscObject *newPetscObjects;
 56:     PetscInt     newPetscObjectsMaxCounts;

 58:     PetscObjectsCounts++;
 59:     for (PetscInt i = 0; i < PetscObjectsMaxCounts; ++i) {
 60:       if (!PetscObjects[i]) {
 61:         PetscObjects[i] = h;
 62:         return 0;
 63:       }
 64:     }
 65:     /* Need to increase the space for storing PETSc objects */
 66:     if (!PetscObjectsMaxCounts) newPetscObjectsMaxCounts = 100;
 67:     else newPetscObjectsMaxCounts = 2 * PetscObjectsMaxCounts;
 68:     PetscCalloc1(newPetscObjectsMaxCounts, &newPetscObjects);
 69:     PetscArraycpy(newPetscObjects, PetscObjects, PetscObjectsMaxCounts);
 70:     PetscFree(PetscObjects);

 72:     PetscObjects                        = newPetscObjects;
 73:     PetscObjects[PetscObjectsMaxCounts] = h;
 74:     PetscObjectsMaxCounts               = newPetscObjectsMaxCounts;
 75:   }
 76: #endif
 77:   return 0;
 78: }

 80: PETSC_INTERN PetscBool      PetscMemoryCollectMaximumUsage;
 81: PETSC_INTERN PetscLogDouble PetscMemoryMaximumUsage;

 83: /*
 84:     PetscHeaderDestroy_Private - Destroys a base PETSc object header. Called by
 85:     the macro PetscHeaderDestroy().
 86: */
 87: PetscErrorCode PetscHeaderDestroy_Private(PetscObject obj, PetscBool clear_for_reuse)
 88: {
 90:   PetscLogObjectDestroy(obj);
 91:   PetscComposedQuantitiesDestroy(obj);
 92:   if (PetscMemoryCollectMaximumUsage) {
 93:     PetscLogDouble usage;

 95:     PetscMemoryGetCurrentUsage(&usage);
 96:     if (usage > PetscMemoryMaximumUsage) PetscMemoryMaximumUsage = usage;
 97:   }
 98:   /* first destroy things that could execute arbitrary code */
 99:   if (obj->python_destroy) {
100:     void *python_context                     = obj->python_context;
101:     PetscErrorCode (*python_destroy)(void *) = obj->python_destroy;

103:     obj->python_context = NULL;
104:     obj->python_destroy = NULL;
105:     (*python_destroy)(python_context);
106:   }
107:   PetscObjectDestroyOptionsHandlers(obj);
108:   PetscObjectListDestroy(&obj->olist);

110:   /* destroy allocated quantities */
111:   if (PetscPrintFunctionList) PetscFunctionListPrintNonEmpty(obj->qlist);
113:   PetscFree(obj->name);
114:   PetscFree(obj->prefix);
115:   PetscFree(obj->type_name);

117:   if (clear_for_reuse) {
118:     /* we will assume that obj->bops->view and destroy are safe to leave as-is */
119:     obj->bops->compose         = PetscObjectCompose_Petsc;
120:     obj->bops->query           = PetscObjectQuery_Petsc;
121:     obj->bops->composefunction = PetscObjectComposeFunction_Petsc;
122:     obj->bops->queryfunction   = PetscObjectQueryFunction_Petsc;

124:     /* reset quantities, in order of appearance in _p_PetscObject */
125:     obj->id       = PetscObjectNewId_Internal();
126:     obj->refct    = 1;
127:     obj->tablevel = 0;
128:     obj->state    = 0;
129:     /* don't deallocate, zero these out instead */
130:     PetscFunctionListClear(obj->qlist);
131:     PetscArrayzero(obj->fortran_func_pointers, obj->num_fortran_func_pointers);
132:     PetscArrayzero(obj->fortrancallback[PETSC_FORTRAN_CALLBACK_CLASS], obj->num_fortrancallback[PETSC_FORTRAN_CALLBACK_CLASS]);
133:     PetscArrayzero(obj->fortrancallback[PETSC_FORTRAN_CALLBACK_SUBTYPE], obj->num_fortrancallback[PETSC_FORTRAN_CALLBACK_SUBTYPE]);
134:     obj->optionsprinted = PETSC_FALSE;
135: #if PetscDefined(HAVE_SAWS)
136:     obj->amsmem          = PETSC_FALSE;
137:     obj->amspublishblock = PETSC_FALSE;
138: #endif
139:     obj->options                                  = NULL;
140:     obj->donotPetscObjectPrintClassNamePrefixType = PETSC_FALSE;
141:   } else {
142:     PetscFunctionListDestroy(&obj->qlist);
143:     PetscFree(obj->fortran_func_pointers);
144:     PetscFree(obj->fortrancallback[PETSC_FORTRAN_CALLBACK_CLASS]);
145:     PetscFree(obj->fortrancallback[PETSC_FORTRAN_CALLBACK_SUBTYPE]);
146:     PetscCommDestroy(&obj->comm);
147:     obj->classid = PETSCFREEDHEADER;

149: #if PetscDefined(USE_LOG)
150:     if (PetscObjectsLog) {
151:       /* Record object removal from list of all objects */
152:       for (PetscInt i = 0; i < PetscObjectsMaxCounts; ++i) {
153:         if (PetscObjects[i] == obj) {
154:           PetscObjects[i] = NULL;
155:           --PetscObjectsCounts;
156:           break;
157:         }
158:       }
159:       if (!PetscObjectsCounts) {
160:         PetscFree(PetscObjects);
161:         PetscObjectsMaxCounts = 0;
162:       }
163:     }
164: #endif
165:   }
166:   return 0;
167: }

169: /*
170:   PetscHeaderReset_Internal - "Reset" a PetscObject header. This is tantamount to destroying
171:   the object but does not free all resources. The object retains its:

173:   - classid
174:   - bops->view
175:   - bops->destroy
176:   - comm
177:   - tag
178:   - class_name
179:   - description
180:   - mansec
181:   - cpp

183:   Note that while subclass information is lost, superclass info remains. Thus this function is
184:   intended to be used to reuse a PetscObject within the same class to avoid reallocating its
185:   resources.
186: */
187: PetscErrorCode PetscHeaderReset_Internal(PetscObject obj)
188: {
189:   PetscHeaderDestroy_Private(obj, PETSC_TRUE);
190:   return 0;
191: }

193: /*@C
194:    PetscObjectCopyFortranFunctionPointers - Copy function pointers to another object

196:    Logically Collective on src

198:    Input Parameters:
199: +  src - source object
200: -  dest - destination object

202:    Level: developer

204:    Note:
205:    Both objects must have the same class.

207:    This is used to help manage user callback functions that were provided in Fortran
208: @*/
209: PetscErrorCode PetscObjectCopyFortranFunctionPointers(PetscObject src, PetscObject dest)
210: {
211:   PetscFortranCallbackId cbtype, numcb[PETSC_FORTRAN_CALLBACK_MAXTYPE];


217:   PetscFree(dest->fortran_func_pointers);
218:   PetscMalloc(src->num_fortran_func_pointers * sizeof(void (*)(void)), &dest->fortran_func_pointers);
219:   PetscMemcpy(dest->fortran_func_pointers, src->fortran_func_pointers, src->num_fortran_func_pointers * sizeof(void (*)(void)));

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

223:   PetscFortranCallbackGetSizes(src->classid, &numcb[PETSC_FORTRAN_CALLBACK_CLASS], &numcb[PETSC_FORTRAN_CALLBACK_SUBTYPE]);
224:   for (cbtype = PETSC_FORTRAN_CALLBACK_CLASS; cbtype < PETSC_FORTRAN_CALLBACK_MAXTYPE; cbtype++) {
225:     PetscFree(dest->fortrancallback[cbtype]);
226:     PetscCalloc1(numcb[cbtype], &dest->fortrancallback[cbtype]);
227:     PetscMemcpy(dest->fortrancallback[cbtype], src->fortrancallback[cbtype], src->num_fortrancallback[cbtype] * sizeof(PetscFortranCallback));
228:     dest->num_fortrancallback[cbtype] = src->num_fortrancallback[cbtype];
229:   }
230:   return 0;
231: }

233: /*@C
234:    PetscObjectSetFortranCallback - set fortran callback function pointer and context

236:    Logically Collective

238:    Input Parameters:
239: +  obj - object on which to set callback
240: .  cbtype - callback type (class or subtype)
241: .  cid - address of callback Id, updated if not yet initialized (zero)
242: .  func - Fortran function
243: -  ctx - Fortran context

245:    Level: developer

247:    Note:
248:    This is used to help manage user callback functions that were provided in Fortran

250: .seealso: `PetscObjectGetFortranCallback()`
251: @*/
252: PetscErrorCode PetscObjectSetFortranCallback(PetscObject obj, PetscFortranCallbackType cbtype, PetscFortranCallbackId *cid, void (*func)(void), void *ctx)
253: {
254:   const char *subtype = NULL;

257:   if (cbtype == PETSC_FORTRAN_CALLBACK_SUBTYPE) subtype = obj->type_name;
258:   if (!*cid) PetscFortranCallbackRegister(obj->classid, subtype, cid);
259:   if (*cid >= PETSC_SMALLEST_FORTRAN_CALLBACK + obj->num_fortrancallback[cbtype]) {
260:     PetscFortranCallbackId oldnum = obj->num_fortrancallback[cbtype];
261:     PetscFortranCallbackId newnum = PetscMax(*cid - PETSC_SMALLEST_FORTRAN_CALLBACK + 1, 2 * oldnum);
262:     PetscFortranCallback  *callback;
263:     PetscMalloc1(newnum, &callback);
264:     PetscMemcpy(callback, obj->fortrancallback[cbtype], oldnum * sizeof(*obj->fortrancallback[cbtype]));
265:     PetscFree(obj->fortrancallback[cbtype]);

267:     obj->fortrancallback[cbtype]     = callback;
268:     obj->num_fortrancallback[cbtype] = newnum;
269:   }
270:   obj->fortrancallback[cbtype][*cid - PETSC_SMALLEST_FORTRAN_CALLBACK].func = func;
271:   obj->fortrancallback[cbtype][*cid - PETSC_SMALLEST_FORTRAN_CALLBACK].ctx  = ctx;
272:   return 0;
273: }

275: /*@C
276:    PetscObjectGetFortranCallback - get fortran callback function pointer and context

278:    Logically Collective

280:    Input Parameters:
281: +  obj - object on which to get callback
282: .  cbtype - callback type
283: -  cid - address of callback Id

285:    Output Parameters:
286: +  func - Fortran function (or NULL if not needed)
287: -  ctx - Fortran context (or NULL if not needed)

289:    Level: developer

291:    Note:
292:    This is used to help manage user callback functions that were provided in Fortran

294: .seealso: `PetscObjectSetFortranCallback()`
295: @*/
296: PetscErrorCode PetscObjectGetFortranCallback(PetscObject obj, PetscFortranCallbackType cbtype, PetscFortranCallbackId cid, void (**func)(void), void **ctx)
297: {
298:   PetscFortranCallback *cb;

303:   cb = &obj->fortrancallback[cbtype][cid - PETSC_SMALLEST_FORTRAN_CALLBACK];
304:   if (func) *func = cb->func;
305:   if (ctx) *ctx = cb->ctx;
306:   return 0;
307: }

309: #if defined(PETSC_USE_LOG)
310: /*@C
311:    PetscObjectsDump - Prints all the currently existing objects.

313:    On rank 0 of `PETSC_COMM_WORLD` prints the values

315:    Input Parameters:
316: +  fd - file pointer
317: -  all - by default only tries to display objects created explicitly by the user, if all is `PETSC_TRUE` then lists all outstanding objects

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

322:    Level: advanced

324: @*/
325: PetscErrorCode PetscObjectsDump(FILE *fd, PetscBool all)
326: {
327:   PetscInt i;
328:   #if defined(PETSC_USE_DEBUG)
329:   PetscInt j, k = 0;
330:   #endif
331:   PetscObject h;

333:   if (PetscObjectsCounts) {
334:     PetscFPrintf(PETSC_COMM_WORLD, fd, "The following objects were never freed\n");
335:     PetscFPrintf(PETSC_COMM_WORLD, fd, "-----------------------------------------\n");
336:     for (i = 0; i < PetscObjectsMaxCounts; i++) {
337:       if ((h = PetscObjects[i])) {
338:         PetscObjectName(h);
339:         {
340:   #if defined(PETSC_USE_DEBUG)
341:           PetscStack *stack = NULL;
342:           char       *create, *rclass;

344:           /* if the PETSc function the user calls is not a create then this object was NOT directly created by them */
345:           PetscMallocGetStack(h, &stack);
346:           if (stack) {
347:             k = stack->currentsize - 2;
348:             if (!all) {
349:               k = 0;
350:               while (!stack->petscroutine[k]) k++;
351:               PetscStrstr(stack->function[k], "Create", &create);
352:               if (!create) PetscStrstr(stack->function[k], "Get", &create);
353:               PetscStrstr(stack->function[k], h->class_name, &rclass);
354:               if (!create) continue;
355:               if (!rclass) continue;
356:             }
357:           }
358:   #endif

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

362:   #if defined(PETSC_USE_DEBUG)
363:           PetscMallocGetStack(h, &stack);
364:           if (stack) {
365:             for (j = k; j >= 0; j--) fprintf(fd, "      [%d]  %s() in %s\n", PetscGlobalRank, stack->function[j], stack->file[j]);
366:           }
367:   #endif
368:         }
369:       }
370:     }
371:   }
372:   return 0;
373: }
374: #endif

376: #if defined(PETSC_USE_LOG)

378: /*@C
379:    PetscObjectsView - Prints the currently existing objects.

381:    Logically Collective on viewer

383:    Input Parameter:
384: .  viewer - must be an `PETSCVIEWERASCII` viewer

386:    Level: advanced

388: @*/
389: PetscErrorCode PetscObjectsView(PetscViewer viewer)
390: {
391:   PetscBool isascii;
392:   FILE     *fd;

394:   if (!viewer) viewer = PETSC_VIEWER_STDOUT_WORLD;
395:   PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii);
397:   PetscViewerASCIIGetPointer(viewer, &fd);
398:   PetscObjectsDump(fd, PETSC_TRUE);
399:   return 0;
400: }

402: /*@C
403:    PetscObjectsGetObject - Get a pointer to a named object

405:    Not collective

407:    Input Parameter:
408: .  name - the name of an object

410:    Output Parameters:
411: +  obj - the object or null if there is no object
412: -  classname - the name of the class

414:    Level: advanced

416: @*/
417: PetscErrorCode PetscObjectsGetObject(const char *name, PetscObject *obj, char **classname)
418: {
419:   PetscInt    i;
420:   PetscObject h;
421:   PetscBool   flg;

425:   *obj = NULL;
426:   for (i = 0; i < PetscObjectsMaxCounts; i++) {
427:     if ((h = PetscObjects[i])) {
428:       PetscObjectName(h);
429:       PetscStrcmp(h->name, name, &flg);
430:       if (flg) {
431:         *obj = h;
432:         if (classname) *classname = h->class_name;
433:         return 0;
434:       }
435:     }
436:   }
437:   return 0;
438: }
439: #endif

441: /*@
442:    PetscObjectSetPrintedOptions - indicate to an object that it should behave as if it has already printed the help for its options so it will not display the help message

444:    Input Parameters:
445: .  obj  - the `PetscObject`

447:    Level: developer

449:    Developer Note:
450:    This is used, for example to prevent sequential objects that are created from a parallel object; such as the `KSP` created by
451:    `PCBJACOBI` from all printing the same help messages to the screen

453: .seealso: `PetscOptionsInsert()`
454: @*/
455: PetscErrorCode PetscObjectSetPrintedOptions(PetscObject obj)
456: {
458:   obj->optionsprinted = PETSC_TRUE;
459:   return 0;
460: }

462: /*@
463:    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.

465:    Input Parameters:
466: +  pobj - the parent object
467: -  obj  - the PetscObject

469:    Level: developer

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

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

477: .seealso: `PetscOptionsInsert()`, `PetscObjectSetPrintedOptions()`
478: @*/
479: PetscErrorCode PetscObjectInheritPrintedOptions(PetscObject pobj, PetscObject obj)
480: {
481:   PetscMPIInt prank, size;

485:   MPI_Comm_rank(pobj->comm, &prank);
486:   MPI_Comm_size(obj->comm, &size);
487:   if (size == 1 && prank > 0) obj->optionsprinted = PETSC_TRUE;
488:   return 0;
489: }

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

494:     Not Collective

496:     Input Parameters:
497: +   obj - the PETSc object
498: .   handle - function that checks for options
499: .   destroy - function to destroy context if provided
500: -   ctx - optional context for check function

502:     Level: developer

504: .seealso: `KSPSetFromOptions()`, `PCSetFromOptions()`, `SNESSetFromOptions()`, `PetscObjectProcessOptionsHandlers()`, `PetscObjectDestroyOptionsHandlers()`
505: @*/
506: PetscErrorCode PetscObjectAddOptionsHandler(PetscObject obj, PetscErrorCode (*handle)(PetscObject, PetscOptionItems *, void *), PetscErrorCode (*destroy)(PetscObject, void *), void *ctx)
507: {
510:   obj->optionhandler[obj->noptionhandler] = handle;
511:   obj->optiondestroy[obj->noptionhandler] = destroy;
512:   obj->optionctx[obj->noptionhandler++]   = ctx;
513:   return 0;
514: }

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

519:     Not Collective

521:     Input Parameters:
522: +   obj - the PETSc object
523: -   PetscOptionsObject - the options context

525:     Level: developer

527: .seealso: `KSPSetFromOptions()`, `PCSetFromOptions()`, `SNESSetFromOptions()`, `PetscObjectAddOptionsHandler()`, `PetscObjectDestroyOptionsHandlers()`
528: @*/
529: PetscErrorCode PetscObjectProcessOptionsHandlers(PetscObject obj, PetscOptionItems *PetscOptionsObject)
530: {
532:   for (PetscInt i = 0; i < obj->noptionhandler; i++) (*obj->optionhandler[i])(obj, PetscOptionsObject, obj->optionctx[i]);
533:   return 0;
534: }

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

539:     Not Collective

541:     Input Parameter:
542: .   obj - the PETSc object

544:     Level: developer

546: .seealso: `KSPSetFromOptions()`, `PCSetFromOptions()`, `SNESSetFromOptions()`, `PetscObjectAddOptionsHandler()`, `PetscObjectProcessOptionsHandlers()`
547: @*/
548: PetscErrorCode PetscObjectDestroyOptionsHandlers(PetscObject obj)
549: {
551:   for (PetscInt i = 0; i < obj->noptionhandler; i++) {
552:     if (obj->optiondestroy[i]) (*obj->optiondestroy[i])(obj, obj->optionctx[i]);
553:   }
554:   obj->noptionhandler = 0;
555:   return 0;
556: }

558: /*@C
559:    PetscObjectReference - Indicates to any `PetscObject` that it is being
560:    referenced by another `PetscObject`. This increases the reference
561:    count for that object by one.

563:    Logically Collective on obj

565:    Input Parameter:
566: .  obj - the PETSc object. This must be cast with (`PetscObject`), for example,
567:          `PetscObjectReference`((`PetscObject`)mat);

569:    Level: advanced

571: .seealso: `PetscObjectCompose()`, `PetscObjectDereference()`
572: @*/
573: PetscErrorCode PetscObjectReference(PetscObject obj)
574: {
575:   if (!obj) return 0;
577:   obj->refct++;
578:   return 0;
579: }

581: /*@C
582:    PetscObjectGetReference - Gets the current reference count for
583:    any PETSc object.

585:    Not Collective

587:    Input Parameter:
588: .  obj - the PETSc object; this must be cast with (`PetscObject`), for example,
589:          `PetscObjectGetReference`((`PetscObject`)mat,&cnt);

591:    Output Parameter:
592: .  cnt - the reference count

594:    Level: advanced

596: .seealso: `PetscObjectCompose()`, `PetscObjectDereference()`, `PetscObjectReference()`
597: @*/
598: PetscErrorCode PetscObjectGetReference(PetscObject obj, PetscInt *cnt)
599: {
602:   *cnt = obj->refct;
603:   return 0;
604: }

606: /*@C
607:    PetscObjectDereference - Indicates to any `PetscObject` that it is being
608:    referenced by one less `PetscObject`. This decreases the reference
609:    count for that object by one.

611:    Collective on obj if reference reaches 0 otherwise Logically Collective

613:    Input Parameter:
614: .  obj - the PETSc object; this must be cast with (`PetscObject`), for example,
615:          `PetscObjectDereference`((`PetscObject`)mat);

617:    Note:
618:     `PetscObjectDestroy()` sets the obj pointer to null after the call, this routine does not.

620:    Level: advanced

622: .seealso: `PetscObjectCompose()`, `PetscObjectReference()`, `PetscObjectDestroy()`
623: @*/
624: PetscErrorCode PetscObjectDereference(PetscObject obj)
625: {
626:   if (!obj) return 0;
628:   if (obj->bops->destroy) (*obj->bops->destroy)(&obj);
630:   return 0;
631: }

633: /* ----------------------------------------------------------------------- */
634: /*
635:      The following routines are the versions private to the PETSc object
636:      data structures.
637: */
638: PetscErrorCode PetscObjectRemoveReference(PetscObject obj, const char name[])
639: {
641:   PetscObjectListRemoveReference(&obj->olist, name);
642:   return 0;
643: }

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

651:     PetscObjectListReverseFind(ptr->olist, obj, &tname, &skipreference);
653:   }
654:   PetscObjectListAdd(&obj->olist, name, ptr);
655:   return 0;
656: }

658: PetscErrorCode PetscObjectQuery_Petsc(PetscObject obj, const char name[], PetscObject *ptr)
659: {
661:   PetscObjectListFind(obj->olist, name, ptr);
662:   return 0;
663: }

665: PetscErrorCode PetscObjectComposeFunction_Petsc(PetscObject obj, const char name[], void (*ptr)(void))
666: {
668:   PetscFunctionListAdd(&obj->qlist, name, ptr);
669:   return 0;
670: }

672: PetscErrorCode PetscObjectQueryFunction_Petsc(PetscObject obj, const char name[], void (**ptr)(void))
673: {
675:   PetscFunctionListFind(obj->qlist, name, ptr);
676:   return 0;
677: }

679: /*@C
680:    PetscObjectCompose - Associates another PETSc object with a given PETSc object.

682:    Not Collective

684:    Input Parameters:
685: +  obj - the PETSc object; this must be cast with (`PetscObject`), for example,
686:          `PetscObjectCompose`((`PetscObject`)mat,...);
687: .  name - name associated with the child object
688: -  ptr - the other PETSc object to associate with the PETSc object; this must also be
689:          cast with (`PetscObject`)

691:    Level: advanced

693:    Notes:
694:    The second objects reference count is automatically increased by one when it is
695:    composed.

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

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

702:    `PetscObjectCompose()` can be used with any PETSc object (such as
703:    `Mat`, `Vec`, `KSP`, `SNES`, etc.) or any user-provided object.

705:    `PetscContainerCreate()` can be used to create an object from a
706:    user-provided pointer that may then be composed with PETSc objects using `PetscObjectCompose()`

708: .seealso: `PetscObjectQuery()`, `PetscContainerCreate()`, `PetscObjectComposeFunction()`, `PetscObjectQueryFunction()`, `PetscContainer`,
709:           `PetscContainerSetPointer()`
710: @*/
711: PetscErrorCode PetscObjectCompose(PetscObject obj, const char name[], PetscObject ptr)
712: {
717:   (*obj->bops->compose)(obj, name, ptr);
718:   return 0;
719: }

721: /*@C
722:    PetscObjectQuery  - Gets a PETSc object associated with a given object that was composed with `PetscObjectCompose()`

724:    Not Collective

726:    Input Parameters:
727: +  obj - the PETSc object
728:          Thus must be cast with a (`PetscObject`), for example,
729:          `PetscObjectCompose`((`PetscObject`)mat,...);
730: .  name - name associated with child object
731: -  ptr - the other PETSc object associated with the PETSc object, this must be
732:          cast with (`PetscObject`*)

734:    Level: advanced

736:    Note:
737:    The reference count of neither object is increased in this call

739: .seealso: `PetscObjectCompose()`, `PetscObjectComposeFunction()`, `PetscObjectQueryFunction()`, `PetscContainer`
740:           `PetscContainerGetPointer()`
741: @*/
742: PetscErrorCode PetscObjectQuery(PetscObject obj, const char name[], PetscObject *ptr)
743: {
747:   (*obj->bops->query)(obj, name, ptr);
748:   return 0;
749: }

751: /*MC
752:    PetscObjectComposeFunction - Associates a function with a given PETSc object.

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

758:    Logically Collective on obj

760:    Input Parameters:
761: +  obj - the PETSc object; this must be cast with a (`PetscObject`), for example,
762:          `PetscObjectCompose`((`PetscObject`)mat,...);
763: .  name - name associated with the child function
764: .  fname - name of the function
765: -  fptr - function pointer

767:    Level: advanced

769:    Notes:
770:    When the first argument of the function is the object within which it has been composed then `PetscTryMethod()` and `PetscUseMethod()`
771:    can be used to call the function directly with error checking.

773:    To remove a registered routine, pass in NULL for fptr().

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

778:    `PetscCallMethod()` is used to call a function that is stored in the objects obj->ops table.

780: .seealso: `PetscObjectQueryFunction()`, `PetscContainerCreate()` `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscTryMethod()`, `PetscUseMethod()`,
781:           `PetscCallMethod()`
782: M*/

784: PetscErrorCode PetscObjectComposeFunction_Private(PetscObject obj, const char name[], void (*fptr)(void))
785: {
788:   (*obj->bops->composefunction)(obj, name, fptr);
789:   return 0;
790: }

792: /*MC
793:    PetscObjectQueryFunction - Gets a function associated with a given object.

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

799:    Logically Collective on obj

801:    Input Parameters:
802: +  obj - the PETSc object; this must be cast with (`PetscObject`), for example,
803:          `PetscObjectQueryFunction`((`PetscObject`)ksp,...);
804: -  name - name associated with the child function

806:    Output Parameter:
807: .  fptr - function pointer

809:    Level: advanced

811: .seealso: `PetscObjectComposeFunction()`, `PetscFunctionListFind()`, `PetscObjectCompose()`, `PetscObjectQuery()`
812: M*/
813: PETSC_EXTERN PetscErrorCode PetscObjectQueryFunction_Private(PetscObject obj, const char name[], void (**ptr)(void))
814: {
817:   (*obj->bops->queryfunction)(obj, name, ptr);
818:   return 0;
819: }

821: struct _p_PetscContainer {
822:   PETSCHEADER(int);
823:   void *ptr;
824:   PetscErrorCode (*userdestroy)(void *);
825: };

827: /*@C
828:    PetscContainerUserDestroyDefault - Default destroy routine for user-provided data that simply calls `PetscFree()` in the data
829:    provided with `PetscContainerSetPointer()`

831:    Logically Collective on the `PetscContainer` containing the user data

833:    Input Parameter:
834: .  ctx - pointer to user-provided data

836:    Level: advanced

838: .seealso: `PetscContainerDestroy()`, `PetscContainerSetUserDestroy()`
839: @*/
840: PetscErrorCode PetscContainerUserDestroyDefault(void *ctx)
841: {
842:   PetscFree(ctx);
843:   return 0;
844: }

846: /*@C
847:    PetscContainerGetPointer - Gets the pointer value contained in the container that was provided with `PetscContainerSetPointer()`

849:    Not Collective

851:    Input Parameter:
852: .  obj - the object created with `PetscContainerCreate()`

854:    Output Parameter:
855: .  ptr - the pointer value

857:    Level: advanced

859: .seealso: `PetscContainerCreate()`, `PetscContainerDestroy()`,
860:           `PetscContainerSetPointer()`
861: @*/
862: PetscErrorCode PetscContainerGetPointer(PetscContainer obj, void **ptr)
863: {
866:   *ptr = obj->ptr;
867:   return 0;
868: }

870: /*@C
871:    PetscContainerSetPointer - Sets the pointer value contained in the container.

873:    Logically Collective on obj

875:    Input Parameters:
876: +  obj - the object created with `PetscContainerCreate()`
877: -  ptr - the pointer value

879:    Level: advanced

881: .seealso: `PetscContainerCreate()`, `PetscContainerDestroy()`, `PetscObjectCompose()`, `PetscObjectQuery()`,
882:           `PetscContainerGetPointer()`
883: @*/
884: PetscErrorCode PetscContainerSetPointer(PetscContainer obj, void *ptr)
885: {
888:   obj->ptr = ptr;
889:   return 0;
890: }

892: /*@C
893:    PetscContainerDestroy - Destroys a PETSc container object.

895:    Collective on obj

897:    Input Parameter:
898: .  obj - an object that was created with `PetscContainerCreate()`

900:    Level: advanced

902:    Note:
903:    If `PetscContainerSetUserDestroy()` was used to provide a user destroy object for the data provided with `PetscContainerSetPointer()`
904:    then that function is called to destroy the data.

906: .seealso: `PetscContainerCreate()`, `PetscContainerSetUserDestroy()`
907: @*/
908: PetscErrorCode PetscContainerDestroy(PetscContainer *obj)
909: {
910:   if (!*obj) return 0;
912:   if (--((PetscObject)(*obj))->refct > 0) {
913:     *obj = NULL;
914:     return 0;
915:   }
916:   if ((*obj)->userdestroy) (*(*obj)->userdestroy)((*obj)->ptr);
917:   PetscHeaderDestroy(obj);
918:   return 0;
919: }

921: /*@C
922:    PetscContainerSetUserDestroy - Sets name of the user destroy function for the data provided to the `PetscContainer` with `PetscContainerSetPointer()`

924:    Logically Collective on obj

926:    Input Parameters:
927: +  obj - an object that was created with `PetscContainerCreate()`
928: -  des - name of the user destroy function

930:    Note:
931:    Use `PetscContainerUserDestroyDefault()` if the memory was obtained by calling `PetscMalloc()` or one of its variants for single memory allocation.

933:    Level: advanced

935: .seealso: `PetscContainerDestroy()`, `PetscContainerUserDestroyDefault()`, `PetscMalloc()`, `PetscMalloc1()`, `PetscCalloc()`, `PetscCalloc1()`
936: @*/
937: PetscErrorCode PetscContainerSetUserDestroy(PetscContainer obj, PetscErrorCode (*des)(void *))
938: {
940:   obj->userdestroy = des;
941:   return 0;
942: }

944: PetscClassId PETSC_CONTAINER_CLASSID;

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

952:    Collective

954:    Input Parameters:
955: .  comm - MPI communicator that shares the object

957:    Output Parameters:
958: .  container - the container created

960:    Level: advanced

962: .seealso: `PetscContainerDestroy()`, `PetscContainerSetPointer()`, `PetscContainerGetPointer()`, `PetscObjectCompose()`, `PetscObjectQuery()`,
963:           `PetscContainerSetUserDestroy()`
964: @*/
965: PetscErrorCode PetscContainerCreate(MPI_Comm comm, PetscContainer *container)
966: {
968:   PetscSysInitializePackage();
969:   PetscHeaderCreate(*container, PETSC_CONTAINER_CLASSID, "PetscContainer", "Container", "Sys", comm, PetscContainerDestroy, NULL);
970:   return 0;
971: }

973: /*@
974:    PetscObjectSetFromOptions - Sets generic parameters from user options.

976:    Collective on obj

978:    Input Parameter:
979: .  obj - the `PetscObject`

981:    Note:
982:    We have no generic options at present, so this does nothing

984:    Level: beginner

986: .seealso: `PetscObjectSetOptionsPrefix()`, `PetscObjectGetOptionsPrefix()`
987: @*/
988: PetscErrorCode PetscObjectSetFromOptions(PetscObject obj)
989: {
991:   return 0;
992: }

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

997:    Collective on obj

999:    Input Parameters:
1000: .  obj - the `PetscObject`

1002:    Note:
1003:    This does nothing at present.

1005:    Level: advanced

1007: .seealso: `PetscObjectDestroy()`
1008: @*/
1009: PetscErrorCode PetscObjectSetUp(PetscObject obj)
1010: {
1012:   return 0;
1013: }