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 9*ed170139SJacob 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 } 33487e5849SBarry Smith PetscFunctionReturn(0); 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 151e5c89e4eSSatish Balay PetscFunctionReturn(0); 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; 166e5c89e4eSSatish Balay PetscFunctionReturn(0); 167e5c89e4eSSatish Balay } 168e5c89e4eSSatish Balay 169e5c89e4eSSatish Balay /* ------------------------------------------------------------------------------*/ 170*ed170139SJacob Faibussowitsch PETSC_HASH_MAP(HMapFunc, const char *, PetscVoidFunction, kh_str_hash_func, kh_str_hash_equal, NULL) 171*ed170139SJacob Faibussowitsch 172140e18c1SBarry Smith struct _n_PetscFunctionList { 173*ed170139SJacob Faibussowitsch PetscHMapFunc map; 174e5c89e4eSSatish Balay }; 175e5c89e4eSSatish Balay 176*ed170139SJacob Faibussowitsch /* Keep a linked list of PetscFunctionLists so that we can destroy all the left-over ones. */ 177*ed170139SJacob Faibussowitsch typedef struct n_PetscFunctionListDLAll *PetscFunctionListDLAll; 178*ed170139SJacob Faibussowitsch struct n_PetscFunctionListDLAll { 179*ed170139SJacob Faibussowitsch PetscFunctionList data; 180*ed170139SJacob Faibussowitsch PetscFunctionListDLAll next; 181*ed170139SJacob Faibussowitsch }; 182e5c89e4eSSatish Balay 183*ed170139SJacob Faibussowitsch static PetscFunctionListDLAll dlallhead = NULL; 184*ed170139SJacob Faibussowitsch 185*ed170139SJacob Faibussowitsch static PetscErrorCode PetscFunctionListDLAllPush_Private(PetscFunctionList fl) 186d71ae5a4SJacob Faibussowitsch { 1870e6b6b59SJacob Faibussowitsch PetscFunctionBegin; 188*ed170139SJacob Faibussowitsch if (PetscDefined(USE_DEBUG) && !PetscDefined(HAVE_THREADSAFETY)) { 189*ed170139SJacob Faibussowitsch PetscFunctionListDLAll head; 190*ed170139SJacob Faibussowitsch 191*ed170139SJacob Faibussowitsch PetscCall(PetscNew(&head)); 192*ed170139SJacob Faibussowitsch head->data = fl; 193*ed170139SJacob Faibussowitsch head->next = dlallhead; 194*ed170139SJacob Faibussowitsch dlallhead = head; 195*ed170139SJacob Faibussowitsch } 196*ed170139SJacob Faibussowitsch PetscFunctionReturn(0); 197*ed170139SJacob Faibussowitsch } 198*ed170139SJacob Faibussowitsch 199*ed170139SJacob Faibussowitsch static PetscErrorCode PetscFunctionListDLAllPop_Private(PetscFunctionList fl) 200*ed170139SJacob Faibussowitsch { 201*ed170139SJacob Faibussowitsch PetscFunctionBegin; 202*ed170139SJacob Faibussowitsch if (PetscDefined(USE_DEBUG) && !PetscDefined(HAVE_THREADSAFETY)) { 203*ed170139SJacob Faibussowitsch PetscFunctionListDLAll current = dlallhead, prev = NULL; 204*ed170139SJacob Faibussowitsch 205*ed170139SJacob Faibussowitsch /* Remove this entry from the main DL list (if it is in it) */ 206*ed170139SJacob Faibussowitsch while (current) { 207*ed170139SJacob Faibussowitsch const PetscFunctionListDLAll next = current->next; 208*ed170139SJacob Faibussowitsch 209*ed170139SJacob Faibussowitsch if (current->data == fl) { 210*ed170139SJacob Faibussowitsch if (prev) { 211*ed170139SJacob Faibussowitsch // somewhere in the middle (or end) of the list 212*ed170139SJacob Faibussowitsch prev->next = next; 213*ed170139SJacob Faibussowitsch } else { 214*ed170139SJacob Faibussowitsch // prev = NULL implies current = dlallhead, so front of list 215*ed170139SJacob Faibussowitsch dlallhead = next; 216*ed170139SJacob Faibussowitsch } 217*ed170139SJacob Faibussowitsch PetscCall(PetscFree(current)); 218*ed170139SJacob Faibussowitsch break; 219*ed170139SJacob Faibussowitsch } 220*ed170139SJacob Faibussowitsch prev = current; 221*ed170139SJacob Faibussowitsch current = next; 222*ed170139SJacob Faibussowitsch } 223*ed170139SJacob Faibussowitsch } 224*ed170139SJacob Faibussowitsch PetscFunctionReturn(0); 225*ed170139SJacob Faibussowitsch } 226*ed170139SJacob Faibussowitsch 227*ed170139SJacob Faibussowitsch static PetscErrorCode PetscHMapFuncInsert_Private(PetscHMapFunc map, const char name[], PetscVoidFunction fnc) 228*ed170139SJacob Faibussowitsch { 229*ed170139SJacob Faibussowitsch PetscHashIter it; 230*ed170139SJacob Faibussowitsch PetscBool found; 231*ed170139SJacob Faibussowitsch 232*ed170139SJacob Faibussowitsch PetscFunctionBegin; 233*ed170139SJacob Faibussowitsch PetscValidCharPointer(name, 2); 234*ed170139SJacob Faibussowitsch if (fnc) PetscValidFunction(fnc, 3); 235*ed170139SJacob Faibussowitsch PetscCall(PetscHMapFuncFind(map, name, &it, &found)); 236*ed170139SJacob Faibussowitsch if (fnc) { 237*ed170139SJacob Faibussowitsch if (found) { 238*ed170139SJacob Faibussowitsch PetscCall(PetscHMapFuncIterSet(map, it, fnc)); 239*ed170139SJacob Faibussowitsch } else { 240*ed170139SJacob Faibussowitsch char *tmp_name; 241*ed170139SJacob Faibussowitsch 242*ed170139SJacob Faibussowitsch PetscCall(PetscStrallocpy(name, &tmp_name)); 243*ed170139SJacob Faibussowitsch PetscCall(PetscHMapFuncSet(map, tmp_name, fnc)); 244*ed170139SJacob Faibussowitsch } 245*ed170139SJacob Faibussowitsch } else if (found) { 246*ed170139SJacob Faibussowitsch const char *tmp_name; 247*ed170139SJacob Faibussowitsch 248*ed170139SJacob Faibussowitsch PetscHashIterGetKey(map, it, tmp_name); 249*ed170139SJacob Faibussowitsch PetscCall(PetscFree(tmp_name)); 250*ed170139SJacob Faibussowitsch PetscCall(PetscHMapFuncIterDel(map, it)); 251*ed170139SJacob Faibussowitsch } 252*ed170139SJacob Faibussowitsch PetscFunctionReturn(0); 253*ed170139SJacob Faibussowitsch } 254*ed170139SJacob Faibussowitsch 255*ed170139SJacob Faibussowitsch static PetscErrorCode PetscFunctionListCreate_Private(PetscInt size, PetscFunctionList *fl) 256*ed170139SJacob Faibussowitsch { 257*ed170139SJacob Faibussowitsch PetscFunctionBegin; 258*ed170139SJacob Faibussowitsch if (*fl) PetscFunctionReturn(0); 259*ed170139SJacob Faibussowitsch PetscCall(PetscNew(fl)); 260*ed170139SJacob Faibussowitsch PetscCall(PetscHMapFuncCreateWithSize(size, &(*fl)->map)); 261*ed170139SJacob Faibussowitsch PetscCall(PetscFunctionListDLAllPush_Private(*fl)); 2620e6b6b59SJacob Faibussowitsch PetscFunctionReturn(0); 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*/ 293*ed170139SJacob 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); 299*ed170139SJacob Faibussowitsch PetscCall(PetscFunctionListCreate_Private(0, fl)); 300*ed170139SJacob Faibussowitsch PetscCall(PetscHMapFuncInsert_Private((*fl)->map, name, fnc)); 301e5c89e4eSSatish Balay PetscFunctionReturn(0); 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; 3171441b1d3SBarry Smith if (!*fl) PetscFunctionReturn(0); 318*ed170139SJacob Faibussowitsch PetscCall(PetscFunctionListDLAllPop_Private(*fl)); 319e5c89e4eSSatish Balay /* free this list */ 320*ed170139SJacob Faibussowitsch PetscCall(PetscFunctionListClear(*fl)); 321*ed170139SJacob Faibussowitsch PetscCall(PetscHMapFuncDestroy(&(*fl)->map)); 322*ed170139SJacob Faibussowitsch PetscCall(PetscFree(*fl)); 323e5c89e4eSSatish Balay PetscFunctionReturn(0); 324e5c89e4eSSatish Balay } 325e5c89e4eSSatish Balay 326*ed170139SJacob Faibussowitsch #define PetscHMapFuncForEach(__func_list__, __key_name__, __val_name__, ...) \ 327*ed170139SJacob Faibussowitsch do { \ 328*ed170139SJacob Faibussowitsch const PetscHMapFunc phmfi_map_ = (__func_list__)->map; \ 329*ed170139SJacob Faibussowitsch PetscHashIter phmfi_iter_; \ 330*ed170139SJacob Faibussowitsch \ 331*ed170139SJacob Faibussowitsch PetscHashIterBegin(phmfi_map_, phmfi_iter_); \ 332*ed170139SJacob Faibussowitsch while (!PetscHashIterAtEnd(phmfi_map_, phmfi_iter_)) { \ 333*ed170139SJacob Faibussowitsch const char *PETSC_UNUSED __key_name__; \ 334*ed170139SJacob Faibussowitsch PetscVoidFunction PETSC_UNUSED __val_name__; \ 335*ed170139SJacob Faibussowitsch \ 336*ed170139SJacob Faibussowitsch PetscHashIterGetKey(phmfi_map_, phmfi_iter_, __key_name__); \ 337*ed170139SJacob Faibussowitsch PetscHashIterGetVal(phmfi_map_, phmfi_iter_, __val_name__); \ 338*ed170139SJacob Faibussowitsch { \ 339*ed170139SJacob Faibussowitsch __VA_ARGS__; \ 340*ed170139SJacob Faibussowitsch } \ 341*ed170139SJacob Faibussowitsch PetscHashIterNext(phmfi_map_, phmfi_iter_); \ 342*ed170139SJacob Faibussowitsch } /* end while */ \ 343*ed170139SJacob Faibussowitsch } while (0) 344*ed170139SJacob 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; 363*ed170139SJacob Faibussowitsch if (fl) { 364*ed170139SJacob Faibussowitsch PetscHMapFuncForEach(fl, name, func, PetscCall(PetscFree(name))); 365*ed170139SJacob Faibussowitsch PetscCall(PetscHMapFuncClear(fl->map)); 3660e6b6b59SJacob Faibussowitsch } 3670e6b6b59SJacob Faibussowitsch PetscFunctionReturn(0); 3680e6b6b59SJacob Faibussowitsch } 3690e6b6b59SJacob Faibussowitsch 370e5c89e4eSSatish Balay /* 3712e956fe4SStefano Zampini Print registered PetscFunctionLists 372e5c89e4eSSatish Balay */ 373d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFunctionListPrintAll(void) 374d71ae5a4SJacob Faibussowitsch { 375*ed170139SJacob Faibussowitsch PetscFunctionListDLAll current = dlallhead; 376e5c89e4eSSatish Balay 377e5c89e4eSSatish Balay PetscFunctionBegin; 378*ed170139SJacob Faibussowitsch if (current) PetscCall(PetscPrintf(PETSC_COMM_SELF, "[%d] Registered PetscFunctionLists\n", PetscGlobalRank)); 379*ed170139SJacob Faibussowitsch while (current) { 380*ed170139SJacob Faibussowitsch PetscCall(PetscFunctionListPrintNonEmpty(current->data)); 381*ed170139SJacob Faibussowitsch current = current->next; 38237e93019SBarry Smith } 383e5c89e4eSSatish Balay PetscFunctionReturn(0); 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; 399*ed170139SJacob Faibussowitsch if (fl) { 400*ed170139SJacob Faibussowitsch // clang-format off 401*ed170139SJacob Faibussowitsch PetscHMapFuncForEach( 402*ed170139SJacob Faibussowitsch fl, 403*ed170139SJacob Faibussowitsch name, func, 404*ed170139SJacob Faibussowitsch PetscCall(PetscFPrintf(PETSC_COMM_SELF, PETSC_STDOUT, "[%d] function name: %s\n", PetscGlobalRank, name)); 405*ed170139SJacob Faibussowitsch ); 406*ed170139SJacob Faibussowitsch // clang-format on 4072e956fe4SStefano Zampini } 4082e956fe4SStefano Zampini PetscFunctionReturn(0); 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*/ 429*ed170139SJacob 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; 435*ed170139SJacob Faibussowitsch if (fl) PetscCall(PetscHMapFuncGet(fl->map, name, r)); 436e5c89e4eSSatish Balay PetscFunctionReturn(0); 437e5c89e4eSSatish Balay } 438e5c89e4eSSatish Balay 439e5c89e4eSSatish Balay /*@ 440140e18c1SBarry Smith PetscFunctionListView - prints out contents of an PetscFunctionList 441e5c89e4eSSatish Balay 442*ed170139SJacob Faibussowitsch Collective on `viewer` 443e5c89e4eSSatish Balay 444e5c89e4eSSatish Balay Input Parameters: 445e5c89e4eSSatish Balay + list - the list of functions 446*ed170139SJacob Faibussowitsch - 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); 458*ed170139SJacob 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"); 463*ed170139SJacob Faibussowitsch { 464*ed170139SJacob Faibussowitsch PetscInt size; 465e5c89e4eSSatish Balay 466*ed170139SJacob Faibussowitsch PetscCall(PetscHMapFuncGetSize(list->map, &size)); 467*ed170139SJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "PetscFunctionList Object:\n")); 468*ed170139SJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 469*ed170139SJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "size: %" PetscInt_FMT "\n", size)); 470*ed170139SJacob Faibussowitsch if (size) { 471*ed170139SJacob Faibussowitsch PetscInt count = 0; 472*ed170139SJacob Faibussowitsch 473*ed170139SJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "functions:\n")); 474*ed170139SJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 475*ed170139SJacob Faibussowitsch PetscHMapFuncForEach(list, name, func, PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT ": %s\n", ++count, name))); 476*ed170139SJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 477e5c89e4eSSatish Balay } 478*ed170139SJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 479*ed170139SJacob Faibussowitsch } 480e5c89e4eSSatish Balay PetscFunctionReturn(0); 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 { 506*ed170139SJacob Faibussowitsch PetscInt size = 0; 507e5c89e4eSSatish Balay 508e5c89e4eSSatish Balay PetscFunctionBegin; 509*ed170139SJacob Faibussowitsch PetscValidPointer(array, 2); 510*ed170139SJacob Faibussowitsch *array = NULL; 511*ed170139SJacob Faibussowitsch if (list) { 512*ed170139SJacob Faibussowitsch const PetscHMapFunc map = list->map; 513*ed170139SJacob Faibussowitsch PetscInt off = 0; 514*ed170139SJacob Faibussowitsch 515*ed170139SJacob Faibussowitsch PetscCall(PetscHMapFuncGetSize(map, &size)); 516*ed170139SJacob Faibussowitsch PetscCall(PetscMalloc1(size, (char ***)array)); 517*ed170139SJacob Faibussowitsch PetscCall(PetscHMapFuncGetKeys(map, &off, *array)); 518e5c89e4eSSatish Balay } 519*ed170139SJacob Faibussowitsch *n = (int)size; 520e5c89e4eSSatish Balay PetscFunctionReturn(0); 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; 548*ed170139SJacob Faibussowitsch (void)fd; 5499566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(p, "-", sizeof(p))); 5509566063dSJacob Faibussowitsch if (prefix) PetscCall(PetscStrlcat(p, prefix, sizeof(p))); 551*ed170139SJacob Faibussowitsch PetscCall((*PetscHelpPrintf)(comm, " %s%s <now %s : formerly %s>: %s (one of)", p, name + 1, newv, def, text)); 552e5c89e4eSSatish Balay 553*ed170139SJacob Faibussowitsch PetscHMapFuncForEach(list, name, func, PetscCall((*PetscHelpPrintf)(comm, " %s", name))); 554*ed170139SJacob Faibussowitsch PetscCall((*PetscHelpPrintf)(comm, " (%s)\n", man)); 555e5c89e4eSSatish Balay PetscFunctionReturn(0); 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; 574*ed170139SJacob Faibussowitsch if (fl) { 575*ed170139SJacob Faibussowitsch PetscHMapFunc dup_map; 576*ed170139SJacob Faibussowitsch 577*ed170139SJacob Faibussowitsch if (!*nl) { 578*ed170139SJacob Faibussowitsch PetscInt n; 579*ed170139SJacob Faibussowitsch 580*ed170139SJacob Faibussowitsch PetscCall(PetscHMapFuncGetSize(fl->map, &n)); 581*ed170139SJacob Faibussowitsch PetscCall(PetscFunctionListCreate_Private(n, nl)); 582*ed170139SJacob Faibussowitsch } 583*ed170139SJacob Faibussowitsch dup_map = (*nl)->map; 584*ed170139SJacob Faibussowitsch PetscHMapFuncForEach(fl, name, func, PetscCall(PetscHMapFuncInsert_Private(dup_map, name, func))); 585e5c89e4eSSatish Balay } 586e5c89e4eSSatish Balay PetscFunctionReturn(0); 587e5c89e4eSSatish Balay } 588