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:   void       *get_tmp;
 38:   PetscInt64 *cidx;
 39:   PetscMPIInt flg;

 41:   h->classid               = classid;
 42:   h->class_name            = (char *)class_name;
 43:   h->description           = (char *)descr;
 44:   h->mansec                = (char *)mansec;
 45:   h->refct                 = 1;
 46:   h->non_cyclic_references = NULL;
 47:   h->id                    = PetscObjectNewId_Internal();
 48:   h->bops->destroy         = destroy;
 49:   h->bops->view            = view;
 50:   h->bops->compose         = PetscObjectCompose_Petsc;
 51:   h->bops->query           = PetscObjectQuery_Petsc;
 52:   h->bops->composefunction = PetscObjectComposeFunction_Petsc;
 53:   h->bops->queryfunction   = PetscObjectQueryFunction_Petsc;

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

 57:   /* Increment and store current object creation index */
 58:   MPI_Comm_get_attr(h->comm, Petsc_CreationIdx_keyval, &get_tmp, &flg);
 59:   if (flg) {
 60:     cidx    = (PetscInt64 *)get_tmp;
 61:     h->cidx = (*cidx)++;
 62:     MPI_Comm_set_attr(h->comm, Petsc_CreationIdx_keyval, cidx);
 63:   } else SETERRQ(h->comm, PETSC_ERR_ARG_CORRUPT, "MPI_Comm does not have an object creation index");

 65: #if defined(PETSC_USE_LOG)
 66:   /* Keep a record of object created */
 67:   if (PetscObjectsLog) {
 68:     PetscObject *newPetscObjects;
 69:     PetscInt     newPetscObjectsMaxCounts;

 71:     PetscObjectsCounts++;
 72:     for (PetscInt i = 0; i < PetscObjectsMaxCounts; ++i) {
 73:       if (!PetscObjects[i]) {
 74:         PetscObjects[i] = h;
 75:         return 0;
 76:       }
 77:     }
 78:     /* Need to increase the space for storing PETSc objects */
 79:     if (!PetscObjectsMaxCounts) newPetscObjectsMaxCounts = 100;
 80:     else newPetscObjectsMaxCounts = 2 * PetscObjectsMaxCounts;
 81:     PetscCalloc1(newPetscObjectsMaxCounts, &newPetscObjects);
 82:     PetscArraycpy(newPetscObjects, PetscObjects, PetscObjectsMaxCounts);
 83:     PetscFree(PetscObjects);

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

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

 96: /*
 97:     PetscHeaderDestroy_Private - Destroys a base PETSc object header. Called by
 98:     the macro PetscHeaderDestroy().
 99: */
100: PetscErrorCode PetscHeaderDestroy_Private(PetscObject obj, PetscBool clear_for_reuse)
101: {
103:   PetscLogObjectDestroy(obj);
104:   PetscComposedQuantitiesDestroy(obj);
105:   if (PetscMemoryCollectMaximumUsage) {
106:     PetscLogDouble usage;

108:     PetscMemoryGetCurrentUsage(&usage);
109:     if (usage > PetscMemoryMaximumUsage) PetscMemoryMaximumUsage = usage;
110:   }
111:   /* first destroy things that could execute arbitrary code */
112:   if (obj->python_destroy) {
113:     void *python_context                     = obj->python_context;
114:     PetscErrorCode (*python_destroy)(void *) = obj->python_destroy;

116:     obj->python_context = NULL;
117:     obj->python_destroy = NULL;
118:     (*python_destroy)(python_context);
119:   }
120:   PetscObjectDestroyOptionsHandlers(obj);
121:   PetscObjectListDestroy(&obj->olist);

123:   /* destroy allocated quantities */
124:   if (PetscPrintFunctionList) PetscFunctionListPrintNonEmpty(obj->qlist);
126:   PetscFree(obj->name);
127:   PetscFree(obj->prefix);
128:   PetscFree(obj->type_name);

130:   if (clear_for_reuse) {
131:     /* we will assume that obj->bops->view and destroy are safe to leave as-is */
132:     obj->bops->compose         = PetscObjectCompose_Petsc;
133:     obj->bops->query           = PetscObjectQuery_Petsc;
134:     obj->bops->composefunction = PetscObjectComposeFunction_Petsc;
135:     obj->bops->queryfunction   = PetscObjectQueryFunction_Petsc;

137:     /* reset quantities, in order of appearance in _p_PetscObject */
138:     obj->id       = PetscObjectNewId_Internal();
139:     obj->refct    = 1;
140:     obj->tablevel = 0;
141:     obj->state    = 0;
142:     /* don't deallocate, zero these out instead */
143:     PetscFunctionListClear(obj->qlist);
144:     PetscArrayzero(obj->fortran_func_pointers, obj->num_fortran_func_pointers);
145:     PetscArrayzero(obj->fortrancallback[PETSC_FORTRAN_CALLBACK_CLASS], obj->num_fortrancallback[PETSC_FORTRAN_CALLBACK_CLASS]);
146:     PetscArrayzero(obj->fortrancallback[PETSC_FORTRAN_CALLBACK_SUBTYPE], obj->num_fortrancallback[PETSC_FORTRAN_CALLBACK_SUBTYPE]);
147:     obj->optionsprinted = PETSC_FALSE;
148: #if PetscDefined(HAVE_SAWS)
149:     obj->amsmem          = PETSC_FALSE;
150:     obj->amspublishblock = PETSC_FALSE;
151: #endif
152:     obj->options                                  = NULL;
153:     obj->donotPetscObjectPrintClassNamePrefixType = PETSC_FALSE;
154:   } else {
155:     PetscFunctionListDestroy(&obj->qlist);
156:     PetscFree(obj->fortran_func_pointers);
157:     PetscFree(obj->fortrancallback[PETSC_FORTRAN_CALLBACK_CLASS]);
158:     PetscFree(obj->fortrancallback[PETSC_FORTRAN_CALLBACK_SUBTYPE]);
159:     PetscCommDestroy(&obj->comm);
160:     obj->classid = PETSCFREEDHEADER;

162: #if PetscDefined(USE_LOG)
163:     if (PetscObjectsLog) {
164:       /* Record object removal from list of all objects */
165:       for (PetscInt i = 0; i < PetscObjectsMaxCounts; ++i) {
166:         if (PetscObjects[i] == obj) {
167:           PetscObjects[i] = NULL;
168:           --PetscObjectsCounts;
169:           break;
170:         }
171:       }
172:       if (!PetscObjectsCounts) {
173:         PetscFree(PetscObjects);
174:         PetscObjectsMaxCounts = 0;
175:       }
176:     }
177: #endif
178:   }
179:   return 0;
180: }

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

186:   - classid
187:   - bops->view
188:   - bops->destroy
189:   - comm
190:   - tag
191:   - class_name
192:   - description
193:   - mansec
194:   - cpp

196:   Note that while subclass information is lost, superclass info remains. Thus this function is
197:   intended to be used to reuse a PetscObject within the same class to avoid reallocating its
198:   resources.
199: */
200: PetscErrorCode PetscHeaderReset_Internal(PetscObject obj)
201: {
202:   PetscHeaderDestroy_Private(obj, PETSC_TRUE);
203:   return 0;
204: }

206: /*@C
207:    PetscObjectCopyFortranFunctionPointers - Copy function pointers to another object

209:    Logically Collective

211:    Input Parameters:
212: +  src - source object
213: -  dest - destination object

215:    Level: developer

217:    Note:
218:    Both objects must have the same class.

220:    This is used to help manage user callback functions that were provided in Fortran
221: @*/
222: PetscErrorCode PetscObjectCopyFortranFunctionPointers(PetscObject src, PetscObject dest)
223: {
224:   PetscFortranCallbackId cbtype, numcb[PETSC_FORTRAN_CALLBACK_MAXTYPE];


230:   PetscFree(dest->fortran_func_pointers);
231:   PetscMalloc(src->num_fortran_func_pointers * sizeof(void (*)(void)), &dest->fortran_func_pointers);
232:   PetscMemcpy(dest->fortran_func_pointers, src->fortran_func_pointers, src->num_fortran_func_pointers * sizeof(void (*)(void)));

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

236:   PetscFortranCallbackGetSizes(src->classid, &numcb[PETSC_FORTRAN_CALLBACK_CLASS], &numcb[PETSC_FORTRAN_CALLBACK_SUBTYPE]);
237:   for (cbtype = PETSC_FORTRAN_CALLBACK_CLASS; cbtype < PETSC_FORTRAN_CALLBACK_MAXTYPE; cbtype++) {
238:     PetscFree(dest->fortrancallback[cbtype]);
239:     PetscCalloc1(numcb[cbtype], &dest->fortrancallback[cbtype]);
240:     PetscMemcpy(dest->fortrancallback[cbtype], src->fortrancallback[cbtype], src->num_fortrancallback[cbtype] * sizeof(PetscFortranCallback));
241:     dest->num_fortrancallback[cbtype] = src->num_fortrancallback[cbtype];
242:   }
243:   return 0;
244: }

246: /*@C
247:    PetscObjectSetFortranCallback - set fortran callback function pointer and context

249:    Logically Collective

251:    Input Parameters:
252: +  obj - object on which to set callback
253: .  cbtype - callback type (class or subtype)
254: .  cid - address of callback Id, updated if not yet initialized (zero)
255: .  func - Fortran function
256: -  ctx - Fortran context

258:    Level: developer

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

263: .seealso: `PetscObjectGetFortranCallback()`
264: @*/
265: PetscErrorCode PetscObjectSetFortranCallback(PetscObject obj, PetscFortranCallbackType cbtype, PetscFortranCallbackId *cid, void (*func)(void), void *ctx)
266: {
267:   const char *subtype = NULL;

270:   if (cbtype == PETSC_FORTRAN_CALLBACK_SUBTYPE) subtype = obj->type_name;
271:   if (!*cid) PetscFortranCallbackRegister(obj->classid, subtype, cid);
272:   if (*cid >= PETSC_SMALLEST_FORTRAN_CALLBACK + obj->num_fortrancallback[cbtype]) {
273:     PetscFortranCallbackId oldnum = obj->num_fortrancallback[cbtype];
274:     PetscFortranCallbackId newnum = PetscMax(*cid - PETSC_SMALLEST_FORTRAN_CALLBACK + 1, 2 * oldnum);
275:     PetscFortranCallback  *callback;
276:     PetscMalloc1(newnum, &callback);
277:     PetscMemcpy(callback, obj->fortrancallback[cbtype], oldnum * sizeof(*obj->fortrancallback[cbtype]));
278:     PetscFree(obj->fortrancallback[cbtype]);

280:     obj->fortrancallback[cbtype]     = callback;
281:     obj->num_fortrancallback[cbtype] = newnum;
282:   }
283:   obj->fortrancallback[cbtype][*cid - PETSC_SMALLEST_FORTRAN_CALLBACK].func = func;
284:   obj->fortrancallback[cbtype][*cid - PETSC_SMALLEST_FORTRAN_CALLBACK].ctx  = ctx;
285:   return 0;
286: }

288: /*@C
289:    PetscObjectGetFortranCallback - get fortran callback function pointer and context

291:    Logically Collective

293:    Input Parameters:
294: +  obj - object on which to get callback
295: .  cbtype - callback type
296: -  cid - address of callback Id

298:    Output Parameters:
299: +  func - Fortran function (or NULL if not needed)
300: -  ctx - Fortran context (or NULL if not needed)

302:    Level: developer

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

307: .seealso: `PetscObjectSetFortranCallback()`
308: @*/
309: PetscErrorCode PetscObjectGetFortranCallback(PetscObject obj, PetscFortranCallbackType cbtype, PetscFortranCallbackId cid, void (**func)(void), void **ctx)
310: {
311:   PetscFortranCallback *cb;

316:   cb = &obj->fortrancallback[cbtype][cid - PETSC_SMALLEST_FORTRAN_CALLBACK];
317:   if (func) *func = cb->func;
318:   if (ctx) *ctx = cb->ctx;
319:   return 0;
320: }

322: #if defined(PETSC_USE_LOG)
323: /*@C
324:    PetscObjectsDump - Prints all the currently existing objects.

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

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

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

335:    Level: advanced

337: @*/
338: PetscErrorCode PetscObjectsDump(FILE *fd, PetscBool all)
339: {
340:   PetscInt i;
341:   #if defined(PETSC_USE_DEBUG)
342:   PetscInt j, k = 0;
343:   #endif
344:   PetscObject h;

346:   if (PetscObjectsCounts) {
347:     PetscFPrintf(PETSC_COMM_WORLD, fd, "The following objects were never freed\n");
348:     PetscFPrintf(PETSC_COMM_WORLD, fd, "-----------------------------------------\n");
349:     for (i = 0; i < PetscObjectsMaxCounts; i++) {
350:       if ((h = PetscObjects[i])) {
351:         PetscObjectName(h);
352:         {
353:   #if defined(PETSC_USE_DEBUG)
354:           PetscStack *stack = NULL;
355:           char       *create, *rclass;

357:           /* if the PETSc function the user calls is not a create then this object was NOT directly created by them */
358:           PetscMallocGetStack(h, &stack);
359:           if (stack) {
360:             k = stack->currentsize - 2;
361:             if (!all) {
362:               k = 0;
363:               while (!stack->petscroutine[k]) k++;
364:               PetscStrstr(stack->function[k], "Create", &create);
365:               if (!create) PetscStrstr(stack->function[k], "Get", &create);
366:               PetscStrstr(stack->function[k], h->class_name, &rclass);
367:               if (!create) continue;
368:               if (!rclass) continue;
369:             }
370:           }
371:   #endif

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

375:   #if defined(PETSC_USE_DEBUG)
376:           PetscMallocGetStack(h, &stack);
377:           if (stack) {
378:             for (j = k; j >= 0; j--) fprintf(fd, "      [%d]  %s() in %s\n", PetscGlobalRank, stack->function[j], stack->file[j]);
379:           }
380:   #endif
381:         }
382:       }
383:     }
384:   }
385:   return 0;
386: }
387: #endif

389: #if defined(PETSC_USE_LOG)

391: /*@C
392:    PetscObjectsView - Prints the currently existing objects.

394:    Logically Collective

396:    Input Parameter:
397: .  viewer - must be an `PETSCVIEWERASCII` viewer

399:    Level: advanced

401: @*/
402: PetscErrorCode PetscObjectsView(PetscViewer viewer)
403: {
404:   PetscBool isascii;
405:   FILE     *fd;

407:   if (!viewer) viewer = PETSC_VIEWER_STDOUT_WORLD;
408:   PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii);
410:   PetscViewerASCIIGetPointer(viewer, &fd);
411:   PetscObjectsDump(fd, PETSC_TRUE);
412:   return 0;
413: }

