Actual source code: inherit.c

  1: /*
  2:      Provides utility routines for manipulating any type of PETSc object.
  3: */
  4: #include <petsc/private/petscimpl.h>
  5: #include <petscviewer.h>

  7: #if defined(PETSC_USE_LOG)
  8: PETSC_INTERN PetscObject *PetscObjects;
  9: PETSC_INTERN PetscInt     PetscObjectsCounts;
 10: PETSC_INTERN PetscInt     PetscObjectsMaxCounts;
 11: PETSC_INTERN PetscBool    PetscObjectsLog;
 12: #endif

 14: #if defined(PETSC_USE_LOG)
 15: PetscObject *PetscObjects       = NULL;
 16: PetscInt     PetscObjectsCounts = 0, PetscObjectsMaxCounts = 0;
 17: PetscBool    PetscObjectsLog = PETSC_FALSE;
 18: #endif

 20: PETSC_EXTERN PetscErrorCode PetscObjectCompose_Petsc(PetscObject, const char[], PetscObject);
 21: PETSC_EXTERN PetscErrorCode PetscObjectQuery_Petsc(PetscObject, const char[], PetscObject *);
 22: PETSC_EXTERN PetscErrorCode PetscObjectComposeFunction_Petsc(PetscObject, const char[], void (*)(void));
 23: PETSC_EXTERN PetscErrorCode PetscObjectQueryFunction_Petsc(PetscObject, const char[], void (**)(void));

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

 31: /*
 32:    PetscHeaderCreate_Private - Creates a base PETSc object header and fills
 33:    in the default values.  Called by the macro PetscHeaderCreate().
 34: */
 35: PetscErrorCode PetscHeaderCreate_Private(PetscObject h, PetscClassId classid, const char class_name[], const char descr[], const char mansec[], MPI_Comm comm, PetscObjectDestroyFunction destroy, PetscObjectViewFunction view)
 36: {
 37:   void       *get_tmp;
 38:   PetscInt64 *cidx;
 39:   PetscMPIInt flg;

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

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

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

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

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

 85:     PetscObjects                        = newPetscObjects;
 86:     PetscObjects[PetscObjectsMaxCounts] = h;
 87:     PetscObjectsMaxCounts               = newPetscObjectsMaxCounts;
 88:   }
 89: #endif
 90:   PetscFunctionReturn(PETSC_SUCCESS);
 91: }

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

 96: /*
 97:     PetscHeaderDestroy_Private - Destroys a base PETSc object header. Called by
 98:     the macro PetscHeaderDestroy().
 99: */
