xref: /petsc/src/sys/dll/reg.c (revision 48a46eb9bd028bec07ec0f396b1a3abb43f14558)
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));
29*48a46eb9SPierre 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
210e5c89e4eSSatish Balay    component (e.g., SNES) should generally call the registration routine
2111c84c290SBarry Smith    for that particular component (e.g., SNESRegister()) instead of
212140e18c1SBarry 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 
383e5c89e4eSSatish Balay    Collective over MPI_Comm
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
413140e18c1SBarry 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 
425e5c89e4eSSatish Balay    Notes:
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
455140e18c1SBarry Smith    PetscFunctionListPrintTypes - Prints the methods available.
456e5c89e4eSSatish Balay 
457e5c89e4eSSatish Balay    Collective over MPI_Comm
458e5c89e4eSSatish Balay 
459e5c89e4eSSatish Balay    Input Parameters:
460e5c89e4eSSatish Balay +  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 
505e5c89e4eSSatish Balay @*/
5069371c9d4SSatish Balay PetscErrorCode PetscFunctionListDuplicate(PetscFunctionList fl, PetscFunctionList *nl) {
507e5c89e4eSSatish Balay   PetscFunctionBegin;
508e5c89e4eSSatish Balay   while (fl) {
5099566063dSJacob Faibussowitsch     PetscCall(PetscFunctionListAdd(nl, fl->name, fl->routine));
510e5c89e4eSSatish Balay     fl = fl->next;
511e5c89e4eSSatish Balay   }
512e5c89e4eSSatish Balay   PetscFunctionReturn(0);
513e5c89e4eSSatish Balay }
514