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(®fin[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