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, PetscObjectDestroyFn *destroy, PetscObjectViewFn *view)
 23: {
 24:   PetscFunctionBegin;
 25:   if (ierr) PetscFunctionReturn(ierr);
 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, PetscObjectDestroyFn *destroy, PetscObjectViewFn *view)
 35: {
 36:   void       *get_tmp;
 37:   PetscInt64 *cidx;
 38:   PetscMPIInt iflg;

 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, &iflg));
 55:   PetscCheck(iflg, 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:   PetscCall(PetscComposedQuantitiesDestroy(obj));
106:   if (PetscMemoryCollectMaximumUsage) {
107:     PetscLogDouble usage;

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

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

124:   /* destroy allocated quantities */
125:   if (PetscPrintFunctionList) PetscCall(PetscFunctionListPrintNonEmpty(obj->qlist));
126:   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);
127:   PetscCall(PetscFree(obj->name));
128:   PetscCall(PetscFree(obj->prefix));
129:   PetscCall(PetscFree(obj->type_name));

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

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

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

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

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

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

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

205:   Logically Collective

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

211:   Level: developer

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

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

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

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

229:   PetscCall(PetscFree(dest->fortran_func_pointers));
230:   PetscCall(PetscMalloc(src->num_fortran_func_pointers * sizeof(PetscFortranCallbackFn *), &dest->fortran_func_pointers));
231:   PetscCall(PetscArraycpy(dest->fortran_func_pointers, src->fortran_func_pointers, src->num_fortran_func_pointers));

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

235:   for (cbtype = PETSC_FORTRAN_CALLBACK_CLASS; cbtype < PETSC_FORTRAN_CALLBACK_MAXTYPE; cbtype++) {
236:     PetscCall(PetscFree(dest->fortrancallback[cbtype]));
237:     PetscCall(PetscCalloc1(src->num_fortrancallback[cbtype], &dest->fortrancallback[cbtype]));
238:     PetscCall(PetscArraycpy(dest->fortrancallback[cbtype], src->fortrancallback[cbtype], src->num_fortrancallback[cbtype]));
239:     dest->num_fortrancallback[cbtype] = src->num_fortrancallback[cbtype];
240:   }
241:   PetscFunctionReturn(PETSC_SUCCESS);
242: }

