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 54e5c89e4eSSatish Balay /*@C 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 802d747510SLisandro Dalcin /*@C 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: 96*89efdf64SMatthew G. Knepley The argument has the following form 97*89efdf64SMatthew G. Knepley .vb 98*89efdf64SMatthew G. Knepley type:filename:format:filemode 99*89efdf64SMatthew G. Knepley .ve 100*89efdf64SMatthew 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 101*89efdf64SMatthew G. Knepley .vb 102*89efdf64SMatthew G. Knepley hdf5:sol.h5::read 103*89efdf64SMatthew G. Knepley .ve 104*89efdf64SMatthew 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 146e5c89e4eSSatish Balay /*@C 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 1792b12f010SJed Brown /*@C 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 206013e2dc7SBarry Smith /*@C 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 402e5c89e4eSSatish Balay /*@C 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