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: . fname - name of the function
778: - fptr - function pointer
780: Level: advanced
782: Notes:
783: When the first argument of the function is the object within which it has been composed then `PetscTryMethod()` and `PetscUseMethod()`
784: can be used to call the function directly with error checking.
786: To remove a registered routine, pass in NULL for fptr().
788: PetscObjectComposeFunction() can be used with any PETSc object (such as
789: `Mat`, `Vec`, `KSP`, `SNES`, etc.) or any user-provided object.
791: `PetscCallMethod()` is used to call a function that is stored in the objects obj->ops table.
793: .seealso: `PetscObjectQueryFunction()`, `PetscContainerCreate()` `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscTryMethod()`, `PetscUseMethod()`,
794: `PetscCallMethod()`
795: M*/
797: PetscErrorCode PetscObjectComposeFunction_Private(PetscObject obj, const char name[], void (*fptr)(void))
798: {
801: (*obj->bops->composefunction)(obj, name, fptr);
802: return 0;
803: }
805: /*MC
806: PetscObjectQueryFunction - Gets a function associated with a given object.
808: Synopsis:
809: #include <petscsys.h>
810: PetscErrorCode PetscObjectQueryFunction(PetscObject obj,const char name[],void (**fptr)(void))
812: Logically Collective
814: Input Parameters:
815: + obj - the PETSc object; this must be cast with (`PetscObject`), for example,
816: `PetscObjectQueryFunction`((`PetscObject`)ksp,...);
817: - name - name associated with the child function
819: Output Parameter:
820: . fptr - function pointer
822: Level: advanced
824: .seealso: `PetscObjectComposeFunction()`, `PetscFunctionListFind()`, `PetscObjectCompose()`, `PetscObjectQuery()`
825: M*/
826: PETSC_EXTERN PetscErrorCode PetscObjectQueryFunction_Private(PetscObject obj, const char name[], void (**ptr)(void))
827: {
830: (*obj->bops->queryfunction)(obj, name, ptr);
831: return 0;
832: }
834: struct _p_PetscContainer {
835: PETSCHEADER(int);
836: void *ptr;
837: PetscErrorCode (*userdestroy)(void *);
838: };
840: /*@C
841: PetscContainerUserDestroyDefault - Default destroy routine for user-provided data that simply calls `PetscFree()` in the data
842: provided with `PetscContainerSetPointer()`
844: Logically Collective on the `PetscContainer` containing the user data
846: Input Parameter:
847: . ctx - pointer to user-provided data
849: Level: advanced
851: .seealso: `PetscContainerDestroy()`, `PetscContainerSetUserDestroy()`
852: @*/
853: PetscErrorCode PetscContainerUserDestroyDefault(void *ctx)
854: {
855: PetscFree(ctx);
856: return 0;
857: }
859: /*@C
860: PetscContainerGetPointer - Gets the pointer value contained in the container that was provided with `PetscContainerSetPointer()`
862: Not Collective
864: Input Parameter:
865: . obj - the object created with `PetscContainerCreate()`
867: Output Parameter:
868: . ptr - the pointer value
870: Level: advanced
872: .seealso: `PetscContainerCreate()`, `PetscContainerDestroy()`,
873: `PetscContainerSetPointer()`
874: @*/
875: PetscErrorCode PetscContainerGetPointer(PetscContainer obj, void **ptr)
876: {
879: *ptr = obj->ptr;
880: return 0;
881: }
883: /*@C
884: PetscContainerSetPointer - Sets the pointer value contained in the container.
886: Logically Collective
888: Input Parameters:
889: + obj - the object created with `PetscContainerCreate()`
890: - ptr - the pointer value
892: Level: advanced
894: .seealso: `PetscContainerCreate()`, `PetscContainerDestroy()`, `PetscObjectCompose()`, `PetscObjectQuery()`,
895: `PetscContainerGetPointer()`
896: @*/
897: PetscErrorCode PetscContainerSetPointer(PetscContainer obj, void *ptr)
898: {
901: obj->ptr = ptr;
902: return 0;
903: }
905: /*@C
906: PetscContainerDestroy - Destroys a PETSc container object.
908: Collective
910: Input Parameter:
911: . obj - an object that was created with `PetscContainerCreate()`
913: Level: advanced
915: Note:
916: If `PetscContainerSetUserDestroy()` was used to provide a user destroy object for the data provided with `PetscContainerSetPointer()`
917: then that function is called to destroy the data.
919: .seealso: `PetscContainerCreate()`, `PetscContainerSetUserDestroy()`
920: @*/
921: PetscErrorCode PetscContainerDestroy(PetscContainer *obj)
922: {
923: if (!*obj) return 0;
925: if (--((PetscObject)(*obj))->refct > 0) {
926: *obj = NULL;
927: return 0;
928: }
929: if ((*obj)->userdestroy) (*(*obj)->userdestroy)((*obj)->ptr);
930: PetscHeaderDestroy(obj);
931: return 0;
932: }
934: /*@C
935: PetscContainerSetUserDestroy - Sets name of the user destroy function for the data provided to the `PetscContainer` with `PetscContainerSetPointer()`
937: Logically Collective
939: Input Parameters:
940: + obj - an object that was created with `PetscContainerCreate()`
941: - des - name of the user destroy function
943: Note:
944: Use `PetscContainerUserDestroyDefault()` if the memory was obtained by calling `PetscMalloc()` or one of its variants for single memory allocation.
946: Level: advanced
948: .seealso: `PetscContainerDestroy()`, `PetscContainerUserDestroyDefault()`, `PetscMalloc()`, `PetscMalloc1()`, `PetscCalloc()`, `PetscCalloc1()`
949: @*/
950: PetscErrorCode PetscContainerSetUserDestroy(PetscContainer obj, PetscErrorCode (*des)(void *))
951: {
953: obj->userdestroy = des;
954: return 0;
955: }
957: PetscClassId PETSC_CONTAINER_CLASSID;
959: /*@C
960: PetscContainerCreate - Creates a PETSc object that has room to hold
961: a single pointer. This allows one to attach any type of data (accessible
962: through a pointer) with the `PetscObjectCompose()` function to a `PetscObject`.
963: The data item itself is attached by a call to `PetscContainerSetPointer()`.
965: Collective
967: Input Parameters:
968: . comm - MPI communicator that shares the object
970: Output Parameters:
971: . container - the container created
973: Level: advanced
975: .seealso: `PetscContainerDestroy()`, `PetscContainerSetPointer()`, `PetscContainerGetPointer()`, `PetscObjectCompose()`, `PetscObjectQuery()`,
976: `PetscContainerSetUserDestroy()`
977: @*/
978: PetscErrorCode PetscContainerCreate(MPI_Comm comm, PetscContainer *container)
979: {
981: PetscSysInitializePackage();
982: PetscHeaderCreate(*container, PETSC_CONTAINER_CLASSID, "PetscContainer", "Container", "Sys", comm, PetscContainerDestroy, NULL);
983: return 0;
984: }
986: /*@
987: PetscObjectSetFromOptions - Sets generic parameters from user options.
989: Collective
991: Input Parameter:
992: . obj - the `PetscObject`
994: Note:
995: We have no generic options at present, so this does nothing
997: Level: beginner
999: .seealso: `PetscObjectSetOptionsPrefix()`, `PetscObjectGetOptionsPrefix()`
1000: @*/
1001: PetscErrorCode PetscObjectSetFromOptions(PetscObject obj)
1002: {
1004: return 0;
1005: }
1007: /*@
1008: PetscObjectSetUp - Sets up the internal data structures for the later use.
1010: Collective
1012: Input Parameters:
1013: . obj - the `PetscObject`
1015: Note:
1016: This does nothing at present.
1018: Level: advanced
1020: .seealso: `PetscObjectDestroy()`
1021: @*/
1022: PetscErrorCode PetscObjectSetUp(PetscObject obj)
1023: {
1025: return 0;
1026: }