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: 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;
50: h->bops->compose = PetscObjectCompose_Petsc;
51: h->bops->query = PetscObjectQuery_Petsc;
52: h->bops->composefunction = PetscObjectComposeFunction_Petsc;
53: h->bops->queryfunction = PetscObjectQueryFunction_Petsc;
55: PetscCommDuplicate(comm, &h->comm, &h->tag);
57: /* Increment and store current object creation index */
58: MPI_Comm_get_attr(h->comm, Petsc_CreationIdx_keyval, &get_tmp, &flg);
59: if (flg) {
60: cidx = (PetscInt64 *)get_tmp;
61: h->cidx = (*cidx)++;
62: MPI_Comm_set_attr(h->comm, Petsc_CreationIdx_keyval, cidx);
63: } else SETERRQ(h->comm, PETSC_ERR_ARG_CORRUPT, "MPI_Comm does not have an object creation index");
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: return 0;
76: }
77: }
78: /* Need to increase the space for storing PETSc objects */
79: if (!PetscObjectsMaxCounts) newPetscObjectsMaxCounts = 100;
80: else newPetscObjectsMaxCounts = 2 * PetscObjectsMaxCounts;
81: PetscCalloc1(newPetscObjectsMaxCounts, &newPetscObjects);
82: PetscArraycpy(newPetscObjects, PetscObjects, PetscObjectsMaxCounts);
83: PetscFree(PetscObjects);
85: PetscObjects = newPetscObjects;
86: PetscObjects[PetscObjectsMaxCounts] = h;
87: PetscObjectsMaxCounts = newPetscObjectsMaxCounts;
88: }
89: #endif
90: return 0;
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: {
103: PetscLogObjectDestroy(obj);
104: PetscComposedQuantitiesDestroy(obj);
105: if (PetscMemoryCollectMaximumUsage) {
106: PetscLogDouble usage;
108: PetscMemoryGetCurrentUsage(&usage);
109: if (usage > PetscMemoryMaximumUsage) PetscMemoryMaximumUsage = usage;
110: }
111: /* first destroy things that could execute arbitrary code */
112: if (obj->python_destroy) {
113: void *python_context = obj->python_context;
114: PetscErrorCode (*python_destroy)(void *) = obj->python_destroy;
116: obj->python_context = NULL;
117: obj->python_destroy = NULL;
118: (*python_destroy)(python_context);
119: }
120: PetscObjectDestroyOptionsHandlers(obj);
121: PetscObjectListDestroy(&obj->olist);
123: /* destroy allocated quantities */
124: if (PetscPrintFunctionList) PetscFunctionListPrintNonEmpty(obj->qlist);
126: PetscFree(obj->name);
127: PetscFree(obj->prefix);
128: PetscFree(obj->type_name);
130: if (clear_for_reuse) {
131: /* we will assume that obj->bops->view and destroy are safe to leave as-is */
132: obj->bops->compose = PetscObjectCompose_Petsc;
133: obj->bops->query = PetscObjectQuery_Petsc;
134: obj->bops->composefunction = PetscObjectComposeFunction_Petsc;
135: obj->bops->queryfunction = PetscObjectQueryFunction_Petsc;
137: /* reset quantities, in order of appearance in _p_PetscObject */
138: obj->id = PetscObjectNewId_Internal();
139: obj->refct = 1;
140: obj->tablevel = 0;
141: obj->state = 0;
142: /* don't deallocate, zero these out instead */
143: PetscFunctionListClear(obj->qlist);
144: PetscArrayzero(obj->fortran_func_pointers, obj->num_fortran_func_pointers);
145: PetscArrayzero(obj->fortrancallback[PETSC_FORTRAN_CALLBACK_CLASS], obj->num_fortrancallback[PETSC_FORTRAN_CALLBACK_CLASS]);
146: PetscArrayzero(obj->fortrancallback[PETSC_FORTRAN_CALLBACK_SUBTYPE], obj->num_fortrancallback[PETSC_FORTRAN_CALLBACK_SUBTYPE]);
147: obj->optionsprinted = PETSC_FALSE;
148: #if PetscDefined(HAVE_SAWS)
149: obj->amsmem = PETSC_FALSE;
150: obj->amspublishblock = PETSC_FALSE;
151: #endif
152: obj->options = NULL;
153: obj->donotPetscObjectPrintClassNamePrefixType = PETSC_FALSE;
154: } else {
155: PetscFunctionListDestroy(&obj->qlist);
156: PetscFree(obj->fortran_func_pointers);
157: PetscFree(obj->fortrancallback[PETSC_FORTRAN_CALLBACK_CLASS]);
158: PetscFree(obj->fortrancallback[PETSC_FORTRAN_CALLBACK_SUBTYPE]);
159: PetscCommDestroy(&obj->comm);
160: obj->classid = PETSCFREEDHEADER;
162: #if PetscDefined(USE_LOG)
163: if (PetscObjectsLog) {
164: /* Record object removal from list of all objects */
165: for (PetscInt i = 0; i < PetscObjectsMaxCounts; ++i) {
166: if (PetscObjects[i] == obj) {
167: PetscObjects[i] = NULL;
168: --PetscObjectsCounts;
169: break;
170: }
171: }
172: if (!PetscObjectsCounts) {
173: PetscFree(PetscObjects);
174: PetscObjectsMaxCounts = 0;
175: }
176: }
177: #endif
178: }
179: return 0;
180: }
182: /*
183: PetscHeaderReset_Internal - "Reset" a PetscObject header. This is tantamount to destroying
184: the object but does not free all resources. The object retains its:
186: - classid
187: - bops->view
188: - bops->destroy
189: - comm
190: - tag
191: - class_name
192: - description
193: - mansec
194: - cpp
196: Note that while subclass information is lost, superclass info remains. Thus this function is
197: intended to be used to reuse a PetscObject within the same class to avoid reallocating its
198: resources.
199: */
200: PetscErrorCode PetscHeaderReset_Internal(PetscObject obj)
201: {
202: PetscHeaderDestroy_Private(obj, PETSC_TRUE);
203: return 0;
204: }
206: /*@C
207: PetscObjectCopyFortranFunctionPointers - Copy function pointers to another object
209: Logically Collective
211: Input Parameters:
212: + src - source object
213: - dest - destination object
215: Level: developer
217: Note:
218: Both objects must have the same class.
220: This is used to help manage user callback functions that were provided in Fortran
221: @*/
222: PetscErrorCode PetscObjectCopyFortranFunctionPointers(PetscObject src, PetscObject dest)
223: {
224: PetscFortranCallbackId cbtype, numcb[PETSC_FORTRAN_CALLBACK_MAXTYPE];
230: PetscFree(dest->fortran_func_pointers);
231: PetscMalloc(src->num_fortran_func_pointers * sizeof(void (*)(void)), &dest->fortran_func_pointers);
232: PetscMemcpy(dest->fortran_func_pointers, src->fortran_func_pointers, src->num_fortran_func_pointers * sizeof(void (*)(void)));
234: dest->num_fortran_func_pointers = src->num_fortran_func_pointers;
236: PetscFortranCallbackGetSizes(src->classid, &numcb[PETSC_FORTRAN_CALLBACK_CLASS], &numcb[PETSC_FORTRAN_CALLBACK_SUBTYPE]);
237: for (cbtype = PETSC_FORTRAN_CALLBACK_CLASS; cbtype < PETSC_FORTRAN_CALLBACK_MAXTYPE; cbtype++) {
238: PetscFree(dest->fortrancallback[cbtype]);
239: PetscCalloc1(numcb[cbtype], &dest->fortrancallback[cbtype]);
240: PetscMemcpy(dest->fortrancallback[cbtype], src->fortrancallback[cbtype], src->num_fortrancallback[cbtype] * sizeof(PetscFortranCallback));
241: dest->num_fortrancallback[cbtype] = src->num_fortrancallback[cbtype];
242: }
243: return 0;
244: }
246: /*@C
247: PetscObjectSetFortranCallback - set fortran callback function pointer and context
249: Logically Collective
251: Input Parameters:
252: + obj - object on which to set callback
253: . cbtype - callback type (class or subtype)
254: . cid - address of callback Id, updated if not yet initialized (zero)
255: . func - Fortran function
256: - ctx - Fortran context
258: Level: developer
260: Note:
261: This is used to help manage user callback functions that were provided in Fortran
263: .seealso: `PetscObjectGetFortranCallback()`
264: @*/
265: PetscErrorCode PetscObjectSetFortranCallback(PetscObject obj, PetscFortranCallbackType cbtype, PetscFortranCallbackId *cid, void (*func)(void), void *ctx)
266: {
267: const char *subtype = NULL;
270: if (cbtype == PETSC_FORTRAN_CALLBACK_SUBTYPE) subtype = obj->type_name;
271: if (!*cid) PetscFortranCallbackRegister(obj->classid, subtype, cid);
272: if (*cid >= PETSC_SMALLEST_FORTRAN_CALLBACK + obj->num_fortrancallback[cbtype]) {
273: PetscFortranCallbackId oldnum = obj->num_fortrancallback[cbtype];
274: PetscFortranCallbackId newnum = PetscMax(*cid - PETSC_SMALLEST_FORTRAN_CALLBACK + 1, 2 * oldnum);
275: PetscFortranCallback *callback;
276: PetscMalloc1(newnum, &callback);
277: PetscMemcpy(callback, obj->fortrancallback[cbtype], oldnum * sizeof(*obj->fortrancallback[cbtype]));
278: PetscFree(obj->fortrancallback[cbtype]);
280: obj->fortrancallback[cbtype] = callback;
281: obj->num_fortrancallback[cbtype] = newnum;
282: }
283: obj->fortrancallback[cbtype][*cid - PETSC_SMALLEST_FORTRAN_CALLBACK].func = func;
284: obj->fortrancallback[cbtype][*cid - PETSC_SMALLEST_FORTRAN_CALLBACK].ctx = ctx;
285: return 0;
286: }
288: /*@C
289: PetscObjectGetFortranCallback - get fortran callback function pointer and context
291: Logically Collective
293: Input Parameters:
294: + obj - object on which to get callback
295: . cbtype - callback type
296: - cid - address of callback Id
298: Output Parameters:
299: + func - Fortran function (or NULL if not needed)
300: - ctx - Fortran context (or NULL if not needed)
302: Level: developer
304: Note:
305: This is used to help manage user callback functions that were provided in Fortran
307: .seealso: `PetscObjectSetFortranCallback()`
308: @*/
309: PetscErrorCode PetscObjectGetFortranCallback(PetscObject obj, PetscFortranCallbackType cbtype, PetscFortranCallbackId cid, void (**func)(void), void **ctx)
310: {
311: PetscFortranCallback *cb;
316: cb = &obj->fortrancallback[cbtype][cid - PETSC_SMALLEST_FORTRAN_CALLBACK];
317: if (func) *func = cb->func;
318: if (ctx) *ctx = cb->ctx;
319: return 0;
320: }
322: #if defined(PETSC_USE_LOG)
323: /*@C
324: PetscObjectsDump - Prints all the currently existing objects.
326: On rank 0 of `PETSC_COMM_WORLD` prints the values
328: Input Parameters:
329: + fd - file pointer
330: - all - by default only tries to display objects created explicitly by the user, if all is `PETSC_TRUE` then lists all outstanding objects
332: Options Database Key:
333: . -objects_dump <all> - print information about all the objects that exist at the end of the programs run
335: Level: advanced
337: @*/
338: PetscErrorCode PetscObjectsDump(FILE *fd, PetscBool all)
339: {
340: PetscInt i;
341: #if defined(PETSC_USE_DEBUG)
342: PetscInt j, k = 0;
343: #endif
344: PetscObject h;
346: if (PetscObjectsCounts) {
347: PetscFPrintf(PETSC_COMM_WORLD, fd, "The following objects were never freed\n");
348: PetscFPrintf(PETSC_COMM_WORLD, fd, "-----------------------------------------\n");
349: for (i = 0; i < PetscObjectsMaxCounts; i++) {
350: if ((h = PetscObjects[i])) {
351: PetscObjectName(h);
352: {
353: #if defined(PETSC_USE_DEBUG)
354: PetscStack *stack = NULL;
355: char *create, *rclass;
357: /* if the PETSc function the user calls is not a create then this object was NOT directly created by them */
358: PetscMallocGetStack(h, &stack);
359: if (stack) {
360: k = stack->currentsize - 2;
361: if (!all) {
362: k = 0;
363: while (!stack->petscroutine[k]) k++;
364: PetscStrstr(stack->function[k], "Create", &create);
365: if (!create) PetscStrstr(stack->function[k], "Get", &create);
366: PetscStrstr(stack->function[k], h->class_name, &rclass);
367: if (!create) continue;
368: if (!rclass) continue;
369: }
370: }
371: #endif
373: PetscFPrintf(PETSC_COMM_WORLD, fd, "[%d] %s %s %s\n", PetscGlobalRank, h->class_name, h->type_name, h->name);
375: #if defined(PETSC_USE_DEBUG)
376: 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: #endif
381: }
382: }
383: }
384: }
385: return 0;
386: }
387: #endif
389: #if defined(PETSC_USE_LOG)
391: /*@C
392: PetscObjectsView - Prints the currently existing objects.
394: Logically Collective
396: Input Parameter:
397: . viewer - must be an `PETSCVIEWERASCII` viewer
399: Level: advanced
401: @*/
402: PetscErrorCode PetscObjectsView(PetscViewer viewer)
403: {
404: PetscBool isascii;
405: FILE *fd;
407: if (!viewer) viewer = PETSC_VIEWER_STDOUT_WORLD;
408: PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii);
410: PetscViewerASCIIGetPointer(viewer, &fd);
411: PetscObjectsDump(fd, PETSC_TRUE);
412: return 0;
413: }
415: /*@C
416: PetscObjectsGetObject - Get a pointer to a named object
418: Not collective
420: Input Parameter:
421: . name - the name of an object
423: Output Parameters:
424: + obj - the object or null if there is no object
425: - classname - the name of the class
427: Level: advanced
429: @*/
430: PetscErrorCode PetscObjectsGetObject(const char *name, PetscObject *obj, char **classname)
431: {
432: PetscInt i;
433: PetscObject h;
434: PetscBool flg;
438: *obj = NULL;
439: for (i = 0; i < PetscObjectsMaxCounts; i++) {
440: if ((h = PetscObjects[i])) {
441: PetscObjectName(h);
442: PetscStrcmp(h->name, name, &flg);
443: if (flg) {
444: *obj = h;
445: if (classname) *classname = h->class_name;
446: return 0;
447: }
448: }
449: }
450: return 0;
451: }
452: #endif
454: /*@
455: 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
457: Input Parameters:
458: . obj - the `PetscObject`
460: Level: developer
462: Developer Note:
463: This is used, for example to prevent sequential objects that are created from a parallel object; such as the `KSP` created by
464: `PCBJACOBI` from all printing the same help messages to the screen
466: .seealso: `PetscOptionsInsert()`
467: @*/
468: PetscErrorCode PetscObjectSetPrintedOptions(PetscObject obj)
469: {
471: obj->optionsprinted = PETSC_TRUE;
472: return 0;
473: }
475: /*@
476: PetscObjectInheritPrintedOptions - If the child object is not on the rank 0 process of the parent object and the child is sequential then the child gets it set.
478: Input Parameters:
479: + pobj - the parent object
480: - obj - the PetscObject
482: Level: developer
484: Developer Notes:
485: This is used, for example to prevent sequential objects that are created from a parallel object; such as the `KSP` created by
486: `PCBJACOBI` from all printing the same help messages to the screen
488: This will not handle more complicated situations like with `PCGASM` where children may live on any subset of the parent's processes and overlap
490: .seealso: `PetscOptionsInsert()`, `PetscObjectSetPrintedOptions()`
491: @*/
492: PetscErrorCode PetscObjectInheritPrintedOptions(PetscObject pobj, PetscObject obj)
493: {
494: PetscMPIInt prank, size;
498: MPI_Comm_rank(pobj->comm, &prank);
499: MPI_Comm_size(obj->comm, &size);
500: if (size == 1 && prank > 0) obj->optionsprinted = PETSC_TRUE;
501: return 0;
502: }
504: /*@C
505: PetscObjectAddOptionsHandler - Adds an additional function to check for options when XXXSetFromOptions() is called.
507: Not Collective
509: Input Parameters:
510: + obj - the PETSc object
511: . handle - function that checks for options
512: . destroy - function to destroy context if provided
513: - ctx - optional context for check function
515: Level: developer
517: .seealso: `KSPSetFromOptions()`, `PCSetFromOptions()`, `SNESSetFromOptions()`, `PetscObjectProcessOptionsHandlers()`, `PetscObjectDestroyOptionsHandlers()`
518: @*/
519: PetscErrorCode PetscObjectAddOptionsHandler(PetscObject obj, PetscErrorCode (*handle)(PetscObject, PetscOptionItems *, void *), PetscErrorCode (*destroy)(PetscObject, void *), void *ctx)
520: {
523: obj->optionhandler[obj->noptionhandler] = handle;
524: obj->optiondestroy[obj->noptionhandler] = destroy;
525: obj->optionctx[obj->noptionhandler++] = ctx;
526: return 0;
527: }
529: /*@C
530: PetscObjectProcessOptionsHandlers - Calls all the options handlers attached to an object
532: Not Collective
534: Input Parameters:
535: + obj - the PETSc object
536: - PetscOptionsObject - the options context
538: Level: developer
540: .seealso: `KSPSetFromOptions()`, `PCSetFromOptions()`, `SNESSetFromOptions()`, `PetscObjectAddOptionsHandler()`, `PetscObjectDestroyOptionsHandlers()`
541: @*/
542: PetscErrorCode PetscObjectProcessOptionsHandlers(PetscObject obj, PetscOptionItems *PetscOptionsObject)
543: {
545: for (PetscInt i = 0; i < obj->noptionhandler; i++) (*obj->optionhandler[i])(obj, PetscOptionsObject, obj->optionctx[i]);
546: return 0;
547: }
549: /*@C
550: PetscObjectDestroyOptionsHandlers - Destroys all the option handlers attached to an object
552: Not Collective
554: Input Parameter:
555: . obj - the PETSc object
557: Level: developer
559: .seealso: `KSPSetFromOptions()`, `PCSetFromOptions()`, `SNESSetFromOptions()`, `PetscObjectAddOptionsHandler()`, `PetscObjectProcessOptionsHandlers()`
560: @*/
561: PetscErrorCode PetscObjectDestroyOptionsHandlers(PetscObject obj)
562: {
564: for (PetscInt i = 0; i < obj->noptionhandler; i++) {
565: if (obj->optiondestroy[i]) (*obj->optiondestroy[i])(obj, obj->optionctx[i]);
566: }
567: obj->noptionhandler = 0;
568: return 0;
569: }
571: /*@C
572: PetscObjectReference - Indicates to any `PetscObject` that it is being
573: referenced by another `PetscObject`. This increases the reference
574: count for that object by one.
576: Logically Collective
578: Input Parameter:
579: . obj - the PETSc object. This must be cast with (`PetscObject`), for example,
580: `PetscObjectReference`((`PetscObject`)mat);
582: Level: advanced
584: .seealso: `PetscObjectCompose()`, `PetscObjectDereference()`
585: @*/
586: PetscErrorCode PetscObjectReference(PetscObject obj)
587: {
588: if (!obj) return 0;
590: obj->refct++;
591: return 0;
592: }
594: /*@C
595: PetscObjectGetReference - Gets the current reference count for
596: any PETSc object.
598: Not Collective
600: Input Parameter:
601: . obj - the PETSc object; this must be cast with (`PetscObject`), for example,
602: `PetscObjectGetReference`((`PetscObject`)mat,&cnt);
604: Output Parameter:
605: . cnt - the reference count
607: Level: advanced
609: .seealso: `PetscObjectCompose()`, `PetscObjectDereference()`, `PetscObjectReference()`
610: @*/
611: PetscErrorCode PetscObjectGetReference(PetscObject obj, PetscInt *cnt)
612: {
615: *cnt = obj->refct;
616: return 0;
617: }
619: /*@C
620: PetscObjectDereference - Indicates to any `PetscObject` that it is being
621: referenced by one less `PetscObject`. This decreases the reference
622: count for that object by one.
624: Collective on obj if reference reaches 0 otherwise Logically Collective
626: Input Parameter:
627: . obj - the PETSc object; this must be cast with (`PetscObject`), for example,
628: `PetscObjectDereference`((`PetscObject`)mat);
630: Note:
631: `PetscObjectDestroy()` sets the obj pointer to null after the call, this routine does not.
633: Level: advanced
635: .seealso: `PetscObjectCompose()`, `PetscObjectReference()`, `PetscObjectDestroy()`
636: @*/
637: PetscErrorCode PetscObjectDereference(PetscObject obj)
638: {
639: if (!obj) return 0;
641: if (obj->bops->destroy) (*obj->bops->destroy)(&obj);
643: return 0;
644: }
646: /* ----------------------------------------------------------------------- */
647: /*
648: The following routines are the versions private to the PETSc object
649: data structures.
650: */
651: PetscErrorCode PetscObjectRemoveReference(PetscObject obj, const char name[])
652: {
654: PetscObjectListRemoveReference(&obj->olist, name);
655: return 0;
656: }
658: PetscErrorCode PetscObjectCompose_Petsc(PetscObject obj, const char name[], PetscObject ptr)
659: {
660: if (ptr) {
661: char *tname;
662: PetscBool skipreference;
664: PetscObjectListReverseFind(ptr->olist, obj, &tname, &skipreference);
666: }
667: PetscObjectListAdd(&obj->olist, name, ptr);
668: return 0;
669: }
671: PetscErrorCode PetscObjectQuery_Petsc(PetscObject obj, const char name[], PetscObject *ptr)
672: {
674: PetscObjectListFind(obj->olist, name, ptr);
675: return 0;
676: }
678: PetscErrorCode PetscObjectComposeFunction_Petsc(PetscObject obj, const char name[], void (*ptr)(void))
679: {
681: PetscFunctionListAdd(&obj->qlist, name, ptr);
682: return 0;
683: }
685: PetscErrorCode PetscObjectQueryFunction_Petsc(PetscObject obj, const char name[], void (**ptr)(void))
686: {
688: PetscFunctionListFind(obj->qlist, name, ptr);
689: return 0;
690: }
692: /*@C
693: PetscObjectCompose - Associates another PETSc object with a given PETSc object.
695: Not Collective
697: Input Parameters:
698: + obj - the PETSc object; this must be cast with (`PetscObject`), for example,
699: `PetscObjectCompose`((`PetscObject`)mat,...);
700: . name - name associated with the child object
701: - ptr - the other PETSc object to associate with the PETSc object; this must also be
702: cast with (`PetscObject`)
704: Level: advanced
706: Notes:
707: The second objects reference count is automatically increased by one when it is
708: composed.
710: Replaces any previous object that had the same name.
712: If ptr is null and name has previously been composed using an object, then that
713: entry is removed from the obj.
715: `PetscObjectCompose()` can be used with any PETSc object (such as
716: `Mat`, `Vec`, `KSP`, `SNES`, etc.) or any user-provided object.
718: `PetscContainerCreate()` can be used to create an object from a
719: user-provided pointer that may then be composed with PETSc objects using `PetscObjectCompose()`
721: .seealso: `PetscObjectQuery()`, `PetscContainerCreate()`, `PetscObjectComposeFunction()`, `PetscObjectQueryFunction()`, `PetscContainer`,
722: `PetscContainerSetPointer()`
723: @*/
724: PetscErrorCode PetscObjectCompose(PetscObject obj, const char name[], PetscObject ptr)
725: {
730: (*obj->bops->compose)(obj, name, ptr);
731: return 0;
732: }
734: /*@C
735: PetscObjectQuery - Gets a PETSc object associated with a given object that was composed with `PetscObjectCompose()`
737: Not Collective
739: Input Parameters:
740: + obj - the PETSc object
741: Thus must be cast with a (`PetscObject`), for example,
742: `PetscObjectCompose`((`PetscObject`)mat,...);
743: . name - name associated with child object
744: - ptr - the other PETSc object associated with the PETSc object, this must be
745: cast with (`PetscObject`*)
747: Level: advanced
749: Note:
750: The reference count of neither object is increased in this call
752: .seealso: `PetscObjectCompose()`, `PetscObjectComposeFunction()`, `PetscObjectQueryFunction()`, `PetscContainer`
753: `PetscContainerGetPointer()`
754: @*/
755: PetscErrorCode PetscObjectQuery(PetscObject obj, const char name[], PetscObject *ptr)
756: {
760: (*obj->bops->query)(obj, name, ptr);
761: return 0;
762: }
764: /*MC
765: PetscObjectComposeFunction - Associates a function with a given PETSc object.
767: Synopsis:
768: #include <petscsys.h>
769: PetscErrorCode PetscObjectComposeFunction(PetscObject obj, const char name[], void (*fptr)(void))
771: Logically Collective
773: Input Parameters:
774: + obj - the PETSc object; this must be cast with a (`PetscObject`), for example,
775: `PetscObjectCompose`((`PetscObject`)mat,...);
776: . name - name associated with the child function
777: - fptr - function pointer
779: Level: advanced
781: Notes:
782: When the first argument of `fptr` is (or is derived from) a `PetscObject` then `PetscTryMethod()` and `PetscUseMethod()`
783: can be used to call the function directly with error checking.
785: To remove a registered routine, pass in `NULL` for `fptr`.
787: `PetscObjectComposeFunction()` can be used with any PETSc object (such as
788: `Mat`, `Vec`, `KSP`, `SNES`, etc.) or any user-provided object.
790: `PetscCallMethod()` is used to call a function that is stored in the objects `obj->ops` table.
792: .seealso: `PetscObjectQueryFunction()`, `PetscContainerCreate()` `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscTryMethod()`, `PetscUseMethod()`,
793: `PetscCallMethod()`
794: M*/
796: PetscErrorCode PetscObjectComposeFunction_Private(PetscObject obj, const char name[], void (*fptr)(void))
797: {
800: (*obj->bops->composefunction)(obj, name, fptr);
801: return 0;
802: }
804: /*MC
805: PetscObjectQueryFunction - Gets a function associated with a given object.
807: Synopsis:
808: #include <petscsys.h>
809: PetscErrorCode PetscObjectQueryFunction(PetscObject obj,const char name[],void (**fptr)(void))
811: Logically Collective
813: Input Parameters:
814: + obj - the PETSc object; this must be cast with (`PetscObject`), for example,
815: `PetscObjectQueryFunction`((`PetscObject`)ksp,...);
816: - name - name associated with the child function
818: Output Parameter:
819: . fptr - function pointer
821: Level: advanced
823: .seealso: `PetscObjectComposeFunction()`, `PetscFunctionListFind()`, `PetscObjectCompose()`, `PetscObjectQuery()`
824: M*/
825: PETSC_EXTERN PetscErrorCode PetscObjectQueryFunction_Private(PetscObject obj, const char name[], void (**ptr)(void))
826: {
829: (*obj->bops->queryfunction)(obj, name, ptr);
830: return 0;
831: }
833: struct _p_PetscContainer {
834: PETSCHEADER(int);
835: void *ptr;
836: PetscErrorCode (*userdestroy)(void *);
837: };
839: /*@C
840: PetscContainerUserDestroyDefault - Default destroy routine for user-provided data that simply calls `PetscFree()` in the data
841: provided with `PetscContainerSetPointer()`
843: Logically Collective on the `PetscContainer` containing the user data
845: Input Parameter:
846: . ctx - pointer to user-provided data
848: Level: advanced
850: .seealso: `PetscContainerDestroy()`, `PetscContainerSetUserDestroy()`
851: @*/
852: PetscErrorCode PetscContainerUserDestroyDefault(void *ctx)
853: {
854: PetscFree(ctx);
855: return 0;
856: }
858: /*@C
859: PetscContainerGetPointer - Gets the pointer value contained in the container that was provided with `PetscContainerSetPointer()`
861: Not Collective
863: Input Parameter:
864: . obj - the object created with `PetscContainerCreate()`
866: Output Parameter:
867: . ptr - the pointer value
869: Level: advanced
871: .seealso: `PetscContainerCreate()`, `PetscContainerDestroy()`,
872: `PetscContainerSetPointer()`
873: @*/
874: PetscErrorCode PetscContainerGetPointer(PetscContainer obj, void **ptr)
875: {
878: *ptr = obj->ptr;
879: return 0;
880: }
882: /*@C
883: PetscContainerSetPointer - Sets the pointer value contained in the container.
885: Logically Collective
887: Input Parameters:
888: + obj - the object created with `PetscContainerCreate()`
889: - ptr - the pointer value
891: Level: advanced
893: .seealso: `PetscContainerCreate()`, `PetscContainerDestroy()`, `PetscObjectCompose()`, `PetscObjectQuery()`,
894: `PetscContainerGetPointer()`
895: @*/
896: PetscErrorCode PetscContainerSetPointer(PetscContainer obj, void *ptr)
897: {
900: obj->ptr = ptr;
901: return 0;
902: }
904: /*@C
905: PetscContainerDestroy - Destroys a PETSc container object.
907: Collective
909: Input Parameter:
910: . obj - an object that was created with `PetscContainerCreate()`
912: Level: advanced
914: Note:
915: If `PetscContainerSetUserDestroy()` was used to provide a user destroy object for the data provided with `PetscContainerSetPointer()`
916: then that function is called to destroy the data.
918: .seealso: `PetscContainerCreate()`, `PetscContainerSetUserDestroy()`
919: @*/
920: PetscErrorCode PetscContainerDestroy(PetscContainer *obj)
921: {
922: if (!*obj) return 0;
924: if (--((PetscObject)(*obj))->refct > 0) {
925: *obj = NULL;
926: return 0;
927: }
928: if ((*obj)->userdestroy) (*(*obj)->userdestroy)((*obj)->ptr);
929: PetscHeaderDestroy(obj);
930: return 0;
931: }
933: /*@C
934: PetscContainerSetUserDestroy - Sets name of the user destroy function for the data provided to the `PetscContainer` with `PetscContainerSetPointer()`
936: Logically Collective
938: Input Parameters:
939: + obj - an object that was created with `PetscContainerCreate()`
940: - des - name of the user destroy function
942: Note:
943: Use `PetscContainerUserDestroyDefault()` if the memory was obtained by calling `PetscMalloc()` or one of its variants for single memory allocation.
945: Level: advanced
947: .seealso: `PetscContainerDestroy()`, `PetscContainerUserDestroyDefault()`, `PetscMalloc()`, `PetscMalloc1()`, `PetscCalloc()`, `PetscCalloc1()`
948: @*/
949: PetscErrorCode PetscContainerSetUserDestroy(PetscContainer obj, PetscErrorCode (*des)(void *))
950: {
952: obj->userdestroy = des;
953: return 0;
954: }
956: PetscClassId PETSC_CONTAINER_CLASSID;
958: /*@C
959: PetscContainerCreate - Creates a PETSc object that has room to hold
960: a single pointer. This allows one to attach any type of data (accessible
961: through a pointer) with the `PetscObjectCompose()` function to a `PetscObject`.
962: The data item itself is attached by a call to `PetscContainerSetPointer()`.
964: Collective
966: Input Parameters:
967: . comm - MPI communicator that shares the object
969: Output Parameters:
970: . container - the container created
972: Level: advanced
974: .seealso: `PetscContainerDestroy()`, `PetscContainerSetPointer()`, `PetscContainerGetPointer()`, `PetscObjectCompose()`, `PetscObjectQuery()`,
975: `PetscContainerSetUserDestroy()`
976: @*/
977: PetscErrorCode PetscContainerCreate(MPI_Comm comm, PetscContainer *container)
978: {
980: PetscSysInitializePackage();
981: PetscHeaderCreate(*container, PETSC_CONTAINER_CLASSID, "PetscContainer", "Container", "Sys", comm, PetscContainerDestroy, NULL);
982: return 0;
983: }
985: /*@
986: PetscObjectSetFromOptions - Sets generic parameters from user options.
988: Collective
990: Input Parameter:
991: . obj - the `PetscObject`
993: Note:
994: We have no generic options at present, so this does nothing
996: Level: beginner
998: .seealso: `PetscObjectSetOptionsPrefix()`, `PetscObjectGetOptionsPrefix()`
999: @*/
1000: PetscErrorCode PetscObjectSetFromOptions(PetscObject obj)
1001: {
1003: return 0;
1004: }
1006: /*@
1007: PetscObjectSetUp - Sets up the internal data structures for the later use.
1009: Collective
1011: Input Parameters:
1012: . obj - the `PetscObject`
1014: Note:
1015: This does nothing at present.
1017: Level: advanced
1019: .seealso: `PetscObjectDestroy()`
1020: @*/
1021: PetscErrorCode PetscObjectSetUp(PetscObject obj)
1022: {
1024: return 0;
1025: }