xref: /petsc/src/sys/objects/destroy.c (revision ffeef943c8ee50edff320d8a3135bb0c94853e4c)
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 
54*ffeef943SBarry Smith /*@
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 
80*ffeef943SBarry Smith /*@
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:
9689efdf64SMatthew G. Knepley   The argument has the following form
9789efdf64SMatthew G. Knepley .vb
9889efdf64SMatthew G. Knepley     type:filename:format:filemode
9989efdf64SMatthew G. Knepley .ve
10089efdf64SMatthew 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
10189efdf64SMatthew G. Knepley .vb
10289efdf64SMatthew G. Knepley     hdf5:sol.h5::read
10389efdf64SMatthew G. Knepley .ve
10489efdf64SMatthew 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 
146*ffeef943SBarry Smith /*@
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 
179*ffeef943SBarry Smith /*@
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 
206*ffeef943SBarry Smith /*@
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 
402*ffeef943SBarry Smith /*@
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