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 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 16*d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLoadDynamicLibrary(const char *name, PetscBool *found) 17*d71ae5a4SJacob 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 } 32487e5849SBarry Smith PetscFunctionReturn(0); 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 5260da17ecSBarry Smith #if defined(PETSC_HAVE_THREADSAFETY) 5322b6d1caSBarry Smith static MPI_Comm PETSC_COMM_WORLD_INNER = 0, PETSC_COMM_SELF_INNER = 0; 54acff04ddSBarry Smith #endif 55acff04ddSBarry Smith 56e5c89e4eSSatish Balay /* 57e5c89e4eSSatish Balay PetscInitialize_DynamicLibraries - Adds the default dynamic link libraries to the 58e5c89e4eSSatish Balay search path. 59e5c89e4eSSatish Balay */ 60*d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode PetscInitialize_DynamicLibraries(void) 61*d71ae5a4SJacob Faibussowitsch { 62487e5849SBarry Smith char *libname[32]; 63e5c89e4eSSatish Balay PetscInt nmax, i; 6460da17ecSBarry Smith PetscBool preload = PETSC_FALSE; 65540e20f2SPierre Jolivet #if defined(PETSC_HAVE_ELEMENTAL) 66540e20f2SPierre Jolivet PetscBool PetscInitialized = PetscInitializeCalled; 67540e20f2SPierre Jolivet #endif 68e5c89e4eSSatish Balay 6960154eb2SBarry Smith PetscFunctionBegin; 7060da17ecSBarry Smith #if defined(PETSC_HAVE_THREADSAFETY) 7160da17ecSBarry Smith /* These must be all initialized here because it is not safe for individual threads to call these initialize routines */ 7260da17ecSBarry Smith preload = PETSC_TRUE; 7360da17ecSBarry Smith #endif 7460da17ecSBarry Smith 75e5c89e4eSSatish Balay nmax = 32; 769566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetStringArray(NULL, NULL, "-dll_prepend", libname, &nmax, NULL)); 77e5c89e4eSSatish Balay for (i = 0; i < nmax; i++) { 789566063dSJacob Faibussowitsch PetscCall(PetscDLLibraryPrepend(PETSC_COMM_WORLD, &PetscDLLibrariesLoaded, libname[i])); 799566063dSJacob Faibussowitsch PetscCall(PetscFree(libname[i])); 80e5c89e4eSSatish Balay } 81e5c89e4eSSatish Balay 829566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-library_preload", &preload, NULL)); 8360da17ecSBarry Smith if (!preload) { 849566063dSJacob Faibussowitsch PetscCall(PetscSysInitializePackage()); 8560da17ecSBarry Smith } else { 8660da17ecSBarry Smith #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES) 87aa2d57e9SJed Brown PetscBool found; 8860154eb2SBarry Smith #if defined(PETSC_USE_SINGLE_LIBRARY) 899566063dSJacob Faibussowitsch PetscCall(PetscLoadDynamicLibrary("", &found)); 9028b400f6SJacob Faibussowitsch PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc dynamic library \n You cannot move the dynamic libraries!"); 9160154eb2SBarry Smith #else 929566063dSJacob Faibussowitsch PetscCall(PetscLoadDynamicLibrary("sys", &found)); 9328b400f6SJacob Faibussowitsch PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc dynamic library \n You cannot move the dynamic libraries!"); 949566063dSJacob Faibussowitsch PetscCall(PetscLoadDynamicLibrary("vec", &found)); 9528b400f6SJacob Faibussowitsch PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc Vec dynamic library \n You cannot move the dynamic libraries!"); 969566063dSJacob Faibussowitsch PetscCall(PetscLoadDynamicLibrary("mat", &found)); 9728b400f6SJacob Faibussowitsch PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc Mat dynamic library \n You cannot move the dynamic libraries!"); 989566063dSJacob Faibussowitsch PetscCall(PetscLoadDynamicLibrary("dm", &found)); 9928b400f6SJacob Faibussowitsch PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc DM dynamic library \n You cannot move the dynamic libraries!"); 1009566063dSJacob Faibussowitsch PetscCall(PetscLoadDynamicLibrary("ksp", &found)); 10128b400f6SJacob Faibussowitsch PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc KSP dynamic library \n You cannot move the dynamic libraries!"); 1029566063dSJacob Faibussowitsch PetscCall(PetscLoadDynamicLibrary("snes", &found)); 10328b400f6SJacob Faibussowitsch PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc SNES dynamic library \n You cannot move the dynamic libraries!"); 1049566063dSJacob Faibussowitsch PetscCall(PetscLoadDynamicLibrary("ts", &found)); 10528b400f6SJacob Faibussowitsch PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc TS dynamic library \n You cannot move the dynamic libraries!"); 1069566063dSJacob Faibussowitsch PetscCall(PetscLoadDynamicLibrary("tao", &found)); 10728b400f6SJacob Faibussowitsch PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate Tao dynamic library \n You cannot move the dynamic libraries!"); 108bb84e0fdSBarry Smith #endif 10960da17ecSBarry Smith #else /* defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES) */ 11060da17ecSBarry Smith #if defined(PETSC_USE_SINGLE_LIBRARY) 1119566063dSJacob Faibussowitsch PetscCall(AOInitializePackage()); 1129566063dSJacob Faibussowitsch PetscCall(PetscSFInitializePackage()); 1137da51e29SSatish Balay #if !defined(PETSC_USE_COMPLEX) 1149566063dSJacob Faibussowitsch PetscCall(CharacteristicInitializePackage()); 1157da51e29SSatish Balay #endif 1169566063dSJacob Faibussowitsch PetscCall(ISInitializePackage()); 1179566063dSJacob Faibussowitsch PetscCall(VecInitializePackage()); 1189566063dSJacob Faibussowitsch PetscCall(MatInitializePackage()); 1199566063dSJacob Faibussowitsch PetscCall(DMInitializePackage()); 1209566063dSJacob Faibussowitsch PetscCall(PCInitializePackage()); 1219566063dSJacob Faibussowitsch PetscCall(KSPInitializePackage()); 1229566063dSJacob Faibussowitsch PetscCall(SNESInitializePackage()); 1239566063dSJacob Faibussowitsch PetscCall(TSInitializePackage()); 1249566063dSJacob Faibussowitsch PetscCall(TaoInitializePackage()); 12560da17ecSBarry Smith #else 12660da17ecSBarry Smith SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP, "Cannot use -library_preload with multiple static PETSc libraries"); 12760da17ecSBarry Smith #endif 12860da17ecSBarry Smith #endif /* defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES) */ 12960da17ecSBarry Smith } 13060da17ecSBarry Smith 13160da17ecSBarry Smith #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES) && defined(PETSC_HAVE_BAMG) 13260da17ecSBarry Smith { 13360da17ecSBarry Smith PetscBool found; 1349566063dSJacob Faibussowitsch PetscCall(PetscLoadDynamicLibrary("bamg", &found)); 13528b400f6SJacob Faibussowitsch PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc BAMG dynamic library \n You cannot move the dynamic libraries!"); 13660da17ecSBarry Smith } 13760da17ecSBarry Smith #endif 13860da17ecSBarry Smith 13960da17ecSBarry Smith nmax = 32; 1409566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetStringArray(NULL, NULL, "-dll_append", libname, &nmax, NULL)); 14160da17ecSBarry Smith for (i = 0; i < nmax; i++) { 1429566063dSJacob Faibussowitsch PetscCall(PetscDLLibraryAppend(PETSC_COMM_WORLD, &PetscDLLibrariesLoaded, libname[i])); 1439566063dSJacob Faibussowitsch PetscCall(PetscFree(libname[i])); 14460da17ecSBarry Smith } 14560da17ecSBarry Smith 14660da17ecSBarry Smith #if defined(PETSC_HAVE_THREADSAFETY) 1479566063dSJacob Faibussowitsch PetscCall(PetscCommDuplicate(PETSC_COMM_SELF, &PETSC_COMM_SELF_INNER, NULL)); 1489566063dSJacob Faibussowitsch PetscCall(PetscCommDuplicate(PETSC_COMM_WORLD, &PETSC_COMM_WORLD_INNER, NULL)); 149acff04ddSBarry Smith #endif 150540e20f2SPierre Jolivet #if defined(PETSC_HAVE_ELEMENTAL) 151540e20f2SPierre Jolivet /* in Fortran, PetscInitializeCalled is set to PETSC_TRUE before PetscInitialize_DynamicLibraries() */ 152540e20f2SPierre Jolivet /* in C, it is not the case, but the value is forced to PETSC_TRUE so that PetscRegisterFinalize() is called */ 153540e20f2SPierre Jolivet PetscInitializeCalled = PETSC_TRUE; 1549566063dSJacob Faibussowitsch PetscCall(PetscElementalInitializePackage()); 155540e20f2SPierre Jolivet PetscInitializeCalled = PetscInitialized; 156540e20f2SPierre Jolivet #endif 157e5c89e4eSSatish Balay PetscFunctionReturn(0); 158e5c89e4eSSatish Balay } 159e5c89e4eSSatish Balay 160ebd79076SLisandro Dalcin /* 161ebd79076SLisandro Dalcin PetscFinalize_DynamicLibraries - Closes the opened dynamic libraries. 162ebd79076SLisandro Dalcin */ 163*d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode PetscFinalize_DynamicLibraries(void) 164*d71ae5a4SJacob Faibussowitsch { 165ace3abfcSBarry Smith PetscBool flg = PETSC_FALSE; 166e5c89e4eSSatish Balay 167ebd79076SLisandro Dalcin PetscFunctionBegin; 1689566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-dll_view", &flg, NULL)); 1699566063dSJacob Faibussowitsch if (flg) PetscCall(PetscDLLibraryPrintPath(PetscDLLibrariesLoaded)); 1709566063dSJacob Faibussowitsch PetscCall(PetscDLLibraryClose(PetscDLLibrariesLoaded)); 171a297a907SKarl Rupp 172acff04ddSBarry Smith #if defined(PETSC_HAVE_THREADSAFETY) 1739566063dSJacob Faibussowitsch PetscCall(PetscCommDestroy(&PETSC_COMM_SELF_INNER)); 1749566063dSJacob Faibussowitsch PetscCall(PetscCommDestroy(&PETSC_COMM_WORLD_INNER)); 175acff04ddSBarry Smith #endif 176acff04ddSBarry Smith 17702c9f0b5SLisandro Dalcin PetscDLLibrariesLoaded = NULL; 178e5c89e4eSSatish Balay PetscFunctionReturn(0); 179e5c89e4eSSatish Balay } 180e5c89e4eSSatish Balay 181e5c89e4eSSatish Balay /* ------------------------------------------------------------------------------*/ 182140e18c1SBarry Smith struct _n_PetscFunctionList { 183e5c89e4eSSatish Balay void (*routine)(void); /* the routine */ 184e5c89e4eSSatish Balay char *name; /* string to identify routine */ 185140e18c1SBarry Smith PetscFunctionList next; /* next pointer */ 186140e18c1SBarry Smith PetscFunctionList next_list; /* used to maintain list of all lists for freeing */ 187e5c89e4eSSatish Balay }; 188e5c89e4eSSatish Balay 189e5c89e4eSSatish Balay /* 190140e18c1SBarry Smith Keep a linked list of PetscFunctionLists so that we can destroy all the left-over ones. 191e5c89e4eSSatish Balay */ 19202c9f0b5SLisandro Dalcin static PetscFunctionList dlallhead = NULL; 193e5c89e4eSSatish Balay 194*d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscFunctionListCreateNode_Private(PetscFunctionList *entry, const char name[], void (*func)(void)) 195*d71ae5a4SJacob Faibussowitsch { 1960e6b6b59SJacob Faibussowitsch PetscFunctionBegin; 1970e6b6b59SJacob Faibussowitsch PetscCall(PetscNew(entry)); 1980e6b6b59SJacob Faibussowitsch PetscCall(PetscStrallocpy(name, &(*entry)->name)); 1990e6b6b59SJacob Faibussowitsch (*entry)->routine = func; 2000e6b6b59SJacob Faibussowitsch (*entry)->next = NULL; 2010e6b6b59SJacob Faibussowitsch PetscFunctionReturn(0); 2020e6b6b59SJacob Faibussowitsch } 2030e6b6b59SJacob Faibussowitsch 204a240a19fSJed Brown /*MC 205140e18c1SBarry Smith PetscFunctionListAdd - Given a routine and a string id, saves that routine in the 206e5c89e4eSSatish Balay specified registry. 207e5c89e4eSSatish Balay 208a240a19fSJed Brown Synopsis: 209aaa7dc30SBarry Smith #include <petscsys.h> 210b9fb364aSBarry Smith PetscErrorCode PetscFunctionListAdd(PetscFunctionList *flist,const char name[],void (*fptr)(void)) 211a240a19fSJed Brown 212d4349b43SBarry Smith Not Collective 213e5c89e4eSSatish Balay 214e5c89e4eSSatish Balay Input Parameters: 215b9fb364aSBarry Smith + flist - pointer to function list object 216e5c89e4eSSatish Balay . name - string to identify routine 217a240a19fSJed Brown - fptr - function pointer 218e5c89e4eSSatish Balay 219e5c89e4eSSatish Balay Notes: 220a240a19fSJed Brown To remove a registered routine, pass in a NULL fptr. 221e5c89e4eSSatish Balay 222e5c89e4eSSatish Balay Users who wish to register new classes for use by a particular PETSc 223811af0c4SBarry Smith component (e.g., `SNES`) should generally call the registration routine 224811af0c4SBarry Smith for that particular component (e.g., `SNESRegister()`) instead of 225811af0c4SBarry Smith calling `PetscFunctionListAdd()` directly. 226e5c89e4eSSatish Balay 227e5c89e4eSSatish Balay Level: developer 228e5c89e4eSSatish Balay 229db781477SPatrick Sanan .seealso: `PetscFunctionListDestroy()`, `SNESRegister()`, `KSPRegister()`, 230db781477SPatrick Sanan `PCRegister()`, `TSRegister()`, `PetscFunctionList`, `PetscObjectComposeFunction()` 231a240a19fSJed Brown M*/ 232*d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscFunctionListAdd_Private(PetscFunctionList *fl, const char name[], void (*fnc)(void)) 233*d71ae5a4SJacob Faibussowitsch { 234e5c89e4eSSatish Balay PetscFunctionBegin; 2350e6b6b59SJacob Faibussowitsch PetscValidPointer(fl, 1); 2360e6b6b59SJacob Faibussowitsch if (name) PetscValidCharPointer(name, 2); 2370e6b6b59SJacob Faibussowitsch if (fnc) PetscValidFunction(fnc, 3); 2380e6b6b59SJacob Faibussowitsch if (*fl) { 239e5c89e4eSSatish Balay /* search list to see if it is already there */ 2400e6b6b59SJacob Faibussowitsch PetscFunctionList empty_node = NULL; 2410e6b6b59SJacob Faibussowitsch PetscFunctionList ne = *fl; 2420e6b6b59SJacob Faibussowitsch 2430e6b6b59SJacob Faibussowitsch while (1) { 244ace3abfcSBarry Smith PetscBool founddup; 245e5c89e4eSSatish Balay 2469566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(ne->name, name, &founddup)); 2470e6b6b59SJacob Faibussowitsch if (founddup) { 2480e6b6b59SJacob Faibussowitsch /* found duplicate, clear it */ 249e5c89e4eSSatish Balay ne->routine = fnc; 2500e6b6b59SJacob Faibussowitsch if (!fnc) PetscCall(PetscFree(ne->name)); 251e5c89e4eSSatish Balay PetscFunctionReturn(0); 252e5c89e4eSSatish Balay } 2530e6b6b59SJacob Faibussowitsch 2540e6b6b59SJacob Faibussowitsch if (!empty_node && !ne->routine && !ne->name) { 2550e6b6b59SJacob Faibussowitsch /* save the empty node for later */ 2560e6b6b59SJacob Faibussowitsch empty_node = ne; 257e5c89e4eSSatish Balay } 2580e6b6b59SJacob Faibussowitsch 2590e6b6b59SJacob Faibussowitsch if (!ne->next) break; /* end of list */ 2600e6b6b59SJacob Faibussowitsch ne = ne->next; 2610e6b6b59SJacob Faibussowitsch } 2620e6b6b59SJacob Faibussowitsch 2630e6b6b59SJacob Faibussowitsch /* there was an empty entry we could grab, fill it and bail */ 2640e6b6b59SJacob Faibussowitsch if (empty_node) { 2650e6b6b59SJacob Faibussowitsch empty_node->routine = fnc; 2660e6b6b59SJacob Faibussowitsch PetscCall(PetscStrallocpy(name, &empty_node->name)); 2670e6b6b59SJacob Faibussowitsch } else { 2680e6b6b59SJacob Faibussowitsch /* create new entry at the end of list */ 2690e6b6b59SJacob Faibussowitsch PetscCall(PetscFunctionListCreateNode_Private(&ne->next, name, fnc)); 2700e6b6b59SJacob Faibussowitsch } 2710e6b6b59SJacob Faibussowitsch PetscFunctionReturn(0); 2720e6b6b59SJacob Faibussowitsch } 2730e6b6b59SJacob Faibussowitsch 2740e6b6b59SJacob Faibussowitsch /* we didn't have a list */ 2750e6b6b59SJacob Faibussowitsch PetscCall(PetscFunctionListCreateNode_Private(fl, name, fnc)); 2760e6b6b59SJacob Faibussowitsch if (PetscDefined(USE_DEBUG)) { 2770e6b6b59SJacob Faibussowitsch const PetscFunctionList head = dlallhead; 2780e6b6b59SJacob Faibussowitsch 2790e6b6b59SJacob Faibussowitsch /* add this new list to list of all lists */ 2800e6b6b59SJacob Faibussowitsch dlallhead = *fl; 2810e6b6b59SJacob Faibussowitsch (*fl)->next_list = head; 282e5c89e4eSSatish Balay } 283e5c89e4eSSatish Balay PetscFunctionReturn(0); 284e5c89e4eSSatish Balay } 285e5c89e4eSSatish Balay 286e5c89e4eSSatish Balay /*@ 287140e18c1SBarry Smith PetscFunctionListDestroy - Destroys a list of registered routines. 288e5c89e4eSSatish Balay 289e5c89e4eSSatish Balay Input Parameter: 290e5c89e4eSSatish Balay . fl - pointer to list 291e5c89e4eSSatish Balay 292e5c89e4eSSatish Balay Level: developer 293e5c89e4eSSatish Balay 2940e6b6b59SJacob Faibussowitsch .seealso: `PetscFunctionListAdd()`, `PetscFunctionList`, `PetscFunctionListClear()` 295e5c89e4eSSatish Balay @*/ 296*d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFunctionListDestroy(PetscFunctionList *fl) 297*d71ae5a4SJacob Faibussowitsch { 298140e18c1SBarry Smith PetscFunctionList next, entry, tmp = dlallhead; 299e5c89e4eSSatish Balay 300e5c89e4eSSatish Balay PetscFunctionBegin; 3011441b1d3SBarry Smith if (!*fl) PetscFunctionReturn(0); 302e5c89e4eSSatish Balay 303e5c89e4eSSatish Balay /* 3049dddd249SSatish Balay Remove this entry from the main DL list (if it is in it) 305e5c89e4eSSatish Balay */ 3061441b1d3SBarry Smith if (dlallhead == *fl) { 307a297a907SKarl Rupp if (dlallhead->next_list) dlallhead = dlallhead->next_list; 30837e93019SBarry Smith else dlallhead = NULL; 30937e93019SBarry Smith } else if (tmp) { 3101441b1d3SBarry Smith while (tmp->next_list != *fl) { 311e5c89e4eSSatish Balay tmp = tmp->next_list; 312e5c89e4eSSatish Balay if (!tmp->next_list) break; 313e5c89e4eSSatish Balay } 314e5c89e4eSSatish Balay if (tmp->next_list) tmp->next_list = tmp->next_list->next_list; 315e5c89e4eSSatish Balay } 316e5c89e4eSSatish Balay 317e5c89e4eSSatish Balay /* free this list */ 3181441b1d3SBarry Smith entry = *fl; 319e5c89e4eSSatish Balay while (entry) { 320e5c89e4eSSatish Balay next = entry->next; 3219566063dSJacob Faibussowitsch PetscCall(PetscFree(entry->name)); 3229566063dSJacob Faibussowitsch PetscCall(PetscFree(entry)); 323e5c89e4eSSatish Balay entry = next; 324e5c89e4eSSatish Balay } 32502c9f0b5SLisandro Dalcin *fl = NULL; 326e5c89e4eSSatish Balay PetscFunctionReturn(0); 327e5c89e4eSSatish Balay } 328e5c89e4eSSatish Balay 3290e6b6b59SJacob Faibussowitsch /*@ 3300e6b6b59SJacob Faibussowitsch PetscFunctionListClear - Clear a `PetscFunctionList` 3310e6b6b59SJacob Faibussowitsch 3320e6b6b59SJacob Faibussowitsch Not Collective 3330e6b6b59SJacob Faibussowitsch 3340e6b6b59SJacob Faibussowitsch Input Parameter: 3350e6b6b59SJacob Faibussowitsch . fl - The `PetscFunctionList` to clear 3360e6b6b59SJacob Faibussowitsch 3370e6b6b59SJacob Faibussowitsch Notes: 3380e6b6b59SJacob Faibussowitsch This clears the contents of `fl` but does not deallocate the entries themselves. 3390e6b6b59SJacob Faibussowitsch 3400e6b6b59SJacob Faibussowitsch Level: developer 3410e6b6b59SJacob Faibussowitsch 3420e6b6b59SJacob Faibussowitsch .seealso: `PetscFunctionList`, `PetscFunctionListDestroy()`, `PetscFunctionListAdd()` 3430e6b6b59SJacob Faibussowitsch @*/ 344*d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFunctionListClear(PetscFunctionList fl) 345*d71ae5a4SJacob Faibussowitsch { 3460e6b6b59SJacob Faibussowitsch PetscFunctionBegin; 3470e6b6b59SJacob Faibussowitsch /* free the names and clear the routine but don't deallocate the node */ 3480e6b6b59SJacob Faibussowitsch while (fl) { 3490e6b6b59SJacob Faibussowitsch PetscCall(PetscFree(fl->name)); 3500e6b6b59SJacob Faibussowitsch fl->routine = NULL; 3510e6b6b59SJacob Faibussowitsch fl = fl->next; 3520e6b6b59SJacob Faibussowitsch } 3530e6b6b59SJacob Faibussowitsch PetscFunctionReturn(0); 3540e6b6b59SJacob Faibussowitsch } 3550e6b6b59SJacob Faibussowitsch 356e5c89e4eSSatish Balay /* 3572e956fe4SStefano Zampini Print registered PetscFunctionLists 358e5c89e4eSSatish Balay */ 359*d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFunctionListPrintAll(void) 360*d71ae5a4SJacob Faibussowitsch { 36137e93019SBarry Smith PetscFunctionList tmp = dlallhead; 362e5c89e4eSSatish Balay 363e5c89e4eSSatish Balay PetscFunctionBegin; 3642e956fe4SStefano Zampini if (tmp) PetscCall(PetscPrintf(PETSC_COMM_SELF, "[%d] Registered PetscFunctionLists\n", PetscGlobalRank)); 36537e93019SBarry Smith while (tmp) { 3662e956fe4SStefano Zampini PetscCall(PetscPrintf(PETSC_COMM_SELF, "[%d] %s\n", PetscGlobalRank, tmp->name)); 36737e93019SBarry Smith tmp = tmp->next_list; 36837e93019SBarry Smith } 369e5c89e4eSSatish Balay PetscFunctionReturn(0); 370e5c89e4eSSatish Balay } 371e5c89e4eSSatish Balay 3721c9cd337SJed Brown /*MC 3732e956fe4SStefano Zampini PetscFunctionListNonEmpty - Print composed names for non null function pointers 3742e956fe4SStefano Zampini 3752e956fe4SStefano Zampini Input Parameter: 3762e956fe4SStefano Zampini . flist - pointer to list 3772e956fe4SStefano Zampini 3782e956fe4SStefano Zampini Level: developer 3792e956fe4SStefano Zampini 3802e956fe4SStefano Zampini .seealso: `PetscFunctionListAdd()`, `PetscFunctionList`, `PetscObjectQueryFunction()` 3812e956fe4SStefano Zampini M*/ 382*d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFunctionListPrintNonEmpty(PetscFunctionList fl) 383*d71ae5a4SJacob Faibussowitsch { 3842e956fe4SStefano Zampini PetscFunctionBegin; 3852e956fe4SStefano Zampini while (fl) { 3862e956fe4SStefano Zampini PetscFunctionList next = fl->next; 3872e956fe4SStefano Zampini if (fl->routine) PetscCall(PetscPrintf(PETSC_COMM_SELF, "[%d] function name: %s\n", PetscGlobalRank, fl->name)); 3882e956fe4SStefano Zampini fl = next; 3892e956fe4SStefano Zampini } 3902e956fe4SStefano Zampini PetscFunctionReturn(0); 3912e956fe4SStefano Zampini } 3922e956fe4SStefano Zampini 3932e956fe4SStefano Zampini /*MC 3941c9cd337SJed Brown PetscFunctionListFind - Find function registered under given name 3951c9cd337SJed Brown 3961c9cd337SJed Brown Synopsis: 397aaa7dc30SBarry Smith #include <petscsys.h> 3981c9cd337SJed Brown PetscErrorCode PetscFunctionListFind(PetscFunctionList flist,const char name[],void (**fptr)(void)) 399e5c89e4eSSatish Balay 400e5c89e4eSSatish Balay Input Parameters: 4011c9cd337SJed Brown + flist - pointer to list 4021c9cd337SJed Brown - name - name registered for the function 403e5c89e4eSSatish Balay 404e5c89e4eSSatish Balay Output Parameters: 4051c9cd337SJed Brown . fptr - the function pointer if name was found, else NULL 406e5c89e4eSSatish Balay 407e5c89e4eSSatish Balay Level: developer 408e5c89e4eSSatish Balay 409db781477SPatrick Sanan .seealso: `PetscFunctionListAdd()`, `PetscFunctionList`, `PetscObjectQueryFunction()` 4101c9cd337SJed Brown M*/ 411*d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscFunctionListFind_Private(PetscFunctionList fl, const char name[], void (**r)(void)) 412*d71ae5a4SJacob Faibussowitsch { 413140e18c1SBarry Smith PetscFunctionList entry = fl; 414e5c89e4eSSatish Balay 415e5c89e4eSSatish Balay PetscFunctionBegin; 4160e6b6b59SJacob Faibussowitsch PetscValidCharPointer(name, 2); 4170e6b6b59SJacob Faibussowitsch PetscValidPointer(r, 3); 418e5c89e4eSSatish Balay while (entry) { 4190e6b6b59SJacob Faibussowitsch PetscBool flg; 4200e6b6b59SJacob Faibussowitsch 4219566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, entry->name, &flg)); 422bdf89e91SBarry Smith if (flg) { 423e5c89e4eSSatish Balay *r = entry->routine; 424e5c89e4eSSatish Balay PetscFunctionReturn(0); 425e5c89e4eSSatish Balay } 426e5c89e4eSSatish Balay entry = entry->next; 427e5c89e4eSSatish Balay } 4280e6b6b59SJacob Faibussowitsch *r = NULL; 429e5c89e4eSSatish Balay PetscFunctionReturn(0); 430e5c89e4eSSatish Balay } 431e5c89e4eSSatish Balay 432e5c89e4eSSatish Balay /*@ 433140e18c1SBarry Smith PetscFunctionListView - prints out contents of an PetscFunctionList 434e5c89e4eSSatish Balay 435811af0c4SBarry Smith Collective over viewer 436e5c89e4eSSatish Balay 437e5c89e4eSSatish Balay Input Parameters: 438e5c89e4eSSatish Balay + list - the list of functions 439e5c89e4eSSatish Balay - viewer - currently ignored 440e5c89e4eSSatish Balay 441e5c89e4eSSatish Balay Level: developer 442e5c89e4eSSatish Balay 443db781477SPatrick Sanan .seealso: `PetscFunctionListAdd()`, `PetscFunctionListPrintTypes()`, `PetscFunctionList` 444e5c89e4eSSatish Balay @*/ 445*d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFunctionListView(PetscFunctionList list, PetscViewer viewer) 446*d71ae5a4SJacob Faibussowitsch { 447ace3abfcSBarry Smith PetscBool iascii; 448e5c89e4eSSatish Balay 449e5c89e4eSSatish Balay PetscFunctionBegin; 450e5c89e4eSSatish Balay if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF; 451e5c89e4eSSatish Balay PetscValidPointer(list, 1); 4520700a824SBarry Smith PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 453e5c89e4eSSatish Balay 4549566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 45528b400f6SJacob Faibussowitsch PetscCheck(iascii, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only ASCII viewer supported"); 456e5c89e4eSSatish Balay 457e5c89e4eSSatish Balay while (list) { 4589566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %s\n", list->name)); 459e5c89e4eSSatish Balay list = list->next; 460e5c89e4eSSatish Balay } 4619566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 462e5c89e4eSSatish Balay PetscFunctionReturn(0); 463e5c89e4eSSatish Balay } 464e5c89e4eSSatish Balay 465065533a5SJed Brown /*@C 466811af0c4SBarry Smith PetscFunctionListGet - Gets an array the contains the entries in `PetscFunctionList`, this is used 467e5c89e4eSSatish Balay by help etc. 468e5c89e4eSSatish Balay 469d4349b43SBarry Smith Not Collective 470e5c89e4eSSatish Balay 471e5c89e4eSSatish Balay Input Parameter: 472e5c89e4eSSatish Balay . list - list of types 473e5c89e4eSSatish Balay 474d8d19677SJose E. Roman Output Parameters: 475e5c89e4eSSatish Balay + array - array of names 476e5c89e4eSSatish Balay - n - length of array 477e5c89e4eSSatish Balay 478811af0c4SBarry Smith Note: 479e5c89e4eSSatish Balay This allocates the array so that must be freed. BUT the individual entries are 480e5c89e4eSSatish Balay not copied so should not be freed. 481e5c89e4eSSatish Balay 482e5c89e4eSSatish Balay Level: developer 483e5c89e4eSSatish Balay 484db781477SPatrick Sanan .seealso: `PetscFunctionListAdd()`, `PetscFunctionList` 485e5c89e4eSSatish Balay @*/ 486*d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFunctionListGet(PetscFunctionList list, const char ***array, int *n) 487*d71ae5a4SJacob Faibussowitsch { 488e5c89e4eSSatish Balay PetscInt count = 0; 489140e18c1SBarry Smith PetscFunctionList klist = list; 490e5c89e4eSSatish Balay 491e5c89e4eSSatish Balay PetscFunctionBegin; 492e5c89e4eSSatish Balay while (list) { 493e5c89e4eSSatish Balay list = list->next; 494e5c89e4eSSatish Balay count++; 495e5c89e4eSSatish Balay } 4969566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(count + 1, (char ***)array)); 497e5c89e4eSSatish Balay count = 0; 498e5c89e4eSSatish Balay while (klist) { 499e5c89e4eSSatish Balay (*array)[count] = klist->name; 500e5c89e4eSSatish Balay klist = klist->next; 501e5c89e4eSSatish Balay count++; 502e5c89e4eSSatish Balay } 50302c9f0b5SLisandro Dalcin (*array)[count] = NULL; 504e5c89e4eSSatish Balay *n = count + 1; 505e5c89e4eSSatish Balay PetscFunctionReturn(0); 506e5c89e4eSSatish Balay } 507e5c89e4eSSatish Balay 508e5c89e4eSSatish Balay /*@C 509811af0c4SBarry Smith PetscFunctionListPrintTypes - Prints the methods available in a list of functions 510e5c89e4eSSatish Balay 511e5c89e4eSSatish Balay Collective over MPI_Comm 512e5c89e4eSSatish Balay 513e5c89e4eSSatish Balay Input Parameters: 514811af0c4SBarry Smith + comm - the communicator (usually `MPI_COMM_WORLD`) 515e5c89e4eSSatish Balay . fd - file to print to, usually stdout 516e5c89e4eSSatish Balay . prefix - prefix to prepend to name (optional) 517e5c89e4eSSatish Balay . name - option string (for example, "-ksp_type") 518e5c89e4eSSatish Balay . text - short description of the object (for example, "Krylov solvers") 519e5c89e4eSSatish Balay . man - name of manual page that discusses the object (for example, "KSPCreate") 5203cc1e11dSBarry Smith . list - list of types 52144ef3d73SBarry Smith . def - default (current) value 52244ef3d73SBarry Smith - newv - new value 523e5c89e4eSSatish Balay 524e5c89e4eSSatish Balay Level: developer 525e5c89e4eSSatish Balay 526db781477SPatrick Sanan .seealso: `PetscFunctionListAdd()`, `PetscFunctionList` 527e5c89e4eSSatish Balay @*/ 528*d71ae5a4SJacob 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[]) 529*d71ae5a4SJacob Faibussowitsch { 530e5c89e4eSSatish Balay char p[64]; 531e5c89e4eSSatish Balay 532e5c89e4eSSatish Balay PetscFunctionBegin; 533da9f1d6bSBarry Smith if (!fd) fd = PETSC_STDOUT; 534e5c89e4eSSatish Balay 5359566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(p, "-", sizeof(p))); 5369566063dSJacob Faibussowitsch if (prefix) PetscCall(PetscStrlcat(p, prefix, sizeof(p))); 5379566063dSJacob Faibussowitsch PetscCall(PetscFPrintf(comm, fd, " %s%s <now %s : formerly %s>: %s (one of)", p, name + 1, newv, def, text)); 538e5c89e4eSSatish Balay 539e5c89e4eSSatish Balay while (list) { 5409566063dSJacob Faibussowitsch PetscCall(PetscFPrintf(comm, fd, " %s", list->name)); 541e5c89e4eSSatish Balay list = list->next; 542e5c89e4eSSatish Balay } 5439566063dSJacob Faibussowitsch PetscCall(PetscFPrintf(comm, fd, " (%s)\n", man)); 544e5c89e4eSSatish Balay PetscFunctionReturn(0); 545e5c89e4eSSatish Balay } 546e5c89e4eSSatish Balay 547e5c89e4eSSatish Balay /*@ 548140e18c1SBarry Smith PetscFunctionListDuplicate - Creates a new list from a given object list. 549e5c89e4eSSatish Balay 550e5c89e4eSSatish Balay Input Parameters: 551e5c89e4eSSatish Balay . fl - pointer to list 552e5c89e4eSSatish Balay 553e5c89e4eSSatish Balay Output Parameters: 554e5c89e4eSSatish Balay . nl - the new list (should point to 0 to start, otherwise appends) 555e5c89e4eSSatish Balay 556e5c89e4eSSatish Balay Level: developer 557e5c89e4eSSatish Balay 558db781477SPatrick Sanan .seealso: `PetscFunctionList`, `PetscFunctionListAdd()`, `PetscFlistDestroy()` 559e5c89e4eSSatish Balay @*/ 560*d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFunctionListDuplicate(PetscFunctionList fl, PetscFunctionList *nl) 561*d71ae5a4SJacob Faibussowitsch { 562e5c89e4eSSatish Balay PetscFunctionBegin; 563e5c89e4eSSatish Balay while (fl) { 5649566063dSJacob Faibussowitsch PetscCall(PetscFunctionListAdd(nl, fl->name, fl->routine)); 565e5c89e4eSSatish Balay fl = fl->next; 566e5c89e4eSSatish Balay } 567e5c89e4eSSatish Balay PetscFunctionReturn(0); 568e5c89e4eSSatish Balay } 569