17d0a6c19SBarry Smith 2e5c89e4eSSatish Balay /* 3e5c89e4eSSatish Balay Provides utility routines for manulating any type of PETSc object. 4e5c89e4eSSatish Balay */ 5af0996ceSBarry Smith #include <petsc/private/petscimpl.h> /*I "petscsys.h" I*/ 6665c2dedSJed Brown #include <petscviewer.h> 7e5c89e4eSSatish Balay 89cd7b5a2SJacob Faibussowitsch static PetscErrorCode DestroyComposedData(void ***composed_star, PetscObjectState **state_star, PetscInt *count_star, void **composed, PetscObjectState **state) 9d71ae5a4SJacob Faibussowitsch { 109cd7b5a2SJacob Faibussowitsch void **tmp_star = *composed_star; 11d42688cbSBarry Smith 12b436f76fSVictor Eijkhout PetscFunctionBegin; 139cd7b5a2SJacob Faibussowitsch for (PetscInt i = 0, imax = *count_star; i < imax; ++i) PetscCall(PetscFree(tmp_star[i])); 149cd7b5a2SJacob Faibussowitsch PetscCall(PetscFree2(*composed_star, *state_star)); 159cd7b5a2SJacob Faibussowitsch PetscCall(PetscFree2(*composed, *state)); 169cd7b5a2SJacob Faibussowitsch *count_star = 0; 179cd7b5a2SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 189cd7b5a2SJacob Faibussowitsch } 199cd7b5a2SJacob Faibussowitsch 209cd7b5a2SJacob Faibussowitsch PetscErrorCode PetscComposedQuantitiesDestroy(PetscObject obj) 219cd7b5a2SJacob Faibussowitsch { 229cd7b5a2SJacob Faibussowitsch PetscFunctionBegin; 23b843b480SStefano Zampini PetscValidHeader(obj, 1); 249cd7b5a2SJacob Faibussowitsch PetscCall(DestroyComposedData((void ***)&obj->intstarcomposeddata, &obj->intstarcomposedstate, &obj->intstar_idmax, (void **)&obj->intcomposeddata, &obj->intcomposedstate)); 259cd7b5a2SJacob Faibussowitsch PetscCall(DestroyComposedData((void ***)&obj->realstarcomposeddata, &obj->realstarcomposedstate, &obj->realstar_idmax, (void **)&obj->realcomposeddata, &obj->realcomposedstate)); 269cd7b5a2SJacob Faibussowitsch #if PetscDefined(USE_COMPLEX) 279cd7b5a2SJacob Faibussowitsch PetscCall(DestroyComposedData((void ***)&obj->scalarstarcomposeddata, &obj->scalarstarcomposedstate, &obj->scalarstar_idmax, (void **)&obj->scalarcomposeddata, &obj->scalarcomposedstate)); 289cd7b5a2SJacob Faibussowitsch #endif 293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 30b436f76fSVictor Eijkhout } 31b436f76fSVictor Eijkhout 32e30d2299SSatish Balay /*@ 33811af0c4SBarry Smith PetscObjectDestroy - Destroys any `PetscObject`, regardless of the type. 34e5c89e4eSSatish Balay 35c3339decSBarry Smith Collective 36e5c89e4eSSatish Balay 37e5c89e4eSSatish Balay Input Parameter: 38811af0c4SBarry Smith . obj - any PETSc object, for example a `Vec`, `Mat` or `KSP`. 39811af0c4SBarry Smith This must be cast with a (`PetscObject`*), for example, 40811af0c4SBarry Smith `PetscObjectDestroy`((`PetscObject`*)&mat); 41e5c89e4eSSatish Balay 42e5c89e4eSSatish Balay Level: beginner 43e5c89e4eSSatish Balay 44811af0c4SBarry Smith .seealso: `PetscObject` 45e5c89e4eSSatish Balay @*/ 46d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscObjectDestroy(PetscObject *obj) 47d71ae5a4SJacob Faibussowitsch { 48e5c89e4eSSatish Balay PetscFunctionBegin; 493ba16761SJacob Faibussowitsch if (!obj || !*obj) PetscFunctionReturn(PETSC_SUCCESS); 506bf464f9SBarry Smith PetscValidHeader(*obj, 1); 515f80ce2aSJacob 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); 529566063dSJacob Faibussowitsch PetscCall((*(*obj)->bops->destroy)(obj)); 533ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 54e5c89e4eSSatish Balay } 55e5c89e4eSSatish Balay 56e5c89e4eSSatish Balay /*@C 57811af0c4SBarry Smith PetscObjectView - Views any `PetscObject`, regardless of the type. 58e5c89e4eSSatish Balay 59c3339decSBarry Smith Collective 60e5c89e4eSSatish Balay 61e5c89e4eSSatish Balay Input Parameters: 62811af0c4SBarry Smith + obj - any PETSc object, for example a `Vec`, `Mat` or `KSP`. 63811af0c4SBarry Smith This must be cast with a (`PetscObject`), for example, 64811af0c4SBarry Smith `PetscObjectView`((`PetscObject`)mat,viewer); 65e5c89e4eSSatish Balay - viewer - any PETSc viewer 66e5c89e4eSSatish Balay 67e5c89e4eSSatish Balay Level: intermediate 68e5c89e4eSSatish Balay 69811af0c4SBarry Smith .seealso: `PetscObject`, `PetscObjectViewFromOptions()` 70e5c89e4eSSatish Balay @*/ 71d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscObjectView(PetscObject obj, PetscViewer viewer) 72d71ae5a4SJacob Faibussowitsch { 73e5c89e4eSSatish Balay PetscFunctionBegin; 74e5c89e4eSSatish Balay PetscValidHeader(obj, 1); 755f80ce2aSJacob Faibussowitsch PetscCheck(obj->bops->view, PETSC_COMM_SELF, PETSC_ERR_SUP, "This PETSc object does not have a generic viewer routine"); 769566063dSJacob Faibussowitsch if (!viewer) PetscCall(PetscViewerASCIIGetStdout(obj->comm, &viewer)); 770700a824SBarry Smith PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 78e5c89e4eSSatish Balay 799566063dSJacob Faibussowitsch PetscCall((*obj->bops->view)(obj, viewer)); 803ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 81e5c89e4eSSatish Balay } 82e5c89e4eSSatish Balay 832d747510SLisandro Dalcin /*@C 84811af0c4SBarry Smith PetscObjectViewFromOptions - Processes command line options to determine if/how a `PetscObject` is to be viewed. 852d747510SLisandro Dalcin 86c3339decSBarry Smith Collective 872d747510SLisandro Dalcin 882d747510SLisandro Dalcin Input Parameters: 892d747510SLisandro Dalcin + obj - the object 9021532e8aSBarry Smith . bobj - optional other object that provides prefix (if `NULL` then the prefix in `obj` is used) 91bb7acecfSBarry Smith - optionname - option string that is used to activate viewing 922d747510SLisandro Dalcin 9311a5261eSBarry Smith Options Database Key: 9421532e8aSBarry Smith . -optionname_view [viewertype]:... - option name and values. In actual usage this would be something like `-mat_coarse_view` 9521532e8aSBarry Smith 9621532e8aSBarry Smith Level: developer 972d747510SLisandro Dalcin 9811a5261eSBarry Smith Notes: 9911a5261eSBarry Smith .vb 10011a5261eSBarry Smith If no value is provided ascii:stdout is used 10111a5261eSBarry Smith ascii[:[filename][:[format][:append]]] defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab, 10211a5261eSBarry Smith for example ascii::ascii_info prints just the information about the object not all details 10311a5261eSBarry Smith unless :append is given filename opens in write mode, overwriting what was already there 10411a5261eSBarry Smith binary[:[filename][:[format][:append]]] defaults to the file binaryoutput 10511a5261eSBarry Smith draw[:drawtype[:filename]] for example, draw:tikz, draw:tikz:figure.tex or draw:x 10611a5261eSBarry Smith socket[:port] defaults to the standard output port 10711a5261eSBarry Smith saws[:communicatorname] publishes object to the Scientific Application Webserver (SAWs) 10811a5261eSBarry Smith .ve 10911a5261eSBarry Smith 11021532e8aSBarry Smith This is not called directly but is called by, for example, `MatViewFromOptions()` 11111a5261eSBarry Smith 11211a5261eSBarry Smith .seealso: `PetscObject`, `PetscObjectView()`, `PetscOptionsGetViewer()` 1132d747510SLisandro Dalcin @*/ 114d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscObjectViewFromOptions(PetscObject obj, PetscObject bobj, const char optionname[]) 115d71ae5a4SJacob Faibussowitsch { 1162d747510SLisandro Dalcin PetscViewer viewer; 1172d747510SLisandro Dalcin PetscBool flg; 1182d747510SLisandro Dalcin static PetscBool incall = PETSC_FALSE; 1192d747510SLisandro Dalcin PetscViewerFormat format; 1202d747510SLisandro Dalcin const char *prefix; 1212d747510SLisandro Dalcin 1222d747510SLisandro Dalcin PetscFunctionBegin; 123b843b480SStefano Zampini PetscValidHeader(obj, 1); 124b843b480SStefano Zampini if (bobj) PetscValidHeader(bobj, 2); 1253ba16761SJacob Faibussowitsch if (incall) PetscFunctionReturn(PETSC_SUCCESS); 1262d747510SLisandro Dalcin incall = PETSC_TRUE; 1272d747510SLisandro Dalcin prefix = bobj ? bobj->prefix : obj->prefix; 1289566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)obj), obj->options, prefix, optionname, &viewer, &format, &flg)); 1292d747510SLisandro Dalcin if (flg) { 1309566063dSJacob Faibussowitsch PetscCall(PetscViewerPushFormat(viewer, format)); 1319566063dSJacob Faibussowitsch PetscCall(PetscObjectView(obj, viewer)); 1329566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 1339566063dSJacob Faibussowitsch PetscCall(PetscViewerPopFormat(viewer)); 1349566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&viewer)); 1352d747510SLisandro Dalcin } 1362d747510SLisandro Dalcin incall = PETSC_FALSE; 1373ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1382d747510SLisandro Dalcin } 1392d747510SLisandro Dalcin 140e5c89e4eSSatish Balay /*@C 141251f4c67SDmitry Karpeev PetscObjectTypeCompare - Determines whether a PETSc object is of a particular type. 142e5c89e4eSSatish Balay 143e5c89e4eSSatish Balay Not Collective 144e5c89e4eSSatish Balay 145e5c89e4eSSatish Balay Input Parameters: 146aa624791SPierre Jolivet + obj - any PETSc object, for example a `Vec`, `Mat` or `KSP`. 147811af0c4SBarry Smith This must be cast with a (`PetscObject`), for example, 148811af0c4SBarry Smith `PetscObjectTypeCompare`((`PetscObject`)mat); 149e5c89e4eSSatish Balay - type_name - string containing a type name 150e5c89e4eSSatish Balay 151e5c89e4eSSatish Balay Output Parameter: 152b843b480SStefano Zampini . same - `PETSC_TRUE` if the type of `obj` and `type_name` are the same or both `NULL`, else `PETSC_FALSE` 153e5c89e4eSSatish Balay 154e5c89e4eSSatish Balay Level: intermediate 155e5c89e4eSSatish Balay 156013e2dc7SBarry Smith .seealso: `PetscObject`, `VecGetType()`, `KSPGetType()`, `PCGetType()`, `SNESGetType()`, `PetscObjectBaseTypeCompare()`, `PetscObjectTypeCompareAny()`, `PetscObjectBaseTypeCompareAny()`, `PetscObjectObjectTypeCompare()` 157e5c89e4eSSatish Balay @*/ 158d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscObjectTypeCompare(PetscObject obj, const char type_name[], PetscBool *same) 159d71ae5a4SJacob Faibussowitsch { 160e5c89e4eSSatish Balay PetscFunctionBegin; 1614f572ea9SToby Isaac PetscAssertPointer(same, 3); 162b843b480SStefano Zampini if (!obj) *same = (PetscBool)!type_name; 163a297a907SKarl Rupp else { 164e5c89e4eSSatish Balay PetscValidHeader(obj, 1); 165b843b480SStefano Zampini if (!type_name || !obj->type_name) *same = (PetscBool)(!obj->type_name == !type_name); 166b843b480SStefano Zampini else { 1674f572ea9SToby Isaac PetscAssertPointer(type_name, 2); 168b843b480SStefano Zampini PetscCall(PetscStrcmp(obj->type_name, type_name, same)); 169b843b480SStefano Zampini } 170e5c89e4eSSatish Balay } 1713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 172e5c89e4eSSatish Balay } 173e5c89e4eSSatish Balay 1742b12f010SJed Brown /*@C 175013e2dc7SBarry Smith PetscObjectObjectTypeCompare - Determines whether two PETSc objects are of the same type 176013e2dc7SBarry Smith 177013e2dc7SBarry Smith Logically Collective 178013e2dc7SBarry Smith 179013e2dc7SBarry Smith Input Parameters: 18021532e8aSBarry Smith + obj1 - any PETSc object, for example a `Vec`, `Mat` or `KSP`. 181da81f932SPierre Jolivet - obj2 - another PETSc object 182013e2dc7SBarry Smith 183013e2dc7SBarry Smith Output Parameter: 184b843b480SStefano Zampini . same - `PETSC_TRUE` if they are the same or both unset, else `PETSC_FALSE` 185013e2dc7SBarry Smith 186013e2dc7SBarry Smith Level: intermediate 187013e2dc7SBarry Smith 188013e2dc7SBarry Smith .seealso: `PetscObjectTypeCompare()`, `VecGetType()`, `KSPGetType()`, `PCGetType()`, `SNESGetType()`, `PetscObjectBaseTypeCompare()`, `PetscObjectTypeCompareAny()`, `PetscObjectBaseTypeCompareAny()` 189013e2dc7SBarry Smith 190013e2dc7SBarry Smith @*/ 191d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscObjectObjectTypeCompare(PetscObject obj1, PetscObject obj2, PetscBool *same) 192d71ae5a4SJacob Faibussowitsch { 193013e2dc7SBarry Smith PetscFunctionBegin; 194013e2dc7SBarry Smith PetscValidHeader(obj1, 1); 195013e2dc7SBarry Smith PetscValidHeader(obj2, 2); 1964f572ea9SToby Isaac PetscAssertPointer(same, 3); 197b843b480SStefano Zampini PetscCall(PetscStrcmp(obj1->type_name, obj2->type_name, same)); 1983ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 199013e2dc7SBarry Smith } 200013e2dc7SBarry Smith 201013e2dc7SBarry Smith /*@C 202811af0c4SBarry Smith PetscObjectBaseTypeCompare - Determines whether a `PetscObject` is of a given base type. For example the base type of `MATSEQAIJPERM` is `MATSEQAIJ` 2034099cc6bSBarry Smith 2044099cc6bSBarry Smith Not Collective 2054099cc6bSBarry Smith 2064099cc6bSBarry Smith Input Parameters: 207aec76313SJacob Faibussowitsch + obj - the matrix 2084099cc6bSBarry Smith - type_name - string containing a type name 2094099cc6bSBarry Smith 2104099cc6bSBarry Smith Output Parameter: 211b843b480SStefano Zampini . same - `PETSC_TRUE` if the object is of the same base type identified by `type_name` or both `NULL`, `PETSC_FALSE` otherwise 2124099cc6bSBarry Smith 2134099cc6bSBarry Smith Level: intermediate 2144099cc6bSBarry Smith 215811af0c4SBarry Smith .seealso: `PetscObject`, `PetscObjectTypeCompare()`, `PetscObjectTypeCompareAny()`, `PetscObjectBaseTypeCompareAny()` 2164099cc6bSBarry Smith @*/ 217d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscObjectBaseTypeCompare(PetscObject obj, const char type_name[], PetscBool *same) 218d71ae5a4SJacob Faibussowitsch { 2194099cc6bSBarry Smith PetscFunctionBegin; 2204f572ea9SToby Isaac PetscAssertPointer(same, 3); 221b843b480SStefano Zampini if (!obj) *same = (PetscBool)!type_name; 2224099cc6bSBarry Smith else { 2234099cc6bSBarry Smith PetscValidHeader(obj, 1); 224b843b480SStefano Zampini if (!type_name || !obj->type_name) *same = (PetscBool)(!obj->type_name == !type_name); 225b843b480SStefano Zampini else { 2264f572ea9SToby Isaac PetscAssertPointer(type_name, 2); 227b843b480SStefano Zampini PetscCall(PetscStrbeginswith(obj->type_name, type_name, same)); 228b843b480SStefano Zampini } 2294099cc6bSBarry Smith } 2303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2314099cc6bSBarry Smith } 2324099cc6bSBarry Smith 2334099cc6bSBarry Smith /*@C 234251f4c67SDmitry Karpeev PetscObjectTypeCompareAny - Determines whether a PETSc object is of any of a list of types. 2352b12f010SJed Brown 2362b12f010SJed Brown Not Collective 2372b12f010SJed Brown 2382b12f010SJed Brown Input Parameters: 239811af0c4SBarry Smith + obj - any PETSc object, for example a `Vec`, `Mat` or `KSP`. 2401a9a975bSPierre Jolivet This must be cast with a (`PetscObject`), for example, `PetscObjectTypeCompareAny`((`PetscObject`)mat,...); 241811af0c4SBarry Smith - type_name - array of strings containing type names, pass the empty string "" to terminate the list 2422b12f010SJed Brown 2432b12f010SJed Brown Output Parameter: 24421532e8aSBarry Smith . match - `PETSC_TRUE` if the type of `obj` matches any in the list, else `PETSC_FALSE` 2452b12f010SJed Brown 2462b12f010SJed Brown Level: intermediate 2472b12f010SJed Brown 248dee2f2dbSPierre Jolivet .seealso: `VecGetType()`, `KSPGetType()`, `PCGetType()`, `SNESGetType()`, `PetscObjectTypeCompare()`, `PetscObjectBaseTypeCompare()` 2492b12f010SJed Brown @*/ 250d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscObjectTypeCompareAny(PetscObject obj, PetscBool *match, const char type_name[], ...) 251d71ae5a4SJacob Faibussowitsch { 2522b12f010SJed Brown va_list Argp; 2532b12f010SJed Brown 2542b12f010SJed Brown PetscFunctionBegin; 2554f572ea9SToby Isaac PetscAssertPointer(match, 2); 2562b12f010SJed Brown *match = PETSC_FALSE; 2573ba16761SJacob Faibussowitsch if (!obj) PetscFunctionReturn(PETSC_SUCCESS); 2582b12f010SJed Brown va_start(Argp, type_name); 2592b12f010SJed Brown while (type_name && type_name[0]) { 2602b12f010SJed Brown PetscBool found; 2619566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare(obj, type_name, &found)); 2622b12f010SJed Brown if (found) { 2632b12f010SJed Brown *match = PETSC_TRUE; 2642b12f010SJed Brown break; 2652b12f010SJed Brown } 2662b12f010SJed Brown type_name = va_arg(Argp, const char *); 2672b12f010SJed Brown } 2682b12f010SJed Brown va_end(Argp); 2693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2702b12f010SJed Brown } 2712b12f010SJed Brown 272b9e7e5c1SBarry Smith /*@C 273b9e7e5c1SBarry Smith PetscObjectBaseTypeCompareAny - Determines whether a PETSc object has the base type of any of a list of types. 274b9e7e5c1SBarry Smith 275b9e7e5c1SBarry Smith Not Collective 276b9e7e5c1SBarry Smith 277b9e7e5c1SBarry Smith Input Parameters: 278811af0c4SBarry Smith + obj - any PETSc object, for example a `Vec`, `Mat` or `KSP`. 279811af0c4SBarry Smith This must be cast with a (`PetscObject`), for example, `PetscObjectBaseTypeCompareAny`((`PetscObject`)mat,...); 280811af0c4SBarry Smith - type_name - array of strings containing type names, pass the empty string "" to terminate the list 281b9e7e5c1SBarry Smith 282b9e7e5c1SBarry Smith Output Parameter: 28321532e8aSBarry Smith . match - `PETSC_TRUE` if the type of `obj` matches any in the list, else `PETSC_FALSE` 284b9e7e5c1SBarry Smith 285b9e7e5c1SBarry Smith Level: intermediate 286b9e7e5c1SBarry Smith 287db781477SPatrick Sanan .seealso: `VecGetType()`, `KSPGetType()`, `PCGetType()`, `SNESGetType()`, `PetscObjectTypeCompare()`, `PetscObjectBaseTypeCompare()`, `PetscObjectTypeCompareAny()` 288b9e7e5c1SBarry Smith @*/ 289d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscObjectBaseTypeCompareAny(PetscObject obj, PetscBool *match, const char type_name[], ...) 290d71ae5a4SJacob Faibussowitsch { 291b9e7e5c1SBarry Smith va_list Argp; 292b9e7e5c1SBarry Smith 293b9e7e5c1SBarry Smith PetscFunctionBegin; 2944f572ea9SToby Isaac PetscAssertPointer(match, 2); 295b9e7e5c1SBarry Smith *match = PETSC_FALSE; 296b9e7e5c1SBarry Smith va_start(Argp, type_name); 297b9e7e5c1SBarry Smith while (type_name && type_name[0]) { 298b9e7e5c1SBarry Smith PetscBool found; 2999566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare(obj, type_name, &found)); 300b9e7e5c1SBarry Smith if (found) { 301b9e7e5c1SBarry Smith *match = PETSC_TRUE; 302b9e7e5c1SBarry Smith break; 303b9e7e5c1SBarry Smith } 304b9e7e5c1SBarry Smith type_name = va_arg(Argp, const char *); 305b9e7e5c1SBarry Smith } 306b9e7e5c1SBarry Smith va_end(Argp); 3073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 308b9e7e5c1SBarry Smith } 309b9e7e5c1SBarry Smith 3103048253cSJacob Faibussowitsch typedef struct { 3113048253cSJacob Faibussowitsch PetscErrorCode (*func)(void); 3123048253cSJacob Faibussowitsch } PetscFinalizeFunction; 3133048253cSJacob Faibussowitsch 3143048253cSJacob Faibussowitsch typedef struct { 3153048253cSJacob Faibussowitsch PetscErrorCode (*func)(void *); 3163048253cSJacob Faibussowitsch void *ctx; 3173048253cSJacob Faibussowitsch } PetscFinalizeFunctionWithCtx; 3183048253cSJacob Faibussowitsch 3193048253cSJacob Faibussowitsch typedef enum { 3203048253cSJacob Faibussowitsch PETSC_FINALIZE_EMPTY, 3213048253cSJacob Faibussowitsch PETSC_FINALIZE_OBJECT, 3223048253cSJacob Faibussowitsch PETSC_FINALIZE_FUNC, 3233048253cSJacob Faibussowitsch PETSC_FINALIZE_FUNC_WITH_CTX 3243048253cSJacob Faibussowitsch } PetscFinalizeType; 3253048253cSJacob Faibussowitsch 3263048253cSJacob Faibussowitsch static const char *const PetscFinalizeTypes[] = {"PETSC_FINALIZE_EMPTY", "PETSC_FINALIZE_OBJECT", "PETSC_FINALIZE_FUNC", "PETSC_FINALIZE_FUNC_WITH_CTX", PETSC_NULLPTR}; 3273048253cSJacob Faibussowitsch 3283048253cSJacob Faibussowitsch typedef struct { 3293048253cSJacob Faibussowitsch union ThunkUnion 3303048253cSJacob Faibussowitsch { 3313048253cSJacob Faibussowitsch PetscObject obj; 3323048253cSJacob Faibussowitsch PetscFinalizeFunction fn; 3333048253cSJacob Faibussowitsch PetscFinalizeFunctionWithCtx fnctx; 3343048253cSJacob Faibussowitsch } thunk; 3353048253cSJacob Faibussowitsch PetscFinalizeType type; 3363048253cSJacob Faibussowitsch } PetscFinalizerContainer; 3373048253cSJacob Faibussowitsch 3383048253cSJacob Faibussowitsch #define PETSC_MAX_REGISTERED_FINALIZERS 256 3393048253cSJacob Faibussowitsch static int reg_count = 0; 3403048253cSJacob Faibussowitsch static PetscFinalizerContainer regfin[PETSC_MAX_REGISTERED_FINALIZERS]; 3413048253cSJacob Faibussowitsch 3423048253cSJacob Faibussowitsch PetscErrorCode PetscRunRegisteredFinalizers(void) 3433048253cSJacob Faibussowitsch { 3443048253cSJacob Faibussowitsch PetscFunctionBegin; 3453048253cSJacob Faibussowitsch while (reg_count) { 3463048253cSJacob Faibussowitsch PetscFinalizerContainer top = regfin[--reg_count]; 3473048253cSJacob Faibussowitsch 3483048253cSJacob Faibussowitsch regfin[reg_count].type = PETSC_FINALIZE_EMPTY; 3493048253cSJacob Faibussowitsch PetscCall(PetscArrayzero(®fin[reg_count].thunk, 1)); 3503048253cSJacob Faibussowitsch switch (top.type) { 3513048253cSJacob Faibussowitsch case PETSC_FINALIZE_OBJECT: 352*34fa283eSBarry Smith top.thunk.obj->persistent = PETSC_FALSE; 3533048253cSJacob Faibussowitsch PetscCall(PetscObjectDestroy(&top.thunk.obj)); 3543048253cSJacob Faibussowitsch break; 3553048253cSJacob Faibussowitsch case PETSC_FINALIZE_FUNC: 3563048253cSJacob Faibussowitsch PetscCall((*top.thunk.fn.func)()); 3573048253cSJacob Faibussowitsch break; 3583048253cSJacob Faibussowitsch case PETSC_FINALIZE_FUNC_WITH_CTX: 3593048253cSJacob Faibussowitsch PetscCall((*top.thunk.fnctx.func)(top.thunk.fnctx.ctx)); 3603048253cSJacob Faibussowitsch break; 3613048253cSJacob Faibussowitsch case PETSC_FINALIZE_EMPTY: 3623048253cSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Finalizer at position %d is empty, yet registration count %d != 0", reg_count, reg_count); 3633048253cSJacob Faibussowitsch break; 3643048253cSJacob Faibussowitsch } 3653048253cSJacob Faibussowitsch } 3663048253cSJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3673048253cSJacob Faibussowitsch } 3683048253cSJacob Faibussowitsch 3693048253cSJacob Faibussowitsch static int PetscFinalizerContainerEqual(const PetscFinalizerContainer *a, const PetscFinalizerContainer *b) 3703048253cSJacob Faibussowitsch { 3713048253cSJacob Faibussowitsch if (a->type != b->type) return 0; 3723048253cSJacob Faibussowitsch switch (a->type) { 3733048253cSJacob Faibussowitsch case PETSC_FINALIZE_EMPTY: 3743048253cSJacob Faibussowitsch break; 3753048253cSJacob Faibussowitsch case PETSC_FINALIZE_OBJECT: 3763048253cSJacob Faibussowitsch return a->thunk.obj == b->thunk.obj; 3773048253cSJacob Faibussowitsch case PETSC_FINALIZE_FUNC: 3783048253cSJacob Faibussowitsch return a->thunk.fn.func == b->thunk.fn.func; 3793048253cSJacob Faibussowitsch case PETSC_FINALIZE_FUNC_WITH_CTX: 3803048253cSJacob Faibussowitsch return a->thunk.fnctx.func == b->thunk.fnctx.func && a->thunk.fnctx.ctx == b->thunk.fnctx.ctx; 3813048253cSJacob Faibussowitsch } 3823048253cSJacob Faibussowitsch return 1; 3833048253cSJacob Faibussowitsch } 3843048253cSJacob Faibussowitsch 3853048253cSJacob Faibussowitsch static PetscErrorCode RegisterFinalizer(PetscFinalizerContainer container) 3863048253cSJacob Faibussowitsch { 3873048253cSJacob Faibussowitsch PetscFunctionBegin; 3883048253cSJacob 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__); 3893048253cSJacob 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); 3903048253cSJacob Faibussowitsch if (PetscDefined(USE_DEBUG)) { 3913048253cSJacob 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]); 3923048253cSJacob Faibussowitsch } 3933048253cSJacob Faibussowitsch regfin[reg_count++] = container; 3943048253cSJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3953048253cSJacob Faibussowitsch } 396e5c89e4eSSatish Balay 397e5c89e4eSSatish Balay /*@C 398e5c89e4eSSatish Balay PetscObjectRegisterDestroy - Registers a PETSc object to be destroyed when 399811af0c4SBarry Smith `PetscFinalize()` is called. 400e5c89e4eSSatish Balay 401c3339decSBarry Smith Logically Collective 402e5c89e4eSSatish Balay 403e5c89e4eSSatish Balay Input Parameter: 404811af0c4SBarry Smith . obj - any PETSc object, for example a `Vec`, `Mat` or `KSP`. 405811af0c4SBarry Smith This must be cast with a (`PetscObject`), for example, 406811af0c4SBarry Smith `PetscObjectRegisterDestroy`((`PetscObject`)mat); 407e5c89e4eSSatish Balay 408e5c89e4eSSatish Balay Level: developer 409e5c89e4eSSatish Balay 410811af0c4SBarry Smith Note: 41121532e8aSBarry Smith This is used by, for example, `PETSC_VIEWER_XXX_()` routines to free the viewer 412e5c89e4eSSatish Balay when PETSc ends. 413e5c89e4eSSatish Balay 414db781477SPatrick Sanan .seealso: `PetscObjectRegisterDestroyAll()` 415e5c89e4eSSatish Balay @*/ 416d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscObjectRegisterDestroy(PetscObject obj) 417d71ae5a4SJacob Faibussowitsch { 4183048253cSJacob Faibussowitsch PetscFinalizerContainer container; 4193048253cSJacob Faibussowitsch 420e5c89e4eSSatish Balay PetscFunctionBegin; 421e5c89e4eSSatish Balay PetscValidHeader(obj, 1); 4223048253cSJacob Faibussowitsch container.thunk.obj = obj; 4233048253cSJacob Faibussowitsch container.type = PETSC_FINALIZE_OBJECT; 4243048253cSJacob Faibussowitsch PetscCall(RegisterFinalizer(container)); 4253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 426e5c89e4eSSatish Balay } 427e5c89e4eSSatish Balay 428e5c89e4eSSatish Balay /*@C 429e5c89e4eSSatish Balay PetscObjectRegisterDestroyAll - Frees all the PETSc objects that have been registered 430811af0c4SBarry Smith with `PetscObjectRegisterDestroy()`. Called by `PetscFinalize()` 431e5c89e4eSSatish Balay 432811af0c4SBarry Smith Logically Collective on the individual `PetscObject`s that are being processed 433e5c89e4eSSatish Balay 434e5c89e4eSSatish Balay Level: developer 435e5c89e4eSSatish Balay 436db781477SPatrick Sanan .seealso: `PetscObjectRegisterDestroy()` 437e5c89e4eSSatish Balay @*/ 438d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscObjectRegisterDestroyAll(void) 439d71ae5a4SJacob Faibussowitsch { 440e5c89e4eSSatish Balay PetscFunctionBegin; 4413048253cSJacob Faibussowitsch PetscCall(PetscRunRegisteredFinalizers()); 4423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 443e5c89e4eSSatish Balay } 444e5c89e4eSSatish Balay 445eb8be38cSBarry Smith /*@C 446811af0c4SBarry Smith PetscRegisterFinalize - Registers a function that is to be called in `PetscFinalize()` 447eb8be38cSBarry Smith 448eb8be38cSBarry Smith Not Collective 449eb8be38cSBarry Smith 450eb8be38cSBarry Smith Input Parameter: 451aec76313SJacob Faibussowitsch . f - function to be called 452eb8be38cSBarry Smith 453eb8be38cSBarry Smith Level: developer 454eb8be38cSBarry Smith 45521532e8aSBarry Smith Notes: 456811af0c4SBarry Smith This is used by, for example, `DMInitializePackage()` to have `DMFinalizePackage()` called 457eb8be38cSBarry Smith 45821532e8aSBarry Smith Use `PetscObjectRegisterDestroy()` to register the destruction of an object in `PetscFinalize()` 45921532e8aSBarry Smith 46021532e8aSBarry Smith .seealso: `PetscRegisterFinalizeAll()`, `PetscObjectRegisterDestroy()` 461eb8be38cSBarry Smith @*/ 462d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscRegisterFinalize(PetscErrorCode (*f)(void)) 463d71ae5a4SJacob Faibussowitsch { 4643048253cSJacob Faibussowitsch PetscFinalizerContainer container; 4653048253cSJacob Faibussowitsch 466f4aac215SBarry Smith PetscFunctionBegin; 4673048253cSJacob Faibussowitsch PetscValidFunction(f, 1); 4683048253cSJacob Faibussowitsch container.thunk.fn.func = f; 4693048253cSJacob Faibussowitsch container.type = PETSC_FINALIZE_FUNC; 4703048253cSJacob Faibussowitsch PetscCall(RegisterFinalizer(container)); 4713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 472eb8be38cSBarry Smith } 473eb8be38cSBarry Smith 474eb8be38cSBarry Smith /*@C 475811af0c4SBarry Smith PetscRegisterFinalizeAll - Runs all the finalize functions set with `PetscRegisterFinalize()` 476eb8be38cSBarry Smith 477eb8be38cSBarry Smith Not Collective unless registered functions are collective 478eb8be38cSBarry Smith 479eb8be38cSBarry Smith Level: developer 480eb8be38cSBarry Smith 48121532e8aSBarry Smith .seealso: `PetscRegisterFinalize()`, `PetscObjectRegisterDestroyAll()` 482eb8be38cSBarry Smith @*/ 483d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscRegisterFinalizeAll(void) 484d71ae5a4SJacob Faibussowitsch { 485eb8be38cSBarry Smith PetscFunctionBegin; 4863048253cSJacob Faibussowitsch PetscCall(PetscRunRegisteredFinalizers()); 4873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 488eb8be38cSBarry Smith } 489