415: /*@C
416:    PetscObjectsGetObject - Get a pointer to a named object

418:    Not collective

420:    Input Parameter:
421: .  name - the name of an object

423:    Output Parameters:
424: +  obj - the object or null if there is no object
425: -  classname - the name of the class

427:    Level: advanced

429: @*/
430: PetscErrorCode PetscObjectsGetObject(const char *name, PetscObject *obj, char **classname)
431: {
432:   PetscInt    i;
433:   PetscObject h;
434:   PetscBool   flg;

438:   *obj = NULL;
439:   for (i = 0; i < PetscObjectsMaxCounts; i++) {
440:     if ((h = PetscObjects[i])) {
441:       PetscObjectName(h);
442:       PetscStrcmp(h->name, name, &flg);
443:       if (flg) {
444:         *obj = h;
445:         if (classname) *classname = h->class_name;
446:         return 0;
447:       }
448:     }
449:   }
450:   return 0;
451: }
452: #endif

454: /*@
455:    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

457:    Input Parameters:
458: .  obj  - the `PetscObject`

460:    Level: developer

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

466: .seealso: `PetscOptionsInsert()`
467: @*/
468: PetscErrorCode PetscObjectSetPrintedOptions(PetscObject obj)
469: {
471:   obj->optionsprinted = PETSC_TRUE;
472:   return 0;
473: }