100: PetscErrorCode PetscHeaderDestroy_Private(PetscObject obj, PetscBool clear_for_reuse)
101: {
102:   PetscFunctionBegin;
104:   PetscCall(PetscLogObjectDestroy(obj));
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 */
133:     obj->bops->compose         = PetscObjectCompose_Petsc;
134:     obj->bops->query           = PetscObjectQuery_Petsc;
135:     obj->bops->composefunction = PetscObjectComposeFunction_Petsc;
136:     obj->bops->queryfunction   = PetscObjectQueryFunction_Petsc;

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

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

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

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

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

208: /*@C
209:    PetscObjectCopyFortranFunctionPointers - Copy function pointers to another object

211:    Logically Collective

213:    Input Parameters:
214: +  src - source object
215: -  dest - destination object

217:    Level: developer

219:    Note:
220:    Both objects must have the same class.

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

224: .seealso: `PetscFortranCallbackRegister()`, `PetscFortranCallbackGetSizes()`
225: @*/
226: PetscErrorCode PetscObjectCopyFortranFunctionPointers(PetscObject src, PetscObject dest)
227: {
228:   PetscFortranCallbackId cbtype, numcb[PETSC_FORTRAN_CALLBACK_MAXTYPE];

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

235:   PetscCall(PetscFree(dest->fortran_func_pointers));
236:   PetscCall(PetscMalloc(src->num_fortran_func_pointers * sizeof(void (*)(void)), &dest->fortran_func_pointers));
237:   PetscCall(PetscMemcpy(dest->fortran_func_pointers, src->fortran_func_pointers, src->num_fortran_func_pointers * sizeof(void (*)(void))));

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

241:   PetscCall(PetscFortranCallbackGetSizes(src->classid, &numcb[PETSC_FORTRAN_CALLBACK_CLASS], &numcb[PETSC_FORTRAN_CALLBACK_SUBTYPE]));
242:   for (cbtype = PETSC_FORTRAN_CALLBACK_CLASS; cbtype < PETSC_FORTRAN_CALLBACK_MAXTYPE; cbtype++) {
243:     PetscCall(PetscFree(dest->fortrancallback[cbtype]));
244:     PetscCall(PetscCalloc1(numcb[cbtype], &dest->fortrancallback[cbtype]));
245:     PetscCall(PetscMemcpy(dest->fortrancallback[cbtype], src->fortrancallback[cbtype], src->num_fortrancallback[cbtype] * sizeof(PetscFortranCallback)));
246:     dest->num_fortrancallback[cbtype] = src->num_fortrancallback[cbtype];
247:   }
248:   PetscFunctionReturn(PETSC_SUCCESS);
249: }

251: /*@C
252:    PetscObjectSetFortranCallback - set fortran callback function pointer and context

254:    Logically Collective

256:    Input Parameters:
257: +  obj - object on which to set callback
258: .  cbtype - callback type (class or subtype)
259: .  cid - address of callback Id, updated if not yet initialized (zero)
260: .  func - Fortran function
261: -  ctx - Fortran context

263:    Level: developer

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

268: .seealso: `PetscObjectGetFortranCallback()`, `PetscFortranCallbackRegister()`, `PetscFortranCallbackGetSizes()`
269: @*/
270: PetscErrorCode PetscObjectSetFortranCallback(PetscObject obj, PetscFortranCallbackType cbtype, PetscFortranCallbackId *cid, void (*func)(void), void *ctx)
271: {
272:   const char *subtype = NULL;

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

286:     obj->fortrancallback[cbtype]     = callback;
287:     obj->num_fortrancallback[cbtype] = newnum;
288:   }
289:   obj->fortrancallback[cbtype][*cid - PETSC_SMALLEST_FORTRAN_CALLBACK].func = func;
290:   obj->fortrancallback[cbtype][*cid - PETSC_SMALLEST_FORTRAN_CALLBACK].ctx  = ctx;
291:   PetscFunctionReturn(PETSC_SUCCESS);
292: }

