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: h->classid = classid;
38: h->class_name = (char *)class_name;
39: h->description = (char *)descr;
40: h->mansec = (char *)mansec;
41: h->refct = 1;
42: h->id = PetscObjectNewId_Internal();
43: h->bops->destroy = destroy;
44: h->bops->view = view;
45: h->bops->compose = PetscObjectCompose_Petsc;
46: h->bops->query = PetscObjectQuery_Petsc;
47: h->bops->composefunction = PetscObjectComposeFunction_Petsc;
48: h->bops->queryfunction = PetscObjectQueryFunction_Petsc;
50: PetscCommDuplicate(comm, &h->comm, &h->tag);
52: #if defined(PETSC_USE_LOG)
53: /* Keep a record of object created */
54: if (PetscObjectsLog) {
55: PetscObject *newPetscObjects;
56: PetscInt newPetscObjectsMaxCounts;
58: PetscObjectsCounts++;
59: for (PetscInt i = 0; i < PetscObjectsMaxCounts; ++i) {
60: if (!PetscObjects[i]) {
61: PetscObjects[i] = h;
62: return 0;
63: }
64: }
65: /* Need to increase the space for storing PETSc objects */
66: if (!PetscObjectsMaxCounts) newPetscObjectsMaxCounts = 100;
67: else newPetscObjectsMaxCounts = 2 * PetscObjectsMaxCounts;
68: PetscCalloc1(newPetscObjectsMaxCounts, &newPetscObjects);
69: PetscArraycpy(newPetscObjects, PetscObjects, PetscObjectsMaxCounts);
70: PetscFree(PetscObjects);
72: PetscObjects = newPetscObjects;
73: PetscObjects[PetscObjectsMaxCounts] = h;
74: PetscObjectsMaxCounts = newPetscObjectsMaxCounts;
75: }
76: #endif
77: return 0;
78: }
80: PETSC_INTERN PetscBool PetscMemoryCollectMaximumUsage;
81: PETSC_INTERN PetscLogDouble PetscMemoryMaximumUsage;
83: /*
84: PetscHeaderDestroy_Private - Destroys a base PETSc object header. Called by
85: the macro PetscHeaderDestroy().
86: */
87: PetscErrorCode PetscHeaderDestroy_Private(PetscObject obj, PetscBool clear_for_reuse)
88: {
90: PetscLogObjectDestroy(obj);
91: PetscComposedQuantitiesDestroy(obj);
92: if (PetscMemoryCollectMaximumUsage) {
93: PetscLogDouble usage;
95: PetscMemoryGetCurrentUsage(&usage);
96: if (usage > PetscMemoryMaximumUsage) PetscMemoryMaximumUsage = usage;
97: }
98: /* first destroy things that could execute arbitrary code */
99: if (obj->python_destroy) {
100: void *python_context = obj->python_context;
101: PetscErrorCode (*python_destroy)(void *) = obj->python_destroy;
103: obj->python_context = NULL;
104: obj->python_destroy = NULL;
105: (*python_destroy)(python_context);
106: }
107: PetscObjectDestroyOptionsHandlers(obj);
108: PetscObjectListDestroy(&obj->olist);
110: /* destroy allocated quantities */
111: if (PetscPrintFunctionList) PetscFunctionListPrintNonEmpty(obj->qlist);
113: PetscFree(obj->name);
114: PetscFree(obj->prefix);
115: PetscFree(obj->type_name);
117: if (clear_for_reuse) {
118: /* we will assume that obj->bops->view and destroy are safe to leave as-is */
119: obj->bops->compose = PetscObjectCompose_Petsc;
120: obj->bops->query = PetscObjectQuery_Petsc;
121: obj->bops->composefunction = PetscObjectComposeFunction_Petsc;
122: obj->bops->queryfunction = PetscObjectQueryFunction_Petsc;
124: /* reset quantities, in order of appearance in _p_PetscObject */
125: obj->id = PetscObjectNewId_Internal();
126: obj->refct = 1;
127: obj->tablevel = 0;
128: obj->state = 0;
129: /* don't deallocate, zero these out instead */
130: PetscFunctionListClear(obj->qlist);
131: PetscArrayzero(obj->fortran_func_pointers, obj->num_fortran_func_pointers);
132: PetscArrayzero(obj->fortrancallback[PETSC_FORTRAN_CALLBACK_CLASS], obj->num_fortrancallback[PETSC_FORTRAN_CALLBACK_CLASS]);
133: PetscArrayzero(obj->fortrancallback[PETSC_FORTRAN_CALLBACK_SUBTYPE], obj->num_fortrancallback[PETSC_FORTRAN_CALLBACK_SUBTYPE]);
134: obj->optionsprinted = PETSC_FALSE;
135: #if PetscDefined(HAVE_SAWS)
136: obj->amsmem = PETSC_FALSE;
137: obj->amspublishblock = PETSC_FALSE;
138: #endif
139: obj->options = NULL;
140: obj->donotPetscObjectPrintClassNamePrefixType = PETSC_FALSE;
141: } else {
142: PetscFunctionListDestroy(&obj->qlist);
143: PetscFree(obj->fortran_func_pointers);
144: PetscFree(obj->fortrancallback[PETSC_FORTRAN_CALLBACK_CLASS]);
145: PetscFree(obj->fortrancallback[PETSC_FORTRAN_CALLBACK_SUBTYPE]);
146: PetscCommDestroy(&obj->comm);
147: obj->classid = PETSCFREEDHEADER;
149: #if PetscDefined(USE_LOG)
150: if (PetscObjectsLog) {
151: /* Record object removal from list of all objects */
152: for (PetscInt i = 0; i < PetscObjectsMaxCounts; ++i) {
153: if (PetscObjects[i] == obj) {
154: PetscObjects[i] = NULL;
155: --PetscObjectsCounts;
156: break;
157: }
158: }
159: if (!PetscObjectsCounts) {
160: PetscFree(PetscObjects);
161: PetscObjectsMaxCounts = 0;
162: }
163: }
164: #endif
165: }
166: return 0;
167: }
169: /*
170: PetscHeaderReset_Internal - "Reset" a PetscObject header. This is tantamount to destroying
171: the object but does not free all resources. The object retains its:
173: - classid
174: - bops->view
175: - bops->destroy
176: - comm
177: - tag
178: - class_name
179: - description
180: - mansec
181: - cpp
183: Note that while subclass information is lost, superclass info remains. Thus this function is
184: intended to be used to reuse a PetscObject within the same class to avoid reallocating its
185: resources.
186: */
187: PetscErrorCode PetscHeaderReset_Internal(PetscObject obj)
188: {
189: PetscHeaderDestroy_Private(obj, PETSC_TRUE);
190: return 0;
191: }
193: /*@C
194: PetscObjectCopyFortranFunctionPointers - Copy function pointers to another object
196: Logically Collective on src
198: Input Parameters:
199: + src - source object
200: - dest - destination object
202: Level: developer
204: Note:
205: Both objects must have the same class.
207: This is used to help manage user callback functions that were provided in Fortran
208: @*/
209: PetscErrorCode PetscObjectCopyFortranFunctionPointers(PetscObject src, PetscObject dest)
210: {
211: PetscFortranCallbackId cbtype, numcb[PETSC_FORTRAN_CALLBACK_MAXTYPE];
217: PetscFree(dest->fortran_func_pointers);
218: PetscMalloc(src->num_fortran_func_pointers * sizeof(void (*)(void)), &dest->fortran_func_pointers);
219: PetscMemcpy(dest->fortran_func_pointers, src->fortran_func_pointers, src->num_fortran_func_pointers * sizeof(void (*)(void)));
221: dest->num_fortran_func_pointers = src->num_fortran_func_pointers;
223: PetscFortranCallbackGetSizes(src->classid, &numcb[PETSC_FORTRAN_CALLBACK_CLASS], &numcb[PETSC_FORTRAN_CALLBACK_SUBTYPE]);
224: for (cbtype = PETSC_FORTRAN_CALLBACK_CLASS; cbtype < PETSC_FORTRAN_CALLBACK_MAXTYPE; cbtype++) {
225: PetscFree(dest->fortrancallback[cbtype]);
226: PetscCalloc1(numcb[cbtype], &dest->fortrancallback[cbtype]);
227: PetscMemcpy(dest->fortrancallback[cbtype], src->fortrancallback[cbtype], src->num_fortrancallback[cbtype] * sizeof(PetscFortranCallback));
228: dest->num_fortrancallback[cbtype] = src->num_fortrancallback[cbtype];
229: }
230: return 0;
231: }
233: /*@C
234: PetscObjectSetFortranCallback - set fortran callback function pointer and context
236: Logically Collective
238: Input Parameters:
239: + obj - object on which to set callback
240: . cbtype - callback type (class or subtype)
241: . cid - address of callback Id, updated if not yet initialized (zero)
242: . func - Fortran function
243: - ctx - Fortran context
245: Level: developer
247: Note:
248: This is used to help manage user callback functions that were provided in Fortran
250: .seealso: `PetscObjectGetFortranCallback()`
251: @*/
252: PetscErrorCode PetscObjectSetFortranCallback(PetscObject obj, PetscFortranCallbackType cbtype, PetscFortranCallbackId *cid, void (*func)(void), void *ctx)
253: {
254: const char *subtype = NULL;
257: if (cbtype == PETSC_FORTRAN_CALLBACK_SUBTYPE) subtype = obj->type_name;
258: if (!*cid) PetscFortranCallbackRegister(obj->classid, subtype, cid);
259: if (*cid >= PETSC_SMALLEST_FORTRAN_CALLBACK + obj->num_fortrancallback[cbtype]) {
260: PetscFortranCallbackId oldnum = obj->num_fortrancallback[cbtype];
261: PetscFortranCallbackId newnum = PetscMax(*cid - PETSC_SMALLEST_FORTRAN_CALLBACK + 1, 2 * oldnum);
262: PetscFortranCallback *callback;
263: PetscMalloc1(newnum, &callback);
264: PetscMemcpy(callback, obj->fortrancallback[cbtype], oldnum * sizeof(*obj->fortrancallback[cbtype]));
265: PetscFree(obj->fortrancallback[cbtype]);
267: obj->fortrancallback[cbtype] = callback;
268: obj->num_fortrancallback[cbtype] = newnum;
269: }
270: obj->fortrancallback[cbtype][*cid - PETSC_SMALLEST_FORTRAN_CALLBACK].func = func;
271: obj->fortrancallback[cbtype][*cid - PETSC_SMALLEST_FORTRAN_CALLBACK].ctx = ctx;
272: return 0;
273: }
275: /*@C
276: PetscObjectGetFortranCallback - get fortran callback function pointer and context
278: Logically Collective
280: Input Parameters:
281: + obj - object on which to get callback
282: . cbtype - callback type
283: - cid - address of callback Id
285: Output Parameters:
286: + func - Fortran function (or NULL if not needed)
287: - ctx - Fortran context (or NULL if not needed)
289: Level: developer
291: Note:
292: This is used to help manage user callback functions that were provided in Fortran
294: .seealso: `PetscObjectSetFortranCallback()`
295: @*/
296: PetscErrorCode PetscObjectGetFortranCallback(PetscObject obj, PetscFortranCallbackType cbtype, PetscFortranCallbackId cid, void (**func)(void), void **ctx)
297: {
298: PetscFortranCallback *cb;
303: cb = &obj->fortrancallback[cbtype][cid - PETSC_SMALLEST_FORTRAN_CALLBACK];
304: if (func) *func = cb->func;
305: if (ctx) *ctx = cb->ctx;
306: return 0;
307: }
309: #if defined(PETSC_USE_LOG)
310: /*@C
311: PetscObjectsDump - Prints all the currently existing objects.
313: On rank 0 of `PETSC_COMM_WORLD` prints the values
315: Input Parameters:
316: + fd - file pointer
317: - all - by default only tries to display objects created explicitly by the user, if all is `PETSC_TRUE` then lists all outstanding objects
319: Options Database Key:
320: . -objects_dump <all> - print information about all the objects that exist at the end of the programs run
322: Level: advanced
324: @*/
325: PetscErrorCode PetscObjectsDump(FILE *fd, PetscBool all)
326: {
327: PetscInt i;
328: #if defined(PETSC_USE_DEBUG)
329: PetscInt j, k = 0;
330: #endif
331: PetscObject h;
333: if (PetscObjectsCounts) {
334: PetscFPrintf(PETSC_COMM_WORLD, fd, "The following objects were never freed\n");
335: PetscFPrintf(PETSC_COMM_WORLD, fd, "-----------------------------------------\n");
336: for (i = 0; i < PetscObjectsMaxCounts; i++) {
337: if ((h = PetscObjects[i])) {
338: PetscObjectName(h);
339: {
340: #if defined(PETSC_USE_DEBUG)
341: PetscStack *stack = NULL;
342: char *create, *rclass;
344: /* if the PETSc function the user calls is not a create then this object was NOT directly created by them */
345: PetscMallocGetStack(h, &stack);
346: if (stack) {
347: k = stack->currentsize - 2;
348: if (!all) {
349: k = 0;
350: while (!stack->petscroutine[k]) k++;
351: PetscStrstr(stack->function[k], "Create", &create);
352: if (!create) PetscStrstr(stack->function[k], "Get", &create);
353: PetscStrstr(stack->function[k], h->class_name, &rclass);
354: if (!create) continue;
355: if (!rclass) continue;
356: }
357: }
358: #endif
360: PetscFPrintf(PETSC_COMM_WORLD, fd, "[%d] %s %s %s\n", PetscGlobalRank, h->class_name, h->type_name, h->name);
362: #if defined(PETSC_USE_DEBUG)
363: PetscMallocGetStack(h, &stack);
364: if (stack) {
365: for (j = k; j >= 0; j--) fprintf(fd, " [%d] %s() in %s\n", PetscGlobalRank, stack->function[j], stack->file[j]);
366: }
367: #endif
368: }
369: }
370: }
371: }
372: return 0;
373: }
374: #endif
376: #if defined(PETSC_USE_LOG)
378: /*@C
379: PetscObjectsView - Prints the currently existing objects.
381: Logically Collective on viewer
383: Input Parameter:
384: . viewer - must be an `PETSCVIEWERASCII` viewer
386: Level: advanced
388: @*/
389: PetscErrorCode PetscObjectsView(PetscViewer viewer)
390: {
391: PetscBool isascii;
392: FILE *fd;
394: if (!viewer) viewer = PETSC_VIEWER_STDOUT_WORLD;
395: PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii);
397: PetscViewerASCIIGetPointer(viewer, &fd);
398: PetscObjectsDump(fd, PETSC_TRUE);
399: return 0;
400: }
402: /*@C
403: PetscObjectsGetObject - Get a pointer to a named object
405: Not collective
407: Input Parameter:
408: . name - the name of an object
410: Output Parameters:
411: + obj - the object or null if there is no object
412: - classname - the name of the class
414: Level: advanced
416: @*/
417: PetscErrorCode PetscObjectsGetObject(const char *name, PetscObject *obj, char **classname)
418: {
419: PetscInt i;
420: PetscObject h;
421: PetscBool flg;
425: *obj = NULL;
426: for (i = 0; i < PetscObjectsMaxCounts; i++) {
427: if ((h = PetscObjects[i])) {
428: PetscObjectName(h);
429: PetscStrcmp(h->name, name, &flg);
430: if (flg) {
431: *obj = h;
432: if (classname) *classname = h->class_name;
433: return 0;
434: }
435: }
436: }
437: return 0;
438: }
439: #endif
441: /*@
442: 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
444: Input Parameters:
445: . obj - the `PetscObject`
447: Level: developer
449: Developer Note:
450: This is used, for example to prevent sequential objects that are created from a parallel object; such as the `KSP` created by
451: `PCBJACOBI` from all printing the same help messages to the screen
453: .seealso: `PetscOptionsInsert()`
454: @*/
455: PetscErrorCode PetscObjectSetPrintedOptions(PetscObject obj)
456: {
458: obj->optionsprinted = PETSC_TRUE;
459: return 0;
460: }
462: /*@
463: 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.
465: Input Parameters:
466: + pobj - the parent object
467: - obj - the PetscObject
469: Level: developer
471: Developer Notes:
472: This is used, for example to prevent sequential objects that are created from a parallel object; such as the `KSP` created by
473: `PCBJACOBI` from all printing the same help messages to the screen
475: This will not handle more complicated situations like with `PCGASM` where children may live on any subset of the parent's processes and overlap
477: .seealso: `PetscOptionsInsert()`, `PetscObjectSetPrintedOptions()`
478: @*/
479: PetscErrorCode PetscObjectInheritPrintedOptions(PetscObject pobj, PetscObject obj)
480: {
481: PetscMPIInt prank, size;
485: MPI_Comm_rank(pobj->comm, &prank);
486: MPI_Comm_size(obj->comm, &size);
487: if (size == 1 && prank > 0) obj->optionsprinted = PETSC_TRUE;
488: return 0;
489: }
491: /*@C
492: PetscObjectAddOptionsHandler - Adds an additional function to check for options when XXXSetFromOptions() is called.
494: Not Collective
496: Input Parameters:
497: + obj - the PETSc object
498: . handle - function that checks for options
499: . destroy - function to destroy context if provided
500: - ctx - optional context for check function
502: Level: developer
504: .seealso: `KSPSetFromOptions()`, `PCSetFromOptions()`, `SNESSetFromOptions()`, `PetscObjectProcessOptionsHandlers()`, `PetscObjectDestroyOptionsHandlers()`
505: @*/
506: PetscErrorCode PetscObjectAddOptionsHandler(PetscObject obj, PetscErrorCode (*handle)(PetscObject, PetscOptionItems *, void *), PetscErrorCode (*destroy)(PetscObject, void *), void *ctx)
507: {
510: obj->optionhandler[obj->noptionhandler] = handle;
511: obj->optiondestroy[obj->noptionhandler] = destroy;
512: obj->optionctx[obj->noptionhandler++] = ctx;
513: return 0;
514: }
516: /*@C
517: PetscObjectProcessOptionsHandlers - Calls all the options handlers attached to an object
519: Not Collective
521: Input Parameters:
522: + obj - the PETSc object
523: - PetscOptionsObject - the options context
525: Level: developer
527: .seealso: `KSPSetFromOptions()`, `PCSetFromOptions()`, `SNESSetFromOptions()`, `PetscObjectAddOptionsHandler()`, `PetscObjectDestroyOptionsHandlers()`
528: @*/
529: PetscErrorCode PetscObjectProcessOptionsHandlers(PetscObject obj, PetscOptionItems *PetscOptionsObject)
530: {
532: for (PetscInt i = 0; i < obj->noptionhandler; i++) (*obj->optionhandler[i])(obj, PetscOptionsObject, obj->optionctx[i]);
533: return 0;
534: }
536: /*@C
537: PetscObjectDestroyOptionsHandlers - Destroys all the option handlers attached to an object
539: Not Collective
541: Input Parameter:
542: . obj - the PETSc object
544: Level: developer
546: .seealso: `KSPSetFromOptions()`, `PCSetFromOptions()`, `SNESSetFromOptions()`, `PetscObjectAddOptionsHandler()`, `PetscObjectProcessOptionsHandlers()`
547: @*/
548: PetscErrorCode PetscObjectDestroyOptionsHandlers(PetscObject obj)
549: {
551: for (PetscInt i = 0; i < obj->noptionhandler; i++) {
552: if (obj->optiondestroy[i]) (*obj->optiondestroy[i])(obj, obj->optionctx[i]);
553: }
554: obj->noptionhandler = 0;
555: return 0;
556: }
558: /*@C
559: PetscObjectReference - Indicates to any `PetscObject` that it is being
560: referenced by another `PetscObject`. This increases the reference
561: count for that object by one.
563: Logically Collective on obj
565: Input Parameter:
566: . obj - the PETSc object. This must be cast with (`PetscObject`), for example,
567: `PetscObjectReference`((`PetscObject`)mat);
569: Level: advanced
571: .seealso: `PetscObjectCompose()`, `PetscObjectDereference()`
572: @*/
573: PetscErrorCode PetscObjectReference(PetscObject obj)
574: {
575: if (!obj) return 0;
577: obj->refct++;
578: return 0;
579: }
581: /*@C
582: PetscObjectGetReference - Gets the current reference count for
583: any PETSc object.
585: Not Collective
587: Input Parameter:
588: . obj - the PETSc object; this must be cast with (`PetscObject`), for example,
589: `PetscObjectGetReference`((`PetscObject`)mat,&cnt);
591: Output Parameter:
592: . cnt - the reference count
594: Level: advanced
596: .seealso: `PetscObjectCompose()`, `PetscObjectDereference()`, `PetscObjectReference()`
597: @*/
598: PetscErrorCode PetscObjectGetReference(PetscObject obj, PetscInt *cnt)
599: {
602: *cnt = obj->refct;
603: return 0;
604: }
606: /*@C
607: PetscObjectDereference - Indicates to any `PetscObject` that it is being
608: referenced by one less `PetscObject`. This decreases the reference
609: count for that object by one.
611: Collective on obj if reference reaches 0 otherwise Logically Collective
613: Input Parameter:
614: . obj - the PETSc object; this must be cast with (`PetscObject`), for example,
615: `PetscObjectDereference`((`PetscObject`)mat);
617: Note:
618: `PetscObjectDestroy()` sets the obj pointer to null after the call, this routine does not.
620: Level: advanced
622: .seealso: `PetscObjectCompose()`, `PetscObjectReference()`, `PetscObjectDestroy()`
623: @*/
624: PetscErrorCode PetscObjectDereference(PetscObject obj)
625: {
626: if (!obj) return 0;
628: if (obj->bops->destroy) (*obj->bops->destroy)(&obj);
630: return 0;
631: }
633: /* ----------------------------------------------------------------------- */
634: /*
635: The following routines are the versions private to the PETSc object
636: data structures.
637: */
638: PetscErrorCode PetscObjectRemoveReference(PetscObject obj, const char name[])
639: {
641: PetscObjectListRemoveReference(&obj->olist, name);
642: return 0;
643: }
645: PetscErrorCode PetscObjectCompose_Petsc(PetscObject obj, const char name[], PetscObject ptr)
646: {
647: if (ptr) {
648: char *tname;
649: PetscBool skipreference;
651: PetscObjectListReverseFind(ptr->olist, obj, &tname, &skipreference);
653: }
654: PetscObjectListAdd(&obj->olist, name, ptr);
655: return 0;
656: }
658: PetscErrorCode PetscObjectQuery_Petsc(PetscObject obj, const char name[], PetscObject *ptr)
659: {
661: PetscObjectListFind(obj->olist, name, ptr);
662: return 0;
663: }
665: PetscErrorCode PetscObjectComposeFunction_Petsc(PetscObject obj, const char name[], void (*ptr)(void))
666: {
668: PetscFunctionListAdd(&obj->qlist, name, ptr);
669: return 0;
670: }
672: PetscErrorCode PetscObjectQueryFunction_Petsc(PetscObject obj, const char name[], void (**ptr)(void))
673: {
675: PetscFunctionListFind(obj->qlist, name, ptr);
676: return 0;
677: }
679: /*@C
680: PetscObjectCompose - Associates another PETSc object with a given PETSc object.
682: Not Collective
684: Input Parameters:
685: + obj - the PETSc object; this must be cast with (`PetscObject`), for example,
686: `PetscObjectCompose`((`PetscObject`)mat,...);
687: . name - name associated with the child object
688: - ptr - the other PETSc object to associate with the PETSc object; this must also be
689: cast with (`PetscObject`)
691: Level: advanced
693: Notes:
694: The second objects reference count is automatically increased by one when it is
695: composed.
697: Replaces any previous object that had the same name.
699: If ptr is null and name has previously been composed using an object, then that
700: entry is removed from the obj.
702: `PetscObjectCompose()` can be used with any PETSc object (such as
703: `Mat`, `Vec`, `KSP`, `SNES`, etc.) or any user-provided object.
705: `PetscContainerCreate()` can be used to create an object from a
706: user-provided pointer that may then be composed with PETSc objects using `PetscObjectCompose()`
708: .seealso: `PetscObjectQuery()`, `PetscContainerCreate()`, `PetscObjectComposeFunction()`, `PetscObjectQueryFunction()`, `PetscContainer`,
709: `PetscContainerSetPointer()`
710: @*/
711: PetscErrorCode PetscObjectCompose(PetscObject obj, const char name[], PetscObject ptr)
712: {
717: (*obj->bops->compose)(obj, name, ptr);
718: return 0;
719: }
721: /*@C
722: PetscObjectQuery - Gets a PETSc object associated with a given object that was composed with `PetscObjectCompose()`
724: Not Collective
726: Input Parameters:
727: + obj - the PETSc object
728: Thus must be cast with a (`PetscObject`), for example,
729: `PetscObjectCompose`((`PetscObject`)mat,...);
730: . name - name associated with child object
731: - ptr - the other PETSc object associated with the PETSc object, this must be
732: cast with (`PetscObject`*)
734: Level: advanced
736: Note:
737: The reference count of neither object is increased in this call
739: .seealso: `PetscObjectCompose()`, `PetscObjectComposeFunction()`, `PetscObjectQueryFunction()`, `PetscContainer`
740: `PetscContainerGetPointer()`
741: @*/
742: PetscErrorCode PetscObjectQuery(PetscObject obj, const char name[], PetscObject *ptr)
743: {
747: (*obj->bops->query)(obj, name, ptr);
748: return 0;
749: }
751: /*MC
752: PetscObjectComposeFunction - Associates a function with a given PETSc object.
754: Synopsis:
755: #include <petscsys.h>
756: PetscErrorCode PetscObjectComposeFunction(PetscObject obj,const char name[],void (*fptr)(void))
758: Logically Collective on obj
760: Input Parameters:
761: + obj - the PETSc object; this must be cast with a (`PetscObject`), for example,
762: `PetscObjectCompose`((`PetscObject`)mat,...);
763: . name - name associated with the child function
764: . fname - name of the function
765: - fptr - function pointer
767: Level: advanced
769: Notes:
770: When the first argument of the function is the object within which it has been composed then `PetscTryMethod()` and `PetscUseMethod()`
771: can be used to call the function directly with error checking.
773: To remove a registered routine, pass in NULL for fptr().
775: PetscObjectComposeFunction() can be used with any PETSc object (such as
776: `Mat`, `Vec`, `KSP`, `SNES`, etc.) or any user-provided object.
778: `PetscCallMethod()` is used to call a function that is stored in the objects obj->ops table.
780: .seealso: `PetscObjectQueryFunction()`, `PetscContainerCreate()` `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscTryMethod()`, `PetscUseMethod()`,
781: `PetscCallMethod()`
782: M*/
784: PetscErrorCode PetscObjectComposeFunction_Private(PetscObject obj, const char name[], void (*fptr)(void))
785: {
788: (*obj->bops->composefunction)(obj, name, fptr);
789: return 0;
790: }
792: /*MC
793: PetscObjectQueryFunction - Gets a function associated with a given object.
795: Synopsis:
796: #include <petscsys.h>
797: PetscErrorCode PetscObjectQueryFunction(PetscObject obj,const char name[],void (**fptr)(void))
799: Logically Collective on obj
801: Input Parameters:
802: + obj - the PETSc object; this must be cast with (`PetscObject`), for example,
803: `PetscObjectQueryFunction`((`PetscObject`)ksp,...);
804: - name - name associated with the child function
806: Output Parameter:
807: . fptr - function pointer
809: Level: advanced
811: .seealso: `PetscObjectComposeFunction()`, `PetscFunctionListFind()`, `PetscObjectCompose()`, `PetscObjectQuery()`
812: M*/
813: PETSC_EXTERN PetscErrorCode PetscObjectQueryFunction_Private(PetscObject obj, const char name[], void (**ptr)(void))
814: {
817: (*obj->bops->queryfunction)(obj, name, ptr);
818: return 0;
819: }
821: struct _p_PetscContainer {
822: PETSCHEADER(int);
823: void *ptr;
824: PetscErrorCode (*userdestroy)(void *);
825: };
827: /*@C
828: PetscContainerUserDestroyDefault - Default destroy routine for user-provided data that simply calls `PetscFree()` in the data
829: provided with `PetscContainerSetPointer()`
831: Logically Collective on the `PetscContainer` containing the user data
833: Input Parameter:
834: . ctx - pointer to user-provided data
836: Level: advanced
838: .seealso: `PetscContainerDestroy()`, `PetscContainerSetUserDestroy()`
839: @*/
840: PetscErrorCode PetscContainerUserDestroyDefault(void *ctx)
841: {
842: PetscFree(ctx);
843: return 0;
844: }
846: /*@C
847: PetscContainerGetPointer - Gets the pointer value contained in the container that was provided with `PetscContainerSetPointer()`
849: Not Collective
851: Input Parameter:
852: . obj - the object created with `PetscContainerCreate()`
854: Output Parameter:
855: . ptr - the pointer value
857: Level: advanced
859: .seealso: `PetscContainerCreate()`, `PetscContainerDestroy()`,
860: `PetscContainerSetPointer()`
861: @*/
862: PetscErrorCode PetscContainerGetPointer(PetscContainer obj, void **ptr)
863: {
866: *ptr = obj->ptr;
867: return 0;
868: }
870: /*@C
871: PetscContainerSetPointer - Sets the pointer value contained in the container.
873: Logically Collective on obj
875: Input Parameters:
876: + obj - the object created with `PetscContainerCreate()`
877: - ptr - the pointer value
879: Level: advanced
881: .seealso: `PetscContainerCreate()`, `PetscContainerDestroy()`, `PetscObjectCompose()`, `PetscObjectQuery()`,
882: `PetscContainerGetPointer()`
883: @*/
884: PetscErrorCode PetscContainerSetPointer(PetscContainer obj, void *ptr)
885: {
888: obj->ptr = ptr;
889: return 0;
890: }
892: /*@C
893: PetscContainerDestroy - Destroys a PETSc container object.
895: Collective on obj
897: Input Parameter:
898: . obj - an object that was created with `PetscContainerCreate()`
900: Level: advanced
902: Note:
903: If `PetscContainerSetUserDestroy()` was used to provide a user destroy object for the data provided with `PetscContainerSetPointer()`
904: then that function is called to destroy the data.
906: .seealso: `PetscContainerCreate()`, `PetscContainerSetUserDestroy()`
907: @*/
908: PetscErrorCode PetscContainerDestroy(PetscContainer *obj)
909: {
910: if (!*obj) return 0;
912: if (--((PetscObject)(*obj))->refct > 0) {
913: *obj = NULL;
914: return 0;
915: }
916: if ((*obj)->userdestroy) (*(*obj)->userdestroy)((*obj)->ptr);
917: PetscHeaderDestroy(obj);
918: return 0;
919: }
921: /*@C
922: PetscContainerSetUserDestroy - Sets name of the user destroy function for the data provided to the `PetscContainer` with `PetscContainerSetPointer()`
924: Logically Collective on obj
926: Input Parameters:
927: + obj - an object that was created with `PetscContainerCreate()`
928: - des - name of the user destroy function
930: Note:
931: Use `PetscContainerUserDestroyDefault()` if the memory was obtained by calling `PetscMalloc()` or one of its variants for single memory allocation.
933: Level: advanced
935: .seealso: `PetscContainerDestroy()`, `PetscContainerUserDestroyDefault()`, `PetscMalloc()`, `PetscMalloc1()`, `PetscCalloc()`, `PetscCalloc1()`
936: @*/
937: PetscErrorCode PetscContainerSetUserDestroy(PetscContainer obj, PetscErrorCode (*des)(void *))
938: {
940: obj->userdestroy = des;
941: return 0;
942: }
944: PetscClassId PETSC_CONTAINER_CLASSID;
946: /*@C
947: PetscContainerCreate - Creates a PETSc object that has room to hold
948: a single pointer. This allows one to attach any type of data (accessible
949: through a pointer) with the `PetscObjectCompose()` function to a `PetscObject`.
950: The data item itself is attached by a call to `PetscContainerSetPointer()`.
952: Collective
954: Input Parameters:
955: . comm - MPI communicator that shares the object
957: Output Parameters:
958: . container - the container created
960: Level: advanced
962: .seealso: `PetscContainerDestroy()`, `PetscContainerSetPointer()`, `PetscContainerGetPointer()`, `PetscObjectCompose()`, `PetscObjectQuery()`,
963: `PetscContainerSetUserDestroy()`
964: @*/
965: PetscErrorCode PetscContainerCreate(MPI_Comm comm, PetscContainer *container)
966: {
968: PetscSysInitializePackage();
969: PetscHeaderCreate(*container, PETSC_CONTAINER_CLASSID, "PetscContainer", "Container", "Sys", comm, PetscContainerDestroy, NULL);
970: return 0;
971: }
973: /*@
974: PetscObjectSetFromOptions - Sets generic parameters from user options.
976: Collective on obj
978: Input Parameter:
979: . obj - the `PetscObject`
981: Note:
982: We have no generic options at present, so this does nothing
984: Level: beginner
986: .seealso: `PetscObjectSetOptionsPrefix()`, `PetscObjectGetOptionsPrefix()`
987: @*/
988: PetscErrorCode PetscObjectSetFromOptions(PetscObject obj)
989: {
991: return 0;
992: }
994: /*@
995: PetscObjectSetUp - Sets up the internal data structures for the later use.
997: Collective on obj
999: Input Parameters:
1000: . obj - the `PetscObject`
1002: Note:
1003: This does nothing at present.
1005: Level: advanced
1007: .seealso: `PetscObjectDestroy()`
1008: @*/
1009: PetscErrorCode PetscObjectSetUp(PetscObject obj)
1010: {
1012: return 0;
1013: }