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: 37811af0c4SBarry Smith . obj - any PETSc object, for example a `Vec`, `Mat` or `KSP`. 38811af0c4SBarry Smith This must be cast with a (`PetscObject`*), for example, 39811af0c4SBarry Smith `PetscObjectDestroy`((`PetscObject`*)&mat); 40e5c89e4eSSatish Balay 41e5c89e4eSSatish Balay Level: beginner 42e5c89e4eSSatish Balay 43811af0c4SBarry Smith .seealso: `PetscObject` 44e5c89e4eSSatish Balay @*/ 45d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscObjectDestroy(PetscObject *obj) 46d71ae5a4SJacob Faibussowitsch { 47e5c89e4eSSatish Balay PetscFunctionBegin; 483ba16761SJacob Faibussowitsch if (!obj || !*obj) PetscFunctionReturn(PETSC_SUCCESS); 496bf464f9SBarry Smith PetscValidHeader(*obj, 1); 505f80ce2aSJacob 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); 519566063dSJacob Faibussowitsch PetscCall((*(*obj)->bops->destroy)(obj)); 523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 53e5c89e4eSSatish Balay } 54e5c89e4eSSatish Balay 55e5c89e4eSSatish Balay /*@C 568ea61f2eSBarry Smith PetscObjectView - Views a `PetscObject`, regardless of the type. 57e5c89e4eSSatish Balay 58c3339decSBarry Smith Collective 59e5c89e4eSSatish Balay 60e5c89e4eSSatish Balay Input Parameters: 61811af0c4SBarry Smith + obj - any PETSc object, for example a `Vec`, `Mat` or `KSP`. 62811af0c4SBarry Smith This must be cast with a (`PetscObject`), for example, 63811af0c4SBarry Smith `PetscObjectView`((`PetscObject`)mat,viewer); 64e5c89e4eSSatish Balay - viewer - any PETSc viewer 65e5c89e4eSSatish Balay 66e5c89e4eSSatish Balay Level: intermediate 67e5c89e4eSSatish Balay 688ea61f2eSBarry Smith .seealso: `PetscObject`, `PetscObjectViewFromOptions()`, `PetscViewer` 69e5c89e4eSSatish Balay @*/ 70d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscObjectView(PetscObject obj, PetscViewer viewer) 71d71ae5a4SJacob Faibussowitsch { 72e5c89e4eSSatish Balay PetscFunctionBegin; 73e5c89e4eSSatish Balay PetscValidHeader(obj, 1); 745f80ce2aSJacob Faibussowitsch PetscCheck(obj->bops->view, PETSC_COMM_SELF, PETSC_ERR_SUP, "This PETSc object does not have a generic viewer routine"); 759566063dSJacob Faibussowitsch if (!viewer) PetscCall(PetscViewerASCIIGetStdout(obj->comm, &viewer)); 760700a824SBarry Smith PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 77e5c89e4eSSatish Balay 789566063dSJacob Faibussowitsch PetscCall((*obj->bops->view)(obj, viewer)); 793ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 80e5c89e4eSSatish Balay } 81e5c89e4eSSatish Balay 822d747510SLisandro Dalcin /*@C 83811af0c4SBarry Smith PetscObjectViewFromOptions - Processes command line options to determine if/how a `PetscObject` is to be viewed. 842d747510SLisandro Dalcin 85c3339decSBarry Smith Collective 862d747510SLisandro Dalcin 872d747510SLisandro Dalcin Input Parameters: 882d747510SLisandro Dalcin + obj - the object 8921532e8aSBarry Smith . bobj - optional other object that provides prefix (if `NULL` then the prefix in `obj` is used) 90bb7acecfSBarry Smith - optionname - option string that is used to activate viewing 912d747510SLisandro Dalcin 9211a5261eSBarry Smith Options Database Key: 9321532e8aSBarry Smith . -optionname_view [viewertype]:... - option name and values. In actual usage this would be something like `-mat_coarse_view` 9421532e8aSBarry Smith 9521532e8aSBarry Smith Level: developer 962d747510SLisandro Dalcin 9711a5261eSBarry Smith Notes: 9811a5261eSBarry Smith .vb 9911a5261eSBarry Smith If no value is provided ascii:stdout is used 10011a5261eSBarry Smith ascii[:[filename][:[format][:append]]] defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab, 10111a5261eSBarry Smith for example ascii::ascii_info prints just the information about the object not all details 10211a5261eSBarry Smith unless :append is given filename opens in write mode, overwriting what was already there 10311a5261eSBarry Smith binary[:[filename][:[format][:append]]] defaults to the file binaryoutput 10411a5261eSBarry Smith draw[:drawtype[:filename]] for example, draw:tikz, draw:tikz:figure.tex or draw:x 10511a5261eSBarry Smith socket[:port] defaults to the standard output port 10611a5261eSBarry Smith saws[:communicatorname] publishes object to the Scientific Application Webserver (SAWs) 10711a5261eSBarry Smith .ve 10811a5261eSBarry Smith 10921532e8aSBarry Smith This is not called directly but is called by, for example, `MatViewFromOptions()` 11011a5261eSBarry Smith 11111a5261eSBarry Smith .seealso: `PetscObject`, `PetscObjectView()`, `PetscOptionsGetViewer()` 1122d747510SLisandro Dalcin @*/ 113d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscObjectViewFromOptions(PetscObject obj, PetscObject bobj, const char optionname[]) 114d71ae5a4SJacob Faibussowitsch { 1152d747510SLisandro Dalcin PetscViewer viewer; 1162d747510SLisandro Dalcin PetscBool flg; 1172d747510SLisandro Dalcin static PetscBool incall = PETSC_FALSE; 1182d747510SLisandro Dalcin PetscViewerFormat format; 1192d747510SLisandro Dalcin const char *prefix; 1202d747510SLisandro Dalcin 1212d747510SLisandro Dalcin PetscFunctionBegin; 122b843b480SStefano Zampini PetscValidHeader(obj, 1); 123b843b480SStefano Zampini if (bobj) PetscValidHeader(bobj, 2); 1243ba16761SJacob Faibussowitsch if (incall) PetscFunctionReturn(PETSC_SUCCESS); 1252d747510SLisandro Dalcin incall = PETSC_TRUE; 1262d747510SLisandro Dalcin prefix = bobj ? bobj->prefix : obj->prefix; 1279566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)obj), obj->options, prefix, optionname, &viewer, &format, &flg)); 1282d747510SLisandro Dalcin if (flg) { 1299566063dSJacob Faibussowitsch PetscCall(PetscViewerPushFormat(viewer, format)); 1309566063dSJacob Faibussowitsch PetscCall(PetscObjectView(obj, viewer)); 1319566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 1329566063dSJacob Faibussowitsch PetscCall(PetscViewerPopFormat(viewer)); 133*cd791dc2SBarry Smith PetscCall(PetscOptionsRestoreViewer(&viewer)); 1342d747510SLisandro Dalcin } 1352d747510SLisandro Dalcin incall = PETSC_FALSE; 1363ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1372d747510SLisandro Dalcin } 1382d747510SLisandro Dalcin 139e5c89e4eSSatish Balay /*@C 140251f4c67SDmitry Karpeev PetscObjectTypeCompare - Determines whether a PETSc object is of a particular type. 141e5c89e4eSSatish Balay 142e5c89e4eSSatish Balay Not Collective 143e5c89e4eSSatish Balay 144e5c89e4eSSatish Balay Input Parameters: 1458ea61f2eSBarry Smith + obj - a PETSc object, for example a `Vec`, `Mat` or `KSP`. 146811af0c4SBarry Smith This must be cast with a (`PetscObject`), for example, 147811af0c4SBarry Smith `PetscObjectTypeCompare`((`PetscObject`)mat); 148e5c89e4eSSatish Balay - type_name - string containing a type name 149e5c89e4eSSatish Balay 150e5c89e4eSSatish Balay Output Parameter: 151b843b480SStefano Zampini . same - `PETSC_TRUE` if the type of `obj` and `type_name` are the same or both `NULL`, else `PETSC_FALSE` 152e5c89e4eSSatish Balay 153e5c89e4eSSatish Balay Level: intermediate 154e5c89e4eSSatish Balay 155013e2dc7SBarry Smith .seealso: `PetscObject`, `VecGetType()`, `KSPGetType()`, `PCGetType()`, `SNESGetType()`, `PetscObjectBaseTypeCompare()`, `PetscObjectTypeCompareAny()`, `PetscObjectBaseTypeCompareAny()`, `PetscObjectObjectTypeCompare()` 156e5c89e4eSSatish Balay @*/ 157d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscObjectTypeCompare(PetscObject obj, const char type_name[], PetscBool *same) 158d71ae5a4SJacob Faibussowitsch { 159e5c89e4eSSatish Balay PetscFunctionBegin; 1604f572ea9SToby Isaac PetscAssertPointer(same, 3); 161b843b480SStefano Zampini if (!obj) *same = (PetscBool)!type_name; 162a297a907SKarl Rupp else { 163e5c89e4eSSatish Balay PetscValidHeader(obj, 1); 164b843b480SStefano Zampini if (!type_name || !obj->type_name) *same = (PetscBool)(!obj->type_name == !type_name); 165b843b480SStefano Zampini else { 1664f572ea9SToby Isaac PetscAssertPointer(type_name, 2); 167b843b480SStefano Zampini PetscCall(PetscStrcmp(obj->type_name, type_name, same)); 168b843b480SStefano Zampini } 169e5c89e4eSSatish Balay } 1703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 171e5c89e4eSSatish Balay } 172e5c89e4eSSatish Balay 1732b12f010SJed Brown /*@C 174013e2dc7SBarry Smith PetscObjectObjectTypeCompare - Determines whether two PETSc objects are of the same type 175013e2dc7SBarry Smith 176013e2dc7SBarry Smith Logically Collective 177013e2dc7SBarry Smith 178013e2dc7SBarry Smith Input Parameters: 17921532e8aSBarry Smith + obj1 - any PETSc object, for example a `Vec`, `Mat` or `KSP`. 180da81f932SPierre Jolivet - obj2 - another PETSc object 181013e2dc7SBarry Smith 182013e2dc7SBarry Smith Output Parameter: 183b843b480SStefano Zampini . same - `PETSC_TRUE` if they are the same or both unset, else `PETSC_FALSE` 184013e2dc7SBarry Smith 185013e2dc7SBarry Smith Level: intermediate 186013e2dc7SBarry Smith 187013e2dc7SBarry Smith .seealso: `PetscObjectTypeCompare()`, `VecGetType()`, `KSPGetType()`, `PCGetType()`, `SNESGetType()`, `PetscObjectBaseTypeCompare()`, `PetscObjectTypeCompareAny()`, `PetscObjectBaseTypeCompareAny()` 188013e2dc7SBarry Smith 189013e2dc7SBarry Smith @*/ 190d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscObjectObjectTypeCompare(PetscObject obj1, PetscObject obj2, PetscBool *same) 191d71ae5a4SJacob Faibussowitsch { 192013e2dc7SBarry Smith PetscFunctionBegin; 193013e2dc7SBarry Smith PetscValidHeader(obj1, 1); 194013e2dc7SBarry Smith PetscValidHeader(obj2, 2); 1954f572ea9SToby Isaac PetscAssertPointer(same, 3); 196b843b480SStefano Zampini PetscCall(PetscStrcmp(obj1->type_name, obj2->type_name, same)); 1973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 198013e2dc7SBarry Smith } 199013e2dc7SBarry Smith 200013e2dc7SBarry Smith /*@C 201811af0c4SBarry Smith PetscObjectBaseTypeCompare - Determines whether a `PetscObject` is of a given base type. For example the base type of `MATSEQAIJPERM` is `MATSEQAIJ` 2024099cc6bSBarry Smith 2034099cc6bSBarry Smith Not Collective 2044099cc6bSBarry Smith 2054099cc6bSBarry Smith Input Parameters: 206aec76313SJacob Faibussowitsch + obj - the matrix 2074099cc6bSBarry Smith - type_name - string containing a type name 2084099cc6bSBarry Smith 2094099cc6bSBarry Smith Output Parameter: 210b843b480SStefano Zampini . same - `PETSC_TRUE` if the object is of the same base type identified by `type_name` or both `NULL`, `PETSC_FALSE` otherwise 2114099cc6bSBarry Smith 2124099cc6bSBarry Smith Level: intermediate 2134099cc6bSBarry Smith 214811af0c4SBarry Smith .seealso: `PetscObject`, `PetscObjectTypeCompare()`, `PetscObjectTypeCompareAny()`, `PetscObjectBaseTypeCompareAny()` 2154099cc6bSBarry Smith @*/ 216d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscObjectBaseTypeCompare(PetscObject obj, const char type_name[], PetscBool *same) 217d71ae5a4SJacob Faibussowitsch { 2184099cc6bSBarry Smith PetscFunctionBegin; 2194f572ea9SToby Isaac PetscAssertPointer(same, 3); 220b843b480SStefano Zampini if (!obj) *same = (PetscBool)!type_name; 2214099cc6bSBarry Smith else { 2224099cc6bSBarry Smith PetscValidHeader(obj, 1); 223b843b480SStefano Zampini if (!type_name || !obj->type_name) *same = (PetscBool)(!obj->type_name == !type_name); 224b843b480SStefano Zampini else { 2254f572ea9SToby Isaac PetscAssertPointer(type_name, 2); 226b843b480SStefano Zampini PetscCall(PetscStrbeginswith(obj->type_name, type_name, same)); 227b843b480SStefano Zampini } 2284099cc6bSBarry Smith } 2293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2304099cc6bSBarry Smith } 2314099cc6bSBarry Smith 2324099cc6bSBarry Smith /*@C 233251f4c67SDmitry Karpeev PetscObjectTypeCompareAny - Determines whether a PETSc object is of any of a list of types. 2342b12f010SJed Brown 2352b12f010SJed Brown Not Collective 2362b12f010SJed Brown 2372b12f010SJed Brown Input Parameters: 2388ea61f2eSBarry Smith + obj - a PETSc object, for example a `Vec`, `Mat` or `KSP`. 2391a9a975bSPierre Jolivet This must be cast with a (`PetscObject`), for example, `PetscObjectTypeCompareAny`((`PetscObject`)mat,...); 240811af0c4SBarry Smith - type_name - array of strings containing type names, pass the empty string "" to terminate the list 2412b12f010SJed Brown 2422b12f010SJed Brown Output Parameter: 24321532e8aSBarry Smith . match - `PETSC_TRUE` if the type of `obj` matches any in the list, else `PETSC_FALSE` 2442b12f010SJed Brown 2452b12f010SJed Brown Level: intermediate 2462b12f010SJed Brown 247dee2f2dbSPierre Jolivet .seealso: `VecGetType()`, `KSPGetType()`, `PCGetType()`, `SNESGetType()`, `PetscObjectTypeCompare()`, `PetscObjectBaseTypeCompare()` 2482b12f010SJed Brown @*/ 249d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscObjectTypeCompareAny(PetscObject obj, PetscBool *match, const char type_name[], ...) 250d71ae5a4SJacob Faibussowitsch { 2512b12f010SJed Brown va_list Argp; 2522b12f010SJed Brown 2532b12f010SJed Brown PetscFunctionBegin; 2544f572ea9SToby Isaac PetscAssertPointer(match, 2); 2552b12f010SJed Brown *match = PETSC_FALSE; 2563ba16761SJacob Faibussowitsch if (!obj) PetscFunctionReturn(PETSC_SUCCESS); 2572b12f010SJed Brown va_start(Argp, type_name); 2582b12f010SJed Brown while (type_name && type_name[0]) { 2592b12f010SJed Brown PetscBool found; 2609566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare(obj, type_name, &found)); 2612b12f010SJed Brown if (found) { 2622b12f010SJed Brown *match = PETSC_TRUE; 2632b12f010SJed Brown break; 2642b12f010SJed Brown } 2652b12f010SJed Brown type_name = va_arg(Argp, const char *); 2662b12f010SJed Brown } 2672b12f010SJed Brown va_end(Argp); 2683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2692b12f010SJed Brown } 2702b12f010SJed Brown 271b9e7e5c1SBarry Smith /*@C 272b9e7e5c1SBarry Smith PetscObjectBaseTypeCompareAny - Determines whether a PETSc object has the base type of any of a list of types. 273b9e7e5c1SBarry Smith 274b9e7e5c1SBarry Smith Not Collective 275b9e7e5c1SBarry Smith 276b9e7e5c1SBarry Smith Input Parameters: 2778ea61f2eSBarry Smith + obj - a PETSc object, for example a `Vec`, `Mat` or `KSP`. 278811af0c4SBarry Smith This must be cast with a (`PetscObject`), for example, `PetscObjectBaseTypeCompareAny`((`PetscObject`)mat,...); 279811af0c4SBarry Smith - type_name - array of strings containing type names, pass the empty string "" to terminate the list 280b9e7e5c1SBarry Smith 281b9e7e5c1SBarry Smith Output Parameter: 28221532e8aSBarry Smith . match - `PETSC_TRUE` if the type of `obj` matches any in the list, else `PETSC_FALSE` 283b9e7e5c1SBarry Smith 284b9e7e5c1SBarry Smith Level: intermediate 285b9e7e5c1SBarry Smith 286db781477SPatrick Sanan .seealso: `VecGetType()`, `KSPGetType()`, `PCGetType()`, `SNESGetType()`, `PetscObjectTypeCompare()`, `PetscObjectBaseTypeCompare()`, `PetscObjectTypeCompareAny()` 287b9e7e5c1SBarry Smith @*/ 288d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscObjectBaseTypeCompareAny(PetscObject obj, PetscBool *match, const char type_name[], ...) 289d71ae5a4SJacob Faibussowitsch { 290b9e7e5c1SBarry Smith va_list Argp; 291b9e7e5c1SBarry Smith 292b9e7e5c1SBarry Smith PetscFunctionBegin; 2934f572ea9SToby Isaac PetscAssertPointer(match, 2); 294b9e7e5c1SBarry Smith *match = PETSC_FALSE; 295b9e7e5c1SBarry Smith va_start(Argp, type_name); 296b9e7e5c1SBarry Smith while (type_name && type_name[0]) { 297b9e7e5c1SBarry Smith PetscBool found; 2989566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare(obj, type_name, &found)); 299b9e7e5c1SBarry Smith if (found) { 300b9e7e5c1SBarry Smith *match = PETSC_TRUE; 301b9e7e5c1SBarry Smith break; 302b9e7e5c1SBarry Smith } 303b9e7e5c1SBarry Smith type_name = va_arg(Argp, const char *); 304b9e7e5c1SBarry Smith } 305b9e7e5c1SBarry Smith va_end(Argp); 3063ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 307b9e7e5c1SBarry Smith } 308b9e7e5c1SBarry Smith 3093048253cSJacob Faibussowitsch typedef struct { 3103048253cSJacob Faibussowitsch PetscErrorCode (*func)(void); 3113048253cSJacob Faibussowitsch } PetscFinalizeFunction; 3123048253cSJacob Faibussowitsch 3133048253cSJacob Faibussowitsch typedef struct { 3143048253cSJacob Faibussowitsch PetscErrorCode (*func)(void *); 3153048253cSJacob Faibussowitsch void *ctx; 3163048253cSJacob Faibussowitsch } PetscFinalizeFunctionWithCtx; 3173048253cSJacob Faibussowitsch 3183048253cSJacob Faibussowitsch typedef enum { 3193048253cSJacob Faibussowitsch PETSC_FINALIZE_EMPTY, 3203048253cSJacob Faibussowitsch PETSC_FINALIZE_OBJECT, 3213048253cSJacob Faibussowitsch PETSC_FINALIZE_FUNC, 3223048253cSJacob Faibussowitsch PETSC_FINALIZE_FUNC_WITH_CTX 3233048253cSJacob Faibussowitsch } PetscFinalizeType; 3243048253cSJacob Faibussowitsch 3253048253cSJacob Faibussowitsch static const char *const PetscFinalizeTypes[] = {"PETSC_FINALIZE_EMPTY", "PETSC_FINALIZE_OBJECT", "PETSC_FINALIZE_FUNC", "PETSC_FINALIZE_FUNC_WITH_CTX", PETSC_NULLPTR}; 3263048253cSJacob Faibussowitsch 3273048253cSJacob Faibussowitsch typedef struct { 3283048253cSJacob Faibussowitsch union ThunkUnion 3293048253cSJacob Faibussowitsch { 3303048253cSJacob Faibussowitsch PetscObject obj; 3313048253cSJacob Faibussowitsch PetscFinalizeFunction fn; 3323048253cSJacob Faibussowitsch PetscFinalizeFunctionWithCtx fnctx; 3333048253cSJacob Faibussowitsch } thunk; 3343048253cSJacob Faibussowitsch PetscFinalizeType type; 3353048253cSJacob Faibussowitsch } PetscFinalizerContainer; 3363048253cSJacob Faibussowitsch 3373048253cSJacob Faibussowitsch #define PETSC_MAX_REGISTERED_FINALIZERS 256 3383048253cSJacob Faibussowitsch static int reg_count = 0; 3393048253cSJacob Faibussowitsch static PetscFinalizerContainer regfin[PETSC_MAX_REGISTERED_FINALIZERS]; 3403048253cSJacob Faibussowitsch 34166976f2fSJacob Faibussowitsch static PetscErrorCode PetscRunRegisteredFinalizers(void) 3423048253cSJacob Faibussowitsch { 3433048253cSJacob Faibussowitsch PetscFunctionBegin; 3443048253cSJacob Faibussowitsch while (reg_count) { 3453048253cSJacob Faibussowitsch PetscFinalizerContainer top = regfin[--reg_count]; 3463048253cSJacob Faibussowitsch 3473048253cSJacob Faibussowitsch regfin[reg_count].type = PETSC_FINALIZE_EMPTY; 3483048253cSJacob Faibussowitsch PetscCall(PetscArrayzero(®fin[reg_count].thunk, 1)); 3493048253cSJacob Faibussowitsch switch (top.type) { 3503048253cSJacob Faibussowitsch case PETSC_FINALIZE_OBJECT: 35134fa283eSBarry Smith top.thunk.obj->persistent = PETSC_FALSE; 3523048253cSJacob Faibussowitsch PetscCall(PetscObjectDestroy(&top.thunk.obj)); 3533048253cSJacob Faibussowitsch break; 3543048253cSJacob Faibussowitsch case PETSC_FINALIZE_FUNC: 3553048253cSJacob Faibussowitsch PetscCall((*top.thunk.fn.func)()); 3563048253cSJacob Faibussowitsch break; 3573048253cSJacob Faibussowitsch case PETSC_FINALIZE_FUNC_WITH_CTX: 3583048253cSJacob Faibussowitsch PetscCall((*top.thunk.fnctx.func)(top.thunk.fnctx.ctx)); 3593048253cSJacob Faibussowitsch break; 3603048253cSJacob Faibussowitsch case PETSC_FINALIZE_EMPTY: 3613048253cSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Finalizer at position %d is empty, yet registration count %d != 0", reg_count, reg_count); 3623048253cSJacob Faibussowitsch break; 3633048253cSJacob Faibussowitsch } 3643048253cSJacob Faibussowitsch } 3653048253cSJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3663048253cSJacob Faibussowitsch } 3673048253cSJacob Faibussowitsch 3683048253cSJacob Faibussowitsch static int PetscFinalizerContainerEqual(const PetscFinalizerContainer *a, const PetscFinalizerContainer *b) 3693048253cSJacob Faibussowitsch { 3703048253cSJacob Faibussowitsch if (a->type != b->type) return 0; 3713048253cSJacob Faibussowitsch switch (a->type) { 3723048253cSJacob Faibussowitsch case PETSC_FINALIZE_EMPTY: 3733048253cSJacob Faibussowitsch break; 3743048253cSJacob Faibussowitsch case PETSC_FINALIZE_OBJECT: 3753048253cSJacob Faibussowitsch return a->thunk.obj == b->thunk.obj; 3763048253cSJacob Faibussowitsch case PETSC_FINALIZE_FUNC: 3773048253cSJacob Faibussowitsch return a->thunk.fn.func == b->thunk.fn.func; 3783048253cSJacob Faibussowitsch case PETSC_FINALIZE_FUNC_WITH_CTX: 3793048253cSJacob Faibussowitsch return a->thunk.fnctx.func == b->thunk.fnctx.func && a->thunk.fnctx.ctx == b->thunk.fnctx.ctx; 3803048253cSJacob Faibussowitsch } 3813048253cSJacob Faibussowitsch return 1; 3823048253cSJacob Faibussowitsch } 3833048253cSJacob Faibussowitsch 3843048253cSJacob Faibussowitsch static PetscErrorCode RegisterFinalizer(PetscFinalizerContainer container) 3853048253cSJacob Faibussowitsch { 3863048253cSJacob Faibussowitsch PetscFunctionBegin; 3873048253cSJacob 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__); 3883048253cSJacob 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); 3893048253cSJacob Faibussowitsch if (PetscDefined(USE_DEBUG)) { 3903048253cSJacob 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]); 3913048253cSJacob Faibussowitsch } 3923048253cSJacob Faibussowitsch regfin[reg_count++] = container; 3933048253cSJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3943048253cSJacob Faibussowitsch } 395e5c89e4eSSatish Balay 396e5c89e4eSSatish Balay /*@C 397e5c89e4eSSatish Balay PetscObjectRegisterDestroy - Registers a PETSc object to be destroyed when 398811af0c4SBarry Smith `PetscFinalize()` is called. 399e5c89e4eSSatish Balay 400c3339decSBarry Smith Logically Collective 401e5c89e4eSSatish Balay 402e5c89e4eSSatish Balay Input Parameter: 4038ea61f2eSBarry Smith . obj - a PETSc object, for example a `Vec`, `Mat` or `KSP`. 404811af0c4SBarry Smith This must be cast with a (`PetscObject`), for example, 405811af0c4SBarry Smith `PetscObjectRegisterDestroy`((`PetscObject`)mat); 406e5c89e4eSSatish Balay 407e5c89e4eSSatish Balay Level: developer 408e5c89e4eSSatish Balay 409811af0c4SBarry Smith Note: 41021532e8aSBarry Smith This is used by, for example, `PETSC_VIEWER_XXX_()` routines to free the viewer 411e5c89e4eSSatish Balay when PETSc ends. 412e5c89e4eSSatish Balay 413db781477SPatrick Sanan .seealso: `PetscObjectRegisterDestroyAll()` 414e5c89e4eSSatish Balay @*/ 415d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscObjectRegisterDestroy(PetscObject obj) 416d71ae5a4SJacob Faibussowitsch { 4173048253cSJacob Faibussowitsch PetscFinalizerContainer container; 4183048253cSJacob Faibussowitsch 419e5c89e4eSSatish Balay PetscFunctionBegin; 420e5c89e4eSSatish Balay PetscValidHeader(obj, 1); 4213048253cSJacob Faibussowitsch container.thunk.obj = obj; 4223048253cSJacob Faibussowitsch container.type = PETSC_FINALIZE_OBJECT; 4233048253cSJacob Faibussowitsch PetscCall(RegisterFinalizer(container)); 4243ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 425e5c89e4eSSatish Balay } 426e5c89e4eSSatish Balay 427e5c89e4eSSatish Balay /*@C 428e5c89e4eSSatish Balay PetscObjectRegisterDestroyAll - Frees all the PETSc objects that have been registered 429811af0c4SBarry Smith with `PetscObjectRegisterDestroy()`. Called by `PetscFinalize()` 430e5c89e4eSSatish Balay 431811af0c4SBarry Smith Logically Collective on the individual `PetscObject`s that are being processed 432e5c89e4eSSatish Balay 433e5c89e4eSSatish Balay Level: developer 434e5c89e4eSSatish Balay 435db781477SPatrick Sanan .seealso: `PetscObjectRegisterDestroy()` 436e5c89e4eSSatish Balay @*/ 437d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscObjectRegisterDestroyAll(void) 438d71ae5a4SJacob Faibussowitsch { 439e5c89e4eSSatish Balay PetscFunctionBegin; 4403048253cSJacob Faibussowitsch PetscCall(PetscRunRegisteredFinalizers()); 4413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 442e5c89e4eSSatish Balay } 443e5c89e4eSSatish Balay 444eb8be38cSBarry Smith /*@C 445811af0c4SBarry Smith PetscRegisterFinalize - Registers a function that is to be called in `PetscFinalize()` 446eb8be38cSBarry Smith 447eb8be38cSBarry Smith Not Collective 448eb8be38cSBarry Smith 449eb8be38cSBarry Smith Input Parameter: 450aec76313SJacob Faibussowitsch . f - function to be called 451eb8be38cSBarry Smith 452eb8be38cSBarry Smith Level: developer 453eb8be38cSBarry Smith 45421532e8aSBarry Smith Notes: 455811af0c4SBarry Smith This is used by, for example, `DMInitializePackage()` to have `DMFinalizePackage()` called 456eb8be38cSBarry Smith 45721532e8aSBarry Smith Use `PetscObjectRegisterDestroy()` to register the destruction of an object in `PetscFinalize()` 45821532e8aSBarry Smith 45921532e8aSBarry Smith .seealso: `PetscRegisterFinalizeAll()`, `PetscObjectRegisterDestroy()` 460eb8be38cSBarry Smith @*/ 461d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscRegisterFinalize(PetscErrorCode (*f)(void)) 462d71ae5a4SJacob Faibussowitsch { 4633048253cSJacob Faibussowitsch PetscFinalizerContainer container; 4643048253cSJacob Faibussowitsch 465f4aac215SBarry Smith PetscFunctionBegin; 4663048253cSJacob Faibussowitsch PetscValidFunction(f, 1); 4673048253cSJacob Faibussowitsch container.thunk.fn.func = f; 4683048253cSJacob Faibussowitsch container.type = PETSC_FINALIZE_FUNC; 4693048253cSJacob Faibussowitsch PetscCall(RegisterFinalizer(container)); 4703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 471eb8be38cSBarry Smith } 472eb8be38cSBarry Smith 473eb8be38cSBarry Smith /*@C 474811af0c4SBarry Smith PetscRegisterFinalizeAll - Runs all the finalize functions set with `PetscRegisterFinalize()` 475eb8be38cSBarry Smith 476eb8be38cSBarry Smith Not Collective unless registered functions are collective 477eb8be38cSBarry Smith 478eb8be38cSBarry Smith Level: developer 479eb8be38cSBarry Smith 48021532e8aSBarry Smith .seealso: `PetscRegisterFinalize()`, `PetscObjectRegisterDestroyAll()` 481eb8be38cSBarry Smith @*/ 482d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscRegisterFinalizeAll(void) 483d71ae5a4SJacob Faibussowitsch { 484eb8be38cSBarry Smith PetscFunctionBegin; 4853048253cSJacob Faibussowitsch PetscCall(PetscRunRegisteredFinalizers()); 4863ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 487eb8be38cSBarry Smith } 488