475: /*@
476:    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.

478:    Input Parameters:
479: +  pobj - the parent object
480: -  obj  - the PetscObject

482:    Level: developer

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

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

490: .seealso: `PetscOptionsInsert()`, `PetscObjectSetPrintedOptions()`
491: @*/
492: PetscErrorCode PetscObjectInheritPrintedOptions(PetscObject pobj, PetscObject obj)
493: {
494:   PetscMPIInt prank, size;

498:   MPI_Comm_rank(pobj->comm, &prank);
499:   MPI_Comm_size(obj->comm, &size);
500:   if (size == 1 && prank > 0) obj->optionsprinted = PETSC_TRUE;
501:   return 0;
502: }

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

507:     Not Collective

509:     Input Parameters:
510: +   obj - the PETSc object
511: .   handle - function that checks for options
512: .   destroy - function to destroy context if provided
513: -   ctx - optional context for check function

515:     Level: developer

517: .seealso: `KSPSetFromOptions()`, `PCSetFromOptions()`, `SNESSetFromOptions()`, `PetscObjectProcessOptionsHandlers()`, `PetscObjectDestroyOptionsHandlers()`
518: @*/
519: PetscErrorCode PetscObjectAddOptionsHandler(PetscObject obj, PetscErrorCode (*handle)(PetscObject, PetscOptionItems *, void *), PetscErrorCode (*destroy)(PetscObject, void *), void *ctx)
520: {
523:   obj->optionhandler[obj->noptionhandler] = handle;
524:   obj->optiondestroy[obj->noptionhandler] = destroy;
525:   obj->optionctx[obj->noptionhandler++]   = ctx;
526:   return 0;
527: }

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

