Actual source code: inherit.c
1: /*
2: Provides utility routines for manipulating any type of PETSc object.
3: */
4: #include <petsc/private/petscimpl.h>
5: #include <petscviewer.h>
7: PETSC_INTERN PetscObject *PetscObjects;
8: PETSC_INTERN PetscInt PetscObjectsCounts;
9: PETSC_INTERN PetscInt PetscObjectsMaxCounts;
10: PETSC_INTERN PetscBool PetscObjectsLog;
12: PetscObject *PetscObjects = NULL;
13: PetscInt PetscObjectsCounts = 0, PetscObjectsMaxCounts = 0;
14: PetscBool PetscObjectsLog = PETSC_FALSE;
16: PetscObjectId PetscObjectNewId_Internal(void)
17: {
18: static PetscObjectId idcnt = 1;
19: return idcnt++;
20: }
22: PetscErrorCode PetscHeaderCreate_Function(PetscErrorCode ierr, PetscObject *h, PetscClassId classid, const char class_name[], const char descr[], const char mansec[], MPI_Comm comm, PetscObjectDestroyFn *destroy, PetscObjectViewFn *view)
23: {
24: PetscFunctionBegin;
25: if (ierr) PetscFunctionReturn(ierr);
26: PetscCall(PetscHeaderCreate_Private(*h, classid, class_name, descr, mansec, comm, destroy, view));
27: PetscCall(PetscLogObjectCreate(*h));
28: PetscFunctionReturn(PETSC_SUCCESS);
29: }
31: /*
32: PetscHeaderCreate_Private - Fills in the default values.
33: */
34: PetscErrorCode PetscHeaderCreate_Private(PetscObject h, PetscClassId classid, const char class_name[], const char descr[], const char mansec[], MPI_Comm comm, PetscObjectDestroyFn *destroy, PetscObjectViewFn *view)
35: {
36: void *get_tmp;
37: PetscInt64 *cidx;
38: PetscMPIInt flg;
40: PetscFunctionBegin;
41: h->classid = classid;
42: h->class_name = (char *)class_name;
43: h->description = (char *)descr;
44: h->mansec = (char *)mansec;
45: h->refct = 1;
46: h->non_cyclic_references = NULL;
47: h->id = PetscObjectNewId_Internal();
48: h->bops->destroy = destroy;
49: h->bops->view = view;
51: PetscCall(PetscCommDuplicate(comm, &h->comm, &h->tag));
53: /* Increment and store current object creation index */
54: PetscCallMPI(MPI_Comm_get_attr(h->comm, Petsc_CreationIdx_keyval, &get_tmp, &flg));
55: PetscCheck(flg, h->comm, PETSC_ERR_ARG_CORRUPT, "MPI_Comm does not have an object creation index");
56: cidx = (PetscInt64 *)get_tmp;
57: h->cidx = (*cidx)++;
59: /* Keep a record of object created */
60: if (PetscDefined(USE_LOG) && PetscObjectsLog) {
61: PetscObject *newPetscObjects;
62: PetscInt newPetscObjectsMaxCounts;
64: PetscObjectsCounts++;
65: for (PetscInt i = 0; i < PetscObjectsMaxCounts; ++i) {
66: if (!PetscObjects[i]) {
67: PetscObjects[i] = h;
68: PetscFunctionReturn(PETSC_SUCCESS);
69: }
70: }
71: /* Need to increase the space for storing PETSc objects */
72: if (!PetscObjectsMaxCounts) newPetscObjectsMaxCounts = 100;
73: else newPetscObjectsMaxCounts = 2 * PetscObjectsMaxCounts;
74: PetscCall(PetscCalloc1(newPetscObjectsMaxCounts, &newPetscObjects));
75: PetscCall(PetscArraycpy(newPetscObjects, PetscObjects, PetscObjectsMaxCounts));
76: PetscCall(PetscFree(PetscObjects));
78: PetscObjects = newPetscObjects;
79: PetscObjects[PetscObjectsMaxCounts] = h;
80: PetscObjectsMaxCounts = newPetscObjectsMaxCounts;
81: }
82: PetscFunctionReturn(PETSC_SUCCESS);
83: }
85: PETSC_INTERN PetscBool PetscMemoryCollectMaximumUsage;
86: PETSC_INTERN PetscLogDouble PetscMemoryMaximumUsage;
88: PetscErrorCode PetscHeaderDestroy_Function(PetscObject *h)
89: {
90: PetscFunctionBegin;
91: PetscCall(PetscLogObjectDestroy(*h));
92: PetscCall(PetscHeaderDestroy_Private(*h, PETSC_FALSE));
93: PetscCall(PetscFree(*h));
94: PetscFunctionReturn(PETSC_SUCCESS);
95: }
97: /*
98: PetscHeaderDestroy_Private - Destroys a base PETSc object header. Called by
99: the macro PetscHeaderDestroy().
100: */
101: PetscErrorCode PetscHeaderDestroy_Private(PetscObject obj, PetscBool clear_for_reuse)
102: {
103: PetscFunctionBegin;
105: PetscCall(PetscComposedQuantitiesDestroy(obj));
106: if (PetscMemoryCollectMaximumUsage) {
107: PetscLogDouble usage;
109: PetscCall(PetscMemoryGetCurrentUsage(&usage));
110: if (usage > PetscMemoryMaximumUsage) PetscMemoryMaximumUsage = usage;
111: }
112: /* first destroy things that could execute arbitrary code */
113: if (obj->python_destroy) {
114: void *python_context = obj->python_context;
115: PetscErrorCode (*python_destroy)(void *) = obj->python_destroy;
117: obj->python_context = NULL;
118: obj->python_destroy = NULL;
119: PetscCall((*python_destroy)(python_context));
120: }
121: PetscCall(PetscObjectDestroyOptionsHandlers(obj));
122: PetscCall(PetscObjectListDestroy(&obj->olist));
124: /* destroy allocated quantities */
125: if (PetscPrintFunctionList) PetscCall(PetscFunctionListPrintNonEmpty(obj->qlist));
126: PetscCheck(--(obj->refct) <= 0, obj->comm, PETSC_ERR_PLIB, "Destroying a PetscObject (%s) with reference count %" PetscInt_FMT " >= 1", obj->name ? obj->name : "unnamed", obj->refct);
127: PetscCall(PetscFree(obj->name));
128: PetscCall(PetscFree(obj->prefix));
129: PetscCall(PetscFree(obj->type_name));
131: if (clear_for_reuse) {
132: /* we will assume that obj->bops->view and destroy are safe to leave as-is */
134: /* reset quantities, in order of appearance in _p_PetscObject */
135: obj->id = PetscObjectNewId_Internal();
136: obj->refct = 1;
137: obj->tablevel = 0;
138: obj->state = 0;
139: /* don't deallocate, zero these out instead */
140: PetscCall(PetscFunctionListClear(obj->qlist));
141: PetscCall(PetscArrayzero(obj->fortran_func_pointers, obj->num_fortran_func_pointers));
142: PetscCall(PetscArrayzero(obj->fortrancallback[PETSC_FORTRAN_CALLBACK_CLASS], obj->num_fortrancallback[PETSC_FORTRAN_CALLBACK_CLASS]));
143: PetscCall(PetscArrayzero(obj->fortrancallback[PETSC_FORTRAN_CALLBACK_SUBTYPE], obj->num_fortrancallback[PETSC_FORTRAN_CALLBACK_SUBTYPE]));
144: obj->optionsprinted = PETSC_FALSE;
145: #if PetscDefined(HAVE_SAWS)
146: obj->amsmem = PETSC_FALSE;
147: obj->amspublishblock = PETSC_FALSE;
148: #endif
149: obj->options = NULL;
150: obj->donotPetscObjectPrintClassNamePrefixType = PETSC_FALSE;
151: } else {
152: PetscCall(PetscFunctionListDestroy(&obj->qlist));
153: PetscCall(PetscFree(obj->fortran_func_pointers));
154: PetscCall(PetscFree(obj->fortrancallback[PETSC_FORTRAN_CALLBACK_CLASS]));
155: PetscCall(PetscFree(obj->fortrancallback[PETSC_FORTRAN_CALLBACK_SUBTYPE]));
156: PetscCall(PetscCommDestroy(&obj->comm));
157: obj->classid = PETSCFREEDHEADER;
159: if (PetscDefined(USE_LOG) && PetscObjectsLog) {
160: /* Record object removal from list of all objects */
161: for (PetscInt i = 0; i < PetscObjectsMaxCounts; ++i) {
162: if (PetscObjects[i] == obj) {
163: PetscObjects[i] = NULL;
164: --PetscObjectsCounts;
165: break;
166: }
167: }
168: if (!PetscObjectsCounts) {
169: PetscCall(PetscFree(PetscObjects));
170: PetscObjectsMaxCounts = 0;
171: }
172: }
173: }
174: PetscFunctionReturn(PETSC_SUCCESS);
175: }
177: /*
178: PetscHeaderReset_Internal - "Reset" a PetscObject header. This is tantamount to destroying
179: the object but does not free all resources. The object retains its:
181: - classid
182: - bops->view
183: - bops->destroy
184: - comm
185: - tag
186: - class_name
187: - description
188: - mansec
189: - cpp
191: Note that while subclass information is lost, superclass info remains. Thus this function is
192: intended to be used to reuse a PetscObject within the same class to avoid reallocating its
193: resources.
194: */
195: PetscErrorCode PetscHeaderReset_Internal(PetscObject obj)
196: {
197: PetscFunctionBegin;
198: PetscCall(PetscHeaderDestroy_Private(obj, PETSC_TRUE));
199: PetscFunctionReturn(PETSC_SUCCESS);
200: }
202: /*@
203: PetscObjectCopyFortranFunctionPointers - Copy function pointers to another object
205: Logically Collective
207: Input Parameters:
208: + src - source object
209: - dest - destination object
211: Level: developer
213: Note:
214: Both objects must have the same class.
216: This is used to help manage user callback functions that were provided in Fortran
218: .seealso: `PetscFortranCallbackRegister()`, `PetscFortranCallbackGetSizes()`
219: @*/
220: PetscErrorCode PetscObjectCopyFortranFunctionPointers(PetscObject src, PetscObject dest)
221: {
222: PetscFortranCallbackId cbtype, numcb[PETSC_FORTRAN_CALLBACK_MAXTYPE];
224: PetscFunctionBegin;
227: PetscCheck(src->classid == dest->classid, src->comm, PETSC_ERR_ARG_INCOMP, "Objects must be of the same class");
229: PetscCall(PetscFree(dest->fortran_func_pointers));
230: PetscCall(PetscMalloc(src->num_fortran_func_pointers * sizeof(void (*)(void)), &dest->fortran_func_pointers));
231: PetscCall(PetscMemcpy(dest->fortran_func_pointers, src->fortran_func_pointers, src->num_fortran_func_pointers * sizeof(void (*)(void))));
233: dest->num_fortran_func_pointers = src->num_fortran_func_pointers;
235: PetscCall(PetscFortranCallbackGetSizes(src->classid, &numcb[PETSC_FORTRAN_CALLBACK_CLASS], &numcb[PETSC_FORTRAN_CALLBACK_SUBTYPE]));
236: for (cbtype = PETSC_FORTRAN_CALLBACK_CLASS; cbtype < PETSC_FORTRAN_CALLBACK_MAXTYPE; cbtype++) {
237: PetscCall(PetscFree(dest->fortrancallback[cbtype]));
238: PetscCall(PetscCalloc1(numcb[cbtype], &dest->fortrancallback[cbtype]));
239: PetscCall(PetscMemcpy(dest->fortrancallback[cbtype], src->fortrancallback[cbtype], src->num_fortrancallback[cbtype] * sizeof(PetscFortranCallback)));
240: dest->num_fortrancallback[cbtype] = src->num_fortrancallback[cbtype];
241: }
242: PetscFunctionReturn(PETSC_SUCCESS);
243: }
245: /*@C
246: PetscObjectSetFortranCallback - set Fortran callback function pointer and context
248: Logically Collective, No Fortran Support
250: Input Parameters:
251: + obj - object on which to set callback
252: . cbtype - callback type (class or subtype)
253: . cid - address of callback Id, updated if not yet initialized (zero)
254: . func - Fortran function
255: - ctx - Fortran context
257: Level: developer
259: Note:
260: This is used to help manage user callback functions that were provided in Fortran
262: .seealso: `PetscObjectGetFortranCallback()`, `PetscFortranCallbackRegister()`, `PetscFortranCallbackGetSizes()`
263: @*/
264: PetscErrorCode PetscObjectSetFortranCallback(PetscObject obj, PetscFortranCallbackType cbtype, PetscFortranCallbackId *cid, void (*func)(void), void *ctx)
265: {
266: const char *subtype = NULL;
268: PetscFunctionBegin;
270: if (cbtype == PETSC_FORTRAN_CALLBACK_SUBTYPE) subtype = obj->type_name;
271: if (!*cid) PetscCall(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: PetscCall(PetscMalloc1(newnum, &callback));
277: PetscCall(PetscMemcpy(callback, obj->fortrancallback[cbtype], oldnum * sizeof(*obj->fortrancallback[cbtype])));
278: PetscCall(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: PetscFunctionReturn(PETSC_SUCCESS);
286: }
288: /*@C
289: PetscObjectGetFortranCallback - get Fortran callback function pointer and context
291: Logically Collective, No Fortran Support
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()`, `PetscFortranCallbackRegister()`, `PetscFortranCallbackGetSizes()`
308: @*/
309: PetscErrorCode PetscObjectGetFortranCallback(PetscObject obj, PetscFortranCallbackType cbtype, PetscFortranCallbackId cid, void (**func)(void), void **ctx)
310: {
311: PetscFortranCallback *cb;
313: PetscFunctionBegin;
315: PetscCheck(cid >= PETSC_SMALLEST_FORTRAN_CALLBACK, obj->comm, PETSC_ERR_ARG_CORRUPT, "Fortran callback Id invalid");
316: PetscCheck(cid < PETSC_SMALLEST_FORTRAN_CALLBACK + obj->num_fortrancallback[cbtype], obj->comm, PETSC_ERR_ARG_CORRUPT, "Fortran callback not set on this object");
317: cb = &obj->fortrancallback[cbtype][cid - PETSC_SMALLEST_FORTRAN_CALLBACK];
318: if (func) *func = cb->func;
319: if (ctx) *ctx = cb->ctx;
320: PetscFunctionReturn(PETSC_SUCCESS);
321: }
323: #if defined(PETSC_USE_LOG)
324: /*@C
325: PetscObjectsDump - Prints all the currently existing objects.
327: Input Parameters:
328: + fd - file pointer
329: - all - by default only tries to display objects created explicitly by the user, if all is `PETSC_TRUE` then lists all outstanding objects
331: Options Database Key:
332: . -objects_dump <all> - print information about all the objects that exist at the end of the programs run
334: Level: advanced
336: Note:
337: Only MPI rank 0 of `PETSC_COMM_WORLD` prints the values
339: .seealso: `PetscObject`
340: @*/
341: PetscErrorCode PetscObjectsDump(FILE *fd, PetscBool all)
342: {
343: PetscInt i, j, k = 0;
344: PetscObject h;
346: PetscFunctionBegin;
347: if (PetscObjectsCounts) {
348: PetscCall(PetscFPrintf(PETSC_COMM_WORLD, fd, "The following objects were never freed\n"));
349: PetscCall(PetscFPrintf(PETSC_COMM_WORLD, fd, "-----------------------------------------\n"));
350: for (i = 0; i < PetscObjectsMaxCounts; i++) {
351: if ((h = PetscObjects[i])) {
352: PetscCall(PetscObjectName(h));
353: {
354: PetscStack *stack = NULL;
355: char *create = NULL, *rclass = NULL;
357: /* if the PETSc function the user calls is not a create then this object was NOT directly created by them */
358: PetscCall(PetscMallocGetStack(h, &stack));
359: if (stack) {
360: k = stack->currentsize - 2;
361: if (!all) {
362: k = 0;
363: while (!stack->petscroutine[k]) k++;
364: PetscCall(PetscStrstr(stack->function[k], "Create", &create));
365: if (!create) PetscCall(PetscStrstr(stack->function[k], "Get", &create));
366: PetscCall(PetscStrstr(stack->function[k], h->class_name, &rclass));
367: if (!create) continue;
368: if (!rclass) continue;
369: }
370: }
372: PetscCall(PetscFPrintf(PETSC_COMM_WORLD, fd, "[%d] %s %s %s\n", PetscGlobalRank, h->class_name, h->type_name, h->name));
374: PetscCall(PetscMallocGetStack(h, &stack));
375: if (stack) {
376: for (j = k; j >= 0; j--) fprintf(fd, " [%d] %s() in %s\n", PetscGlobalRank, stack->function[j], stack->file[j]);
377: }
378: }
379: }
380: }
381: }
382: PetscFunctionReturn(PETSC_SUCCESS);
383: }
385: /*@
386: PetscObjectsView - Prints the currently existing objects.
388: Logically Collective
390: Input Parameter:
391: . viewer - must be an `PETSCVIEWERASCII` viewer
393: Level: advanced
395: .seealso: `PetscObject`
396: @*/
397: PetscErrorCode PetscObjectsView(PetscViewer viewer)
398: {
399: PetscBool isascii;
400: FILE *fd;
402: PetscFunctionBegin;
403: if (!viewer) viewer = PETSC_VIEWER_STDOUT_WORLD;
404: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
405: PetscCheck(isascii, PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Only supports ASCII viewer");
406: PetscCall(PetscViewerASCIIGetPointer(viewer, &fd));
407: PetscCall(PetscObjectsDump(fd, PETSC_TRUE));
408: PetscFunctionReturn(PETSC_SUCCESS);
409: }
411: /*@
412: PetscObjectsGetObject - Get a pointer to a named object
414: Not Collective
416: Input Parameter:
417: . name - the name of an object
419: Output Parameters:
420: + obj - the object or `NULL` if there is no object, optional, pass in `NULL` if not needed
421: - classname - the name of the class of the object, optional, pass in `NULL` if not needed
423: Level: advanced
425: .seealso: `PetscObject`
426: @*/
427: PetscErrorCode PetscObjectsGetObject(const char name[], PetscObject *obj, const char *classname[])
428: {
429: PetscInt i;
430: PetscObject h;
431: PetscBool flg;
433: PetscFunctionBegin;
434: PetscAssertPointer(name, 1);
435: if (obj) *obj = NULL;
436: for (i = 0; i < PetscObjectsMaxCounts; i++) {
437: if ((h = PetscObjects[i])) {
438: PetscCall(PetscObjectName(h));
439: PetscCall(PetscStrcmp(h->name, name, &flg));
440: if (flg) {
441: if (obj) *obj = h;
442: if (classname) *classname = h->class_name;
443: PetscFunctionReturn(PETSC_SUCCESS);
444: }
445: }
446: }
447: PetscFunctionReturn(PETSC_SUCCESS);
448: }
449: #else
450: PetscErrorCode PetscObjectsView(PetscViewer viewer)
451: {
452: PetscFunctionReturn(PETSC_SUCCESS);
453: }
455: PetscErrorCode PetscObjectsGetObject(const char name[], PetscObject *obj, const char *classname[])
456: {
457: PetscFunctionReturn(PETSC_SUCCESS);
458: }
459: #endif
461: /*@
462: 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
464: Input Parameter:
465: . obj - the `PetscObject`
467: Level: developer
469: Developer Notes:
470: This is used, for example to prevent sequential objects that are created from a parallel object; such as the `KSP` created by
471: `PCBJACOBI` from all printing the same help messages to the screen
473: .seealso: `PetscOptionsInsert()`, `PetscObject`
474: @*/
475: PetscErrorCode PetscObjectSetPrintedOptions(PetscObject obj)
476: {
477: PetscFunctionBegin;
478: PetscAssertPointer(obj, 1);
479: obj->optionsprinted = PETSC_TRUE;
480: PetscFunctionReturn(PETSC_SUCCESS);
481: }
483: /*@
484: PetscObjectInheritPrintedOptions - If the child object is not on the MPI rank 0 process of the parent object and the child is sequential then the child gets it set.
486: Input Parameters:
487: + pobj - the parent object
488: - obj - the `PetscObject`
490: Level: developer
492: Developer Notes:
493: This is used, for example to prevent sequential objects that are created from a parallel object; such as the `KSP` created by
494: `PCBJACOBI` from all printing the same help messages to the screen
496: This will not handle more complicated situations like with `PCGASM` where children may live on any subset of the parent's processes and overlap
498: .seealso: `PetscOptionsInsert()`, `PetscObjectSetPrintedOptions()`, `PetscObject`
499: @*/
500: PetscErrorCode PetscObjectInheritPrintedOptions(PetscObject pobj, PetscObject obj)
501: {
502: PetscMPIInt prank, size;
504: PetscFunctionBegin;
507: PetscCallMPI(MPI_Comm_rank(pobj->comm, &prank));
508: PetscCallMPI(MPI_Comm_size(obj->comm, &size));
509: if (size == 1 && prank > 0) obj->optionsprinted = PETSC_TRUE;
510: PetscFunctionReturn(PETSC_SUCCESS);
511: }
513: /*@C
514: PetscObjectAddOptionsHandler - Adds an additional function to check for options when `XXXSetFromOptions()` is called.
516: Not Collective
518: Input Parameters:
519: + obj - the PETSc object
520: . handle - function that checks for options
521: . destroy - function to destroy `ctx` if provided
522: - ctx - optional context for check function
524: Calling sequence of `handle`:
525: + obj - the PETSc object
526: . PetscOptionsObject - the `PetscOptionItems` object
527: - ctx - optional context for `handle`
529: Calling sequence of `destroy`:
530: + obj - the PETSc object
531: - ctx - optional context for `handle`
533: Level: developer
535: .seealso: `KSPSetFromOptions()`, `PCSetFromOptions()`, `SNESSetFromOptions()`, `PetscObjectProcessOptionsHandlers()`, `PetscObjectDestroyOptionsHandlers()`,
536: `PetscObject`
537: @*/
538: PetscErrorCode PetscObjectAddOptionsHandler(PetscObject obj, PetscErrorCode (*handle)(PetscObject obj, PetscOptionItems PetscOptionsObject, void *ctx), PetscErrorCode (*destroy)(PetscObject obj, void *ctx), void *ctx)
539: {
540: PetscFunctionBegin;
542: for (PetscInt i = 0; i < obj->noptionhandler; i++) {
543: PetscBool identical = (PetscBool)(obj->optionhandler[i] == handle && obj->optiondestroy[i] == destroy && obj->optionctx[i] == ctx);
544: if (identical) PetscFunctionReturn(PETSC_SUCCESS);
545: }
546: PetscCheck(obj->noptionhandler < PETSC_MAX_OPTIONS_HANDLER, obj->comm, PETSC_ERR_ARG_OUTOFRANGE, "Too many options handlers added");
547: obj->optionhandler[obj->noptionhandler] = handle;
548: obj->optiondestroy[obj->noptionhandler] = destroy;
549: obj->optionctx[obj->noptionhandler++] = ctx;
550: PetscFunctionReturn(PETSC_SUCCESS);
551: }
553: /*@C
554: PetscObjectProcessOptionsHandlers - Calls all the options handlers attached to an object
556: Not Collective
558: Input Parameters:
559: + obj - the PETSc object
560: - PetscOptionsObject - the options context
562: Level: developer
564: .seealso: `KSPSetFromOptions()`, `PCSetFromOptions()`, `SNESSetFromOptions()`, `PetscObjectAddOptionsHandler()`, `PetscObjectDestroyOptionsHandlers()`,
565: `PetscObject`
566: @*/
567: PetscErrorCode PetscObjectProcessOptionsHandlers(PetscObject obj, PetscOptionItems PetscOptionsObject)
568: {
569: PetscFunctionBegin;
571: for (PetscInt i = 0; i < obj->noptionhandler; i++) PetscCall((*obj->optionhandler[i])(obj, PetscOptionsObject, obj->optionctx[i]));
572: PetscFunctionReturn(PETSC_SUCCESS);
573: }
575: /*@
576: PetscObjectDestroyOptionsHandlers - Destroys all the option handlers attached to an object
578: Not Collective
580: Input Parameter:
581: . obj - the PETSc object
583: Level: developer
585: .seealso: `KSPSetFromOptions()`, `PCSetFromOptions()`, `SNESSetFromOptions()`, `PetscObjectAddOptionsHandler()`, `PetscObjectProcessOptionsHandlers()`,
586: `PetscObject`
587: @*/
588: PetscErrorCode PetscObjectDestroyOptionsHandlers(PetscObject obj)
589: {
590: PetscFunctionBegin;
592: for (PetscInt i = 0; i < obj->noptionhandler; i++) {
593: if (obj->optiondestroy[i]) PetscCall((*obj->optiondestroy[i])(obj, obj->optionctx[i]));
594: }
595: obj->noptionhandler = 0;
596: PetscFunctionReturn(PETSC_SUCCESS);
597: }
599: /*@
600: PetscObjectReference - Indicates to a `PetscObject` that it is being
601: referenced by another `PetscObject`. This increases the reference
602: count for that object by one.
604: Logically Collective
606: Input Parameter:
607: . obj - the PETSc object. This must be cast with (`PetscObject`), for example, `PetscObjectReference`((`PetscObject`)mat);
609: Level: advanced
611: Note:
612: If `obj` is `NULL` this function returns without doing anything.
614: .seealso: `PetscObjectCompose()`, `PetscObjectDereference()`, `PetscObject`
615: @*/
616: PetscErrorCode PetscObjectReference(PetscObject obj)
617: {
618: PetscFunctionBegin;
619: if (!obj) PetscFunctionReturn(PETSC_SUCCESS);
621: obj->refct++;
622: PetscFunctionReturn(PETSC_SUCCESS);
623: }
625: /*@
626: PetscObjectGetReference - Gets the current reference count for a PETSc object.
628: Not Collective
630: Input Parameter:
631: . obj - the PETSc object; this must be cast with (`PetscObject`), for example,
632: `PetscObjectGetReference`((`PetscObject`)mat,&cnt); `obj` cannot be `NULL`
634: Output Parameter:
635: . cnt - the reference count
637: Level: advanced
639: .seealso: `PetscObjectCompose()`, `PetscObjectDereference()`, `PetscObjectReference()`, `PetscObject`
640: @*/
641: PetscErrorCode PetscObjectGetReference(PetscObject obj, PetscInt *cnt)
642: {
643: PetscFunctionBegin;
645: PetscAssertPointer(cnt, 2);
646: *cnt = obj->refct;
647: PetscFunctionReturn(PETSC_SUCCESS);
648: }
650: /*@
651: PetscObjectDereference - Indicates to any `PetscObject` that it is being
652: referenced by one less `PetscObject`. This decreases the reference
653: count for that object by one.
655: Collective on `obj` if reference reaches 0 otherwise Logically Collective
657: Input Parameter:
658: . obj - the PETSc object; this must be cast with (`PetscObject`), for example,
659: `PetscObjectDereference`((`PetscObject`)mat);
661: Level: advanced
663: Notes:
664: `PetscObjectDestroy()` sets the `obj` pointer to `NULL` after the call, this routine does not.
666: If `obj` is `NULL` this function returns without doing anything.
668: .seealso: `PetscObjectCompose()`, `PetscObjectReference()`, `PetscObjectDestroy()`, `PetscObject`
669: @*/
670: PetscErrorCode PetscObjectDereference(PetscObject obj)
671: {
672: PetscFunctionBegin;
673: if (!obj) PetscFunctionReturn(PETSC_SUCCESS);
675: if (obj->bops->destroy) PetscCall((*obj->bops->destroy)(&obj));
676: else PetscCheck(--(obj->refct), PETSC_COMM_SELF, PETSC_ERR_SUP, "This PETSc object does not have a generic destroy routine");
677: PetscFunctionReturn(PETSC_SUCCESS);
678: }
680: /*
681: The following routines are the versions private to the PETSc object
682: data structures.
683: */
684: PetscErrorCode PetscObjectRemoveReference(PetscObject obj, const char name[])
685: {
686: PetscFunctionBegin;
688: PetscCall(PetscObjectListRemoveReference(&obj->olist, name));
689: PetscFunctionReturn(PETSC_SUCCESS);
690: }
692: /*@
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 been composed with the same name.
712: If `ptr` is `NULL` and `name` has previously been composed using an object, then that
713: entry is removed from `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()` or `PetscObjectContainerCompose()` can be used to create an object from a
719: user-provided pointer that may then be composed with PETSc objects using `PetscObjectCompose()`
721: Fortran Note:
722: Use
723: .vb
724: call PetscObjectCompose(obj, name, PetscObjectCast(ptr), ierr)
725: .ve
727: .seealso: `PetscObjectQuery()`, `PetscContainerCreate()`, `PetscObjectComposeFunction()`, `PetscObjectQueryFunction()`, `PetscContainer`,
728: `PetscContainerSetPointer()`, `PetscObject`, `PetscObjectContainerCompose()`
729: @*/
730: PetscErrorCode PetscObjectCompose(PetscObject obj, const char name[], PetscObject ptr)
731: {
732: PetscFunctionBegin;
734: PetscAssertPointer(name, 2);
736: PetscCheck(obj != ptr, PetscObjectComm(obj), PETSC_ERR_SUP, "Cannot compose object with itself");
737: if (ptr) {
738: const char *tname;
739: PetscBool skipreference;
741: PetscCall(PetscObjectListReverseFind(ptr->olist, obj, &tname, &skipreference));
742: if (tname) PetscCheck(skipreference, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "An object cannot be composed with an object that was composed with it");
743: }
744: PetscCall(PetscObjectListAdd(&obj->olist, name, ptr));
745: PetscFunctionReturn(PETSC_SUCCESS);
746: }
748: /*@
749: PetscObjectQuery - Gets a PETSc object associated with a given object that was composed with `PetscObjectCompose()`
751: Not Collective
753: Input Parameters:
754: + obj - the PETSc object. It must be cast with a (`PetscObject`), for example,
755: `PetscObjectCompose`((`PetscObject`)mat,...);
756: . name - name associated with child object
757: - ptr - the other PETSc object associated with the PETSc object, this must be
758: cast with (`PetscObject`*)
760: Level: advanced
762: Note:
763: The reference count of neither object is increased in this call
765: Fortran Note:
766: Use
767: .vb
768: call PetscObjectQuery(PetscObjectCast(obj), name, ptr, ierr)
769: .ve
771: .seealso: `PetscObjectCompose()`, `PetscObjectComposeFunction()`, `PetscObjectQueryFunction()`, `PetscContainer`
772: `PetscContainerGetPointer()`, `PetscObject`
773: @*/
774: PetscErrorCode PetscObjectQuery(PetscObject obj, const char name[], PetscObject *ptr)
775: {
776: PetscFunctionBegin;
778: PetscAssertPointer(name, 2);
779: PetscAssertPointer(ptr, 3);
780: PetscCall(PetscObjectListFind(obj->olist, name, ptr));
781: PetscFunctionReturn(PETSC_SUCCESS);
782: }
784: /*MC
785: PetscObjectComposeFunction - Associates a function with a given PETSc object.
787: Synopsis:
788: #include <petscsys.h>
789: PetscErrorCode PetscObjectComposeFunction(PetscObject obj, const char name[], void (*fptr)(void))
791: Logically Collective
793: Input Parameters:
794: + obj - the PETSc object; this must be cast with a (`PetscObject`), for example,
795: `PetscObjectCompose`((`PetscObject`)mat,...);
796: . name - name associated with the child function
797: - fptr - function pointer
799: Level: advanced
801: Notes:
802: When the first argument of `fptr` is (or is derived from) a `PetscObject` then `PetscTryMethod()` and `PetscUseMethod()`
803: can be used to call the function directly with error checking.
805: To remove a registered routine, pass in `NULL` for `fptr`.
807: `PetscObjectComposeFunction()` can be used with any PETSc object (such as
808: `Mat`, `Vec`, `KSP`, `SNES`, etc.) or any user-provided object.
810: `PetscUseTypeMethod()` and `PetscTryTypeMethod()` are used to call a function that is stored in the objects `obj->ops` table.
812: .seealso: `PetscObjectQueryFunction()`, `PetscContainerCreate()` `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscTryMethod()`, `PetscUseMethod()`,
813: `PetscUseTypeMethod()`, `PetscTryTypeMethod()`, `PetscObject`
814: M*/
815: PetscErrorCode PetscObjectComposeFunction_Private(PetscObject obj, const char name[], void (*fptr)(void))
816: {
817: PetscFunctionBegin;
819: PetscAssertPointer(name, 2);
820: PetscCall(PetscFunctionListAdd_Private(&obj->qlist, name, fptr));
821: PetscFunctionReturn(PETSC_SUCCESS);
822: }
824: /*MC
825: PetscObjectQueryFunction - Gets a function associated with a given object.
827: Synopsis:
828: #include <petscsys.h>
829: PetscErrorCode PetscObjectQueryFunction(PetscObject obj, const char name[], void (**fptr)(void))
831: Logically Collective
833: Input Parameters:
834: + obj - the PETSc object; this must be cast with (`PetscObject`), for example,
835: `PetscObjectQueryFunction`((`PetscObject`)ksp,...);
836: - name - name associated with the child function
838: Output Parameter:
839: . fptr - function pointer
841: Level: advanced
843: .seealso: `PetscObjectComposeFunction()`, `PetscFunctionListFind()`, `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObject`
844: M*/
845: PETSC_EXTERN PetscErrorCode PetscObjectQueryFunction_Private(PetscObject obj, const char name[], void (**fptr)(void))
846: {
847: PetscFunctionBegin;
849: PetscAssertPointer(name, 2);
850: PetscCall(PetscFunctionListFind_Private(obj->qlist, name, fptr));
851: PetscFunctionReturn(PETSC_SUCCESS);
852: }
854: /*@
855: PetscObjectHasFunction - Query if a function is associated with a given object.
857: Logically Collective
859: Input Parameters:
860: + obj - the PETSc object
861: - name - name associated with the child function
863: Output Parameter:
864: . has - the boolean value
866: Level: advanced
868: .seealso: `PetscObject`, `PetscObjectComposeFunction()`, `PetscObjectQueryFunction()`
869: @*/
870: PetscErrorCode PetscObjectHasFunction(PetscObject obj, const char name[], PetscBool *has)
871: {
872: void (*fptr)(void) = NULL;
874: PetscFunctionBegin;
875: PetscAssertPointer(has, 3);
876: PetscCall(PetscObjectQueryFunction(obj, name, &fptr));
877: *has = fptr ? PETSC_TRUE : PETSC_FALSE;
878: PetscFunctionReturn(PETSC_SUCCESS);
879: }
881: struct _p_PetscContainer {
882: PETSCHEADER(int);
883: void *ctx;
884: PetscCtxDestroyFn *ctxdestroy;
885: PetscErrorCode (*userdestroy_deprecated)(void *);
886: };
888: /*@C
889: PetscContainerGetPointer - Gets the pointer value contained in the container that was provided with `PetscContainerSetPointer()`
891: Not Collective, No Fortran Support
893: Input Parameter:
894: . obj - the object created with `PetscContainerCreate()`
896: Output Parameter:
897: . ptr - the pointer value
899: Level: advanced
901: .seealso: `PetscContainerCreate()`, `PetscContainerDestroy()`, `PetscObject`,
902: `PetscContainerSetPointer()`, `PetscObjectContainerCompose()`, `PetscObjectContainerQuery()`
903: @*/
904: PetscErrorCode PetscContainerGetPointer(PetscContainer obj, PeCtx ptr)
905: {
906: PetscFunctionBegin;
908: PetscAssertPointer(ptr, 2);
909: *(void **)ptr = obj->ctx;
910: PetscFunctionReturn(PETSC_SUCCESS);
911: }
913: /*@C
914: PetscContainerSetPointer - Sets the pointer value contained in the container.
916: Logically Collective, No Fortran Support
918: Input Parameters:
919: + obj - the object created with `PetscContainerCreate()`
920: - ptr - the pointer value
922: Level: advanced
924: .seealso: `PetscContainerCreate()`, `PetscContainerDestroy()`, `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObject`,
925: `PetscContainerGetPointer()`, `PetscObjectContainerCompose()`, `PetscObjectContainerQuery()`
926: @*/
927: PetscErrorCode PetscContainerSetPointer(PetscContainer obj, void *ptr)
928: {
929: PetscFunctionBegin;
931: if (ptr) PetscAssertPointer(ptr, 2);
932: obj->ctx = ptr;
933: PetscFunctionReturn(PETSC_SUCCESS);
934: }
936: /*@C
937: PetscContainerDestroy - Destroys a PETSc container object.
939: Collective, No Fortran Support
941: Input Parameter:
942: . obj - an object that was created with `PetscContainerCreate()`
944: Level: advanced
946: Note:
947: If `PetscContainerSetCtxDestroy()` was used to provide a user destroy object for the data provided with `PetscContainerSetPointer()`
948: then that function is called to destroy the data.
950: .seealso: `PetscContainerCreate()`, `PetscContainerSetCtxDestroy()`, `PetscObject`, `PetscObjectContainerCompose()`, `PetscObjectContainerQuery()`
951: @*/
952: PetscErrorCode PetscContainerDestroy(PetscContainer *obj)
953: {
954: PetscFunctionBegin;
955: if (!*obj) PetscFunctionReturn(PETSC_SUCCESS);
957: if (--((PetscObject)*obj)->refct > 0) {
958: *obj = NULL;
959: PetscFunctionReturn(PETSC_SUCCESS);
960: }
961: if ((*obj)->ctxdestroy) PetscCall((*(*obj)->ctxdestroy)(&(*obj)->ctx));
962: else if ((*obj)->userdestroy_deprecated) PetscCall((*(*obj)->userdestroy_deprecated)((*obj)->ctx));
963: PetscCall(PetscHeaderDestroy(obj));
964: PetscFunctionReturn(PETSC_SUCCESS);
965: }
967: /*@C
968: PetscContainerSetCtxDestroy - Sets the destroy function for the data provided to the `PetscContainer` with `PetscContainerSetPointer()`
970: Logically Collective, No Fortran Support
972: Input Parameters:
973: + obj - an object that was created with `PetscContainerCreate()`
974: - des - name of the ctx destroy function, see `PetscCtxDestroyFn` for its calling sequence
976: Level: advanced
978: Note:
979: Use `PetscCtxDestroyDefault()` if the memory was obtained by calling `PetscMalloc()` or one of its variants for single memory allocation.
981: .seealso: `PetscContainerDestroy()`, `PetscContainerUserDestroyDefault()`, `PetscMalloc()`, `PetscMalloc1()`, `PetscCalloc()`, `PetscCalloc1()`, `PetscObject`,
982: `PetscObjectContainerCompose()`, `PetscObjectContainerQuery()`
983: @*/
984: PetscErrorCode PetscContainerSetCtxDestroy(PetscContainer obj, PetscCtxDestroyFn *des)
985: {
986: PetscFunctionBegin;
988: obj->ctxdestroy = des;
989: PetscFunctionReturn(PETSC_SUCCESS);
990: }
992: /*@C
993: PetscContainerSetUserDestroy - Sets the destroy function for the data provided to the `PetscContainer` with `PetscContainerSetPointer()`
995: Logically Collective, No Fortran Support
997: Input Parameters:
998: + obj - an object that was created with `PetscContainerCreate()`
999: - des - name of the ctx destroy function
1001: Level: advanced
1003: Notes:
1004: Deprecated, use `PetscContainerSetCtxDestroy()`
1006: .seealso: `PetscContainerSetCtxDestroy()`, `PetscContainerDestroy()`, `PetscContainerUserDestroyDefault()`, `PetscMalloc()`, `PetscMalloc1()`, `PetscCalloc()`, `PetscCalloc1()`, `PetscObject`,
1007: `PetscObjectContainerCompose()`, `PetscObjectContainerQuery()`
1008: @*/
1009: PetscErrorCode PetscContainerSetUserDestroy(PetscContainer obj, PetscErrorCode (*des)(void *))
1010: {
1011: PetscFunctionBegin;
1013: obj->userdestroy_deprecated = des;
1014: PetscFunctionReturn(PETSC_SUCCESS);
1015: }
1017: PetscClassId PETSC_CONTAINER_CLASSID;
1019: /*@C
1020: PetscContainerCreate - Creates a PETSc object that has room to hold a single pointer.
1022: Collective, No Fortran Support
1024: Input Parameter:
1025: . comm - MPI communicator that shares the object
1027: Output Parameter:
1028: . container - the container created
1030: Level: advanced
1032: Notes:
1033: This allows one to attach any type of data (accessible through a pointer) with the
1034: `PetscObjectCompose()` function to a `PetscObject`. The data item itself is attached by a
1035: call to `PetscContainerSetPointer()`.
1037: .seealso: `PetscContainerDestroy()`, `PetscContainerSetPointer()`, `PetscContainerGetPointer()`, `PetscObjectCompose()`, `PetscObjectQuery()`,
1038: `PetscContainerSetCtxDestroy()`, `PetscObject`, `PetscObjectContainerCompose()`, `PetscObjectContainerQuery()`
1039: @*/
1040: PetscErrorCode PetscContainerCreate(MPI_Comm comm, PetscContainer *container)
1041: {
1042: PetscFunctionBegin;
1043: PetscAssertPointer(container, 2);
1044: PetscCall(PetscSysInitializePackage());
1045: PetscCall(PetscHeaderCreate(*container, PETSC_CONTAINER_CLASSID, "PetscContainer", "Container", "Sys", comm, PetscContainerDestroy, NULL));
1046: PetscFunctionReturn(PETSC_SUCCESS);
1047: }
1049: /*@C
1050: PetscObjectContainerCompose - Creates a `PetscContainer`, provides all of its values and composes it with a `PetscObject`
1052: Collective
1054: Input Parameters:
1055: + obj - the `PetscObject`
1056: . name - the name for the composed container
1057: . pointer - the pointer to the data
1058: - destroy - the routine to destroy the container's data, see `PetscCtxDestroyFn` for its calling sequence; use `PetscCtxDestroyDefault()` if a `PetscFree()` frees the data
1060: Level: advanced
1062: Notes:
1063: This allows one to attach any type of data (accessible through a pointer) with the
1064: `PetscObjectCompose()` function to a `PetscObject`. The data item itself is attached by a
1065: call to `PetscContainerSetPointer()`.
1067: .seealso: `PetscContainerCreate()`, `PetscContainerDestroy()`, `PetscContainerSetPointer()`, `PetscContainerGetPointer()`, `PetscObjectCompose()`, `PetscObjectQuery()`,
1068: `PetscContainerSetCtxDestroy()`, `PetscObject`, `PetscObjectContainerQuery()`
1069: @*/
1070: PetscErrorCode PetscObjectContainerCompose(PetscObject obj, const char *name, void *pointer, PetscCtxDestroyFn *destroy)
1071: {
1072: PetscContainer container;
1074: PetscFunctionBegin;
1075: PetscCall(PetscContainerCreate(PetscObjectComm(obj), &container));
1076: PetscCall(PetscContainerSetPointer(container, pointer));
1077: if (destroy) PetscCall(PetscContainerSetCtxDestroy(container, destroy));
1078: PetscCall(PetscObjectCompose(obj, name, (PetscObject)container));
1079: PetscCall(PetscContainerDestroy(&container));
1080: PetscFunctionReturn(PETSC_SUCCESS);
1081: }
1083: /*@C
1084: PetscObjectContainerQuery - Accesses the pointer in a container composed to a `PetscObject` with `PetscObjectContainerCompose()`
1086: Collective
1088: Input Parameters:
1089: + obj - the `PetscObject`
1090: - name - the name for the composed container
1092: Output Parameter:
1093: . pointer - the pointer to the data
1095: Level: advanced
1097: .seealso: `PetscContainerCreate()`, `PetscContainerDestroy()`, `PetscContainerSetPointer()`, `PetscContainerGetPointer()`, `PetscObjectCompose()`, `PetscObjectQuery()`,
1098: `PetscContainerSetCtxDestroy()`, `PetscObject`, `PetscObjectContainerCompose()`
1099: @*/
1100: PetscErrorCode PetscObjectContainerQuery(PetscObject obj, const char *name, PeCtx pointer)
1101: {
1102: PetscContainer container;
1104: PetscFunctionBegin;
1105: PetscCall(PetscObjectQuery(obj, name, (PetscObject *)&container));
1106: if (container) PetscCall(PetscContainerGetPointer(container, pointer));
1107: else *(void **)pointer = NULL;
1108: PetscFunctionReturn(PETSC_SUCCESS);
1109: }
1111: /*@
1112: PetscObjectSetFromOptions - Sets generic parameters from user options.
1114: Collective
1116: Input Parameter:
1117: . obj - the `PetscObject`
1119: Level: beginner
1121: Note:
1122: We have no generic options at present, so this does nothing.
1124: .seealso: `PetscObjectSetOptionsPrefix()`, `PetscObjectGetOptionsPrefix()`, `PetscObject`
1125: @*/
1126: PetscErrorCode PetscObjectSetFromOptions(PetscObject obj)
1127: {
1128: PetscFunctionBegin;
1130: PetscFunctionReturn(PETSC_SUCCESS);
1131: }
1133: /*@
1134: PetscObjectSetUp - Sets up the internal data structures for later use of the object
1136: Collective
1138: Input Parameter:
1139: . obj - the `PetscObject`
1141: Level: advanced
1143: Note:
1144: This does nothing at present.
1146: .seealso: `PetscObjectDestroy()`, `PetscObject`
1147: @*/
1148: PetscErrorCode PetscObjectSetUp(PetscObject obj)
1149: {
1150: PetscFunctionBegin;
1152: PetscFunctionReturn(PETSC_SUCCESS);
1153: }
1155: /*MC
1156: PetscObjectIsNull - returns true if the given PETSc object is a null object
1158: Fortran only
1160: Synopsis:
1161: #include <petsc/finclude/petscsys.h>
1162: PetscBool PetscObjectIsNull(PetscObject obj)
1164: Logically Collective
1166: Input Parameters:
1167: . obj - the PETSc object
1169: Level: beginner
1171: Example Usage:
1172: .vb
1173: if (PetscObjectIsNull(dm)) then
1174: if (.not. PetscObjectIsNull(dm)) then
1175: .ve
1177: Note:
1178: Code such as
1179: .vb
1180: if (dm == PETSC_NULL_DM) then
1181: .ve
1182: is not allowed.
1184: .seealso: `PetscObject`, `PETSC_NULL_OBJECT`, `PETSC_NULL_VEC`, `PETSC_NULL_VEC_ARRAY`
1185: M*/
1187: /*MC
1188: PetscObjectCast - Casts a `PetscObject` to the base `PetscObject` type in function calls
1190: Fortran only
1192: Synopsis:
1193: use petscsys
1195: Level: beginner
1197: Example Usage:
1198: PetscFE fe
1199: .vb
1200: PetscCallA(DMAddField(dm, 0, PetscObjectCast(fe),ierr)
1201: .ve
1203: .seealso: `PetscObject`, `PetscObjectSpecificCast()`
1204: M*/
1206: /*MC
1207: PetscObjectSpecificCast - Casts a `PetscObject` to any specific `PetscObject`
1209: Fortran only
1211: Synopsis:
1212: use petscsys
1214: Level: beginner
1216: Example Usage:
1217: PetscObject obj
1218: PetscFE fe
1219: .vb
1220: PetscCallA(PetscDSGetDiscretization(ds, 0, obj, ierr)
1221: PetscObjectSpecificCast(fe,obj)
1222: .ve
1224: .seealso: `PetscObject`, `PetscObjectCast()`
1225: M*/
1227: /*MC
1228: PetscEnumCase - `case()` statement for a PETSc enum variable or value
1230: Fortran only
1232: Synopsis:
1233: #include <petsc/finclude/petscsys.h>
1234: PetscEnumCase(PetscObject enm)
1236: Input Parameters:
1237: . enum - the PETSc enum value or variable
1239: Level: beginner
1241: Example Usage:
1242: .vb
1243: DMPolytopeType cellType
1244: select PetscEnumCase(cellType)
1245: PetscEnumCase(DM_POLYTOPE_TRIANGLE)
1246: write(*,*) 'cell is a triangle'
1247: PetscEnumCase(DM_POLYTOPE_TETRAHEDRON)
1248: write(*,*) 'cell is a tetrahedron'
1249: case default
1250: write(*,*) 'cell is a something else'
1251: end select
1252: .ve
1253: is equivalent to
1254: .vb
1255: DMPolytopeType cellType
1256: select case(cellType%v)
1257: case(DM_POLYTOPE_TRIANGLE%v)
1258: write(*,*) 'cell is a triangle'
1259: case(DM_POLYTOPE_TETRAHEDRON%v)
1260: write(*,*) 'cell is a tetrahedron'
1261: case default
1262: write(*,*) 'cell is a something else'
1263: end select
1264: .ve
1266: .seealso: `PetscObject`
1267: M*/