xref: /petsc/src/sys/objects/destroy.c (revision 4e8208cbcbc709572b8abe32f33c78b69c819375)
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 
DestroyComposedData(void *** composed_star,PetscObjectState ** state_star,PetscInt * count_star,void ** composed,PetscObjectState ** state)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 
PetscComposedQuantitiesDestroy(PetscObject obj)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 @*/
PetscObjectDestroy(PetscObject * obj)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 
54ffeef943SBarry 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 @*/
PetscObjectView(PetscObject obj,PetscViewer viewer)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 
80ffeef943SBarry 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 
118648c30bcSBarry Smith .seealso: `PetscObject`, `PetscObjectView()`, `PetscOptionsCreateViewer()`
1192d747510SLisandro Dalcin @*/
PetscObjectViewFromOptions(PetscObject obj,PetscObject bobj,const char optionname[])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;
134835f2295SStefano Zampini   PetscCall(PetscOptionsCreateViewer(PetscObjectComm(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));
140648c30bcSBarry Smith     PetscCall(PetscViewerDestroy(&viewer));
1412d747510SLisandro Dalcin   }
1422d747510SLisandro Dalcin   incall = PETSC_FALSE;
1433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1442d747510SLisandro Dalcin }
1452d747510SLisandro Dalcin 
146ffeef943SBarry 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 @*/
PetscObjectTypeCompare(PetscObject obj,const char type_name[],PetscBool * same)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 
179ffeef943SBarry 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 @*/
PetscObjectObjectTypeCompare(PetscObject obj1,PetscObject obj2,PetscBool * same)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 
206ffeef943SBarry 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 @*/
PetscObjectBaseTypeCompare(PetscObject obj,const char type_name[],PetscBool * same)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 @*/
PetscObjectTypeCompareAny(PetscObject obj,PetscBool * match,const char type_name[],...)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 @*/
PetscObjectBaseTypeCompareAny(PetscObject obj,PetscBool * match,const char type_name[],...)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 *);
321*2a8381b2SBarry Smith   PetscCtx 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 
PetscRunRegisteredFinalizers(void)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:
3573048253cSJacob Faibussowitsch       PetscCall(PetscObjectDestroy(&top.thunk.obj));
3583048253cSJacob Faibussowitsch       break;
3593048253cSJacob Faibussowitsch     case PETSC_FINALIZE_FUNC:
3603048253cSJacob Faibussowitsch       PetscCall((*top.thunk.fn.func)());
3613048253cSJacob Faibussowitsch       break;
3623048253cSJacob Faibussowitsch     case PETSC_FINALIZE_FUNC_WITH_CTX:
3633048253cSJacob Faibussowitsch       PetscCall((*top.thunk.fnctx.func)(top.thunk.fnctx.ctx));
3643048253cSJacob Faibussowitsch       break;
3653048253cSJacob Faibussowitsch     case PETSC_FINALIZE_EMPTY:
3663048253cSJacob Faibussowitsch       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Finalizer at position %d is empty, yet registration count %d != 0", reg_count, reg_count);
3673048253cSJacob Faibussowitsch       break;
3683048253cSJacob Faibussowitsch     }
3693048253cSJacob Faibussowitsch   }
3703048253cSJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3713048253cSJacob Faibussowitsch }
3723048253cSJacob Faibussowitsch 
PetscFinalizerContainerEqual(const PetscFinalizerContainer * a,const PetscFinalizerContainer * b)3733048253cSJacob Faibussowitsch static int PetscFinalizerContainerEqual(const PetscFinalizerContainer *a, const PetscFinalizerContainer *b)
3743048253cSJacob Faibussowitsch {
3753048253cSJacob Faibussowitsch   if (a->type != b->type) return 0;
3763048253cSJacob Faibussowitsch   switch (a->type) {
3773048253cSJacob Faibussowitsch   case PETSC_FINALIZE_EMPTY:
3783048253cSJacob Faibussowitsch     break;
3793048253cSJacob Faibussowitsch   case PETSC_FINALIZE_OBJECT:
3803048253cSJacob Faibussowitsch     return a->thunk.obj == b->thunk.obj;
3813048253cSJacob Faibussowitsch   case PETSC_FINALIZE_FUNC:
3823048253cSJacob Faibussowitsch     return a->thunk.fn.func == b->thunk.fn.func;
3833048253cSJacob Faibussowitsch   case PETSC_FINALIZE_FUNC_WITH_CTX:
3843048253cSJacob Faibussowitsch     return a->thunk.fnctx.func == b->thunk.fnctx.func && a->thunk.fnctx.ctx == b->thunk.fnctx.ctx;
3853048253cSJacob Faibussowitsch   }
3863048253cSJacob Faibussowitsch   return 1;
3873048253cSJacob Faibussowitsch }
3883048253cSJacob Faibussowitsch 
RegisterFinalizer(PetscFinalizerContainer container)3893048253cSJacob Faibussowitsch static PetscErrorCode RegisterFinalizer(PetscFinalizerContainer container)
3903048253cSJacob Faibussowitsch {
3913048253cSJacob Faibussowitsch   PetscFunctionBegin;
3923048253cSJacob 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__);
3933048253cSJacob 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);
3943048253cSJacob Faibussowitsch   if (PetscDefined(USE_DEBUG)) {
3953048253cSJacob 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]);
3963048253cSJacob Faibussowitsch   }
3973048253cSJacob Faibussowitsch   regfin[reg_count++] = container;
3983048253cSJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3993048253cSJacob Faibussowitsch }
400e5c89e4eSSatish Balay 
401ffeef943SBarry Smith /*@
402e5c89e4eSSatish Balay   PetscObjectRegisterDestroy - Registers a PETSc object to be destroyed when
403811af0c4SBarry Smith   `PetscFinalize()` is called.
404e5c89e4eSSatish Balay 
405c3339decSBarry Smith   Logically Collective
406e5c89e4eSSatish Balay 
407e5c89e4eSSatish Balay   Input Parameter:
408dde44402SBarry Smith . obj - a PETSc object, for example a `Vec`, `Mat` or `KSP`. It must be cast with a (`PetscObject`), for example,
409811af0c4SBarry Smith         `PetscObjectRegisterDestroy`((`PetscObject`)mat);
410e5c89e4eSSatish Balay 
411e5c89e4eSSatish Balay   Level: developer
412e5c89e4eSSatish Balay 
413811af0c4SBarry Smith   Note:
41421532e8aSBarry Smith   This is used by, for example, `PETSC_VIEWER_XXX_()` routines to free the viewer
415e5c89e4eSSatish Balay   when PETSc ends.
416e5c89e4eSSatish Balay 
417db781477SPatrick Sanan .seealso: `PetscObjectRegisterDestroyAll()`
418e5c89e4eSSatish Balay @*/
PetscObjectRegisterDestroy(PetscObject obj)419d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscObjectRegisterDestroy(PetscObject obj)
420d71ae5a4SJacob Faibussowitsch {
4213048253cSJacob Faibussowitsch   PetscFinalizerContainer container;
4223048253cSJacob Faibussowitsch 
423e5c89e4eSSatish Balay   PetscFunctionBegin;
424e5c89e4eSSatish Balay   PetscValidHeader(obj, 1);
4253048253cSJacob Faibussowitsch   container.thunk.obj = obj;
4263048253cSJacob Faibussowitsch   container.type      = PETSC_FINALIZE_OBJECT;
4273048253cSJacob Faibussowitsch   PetscCall(RegisterFinalizer(container));
4283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
429e5c89e4eSSatish Balay }
430e5c89e4eSSatish Balay 
431e5c89e4eSSatish Balay /*@C
432e5c89e4eSSatish Balay   PetscObjectRegisterDestroyAll - Frees all the PETSc objects that have been registered
433811af0c4SBarry Smith   with `PetscObjectRegisterDestroy()`. Called by `PetscFinalize()`
434e5c89e4eSSatish Balay 
435811af0c4SBarry Smith   Logically Collective on the individual `PetscObject`s that are being processed
436e5c89e4eSSatish Balay 
437e5c89e4eSSatish Balay   Level: developer
438e5c89e4eSSatish Balay 
439db781477SPatrick Sanan .seealso: `PetscObjectRegisterDestroy()`
440e5c89e4eSSatish Balay @*/
PetscObjectRegisterDestroyAll(void)441d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscObjectRegisterDestroyAll(void)
442d71ae5a4SJacob Faibussowitsch {
443e5c89e4eSSatish Balay   PetscFunctionBegin;
4443048253cSJacob Faibussowitsch   PetscCall(PetscRunRegisteredFinalizers());
4453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
446e5c89e4eSSatish Balay }
447e5c89e4eSSatish Balay 
448eb8be38cSBarry Smith /*@C
449811af0c4SBarry Smith   PetscRegisterFinalize - Registers a function that is to be called in `PetscFinalize()`
450eb8be38cSBarry Smith 
451eb8be38cSBarry Smith   Not Collective
452eb8be38cSBarry Smith 
453eb8be38cSBarry Smith   Input Parameter:
454aec76313SJacob Faibussowitsch . f - function to be called
455eb8be38cSBarry Smith 
456eb8be38cSBarry Smith   Level: developer
457eb8be38cSBarry Smith 
45821532e8aSBarry Smith   Notes:
459811af0c4SBarry Smith   This is used by, for example, `DMInitializePackage()` to have `DMFinalizePackage()` called
460eb8be38cSBarry Smith 
46121532e8aSBarry Smith   Use `PetscObjectRegisterDestroy()` to register the destruction of an object in `PetscFinalize()`
46221532e8aSBarry Smith 
46321532e8aSBarry Smith .seealso: `PetscRegisterFinalizeAll()`, `PetscObjectRegisterDestroy()`
464eb8be38cSBarry Smith @*/
PetscRegisterFinalize(PetscErrorCode (* f)(void))465d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscRegisterFinalize(PetscErrorCode (*f)(void))
466d71ae5a4SJacob Faibussowitsch {
4673048253cSJacob Faibussowitsch   PetscFinalizerContainer container;
4683048253cSJacob Faibussowitsch 
469f4aac215SBarry Smith   PetscFunctionBegin;
4703048253cSJacob Faibussowitsch   PetscValidFunction(f, 1);
4713048253cSJacob Faibussowitsch   container.thunk.fn.func = f;
4723048253cSJacob Faibussowitsch   container.type          = PETSC_FINALIZE_FUNC;
4733048253cSJacob Faibussowitsch   PetscCall(RegisterFinalizer(container));
4743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
475eb8be38cSBarry Smith }
476eb8be38cSBarry Smith 
477eb8be38cSBarry Smith /*@C
478811af0c4SBarry Smith   PetscRegisterFinalizeAll - Runs all the finalize functions set with `PetscRegisterFinalize()`
479eb8be38cSBarry Smith 
480eb8be38cSBarry Smith   Not Collective unless registered functions are collective
481eb8be38cSBarry Smith 
482eb8be38cSBarry Smith   Level: developer
483eb8be38cSBarry Smith 
48421532e8aSBarry Smith .seealso: `PetscRegisterFinalize()`, `PetscObjectRegisterDestroyAll()`
485eb8be38cSBarry Smith @*/
PetscRegisterFinalizeAll(void)486d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscRegisterFinalizeAll(void)
487d71ae5a4SJacob Faibussowitsch {
488eb8be38cSBarry Smith   PetscFunctionBegin;
4893048253cSJacob Faibussowitsch   PetscCall(PetscRunRegisteredFinalizers());
4903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
491eb8be38cSBarry Smith }
492