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: }