Actual source code: inherit.c
1: /*
2: Provides utility routines for manipulating any type of PETSc object.
3: */
4: #include <petsc/private/petscimpl.h>
5: #include <petscviewer.h>
7: PETSC_INTERN PetscObject *PetscObjects;
8: PETSC_INTERN PetscInt PetscObjectsCounts;
9: PETSC_INTERN PetscInt PetscObjectsMaxCounts;
10: PETSC_INTERN PetscBool PetscObjectsLog;
12: PetscObject *PetscObjects = NULL;
13: PetscInt PetscObjectsCounts = 0, PetscObjectsMaxCounts = 0;
14: PetscBool PetscObjectsLog = PETSC_FALSE;
16: PetscObjectId PetscObjectNewId_Internal(void)
17: {
18: static PetscObjectId idcnt = 1;
19: return idcnt++;
20: }
22: PetscErrorCode PetscHeaderCreate_Function(PetscErrorCode ierr, PetscObject *h, PetscClassId classid, const char class_name[], const char descr[], const char mansec[], MPI_Comm comm, PetscObjectDestroyFunction destroy, PetscObjectViewFunction view)
23: {
24: if (ierr) return ierr;
25: PetscFunctionBegin;
26: PetscCall(PetscHeaderCreate_Private(*h, classid, class_name, descr, mansec, comm, destroy, view));
27: PetscCall(PetscLogObjectCreate(*h));
28: PetscFunctionReturn(PETSC_SUCCESS);
29: }
31: /*
32: PetscHeaderCreate_Private - Fills in the default values.
33: */
34: PetscErrorCode PetscHeaderCreate_Private(PetscObject h, PetscClassId classid, const char class_name[], const char descr[], const char mansec[], MPI_Comm comm, PetscObjectDestroyFunction destroy, PetscObjectViewFunction view)
35: {
36: void *get_tmp;
37: PetscInt64 *cidx;
38: PetscMPIInt flg;
40: PetscFunctionBegin;
41: h->classid = classid;
42: h->class_name = (char *)class_name;
43: h->description = (char *)descr;
44: h->mansec = (char *)mansec;
45: h->refct = 1;
46: h->non_cyclic_references = NULL;
47: h->id = PetscObjectNewId_Internal();
48: h->bops->destroy = destroy;
49: h->bops->view = view;
51: PetscCall(PetscCommDuplicate(comm, &h->comm, &h->tag));
53: /* Increment and store current object creation index */
54: PetscCallMPI(MPI_Comm_get_attr(h->comm, Petsc_CreationIdx_keyval, &get_tmp, &flg));
55: PetscCheck(flg, h->comm, PETSC_ERR_ARG_CORRUPT, "MPI_Comm does not have an object creation index");
56: cidx = (PetscInt64 *)get_tmp;
57: h->cidx = (*cidx)++;
58: PetscCallMPI(MPI_Comm_set_attr(h->comm, Petsc_CreationIdx_keyval, cidx));
60: /* Keep a record of object created */
61: if (PetscDefined(USE_LOG) && PetscObjectsLog) {
62: PetscObject *newPetscObjects;
63: PetscInt newPetscObjectsMaxCounts;
65: PetscObjectsCounts++;
66: for (PetscInt i = 0; i < PetscObjectsMaxCounts; ++i) {
67: if (!PetscObjects[i]) {
68: PetscObjects[i] = h;
69: PetscFunctionReturn(PETSC_SUCCESS);
70: }
71: }
72: /* Need to increase the space for storing PETSc objects */
73: if (!PetscObjectsMaxCounts) newPetscObjectsMaxCounts = 100;
74: else newPetscObjectsMaxCounts = 2 * PetscObjectsMaxCounts;
75: PetscCall(PetscCalloc1(newPetscObjectsMaxCounts, &newPetscObjects));
76: PetscCall(PetscArraycpy(newPetscObjects, PetscObjects, PetscObjectsMaxCounts));
77: PetscCall(PetscFree(PetscObjects));
79: PetscObjects = newPetscObjects;
80: PetscObjects[PetscObjectsMaxCounts] = h;
81: PetscObjectsMaxCounts = newPetscObjectsMaxCounts;
82: }
83: PetscFunctionReturn(PETSC_SUCCESS);
84: }
86: PETSC_INTERN PetscBool PetscMemoryCollectMaximumUsage;
87: PETSC_INTERN PetscLogDouble PetscMemoryMaximumUsage;
89: PetscErrorCode PetscHeaderDestroy_Function(PetscObject *h)
90: {
91: PetscFunctionBegin;
92: PetscCall(PetscLogObjectDestroy(*h));
93: PetscCall(PetscHeaderDestroy_Private(*h, PETSC_FALSE));
94: PetscCall(PetscFree(*h));
95: PetscFunctionReturn(PETSC_SUCCESS);
96: }
98: /*
99: PetscHeaderDestroy_Private - Destroys a base PETSc object header. Called by
100: the macro PetscHeaderDestroy().
101: */
102: PetscErrorCode PetscHeaderDestroy_Private(PetscObject obj, PetscBool clear_for_reuse)
103: {
104: PetscFunctionBegin;
106: PetscCheck(!obj->persistent, PetscObjectComm((PetscObject)obj), PETSC_ERR_ARG_WRONGSTATE, "Cannot destroy this object, it is destroyed automatically in PetscFinalize()");
107: PetscCall(PetscComposedQuantitiesDestroy(obj));
108: if (PetscMemoryCollectMaximumUsage) {
109: PetscLogDouble usage;
111: PetscCall(PetscMemoryGetCurrentUsage(&usage));
112: if (usage > PetscMemoryMaximumUsage) PetscMemoryMaximumUsage = usage;
113: }
114: /* first destroy things that could execute arbitrary code */
115: if (obj->python_destroy) {
116: void *python_context = obj->python_context;
117: PetscErrorCode (*python_destroy)(void *) = obj->python_destroy;
119: obj->python_context = NULL;
120: obj->python_destroy = NULL;
121: PetscCall((*python_destroy)(python_context));
122: }
123: PetscCall(PetscObjectDestroyOptionsHandlers(obj));
124: PetscCall(PetscObjectListDestroy(&obj->olist));
126: /* destroy allocated quantities */
127: if (PetscPrintFunctionList) PetscCall(PetscFunctionListPrintNonEmpty(obj->qlist));
128: 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);
129: PetscCall(PetscFree(obj->name));
130: PetscCall(PetscFree(obj->prefix));
131: PetscCall(PetscFree(obj->type_name));
133: if (clear_for_reuse) {
134: /* we will assume that obj->bops->view and destroy are safe to leave as-is */
136: /* reset quantities, in order of appearance in _p_PetscObject */
137: obj->id = PetscObjectNewId_Internal();
138: obj->refct = 1;
139: obj->tablevel = 0;
140: obj->state = 0;
141: /* don't deallocate, zero these out instead */
142: PetscCall(PetscFunctionListClear(obj->qlist));
143: PetscCall(PetscArrayzero(obj->fortran_func_pointers, obj->num_fortran_func_pointers));
144: PetscCall(PetscArrayzero(obj->fortrancallback[PETSC_FORTRAN_CALLBACK_CLASS], obj->num_fortrancallback[PETSC_FORTRAN_CALLBACK_CLASS]));
145: PetscCall(PetscArrayzero(obj->fortrancallback[PETSC_FORTRAN_CALLBACK_SUBTYPE], obj->num_fortrancallback[PETSC_FORTRAN_CALLBACK_SUBTYPE]));
146: obj->optionsprinted = PETSC_FALSE;
147: #if PetscDefined(HAVE_SAWS)
148: obj->amsmem = PETSC_FALSE;
149: obj->amspublishblock = PETSC_FALSE;
150: #endif
151: obj->options = NULL;
152: obj->donotPetscObjectPrintClassNamePrefixType = PETSC_FALSE;
153: } else {
154: PetscCall(PetscFunctionListDestroy(&obj->qlist));
155: PetscCall(PetscFree(obj->fortran_func_pointers));
156: PetscCall(PetscFree(obj->fortrancallback[PETSC_FORTRAN_CALLBACK_CLASS]));
157: PetscCall(PetscFree(obj->fortrancallback[PETSC_FORTRAN_CALLBACK_SUBTYPE]));
158: PetscCall(PetscCommDestroy(&obj->comm));
159: obj->classid = PETSCFREEDHEADER;
161: if (PetscDefined(USE_LOG) && PetscObjectsLog) {
162: /* Record object removal from list of all objects */
163: for (PetscInt i = 0; i < PetscObjectsMaxCounts; ++i) {
164: if (PetscObjects[i] == obj) {
165: PetscObjects[i] = NULL;
166: --PetscObjectsCounts;
167: break;
168: }
169: }
170: if (!PetscObjectsCounts) {
171: PetscCall(PetscFree(PetscObjects));
172: PetscObjectsMaxCounts = 0;
173: }
174: }
175: }
176: PetscFunctionReturn(PETSC_SUCCESS);
177: }
179: /*
180: PetscHeaderReset_Internal - "Reset" a PetscObject header. This is tantamount to destroying
181: the object but does not free all resources. The object retains its:
183: - classid
184: - bops->view
185: - bops->destroy
186: - comm
187: - tag
188: - class_name
189: - description
190: - mansec
191: - cpp
193: Note that while subclass information is lost, superclass info remains. Thus this function is
194: intended to be used to reuse a PetscObject within the same class to avoid reallocating its
195: resources.
196: */
197: PetscErrorCode PetscHeaderReset_Internal(PetscObject obj)
198: {
199: PetscFunctionBegin;
200: PetscCall(PetscHeaderDestroy_Private(obj, PETSC_TRUE));
201: PetscFunctionReturn(PETSC_SUCCESS);
202: }
204: /*@C
205: PetscObjectCopyFortranFunctionPointers - Copy function pointers to another object
207: Logically Collective
209: Input Parameters:
210: + src - source object
211: - dest - destination object
213: Level: developer
215: Note:
216: Both objects must have the same class.
218: This is used to help manage user callback functions that were provided in Fortran
220: .seealso: `PetscFortranCallbackRegister()`, `PetscFortranCallbackGetSizes()`
221: @*/
222: PetscErrorCode PetscObjectCopyFortranFunctionPointers(PetscObject src, PetscObject dest)
223: {
224: PetscFortranCallbackId cbtype, numcb[PETSC_FORTRAN_CALLBACK_MAXTYPE];
226: PetscFunctionBegin;
229: PetscCheck(src->classid == dest->classid, src->comm, PETSC_ERR_ARG_INCOMP, "Objects must be of the same class");
231: PetscCall(PetscFree(dest->fortran_func_pointers));
232: PetscCall(PetscMalloc(src->num_fortran_func_pointers * sizeof(void (*)(void)), &dest->fortran_func_pointers));
233: PetscCall(PetscMemcpy(dest->fortran_func_pointers, src->fortran_func_pointers, src->num_fortran_func_pointers * sizeof(void (*)(void))));
235: dest->num_fortran_func_pointers = src->num_fortran_func_pointers;
237: PetscCall(PetscFortranCallbackGetSizes(src->classid, &numcb[PETSC_FORTRAN_CALLBACK_CLASS], &numcb[PETSC_FORTRAN_CALLBACK_SUBTYPE]));
238: for (cbtype = PETSC_FORTRAN_CALLBACK_CLASS; cbtype < PETSC_FORTRAN_CALLBACK_MAXTYPE; cbtype++) {
239: PetscCall(PetscFree(dest->fortrancallback[cbtype]));
240: PetscCall(PetscCalloc1(numcb[cbtype], &dest->fortrancallback[cbtype]));
241: PetscCall(PetscMemcpy(dest->fortrancallback[cbtype], src->fortrancallback[cbtype], src->num_fortrancallback[cbtype] * sizeof(PetscFortranCallback)));
242: dest->num_fortrancallback[cbtype] = src->num_fortrancallback[cbtype];
243: }
244: PetscFunctionReturn(PETSC_SUCCESS);
245: }
247: /*@C
248: PetscObjectSetFortranCallback - set fortran callback function pointer and context
250: Logically Collective
252: Input Parameters:
253: + obj - object on which to set callback
254: . cbtype - callback type (class or subtype)
255: . cid - address of callback Id, updated if not yet initialized (zero)
256: . func - Fortran function
257: - ctx - Fortran context
259: Level: developer
261: Note:
262: This is used to help manage user callback functions that were provided in Fortran
264: .seealso: `PetscObjectGetFortranCallback()`, `PetscFortranCallbackRegister()`, `PetscFortranCallbackGetSizes()`
265: @*/
266: PetscErrorCode PetscObjectSetFortranCallback(PetscObject obj, PetscFortranCallbackType cbtype, PetscFortranCallbackId *cid, void (*func)(void), void *ctx)
267: {
268: const char *subtype = NULL;
270: PetscFunctionBegin;
272: if (cbtype == PETSC_FORTRAN_CALLBACK_SUBTYPE) subtype = obj->type_name;
273: if (!*cid) PetscCall(PetscFortranCallbackRegister(obj->classid, subtype, cid));
274: if (*cid >= PETSC_SMALLEST_FORTRAN_CALLBACK + obj->num_fortrancallback[cbtype]) {
275: PetscFortranCallbackId oldnum = obj->num_fortrancallback[cbtype];
276: PetscFortranCallbackId newnum = PetscMax(*cid - PETSC_SMALLEST_FORTRAN_CALLBACK + 1, 2 * oldnum);
277: PetscFortranCallback *callback;
278: PetscCall(PetscMalloc1(newnum, &callback));
279: PetscCall(PetscMemcpy(callback, obj->fortrancallback[cbtype], oldnum * sizeof(*obj->fortrancallback[cbtype])));
280: PetscCall(PetscFree(obj->fortrancallback[cbtype]));
282: obj->fortrancallback[cbtype] = callback;
283: obj->num_fortrancallback[cbtype] = newnum;
284: }
285: obj->fortrancallback[cbtype][*cid - PETSC_SMALLEST_FORTRAN_CALLBACK].func = func;
286: obj->fortrancallback[cbtype][*cid - PETSC_SMALLEST_FORTRAN_CALLBACK].ctx = ctx;
287: PetscFunctionReturn(PETSC_SUCCESS);
288: }
290: /*@C
291: PetscObjectGetFortranCallback - get fortran callback function pointer and context
293: Logically Collective
295: Input Parameters:
296: + obj - object on which to get callback
297: . cbtype - callback type
298: - cid - address of callback Id
300: Output Parameters:
301: + func - Fortran function (or `NULL` if not needed)
302: - ctx - Fortran context (or `NULL` if not needed)
304: Level: developer
306: Note:
307: This is used to help manage user callback functions that were provided in Fortran
309: .seealso: `PetscObjectSetFortranCallback()`, `PetscFortranCallbackRegister()`, `PetscFortranCallbackGetSizes()`
310: @*/
311: PetscErrorCode PetscObjectGetFortranCallback(PetscObject obj, PetscFortranCallbackType cbtype, PetscFortranCallbackId cid, void (**func)(void), void **ctx)
312: {
313: PetscFortranCallback *cb;
315: PetscFunctionBegin;
317: PetscCheck(cid >= PETSC_SMALLEST_FORTRAN_CALLBACK, obj->comm, PETSC_ERR_ARG_CORRUPT, "Fortran callback Id invalid");
318: PetscCheck(cid < PETSC_SMALLEST_FORTRAN_CALLBACK + obj->num_fortrancallback[cbtype], obj->comm, PETSC_ERR_ARG_CORRUPT, "Fortran callback not set on this object");
319: cb = &obj->fortrancallback[cbtype][cid - PETSC_SMALLEST_FORTRAN_CALLBACK];
320: if (func) *func = cb->func;
321: if (ctx) *ctx = cb->ctx;
322: PetscFunctionReturn(PETSC_SUCCESS);
323: }
325: #if defined(PETSC_USE_LOG)
326: /*@C
327: PetscObjectsDump - Prints all the currently existing objects.
329: On rank 0 of `PETSC_COMM_WORLD` prints the values
331: Input Parameters:
332: + fd - file pointer
333: - all - by default only tries to display objects created explicitly by the user, if all is `PETSC_TRUE` then lists all outstanding objects
335: Options Database Key:
336: . -objects_dump <all> - print information about all the objects that exist at the end of the programs run
338: Level: advanced
340: .seealso: `PetscObject`
341: @*/
342: PetscErrorCode PetscObjectsDump(FILE *fd, PetscBool all)
343: {
344: PetscInt i, j, k = 0;
345: PetscObject h;
347: PetscFunctionBegin;
348: if (PetscObjectsCounts) {
349: PetscCall(PetscFPrintf(PETSC_COMM_WORLD, fd, "The following objects were never freed\n"));
350: PetscCall(PetscFPrintf(PETSC_COMM_WORLD, fd, "-----------------------------------------\n"));
351: for (i = 0; i < PetscObjectsMaxCounts; i++) {
352: if ((h = PetscObjects[i])) {
353: PetscCall(PetscObjectName(h));
354: {
355: PetscStack *stack = NULL;
356: char *create = NULL, *rclass = NULL;
358: /* if the PETSc function the user calls is not a create then this object was NOT directly created by them */
359: PetscCall(PetscMallocGetStack(h, &stack));
360: if (stack) {
361: k = stack->currentsize - 2;
362: if (!all) {
363: k = 0;
364: while (!stack->petscroutine[k]) k++;
365: PetscCall(PetscStrstr(stack->function[k], "Create", &create));
366: if (!create) PetscCall(PetscStrstr(stack->function[k], "Get", &create));
367: PetscCall(PetscStrstr(stack->function[k], h->class_name, &rclass));
368: if (!create) continue;
369: if (!rclass) continue;
370: }
371: }
373: PetscCall(PetscFPrintf(PETSC_COMM_WORLD, fd, "[%d] %s %s %s\n", PetscGlobalRank, h->class_name, h->type_name, h->name));
375: PetscCall(PetscMallocGetStack(h, &stack));
376: if (stack) {
377: for (j = k; j >= 0; j--) fprintf(fd, " [%d] %s() in %s\n", PetscGlobalRank, stack->function[j], stack->file[j]);
378: }
379: }
380: }
381: }
382: }
383: PetscFunctionReturn(PETSC_SUCCESS);
384: }
386: /*@C
387: PetscObjectsView - Prints the currently existing objects.
389: Logically Collective
391: Input Parameter:
392: . viewer - must be an `PETSCVIEWERASCII` viewer
394: Level: advanced
396: .seealso: `PetscObject`
397: @*/
398: PetscErrorCode PetscObjectsView(PetscViewer viewer)
399: {
400: PetscBool isascii;
401: FILE *fd;
403: PetscFunctionBegin;
404: if (!viewer) viewer = PETSC_VIEWER_STDOUT_WORLD;
405: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
406: PetscCheck(isascii, PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Only supports ASCII viewer");
407: PetscCall(PetscViewerASCIIGetPointer(viewer, &fd));
408: PetscCall(PetscObjectsDump(fd, PETSC_TRUE));
409: PetscFunctionReturn(PETSC_SUCCESS);
410: }
412: /*@C
413: PetscObjectsGetObject - Get a pointer to a named object
415: Not Collective
417: Input Parameter:
418: . name - the name of an object
420: Output Parameters:
421: + obj - the object or `NULL` if there is no object
422: - classname - the name of the class
424: Level: advanced
426: .seealso: `PetscObject`
427: @*/
428: PetscErrorCode PetscObjectsGetObject(const char *name, PetscObject *obj, char **classname)
429: {
430: PetscInt i;
431: PetscObject h;
432: PetscBool flg;
434: PetscFunctionBegin;
435: PetscAssertPointer(name, 1);
436: PetscAssertPointer(obj, 2);
437: *obj = NULL;
438: for (i = 0; i < PetscObjectsMaxCounts; i++) {
439: if ((h = PetscObjects[i])) {
440: PetscCall(PetscObjectName(h));
441: PetscCall(PetscStrcmp(h->name, name, &flg));
442: if (flg) {
443: *obj = h;
444: if (classname) *classname = h->class_name;
445: PetscFunctionReturn(PETSC_SUCCESS);
446: }
447: }
448: }
449: PetscFunctionReturn(PETSC_SUCCESS);
450: }
451: #endif
453: /*@
454: 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
456: Input Parameter:
457: . obj - the `PetscObject`
459: Level: developer
461: Developer Notes:
462: This is used, for example to prevent sequential objects that are created from a parallel object; such as the `KSP` created by
463: `PCBJACOBI` from all printing the same help messages to the screen
465: .seealso: `PetscOptionsInsert()`, `PetscObject`
466: @*/
467: PetscErrorCode PetscObjectSetPrintedOptions(PetscObject obj)
468: {
469: PetscFunctionBegin;
470: PetscAssertPointer(obj, 1);
471: obj->optionsprinted = PETSC_TRUE;
472: PetscFunctionReturn(PETSC_SUCCESS);
473: }
475: /*@
476: PetscObjectInheritPrintedOptions - If the child object is not on the rank 0 process of the parent object and the child is sequential then the child gets it set.
478: Input Parameters:
479: + pobj - the parent object
480: - obj - the `PetscObject`
482: Level: developer
484: Developer Notes:
485: This is used, for example to prevent sequential objects that are created from a parallel object; such as the `KSP` created by
486: `PCBJACOBI` from all printing the same help messages to the screen
488: This will not handle more complicated situations like with `PCGASM` where children may live on any subset of the parent's processes and overlap
490: .seealso: `PetscOptionsInsert()`, `PetscObjectSetPrintedOptions()`, `PetscObject`
491: @*/
492: PetscErrorCode PetscObjectInheritPrintedOptions(PetscObject pobj, PetscObject obj)
493: {
494: PetscMPIInt prank, size;
496: PetscFunctionBegin;
499: PetscCallMPI(MPI_Comm_rank(pobj->comm, &prank));
500: PetscCallMPI(MPI_Comm_size(obj->comm, &size));
501: if (size == 1 && prank > 0) obj->optionsprinted = PETSC_TRUE;
502: PetscFunctionReturn(PETSC_SUCCESS);
503: }
505: /*@C
506: PetscObjectAddOptionsHandler - Adds an additional function to check for options when `XXXSetFromOptions()` is called.
508: Not Collective
510: Input Parameters:
511: + obj - the PETSc object
512: . handle - function that checks for options
513: . destroy - function to destroy context if provided
514: - ctx - optional context for check function
516: Level: developer
518: .seealso: `KSPSetFromOptions()`, `PCSetFromOptions()`, `SNESSetFromOptions()`, `PetscObjectProcessOptionsHandlers()`, `PetscObjectDestroyOptionsHandlers()`,
519: `PetscObject`
520: @*/
521: PetscErrorCode PetscObjectAddOptionsHandler(PetscObject obj, PetscErrorCode (*handle)(PetscObject, PetscOptionItems *, void *), PetscErrorCode (*destroy)(PetscObject, void *), void *ctx)
522: {
523: PetscFunctionBegin;
525: PetscCheck(obj->noptionhandler < PETSC_MAX_OPTIONS_HANDLER, obj->comm, PETSC_ERR_ARG_OUTOFRANGE, "To many options handlers added");
526: obj->optionhandler[obj->noptionhandler] = handle;
527: obj->optiondestroy[obj->noptionhandler] = destroy;
528: obj->optionctx[obj->noptionhandler++] = ctx;
529: PetscFunctionReturn(PETSC_SUCCESS);
530: }
532: /*@C
533: PetscObjectProcessOptionsHandlers - Calls all the options handlers attached to an object
535: Not Collective
537: Input Parameters:
538: + obj - the PETSc object
539: - PetscOptionsObject - the options context
541: Level: developer
543: .seealso: `KSPSetFromOptions()`, `PCSetFromOptions()`, `SNESSetFromOptions()`, `PetscObjectAddOptionsHandler()`, `PetscObjectDestroyOptionsHandlers()`,
544: `PetscObject`
545: @*/
546: PetscErrorCode PetscObjectProcessOptionsHandlers(PetscObject obj, PetscOptionItems *PetscOptionsObject)
547: {
548: PetscFunctionBegin;
550: for (PetscInt i = 0; i < obj->noptionhandler; i++) PetscCall((*obj->optionhandler[i])(obj, PetscOptionsObject, obj->optionctx[i]));
551: PetscFunctionReturn(PETSC_SUCCESS);
552: }
554: /*@C
555: PetscObjectDestroyOptionsHandlers - Destroys all the option handlers attached to an object
557: Not Collective
559: Input Parameter:
560: . obj - the PETSc object
562: Level: developer
564: .seealso: `KSPSetFromOptions()`, `PCSetFromOptions()`, `SNESSetFromOptions()`, `PetscObjectAddOptionsHandler()`, `PetscObjectProcessOptionsHandlers()`,
565: `PetscObject`
566: @*/
567: PetscErrorCode PetscObjectDestroyOptionsHandlers(PetscObject obj)
568: {
569: PetscFunctionBegin;
571: for (PetscInt i = 0; i < obj->noptionhandler; i++) {
572: if (obj->optiondestroy[i]) PetscCall((*obj->optiondestroy[i])(obj, obj->optionctx[i]));
573: }
574: obj->noptionhandler = 0;
575: PetscFunctionReturn(PETSC_SUCCESS);
576: }
578: /*@C
579: PetscObjectReference - Indicates to any `PetscObject` that it is being
580: referenced by another `PetscObject`. This increases the reference
581: count for that object by one.
583: Logically Collective
585: Input Parameter:
586: . obj - the PETSc object. This must be cast with (`PetscObject`), for example,
587: `PetscObjectReference`((`PetscObject`)mat);
589: Level: advanced
591: .seealso: `PetscObjectCompose()`, `PetscObjectDereference()`, `PetscObject`
592: @*/
593: PetscErrorCode PetscObjectReference(PetscObject obj)
594: {
595: PetscFunctionBegin;
596: if (!obj) PetscFunctionReturn(PETSC_SUCCESS);
598: obj->refct++;
599: PetscFunctionReturn(PETSC_SUCCESS);
600: }
602: /*@C
603: PetscObjectGetReference - Gets the current reference count for
604: any PETSc object.
606: Not Collective
608: Input Parameter:
609: . obj - the PETSc object; this must be cast with (`PetscObject`), for example,
610: `PetscObjectGetReference`((`PetscObject`)mat,&cnt);
612: Output Parameter:
613: . cnt - the reference count
615: Level: advanced
617: .seealso: `PetscObjectCompose()`, `PetscObjectDereference()`, `PetscObjectReference()`, `PetscObject`
618: @*/
619: PetscErrorCode PetscObjectGetReference(PetscObject obj, PetscInt *cnt)
620: {
621: PetscFunctionBegin;
623: PetscAssertPointer(cnt, 2);
624: *cnt = obj->refct;
625: PetscFunctionReturn(PETSC_SUCCESS);
626: }
628: /*@C
629: PetscObjectDereference - Indicates to any `PetscObject` that it is being
630: referenced by one less `PetscObject`. This decreases the reference
631: count for that object by one.
633: Collective on `obj` if reference reaches 0 otherwise Logically Collective
635: Input Parameter:
636: . obj - the PETSc object; this must be cast with (`PetscObject`), for example,
637: `PetscObjectDereference`((`PetscObject`)mat);
639: Level: advanced
641: Note:
642: `PetscObjectDestroy()` sets the obj pointer to null after the call, this routine does not.
644: .seealso: `PetscObjectCompose()`, `PetscObjectReference()`, `PetscObjectDestroy()`, `PetscObject`
645: @*/
646: PetscErrorCode PetscObjectDereference(PetscObject obj)
647: {
648: PetscFunctionBegin;
649: if (!obj) PetscFunctionReturn(PETSC_SUCCESS);
651: if (obj->bops->destroy) PetscCall((*obj->bops->destroy)(&obj));
652: else PetscCheck(--(obj->refct), PETSC_COMM_SELF, PETSC_ERR_SUP, "This PETSc object does not have a generic destroy routine");
653: PetscFunctionReturn(PETSC_SUCCESS);
654: }
656: /*
657: The following routines are the versions private to the PETSc object
658: data structures.
659: */
660: PetscErrorCode PetscObjectRemoveReference(PetscObject obj, const char name[])
661: {
662: PetscFunctionBegin;
664: PetscCall(PetscObjectListRemoveReference(&obj->olist, name));
665: PetscFunctionReturn(PETSC_SUCCESS);
666: }
668: /*@C
669: PetscObjectCompose - Associates another PETSc object with a given PETSc object.
671: Not Collective
673: Input Parameters:
674: + obj - the PETSc object; this must be cast with (`PetscObject`), for example,
675: `PetscObjectCompose`((`PetscObject`)mat,...);
676: . name - name associated with the child object
677: - ptr - the other PETSc object to associate with the PETSc object; this must also be
678: cast with (`PetscObject`)
680: Level: advanced
682: Notes:
683: The second objects reference count is automatically increased by one when it is
684: composed.
686: Replaces any previous object that had the same name.
688: If ptr is null and name has previously been composed using an object, then that
689: entry is removed from the obj.
691: `PetscObjectCompose()` can be used with any PETSc object (such as
692: `Mat`, `Vec`, `KSP`, `SNES`, etc.) or any user-provided object.
694: `PetscContainerCreate()` can be used to create an object from a
695: user-provided pointer that may then be composed with PETSc objects using `PetscObjectCompose()`
697: .seealso: `PetscObjectQuery()`, `PetscContainerCreate()`, `PetscObjectComposeFunction()`, `PetscObjectQueryFunction()`, `PetscContainer`,
698: `PetscContainerSetPointer()`, `PetscObject`
699: @*/
700: PetscErrorCode PetscObjectCompose(PetscObject obj, const char name[], PetscObject ptr)
701: {
702: PetscFunctionBegin;
704: PetscAssertPointer(name, 2);
706: PetscCheck(obj != ptr, PetscObjectComm((PetscObject)obj), PETSC_ERR_SUP, "Cannot compose object with itself");
707: if (ptr) {
708: char *tname;
709: PetscBool skipreference;
711: PetscCall(PetscObjectListReverseFind(ptr->olist, obj, &tname, &skipreference));
712: if (tname) PetscCheck(skipreference, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "An object cannot be composed with an object that was composed with it");
713: }
714: PetscCall(PetscObjectListAdd(&obj->olist, name, ptr));
715: PetscFunctionReturn(PETSC_SUCCESS);
716: }
718: /*@C
719: PetscObjectQuery - Gets a PETSc object associated with a given object that was composed with `PetscObjectCompose()`
721: Not Collective
723: Input Parameters:
724: + obj - the PETSc object
725: Thus must be cast with a (`PetscObject`), for example,
726: `PetscObjectCompose`((`PetscObject`)mat,...);
727: . name - name associated with child object
728: - ptr - the other PETSc object associated with the PETSc object, this must be
729: cast with (`PetscObject`*)
731: Level: advanced
733: Note:
734: The reference count of neither object is increased in this call
736: .seealso: `PetscObjectCompose()`, `PetscObjectComposeFunction()`, `PetscObjectQueryFunction()`, `PetscContainer`
737: `PetscContainerGetPointer()`, `PetscObject`
738: @*/
739: PetscErrorCode PetscObjectQuery(PetscObject obj, const char name[], PetscObject *ptr)
740: {
741: PetscFunctionBegin;
743: PetscAssertPointer(name, 2);
744: PetscAssertPointer(ptr, 3);
745: PetscCall(PetscObjectListFind(obj->olist, name, ptr));
746: PetscFunctionReturn(PETSC_SUCCESS);
747: }
749: /*MC
750: PetscObjectComposeFunction - Associates a function with a given PETSc object.
752: Synopsis:
753: #include <petscsys.h>
754: PetscErrorCode PetscObjectComposeFunction(PetscObject obj, const char name[], void (*fptr)(void))
756: Logically Collective
758: Input Parameters:
759: + obj - the PETSc object; this must be cast with a (`PetscObject`), for example,
760: `PetscObjectCompose`((`PetscObject`)mat,...);
761: . name - name associated with the child function
762: - fptr - function pointer
764: Level: advanced
766: Notes:
767: When the first argument of `fptr` is (or is derived from) a `PetscObject` then `PetscTryMethod()` and `PetscUseMethod()`
768: can be used to call the function directly with error checking.
770: To remove a registered routine, pass in `NULL` for `fptr`.
772: `PetscObjectComposeFunction()` can be used with any PETSc object (such as
773: `Mat`, `Vec`, `KSP`, `SNES`, etc.) or any user-provided object.
775: `PetscUseTypeMethod()` and `PetscTryTypeMethod()` are used to call a function that is stored in the objects `obj->ops` table.
777: .seealso: `PetscObjectQueryFunction()`, `PetscContainerCreate()` `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscTryMethod()`, `PetscUseMethod()`,
778: `PetscUseTypeMethod()`, `PetscTryTypeMethod()`, `PetscObject`
779: M*/
780: PetscErrorCode PetscObjectComposeFunction_Private(PetscObject obj, const char name[], void (*fptr)(void))
781: {
782: PetscFunctionBegin;
784: PetscAssertPointer(name, 2);
785: PetscCall(PetscFunctionListAdd(&obj->qlist, name, fptr));
786: PetscFunctionReturn(PETSC_SUCCESS);
787: }
789: /*MC
790: PetscObjectQueryFunction - Gets a function associated with a given object.
792: Synopsis:
793: #include <petscsys.h>
794: PetscErrorCode PetscObjectQueryFunction(PetscObject obj, const char name[], void (**fptr)(void))
796: Logically Collective
798: Input Parameters:
799: + obj - the PETSc object; this must be cast with (`PetscObject`), for example,
800: `PetscObjectQueryFunction`((`PetscObject`)ksp,...);
801: - name - name associated with the child function
803: Output Parameter:
804: . fptr - function pointer
806: Level: advanced
808: .seealso: `PetscObjectComposeFunction()`, `PetscFunctionListFind()`, `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObject`
809: M*/
810: PETSC_EXTERN PetscErrorCode PetscObjectQueryFunction_Private(PetscObject obj, const char name[], void (**fptr)(void))
811: {
812: PetscFunctionBegin;
814: PetscAssertPointer(name, 2);
815: PetscCall(PetscFunctionListFind(obj->qlist, name, fptr));
816: PetscFunctionReturn(PETSC_SUCCESS);
817: }
819: struct _p_PetscContainer {
820: PETSCHEADER(int);
821: void *ptr;
822: PetscErrorCode (*userdestroy)(void *);
823: };
825: /*@C
826: PetscContainerUserDestroyDefault - Default destroy routine for user-provided data that simply calls `PetscFree()` in the data
827: provided with `PetscContainerSetPointer()`
829: Logically Collective on the `PetscContainer` containing the user data
831: Input Parameter:
832: . ctx - pointer to user-provided data
834: Level: advanced
836: .seealso: `PetscContainerDestroy()`, `PetscContainerSetUserDestroy()`, `PetscObject`
837: @*/
838: PetscErrorCode PetscContainerUserDestroyDefault(void *ctx)
839: {
840: PetscFunctionBegin;
841: PetscCall(PetscFree(ctx));
842: PetscFunctionReturn(PETSC_SUCCESS);
843: }
845: /*@C
846: PetscContainerGetPointer - Gets the pointer value contained in the container that was provided with `PetscContainerSetPointer()`
848: Not Collective
850: Input Parameter:
851: . obj - the object created with `PetscContainerCreate()`
853: Output Parameter:
854: . ptr - the pointer value
856: Level: advanced
858: .seealso: `PetscContainerCreate()`, `PetscContainerDestroy()`, `PetscObject`,
859: `PetscContainerSetPointer()`
860: @*/
861: PetscErrorCode PetscContainerGetPointer(PetscContainer obj, void **ptr)
862: {
863: PetscFunctionBegin;
865: PetscAssertPointer(ptr, 2);
866: *ptr = obj->ptr;
867: PetscFunctionReturn(PETSC_SUCCESS);
868: }
870: /*@C
871: PetscContainerSetPointer - Sets the pointer value contained in the container.
873: Logically Collective
875: Input Parameters:
876: + obj - the object created with `PetscContainerCreate()`
877: - ptr - the pointer value
879: Level: advanced
881: .seealso: `PetscContainerCreate()`, `PetscContainerDestroy()`, `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObject`,
882: `PetscContainerGetPointer()`
883: @*/
884: PetscErrorCode PetscContainerSetPointer(PetscContainer obj, void *ptr)
885: {
886: PetscFunctionBegin;
888: if (ptr) PetscAssertPointer(ptr, 2);
889: obj->ptr = ptr;
890: PetscFunctionReturn(PETSC_SUCCESS);
891: }
893: /*@C
894: PetscContainerDestroy - Destroys a PETSc container object.
896: Collective
898: Input Parameter:
899: . obj - an object that was created with `PetscContainerCreate()`
901: Level: advanced
903: Note:
904: If `PetscContainerSetUserDestroy()` was used to provide a user destroy object for the data provided with `PetscContainerSetPointer()`
905: then that function is called to destroy the data.
907: .seealso: `PetscContainerCreate()`, `PetscContainerSetUserDestroy()`, `PetscObject`
908: @*/
909: PetscErrorCode PetscContainerDestroy(PetscContainer *obj)
910: {
911: PetscFunctionBegin;
912: if (!*obj) PetscFunctionReturn(PETSC_SUCCESS);
914: if (--((PetscObject)(*obj))->refct > 0) {
915: *obj = NULL;
916: PetscFunctionReturn(PETSC_SUCCESS);
917: }
918: if ((*obj)->userdestroy) PetscCall((*(*obj)->userdestroy)((*obj)->ptr));
919: PetscCall(PetscHeaderDestroy(obj));
920: PetscFunctionReturn(PETSC_SUCCESS);
921: }
923: /*@C
924: PetscContainerSetUserDestroy - Sets name of the user destroy function for the data provided to the `PetscContainer` with `PetscContainerSetPointer()`
926: Logically Collective
928: Input Parameters:
929: + obj - an object that was created with `PetscContainerCreate()`
930: - des - name of the user destroy function
932: Level: advanced
934: Note:
935: Use `PetscContainerUserDestroyDefault()` if the memory was obtained by calling `PetscMalloc()` or one of its variants for single memory allocation.
937: .seealso: `PetscContainerDestroy()`, `PetscContainerUserDestroyDefault()`, `PetscMalloc()`, `PetscMalloc1()`, `PetscCalloc()`, `PetscCalloc1()`, `PetscObject`
938: @*/
939: PetscErrorCode PetscContainerSetUserDestroy(PetscContainer obj, PetscErrorCode (*des)(void *))
940: {
941: PetscFunctionBegin;
943: obj->userdestroy = des;
944: PetscFunctionReturn(PETSC_SUCCESS);
945: }
947: PetscClassId PETSC_CONTAINER_CLASSID;
949: /*@C
950: PetscContainerCreate - Creates a PETSc object that has room to hold a single pointer.
952: Collective
954: Input Parameter:
955: . comm - MPI communicator that shares the object
957: Output Parameter:
958: . container - the container created
960: Level: advanced
962: Notes:
963: This allows one to attach any type of data (accessible through a pointer) with the
964: `PetscObjectCompose()` function to a `PetscObject`. The data item itself is attached by a
965: call to `PetscContainerSetPointer()`.
967: .seealso: `PetscContainerDestroy()`, `PetscContainerSetPointer()`, `PetscContainerGetPointer()`, `PetscObjectCompose()`, `PetscObjectQuery()`,
968: `PetscContainerSetUserDestroy()`, `PetscObject`
969: @*/
970: PetscErrorCode PetscContainerCreate(MPI_Comm comm, PetscContainer *container)
971: {
972: PetscFunctionBegin;
973: PetscAssertPointer(container, 2);
974: PetscCall(PetscSysInitializePackage());
975: PetscCall(PetscHeaderCreate(*container, PETSC_CONTAINER_CLASSID, "PetscContainer", "Container", "Sys", comm, PetscContainerDestroy, NULL));
976: PetscFunctionReturn(PETSC_SUCCESS);
977: }
979: /*@
980: PetscObjectSetFromOptions - Sets generic parameters from user options.
982: Collective
984: Input Parameter:
985: . obj - the `PetscObject`
987: Level: beginner
989: Note:
990: We have no generic options at present, so this does nothing
992: .seealso: `PetscObjectSetOptionsPrefix()`, `PetscObjectGetOptionsPrefix()`, `PetscObject`
993: @*/
994: PetscErrorCode PetscObjectSetFromOptions(PetscObject obj)
995: {
996: PetscFunctionBegin;
998: PetscFunctionReturn(PETSC_SUCCESS);
999: }
1001: /*@
1002: PetscObjectSetUp - Sets up the internal data structures for the later use.
1004: Collective
1006: Input Parameter:
1007: . obj - the `PetscObject`
1009: Level: advanced
1011: Note:
1012: This does nothing at present.
1014: .seealso: `PetscObjectDestroy()`, `PetscObject`
1015: @*/
1016: PetscErrorCode PetscObjectSetUp(PetscObject obj)
1017: {
1018: PetscFunctionBegin;
1020: PetscFunctionReturn(PETSC_SUCCESS);
1021: }