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 iflg;
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, &iflg));
55: PetscCheck(iflg, 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;
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(PetscFortranCallbackFn *), &dest->fortran_func_pointers));
231: PetscCall(PetscArraycpy(dest->fortran_func_pointers, src->fortran_func_pointers, src->num_fortran_func_pointers));
233: dest->num_fortran_func_pointers = src->num_fortran_func_pointers;
235: for (cbtype = PETSC_FORTRAN_CALLBACK_CLASS; cbtype < PETSC_FORTRAN_CALLBACK_MAXTYPE; cbtype++) {
236: PetscCall(PetscFree(dest->fortrancallback[cbtype]));
237: PetscCall(PetscCalloc1(src->num_fortrancallback[cbtype], &dest->fortrancallback[cbtype]));
238: PetscCall(PetscArraycpy(dest->fortrancallback[cbtype], src->fortrancallback[cbtype], src->num_fortrancallback[cbtype]));
239: dest->num_fortrancallback[cbtype] = src->num_fortrancallback[cbtype];
240: }
241: PetscFunctionReturn(PETSC_SUCCESS);
242: }
244: /*@
245: PetscObjectSetFortranCallback - set Fortran callback function pointer and context
247: Logically Collective, No Fortran Support
249: Input Parameters:
250: + obj - object on which to set callback
251: . cbtype - callback type (class or subtype)
252: . cid - address of callback Id, updated if not yet initialized (zero)
253: . func - Fortran function
254: - ctx - Fortran context
256: Level: developer
258: Note:
259: This is used to help manage user callback functions that were provided in Fortran
261: .seealso: `PetscObjectGetFortranCallback()`, `PetscFortranCallbackRegister()`, `PetscFortranCallbackGetSizes()`
262: @*/
263: PetscErrorCode PetscObjectSetFortranCallback(PetscObject obj, PetscFortranCallbackType cbtype, PetscFortranCallbackId *cid, PetscFortranCallbackFn *func, PetscCtx ctx)
264: {
265: const char *subtype = NULL;
267: PetscFunctionBegin;
269: if (cbtype == PETSC_FORTRAN_CALLBACK_SUBTYPE) subtype = obj->type_name;
270: if (!*cid) PetscCall(PetscFortranCallbackRegister(obj->classid, subtype, cid));
271: if (*cid >= PETSC_SMALLEST_FORTRAN_CALLBACK + obj->num_fortrancallback[cbtype]) {
272: PetscFortranCallbackId oldnum = obj->num_fortrancallback[cbtype];
273: PetscFortranCallbackId newnum = PetscMax(*cid - PETSC_SMALLEST_FORTRAN_CALLBACK + 1, 2 * oldnum);
274: PetscFortranCallback *callback;
275: PetscCall(PetscMalloc1(newnum, &callback));
276: PetscCall(PetscArraycpy(callback, obj->fortrancallback[cbtype], oldnum));
277: PetscCall(PetscFree(obj->fortrancallback[cbtype]));
279: obj->fortrancallback[cbtype] = callback;
280: obj->num_fortrancallback[cbtype] = newnum;
281: }
282: obj->fortrancallback[cbtype][*cid - PETSC_SMALLEST_FORTRAN_CALLBACK].func = func;
283: obj->fortrancallback[cbtype][*cid - PETSC_SMALLEST_FORTRAN_CALLBACK].ctx = ctx;
284: PetscFunctionReturn(PETSC_SUCCESS);
285: }
287: /*@
288: PetscObjectGetFortranCallback - get Fortran callback function pointer and context
290: Logically Collective, No Fortran Support
292: Input Parameters:
293: + obj - object on which to get callback
294: . cbtype - callback type
295: - cid - address of callback Id
297: Output Parameters:
298: + func - Fortran function (or `NULL` if not needed)
299: - ctx - Fortran context (or `NULL` if not needed)
301: Level: developer
303: Note:
304: This is used to help manage user callback functions that were provided in Fortran
306: .seealso: `PetscObjectSetFortranCallback()`, `PetscFortranCallbackRegister()`, `PetscFortranCallbackGetSizes()`
307: @*/
308: PetscErrorCode PetscObjectGetFortranCallback(PetscObject obj, PetscFortranCallbackType cbtype, PetscFortranCallbackId cid, PetscFortranCallbackFn **func, void **ctx)
309: {
310: PetscFortranCallback *cb;
312: PetscFunctionBegin;
314: PetscCheck(cid >= PETSC_SMALLEST_FORTRAN_CALLBACK, obj->comm, PETSC_ERR_ARG_CORRUPT, "Fortran callback Id invalid");
315: PetscCheck(cid < PETSC_SMALLEST_FORTRAN_CALLBACK + obj->num_fortrancallback[cbtype], obj->comm, PETSC_ERR_ARG_CORRUPT, "Fortran callback not set on this object");
316: cb = &obj->fortrancallback[cbtype][cid - PETSC_SMALLEST_FORTRAN_CALLBACK];
317: if (func) *func = cb->func;
318: if (ctx) *ctx = cb->ctx;
319: PetscFunctionReturn(PETSC_SUCCESS);
320: }
322: #if PetscDefined(USE_LOG)
323: /*@
324: PetscObjectsDump - Prints all the currently existing objects.
326: Input Parameters:
327: + fd - file pointer
328: - all - by default only tries to display objects created explicitly by the user, if all is `PETSC_TRUE` then lists all outstanding objects
330: Options Database Key:
331: . -objects_dump all - print information about all the objects that exist at the end of the programs run
333: Level: advanced
335: Note:
336: Only MPI rank 0 of `PETSC_COMM_WORLD` prints the values
338: .seealso: `PetscObject`
339: @*/
340: PetscErrorCode PetscObjectsDump(FILE *fd, PetscBool all)
341: {
342: PetscInt i, j, k = 0;
343: PetscObject h;
345: PetscFunctionBegin;
346: if (PetscObjectsCounts) {
347: PetscCall(PetscFPrintf(PETSC_COMM_WORLD, fd, "The following objects were never freed\n"));
348: PetscCall(PetscFPrintf(PETSC_COMM_WORLD, fd, "-----------------------------------------\n"));
349: for (i = 0; i < PetscObjectsMaxCounts; i++) {
350: if ((h = PetscObjects[i])) {
351: PetscCall(PetscObjectName(h));
352: {
353: PetscStack *stack = NULL;
354: char *create = NULL, *rclass = NULL;
356: /* if the PETSc function the user calls is not a create then this object was NOT directly created by them */
357: PetscCall(PetscMallocGetStack(h, &stack));
358: if (stack) {
359: k = stack->currentsize - 2;
360: if (!all) {
361: k = 0;
362: while (!stack->petscroutine[k]) k++;
363: PetscCall(PetscStrstr(stack->function[k], "Create", &create));
364: if (!create) PetscCall(PetscStrstr(stack->function[k], "Get", &create));
365: PetscCall(PetscStrstr(stack->function[k], h->class_name, &rclass));
366: if (!create) continue;
367: if (!rclass) continue;
368: }
369: }
371: PetscCall(PetscFPrintf(PETSC_COMM_WORLD, fd, "[%d] %s %s %s\n", PetscGlobalRank, h->class_name, h->type_name, h->name));
373: PetscCall(PetscMallocGetStack(h, &stack));
374: if (stack) {
375: for (j = k; j >= 0; j--) fprintf(fd, " [%d] %s() in %s\n", PetscGlobalRank, stack->function[j], stack->file[j]);
376: }
377: }
378: }
379: }
380: }
381: PetscFunctionReturn(PETSC_SUCCESS);
382: }
384: /*@
385: PetscObjectsView - Prints the currently existing objects.
387: Logically Collective
389: Input Parameter:
390: . viewer - must be an `PETSCVIEWERASCII` viewer
392: Level: advanced
394: .seealso: `PetscObject`
395: @*/
396: PetscErrorCode PetscObjectsView(PetscViewer viewer)
397: {
398: PetscBool isascii;
399: FILE *fd;
401: PetscFunctionBegin;
402: if (!viewer) viewer = PETSC_VIEWER_STDOUT_WORLD;
403: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
404: PetscCheck(isascii, PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Only supports ASCII viewer");
405: PetscCall(PetscViewerASCIIGetPointer(viewer, &fd));
406: PetscCall(PetscObjectsDump(fd, PETSC_TRUE));
407: PetscFunctionReturn(PETSC_SUCCESS);
408: }
410: /*@
411: PetscObjectsGetObject - Get a pointer to a named object
413: Not Collective
415: Input Parameter:
416: . name - the name of an object
418: Output Parameters:
419: + obj - the object or `NULL` if there is no object, optional, pass in `NULL` if not needed
420: - classname - the name of the class of the object, optional, pass in `NULL` if not needed
422: Level: advanced
424: .seealso: `PetscObject`
425: @*/
426: PetscErrorCode PetscObjectsGetObject(const char name[], PetscObject *obj, const char *classname[])
427: {
428: PetscObject h;
429: PetscBool flg;
431: PetscFunctionBegin;
432: PetscAssertPointer(name, 1);
433: if (obj) *obj = NULL;
434: for (PetscInt i = 0; i < PetscObjectsMaxCounts; i++) {
435: if ((h = PetscObjects[i])) {
436: PetscCall(PetscObjectName(h));
437: PetscCall(PetscStrcmp(h->name, name, &flg));
438: if (flg) {
439: if (obj) *obj = h;
440: if (classname) *classname = h->class_name;
441: PetscFunctionReturn(PETSC_SUCCESS);
442: }
443: }
444: }
445: PetscFunctionReturn(PETSC_SUCCESS);
446: }
447: #else
448: PetscErrorCode PetscObjectsView(PetscViewer viewer)
449: {
450: PetscFunctionReturn(PETSC_SUCCESS);
451: }
453: PetscErrorCode PetscObjectsGetObject(const char name[], PetscObject *obj, const char *classname[])
454: {
455: PetscFunctionReturn(PETSC_SUCCESS);
456: }
457: #endif
459: /*@
460: 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
462: Input Parameter:
463: . obj - the `PetscObject`
465: Level: developer
467: Developer Notes:
468: This is used, for example to prevent sequential objects that are created from a parallel object; such as the `KSP` created by
469: `PCBJACOBI` from all printing the same help messages to the screen
471: .seealso: `PetscOptionsInsert()`, `PetscObject`
472: @*/
473: PetscErrorCode PetscObjectSetPrintedOptions(PetscObject obj)
474: {
475: PetscFunctionBegin;
476: PetscAssertPointer(obj, 1);
477: obj->optionsprinted = PETSC_TRUE;
478: PetscFunctionReturn(PETSC_SUCCESS);
479: }
481: /*@
482: 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.
484: Input Parameters:
485: + pobj - the parent object
486: - obj - the `PetscObject`
488: Level: developer
490: Developer Notes:
491: This is used, for example to prevent sequential objects that are created from a parallel object; such as the `KSP` created by
492: `PCBJACOBI` from all printing the same help messages to the screen
494: This will not handle more complicated situations like with `PCGASM` where children may live on any subset of the parent's processes and overlap
496: .seealso: `PetscOptionsInsert()`, `PetscObjectSetPrintedOptions()`, `PetscObject`
497: @*/
498: PetscErrorCode PetscObjectInheritPrintedOptions(PetscObject pobj, PetscObject obj)
499: {
500: PetscMPIInt prank, size;
502: PetscFunctionBegin;
505: PetscCallMPI(MPI_Comm_rank(pobj->comm, &prank));
506: PetscCallMPI(MPI_Comm_size(obj->comm, &size));
507: if (size == 1 && prank > 0) obj->optionsprinted = PETSC_TRUE;
508: PetscFunctionReturn(PETSC_SUCCESS);
509: }
511: /*@
512: PetscObjectAddOptionsHandler - Adds an additional function to check for options when `XXXSetFromOptions()` is called.
514: Not Collective
516: Input Parameters:
517: + obj - the PETSc object
518: . handle - function that checks for options
519: . destroy - function to destroy `ctx` if provided
520: - ctx - optional context for check function
522: Calling sequence of `handle`:
523: + obj - the PETSc object
524: . PetscOptionsObject - the `PetscOptionItems` object
525: - ctx - optional context for `handle`
527: Calling sequence of `destroy`:
528: + obj - the PETSc object
529: - ctx - optional context for `handle`
531: Level: developer
533: .seealso: `KSPSetFromOptions()`, `PCSetFromOptions()`, `SNESSetFromOptions()`, `PetscObjectProcessOptionsHandlers()`, `PetscObjectDestroyOptionsHandlers()`,
534: `PetscObject`
535: @*/
536: PetscErrorCode PetscObjectAddOptionsHandler(PetscObject obj, PetscErrorCode (*handle)(PetscObject obj, PetscOptionItems PetscOptionsObject, PetscCtx ctx), PetscErrorCode (*destroy)(PetscObject obj, PetscCtxRt ctx), PetscCtx ctx)
537: {
538: PetscFunctionBegin;
540: for (PetscInt i = 0; i < obj->noptionhandler; i++) {
541: PetscBool identical = (PetscBool)(obj->optionhandler[i] == handle && obj->optiondestroy[i] == destroy && obj->optionctx[i] == ctx);
542: if (identical) PetscFunctionReturn(PETSC_SUCCESS);
543: }
544: PetscCheck(obj->noptionhandler < PETSC_MAX_OPTIONS_HANDLER, obj->comm, PETSC_ERR_ARG_OUTOFRANGE, "Too many options handlers added");
545: obj->optionhandler[obj->noptionhandler] = handle;
546: obj->optiondestroy[obj->noptionhandler] = destroy;
547: obj->optionctx[obj->noptionhandler++] = ctx;
548: PetscFunctionReturn(PETSC_SUCCESS);
549: }
551: /*@
552: PetscObjectProcessOptionsHandlers - Calls all the options handlers attached to an object
554: Not Collective
556: Input Parameters:
557: + obj - the PETSc object
558: - PetscOptionsObject - the options context
560: Level: developer
562: .seealso: `KSPSetFromOptions()`, `PCSetFromOptions()`, `SNESSetFromOptions()`, `PetscObjectAddOptionsHandler()`, `PetscObjectDestroyOptionsHandlers()`,
563: `PetscObject`
564: @*/
565: PetscErrorCode PetscObjectProcessOptionsHandlers(PetscObject obj, PetscOptionItems PetscOptionsObject)
566: {
567: PetscFunctionBegin;
569: for (PetscInt i = 0; i < obj->noptionhandler; i++) PetscCall((*obj->optionhandler[i])(obj, PetscOptionsObject, obj->optionctx[i]));
570: PetscFunctionReturn(PETSC_SUCCESS);
571: }
573: /*@
574: PetscObjectDestroyOptionsHandlers - Destroys all the option handlers attached to an object
576: Not Collective
578: Input Parameter:
579: . obj - the PETSc object
581: Level: developer
583: .seealso: `KSPSetFromOptions()`, `PCSetFromOptions()`, `SNESSetFromOptions()`, `PetscObjectAddOptionsHandler()`, `PetscObjectProcessOptionsHandlers()`,
584: `PetscObject`
585: @*/
586: PetscErrorCode PetscObjectDestroyOptionsHandlers(PetscObject obj)
587: {
588: PetscFunctionBegin;
590: for (PetscInt i = 0; i < obj->noptionhandler; i++) {
591: if (obj->optiondestroy[i]) PetscCall((*obj->optiondestroy[i])(obj, obj->optionctx[i]));
592: }
593: obj->noptionhandler = 0;
594: PetscFunctionReturn(PETSC_SUCCESS);
595: }
597: /*@
598: PetscObjectReference - Indicates to a `PetscObject` that it is being
599: referenced by another `PetscObject`. This increases the reference
600: count for that object by one.
602: Logically Collective
604: Input Parameter:
605: . obj - the PETSc object. This must be cast with (`PetscObject`), for example, `PetscObjectReference`((`PetscObject`)mat);
607: Level: advanced
609: Note:
610: If `obj` is `NULL` this function returns without doing anything.
612: .seealso: `PetscObjectCompose()`, `PetscObjectDereference()`, `PetscObject`
613: @*/
614: PetscErrorCode PetscObjectReference(PetscObject obj)
615: {
616: PetscFunctionBegin;
617: if (!obj) PetscFunctionReturn(PETSC_SUCCESS);
619: obj->refct++;
620: PetscFunctionReturn(PETSC_SUCCESS);
621: }
623: /*@
624: PetscObjectGetReference - Gets the current reference count for a PETSc object.
626: Not Collective
628: Input Parameter:
629: . obj - the PETSc object; this must be cast with (`PetscObject`), for example,
630: `PetscObjectGetReference`((`PetscObject`)mat,&cnt); `obj` cannot be `NULL`
632: Output Parameter:
633: . cnt - the reference count
635: Level: advanced
637: .seealso: `PetscObjectCompose()`, `PetscObjectDereference()`, `PetscObjectReference()`, `PetscObject`
638: @*/
639: PetscErrorCode PetscObjectGetReference(PetscObject obj, PetscInt *cnt)
640: {
641: PetscFunctionBegin;
643: PetscAssertPointer(cnt, 2);
644: *cnt = obj->refct;
645: PetscFunctionReturn(PETSC_SUCCESS);
646: }
648: /*@
649: PetscObjectDereference - Indicates to any `PetscObject` that it is being
650: referenced by one less `PetscObject`. This decreases the reference
651: count for that object by one.
653: Collective on `obj` if reference reaches 0 otherwise Logically Collective
655: Input Parameter:
656: . obj - the PETSc object; this must be cast with (`PetscObject`), for example,
657: `PetscObjectDereference`((`PetscObject`)mat);
659: Level: advanced
661: Notes:
662: `PetscObjectDestroy()` sets the `obj` pointer to `NULL` after the call, this routine does not.
664: If `obj` is `NULL` this function returns without doing anything.
666: .seealso: `PetscObjectCompose()`, `PetscObjectReference()`, `PetscObjectDestroy()`, `PetscObject`
667: @*/
668: PetscErrorCode PetscObjectDereference(PetscObject obj)
669: {
670: PetscFunctionBegin;
671: if (!obj) PetscFunctionReturn(PETSC_SUCCESS);
673: if (obj->bops->destroy) PetscCall((*obj->bops->destroy)(&obj));
674: else PetscCheck(--obj->refct, PETSC_COMM_SELF, PETSC_ERR_SUP, "This PETSc object does not have a generic destroy routine");
675: PetscFunctionReturn(PETSC_SUCCESS);
676: }
678: /*
679: The following routines are the versions private to the PETSc object
680: data structures.
681: */
682: /*@
683: PetscObjectRemoveReference - Removes a reference link from a `PetscObject`'s object list without dereferencing the referenced object
685: Logically collective
687: Input Parameters:
688: + obj - the `PetscObject` whose list will be modified
689: - name - the name under which the reference was composed
691: Level: developer
693: Note:
694: This is a private helper used to break composed reference cycles; user code should normally use `PetscObjectCompose()`
695: with a `NULL` pointer to remove a composed object.
697: .seealso: `PetscObject`, `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObjectReference()`, `PetscObjectDereference()`
698: @*/
699: PetscErrorCode PetscObjectRemoveReference(PetscObject obj, const char name[])
700: {
701: PetscFunctionBegin;
703: PetscCall(PetscObjectListRemoveReference(&obj->olist, name));
704: PetscFunctionReturn(PETSC_SUCCESS);
705: }
707: /*@
708: PetscObjectCompose - Associates another PETSc object with a given PETSc object.
710: Not Collective
712: Input Parameters:
713: + obj - the PETSc object; this must be cast with (`PetscObject`), for example,
714: `PetscObjectCompose`((`PetscObject`)mat,...);
715: . name - name associated with the child object
716: - ptr - the other PETSc object to associate with the PETSc object; this must also be
717: cast with (`PetscObject`)
719: Level: advanced
721: Notes:
722: The second objects reference count is automatically increased by one when it is
723: composed.
725: Replaces any previous object that had been composed with the same name.
727: If `ptr` is `NULL` and `name` has previously been composed using an object, then that
728: entry is removed from `obj`.
730: `PetscObjectCompose()` can be used with any PETSc object (such as
731: `Mat`, `Vec`, `KSP`, `SNES`, etc.) or any user-provided object.
733: `PetscContainerCreate()` or `PetscObjectContainerCompose()` can be used to create an object from a
734: user-provided pointer that may then be composed with PETSc objects using `PetscObjectCompose()`
736: Fortran Note:
737: Use
738: .vb
739: call PetscObjectCompose(obj, name, PetscObjectCast(ptr), ierr)
740: .ve
742: .seealso: `PetscObjectQuery()`, `PetscContainerCreate()`, `PetscObjectComposeFunction()`, `PetscObjectQueryFunction()`, `PetscContainer`,
743: `PetscContainerSetPointer()`, `PetscObject`, `PetscObjectContainerCompose()`
744: @*/
745: PetscErrorCode PetscObjectCompose(PetscObject obj, const char name[], PetscObject ptr)
746: {
747: PetscFunctionBegin;
749: PetscAssertPointer(name, 2);
751: PetscCheck(obj != ptr, PetscObjectComm(obj), PETSC_ERR_SUP, "Cannot compose object with itself");
752: if (ptr) {
753: const char *tname;
754: PetscBool skipreference;
756: PetscCall(PetscObjectListReverseFind(ptr->olist, obj, &tname, &skipreference));
757: if (tname) PetscCheck(skipreference, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "An object cannot be composed with an object that was composed with it");
758: }
759: PetscCall(PetscObjectListAdd(&obj->olist, name, ptr));
760: PetscFunctionReturn(PETSC_SUCCESS);
761: }
763: /*@
764: PetscObjectQuery - Gets a PETSc object associated with a given object that was composed with `PetscObjectCompose()`
766: Not Collective
768: Input Parameters:
769: + obj - the PETSc object. It must be cast with a (`PetscObject`), for example,
770: `PetscObjectCompose`((`PetscObject`)mat,...);
771: . name - name associated with child object
772: - ptr - the other PETSc object associated with the PETSc object, this must be
773: cast with (`PetscObject`*)
775: Level: advanced
777: Note:
778: The reference count of neither object is increased in this call
780: Fortran Note:
781: Use
782: .vb
783: call PetscObjectQuery(PetscObjectCast(obj), name, ptr, ierr)
784: .ve
786: .seealso: `PetscObjectCompose()`, `PetscObjectComposeFunction()`, `PetscObjectQueryFunction()`, `PetscContainer`,
787: `PetscContainerGetPointer()`, `PetscObject`
788: @*/
789: PetscErrorCode PetscObjectQuery(PetscObject obj, const char name[], PetscObject *ptr)
790: {
791: PetscFunctionBegin;
793: PetscAssertPointer(name, 2);
794: PetscAssertPointer(ptr, 3);
795: PetscCall(PetscObjectListFind(obj->olist, name, ptr));
796: PetscFunctionReturn(PETSC_SUCCESS);
797: }
799: /*MC
800: PetscObjectComposeFunction - Associates a function with a given PETSc object.
802: Synopsis:
803: #include <petscsys.h>
804: PetscErrorCode PetscObjectComposeFunction(PetscObject obj, const char name[], PetscErrorCodeFn *fptr)
806: Logically Collective
808: Input Parameters:
809: + obj - the PETSc object; this must be cast with a (`PetscObject`), for example,
810: `PetscObjectCompose`((`PetscObject`)mat,...);
811: . name - name associated with the child function
812: - fptr - function pointer
814: Level: advanced
816: Notes:
817: When the first argument of `fptr` is (or is derived from) a `PetscObject` then `PetscTryMethod()` and `PetscUseMethod()`
818: can be used to call the function directly with error checking.
820: To remove a registered routine, pass in `NULL` for `fptr`.
822: `PetscObjectComposeFunction()` can be used with any PETSc object (such as
823: `Mat`, `Vec`, `KSP`, `SNES`, etc.) or any user-provided object.
825: `PetscUseTypeMethod()` and `PetscTryTypeMethod()` are used to call a function that is stored in the objects `obj->ops` table.
827: .seealso: `PetscObjectQueryFunction()`, `PetscContainerCreate()` `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscTryMethod()`, `PetscUseMethod()`,
828: `PetscUseTypeMethod()`, `PetscTryTypeMethod()`, `PetscObject`
829: M*/
830: PetscErrorCode PetscObjectComposeFunction_Private(PetscObject obj, const char name[], PetscErrorCodeFn *fptr)
831: {
832: PetscFunctionBegin;
834: PetscAssertPointer(name, 2);
835: PetscCall(PetscFunctionListAdd_Private(&obj->qlist, name, fptr));
836: PetscFunctionReturn(PETSC_SUCCESS);
837: }
839: PETSC_EXTERN PetscErrorCode PetscObjectQueryFunction_Private(PetscObject obj, const char name[], PetscErrorCodeFn **fptr)
840: {
841: PetscFunctionBegin;
843: PetscAssertPointer(name, 2);
844: PetscCall(PetscFunctionListFind_Private(obj->qlist, name, fptr));
845: PetscFunctionReturn(PETSC_SUCCESS);
846: }
848: /*@
849: PetscObjectHasFunction - Query if a function is associated with a given object.
851: Logically Collective
853: Input Parameters:
854: + obj - the PETSc object
855: - name - name associated with the child function
857: Output Parameter:
858: . has - the boolean value
860: Level: advanced
862: .seealso: `PetscObject`, `PetscObjectComposeFunction()`, `PetscObjectQueryFunction()`
863: @*/
864: PetscErrorCode PetscObjectHasFunction(PetscObject obj, const char name[], PetscBool *has)
865: {
866: PetscErrorCodeFn *fptr = NULL;
868: PetscFunctionBegin;
869: PetscAssertPointer(has, 3);
870: PetscCall(PetscObjectQueryFunction(obj, name, &fptr));
871: *has = fptr ? PETSC_TRUE : PETSC_FALSE;
872: PetscFunctionReturn(PETSC_SUCCESS);
873: }
875: struct _p_PetscContainer {
876: PETSCHEADER(int);
877: void *ctx;
878: PetscCtxDestroyFn *ctxdestroy;
879: PetscErrorCode (*userdestroy_deprecated)(void *);
880: };
882: /*@
883: PetscContainerGetPointer - Gets the pointer value contained in the container that was provided with `PetscContainerSetPointer()`
885: Not Collective, No Fortran Support
887: Input Parameter:
888: . obj - the object created with `PetscContainerCreate()`
890: Output Parameter:
891: . ptr - the pointer value
893: Level: advanced
895: .seealso: `PetscContainerCreate()`, `PetscContainerDestroy()`, `PetscObject`,
896: `PetscContainerSetPointer()`, `PetscObjectContainerCompose()`, `PetscObjectContainerQuery()`
897: @*/
898: PetscErrorCode PetscContainerGetPointer(PetscContainer obj, PetscCtxRt ptr)
899: {
900: PetscFunctionBegin;
902: PetscAssertPointer(ptr, 2);
903: *(void **)ptr = obj->ctx;
904: PetscFunctionReturn(PETSC_SUCCESS);
905: }
907: /*@
908: PetscContainerSetPointer - Sets the pointer value contained in the container.
910: Logically Collective, No Fortran Support
912: Input Parameters:
913: + obj - the object created with `PetscContainerCreate()`
914: - ptr - the pointer value
916: Level: advanced
918: .seealso: `PetscContainerCreate()`, `PetscContainerDestroy()`, `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObject`,
919: `PetscContainerGetPointer()`, `PetscObjectContainerCompose()`, `PetscObjectContainerQuery()`
920: @*/
921: PetscErrorCode PetscContainerSetPointer(PetscContainer obj, void *ptr)
922: {
923: PetscFunctionBegin;
925: if (ptr) PetscAssertPointer(ptr, 2);
926: obj->ctx = ptr;
927: PetscFunctionReturn(PETSC_SUCCESS);
928: }
930: /*@
931: PetscContainerDestroy - Destroys a PETSc container object.
933: Collective, No Fortran Support
935: Input Parameter:
936: . obj - an object that was created with `PetscContainerCreate()`
938: Level: advanced
940: Note:
941: If `PetscContainerSetCtxDestroy()` was used to provide a user destroy object for the data provided with `PetscContainerSetPointer()`
942: then that function is called to destroy the data.
944: .seealso: `PetscContainerCreate()`, `PetscContainerSetCtxDestroy()`, `PetscObject`, `PetscObjectContainerCompose()`, `PetscObjectContainerQuery()`
945: @*/
946: PetscErrorCode PetscContainerDestroy(PetscContainer *obj)
947: {
948: PetscFunctionBegin;
949: if (!*obj) PetscFunctionReturn(PETSC_SUCCESS);
951: if (--((PetscObject)*obj)->refct > 0) {
952: *obj = NULL;
953: PetscFunctionReturn(PETSC_SUCCESS);
954: }
955: if ((*obj)->ctxdestroy) PetscCall((*(*obj)->ctxdestroy)(&(*obj)->ctx));
956: else if ((*obj)->userdestroy_deprecated) PetscCall((*(*obj)->userdestroy_deprecated)((*obj)->ctx));
957: PetscCall(PetscHeaderDestroy(obj));
958: PetscFunctionReturn(PETSC_SUCCESS);
959: }
961: /*@
962: PetscContainerSetCtxDestroy - Sets the destroy function for the data provided to the `PetscContainer` with `PetscContainerSetPointer()`
964: Logically Collective, No Fortran Support
966: Input Parameters:
967: + obj - an object that was created with `PetscContainerCreate()`
968: - des - name of the ctx destroy function, see `PetscCtxDestroyFn` for its calling sequence
970: Level: advanced
972: Note:
973: Use `PetscCtxDestroyDefault()` if the memory was obtained by calling `PetscMalloc()` or one of its variants for single memory allocation.
975: .seealso: `PetscContainerDestroy()`, `PetscContainerUserDestroyDefault()`, `PetscMalloc()`, `PetscMalloc1()`, `PetscCalloc()`, `PetscCalloc1()`, `PetscObject`,
976: `PetscObjectContainerCompose()`, `PetscObjectContainerQuery()`
977: @*/
978: PetscErrorCode PetscContainerSetCtxDestroy(PetscContainer obj, PetscCtxDestroyFn *des)
979: {
980: PetscFunctionBegin;
982: obj->ctxdestroy = des;
983: PetscFunctionReturn(PETSC_SUCCESS);
984: }
986: /*@
987: PetscContainerSetUserDestroy - Sets the destroy function for the data provided to the `PetscContainer` with `PetscContainerSetPointer()`
989: Logically Collective, No Fortran Support
991: Input Parameters:
992: + obj - an object that was created with `PetscContainerCreate()`
993: - des - name of the ctx destroy function
995: Level: advanced
997: Notes:
998: Deprecated, use `PetscContainerSetCtxDestroy()`
1000: .seealso: `PetscContainerSetCtxDestroy()`, `PetscContainerDestroy()`, `PetscContainerUserDestroyDefault()`, `PetscMalloc()`, `PetscMalloc1()`, `PetscCalloc()`, `PetscCalloc1()`, `PetscObject`,
1001: `PetscObjectContainerCompose()`, `PetscObjectContainerQuery()`
1002: @*/
1003: PetscErrorCode PetscContainerSetUserDestroy(PetscContainer obj, PetscErrorCode (*des)(void *))
1004: {
1005: PetscFunctionBegin;
1007: obj->userdestroy_deprecated = des;
1008: PetscFunctionReturn(PETSC_SUCCESS);
1009: }
1011: PetscClassId PETSC_CONTAINER_CLASSID;
1013: /*@
1014: PetscContainerCreate - Creates a PETSc object that has room to hold a single pointer.
1016: Collective, No Fortran Support
1018: Input Parameter:
1019: . comm - MPI communicator that shares the object
1021: Output Parameter:
1022: . container - the container created
1024: Level: advanced
1026: Notes:
1027: This allows one to attach any type of data (accessible through a pointer) with the
1028: `PetscObjectCompose()` function to a `PetscObject`. The data item itself is attached by a
1029: call to `PetscContainerSetPointer()`.
1031: .seealso: `PetscContainerDestroy()`, `PetscContainerSetPointer()`, `PetscContainerGetPointer()`, `PetscObjectCompose()`, `PetscObjectQuery()`,
1032: `PetscContainerSetCtxDestroy()`, `PetscObject`, `PetscObjectContainerCompose()`, `PetscObjectContainerQuery()`
1033: @*/
1034: PetscErrorCode PetscContainerCreate(MPI_Comm comm, PetscContainer *container)
1035: {
1036: PetscFunctionBegin;
1037: PetscAssertPointer(container, 2);
1038: PetscCall(PetscSysInitializePackage());
1039: PetscCall(PetscHeaderCreate(*container, PETSC_CONTAINER_CLASSID, "PetscContainer", "Container", "Sys", comm, PetscContainerDestroy, NULL));
1040: PetscFunctionReturn(PETSC_SUCCESS);
1041: }
1043: /*@
1044: PetscObjectContainerCompose - Creates a `PetscContainer`, provides all of its values and composes it with a `PetscObject`
1046: Collective
1048: Input Parameters:
1049: + obj - the `PetscObject`
1050: . name - the name for the composed container
1051: . pointer - the pointer to the data
1052: - destroy - the routine to destroy the container's data, see `PetscCtxDestroyFn` for its calling sequence; use `PetscCtxDestroyDefault()` if a `PetscFree()` frees the data
1054: Level: advanced
1056: Notes:
1057: This allows one to attach any type of data (accessible through a pointer) with the
1058: `PetscObjectCompose()` function to a `PetscObject`. The data item itself is attached by a
1059: call to `PetscContainerSetPointer()`.
1061: .seealso: `PetscContainerCreate()`, `PetscContainerDestroy()`, `PetscContainerSetPointer()`, `PetscContainerGetPointer()`, `PetscObjectCompose()`, `PetscObjectQuery()`,
1062: `PetscContainerSetCtxDestroy()`, `PetscObject`, `PetscObjectContainerQuery()`
1063: @*/
1064: PetscErrorCode PetscObjectContainerCompose(PetscObject obj, const char *name, void *pointer, PetscCtxDestroyFn *destroy)
1065: {
1066: PetscContainer container;
1068: PetscFunctionBegin;
1069: PetscCall(PetscContainerCreate(PetscObjectComm(obj), &container));
1070: PetscCall(PetscContainerSetPointer(container, pointer));
1071: if (destroy) PetscCall(PetscContainerSetCtxDestroy(container, destroy));
1072: PetscCall(PetscObjectCompose(obj, name, (PetscObject)container));
1073: PetscCall(PetscContainerDestroy(&container));
1074: PetscFunctionReturn(PETSC_SUCCESS);
1075: }
1077: /*@
1078: PetscObjectContainerQuery - Accesses the pointer in a container composed to a `PetscObject` with `PetscObjectContainerCompose()`
1080: Collective
1082: Input Parameters:
1083: + obj - the `PetscObject`
1084: - name - the name for the composed container
1086: Output Parameter:
1087: . ptr - the pointer to the data
1089: Level: advanced
1091: .seealso: `PetscContainerCreate()`, `PetscContainerDestroy()`, `PetscContainerSetPointer()`, `PetscContainerGetPointer()`, `PetscObjectCompose()`, `PetscObjectQuery()`,
1092: `PetscContainerSetCtxDestroy()`, `PetscObject`, `PetscObjectContainerCompose()`
1093: @*/
1094: PetscErrorCode PetscObjectContainerQuery(PetscObject obj, const char *name, PetscCtxRt ptr)
1095: {
1096: PetscContainer container;
1098: PetscFunctionBegin;
1099: PetscCall(PetscObjectQuery(obj, name, (PetscObject *)&container));
1100: if (container) PetscCall(PetscContainerGetPointer(container, ptr));
1101: else *(void **)ptr = NULL;
1102: PetscFunctionReturn(PETSC_SUCCESS);
1103: }
1105: /*@
1106: PetscObjectSetFromOptions - Sets generic parameters from user options.
1108: Collective
1110: Input Parameter:
1111: . obj - the `PetscObject`
1113: Level: beginner
1115: Note:
1116: We have no generic options at present, so this does nothing.
1118: .seealso: `PetscObjectSetOptionsPrefix()`, `PetscObjectGetOptionsPrefix()`, `PetscObject`
1119: @*/
1120: PetscErrorCode PetscObjectSetFromOptions(PetscObject obj)
1121: {
1122: PetscFunctionBegin;
1124: PetscFunctionReturn(PETSC_SUCCESS);
1125: }
1127: /*@
1128: PetscObjectSetUp - Sets up the internal data structures for later use of the object
1130: Collective
1132: Input Parameter:
1133: . obj - the `PetscObject`
1135: Level: advanced
1137: Note:
1138: This does nothing at present.
1140: .seealso: `PetscObjectDestroy()`, `PetscObject`
1141: @*/
1142: PetscErrorCode PetscObjectSetUp(PetscObject obj)
1143: {
1144: PetscFunctionBegin;
1146: PetscFunctionReturn(PETSC_SUCCESS);
1147: }
1149: /*MC
1150: PetscObjectIsNull - returns true if the given PETSc object is a null object
1152: Fortran only
1154: Synopsis:
1155: #include <petsc/finclude/petscsys.h>
1156: PetscBool PetscObjectIsNull(PetscObject obj)
1158: Logically Collective
1160: Input Parameter:
1161: . obj - the PETSc object
1163: Level: beginner
1165: Example Usage:
1166: .vb
1167: if (PetscObjectIsNull(dm)) then
1168: if (.not. PetscObjectIsNull(dm)) then
1169: .ve
1171: Note:
1172: Code such as
1173: .vb
1174: if (dm == PETSC_NULL_DM) then
1175: .ve
1176: is not allowed.
1178: .seealso: `PetscObject`, `PETSC_NULL_OBJECT`, `PETSC_NULL_VEC`, `PETSC_NULL_VEC_ARRAY`, `PetscObjectNullify()`
1179: M*/
1181: /*MC
1182: PetscObjectNullify - sets a PETSc object, such as `Vec`, back to the state it had when it was declared, so it
1183: can be used in a creation routine, such as `VecCreate()`
1185: Fortran only
1187: Synopsis:
1188: #include <petsc/finclude/petscsys.h>
1189: PetscObjectNullify(PetscObject obj)
1191: Logically Collective
1193: Input Parameter:
1194: . obj - the PETSc object
1196: Level: beginner
1198: Example Usage:
1199: .vb
1200: Vec x, y
1202: VecCreate(PETSC_COMM_WORLD, x, ierr)
1203: ...
1204: y = x
1205: ...
1206: PetscObjectNullify(y)
1207: .ve
1208: You should not call `VecDestroy()` on `y` because that will destroy `x` since the assignment `y = x` does
1209: not increase the reference count of `x`
1211: Note:
1212: Code such as
1213: .vb
1214: y = PETSC_NULL_VEC
1215: .ve
1216: is not allowed.
1218: .seealso: `PetscObject`, `PETSC_NULL_OBJECT`, `PETSC_NULL_VEC`, `PETSC_NULL_VEC_ARRAY`, `PetscObjectIsNull()`
1219: M*/
1221: /*MC
1222: PetscObjectCast - Casts a `PetscObject` to the base `PetscObject` type in function calls
1224: Fortran only
1226: Synopsis:
1227: use petscsys
1229: Level: beginner
1231: Example Usage:
1232: PetscFE fe
1233: .vb
1234: PetscCallA(DMAddField(dm, 0, PetscObjectCast(fe),ierr)
1235: .ve
1237: .seealso: `PetscObject`, `PetscObjectSpecificCast()`
1238: M*/
1240: /*MC
1241: PetscObjectSpecificCast - Casts a `PetscObject` to any specific `PetscObject`
1243: Fortran only
1245: Synopsis:
1246: use petscsys
1248: Level: beginner
1250: Example Usage:
1251: PetscObject obj
1252: PetscFE fe
1253: .vb
1254: PetscCallA(PetscDSGetDiscretization(ds, 0, obj, ierr)
1255: PetscObjectSpecificCast(fe,obj)
1256: .ve
1258: .seealso: `PetscObject`, `PetscObjectCast()`
1259: M*/
1261: /*MC
1262: PetscEnumCase - `case()` statement for a PETSc enum variable or value
1264: Fortran only
1266: Synopsis:
1267: #include <petsc/finclude/petscsys.h>
1268: PetscEnumCase(PetscObject enm)
1270: Input Parameters:
1271: . enum - the PETSc enum value or variable
1273: Level: beginner
1275: Example Usage:
1276: .vb
1277: DMPolytopeType cellType
1278: select PetscEnumCase(cellType)
1279: PetscEnumCase(DM_POLYTOPE_TRIANGLE)
1280: write(*,*) 'cell is a triangle'
1281: PetscEnumCase(DM_POLYTOPE_TETRAHEDRON)
1282: write(*,*) 'cell is a tetrahedron'
1283: case default
1284: write(*,*) 'cell is a something else'
1285: end select
1286: .ve
1287: is equivalent to
1288: .vb
1289: DMPolytopeType cellType
1290: select case(cellType%v)
1291: case(DM_POLYTOPE_TRIANGLE%v)
1292: write(*,*) 'cell is a triangle'
1293: case(DM_POLYTOPE_TETRAHEDRON%v)
1294: write(*,*) 'cell is a tetrahedron'
1295: case default
1296: write(*,*) 'cell is a something else'
1297: end select
1298: .ve
1300: .seealso: `PetscObject`
1301: M*/