532:     Not Collective

534:     Input Parameters:
535: +   obj - the PETSc object
536: -   PetscOptionsObject - the options context

538:     Level: developer

540: .seealso: `KSPSetFromOptions()`, `PCSetFromOptions()`, `SNESSetFromOptions()`, `PetscObjectAddOptionsHandler()`, `PetscObjectDestroyOptionsHandlers()`
541: @*/
542: PetscErrorCode PetscObjectProcessOptionsHandlers(PetscObject obj, PetscOptionItems *PetscOptionsObject)
543: {
545:   for (PetscInt i = 0; i < obj->noptionhandler; i++) (*obj->optionhandler[i])(obj, PetscOptionsObject, obj->optionctx[i]);
546:   return 0;
547: }

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

552:     Not Collective

554:     Input Parameter:
555: .   obj - the PETSc object

557:     Level: developer

559: .seealso: `KSPSetFromOptions()`, `PCSetFromOptions()`, `SNESSetFromOptions()`, `PetscObjectAddOptionsHandler()`, `PetscObjectProcessOptionsHandlers()`
560: @*/
561: PetscErrorCode PetscObjectDestroyOptionsHandlers(PetscObject obj)
562: {
564:   for (PetscInt i = 0; i < obj->noptionhandler; i++) {
565:     if (obj->optiondestroy[i]) (*obj->optiondestroy[i])(obj, obj->optionctx[i]);
566:   }
567:   obj->noptionhandler = 0;
568:   return 0;
569: }

