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`. It must be cast with a (`PetscObject`\*), for example,
38: `PetscObjectDestroy`((`PetscObject`\*)&mat);
40: Level: beginner
42: .seealso: `PetscObject`
43: @*/
44: PetscErrorCode PetscObjectDestroy(PetscObject *obj)
45: {
46: PetscFunctionBegin;
47: if (!obj || !*obj) PetscFunctionReturn(PETSC_SUCCESS);
49: 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);
50: PetscCall((*(*obj)->bops->destroy)(obj));
51: PetscFunctionReturn(PETSC_SUCCESS);
52: }
54: /*@C
55: PetscObjectView - Views a `PetscObject` regardless of the type.
57: Collective
59: Input Parameters:
60: + obj - any PETSc object, for example a `Vec`, `Mat` or `KSP`. It must be cast with a (`PetscObject`), for example,
61: `PetscObjectView`((`PetscObject`)mat,`viewer`);
62: - viewer - any PETSc viewer
64: Level: intermediate
66: .seealso: `PetscObject`, `PetscObjectViewFromOptions()`, `PetscViewer`
67: @*/
68: PetscErrorCode PetscObjectView(PetscObject obj, PetscViewer viewer)
69: {
70: PetscFunctionBegin;
72: PetscCheck(obj->bops->view, PETSC_COMM_SELF, PETSC_ERR_SUP, "This PETSc object does not have a generic viewer routine");
73: if (!viewer) PetscCall(PetscViewerASCIIGetStdout(obj->comm, &viewer));
76: PetscCall((*obj->bops->view)(obj, viewer));
77: PetscFunctionReturn(PETSC_SUCCESS);
78: }
80: /*@C
81: PetscObjectViewFromOptions - Processes command line options to determine if/how a `PetscObject` is to be viewed.
83: Collective
85: Input Parameters:
86: + obj - the object
87: . bobj - optional other object that provides prefix (if `NULL` then the prefix in `obj` is used)
88: - optionname - option string that is used to activate viewing
90: Options Database Key:
91: . -optionname_view [viewertype]:... - option name and values. In actual usage this would be something like `-mat_coarse_view`
93: Level: developer
95: Notes:
96: .vb
97: If no value is provided ascii:stdout is used
98: ascii[:[filename][:[format][:append]]] defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab,
99: for example ascii::ascii_info prints just the information about the object not all details
100: unless :append is given filename opens in write mode, overwriting what was already there
101: binary[:[filename][:[format][:append]]] defaults to the file binaryoutput
102: draw[:drawtype[:filename]] for example, draw:tikz, draw:tikz:figure.tex or draw:x
103: socket[:port] defaults to the standard output port
104: saws[:communicatorname] publishes object to the Scientific Application Webserver (SAWs)
105: .ve
107: This is not called directly but is called by, for example, `MatViewFromOptions()`
109: .seealso: `PetscObject`, `PetscObjectView()`, `PetscOptionsGetViewer()`
110: @*/
111: PetscErrorCode PetscObjectViewFromOptions(PetscObject obj, PetscObject bobj, const char optionname[])
112: {
113: PetscViewer viewer;
114: PetscBool flg;
115: static PetscBool incall = PETSC_FALSE;
116: PetscViewerFormat format;
117: const char *prefix;
119: PetscFunctionBegin;
122: if (incall) PetscFunctionReturn(PETSC_SUCCESS);
123: incall = PETSC_TRUE;
124: prefix = bobj ? bobj->prefix : obj->prefix;
125: PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)obj), obj->options, prefix, optionname, &viewer, &format, &flg));
126: if (flg) {
127: PetscCall(PetscViewerPushFormat(viewer, format));
128: PetscCall(PetscObjectView(obj, viewer));
129: PetscCall(PetscViewerFlush(viewer));
130: PetscCall(PetscViewerPopFormat(viewer));
131: PetscCall(PetscOptionsRestoreViewer(&viewer));
132: }
133: incall = PETSC_FALSE;
134: PetscFunctionReturn(PETSC_SUCCESS);
135: }
137: /*@C
138: PetscObjectTypeCompare - Determines whether a PETSc object is of a particular type.
140: Not Collective
142: Input Parameters:
143: + obj - a PETSc object, for example a `Vec`, `Mat` or `KSP`. It must be cast with a (`PetscObject`), for example,
144: `PetscObjectTypeCompare`((`PetscObject`)mat);
145: - type_name - string containing a type name
147: Output Parameter:
148: . same - `PETSC_TRUE` if the type of `obj` and `type_name` are the same or both `NULL`, else `PETSC_FALSE`
150: Level: intermediate
152: .seealso: `PetscObject`, `VecGetType()`, `KSPGetType()`, `PCGetType()`, `SNESGetType()`, `PetscObjectBaseTypeCompare()`, `PetscObjectTypeCompareAny()`, `PetscObjectBaseTypeCompareAny()`, `PetscObjectObjectTypeCompare()`
153: @*/
154: PetscErrorCode PetscObjectTypeCompare(PetscObject obj, const char type_name[], PetscBool *same)
155: {
156: PetscFunctionBegin;
157: PetscAssertPointer(same, 3);
158: if (!obj) *same = (PetscBool)!type_name;
159: else {
161: if (!type_name || !obj->type_name) *same = (PetscBool)(!obj->type_name == !type_name);
162: else {
163: PetscAssertPointer(type_name, 2);
164: PetscCall(PetscStrcmp(obj->type_name, type_name, same));
165: }
166: }
167: PetscFunctionReturn(PETSC_SUCCESS);
168: }
170: /*@C
171: PetscObjectObjectTypeCompare - Determines whether two PETSc objects are of the same type
173: Logically Collective
175: Input Parameters:
176: + obj1 - any PETSc object, for example a `Vec`, `Mat` or `KSP`.
177: - obj2 - another PETSc object
179: Output Parameter:
180: . same - `PETSC_TRUE` if they are the same or both unset, else `PETSC_FALSE`
182: Level: intermediate
184: .seealso: `PetscObjectTypeCompare()`, `VecGetType()`, `KSPGetType()`, `PCGetType()`, `SNESGetType()`, `PetscObjectBaseTypeCompare()`, `PetscObjectTypeCompareAny()`, `PetscObjectBaseTypeCompareAny()`
186: @*/
187: PetscErrorCode PetscObjectObjectTypeCompare(PetscObject obj1, PetscObject obj2, PetscBool *same)
188: {
189: PetscFunctionBegin;
192: PetscAssertPointer(same, 3);
193: PetscCall(PetscStrcmp(obj1->type_name, obj2->type_name, same));
194: PetscFunctionReturn(PETSC_SUCCESS);
195: }
197: /*@C
198: PetscObjectBaseTypeCompare - Determines whether a `PetscObject` is of a given base type. For example the base type of `MATSEQAIJPERM` is `MATSEQAIJ`
200: Not Collective
202: Input Parameters:
203: + obj - the object
204: - type_name - string containing a type name
206: Output Parameter:
207: . same - `PETSC_TRUE` if the object is of the same base type identified by `type_name` or both `NULL`, `PETSC_FALSE` otherwise
209: Level: intermediate
211: .seealso: `PetscObject`, `PetscObjectTypeCompare()`, `PetscObjectTypeCompareAny()`, `PetscObjectBaseTypeCompareAny()`
212: @*/
213: PetscErrorCode PetscObjectBaseTypeCompare(PetscObject obj, const char type_name[], PetscBool *same)
214: {
215: PetscFunctionBegin;
216: PetscAssertPointer(same, 3);
217: if (!obj) *same = (PetscBool)!type_name;
218: else {
220: if (!type_name || !obj->type_name) *same = (PetscBool)(!obj->type_name == !type_name);
221: else {
222: PetscAssertPointer(type_name, 2);
223: PetscCall(PetscStrbeginswith(obj->type_name, type_name, same));
224: }
225: }
226: PetscFunctionReturn(PETSC_SUCCESS);
227: }
229: /*@C
230: PetscObjectTypeCompareAny - Determines whether a PETSc object is of any of a list of types.
232: Not Collective
234: Input Parameters:
235: + obj - a PETSc object, for example a `Vec`, `Mat` or `KSP`. It must be cast with a (`PetscObject`),
236: for example, `PetscObjectTypeCompareAny`((`PetscObject`)mat,...);
237: - type_name - one or more string arguments containing type names, pass the empty string "" as the last argument
239: Output Parameter:
240: . match - `PETSC_TRUE` if the type of `obj` matches any in the list, else `PETSC_FALSE`
242: Level: intermediate
244: .seealso: `VecGetType()`, `KSPGetType()`, `PCGetType()`, `SNESGetType()`, `PetscObjectTypeCompare()`, `PetscObjectBaseTypeCompare()`
245: @*/
246: PetscErrorCode PetscObjectTypeCompareAny(PetscObject obj, PetscBool *match, const char type_name[], ...)
247: {
248: va_list Argp;
250: PetscFunctionBegin;
251: PetscAssertPointer(match, 2);
252: *match = PETSC_FALSE;
253: if (!obj) PetscFunctionReturn(PETSC_SUCCESS);
254: va_start(Argp, type_name);
255: while (type_name && type_name[0]) {
256: PetscBool found;
257: PetscCall(PetscObjectTypeCompare(obj, type_name, &found));
258: if (found) {
259: *match = PETSC_TRUE;
260: break;
261: }
262: type_name = va_arg(Argp, const char *);
263: }
264: va_end(Argp);
265: PetscFunctionReturn(PETSC_SUCCESS);
266: }
268: /*@C
269: PetscObjectBaseTypeCompareAny - Determines whether a PETSc object has the base type of any of a list of types.
271: Not Collective
273: Input Parameters:
274: + obj - a PETSc object, for example a `Vec`, `Mat` or `KSP`. It must be cast with a (`PetscObject`),
275: for example, `PetscObjectBaseTypeCompareAny`((`PetscObject`)mat,...);
276: - type_name - one or more string arguments containing type names, pass the empty string "" as the last argument
278: Output Parameter:
279: . match - `PETSC_TRUE` if the type of `obj` matches any in the list, else `PETSC_FALSE`
281: Level: intermediate
283: .seealso: `VecGetType()`, `KSPGetType()`, `PCGetType()`, `SNESGetType()`, `PetscObjectTypeCompare()`, `PetscObjectBaseTypeCompare()`, `PetscObjectTypeCompareAny()`
284: @*/
285: PetscErrorCode PetscObjectBaseTypeCompareAny(PetscObject obj, PetscBool *match, const char type_name[], ...)
286: {
287: va_list Argp;
289: PetscFunctionBegin;
290: PetscAssertPointer(match, 2);
291: *match = PETSC_FALSE;
292: va_start(Argp, type_name);
293: while (type_name && type_name[0]) {
294: PetscBool found;
295: PetscCall(PetscObjectBaseTypeCompare(obj, type_name, &found));
296: if (found) {
297: *match = PETSC_TRUE;
298: break;
299: }
300: type_name = va_arg(Argp, const char *);
301: }
302: va_end(Argp);
303: PetscFunctionReturn(PETSC_SUCCESS);
304: }
306: typedef struct {
307: PetscErrorCode (*func)(void);
308: } PetscFinalizeFunction;
310: typedef struct {
311: PetscErrorCode (*func)(void *);
312: void *ctx;
313: } PetscFinalizeFunctionWithCtx;
315: typedef enum {
316: PETSC_FINALIZE_EMPTY,
317: PETSC_FINALIZE_OBJECT,
318: PETSC_FINALIZE_FUNC,
319: PETSC_FINALIZE_FUNC_WITH_CTX
320: } PetscFinalizeType;
322: static const char *const PetscFinalizeTypes[] = {"PETSC_FINALIZE_EMPTY", "PETSC_FINALIZE_OBJECT", "PETSC_FINALIZE_FUNC", "PETSC_FINALIZE_FUNC_WITH_CTX", PETSC_NULLPTR};
324: typedef struct {
325: union ThunkUnion
326: {
327: PetscObject obj;
328: PetscFinalizeFunction fn;
329: PetscFinalizeFunctionWithCtx fnctx;
330: } thunk;
331: PetscFinalizeType type;
332: } PetscFinalizerContainer;
334: #define PETSC_MAX_REGISTERED_FINALIZERS 256
335: static int reg_count = 0;
336: static PetscFinalizerContainer regfin[PETSC_MAX_REGISTERED_FINALIZERS];
338: static PetscErrorCode PetscRunRegisteredFinalizers(void)
339: {
340: PetscFunctionBegin;
341: while (reg_count) {
342: PetscFinalizerContainer top = regfin[--reg_count];
344: regfin[reg_count].type = PETSC_FINALIZE_EMPTY;
345: PetscCall(PetscArrayzero(®fin[reg_count].thunk, 1));
346: switch (top.type) {
347: case PETSC_FINALIZE_OBJECT:
348: top.thunk.obj->persistent = PETSC_FALSE;
349: PetscCall(PetscObjectDestroy(&top.thunk.obj));
350: break;
351: case PETSC_FINALIZE_FUNC:
352: PetscCall((*top.thunk.fn.func)());
353: break;
354: case PETSC_FINALIZE_FUNC_WITH_CTX:
355: PetscCall((*top.thunk.fnctx.func)(top.thunk.fnctx.ctx));
356: break;
357: case PETSC_FINALIZE_EMPTY:
358: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Finalizer at position %d is empty, yet registration count %d != 0", reg_count, reg_count);
359: break;
360: }
361: }
362: PetscFunctionReturn(PETSC_SUCCESS);
363: }
365: static int PetscFinalizerContainerEqual(const PetscFinalizerContainer *a, const PetscFinalizerContainer *b)
366: {
367: if (a->type != b->type) return 0;
368: switch (a->type) {
369: case PETSC_FINALIZE_EMPTY:
370: break;
371: case PETSC_FINALIZE_OBJECT:
372: return a->thunk.obj == b->thunk.obj;
373: case PETSC_FINALIZE_FUNC:
374: return a->thunk.fn.func == b->thunk.fn.func;
375: case PETSC_FINALIZE_FUNC_WITH_CTX:
376: return a->thunk.fnctx.func == b->thunk.fnctx.func && a->thunk.fnctx.ctx == b->thunk.fnctx.ctx;
377: }
378: return 1;
379: }
381: static PetscErrorCode RegisterFinalizer(PetscFinalizerContainer container)
382: {
383: PetscFunctionBegin;
384: 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__);
385: 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);
386: if (PetscDefined(USE_DEBUG)) {
387: 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]);
388: }
389: regfin[reg_count++] = container;
390: PetscFunctionReturn(PETSC_SUCCESS);
391: }
393: /*@C
394: PetscObjectRegisterDestroy - Registers a PETSc object to be destroyed when
395: `PetscFinalize()` is called.
397: Logically Collective
399: Input Parameter:
400: . obj - a PETSc object, for example a `Vec`, `Mat` or `KSP`. It must be cast with a (`PetscObject`), for example,
401: `PetscObjectRegisterDestroy`((`PetscObject`)mat);
403: Level: developer
405: Note:
406: This is used by, for example, `PETSC_VIEWER_XXX_()` routines to free the viewer
407: when PETSc ends.
409: .seealso: `PetscObjectRegisterDestroyAll()`
410: @*/
411: PetscErrorCode PetscObjectRegisterDestroy(PetscObject obj)
412: {
413: PetscFinalizerContainer container;
415: PetscFunctionBegin;
417: container.thunk.obj = obj;
418: container.type = PETSC_FINALIZE_OBJECT;
419: PetscCall(RegisterFinalizer(container));
420: PetscFunctionReturn(PETSC_SUCCESS);
421: }
423: /*@C
424: PetscObjectRegisterDestroyAll - Frees all the PETSc objects that have been registered
425: with `PetscObjectRegisterDestroy()`. Called by `PetscFinalize()`
427: Logically Collective on the individual `PetscObject`s that are being processed
429: Level: developer
431: .seealso: `PetscObjectRegisterDestroy()`
432: @*/
433: PetscErrorCode PetscObjectRegisterDestroyAll(void)
434: {
435: PetscFunctionBegin;
436: PetscCall(PetscRunRegisteredFinalizers());
437: PetscFunctionReturn(PETSC_SUCCESS);
438: }
440: /*@C
441: PetscRegisterFinalize - Registers a function that is to be called in `PetscFinalize()`
443: Not Collective
445: Input Parameter:
446: . f - function to be called
448: Level: developer
450: Notes:
451: This is used by, for example, `DMInitializePackage()` to have `DMFinalizePackage()` called
453: Use `PetscObjectRegisterDestroy()` to register the destruction of an object in `PetscFinalize()`
455: .seealso: `PetscRegisterFinalizeAll()`, `PetscObjectRegisterDestroy()`
456: @*/
457: PetscErrorCode PetscRegisterFinalize(PetscErrorCode (*f)(void))
458: {
459: PetscFinalizerContainer container;
461: PetscFunctionBegin;
463: container.thunk.fn.func = f;
464: container.type = PETSC_FINALIZE_FUNC;
465: PetscCall(RegisterFinalizer(container));
466: PetscFunctionReturn(PETSC_SUCCESS);
467: }
469: /*@C
470: PetscRegisterFinalizeAll - Runs all the finalize functions set with `PetscRegisterFinalize()`
472: Not Collective unless registered functions are collective
474: Level: developer
476: .seealso: `PetscRegisterFinalize()`, `PetscObjectRegisterDestroyAll()`
477: @*/
478: PetscErrorCode PetscRegisterFinalizeAll(void)
479: {
480: PetscFunctionBegin;
481: PetscCall(PetscRunRegisteredFinalizers());
482: PetscFunctionReturn(PETSC_SUCCESS);
483: }