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 14160da17ecSBarry Smith 14260da17ecSBarry Smith nmax = 32; 1439566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetStringArray(NULL, NULL, "-dll_append", libname, &nmax, NULL)); 14460da17ecSBarry Smith for (i = 0; i < nmax; i++) { 1459566063dSJacob Faibussowitsch PetscCall(PetscDLLibraryAppend(PETSC_COMM_WORLD, &PetscDLLibrariesLoaded, libname[i])); 1469566063dSJacob Faibussowitsch PetscCall(PetscFree(libname[i])); 14760da17ecSBarry Smith } 14860da17ecSBarry Smith 149540e20f2SPierre Jolivet #if defined(PETSC_HAVE_ELEMENTAL) 150540e20f2SPierre Jolivet /* in Fortran, PetscInitializeCalled is set to PETSC_TRUE before PetscInitialize_DynamicLibraries() */ 151540e20f2SPierre Jolivet /* in C, it is not the case, but the value is forced to PETSC_TRUE so that PetscRegisterFinalize() is called */ 152540e20f2SPierre Jolivet PetscInitializeCalled = PETSC_TRUE; 1539566063dSJacob Faibussowitsch PetscCall(PetscElementalInitializePackage()); 154540e20f2SPierre Jolivet PetscInitializeCalled = PetscInitialized; 155540e20f2SPierre Jolivet #endif 1563ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 157e5c89e4eSSatish Balay } 158e5c89e4eSSatish Balay 159ebd79076SLisandro Dalcin /* 160ebd79076SLisandro Dalcin PetscFinalize_DynamicLibraries - Closes the opened dynamic libraries. 161ebd79076SLisandro Dalcin */ 162d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode PetscFinalize_DynamicLibraries(void) 163d71ae5a4SJacob Faibussowitsch { 164ace3abfcSBarry Smith PetscBool flg = PETSC_FALSE; 165e5c89e4eSSatish Balay 166ebd79076SLisandro Dalcin PetscFunctionBegin; 1679566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-dll_view", &flg, NULL)); 1689566063dSJacob Faibussowitsch if (flg) PetscCall(PetscDLLibraryPrintPath(PetscDLLibrariesLoaded)); 1699566063dSJacob Faibussowitsch PetscCall(PetscDLLibraryClose(PetscDLLibrariesLoaded)); 17002c9f0b5SLisandro Dalcin PetscDLLibrariesLoaded = NULL; 1713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 172e5c89e4eSSatish Balay } 173e5c89e4eSSatish Balay 1748434afd1SBarry Smith PETSC_HASH_MAP(HMapFunc, const char *, PetscVoidFn *, kh_str_hash_func, kh_str_hash_equal, NULL) 175ed170139SJacob Faibussowitsch 176140e18c1SBarry Smith struct _n_PetscFunctionList { 177ed170139SJacob Faibussowitsch PetscHMapFunc map; 178e5c89e4eSSatish Balay }; 179e5c89e4eSSatish Balay 180ed170139SJacob Faibussowitsch /* Keep a linked list of PetscFunctionLists so that we can destroy all the left-over ones. */ 181ed170139SJacob Faibussowitsch typedef struct n_PetscFunctionListDLAll *PetscFunctionListDLAll; 182ed170139SJacob Faibussowitsch struct n_PetscFunctionListDLAll { 183ed170139SJacob Faibussowitsch PetscFunctionList data; 184ed170139SJacob Faibussowitsch PetscFunctionListDLAll next; 185ed170139SJacob Faibussowitsch }; 186e5c89e4eSSatish Balay 187ed170139SJacob Faibussowitsch static PetscFunctionListDLAll dlallhead = NULL; 188ed170139SJacob Faibussowitsch 189ed170139SJacob Faibussowitsch static PetscErrorCode PetscFunctionListDLAllPush_Private(PetscFunctionList fl) 190d71ae5a4SJacob Faibussowitsch { 1910e6b6b59SJacob Faibussowitsch PetscFunctionBegin; 192ed170139SJacob Faibussowitsch if (PetscDefined(USE_DEBUG) && !PetscDefined(HAVE_THREADSAFETY)) { 193ed170139SJacob Faibussowitsch PetscFunctionListDLAll head; 194ed170139SJacob Faibussowitsch 195ed170139SJacob Faibussowitsch PetscCall(PetscNew(&head)); 196ed170139SJacob Faibussowitsch head->data = fl; 197ed170139SJacob Faibussowitsch head->next = dlallhead; 198ed170139SJacob Faibussowitsch dlallhead = head; 199ed170139SJacob Faibussowitsch } 2003ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 201ed170139SJacob Faibussowitsch } 202ed170139SJacob Faibussowitsch 203ed170139SJacob Faibussowitsch static PetscErrorCode PetscFunctionListDLAllPop_Private(PetscFunctionList fl) 204ed170139SJacob Faibussowitsch { 205ed170139SJacob Faibussowitsch PetscFunctionBegin; 206ed170139SJacob Faibussowitsch if (PetscDefined(USE_DEBUG) && !PetscDefined(HAVE_THREADSAFETY)) { 207ed170139SJacob Faibussowitsch PetscFunctionListDLAll current = dlallhead, prev = NULL; 208ed170139SJacob Faibussowitsch 209ed170139SJacob Faibussowitsch /* Remove this entry from the main DL list (if it is in it) */ 210ed170139SJacob Faibussowitsch while (current) { 211ed170139SJacob Faibussowitsch const PetscFunctionListDLAll next = current->next; 212ed170139SJacob Faibussowitsch 213ed170139SJacob Faibussowitsch if (current->data == fl) { 214ed170139SJacob Faibussowitsch if (prev) { 215ed170139SJacob Faibussowitsch // somewhere in the middle (or end) of the list 216ed170139SJacob Faibussowitsch prev->next = next; 217ed170139SJacob Faibussowitsch } else { 218ed170139SJacob Faibussowitsch // prev = NULL implies current = dlallhead, so front of list 219ed170139SJacob Faibussowitsch dlallhead = next; 220ed170139SJacob Faibussowitsch } 221ed170139SJacob Faibussowitsch PetscCall(PetscFree(current)); 222ed170139SJacob Faibussowitsch break; 223ed170139SJacob Faibussowitsch } 224ed170139SJacob Faibussowitsch prev = current; 225ed170139SJacob Faibussowitsch current = next; 226ed170139SJacob Faibussowitsch } 227ed170139SJacob Faibussowitsch } 2283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 229ed170139SJacob Faibussowitsch } 230ed170139SJacob Faibussowitsch 2318434afd1SBarry Smith static PetscErrorCode PetscHMapFuncInsert_Private(PetscHMapFunc map, const char name[], PetscVoidFn *fnc) 232ed170139SJacob Faibussowitsch { 233ed170139SJacob Faibussowitsch PetscHashIter it; 234ed170139SJacob Faibussowitsch PetscBool found; 235ed170139SJacob Faibussowitsch 236ed170139SJacob Faibussowitsch PetscFunctionBegin; 2374f572ea9SToby Isaac PetscAssertPointer(name, 2); 238ed170139SJacob Faibussowitsch if (fnc) PetscValidFunction(fnc, 3); 239ed170139SJacob Faibussowitsch PetscCall(PetscHMapFuncFind(map, name, &it, &found)); 240ed170139SJacob Faibussowitsch if (fnc) { 241ed170139SJacob Faibussowitsch if (found) { 242ed170139SJacob Faibussowitsch PetscCall(PetscHMapFuncIterSet(map, it, fnc)); 243ed170139SJacob Faibussowitsch } else { 244ed170139SJacob Faibussowitsch char *tmp_name; 245ed170139SJacob Faibussowitsch 246ed170139SJacob Faibussowitsch PetscCall(PetscStrallocpy(name, &tmp_name)); 247ed170139SJacob Faibussowitsch PetscCall(PetscHMapFuncSet(map, tmp_name, fnc)); 248ed170139SJacob Faibussowitsch } 249ed170139SJacob Faibussowitsch } else if (found) { 250ed170139SJacob Faibussowitsch const char *tmp_name; 251ed170139SJacob Faibussowitsch 252ed170139SJacob Faibussowitsch PetscHashIterGetKey(map, it, tmp_name); 253ed170139SJacob Faibussowitsch PetscCall(PetscFree(tmp_name)); 254ed170139SJacob Faibussowitsch PetscCall(PetscHMapFuncIterDel(map, it)); 255ed170139SJacob Faibussowitsch } 2563ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 257ed170139SJacob Faibussowitsch } 258ed170139SJacob Faibussowitsch 259ed170139SJacob Faibussowitsch static PetscErrorCode PetscFunctionListCreate_Private(PetscInt size, PetscFunctionList *fl) 260ed170139SJacob Faibussowitsch { 261ed170139SJacob Faibussowitsch PetscFunctionBegin; 2623ba16761SJacob Faibussowitsch if (*fl) PetscFunctionReturn(PETSC_SUCCESS); 263ed170139SJacob Faibussowitsch PetscCall(PetscNew(fl)); 264ed170139SJacob Faibussowitsch PetscCall(PetscHMapFuncCreateWithSize(size, &(*fl)->map)); 265ed170139SJacob Faibussowitsch PetscCall(PetscFunctionListDLAllPush_Private(*fl)); 2663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2670e6b6b59SJacob Faibussowitsch } 2680e6b6b59SJacob Faibussowitsch 269a240a19fSJed Brown /*MC 270140e18c1SBarry Smith PetscFunctionListAdd - Given a routine and a string id, saves that routine in the 271e5c89e4eSSatish Balay specified registry. 272e5c89e4eSSatish Balay 273a240a19fSJed Brown Synopsis: 274aaa7dc30SBarry Smith #include <petscsys.h> 275b9fb364aSBarry Smith PetscErrorCode PetscFunctionListAdd(PetscFunctionList *flist,const char name[],void (*fptr)(void)) 276a240a19fSJed Brown 277d4349b43SBarry Smith Not Collective 278e5c89e4eSSatish Balay 279e5c89e4eSSatish Balay Input Parameters: 28010450e9eSJacob Faibussowitsch + fl - pointer to function list object 281e5c89e4eSSatish Balay . name - string to identify routine 282a240a19fSJed Brown - fptr - function pointer 283e5c89e4eSSatish Balay 28421532e8aSBarry Smith Level: developer 28521532e8aSBarry Smith 286e5c89e4eSSatish Balay Notes: 28721532e8aSBarry Smith To remove a registered routine, pass in a `NULL` `fptr`. 288e5c89e4eSSatish Balay 289e5c89e4eSSatish Balay Users who wish to register new classes for use by a particular PETSc 290811af0c4SBarry Smith component (e.g., `SNES`) should generally call the registration routine 291811af0c4SBarry Smith for that particular component (e.g., `SNESRegister()`) instead of 292811af0c4SBarry Smith calling `PetscFunctionListAdd()` directly. 293e5c89e4eSSatish Balay 29421532e8aSBarry Smith .seealso: `PetscFunctionListDestroy()`, `SNESRegister()`, `KSPRegister()`,`PetscFunctionListDuplicate()` 295db781477SPatrick Sanan `PCRegister()`, `TSRegister()`, `PetscFunctionList`, `PetscObjectComposeFunction()` 296a240a19fSJed Brown M*/ 2978434afd1SBarry Smith PetscErrorCode PetscFunctionListAdd_Private(PetscFunctionList *fl, const char name[], PetscVoidFn *fptr) 298d71ae5a4SJacob Faibussowitsch { 299e5c89e4eSSatish Balay PetscFunctionBegin; 3004f572ea9SToby Isaac PetscAssertPointer(fl, 1); 3014f572ea9SToby Isaac if (name) PetscAssertPointer(name, 2); 30210450e9eSJacob Faibussowitsch if (fptr) PetscValidFunction(fptr, 3); 303ebd2f95aSStefano Zampini if (!fptr && !*fl) PetscFunctionReturn(PETSC_SUCCESS); 304ed170139SJacob Faibussowitsch PetscCall(PetscFunctionListCreate_Private(0, fl)); 30510450e9eSJacob Faibussowitsch PetscCall(PetscHMapFuncInsert_Private((*fl)->map, name, fptr)); 3063ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 307e5c89e4eSSatish Balay } 308e5c89e4eSSatish Balay 309ffeef943SBarry Smith /*@C 310140e18c1SBarry Smith PetscFunctionListDestroy - Destroys a list of registered routines. 311e5c89e4eSSatish Balay 312e5c89e4eSSatish Balay Input Parameter: 313e5c89e4eSSatish Balay . fl - pointer to list 314e5c89e4eSSatish Balay 315e5c89e4eSSatish Balay Level: developer 316e5c89e4eSSatish Balay 3170e6b6b59SJacob Faibussowitsch .seealso: `PetscFunctionListAdd()`, `PetscFunctionList`, `PetscFunctionListClear()` 318e5c89e4eSSatish Balay @*/ 319d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFunctionListDestroy(PetscFunctionList *fl) 320d71ae5a4SJacob Faibussowitsch { 321e5c89e4eSSatish Balay PetscFunctionBegin; 3223ba16761SJacob Faibussowitsch if (!*fl) PetscFunctionReturn(PETSC_SUCCESS); 323ed170139SJacob Faibussowitsch PetscCall(PetscFunctionListDLAllPop_Private(*fl)); 324e5c89e4eSSatish Balay /* free this list */ 325ed170139SJacob Faibussowitsch PetscCall(PetscFunctionListClear(*fl)); 326ed170139SJacob Faibussowitsch PetscCall(PetscHMapFuncDestroy(&(*fl)->map)); 327ed170139SJacob Faibussowitsch PetscCall(PetscFree(*fl)); 3283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 329e5c89e4eSSatish Balay } 330e5c89e4eSSatish Balay 331ed170139SJacob Faibussowitsch #define PetscHMapFuncForEach(__func_list__, __key_name__, __val_name__, ...) \ 332ed170139SJacob Faibussowitsch do { \ 333ed170139SJacob Faibussowitsch const PetscHMapFunc phmfi_map_ = (__func_list__)->map; \ 334ed170139SJacob Faibussowitsch PetscHashIter phmfi_iter_; \ 335ed170139SJacob Faibussowitsch \ 336ed170139SJacob Faibussowitsch PetscHashIterBegin(phmfi_map_, phmfi_iter_); \ 337ed170139SJacob Faibussowitsch while (!PetscHashIterAtEnd(phmfi_map_, phmfi_iter_)) { \ 338ed170139SJacob Faibussowitsch const char *PETSC_UNUSED __key_name__; \ 3398434afd1SBarry Smith PetscVoidFn *PETSC_UNUSED __val_name__; \ 340ed170139SJacob Faibussowitsch \ 341ed170139SJacob Faibussowitsch PetscHashIterGetKey(phmfi_map_, phmfi_iter_, __key_name__); \ 342ed170139SJacob Faibussowitsch PetscHashIterGetVal(phmfi_map_, phmfi_iter_, __val_name__); \ 343ed170139SJacob Faibussowitsch { \ 344ed170139SJacob Faibussowitsch __VA_ARGS__; \ 345ed170139SJacob Faibussowitsch } \ 346ed170139SJacob Faibussowitsch PetscHashIterNext(phmfi_map_, phmfi_iter_); \ 347ed170139SJacob Faibussowitsch } /* end while */ \ 348ed170139SJacob Faibussowitsch } while (0) 349ed170139SJacob Faibussowitsch 350ffeef943SBarry Smith /*@C 3510e6b6b59SJacob Faibussowitsch PetscFunctionListClear - Clear a `PetscFunctionList` 3520e6b6b59SJacob Faibussowitsch 3530e6b6b59SJacob Faibussowitsch Not Collective 3540e6b6b59SJacob Faibussowitsch 3550e6b6b59SJacob Faibussowitsch Input Parameter: 3560e6b6b59SJacob Faibussowitsch . fl - The `PetscFunctionList` to clear 3570e6b6b59SJacob Faibussowitsch 35821532e8aSBarry Smith Level: developer 35921532e8aSBarry Smith 3600e6b6b59SJacob Faibussowitsch Notes: 3610e6b6b59SJacob Faibussowitsch This clears the contents of `fl` but does not deallocate the entries themselves. 3620e6b6b59SJacob Faibussowitsch 3630e6b6b59SJacob Faibussowitsch .seealso: `PetscFunctionList`, `PetscFunctionListDestroy()`, `PetscFunctionListAdd()` 3640e6b6b59SJacob Faibussowitsch @*/ 365d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFunctionListClear(PetscFunctionList fl) 366d71ae5a4SJacob Faibussowitsch { 3670e6b6b59SJacob Faibussowitsch PetscFunctionBegin; 368ed170139SJacob Faibussowitsch if (fl) { 369ed170139SJacob Faibussowitsch PetscHMapFuncForEach(fl, name, func, PetscCall(PetscFree(name))); 370ed170139SJacob Faibussowitsch PetscCall(PetscHMapFuncClear(fl->map)); 3710e6b6b59SJacob Faibussowitsch } 3723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3730e6b6b59SJacob Faibussowitsch } 3740e6b6b59SJacob Faibussowitsch 375e5c89e4eSSatish Balay /* 3762e956fe4SStefano Zampini Print registered PetscFunctionLists 377e5c89e4eSSatish Balay */ 378d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFunctionListPrintAll(void) 379d71ae5a4SJacob Faibussowitsch { 380ed170139SJacob Faibussowitsch PetscFunctionListDLAll current = dlallhead; 381e5c89e4eSSatish Balay 382e5c89e4eSSatish Balay PetscFunctionBegin; 383ed170139SJacob Faibussowitsch if (current) PetscCall(PetscPrintf(PETSC_COMM_SELF, "[%d] Registered PetscFunctionLists\n", PetscGlobalRank)); 384ed170139SJacob Faibussowitsch while (current) { 385ed170139SJacob Faibussowitsch PetscCall(PetscFunctionListPrintNonEmpty(current->data)); 386ed170139SJacob Faibussowitsch current = current->next; 38737e93019SBarry Smith } 3883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 389e5c89e4eSSatish Balay } 390e5c89e4eSSatish Balay 39110450e9eSJacob Faibussowitsch /*@C 39210450e9eSJacob Faibussowitsch PetscFunctionListPrintNonEmpty - Print composed names for non `NULL` function pointers 3932e956fe4SStefano Zampini 394cc4c1da9SBarry Smith Logically Collective, No Fortran Support 395cc4c1da9SBarry Smith 3962e956fe4SStefano Zampini Input Parameter: 39710450e9eSJacob Faibussowitsch . fl - the function list 3982e956fe4SStefano Zampini 3992e956fe4SStefano Zampini Level: developer 4002e956fe4SStefano Zampini 4012e956fe4SStefano Zampini .seealso: `PetscFunctionListAdd()`, `PetscFunctionList`, `PetscObjectQueryFunction()` 40210450e9eSJacob Faibussowitsch @*/ 403d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFunctionListPrintNonEmpty(PetscFunctionList fl) 404d71ae5a4SJacob Faibussowitsch { 4052e956fe4SStefano Zampini PetscFunctionBegin; 406ed170139SJacob Faibussowitsch if (fl) { 407ed170139SJacob Faibussowitsch // clang-format off 408ed170139SJacob Faibussowitsch PetscHMapFuncForEach( 409ed170139SJacob Faibussowitsch fl, 410ed170139SJacob Faibussowitsch name, func, 411ed170139SJacob Faibussowitsch PetscCall(PetscFPrintf(PETSC_COMM_SELF, PETSC_STDOUT, "[%d] function name: %s\n", PetscGlobalRank, name)); 412ed170139SJacob Faibussowitsch ); 413ed170139SJacob Faibussowitsch // clang-format on 4142e956fe4SStefano Zampini } 4153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4162e956fe4SStefano Zampini } 4172e956fe4SStefano Zampini 4182e956fe4SStefano Zampini /*MC 4191c9cd337SJed Brown PetscFunctionListFind - Find function registered under given name 4201c9cd337SJed Brown 421cc4c1da9SBarry Smith Not Collective, No Fortran Support 422cc4c1da9SBarry Smith 4231c9cd337SJed Brown Synopsis: 424aaa7dc30SBarry Smith #include <petscsys.h> 4251c9cd337SJed Brown PetscErrorCode PetscFunctionListFind(PetscFunctionList flist,const char name[],void (**fptr)(void)) 426e5c89e4eSSatish Balay 427e5c89e4eSSatish Balay Input Parameters: 42810450e9eSJacob Faibussowitsch + fl - the function list 4291c9cd337SJed Brown - name - name registered for the function 430e5c89e4eSSatish Balay 4312fe279fdSBarry Smith Output Parameter: 43221532e8aSBarry Smith . fptr - the function pointer if name was found, else `NULL` 433e5c89e4eSSatish Balay 434e5c89e4eSSatish Balay Level: developer 435e5c89e4eSSatish Balay 43621532e8aSBarry Smith .seealso: `PetscFunctionListAdd()`, `PetscFunctionList`, `PetscObjectQueryFunction()`, `PetscFunctionListDuplicate()` 4371c9cd337SJed Brown M*/ 4388434afd1SBarry Smith PetscErrorCode PetscFunctionListFind_Private(PetscFunctionList fl, const char name[], PetscVoidFn **fptr) 439d71ae5a4SJacob Faibussowitsch { 440e5c89e4eSSatish Balay PetscFunctionBegin; 4414f572ea9SToby Isaac PetscAssertPointer(name, 2); 4424f572ea9SToby Isaac PetscAssertPointer(fptr, 3); 44310450e9eSJacob Faibussowitsch *fptr = NULL; 44410450e9eSJacob Faibussowitsch if (fl) PetscCall(PetscHMapFuncGet(fl->map, name, fptr)); 4453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 446e5c89e4eSSatish Balay } 447e5c89e4eSSatish Balay 448ffeef943SBarry Smith /*@C 44920f4b53cSBarry Smith PetscFunctionListView - prints out contents of a `PetscFunctionList` 450e5c89e4eSSatish Balay 45120f4b53cSBarry Smith Collective 452e5c89e4eSSatish Balay 453e5c89e4eSSatish Balay Input Parameters: 454e5c89e4eSSatish Balay + list - the list of functions 45520f4b53cSBarry Smith - viewer - the `PetscViewer` used to view the `PetscFunctionList` 456e5c89e4eSSatish Balay 457e5c89e4eSSatish Balay Level: developer 458e5c89e4eSSatish Balay 459db781477SPatrick Sanan .seealso: `PetscFunctionListAdd()`, `PetscFunctionListPrintTypes()`, `PetscFunctionList` 460e5c89e4eSSatish Balay @*/ 461d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFunctionListView(PetscFunctionList list, PetscViewer viewer) 462d71ae5a4SJacob Faibussowitsch { 463*9f196a02SMartin Diehl PetscBool isascii; 464e5c89e4eSSatish Balay 465e5c89e4eSSatish Balay PetscFunctionBegin; 4664f572ea9SToby Isaac PetscAssertPointer(list, 1); 467ed170139SJacob Faibussowitsch if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PETSC_COMM_SELF, &viewer)); 4680700a824SBarry Smith PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 469e5c89e4eSSatish Balay 470*9f196a02SMartin Diehl PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 471*9f196a02SMartin Diehl PetscCheck(isascii, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only ASCII viewer supported"); 472ed170139SJacob Faibussowitsch { 473ed170139SJacob Faibussowitsch PetscInt size; 474e5c89e4eSSatish Balay 475ed170139SJacob Faibussowitsch PetscCall(PetscHMapFuncGetSize(list->map, &size)); 476ed170139SJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "PetscFunctionList Object:\n")); 477ed170139SJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 478ed170139SJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "size: %" PetscInt_FMT "\n", size)); 479ed170139SJacob Faibussowitsch if (size) { 480ed170139SJacob Faibussowitsch PetscInt count = 0; 481ed170139SJacob Faibussowitsch 482ed170139SJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "functions:\n")); 483ed170139SJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 484ed170139SJacob Faibussowitsch PetscHMapFuncForEach(list, name, func, PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT ": %s\n", ++count, name))); 485ed170139SJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 486e5c89e4eSSatish Balay } 487ed170139SJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 488ed170139SJacob Faibussowitsch } 4893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 490e5c89e4eSSatish Balay } 491e5c89e4eSSatish Balay 492065533a5SJed Brown /*@C 493811af0c4SBarry Smith PetscFunctionListGet - Gets an array the contains the entries in `PetscFunctionList`, this is used 494e5c89e4eSSatish Balay by help etc. 495e5c89e4eSSatish Balay 496cc4c1da9SBarry Smith Not Collective, No Fortran Support 497e5c89e4eSSatish Balay 498e5c89e4eSSatish Balay Input Parameter: 499e5c89e4eSSatish Balay . list - list of types 500e5c89e4eSSatish Balay 501d8d19677SJose E. Roman Output Parameters: 502e5c89e4eSSatish Balay + array - array of names 50321532e8aSBarry Smith - n - length of `array` 50421532e8aSBarry Smith 50521532e8aSBarry Smith Level: developer 506e5c89e4eSSatish Balay 507811af0c4SBarry Smith Note: 508a3b724e8SBarry Smith This allocates the array so that must be freed with `PetscFree()`. BUT the individual entries should not be freed. 509e5c89e4eSSatish Balay 510db781477SPatrick Sanan .seealso: `PetscFunctionListAdd()`, `PetscFunctionList` 511e5c89e4eSSatish Balay @*/ 512d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFunctionListGet(PetscFunctionList list, const char ***array, int *n) 513d71ae5a4SJacob Faibussowitsch { 514ed170139SJacob Faibussowitsch PetscInt size = 0; 515e5c89e4eSSatish Balay 516e5c89e4eSSatish Balay PetscFunctionBegin; 5174f572ea9SToby Isaac PetscAssertPointer(array, 2); 518ed170139SJacob Faibussowitsch *array = NULL; 519ed170139SJacob Faibussowitsch if (list) { 520ed170139SJacob Faibussowitsch const PetscHMapFunc map = list->map; 521ed170139SJacob Faibussowitsch PetscInt off = 0; 522ed170139SJacob Faibussowitsch 523ed170139SJacob Faibussowitsch PetscCall(PetscHMapFuncGetSize(map, &size)); 524ed170139SJacob Faibussowitsch PetscCall(PetscMalloc1(size, (char ***)array)); 525ed170139SJacob Faibussowitsch PetscCall(PetscHMapFuncGetKeys(map, &off, *array)); 526e5c89e4eSSatish Balay } 527835f2295SStefano Zampini PetscCall(PetscCIntCast(size, n)); 5283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 529e5c89e4eSSatish Balay } 530e5c89e4eSSatish Balay 531e5c89e4eSSatish Balay /*@C 532811af0c4SBarry Smith PetscFunctionListPrintTypes - Prints the methods available in a list of functions 533e5c89e4eSSatish Balay 534cc4c1da9SBarry Smith Collective, No Fortran Support 535e5c89e4eSSatish Balay 536e5c89e4eSSatish Balay Input Parameters: 537811af0c4SBarry Smith + comm - the communicator (usually `MPI_COMM_WORLD`) 53821532e8aSBarry Smith . fd - file to print to, usually `stdout` 539e5c89e4eSSatish Balay . prefix - prefix to prepend to name (optional) 54021532e8aSBarry Smith . name - option string (for example, `-ksp_type`) 541e5c89e4eSSatish Balay . text - short description of the object (for example, "Krylov solvers") 54221532e8aSBarry Smith . man - name of manual page that discusses the object (for example, `KSPCreate`) 5433cc1e11dSBarry Smith . list - list of types 54444ef3d73SBarry Smith . def - default (current) value 54544ef3d73SBarry Smith - newv - new value 546e5c89e4eSSatish Balay 547e5c89e4eSSatish Balay Level: developer 548e5c89e4eSSatish Balay 549db781477SPatrick Sanan .seealso: `PetscFunctionListAdd()`, `PetscFunctionList` 550e5c89e4eSSatish Balay @*/ 551d71ae5a4SJacob 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[]) 552d71ae5a4SJacob Faibussowitsch { 553e5c89e4eSSatish Balay char p[64]; 554e5c89e4eSSatish Balay 555e5c89e4eSSatish Balay PetscFunctionBegin; 556ed170139SJacob Faibussowitsch (void)fd; 5579566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(p, "-", sizeof(p))); 5589566063dSJacob Faibussowitsch if (prefix) PetscCall(PetscStrlcat(p, prefix, sizeof(p))); 559ed170139SJacob Faibussowitsch PetscCall((*PetscHelpPrintf)(comm, " %s%s <now %s : formerly %s>: %s (one of)", p, name + 1, newv, def, text)); 560e5c89e4eSSatish Balay 5618c7e48aeSJacob Faibussowitsch if (list) PetscHMapFuncForEach(list, name, func, PetscCall((*PetscHelpPrintf)(comm, " %s", name))); 562ed170139SJacob Faibussowitsch PetscCall((*PetscHelpPrintf)(comm, " (%s)\n", man)); 5633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 564e5c89e4eSSatish Balay } 565e5c89e4eSSatish Balay 566ffeef943SBarry Smith /*@C 56721532e8aSBarry Smith PetscFunctionListDuplicate - Creates a new list from a given function list `PetscFunctionList`. 568e5c89e4eSSatish Balay 5692fe279fdSBarry Smith Input Parameter: 570e5c89e4eSSatish Balay . fl - pointer to list 571e5c89e4eSSatish Balay 5722fe279fdSBarry Smith Output Parameter: 57321532e8aSBarry Smith . nl - the new list (should point to `NULL` to start, otherwise appends) 574e5c89e4eSSatish Balay 575e5c89e4eSSatish Balay Level: developer 576e5c89e4eSSatish Balay 577db781477SPatrick Sanan .seealso: `PetscFunctionList`, `PetscFunctionListAdd()`, `PetscFlistDestroy()` 578e5c89e4eSSatish Balay @*/ 579d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFunctionListDuplicate(PetscFunctionList fl, PetscFunctionList *nl) 580d71ae5a4SJacob Faibussowitsch { 581e5c89e4eSSatish Balay PetscFunctionBegin; 582ed170139SJacob Faibussowitsch if (fl) { 583ed170139SJacob Faibussowitsch PetscHMapFunc dup_map; 584ed170139SJacob Faibussowitsch 585ed170139SJacob Faibussowitsch if (!*nl) { 586ed170139SJacob Faibussowitsch PetscInt n; 587ed170139SJacob Faibussowitsch 588ed170139SJacob Faibussowitsch PetscCall(PetscHMapFuncGetSize(fl->map, &n)); 589ed170139SJacob Faibussowitsch PetscCall(PetscFunctionListCreate_Private(n, nl)); 590ed170139SJacob Faibussowitsch } 591ed170139SJacob Faibussowitsch dup_map = (*nl)->map; 592ed170139SJacob Faibussowitsch PetscHMapFuncForEach(fl, name, func, PetscCall(PetscHMapFuncInsert_Private(dup_map, name, func))); 593e5c89e4eSSatish Balay } 5943ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 595e5c89e4eSSatish Balay } 596