244: /*@
245:   PetscObjectSetFortranCallback - set Fortran callback function pointer and context

247:   Logically Collective, No Fortran Support

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

256:   Level: developer

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

261: .seealso: `PetscObjectGetFortranCallback()`, `PetscFortranCallbackRegister()`, `PetscFortranCallbackGetSizes()`
262: @*/
263: PetscErrorCode PetscObjectSetFortranCallback(PetscObject obj, PetscFortranCallbackType cbtype, PetscFortranCallbackId *cid, PetscFortranCallbackFn *func, PetscCtx ctx)
264: {
265:   const char *subtype = NULL;

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

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

287: /*@
288:   PetscObjectGetFortranCallback - get Fortran callback function pointer and context

290:   Logically Collective, No Fortran Support

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

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

301:   Level: developer

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

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

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

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

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

330:   Options Database Key:
331: . -objects_dump all - print information about all the objects that exist at the end of the programs run

333:   Level: advanced

335:   Note:
336:   Only MPI rank 0 of `PETSC_COMM_WORLD` prints the values

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

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

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

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

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

384: /*@
385:   PetscObjectsView - Prints the currently existing objects.

387:   Logically Collective

389:   Input Parameter:
390: . viewer - must be an `PETSCVIEWERASCII` viewer

392:   Level: advanced

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

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

410: /*@
411:   PetscObjectsGetObject - Get a pointer to a named object

413:   Not Collective

415:   Input Parameter:
416: . name - the name of an object

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

422:   Level: advanced

424: .seealso: `PetscObject`
425: @*/
426: PetscErrorCode PetscObjectsGetObject(const char name[], PetscObject *obj, const char *classname[])
427: {
428:   PetscObject h;
429:   PetscBool   flg;

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

453: PetscErrorCode PetscObjectsGetObject(const char name[], PetscObject *obj, const char *classname[])
454: {
455:   PetscFunctionReturn(PETSC_SUCCESS);
456: }
457: #endif

459: /*@
460:   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

462:   Input Parameter:
463: . obj - the `PetscObject`

465:   Level: developer

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

471: .seealso: `PetscOptionsInsert()`, `PetscObject`
472: @*/
473: PetscErrorCode PetscObjectSetPrintedOptions(PetscObject obj)
474: {
475:   PetscFunctionBegin;
476:   PetscAssertPointer(obj, 1);
477:   obj->optionsprinted = PETSC_TRUE;
478:   PetscFunctionReturn(PETSC_SUCCESS);
479: }

481: /*@
482:   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.

484:   Input Parameters:
485: + pobj - the parent object
486: - obj  - the `PetscObject`

488:   Level: developer

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

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

496: .seealso: `PetscOptionsInsert()`, `PetscObjectSetPrintedOptions()`, `PetscObject`
497: @*/
498: PetscErrorCode PetscObjectInheritPrintedOptions(PetscObject pobj, PetscObject obj)
499: {
500:   PetscMPIInt prank, size;

502:   PetscFunctionBegin;
505:   PetscCallMPI(MPI_Comm_rank(pobj->comm, &prank));
506:   PetscCallMPI(MPI_Comm_size(obj->comm, &size));
507:   if (size == 1 && prank > 0) obj->optionsprinted = PETSC_TRUE;
508:   PetscFunctionReturn(PETSC_SUCCESS);
509: }

511: /*@
512:   PetscObjectAddOptionsHandler - Adds an additional function to check for options when `XXXSetFromOptions()` is called.

514:   Not Collective

516:   Input Parameters:
517: + obj     - the PETSc object
518: . handle  - function that checks for options
519: . destroy - function to destroy `ctx` if provided
520: - ctx     - optional context for check function

522:   Calling sequence of `handle`:
523: + obj                - the PETSc object
524: . PetscOptionsObject - the `PetscOptionItems` object
525: - ctx                - optional context for `handle`

527:   Calling sequence of `destroy`:
528: + obj - the PETSc object
529: - ctx - optional context for `handle`

531:   Level: developer

533: .seealso: `KSPSetFromOptions()`, `PCSetFromOptions()`, `SNESSetFromOptions()`, `PetscObjectProcessOptionsHandlers()`, `PetscObjectDestroyOptionsHandlers()`,
534:           `PetscObject`
535: @*/
536: PetscErrorCode PetscObjectAddOptionsHandler(PetscObject obj, PetscErrorCode (*handle)(PetscObject obj, PetscOptionItems PetscOptionsObject, PetscCtx ctx), PetscErrorCode (*destroy)(PetscObject obj, PetscCtxRt ctx), PetscCtx ctx)
537: {
538:   PetscFunctionBegin;
540:   for (PetscInt i = 0; i < obj->noptionhandler; i++) {
541:     PetscBool identical = (PetscBool)(obj->optionhandler[i] == handle && obj->optiondestroy[i] == destroy && obj->optionctx[i] == ctx);
542:     if (identical) PetscFunctionReturn(PETSC_SUCCESS);
543:   }
544:   PetscCheck(obj->noptionhandler < PETSC_MAX_OPTIONS_HANDLER, obj->comm, PETSC_ERR_ARG_OUTOFRANGE, "Too many options handlers added");
545:   obj->optionhandler[obj->noptionhandler] = handle;
546:   obj->optiondestroy[obj->noptionhandler] = destroy;
547:   obj->optionctx[obj->noptionhandler++]   = ctx;
548:   PetscFunctionReturn(PETSC_SUCCESS);
549: }

551: /*@
552:   PetscObjectProcessOptionsHandlers - Calls all the options handlers attached to an object

554:   Not Collective

556:   Input Parameters:
557: + obj                - the PETSc object
558: - PetscOptionsObject - the options context

560:   Level: developer

562: .seealso: `KSPSetFromOptions()`, `PCSetFromOptions()`, `SNESSetFromOptions()`, `PetscObjectAddOptionsHandler()`, `PetscObjectDestroyOptionsHandlers()`,
563:           `PetscObject`
564: @*/
565: PetscErrorCode PetscObjectProcessOptionsHandlers(PetscObject obj, PetscOptionItems PetscOptionsObject)
566: {
567:   PetscFunctionBegin;
569:   for (PetscInt i = 0; i < obj->noptionhandler; i++) PetscCall((*obj->optionhandler[i])(obj, PetscOptionsObject, obj->optionctx[i]));
570:   PetscFunctionReturn(PETSC_SUCCESS);
571: }

573: /*@
574:   PetscObjectDestroyOptionsHandlers - Destroys all the option handlers attached to an object

576:   Not Collective

578:   Input Parameter:
579: . obj - the PETSc object

581:   Level: developer

583: .seealso: `KSPSetFromOptions()`, `PCSetFromOptions()`, `SNESSetFromOptions()`, `PetscObjectAddOptionsHandler()`, `PetscObjectProcessOptionsHandlers()`,
584:           `PetscObject`
585: @*/
586: PetscErrorCode PetscObjectDestroyOptionsHandlers(PetscObject obj)
587: {
588:   PetscFunctionBegin;
590:   for (PetscInt i = 0; i < obj->noptionhandler; i++) {
591:     if (obj->optiondestroy[i]) PetscCall((*obj->optiondestroy[i])(obj, obj->optionctx[i]));
592:   }
593:   obj->noptionhandler = 0;
594:   PetscFunctionReturn(PETSC_SUCCESS);
595: }

597: /*@
598:   PetscObjectReference - Indicates to a `PetscObject` that it is being
599:   referenced by another `PetscObject`. This increases the reference
600:   count for that object by one.

602:   Logically Collective

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

607:   Level: advanced

609:   Note:
610:   If `obj` is `NULL` this function returns without doing anything.

612: .seealso: `PetscObjectCompose()`, `PetscObjectDereference()`, `PetscObject`
613: @*/
614: PetscErrorCode PetscObjectReference(PetscObject obj)
615: {
616:   PetscFunctionBegin;
617:   if (!obj) PetscFunctionReturn(PETSC_SUCCESS);
619:   obj->refct++;
620:   PetscFunctionReturn(PETSC_SUCCESS);
621: }

623: /*@
624:   PetscObjectGetReference - Gets the current reference count for a PETSc object.

626:   Not Collective

628:   Input Parameter:
629: . obj - the PETSc object; this must be cast with (`PetscObject`), for example,
630:         `PetscObjectGetReference`((`PetscObject`)mat,&cnt); `obj` cannot be `NULL`

632:   Output Parameter:
633: . cnt - the reference count

635:   Level: advanced

637: .seealso: `PetscObjectCompose()`, `PetscObjectDereference()`, `PetscObjectReference()`, `PetscObject`
638: @*/
639: PetscErrorCode PetscObjectGetReference(PetscObject obj, PetscInt *cnt)
640: {
641:   PetscFunctionBegin;
643:   PetscAssertPointer(cnt, 2);
644:   *cnt = obj->refct;
645:   PetscFunctionReturn(PETSC_SUCCESS);
646: }

648: /*@
649:   PetscObjectDereference - Indicates to any `PetscObject` that it is being
650:   referenced by one less `PetscObject`. This decreases the reference
651:   count for that object by one.

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

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

659:   Level: advanced

661:   Notes:
662:   `PetscObjectDestroy()` sets the `obj` pointer to `NULL` after the call, this routine does not.

664:   If `obj` is `NULL` this function returns without doing anything.

666: .seealso: `PetscObjectCompose()`, `PetscObjectReference()`, `PetscObjectDestroy()`, `PetscObject`
667: @*/
668: PetscErrorCode PetscObjectDereference(PetscObject obj)
669: {
670:   PetscFunctionBegin;
671:   if (!obj) PetscFunctionReturn(PETSC_SUCCESS);
673:   if (obj->bops->destroy) PetscCall((*obj->bops->destroy)(&obj));
674:   else PetscCheck(--obj->refct, PETSC_COMM_SELF, PETSC_ERR_SUP, "This PETSc object does not have a generic destroy routine");
675:   PetscFunctionReturn(PETSC_SUCCESS);
676: }

678: /*
679:      The following routines are the versions private to the PETSc object
680:      data structures.
681: */
682: /*@
683:   PetscObjectRemoveReference - Removes a reference link from a `PetscObject`'s object list without dereferencing the referenced object

685:   Logically collective

687:   Input Parameters:
688: + obj  - the `PetscObject` whose list will be modified
689: - name - the name under which the reference was composed

691:   Level: developer

693:   Note:
694:   This is a private helper used to break composed reference cycles; user code should normally use `PetscObjectCompose()`
695:   with a `NULL` pointer to remove a composed object.

697: .seealso: `PetscObject`, `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectReference()`, `PetscObjectDereference()`
698: @*/
699: PetscErrorCode PetscObjectRemoveReference(PetscObject obj, const char name[])
700: {
701:   PetscFunctionBegin;
703:   PetscCall(PetscObjectListRemoveReference(&obj->olist, name));
704:   PetscFunctionReturn(PETSC_SUCCESS);
705: }

707: /*@
708:   PetscObjectCompose - Associates another PETSc object with a given PETSc object.

710:   Not Collective

712:   Input Parameters:
713: + obj  - the PETSc object; this must be cast with (`PetscObject`), for example,
714:          `PetscObjectCompose`((`PetscObject`)mat,...);
715: . name - name associated with the child object
716: - ptr  - the other PETSc object to associate with the PETSc object; this must also be
717:          cast with (`PetscObject`)

719:   Level: advanced

721:   Notes:
722:   The second objects reference count is automatically increased by one when it is
723:   composed.

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

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

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

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

736:   Fortran Note:
737:   Use
738: .vb
739:   call PetscObjectCompose(obj, name, PetscObjectCast(ptr), ierr)
740: .ve

742: .seealso: `PetscObjectQuery()`, `PetscContainerCreate()`, `PetscObjectComposeFunction()`, `PetscObjectQueryFunction()`, `PetscContainer`,
743:           `PetscContainerSetPointer()`, `PetscObject`, `PetscObjectContainerCompose()`
744: @*/
745: PetscErrorCode PetscObjectCompose(PetscObject obj, const char name[], PetscObject ptr)
746: {
747:   PetscFunctionBegin;
749:   PetscAssertPointer(name, 2);
751:   PetscCheck(obj != ptr, PetscObjectComm(obj), PETSC_ERR_SUP, "Cannot compose object with itself");
752:   if (ptr) {
753:     const char *tname;
754:     PetscBool   skipreference;

756:     PetscCall(PetscObjectListReverseFind(ptr->olist, obj, &tname, &skipreference));
757:     if (tname) PetscCheck(skipreference, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "An object cannot be composed with an object that was composed with it");
758:   }
759:   PetscCall(PetscObjectListAdd(&obj->olist, name, ptr));
760:   PetscFunctionReturn(PETSC_SUCCESS);
761: }

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

766:   Not Collective

768:   Input Parameters:
769: + obj  - the PETSc object. It must be cast with a (`PetscObject`), for example,
770:          `PetscObjectCompose`((`PetscObject`)mat,...);
771: . name - name associated with child object
772: - ptr  - the other PETSc object associated with the PETSc object, this must be
773:          cast with (`PetscObject`*)

775:   Level: advanced

777:   Note:
778:   The reference count of neither object is increased in this call

780:   Fortran Note:
781:   Use
782: .vb
783:   call PetscObjectQuery(PetscObjectCast(obj), name, ptr, ierr)
784: .ve

786: .seealso: `PetscObjectCompose()`, `PetscObjectComposeFunction()`, `PetscObjectQueryFunction()`, `PetscContainer`,
787:           `PetscContainerGetPointer()`, `PetscObject`
788: @*/
789: PetscErrorCode PetscObjectQuery(PetscObject obj, const char name[], PetscObject *ptr)
790: {
791:   PetscFunctionBegin;
793:   PetscAssertPointer(name, 2);
794:   PetscAssertPointer(ptr, 3);
795:   PetscCall(PetscObjectListFind(obj->olist, name, ptr));
796:   PetscFunctionReturn(PETSC_SUCCESS);
797: }

799: /*MC
800:   PetscObjectComposeFunction - Associates a function with a given PETSc object.

802:   Synopsis:
803: #include <petscsys.h>
804:   PetscErrorCode PetscObjectComposeFunction(PetscObject obj, const char name[], PetscErrorCodeFn *fptr)

806:   Logically Collective

808:   Input Parameters:
809: + obj  - the PETSc object; this must be cast with a (`PetscObject`), for example,
810:          `PetscObjectCompose`((`PetscObject`)mat,...);
811: . name - name associated with the child function
812: - fptr - function pointer

814:   Level: advanced

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

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

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

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

827: .seealso: `PetscObjectQueryFunction()`, `PetscContainerCreate()` `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscTryMethod()`, `PetscUseMethod()`,
828:           `PetscUseTypeMethod()`, `PetscTryTypeMethod()`, `PetscObject`
829: M*/
830: PetscErrorCode PetscObjectComposeFunction_Private(PetscObject obj, const char name[], PetscErrorCodeFn *fptr)
831: {
832:   PetscFunctionBegin;
834:   PetscAssertPointer(name, 2);
835:   PetscCall(PetscFunctionListAdd_Private(&obj->qlist, name, fptr));
836:   PetscFunctionReturn(PETSC_SUCCESS);
837: }

839: PETSC_EXTERN PetscErrorCode PetscObjectQueryFunction_Private(PetscObject obj, const char name[], PetscErrorCodeFn **fptr)
840: {
841:   PetscFunctionBegin;
843:   PetscAssertPointer(name, 2);
844:   PetscCall(PetscFunctionListFind_Private(obj->qlist, name, fptr));
845:   PetscFunctionReturn(PETSC_SUCCESS);
846: }

848: /*@
849:   PetscObjectHasFunction - Query if a function is associated with a given object.

851:   Logically Collective

853:   Input Parameters:
854: + obj  - the PETSc object
855: - name - name associated with the child function

857:   Output Parameter:
858: . has - the boolean value

860:   Level: advanced

862: .seealso: `PetscObject`, `PetscObjectComposeFunction()`, `PetscObjectQueryFunction()`
863: @*/
864: PetscErrorCode PetscObjectHasFunction(PetscObject obj, const char name[], PetscBool *has)
865: {
866:   PetscErrorCodeFn *fptr = NULL;

868:   PetscFunctionBegin;
869:   PetscAssertPointer(has, 3);
870:   PetscCall(PetscObjectQueryFunction(obj, name, &fptr));
871:   *has = fptr ? PETSC_TRUE : PETSC_FALSE;
872:   PetscFunctionReturn(PETSC_SUCCESS);
873: }

875: struct _p_PetscContainer {
876:   PETSCHEADER(int);
877:   void              *ctx;
878:   PetscCtxDestroyFn *ctxdestroy;
879:   PetscErrorCode (*userdestroy_deprecated)(void *);
880: };

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

885:   Not Collective, No Fortran Support

887:   Input Parameter:
888: . obj - the object created with `PetscContainerCreate()`

890:   Output Parameter:
891: . ptr - the pointer value

893:   Level: advanced

895: .seealso: `PetscContainerCreate()`, `PetscContainerDestroy()`, `PetscObject`,
896:           `PetscContainerSetPointer()`, `PetscObjectContainerCompose()`, `PetscObjectContainerQuery()`
897: @*/
898: PetscErrorCode PetscContainerGetPointer(PetscContainer obj, PetscCtxRt ptr)
899: {
900:   PetscFunctionBegin;
902:   PetscAssertPointer(ptr, 2);
903:   *(void **)ptr = obj->ctx;
904:   PetscFunctionReturn(PETSC_SUCCESS);
905: }

907: /*@
908:   PetscContainerSetPointer - Sets the pointer value contained in the container.

910:   Logically Collective, No Fortran Support

912:   Input Parameters:
913: + obj - the object created with `PetscContainerCreate()`
914: - ptr - the pointer value

916:   Level: advanced

918: .seealso: `PetscContainerCreate()`, `PetscContainerDestroy()`, `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObject`,
919:           `PetscContainerGetPointer()`, `PetscObjectContainerCompose()`, `PetscObjectContainerQuery()`
920: @*/
921: PetscErrorCode PetscContainerSetPointer(PetscContainer obj, void *ptr)
922: {
923:   PetscFunctionBegin;
925:   if (ptr) PetscAssertPointer(ptr, 2);
926:   obj->ctx = ptr;
927:   PetscFunctionReturn(PETSC_SUCCESS);
928: }

930: /*@
931:   PetscContainerDestroy - Destroys a PETSc container object.

933:   Collective, No Fortran Support

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

938:   Level: advanced

940:   Note:
941:   If `PetscContainerSetCtxDestroy()` was used to provide a user destroy object for the data provided with `PetscContainerSetPointer()`
942:   then that function is called to destroy the data.

944: .seealso: `PetscContainerCreate()`, `PetscContainerSetCtxDestroy()`, `PetscObject`, `PetscObjectContainerCompose()`, `PetscObjectContainerQuery()`
945: @*/
946: PetscErrorCode PetscContainerDestroy(PetscContainer *obj)
947: {
948:   PetscFunctionBegin;
949:   if (!*obj) PetscFunctionReturn(PETSC_SUCCESS);
951:   if (--((PetscObject)*obj)->refct > 0) {
952:     *obj = NULL;
953:     PetscFunctionReturn(PETSC_SUCCESS);
954:   }
955:   if ((*obj)->ctxdestroy) PetscCall((*(*obj)->ctxdestroy)(&(*obj)->ctx));
956:   else if ((*obj)->userdestroy_deprecated) PetscCall((*(*obj)->userdestroy_deprecated)((*obj)->ctx));
957:   PetscCall(PetscHeaderDestroy(obj));
958:   PetscFunctionReturn(PETSC_SUCCESS);
959: }

961: /*@
962:   PetscContainerSetCtxDestroy - Sets the destroy function for the data provided to the `PetscContainer` with `PetscContainerSetPointer()`

964:   Logically Collective, No Fortran Support

966:   Input Parameters:
967: + obj - an object that was created with `PetscContainerCreate()`
968: - des - name of the ctx destroy function, see `PetscCtxDestroyFn` for its calling sequence

970:   Level: advanced

972:   Note:
973:   Use `PetscCtxDestroyDefault()` if the memory was obtained by calling `PetscMalloc()` or one of its variants for single memory allocation.

975: .seealso: `PetscContainerDestroy()`, `PetscContainerUserDestroyDefault()`, `PetscMalloc()`, `PetscMalloc1()`, `PetscCalloc()`, `PetscCalloc1()`, `PetscObject`,
976:           `PetscObjectContainerCompose()`, `PetscObjectContainerQuery()`
977: @*/
978: PetscErrorCode PetscContainerSetCtxDestroy(PetscContainer obj, PetscCtxDestroyFn *des)
979: {
980:   PetscFunctionBegin;
982:   obj->ctxdestroy = des;
983:   PetscFunctionReturn(PETSC_SUCCESS);
984: }

986: /*@
987:   PetscContainerSetUserDestroy - Sets the destroy function for the data provided to the `PetscContainer` with `PetscContainerSetPointer()`

989:   Logically Collective, No Fortran Support

991:   Input Parameters:
992: + obj - an object that was created with `PetscContainerCreate()`
993: - des - name of the ctx destroy function

995:   Level: advanced

997:   Notes:
998:   Deprecated, use `PetscContainerSetCtxDestroy()`

1000: .seealso: `PetscContainerSetCtxDestroy()`, `PetscContainerDestroy()`, `PetscContainerUserDestroyDefault()`, `PetscMalloc()`, `PetscMalloc1()`, `PetscCalloc()`, `PetscCalloc1()`, `PetscObject`,
1001:           `PetscObjectContainerCompose()`, `PetscObjectContainerQuery()`
1002: @*/
1003: PetscErrorCode PetscContainerSetUserDestroy(PetscContainer obj, PetscErrorCode (*des)(void *))
1004: {
1005:   PetscFunctionBegin;
1007:   obj->userdestroy_deprecated = des;
1008:   PetscFunctionReturn(PETSC_SUCCESS);
1009: }

1011: PetscClassId PETSC_CONTAINER_CLASSID;

1013: /*@
1014:   PetscContainerCreate - Creates a PETSc object that has room to hold a single pointer.

1016:   Collective, No Fortran Support

1018:   Input Parameter:
1019: . comm - MPI communicator that shares the object

1021:   Output Parameter:
1022: . container - the container created

1024:   Level: advanced

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

1031: .seealso: `PetscContainerDestroy()`, `PetscContainerSetPointer()`, `PetscContainerGetPointer()`, `PetscObjectCompose()`, `PetscObjectQuery()`,
1032:           `PetscContainerSetCtxDestroy()`, `PetscObject`, `PetscObjectContainerCompose()`, `PetscObjectContainerQuery()`
1033: @*/
1034: PetscErrorCode PetscContainerCreate(MPI_Comm comm, PetscContainer *container)
1035: {
1036:   PetscFunctionBegin;
1037:   PetscAssertPointer(container, 2);
1038:   PetscCall(PetscSysInitializePackage());
1039:   PetscCall(PetscHeaderCreate(*container, PETSC_CONTAINER_CLASSID, "PetscContainer", "Container", "Sys", comm, PetscContainerDestroy, NULL));
1040:   PetscFunctionReturn(PETSC_SUCCESS);
1041: }

1043: /*@
1044:   PetscObjectContainerCompose - Creates a `PetscContainer`, provides all of its values and composes it with a `PetscObject`

1046:   Collective

1048:   Input Parameters:
1049: + obj     - the `PetscObject`
1050: . name    - the name for the composed container
1051: . pointer - the pointer to the data
1052: - destroy - the routine to destroy the container's data, see `PetscCtxDestroyFn` for its calling sequence; use `PetscCtxDestroyDefault()` if a `PetscFree()` frees the data

1054:   Level: advanced

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

1061: .seealso: `PetscContainerCreate()`, `PetscContainerDestroy()`, `PetscContainerSetPointer()`, `PetscContainerGetPointer()`, `PetscObjectCompose()`, `PetscObjectQuery()`,
1062:           `PetscContainerSetCtxDestroy()`, `PetscObject`, `PetscObjectContainerQuery()`
1063: @*/
1064: PetscErrorCode PetscObjectContainerCompose(PetscObject obj, const char *name, void *pointer, PetscCtxDestroyFn *destroy)
1065: {
1066:   PetscContainer container;

1068:   PetscFunctionBegin;
1069:   PetscCall(PetscContainerCreate(PetscObjectComm(obj), &container));
1070:   PetscCall(PetscContainerSetPointer(container, pointer));
1071:   if (destroy) PetscCall(PetscContainerSetCtxDestroy(container, destroy));
1072:   PetscCall(PetscObjectCompose(obj, name, (PetscObject)container));
1073:   PetscCall(PetscContainerDestroy(&container));
1074:   PetscFunctionReturn(PETSC_SUCCESS);
1075: }

1077: /*@
1078:   PetscObjectContainerQuery - Accesses the pointer in a container composed to a `PetscObject` with `PetscObjectContainerCompose()`

1080:   Collective

1082:   Input Parameters:
1083: + obj  - the `PetscObject`
1084: - name - the name for the composed container

1086:   Output Parameter:
1087: . ptr - the pointer to the data

1089:   Level: advanced

1091: .seealso: `PetscContainerCreate()`, `PetscContainerDestroy()`, `PetscContainerSetPointer()`, `PetscContainerGetPointer()`, `PetscObjectCompose()`, `PetscObjectQuery()`,
1092:           `PetscContainerSetCtxDestroy()`, `PetscObject`, `PetscObjectContainerCompose()`
1093: @*/
1094: PetscErrorCode PetscObjectContainerQuery(PetscObject obj, const char *name, PetscCtxRt ptr)
1095: {
1096:   PetscContainer container;

1098:   PetscFunctionBegin;
1099:   PetscCall(PetscObjectQuery(obj, name, (PetscObject *)&container));
1100:   if (container) PetscCall(PetscContainerGetPointer(container, ptr));
1101:   else *(void **)ptr = NULL;
1102:   PetscFunctionReturn(PETSC_SUCCESS);
1103: }

1105: /*@
1106:   PetscObjectSetFromOptions - Sets generic parameters from user options.

1108:   Collective

1110:   Input Parameter:
1111: . obj - the `PetscObject`

1113:   Level: beginner

1115:   Note:
1116:   We have no generic options at present, so this does nothing.

1118: .seealso: `PetscObjectSetOptionsPrefix()`, `PetscObjectGetOptionsPrefix()`, `PetscObject`
1119: @*/
1120: PetscErrorCode PetscObjectSetFromOptions(PetscObject obj)
1121: {
1122:   PetscFunctionBegin;
1124:   PetscFunctionReturn(PETSC_SUCCESS);
1125: }

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

1130:   Collective

1132:   Input Parameter:
1133: . obj - the `PetscObject`

1135:   Level: advanced

1137:   Note:
1138:   This does nothing at present.

1140: .seealso: `PetscObjectDestroy()`, `PetscObject`
1141: @*/
1142: PetscErrorCode PetscObjectSetUp(PetscObject obj)
1143: {
1144:   PetscFunctionBegin;
1146:   PetscFunctionReturn(PETSC_SUCCESS);
1147: }

1149: /*MC
1150:   PetscObjectIsNull - returns true if the given PETSc object is a null object

1152:   Fortran only

1154:   Synopsis:
1155:   #include <petsc/finclude/petscsys.h>
1156:   PetscBool PetscObjectIsNull(PetscObject obj)

1158:   Logically Collective

1160:   Input Parameter:
1161: . obj  - the PETSc object

1163:   Level: beginner

1165:   Example Usage:
1166: .vb
1167:   if (PetscObjectIsNull(dm)) then
1168:   if (.not. PetscObjectIsNull(dm)) then
1169: .ve

1171:   Note:
1172:   Code such as
1173: .vb
1174:   if (dm == PETSC_NULL_DM) then
1175: .ve
1176:   is not allowed.

1178: .seealso: `PetscObject`, `PETSC_NULL_OBJECT`, `PETSC_NULL_VEC`, `PETSC_NULL_VEC_ARRAY`, `PetscObjectNullify()`
1179: M*/

1181: /*MC
1182:   PetscObjectNullify - sets a PETSc object, such as `Vec`, back to the state it had when it was declared, so it
1183:   can be used in a creation routine, such as `VecCreate()`

1185:   Fortran only

1187:   Synopsis:
1188:   #include <petsc/finclude/petscsys.h>
1189:   PetscObjectNullify(PetscObject obj)

1191:   Logically Collective

1193:   Input Parameter:
1194: . obj  - the PETSc object

1196:   Level: beginner

1198:   Example Usage:
1199: .vb
1200:   Vec x, y

1202:   VecCreate(PETSC_COMM_WORLD, x, ierr)
1203:   ...
1204:   y = x
1205:   ...
1206:   PetscObjectNullify(y)
1207: .ve
1208:   You should not call `VecDestroy()` on `y` because that will destroy `x` since the assignment `y = x` does
1209:   not increase the reference count of `x`

1211:   Note:
1212:   Code such as
1213: .vb
1214:   y = PETSC_NULL_VEC
1215: .ve
1216:   is not allowed.

1218: .seealso: `PetscObject`, `PETSC_NULL_OBJECT`, `PETSC_NULL_VEC`, `PETSC_NULL_VEC_ARRAY`, `PetscObjectIsNull()`
1219: M*/

1221: /*MC
1222:   PetscObjectCast - Casts a `PetscObject` to the base `PetscObject` type in function calls

1224:   Fortran only

1226:   Synopsis:
1227:   use petscsys

1229:   Level: beginner

1231:   Example Usage:
1232:   PetscFE fe
1233: .vb
1234:   PetscCallA(DMAddField(dm, 0, PetscObjectCast(fe),ierr)
1235: .ve

1237: .seealso: `PetscObject`, `PetscObjectSpecificCast()`
1238: M*/

1240: /*MC
1241:   PetscObjectSpecificCast - Casts a `PetscObject` to any specific `PetscObject`

1243:   Fortran only

1245:   Synopsis:
1246:   use petscsys

1248:   Level: beginner

1250:   Example Usage:
1251:   PetscObject obj
1252:   PetscFE     fe
1253: .vb
1254:   PetscCallA(PetscDSGetDiscretization(ds, 0, obj, ierr)
1255:   PetscObjectSpecificCast(fe,obj)
1256: .ve

1258: .seealso: `PetscObject`, `PetscObjectCast()`
1259: M*/

1261: /*MC
1262:   PetscEnumCase - `case()` statement for a PETSc enum variable or value

1264:   Fortran only

1266:   Synopsis:
1267:   #include <petsc/finclude/petscsys.h>
1268:   PetscEnumCase(PetscObject enm)

1270:   Input Parameters:
1271: . enum  - the PETSc enum value or variable

1273:   Level: beginner

1275:   Example Usage:
1276: .vb
1277:   DMPolytopeType cellType
1278:   select PetscEnumCase(cellType)
1279:     PetscEnumCase(DM_POLYTOPE_TRIANGLE)
1280:       write(*,*) 'cell is a triangle'
1281:     PetscEnumCase(DM_POLYTOPE_TETRAHEDRON)
1282:       write(*,*) 'cell is a tetrahedron'
1283:     case default
1284:       write(*,*) 'cell is a something else'
1285:   end select
1286: .ve
1287:   is equivalent to
1288: .vb
1289:   DMPolytopeType cellType
1290:   select case(cellType%v)
1291:     case(DM_POLYTOPE_TRIANGLE%v)
1292:       write(*,*) 'cell is a triangle'
1293:     case(DM_POLYTOPE_TETRAHEDRON%v)
1294:       write(*,*) 'cell is a tetrahedron'
1295:     case default
1296:       write(*,*) 'cell is a something else'
1297:   end select
1298: .ve

1300: .seealso: `PetscObject`
1301: M*/