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 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 @*/ 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 @*/ 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 @*/ 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 @*/ 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 @*/ 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 *); 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 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 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 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 @*/ 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 @*/ 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 @*/ 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 @*/ 486d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscRegisterFinalizeAll(void) 487d71ae5a4SJacob Faibussowitsch { 488eb8be38cSBarry Smith PetscFunctionBegin; 4893048253cSJacob Faibussowitsch PetscCall(PetscRunRegisteredFinalizers()); 4903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 491eb8be38cSBarry Smith } 492