Actual source code: destroy.c
1: /*
2: Provides utility routines for manulating any type of PETSc object.
3: */
4: #include <petsc/private/petscimpl.h>
5: #include <petscviewer.h>
7: static PetscErrorCode DestroyComposedData(void ***composed_star, PetscObjectState **state_star, PetscInt *count_star, void **composed, PetscObjectState **state)
8: {
9: void **tmp_star = *composed_star;
11: PetscFunctionBegin;
12: for (PetscInt i = 0, imax = *count_star; i < imax; ++i) PetscCall(PetscFree(tmp_star[i]));
13: PetscCall(PetscFree2(*composed_star, *state_star));
14: PetscCall(PetscFree2(*composed, *state));
15: *count_star = 0;
16: PetscFunctionReturn(PETSC_SUCCESS);
17: }
19: PetscErrorCode PetscComposedQuantitiesDestroy(PetscObject obj)
20: {
21: PetscFunctionBegin;
23: PetscCall(DestroyComposedData((void ***)&obj->intstarcomposeddata, &obj->intstarcomposedstate, &obj->intstar_idmax, (void **)&obj->intcomposeddata, &obj->intcomposedstate));
24: PetscCall(DestroyComposedData((void ***)&obj->realstarcomposeddata, &obj->realstarcomposedstate, &obj->realstar_idmax, (void **)&obj->realcomposeddata, &obj->realcomposedstate));
25: #if PetscDefined(USE_COMPLEX)
26: PetscCall(DestroyComposedData((void ***)&obj->scalarstarcomposeddata, &obj->scalarstarcomposedstate, &obj->scalarstar_idmax, (void **)&obj->scalarcomposeddata, &obj->scalarcomposedstate));
27: #endif
28: PetscFunctionReturn(PETSC_SUCCESS);
29: }
31: /*@
32: PetscObjectDestroy - Destroys a `PetscObject`, regardless of the type.
34: Collective
36: Input Parameter:
37: . obj - any PETSc object, for example a `Vec`, `Mat` or `KSP`.
38: This must be cast with a (`PetscObject`*), for example,
39: `PetscObjectDestroy`((`PetscObject`*)&mat);
41: Level: beginner
43: .seealso: `PetscObject`
44: @*/
45: PetscErrorCode PetscObjectDestroy(PetscObject *obj)
46: {
47: PetscFunctionBegin;
48: if (!obj || !*obj) PetscFunctionReturn(PETSC_SUCCESS);
50: 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);
51: PetscCall((*(*obj)->bops->destroy)(obj));
52: PetscFunctionReturn(PETSC_SUCCESS);
53: }
55: /*@C
56: PetscObjectView - Views a `PetscObject`, regardless of the type.
58: Collective
60: Input Parameters:
61: + obj - any PETSc object, for example a `Vec`, `Mat` or `KSP`.
62: This must be cast with a (`PetscObject`), for example,
63: `PetscObjectView`((`PetscObject`)mat,viewer);
64: - viewer - any PETSc viewer
66: Level: intermediate
68: .seealso: `PetscObject`, `PetscObjectViewFromOptions()`, `PetscViewer`
69: @*/
70: PetscErrorCode PetscObjectView(PetscObject obj, PetscViewer viewer)
71: {
72: PetscFunctionBegin;
74: PetscCheck(obj->bops->view, PETSC_COMM_SELF, PETSC_ERR_SUP, "This PETSc object does not have a generic viewer routine");
75: if (!viewer) PetscCall(PetscViewerASCIIGetStdout(obj->comm, &viewer));
78: PetscCall((*obj->bops->view)(obj, viewer));
79: PetscFunctionReturn(PETSC_SUCCESS);
80: }
82: /*@C
83: PetscObjectViewFromOptions - Processes command line options to determine if/how a `PetscObject` is to be viewed.
85: Collective
87: Input Parameters:
88: + obj - the object
89: . bobj - optional other object that provides prefix (if `NULL` then the prefix in `obj` is used)
90: - optionname - option string that is used to activate viewing
92: Options Database Key:
93: . -optionname_view [viewertype]:... - option name and values. In actual usage this would be something like `-mat_coarse_view`
95: Level: developer
97: Notes:
98: .vb
99: If no value is provided ascii:stdout is used
100: ascii[:[filename][:[format][:append]]] defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab,
101: for example ascii::ascii_info prints just the information about the object not all details
102: unless :append is given filename opens in write mode, overwriting what was already there
103: binary[:[filename][:[format][:append]]] defaults to the file binaryoutput
104: draw[:drawtype[:filename]] for example, draw:tikz, draw:tikz:figure.tex or draw:x
105: socket[:port] defaults to the standard output port
106: saws[:communicatorname] publishes object to the Scientific Application Webserver (SAWs)
107: .ve
109: This is not called directly but is called by, for example, `MatViewFromOptions()`
111: .seealso: `PetscObject`, `PetscObjectView()`, `PetscOptionsGetViewer()`
112: @*/
113: PetscErrorCode PetscObjectViewFromOptions(PetscObject obj, PetscObject bobj, const char optionname[])
114: {
115: PetscViewer viewer;
116: PetscBool flg;
117: static PetscBool incall = PETSC_FALSE;
118: PetscViewerFormat format;
119: const char *prefix;
121: PetscFunctionBegin;
124: if (incall) PetscFunctionReturn(PETSC_SUCCESS);
125: incall = PETSC_TRUE;
126: prefix = bobj ? bobj->prefix : obj->prefix;
127: PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)obj), obj->options, prefix, optionname, &viewer, &format, &flg));
128: if (flg) {
129: PetscCall(PetscViewerPushFormat(viewer, format));
130: PetscCall(PetscObjectView(obj, viewer));
131: PetscCall(PetscViewerFlush(viewer));
132: PetscCall(PetscViewerPopFormat(viewer));
133: PetscCall(PetscViewerDestroy(&viewer));
134: }
135: incall = PETSC_FALSE;
136: PetscFunctionReturn(PETSC_SUCCESS);
137: }
139: /*@C
140: PetscObjectTypeCompare - Determines whether a PETSc object is of a particular type.
142: Not Collective
144: Input Parameters:
145: + obj - a PETSc object, for example a `Vec`, `Mat` or `KSP`.
146: This must be cast with a (`PetscObject`), for example,
147: `PetscObjectTypeCompare`((`PetscObject`)mat);
148: - type_name - string containing a type name
150: Output Parameter:
151: . same - `PETSC_TRUE` if the type of `obj` and `type_name` are the same or both `NULL`, else `PETSC_FALSE`
153: Level: intermediate
155: .seealso: `PetscObject`, `VecGetType()`, `KSPGetType()`, `PCGetType()`, `SNESGetType()`, `PetscObjectBaseTypeCompare()`, `PetscObjectTypeCompareAny()`, `PetscObjectBaseTypeCompareAny()`, `PetscObjectObjectTypeCompare()`
156: @*/
157: PetscErrorCode PetscObjectTypeCompare(PetscObject obj, const char type_name[], PetscBool *same)
158: {
159: PetscFunctionBegin;
160: PetscAssertPointer(same, 3);
161: if (!obj) *same = (PetscBool)!type_name;
162: else {
164: if (!type_name || !obj->type_name) *same = (PetscBool)(!obj->type_name == !type_name);
165: else {
166: PetscAssertPointer(type_name, 2);
167: PetscCall(PetscStrcmp(obj->type_name, type_name, same));
168: }
169: }
170: PetscFunctionReturn(PETSC_SUCCESS);
171: }
173: /*@C
174: PetscObjectObjectTypeCompare - Determines whether two PETSc objects are of the same type
176: Logically Collective
178: Input Parameters:
179: + obj1 - any PETSc object, for example a `Vec`, `Mat` or `KSP`.
180: - obj2 - another PETSc object
182: Output Parameter:
183: . same - `PETSC_TRUE` if they are the same or both unset, else `PETSC_FALSE`
185: Level: intermediate
187: .seealso: `PetscObjectTypeCompare()`, `VecGetType()`, `KSPGetType()`, `PCGetType()`, `SNESGetType()`, `PetscObjectBaseTypeCompare()`, `PetscObjectTypeCompareAny()`, `PetscObjectBaseTypeCompareAny()`
189: @*/
190: PetscErrorCode PetscObjectObjectTypeCompare(PetscObject obj1, PetscObject obj2, PetscBool *same)
191: {
192: PetscFunctionBegin;
195: PetscAssertPointer(same, 3);
196: PetscCall(PetscStrcmp(obj1->type_name, obj2->type_name, same));
197: PetscFunctionReturn(PETSC_SUCCESS);
198: }
200: /*@C
201: PetscObjectBaseTypeCompare - Determines whether a `PetscObject` is of a given base type. For example the base type of `MATSEQAIJPERM` is `MATSEQAIJ`
203: Not Collective
205: Input Parameters:
206: + obj - the matrix
207: - type_name - string containing a type name
209: Output Parameter:
210: . same - `PETSC_TRUE` if the object is of the same base type identified by `type_name` or both `NULL`, `PETSC_FALSE` otherwise
212: Level: intermediate
214: .seealso: `PetscObject`, `PetscObjectTypeCompare()`, `PetscObjectTypeCompareAny()`, `PetscObjectBaseTypeCompareAny()`
215: @*/
216: PetscErrorCode PetscObjectBaseTypeCompare(PetscObject obj, const char type_name[], PetscBool *same)
217: {
218: PetscFunctionBegin;
219: PetscAssertPointer(same, 3);
220: if (!obj) *same = (PetscBool)!type_name;
221: else {
223: if (!type_name || !obj->type_name) *same = (PetscBool)(!obj->type_name == !type_name);
224: else {
225: PetscAssertPointer(type_name, 2);
226: PetscCall(PetscStrbeginswith(obj->type_name, type_name, same));
227: }
228: }
229: PetscFunctionReturn(PETSC_SUCCESS);
230: }
232: /*@C
233: PetscObjectTypeCompareAny - Determines whether a PETSc object is of any of a list of types.
235: Not Collective
237: Input Parameters:
238: + obj - a PETSc object, for example a `Vec`, `Mat` or `KSP`.
239: This must be cast with a (`PetscObject`), for example, `PetscObjectTypeCompareAny`((`PetscObject`)mat,...);
240: - type_name - array of strings containing type names, pass the empty string "" to terminate the list
242: Output Parameter:
243: . match - `PETSC_TRUE` if the type of `obj` matches any in the list, else `PETSC_FALSE`
245: Level: intermediate
247: .seealso: `VecGetType()`, `KSPGetType()`, `PCGetType()`, `SNESGetType()`, `PetscObjectTypeCompare()`, `PetscObjectBaseTypeCompare()`
248: @*/
249: PetscErrorCode PetscObjectTypeCompareAny(PetscObject obj, PetscBool *match, const char type_name[], ...)
250: {
251: va_list Argp;
253: PetscFunctionBegin;
254: PetscAssertPointer(match, 2);
255: *match = PETSC_FALSE;
256: if (!obj) PetscFunctionReturn(PETSC_SUCCESS);
257: va_start(Argp, type_name);
258: while (type_name && type_name[0]) {
259: PetscBool found;
260: PetscCall(PetscObjectTypeCompare(obj, type_name, &found));
261: if (found) {
262: *match = PETSC_TRUE;
263: break;
264: }
265: type_name = va_arg(Argp, const char *);
266: }
267: va_end(Argp);
268: PetscFunctionReturn(PETSC_SUCCESS);
269: }
271: /*@C
272: PetscObjectBaseTypeCompareAny - Determines whether a PETSc object has the base type of any of a list of types.
274: Not Collective
276: Input Parameters:
277: + obj - a PETSc object, for example a `Vec`, `Mat` or `KSP`.
278: This must be cast with a (`PetscObject`), for example, `PetscObjectBaseTypeCompareAny`((`PetscObject`)mat,...);
279: - type_name - array of strings containing type names, pass the empty string "" to terminate the list
281: Output Parameter:
282: . match - `PETSC_TRUE` if the type of `obj` matches any in the list, else `PETSC_FALSE`
284: Level: intermediate
286: .seealso: `VecGetType()`, `KSPGetType()`, `PCGetType()`, `SNESGetType()`, `PetscObjectTypeCompare()`, `PetscObjectBaseTypeCompare()`, `PetscObjectTypeCompareAny()`
287: @*/
288: PetscErrorCode PetscObjectBaseTypeCompareAny(PetscObject obj, PetscBool *match, const char type_name[], ...)
289: {
290: va_list Argp;
292: PetscFunctionBegin;
293: PetscAssertPointer(match, 2);
294: *match = PETSC_FALSE;
295: va_start(Argp, type_name);
296: while (type_name && type_name[0]) {
297: PetscBool found;
298: PetscCall(PetscObjectBaseTypeCompare(obj, type_name, &found));
299: if (found) {
300: *match = PETSC_TRUE;
301: break;
302: }
303: type_name = va_arg(Argp, const char *);
304: }
305: va_end(Argp);
306: PetscFunctionReturn(PETSC_SUCCESS);
307: }
309: typedef struct {
310: PetscErrorCode (*func)(void);
311: } PetscFinalizeFunction;
313: typedef struct {
314: PetscErrorCode (*func)(void *);
315: void *ctx;
316: } PetscFinalizeFunctionWithCtx;
318: typedef enum {
319: PETSC_FINALIZE_EMPTY,
320: PETSC_FINALIZE_OBJECT,
321: PETSC_FINALIZE_FUNC,
322: PETSC_FINALIZE_FUNC_WITH_CTX
323: } PetscFinalizeType;
325: static const char *const PetscFinalizeTypes[] = {"PETSC_FINALIZE_EMPTY", "PETSC_FINALIZE_OBJECT", "PETSC_FINALIZE_FUNC", "PETSC_FINALIZE_FUNC_WITH_CTX", PETSC_NULLPTR};
327: typedef struct {
328: union ThunkUnion
329: {
330: PetscObject obj;
331: PetscFinalizeFunction fn;
332: PetscFinalizeFunctionWithCtx fnctx;
333: } thunk;
334: PetscFinalizeType type;
335: } PetscFinalizerContainer;
337: #define PETSC_MAX_REGISTERED_FINALIZERS 256
338: static int reg_count = 0;
339: static PetscFinalizerContainer regfin[PETSC_MAX_REGISTERED_FINALIZERS];
341: static PetscErrorCode PetscRunRegisteredFinalizers(void)
342: {
343: PetscFunctionBegin;
344: while (reg_count) {
345: PetscFinalizerContainer top = regfin[--reg_count];
347: regfin[reg_count].type = PETSC_FINALIZE_EMPTY;
348: PetscCall(PetscArrayzero(®fin[reg_count].thunk, 1));
349: switch (top.type) {
350: case PETSC_FINALIZE_OBJECT:
351: top.thunk.obj->persistent = PETSC_FALSE;
352: PetscCall(PetscObjectDestroy(&top.thunk.obj));
353: break;
354: case PETSC_FINALIZE_FUNC:
355: PetscCall((*top.thunk.fn.func)());
356: break;
357: case PETSC_FINALIZE_FUNC_WITH_CTX:
358: PetscCall((*top.thunk.fnctx.func)(top.thunk.fnctx.ctx));
359: break;
360: case PETSC_FINALIZE_EMPTY:
361: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Finalizer at position %d is empty, yet registration count %d != 0", reg_count, reg_count);
362: break;
363: }
364: }
365: PetscFunctionReturn(PETSC_SUCCESS);
366: }
368: static int PetscFinalizerContainerEqual(const PetscFinalizerContainer *a, const PetscFinalizerContainer *b)
369: {
370: if (a->type != b->type) return 0;
371: switch (a->type) {
372: case PETSC_FINALIZE_EMPTY:
373: break;
374: case PETSC_FINALIZE_OBJECT:
375: return a->thunk.obj == b->thunk.obj;
376: case PETSC_FINALIZE_FUNC:
377: return a->thunk.fn.func == b->thunk.fn.func;
378: case PETSC_FINALIZE_FUNC_WITH_CTX:
379: return a->thunk.fnctx.func == b->thunk.fnctx.func && a->thunk.fnctx.ctx == b->thunk.fnctx.ctx;
380: }
381: return 1;
382: }
384: static PetscErrorCode RegisterFinalizer(PetscFinalizerContainer container)
385: {
386: PetscFunctionBegin;
387: 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__);
388: 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);
389: if (PetscDefined(USE_DEBUG)) {
390: 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]);
391: }
392: regfin[reg_count++] = container;
393: PetscFunctionReturn(PETSC_SUCCESS);
394: }
396: /*@C
397: PetscObjectRegisterDestroy - Registers a PETSc object to be destroyed when
398: `PetscFinalize()` is called.
400: Logically Collective
402: Input Parameter:
403: . obj - a PETSc object, for example a `Vec`, `Mat` or `KSP`.
404: This must be cast with a (`PetscObject`), for example,
405: `PetscObjectRegisterDestroy`((`PetscObject`)mat);
407: Level: developer
409: Note:
410: This is used by, for example, `PETSC_VIEWER_XXX_()` routines to free the viewer
411: when PETSc ends.
413: .seealso: `PetscObjectRegisterDestroyAll()`
414: @*/
415: PetscErrorCode PetscObjectRegisterDestroy(PetscObject obj)
416: {
417: PetscFinalizerContainer container;
419: PetscFunctionBegin;
421: container.thunk.obj = obj;
422: container.type = PETSC_FINALIZE_OBJECT;
423: PetscCall(RegisterFinalizer(container));
424: PetscFunctionReturn(PETSC_SUCCESS);
425: }
427: /*@C
428: PetscObjectRegisterDestroyAll - Frees all the PETSc objects that have been registered
429: with `PetscObjectRegisterDestroy()`. Called by `PetscFinalize()`
431: Logically Collective on the individual `PetscObject`s that are being processed
433: Level: developer
435: .seealso: `PetscObjectRegisterDestroy()`
436: @*/
437: PetscErrorCode PetscObjectRegisterDestroyAll(void)
438: {
439: PetscFunctionBegin;
440: PetscCall(PetscRunRegisteredFinalizers());
441: PetscFunctionReturn(PETSC_SUCCESS);
442: }
444: /*@C
445: PetscRegisterFinalize - Registers a function that is to be called in `PetscFinalize()`
447: Not Collective
449: Input Parameter:
450: . f - function to be called
452: Level: developer
454: Notes:
455: This is used by, for example, `DMInitializePackage()` to have `DMFinalizePackage()` called
457: Use `PetscObjectRegisterDestroy()` to register the destruction of an object in `PetscFinalize()`
459: .seealso: `PetscRegisterFinalizeAll()`, `PetscObjectRegisterDestroy()`
460: @*/
461: PetscErrorCode PetscRegisterFinalize(PetscErrorCode (*f)(void))
462: {
463: PetscFinalizerContainer container;
465: PetscFunctionBegin;
467: container.thunk.fn.func = f;
468: container.type = PETSC_FINALIZE_FUNC;
469: PetscCall(RegisterFinalizer(container));
470: PetscFunctionReturn(PETSC_SUCCESS);
471: }
473: /*@C
474: PetscRegisterFinalizeAll - Runs all the finalize functions set with `PetscRegisterFinalize()`
476: Not Collective unless registered functions are collective
478: Level: developer
480: .seealso: `PetscRegisterFinalize()`, `PetscObjectRegisterDestroyAll()`
481: @*/
482: PetscErrorCode PetscRegisterFinalizeAll(void)
483: {
484: PetscFunctionBegin;
485: PetscCall(PetscRunRegisteredFinalizers());
486: PetscFunctionReturn(PETSC_SUCCESS);
487: }