571: /*@C
572:    PetscObjectReference - Indicates to any `PetscObject` that it is being
573:    referenced by another `PetscObject`. This increases the reference
574:    count for that object by one.

576:    Logically Collective

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

582:    Level: advanced

584: .seealso: `PetscObjectCompose()`, `PetscObjectDereference()`
585: @*/
586: PetscErrorCode PetscObjectReference(PetscObject obj)
587: {
588:   if (!obj) return 0;
590:   obj->refct++;
591:   return 0;
592: }

594: /*@C
595:    PetscObjectGetReference - Gets the current reference count for
596:    any PETSc object.

598:    Not Collective

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

604:    Output Parameter:
605: .  cnt - the reference count

607:    Level: advanced

609: .seealso: `PetscObjectCompose()`, `PetscObjectDereference()`, `PetscObjectReference()`
610: @*/
611: PetscErrorCode PetscObjectGetReference(PetscObject obj, PetscInt *cnt)
612: {
615:   *cnt = obj->refct;
616:   return 0;
617: }

619: /*@C
620:    PetscObjectDereference - Indicates to any `PetscObject` that it is being
621:    referenced by one less `PetscObject`. This decreases the reference
622:    count for that object by one.

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

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

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

633:    Level: advanced

635: .seealso: `PetscObjectCompose()`, `PetscObjectReference()`, `PetscObjectDestroy()`
636: @*/
637: PetscErrorCode PetscObjectDereference(PetscObject obj)
638: {
639:   if (!obj) return 0;
641:   if (obj->bops->destroy) (*obj->bops->destroy)(&obj);
643:   return 0;
644: }

