Actual source code: inherit.c
1: /*
2: Provides utility routines for manipulating any type of PETSc object.
3: */
4: #include <petsc/private/petscimpl.h>
5: #include <petscviewer.h>
7: PETSC_INTERN PetscObject *PetscObjects;
8: PETSC_INTERN PetscInt PetscObjectsCounts;
9: PETSC_INTERN PetscInt PetscObjectsMaxCounts;
10: PETSC_INTERN PetscBool PetscObjectsLog;
12: PetscObject *PetscObjects = NULL;
13: PetscInt PetscObjectsCounts = 0, PetscObjectsMaxCounts = 0;
14: PetscBool PetscObjectsLog = PETSC_FALSE;
16: PetscObjectId PetscObjectNewId_Internal(void)
17: {
18: static PetscObjectId idcnt = 1;
19: return idcnt++;
20: }
22: PetscErrorCode PetscHeaderCreate_Function(PetscErrorCode ierr, PetscObject *h, PetscClassId classid, const char class_name[], const char descr[], const char mansec[], MPI_Comm comm, PetscObjectDestroyFunction destroy, PetscObjectViewFunction view)
23: {
24: if (ierr) return ierr;
25: PetscFunctionBegin;
26: PetscCall(PetscHeaderCreate_Private(*h, classid, class_name, descr, mansec, comm, destroy, view));
27: PetscCall(PetscLogObjectCreate(*h));
28: PetscFunctionReturn(PETSC_SUCCESS);
29: }
31: /*
32: PetscHeaderCreate_Private - Fills in the default values.
33: */
34: PetscErrorCode PetscHeaderCreate_Private(PetscObject h, PetscClassId classid, const char class_name[], const char descr[], const char mansec[], MPI_Comm comm, PetscObjectDestroyFunction destroy, PetscObjectViewFunction view)
35: {
36: void *get_tmp;
37: PetscInt64 *cidx;
38: PetscMPIInt flg;
40: PetscFunctionBegin;
41: h->classid = classid;
42: h->class_name = (char *)class_name;
43: h->description = (char *)descr;
44: h->mansec = (char *)mansec;
45: h->refct = 1;
46: h->non_cyclic_references = NULL;
47: h->id = PetscObjectNewId_Internal();
48: h->bops->destroy = destroy;
49: h->bops->view = view;
51: PetscCall(PetscCommDuplicate(comm, &h->comm, &h->tag));
53: /* Increment and store current object creation index */
54: PetscCallMPI(MPI_Comm_get_attr(h->comm, Petsc_CreationIdx_keyval, &get_tmp, &flg));
55: PetscCheck(flg, h->comm, PETSC_ERR_ARG_CORRUPT, "MPI_Comm does not have an object creation index");
56: cidx = (PetscInt64 *)get_tmp;
57: h->cidx = (*cidx)++;
59: /* Keep a record of object created */
60: if (PetscDefined(USE_LOG) && PetscObjectsLog) {
61: PetscObject *newPetscObjects;
62: PetscInt newPetscObjectsMaxCounts;
64: PetscObjectsCounts++;
65: for (PetscInt i = 0; i < PetscObjectsMaxCounts; ++i) {
66: if (!PetscObjects[i]) {
67: PetscObjects[i] = h;
68: PetscFunctionReturn(PETSC_SUCCESS);
69: }
70: }
71: /* Need to increase the space for storing PETSc objects */
72: if (!PetscObjectsMaxCounts) newPetscObjectsMaxCounts = 100;
73: else newPetscObjectsMaxCounts = 2 * PetscObjectsMaxCounts;
74: PetscCall(PetscCalloc1(newPetscObjectsMaxCounts, &newPetscObjects));
75: PetscCall(PetscArraycpy(newPetscObjects, PetscObjects, PetscObjectsMaxCounts));
76: PetscCall(PetscFree(PetscObjects));
78: PetscObjects = newPetscObjects;
79: PetscObjects[PetscObjectsMaxCounts] = h;
80: PetscObjectsMaxCounts = newPetscObjectsMaxCounts;
81: }
82: PetscFunctionReturn(PETSC_SUCCESS);
83: }
85: PETSC_INTERN PetscBool PetscMemoryCollectMaximumUsage;
86: PETSC_INTERN PetscLogDouble PetscMemoryMaximumUsage;
88: PetscErrorCode PetscHeaderDestroy_Function(PetscObject *h)
89: {
90: PetscFunctionBegin;
91: PetscCall(PetscLogObjectDestroy(*h));
92: PetscCall(PetscHeaderDestroy_Private(*h, PETSC_FALSE));
93: PetscCall(PetscFree(*h));
94: PetscFunctionReturn(PETSC_SUCCESS);
95: }
97: /*
98: PetscHeaderDestroy_Private - Destroys a base PETSc object header. Called by
99: the macro PetscHeaderDestroy().
100: */
101: PetscErrorCode PetscHeaderDestroy_Private(PetscObject obj, PetscBool clear_for_reuse)
102: {
103: PetscFunctionBegin;
105: PetscCheck(!obj->persistent, PetscObjectComm((PetscObject)obj), PETSC_ERR_ARG_WRONGSTATE, "Cannot destroy this object, it is destroyed automatically in PetscFinalize()");
106: PetscCall(PetscComposedQuantitiesDestroy(obj));
107: if (PetscMemoryCollectMaximumUsage) {
108: PetscLogDouble usage;
110: PetscCall(PetscMemoryGetCurrentUsage(&usage));
111: if (usage > PetscMemoryMaximumUsage) PetscMemoryMaximumUsage = usage;
112: }
113: /* first destroy things that could execute arbitrary code */
114: if (obj->python_destroy) {
115: void *python_context = obj->python_context;
116: PetscErrorCode (*python_destroy)(void *) = obj->python_destroy;
118: obj->python_context = NULL;
119: obj->python_destroy = NULL;
120: PetscCall((*python_destroy)(python_context));
121: }
122: PetscCall(PetscObjectDestroyOptionsHandlers(obj));
123: PetscCall(PetscObjectListDestroy(&obj->olist));
125: /* destroy allocated quantities */
126: if (PetscPrintFunctionList) PetscCall(PetscFunctionListPrintNonEmpty(obj->qlist));
127: PetscCheck(--(obj->refct) <= 0, obj->comm, PETSC_ERR_PLIB, "Destroying a PetscObject (%s) with reference count %" PetscInt_FMT " >= 1", obj->name ? obj->name : "unnamed", obj->refct);
128: PetscCall(PetscFree(obj->name));
129: PetscCall(PetscFree(obj->prefix));
130: PetscCall(PetscFree(obj->type_name));
132: if (clear_for_reuse) {
133: /* we will assume that obj->bops->view and destroy are safe to leave as-is */
135: /* reset quantities, in order of appearance in _p_PetscObject */
136: obj->id = PetscObjectNewId_Internal();
137: obj->refct = 1;
138: obj->tablevel = 0;
139: obj->state = 0;
140: /* don't deallocate, zero these out instead */
141: PetscCall(PetscFunctionListClear(obj->qlist));
142: PetscCall(PetscArrayzero(obj->fortran_func_pointers, obj->num_fortran_func_pointers));
143: PetscCall(PetscArrayzero(obj->fortrancallback[PETSC_FORTRAN_CALLBACK_CLASS], obj->num_fortrancallback[PETSC_FORTRAN_CALLBACK_CLASS]));
144: PetscCall(PetscArrayzero(obj->fortrancallback[PETSC_FORTRAN_CALLBACK_SUBTYPE], obj->num_fortrancallback[PETSC_FORTRAN_CALLBACK_SUBTYPE]));
145: obj->optionsprinted = PETSC_FALSE;
146: #if PetscDefined(HAVE_SAWS)
147: obj->amsmem = PETSC_FALSE;
148: obj->amspublishblock = PETSC_FALSE;
149: #endif
150: obj->options = NULL;
151: obj->donotPetscObjectPrintClassNamePrefixType = PETSC_FALSE;
152: } else {
153: PetscCall(PetscFunctionListDestroy(&obj->qlist));
154: PetscCall(PetscFree(obj->fortran_func_pointers));
155: PetscCall(PetscFree(obj->fortrancallback[PETSC_FORTRAN_CALLBACK_CLASS]));
156: PetscCall(PetscFree(obj->fortrancallback[PETSC_FORTRAN_CALLBACK_SUBTYPE]));
157: PetscCall(PetscCommDestroy(&obj->comm));
158: obj->classid = PETSCFREEDHEADER;
160: if (PetscDefined(USE_LOG) && PetscObjectsLog) {
161: /* Record object removal from list of all objects */
162: for (PetscInt i = 0; i < PetscObjectsMaxCounts; ++i) {
163: if (PetscObjects[i] == obj) {
164: PetscObjects[i] = NULL;
165: --PetscObjectsCounts;
166: break;
167: }
168: }
169: if (!PetscObjectsCounts) {
170: PetscCall(PetscFree(PetscObjects));
171: PetscObjectsMaxCounts = 0;
172: }
173: }
174: }
175: PetscFunctionReturn(PETSC_SUCCESS);
176: }
178: /*
179: PetscHeaderReset_Internal - "Reset" a PetscObject header. This is tantamount to destroying
180: the object but does not free all resources. The object retains its:
182: - classid
183: - bops->view
184: - bops->destroy
185: - comm
186: - tag
187: - class_name
188: - description
189: - mansec
190: - cpp
192: Note that while subclass information is lost, superclass info remains. Thus this function is
193: intended to be used to reuse a PetscObject within the same class to avoid reallocating its
194: resources.
195: */
196: PetscErrorCode PetscHeaderReset_Internal(PetscObject obj)
197: {
198: PetscFunctionBegin;
199: PetscCall(PetscHeaderDestroy_Private(obj, PETSC_TRUE));
200: PetscFunctionReturn(PETSC_SUCCESS);
201: }
203: /*@C
204: PetscObjectCopyFortranFunctionPointers - Copy function pointers to another object
206: Logically Collective
208: Input Parameters:
209: + src - source object
210: - dest - destination object
212: Level: developer
214: Note:
215: Both objects must have the same class.
217: This is used to help manage user callback functions that were provided in Fortran
219: .seealso: `PetscFortranCallbackRegister()`, `PetscFortranCallbackGetSizes()`
220: @*/
221: PetscErrorCode PetscObjectCopyFortranFunctionPointers(PetscObject src, PetscObject dest)
222: {
223: PetscFortranCallbackId cbtype, numcb[PETSC_FORTRAN_CALLBACK_MAXTYPE];
225: PetscFunctionBegin;
228: PetscCheck(src->classid == dest->classid, src->comm, PETSC_ERR_ARG_INCOMP, "Objects must be of the same class");
230: PetscCall(PetscFree(dest->fortran_func_pointers));
231: PetscCall(PetscMalloc(src->num_fortran_func_pointers * sizeof(void (*)(void)), &dest->fortran_func_pointers));
232: PetscCall(PetscMemcpy(dest->fortran_func_pointers, src->fortran_func_pointers, src->num_fortran_func_pointers * sizeof(void (*)(void))));
234: dest->num_fortran_func_pointers = src->num_fortran_func_pointers;
236: PetscCall(PetscFortranCallbackGetSizes(src->classid, &numcb[PETSC_FORTRAN_CALLBACK_CLASS], &numcb[PETSC_FORTRAN_CALLBACK_SUBTYPE]));
237: for (cbtype = PETSC_FORTRAN_CALLBACK_CLASS; cbtype < PETSC_FORTRAN_CALLBACK_MAXTYPE; cbtype++) {
238: PetscCall(PetscFree(dest->fortrancallback[cbtype]));
239: PetscCall(PetscCalloc1(numcb[cbtype], &dest->fortrancallback[cbtype]));
240: PetscCall(PetscMemcpy(dest->fortrancallback[cbtype], src->fortrancallback[cbtype], src->num_fortrancallback[cbtype] * sizeof(PetscFortranCallback)));
241: dest->num_fortrancallback[cbtype] = src->num_fortrancallback[cbtype];
242: }
243: PetscFunctionReturn(PETSC_SUCCESS);
244: }
246: /*@C
247: PetscObjectSetFortranCallback - set Fortran callback function pointer and context
249: Logically Collective
251: Input Parameters:
252: + obj - object on which to set callback
253: . cbtype - callback type (class or subtype)
254: . cid - address of callback Id, updated if not yet initialized (zero)
255: . func - Fortran function
256: - ctx - Fortran context
258: Level: developer
260: Note:
261: This is used to help manage user callback functions that were provided in Fortran
263: .seealso: `PetscObjectGetFortranCallback()`, `PetscFortranCallbackRegister()`, `PetscFortranCallbackGetSizes()`
264: @*/
265: PetscErrorCode PetscObjectSetFortranCallback(PetscObject obj, PetscFortranCallbackType cbtype, PetscFortranCallbackId *cid, void (*func)(void), void *ctx)
266: {
267: const char *subtype = NULL;
269: PetscFunctionBegin;
271: if (cbtype == PETSC_FORTRAN_CALLBACK_SUBTYPE) subtype = obj->type_name;
272: if (!*cid) PetscCall(PetscFortranCallbackRegister(obj->classid, subtype, cid));
273: if (*cid >= PETSC_SMALLEST_FORTRAN_CALLBACK + obj->num_fortrancallback[cbtype]) {
274: PetscFortranCallbackId oldnum = obj->num_fortrancallback[cbtype];
275: PetscFortranCallbackId newnum = PetscMax(*cid - PETSC_SMALLEST_FORTRAN_CALLBACK + 1, 2 * oldnum);
276: PetscFortranCallback *callback;
277: PetscCall(PetscMalloc1(newnum, &callback));
278: PetscCall(PetscMemcpy(callback, obj->fortrancallback[cbtype], oldnum * sizeof(*obj->fortrancallback[cbtype])));
279: PetscCall(PetscFree(obj->fortrancallback[cbtype]));
281: obj->fortrancallback[cbtype] = callback;
282: obj->num_fortrancallback[cbtype] = newnum;
283: }
284: obj->fortrancallback[cbtype][*cid - PETSC_SMALLEST_FORTRAN_CALLBACK].func = func;
285: obj->fortrancallback[cbtype][*cid - PETSC_SMALLEST_FORTRAN_CALLBACK].ctx = ctx;
286: PetscFunctionReturn(PETSC_SUCCESS);
287: }
289: /*@C
290: PetscObjectGetFortranCallback - get Fortran callback function pointer and context
292: Logically Collective
294: Input Parameters:
295: + obj - object on which to get callback
296: . cbtype - callback type
297: - cid - address of callback Id
299: Output Parameters:
300: + func - Fortran function (or `NULL` if not needed)
301: - ctx - Fortran context (or `NULL` if not needed)
303: Level: developer
305: Note:
306: This is used to help manage user callback functions that were provided in Fortran
308: .seealso: `PetscObjectSetFortranCallback()`, `PetscFortranCallbackRegister()`, `PetscFortranCallbackGetSizes()`
309: @*/
310: PetscErrorCode PetscObjectGetFortranCallback(PetscObject obj, PetscFortranCallbackType cbtype, PetscFortranCallbackId cid, void (**func)(void), void **ctx)
311: {
312: PetscFortranCallback *cb;
314: PetscFunctionBegin;
316: PetscCheck(cid >= PETSC_SMALLEST_FORTRAN_CALLBACK, obj->comm, PETSC_ERR_ARG_CORRUPT, "Fortran callback Id invalid");
317: PetscCheck(cid < PETSC_SMALLEST_FORTRAN_CALLBACK + obj->num_fortrancallback[cbtype], obj->comm, PETSC_ERR_ARG_CORRUPT, "Fortran callback not set on this object");
318: cb = &obj->fortrancallback[cbtype][cid - PETSC_SMALLEST_FORTRAN_CALLBACK];
319: if (func) *func = cb->func;
320: if (ctx) *ctx = cb->ctx;
321: PetscFunctionReturn(PETSC_SUCCESS);
322: }
324: #if defined(PETSC_USE_LOG)
325: /*@C
326: PetscObjectsDump - Prints all the currently existing objects.
328: Input Parameters:
329: + fd - file pointer
330: - all - by default only tries to display objects created explicitly by the user, if all is `PETSC_TRUE` then lists all outstanding objects
332: Options Database Key:
333: . -objects_dump <all> - print information about all the objects that exist at the end of the programs run
335: Level: advanced
337: Note:
338: Only MPI rank 0 of `PETSC_COMM_WORLD` prints the values
340: .seealso: `PetscObject`
341: @*/
342: PetscErrorCode PetscObjectsDump(FILE *fd, PetscBool all)
343: {
344: PetscInt i, j, k = 0;
345: PetscObject h;
347: PetscFunctionBegin;
348: if (PetscObjectsCounts) {
349: PetscCall(PetscFPrintf(PETSC_COMM_WORLD, fd, "The following objects were never freed\n"));
350: PetscCall(PetscFPrintf(PETSC_COMM_WORLD, fd, "-----------------------------------------\n"));
351: for (i = 0; i < PetscObjectsMaxCounts; i++) {
352: if ((h = PetscObjects[i])) {
353: PetscCall(PetscObjectName(h));
354: {
355: PetscStack *stack = NULL;
356: char *create = NULL, *rclass = NULL;
358: /* if the PETSc function the user calls is not a create then this object was NOT directly created by them */
359: PetscCall(PetscMallocGetStack(h, &stack));
360: if (stack) {
361: k = stack->currentsize - 2;
362: if (!all) {
363: k = 0;
364: while (!stack->petscroutine[k]) k++;
365: PetscCall(PetscStrstr(stack->function[k], "Create", &create));
366: if (!create) PetscCall(PetscStrstr(stack->function[k], "Get", &create));
367: PetscCall(PetscStrstr(stack->function[k], h->class_name, &rclass));
368: if (!create) continue;
369: if (!rclass) continue;
370: }
371: }
373: PetscCall(PetscFPrintf(PETSC_COMM_WORLD, fd, "[%d] %s %s %s\n", PetscGlobalRank, h->class_name, h->type_name, h->name));
375: PetscCall(PetscMallocGetStack(h, &stack));
376: if (stack) {
377: for (j = k; j >= 0; j--) fprintf(fd, " [%d] %s() in %s\n", PetscGlobalRank, stack->function[j], stack->file[j]);
378: }
379: }
380: }
381: }
382: }
383: PetscFunctionReturn(PETSC_SUCCESS);
384: }
386: /*@C
387: PetscObjectsView - Prints the currently existing objects.
389: Logically Collective
391: Input Parameter:
392: . viewer - must be an `PETSCVIEWERASCII` viewer
394: Level: advanced
396: .seealso: `PetscObject`
397: @*/
398: PetscErrorCode PetscObjectsView(PetscViewer viewer)
399: {
400: PetscBool isascii;
401: FILE *fd;
403: PetscFunctionBegin;
404: if (!viewer) viewer = PETSC_VIEWER_STDOUT_WORLD;
405: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
406: PetscCheck(isascii, PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Only supports ASCII viewer");
407: PetscCall(PetscViewerASCIIGetPointer(viewer, &fd));
408: PetscCall(PetscObjectsDump(fd, PETSC_TRUE));
409: PetscFunctionReturn(PETSC_SUCCESS);
410: }
412: /*@C
413: PetscObjectsGetObject - Get a pointer to a named object
415: Not Collective
417: Input Parameter:
418: . name - the name of an object
420: Output Parameters:
421: + obj - the object or `NULL` if there is no object, optional, pass in `NULL` if not needed
422: - classname - the name of the class of the object, optional, pass in `NULL` if not needed
424: Level: advanced
426: .seealso: `PetscObject`
427: @*/
428: PetscErrorCode PetscObjectsGetObject(const char *name, PetscObject *obj, char **classname)
429: {
430: PetscInt i;
431: PetscObject h;
432: PetscBool flg;
434: PetscFunctionBegin;
435: PetscAssertPointer(name, 1);
436: if (obj) *obj = NULL;
437: for (i = 0; i < PetscObjectsMaxCounts; i++) {
438: if ((h = PetscObjects[i])) {
439: PetscCall(PetscObjectName(h));
440: PetscCall(PetscStrcmp(h->name, name, &flg));
441: if (flg) {
442: if (obj) *obj = h;
443: if (classname) *classname = h->class_name;
444: PetscFunctionReturn(PETSC_SUCCESS);
445: }
446: }
447: }
448: PetscFunctionReturn(PETSC_SUCCESS);
449: }
450: #endif
452: /*@
453: PetscObjectSetPrintedOptions - indicate to an object that it should behave as if it has already printed the help for its options so it will not display the help message
455: Input Parameter:
456: . obj - the `PetscObject`
458: Level: developer
460: Developer Notes:
461: This is used, for example to prevent sequential objects that are created from a parallel object; such as the `KSP` created by
462: `PCBJACOBI` from all printing the same help messages to the screen
464: .seealso: `PetscOptionsInsert()`, `PetscObject`
465: @*/
466: PetscErrorCode PetscObjectSetPrintedOptions(PetscObject obj)
467: {
468: PetscFunctionBegin;
469: PetscAssertPointer(obj, 1);
470: obj->optionsprinted = PETSC_TRUE;
471: PetscFunctionReturn(PETSC_SUCCESS);
472: }
474: /*@
475: PetscObjectInheritPrintedOptions - If the child object is not on the MPI rank 0 process of the parent object and the child is sequential then the child gets it set.
477: Input Parameters:
478: + pobj - the parent object
479: - obj - the `PetscObject`
481: Level: developer
483: Developer Notes:
484: This is used, for example to prevent sequential objects that are created from a parallel object; such as the `KSP` created by
485: `PCBJACOBI` from all printing the same help messages to the screen
487: This will not handle more complicated situations like with `PCGASM` where children may live on any subset of the parent's processes and overlap
489: .seealso: `PetscOptionsInsert()`, `PetscObjectSetPrintedOptions()`, `PetscObject`
490: @*/
491: PetscErrorCode PetscObjectInheritPrintedOptions(PetscObject pobj, PetscObject obj)
492: {
493: PetscMPIInt prank, size;
495: PetscFunctionBegin;
498: PetscCallMPI(MPI_Comm_rank(pobj->comm, &prank));
499: PetscCallMPI(MPI_Comm_size(obj->comm, &size));
500: if (size == 1 && prank > 0) obj->optionsprinted = PETSC_TRUE;
501: PetscFunctionReturn(PETSC_SUCCESS);
502: }
504: /*@C
505: PetscObjectAddOptionsHandler - Adds an additional function to check for options when `XXXSetFromOptions()` is called.
507: Not Collective
509: Input Parameters:
510: + obj - the PETSc object
511: . handle - function that checks for options
512: . destroy - function to destroy `ctx` if provided
513: - ctx - optional context for check function
515: Calling sequence of `handle`:
516: + obj - the PETSc object
517: . PetscOptionsObject - the `PetscOptionItems` object
518: - ctx - optional context for `handle`
520: Calling sequence of `destroy`:
521: + obj - the PETSc object
522: - ctx - optional context for `handle`
524: Level: developer
526: .seealso: `KSPSetFromOptions()`, `PCSetFromOptions()`, `SNESSetFromOptions()`, `PetscObjectProcessOptionsHandlers()`, `PetscObjectDestroyOptionsHandlers()`,
527: `PetscObject`
528: @*/
529: PetscErrorCode PetscObjectAddOptionsHandler(PetscObject obj, PetscErrorCode (*handle)(PetscObject obj, PetscOptionItems *PetscOptionsObject, void *ctx), PetscErrorCode (*destroy)(PetscObject obj, void *ctx), void *ctx)
530: {
531: PetscFunctionBegin;
533: PetscCheck(obj->noptionhandler < PETSC_MAX_OPTIONS_HANDLER, obj->comm, PETSC_ERR_ARG_OUTOFRANGE, "To many options handlers added");
534: obj->optionhandler[obj->noptionhandler] = handle;
535: obj->optiondestroy[obj->noptionhandler] = destroy;
536: obj->optionctx[obj->noptionhandler++] = ctx;
537: PetscFunctionReturn(PETSC_SUCCESS);
538: }
540: /*@C
541: PetscObjectProcessOptionsHandlers - Calls all the options handlers attached to an object
543: Not Collective
545: Input Parameters:
546: + obj - the PETSc object
547: - PetscOptionsObject - the options context
549: Level: developer
551: .seealso: `KSPSetFromOptions()`, `PCSetFromOptions()`, `SNESSetFromOptions()`, `PetscObjectAddOptionsHandler()`, `PetscObjectDestroyOptionsHandlers()`,
552: `PetscObject`
553: @*/
554: PetscErrorCode PetscObjectProcessOptionsHandlers(PetscObject obj, PetscOptionItems *PetscOptionsObject)
555: {
556: PetscFunctionBegin;
558: for (PetscInt i = 0; i < obj->noptionhandler; i++) PetscCall((*obj->optionhandler[i])(obj, PetscOptionsObject, obj->optionctx[i]));
559: PetscFunctionReturn(PETSC_SUCCESS);
560: }
562: /*@C
563: PetscObjectDestroyOptionsHandlers - Destroys all the option handlers attached to an object
565: Not Collective
567: Input Parameter:
568: . obj - the PETSc object
570: Level: developer
572: .seealso: `KSPSetFromOptions()`, `PCSetFromOptions()`, `SNESSetFromOptions()`, `PetscObjectAddOptionsHandler()`, `PetscObjectProcessOptionsHandlers()`,
573: `PetscObject`
574: @*/
575: PetscErrorCode PetscObjectDestroyOptionsHandlers(PetscObject obj)
576: {
577: PetscFunctionBegin;
579: for (PetscInt i = 0; i < obj->noptionhandler; i++) {
580: if (obj->optiondestroy[i]) PetscCall((*obj->optiondestroy[i])(obj, obj->optionctx[i]));
581: }
582: obj->noptionhandler = 0;
583: PetscFunctionReturn(PETSC_SUCCESS);
584: }
586: /*@C
587: PetscObjectReference - Indicates to a `PetscObject` that it is being
588: referenced by another `PetscObject`. This increases the reference
589: count for that object by one.
591: Logically Collective
593: Input Parameter:
594: . obj - the PETSc object. This must be cast with (`PetscObject`), for example,
595: `PetscObjectReference`((`PetscObject`)mat);
597: Level: advanced
599: .seealso: `PetscObjectCompose()`, `PetscObjectDereference()`, `PetscObject`
600: @*/
601: PetscErrorCode PetscObjectReference(PetscObject obj)
602: {
603: PetscFunctionBegin;
604: if (!obj) PetscFunctionReturn(PETSC_SUCCESS);
606: obj->refct++;
607: PetscFunctionReturn(PETSC_SUCCESS);
608: }
610: /*@C
611: PetscObjectGetReference - Gets the current reference count for a PETSc object.
613: Not Collective
615: Input Parameter:
616: . obj - the PETSc object; this must be cast with (`PetscObject`), for example,
617: `PetscObjectGetReference`((`PetscObject`)mat,&cnt);
619: Output Parameter:
620: . cnt - the reference count
622: Level: advanced
624: .seealso: `PetscObjectCompose()`, `PetscObjectDereference()`, `PetscObjectReference()`, `PetscObject`
625: @*/
626: PetscErrorCode PetscObjectGetReference(PetscObject obj, PetscInt *cnt)
627: {
628: PetscFunctionBegin;
630: PetscAssertPointer(cnt, 2);
631: *cnt = obj->refct;
632: PetscFunctionReturn(PETSC_SUCCESS);
633: }
635: /*@C
636: PetscObjectDereference - Indicates to any `PetscObject` that it is being
637: referenced by one less `PetscObject`. This decreases the reference
638: count for that object by one.
640: Collective on `obj` if reference reaches 0 otherwise Logically Collective
642: Input Parameter:
643: . obj - the PETSc object; this must be cast with (`PetscObject`), for example,
644: `PetscObjectDereference`((`PetscObject`)mat);
646: Level: advanced
648: Note:
649: `PetscObjectDestroy()` sets the `obj` pointer to `NULL` after the call, this routine does not.
651: .seealso: `PetscObjectCompose()`, `PetscObjectReference()`, `PetscObjectDestroy()`, `PetscObject`
652: @*/
653: PetscErrorCode PetscObjectDereference(PetscObject obj)
654: {
655: PetscFunctionBegin;
656: if (!obj) PetscFunctionReturn(PETSC_SUCCESS);
658: if (obj->bops->destroy) PetscCall((*obj->bops->destroy)(&obj));
659: else PetscCheck(--(obj->refct), PETSC_COMM_SELF, PETSC_ERR_SUP, "This PETSc object does not have a generic destroy routine");
660: PetscFunctionReturn(PETSC_SUCCESS);
661: }
663: /*
664: The following routines are the versions private to the PETSc object
665: data structures.
666: */
667: PetscErrorCode PetscObjectRemoveReference(PetscObject obj, const char name[])
668: {
669: PetscFunctionBegin;
671: PetscCall(PetscObjectListRemoveReference(&obj->olist, name));
672: PetscFunctionReturn(PETSC_SUCCESS);
673: }
675: /*@C
676: PetscObjectCompose - Associates another PETSc object with a given PETSc object.
678: Not Collective
680: Input Parameters:
681: + obj - the PETSc object; this must be cast with (`PetscObject`), for example,
682: `PetscObjectCompose`((`PetscObject`)mat,...);
683: . name - name associated with the child object
684: - ptr - the other PETSc object to associate with the PETSc object; this must also be
685: cast with (`PetscObject`)
687: Level: advanced
689: Notes:
690: The second objects reference count is automatically increased by one when it is
691: composed.
693: Replaces any previous object that had been composed with the same name.
695: If `ptr` is `NULL` and `name` has previously been composed using an object, then that
696: entry is removed from `obj`.
698: `PetscObjectCompose()` can be used with any PETSc object (such as
699: `Mat`, `Vec`, `KSP`, `SNES`, etc.) or any user-provided object.
701: `PetscContainerCreate()` can be used to create an object from a
702: user-provided pointer that may then be composed with PETSc objects using `PetscObjectCompose()`
704: .seealso: `PetscObjectQuery()`, `PetscContainerCreate()`, `PetscObjectComposeFunction()`, `PetscObjectQueryFunction()`, `PetscContainer`,
705: `PetscContainerSetPointer()`, `PetscObject`
706: @*/
707: PetscErrorCode PetscObjectCompose(PetscObject obj, const char name[], PetscObject ptr)
708: {
709: PetscFunctionBegin;
711: PetscAssertPointer(name, 2);
713: PetscCheck(obj != ptr, PetscObjectComm((PetscObject)obj), PETSC_ERR_SUP, "Cannot compose object with itself");
714: if (ptr) {
715: char *tname;
716: PetscBool skipreference;
718: PetscCall(PetscObjectListReverseFind(ptr->olist, obj, &tname, &skipreference));
719: if (tname) PetscCheck(skipreference, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "An object cannot be composed with an object that was composed with it");
720: }
721: PetscCall(PetscObjectListAdd(&obj->olist, name, ptr));
722: PetscFunctionReturn(PETSC_SUCCESS);
723: }
725: /*@C
726: PetscObjectQuery - Gets a PETSc object associated with a given object that was composed with `PetscObjectCompose()`
728: Not Collective
730: Input Parameters:
731: + obj - the PETSc object. It must be cast with a (`PetscObject`), for example,
732: `PetscObjectCompose`((`PetscObject`)mat,...);
733: . name - name associated with child object
734: - ptr - the other PETSc object associated with the PETSc object, this must be
735: cast with (`PetscObject`*)
737: Level: advanced
739: Note:
740: The reference count of neither object is increased in this call
742: .seealso: `PetscObjectCompose()`, `PetscObjectComposeFunction()`, `PetscObjectQueryFunction()`, `PetscContainer`
743: `PetscContainerGetPointer()`, `PetscObject`
744: @*/
745: PetscErrorCode PetscObjectQuery(PetscObject obj, const char name[], PetscObject *ptr)
746: {
747: PetscFunctionBegin;
749: PetscAssertPointer(name, 2);
750: PetscAssertPointer(ptr, 3);
751: PetscCall(PetscObjectListFind(obj->olist, name, ptr));
752: PetscFunctionReturn(PETSC_SUCCESS);
753: }
755: /*MC
756: PetscObjectComposeFunction - Associates a function with a given PETSc object.
758: Synopsis:
759: #include <petscsys.h>
760: PetscErrorCode PetscObjectComposeFunction(PetscObject obj, const char name[], void (*fptr)(void))
762: Logically Collective
764: Input Parameters:
765: + obj - the PETSc object; this must be cast with a (`PetscObject`), for example,
766: `PetscObjectCompose`((`PetscObject`)mat,...);
767: . name - name associated with the child function
768: - fptr - function pointer
770: Level: advanced
772: Notes:
773: When the first argument of `fptr` is (or is derived from) a `PetscObject` then `PetscTryMethod()` and `PetscUseMethod()`
774: can be used to call the function directly with error checking.
776: To remove a registered routine, pass in `NULL` for `fptr`.
778: `PetscObjectComposeFunction()` can be used with any PETSc object (such as
779: `Mat`, `Vec`, `KSP`, `SNES`, etc.) or any user-provided object.
781: `PetscUseTypeMethod()` and `PetscTryTypeMethod()` are used to call a function that is stored in the objects `obj->ops` table.
783: .seealso: `PetscObjectQueryFunction()`, `PetscContainerCreate()` `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscTryMethod()`, `PetscUseMethod()`,
784: `PetscUseTypeMethod()`, `PetscTryTypeMethod()`, `PetscObject`
785: M*/
786: PetscErrorCode PetscObjectComposeFunction_Private(PetscObject obj, const char name[], void (*fptr)(void))
787: {
788: PetscFunctionBegin;
790: PetscAssertPointer(name, 2);
791: PetscCall(PetscFunctionListAdd(&obj->qlist, name, fptr));
792: PetscFunctionReturn(PETSC_SUCCESS);
793: }
795: /*MC
796: PetscObjectQueryFunction - Gets a function associated with a given object.
798: Synopsis:
799: #include <petscsys.h>
800: PetscErrorCode PetscObjectQueryFunction(PetscObject obj, const char name[], void (**fptr)(void))
802: Logically Collective
804: Input Parameters:
805: + obj - the PETSc object; this must be cast with (`PetscObject`), for example,
806: `PetscObjectQueryFunction`((`PetscObject`)ksp,...);
807: - name - name associated with the child function
809: Output Parameter:
810: . fptr - function pointer
812: Level: advanced
814: .seealso: `PetscObjectComposeFunction()`, `PetscFunctionListFind()`, `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObject`
815: M*/
816: PETSC_EXTERN PetscErrorCode PetscObjectQueryFunction_Private(PetscObject obj, const char name[], void (**fptr)(void))
817: {
818: PetscFunctionBegin;
820: PetscAssertPointer(name, 2);
821: PetscCall(PetscFunctionListFind(obj->qlist, name, fptr));
822: PetscFunctionReturn(PETSC_SUCCESS);
823: }
825: struct _p_PetscContainer {
826: PETSCHEADER(int);
827: void *ptr;
828: PetscErrorCode (*userdestroy)(void *);
829: };
831: /*@C
832: PetscContainerUserDestroyDefault - Default destroy routine for user-provided data that simply calls `PetscFree()` in the data
833: provided with `PetscContainerSetPointer()`
835: Logically Collective on the `PetscContainer` containing the user data
837: Input Parameter:
838: . ctx - pointer to user-provided data
840: Level: advanced
842: .seealso: `PetscContainerDestroy()`, `PetscContainerSetUserDestroy()`, `PetscObject`
843: @*/
844: PetscErrorCode PetscContainerUserDestroyDefault(void *ctx)
845: {
846: PetscFunctionBegin;
847: PetscCall(PetscFree(ctx));
848: PetscFunctionReturn(PETSC_SUCCESS);
849: }
851: /*@C
852: PetscContainerGetPointer - Gets the pointer value contained in the container that was provided with `PetscContainerSetPointer()`
854: Not Collective
856: Input Parameter:
857: . obj - the object created with `PetscContainerCreate()`
859: Output Parameter:
860: . ptr - the pointer value
862: Level: advanced
864: .seealso: `PetscContainerCreate()`, `PetscContainerDestroy()`, `PetscObject`,
865: `PetscContainerSetPointer()`
866: @*/
867: PetscErrorCode PetscContainerGetPointer(PetscContainer obj, void **ptr)
868: {
869: PetscFunctionBegin;
871: PetscAssertPointer(ptr, 2);
872: *ptr = obj->ptr;
873: PetscFunctionReturn(PETSC_SUCCESS);
874: }
876: /*@C
877: PetscContainerSetPointer - Sets the pointer value contained in the container.
879: Logically Collective
881: Input Parameters:
882: + obj - the object created with `PetscContainerCreate()`
883: - ptr - the pointer value
885: Level: advanced
887: .seealso: `PetscContainerCreate()`, `PetscContainerDestroy()`, `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObject`,
888: `PetscContainerGetPointer()`
889: @*/
890: PetscErrorCode PetscContainerSetPointer(PetscContainer obj, void *ptr)
891: {
892: PetscFunctionBegin;
894: if (ptr) PetscAssertPointer(ptr, 2);
895: obj->ptr = ptr;
896: PetscFunctionReturn(PETSC_SUCCESS);
897: }
899: /*@C
900: PetscContainerDestroy - Destroys a PETSc container object.
902: Collective
904: Input Parameter:
905: . obj - an object that was created with `PetscContainerCreate()`
907: Level: advanced
909: Note:
910: If `PetscContainerSetUserDestroy()` was used to provide a user destroy object for the data provided with `PetscContainerSetPointer()`
911: then that function is called to destroy the data.
913: .seealso: `PetscContainerCreate()`, `PetscContainerSetUserDestroy()`, `PetscObject`
914: @*/
915: PetscErrorCode PetscContainerDestroy(PetscContainer *obj)
916: {
917: PetscFunctionBegin;
918: if (!*obj) PetscFunctionReturn(PETSC_SUCCESS);
920: if (--((PetscObject)(*obj))->refct > 0) {
921: *obj = NULL;
922: PetscFunctionReturn(PETSC_SUCCESS);
923: }
924: if ((*obj)->userdestroy) PetscCall((*(*obj)->userdestroy)((*obj)->ptr));
925: PetscCall(PetscHeaderDestroy(obj));
926: PetscFunctionReturn(PETSC_SUCCESS);
927: }
929: /*@C
930: PetscContainerSetUserDestroy - Sets name of the user destroy function for the data provided to the `PetscContainer` with `PetscContainerSetPointer()`
932: Logically Collective
934: Input Parameters:
935: + obj - an object that was created with `PetscContainerCreate()`
936: - des - name of the user destroy function
938: Level: advanced
940: Note:
941: Use `PetscContainerUserDestroyDefault()` if the memory was obtained by calling `PetscMalloc()` or one of its variants for single memory allocation.
943: .seealso: `PetscContainerDestroy()`, `PetscContainerUserDestroyDefault()`, `PetscMalloc()`, `PetscMalloc1()`, `PetscCalloc()`, `PetscCalloc1()`, `PetscObject`
944: @*/
945: PetscErrorCode PetscContainerSetUserDestroy(PetscContainer obj, PetscErrorCode (*des)(void *))
946: {
947: PetscFunctionBegin;
949: obj->userdestroy = des;
950: PetscFunctionReturn(PETSC_SUCCESS);
951: }
953: PetscClassId PETSC_CONTAINER_CLASSID;
955: /*@C
956: PetscContainerCreate - Creates a PETSc object that has room to hold a single pointer.
958: Collective
960: Input Parameter:
961: . comm - MPI communicator that shares the object
963: Output Parameter:
964: . container - the container created
966: Level: advanced
968: Notes:
969: This allows one to attach any type of data (accessible through a pointer) with the
970: `PetscObjectCompose()` function to a `PetscObject`. The data item itself is attached by a
971: call to `PetscContainerSetPointer()`.
973: .seealso: `PetscContainerDestroy()`, `PetscContainerSetPointer()`, `PetscContainerGetPointer()`, `PetscObjectCompose()`, `PetscObjectQuery()`,
974: `PetscContainerSetUserDestroy()`, `PetscObject`
975: @*/
976: PetscErrorCode PetscContainerCreate(MPI_Comm comm, PetscContainer *container)
977: {
978: PetscFunctionBegin;
979: PetscAssertPointer(container, 2);
980: PetscCall(PetscSysInitializePackage());
981: PetscCall(PetscHeaderCreate(*container, PETSC_CONTAINER_CLASSID, "PetscContainer", "Container", "Sys", comm, PetscContainerDestroy, NULL));
982: PetscFunctionReturn(PETSC_SUCCESS);
983: }
985: /*@
986: PetscObjectSetFromOptions - Sets generic parameters from user options.
988: Collective
990: Input Parameter:
991: . obj - the `PetscObject`
993: Level: beginner
995: Note:
996: We have no generic options at present, so this does nothing
998: .seealso: `PetscObjectSetOptionsPrefix()`, `PetscObjectGetOptionsPrefix()`, `PetscObject`
999: @*/
1000: PetscErrorCode PetscObjectSetFromOptions(PetscObject obj)
1001: {
1002: PetscFunctionBegin;
1004: PetscFunctionReturn(PETSC_SUCCESS);
1005: }
1007: /*@
1008: PetscObjectSetUp - Sets up the internal data structures for later use of the object
1010: Collective
1012: Input Parameter:
1013: . obj - the `PetscObject`
1015: Level: advanced
1017: Note:
1018: This does nothing at present.
1020: .seealso: `PetscObjectDestroy()`, `PetscObject`
1021: @*/
1022: PetscErrorCode PetscObjectSetUp(PetscObject obj)
1023: {
1024: PetscFunctionBegin;
1026: PetscFunctionReturn(PETSC_SUCCESS);
1027: }