Actual source code: destroy.c
1: /*
2: Provides utility routines for manulating any type of PETSc object.
3: */
4: #include <petsc/private/petscimpl.h>
6: static PetscErrorCode DestroyComposedData(void ***composed_star, PetscObjectState **state_star, PetscInt *count_star, void **composed, PetscObjectState **state)
7: {
8: void **tmp_star = *composed_star;
10: PetscFunctionBegin;
11: for (PetscInt i = 0, imax = *count_star; i < imax; ++i) PetscCall(PetscFree(tmp_star[i]));
12: PetscCall(PetscFree2(*composed_star, *state_star));
13: PetscCall(PetscFree2(*composed, *state));
14: *count_star = 0;
15: PetscFunctionReturn(PETSC_SUCCESS);
16: }
18: PetscErrorCode PetscComposedQuantitiesDestroy(PetscObject obj)
19: {
20: PetscFunctionBegin;
22: PetscCall(DestroyComposedData((void ***)&obj->intstarcomposeddata, &obj->intstarcomposedstate, &obj->intstar_idmax, (void **)&obj->intcomposeddata, &obj->intcomposedstate));
23: PetscCall(DestroyComposedData((void ***)&obj->realstarcomposeddata, &obj->realstarcomposedstate, &obj->realstar_idmax, (void **)&obj->realcomposeddata, &obj->realcomposedstate));
24: #if PetscDefined(USE_COMPLEX)
25: PetscCall(DestroyComposedData((void ***)&obj->scalarstarcomposeddata, &obj->scalarstarcomposedstate, &obj->scalarstar_idmax, (void **)&obj->scalarcomposeddata, &obj->scalarcomposedstate));
26: #endif
27: PetscFunctionReturn(PETSC_SUCCESS);
28: }
30: /*@
31: PetscObjectDestroy - Destroys a `PetscObject`, regardless of the class.
33: Collective
35: Input Parameter:
36: . obj - any PETSc object, for example a `Vec`, `Mat` or `KSP`. It must be cast with a (`PetscObject`\*), for example,
37: `PetscObjectDestroy`((`PetscObject`\*)&mat);
39: Level: beginner
41: .seealso: `PetscObject`
42: @*/
43: PetscErrorCode PetscObjectDestroy(PetscObject *obj)
44: {
45: PetscFunctionBegin;
46: if (!obj || !*obj) PetscFunctionReturn(PETSC_SUCCESS);
48: PetscCheck((*obj)->bops->destroy, PETSC_COMM_SELF, PETSC_ERR_PLIB, "This PETSc object of class %s does not have a generic destroy routine", (*obj)->class_name);
49: PetscCall((*(*obj)->bops->destroy)(obj));
50: PetscFunctionReturn(PETSC_SUCCESS);
51: }
53: /*@
54: PetscObjectView - Views, that is displays or stores information about a `PetscObject`.
56: Collective
58: Input Parameters:
59: + obj - any PETSc object, for example a `Vec`, `Mat` or `KSP`. It must be cast with a (`PetscObject`), for example,
60: `PetscObjectView`((`PetscObject`)mat,`viewer`);
61: - viewer - any PETSc viewer
63: Level: intermediate
65: .seealso: `PetscObject`, `PetscObjectViewFromOptions()`, `PetscViewer`
66: @*/
67: PetscErrorCode PetscObjectView(PetscObject obj, PetscViewer viewer)
68: {
69: PetscFunctionBegin;
71: PetscCheck(obj->bops->view, PETSC_COMM_SELF, PETSC_ERR_SUP, "This PETSc object does not have a generic viewer routine");
72: if (!viewer) PetscCall(PetscViewerASCIIGetStdout(obj->comm, &viewer));
75: PetscCall((*obj->bops->view)(obj, viewer));
76: PetscFunctionReturn(PETSC_SUCCESS);
77: }
79: /*@
80: PetscObjectViewFromOptions - Processes command line options to determine if/how a `PetscObject` is to be viewed.
82: Collective
84: Input Parameters:
85: + obj - the object
86: . bobj - optional other object that provides prefix (if `NULL` then the prefix in `obj` is used)
87: - name - option string that is used to activate viewing. It typically ends with `_view`.
89: Options Database Key:
90: . -name viewer_specification - See `PetscOptionsCreateViewer()` for the values of `viewer_specification`
92: Level: developer
94: Notes:
95: This function is usually not called directly but is called by, for example, `MatViewFromOptions()`.
97: This checks the options database, creates the viewer on-the-fly, uses it and then destroys it. Hence it should not be called in heavily used routines,
98: rather `PetscOptionsCreateViewer()` should be used to construct the viewer once which can then be utilized in the heavily used routine.
100: .seealso: `PetscObject`, `PetscObjectViewSynchronizedFromOptions()`, `PetscObjectView()`, `PetscOptionsCreateViewer()`
101: @*/
102: PetscErrorCode PetscObjectViewFromOptions(PetscObject obj, PetscObject bobj, const char name[])
103: {
104: PetscViewer viewer;
105: PetscBool flg;
106: static PetscBool incall = PETSC_FALSE;
107: PetscViewerFormat format;
108: const char *prefix;
110: PetscFunctionBegin;
113: if (incall) PetscFunctionReturn(PETSC_SUCCESS);
114: incall = PETSC_TRUE;
115: prefix = bobj ? bobj->prefix : obj->prefix;
116: PetscCall(PetscOptionsCreateViewer(PetscObjectComm(obj), obj->options, prefix, name, &viewer, &format, &flg));
117: if (flg) {
118: PetscCall(PetscViewerPushFormat(viewer, format));
119: PetscCall(PetscObjectView(obj, viewer));
120: PetscCall(PetscViewerFlush(viewer));
121: PetscCall(PetscViewerPopFormat(viewer));
122: PetscCall(PetscViewerDestroy(&viewer));
123: }
124: incall = PETSC_FALSE;
125: PetscFunctionReturn(PETSC_SUCCESS);
126: }
128: /*@
129: PetscObjectViewSynchronizedFromOptions - Processes command line options to determine if/how a serial `PetscObject` is to be collectively viewed.
131: Collective
133: Input Parameters:
134: + obj - the serial object
135: . sobj - synchronization object that provides the synchronizing communicator
136: - name - option string that is used to activate viewing. It typically ends with `_view`.
138: Options Database Key:
139: . -name viewer_specification - See `PetscOptionsCreateViewer()` for the values of `viewer_specification`
141: Level: developer
143: Notes:
144: The objects will be viewed in sequence, following the MPI rank order.
146: The prefix of `obj` is used to search the options database key
148: .seealso: `PetscObject`, `PetscObjectViewFromOptions()`, `PetscObjectView()`, `PetscOptionsCreateViewer()`
149: @*/
150: PetscErrorCode PetscObjectViewSynchronizedFromOptions(PetscObject obj, PetscObject sobj, const char name[])
151: {
152: PetscViewer viewer;
153: PetscBool flg;
154: static PetscBool incall = PETSC_FALSE;
155: PetscViewerFormat format;
157: PetscFunctionBegin;
160: if (incall) PetscFunctionReturn(PETSC_SUCCESS);
161: incall = PETSC_TRUE;
162: PetscCall(PetscOptionsCreateViewer(PetscObjectComm(sobj), obj->options, obj->prefix, name, &viewer, &format, &flg));
163: if (flg) {
164: PetscViewer selfviewer;
166: PetscCall(PetscViewerPushFormat(viewer, format));
167: PetscCall(PetscViewerASCIIPushSynchronized(viewer));
168: PetscCall(PetscViewerGetSubViewer(viewer, PETSC_COMM_SELF, &selfviewer));
169: PetscCall(PetscObjectView(obj, selfviewer));
170: PetscCall(PetscViewerRestoreSubViewer(viewer, PETSC_COMM_SELF, &selfviewer));
171: PetscCall(PetscViewerASCIIPopSynchronized(viewer));
172: PetscCall(PetscViewerFlush(viewer));
173: PetscCall(PetscViewerPopFormat(viewer));
174: PetscCall(PetscViewerDestroy(&viewer));
175: }
176: incall = PETSC_FALSE;
177: PetscFunctionReturn(PETSC_SUCCESS);
178: }
180: /*@
181: PetscObjectTypeCompare - Determines whether a PETSc object is of a particular type.
183: Not Collective
185: Input Parameters:
186: + obj - a PETSc object, for example a `Vec`, `Mat` or `KSP`. It must be cast with a (`PetscObject`), for example,
187: `PetscObjectTypeCompare`((`PetscObject`)mat);
188: - type_name - string containing a type name
190: Output Parameter:
191: . same - `PETSC_TRUE` if the type of `obj` and `type_name` are the same or both `NULL`, else `PETSC_FALSE`
193: Level: intermediate
195: .seealso: `PetscObject`, `VecGetType()`, `KSPGetType()`, `PCGetType()`, `SNESGetType()`, `PetscObjectBaseTypeCompare()`, `PetscObjectTypeCompareAny()`, `PetscObjectBaseTypeCompareAny()`, `PetscObjectObjectTypeCompare()`
196: @*/
197: PetscErrorCode PetscObjectTypeCompare(PetscObject obj, const char type_name[], PetscBool *same)
198: {
199: PetscFunctionBegin;
200: PetscAssertPointer(same, 3);
201: if (!obj) *same = (PetscBool)!type_name;
202: else {
204: if (!type_name || !obj->type_name) *same = (PetscBool)(!obj->type_name == !type_name);
205: else {
206: PetscAssertPointer(type_name, 2);
207: PetscCall(PetscStrcmp(obj->type_name, type_name, same));
208: }
209: }
210: PetscFunctionReturn(PETSC_SUCCESS);
211: }
213: /*@
214: PetscObjectObjectTypeCompare - Determines whether two PETSc objects are of the same type
216: Logically Collective
218: Input Parameters:
219: + obj1 - any PETSc object, for example a `Vec`, `Mat` or `KSP`.
220: - obj2 - another PETSc object
222: Output Parameter:
223: . same - `PETSC_TRUE` if they are the same or both unset, else `PETSC_FALSE`
225: Level: intermediate
227: Note:
228: Both objects must be of the same class, for example both `Vec` objects.
230: .seealso: `PetscObjectTypeCompare()`, `VecGetType()`, `KSPGetType()`, `PCGetType()`, `SNESGetType()`, `PetscObjectBaseTypeCompare()`, `PetscObjectTypeCompareAny()`, `PetscObjectBaseTypeCompareAny()`
231: @*/
232: PetscErrorCode PetscObjectObjectTypeCompare(PetscObject obj1, PetscObject obj2, PetscBool *same)
233: {
234: PetscFunctionBegin;
237: PetscAssertPointer(same, 3);
238: PetscCall(PetscStrcmp(obj1->type_name, obj2->type_name, same));
239: PetscFunctionReturn(PETSC_SUCCESS);
240: }
242: /*@
243: PetscObjectBaseTypeCompare - Determines whether a `PetscObject` is of a given base type. For example the base type of `MATSEQAIJPERM` is `MATSEQAIJ`
245: Not Collective
247: Input Parameters:
248: + obj - the object
249: - type_name - string containing a type name
251: Output Parameter:
252: . same - `PETSC_TRUE` if the object is of the same base type identified by `type_name` or both `NULL`, `PETSC_FALSE` otherwise
254: Level: intermediate
256: .seealso: `PetscObject`, `PetscObjectTypeCompare()`, `PetscObjectTypeCompareAny()`, `PetscObjectBaseTypeCompareAny()`
257: @*/
258: PetscErrorCode PetscObjectBaseTypeCompare(PetscObject obj, const char type_name[], PetscBool *same)
259: {
260: PetscFunctionBegin;
261: PetscAssertPointer(same, 3);
262: if (!obj) *same = (PetscBool)!type_name;
263: else {
265: if (!type_name || !obj->type_name) *same = (PetscBool)(!obj->type_name == !type_name);
266: else {
267: PetscAssertPointer(type_name, 2);
268: PetscCall(PetscStrbeginswith(obj->type_name, type_name, same));
269: }
270: }
271: PetscFunctionReturn(PETSC_SUCCESS);
272: }
274: /*@
275: PetscObjectTypeCompareAny - Determines whether a PETSc object is of any of a list of types.
277: Not Collective
279: Input Parameters:
280: + obj - a PETSc object, for example a `Vec`, `Mat` or `KSP`. It must be cast with a (`PetscObject`),
281: for example, `PetscObjectTypeCompareAny`((`PetscObject`)mat,...);
282: - type_name - one or more string arguments containing type names, pass the empty string `""` as the last argument
284: Output Parameter:
285: . match - `PETSC_TRUE` if the type of `obj` matches any in the list, else `PETSC_FALSE`
287: Level: intermediate
289: .seealso: `VecGetType()`, `KSPGetType()`, `PCGetType()`, `SNESGetType()`, `PetscObjectTypeCompare()`, `PetscObjectBaseTypeCompare()`
290: @*/
291: PetscErrorCode PetscObjectTypeCompareAny(PetscObject obj, PetscBool *match, const char type_name[], ...)
292: {
293: va_list Argp;
295: PetscFunctionBegin;
296: PetscAssertPointer(match, 2);
297: *match = PETSC_FALSE;
298: if (!obj) PetscFunctionReturn(PETSC_SUCCESS);
299: va_start(Argp, type_name);
300: while (type_name && type_name[0]) {
301: PetscBool found;
302: PetscCall(PetscObjectTypeCompare(obj, type_name, &found));
303: if (found) {
304: *match = PETSC_TRUE;
305: break;
306: }
307: type_name = va_arg(Argp, const char *);
308: }
309: va_end(Argp);
310: PetscFunctionReturn(PETSC_SUCCESS);
311: }
313: /*@
314: PetscObjectBaseTypeCompareAny - Determines whether a PETSc object has the base type of any of a list of types.
316: Not Collective
318: Input Parameters:
319: + obj - a PETSc object, for example a `Vec`, `Mat` or `KSP`. It must be cast with a (`PetscObject`),
320: for example, `PetscObjectBaseTypeCompareAny`((`PetscObject`)mat,...);
321: - type_name - one or more string arguments containing type names, pass the empty string `""` as the last argument
323: Output Parameter:
324: . match - `PETSC_TRUE` if the type of `obj` matches any in the list, else `PETSC_FALSE`
326: Level: intermediate
328: .seealso: `VecGetType()`, `KSPGetType()`, `PCGetType()`, `SNESGetType()`, `PetscObjectTypeCompare()`, `PetscObjectBaseTypeCompare()`, `PetscObjectTypeCompareAny()`
329: @*/
330: PetscErrorCode PetscObjectBaseTypeCompareAny(PetscObject obj, PetscBool *match, const char type_name[], ...)
331: {
332: va_list Argp;
334: PetscFunctionBegin;
335: PetscAssertPointer(match, 2);
336: *match = PETSC_FALSE;
337: va_start(Argp, type_name);
338: while (type_name && type_name[0]) {
339: PetscBool found;
340: PetscCall(PetscObjectBaseTypeCompare(obj, type_name, &found));
341: if (found) {
342: *match = PETSC_TRUE;
343: break;
344: }
345: type_name = va_arg(Argp, const char *);
346: }
347: va_end(Argp);
348: PetscFunctionReturn(PETSC_SUCCESS);
349: }
351: typedef struct {
352: PetscErrorCode (*func)(void);
353: } PetscFinalizeFunction;
355: typedef struct {
356: PetscErrorCode (*func)(void *);
357: PetscCtx ctx;
358: } PetscFinalizeFunctionWithCtx;
360: typedef enum {
361: PETSC_FINALIZE_EMPTY,
362: PETSC_FINALIZE_OBJECT,
363: PETSC_FINALIZE_FUNC,
364: PETSC_FINALIZE_FUNC_WITH_CTX
365: } PetscFinalizeType;
367: static const char *const PetscFinalizeTypes[] = {"PETSC_FINALIZE_EMPTY", "PETSC_FINALIZE_OBJECT", "PETSC_FINALIZE_FUNC", "PETSC_FINALIZE_FUNC_WITH_CTX", PETSC_NULLPTR};
369: typedef struct {
370: union ThunkUnion
371: {
372: PetscObject obj;
373: PetscFinalizeFunction fn;
374: PetscFinalizeFunctionWithCtx fnctx;
375: } thunk;
376: PetscFinalizeType type;
377: } PetscFinalizerContainer;
379: #define PETSC_MAX_REGISTERED_FINALIZERS 256
380: static int reg_count = 0;
381: static PetscFinalizerContainer regfin[PETSC_MAX_REGISTERED_FINALIZERS];
383: static PetscErrorCode PetscRunRegisteredFinalizers(void)
384: {
385: PetscFunctionBegin;
386: while (reg_count) {
387: PetscFinalizerContainer top = regfin[--reg_count];
389: regfin[reg_count].type = PETSC_FINALIZE_EMPTY;
390: PetscCall(PetscArrayzero(®fin[reg_count].thunk, 1));
391: switch (top.type) {
392: case PETSC_FINALIZE_OBJECT:
393: PetscCall(PetscObjectDestroy(&top.thunk.obj));
394: break;
395: case PETSC_FINALIZE_FUNC:
396: PetscCall((*top.thunk.fn.func)());
397: break;
398: case PETSC_FINALIZE_FUNC_WITH_CTX:
399: PetscCall((*top.thunk.fnctx.func)(top.thunk.fnctx.ctx));
400: break;
401: case PETSC_FINALIZE_EMPTY:
402: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Finalizer at position %d is empty, yet registration count %d != 0", reg_count, reg_count);
403: break;
404: }
405: }
406: PetscFunctionReturn(PETSC_SUCCESS);
407: }
409: static int PetscFinalizerContainerEqual(const PetscFinalizerContainer *a, const PetscFinalizerContainer *b)
410: {
411: if (a->type != b->type) return 0;
412: switch (a->type) {
413: case PETSC_FINALIZE_EMPTY:
414: break;
415: case PETSC_FINALIZE_OBJECT:
416: return a->thunk.obj == b->thunk.obj;
417: case PETSC_FINALIZE_FUNC:
418: return a->thunk.fn.func == b->thunk.fn.func;
419: case PETSC_FINALIZE_FUNC_WITH_CTX:
420: return a->thunk.fnctx.func == b->thunk.fnctx.func && a->thunk.fnctx.ctx == b->thunk.fnctx.ctx;
421: }
422: return 1;
423: }
425: static PetscErrorCode RegisterFinalizer(PetscFinalizerContainer container)
426: {
427: PetscFunctionBegin;
428: PetscAssert(reg_count < (int)PETSC_STATIC_ARRAY_LENGTH(regfin), PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "No more room in array, limit %zu, recompile %s with larger value for " PetscStringize(regfin), PETSC_STATIC_ARRAY_LENGTH(regfin), __FILE__);
429: PetscAssert(regfin[reg_count].type == PETSC_FINALIZE_EMPTY, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Finalizer type (%s) at position %d is not PETSC_FINALIZE_EMPTY!", PetscFinalizeTypes[regfin[reg_count].type], reg_count);
430: if (PetscDefined(USE_DEBUG)) {
431: for (int i = 0; i < reg_count; ++i) PetscCheck(!PetscFinalizerContainerEqual(regfin + i, &container), PETSC_COMM_SELF, PETSC_ERR_ORDER, "Finalizer (of type %s) already registered!", PetscFinalizeTypes[container.type]);
432: }
433: regfin[reg_count++] = container;
434: PetscFunctionReturn(PETSC_SUCCESS);
435: }
437: /*@
438: PetscObjectRegisterDestroy - Registers a PETSc object to be destroyed when
439: `PetscFinalize()` is called.
441: Logically Collective
443: Input Parameter:
444: . obj - a PETSc object, for example a `Vec`, `Mat` or `KSP`. It must be cast with a (`PetscObject`), for example,
445: `PetscObjectRegisterDestroy`((`PetscObject`)mat);
447: Level: developer
449: Notes:
450: This is used by, for example, `PETSC_VIEWER_XXX_()` routines to free the viewer
451: when PETSc ends.
453: This should be used only where there is no natural location in the code to put a call to the destructor of the object.
455: .seealso: `PetscObjectRegisterDestroyAll()`
456: @*/
457: PetscErrorCode PetscObjectRegisterDestroy(PetscObject obj)
458: {
459: PetscFinalizerContainer container;
461: PetscFunctionBegin;
463: container.thunk.obj = obj;
464: container.type = PETSC_FINALIZE_OBJECT;
465: PetscCall(RegisterFinalizer(container));
466: PetscFunctionReturn(PETSC_SUCCESS);
467: }
469: /*@
470: PetscObjectRegisterDestroyAll - Frees all the PETSc objects that have been registered
471: with `PetscObjectRegisterDestroy()`. Called by `PetscFinalize()`
473: Logically Collective on the individual `PetscObject`s that are being processed
475: Level: developer
477: .seealso: `PetscObjectRegisterDestroy()`
478: @*/
479: PetscErrorCode PetscObjectRegisterDestroyAll(void)
480: {
481: PetscFunctionBegin;
482: PetscCall(PetscRunRegisteredFinalizers());
483: PetscFunctionReturn(PETSC_SUCCESS);
484: }
486: /*@
487: PetscRegisterFinalize - Registers a function that is to be called in `PetscFinalize()`
489: Not Collective
491: Input Parameter:
492: . f - function to be called
494: Level: developer
496: Notes:
497: This is used by, for example, `DMInitializePackage()` to have `DMFinalizePackage()` called
499: Use `PetscObjectRegisterDestroy()` to register the destruction of an object in `PetscFinalize()`
501: .seealso: `PetscRegisterFinalizeAll()`, `PetscObjectRegisterDestroy()`
502: @*/
503: PetscErrorCode PetscRegisterFinalize(PetscErrorCode (*f)(void))
504: {
505: PetscFinalizerContainer container;
507: PetscFunctionBegin;
509: container.thunk.fn.func = f;
510: container.type = PETSC_FINALIZE_FUNC;
511: PetscCall(RegisterFinalizer(container));
512: PetscFunctionReturn(PETSC_SUCCESS);
513: }
515: /*@
516: PetscRegisterFinalizeAll - Runs all the finalize functions set with `PetscRegisterFinalize()`
518: Not Collective except for registered functions that are collective
520: Level: developer
522: .seealso: `PetscRegisterFinalize()`, `PetscObjectRegisterDestroyAll()`
523: @*/
524: PetscErrorCode PetscRegisterFinalizeAll(void)
525: {
526: PetscFunctionBegin;
527: PetscCall(PetscRunRegisteredFinalizers());
528: PetscFunctionReturn(PETSC_SUCCESS);
529: }