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: PETSC_INTERN PetscObject *PetscObjects;
  8: PETSC_INTERN PetscInt     PetscObjectsCounts;
  9: PETSC_INTERN PetscInt     PetscObjectsMaxCounts;
 10: PETSC_INTERN PetscBool    PetscObjectsLog;

 12: PetscObject *PetscObjects       = NULL;
 13: PetscInt     PetscObjectsCounts = 0, PetscObjectsMaxCounts = 0;
 14: PetscBool    PetscObjectsLog = PETSC_FALSE;

 16: PetscObjectId PetscObjectNewId_Internal(void)
 17: {
 18:   static PetscObjectId idcnt = 1;
 19:   return idcnt++;
 20: }

 22: PetscErrorCode PetscHeaderCreate_Function(PetscErrorCode ierr, PetscObject *h, PetscClassId classid, const char class_name[], const char descr[], const char mansec[], MPI_Comm comm, PetscObjectDestroyFunction destroy, PetscObjectViewFunction view)
 23: {
 24:   if (ierr) return ierr;
 25:   PetscFunctionBegin;
 26:   PetscCall(PetscHeaderCreate_Private(*h, classid, class_name, descr, mansec, comm, destroy, view));
 27:   PetscCall(PetscLogObjectCreate(*h));
 28:   PetscFunctionReturn(PETSC_SUCCESS);
 29: }

 31: /*
 32:    PetscHeaderCreate_Private - Fills in the default values.
 33: */
 34: PetscErrorCode PetscHeaderCreate_Private(PetscObject h, PetscClassId classid, const char class_name[], const char descr[], const char mansec[], MPI_Comm comm, PetscObjectDestroyFunction destroy, PetscObjectViewFunction view)
 35: {
 36:   void       *get_tmp;
 37:   PetscInt64 *cidx;
 38:   PetscMPIInt flg;

 40:   PetscFunctionBegin;
 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;

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

 53:   /* Increment and store current object creation index */
 54:   PetscCallMPI(MPI_Comm_get_attr(h->comm, Petsc_CreationIdx_keyval, &get_tmp, &flg));
 55:   PetscCheck(flg, h->comm, PETSC_ERR_ARG_CORRUPT, "MPI_Comm does not have an object creation index");
 56:   cidx    = (PetscInt64 *)get_tmp;
 57:   h->cidx = (*cidx)++;

 59:   /* Keep a record of object created */
 60:   if (PetscDefined(USE_LOG) && PetscObjectsLog) {
 61:     PetscObject *newPetscObjects;
 62:     PetscInt     newPetscObjectsMaxCounts;

 64:     PetscObjectsCounts++;
 65:     for (PetscInt i = 0; i < PetscObjectsMaxCounts; ++i) {
 66:       if (!PetscObjects[i]) {
 67:         PetscObjects[i] = h;
 68:         PetscFunctionReturn(PETSC_SUCCESS);
 69:       }
 70:     }
 71:     /* Need to increase the space for storing PETSc objects */
 72:     if (!PetscObjectsMaxCounts) newPetscObjectsMaxCounts = 100;
 73:     else newPetscObjectsMaxCounts = 2 * PetscObjectsMaxCounts;
 74:     PetscCall(PetscCalloc1(newPetscObjectsMaxCounts, &newPetscObjects));
 75:     PetscCall(PetscArraycpy(newPetscObjects, PetscObjects, PetscObjectsMaxCounts));
 76:     PetscCall(PetscFree(PetscObjects));

 78:     PetscObjects                        = newPetscObjects;
 79:     PetscObjects[PetscObjectsMaxCounts] = h;
 80:     PetscObjectsMaxCounts               = newPetscObjectsMaxCounts;
 81:   }
 82:   PetscFunctionReturn(PETSC_SUCCESS);
 83: }

 85: PETSC_INTERN PetscBool      PetscMemoryCollectMaximumUsage;
 86: PETSC_INTERN PetscLogDouble PetscMemoryMaximumUsage;

 88: PetscErrorCode PetscHeaderDestroy_Function(PetscObject *h)
 89: {
 90:   PetscFunctionBegin;
 91:   PetscCall(PetscLogObjectDestroy(*h));
 92:   PetscCall(PetscHeaderDestroy_Private(*h, PETSC_FALSE));
 93:   PetscCall(PetscFree(*h));
 94:   PetscFunctionReturn(PETSC_SUCCESS);
 95: }

 97: /*
 98:     PetscHeaderDestroy_Private - Destroys a base PETSc object header. Called by
 99:     the macro PetscHeaderDestroy().
100: */
101: PetscErrorCode PetscHeaderDestroy_Private(PetscObject obj, PetscBool clear_for_reuse)
102: {
103:   PetscFunctionBegin;
105:   PetscCheck(!obj->persistent, PetscObjectComm((PetscObject)obj), PETSC_ERR_ARG_WRONGSTATE, "Cannot destroy this object, it is destroyed automatically in PetscFinalize()");
106:   PetscCall(PetscComposedQuantitiesDestroy(obj));
107:   if (PetscMemoryCollectMaximumUsage) {
108:     PetscLogDouble usage;

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

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

125:   /* destroy allocated quantities */
126:   if (PetscPrintFunctionList) PetscCall(PetscFunctionListPrintNonEmpty(obj->qlist));
127:   PetscCheck(--(obj->refct) <= 0, obj->comm, PETSC_ERR_PLIB, "Destroying a PetscObject (%s) with reference count %" PetscInt_FMT " >= 1", obj->name ? obj->name : "unnamed", obj->refct);
128:   PetscCall(PetscFree(obj->name));
129:   PetscCall(PetscFree(obj->prefix));
130:   PetscCall(PetscFree(obj->type_name));

132:   if (clear_for_reuse) {
133:     /* we will assume that obj->bops->view and destroy are safe to leave as-is */

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

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

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

182:   - classid
183:   - bops->view
184:   - bops->destroy
185:   - comm
186:   - tag
187:   - class_name
188:   - description
189:   - mansec
190:   - cpp

192:   Note that while subclass information is lost, superclass info remains. Thus this function is
193:   intended to be used to reuse a PetscObject within the same class to avoid reallocating its
194:   resources.
195: */
196: PetscErrorCode PetscHeaderReset_Internal(PetscObject obj)
197: {
198:   PetscFunctionBegin;
199:   PetscCall(PetscHeaderDestroy_Private(obj, PETSC_TRUE));
200:   PetscFunctionReturn(PETSC_SUCCESS);
201: }

203: /*@C
204:   PetscObjectCopyFortranFunctionPointers - Copy function pointers to another object

206:   Logically Collective

208:   Input Parameters:
209: + src  - source object
210: - dest - destination object

212:   Level: developer

214:   Note:
215:   Both objects must have the same class.

217:   This is used to help manage user callback functions that were provided in Fortran

219: .seealso: `PetscFortranCallbackRegister()`, `PetscFortranCallbackGetSizes()`
220: @*/
221: PetscErrorCode PetscObjectCopyFortranFunctionPointers(PetscObject src, PetscObject dest)
222: {
223:   PetscFortranCallbackId cbtype, numcb[PETSC_FORTRAN_CALLBACK_MAXTYPE];

225:   PetscFunctionBegin;
228:   PetscCheck(src->classid == dest->classid, src->comm, PETSC_ERR_ARG_INCOMP, "Objects must be of the same class");

230:   PetscCall(PetscFree(dest->fortran_func_pointers));
231:   PetscCall(PetscMalloc(src->num_fortran_func_pointers * sizeof(void (*)(void)), &dest->fortran_func_pointers));
232:   PetscCall(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:   PetscCall(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:     PetscCall(PetscFree(dest->fortrancallback[cbtype]));
239:     PetscCall(PetscCalloc1(numcb[cbtype], &dest->fortrancallback[cbtype]));
240:     PetscCall(PetscMemcpy(dest->fortrancallback[cbtype], src->fortrancallback[cbtype], src->num_fortrancallback[cbtype] * sizeof(PetscFortranCallback)));
241:     dest->num_fortrancallback[cbtype] = src->num_fortrancallback[cbtype];
242:   }
243:   PetscFunctionReturn(PETSC_SUCCESS);
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()`, `PetscFortranCallbackRegister()`, `PetscFortranCallbackGetSizes()`
264: @*/
265: PetscErrorCode PetscObjectSetFortranCallback(PetscObject obj, PetscFortranCallbackType cbtype, PetscFortranCallbackId *cid, void (*func)(void), void *ctx)
266: {
267:   const char *subtype = NULL;

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

281:     obj->fortrancallback[cbtype]     = callback;
282:     obj->num_fortrancallback[cbtype] = newnum;
283:   }
284:   obj->fortrancallback[cbtype][*cid - PETSC_SMALLEST_FORTRAN_CALLBACK].func = func;
285:   obj->fortrancallback[cbtype][*cid - PETSC_SMALLEST_FORTRAN_CALLBACK].ctx  = ctx;
286:   PetscFunctionReturn(PETSC_SUCCESS);
287: }

289: /*@C
290:   PetscObjectGetFortranCallback - get Fortran callback function pointer and context

292:   Logically Collective

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

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

303:   Level: developer

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

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

314:   PetscFunctionBegin;
316:   PetscCheck(cid >= PETSC_SMALLEST_FORTRAN_CALLBACK, obj->comm, PETSC_ERR_ARG_CORRUPT, "Fortran callback Id invalid");
317:   PetscCheck(cid < PETSC_SMALLEST_FORTRAN_CALLBACK + obj->num_fortrancallback[cbtype], obj->comm, PETSC_ERR_ARG_CORRUPT, "Fortran callback not set on this object");
318:   cb = &obj->fortrancallback[cbtype][cid - PETSC_SMALLEST_FORTRAN_CALLBACK];
319:   if (func) *func = cb->func;
320:   if (ctx) *ctx = cb->ctx;
321:   PetscFunctionReturn(PETSC_SUCCESS);
322: }

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

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:   Note:
338:   Only MPI rank 0 of `PETSC_COMM_WORLD` prints the values

340: .seealso: `PetscObject`
341: @*/
342: PetscErrorCode PetscObjectsDump(FILE *fd, PetscBool all)
343: {
344:   PetscInt    i, j, k = 0;
345:   PetscObject h;

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

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

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

375:           PetscCall(PetscMallocGetStack(h, &stack));
376:           if (stack) {
377:             for (j = k; j >= 0; j--) fprintf(fd, "      [%d]  %s() in %s\n", PetscGlobalRank, stack->function[j], stack->file[j]);
378:           }
379:         }
380:       }
381:     }
382:   }
383:   PetscFunctionReturn(PETSC_SUCCESS);
384: }

386: /*@C
387:   PetscObjectsView - Prints the currently existing objects.

389:   Logically Collective

391:   Input Parameter:
392: . viewer - must be an `PETSCVIEWERASCII` viewer

394:   Level: advanced

396: .seealso: `PetscObject`
397: @*/
398: PetscErrorCode PetscObjectsView(PetscViewer viewer)
399: {
400:   PetscBool isascii;
401:   FILE     *fd;

403:   PetscFunctionBegin;
404:   if (!viewer) viewer = PETSC_VIEWER_STDOUT_WORLD;
405:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
406:   PetscCheck(isascii, PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Only supports ASCII viewer");
407:   PetscCall(PetscViewerASCIIGetPointer(viewer, &fd));
408:   PetscCall(PetscObjectsDump(fd, PETSC_TRUE));
409:   PetscFunctionReturn(PETSC_SUCCESS);
410: }

412: /*@C
413:   PetscObjectsGetObject - Get a pointer to a named object

415:   Not Collective

417:   Input Parameter:
418: . name - the name of an object

420:   Output Parameters:
421: + obj       - the object or `NULL` if there is no object, optional, pass in `NULL` if not needed
422: - classname - the name of the class of the object, optional, pass in `NULL` if not needed

424:   Level: advanced

426: .seealso: `PetscObject`
427: @*/
428: PetscErrorCode PetscObjectsGetObject(const char *name, PetscObject *obj, char **classname)
429: {
430:   PetscInt    i;
431:   PetscObject h;
432:   PetscBool   flg;

434:   PetscFunctionBegin;
435:   PetscAssertPointer(name, 1);
436:   if (obj) *obj = NULL;
437:   for (i = 0; i < PetscObjectsMaxCounts; i++) {
438:     if ((h = PetscObjects[i])) {
439:       PetscCall(PetscObjectName(h));
440:       PetscCall(PetscStrcmp(h->name, name, &flg));
441:       if (flg) {
442:         if (obj) *obj = h;
443:         if (classname) *classname = h->class_name;
444:         PetscFunctionReturn(PETSC_SUCCESS);
445:       }
446:     }
447:   }
448:   PetscFunctionReturn(PETSC_SUCCESS);
449: }
450: #endif

452: /*@
453:   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

455:   Input Parameter:
456: . obj - the `PetscObject`

458:   Level: developer

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

464: .seealso: `PetscOptionsInsert()`, `PetscObject`
465: @*/
466: PetscErrorCode PetscObjectSetPrintedOptions(PetscObject obj)
467: {
468:   PetscFunctionBegin;
469:   PetscAssertPointer(obj, 1);
470:   obj->optionsprinted = PETSC_TRUE;
471:   PetscFunctionReturn(PETSC_SUCCESS);
472: }

474: /*@
475:   PetscObjectInheritPrintedOptions - If the child object is not on the MPI rank 0 process of the parent object and the child is sequential then the child gets it set.

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

481:   Level: developer

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

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

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

495:   PetscFunctionBegin;
498:   PetscCallMPI(MPI_Comm_rank(pobj->comm, &prank));
499:   PetscCallMPI(MPI_Comm_size(obj->comm, &size));
500:   if (size == 1 && prank > 0) obj->optionsprinted = PETSC_TRUE;
501:   PetscFunctionReturn(PETSC_SUCCESS);
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 `ctx` if provided
513: - ctx     - optional context for check function

515:   Calling sequence of `handle`:
516: + obj                - the PETSc object
517: . PetscOptionsObject - the `PetscOptionItems` object
518: - ctx                - optional context for `handle`

520:   Calling sequence of `destroy`:
521: + obj - the PETSc object
522: - ctx - optional context for `handle`

524:   Level: developer

526: .seealso: `KSPSetFromOptions()`, `PCSetFromOptions()`, `SNESSetFromOptions()`, `PetscObjectProcessOptionsHandlers()`, `PetscObjectDestroyOptionsHandlers()`,
527:           `PetscObject`
528: @*/
529: PetscErrorCode PetscObjectAddOptionsHandler(PetscObject obj, PetscErrorCode (*handle)(PetscObject obj, PetscOptionItems *PetscOptionsObject, void *ctx), PetscErrorCode (*destroy)(PetscObject obj, void *ctx), void *ctx)
530: {
531:   PetscFunctionBegin;
533:   PetscCheck(obj->noptionhandler < PETSC_MAX_OPTIONS_HANDLER, obj->comm, PETSC_ERR_ARG_OUTOFRANGE, "To many options handlers added");
534:   obj->optionhandler[obj->noptionhandler] = handle;
535:   obj->optiondestroy[obj->noptionhandler] = destroy;
536:   obj->optionctx[obj->noptionhandler++]   = ctx;
537:   PetscFunctionReturn(PETSC_SUCCESS);
538: }

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

543:   Not Collective

545:   Input Parameters:
546: + obj                - the PETSc object
547: - PetscOptionsObject - the options context

549:   Level: developer

551: .seealso: `KSPSetFromOptions()`, `PCSetFromOptions()`, `SNESSetFromOptions()`, `PetscObjectAddOptionsHandler()`, `PetscObjectDestroyOptionsHandlers()`,
552:           `PetscObject`
553: @*/
554: PetscErrorCode PetscObjectProcessOptionsHandlers(PetscObject obj, PetscOptionItems *PetscOptionsObject)
555: {
556:   PetscFunctionBegin;
558:   for (PetscInt i = 0; i < obj->noptionhandler; i++) PetscCall((*obj->optionhandler[i])(obj, PetscOptionsObject, obj->optionctx[i]));
559:   PetscFunctionReturn(PETSC_SUCCESS);
560: }

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

565:   Not Collective

567:   Input Parameter:
568: . obj - the PETSc object

570:   Level: developer

572: .seealso: `KSPSetFromOptions()`, `PCSetFromOptions()`, `SNESSetFromOptions()`, `PetscObjectAddOptionsHandler()`, `PetscObjectProcessOptionsHandlers()`,
573:           `PetscObject`
574: @*/
575: PetscErrorCode PetscObjectDestroyOptionsHandlers(PetscObject obj)
576: {
577:   PetscFunctionBegin;
579:   for (PetscInt i = 0; i < obj->noptionhandler; i++) {
580:     if (obj->optiondestroy[i]) PetscCall((*obj->optiondestroy[i])(obj, obj->optionctx[i]));
581:   }
582:   obj->noptionhandler = 0;
583:   PetscFunctionReturn(PETSC_SUCCESS);
584: }

586: /*@C
587:   PetscObjectReference - Indicates to a `PetscObject` that it is being
588:   referenced by another `PetscObject`. This increases the reference
589:   count for that object by one.

591:   Logically Collective

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

597:   Level: advanced

599: .seealso: `PetscObjectCompose()`, `PetscObjectDereference()`, `PetscObject`
600: @*/
601: PetscErrorCode PetscObjectReference(PetscObject obj)
602: {
603:   PetscFunctionBegin;
604:   if (!obj) PetscFunctionReturn(PETSC_SUCCESS);
606:   obj->refct++;
607:   PetscFunctionReturn(PETSC_SUCCESS);
608: }

610: /*@C
611:   PetscObjectGetReference - Gets the current reference count for a PETSc object.

613:   Not Collective

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

619:   Output Parameter:
620: . cnt - the reference count

622:   Level: advanced

624: .seealso: `PetscObjectCompose()`, `PetscObjectDereference()`, `PetscObjectReference()`, `PetscObject`
625: @*/
626: PetscErrorCode PetscObjectGetReference(PetscObject obj, PetscInt *cnt)
627: {
628:   PetscFunctionBegin;
630:   PetscAssertPointer(cnt, 2);
631:   *cnt = obj->refct;
632:   PetscFunctionReturn(PETSC_SUCCESS);
633: }

635: /*@C
636:   PetscObjectDereference - Indicates to any `PetscObject` that it is being
637:   referenced by one less `PetscObject`. This decreases the reference
638:   count for that object by one.

640:   Collective on `obj` if reference reaches 0 otherwise Logically Collective

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

646:   Level: advanced

648:   Note:
649:   `PetscObjectDestroy()` sets the `obj` pointer to `NULL` after the call, this routine does not.

651: .seealso: `PetscObjectCompose()`, `PetscObjectReference()`, `PetscObjectDestroy()`, `PetscObject`
652: @*/
653: PetscErrorCode PetscObjectDereference(PetscObject obj)
654: {
655:   PetscFunctionBegin;
656:   if (!obj) PetscFunctionReturn(PETSC_SUCCESS);
658:   if (obj->bops->destroy) PetscCall((*obj->bops->destroy)(&obj));
659:   else PetscCheck(--(obj->refct), PETSC_COMM_SELF, PETSC_ERR_SUP, "This PETSc object does not have a generic destroy routine");
660:   PetscFunctionReturn(PETSC_SUCCESS);
661: }

663: /*
664:      The following routines are the versions private to the PETSc object
665:      data structures.
666: */
667: PetscErrorCode PetscObjectRemoveReference(PetscObject obj, const char name[])
668: {
669:   PetscFunctionBegin;
671:   PetscCall(PetscObjectListRemoveReference(&obj->olist, name));
672:   PetscFunctionReturn(PETSC_SUCCESS);
673: }

675: /*@C
676:   PetscObjectCompose - Associates another PETSc object with a given PETSc object.

678:   Not Collective

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

687:   Level: advanced

689:   Notes:
690:   The second objects reference count is automatically increased by one when it is
691:   composed.

693:   Replaces any previous object that had been composed with the same name.

695:   If `ptr` is `NULL` and `name` has previously been composed using an object, then that
696:   entry is removed from `obj`.

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

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

704: .seealso: `PetscObjectQuery()`, `PetscContainerCreate()`, `PetscObjectComposeFunction()`, `PetscObjectQueryFunction()`, `PetscContainer`,
705:           `PetscContainerSetPointer()`, `PetscObject`
706: @*/
707: PetscErrorCode PetscObjectCompose(PetscObject obj, const char name[], PetscObject ptr)
708: {
709:   PetscFunctionBegin;
711:   PetscAssertPointer(name, 2);
713:   PetscCheck(obj != ptr, PetscObjectComm((PetscObject)obj), PETSC_ERR_SUP, "Cannot compose object with itself");
714:   if (ptr) {
715:     char     *tname;
716:     PetscBool skipreference;

718:     PetscCall(PetscObjectListReverseFind(ptr->olist, obj, &tname, &skipreference));
719:     if (tname) PetscCheck(skipreference, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "An object cannot be composed with an object that was composed with it");
720:   }
721:   PetscCall(PetscObjectListAdd(&obj->olist, name, ptr));
722:   PetscFunctionReturn(PETSC_SUCCESS);
723: }

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

728:   Not Collective

730:   Input Parameters:
731: + obj  - the PETSc object. It must be cast with a (`PetscObject`), for example,
732:          `PetscObjectCompose`((`PetscObject`)mat,...);
733: . name - name associated with child object
734: - ptr  - the other PETSc object associated with the PETSc object, this must be
735:          cast with (`PetscObject`*)

737:   Level: advanced

739:   Note:
740:   The reference count of neither object is increased in this call

742: .seealso: `PetscObjectCompose()`, `PetscObjectComposeFunction()`, `PetscObjectQueryFunction()`, `PetscContainer`
743:           `PetscContainerGetPointer()`, `PetscObject`
744: @*/
745: PetscErrorCode PetscObjectQuery(PetscObject obj, const char name[], PetscObject *ptr)
746: {
747:   PetscFunctionBegin;
749:   PetscAssertPointer(name, 2);
750:   PetscAssertPointer(ptr, 3);
751:   PetscCall(PetscObjectListFind(obj->olist, name, ptr));
752:   PetscFunctionReturn(PETSC_SUCCESS);
753: }

755: /*MC
756:   PetscObjectComposeFunction - Associates a function with a given PETSc object.

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

762:   Logically Collective

764:   Input Parameters:
765: + obj  - the PETSc object; this must be cast with a (`PetscObject`), for example,
766:          `PetscObjectCompose`((`PetscObject`)mat,...);
767: . name - name associated with the child function
768: - fptr - function pointer

770:   Level: advanced

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

776:   To remove a registered routine, pass in `NULL` for `fptr`.

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

781:   `PetscUseTypeMethod()` and `PetscTryTypeMethod()` are used to call a function that is stored in the objects `obj->ops` table.

783: .seealso: `PetscObjectQueryFunction()`, `PetscContainerCreate()` `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscTryMethod()`, `PetscUseMethod()`,
784:           `PetscUseTypeMethod()`, `PetscTryTypeMethod()`, `PetscObject`
785: M*/
786: PetscErrorCode PetscObjectComposeFunction_Private(PetscObject obj, const char name[], void (*fptr)(void))
787: {
788:   PetscFunctionBegin;
790:   PetscAssertPointer(name, 2);
791:   PetscCall(PetscFunctionListAdd(&obj->qlist, name, fptr));
792:   PetscFunctionReturn(PETSC_SUCCESS);
793: }

795: /*MC
796:   PetscObjectQueryFunction - Gets a function associated with a given object.

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

802:   Logically Collective

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

809:   Output Parameter:
810: . fptr - function pointer

812:   Level: advanced

814: .seealso: `PetscObjectComposeFunction()`, `PetscFunctionListFind()`, `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObject`
815: M*/
816: PETSC_EXTERN PetscErrorCode PetscObjectQueryFunction_Private(PetscObject obj, const char name[], void (**fptr)(void))
817: {
818:   PetscFunctionBegin;
820:   PetscAssertPointer(name, 2);
821:   PetscCall(PetscFunctionListFind(obj->qlist, name, fptr));
822:   PetscFunctionReturn(PETSC_SUCCESS);
823: }

825: struct _p_PetscContainer {
826:   PETSCHEADER(int);
827:   void *ptr;
828:   PetscErrorCode (*userdestroy)(void *);
829: };

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

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

837:   Input Parameter:
838: . ctx - pointer to user-provided data

840:   Level: advanced

842: .seealso: `PetscContainerDestroy()`, `PetscContainerSetUserDestroy()`, `PetscObject`
843: @*/
844: PetscErrorCode PetscContainerUserDestroyDefault(void *ctx)
845: {
846:   PetscFunctionBegin;
847:   PetscCall(PetscFree(ctx));
848:   PetscFunctionReturn(PETSC_SUCCESS);
849: }

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

854:   Not Collective

856:   Input Parameter:
857: . obj - the object created with `PetscContainerCreate()`

859:   Output Parameter:
860: . ptr - the pointer value

862:   Level: advanced

864: .seealso: `PetscContainerCreate()`, `PetscContainerDestroy()`, `PetscObject`,
865:           `PetscContainerSetPointer()`
866: @*/
867: PetscErrorCode PetscContainerGetPointer(PetscContainer obj, void **ptr)
868: {
869:   PetscFunctionBegin;
871:   PetscAssertPointer(ptr, 2);
872:   *ptr = obj->ptr;
873:   PetscFunctionReturn(PETSC_SUCCESS);
874: }

876: /*@C
877:   PetscContainerSetPointer - Sets the pointer value contained in the container.

879:   Logically Collective

881:   Input Parameters:
882: + obj - the object created with `PetscContainerCreate()`
883: - ptr - the pointer value

885:   Level: advanced

887: .seealso: `PetscContainerCreate()`, `PetscContainerDestroy()`, `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObject`,
888:           `PetscContainerGetPointer()`
889: @*/
890: PetscErrorCode PetscContainerSetPointer(PetscContainer obj, void *ptr)
891: {
892:   PetscFunctionBegin;
894:   if (ptr) PetscAssertPointer(ptr, 2);
895:   obj->ptr = ptr;
896:   PetscFunctionReturn(PETSC_SUCCESS);
897: }

899: /*@C
900:   PetscContainerDestroy - Destroys a PETSc container object.

902:   Collective

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

907:   Level: advanced

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

913: .seealso: `PetscContainerCreate()`, `PetscContainerSetUserDestroy()`, `PetscObject`
914: @*/
915: PetscErrorCode PetscContainerDestroy(PetscContainer *obj)
916: {
917:   PetscFunctionBegin;
918:   if (!*obj) PetscFunctionReturn(PETSC_SUCCESS);
920:   if (--((PetscObject)(*obj))->refct > 0) {
921:     *obj = NULL;
922:     PetscFunctionReturn(PETSC_SUCCESS);
923:   }
924:   if ((*obj)->userdestroy) PetscCall((*(*obj)->userdestroy)((*obj)->ptr));
925:   PetscCall(PetscHeaderDestroy(obj));
926:   PetscFunctionReturn(PETSC_SUCCESS);
927: }

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

932:   Logically Collective

934:   Input Parameters:
935: + obj - an object that was created with `PetscContainerCreate()`
936: - des - name of the user destroy function

938:   Level: advanced

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

943: .seealso: `PetscContainerDestroy()`, `PetscContainerUserDestroyDefault()`, `PetscMalloc()`, `PetscMalloc1()`, `PetscCalloc()`, `PetscCalloc1()`, `PetscObject`
944: @*/
945: PetscErrorCode PetscContainerSetUserDestroy(PetscContainer obj, PetscErrorCode (*des)(void *))
946: {
947:   PetscFunctionBegin;
949:   obj->userdestroy = des;
950:   PetscFunctionReturn(PETSC_SUCCESS);
951: }

953: PetscClassId PETSC_CONTAINER_CLASSID;

955: /*@C
956:   PetscContainerCreate - Creates a PETSc object that has room to hold a single pointer.

958:   Collective

960:   Input Parameter:
961: . comm - MPI communicator that shares the object

963:   Output Parameter:
964: . container - the container created

966:   Level: advanced

968:   Notes:
969:   This allows one to attach any type of data (accessible through a pointer) with the
970:   `PetscObjectCompose()` function to a `PetscObject`. The data item itself is attached by a
971:   call to `PetscContainerSetPointer()`.

973: .seealso: `PetscContainerDestroy()`, `PetscContainerSetPointer()`, `PetscContainerGetPointer()`, `PetscObjectCompose()`, `PetscObjectQuery()`,
974:           `PetscContainerSetUserDestroy()`, `PetscObject`
975: @*/
976: PetscErrorCode PetscContainerCreate(MPI_Comm comm, PetscContainer *container)
977: {
978:   PetscFunctionBegin;
979:   PetscAssertPointer(container, 2);
980:   PetscCall(PetscSysInitializePackage());
981:   PetscCall(PetscHeaderCreate(*container, PETSC_CONTAINER_CLASSID, "PetscContainer", "Container", "Sys", comm, PetscContainerDestroy, NULL));
982:   PetscFunctionReturn(PETSC_SUCCESS);
983: }

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

988:   Collective

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

993:   Level: beginner

995:   Note:
996:   We have no generic options at present, so this does nothing

998: .seealso: `PetscObjectSetOptionsPrefix()`, `PetscObjectGetOptionsPrefix()`, `PetscObject`
999: @*/
1000: PetscErrorCode PetscObjectSetFromOptions(PetscObject obj)
1001: {
1002:   PetscFunctionBegin;
1004:   PetscFunctionReturn(PETSC_SUCCESS);
1005: }

1007: /*@
1008:   PetscObjectSetUp - Sets up the internal data structures for later use of the object

1010:   Collective

1012:   Input Parameter:
1013: . obj - the `PetscObject`

1015:   Level: advanced

1017:   Note:
1018:   This does nothing at present.

1020: .seealso: `PetscObjectDestroy()`, `PetscObject`
1021: @*/
1022: PetscErrorCode PetscObjectSetUp(PetscObject obj)
1023: {
1024:   PetscFunctionBegin;
1026:   PetscFunctionReturn(PETSC_SUCCESS);
1027: }