17d0a6c19SBarry Smith 2e5c89e4eSSatish Balay /* 3e5c89e4eSSatish Balay Provides a general mechanism to allow one to register new routines in 4e5c89e4eSSatish Balay dynamic libraries for many of the PETSc objects (including, e.g., KSP and PC). 5e5c89e4eSSatish Balay */ 6af0996ceSBarry Smith #include <petsc/private/petscimpl.h> /*I "petscsys.h" I*/ 7665c2dedSJed Brown #include <petscviewer.h> 8e5c89e4eSSatish Balay 9ed170139SJacob Faibussowitsch #include <petsc/private/hashmap.h> 103fa76a5bSLisandro Dalcin /* 113fa76a5bSLisandro Dalcin This is the default list used by PETSc with the PetscDLLibrary register routines 123fa76a5bSLisandro Dalcin */ 1302c9f0b5SLisandro Dalcin PetscDLLibrary PetscDLLibrariesLoaded = NULL; 143fa76a5bSLisandro Dalcin 15cbd104e6SBarry Smith #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES) 16ebd79076SLisandro Dalcin 17d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLoadDynamicLibrary(const char *name, PetscBool *found) 18d71ae5a4SJacob Faibussowitsch { 19487e5849SBarry Smith char libs[PETSC_MAX_PATH_LEN], dlib[PETSC_MAX_PATH_LEN]; 20487e5849SBarry Smith 21487e5849SBarry Smith PetscFunctionBegin; 229566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(libs, "${PETSC_LIB_DIR}/libpetsc", sizeof(libs))); 239566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(libs, name, sizeof(libs))); 249566063dSJacob Faibussowitsch PetscCall(PetscDLLibraryRetrieve(PETSC_COMM_WORLD, libs, dlib, 1024, found)); 25487e5849SBarry Smith if (*found) { 269566063dSJacob Faibussowitsch PetscCall(PetscDLLibraryAppend(PETSC_COMM_WORLD, &PetscDLLibrariesLoaded, dlib)); 27487e5849SBarry Smith } else { 289566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(libs, "${PETSC_DIR}/${PETSC_ARCH}/lib/libpetsc", sizeof(libs))); 299566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(libs, name, sizeof(libs))); 309566063dSJacob Faibussowitsch PetscCall(PetscDLLibraryRetrieve(PETSC_COMM_WORLD, libs, dlib, 1024, found)); 3148a46eb9SPierre Jolivet if (*found) PetscCall(PetscDLLibraryAppend(PETSC_COMM_WORLD, &PetscDLLibrariesLoaded, dlib)); 32487e5849SBarry Smith } 333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 34487e5849SBarry Smith } 353fa76a5bSLisandro Dalcin #endif 363fa76a5bSLisandro Dalcin 3760da17ecSBarry Smith #if defined(PETSC_USE_SINGLE_LIBRARY) && !(defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES)) 3895c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode AOInitializePackage(void); 3995c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscSFInitializePackage(void); 407da51e29SSatish Balay #if !defined(PETSC_USE_COMPLEX) 4195c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode CharacteristicInitializePackage(void); 427da51e29SSatish Balay #endif 4395c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode ISInitializePackage(void); 4495c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode VecInitializePackage(void); 4595c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode MatInitializePackage(void); 4695c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode DMInitializePackage(void); 4795c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode PCInitializePackage(void); 4895c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode KSPInitializePackage(void); 4995c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode SNESInitializePackage(void); 5095c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode TSInitializePackage(void); 5160da17ecSBarry Smith PETSC_EXTERN PetscErrorCode TaoInitializePackage(void); 5260da17ecSBarry Smith #endif 53acff04ddSBarry Smith 54e5c89e4eSSatish Balay /* 55e5c89e4eSSatish Balay PetscInitialize_DynamicLibraries - Adds the default dynamic link libraries to the 56e5c89e4eSSatish Balay search path. 57e5c89e4eSSatish Balay */ 58d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode PetscInitialize_DynamicLibraries(void) 59d71ae5a4SJacob Faibussowitsch { 60487e5849SBarry Smith char *libname[32]; 61e5c89e4eSSatish Balay PetscInt nmax, i; 6260da17ecSBarry Smith PetscBool preload = PETSC_FALSE; 63540e20f2SPierre Jolivet #if defined(PETSC_HAVE_ELEMENTAL) 64540e20f2SPierre Jolivet PetscBool PetscInitialized = PetscInitializeCalled; 65540e20f2SPierre Jolivet #endif 66e5c89e4eSSatish Balay 6760154eb2SBarry Smith PetscFunctionBegin; 6860da17ecSBarry Smith #if defined(PETSC_HAVE_THREADSAFETY) 6960da17ecSBarry Smith /* These must be all initialized here because it is not safe for individual threads to call these initialize routines */ 7060da17ecSBarry Smith preload = PETSC_TRUE; 7160da17ecSBarry Smith #endif 7260da17ecSBarry Smith 73e5c89e4eSSatish Balay nmax = 32; 749566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetStringArray(NULL, NULL, "-dll_prepend", libname, &nmax, NULL)); 75e5c89e4eSSatish Balay for (i = 0; i < nmax; i++) { 769566063dSJacob Faibussowitsch PetscCall(PetscDLLibraryPrepend(PETSC_COMM_WORLD, &PetscDLLibrariesLoaded, libname[i])); 779566063dSJacob Faibussowitsch PetscCall(PetscFree(libname[i])); 78e5c89e4eSSatish Balay } 79e5c89e4eSSatish Balay 809566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-library_preload", &preload, NULL)); 8160da17ecSBarry Smith if (!preload) { 829566063dSJacob Faibussowitsch PetscCall(PetscSysInitializePackage()); 8360da17ecSBarry Smith } else { 8460da17ecSBarry Smith #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES) 85aa2d57e9SJed Brown PetscBool found; 8660154eb2SBarry Smith #if defined(PETSC_USE_SINGLE_LIBRARY) 879566063dSJacob Faibussowitsch PetscCall(PetscLoadDynamicLibrary("", &found)); 8828b400f6SJacob Faibussowitsch PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc dynamic library \n You cannot move the dynamic libraries!"); 8960154eb2SBarry Smith #else 909566063dSJacob Faibussowitsch PetscCall(PetscLoadDynamicLibrary("sys", &found)); 9128b400f6SJacob Faibussowitsch PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc dynamic library \n You cannot move the dynamic libraries!"); 929566063dSJacob Faibussowitsch PetscCall(PetscLoadDynamicLibrary("vec", &found)); 9328b400f6SJacob Faibussowitsch PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc Vec dynamic library \n You cannot move the dynamic libraries!"); 949566063dSJacob Faibussowitsch PetscCall(PetscLoadDynamicLibrary("mat", &found)); 9528b400f6SJacob Faibussowitsch PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc Mat dynamic library \n You cannot move the dynamic libraries!"); 969566063dSJacob Faibussowitsch PetscCall(PetscLoadDynamicLibrary("dm", &found)); 9728b400f6SJacob Faibussowitsch PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc DM dynamic library \n You cannot move the dynamic libraries!"); 989566063dSJacob Faibussowitsch PetscCall(PetscLoadDynamicLibrary("ksp", &found)); 9928b400f6SJacob Faibussowitsch PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc KSP dynamic library \n You cannot move the dynamic libraries!"); 1009566063dSJacob Faibussowitsch PetscCall(PetscLoadDynamicLibrary("snes", &found)); 10128b400f6SJacob Faibussowitsch PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc SNES dynamic library \n You cannot move the dynamic libraries!"); 1029566063dSJacob Faibussowitsch PetscCall(PetscLoadDynamicLibrary("ts", &found)); 10328b400f6SJacob Faibussowitsch PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc TS dynamic library \n You cannot move the dynamic libraries!"); 1049566063dSJacob Faibussowitsch PetscCall(PetscLoadDynamicLibrary("tao", &found)); 10528b400f6SJacob Faibussowitsch PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate Tao dynamic library \n You cannot move the dynamic libraries!"); 106bb84e0fdSBarry Smith #endif 10760da17ecSBarry Smith #else /* defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES) */ 10860da17ecSBarry Smith #if defined(PETSC_USE_SINGLE_LIBRARY) 1099566063dSJacob Faibussowitsch PetscCall(AOInitializePackage()); 1109566063dSJacob Faibussowitsch PetscCall(PetscSFInitializePackage()); 1117da51e29SSatish Balay #if !defined(PETSC_USE_COMPLEX) 1129566063dSJacob Faibussowitsch PetscCall(CharacteristicInitializePackage()); 1137da51e29SSatish Balay #endif 1149566063dSJacob Faibussowitsch PetscCall(ISInitializePackage()); 1159566063dSJacob Faibussowitsch PetscCall(VecInitializePackage()); 1169566063dSJacob Faibussowitsch PetscCall(MatInitializePackage()); 1179566063dSJacob Faibussowitsch PetscCall(DMInitializePackage()); 1189566063dSJacob Faibussowitsch PetscCall(PCInitializePackage()); 1199566063dSJacob Faibussowitsch PetscCall(KSPInitializePackage()); 1209566063dSJacob Faibussowitsch PetscCall(SNESInitializePackage()); 1219566063dSJacob Faibussowitsch PetscCall(TSInitializePackage()); 1229566063dSJacob Faibussowitsch PetscCall(TaoInitializePackage()); 12360da17ecSBarry Smith #else 12460da17ecSBarry Smith SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP, "Cannot use -library_preload with multiple static PETSc libraries"); 12560da17ecSBarry Smith #endif 12660da17ecSBarry Smith #endif /* defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES) */ 12760da17ecSBarry Smith } 12860da17ecSBarry Smith 12960da17ecSBarry Smith #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES) && defined(PETSC_HAVE_BAMG) 13060da17ecSBarry Smith { 13160da17ecSBarry Smith PetscBool found; 1329566063dSJacob Faibussowitsch PetscCall(PetscLoadDynamicLibrary("bamg", &found)); 13328b400f6SJacob Faibussowitsch PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc BAMG dynamic library \n You cannot move the dynamic libraries!"); 13460da17ecSBarry Smith } 13560da17ecSBarry Smith #endif 13660da17ecSBarry Smith 13760da17ecSBarry Smith nmax = 32; 1389566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetStringArray(NULL, NULL, "-dll_append", libname, &nmax, NULL)); 13960da17ecSBarry Smith for (i = 0; i < nmax; i++) { 1409566063dSJacob Faibussowitsch PetscCall(PetscDLLibraryAppend(PETSC_COMM_WORLD, &PetscDLLibrariesLoaded, libname[i])); 1419566063dSJacob Faibussowitsch PetscCall(PetscFree(libname[i])); 14260da17ecSBarry Smith } 14360da17ecSBarry Smith 144540e20f2SPierre Jolivet #if defined(PETSC_HAVE_ELEMENTAL) 145540e20f2SPierre Jolivet /* in Fortran, PetscInitializeCalled is set to PETSC_TRUE before PetscInitialize_DynamicLibraries() */ 146540e20f2SPierre Jolivet /* in C, it is not the case, but the value is forced to PETSC_TRUE so that PetscRegisterFinalize() is called */ 147540e20f2SPierre Jolivet PetscInitializeCalled = PETSC_TRUE; 1489566063dSJacob Faibussowitsch PetscCall(PetscElementalInitializePackage()); 149540e20f2SPierre Jolivet PetscInitializeCalled = PetscInitialized; 150540e20f2SPierre Jolivet #endif 1513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 152e5c89e4eSSatish Balay } 153e5c89e4eSSatish Balay 154ebd79076SLisandro Dalcin /* 155ebd79076SLisandro Dalcin PetscFinalize_DynamicLibraries - Closes the opened dynamic libraries. 156ebd79076SLisandro Dalcin */ 157d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode PetscFinalize_DynamicLibraries(void) 158d71ae5a4SJacob Faibussowitsch { 159ace3abfcSBarry Smith PetscBool flg = PETSC_FALSE; 160e5c89e4eSSatish Balay 161ebd79076SLisandro Dalcin PetscFunctionBegin; 1629566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-dll_view", &flg, NULL)); 1639566063dSJacob Faibussowitsch if (flg) PetscCall(PetscDLLibraryPrintPath(PetscDLLibrariesLoaded)); 1649566063dSJacob Faibussowitsch PetscCall(PetscDLLibraryClose(PetscDLLibrariesLoaded)); 16502c9f0b5SLisandro Dalcin PetscDLLibrariesLoaded = NULL; 1663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 167e5c89e4eSSatish Balay } 168e5c89e4eSSatish Balay 169e5c89e4eSSatish Balay /* ------------------------------------------------------------------------------*/ 170ed170139SJacob Faibussowitsch PETSC_HASH_MAP(HMapFunc, const char *, PetscVoidFunction, kh_str_hash_func, kh_str_hash_equal, NULL) 171ed170139SJacob Faibussowitsch 172140e18c1SBarry Smith struct _n_PetscFunctionList { 173ed170139SJacob Faibussowitsch PetscHMapFunc map; 174e5c89e4eSSatish Balay }; 175e5c89e4eSSatish Balay 176ed170139SJacob Faibussowitsch /* Keep a linked list of PetscFunctionLists so that we can destroy all the left-over ones. */ 177ed170139SJacob Faibussowitsch typedef struct n_PetscFunctionListDLAll *PetscFunctionListDLAll; 178ed170139SJacob Faibussowitsch struct n_PetscFunctionListDLAll { 179ed170139SJacob Faibussowitsch PetscFunctionList data; 180ed170139SJacob Faibussowitsch PetscFunctionListDLAll next; 181ed170139SJacob Faibussowitsch }; 182e5c89e4eSSatish Balay 183ed170139SJacob Faibussowitsch static PetscFunctionListDLAll dlallhead = NULL; 184ed170139SJacob Faibussowitsch 185ed170139SJacob Faibussowitsch static PetscErrorCode PetscFunctionListDLAllPush_Private(PetscFunctionList fl) 186d71ae5a4SJacob Faibussowitsch { 1870e6b6b59SJacob Faibussowitsch PetscFunctionBegin; 188ed170139SJacob Faibussowitsch if (PetscDefined(USE_DEBUG) && !PetscDefined(HAVE_THREADSAFETY)) { 189ed170139SJacob Faibussowitsch PetscFunctionListDLAll head; 190ed170139SJacob Faibussowitsch 191ed170139SJacob Faibussowitsch PetscCall(PetscNew(&head)); 192ed170139SJacob Faibussowitsch head->data = fl; 193ed170139SJacob Faibussowitsch head->next = dlallhead; 194ed170139SJacob Faibussowitsch dlallhead = head; 195ed170139SJacob Faibussowitsch } 1963ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 197ed170139SJacob Faibussowitsch } 198ed170139SJacob Faibussowitsch 199ed170139SJacob Faibussowitsch static PetscErrorCode PetscFunctionListDLAllPop_Private(PetscFunctionList fl) 200ed170139SJacob Faibussowitsch { 201ed170139SJacob Faibussowitsch PetscFunctionBegin; 202ed170139SJacob Faibussowitsch if (PetscDefined(USE_DEBUG) && !PetscDefined(HAVE_THREADSAFETY)) { 203ed170139SJacob Faibussowitsch PetscFunctionListDLAll current = dlallhead, prev = NULL; 204ed170139SJacob Faibussowitsch 205ed170139SJacob Faibussowitsch /* Remove this entry from the main DL list (if it is in it) */ 206ed170139SJacob Faibussowitsch while (current) { 207ed170139SJacob Faibussowitsch const PetscFunctionListDLAll next = current->next; 208ed170139SJacob Faibussowitsch 209ed170139SJacob Faibussowitsch if (current->data == fl) { 210ed170139SJacob Faibussowitsch if (prev) { 211ed170139SJacob Faibussowitsch // somewhere in the middle (or end) of the list 212ed170139SJacob Faibussowitsch prev->next = next; 213ed170139SJacob Faibussowitsch } else { 214ed170139SJacob Faibussowitsch // prev = NULL implies current = dlallhead, so front of list 215ed170139SJacob Faibussowitsch dlallhead = next; 216ed170139SJacob Faibussowitsch } 217ed170139SJacob Faibussowitsch PetscCall(PetscFree(current)); 218ed170139SJacob Faibussowitsch break; 219ed170139SJacob Faibussowitsch } 220ed170139SJacob Faibussowitsch prev = current; 221ed170139SJacob Faibussowitsch current = next; 222ed170139SJacob Faibussowitsch } 223ed170139SJacob Faibussowitsch } 2243ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 225ed170139SJacob Faibussowitsch } 226ed170139SJacob Faibussowitsch 227ed170139SJacob Faibussowitsch static PetscErrorCode PetscHMapFuncInsert_Private(PetscHMapFunc map, const char name[], PetscVoidFunction fnc) 228ed170139SJacob Faibussowitsch { 229ed170139SJacob Faibussowitsch PetscHashIter it; 230ed170139SJacob Faibussowitsch PetscBool found; 231ed170139SJacob Faibussowitsch 232ed170139SJacob Faibussowitsch PetscFunctionBegin; 233ed170139SJacob Faibussowitsch PetscValidCharPointer(name, 2); 234ed170139SJacob Faibussowitsch if (fnc) PetscValidFunction(fnc, 3); 235ed170139SJacob Faibussowitsch PetscCall(PetscHMapFuncFind(map, name, &it, &found)); 236ed170139SJacob Faibussowitsch if (fnc) { 237ed170139SJacob Faibussowitsch if (found) { 238ed170139SJacob Faibussowitsch PetscCall(PetscHMapFuncIterSet(map, it, fnc)); 239ed170139SJacob Faibussowitsch } else { 240ed170139SJacob Faibussowitsch char *tmp_name; 241ed170139SJacob Faibussowitsch 242ed170139SJacob Faibussowitsch PetscCall(PetscStrallocpy(name, &tmp_name)); 243ed170139SJacob Faibussowitsch PetscCall(PetscHMapFuncSet(map, tmp_name, fnc)); 244ed170139SJacob Faibussowitsch } 245ed170139SJacob Faibussowitsch } else if (found) { 246ed170139SJacob Faibussowitsch const char *tmp_name; 247ed170139SJacob Faibussowitsch 248ed170139SJacob Faibussowitsch PetscHashIterGetKey(map, it, tmp_name); 249ed170139SJacob Faibussowitsch PetscCall(PetscFree(tmp_name)); 250ed170139SJacob Faibussowitsch PetscCall(PetscHMapFuncIterDel(map, it)); 251ed170139SJacob Faibussowitsch } 2523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 253ed170139SJacob Faibussowitsch } 254ed170139SJacob Faibussowitsch 255ed170139SJacob Faibussowitsch static PetscErrorCode PetscFunctionListCreate_Private(PetscInt size, PetscFunctionList *fl) 256ed170139SJacob Faibussowitsch { 257ed170139SJacob Faibussowitsch PetscFunctionBegin; 2583ba16761SJacob Faibussowitsch if (*fl) PetscFunctionReturn(PETSC_SUCCESS); 259ed170139SJacob Faibussowitsch PetscCall(PetscNew(fl)); 260ed170139SJacob Faibussowitsch PetscCall(PetscHMapFuncCreateWithSize(size, &(*fl)->map)); 261ed170139SJacob Faibussowitsch PetscCall(PetscFunctionListDLAllPush_Private(*fl)); 2623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2630e6b6b59SJacob Faibussowitsch } 2640e6b6b59SJacob Faibussowitsch 265a240a19fSJed Brown /*MC 266140e18c1SBarry Smith PetscFunctionListAdd - Given a routine and a string id, saves that routine in the 267e5c89e4eSSatish Balay specified registry. 268e5c89e4eSSatish Balay 269a240a19fSJed Brown Synopsis: 270aaa7dc30SBarry Smith #include <petscsys.h> 271b9fb364aSBarry Smith PetscErrorCode PetscFunctionListAdd(PetscFunctionList *flist,const char name[],void (*fptr)(void)) 272a240a19fSJed Brown 273d4349b43SBarry Smith Not Collective 274e5c89e4eSSatish Balay 275e5c89e4eSSatish Balay Input Parameters: 276b9fb364aSBarry Smith + flist - pointer to function list object 277e5c89e4eSSatish Balay . name - string to identify routine 278a240a19fSJed Brown - fptr - function pointer 279e5c89e4eSSatish Balay 280e5c89e4eSSatish Balay Notes: 281a240a19fSJed Brown To remove a registered routine, pass in a NULL fptr. 282e5c89e4eSSatish Balay 283e5c89e4eSSatish Balay Users who wish to register new classes for use by a particular PETSc 284811af0c4SBarry Smith component (e.g., `SNES`) should generally call the registration routine 285811af0c4SBarry Smith for that particular component (e.g., `SNESRegister()`) instead of 286811af0c4SBarry Smith calling `PetscFunctionListAdd()` directly. 287e5c89e4eSSatish Balay 288e5c89e4eSSatish Balay Level: developer 289e5c89e4eSSatish Balay 290db781477SPatrick Sanan .seealso: `PetscFunctionListDestroy()`, `SNESRegister()`, `KSPRegister()`, 291db781477SPatrick Sanan `PCRegister()`, `TSRegister()`, `PetscFunctionList`, `PetscObjectComposeFunction()` 292a240a19fSJed Brown M*/ 293ed170139SJacob Faibussowitsch PetscErrorCode PetscFunctionListAdd_Private(PetscFunctionList *fl, const char name[], PetscVoidFunction fnc) 294d71ae5a4SJacob Faibussowitsch { 295e5c89e4eSSatish Balay PetscFunctionBegin; 2960e6b6b59SJacob Faibussowitsch PetscValidPointer(fl, 1); 2970e6b6b59SJacob Faibussowitsch if (name) PetscValidCharPointer(name, 2); 2980e6b6b59SJacob Faibussowitsch if (fnc) PetscValidFunction(fnc, 3); 299ed170139SJacob Faibussowitsch PetscCall(PetscFunctionListCreate_Private(0, fl)); 300ed170139SJacob Faibussowitsch PetscCall(PetscHMapFuncInsert_Private((*fl)->map, name, fnc)); 3013ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 302e5c89e4eSSatish Balay } 303e5c89e4eSSatish Balay 304e5c89e4eSSatish Balay /*@ 305140e18c1SBarry Smith PetscFunctionListDestroy - Destroys a list of registered routines. 306e5c89e4eSSatish Balay 307e5c89e4eSSatish Balay Input Parameter: 308e5c89e4eSSatish Balay . fl - pointer to list 309e5c89e4eSSatish Balay 310e5c89e4eSSatish Balay Level: developer 311e5c89e4eSSatish Balay 3120e6b6b59SJacob Faibussowitsch .seealso: `PetscFunctionListAdd()`, `PetscFunctionList`, `PetscFunctionListClear()` 313e5c89e4eSSatish Balay @*/ 314d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFunctionListDestroy(PetscFunctionList *fl) 315d71ae5a4SJacob Faibussowitsch { 316e5c89e4eSSatish Balay PetscFunctionBegin; 3173ba16761SJacob Faibussowitsch if (!*fl) PetscFunctionReturn(PETSC_SUCCESS); 318ed170139SJacob Faibussowitsch PetscCall(PetscFunctionListDLAllPop_Private(*fl)); 319e5c89e4eSSatish Balay /* free this list */ 320ed170139SJacob Faibussowitsch PetscCall(PetscFunctionListClear(*fl)); 321ed170139SJacob Faibussowitsch PetscCall(PetscHMapFuncDestroy(&(*fl)->map)); 322ed170139SJacob Faibussowitsch PetscCall(PetscFree(*fl)); 3233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 324e5c89e4eSSatish Balay } 325e5c89e4eSSatish Balay 326ed170139SJacob Faibussowitsch #define PetscHMapFuncForEach(__func_list__, __key_name__, __val_name__, ...) \ 327ed170139SJacob Faibussowitsch do { \ 328ed170139SJacob Faibussowitsch const PetscHMapFunc phmfi_map_ = (__func_list__)->map; \ 329ed170139SJacob Faibussowitsch PetscHashIter phmfi_iter_; \ 330ed170139SJacob Faibussowitsch \ 331ed170139SJacob Faibussowitsch PetscHashIterBegin(phmfi_map_, phmfi_iter_); \ 332ed170139SJacob Faibussowitsch while (!PetscHashIterAtEnd(phmfi_map_, phmfi_iter_)) { \ 333ed170139SJacob Faibussowitsch const char *PETSC_UNUSED __key_name__; \ 334ed170139SJacob Faibussowitsch PetscVoidFunction PETSC_UNUSED __val_name__; \ 335ed170139SJacob Faibussowitsch \ 336ed170139SJacob Faibussowitsch PetscHashIterGetKey(phmfi_map_, phmfi_iter_, __key_name__); \ 337ed170139SJacob Faibussowitsch PetscHashIterGetVal(phmfi_map_, phmfi_iter_, __val_name__); \ 338ed170139SJacob Faibussowitsch { \ 339ed170139SJacob Faibussowitsch __VA_ARGS__; \ 340ed170139SJacob Faibussowitsch } \ 341ed170139SJacob Faibussowitsch PetscHashIterNext(phmfi_map_, phmfi_iter_); \ 342ed170139SJacob Faibussowitsch } /* end while */ \ 343ed170139SJacob Faibussowitsch } while (0) 344ed170139SJacob Faibussowitsch 3450e6b6b59SJacob Faibussowitsch /*@ 3460e6b6b59SJacob Faibussowitsch PetscFunctionListClear - Clear a `PetscFunctionList` 3470e6b6b59SJacob Faibussowitsch 3480e6b6b59SJacob Faibussowitsch Not Collective 3490e6b6b59SJacob Faibussowitsch 3500e6b6b59SJacob Faibussowitsch Input Parameter: 3510e6b6b59SJacob Faibussowitsch . fl - The `PetscFunctionList` to clear 3520e6b6b59SJacob Faibussowitsch 3530e6b6b59SJacob Faibussowitsch Notes: 3540e6b6b59SJacob Faibussowitsch This clears the contents of `fl` but does not deallocate the entries themselves. 3550e6b6b59SJacob Faibussowitsch 3560e6b6b59SJacob Faibussowitsch Level: developer 3570e6b6b59SJacob Faibussowitsch 3580e6b6b59SJacob Faibussowitsch .seealso: `PetscFunctionList`, `PetscFunctionListDestroy()`, `PetscFunctionListAdd()` 3590e6b6b59SJacob Faibussowitsch @*/ 360d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFunctionListClear(PetscFunctionList fl) 361d71ae5a4SJacob Faibussowitsch { 3620e6b6b59SJacob Faibussowitsch PetscFunctionBegin; 363ed170139SJacob Faibussowitsch if (fl) { 364ed170139SJacob Faibussowitsch PetscHMapFuncForEach(fl, name, func, PetscCall(PetscFree(name))); 365ed170139SJacob Faibussowitsch PetscCall(PetscHMapFuncClear(fl->map)); 3660e6b6b59SJacob Faibussowitsch } 3673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3680e6b6b59SJacob Faibussowitsch } 3690e6b6b59SJacob Faibussowitsch 370e5c89e4eSSatish Balay /* 3712e956fe4SStefano Zampini Print registered PetscFunctionLists 372e5c89e4eSSatish Balay */ 373d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFunctionListPrintAll(void) 374d71ae5a4SJacob Faibussowitsch { 375ed170139SJacob Faibussowitsch PetscFunctionListDLAll current = dlallhead; 376e5c89e4eSSatish Balay 377e5c89e4eSSatish Balay PetscFunctionBegin; 378ed170139SJacob Faibussowitsch if (current) PetscCall(PetscPrintf(PETSC_COMM_SELF, "[%d] Registered PetscFunctionLists\n", PetscGlobalRank)); 379ed170139SJacob Faibussowitsch while (current) { 380ed170139SJacob Faibussowitsch PetscCall(PetscFunctionListPrintNonEmpty(current->data)); 381ed170139SJacob Faibussowitsch current = current->next; 38237e93019SBarry Smith } 3833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 384e5c89e4eSSatish Balay } 385e5c89e4eSSatish Balay 3861c9cd337SJed Brown /*MC 3872e956fe4SStefano Zampini PetscFunctionListNonEmpty - Print composed names for non null function pointers 3882e956fe4SStefano Zampini 3892e956fe4SStefano Zampini Input Parameter: 3902e956fe4SStefano Zampini . flist - pointer to list 3912e956fe4SStefano Zampini 3922e956fe4SStefano Zampini Level: developer 3932e956fe4SStefano Zampini 3942e956fe4SStefano Zampini .seealso: `PetscFunctionListAdd()`, `PetscFunctionList`, `PetscObjectQueryFunction()` 3952e956fe4SStefano Zampini M*/ 396d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFunctionListPrintNonEmpty(PetscFunctionList fl) 397d71ae5a4SJacob Faibussowitsch { 3982e956fe4SStefano Zampini PetscFunctionBegin; 399ed170139SJacob Faibussowitsch if (fl) { 400ed170139SJacob Faibussowitsch // clang-format off 401ed170139SJacob Faibussowitsch PetscHMapFuncForEach( 402ed170139SJacob Faibussowitsch fl, 403ed170139SJacob Faibussowitsch name, func, 404ed170139SJacob Faibussowitsch PetscCall(PetscFPrintf(PETSC_COMM_SELF, PETSC_STDOUT, "[%d] function name: %s\n", PetscGlobalRank, name)); 405ed170139SJacob Faibussowitsch ); 406ed170139SJacob Faibussowitsch // clang-format on 4072e956fe4SStefano Zampini } 4083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4092e956fe4SStefano Zampini } 4102e956fe4SStefano Zampini 4112e956fe4SStefano Zampini /*MC 4121c9cd337SJed Brown PetscFunctionListFind - Find function registered under given name 4131c9cd337SJed Brown 4141c9cd337SJed Brown Synopsis: 415aaa7dc30SBarry Smith #include <petscsys.h> 4161c9cd337SJed Brown PetscErrorCode PetscFunctionListFind(PetscFunctionList flist,const char name[],void (**fptr)(void)) 417e5c89e4eSSatish Balay 418e5c89e4eSSatish Balay Input Parameters: 4191c9cd337SJed Brown + flist - pointer to list 4201c9cd337SJed Brown - name - name registered for the function 421e5c89e4eSSatish Balay 422e5c89e4eSSatish Balay Output Parameters: 4231c9cd337SJed Brown . fptr - the function pointer if name was found, else NULL 424e5c89e4eSSatish Balay 425e5c89e4eSSatish Balay Level: developer 426e5c89e4eSSatish Balay 427db781477SPatrick Sanan .seealso: `PetscFunctionListAdd()`, `PetscFunctionList`, `PetscObjectQueryFunction()` 4281c9cd337SJed Brown M*/ 429ed170139SJacob Faibussowitsch PetscErrorCode PetscFunctionListFind_Private(PetscFunctionList fl, const char name[], PetscVoidFunction *r) 430d71ae5a4SJacob Faibussowitsch { 431e5c89e4eSSatish Balay PetscFunctionBegin; 4320e6b6b59SJacob Faibussowitsch PetscValidCharPointer(name, 2); 4330e6b6b59SJacob Faibussowitsch PetscValidPointer(r, 3); 4340e6b6b59SJacob Faibussowitsch *r = NULL; 435ed170139SJacob Faibussowitsch if (fl) PetscCall(PetscHMapFuncGet(fl->map, name, r)); 4363ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 437e5c89e4eSSatish Balay } 438e5c89e4eSSatish Balay 439e5c89e4eSSatish Balay /*@ 440*20f4b53cSBarry Smith PetscFunctionListView - prints out contents of a `PetscFunctionList` 441e5c89e4eSSatish Balay 442*20f4b53cSBarry Smith Collective 443e5c89e4eSSatish Balay 444e5c89e4eSSatish Balay Input Parameters: 445e5c89e4eSSatish Balay + list - the list of functions 446*20f4b53cSBarry Smith - viewer - the `PetscViewer` used to view the `PetscFunctionList` 447e5c89e4eSSatish Balay 448e5c89e4eSSatish Balay Level: developer 449e5c89e4eSSatish Balay 450db781477SPatrick Sanan .seealso: `PetscFunctionListAdd()`, `PetscFunctionListPrintTypes()`, `PetscFunctionList` 451e5c89e4eSSatish Balay @*/ 452d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFunctionListView(PetscFunctionList list, PetscViewer viewer) 453d71ae5a4SJacob Faibussowitsch { 454ace3abfcSBarry Smith PetscBool iascii; 455e5c89e4eSSatish Balay 456e5c89e4eSSatish Balay PetscFunctionBegin; 457e5c89e4eSSatish Balay PetscValidPointer(list, 1); 458ed170139SJacob Faibussowitsch if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PETSC_COMM_SELF, &viewer)); 4590700a824SBarry Smith PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 460e5c89e4eSSatish Balay 4619566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 46228b400f6SJacob Faibussowitsch PetscCheck(iascii, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only ASCII viewer supported"); 463ed170139SJacob Faibussowitsch { 464ed170139SJacob Faibussowitsch PetscInt size; 465e5c89e4eSSatish Balay 466ed170139SJacob Faibussowitsch PetscCall(PetscHMapFuncGetSize(list->map, &size)); 467ed170139SJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "PetscFunctionList Object:\n")); 468ed170139SJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 469ed170139SJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "size: %" PetscInt_FMT "\n", size)); 470ed170139SJacob Faibussowitsch if (size) { 471ed170139SJacob Faibussowitsch PetscInt count = 0; 472ed170139SJacob Faibussowitsch 473ed170139SJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "functions:\n")); 474ed170139SJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 475ed170139SJacob Faibussowitsch PetscHMapFuncForEach(list, name, func, PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT ": %s\n", ++count, name))); 476ed170139SJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 477e5c89e4eSSatish Balay } 478ed170139SJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 479ed170139SJacob Faibussowitsch } 4803ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 481e5c89e4eSSatish Balay } 482e5c89e4eSSatish Balay 483065533a5SJed Brown /*@C 484811af0c4SBarry Smith PetscFunctionListGet - Gets an array the contains the entries in `PetscFunctionList`, this is used 485e5c89e4eSSatish Balay by help etc. 486e5c89e4eSSatish Balay 487d4349b43SBarry Smith Not Collective 488e5c89e4eSSatish Balay 489e5c89e4eSSatish Balay Input Parameter: 490e5c89e4eSSatish Balay . list - list of types 491e5c89e4eSSatish Balay 492d8d19677SJose E. Roman Output Parameters: 493e5c89e4eSSatish Balay + array - array of names 494e5c89e4eSSatish Balay - n - length of array 495e5c89e4eSSatish Balay 496811af0c4SBarry Smith Note: 497e5c89e4eSSatish Balay This allocates the array so that must be freed. BUT the individual entries are 498e5c89e4eSSatish Balay not copied so should not be freed. 499e5c89e4eSSatish Balay 500e5c89e4eSSatish Balay Level: developer 501e5c89e4eSSatish Balay 502db781477SPatrick Sanan .seealso: `PetscFunctionListAdd()`, `PetscFunctionList` 503e5c89e4eSSatish Balay @*/ 504d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFunctionListGet(PetscFunctionList list, const char ***array, int *n) 505d71ae5a4SJacob Faibussowitsch { 506ed170139SJacob Faibussowitsch PetscInt size = 0; 507e5c89e4eSSatish Balay 508e5c89e4eSSatish Balay PetscFunctionBegin; 509ed170139SJacob Faibussowitsch PetscValidPointer(array, 2); 510ed170139SJacob Faibussowitsch *array = NULL; 511ed170139SJacob Faibussowitsch if (list) { 512ed170139SJacob Faibussowitsch const PetscHMapFunc map = list->map; 513ed170139SJacob Faibussowitsch PetscInt off = 0; 514ed170139SJacob Faibussowitsch 515ed170139SJacob Faibussowitsch PetscCall(PetscHMapFuncGetSize(map, &size)); 516ed170139SJacob Faibussowitsch PetscCall(PetscMalloc1(size, (char ***)array)); 517ed170139SJacob Faibussowitsch PetscCall(PetscHMapFuncGetKeys(map, &off, *array)); 518e5c89e4eSSatish Balay } 519ed170139SJacob Faibussowitsch *n = (int)size; 5203ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 521e5c89e4eSSatish Balay } 522e5c89e4eSSatish Balay 523e5c89e4eSSatish Balay /*@C 524811af0c4SBarry Smith PetscFunctionListPrintTypes - Prints the methods available in a list of functions 525e5c89e4eSSatish Balay 526e5c89e4eSSatish Balay Collective over MPI_Comm 527e5c89e4eSSatish Balay 528e5c89e4eSSatish Balay Input Parameters: 529811af0c4SBarry Smith + comm - the communicator (usually `MPI_COMM_WORLD`) 530e5c89e4eSSatish Balay . fd - file to print to, usually stdout 531e5c89e4eSSatish Balay . prefix - prefix to prepend to name (optional) 532e5c89e4eSSatish Balay . name - option string (for example, "-ksp_type") 533e5c89e4eSSatish Balay . text - short description of the object (for example, "Krylov solvers") 534e5c89e4eSSatish Balay . man - name of manual page that discusses the object (for example, "KSPCreate") 5353cc1e11dSBarry Smith . list - list of types 53644ef3d73SBarry Smith . def - default (current) value 53744ef3d73SBarry Smith - newv - new value 538e5c89e4eSSatish Balay 539e5c89e4eSSatish Balay Level: developer 540e5c89e4eSSatish Balay 541db781477SPatrick Sanan .seealso: `PetscFunctionListAdd()`, `PetscFunctionList` 542e5c89e4eSSatish Balay @*/ 543d71ae5a4SJacob 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[]) 544d71ae5a4SJacob Faibussowitsch { 545e5c89e4eSSatish Balay char p[64]; 546e5c89e4eSSatish Balay 547e5c89e4eSSatish Balay PetscFunctionBegin; 548ed170139SJacob Faibussowitsch (void)fd; 5499566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(p, "-", sizeof(p))); 5509566063dSJacob Faibussowitsch if (prefix) PetscCall(PetscStrlcat(p, prefix, sizeof(p))); 551ed170139SJacob Faibussowitsch PetscCall((*PetscHelpPrintf)(comm, " %s%s <now %s : formerly %s>: %s (one of)", p, name + 1, newv, def, text)); 552e5c89e4eSSatish Balay 5538c7e48aeSJacob Faibussowitsch if (list) PetscHMapFuncForEach(list, name, func, PetscCall((*PetscHelpPrintf)(comm, " %s", name))); 554ed170139SJacob Faibussowitsch PetscCall((*PetscHelpPrintf)(comm, " (%s)\n", man)); 5553ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 556e5c89e4eSSatish Balay } 557e5c89e4eSSatish Balay 558e5c89e4eSSatish Balay /*@ 559140e18c1SBarry Smith PetscFunctionListDuplicate - Creates a new list from a given object list. 560e5c89e4eSSatish Balay 561e5c89e4eSSatish Balay Input Parameters: 562e5c89e4eSSatish Balay . fl - pointer to list 563e5c89e4eSSatish Balay 564e5c89e4eSSatish Balay Output Parameters: 565e5c89e4eSSatish Balay . nl - the new list (should point to 0 to start, otherwise appends) 566e5c89e4eSSatish Balay 567e5c89e4eSSatish Balay Level: developer 568e5c89e4eSSatish Balay 569db781477SPatrick Sanan .seealso: `PetscFunctionList`, `PetscFunctionListAdd()`, `PetscFlistDestroy()` 570e5c89e4eSSatish Balay @*/ 571d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFunctionListDuplicate(PetscFunctionList fl, PetscFunctionList *nl) 572d71ae5a4SJacob Faibussowitsch { 573e5c89e4eSSatish Balay PetscFunctionBegin; 574ed170139SJacob Faibussowitsch if (fl) { 575ed170139SJacob Faibussowitsch PetscHMapFunc dup_map; 576ed170139SJacob Faibussowitsch 577ed170139SJacob Faibussowitsch if (!*nl) { 578ed170139SJacob Faibussowitsch PetscInt n; 579ed170139SJacob Faibussowitsch 580ed170139SJacob Faibussowitsch PetscCall(PetscHMapFuncGetSize(fl->map, &n)); 581ed170139SJacob Faibussowitsch PetscCall(PetscFunctionListCreate_Private(n, nl)); 582ed170139SJacob Faibussowitsch } 583ed170139SJacob Faibussowitsch dup_map = (*nl)->map; 584ed170139SJacob Faibussowitsch PetscHMapFuncForEach(fl, name, func, PetscCall(PetscHMapFuncInsert_Private(dup_map, name, func))); 585e5c89e4eSSatish Balay } 5863ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 587e5c89e4eSSatish Balay } 588