294: /*@C
295:    PetscObjectGetFortranCallback - get fortran callback function pointer and context

297:    Logically Collective

299:    Input Parameters:
300: +  obj - object on which to get callback
301: .  cbtype - callback type
302: -  cid - address of callback Id

304:    Output Parameters:
305: +  func - Fortran function (or `NULL` if not needed)
306: -  ctx - Fortran context (or `NULL` if not needed)

308:    Level: developer

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

313: .seealso: `PetscObjectSetFortranCallback()`, `PetscObjectGetFortranCallback()`, `PetscFortranCallbackRegister()`, `PetscFortranCallbackGetSizes()`
314: @*/
315: PetscErrorCode PetscObjectGetFortranCallback(PetscObject obj, PetscFortranCallbackType cbtype, PetscFortranCallbackId cid, void (**func)(void), void **ctx)
316: {
317:   PetscFortranCallback *cb;

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

329: #if defined(PETSC_USE_LOG)
330: /*@C
331:    PetscObjectsDump - Prints all the currently existing objects.

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

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

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

342:    Level: advanced

344: .seealso: `PetscObject`
345: @*/
346: PetscErrorCode PetscObjectsDump(FILE *fd, PetscBool all)
347: {
348:   PetscInt    i, j, k = 0;
349:   PetscObject h;

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

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

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

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

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

393:    Logically Collective

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

398:    Level: advanced

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

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

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

419:    Not Collective

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

424:    Output Parameters:
425: +  obj - the object or `NULL` if there is no object
426: -  classname - the name of the class

428:    Level: advanced

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

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

457: /*@
458:    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

460:    Input Parameter:
461: .  obj  - the `PetscObject`

463:    Level: developer

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

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

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

482:    Input Parameters:
483: +  pobj - the parent object
484: -  obj  - the `PetscObject`

486:    Level: developer

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

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

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

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

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

512:     Not Collective

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

520:     Level: developer

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

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

539:     Not Collective

541:     Input Parameters:
542: +   obj - the PETSc object
543: -   PetscOptionsObject - the options context

545:     Level: developer

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

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

561:     Not Collective

563:     Input Parameter:
564: .   obj - the PETSc object

566:     Level: developer

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

582: /*@C
583:    PetscObjectReference - Indicates to any `PetscObject` that it is being
584:    referenced by another `PetscObject`. This increases the reference
585:    count for that object by one.

587:    Logically Collective

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

593:    Level: advanced

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

606: /*@C
607:    PetscObjectGetReference - Gets the current reference count for
608:    any PETSc object.

610:    Not Collective

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

616:    Output Parameter:
617: .  cnt - the reference count

619:    Level: advanced

621: .seealso: `PetscObjectCompose()`, `PetscObjectDereference()`, `PetscObjectReference()`, `PetscObject`
622: @*/
623: PetscErrorCode PetscObjectGetReference(PetscObject obj, PetscInt *cnt)
624: {
625:   PetscFunctionBegin;
628:   *cnt = obj->refct;
629:   PetscFunctionReturn(PETSC_SUCCESS);
630: }

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

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

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

643:    Level: advanced

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

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

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

672: PetscErrorCode PetscObjectCompose_Petsc(PetscObject obj, const char name[], PetscObject ptr)
673: {
674:   PetscFunctionBegin;
675:   if (ptr) {
676:     char     *tname;
677:     PetscBool skipreference;

679:     PetscCall(PetscObjectListReverseFind(ptr->olist, obj, &tname, &skipreference));
680:     if (tname) PetscCheck(skipreference, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "An object cannot be composed with an object that was composed with it");
681:   }
682:   PetscCall(PetscObjectListAdd(&obj->olist, name, ptr));
683:   PetscFunctionReturn(PETSC_SUCCESS);
684: }

686: PetscErrorCode PetscObjectQuery_Petsc(PetscObject obj, const char name[], PetscObject *ptr)
687: {
688:   PetscFunctionBegin;
690:   PetscCall(PetscObjectListFind(obj->olist, name, ptr));
691:   PetscFunctionReturn(PETSC_SUCCESS);
692: }

694: PetscErrorCode PetscObjectComposeFunction_Petsc(PetscObject obj, const char name[], void (*ptr)(void))
695: {
696:   PetscFunctionBegin;
698:   PetscCall(PetscFunctionListAdd(&obj->qlist, name, ptr));
699:   PetscFunctionReturn(PETSC_SUCCESS);
700: }

702: PetscErrorCode PetscObjectQueryFunction_Petsc(PetscObject obj, const char name[], void (**ptr)(void))
703: {
704:   PetscFunctionBegin;
706:   PetscCall(PetscFunctionListFind(obj->qlist, name, ptr));
707:   PetscFunctionReturn(PETSC_SUCCESS);
708: }

710: /*@C
711:    PetscObjectCompose - Associates another PETSc object with a given PETSc object.

713:    Not Collective

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

722:    Level: advanced

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

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

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

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

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

739: .seealso: `PetscObjectQuery()`, `PetscContainerCreate()`, `PetscObjectComposeFunction()`, `PetscObjectQueryFunction()`, `PetscContainer`,
740:           `PetscContainerSetPointer()`, `PetscObject`
741: @*/
742: PetscErrorCode PetscObjectCompose(PetscObject obj, const char name[], PetscObject ptr)
743: {
744:   PetscFunctionBegin;
748:   PetscCheck(obj != ptr, PetscObjectComm((PetscObject)obj), PETSC_ERR_SUP, "Cannot compose object with itself");
749:   PetscCall((*obj->bops->compose)(obj, name, ptr));
750:   PetscFunctionReturn(PETSC_SUCCESS);
751: }

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

756:    Not Collective

758:    Input Parameters:
759: +  obj - the PETSc object
760:          Thus must be cast with a (`PetscObject`), for example,
761:          `PetscObjectCompose`((`PetscObject`)mat,...);
762: .  name - name associated with child object
763: -  ptr - the other PETSc object associated with the PETSc object, this must be
764:          cast with (`PetscObject`*)

766:    Level: advanced

768:    Note:
769:    The reference count of neither object is increased in this call

771: .seealso: `PetscObjectCompose()`, `PetscObjectComposeFunction()`, `PetscObjectQueryFunction()`, `PetscContainer`
772:           `PetscContainerGetPointer()`, `PetscObject`
773: @*/
774: PetscErrorCode PetscObjectQuery(PetscObject obj, const char name[], PetscObject *ptr)
775: {
776:   PetscFunctionBegin;
780:   PetscCall((*obj->bops->query)(obj, name, ptr));
781:   PetscFunctionReturn(PETSC_SUCCESS);
782: }

784: /*MC
785:    PetscObjectComposeFunction - Associates a function with a given PETSc object.

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

791:    Logically Collective

793:    Input Parameters:
794: +  obj - the PETSc object; this must be cast with a (`PetscObject`), for example,
795:          `PetscObjectCompose`((`PetscObject`)mat,...);
796: .  name - name associated with the child function
797: -  fptr - function pointer

799:    Level: advanced

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

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

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

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

812: .seealso: `PetscObjectQueryFunction()`, `PetscContainerCreate()` `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscTryMethod()`, `PetscUseMethod()`,
813:           `PetscUseTypeMethod()`, `PetscTryTypeMethod()`, `PetscObject`
814: M*/

816: PetscErrorCode PetscObjectComposeFunction_Private(PetscObject obj, const char name[], void (*fptr)(void))
817: {
818:   PetscFunctionBegin;
821:   PetscCall((*obj->bops->composefunction)(obj, name, fptr));
822:   PetscFunctionReturn(PETSC_SUCCESS);
823: }

825: /*MC
826:    PetscObjectQueryFunction - Gets a function associated with a given object.

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

832:    Logically Collective

834:    Input Parameters:
835: +  obj - the PETSc object; this must be cast with (`PetscObject`), for example,
836:          `PetscObjectQueryFunction`((`PetscObject`)ksp,...);
837: -  name - name associated with the child function

839:    Output Parameter:
840: .  fptr - function pointer

842:    Level: advanced

844: .seealso: `PetscObjectComposeFunction()`, `PetscFunctionListFind()`, `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObject`
845: M*/
846: PETSC_EXTERN PetscErrorCode PetscObjectQueryFunction_Private(PetscObject obj, const char name[], void (**ptr)(void))
847: {
848:   PetscFunctionBegin;
851:   PetscCall((*obj->bops->queryfunction)(obj, name, ptr));
852:   PetscFunctionReturn(PETSC_SUCCESS);
853: }

855: struct _p_PetscContainer {
856:   PETSCHEADER(int);
857:   void *ptr;
858:   PetscErrorCode (*userdestroy)(void *);
859: };

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

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

867:    Input Parameter:
868: .  ctx - pointer to user-provided data

870:    Level: advanced

872: .seealso: `PetscContainerDestroy()`, `PetscContainerSetUserDestroy(`), `PetscObject`
873: @*/
874: PetscErrorCode PetscContainerUserDestroyDefault(void *ctx)
875: {
876:   PetscFunctionBegin;
877:   PetscCall(PetscFree(ctx));
878:   PetscFunctionReturn(PETSC_SUCCESS);
879: }

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

884:    Not Collective

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

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

892:    Level: advanced

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

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

909:    Logically Collective

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

915:    Level: advanced

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

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

932:    Collective

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

937:    Level: advanced

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

943: .seealso: `PetscContainerCreate()`, `PetscContainerSetUserDestroy()`, `PetscObject`
944: @*/
945: PetscErrorCode PetscContainerDestroy(PetscContainer *obj)
946: {
947:   PetscFunctionBegin;
948:   if (!*obj) PetscFunctionReturn(PETSC_SUCCESS);
950:   if (--((PetscObject)(*obj))->refct > 0) {
951:     *obj = NULL;
952:     PetscFunctionReturn(PETSC_SUCCESS);
953:   }
954:   if ((*obj)->userdestroy) PetscCall((*(*obj)->userdestroy)((*obj)->ptr));
955:   PetscCall(PetscHeaderDestroy(obj));
956:   PetscFunctionReturn(PETSC_SUCCESS);
957: }

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

962:    Logically Collective

964:    Input Parameters:
965: +  obj - an object that was created with `PetscContainerCreate()`
966: -  des - name of the user destroy function

968:    Level: advanced

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

973: .seealso: `PetscContainerDestroy()`, `PetscContainerUserDestroyDefault()`, `PetscMalloc()`, `PetscMalloc1()`, `PetscCalloc()`, `PetscCalloc1()`, `PetscObject`
974: @*/
975: PetscErrorCode PetscContainerSetUserDestroy(PetscContainer obj, PetscErrorCode (*des)(void *))
976: {
977:   PetscFunctionBegin;
979:   obj->userdestroy = des;
980:   PetscFunctionReturn(PETSC_SUCCESS);
981: }

983: PetscClassId PETSC_CONTAINER_CLASSID;

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

991:    Collective

993:    Input Parameter:
994: .  comm - MPI communicator that shares the object

996:    Output Parameter:
997: .  container - the container created

999:    Level: advanced

1001: .seealso: `PetscContainerDestroy()`, `PetscContainerSetPointer()`, `PetscContainerGetPointer()`, `PetscObjectCompose()`, `PetscObjectQuery()`,
1002:           `PetscContainerSetUserDestroy()`, `PetscObject`
1003: @*/
1004: PetscErrorCode PetscContainerCreate(MPI_Comm comm, PetscContainer *container)
1005: {
1006:   PetscFunctionBegin;
1008:   PetscCall(PetscSysInitializePackage());
1009:   PetscCall(PetscHeaderCreate(*container, PETSC_CONTAINER_CLASSID, "PetscContainer", "Container", "Sys", comm, PetscContainerDestroy, NULL));
1010:   PetscFunctionReturn(PETSC_SUCCESS);
1011: }

1013: /*@
1014:    PetscObjectSetFromOptions - Sets generic parameters from user options.

1016:    Collective

1018:    Input Parameter:
1019: .  obj - the `PetscObject`

1021:    Level: beginner

1023:    Note:
1024:    We have no generic options at present, so this does nothing

1026: .seealso: `PetscObjectSetOptionsPrefix()`, `PetscObjectGetOptionsPrefix()`, `PetscObject`
1027: @*/
1028: PetscErrorCode PetscObjectSetFromOptions(PetscObject obj)
1029: {
1030:   PetscFunctionBegin;
1032:   PetscFunctionReturn(PETSC_SUCCESS);
1033: }

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

1038:    Collective

1040:    Input Parameter:
1041: .  obj - the `PetscObject`

1043:    Level: advanced

1045:    Note:
1046:    This does nothing at present.

1048: .seealso: `PetscObjectDestroy()`, `PetscObject`
1049: @*/
1050: PetscErrorCode PetscObjectSetUp(PetscObject obj)
1051: {
1052:   PetscFunctionBegin;
1054:   PetscFunctionReturn(PETSC_SUCCESS);
1055: }