xref: /petsc/src/sys/dll/reg.c (revision d71ae5a4db6382e7f06317b8d368875286fe9008)
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