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