646: /* ----------------------------------------------------------------------- */
647: /*
648:      The following routines are the versions private to the PETSc object
649:      data structures.
650: */
651: PetscErrorCode PetscObjectRemoveReference(PetscObject obj, const char name[])
652: {
654:   PetscObjectListRemoveReference(&obj->olist, name);
655:   return 0;
656: }

658: PetscErrorCode PetscObjectCompose_Petsc(PetscObject obj, const char name[], PetscObject ptr)
659: {
660:   if (ptr) {
661:     char     *tname;
662:     PetscBool skipreference;

664:     PetscObjectListReverseFind(ptr->olist, obj, &tname, &skipreference);
666:   }
667:   PetscObjectListAdd(&obj->olist, name, ptr);
668:   return 0;
669: }

671: PetscErrorCode PetscObjectQuery_Petsc(PetscObject obj, const char name[], PetscObject *ptr)
672: {
674:   PetscObjectListFind(obj->olist, name, ptr);
675:   return 0;
676: }

678: PetscErrorCode PetscObjectComposeFunction_Petsc(PetscObject obj, const char name[], void (*ptr)(void))
679: {
681:   PetscFunctionListAdd(&obj->qlist, name, ptr);
682:   return 0;
683: }

685: PetscErrorCode PetscObjectQueryFunction_Petsc(PetscObject obj, const char name[], void (**ptr)(void))
686: {
688:   PetscFunctionListFind(obj->qlist, name, ptr);
689:   return 0;
690: }

692: /*@C
693:    PetscObjectCompose - Associates another PETSc object with a given PETSc object.

695:    Not Collective

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

704:    Level: advanced

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

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

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

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

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

721: .seealso: `PetscObjectQuery()`, `PetscContainerCreate()`, `PetscObjectComposeFunction()`, `PetscObjectQueryFunction()`, `PetscContainer`,
722:           `PetscContainerSetPointer()`
723: @*/
724: PetscErrorCode PetscObjectCompose(PetscObject obj, const char name[], PetscObject ptr)
725: {
730:   (*obj->bops->compose)(obj, name, ptr);
731:   return 0;
732: }

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

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:    Note:
750:    The reference count of neither object is increased in this call

752: .seealso: `PetscObjectCompose()`, `PetscObjectComposeFunction()`, `PetscObjectQueryFunction()`, `PetscContainer`
753:           `PetscContainerGetPointer()`
754: @*/
755: PetscErrorCode PetscObjectQuery(PetscObject obj, const char name[], PetscObject *ptr)
756: {
760:   (*obj->bops->query)(obj, name, ptr);
761:   return 0;
762: }

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

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

771:    Logically Collective

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

779:    Level: advanced

781:    Notes:
782:    When the first argument of `fptr` is (or is derived from) a `PetscObject` then `PetscTryMethod()` and `PetscUseMethod()`
783:    can be used to call the function directly with error checking.

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:    `PetscCallMethod()` is used to call a function that is stored in the objects `obj->ops` table.

