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: Input Parameters:
330: + fd - file pointer
331: - all - by default only tries to display objects created explicitly by the user, if all is `PETSC_TRUE` then lists all outstanding objects
333: Options Database Key:
334: . -objects_dump <all> - print information about all the objects that exist at the end of the programs run
336: Level: advanced
338: Note:
339: Only MPI rank 0 of `PETSC_COMM_WORLD` prints the values
341: .seealso: `PetscObject`
342: @*/
343: PetscErrorCode PetscObjectsDump(FILE *fd, PetscBool all)
344: {
345: PetscInt i, j, k = 0;
346: PetscObject h;
348: PetscFunctionBegin;
349: if (PetscObjectsCounts) {
350: PetscCall(PetscFPrintf(PETSC_COMM_WORLD, fd, "The following objects were never freed\n"));
351: PetscCall(PetscFPrintf(PETSC_COMM_WORLD, fd, "-----------------------------------------\n"));
352: for (i = 0; i < PetscObjectsMaxCounts; i++) {
353: if ((h = PetscObjects[i])) {
354: PetscCall(PetscObjectName(h));
355: {
356: PetscStack *stack = NULL;
357: char *create = NULL, *rclass = NULL;
359: /* if the PETSc function the user calls is not a create then this object was NOT directly created by them */
360: PetscCall(PetscMallocGetStack(h, &stack));
361: if (stack) {
362: k = stack->currentsize - 2;
363: if (!all) {
364: k = 0;
365: while (!stack->petscroutine[k]) k++;
366: PetscCall(PetscStrstr(stack->function[k], "Create", &create));
367: if (!create) PetscCall(PetscStrstr(stack->function[k], "Get", &create));
368: PetscCall(PetscStrstr(stack->function[k], h->class_name, &rclass));
369: if (!create) continue;
370: if (!rclass) continue;
371: }
372: }
374: PetscCall(PetscFPrintf(PETSC_COMM_WORLD, fd, "[%d] %s %s %s\n", PetscGlobalRank, h->class_name, h->type_name, h->name));
376: PetscCall(PetscMallocGetStack(h, &stack));
377: if (stack) {
378: for (j = k; j >= 0; j--) fprintf(fd, " [%d] %s() in %s\n", PetscGlobalRank, stack->function[j], stack->file[j]);
379: }
380: }
381: }
382: }
383: }
384: PetscFunctionReturn(PETSC_SUCCESS);
385: }
387: /*@C
388: PetscObjectsView - Prints the currently existing objects.
390: Logically Collective
392: Input Parameter:
393: . viewer - must be an `PETSCVIEWERASCII` viewer
395: Level: advanced
397: .seealso: `PetscObject`
398: @*/
399: PetscErrorCode PetscObjectsView(PetscViewer viewer)
400: {
401: PetscBool isascii;
402: FILE *fd;
404: PetscFunctionBegin;
405: if (!viewer) viewer = PETSC_VIEWER_STDOUT_WORLD;
406: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
407: PetscCheck(isascii, PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Only supports ASCII viewer");
408: PetscCall(PetscViewerASCIIGetPointer(viewer, &fd));
409: PetscCall(PetscObjectsDump(fd, PETSC_TRUE));
410: PetscFunctionReturn(PETSC_SUCCESS);
411: }
413: /*@C
414: PetscObjectsGetObject - Get a pointer to a named object
416: Not Collective
418: Input Parameter:
419: . name - the name of an object
421: Output Parameters:
422: + obj - the object or `NULL` if there is no object, optional, pass in `NULL` if not needed
423: - classname - the name of the class of the object, optional, pass in `NULL` if not needed
425: Level: advanced
427: .seealso: `PetscObject`
428: @*/
429: PetscErrorCode PetscObjectsGetObject(const char *name, PetscObject *obj, char **classname)
430: {
431: PetscInt i;
432: PetscObject h;
433: PetscBool flg;
435: PetscFunctionBegin;
436: PetscAssertPointer(name, 1);
437: if (obj) *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: if (obj) *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 MPI 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 `ctx` if provided
514: - ctx - optional context for check function
516: Calling sequence of `handle`:
517: + obj - the PETSc object
518: . PetscOptionsObject - the `PetscOptionItems` object
519: - ctx - optional context for `handle`
521: Calling sequence of `destroy`:
522: + obj - the PETSc object
523: - ctx - optional context for `handle`
525: Level: developer
527: .seealso: `KSPSetFromOptions()`, `PCSetFromOptions()`, `SNESSetFromOptions()`, `PetscObjectProcessOptionsHandlers()`, `PetscObjectDestroyOptionsHandlers()`,
528: `PetscObject`
529: @*/
530: PetscErrorCode PetscObjectAddOptionsHandler(PetscObject obj, PetscErrorCode (*handle)(PetscObject obj, PetscOptionItems *PetscOptionsObject, void *ctx), PetscErrorCode (*destroy)(PetscObject obj, void *ctx), void *ctx)
531: {
532: PetscFunctionBegin;
534: PetscCheck(obj->noptionhandler < PETSC_MAX_OPTIONS_HANDLER, obj->comm, PETSC_ERR_ARG_OUTOFRANGE, "To many options handlers added");
535: obj->optionhandler[obj->noptionhandler] = handle;
536: obj->optiondestroy[obj->noptionhandler] = destroy;
537: obj->optionctx[obj->noptionhandler++] = ctx;
538: PetscFunctionReturn(PETSC_SUCCESS);
539: }
541: /*@C
542: PetscObjectProcessOptionsHandlers - Calls all the options handlers attached to an object
544: Not Collective
546: Input Parameters:
547: + obj - the PETSc object
548: - PetscOptionsObject - the options context
550: Level: developer
552: .seealso: `KSPSetFromOptions()`, `PCSetFromOptions()`, `SNESSetFromOptions()`, `PetscObjectAddOptionsHandler()`, `PetscObjectDestroyOptionsHandlers()`,
553: `PetscObject`
554: @*/
555: PetscErrorCode PetscObjectProcessOptionsHandlers(PetscObject obj, PetscOptionItems *PetscOptionsObject)
556: {
557: PetscFunctionBegin;
559: for (PetscInt i = 0; i < obj->noptionhandler; i++) PetscCall((*obj->optionhandler[i])(obj, PetscOptionsObject, obj->optionctx[i]));
560: PetscFunctionReturn(PETSC_SUCCESS);
561: }
563: /*@C
564: PetscObjectDestroyOptionsHandlers - Destroys all the option handlers attached to an object
566: Not Collective
568: Input Parameter:
569: . obj - the PETSc object
571: Level: developer
573: .seealso: `KSPSetFromOptions()`, `PCSetFromOptions()`, `SNESSetFromOptions()`, `PetscObjectAddOptionsHandler()`, `PetscObjectProcessOptionsHandlers()`,
574: `PetscObject`
575: @*/
576: PetscErrorCode PetscObjectDestroyOptionsHandlers(PetscObject obj)
577: {
578: PetscFunctionBegin;
580: for (PetscInt i = 0; i < obj->noptionhandler; i++) {
581: if (obj->optiondestroy[i]) PetscCall((*obj->optiondestroy[i])(obj, obj->optionctx[i]));
582: }
583: obj->noptionhandler = 0;
584: PetscFunctionReturn(PETSC_SUCCESS);
585: }
587: /*@C
588: PetscObjectReference - Indicates to a `PetscObject` that it is being
589: referenced by another `PetscObject`. This increases the reference
590: count for that object by one.
592: Logically Collective
594: Input Parameter:
595: . obj - the PETSc object. This must be cast with (`PetscObject`), for example,
596: `PetscObjectReference`((`PetscObject`)mat);
598: Level: advanced
600: .seealso: `PetscObjectCompose()`, `PetscObjectDereference()`, `PetscObject`
601: @*/
602: PetscErrorCode PetscObjectReference(PetscObject obj)
603: {
604: PetscFunctionBegin;
605: if (!obj) PetscFunctionReturn(PETSC_SUCCESS);
607: obj->refct++;
608: PetscFunctionReturn(PETSC_SUCCESS);
609: }
611: /*@C
612: PetscObjectGetReference - Gets the current reference count for a PETSc object.
614: Not Collective
616: Input Parameter:
617: . obj - the PETSc object; this must be cast with (`PetscObject`), for example,
618: `PetscObjectGetReference`((`PetscObject`)mat,&cnt);
620: Output Parameter:
621: . cnt - the reference count
623: Level: advanced
625: .seealso: `PetscObjectCompose()`, `PetscObjectDereference()`, `PetscObjectReference()`, `PetscObject`
626: @*/
627: PetscErrorCode PetscObjectGetReference(PetscObject obj, PetscInt *cnt)
628: {
629: PetscFunctionBegin;
631: PetscAssertPointer(cnt, 2);
632: *cnt = obj->refct;
633: PetscFunctionReturn(PETSC_SUCCESS);
634: }
636: /*@C
637: PetscObjectDereference - Indicates to any `PetscObject` that it is being
638: referenced by one less `PetscObject`. This decreases the reference
639: count for that object by one.
641: Collective on `obj` if reference reaches 0 otherwise Logically Collective
643: Input Parameter:
644: . obj - the PETSc object; this must be cast with (`PetscObject`), for example,
645: `PetscObjectDereference`((`PetscObject`)mat);
647: Level: advanced
649: Note:
650: `PetscObjectDestroy()` sets the `obj` pointer to `NULL` after the call, this routine does not.
652: .seealso: `PetscObjectCompose()`, `PetscObjectReference()`, `PetscObjectDestroy()`, `PetscObject`
653: @*/
654: PetscErrorCode PetscObjectDereference(PetscObject obj)
655: {
656: PetscFunctionBegin;
657: if (!obj) PetscFunctionReturn(PETSC_SUCCESS);
659: if (obj->bops->destroy) PetscCall((*obj->bops->destroy)(&obj));
660: else PetscCheck(--(obj->refct), PETSC_COMM_SELF, PETSC_ERR_SUP, "This PETSc object does not have a generic destroy routine");
661: PetscFunctionReturn(PETSC_SUCCESS);
662: }
664: /*
665: The following routines are the versions private to the PETSc object
666: data structures.
667: */
668: PetscErrorCode PetscObjectRemoveReference(PetscObject obj, const char name[])
669: {
670: PetscFunctionBegin;
672: PetscCall(PetscObjectListRemoveReference(&obj->olist, name));
673: PetscFunctionReturn(PETSC_SUCCESS);
674: }
676: /*@C
677: PetscObjectCompose - Associates another PETSc object with a given PETSc object.
679: Not Collective
681: Input Parameters:
682: + obj - the PETSc object; this must be cast with (`PetscObject`), for example,
683: `PetscObjectCompose`((`PetscObject`)mat,...);
684: . name - name associated with the child object
685: - ptr - the other PETSc object to associate with the PETSc object; this must also be
686: cast with (`PetscObject`)
688: Level: advanced
690: Notes:
691: The second objects reference count is automatically increased by one when it is
692: composed.
694: Replaces any previous object that had been composed with the same name.
696: If `ptr` is `NULL` and `name` has previously been composed using an object, then that
697: entry is removed from `obj`.
699: `PetscObjectCompose()` can be used with any PETSc object (such as
700: `Mat`, `Vec`, `KSP`, `SNES`, etc.) or any user-provided object.
702: `PetscContainerCreate()` can be used to create an object from a
703: user-provided pointer that may then be composed with PETSc objects using `PetscObjectCompose()`
705: .seealso: `PetscObjectQuery()`, `PetscContainerCreate()`, `PetscObjectComposeFunction()`, `PetscObjectQueryFunction()`, `PetscContainer`,
706: `PetscContainerSetPointer()`, `PetscObject`
707: @*/
708: PetscErrorCode PetscObjectCompose(PetscObject obj, const char name[], PetscObject ptr)
709: {
710: PetscFunctionBegin;
712: PetscAssertPointer(name, 2);
714: PetscCheck(obj != ptr, PetscObjectComm((PetscObject)obj), PETSC_ERR_SUP, "Cannot compose object with itself");
715: if (ptr) {
716: char *tname;
717: PetscBool skipreference;
719: PetscCall(PetscObjectListReverseFind(ptr->olist, obj, &tname, &skipreference));
720: if (tname) PetscCheck(skipreference, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "An object cannot be composed with an object that was composed with it");
721: }
722: PetscCall(PetscObjectListAdd(&obj->olist, name, ptr));
723: PetscFunctionReturn(PETSC_SUCCESS);
724: }
726: /*@C
727: PetscObjectQuery - Gets a PETSc object associated with a given object that was composed with `PetscObjectCompose()`
729: Not Collective
731: Input Parameters:
732: + obj - the PETSc object. It must be cast with a (`PetscObject`), for example,
733: `PetscObjectCompose`((`PetscObject`)mat,...);
734: . name - name associated with child object
735: - ptr - the other PETSc object associated with the PETSc object, this must be
736: cast with (`PetscObject`*)
738: Level: advanced
740: Note:
741: The reference count of neither object is increased in this call
743: .seealso: `PetscObjectCompose()`, `PetscObjectComposeFunction()`, `PetscObjectQueryFunction()`, `PetscContainer`
744: `PetscContainerGetPointer()`, `PetscObject`
745: @*/
746: PetscErrorCode PetscObjectQuery(PetscObject obj, const char name[], PetscObject *ptr)
747: {
748: PetscFunctionBegin;
750: PetscAssertPointer(name, 2);
751: PetscAssertPointer(ptr, 3);
752: PetscCall(PetscObjectListFind(obj->olist, name, ptr));
753: PetscFunctionReturn(PETSC_SUCCESS);
754: }
756: /*MC
757: PetscObjectComposeFunction - Associates a function with a given PETSc object.
759: Synopsis:
760: #include <petscsys.h>
761: PetscErrorCode PetscObjectComposeFunction(PetscObject obj, const char name[], void (*fptr)(void))
763: Logically Collective
765: Input Parameters:
766: + obj - the PETSc object; this must be cast with a (`PetscObject`), for example,
767: `PetscObjectCompose`((`PetscObject`)mat,...);
768: . name - name associated with the child function
769: - fptr - function pointer
771: Level: advanced
773: Notes:
774: When the first argument of `fptr` is (or is derived from) a `PetscObject` then `PetscTryMethod()` and `PetscUseMethod()`
775: can be used to call the function directly with error checking.
777: To remove a registered routine, pass in `NULL` for `fptr`.
779: `PetscObjectComposeFunction()` can be used with any PETSc object (such as
780: `Mat`, `Vec`, `KSP`, `SNES`, etc.) or any user-provided object.
782: `PetscUseTypeMethod()` and `PetscTryTypeMethod()` are used to call a function that is stored in the objects `obj->ops` table.
784: .seealso: `PetscObjectQueryFunction()`, `PetscContainerCreate()` `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscTryMethod()`, `PetscUseMethod()`,
785: `PetscUseTypeMethod()`, `PetscTryTypeMethod()`, `PetscObject`
786: M*/
787: PetscErrorCode PetscObjectComposeFunction_Private(PetscObject obj, const char name[], void (*fptr)(void))
788: {
789: PetscFunctionBegin;
791: PetscAssertPointer(name, 2);
792: PetscCall(PetscFunctionListAdd(&obj->qlist, name, fptr));
793: PetscFunctionReturn(PETSC_SUCCESS);
794: }
796: /*MC
797: PetscObjectQueryFunction - Gets a function associated with a given object.
799: Synopsis:
800: #include <petscsys.h>
801: PetscErrorCode PetscObjectQueryFunction(PetscObject obj, const char name[], void (**fptr)(void))
803: Logically Collective
805: Input Parameters:
806: + obj - the PETSc object; this must be cast with (`PetscObject`), for example,
807: `PetscObjectQueryFunction`((`PetscObject`)ksp,...);
808: - name - name associated with the child function
810: Output Parameter:
811: . fptr - function pointer
813: Level: advanced
815: .seealso: `PetscObjectComposeFunction()`, `PetscFunctionListFind()`, `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObject`
816: M*/
817: PETSC_EXTERN PetscErrorCode PetscObjectQueryFunction_Private(PetscObject obj, const char name[], void (**fptr)(void))
818: {
819: PetscFunctionBegin;
821: PetscAssertPointer(name, 2);
822: PetscCall(PetscFunctionListFind(obj->qlist, name, fptr));
823: PetscFunctionReturn(PETSC_SUCCESS);
824: }
826: struct _p_PetscContainer {
827: PETSCHEADER(int);
828: void *ptr;
829: PetscErrorCode (*userdestroy)(void *);
830: };
832: /*@C
833: PetscContainerUserDestroyDefault - Default destroy routine for user-provided data that simply calls `PetscFree()` in the data
834: provided with `PetscContainerSetPointer()`
836: Logically Collective on the `PetscContainer` containing the user data
838: Input Parameter:
839: . ctx - pointer to user-provided data
841: Level: advanced
843: .seealso: `PetscContainerDestroy()`, `PetscContainerSetUserDestroy()`, `PetscObject`
844: @*/
845: PetscErrorCode PetscContainerUserDestroyDefault(void *ctx)
846: {
847: PetscFunctionBegin;
848: PetscCall(PetscFree(ctx));
849: PetscFunctionReturn(PETSC_SUCCESS);
850: }
852: /*@C
853: PetscContainerGetPointer - Gets the pointer value contained in the container that was provided with `PetscContainerSetPointer()`
855: Not Collective
857: Input Parameter:
858: . obj - the object created with `PetscContainerCreate()`
860: Output Parameter:
861: . ptr - the pointer value
863: Level: advanced
865: .seealso: `PetscContainerCreate()`, `PetscContainerDestroy()`, `PetscObject`,
866: `PetscContainerSetPointer()`
867: @*/
868: PetscErrorCode PetscContainerGetPointer(PetscContainer obj, void **ptr)
869: {
870: PetscFunctionBegin;
872: PetscAssertPointer(ptr, 2);
873: *ptr = obj->ptr;
874: PetscFunctionReturn(PETSC_SUCCESS);
875: }
877: /*@C
878: PetscContainerSetPointer - Sets the pointer value contained in the container.
880: Logically Collective
882: Input Parameters:
883: + obj - the object created with `PetscContainerCreate()`
884: - ptr - the pointer value
886: Level: advanced
888: .seealso: `PetscContainerCreate()`, `PetscContainerDestroy()`, `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObject`,
889: `PetscContainerGetPointer()`
890: @*/
891: PetscErrorCode PetscContainerSetPointer(PetscContainer obj, void *ptr)
892: {
893: PetscFunctionBegin;
895: if (ptr) PetscAssertPointer(ptr, 2);
896: obj->ptr = ptr;
897: PetscFunctionReturn(PETSC_SUCCESS);
898: }
900: /*@C
901: PetscContainerDestroy - Destroys a PETSc container object.
903: Collective
905: Input Parameter:
906: . obj - an object that was created with `PetscContainerCreate()`
908: Level: advanced
910: Note:
911: If `PetscContainerSetUserDestroy()` was used to provide a user destroy object for the data provided with `PetscContainerSetPointer()`
912: then that function is called to destroy the data.
914: .seealso: `PetscContainerCreate()`, `PetscContainerSetUserDestroy()`, `PetscObject`
915: @*/
916: PetscErrorCode PetscContainerDestroy(PetscContainer *obj)
917: {
918: PetscFunctionBegin;
919: if (!*obj) PetscFunctionReturn(PETSC_SUCCESS);
921: if (--((PetscObject)(*obj))->refct > 0) {
922: *obj = NULL;
923: PetscFunctionReturn(PETSC_SUCCESS);
924: }
925: if ((*obj)->userdestroy) PetscCall((*(*obj)->userdestroy)((*obj)->ptr));
926: PetscCall(PetscHeaderDestroy(obj));
927: PetscFunctionReturn(PETSC_SUCCESS);
928: }
930: /*@C
931: PetscContainerSetUserDestroy - Sets name of the user destroy function for the data provided to the `PetscContainer` with `PetscContainerSetPointer()`
933: Logically Collective
935: Input Parameters:
936: + obj - an object that was created with `PetscContainerCreate()`
937: - des - name of the user destroy function
939: Level: advanced
941: Note:
942: Use `PetscContainerUserDestroyDefault()` if the memory was obtained by calling `PetscMalloc()` or one of its variants for single memory allocation.
944: .seealso: `PetscContainerDestroy()`, `PetscContainerUserDestroyDefault()`, `PetscMalloc()`, `PetscMalloc1()`, `PetscCalloc()`, `PetscCalloc1()`, `PetscObject`
945: @*/
946: PetscErrorCode PetscContainerSetUserDestroy(PetscContainer obj, PetscErrorCode (*des)(void *))
947: {
948: PetscFunctionBegin;
950: obj->userdestroy = des;
951: PetscFunctionReturn(PETSC_SUCCESS);
952: }
954: PetscClassId PETSC_CONTAINER_CLASSID;
956: /*@C
957: PetscContainerCreate - Creates a PETSc object that has room to hold a single pointer.
959: Collective
961: Input Parameter:
962: . comm - MPI communicator that shares the object
964: Output Parameter:
965: . container - the container created
967: Level: advanced
969: Notes:
970: This allows one to attach any type of data (accessible through a pointer) with the
971: `PetscObjectCompose()` function to a `PetscObject`. The data item itself is attached by a
972: call to `PetscContainerSetPointer()`.
974: .seealso: `PetscContainerDestroy()`, `PetscContainerSetPointer()`, `PetscContainerGetPointer()`, `PetscObjectCompose()`, `PetscObjectQuery()`,
975: `PetscContainerSetUserDestroy()`, `PetscObject`
976: @*/
977: PetscErrorCode PetscContainerCreate(MPI_Comm comm, PetscContainer *container)
978: {
979: PetscFunctionBegin;
980: PetscAssertPointer(container, 2);
981: PetscCall(PetscSysInitializePackage());
982: PetscCall(PetscHeaderCreate(*container, PETSC_CONTAINER_CLASSID, "PetscContainer", "Container", "Sys", comm, PetscContainerDestroy, NULL));
983: PetscFunctionReturn(PETSC_SUCCESS);
984: }
986: /*@
987: PetscObjectSetFromOptions - Sets generic parameters from user options.
989: Collective
991: Input Parameter:
992: . obj - the `PetscObject`
994: Level: beginner
996: Note:
997: We have no generic options at present, so this does nothing
999: .seealso: `PetscObjectSetOptionsPrefix()`, `PetscObjectGetOptionsPrefix()`, `PetscObject`
1000: @*/
1001: PetscErrorCode PetscObjectSetFromOptions(PetscObject obj)
1002: {
1003: PetscFunctionBegin;
1005: PetscFunctionReturn(PETSC_SUCCESS);
1006: }
1008: /*@
1009: PetscObjectSetUp - Sets up the internal data structures for later use of the object
1011: Collective
1013: Input Parameter:
1014: . obj - the `PetscObject`
1016: Level: advanced
1018: Note:
1019: This does nothing at present.
1021: .seealso: `PetscObjectDestroy()`, `PetscObject`
1022: @*/
1023: PetscErrorCode PetscObjectSetUp(PetscObject obj)
1024: {
1025: PetscFunctionBegin;
1027: PetscFunctionReturn(PETSC_SUCCESS);
1028: }