Date: 2026-07-30T21:14:25+00:00

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: /*@C
    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: /*@C
    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 defined(PETSC_USE_LOG)
    323: /*@C
    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:   PetscInt    i;
    429:   PetscObject h;
    430:   PetscBool   flg;

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

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

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

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

    466:   Level: developer

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

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

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

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

    489:   Level: developer

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

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

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

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

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

    515:   Not Collective

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

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

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

    532:   Level: developer

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

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

    555:   Not Collective

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

    561:   Level: developer

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

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

    577:   Not Collective

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

    582:   Level: developer

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

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

    603:   Logically Collective

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

    608:   Level: advanced

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

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

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

    627:   Not Collective

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

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

    636:   Level: advanced

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

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

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

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

    660:   Level: advanced

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

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

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

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

    686:   Logically collective

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

    692:   Level: developer

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

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

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

    711:   Not Collective

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

    720:   Level: advanced

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

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

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

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

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

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

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

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

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

    767:   Not Collective

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

    776:   Level: advanced

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

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

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

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

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

    807:   Logically Collective

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

    815:   Level: advanced

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

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

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

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

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

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

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

    852:   Logically Collective

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

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

    861:   Level: advanced

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

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

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

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

    886:   Not Collective, No Fortran Support

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

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

    894:   Level: advanced

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

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

    911:   Logically Collective, No Fortran Support

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

    917:   Level: advanced

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

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

    934:   Collective, No Fortran Support

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

    939:   Level: advanced

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

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

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

    965:   Logically Collective, No Fortran Support

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

    971:   Level: advanced

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

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

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

    990:   Logically Collective, No Fortran Support

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

    996:   Level: advanced

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

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

    1012: PetscClassId PETSC_CONTAINER_CLASSID;

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

    1017:   Collective, No Fortran Support

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

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

    1025:   Level: advanced

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

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

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

    1047:   Collective

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

    1055:   Level: advanced

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

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

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

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

    1081:   Collective

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

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

    1090:   Level: advanced

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

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

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

    1109:   Collective

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

    1114:   Level: beginner

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

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

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

    1131:   Collective

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

    1136:   Level: advanced

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

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

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

    1153:   Fortran only

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

    1159:   Logically Collective

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

    1164:   Level: beginner

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

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

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

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

    1186:   Fortran only

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

    1192:   Logically Collective

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

    1197:   Level: beginner

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

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

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

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

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

    1225:   Fortran only

    1227:   Synopsis:
    1228:   use petscsys

    1230:   Level: beginner

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

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

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

    1244:   Fortran only

    1246:   Synopsis:
    1247:   use petscsys

    1249:   Level: beginner

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

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

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

    1265:   Fortran only

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

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

    1274:   Level: beginner

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

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