xref: /petsc/src/sys/objects/destroy.c (revision 89efdf644546d6d1c77aecbca05cebb2e50c620f)
1e5c89e4eSSatish Balay /*
2e5c89e4eSSatish Balay      Provides utility routines for manulating any type of PETSc object.
3e5c89e4eSSatish Balay */
4af0996ceSBarry Smith #include <petsc/private/petscimpl.h> /*I   "petscsys.h"    I*/
5665c2dedSJed Brown #include <petscviewer.h>
6e5c89e4eSSatish Balay 
79cd7b5a2SJacob Faibussowitsch static PetscErrorCode DestroyComposedData(void ***composed_star, PetscObjectState **state_star, PetscInt *count_star, void **composed, PetscObjectState **state)
8d71ae5a4SJacob Faibussowitsch {
99cd7b5a2SJacob Faibussowitsch   void **tmp_star = *composed_star;
10d42688cbSBarry Smith 
11b436f76fSVictor Eijkhout   PetscFunctionBegin;
129cd7b5a2SJacob Faibussowitsch   for (PetscInt i = 0, imax = *count_star; i < imax; ++i) PetscCall(PetscFree(tmp_star[i]));
139cd7b5a2SJacob Faibussowitsch   PetscCall(PetscFree2(*composed_star, *state_star));
149cd7b5a2SJacob Faibussowitsch   PetscCall(PetscFree2(*composed, *state));
159cd7b5a2SJacob Faibussowitsch   *count_star = 0;
169cd7b5a2SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
179cd7b5a2SJacob Faibussowitsch }
189cd7b5a2SJacob Faibussowitsch 
199cd7b5a2SJacob Faibussowitsch PetscErrorCode PetscComposedQuantitiesDestroy(PetscObject obj)
209cd7b5a2SJacob Faibussowitsch {
219cd7b5a2SJacob Faibussowitsch   PetscFunctionBegin;
22b843b480SStefano Zampini   PetscValidHeader(obj, 1);
239cd7b5a2SJacob Faibussowitsch   PetscCall(DestroyComposedData((void ***)&obj->intstarcomposeddata, &obj->intstarcomposedstate, &obj->intstar_idmax, (void **)&obj->intcomposeddata, &obj->intcomposedstate));
249cd7b5a2SJacob Faibussowitsch   PetscCall(DestroyComposedData((void ***)&obj->realstarcomposeddata, &obj->realstarcomposedstate, &obj->realstar_idmax, (void **)&obj->realcomposeddata, &obj->realcomposedstate));
259cd7b5a2SJacob Faibussowitsch #if PetscDefined(USE_COMPLEX)
269cd7b5a2SJacob Faibussowitsch   PetscCall(DestroyComposedData((void ***)&obj->scalarstarcomposeddata, &obj->scalarstarcomposedstate, &obj->scalarstar_idmax, (void **)&obj->scalarcomposeddata, &obj->scalarcomposedstate));
279cd7b5a2SJacob Faibussowitsch #endif
283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
29b436f76fSVictor Eijkhout }
30b436f76fSVictor Eijkhout 
31e30d2299SSatish Balay /*@
328ea61f2eSBarry Smith   PetscObjectDestroy - Destroys a `PetscObject`, regardless of the type.
33e5c89e4eSSatish Balay 
34c3339decSBarry Smith   Collective
35e5c89e4eSSatish Balay 
36e5c89e4eSSatish Balay   Input Parameter:
37dde44402SBarry Smith . obj - any PETSc object, for example a `Vec`, `Mat` or `KSP`. It must be cast with a (`PetscObject`\*), for example,
38dde44402SBarry Smith         `PetscObjectDestroy`((`PetscObject`\*)&mat);
39e5c89e4eSSatish Balay 
40e5c89e4eSSatish Balay   Level: beginner
41e5c89e4eSSatish Balay 
42811af0c4SBarry Smith .seealso: `PetscObject`
43e5c89e4eSSatish Balay @*/
44d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscObjectDestroy(PetscObject *obj)
45d71ae5a4SJacob Faibussowitsch {
46e5c89e4eSSatish Balay   PetscFunctionBegin;
473ba16761SJacob Faibussowitsch   if (!obj || !*obj) PetscFunctionReturn(PETSC_SUCCESS);
486bf464f9SBarry Smith   PetscValidHeader(*obj, 1);
495f80ce2aSJacob Faibussowitsch   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);
509566063dSJacob Faibussowitsch   PetscCall((*(*obj)->bops->destroy)(obj));
513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
52e5c89e4eSSatish Balay }
53e5c89e4eSSatish Balay 
54e5c89e4eSSatish Balay /*@C
55dde44402SBarry Smith   PetscObjectView - Views a `PetscObject` regardless of the type.
56e5c89e4eSSatish Balay 
57c3339decSBarry Smith   Collective
58e5c89e4eSSatish Balay 
59e5c89e4eSSatish Balay   Input Parameters:
60dde44402SBarry Smith + obj    - any PETSc object, for example a `Vec`, `Mat` or `KSP`. It must be cast with a (`PetscObject`), for example,
61dde44402SBarry Smith            `PetscObjectView`((`PetscObject`)mat,`viewer`);
62e5c89e4eSSatish Balay - viewer - any PETSc viewer
63e5c89e4eSSatish Balay 
64e5c89e4eSSatish Balay   Level: intermediate
65e5c89e4eSSatish Balay 
668ea61f2eSBarry Smith .seealso: `PetscObject`, `PetscObjectViewFromOptions()`, `PetscViewer`
67e5c89e4eSSatish Balay @*/
68d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscObjectView(PetscObject obj, PetscViewer viewer)
69d71ae5a4SJacob Faibussowitsch {
70e5c89e4eSSatish Balay   PetscFunctionBegin;
71e5c89e4eSSatish Balay   PetscValidHeader(obj, 1);
725f80ce2aSJacob Faibussowitsch   PetscCheck(obj->bops->view, PETSC_COMM_SELF, PETSC_ERR_SUP, "This PETSc object does not have a generic viewer routine");
739566063dSJacob Faibussowitsch   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(obj->comm, &viewer));
740700a824SBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
75e5c89e4eSSatish Balay 
769566063dSJacob Faibussowitsch   PetscCall((*obj->bops->view)(obj, viewer));
773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
78e5c89e4eSSatish Balay }
79e5c89e4eSSatish Balay 
802d747510SLisandro Dalcin /*@C
81811af0c4SBarry Smith   PetscObjectViewFromOptions - Processes command line options to determine if/how a `PetscObject` is to be viewed.
822d747510SLisandro Dalcin 
83c3339decSBarry Smith   Collective
842d747510SLisandro Dalcin 
852d747510SLisandro Dalcin   Input Parameters:
862d747510SLisandro Dalcin + obj        - the object
8721532e8aSBarry Smith . bobj       - optional other object that provides prefix (if `NULL` then the prefix in `obj` is used)
88bb7acecfSBarry Smith - optionname - option string that is used to activate viewing
892d747510SLisandro Dalcin 
9011a5261eSBarry Smith   Options Database Key:
9121532e8aSBarry Smith . -optionname_view [viewertype]:... - option name and values. In actual usage this would be something like `-mat_coarse_view`
9221532e8aSBarry Smith 
9321532e8aSBarry Smith   Level: developer
942d747510SLisandro Dalcin 
9511a5261eSBarry Smith   Notes:
96*89efdf64SMatthew G. Knepley   The argument has the following form
97*89efdf64SMatthew G. Knepley .vb
98*89efdf64SMatthew G. Knepley     type:filename:format:filemode
99*89efdf64SMatthew G. Knepley .ve
100*89efdf64SMatthew G. Knepley   where all parts are optional, but you need to include the colon to access the next part. For example, to read from an HDF5 file, use
101*89efdf64SMatthew G. Knepley .vb
102*89efdf64SMatthew G. Knepley     hdf5:sol.h5::read
103*89efdf64SMatthew G. Knepley .ve
104*89efdf64SMatthew G. Knepley 
10511a5261eSBarry Smith .vb
10611a5261eSBarry Smith     If no value is provided ascii:stdout is used
10711a5261eSBarry Smith        ascii[:[filename][:[format][:append]]]    defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab,
10811a5261eSBarry Smith                                                   for example ascii::ascii_info prints just the information about the object not all details
10911a5261eSBarry Smith                                                   unless :append is given filename opens in write mode, overwriting what was already there
11011a5261eSBarry Smith        binary[:[filename][:[format][:append]]]   defaults to the file binaryoutput
11111a5261eSBarry Smith        draw[:drawtype[:filename]]                for example, draw:tikz, draw:tikz:figure.tex  or draw:x
11211a5261eSBarry Smith        socket[:port]                             defaults to the standard output port
11311a5261eSBarry Smith        saws[:communicatorname]                    publishes object to the Scientific Application Webserver (SAWs)
11411a5261eSBarry Smith .ve
11511a5261eSBarry Smith 
11621532e8aSBarry Smith   This is not called directly but is called by, for example, `MatViewFromOptions()`
11711a5261eSBarry Smith 
11811a5261eSBarry Smith .seealso: `PetscObject`, `PetscObjectView()`, `PetscOptionsGetViewer()`
1192d747510SLisandro Dalcin @*/
120d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscObjectViewFromOptions(PetscObject obj, PetscObject bobj, const char optionname[])
121d71ae5a4SJacob Faibussowitsch {
1222d747510SLisandro Dalcin   PetscViewer       viewer;
1232d747510SLisandro Dalcin   PetscBool         flg;
1242d747510SLisandro Dalcin   static PetscBool  incall = PETSC_FALSE;
1252d747510SLisandro Dalcin   PetscViewerFormat format;
1262d747510SLisandro Dalcin   const char       *prefix;
1272d747510SLisandro Dalcin 
1282d747510SLisandro Dalcin   PetscFunctionBegin;
129b843b480SStefano Zampini   PetscValidHeader(obj, 1);
130b843b480SStefano Zampini   if (bobj) PetscValidHeader(bobj, 2);
1313ba16761SJacob Faibussowitsch   if (incall) PetscFunctionReturn(PETSC_SUCCESS);
1322d747510SLisandro Dalcin   incall = PETSC_TRUE;
1332d747510SLisandro Dalcin   prefix = bobj ? bobj->prefix : obj->prefix;
1349566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)obj), obj->options, prefix, optionname, &viewer, &format, &flg));
1352d747510SLisandro Dalcin   if (flg) {
1369566063dSJacob Faibussowitsch     PetscCall(PetscViewerPushFormat(viewer, format));
1379566063dSJacob Faibussowitsch     PetscCall(PetscObjectView(obj, viewer));
1389566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
1399566063dSJacob Faibussowitsch     PetscCall(PetscViewerPopFormat(viewer));
140cd791dc2SBarry Smith     PetscCall(PetscOptionsRestoreViewer(&viewer));
1412d747510SLisandro Dalcin   }
1422d747510SLisandro Dalcin   incall = PETSC_FALSE;
1433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1442d747510SLisandro Dalcin }
1452d747510SLisandro Dalcin 
146e5c89e4eSSatish Balay /*@C
147251f4c67SDmitry Karpeev   PetscObjectTypeCompare - Determines whether a PETSc object is of a particular type.
148e5c89e4eSSatish Balay 
149e5c89e4eSSatish Balay   Not Collective
150e5c89e4eSSatish Balay 
151e5c89e4eSSatish Balay   Input Parameters:
152dde44402SBarry Smith + obj       - a PETSc object, for example a `Vec`, `Mat` or `KSP`. It must be cast with a (`PetscObject`), for example,
153811af0c4SBarry Smith               `PetscObjectTypeCompare`((`PetscObject`)mat);
154e5c89e4eSSatish Balay - type_name - string containing a type name
155e5c89e4eSSatish Balay 
156e5c89e4eSSatish Balay   Output Parameter:
157b843b480SStefano Zampini . same - `PETSC_TRUE` if the type of `obj` and `type_name` are the same or both `NULL`, else `PETSC_FALSE`
158e5c89e4eSSatish Balay 
159e5c89e4eSSatish Balay   Level: intermediate
160e5c89e4eSSatish Balay 
161013e2dc7SBarry Smith .seealso: `PetscObject`, `VecGetType()`, `KSPGetType()`, `PCGetType()`, `SNESGetType()`, `PetscObjectBaseTypeCompare()`, `PetscObjectTypeCompareAny()`, `PetscObjectBaseTypeCompareAny()`, `PetscObjectObjectTypeCompare()`
162e5c89e4eSSatish Balay @*/
163d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscObjectTypeCompare(PetscObject obj, const char type_name[], PetscBool *same)
164d71ae5a4SJacob Faibussowitsch {
165e5c89e4eSSatish Balay   PetscFunctionBegin;
1664f572ea9SToby Isaac   PetscAssertPointer(same, 3);
167b843b480SStefano Zampini   if (!obj) *same = (PetscBool)!type_name;
168a297a907SKarl Rupp   else {
169e5c89e4eSSatish Balay     PetscValidHeader(obj, 1);
170b843b480SStefano Zampini     if (!type_name || !obj->type_name) *same = (PetscBool)(!obj->type_name == !type_name);
171b843b480SStefano Zampini     else {
1724f572ea9SToby Isaac       PetscAssertPointer(type_name, 2);
173b843b480SStefano Zampini       PetscCall(PetscStrcmp(obj->type_name, type_name, same));
174b843b480SStefano Zampini     }
175e5c89e4eSSatish Balay   }
1763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
177e5c89e4eSSatish Balay }
178e5c89e4eSSatish Balay 
1792b12f010SJed Brown /*@C
180013e2dc7SBarry Smith   PetscObjectObjectTypeCompare - Determines whether two PETSc objects are of the same type
181013e2dc7SBarry Smith 
182013e2dc7SBarry Smith   Logically Collective
183013e2dc7SBarry Smith 
184013e2dc7SBarry Smith   Input Parameters:
18521532e8aSBarry Smith + obj1 - any PETSc object, for example a `Vec`, `Mat` or `KSP`.
186da81f932SPierre Jolivet - obj2 - another PETSc object
187013e2dc7SBarry Smith 
188013e2dc7SBarry Smith   Output Parameter:
189b843b480SStefano Zampini . same - `PETSC_TRUE` if they are the same or both unset, else `PETSC_FALSE`
190013e2dc7SBarry Smith 
191013e2dc7SBarry Smith   Level: intermediate
192013e2dc7SBarry Smith 
193013e2dc7SBarry Smith .seealso: `PetscObjectTypeCompare()`, `VecGetType()`, `KSPGetType()`, `PCGetType()`, `SNESGetType()`, `PetscObjectBaseTypeCompare()`, `PetscObjectTypeCompareAny()`, `PetscObjectBaseTypeCompareAny()`
194013e2dc7SBarry Smith 
195013e2dc7SBarry Smith @*/
196d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscObjectObjectTypeCompare(PetscObject obj1, PetscObject obj2, PetscBool *same)
197d71ae5a4SJacob Faibussowitsch {
198013e2dc7SBarry Smith   PetscFunctionBegin;
199013e2dc7SBarry Smith   PetscValidHeader(obj1, 1);
200013e2dc7SBarry Smith   PetscValidHeader(obj2, 2);
2014f572ea9SToby Isaac   PetscAssertPointer(same, 3);
202b843b480SStefano Zampini   PetscCall(PetscStrcmp(obj1->type_name, obj2->type_name, same));
2033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
204013e2dc7SBarry Smith }
205013e2dc7SBarry Smith 
206013e2dc7SBarry Smith /*@C
207811af0c4SBarry Smith   PetscObjectBaseTypeCompare - Determines whether a `PetscObject` is of a given base type. For example the base type of `MATSEQAIJPERM` is `MATSEQAIJ`
2084099cc6bSBarry Smith 
2094099cc6bSBarry Smith   Not Collective
2104099cc6bSBarry Smith 
2114099cc6bSBarry Smith   Input Parameters:
212dde44402SBarry Smith + obj       - the object
2134099cc6bSBarry Smith - type_name - string containing a type name
2144099cc6bSBarry Smith 
2154099cc6bSBarry Smith   Output Parameter:
216b843b480SStefano Zampini . same - `PETSC_TRUE` if the object is of the same base type identified by `type_name` or both `NULL`, `PETSC_FALSE` otherwise
2174099cc6bSBarry Smith 
2184099cc6bSBarry Smith   Level: intermediate
2194099cc6bSBarry Smith 
220811af0c4SBarry Smith .seealso: `PetscObject`, `PetscObjectTypeCompare()`, `PetscObjectTypeCompareAny()`, `PetscObjectBaseTypeCompareAny()`
2214099cc6bSBarry Smith @*/
222d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscObjectBaseTypeCompare(PetscObject obj, const char type_name[], PetscBool *same)
223d71ae5a4SJacob Faibussowitsch {
2244099cc6bSBarry Smith   PetscFunctionBegin;
2254f572ea9SToby Isaac   PetscAssertPointer(same, 3);
226b843b480SStefano Zampini   if (!obj) *same = (PetscBool)!type_name;
2274099cc6bSBarry Smith   else {
2284099cc6bSBarry Smith     PetscValidHeader(obj, 1);
229b843b480SStefano Zampini     if (!type_name || !obj->type_name) *same = (PetscBool)(!obj->type_name == !type_name);
230b843b480SStefano Zampini     else {
2314f572ea9SToby Isaac       PetscAssertPointer(type_name, 2);
232b843b480SStefano Zampini       PetscCall(PetscStrbeginswith(obj->type_name, type_name, same));
233b843b480SStefano Zampini     }
2344099cc6bSBarry Smith   }
2353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2364099cc6bSBarry Smith }
2374099cc6bSBarry Smith 
2384099cc6bSBarry Smith /*@C
239251f4c67SDmitry Karpeev   PetscObjectTypeCompareAny - Determines whether a PETSc object is of any of a list of types.
2402b12f010SJed Brown 
2412b12f010SJed Brown   Not Collective
2422b12f010SJed Brown 
2432b12f010SJed Brown   Input Parameters:
244dde44402SBarry Smith + obj       - a PETSc object, for example a `Vec`, `Mat` or `KSP`. It must be cast with a (`PetscObject`),
245dde44402SBarry Smith               for example, `PetscObjectTypeCompareAny`((`PetscObject`)mat,...);
246dde44402SBarry Smith - type_name - one or more string arguments containing type names, pass the empty string "" as the last argument
2472b12f010SJed Brown 
2482b12f010SJed Brown   Output Parameter:
24921532e8aSBarry Smith . match - `PETSC_TRUE` if the type of `obj` matches any in the list, else `PETSC_FALSE`
2502b12f010SJed Brown 
2512b12f010SJed Brown   Level: intermediate
2522b12f010SJed Brown 
253dee2f2dbSPierre Jolivet .seealso: `VecGetType()`, `KSPGetType()`, `PCGetType()`, `SNESGetType()`, `PetscObjectTypeCompare()`, `PetscObjectBaseTypeCompare()`
2542b12f010SJed Brown @*/
255d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscObjectTypeCompareAny(PetscObject obj, PetscBool *match, const char type_name[], ...)
256d71ae5a4SJacob Faibussowitsch {
2572b12f010SJed Brown   va_list Argp;
2582b12f010SJed Brown 
2592b12f010SJed Brown   PetscFunctionBegin;
2604f572ea9SToby Isaac   PetscAssertPointer(match, 2);
2612b12f010SJed Brown   *match = PETSC_FALSE;
2623ba16761SJacob Faibussowitsch   if (!obj) PetscFunctionReturn(PETSC_SUCCESS);
2632b12f010SJed Brown   va_start(Argp, type_name);
2642b12f010SJed Brown   while (type_name && type_name[0]) {
2652b12f010SJed Brown     PetscBool found;
2669566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare(obj, type_name, &found));
2672b12f010SJed Brown     if (found) {
2682b12f010SJed Brown       *match = PETSC_TRUE;
2692b12f010SJed Brown       break;
2702b12f010SJed Brown     }
2712b12f010SJed Brown     type_name = va_arg(Argp, const char *);
2722b12f010SJed Brown   }
2732b12f010SJed Brown   va_end(Argp);
2743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2752b12f010SJed Brown }
2762b12f010SJed Brown 
277b9e7e5c1SBarry Smith /*@C
278b9e7e5c1SBarry Smith   PetscObjectBaseTypeCompareAny - Determines whether a PETSc object has the base type of any of a list of types.
279b9e7e5c1SBarry Smith 
280b9e7e5c1SBarry Smith   Not Collective
281b9e7e5c1SBarry Smith 
282b9e7e5c1SBarry Smith   Input Parameters:
283dde44402SBarry Smith + obj       - a PETSc object, for example a `Vec`, `Mat` or `KSP`. It must be cast with a (`PetscObject`),
284dde44402SBarry Smith               for example, `PetscObjectBaseTypeCompareAny`((`PetscObject`)mat,...);
285dde44402SBarry Smith - type_name - one or more string arguments containing type names, pass the empty string "" as the last argument
286b9e7e5c1SBarry Smith 
287b9e7e5c1SBarry Smith   Output Parameter:
28821532e8aSBarry Smith . match - `PETSC_TRUE` if the type of `obj` matches any in the list, else `PETSC_FALSE`
289b9e7e5c1SBarry Smith 
290b9e7e5c1SBarry Smith   Level: intermediate
291b9e7e5c1SBarry Smith 
292db781477SPatrick Sanan .seealso: `VecGetType()`, `KSPGetType()`, `PCGetType()`, `SNESGetType()`, `PetscObjectTypeCompare()`, `PetscObjectBaseTypeCompare()`, `PetscObjectTypeCompareAny()`
293b9e7e5c1SBarry Smith @*/
294d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscObjectBaseTypeCompareAny(PetscObject obj, PetscBool *match, const char type_name[], ...)
295d71ae5a4SJacob Faibussowitsch {
296b9e7e5c1SBarry Smith   va_list Argp;
297b9e7e5c1SBarry Smith 
298b9e7e5c1SBarry Smith   PetscFunctionBegin;
2994f572ea9SToby Isaac   PetscAssertPointer(match, 2);
300b9e7e5c1SBarry Smith   *match = PETSC_FALSE;
301b9e7e5c1SBarry Smith   va_start(Argp, type_name);
302b9e7e5c1SBarry Smith   while (type_name && type_name[0]) {
303b9e7e5c1SBarry Smith     PetscBool found;
3049566063dSJacob Faibussowitsch     PetscCall(PetscObjectBaseTypeCompare(obj, type_name, &found));
305b9e7e5c1SBarry Smith     if (found) {
306b9e7e5c1SBarry Smith       *match = PETSC_TRUE;
307b9e7e5c1SBarry Smith       break;
308b9e7e5c1SBarry Smith     }
309b9e7e5c1SBarry Smith     type_name = va_arg(Argp, const char *);
310b9e7e5c1SBarry Smith   }
311b9e7e5c1SBarry Smith   va_end(Argp);
3123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
313b9e7e5c1SBarry Smith }
314b9e7e5c1SBarry Smith 
3153048253cSJacob Faibussowitsch typedef struct {
3163048253cSJacob Faibussowitsch   PetscErrorCode (*func)(void);
3173048253cSJacob Faibussowitsch } PetscFinalizeFunction;
3183048253cSJacob Faibussowitsch 
3193048253cSJacob Faibussowitsch typedef struct {
3203048253cSJacob Faibussowitsch   PetscErrorCode (*func)(void *);
3213048253cSJacob Faibussowitsch   void *ctx;
3223048253cSJacob Faibussowitsch } PetscFinalizeFunctionWithCtx;
3233048253cSJacob Faibussowitsch 
3243048253cSJacob Faibussowitsch typedef enum {
3253048253cSJacob Faibussowitsch   PETSC_FINALIZE_EMPTY,
3263048253cSJacob Faibussowitsch   PETSC_FINALIZE_OBJECT,
3273048253cSJacob Faibussowitsch   PETSC_FINALIZE_FUNC,
3283048253cSJacob Faibussowitsch   PETSC_FINALIZE_FUNC_WITH_CTX
3293048253cSJacob Faibussowitsch } PetscFinalizeType;
3303048253cSJacob Faibussowitsch 
3313048253cSJacob Faibussowitsch static const char *const PetscFinalizeTypes[] = {"PETSC_FINALIZE_EMPTY", "PETSC_FINALIZE_OBJECT", "PETSC_FINALIZE_FUNC", "PETSC_FINALIZE_FUNC_WITH_CTX", PETSC_NULLPTR};
3323048253cSJacob Faibussowitsch 
3333048253cSJacob Faibussowitsch typedef struct {
3343048253cSJacob Faibussowitsch   union ThunkUnion
3353048253cSJacob Faibussowitsch   {
3363048253cSJacob Faibussowitsch     PetscObject                  obj;
3373048253cSJacob Faibussowitsch     PetscFinalizeFunction        fn;
3383048253cSJacob Faibussowitsch     PetscFinalizeFunctionWithCtx fnctx;
3393048253cSJacob Faibussowitsch   } thunk;
3403048253cSJacob Faibussowitsch   PetscFinalizeType type;
3413048253cSJacob Faibussowitsch } PetscFinalizerContainer;
3423048253cSJacob Faibussowitsch 
3433048253cSJacob Faibussowitsch #define PETSC_MAX_REGISTERED_FINALIZERS 256
3443048253cSJacob Faibussowitsch static int                     reg_count = 0;
3453048253cSJacob Faibussowitsch static PetscFinalizerContainer regfin[PETSC_MAX_REGISTERED_FINALIZERS];
3463048253cSJacob Faibussowitsch 
34766976f2fSJacob Faibussowitsch static PetscErrorCode PetscRunRegisteredFinalizers(void)
3483048253cSJacob Faibussowitsch {
3493048253cSJacob Faibussowitsch   PetscFunctionBegin;
3503048253cSJacob Faibussowitsch   while (reg_count) {
3513048253cSJacob Faibussowitsch     PetscFinalizerContainer top = regfin[--reg_count];
3523048253cSJacob Faibussowitsch 
3533048253cSJacob Faibussowitsch     regfin[reg_count].type = PETSC_FINALIZE_EMPTY;
3543048253cSJacob Faibussowitsch     PetscCall(PetscArrayzero(&regfin[reg_count].thunk, 1));
3553048253cSJacob Faibussowitsch     switch (top.type) {
3563048253cSJacob Faibussowitsch     case PETSC_FINALIZE_OBJECT:
35734fa283eSBarry Smith       top.thunk.obj->persistent = PETSC_FALSE;
3583048253cSJacob Faibussowitsch       PetscCall(PetscObjectDestroy(&top.thunk.obj));
3593048253cSJacob Faibussowitsch       break;
3603048253cSJacob Faibussowitsch     case PETSC_FINALIZE_FUNC:
3613048253cSJacob Faibussowitsch       PetscCall((*top.thunk.fn.func)());
3623048253cSJacob Faibussowitsch       break;
3633048253cSJacob Faibussowitsch     case PETSC_FINALIZE_FUNC_WITH_CTX:
3643048253cSJacob Faibussowitsch       PetscCall((*top.thunk.fnctx.func)(top.thunk.fnctx.ctx));
3653048253cSJacob Faibussowitsch       break;
3663048253cSJacob Faibussowitsch     case PETSC_FINALIZE_EMPTY:
3673048253cSJacob Faibussowitsch       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Finalizer at position %d is empty, yet registration count %d != 0", reg_count, reg_count);
3683048253cSJacob Faibussowitsch       break;
3693048253cSJacob Faibussowitsch     }
3703048253cSJacob Faibussowitsch   }
3713048253cSJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3723048253cSJacob Faibussowitsch }
3733048253cSJacob Faibussowitsch 
3743048253cSJacob Faibussowitsch static int PetscFinalizerContainerEqual(const PetscFinalizerContainer *a, const PetscFinalizerContainer *b)
3753048253cSJacob Faibussowitsch {
3763048253cSJacob Faibussowitsch   if (a->type != b->type) return 0;
3773048253cSJacob Faibussowitsch   switch (a->type) {
3783048253cSJacob Faibussowitsch   case PETSC_FINALIZE_EMPTY:
3793048253cSJacob Faibussowitsch     break;
3803048253cSJacob Faibussowitsch   case PETSC_FINALIZE_OBJECT:
3813048253cSJacob Faibussowitsch     return a->thunk.obj == b->thunk.obj;
3823048253cSJacob Faibussowitsch   case PETSC_FINALIZE_FUNC:
3833048253cSJacob Faibussowitsch     return a->thunk.fn.func == b->thunk.fn.func;
3843048253cSJacob Faibussowitsch   case PETSC_FINALIZE_FUNC_WITH_CTX:
3853048253cSJacob Faibussowitsch     return a->thunk.fnctx.func == b->thunk.fnctx.func && a->thunk.fnctx.ctx == b->thunk.fnctx.ctx;
3863048253cSJacob Faibussowitsch   }
3873048253cSJacob Faibussowitsch   return 1;
3883048253cSJacob Faibussowitsch }
3893048253cSJacob Faibussowitsch 
3903048253cSJacob Faibussowitsch static PetscErrorCode RegisterFinalizer(PetscFinalizerContainer container)
3913048253cSJacob Faibussowitsch {
3923048253cSJacob Faibussowitsch   PetscFunctionBegin;
3933048253cSJacob Faibussowitsch   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__);
3943048253cSJacob Faibussowitsch   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);
3953048253cSJacob Faibussowitsch   if (PetscDefined(USE_DEBUG)) {
3963048253cSJacob Faibussowitsch     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]);
3973048253cSJacob Faibussowitsch   }
3983048253cSJacob Faibussowitsch   regfin[reg_count++] = container;
3993048253cSJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4003048253cSJacob Faibussowitsch }
401e5c89e4eSSatish Balay 
402e5c89e4eSSatish Balay /*@C
403e5c89e4eSSatish Balay   PetscObjectRegisterDestroy - Registers a PETSc object to be destroyed when
404811af0c4SBarry Smith   `PetscFinalize()` is called.
405e5c89e4eSSatish Balay 
406c3339decSBarry Smith   Logically Collective
407e5c89e4eSSatish Balay 
408e5c89e4eSSatish Balay   Input Parameter:
409dde44402SBarry Smith . obj - a PETSc object, for example a `Vec`, `Mat` or `KSP`. It must be cast with a (`PetscObject`), for example,
410811af0c4SBarry Smith         `PetscObjectRegisterDestroy`((`PetscObject`)mat);
411e5c89e4eSSatish Balay 
412e5c89e4eSSatish Balay   Level: developer
413e5c89e4eSSatish Balay 
414811af0c4SBarry Smith   Note:
41521532e8aSBarry Smith   This is used by, for example, `PETSC_VIEWER_XXX_()` routines to free the viewer
416e5c89e4eSSatish Balay   when PETSc ends.
417e5c89e4eSSatish Balay 
418db781477SPatrick Sanan .seealso: `PetscObjectRegisterDestroyAll()`
419e5c89e4eSSatish Balay @*/
420d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscObjectRegisterDestroy(PetscObject obj)
421d71ae5a4SJacob Faibussowitsch {
4223048253cSJacob Faibussowitsch   PetscFinalizerContainer container;
4233048253cSJacob Faibussowitsch 
424e5c89e4eSSatish Balay   PetscFunctionBegin;
425e5c89e4eSSatish Balay   PetscValidHeader(obj, 1);
4263048253cSJacob Faibussowitsch   container.thunk.obj = obj;
4273048253cSJacob Faibussowitsch   container.type      = PETSC_FINALIZE_OBJECT;
4283048253cSJacob Faibussowitsch   PetscCall(RegisterFinalizer(container));
4293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
430e5c89e4eSSatish Balay }
431e5c89e4eSSatish Balay 
432e5c89e4eSSatish Balay /*@C
433e5c89e4eSSatish Balay   PetscObjectRegisterDestroyAll - Frees all the PETSc objects that have been registered
434811af0c4SBarry Smith   with `PetscObjectRegisterDestroy()`. Called by `PetscFinalize()`
435e5c89e4eSSatish Balay 
436811af0c4SBarry Smith   Logically Collective on the individual `PetscObject`s that are being processed
437e5c89e4eSSatish Balay 
438e5c89e4eSSatish Balay   Level: developer
439e5c89e4eSSatish Balay 
440db781477SPatrick Sanan .seealso: `PetscObjectRegisterDestroy()`
441e5c89e4eSSatish Balay @*/
442d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscObjectRegisterDestroyAll(void)
443d71ae5a4SJacob Faibussowitsch {
444e5c89e4eSSatish Balay   PetscFunctionBegin;
4453048253cSJacob Faibussowitsch   PetscCall(PetscRunRegisteredFinalizers());
4463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
447e5c89e4eSSatish Balay }
448e5c89e4eSSatish Balay 
449eb8be38cSBarry Smith /*@C
450811af0c4SBarry Smith   PetscRegisterFinalize - Registers a function that is to be called in `PetscFinalize()`
451eb8be38cSBarry Smith 
452eb8be38cSBarry Smith   Not Collective
453eb8be38cSBarry Smith 
454eb8be38cSBarry Smith   Input Parameter:
455aec76313SJacob Faibussowitsch . f - function to be called
456eb8be38cSBarry Smith 
457eb8be38cSBarry Smith   Level: developer
458eb8be38cSBarry Smith 
45921532e8aSBarry Smith   Notes:
460811af0c4SBarry Smith   This is used by, for example, `DMInitializePackage()` to have `DMFinalizePackage()` called
461eb8be38cSBarry Smith 
46221532e8aSBarry Smith   Use `PetscObjectRegisterDestroy()` to register the destruction of an object in `PetscFinalize()`
46321532e8aSBarry Smith 
46421532e8aSBarry Smith .seealso: `PetscRegisterFinalizeAll()`, `PetscObjectRegisterDestroy()`
465eb8be38cSBarry Smith @*/
466d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscRegisterFinalize(PetscErrorCode (*f)(void))
467d71ae5a4SJacob Faibussowitsch {
4683048253cSJacob Faibussowitsch   PetscFinalizerContainer container;
4693048253cSJacob Faibussowitsch 
470f4aac215SBarry Smith   PetscFunctionBegin;
4713048253cSJacob Faibussowitsch   PetscValidFunction(f, 1);
4723048253cSJacob Faibussowitsch   container.thunk.fn.func = f;
4733048253cSJacob Faibussowitsch   container.type          = PETSC_FINALIZE_FUNC;
4743048253cSJacob Faibussowitsch   PetscCall(RegisterFinalizer(container));
4753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
476eb8be38cSBarry Smith }
477eb8be38cSBarry Smith 
478eb8be38cSBarry Smith /*@C
479811af0c4SBarry Smith   PetscRegisterFinalizeAll - Runs all the finalize functions set with `PetscRegisterFinalize()`
480eb8be38cSBarry Smith 
481eb8be38cSBarry Smith   Not Collective unless registered functions are collective
482eb8be38cSBarry Smith 
483eb8be38cSBarry Smith   Level: developer
484eb8be38cSBarry Smith 
48521532e8aSBarry Smith .seealso: `PetscRegisterFinalize()`, `PetscObjectRegisterDestroyAll()`
486eb8be38cSBarry Smith @*/
487d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscRegisterFinalizeAll(void)
488d71ae5a4SJacob Faibussowitsch {
489eb8be38cSBarry Smith   PetscFunctionBegin;
4903048253cSJacob Faibussowitsch   PetscCall(PetscRunRegisteredFinalizers());
4913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
492eb8be38cSBarry Smith }
493