792: .seealso: `PetscObjectQueryFunction()`, `PetscContainerCreate()` `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscTryMethod()`, `PetscUseMethod()`,
793:           `PetscCallMethod()`
794: M*/

796: PetscErrorCode PetscObjectComposeFunction_Private(PetscObject obj, const char name[], void (*fptr)(void))
797: {
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

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()`, `PetscObjectCompose()`, `PetscObjectQuery()`
824: M*/
825: PETSC_EXTERN PetscErrorCode PetscObjectQueryFunction_Private(PetscObject obj, const char name[], void (**ptr)(void))
826: {
829:   (*obj->bops->queryfunction)(obj, name, ptr);
830:   return 0;
831: }

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

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

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

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

848:    Level: advanced

850: .seealso: `PetscContainerDestroy()`, `PetscContainerSetUserDestroy()`
851: @*/
852: PetscErrorCode PetscContainerUserDestroyDefault(void *ctx)
853: {
854:   PetscFree(ctx);
855:   return 0;
856: }

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

861:    Not Collective

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

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

869:    Level: advanced

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

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

885:    Logically Collective

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

891:    Level: advanced

893: .seealso: `PetscContainerCreate()`, `PetscContainerDestroy()`, `PetscObjectCompose()`, `PetscObjectQuery()`,
894:           `PetscContainerGetPointer()`
895: @*/
896: PetscErrorCode PetscContainerSetPointer(PetscContainer obj, void *ptr)
897: {
900:   obj->ptr = ptr;
901:   return 0;
902: }

904: /*@C
905:    PetscContainerDestroy - Destroys a PETSc container object.

907:    Collective

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

912:    Level: advanced

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

918: .seealso: `PetscContainerCreate()`, `PetscContainerSetUserDestroy()`
919: @*/
920: PetscErrorCode PetscContainerDestroy(PetscContainer *obj)
921: {
922:   if (!*obj) return 0;
924:   if (--((PetscObject)(*obj))->refct > 0) {
925:     *obj = NULL;
926:     return 0;
927:   }
928:   if ((*obj)->userdestroy) (*(*obj)->userdestroy)((*obj)->ptr);
929:   PetscHeaderDestroy(obj);
930:   return 0;
931: }

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

936:    Logically Collective

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

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

945:    Level: advanced

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

956: PetscClassId PETSC_CONTAINER_CLASSID;

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

964:    Collective

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

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

972:    Level: advanced

974: .seealso: `PetscContainerDestroy()`, `PetscContainerSetPointer()`, `PetscContainerGetPointer()`, `PetscObjectCompose()`, `PetscObjectQuery()`,
975:           `PetscContainerSetUserDestroy()`
976: @*/
977: PetscErrorCode PetscContainerCreate(MPI_Comm comm, PetscContainer *container)
978: {
980:   PetscSysInitializePackage();
981:   PetscHeaderCreate(*container, PETSC_CONTAINER_CLASSID, "PetscContainer", "Container", "Sys", comm, PetscContainerDestroy, NULL);
982:   return 0;
983: }

985: /*@
986:    PetscObjectSetFromOptions - Sets generic parameters from user options.

988:    Collective

990:    Input Parameter:
991: .  obj - the `PetscObject`

993:    Note:
994:    We have no generic options at present, so this does nothing

996:    Level: beginner

998: .seealso: `PetscObjectSetOptionsPrefix()`, `PetscObjectGetOptionsPrefix()`
999: @*/
1000: PetscErrorCode PetscObjectSetFromOptions(PetscObject obj)
1001: {
1003:   return 0;
1004: }

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

1009:    Collective

1011:    Input Parameters:
1012: .  obj - the `PetscObject`

1014:    Note:
1015:    This does nothing at present.

1017:    Level: advanced

1019: .seealso: `PetscObjectDestroy()`
1020: @*/
1021: PetscErrorCode PetscObjectSetUp(PetscObject obj)
1022: {
1024:   return 0;
1025: }