xref: /petsc/src/sys/dll/reg.c (revision 811af0c4b09a35de4306c442f88bd09fdc09897d)
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 
169371c9d4SSatish Balay static PetscErrorCode PetscLoadDynamicLibrary(const char *name, PetscBool *found) {
17487e5849SBarry Smith   char libs[PETSC_MAX_PATH_LEN], dlib[PETSC_MAX_PATH_LEN];
18487e5849SBarry Smith 
19487e5849SBarry Smith   PetscFunctionBegin;
209566063dSJacob Faibussowitsch   PetscCall(PetscStrncpy(libs, "${PETSC_LIB_DIR}/libpetsc", sizeof(libs)));
219566063dSJacob Faibussowitsch   PetscCall(PetscStrlcat(libs, name, sizeof(libs)));
229566063dSJacob Faibussowitsch   PetscCall(PetscDLLibraryRetrieve(PETSC_COMM_WORLD, libs, dlib, 1024, found));
23487e5849SBarry Smith   if (*found) {
249566063dSJacob Faibussowitsch     PetscCall(PetscDLLibraryAppend(PETSC_COMM_WORLD, &PetscDLLibrariesLoaded, dlib));
25487e5849SBarry Smith   } else {
269566063dSJacob Faibussowitsch     PetscCall(PetscStrncpy(libs, "${PETSC_DIR}/${PETSC_ARCH}/lib/libpetsc", sizeof(libs)));
279566063dSJacob Faibussowitsch     PetscCall(PetscStrlcat(libs, name, sizeof(libs)));
289566063dSJacob Faibussowitsch     PetscCall(PetscDLLibraryRetrieve(PETSC_COMM_WORLD, libs, dlib, 1024, found));
2948a46eb9SPierre Jolivet     if (*found) PetscCall(PetscDLLibraryAppend(PETSC_COMM_WORLD, &PetscDLLibrariesLoaded, dlib));
30487e5849SBarry Smith   }
31487e5849SBarry Smith   PetscFunctionReturn(0);
32487e5849SBarry Smith }
333fa76a5bSLisandro Dalcin #endif
343fa76a5bSLisandro Dalcin 
3560da17ecSBarry Smith #if defined(PETSC_USE_SINGLE_LIBRARY) && !(defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES))
3695c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode AOInitializePackage(void);
3795c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscSFInitializePackage(void);
387da51e29SSatish Balay #if !defined(PETSC_USE_COMPLEX)
3995c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode CharacteristicInitializePackage(void);
407da51e29SSatish Balay #endif
4195c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode ISInitializePackage(void);
4295c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode VecInitializePackage(void);
4395c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode MatInitializePackage(void);
4495c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode DMInitializePackage(void);
4595c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode PCInitializePackage(void);
4695c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode KSPInitializePackage(void);
4795c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode SNESInitializePackage(void);
4895c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode TSInitializePackage(void);
4960da17ecSBarry Smith PETSC_EXTERN PetscErrorCode TaoInitializePackage(void);
5060da17ecSBarry Smith #endif
5160da17ecSBarry Smith #if defined(PETSC_HAVE_THREADSAFETY)
5222b6d1caSBarry Smith static MPI_Comm PETSC_COMM_WORLD_INNER = 0, PETSC_COMM_SELF_INNER = 0;
53acff04ddSBarry Smith #endif
54acff04ddSBarry Smith 
55e5c89e4eSSatish Balay /*
56e5c89e4eSSatish Balay     PetscInitialize_DynamicLibraries - Adds the default dynamic link libraries to the
57e5c89e4eSSatish Balay     search path.
58e5c89e4eSSatish Balay */
599371c9d4SSatish Balay PETSC_INTERN PetscErrorCode PetscInitialize_DynamicLibraries(void) {
60487e5849SBarry Smith   char     *libname[32];
61e5c89e4eSSatish Balay   PetscInt  nmax, i;
6260da17ecSBarry Smith   PetscBool preload = PETSC_FALSE;
63540e20f2SPierre Jolivet #if defined(PETSC_HAVE_ELEMENTAL)
64540e20f2SPierre Jolivet   PetscBool PetscInitialized = PetscInitializeCalled;
65540e20f2SPierre Jolivet #endif
66e5c89e4eSSatish Balay 
6760154eb2SBarry Smith   PetscFunctionBegin;
6860da17ecSBarry Smith #if defined(PETSC_HAVE_THREADSAFETY)
6960da17ecSBarry Smith   /* These must be all initialized here because it is not safe for individual threads to call these initialize routines */
7060da17ecSBarry Smith   preload = PETSC_TRUE;
7160da17ecSBarry Smith #endif
7260da17ecSBarry Smith 
73e5c89e4eSSatish Balay   nmax = 32;
749566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetStringArray(NULL, NULL, "-dll_prepend", libname, &nmax, NULL));
75e5c89e4eSSatish Balay   for (i = 0; i < nmax; i++) {
769566063dSJacob Faibussowitsch     PetscCall(PetscDLLibraryPrepend(PETSC_COMM_WORLD, &PetscDLLibrariesLoaded, libname[i]));
779566063dSJacob Faibussowitsch     PetscCall(PetscFree(libname[i]));
78e5c89e4eSSatish Balay   }
79e5c89e4eSSatish Balay 
809566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(NULL, NULL, "-library_preload", &preload, NULL));
8160da17ecSBarry Smith   if (!preload) {
829566063dSJacob Faibussowitsch     PetscCall(PetscSysInitializePackage());
8360da17ecSBarry Smith   } else {
8460da17ecSBarry Smith #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES)
85aa2d57e9SJed Brown     PetscBool found;
8660154eb2SBarry Smith #if defined(PETSC_USE_SINGLE_LIBRARY)
879566063dSJacob Faibussowitsch     PetscCall(PetscLoadDynamicLibrary("", &found));
8828b400f6SJacob Faibussowitsch     PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc dynamic library \n You cannot move the dynamic libraries!");
8960154eb2SBarry Smith #else
909566063dSJacob Faibussowitsch     PetscCall(PetscLoadDynamicLibrary("sys", &found));
9128b400f6SJacob Faibussowitsch     PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc dynamic library \n You cannot move the dynamic libraries!");
929566063dSJacob Faibussowitsch     PetscCall(PetscLoadDynamicLibrary("vec", &found));
9328b400f6SJacob Faibussowitsch     PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc Vec dynamic library \n You cannot move the dynamic libraries!");
949566063dSJacob Faibussowitsch     PetscCall(PetscLoadDynamicLibrary("mat", &found));
9528b400f6SJacob Faibussowitsch     PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc Mat dynamic library \n You cannot move the dynamic libraries!");
969566063dSJacob Faibussowitsch     PetscCall(PetscLoadDynamicLibrary("dm", &found));
9728b400f6SJacob Faibussowitsch     PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc DM dynamic library \n You cannot move the dynamic libraries!");
989566063dSJacob Faibussowitsch     PetscCall(PetscLoadDynamicLibrary("ksp", &found));
9928b400f6SJacob Faibussowitsch     PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc KSP dynamic library \n You cannot move the dynamic libraries!");
1009566063dSJacob Faibussowitsch     PetscCall(PetscLoadDynamicLibrary("snes", &found));
10128b400f6SJacob Faibussowitsch     PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc SNES dynamic library \n You cannot move the dynamic libraries!");
1029566063dSJacob Faibussowitsch     PetscCall(PetscLoadDynamicLibrary("ts", &found));
10328b400f6SJacob Faibussowitsch     PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc TS dynamic library \n You cannot move the dynamic libraries!");
1049566063dSJacob Faibussowitsch     PetscCall(PetscLoadDynamicLibrary("tao", &found));
10528b400f6SJacob Faibussowitsch     PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate Tao dynamic library \n You cannot move the dynamic libraries!");
106bb84e0fdSBarry Smith #endif
10760da17ecSBarry Smith #else /* defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES) */
10860da17ecSBarry Smith #if defined(PETSC_USE_SINGLE_LIBRARY)
1099566063dSJacob Faibussowitsch     PetscCall(AOInitializePackage());
1109566063dSJacob Faibussowitsch     PetscCall(PetscSFInitializePackage());
1117da51e29SSatish Balay #if !defined(PETSC_USE_COMPLEX)
1129566063dSJacob Faibussowitsch     PetscCall(CharacteristicInitializePackage());
1137da51e29SSatish Balay #endif
1149566063dSJacob Faibussowitsch     PetscCall(ISInitializePackage());
1159566063dSJacob Faibussowitsch     PetscCall(VecInitializePackage());
1169566063dSJacob Faibussowitsch     PetscCall(MatInitializePackage());
1179566063dSJacob Faibussowitsch     PetscCall(DMInitializePackage());
1189566063dSJacob Faibussowitsch     PetscCall(PCInitializePackage());
1199566063dSJacob Faibussowitsch     PetscCall(KSPInitializePackage());
1209566063dSJacob Faibussowitsch     PetscCall(SNESInitializePackage());
1219566063dSJacob Faibussowitsch     PetscCall(TSInitializePackage());
1229566063dSJacob Faibussowitsch     PetscCall(TaoInitializePackage());
12360da17ecSBarry Smith #else
12460da17ecSBarry Smith     SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP, "Cannot use -library_preload with multiple static PETSc libraries");
12560da17ecSBarry Smith #endif
12660da17ecSBarry Smith #endif /* defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES) */
12760da17ecSBarry Smith   }
12860da17ecSBarry Smith 
12960da17ecSBarry Smith #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES) && defined(PETSC_HAVE_BAMG)
13060da17ecSBarry Smith   {
13160da17ecSBarry Smith     PetscBool found;
1329566063dSJacob Faibussowitsch     PetscCall(PetscLoadDynamicLibrary("bamg", &found));
13328b400f6SJacob Faibussowitsch     PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc BAMG dynamic library \n You cannot move the dynamic libraries!");
13460da17ecSBarry Smith   }
13560da17ecSBarry Smith #endif
13660da17ecSBarry Smith 
13760da17ecSBarry Smith   nmax = 32;
1389566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetStringArray(NULL, NULL, "-dll_append", libname, &nmax, NULL));
13960da17ecSBarry Smith   for (i = 0; i < nmax; i++) {
1409566063dSJacob Faibussowitsch     PetscCall(PetscDLLibraryAppend(PETSC_COMM_WORLD, &PetscDLLibrariesLoaded, libname[i]));
1419566063dSJacob Faibussowitsch     PetscCall(PetscFree(libname[i]));
14260da17ecSBarry Smith   }
14360da17ecSBarry Smith 
14460da17ecSBarry Smith #if defined(PETSC_HAVE_THREADSAFETY)
1459566063dSJacob Faibussowitsch   PetscCall(PetscCommDuplicate(PETSC_COMM_SELF, &PETSC_COMM_SELF_INNER, NULL));
1469566063dSJacob Faibussowitsch   PetscCall(PetscCommDuplicate(PETSC_COMM_WORLD, &PETSC_COMM_WORLD_INNER, NULL));
147acff04ddSBarry Smith #endif
148540e20f2SPierre Jolivet #if defined(PETSC_HAVE_ELEMENTAL)
149540e20f2SPierre Jolivet   /* in Fortran, PetscInitializeCalled is set to PETSC_TRUE before PetscInitialize_DynamicLibraries() */
150540e20f2SPierre Jolivet   /* in C, it is not the case, but the value is forced to PETSC_TRUE so that PetscRegisterFinalize() is called */
151540e20f2SPierre Jolivet   PetscInitializeCalled = PETSC_TRUE;
1529566063dSJacob Faibussowitsch   PetscCall(PetscElementalInitializePackage());
153540e20f2SPierre Jolivet   PetscInitializeCalled = PetscInitialized;
154540e20f2SPierre Jolivet #endif
155e5c89e4eSSatish Balay   PetscFunctionReturn(0);
156e5c89e4eSSatish Balay }
157e5c89e4eSSatish Balay 
158ebd79076SLisandro Dalcin /*
159ebd79076SLisandro Dalcin      PetscFinalize_DynamicLibraries - Closes the opened dynamic libraries.
160ebd79076SLisandro Dalcin */
1619371c9d4SSatish Balay PETSC_INTERN PetscErrorCode PetscFinalize_DynamicLibraries(void) {
162ace3abfcSBarry Smith   PetscBool flg = PETSC_FALSE;
163e5c89e4eSSatish Balay 
164ebd79076SLisandro Dalcin   PetscFunctionBegin;
1659566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(NULL, NULL, "-dll_view", &flg, NULL));
1669566063dSJacob Faibussowitsch   if (flg) PetscCall(PetscDLLibraryPrintPath(PetscDLLibrariesLoaded));
1679566063dSJacob Faibussowitsch   PetscCall(PetscDLLibraryClose(PetscDLLibrariesLoaded));
168a297a907SKarl Rupp 
169acff04ddSBarry Smith #if defined(PETSC_HAVE_THREADSAFETY)
1709566063dSJacob Faibussowitsch   PetscCall(PetscCommDestroy(&PETSC_COMM_SELF_INNER));
1719566063dSJacob Faibussowitsch   PetscCall(PetscCommDestroy(&PETSC_COMM_WORLD_INNER));
172acff04ddSBarry Smith #endif
173acff04ddSBarry Smith 
17402c9f0b5SLisandro Dalcin   PetscDLLibrariesLoaded = NULL;
175e5c89e4eSSatish Balay   PetscFunctionReturn(0);
176e5c89e4eSSatish Balay }
177e5c89e4eSSatish Balay 
178e5c89e4eSSatish Balay /* ------------------------------------------------------------------------------*/
179140e18c1SBarry Smith struct _n_PetscFunctionList {
180e5c89e4eSSatish Balay   void (*routine)(void);       /* the routine */
181e5c89e4eSSatish Balay   char             *name;      /* string to identify routine */
182140e18c1SBarry Smith   PetscFunctionList next;      /* next pointer */
183140e18c1SBarry Smith   PetscFunctionList next_list; /* used to maintain list of all lists for freeing */
184e5c89e4eSSatish Balay };
185e5c89e4eSSatish Balay 
186e5c89e4eSSatish Balay /*
187140e18c1SBarry Smith      Keep a linked list of PetscFunctionLists so that we can destroy all the left-over ones.
188e5c89e4eSSatish Balay */
18902c9f0b5SLisandro Dalcin static PetscFunctionList dlallhead = NULL;
190e5c89e4eSSatish Balay 
191a240a19fSJed Brown /*MC
192140e18c1SBarry Smith    PetscFunctionListAdd - Given a routine and a string id, saves that routine in the
193e5c89e4eSSatish Balay    specified registry.
194e5c89e4eSSatish Balay 
195a240a19fSJed Brown    Synopsis:
196aaa7dc30SBarry Smith    #include <petscsys.h>
197b9fb364aSBarry Smith    PetscErrorCode PetscFunctionListAdd(PetscFunctionList *flist,const char name[],void (*fptr)(void))
198a240a19fSJed Brown 
199d4349b43SBarry Smith    Not Collective
200e5c89e4eSSatish Balay 
201e5c89e4eSSatish Balay    Input Parameters:
202b9fb364aSBarry Smith +  flist - pointer to function list object
203e5c89e4eSSatish Balay .  name - string to identify routine
204a240a19fSJed Brown -  fptr - function pointer
205e5c89e4eSSatish Balay 
206e5c89e4eSSatish Balay    Notes:
207a240a19fSJed Brown    To remove a registered routine, pass in a NULL fptr.
208e5c89e4eSSatish Balay 
209e5c89e4eSSatish Balay    Users who wish to register new classes for use by a particular PETSc
210*811af0c4SBarry Smith    component (e.g., `SNES`) should generally call the registration routine
211*811af0c4SBarry Smith    for that particular component (e.g., `SNESRegister()`) instead of
212*811af0c4SBarry Smith    calling `PetscFunctionListAdd()` directly.
213e5c89e4eSSatish Balay 
214e5c89e4eSSatish Balay     Level: developer
215e5c89e4eSSatish Balay 
216db781477SPatrick Sanan .seealso: `PetscFunctionListDestroy()`, `SNESRegister()`, `KSPRegister()`,
217db781477SPatrick Sanan           `PCRegister()`, `TSRegister()`, `PetscFunctionList`, `PetscObjectComposeFunction()`
218a240a19fSJed Brown M*/
2199371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode PetscFunctionListAdd_Private(PetscFunctionList *fl, const char name[], void (*fnc)(void)) {
220140e18c1SBarry Smith   PetscFunctionList entry, ne;
221e5c89e4eSSatish Balay 
222e5c89e4eSSatish Balay   PetscFunctionBegin;
223e5c89e4eSSatish Balay   if (!*fl) {
2249566063dSJacob Faibussowitsch     PetscCall(PetscNew(&entry));
2259566063dSJacob Faibussowitsch     PetscCall(PetscStrallocpy(name, &entry->name));
226e5c89e4eSSatish Balay     entry->routine = fnc;
22702c9f0b5SLisandro Dalcin     entry->next    = NULL;
228e5c89e4eSSatish Balay     *fl            = entry;
229e5c89e4eSSatish Balay 
23076bd3646SJed Brown     if (PetscDefined(USE_DEBUG)) {
231e5c89e4eSSatish Balay       /* add this new list to list of all lists */
232e5c89e4eSSatish Balay       if (!dlallhead) {
233e5c89e4eSSatish Balay         dlallhead        = *fl;
23402c9f0b5SLisandro Dalcin         (*fl)->next_list = NULL;
235e5c89e4eSSatish Balay       } else {
236e5c89e4eSSatish Balay         ne               = dlallhead;
237e5c89e4eSSatish Balay         dlallhead        = *fl;
238e5c89e4eSSatish Balay         (*fl)->next_list = ne;
239e5c89e4eSSatish Balay       }
24076bd3646SJed Brown     }
241a8a6328fSBarry Smith 
242e5c89e4eSSatish Balay   } else {
243e5c89e4eSSatish Balay     /* search list to see if it is already there */
244e5c89e4eSSatish Balay     ne = *fl;
245e5c89e4eSSatish Balay     while (ne) {
246ace3abfcSBarry Smith       PetscBool founddup;
247e5c89e4eSSatish Balay 
2489566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(ne->name, name, &founddup));
249e5c89e4eSSatish Balay       if (founddup) { /* found duplicate */
250e5c89e4eSSatish Balay         ne->routine = fnc;
251e5c89e4eSSatish Balay         PetscFunctionReturn(0);
252e5c89e4eSSatish Balay       }
253a297a907SKarl Rupp       if (ne->next) ne = ne->next;
254a297a907SKarl Rupp       else break;
255e5c89e4eSSatish Balay     }
256e5c89e4eSSatish Balay     /* create new entry and add to end of list */
2579566063dSJacob Faibussowitsch     PetscCall(PetscNew(&entry));
2589566063dSJacob Faibussowitsch     PetscCall(PetscStrallocpy(name, &entry->name));
259e5c89e4eSSatish Balay     entry->routine = fnc;
26002c9f0b5SLisandro Dalcin     entry->next    = NULL;
261e5c89e4eSSatish Balay     ne->next       = entry;
262e5c89e4eSSatish Balay   }
263e5c89e4eSSatish Balay   PetscFunctionReturn(0);
264e5c89e4eSSatish Balay }
265e5c89e4eSSatish Balay 
266e5c89e4eSSatish Balay /*@
267140e18c1SBarry Smith     PetscFunctionListDestroy - Destroys a list of registered routines.
268e5c89e4eSSatish Balay 
269e5c89e4eSSatish Balay     Input Parameter:
270e5c89e4eSSatish Balay .   fl  - pointer to list
271e5c89e4eSSatish Balay 
272e5c89e4eSSatish Balay     Level: developer
273e5c89e4eSSatish Balay 
274db781477SPatrick Sanan .seealso: `PetscFunctionListAdd()`, `PetscFunctionList`
275e5c89e4eSSatish Balay @*/
2769371c9d4SSatish Balay PetscErrorCode PetscFunctionListDestroy(PetscFunctionList *fl) {
277140e18c1SBarry Smith   PetscFunctionList next, entry, tmp = dlallhead;
278e5c89e4eSSatish Balay 
279e5c89e4eSSatish Balay   PetscFunctionBegin;
2801441b1d3SBarry Smith   if (!*fl) PetscFunctionReturn(0);
281e5c89e4eSSatish Balay 
282e5c89e4eSSatish Balay   /*
2839dddd249SSatish Balay        Remove this entry from the main DL list (if it is in it)
284e5c89e4eSSatish Balay   */
2851441b1d3SBarry Smith   if (dlallhead == *fl) {
286a297a907SKarl Rupp     if (dlallhead->next_list) dlallhead = dlallhead->next_list;
28737e93019SBarry Smith     else dlallhead = NULL;
28837e93019SBarry Smith   } else if (tmp) {
2891441b1d3SBarry Smith     while (tmp->next_list != *fl) {
290e5c89e4eSSatish Balay       tmp = tmp->next_list;
291e5c89e4eSSatish Balay       if (!tmp->next_list) break;
292e5c89e4eSSatish Balay     }
293e5c89e4eSSatish Balay     if (tmp->next_list) tmp->next_list = tmp->next_list->next_list;
294e5c89e4eSSatish Balay   }
295e5c89e4eSSatish Balay 
296e5c89e4eSSatish Balay   /* free this list */
2971441b1d3SBarry Smith   entry = *fl;
298e5c89e4eSSatish Balay   while (entry) {
299e5c89e4eSSatish Balay     next = entry->next;
3009566063dSJacob Faibussowitsch     PetscCall(PetscFree(entry->name));
3019566063dSJacob Faibussowitsch     PetscCall(PetscFree(entry));
302e5c89e4eSSatish Balay     entry = next;
303e5c89e4eSSatish Balay   }
30402c9f0b5SLisandro Dalcin   *fl = NULL;
305e5c89e4eSSatish Balay   PetscFunctionReturn(0);
306e5c89e4eSSatish Balay }
307e5c89e4eSSatish Balay 
308e5c89e4eSSatish Balay /*
3092e956fe4SStefano Zampini    Print registered PetscFunctionLists
310e5c89e4eSSatish Balay */
3119371c9d4SSatish Balay PetscErrorCode PetscFunctionListPrintAll(void) {
31237e93019SBarry Smith   PetscFunctionList tmp = dlallhead;
313e5c89e4eSSatish Balay 
314e5c89e4eSSatish Balay   PetscFunctionBegin;
3152e956fe4SStefano Zampini   if (tmp) PetscCall(PetscPrintf(PETSC_COMM_SELF, "[%d] Registered PetscFunctionLists\n", PetscGlobalRank));
31637e93019SBarry Smith   while (tmp) {
3172e956fe4SStefano Zampini     PetscCall(PetscPrintf(PETSC_COMM_SELF, "[%d]   %s\n", PetscGlobalRank, tmp->name));
31837e93019SBarry Smith     tmp = tmp->next_list;
31937e93019SBarry Smith   }
320e5c89e4eSSatish Balay   PetscFunctionReturn(0);
321e5c89e4eSSatish Balay }
322e5c89e4eSSatish Balay 
3231c9cd337SJed Brown /*MC
3242e956fe4SStefano Zampini     PetscFunctionListNonEmpty - Print composed names for non null function pointers
3252e956fe4SStefano Zampini 
3262e956fe4SStefano Zampini     Input Parameter:
3272e956fe4SStefano Zampini .   flist   - pointer to list
3282e956fe4SStefano Zampini 
3292e956fe4SStefano Zampini     Level: developer
3302e956fe4SStefano Zampini 
3312e956fe4SStefano Zampini .seealso: `PetscFunctionListAdd()`, `PetscFunctionList`, `PetscObjectQueryFunction()`
3322e956fe4SStefano Zampini M*/
3339371c9d4SSatish Balay PetscErrorCode PetscFunctionListPrintNonEmpty(PetscFunctionList fl) {
3342e956fe4SStefano Zampini   PetscFunctionBegin;
3352e956fe4SStefano Zampini   while (fl) {
3362e956fe4SStefano Zampini     PetscFunctionList next = fl->next;
3372e956fe4SStefano Zampini     if (fl->routine) PetscCall(PetscPrintf(PETSC_COMM_SELF, "[%d] function name: %s\n", PetscGlobalRank, fl->name));
3382e956fe4SStefano Zampini     fl = next;
3392e956fe4SStefano Zampini   }
3402e956fe4SStefano Zampini   PetscFunctionReturn(0);
3412e956fe4SStefano Zampini }
3422e956fe4SStefano Zampini 
3432e956fe4SStefano Zampini /*MC
3441c9cd337SJed Brown     PetscFunctionListFind - Find function registered under given name
3451c9cd337SJed Brown 
3461c9cd337SJed Brown     Synopsis:
347aaa7dc30SBarry Smith     #include <petscsys.h>
3481c9cd337SJed Brown     PetscErrorCode PetscFunctionListFind(PetscFunctionList flist,const char name[],void (**fptr)(void))
349e5c89e4eSSatish Balay 
350e5c89e4eSSatish Balay     Input Parameters:
3511c9cd337SJed Brown +   flist   - pointer to list
3521c9cd337SJed Brown -   name - name registered for the function
353e5c89e4eSSatish Balay 
354e5c89e4eSSatish Balay     Output Parameters:
3551c9cd337SJed Brown .   fptr - the function pointer if name was found, else NULL
356e5c89e4eSSatish Balay 
357e5c89e4eSSatish Balay     Level: developer
358e5c89e4eSSatish Balay 
359db781477SPatrick Sanan .seealso: `PetscFunctionListAdd()`, `PetscFunctionList`, `PetscObjectQueryFunction()`
3601c9cd337SJed Brown M*/
3619371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode PetscFunctionListFind_Private(PetscFunctionList fl, const char name[], void (**r)(void)) {
362140e18c1SBarry Smith   PetscFunctionList entry = fl;
363bdf89e91SBarry Smith   PetscBool         flg;
364e5c89e4eSSatish Balay 
365e5c89e4eSSatish Balay   PetscFunctionBegin;
36628b400f6SJacob Faibussowitsch   PetscCheck(name, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Trying to find routine with null name");
367e5c89e4eSSatish Balay 
36802c9f0b5SLisandro Dalcin   *r = NULL;
369e5c89e4eSSatish Balay   while (entry) {
3709566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, entry->name, &flg));
371bdf89e91SBarry Smith     if (flg) {
372e5c89e4eSSatish Balay       *r = entry->routine;
373e5c89e4eSSatish Balay       PetscFunctionReturn(0);
374e5c89e4eSSatish Balay     }
375e5c89e4eSSatish Balay     entry = entry->next;
376e5c89e4eSSatish Balay   }
377e5c89e4eSSatish Balay   PetscFunctionReturn(0);
378e5c89e4eSSatish Balay }
379e5c89e4eSSatish Balay 
380e5c89e4eSSatish Balay /*@
381140e18c1SBarry Smith    PetscFunctionListView - prints out contents of an PetscFunctionList
382e5c89e4eSSatish Balay 
383*811af0c4SBarry Smith    Collective over viewer
384e5c89e4eSSatish Balay 
385e5c89e4eSSatish Balay    Input Parameters:
386e5c89e4eSSatish Balay +  list - the list of functions
387e5c89e4eSSatish Balay -  viewer - currently ignored
388e5c89e4eSSatish Balay 
389e5c89e4eSSatish Balay    Level: developer
390e5c89e4eSSatish Balay 
391db781477SPatrick Sanan .seealso: `PetscFunctionListAdd()`, `PetscFunctionListPrintTypes()`, `PetscFunctionList`
392e5c89e4eSSatish Balay @*/
3939371c9d4SSatish Balay PetscErrorCode PetscFunctionListView(PetscFunctionList list, PetscViewer viewer) {
394ace3abfcSBarry Smith   PetscBool iascii;
395e5c89e4eSSatish Balay 
396e5c89e4eSSatish Balay   PetscFunctionBegin;
397e5c89e4eSSatish Balay   if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;
398e5c89e4eSSatish Balay   PetscValidPointer(list, 1);
3990700a824SBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
400e5c89e4eSSatish Balay 
4019566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
40228b400f6SJacob Faibussowitsch   PetscCheck(iascii, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only ASCII viewer supported");
403e5c89e4eSSatish Balay 
404e5c89e4eSSatish Balay   while (list) {
4059566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, " %s\n", list->name));
406e5c89e4eSSatish Balay     list = list->next;
407e5c89e4eSSatish Balay   }
4089566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
409e5c89e4eSSatish Balay   PetscFunctionReturn(0);
410e5c89e4eSSatish Balay }
411e5c89e4eSSatish Balay 
412065533a5SJed Brown /*@C
413*811af0c4SBarry Smith    PetscFunctionListGet - Gets an array the contains the entries in `PetscFunctionList`, this is used
414e5c89e4eSSatish Balay          by help etc.
415e5c89e4eSSatish Balay 
416d4349b43SBarry Smith    Not Collective
417e5c89e4eSSatish Balay 
418e5c89e4eSSatish Balay    Input Parameter:
419e5c89e4eSSatish Balay .  list   - list of types
420e5c89e4eSSatish Balay 
421d8d19677SJose E. Roman    Output Parameters:
422e5c89e4eSSatish Balay +  array - array of names
423e5c89e4eSSatish Balay -  n - length of array
424e5c89e4eSSatish Balay 
425*811af0c4SBarry Smith    Note:
426e5c89e4eSSatish Balay        This allocates the array so that must be freed. BUT the individual entries are
427e5c89e4eSSatish Balay     not copied so should not be freed.
428e5c89e4eSSatish Balay 
429e5c89e4eSSatish Balay    Level: developer
430e5c89e4eSSatish Balay 
431db781477SPatrick Sanan .seealso: `PetscFunctionListAdd()`, `PetscFunctionList`
432e5c89e4eSSatish Balay @*/
4339371c9d4SSatish Balay PetscErrorCode PetscFunctionListGet(PetscFunctionList list, const char ***array, int *n) {
434e5c89e4eSSatish Balay   PetscInt          count = 0;
435140e18c1SBarry Smith   PetscFunctionList klist = list;
436e5c89e4eSSatish Balay 
437e5c89e4eSSatish Balay   PetscFunctionBegin;
438e5c89e4eSSatish Balay   while (list) {
439e5c89e4eSSatish Balay     list = list->next;
440e5c89e4eSSatish Balay     count++;
441e5c89e4eSSatish Balay   }
4429566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(count + 1, (char ***)array));
443e5c89e4eSSatish Balay   count = 0;
444e5c89e4eSSatish Balay   while (klist) {
445e5c89e4eSSatish Balay     (*array)[count] = klist->name;
446e5c89e4eSSatish Balay     klist           = klist->next;
447e5c89e4eSSatish Balay     count++;
448e5c89e4eSSatish Balay   }
44902c9f0b5SLisandro Dalcin   (*array)[count] = NULL;
450e5c89e4eSSatish Balay   *n              = count + 1;
451e5c89e4eSSatish Balay   PetscFunctionReturn(0);
452e5c89e4eSSatish Balay }
453e5c89e4eSSatish Balay 
454e5c89e4eSSatish Balay /*@C
455*811af0c4SBarry Smith    PetscFunctionListPrintTypes - Prints the methods available in a list of functions
456e5c89e4eSSatish Balay 
457e5c89e4eSSatish Balay    Collective over MPI_Comm
458e5c89e4eSSatish Balay 
459e5c89e4eSSatish Balay    Input Parameters:
460*811af0c4SBarry Smith +  comm   - the communicator (usually `MPI_COMM_WORLD`)
461e5c89e4eSSatish Balay .  fd     - file to print to, usually stdout
462e5c89e4eSSatish Balay .  prefix - prefix to prepend to name (optional)
463e5c89e4eSSatish Balay .  name   - option string (for example, "-ksp_type")
464e5c89e4eSSatish Balay .  text - short description of the object (for example, "Krylov solvers")
465e5c89e4eSSatish Balay .  man - name of manual page that discusses the object (for example, "KSPCreate")
4663cc1e11dSBarry Smith .  list   - list of types
46744ef3d73SBarry Smith .  def - default (current) value
46844ef3d73SBarry Smith -  newv - new value
469e5c89e4eSSatish Balay 
470e5c89e4eSSatish Balay    Level: developer
471e5c89e4eSSatish Balay 
472db781477SPatrick Sanan .seealso: `PetscFunctionListAdd()`, `PetscFunctionList`
473e5c89e4eSSatish Balay @*/
4749371c9d4SSatish Balay 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[]) {
475e5c89e4eSSatish Balay   char p[64];
476e5c89e4eSSatish Balay 
477e5c89e4eSSatish Balay   PetscFunctionBegin;
478da9f1d6bSBarry Smith   if (!fd) fd = PETSC_STDOUT;
479e5c89e4eSSatish Balay 
4809566063dSJacob Faibussowitsch   PetscCall(PetscStrncpy(p, "-", sizeof(p)));
4819566063dSJacob Faibussowitsch   if (prefix) PetscCall(PetscStrlcat(p, prefix, sizeof(p)));
4829566063dSJacob Faibussowitsch   PetscCall(PetscFPrintf(comm, fd, "  %s%s <now %s : formerly %s>: %s (one of)", p, name + 1, newv, def, text));
483e5c89e4eSSatish Balay 
484e5c89e4eSSatish Balay   while (list) {
4859566063dSJacob Faibussowitsch     PetscCall(PetscFPrintf(comm, fd, " %s", list->name));
486e5c89e4eSSatish Balay     list = list->next;
487e5c89e4eSSatish Balay   }
4889566063dSJacob Faibussowitsch   PetscCall(PetscFPrintf(comm, fd, " (%s)\n", man));
489e5c89e4eSSatish Balay   PetscFunctionReturn(0);
490e5c89e4eSSatish Balay }
491e5c89e4eSSatish Balay 
492e5c89e4eSSatish Balay /*@
493140e18c1SBarry Smith     PetscFunctionListDuplicate - Creates a new list from a given object list.
494e5c89e4eSSatish Balay 
495e5c89e4eSSatish Balay     Input Parameters:
496e5c89e4eSSatish Balay .   fl   - pointer to list
497e5c89e4eSSatish Balay 
498e5c89e4eSSatish Balay     Output Parameters:
499e5c89e4eSSatish Balay .   nl - the new list (should point to 0 to start, otherwise appends)
500e5c89e4eSSatish Balay 
501e5c89e4eSSatish Balay     Level: developer
502e5c89e4eSSatish Balay 
503db781477SPatrick Sanan .seealso: `PetscFunctionList`, `PetscFunctionListAdd()`, `PetscFlistDestroy()`
504e5c89e4eSSatish Balay @*/
5059371c9d4SSatish Balay PetscErrorCode PetscFunctionListDuplicate(PetscFunctionList fl, PetscFunctionList *nl) {
506e5c89e4eSSatish Balay   PetscFunctionBegin;
507e5c89e4eSSatish Balay   while (fl) {
5089566063dSJacob Faibussowitsch     PetscCall(PetscFunctionListAdd(nl, fl->name, fl->routine));
509e5c89e4eSSatish Balay     fl = fl->next;
510e5c89e4eSSatish Balay   }
511e5c89e4eSSatish Balay   PetscFunctionReturn(0);
512e5c89e4eSSatish Balay }
513