1e5c89e4eSSatish Balay /* 2e5c89e4eSSatish Balay Provides a general mechanism to allow one to register new routines in 3e5c89e4eSSatish Balay dynamic libraries for many of the PETSc objects (including, e.g., KSP and PC). 4e5c89e4eSSatish Balay */ 5af0996ceSBarry Smith #include <petsc/private/petscimpl.h> /*I "petscsys.h" I*/ 6665c2dedSJed Brown #include <petscviewer.h> 7e5c89e4eSSatish Balay 8ed170139SJacob Faibussowitsch #include <petsc/private/hashmap.h> 93fa76a5bSLisandro Dalcin /* 103fa76a5bSLisandro Dalcin This is the default list used by PETSc with the PetscDLLibrary register routines 113fa76a5bSLisandro Dalcin */ 1202c9f0b5SLisandro Dalcin PetscDLLibrary PetscDLLibrariesLoaded = NULL; 133fa76a5bSLisandro Dalcin 14cbd104e6SBarry Smith #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES) 15ebd79076SLisandro Dalcin 16d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLoadDynamicLibrary(const char *name, PetscBool *found) 17d71ae5a4SJacob Faibussowitsch { 18487e5849SBarry Smith char libs[PETSC_MAX_PATH_LEN], dlib[PETSC_MAX_PATH_LEN]; 19487e5849SBarry Smith 20487e5849SBarry Smith PetscFunctionBegin; 219566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(libs, "${PETSC_LIB_DIR}/libpetsc", sizeof(libs))); 229566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(libs, name, sizeof(libs))); 23859f1752SFrancesco Ballarin #if defined(PETSC_LIB_NAME_SUFFIX) 24859f1752SFrancesco Ballarin PetscCall(PetscStrlcat(libs, PETSC_LIB_NAME_SUFFIX, sizeof(libs))); 25859f1752SFrancesco Ballarin #endif 269566063dSJacob Faibussowitsch PetscCall(PetscDLLibraryRetrieve(PETSC_COMM_WORLD, libs, dlib, 1024, found)); 27487e5849SBarry Smith if (*found) { 289566063dSJacob Faibussowitsch PetscCall(PetscDLLibraryAppend(PETSC_COMM_WORLD, &PetscDLLibrariesLoaded, dlib)); 29487e5849SBarry Smith } else { 309566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(libs, "${PETSC_DIR}/${PETSC_ARCH}/lib/libpetsc", sizeof(libs))); 319566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(libs, name, sizeof(libs))); 32859f1752SFrancesco Ballarin #if defined(PETSC_LIB_NAME_SUFFIX) 33859f1752SFrancesco Ballarin PetscCall(PetscStrlcat(libs, PETSC_LIB_NAME_SUFFIX, sizeof(libs))); 34859f1752SFrancesco Ballarin #endif 359566063dSJacob Faibussowitsch PetscCall(PetscDLLibraryRetrieve(PETSC_COMM_WORLD, libs, dlib, 1024, found)); 3648a46eb9SPierre Jolivet if (*found) PetscCall(PetscDLLibraryAppend(PETSC_COMM_WORLD, &PetscDLLibrariesLoaded, dlib)); 37487e5849SBarry Smith } 383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 39487e5849SBarry Smith } 403fa76a5bSLisandro Dalcin #endif 413fa76a5bSLisandro Dalcin 4260da17ecSBarry Smith #if defined(PETSC_USE_SINGLE_LIBRARY) && !(defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES)) 4395c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode AOInitializePackage(void); 4495c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscSFInitializePackage(void); 457da51e29SSatish Balay #if !defined(PETSC_USE_COMPLEX) 4695c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode CharacteristicInitializePackage(void); 477da51e29SSatish Balay #endif 4895c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode ISInitializePackage(void); 4995c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode VecInitializePackage(void); 5095c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode MatInitializePackage(void); 5195c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode DMInitializePackage(void); 5295c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode PCInitializePackage(void); 5395c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode KSPInitializePackage(void); 5495c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode SNESInitializePackage(void); 5595c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode TSInitializePackage(void); 5660da17ecSBarry Smith PETSC_EXTERN PetscErrorCode TaoInitializePackage(void); 5760da17ecSBarry Smith #endif 58acff04ddSBarry Smith 59e5c89e4eSSatish Balay /* 60e5c89e4eSSatish Balay PetscInitialize_DynamicLibraries - Adds the default dynamic link libraries to the 61e5c89e4eSSatish Balay search path. 62e5c89e4eSSatish Balay */ 63d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode PetscInitialize_DynamicLibraries(void) 64d71ae5a4SJacob Faibussowitsch { 65487e5849SBarry Smith char *libname[32]; 66e5c89e4eSSatish Balay PetscInt nmax, i; 6760da17ecSBarry Smith PetscBool preload = PETSC_FALSE; 68540e20f2SPierre Jolivet #if defined(PETSC_HAVE_ELEMENTAL) 69540e20f2SPierre Jolivet PetscBool PetscInitialized = PetscInitializeCalled; 70540e20f2SPierre Jolivet #endif 71e5c89e4eSSatish Balay 7260154eb2SBarry Smith PetscFunctionBegin; 7360da17ecSBarry Smith #if defined(PETSC_HAVE_THREADSAFETY) 7460da17ecSBarry Smith /* These must be all initialized here because it is not safe for individual threads to call these initialize routines */ 7560da17ecSBarry Smith preload = PETSC_TRUE; 7660da17ecSBarry Smith #endif 7760da17ecSBarry Smith 78e5c89e4eSSatish Balay nmax = 32; 799566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetStringArray(NULL, NULL, "-dll_prepend", libname, &nmax, NULL)); 80e5c89e4eSSatish Balay for (i = 0; i < nmax; i++) { 819566063dSJacob Faibussowitsch PetscCall(PetscDLLibraryPrepend(PETSC_COMM_WORLD, &PetscDLLibrariesLoaded, libname[i])); 829566063dSJacob Faibussowitsch PetscCall(PetscFree(libname[i])); 83e5c89e4eSSatish Balay } 84e5c89e4eSSatish Balay 859566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-library_preload", &preload, NULL)); 8660da17ecSBarry Smith if (!preload) { 879566063dSJacob Faibussowitsch PetscCall(PetscSysInitializePackage()); 8860da17ecSBarry Smith } else { 8960da17ecSBarry Smith #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES) 90aa2d57e9SJed Brown PetscBool found; 9160154eb2SBarry Smith #if defined(PETSC_USE_SINGLE_LIBRARY) 929566063dSJacob Faibussowitsch PetscCall(PetscLoadDynamicLibrary("", &found)); 9300045ab3SPierre Jolivet PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc dynamic library. You cannot move the dynamic libraries!"); 9460154eb2SBarry Smith #else 959566063dSJacob Faibussowitsch PetscCall(PetscLoadDynamicLibrary("sys", &found)); 9600045ab3SPierre Jolivet PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc Sys dynamic library. You cannot move the dynamic libraries!"); 979566063dSJacob Faibussowitsch PetscCall(PetscLoadDynamicLibrary("vec", &found)); 9800045ab3SPierre Jolivet PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc Vec dynamic library. You cannot move the dynamic libraries!"); 999566063dSJacob Faibussowitsch PetscCall(PetscLoadDynamicLibrary("mat", &found)); 10000045ab3SPierre Jolivet PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc Mat dynamic library. You cannot move the dynamic libraries!"); 1019566063dSJacob Faibussowitsch PetscCall(PetscLoadDynamicLibrary("dm", &found)); 10200045ab3SPierre Jolivet PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc DM dynamic library. You cannot move the dynamic libraries!"); 1039566063dSJacob Faibussowitsch PetscCall(PetscLoadDynamicLibrary("ksp", &found)); 10400045ab3SPierre Jolivet PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc KSP dynamic library. You cannot move the dynamic libraries!"); 1059566063dSJacob Faibussowitsch PetscCall(PetscLoadDynamicLibrary("snes", &found)); 10600045ab3SPierre Jolivet PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc SNES dynamic library. You cannot move the dynamic libraries!"); 1079566063dSJacob Faibussowitsch PetscCall(PetscLoadDynamicLibrary("ts", &found)); 10800045ab3SPierre Jolivet PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc TS dynamic library. You cannot move the dynamic libraries!"); 1099566063dSJacob Faibussowitsch PetscCall(PetscLoadDynamicLibrary("tao", &found)); 11000045ab3SPierre Jolivet PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate Tao dynamic library. You cannot move the dynamic libraries!"); 111bb84e0fdSBarry Smith #endif 11260da17ecSBarry Smith #else /* defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES) */ 11360da17ecSBarry Smith #if defined(PETSC_USE_SINGLE_LIBRARY) 1149566063dSJacob Faibussowitsch PetscCall(AOInitializePackage()); 1159566063dSJacob Faibussowitsch PetscCall(PetscSFInitializePackage()); 1167da51e29SSatish Balay #if !defined(PETSC_USE_COMPLEX) 1179566063dSJacob Faibussowitsch PetscCall(CharacteristicInitializePackage()); 1187da51e29SSatish Balay #endif 1199566063dSJacob Faibussowitsch PetscCall(ISInitializePackage()); 1209566063dSJacob Faibussowitsch PetscCall(VecInitializePackage()); 1219566063dSJacob Faibussowitsch PetscCall(MatInitializePackage()); 1229566063dSJacob Faibussowitsch PetscCall(DMInitializePackage()); 1239566063dSJacob Faibussowitsch PetscCall(PCInitializePackage()); 1249566063dSJacob Faibussowitsch PetscCall(KSPInitializePackage()); 1259566063dSJacob Faibussowitsch PetscCall(SNESInitializePackage()); 1269566063dSJacob Faibussowitsch PetscCall(TSInitializePackage()); 1279566063dSJacob Faibussowitsch PetscCall(TaoInitializePackage()); 12860da17ecSBarry Smith #else 12960da17ecSBarry Smith SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP, "Cannot use -library_preload with multiple static PETSc libraries"); 13060da17ecSBarry Smith #endif 13160da17ecSBarry Smith #endif /* defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES) */ 13260da17ecSBarry Smith } 13360da17ecSBarry Smith 13460da17ecSBarry Smith #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES) && defined(PETSC_HAVE_BAMG) 13560da17ecSBarry Smith { 13660da17ecSBarry Smith PetscBool found; 1379566063dSJacob Faibussowitsch PetscCall(PetscLoadDynamicLibrary("bamg", &found)); 13800045ab3SPierre Jolivet PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc BAMG dynamic library. You cannot move the dynamic libraries!"); 13960da17ecSBarry Smith } 14060da17ecSBarry Smith #endif 141*54606e8bSsdargavi #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES) && defined(PETSC_HAVE_PFLARE) 142*54606e8bSsdargavi { 143*54606e8bSsdargavi PetscBool found; 144*54606e8bSsdargavi PetscCall(PetscLoadDynamicLibrary("pflare", &found)); 145*54606e8bSsdargavi PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PFLARE dynamic library. You cannot move the dynamic libraries!"); 146*54606e8bSsdargavi } 147*54606e8bSsdargavi #endif 14860da17ecSBarry Smith 14960da17ecSBarry Smith nmax = 32; 1509566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetStringArray(NULL, NULL, "-dll_append", libname, &nmax, NULL)); 15160da17ecSBarry Smith for (i = 0; i < nmax; i++) { 1529566063dSJacob Faibussowitsch PetscCall(PetscDLLibraryAppend(PETSC_COMM_WORLD, &PetscDLLibrariesLoaded, libname[i])); 1539566063dSJacob Faibussowitsch PetscCall(PetscFree(libname[i])); 15460da17ecSBarry Smith } 15560da17ecSBarry Smith 156540e20f2SPierre Jolivet #if defined(PETSC_HAVE_ELEMENTAL) 157540e20f2SPierre Jolivet /* in Fortran, PetscInitializeCalled is set to PETSC_TRUE before PetscInitialize_DynamicLibraries() */ 158540e20f2SPierre Jolivet /* in C, it is not the case, but the value is forced to PETSC_TRUE so that PetscRegisterFinalize() is called */ 159540e20f2SPierre Jolivet PetscInitializeCalled = PETSC_TRUE; 1609566063dSJacob Faibussowitsch PetscCall(PetscElementalInitializePackage()); 161540e20f2SPierre Jolivet PetscInitializeCalled = PetscInitialized; 162540e20f2SPierre Jolivet #endif 1633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 164e5c89e4eSSatish Balay } 165e5c89e4eSSatish Balay 166ebd79076SLisandro Dalcin /* 167ebd79076SLisandro Dalcin PetscFinalize_DynamicLibraries - Closes the opened dynamic libraries. 168ebd79076SLisandro Dalcin */ 169d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode PetscFinalize_DynamicLibraries(void) 170d71ae5a4SJacob Faibussowitsch { 171ace3abfcSBarry Smith PetscBool flg = PETSC_FALSE; 172e5c89e4eSSatish Balay 173ebd79076SLisandro Dalcin PetscFunctionBegin; 1749566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-dll_view", &flg, NULL)); 1759566063dSJacob Faibussowitsch if (flg) PetscCall(PetscDLLibraryPrintPath(PetscDLLibrariesLoaded)); 1769566063dSJacob Faibussowitsch PetscCall(PetscDLLibraryClose(PetscDLLibrariesLoaded)); 17702c9f0b5SLisandro Dalcin PetscDLLibrariesLoaded = NULL; 1783ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 179e5c89e4eSSatish Balay } 180e5c89e4eSSatish Balay 18157d50842SBarry Smith PETSC_HASH_MAP(HMapFunc, const char *, PetscErrorCodeFn *, kh_str_hash_func, kh_str_hash_equal, NULL) 182ed170139SJacob Faibussowitsch 183140e18c1SBarry Smith struct _n_PetscFunctionList { 184ed170139SJacob Faibussowitsch PetscHMapFunc map; 185e5c89e4eSSatish Balay }; 186e5c89e4eSSatish Balay 187ed170139SJacob Faibussowitsch /* Keep a linked list of PetscFunctionLists so that we can destroy all the left-over ones. */ 188ed170139SJacob Faibussowitsch typedef struct n_PetscFunctionListDLAll *PetscFunctionListDLAll; 189ed170139SJacob Faibussowitsch struct n_PetscFunctionListDLAll { 190ed170139SJacob Faibussowitsch PetscFunctionList data; 191ed170139SJacob Faibussowitsch PetscFunctionListDLAll next; 192ed170139SJacob Faibussowitsch }; 193e5c89e4eSSatish Balay 194ed170139SJacob Faibussowitsch static PetscFunctionListDLAll dlallhead = NULL; 195ed170139SJacob Faibussowitsch 196ed170139SJacob Faibussowitsch static PetscErrorCode PetscFunctionListDLAllPush_Private(PetscFunctionList fl) 197d71ae5a4SJacob Faibussowitsch { 1980e6b6b59SJacob Faibussowitsch PetscFunctionBegin; 199ed170139SJacob Faibussowitsch if (PetscDefined(USE_DEBUG) && !PetscDefined(HAVE_THREADSAFETY)) { 200ed170139SJacob Faibussowitsch PetscFunctionListDLAll head; 201ed170139SJacob Faibussowitsch 202ed170139SJacob Faibussowitsch PetscCall(PetscNew(&head)); 203ed170139SJacob Faibussowitsch head->data = fl; 204ed170139SJacob Faibussowitsch head->next = dlallhead; 205ed170139SJacob Faibussowitsch dlallhead = head; 206ed170139SJacob Faibussowitsch } 2073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 208ed170139SJacob Faibussowitsch } 209ed170139SJacob Faibussowitsch 210ed170139SJacob Faibussowitsch static PetscErrorCode PetscFunctionListDLAllPop_Private(PetscFunctionList fl) 211ed170139SJacob Faibussowitsch { 212ed170139SJacob Faibussowitsch PetscFunctionBegin; 213ed170139SJacob Faibussowitsch if (PetscDefined(USE_DEBUG) && !PetscDefined(HAVE_THREADSAFETY)) { 214ed170139SJacob Faibussowitsch PetscFunctionListDLAll current = dlallhead, prev = NULL; 215ed170139SJacob Faibussowitsch 216ed170139SJacob Faibussowitsch /* Remove this entry from the main DL list (if it is in it) */ 217ed170139SJacob Faibussowitsch while (current) { 218ed170139SJacob Faibussowitsch const PetscFunctionListDLAll next = current->next; 219ed170139SJacob Faibussowitsch 220ed170139SJacob Faibussowitsch if (current->data == fl) { 221ed170139SJacob Faibussowitsch if (prev) { 222ed170139SJacob Faibussowitsch // somewhere in the middle (or end) of the list 223ed170139SJacob Faibussowitsch prev->next = next; 224ed170139SJacob Faibussowitsch } else { 225ed170139SJacob Faibussowitsch // prev = NULL implies current = dlallhead, so front of list 226ed170139SJacob Faibussowitsch dlallhead = next; 227ed170139SJacob Faibussowitsch } 228ed170139SJacob Faibussowitsch PetscCall(PetscFree(current)); 229ed170139SJacob Faibussowitsch break; 230ed170139SJacob Faibussowitsch } 231ed170139SJacob Faibussowitsch prev = current; 232ed170139SJacob Faibussowitsch current = next; 233ed170139SJacob Faibussowitsch } 234ed170139SJacob Faibussowitsch } 2353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 236ed170139SJacob Faibussowitsch } 237ed170139SJacob Faibussowitsch 23857d50842SBarry Smith static PetscErrorCode PetscHMapFuncInsert_Private(PetscHMapFunc map, const char name[], PetscErrorCodeFn *fnc) 239ed170139SJacob Faibussowitsch { 240ed170139SJacob Faibussowitsch PetscHashIter it; 241ed170139SJacob Faibussowitsch PetscBool found; 242ed170139SJacob Faibussowitsch 243ed170139SJacob Faibussowitsch PetscFunctionBegin; 2444f572ea9SToby Isaac PetscAssertPointer(name, 2); 245ed170139SJacob Faibussowitsch if (fnc) PetscValidFunction(fnc, 3); 246ed170139SJacob Faibussowitsch PetscCall(PetscHMapFuncFind(map, name, &it, &found)); 247ed170139SJacob Faibussowitsch if (fnc) { 248ed170139SJacob Faibussowitsch if (found) { 249ed170139SJacob Faibussowitsch PetscCall(PetscHMapFuncIterSet(map, it, fnc)); 250ed170139SJacob Faibussowitsch } else { 251ed170139SJacob Faibussowitsch char *tmp_name; 252ed170139SJacob Faibussowitsch 253ed170139SJacob Faibussowitsch PetscCall(PetscStrallocpy(name, &tmp_name)); 254ed170139SJacob Faibussowitsch PetscCall(PetscHMapFuncSet(map, tmp_name, fnc)); 255ed170139SJacob Faibussowitsch } 256ed170139SJacob Faibussowitsch } else if (found) { 257ed170139SJacob Faibussowitsch const char *tmp_name; 258ed170139SJacob Faibussowitsch 259ed170139SJacob Faibussowitsch PetscHashIterGetKey(map, it, tmp_name); 260ed170139SJacob Faibussowitsch PetscCall(PetscFree(tmp_name)); 261ed170139SJacob Faibussowitsch PetscCall(PetscHMapFuncIterDel(map, it)); 262ed170139SJacob Faibussowitsch } 2633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 264ed170139SJacob Faibussowitsch } 265ed170139SJacob Faibussowitsch 266ed170139SJacob Faibussowitsch static PetscErrorCode PetscFunctionListCreate_Private(PetscInt size, PetscFunctionList *fl) 267ed170139SJacob Faibussowitsch { 268ed170139SJacob Faibussowitsch PetscFunctionBegin; 2693ba16761SJacob Faibussowitsch if (*fl) PetscFunctionReturn(PETSC_SUCCESS); 270ed170139SJacob Faibussowitsch PetscCall(PetscNew(fl)); 271ed170139SJacob Faibussowitsch PetscCall(PetscHMapFuncCreateWithSize(size, &(*fl)->map)); 272ed170139SJacob Faibussowitsch PetscCall(PetscFunctionListDLAllPush_Private(*fl)); 2733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2740e6b6b59SJacob Faibussowitsch } 2750e6b6b59SJacob Faibussowitsch 276a240a19fSJed Brown /*MC 277140e18c1SBarry Smith PetscFunctionListAdd - Given a routine and a string id, saves that routine in the 278e5c89e4eSSatish Balay specified registry. 279e5c89e4eSSatish Balay 280a240a19fSJed Brown Synopsis: 281aaa7dc30SBarry Smith #include <petscsys.h> 28257d50842SBarry Smith PetscErrorCode PetscFunctionListAdd(PetscFunctionList *flist, const char name[], PetscErrorCodeFn *fptr) 283a240a19fSJed Brown 284d4349b43SBarry Smith Not Collective 285e5c89e4eSSatish Balay 286e5c89e4eSSatish Balay Input Parameters: 28710450e9eSJacob Faibussowitsch + fl - pointer to function list object 288e5c89e4eSSatish Balay . name - string to identify routine 289a240a19fSJed Brown - fptr - function pointer 290e5c89e4eSSatish Balay 29121532e8aSBarry Smith Level: developer 29221532e8aSBarry Smith 293e5c89e4eSSatish Balay Notes: 29421532e8aSBarry Smith To remove a registered routine, pass in a `NULL` `fptr`. 295e5c89e4eSSatish Balay 296e5c89e4eSSatish Balay Users who wish to register new classes for use by a particular PETSc 297811af0c4SBarry Smith component (e.g., `SNES`) should generally call the registration routine 298811af0c4SBarry Smith for that particular component (e.g., `SNESRegister()`) instead of 299811af0c4SBarry Smith calling `PetscFunctionListAdd()` directly. 300e5c89e4eSSatish Balay 30121532e8aSBarry Smith .seealso: `PetscFunctionListDestroy()`, `SNESRegister()`, `KSPRegister()`,`PetscFunctionListDuplicate()` 302db781477SPatrick Sanan `PCRegister()`, `TSRegister()`, `PetscFunctionList`, `PetscObjectComposeFunction()` 303a240a19fSJed Brown M*/ 30457d50842SBarry Smith PetscErrorCode PetscFunctionListAdd_Private(PetscFunctionList *fl, const char name[], PetscErrorCodeFn *fptr) 305d71ae5a4SJacob Faibussowitsch { 306e5c89e4eSSatish Balay PetscFunctionBegin; 3074f572ea9SToby Isaac PetscAssertPointer(fl, 1); 3084f572ea9SToby Isaac if (name) PetscAssertPointer(name, 2); 30910450e9eSJacob Faibussowitsch if (fptr) PetscValidFunction(fptr, 3); 310ebd2f95aSStefano Zampini if (!fptr && !*fl) PetscFunctionReturn(PETSC_SUCCESS); 311ed170139SJacob Faibussowitsch PetscCall(PetscFunctionListCreate_Private(0, fl)); 31210450e9eSJacob Faibussowitsch PetscCall(PetscHMapFuncInsert_Private((*fl)->map, name, fptr)); 3133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 314e5c89e4eSSatish Balay } 315e5c89e4eSSatish Balay 316ffeef943SBarry Smith /*@C 317140e18c1SBarry Smith PetscFunctionListDestroy - Destroys a list of registered routines. 318e5c89e4eSSatish Balay 319e5c89e4eSSatish Balay Input Parameter: 320e5c89e4eSSatish Balay . fl - pointer to list 321e5c89e4eSSatish Balay 322e5c89e4eSSatish Balay Level: developer 323e5c89e4eSSatish Balay 3240e6b6b59SJacob Faibussowitsch .seealso: `PetscFunctionListAdd()`, `PetscFunctionList`, `PetscFunctionListClear()` 325e5c89e4eSSatish Balay @*/ 326d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFunctionListDestroy(PetscFunctionList *fl) 327d71ae5a4SJacob Faibussowitsch { 328e5c89e4eSSatish Balay PetscFunctionBegin; 3293ba16761SJacob Faibussowitsch if (!*fl) PetscFunctionReturn(PETSC_SUCCESS); 330ed170139SJacob Faibussowitsch PetscCall(PetscFunctionListDLAllPop_Private(*fl)); 331e5c89e4eSSatish Balay /* free this list */ 332ed170139SJacob Faibussowitsch PetscCall(PetscFunctionListClear(*fl)); 333ed170139SJacob Faibussowitsch PetscCall(PetscHMapFuncDestroy(&(*fl)->map)); 334ed170139SJacob Faibussowitsch PetscCall(PetscFree(*fl)); 3353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 336e5c89e4eSSatish Balay } 337e5c89e4eSSatish Balay 338ed170139SJacob Faibussowitsch #define PetscHMapFuncForEach(__func_list__, __key_name__, __val_name__, ...) \ 339ed170139SJacob Faibussowitsch do { \ 340ed170139SJacob Faibussowitsch const PetscHMapFunc phmfi_map_ = (__func_list__)->map; \ 341ed170139SJacob Faibussowitsch PetscHashIter phmfi_iter_; \ 342ed170139SJacob Faibussowitsch \ 343ed170139SJacob Faibussowitsch PetscHashIterBegin(phmfi_map_, phmfi_iter_); \ 344ed170139SJacob Faibussowitsch while (!PetscHashIterAtEnd(phmfi_map_, phmfi_iter_)) { \ 345ed170139SJacob Faibussowitsch const char *PETSC_UNUSED __key_name__; \ 34657d50842SBarry Smith PetscErrorCodeFn *PETSC_UNUSED __val_name__; \ 347ed170139SJacob Faibussowitsch \ 348ed170139SJacob Faibussowitsch PetscHashIterGetKey(phmfi_map_, phmfi_iter_, __key_name__); \ 349ed170139SJacob Faibussowitsch PetscHashIterGetVal(phmfi_map_, phmfi_iter_, __val_name__); \ 350ed170139SJacob Faibussowitsch { \ 351ed170139SJacob Faibussowitsch __VA_ARGS__; \ 352ed170139SJacob Faibussowitsch } \ 353ed170139SJacob Faibussowitsch PetscHashIterNext(phmfi_map_, phmfi_iter_); \ 354ed170139SJacob Faibussowitsch } /* end while */ \ 355ed170139SJacob Faibussowitsch } while (0) 356ed170139SJacob Faibussowitsch 357ffeef943SBarry Smith /*@C 3580e6b6b59SJacob Faibussowitsch PetscFunctionListClear - Clear a `PetscFunctionList` 3590e6b6b59SJacob Faibussowitsch 3600e6b6b59SJacob Faibussowitsch Not Collective 3610e6b6b59SJacob Faibussowitsch 3620e6b6b59SJacob Faibussowitsch Input Parameter: 3630e6b6b59SJacob Faibussowitsch . fl - The `PetscFunctionList` to clear 3640e6b6b59SJacob Faibussowitsch 36521532e8aSBarry Smith Level: developer 36621532e8aSBarry Smith 3670e6b6b59SJacob Faibussowitsch Notes: 3680e6b6b59SJacob Faibussowitsch This clears the contents of `fl` but does not deallocate the entries themselves. 3690e6b6b59SJacob Faibussowitsch 3700e6b6b59SJacob Faibussowitsch .seealso: `PetscFunctionList`, `PetscFunctionListDestroy()`, `PetscFunctionListAdd()` 3710e6b6b59SJacob Faibussowitsch @*/ 372d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFunctionListClear(PetscFunctionList fl) 373d71ae5a4SJacob Faibussowitsch { 3740e6b6b59SJacob Faibussowitsch PetscFunctionBegin; 375ed170139SJacob Faibussowitsch if (fl) { 376ed170139SJacob Faibussowitsch PetscHMapFuncForEach(fl, name, func, PetscCall(PetscFree(name))); 377ed170139SJacob Faibussowitsch PetscCall(PetscHMapFuncClear(fl->map)); 3780e6b6b59SJacob Faibussowitsch } 3793ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3800e6b6b59SJacob Faibussowitsch } 3810e6b6b59SJacob Faibussowitsch 382e5c89e4eSSatish Balay /* 3832e956fe4SStefano Zampini Print registered PetscFunctionLists 384e5c89e4eSSatish Balay */ 385d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFunctionListPrintAll(void) 386d71ae5a4SJacob Faibussowitsch { 387ed170139SJacob Faibussowitsch PetscFunctionListDLAll current = dlallhead; 388e5c89e4eSSatish Balay 389e5c89e4eSSatish Balay PetscFunctionBegin; 390ed170139SJacob Faibussowitsch if (current) PetscCall(PetscPrintf(PETSC_COMM_SELF, "[%d] Registered PetscFunctionLists\n", PetscGlobalRank)); 391ed170139SJacob Faibussowitsch while (current) { 392ed170139SJacob Faibussowitsch PetscCall(PetscFunctionListPrintNonEmpty(current->data)); 393ed170139SJacob Faibussowitsch current = current->next; 39437e93019SBarry Smith } 3953ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 396e5c89e4eSSatish Balay } 397e5c89e4eSSatish Balay 39810450e9eSJacob Faibussowitsch /*@C 39910450e9eSJacob Faibussowitsch PetscFunctionListPrintNonEmpty - Print composed names for non `NULL` function pointers 4002e956fe4SStefano Zampini 401cc4c1da9SBarry Smith Logically Collective, No Fortran Support 402cc4c1da9SBarry Smith 4032e956fe4SStefano Zampini Input Parameter: 40410450e9eSJacob Faibussowitsch . fl - the function list 4052e956fe4SStefano Zampini 4062e956fe4SStefano Zampini Level: developer 4072e956fe4SStefano Zampini 4082e956fe4SStefano Zampini .seealso: `PetscFunctionListAdd()`, `PetscFunctionList`, `PetscObjectQueryFunction()` 40910450e9eSJacob Faibussowitsch @*/ 410d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFunctionListPrintNonEmpty(PetscFunctionList fl) 411d71ae5a4SJacob Faibussowitsch { 4122e956fe4SStefano Zampini PetscFunctionBegin; 413ed170139SJacob Faibussowitsch if (fl) { 414ed170139SJacob Faibussowitsch // clang-format off 415ed170139SJacob Faibussowitsch PetscHMapFuncForEach( 416ed170139SJacob Faibussowitsch fl, 417ed170139SJacob Faibussowitsch name, func, 418ed170139SJacob Faibussowitsch PetscCall(PetscFPrintf(PETSC_COMM_SELF, PETSC_STDOUT, "[%d] function name: %s\n", PetscGlobalRank, name)); 419ed170139SJacob Faibussowitsch ); 420ed170139SJacob Faibussowitsch // clang-format on 4212e956fe4SStefano Zampini } 4223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4232e956fe4SStefano Zampini } 4242e956fe4SStefano Zampini 4252e956fe4SStefano Zampini /*MC 4261c9cd337SJed Brown PetscFunctionListFind - Find function registered under given name 4271c9cd337SJed Brown 428cc4c1da9SBarry Smith Not Collective, No Fortran Support 429cc4c1da9SBarry Smith 4301c9cd337SJed Brown Synopsis: 431aaa7dc30SBarry Smith #include <petscsys.h> 43257d50842SBarry Smith PetscErrorCode PetscFunctionListFind(PetscFunctionList flist, const char name[], PetscErrorCodeFn **fptr) 433e5c89e4eSSatish Balay 434e5c89e4eSSatish Balay Input Parameters: 43510450e9eSJacob Faibussowitsch + fl - the function list 4361c9cd337SJed Brown - name - name registered for the function 437e5c89e4eSSatish Balay 4382fe279fdSBarry Smith Output Parameter: 43921532e8aSBarry Smith . fptr - the function pointer if name was found, else `NULL` 440e5c89e4eSSatish Balay 441e5c89e4eSSatish Balay Level: developer 442e5c89e4eSSatish Balay 44321532e8aSBarry Smith .seealso: `PetscFunctionListAdd()`, `PetscFunctionList`, `PetscObjectQueryFunction()`, `PetscFunctionListDuplicate()` 4441c9cd337SJed Brown M*/ 44557d50842SBarry Smith PetscErrorCode PetscFunctionListFind_Private(PetscFunctionList fl, const char name[], PetscErrorCodeFn **fptr) 446d71ae5a4SJacob Faibussowitsch { 447e5c89e4eSSatish Balay PetscFunctionBegin; 4484f572ea9SToby Isaac PetscAssertPointer(name, 2); 4494f572ea9SToby Isaac PetscAssertPointer(fptr, 3); 45010450e9eSJacob Faibussowitsch *fptr = NULL; 45110450e9eSJacob Faibussowitsch if (fl) PetscCall(PetscHMapFuncGet(fl->map, name, fptr)); 4523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 453e5c89e4eSSatish Balay } 454e5c89e4eSSatish Balay 455ffeef943SBarry Smith /*@C 45620f4b53cSBarry Smith PetscFunctionListView - prints out contents of a `PetscFunctionList` 457e5c89e4eSSatish Balay 45820f4b53cSBarry Smith Collective 459e5c89e4eSSatish Balay 460e5c89e4eSSatish Balay Input Parameters: 461e5c89e4eSSatish Balay + list - the list of functions 46220f4b53cSBarry Smith - viewer - the `PetscViewer` used to view the `PetscFunctionList` 463e5c89e4eSSatish Balay 464e5c89e4eSSatish Balay Level: developer 465e5c89e4eSSatish Balay 466db781477SPatrick Sanan .seealso: `PetscFunctionListAdd()`, `PetscFunctionListPrintTypes()`, `PetscFunctionList` 467e5c89e4eSSatish Balay @*/ 468d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFunctionListView(PetscFunctionList list, PetscViewer viewer) 469d71ae5a4SJacob Faibussowitsch { 4709f196a02SMartin Diehl PetscBool isascii; 471e5c89e4eSSatish Balay 472e5c89e4eSSatish Balay PetscFunctionBegin; 4734f572ea9SToby Isaac PetscAssertPointer(list, 1); 474ed170139SJacob Faibussowitsch if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PETSC_COMM_SELF, &viewer)); 4750700a824SBarry Smith PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 476e5c89e4eSSatish Balay 4779f196a02SMartin Diehl PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 4789f196a02SMartin Diehl PetscCheck(isascii, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only ASCII viewer supported"); 479ed170139SJacob Faibussowitsch { 480ed170139SJacob Faibussowitsch PetscInt size; 481e5c89e4eSSatish Balay 482ed170139SJacob Faibussowitsch PetscCall(PetscHMapFuncGetSize(list->map, &size)); 483ed170139SJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "PetscFunctionList Object:\n")); 484ed170139SJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 485ed170139SJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "size: %" PetscInt_FMT "\n", size)); 486ed170139SJacob Faibussowitsch if (size) { 487ed170139SJacob Faibussowitsch PetscInt count = 0; 488ed170139SJacob Faibussowitsch 489ed170139SJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "functions:\n")); 490ed170139SJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 491ed170139SJacob Faibussowitsch PetscHMapFuncForEach(list, name, func, PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT ": %s\n", ++count, name))); 492ed170139SJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 493e5c89e4eSSatish Balay } 494ed170139SJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 495ed170139SJacob Faibussowitsch } 4963ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 497e5c89e4eSSatish Balay } 498e5c89e4eSSatish Balay 499065533a5SJed Brown /*@C 500811af0c4SBarry Smith PetscFunctionListGet - Gets an array the contains the entries in `PetscFunctionList`, this is used 501e5c89e4eSSatish Balay by help etc. 502e5c89e4eSSatish Balay 503cc4c1da9SBarry Smith Not Collective, No Fortran Support 504e5c89e4eSSatish Balay 505e5c89e4eSSatish Balay Input Parameter: 506e5c89e4eSSatish Balay . list - list of types 507e5c89e4eSSatish Balay 508d8d19677SJose E. Roman Output Parameters: 509e5c89e4eSSatish Balay + array - array of names 51021532e8aSBarry Smith - n - length of `array` 51121532e8aSBarry Smith 51221532e8aSBarry Smith Level: developer 513e5c89e4eSSatish Balay 514811af0c4SBarry Smith Note: 515a3b724e8SBarry Smith This allocates the array so that must be freed with `PetscFree()`. BUT the individual entries should not be freed. 516e5c89e4eSSatish Balay 517db781477SPatrick Sanan .seealso: `PetscFunctionListAdd()`, `PetscFunctionList` 518e5c89e4eSSatish Balay @*/ 519d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFunctionListGet(PetscFunctionList list, const char ***array, int *n) 520d71ae5a4SJacob Faibussowitsch { 521ed170139SJacob Faibussowitsch PetscInt size = 0; 522e5c89e4eSSatish Balay 523e5c89e4eSSatish Balay PetscFunctionBegin; 5244f572ea9SToby Isaac PetscAssertPointer(array, 2); 525ed170139SJacob Faibussowitsch *array = NULL; 526ed170139SJacob Faibussowitsch if (list) { 527ed170139SJacob Faibussowitsch const PetscHMapFunc map = list->map; 528ed170139SJacob Faibussowitsch PetscInt off = 0; 529ed170139SJacob Faibussowitsch 530ed170139SJacob Faibussowitsch PetscCall(PetscHMapFuncGetSize(map, &size)); 531ed170139SJacob Faibussowitsch PetscCall(PetscMalloc1(size, (char ***)array)); 532ed170139SJacob Faibussowitsch PetscCall(PetscHMapFuncGetKeys(map, &off, *array)); 533e5c89e4eSSatish Balay } 534835f2295SStefano Zampini PetscCall(PetscCIntCast(size, n)); 5353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 536e5c89e4eSSatish Balay } 537e5c89e4eSSatish Balay 538e5c89e4eSSatish Balay /*@C 539811af0c4SBarry Smith PetscFunctionListPrintTypes - Prints the methods available in a list of functions 540e5c89e4eSSatish Balay 541cc4c1da9SBarry Smith Collective, No Fortran Support 542e5c89e4eSSatish Balay 543e5c89e4eSSatish Balay Input Parameters: 544811af0c4SBarry Smith + comm - the communicator (usually `MPI_COMM_WORLD`) 54521532e8aSBarry Smith . fd - file to print to, usually `stdout` 546e5c89e4eSSatish Balay . prefix - prefix to prepend to name (optional) 54721532e8aSBarry Smith . name - option string (for example, `-ksp_type`) 548e5c89e4eSSatish Balay . text - short description of the object (for example, "Krylov solvers") 54921532e8aSBarry Smith . man - name of manual page that discusses the object (for example, `KSPCreate`) 5503cc1e11dSBarry Smith . list - list of types 55144ef3d73SBarry Smith . def - default (current) value 55244ef3d73SBarry Smith - newv - new value 553e5c89e4eSSatish Balay 554e5c89e4eSSatish Balay Level: developer 555e5c89e4eSSatish Balay 556db781477SPatrick Sanan .seealso: `PetscFunctionListAdd()`, `PetscFunctionList` 557e5c89e4eSSatish Balay @*/ 558d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFunctionListPrintTypes(MPI_Comm comm, FILE *fd, const char prefix[], const char name[], const char text[], const char man[], PetscFunctionList list, const char def[], const char newv[]) 559d71ae5a4SJacob Faibussowitsch { 560e5c89e4eSSatish Balay char p[64]; 561e5c89e4eSSatish Balay 562e5c89e4eSSatish Balay PetscFunctionBegin; 563ed170139SJacob Faibussowitsch (void)fd; 5649566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(p, "-", sizeof(p))); 5659566063dSJacob Faibussowitsch if (prefix) PetscCall(PetscStrlcat(p, prefix, sizeof(p))); 566ed170139SJacob Faibussowitsch PetscCall((*PetscHelpPrintf)(comm, " %s%s <now %s : formerly %s>: %s (one of)", p, name + 1, newv, def, text)); 567e5c89e4eSSatish Balay 5688c7e48aeSJacob Faibussowitsch if (list) PetscHMapFuncForEach(list, name, func, PetscCall((*PetscHelpPrintf)(comm, " %s", name))); 569ed170139SJacob Faibussowitsch PetscCall((*PetscHelpPrintf)(comm, " (%s)\n", man)); 5703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 571e5c89e4eSSatish Balay } 572e5c89e4eSSatish Balay 573ffeef943SBarry Smith /*@C 57421532e8aSBarry Smith PetscFunctionListDuplicate - Creates a new list from a given function list `PetscFunctionList`. 575e5c89e4eSSatish Balay 5762fe279fdSBarry Smith Input Parameter: 577e5c89e4eSSatish Balay . fl - pointer to list 578e5c89e4eSSatish Balay 5792fe279fdSBarry Smith Output Parameter: 58021532e8aSBarry Smith . nl - the new list (should point to `NULL` to start, otherwise appends) 581e5c89e4eSSatish Balay 582e5c89e4eSSatish Balay Level: developer 583e5c89e4eSSatish Balay 584db781477SPatrick Sanan .seealso: `PetscFunctionList`, `PetscFunctionListAdd()`, `PetscFlistDestroy()` 585e5c89e4eSSatish Balay @*/ 586d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFunctionListDuplicate(PetscFunctionList fl, PetscFunctionList *nl) 587d71ae5a4SJacob Faibussowitsch { 588e5c89e4eSSatish Balay PetscFunctionBegin; 589ed170139SJacob Faibussowitsch if (fl) { 590ed170139SJacob Faibussowitsch PetscHMapFunc dup_map; 591ed170139SJacob Faibussowitsch 592ed170139SJacob Faibussowitsch if (!*nl) { 593ed170139SJacob Faibussowitsch PetscInt n; 594ed170139SJacob Faibussowitsch 595ed170139SJacob Faibussowitsch PetscCall(PetscHMapFuncGetSize(fl->map, &n)); 596ed170139SJacob Faibussowitsch PetscCall(PetscFunctionListCreate_Private(n, nl)); 597ed170139SJacob Faibussowitsch } 598ed170139SJacob Faibussowitsch dup_map = (*nl)->map; 599ed170139SJacob Faibussowitsch PetscHMapFuncForEach(fl, name, func, PetscCall(PetscHMapFuncInsert_Private(dup_map, name, func))); 600e5c89e4eSSatish Balay } 6013ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 602e5c89e4eSSatish Balay } 603