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))); 239566063dSJacob Faibussowitsch PetscCall(PetscDLLibraryRetrieve(PETSC_COMM_WORLD, libs, dlib, 1024, found)); 24487e5849SBarry Smith if (*found) { 259566063dSJacob Faibussowitsch PetscCall(PetscDLLibraryAppend(PETSC_COMM_WORLD, &PetscDLLibrariesLoaded, dlib)); 26487e5849SBarry Smith } else { 279566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(libs, "${PETSC_DIR}/${PETSC_ARCH}/lib/libpetsc", sizeof(libs))); 289566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(libs, name, sizeof(libs))); 299566063dSJacob Faibussowitsch PetscCall(PetscDLLibraryRetrieve(PETSC_COMM_WORLD, libs, dlib, 1024, found)); 3048a46eb9SPierre Jolivet if (*found) PetscCall(PetscDLLibraryAppend(PETSC_COMM_WORLD, &PetscDLLibrariesLoaded, dlib)); 31487e5849SBarry Smith } 323ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 33487e5849SBarry Smith } 343fa76a5bSLisandro Dalcin #endif 353fa76a5bSLisandro Dalcin 3660da17ecSBarry Smith #if defined(PETSC_USE_SINGLE_LIBRARY) && !(defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES)) 3795c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode AOInitializePackage(void); 3895c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscSFInitializePackage(void); 397da51e29SSatish Balay #if !defined(PETSC_USE_COMPLEX) 4095c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode CharacteristicInitializePackage(void); 417da51e29SSatish Balay #endif 4295c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode ISInitializePackage(void); 4395c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode VecInitializePackage(void); 4495c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode MatInitializePackage(void); 4595c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode DMInitializePackage(void); 4695c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode PCInitializePackage(void); 4795c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode KSPInitializePackage(void); 4895c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode SNESInitializePackage(void); 4995c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode TSInitializePackage(void); 5060da17ecSBarry Smith PETSC_EXTERN PetscErrorCode TaoInitializePackage(void); 5160da17ecSBarry Smith #endif 52acff04ddSBarry Smith 53e5c89e4eSSatish Balay /* 54e5c89e4eSSatish Balay PetscInitialize_DynamicLibraries - Adds the default dynamic link libraries to the 55e5c89e4eSSatish Balay search path. 56e5c89e4eSSatish Balay */ 57d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode PetscInitialize_DynamicLibraries(void) 58d71ae5a4SJacob Faibussowitsch { 59487e5849SBarry Smith char *libname[32]; 60e5c89e4eSSatish Balay PetscInt nmax, i; 6160da17ecSBarry Smith PetscBool preload = PETSC_FALSE; 62540e20f2SPierre Jolivet #if defined(PETSC_HAVE_ELEMENTAL) 63540e20f2SPierre Jolivet PetscBool PetscInitialized = PetscInitializeCalled; 64540e20f2SPierre Jolivet #endif 65e5c89e4eSSatish Balay 6660154eb2SBarry Smith PetscFunctionBegin; 6760da17ecSBarry Smith #if defined(PETSC_HAVE_THREADSAFETY) 6860da17ecSBarry Smith /* These must be all initialized here because it is not safe for individual threads to call these initialize routines */ 6960da17ecSBarry Smith preload = PETSC_TRUE; 7060da17ecSBarry Smith #endif 7160da17ecSBarry Smith 72e5c89e4eSSatish Balay nmax = 32; 739566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetStringArray(NULL, NULL, "-dll_prepend", libname, &nmax, NULL)); 74e5c89e4eSSatish Balay for (i = 0; i < nmax; i++) { 759566063dSJacob Faibussowitsch PetscCall(PetscDLLibraryPrepend(PETSC_COMM_WORLD, &PetscDLLibrariesLoaded, libname[i])); 769566063dSJacob Faibussowitsch PetscCall(PetscFree(libname[i])); 77e5c89e4eSSatish Balay } 78e5c89e4eSSatish Balay 799566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-library_preload", &preload, NULL)); 8060da17ecSBarry Smith if (!preload) { 819566063dSJacob Faibussowitsch PetscCall(PetscSysInitializePackage()); 8260da17ecSBarry Smith } else { 8360da17ecSBarry Smith #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES) 84aa2d57e9SJed Brown PetscBool found; 8560154eb2SBarry Smith #if defined(PETSC_USE_SINGLE_LIBRARY) 869566063dSJacob Faibussowitsch PetscCall(PetscLoadDynamicLibrary("", &found)); 8700045ab3SPierre Jolivet PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc dynamic library. You cannot move the dynamic libraries!"); 8860154eb2SBarry Smith #else 899566063dSJacob Faibussowitsch PetscCall(PetscLoadDynamicLibrary("sys", &found)); 9000045ab3SPierre Jolivet PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc Sys dynamic library. You cannot move the dynamic libraries!"); 919566063dSJacob Faibussowitsch PetscCall(PetscLoadDynamicLibrary("vec", &found)); 9200045ab3SPierre Jolivet PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc Vec dynamic library. You cannot move the dynamic libraries!"); 939566063dSJacob Faibussowitsch PetscCall(PetscLoadDynamicLibrary("mat", &found)); 9400045ab3SPierre Jolivet PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc Mat dynamic library. You cannot move the dynamic libraries!"); 959566063dSJacob Faibussowitsch PetscCall(PetscLoadDynamicLibrary("dm", &found)); 9600045ab3SPierre Jolivet PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc DM dynamic library. You cannot move the dynamic libraries!"); 979566063dSJacob Faibussowitsch PetscCall(PetscLoadDynamicLibrary("ksp", &found)); 9800045ab3SPierre Jolivet PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc KSP dynamic library. You cannot move the dynamic libraries!"); 999566063dSJacob Faibussowitsch PetscCall(PetscLoadDynamicLibrary("snes", &found)); 10000045ab3SPierre Jolivet PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc SNES dynamic library. You cannot move the dynamic libraries!"); 1019566063dSJacob Faibussowitsch PetscCall(PetscLoadDynamicLibrary("ts", &found)); 10200045ab3SPierre Jolivet PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc TS dynamic library. You cannot move the dynamic libraries!"); 1039566063dSJacob Faibussowitsch PetscCall(PetscLoadDynamicLibrary("tao", &found)); 10400045ab3SPierre Jolivet PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate Tao dynamic library. You cannot move the dynamic libraries!"); 105bb84e0fdSBarry Smith #endif 10660da17ecSBarry Smith #else /* defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES) */ 10760da17ecSBarry Smith #if defined(PETSC_USE_SINGLE_LIBRARY) 1089566063dSJacob Faibussowitsch PetscCall(AOInitializePackage()); 1099566063dSJacob Faibussowitsch PetscCall(PetscSFInitializePackage()); 1107da51e29SSatish Balay #if !defined(PETSC_USE_COMPLEX) 1119566063dSJacob Faibussowitsch PetscCall(CharacteristicInitializePackage()); 1127da51e29SSatish Balay #endif 1139566063dSJacob Faibussowitsch PetscCall(ISInitializePackage()); 1149566063dSJacob Faibussowitsch PetscCall(VecInitializePackage()); 1159566063dSJacob Faibussowitsch PetscCall(MatInitializePackage()); 1169566063dSJacob Faibussowitsch PetscCall(DMInitializePackage()); 1179566063dSJacob Faibussowitsch PetscCall(PCInitializePackage()); 1189566063dSJacob Faibussowitsch PetscCall(KSPInitializePackage()); 1199566063dSJacob Faibussowitsch PetscCall(SNESInitializePackage()); 1209566063dSJacob Faibussowitsch PetscCall(TSInitializePackage()); 1219566063dSJacob Faibussowitsch PetscCall(TaoInitializePackage()); 12260da17ecSBarry Smith #else 12360da17ecSBarry Smith SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP, "Cannot use -library_preload with multiple static PETSc libraries"); 12460da17ecSBarry Smith #endif 12560da17ecSBarry Smith #endif /* defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES) */ 12660da17ecSBarry Smith } 12760da17ecSBarry Smith 12860da17ecSBarry Smith #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES) && defined(PETSC_HAVE_BAMG) 12960da17ecSBarry Smith { 13060da17ecSBarry Smith PetscBool found; 1319566063dSJacob Faibussowitsch PetscCall(PetscLoadDynamicLibrary("bamg", &found)); 13200045ab3SPierre Jolivet PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc BAMG dynamic library. You cannot move the dynamic libraries!"); 13360da17ecSBarry Smith } 13460da17ecSBarry Smith #endif 13560da17ecSBarry Smith 13660da17ecSBarry Smith nmax = 32; 1379566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetStringArray(NULL, NULL, "-dll_append", libname, &nmax, NULL)); 13860da17ecSBarry Smith for (i = 0; i < nmax; i++) { 1399566063dSJacob Faibussowitsch PetscCall(PetscDLLibraryAppend(PETSC_COMM_WORLD, &PetscDLLibrariesLoaded, libname[i])); 1409566063dSJacob Faibussowitsch PetscCall(PetscFree(libname[i])); 14160da17ecSBarry Smith } 14260da17ecSBarry Smith 143540e20f2SPierre Jolivet #if defined(PETSC_HAVE_ELEMENTAL) 144540e20f2SPierre Jolivet /* in Fortran, PetscInitializeCalled is set to PETSC_TRUE before PetscInitialize_DynamicLibraries() */ 145540e20f2SPierre Jolivet /* in C, it is not the case, but the value is forced to PETSC_TRUE so that PetscRegisterFinalize() is called */ 146540e20f2SPierre Jolivet PetscInitializeCalled = PETSC_TRUE; 1479566063dSJacob Faibussowitsch PetscCall(PetscElementalInitializePackage()); 148540e20f2SPierre Jolivet PetscInitializeCalled = PetscInitialized; 149540e20f2SPierre Jolivet #endif 1503ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 151e5c89e4eSSatish Balay } 152e5c89e4eSSatish Balay 153ebd79076SLisandro Dalcin /* 154ebd79076SLisandro Dalcin PetscFinalize_DynamicLibraries - Closes the opened dynamic libraries. 155ebd79076SLisandro Dalcin */ 156d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode PetscFinalize_DynamicLibraries(void) 157d71ae5a4SJacob Faibussowitsch { 158ace3abfcSBarry Smith PetscBool flg = PETSC_FALSE; 159e5c89e4eSSatish Balay 160ebd79076SLisandro Dalcin PetscFunctionBegin; 1619566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-dll_view", &flg, NULL)); 1629566063dSJacob Faibussowitsch if (flg) PetscCall(PetscDLLibraryPrintPath(PetscDLLibrariesLoaded)); 1639566063dSJacob Faibussowitsch PetscCall(PetscDLLibraryClose(PetscDLLibrariesLoaded)); 16402c9f0b5SLisandro Dalcin PetscDLLibrariesLoaded = NULL; 1653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 166e5c89e4eSSatish Balay } 167e5c89e4eSSatish Balay 1688434afd1SBarry Smith PETSC_HASH_MAP(HMapFunc, const char *, PetscVoidFn *, kh_str_hash_func, kh_str_hash_equal, NULL) 169ed170139SJacob Faibussowitsch 170140e18c1SBarry Smith struct _n_PetscFunctionList { 171ed170139SJacob Faibussowitsch PetscHMapFunc map; 172e5c89e4eSSatish Balay }; 173e5c89e4eSSatish Balay 174ed170139SJacob Faibussowitsch /* Keep a linked list of PetscFunctionLists so that we can destroy all the left-over ones. */ 175ed170139SJacob Faibussowitsch typedef struct n_PetscFunctionListDLAll *PetscFunctionListDLAll; 176ed170139SJacob Faibussowitsch struct n_PetscFunctionListDLAll { 177ed170139SJacob Faibussowitsch PetscFunctionList data; 178ed170139SJacob Faibussowitsch PetscFunctionListDLAll next; 179ed170139SJacob Faibussowitsch }; 180e5c89e4eSSatish Balay 181ed170139SJacob Faibussowitsch static PetscFunctionListDLAll dlallhead = NULL; 182ed170139SJacob Faibussowitsch 183ed170139SJacob Faibussowitsch static PetscErrorCode PetscFunctionListDLAllPush_Private(PetscFunctionList fl) 184d71ae5a4SJacob Faibussowitsch { 1850e6b6b59SJacob Faibussowitsch PetscFunctionBegin; 186ed170139SJacob Faibussowitsch if (PetscDefined(USE_DEBUG) && !PetscDefined(HAVE_THREADSAFETY)) { 187ed170139SJacob Faibussowitsch PetscFunctionListDLAll head; 188ed170139SJacob Faibussowitsch 189ed170139SJacob Faibussowitsch PetscCall(PetscNew(&head)); 190ed170139SJacob Faibussowitsch head->data = fl; 191ed170139SJacob Faibussowitsch head->next = dlallhead; 192ed170139SJacob Faibussowitsch dlallhead = head; 193ed170139SJacob Faibussowitsch } 1943ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 195ed170139SJacob Faibussowitsch } 196ed170139SJacob Faibussowitsch 197ed170139SJacob Faibussowitsch static PetscErrorCode PetscFunctionListDLAllPop_Private(PetscFunctionList fl) 198ed170139SJacob Faibussowitsch { 199ed170139SJacob Faibussowitsch PetscFunctionBegin; 200ed170139SJacob Faibussowitsch if (PetscDefined(USE_DEBUG) && !PetscDefined(HAVE_THREADSAFETY)) { 201ed170139SJacob Faibussowitsch PetscFunctionListDLAll current = dlallhead, prev = NULL; 202ed170139SJacob Faibussowitsch 203ed170139SJacob Faibussowitsch /* Remove this entry from the main DL list (if it is in it) */ 204ed170139SJacob Faibussowitsch while (current) { 205ed170139SJacob Faibussowitsch const PetscFunctionListDLAll next = current->next; 206ed170139SJacob Faibussowitsch 207ed170139SJacob Faibussowitsch if (current->data == fl) { 208ed170139SJacob Faibussowitsch if (prev) { 209ed170139SJacob Faibussowitsch // somewhere in the middle (or end) of the list 210ed170139SJacob Faibussowitsch prev->next = next; 211ed170139SJacob Faibussowitsch } else { 212ed170139SJacob Faibussowitsch // prev = NULL implies current = dlallhead, so front of list 213ed170139SJacob Faibussowitsch dlallhead = next; 214ed170139SJacob Faibussowitsch } 215ed170139SJacob Faibussowitsch PetscCall(PetscFree(current)); 216ed170139SJacob Faibussowitsch break; 217ed170139SJacob Faibussowitsch } 218ed170139SJacob Faibussowitsch prev = current; 219ed170139SJacob Faibussowitsch current = next; 220ed170139SJacob Faibussowitsch } 221ed170139SJacob Faibussowitsch } 2223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 223ed170139SJacob Faibussowitsch } 224ed170139SJacob Faibussowitsch 2258434afd1SBarry Smith static PetscErrorCode PetscHMapFuncInsert_Private(PetscHMapFunc map, const char name[], PetscVoidFn *fnc) 226ed170139SJacob Faibussowitsch { 227ed170139SJacob Faibussowitsch PetscHashIter it; 228ed170139SJacob Faibussowitsch PetscBool found; 229ed170139SJacob Faibussowitsch 230ed170139SJacob Faibussowitsch PetscFunctionBegin; 2314f572ea9SToby Isaac PetscAssertPointer(name, 2); 232ed170139SJacob Faibussowitsch if (fnc) PetscValidFunction(fnc, 3); 233ed170139SJacob Faibussowitsch PetscCall(PetscHMapFuncFind(map, name, &it, &found)); 234ed170139SJacob Faibussowitsch if (fnc) { 235ed170139SJacob Faibussowitsch if (found) { 236ed170139SJacob Faibussowitsch PetscCall(PetscHMapFuncIterSet(map, it, fnc)); 237ed170139SJacob Faibussowitsch } else { 238ed170139SJacob Faibussowitsch char *tmp_name; 239ed170139SJacob Faibussowitsch 240ed170139SJacob Faibussowitsch PetscCall(PetscStrallocpy(name, &tmp_name)); 241ed170139SJacob Faibussowitsch PetscCall(PetscHMapFuncSet(map, tmp_name, fnc)); 242ed170139SJacob Faibussowitsch } 243ed170139SJacob Faibussowitsch } else if (found) { 244ed170139SJacob Faibussowitsch const char *tmp_name; 245ed170139SJacob Faibussowitsch 246ed170139SJacob Faibussowitsch PetscHashIterGetKey(map, it, tmp_name); 247ed170139SJacob Faibussowitsch PetscCall(PetscFree(tmp_name)); 248ed170139SJacob Faibussowitsch PetscCall(PetscHMapFuncIterDel(map, it)); 249ed170139SJacob Faibussowitsch } 2503ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 251ed170139SJacob Faibussowitsch } 252ed170139SJacob Faibussowitsch 253ed170139SJacob Faibussowitsch static PetscErrorCode PetscFunctionListCreate_Private(PetscInt size, PetscFunctionList *fl) 254ed170139SJacob Faibussowitsch { 255ed170139SJacob Faibussowitsch PetscFunctionBegin; 2563ba16761SJacob Faibussowitsch if (*fl) PetscFunctionReturn(PETSC_SUCCESS); 257ed170139SJacob Faibussowitsch PetscCall(PetscNew(fl)); 258ed170139SJacob Faibussowitsch PetscCall(PetscHMapFuncCreateWithSize(size, &(*fl)->map)); 259ed170139SJacob Faibussowitsch PetscCall(PetscFunctionListDLAllPush_Private(*fl)); 2603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2610e6b6b59SJacob Faibussowitsch } 2620e6b6b59SJacob Faibussowitsch 263a240a19fSJed Brown /*MC 264140e18c1SBarry Smith PetscFunctionListAdd - Given a routine and a string id, saves that routine in the 265e5c89e4eSSatish Balay specified registry. 266e5c89e4eSSatish Balay 267a240a19fSJed Brown Synopsis: 268aaa7dc30SBarry Smith #include <petscsys.h> 269b9fb364aSBarry Smith PetscErrorCode PetscFunctionListAdd(PetscFunctionList *flist,const char name[],void (*fptr)(void)) 270a240a19fSJed Brown 271d4349b43SBarry Smith Not Collective 272e5c89e4eSSatish Balay 273e5c89e4eSSatish Balay Input Parameters: 27410450e9eSJacob Faibussowitsch + fl - pointer to function list object 275e5c89e4eSSatish Balay . name - string to identify routine 276a240a19fSJed Brown - fptr - function pointer 277e5c89e4eSSatish Balay 27821532e8aSBarry Smith Level: developer 27921532e8aSBarry Smith 280e5c89e4eSSatish Balay Notes: 28121532e8aSBarry Smith 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 28821532e8aSBarry Smith .seealso: `PetscFunctionListDestroy()`, `SNESRegister()`, `KSPRegister()`,`PetscFunctionListDuplicate()` 289db781477SPatrick Sanan `PCRegister()`, `TSRegister()`, `PetscFunctionList`, `PetscObjectComposeFunction()` 290a240a19fSJed Brown M*/ 2918434afd1SBarry Smith PetscErrorCode PetscFunctionListAdd_Private(PetscFunctionList *fl, const char name[], PetscVoidFn *fptr) 292d71ae5a4SJacob Faibussowitsch { 293e5c89e4eSSatish Balay PetscFunctionBegin; 2944f572ea9SToby Isaac PetscAssertPointer(fl, 1); 2954f572ea9SToby Isaac if (name) PetscAssertPointer(name, 2); 29610450e9eSJacob Faibussowitsch if (fptr) PetscValidFunction(fptr, 3); 297ebd2f95aSStefano Zampini if (!fptr && !*fl) PetscFunctionReturn(PETSC_SUCCESS); 298ed170139SJacob Faibussowitsch PetscCall(PetscFunctionListCreate_Private(0, fl)); 29910450e9eSJacob Faibussowitsch PetscCall(PetscHMapFuncInsert_Private((*fl)->map, name, fptr)); 3003ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 301e5c89e4eSSatish Balay } 302e5c89e4eSSatish Balay 303*ffeef943SBarry Smith /*@C 304140e18c1SBarry Smith PetscFunctionListDestroy - Destroys a list of registered routines. 305e5c89e4eSSatish Balay 306e5c89e4eSSatish Balay Input Parameter: 307e5c89e4eSSatish Balay . fl - pointer to list 308e5c89e4eSSatish Balay 309e5c89e4eSSatish Balay Level: developer 310e5c89e4eSSatish Balay 3110e6b6b59SJacob Faibussowitsch .seealso: `PetscFunctionListAdd()`, `PetscFunctionList`, `PetscFunctionListClear()` 312e5c89e4eSSatish Balay @*/ 313d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFunctionListDestroy(PetscFunctionList *fl) 314d71ae5a4SJacob Faibussowitsch { 315e5c89e4eSSatish Balay PetscFunctionBegin; 3163ba16761SJacob Faibussowitsch if (!*fl) PetscFunctionReturn(PETSC_SUCCESS); 317ed170139SJacob Faibussowitsch PetscCall(PetscFunctionListDLAllPop_Private(*fl)); 318e5c89e4eSSatish Balay /* free this list */ 319ed170139SJacob Faibussowitsch PetscCall(PetscFunctionListClear(*fl)); 320ed170139SJacob Faibussowitsch PetscCall(PetscHMapFuncDestroy(&(*fl)->map)); 321ed170139SJacob Faibussowitsch PetscCall(PetscFree(*fl)); 3223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 323e5c89e4eSSatish Balay } 324e5c89e4eSSatish Balay 325ed170139SJacob Faibussowitsch #define PetscHMapFuncForEach(__func_list__, __key_name__, __val_name__, ...) \ 326ed170139SJacob Faibussowitsch do { \ 327ed170139SJacob Faibussowitsch const PetscHMapFunc phmfi_map_ = (__func_list__)->map; \ 328ed170139SJacob Faibussowitsch PetscHashIter phmfi_iter_; \ 329ed170139SJacob Faibussowitsch \ 330ed170139SJacob Faibussowitsch PetscHashIterBegin(phmfi_map_, phmfi_iter_); \ 331ed170139SJacob Faibussowitsch while (!PetscHashIterAtEnd(phmfi_map_, phmfi_iter_)) { \ 332ed170139SJacob Faibussowitsch const char *PETSC_UNUSED __key_name__; \ 3338434afd1SBarry Smith PetscVoidFn *PETSC_UNUSED __val_name__; \ 334ed170139SJacob Faibussowitsch \ 335ed170139SJacob Faibussowitsch PetscHashIterGetKey(phmfi_map_, phmfi_iter_, __key_name__); \ 336ed170139SJacob Faibussowitsch PetscHashIterGetVal(phmfi_map_, phmfi_iter_, __val_name__); \ 337ed170139SJacob Faibussowitsch { \ 338ed170139SJacob Faibussowitsch __VA_ARGS__; \ 339ed170139SJacob Faibussowitsch } \ 340ed170139SJacob Faibussowitsch PetscHashIterNext(phmfi_map_, phmfi_iter_); \ 341ed170139SJacob Faibussowitsch } /* end while */ \ 342ed170139SJacob Faibussowitsch } while (0) 343ed170139SJacob Faibussowitsch 344*ffeef943SBarry Smith /*@C 3450e6b6b59SJacob Faibussowitsch PetscFunctionListClear - Clear a `PetscFunctionList` 3460e6b6b59SJacob Faibussowitsch 3470e6b6b59SJacob Faibussowitsch Not Collective 3480e6b6b59SJacob Faibussowitsch 3490e6b6b59SJacob Faibussowitsch Input Parameter: 3500e6b6b59SJacob Faibussowitsch . fl - The `PetscFunctionList` to clear 3510e6b6b59SJacob Faibussowitsch 35221532e8aSBarry Smith Level: developer 35321532e8aSBarry Smith 3540e6b6b59SJacob Faibussowitsch Notes: 3550e6b6b59SJacob Faibussowitsch This clears the contents of `fl` but does not deallocate the entries themselves. 3560e6b6b59SJacob Faibussowitsch 3570e6b6b59SJacob Faibussowitsch .seealso: `PetscFunctionList`, `PetscFunctionListDestroy()`, `PetscFunctionListAdd()` 3580e6b6b59SJacob Faibussowitsch @*/ 359d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFunctionListClear(PetscFunctionList fl) 360d71ae5a4SJacob Faibussowitsch { 3610e6b6b59SJacob Faibussowitsch PetscFunctionBegin; 362ed170139SJacob Faibussowitsch if (fl) { 363ed170139SJacob Faibussowitsch PetscHMapFuncForEach(fl, name, func, PetscCall(PetscFree(name))); 364ed170139SJacob Faibussowitsch PetscCall(PetscHMapFuncClear(fl->map)); 3650e6b6b59SJacob Faibussowitsch } 3663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3670e6b6b59SJacob Faibussowitsch } 3680e6b6b59SJacob Faibussowitsch 369e5c89e4eSSatish Balay /* 3702e956fe4SStefano Zampini Print registered PetscFunctionLists 371e5c89e4eSSatish Balay */ 372d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFunctionListPrintAll(void) 373d71ae5a4SJacob Faibussowitsch { 374ed170139SJacob Faibussowitsch PetscFunctionListDLAll current = dlallhead; 375e5c89e4eSSatish Balay 376e5c89e4eSSatish Balay PetscFunctionBegin; 377ed170139SJacob Faibussowitsch if (current) PetscCall(PetscPrintf(PETSC_COMM_SELF, "[%d] Registered PetscFunctionLists\n", PetscGlobalRank)); 378ed170139SJacob Faibussowitsch while (current) { 379ed170139SJacob Faibussowitsch PetscCall(PetscFunctionListPrintNonEmpty(current->data)); 380ed170139SJacob Faibussowitsch current = current->next; 38137e93019SBarry Smith } 3823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 383e5c89e4eSSatish Balay } 384e5c89e4eSSatish Balay 38510450e9eSJacob Faibussowitsch /*@C 38610450e9eSJacob Faibussowitsch PetscFunctionListPrintNonEmpty - Print composed names for non `NULL` function pointers 3872e956fe4SStefano Zampini 388cc4c1da9SBarry Smith Logically Collective, No Fortran Support 389cc4c1da9SBarry Smith 3902e956fe4SStefano Zampini Input Parameter: 39110450e9eSJacob Faibussowitsch . fl - the function list 3922e956fe4SStefano Zampini 3932e956fe4SStefano Zampini Level: developer 3942e956fe4SStefano Zampini 3952e956fe4SStefano Zampini .seealso: `PetscFunctionListAdd()`, `PetscFunctionList`, `PetscObjectQueryFunction()` 39610450e9eSJacob Faibussowitsch @*/ 397d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFunctionListPrintNonEmpty(PetscFunctionList fl) 398d71ae5a4SJacob Faibussowitsch { 3992e956fe4SStefano Zampini PetscFunctionBegin; 400ed170139SJacob Faibussowitsch if (fl) { 401ed170139SJacob Faibussowitsch // clang-format off 402ed170139SJacob Faibussowitsch PetscHMapFuncForEach( 403ed170139SJacob Faibussowitsch fl, 404ed170139SJacob Faibussowitsch name, func, 405ed170139SJacob Faibussowitsch PetscCall(PetscFPrintf(PETSC_COMM_SELF, PETSC_STDOUT, "[%d] function name: %s\n", PetscGlobalRank, name)); 406ed170139SJacob Faibussowitsch ); 407ed170139SJacob Faibussowitsch // clang-format on 4082e956fe4SStefano Zampini } 4093ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4102e956fe4SStefano Zampini } 4112e956fe4SStefano Zampini 4122e956fe4SStefano Zampini /*MC 4131c9cd337SJed Brown PetscFunctionListFind - Find function registered under given name 4141c9cd337SJed Brown 415cc4c1da9SBarry Smith Not Collective, No Fortran Support 416cc4c1da9SBarry Smith 4171c9cd337SJed Brown Synopsis: 418aaa7dc30SBarry Smith #include <petscsys.h> 4191c9cd337SJed Brown PetscErrorCode PetscFunctionListFind(PetscFunctionList flist,const char name[],void (**fptr)(void)) 420e5c89e4eSSatish Balay 421e5c89e4eSSatish Balay Input Parameters: 42210450e9eSJacob Faibussowitsch + fl - the function list 4231c9cd337SJed Brown - name - name registered for the function 424e5c89e4eSSatish Balay 4252fe279fdSBarry Smith Output Parameter: 42621532e8aSBarry Smith . fptr - the function pointer if name was found, else `NULL` 427e5c89e4eSSatish Balay 428e5c89e4eSSatish Balay Level: developer 429e5c89e4eSSatish Balay 43021532e8aSBarry Smith .seealso: `PetscFunctionListAdd()`, `PetscFunctionList`, `PetscObjectQueryFunction()`, `PetscFunctionListDuplicate()` 4311c9cd337SJed Brown M*/ 4328434afd1SBarry Smith PetscErrorCode PetscFunctionListFind_Private(PetscFunctionList fl, const char name[], PetscVoidFn **fptr) 433d71ae5a4SJacob Faibussowitsch { 434e5c89e4eSSatish Balay PetscFunctionBegin; 4354f572ea9SToby Isaac PetscAssertPointer(name, 2); 4364f572ea9SToby Isaac PetscAssertPointer(fptr, 3); 43710450e9eSJacob Faibussowitsch *fptr = NULL; 43810450e9eSJacob Faibussowitsch if (fl) PetscCall(PetscHMapFuncGet(fl->map, name, fptr)); 4393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 440e5c89e4eSSatish Balay } 441e5c89e4eSSatish Balay 442*ffeef943SBarry Smith /*@C 44320f4b53cSBarry Smith PetscFunctionListView - prints out contents of a `PetscFunctionList` 444e5c89e4eSSatish Balay 44520f4b53cSBarry Smith Collective 446e5c89e4eSSatish Balay 447e5c89e4eSSatish Balay Input Parameters: 448e5c89e4eSSatish Balay + list - the list of functions 44920f4b53cSBarry Smith - viewer - the `PetscViewer` used to view the `PetscFunctionList` 450e5c89e4eSSatish Balay 451e5c89e4eSSatish Balay Level: developer 452e5c89e4eSSatish Balay 453db781477SPatrick Sanan .seealso: `PetscFunctionListAdd()`, `PetscFunctionListPrintTypes()`, `PetscFunctionList` 454e5c89e4eSSatish Balay @*/ 455d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFunctionListView(PetscFunctionList list, PetscViewer viewer) 456d71ae5a4SJacob Faibussowitsch { 457ace3abfcSBarry Smith PetscBool iascii; 458e5c89e4eSSatish Balay 459e5c89e4eSSatish Balay PetscFunctionBegin; 4604f572ea9SToby Isaac PetscAssertPointer(list, 1); 461ed170139SJacob Faibussowitsch if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PETSC_COMM_SELF, &viewer)); 4620700a824SBarry Smith PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 463e5c89e4eSSatish Balay 4649566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 46528b400f6SJacob Faibussowitsch PetscCheck(iascii, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only ASCII viewer supported"); 466ed170139SJacob Faibussowitsch { 467ed170139SJacob Faibussowitsch PetscInt size; 468e5c89e4eSSatish Balay 469ed170139SJacob Faibussowitsch PetscCall(PetscHMapFuncGetSize(list->map, &size)); 470ed170139SJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "PetscFunctionList Object:\n")); 471ed170139SJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 472ed170139SJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "size: %" PetscInt_FMT "\n", size)); 473ed170139SJacob Faibussowitsch if (size) { 474ed170139SJacob Faibussowitsch PetscInt count = 0; 475ed170139SJacob Faibussowitsch 476ed170139SJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "functions:\n")); 477ed170139SJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 478ed170139SJacob Faibussowitsch PetscHMapFuncForEach(list, name, func, PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT ": %s\n", ++count, name))); 479ed170139SJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 480e5c89e4eSSatish Balay } 481ed170139SJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 482ed170139SJacob Faibussowitsch } 4833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 484e5c89e4eSSatish Balay } 485e5c89e4eSSatish Balay 486065533a5SJed Brown /*@C 487811af0c4SBarry Smith PetscFunctionListGet - Gets an array the contains the entries in `PetscFunctionList`, this is used 488e5c89e4eSSatish Balay by help etc. 489e5c89e4eSSatish Balay 490cc4c1da9SBarry Smith Not Collective, No Fortran Support 491e5c89e4eSSatish Balay 492e5c89e4eSSatish Balay Input Parameter: 493e5c89e4eSSatish Balay . list - list of types 494e5c89e4eSSatish Balay 495d8d19677SJose E. Roman Output Parameters: 496e5c89e4eSSatish Balay + array - array of names 49721532e8aSBarry Smith - n - length of `array` 49821532e8aSBarry Smith 49921532e8aSBarry Smith Level: developer 500e5c89e4eSSatish Balay 501811af0c4SBarry Smith Note: 502a3b724e8SBarry Smith This allocates the array so that must be freed with `PetscFree()`. BUT the individual entries should not be freed. 503e5c89e4eSSatish Balay 504db781477SPatrick Sanan .seealso: `PetscFunctionListAdd()`, `PetscFunctionList` 505e5c89e4eSSatish Balay @*/ 506d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFunctionListGet(PetscFunctionList list, const char ***array, int *n) 507d71ae5a4SJacob Faibussowitsch { 508ed170139SJacob Faibussowitsch PetscInt size = 0; 509e5c89e4eSSatish Balay 510e5c89e4eSSatish Balay PetscFunctionBegin; 5114f572ea9SToby Isaac PetscAssertPointer(array, 2); 512ed170139SJacob Faibussowitsch *array = NULL; 513ed170139SJacob Faibussowitsch if (list) { 514ed170139SJacob Faibussowitsch const PetscHMapFunc map = list->map; 515ed170139SJacob Faibussowitsch PetscInt off = 0; 516ed170139SJacob Faibussowitsch 517ed170139SJacob Faibussowitsch PetscCall(PetscHMapFuncGetSize(map, &size)); 518ed170139SJacob Faibussowitsch PetscCall(PetscMalloc1(size, (char ***)array)); 519ed170139SJacob Faibussowitsch PetscCall(PetscHMapFuncGetKeys(map, &off, *array)); 520e5c89e4eSSatish Balay } 521ed170139SJacob Faibussowitsch *n = (int)size; 5223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 523e5c89e4eSSatish Balay } 524e5c89e4eSSatish Balay 525e5c89e4eSSatish Balay /*@C 526811af0c4SBarry Smith PetscFunctionListPrintTypes - Prints the methods available in a list of functions 527e5c89e4eSSatish Balay 528cc4c1da9SBarry Smith Collective, No Fortran Support 529e5c89e4eSSatish Balay 530e5c89e4eSSatish Balay Input Parameters: 531811af0c4SBarry Smith + comm - the communicator (usually `MPI_COMM_WORLD`) 53221532e8aSBarry Smith . fd - file to print to, usually `stdout` 533e5c89e4eSSatish Balay . prefix - prefix to prepend to name (optional) 53421532e8aSBarry Smith . name - option string (for example, `-ksp_type`) 535e5c89e4eSSatish Balay . text - short description of the object (for example, "Krylov solvers") 53621532e8aSBarry Smith . man - name of manual page that discusses the object (for example, `KSPCreate`) 5373cc1e11dSBarry Smith . list - list of types 53844ef3d73SBarry Smith . def - default (current) value 53944ef3d73SBarry Smith - newv - new value 540e5c89e4eSSatish Balay 541e5c89e4eSSatish Balay Level: developer 542e5c89e4eSSatish Balay 543db781477SPatrick Sanan .seealso: `PetscFunctionListAdd()`, `PetscFunctionList` 544e5c89e4eSSatish Balay @*/ 545d71ae5a4SJacob 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[]) 546d71ae5a4SJacob Faibussowitsch { 547e5c89e4eSSatish Balay char p[64]; 548e5c89e4eSSatish Balay 549e5c89e4eSSatish Balay PetscFunctionBegin; 550ed170139SJacob Faibussowitsch (void)fd; 5519566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(p, "-", sizeof(p))); 5529566063dSJacob Faibussowitsch if (prefix) PetscCall(PetscStrlcat(p, prefix, sizeof(p))); 553ed170139SJacob Faibussowitsch PetscCall((*PetscHelpPrintf)(comm, " %s%s <now %s : formerly %s>: %s (one of)", p, name + 1, newv, def, text)); 554e5c89e4eSSatish Balay 5558c7e48aeSJacob Faibussowitsch if (list) PetscHMapFuncForEach(list, name, func, PetscCall((*PetscHelpPrintf)(comm, " %s", name))); 556ed170139SJacob Faibussowitsch PetscCall((*PetscHelpPrintf)(comm, " (%s)\n", man)); 5573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 558e5c89e4eSSatish Balay } 559e5c89e4eSSatish Balay 560*ffeef943SBarry Smith /*@C 56121532e8aSBarry Smith PetscFunctionListDuplicate - Creates a new list from a given function list `PetscFunctionList`. 562e5c89e4eSSatish Balay 5632fe279fdSBarry Smith Input Parameter: 564e5c89e4eSSatish Balay . fl - pointer to list 565e5c89e4eSSatish Balay 5662fe279fdSBarry Smith Output Parameter: 56721532e8aSBarry Smith . nl - the new list (should point to `NULL` to start, otherwise appends) 568e5c89e4eSSatish Balay 569e5c89e4eSSatish Balay Level: developer 570e5c89e4eSSatish Balay 571db781477SPatrick Sanan .seealso: `PetscFunctionList`, `PetscFunctionListAdd()`, `PetscFlistDestroy()` 572e5c89e4eSSatish Balay @*/ 573d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFunctionListDuplicate(PetscFunctionList fl, PetscFunctionList *nl) 574d71ae5a4SJacob Faibussowitsch { 575e5c89e4eSSatish Balay PetscFunctionBegin; 576ed170139SJacob Faibussowitsch if (fl) { 577ed170139SJacob Faibussowitsch PetscHMapFunc dup_map; 578ed170139SJacob Faibussowitsch 579ed170139SJacob Faibussowitsch if (!*nl) { 580ed170139SJacob Faibussowitsch PetscInt n; 581ed170139SJacob Faibussowitsch 582ed170139SJacob Faibussowitsch PetscCall(PetscHMapFuncGetSize(fl->map, &n)); 583ed170139SJacob Faibussowitsch PetscCall(PetscFunctionListCreate_Private(n, nl)); 584ed170139SJacob Faibussowitsch } 585ed170139SJacob Faibussowitsch dup_map = (*nl)->map; 586ed170139SJacob Faibussowitsch PetscHMapFuncForEach(fl, name, func, PetscCall(PetscHMapFuncInsert_Private(dup_map, name, func))); 587e5c89e4eSSatish Balay } 5883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 589e5c89e4eSSatish Balay } 590