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: 37*dde44402SBarry Smith . obj - any PETSc object, for example a `Vec`, `Mat` or `KSP`. It must be cast with a (`PetscObject`\*), for example, 38*dde44402SBarry 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 55*dde44402SBarry Smith PetscObjectView - Views a `PetscObject` regardless of the type. 56e5c89e4eSSatish Balay 57c3339decSBarry Smith Collective 58e5c89e4eSSatish Balay 59e5c89e4eSSatish Balay Input Parameters: 60*dde44402SBarry Smith + obj - any PETSc object, for example a `Vec`, `Mat` or `KSP`. It must be cast with a (`PetscObject`), for example, 61*dde44402SBarry 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: 9611a5261eSBarry Smith .vb 9711a5261eSBarry Smith If no value is provided ascii:stdout is used 9811a5261eSBarry Smith ascii[:[filename][:[format][:append]]] defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab, 9911a5261eSBarry Smith for example ascii::ascii_info prints just the information about the object not all details 10011a5261eSBarry Smith unless :append is given filename opens in write mode, overwriting what was already there 10111a5261eSBarry Smith binary[:[filename][:[format][:append]]] defaults to the file binaryoutput 10211a5261eSBarry Smith draw[:drawtype[:filename]] for example, draw:tikz, draw:tikz:figure.tex or draw:x 10311a5261eSBarry Smith socket[:port] defaults to the standard output port 10411a5261eSBarry Smith saws[:communicatorname] publishes object to the Scientific Application Webserver (SAWs) 10511a5261eSBarry Smith .ve 10611a5261eSBarry Smith 10721532e8aSBarry Smith This is not called directly but is called by, for example, `MatViewFromOptions()` 10811a5261eSBarry Smith 10911a5261eSBarry Smith .seealso: `PetscObject`, `PetscObjectView()`, `PetscOptionsGetViewer()` 1102d747510SLisandro Dalcin @*/ 111d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscObjectViewFromOptions(PetscObject obj, PetscObject bobj, const char optionname[]) 112d71ae5a4SJacob Faibussowitsch { 1132d747510SLisandro Dalcin PetscViewer viewer; 1142d747510SLisandro Dalcin PetscBool flg; 1152d747510SLisandro Dalcin static PetscBool incall = PETSC_FALSE; 1162d747510SLisandro Dalcin PetscViewerFormat format; 1172d747510SLisandro Dalcin const char *prefix; 1182d747510SLisandro Dalcin 1192d747510SLisandro Dalcin PetscFunctionBegin; 120b843b480SStefano Zampini PetscValidHeader(obj, 1); 121b843b480SStefano Zampini if (bobj) PetscValidHeader(bobj, 2); 1223ba16761SJacob Faibussowitsch if (incall) PetscFunctionReturn(PETSC_SUCCESS); 1232d747510SLisandro Dalcin incall = PETSC_TRUE; 1242d747510SLisandro Dalcin prefix = bobj ? bobj->prefix : obj->prefix; 1259566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)obj), obj->options, prefix, optionname, &viewer, &format, &flg)); 1262d747510SLisandro Dalcin if (flg) { 1279566063dSJacob Faibussowitsch PetscCall(PetscViewerPushFormat(viewer, format)); 1289566063dSJacob Faibussowitsch PetscCall(PetscObjectView(obj, viewer)); 1299566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 1309566063dSJacob Faibussowitsch PetscCall(PetscViewerPopFormat(viewer)); 1319566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&viewer)); 1322d747510SLisandro Dalcin } 1332d747510SLisandro Dalcin incall = PETSC_FALSE; 1343ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1352d747510SLisandro Dalcin } 1362d747510SLisandro Dalcin 137e5c89e4eSSatish Balay /*@C 138251f4c67SDmitry Karpeev PetscObjectTypeCompare - Determines whether a PETSc object is of a particular type. 139e5c89e4eSSatish Balay 140e5c89e4eSSatish Balay Not Collective 141e5c89e4eSSatish Balay 142e5c89e4eSSatish Balay Input Parameters: 143*dde44402SBarry Smith + obj - a PETSc object, for example a `Vec`, `Mat` or `KSP`. It must be cast with a (`PetscObject`), for example, 144811af0c4SBarry Smith `PetscObjectTypeCompare`((`PetscObject`)mat); 145e5c89e4eSSatish Balay - type_name - string containing a type name 146e5c89e4eSSatish Balay 147e5c89e4eSSatish Balay Output Parameter: 148b843b480SStefano Zampini . same - `PETSC_TRUE` if the type of `obj` and `type_name` are the same or both `NULL`, else `PETSC_FALSE` 149e5c89e4eSSatish Balay 150e5c89e4eSSatish Balay Level: intermediate 151e5c89e4eSSatish Balay 152013e2dc7SBarry Smith .seealso: `PetscObject`, `VecGetType()`, `KSPGetType()`, `PCGetType()`, `SNESGetType()`, `PetscObjectBaseTypeCompare()`, `PetscObjectTypeCompareAny()`, `PetscObjectBaseTypeCompareAny()`, `PetscObjectObjectTypeCompare()` 153e5c89e4eSSatish Balay @*/ 154d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscObjectTypeCompare(PetscObject obj, const char type_name[], PetscBool *same) 155d71ae5a4SJacob Faibussowitsch { 156e5c89e4eSSatish Balay PetscFunctionBegin; 1574f572ea9SToby Isaac PetscAssertPointer(same, 3); 158b843b480SStefano Zampini if (!obj) *same = (PetscBool)!type_name; 159a297a907SKarl Rupp else { 160e5c89e4eSSatish Balay PetscValidHeader(obj, 1); 161b843b480SStefano Zampini if (!type_name || !obj->type_name) *same = (PetscBool)(!obj->type_name == !type_name); 162b843b480SStefano Zampini else { 1634f572ea9SToby Isaac PetscAssertPointer(type_name, 2); 164b843b480SStefano Zampini PetscCall(PetscStrcmp(obj->type_name, type_name, same)); 165b843b480SStefano Zampini } 166e5c89e4eSSatish Balay } 1673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 168e5c89e4eSSatish Balay } 169e5c89e4eSSatish Balay 1702b12f010SJed Brown /*@C 171013e2dc7SBarry Smith PetscObjectObjectTypeCompare - Determines whether two PETSc objects are of the same type 172013e2dc7SBarry Smith 173013e2dc7SBarry Smith Logically Collective 174013e2dc7SBarry Smith 175013e2dc7SBarry Smith Input Parameters: 17621532e8aSBarry Smith + obj1 - any PETSc object, for example a `Vec`, `Mat` or `KSP`. 177da81f932SPierre Jolivet - obj2 - another PETSc object 178013e2dc7SBarry Smith 179013e2dc7SBarry Smith Output Parameter: 180b843b480SStefano Zampini . same - `PETSC_TRUE` if they are the same or both unset, else `PETSC_FALSE` 181013e2dc7SBarry Smith 182013e2dc7SBarry Smith Level: intermediate 183013e2dc7SBarry Smith 184013e2dc7SBarry Smith .seealso: `PetscObjectTypeCompare()`, `VecGetType()`, `KSPGetType()`, `PCGetType()`, `SNESGetType()`, `PetscObjectBaseTypeCompare()`, `PetscObjectTypeCompareAny()`, `PetscObjectBaseTypeCompareAny()` 185013e2dc7SBarry Smith 186013e2dc7SBarry Smith @*/ 187d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscObjectObjectTypeCompare(PetscObject obj1, PetscObject obj2, PetscBool *same) 188d71ae5a4SJacob Faibussowitsch { 189013e2dc7SBarry Smith PetscFunctionBegin; 190013e2dc7SBarry Smith PetscValidHeader(obj1, 1); 191013e2dc7SBarry Smith PetscValidHeader(obj2, 2); 1924f572ea9SToby Isaac PetscAssertPointer(same, 3); 193b843b480SStefano Zampini PetscCall(PetscStrcmp(obj1->type_name, obj2->type_name, same)); 1943ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 195013e2dc7SBarry Smith } 196013e2dc7SBarry Smith 197013e2dc7SBarry Smith /*@C 198811af0c4SBarry Smith PetscObjectBaseTypeCompare - Determines whether a `PetscObject` is of a given base type. For example the base type of `MATSEQAIJPERM` is `MATSEQAIJ` 1994099cc6bSBarry Smith 2004099cc6bSBarry Smith Not Collective 2014099cc6bSBarry Smith 2024099cc6bSBarry Smith Input Parameters: 203*dde44402SBarry Smith + obj - the object 2044099cc6bSBarry Smith - type_name - string containing a type name 2054099cc6bSBarry Smith 2064099cc6bSBarry Smith Output Parameter: 207b843b480SStefano Zampini . same - `PETSC_TRUE` if the object is of the same base type identified by `type_name` or both `NULL`, `PETSC_FALSE` otherwise 2084099cc6bSBarry Smith 2094099cc6bSBarry Smith Level: intermediate 2104099cc6bSBarry Smith 211811af0c4SBarry Smith .seealso: `PetscObject`, `PetscObjectTypeCompare()`, `PetscObjectTypeCompareAny()`, `PetscObjectBaseTypeCompareAny()` 2124099cc6bSBarry Smith @*/ 213d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscObjectBaseTypeCompare(PetscObject obj, const char type_name[], PetscBool *same) 214d71ae5a4SJacob Faibussowitsch { 2154099cc6bSBarry Smith PetscFunctionBegin; 2164f572ea9SToby Isaac PetscAssertPointer(same, 3); 217b843b480SStefano Zampini if (!obj) *same = (PetscBool)!type_name; 2184099cc6bSBarry Smith else { 2194099cc6bSBarry Smith PetscValidHeader(obj, 1); 220b843b480SStefano Zampini if (!type_name || !obj->type_name) *same = (PetscBool)(!obj->type_name == !type_name); 221b843b480SStefano Zampini else { 2224f572ea9SToby Isaac PetscAssertPointer(type_name, 2); 223b843b480SStefano Zampini PetscCall(PetscStrbeginswith(obj->type_name, type_name, same)); 224b843b480SStefano Zampini } 2254099cc6bSBarry Smith } 2263ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2274099cc6bSBarry Smith } 2284099cc6bSBarry Smith 2294099cc6bSBarry Smith /*@C 230251f4c67SDmitry Karpeev PetscObjectTypeCompareAny - Determines whether a PETSc object is of any of a list of types. 2312b12f010SJed Brown 2322b12f010SJed Brown Not Collective 2332b12f010SJed Brown 2342b12f010SJed Brown Input Parameters: 235*dde44402SBarry Smith + obj - a PETSc object, for example a `Vec`, `Mat` or `KSP`. It must be cast with a (`PetscObject`), 236*dde44402SBarry Smith for example, `PetscObjectTypeCompareAny`((`PetscObject`)mat,...); 237*dde44402SBarry Smith - type_name - one or more string arguments containing type names, pass the empty string "" as the last argument 2382b12f010SJed Brown 2392b12f010SJed Brown Output Parameter: 24021532e8aSBarry Smith . match - `PETSC_TRUE` if the type of `obj` matches any in the list, else `PETSC_FALSE` 2412b12f010SJed Brown 2422b12f010SJed Brown Level: intermediate 2432b12f010SJed Brown 244dee2f2dbSPierre Jolivet .seealso: `VecGetType()`, `KSPGetType()`, `PCGetType()`, `SNESGetType()`, `PetscObjectTypeCompare()`, `PetscObjectBaseTypeCompare()` 2452b12f010SJed Brown @*/ 246d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscObjectTypeCompareAny(PetscObject obj, PetscBool *match, const char type_name[], ...) 247d71ae5a4SJacob Faibussowitsch { 2482b12f010SJed Brown va_list Argp; 2492b12f010SJed Brown 2502b12f010SJed Brown PetscFunctionBegin; 2514f572ea9SToby Isaac PetscAssertPointer(match, 2); 2522b12f010SJed Brown *match = PETSC_FALSE; 2533ba16761SJacob Faibussowitsch if (!obj) PetscFunctionReturn(PETSC_SUCCESS); 2542b12f010SJed Brown va_start(Argp, type_name); 2552b12f010SJed Brown while (type_name && type_name[0]) { 2562b12f010SJed Brown PetscBool found; 2579566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare(obj, type_name, &found)); 2582b12f010SJed Brown if (found) { 2592b12f010SJed Brown *match = PETSC_TRUE; 2602b12f010SJed Brown break; 2612b12f010SJed Brown } 2622b12f010SJed Brown type_name = va_arg(Argp, const char *); 2632b12f010SJed Brown } 2642b12f010SJed Brown va_end(Argp); 2653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2662b12f010SJed Brown } 2672b12f010SJed Brown 268b9e7e5c1SBarry Smith /*@C 269b9e7e5c1SBarry Smith PetscObjectBaseTypeCompareAny - Determines whether a PETSc object has the base type of any of a list of types. 270b9e7e5c1SBarry Smith 271b9e7e5c1SBarry Smith Not Collective 272b9e7e5c1SBarry Smith 273b9e7e5c1SBarry Smith Input Parameters: 274*dde44402SBarry Smith + obj - a PETSc object, for example a `Vec`, `Mat` or `KSP`. It must be cast with a (`PetscObject`), 275*dde44402SBarry Smith for example, `PetscObjectBaseTypeCompareAny`((`PetscObject`)mat,...); 276*dde44402SBarry Smith - type_name - one or more string arguments containing type names, pass the empty string "" as the last argument 277b9e7e5c1SBarry Smith 278b9e7e5c1SBarry Smith Output Parameter: 27921532e8aSBarry Smith . match - `PETSC_TRUE` if the type of `obj` matches any in the list, else `PETSC_FALSE` 280b9e7e5c1SBarry Smith 281b9e7e5c1SBarry Smith Level: intermediate 282b9e7e5c1SBarry Smith 283db781477SPatrick Sanan .seealso: `VecGetType()`, `KSPGetType()`, `PCGetType()`, `SNESGetType()`, `PetscObjectTypeCompare()`, `PetscObjectBaseTypeCompare()`, `PetscObjectTypeCompareAny()` 284b9e7e5c1SBarry Smith @*/ 285d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscObjectBaseTypeCompareAny(PetscObject obj, PetscBool *match, const char type_name[], ...) 286d71ae5a4SJacob Faibussowitsch { 287b9e7e5c1SBarry Smith va_list Argp; 288b9e7e5c1SBarry Smith 289b9e7e5c1SBarry Smith PetscFunctionBegin; 2904f572ea9SToby Isaac PetscAssertPointer(match, 2); 291b9e7e5c1SBarry Smith *match = PETSC_FALSE; 292b9e7e5c1SBarry Smith va_start(Argp, type_name); 293b9e7e5c1SBarry Smith while (type_name && type_name[0]) { 294b9e7e5c1SBarry Smith PetscBool found; 2959566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare(obj, type_name, &found)); 296b9e7e5c1SBarry Smith if (found) { 297b9e7e5c1SBarry Smith *match = PETSC_TRUE; 298b9e7e5c1SBarry Smith break; 299b9e7e5c1SBarry Smith } 300b9e7e5c1SBarry Smith type_name = va_arg(Argp, const char *); 301b9e7e5c1SBarry Smith } 302b9e7e5c1SBarry Smith va_end(Argp); 3033ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 304b9e7e5c1SBarry Smith } 305b9e7e5c1SBarry Smith 3063048253cSJacob Faibussowitsch typedef struct { 3073048253cSJacob Faibussowitsch PetscErrorCode (*func)(void); 3083048253cSJacob Faibussowitsch } PetscFinalizeFunction; 3093048253cSJacob Faibussowitsch 3103048253cSJacob Faibussowitsch typedef struct { 3113048253cSJacob Faibussowitsch PetscErrorCode (*func)(void *); 3123048253cSJacob Faibussowitsch void *ctx; 3133048253cSJacob Faibussowitsch } PetscFinalizeFunctionWithCtx; 3143048253cSJacob Faibussowitsch 3153048253cSJacob Faibussowitsch typedef enum { 3163048253cSJacob Faibussowitsch PETSC_FINALIZE_EMPTY, 3173048253cSJacob Faibussowitsch PETSC_FINALIZE_OBJECT, 3183048253cSJacob Faibussowitsch PETSC_FINALIZE_FUNC, 3193048253cSJacob Faibussowitsch PETSC_FINALIZE_FUNC_WITH_CTX 3203048253cSJacob Faibussowitsch } PetscFinalizeType; 3213048253cSJacob Faibussowitsch 3223048253cSJacob Faibussowitsch static const char *const PetscFinalizeTypes[] = {"PETSC_FINALIZE_EMPTY", "PETSC_FINALIZE_OBJECT", "PETSC_FINALIZE_FUNC", "PETSC_FINALIZE_FUNC_WITH_CTX", PETSC_NULLPTR}; 3233048253cSJacob Faibussowitsch 3243048253cSJacob Faibussowitsch typedef struct { 3253048253cSJacob Faibussowitsch union ThunkUnion 3263048253cSJacob Faibussowitsch { 3273048253cSJacob Faibussowitsch PetscObject obj; 3283048253cSJacob Faibussowitsch PetscFinalizeFunction fn; 3293048253cSJacob Faibussowitsch PetscFinalizeFunctionWithCtx fnctx; 3303048253cSJacob Faibussowitsch } thunk; 3313048253cSJacob Faibussowitsch PetscFinalizeType type; 3323048253cSJacob Faibussowitsch } PetscFinalizerContainer; 3333048253cSJacob Faibussowitsch 3343048253cSJacob Faibussowitsch #define PETSC_MAX_REGISTERED_FINALIZERS 256 3353048253cSJacob Faibussowitsch static int reg_count = 0; 3363048253cSJacob Faibussowitsch static PetscFinalizerContainer regfin[PETSC_MAX_REGISTERED_FINALIZERS]; 3373048253cSJacob Faibussowitsch 33866976f2fSJacob Faibussowitsch static PetscErrorCode PetscRunRegisteredFinalizers(void) 3393048253cSJacob Faibussowitsch { 3403048253cSJacob Faibussowitsch PetscFunctionBegin; 3413048253cSJacob Faibussowitsch while (reg_count) { 3423048253cSJacob Faibussowitsch PetscFinalizerContainer top = regfin[--reg_count]; 3433048253cSJacob Faibussowitsch 3443048253cSJacob Faibussowitsch regfin[reg_count].type = PETSC_FINALIZE_EMPTY; 3453048253cSJacob Faibussowitsch PetscCall(PetscArrayzero(®fin[reg_count].thunk, 1)); 3463048253cSJacob Faibussowitsch switch (top.type) { 3473048253cSJacob Faibussowitsch case PETSC_FINALIZE_OBJECT: 34834fa283eSBarry Smith top.thunk.obj->persistent = PETSC_FALSE; 3493048253cSJacob Faibussowitsch PetscCall(PetscObjectDestroy(&top.thunk.obj)); 3503048253cSJacob Faibussowitsch break; 3513048253cSJacob Faibussowitsch case PETSC_FINALIZE_FUNC: 3523048253cSJacob Faibussowitsch PetscCall((*top.thunk.fn.func)()); 3533048253cSJacob Faibussowitsch break; 3543048253cSJacob Faibussowitsch case PETSC_FINALIZE_FUNC_WITH_CTX: 3553048253cSJacob Faibussowitsch PetscCall((*top.thunk.fnctx.func)(top.thunk.fnctx.ctx)); 3563048253cSJacob Faibussowitsch break; 3573048253cSJacob Faibussowitsch case PETSC_FINALIZE_EMPTY: 3583048253cSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Finalizer at position %d is empty, yet registration count %d != 0", reg_count, reg_count); 3593048253cSJacob Faibussowitsch break; 3603048253cSJacob Faibussowitsch } 3613048253cSJacob Faibussowitsch } 3623048253cSJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3633048253cSJacob Faibussowitsch } 3643048253cSJacob Faibussowitsch 3653048253cSJacob Faibussowitsch static int PetscFinalizerContainerEqual(const PetscFinalizerContainer *a, const PetscFinalizerContainer *b) 3663048253cSJacob Faibussowitsch { 3673048253cSJacob Faibussowitsch if (a->type != b->type) return 0; 3683048253cSJacob Faibussowitsch switch (a->type) { 3693048253cSJacob Faibussowitsch case PETSC_FINALIZE_EMPTY: 3703048253cSJacob Faibussowitsch break; 3713048253cSJacob Faibussowitsch case PETSC_FINALIZE_OBJECT: 3723048253cSJacob Faibussowitsch return a->thunk.obj == b->thunk.obj; 3733048253cSJacob Faibussowitsch case PETSC_FINALIZE_FUNC: 3743048253cSJacob Faibussowitsch return a->thunk.fn.func == b->thunk.fn.func; 3753048253cSJacob Faibussowitsch case PETSC_FINALIZE_FUNC_WITH_CTX: 3763048253cSJacob Faibussowitsch return a->thunk.fnctx.func == b->thunk.fnctx.func && a->thunk.fnctx.ctx == b->thunk.fnctx.ctx; 3773048253cSJacob Faibussowitsch } 3783048253cSJacob Faibussowitsch return 1; 3793048253cSJacob Faibussowitsch } 3803048253cSJacob Faibussowitsch 3813048253cSJacob Faibussowitsch static PetscErrorCode RegisterFinalizer(PetscFinalizerContainer container) 3823048253cSJacob Faibussowitsch { 3833048253cSJacob Faibussowitsch PetscFunctionBegin; 3843048253cSJacob 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__); 3853048253cSJacob 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); 3863048253cSJacob Faibussowitsch if (PetscDefined(USE_DEBUG)) { 3873048253cSJacob 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]); 3883048253cSJacob Faibussowitsch } 3893048253cSJacob Faibussowitsch regfin[reg_count++] = container; 3903048253cSJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3913048253cSJacob Faibussowitsch } 392e5c89e4eSSatish Balay 393e5c89e4eSSatish Balay /*@C 394e5c89e4eSSatish Balay PetscObjectRegisterDestroy - Registers a PETSc object to be destroyed when 395811af0c4SBarry Smith `PetscFinalize()` is called. 396e5c89e4eSSatish Balay 397c3339decSBarry Smith Logically Collective 398e5c89e4eSSatish Balay 399e5c89e4eSSatish Balay Input Parameter: 400*dde44402SBarry Smith . obj - a PETSc object, for example a `Vec`, `Mat` or `KSP`. It must be cast with a (`PetscObject`), for example, 401811af0c4SBarry Smith `PetscObjectRegisterDestroy`((`PetscObject`)mat); 402e5c89e4eSSatish Balay 403e5c89e4eSSatish Balay Level: developer 404e5c89e4eSSatish Balay 405811af0c4SBarry Smith Note: 40621532e8aSBarry Smith This is used by, for example, `PETSC_VIEWER_XXX_()` routines to free the viewer 407e5c89e4eSSatish Balay when PETSc ends. 408e5c89e4eSSatish Balay 409db781477SPatrick Sanan .seealso: `PetscObjectRegisterDestroyAll()` 410e5c89e4eSSatish Balay @*/ 411d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscObjectRegisterDestroy(PetscObject obj) 412d71ae5a4SJacob Faibussowitsch { 4133048253cSJacob Faibussowitsch PetscFinalizerContainer container; 4143048253cSJacob Faibussowitsch 415e5c89e4eSSatish Balay PetscFunctionBegin; 416e5c89e4eSSatish Balay PetscValidHeader(obj, 1); 4173048253cSJacob Faibussowitsch container.thunk.obj = obj; 4183048253cSJacob Faibussowitsch container.type = PETSC_FINALIZE_OBJECT; 4193048253cSJacob Faibussowitsch PetscCall(RegisterFinalizer(container)); 4203ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 421e5c89e4eSSatish Balay } 422e5c89e4eSSatish Balay 423e5c89e4eSSatish Balay /*@C 424e5c89e4eSSatish Balay PetscObjectRegisterDestroyAll - Frees all the PETSc objects that have been registered 425811af0c4SBarry Smith with `PetscObjectRegisterDestroy()`. Called by `PetscFinalize()` 426e5c89e4eSSatish Balay 427811af0c4SBarry Smith Logically Collective on the individual `PetscObject`s that are being processed 428e5c89e4eSSatish Balay 429e5c89e4eSSatish Balay Level: developer 430e5c89e4eSSatish Balay 431db781477SPatrick Sanan .seealso: `PetscObjectRegisterDestroy()` 432e5c89e4eSSatish Balay @*/ 433d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscObjectRegisterDestroyAll(void) 434d71ae5a4SJacob Faibussowitsch { 435e5c89e4eSSatish Balay PetscFunctionBegin; 4363048253cSJacob Faibussowitsch PetscCall(PetscRunRegisteredFinalizers()); 4373ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 438e5c89e4eSSatish Balay } 439e5c89e4eSSatish Balay 440eb8be38cSBarry Smith /*@C 441811af0c4SBarry Smith PetscRegisterFinalize - Registers a function that is to be called in `PetscFinalize()` 442eb8be38cSBarry Smith 443eb8be38cSBarry Smith Not Collective 444eb8be38cSBarry Smith 445eb8be38cSBarry Smith Input Parameter: 446aec76313SJacob Faibussowitsch . f - function to be called 447eb8be38cSBarry Smith 448eb8be38cSBarry Smith Level: developer 449eb8be38cSBarry Smith 45021532e8aSBarry Smith Notes: 451811af0c4SBarry Smith This is used by, for example, `DMInitializePackage()` to have `DMFinalizePackage()` called 452eb8be38cSBarry Smith 45321532e8aSBarry Smith Use `PetscObjectRegisterDestroy()` to register the destruction of an object in `PetscFinalize()` 45421532e8aSBarry Smith 45521532e8aSBarry Smith .seealso: `PetscRegisterFinalizeAll()`, `PetscObjectRegisterDestroy()` 456eb8be38cSBarry Smith @*/ 457d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscRegisterFinalize(PetscErrorCode (*f)(void)) 458d71ae5a4SJacob Faibussowitsch { 4593048253cSJacob Faibussowitsch PetscFinalizerContainer container; 4603048253cSJacob Faibussowitsch 461f4aac215SBarry Smith PetscFunctionBegin; 4623048253cSJacob Faibussowitsch PetscValidFunction(f, 1); 4633048253cSJacob Faibussowitsch container.thunk.fn.func = f; 4643048253cSJacob Faibussowitsch container.type = PETSC_FINALIZE_FUNC; 4653048253cSJacob Faibussowitsch PetscCall(RegisterFinalizer(container)); 4663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 467eb8be38cSBarry Smith } 468eb8be38cSBarry Smith 469eb8be38cSBarry Smith /*@C 470811af0c4SBarry Smith PetscRegisterFinalizeAll - Runs all the finalize functions set with `PetscRegisterFinalize()` 471eb8be38cSBarry Smith 472eb8be38cSBarry Smith Not Collective unless registered functions are collective 473eb8be38cSBarry Smith 474eb8be38cSBarry Smith Level: developer 475eb8be38cSBarry Smith 47621532e8aSBarry Smith .seealso: `PetscRegisterFinalize()`, `PetscObjectRegisterDestroyAll()` 477eb8be38cSBarry Smith @*/ 478d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscRegisterFinalizeAll(void) 479d71ae5a4SJacob Faibussowitsch { 480eb8be38cSBarry Smith PetscFunctionBegin; 4813048253cSJacob Faibussowitsch PetscCall(PetscRunRegisteredFinalizers()); 4823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 483eb8be38cSBarry Smith } 484