xref: /petsc/src/sys/dll/reg.c (revision 9f196a0264fbaf0568fead3a30c861c7ae4cf663)
1e5c89e4eSSatish Balay /*
2e5c89e4eSSatish Balay     Provides a general mechanism to allow one to register new routines in
3e5c89e4eSSatish Balay     dynamic libraries for many of the PETSc objects (including, e.g., KSP and PC).
4e5c89e4eSSatish Balay */
5af0996ceSBarry Smith #include <petsc/private/petscimpl.h> /*I "petscsys.h" I*/
6665c2dedSJed Brown #include <petscviewer.h>
7e5c89e4eSSatish Balay 
8ed170139SJacob Faibussowitsch #include <petsc/private/hashmap.h>
93fa76a5bSLisandro Dalcin /*
103fa76a5bSLisandro Dalcin     This is the default list used by PETSc with the PetscDLLibrary register routines
113fa76a5bSLisandro Dalcin */
1202c9f0b5SLisandro Dalcin PetscDLLibrary PetscDLLibrariesLoaded = NULL;
133fa76a5bSLisandro Dalcin 
14cbd104e6SBarry Smith #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES)
15ebd79076SLisandro Dalcin 
16d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscLoadDynamicLibrary(const char *name, PetscBool *found)
17d71ae5a4SJacob Faibussowitsch {
18487e5849SBarry Smith   char libs[PETSC_MAX_PATH_LEN], dlib[PETSC_MAX_PATH_LEN];
19487e5849SBarry Smith 
20487e5849SBarry Smith   PetscFunctionBegin;
219566063dSJacob Faibussowitsch   PetscCall(PetscStrncpy(libs, "${PETSC_LIB_DIR}/libpetsc", sizeof(libs)));
229566063dSJacob Faibussowitsch   PetscCall(PetscStrlcat(libs, name, sizeof(libs)));
23859f1752SFrancesco Ballarin   #if defined(PETSC_LIB_NAME_SUFFIX)
24859f1752SFrancesco Ballarin   PetscCall(PetscStrlcat(libs, PETSC_LIB_NAME_SUFFIX, sizeof(libs)));
25859f1752SFrancesco Ballarin   #endif
269566063dSJacob Faibussowitsch   PetscCall(PetscDLLibraryRetrieve(PETSC_COMM_WORLD, libs, dlib, 1024, found));
27487e5849SBarry Smith   if (*found) {
289566063dSJacob Faibussowitsch     PetscCall(PetscDLLibraryAppend(PETSC_COMM_WORLD, &PetscDLLibrariesLoaded, dlib));
29487e5849SBarry Smith   } else {
309566063dSJacob Faibussowitsch     PetscCall(PetscStrncpy(libs, "${PETSC_DIR}/${PETSC_ARCH}/lib/libpetsc", sizeof(libs)));
319566063dSJacob Faibussowitsch     PetscCall(PetscStrlcat(libs, name, sizeof(libs)));
32859f1752SFrancesco Ballarin   #if defined(PETSC_LIB_NAME_SUFFIX)
33859f1752SFrancesco Ballarin     PetscCall(PetscStrlcat(libs, PETSC_LIB_NAME_SUFFIX, sizeof(libs)));
34859f1752SFrancesco Ballarin   #endif
359566063dSJacob Faibussowitsch     PetscCall(PetscDLLibraryRetrieve(PETSC_COMM_WORLD, libs, dlib, 1024, found));
3648a46eb9SPierre Jolivet     if (*found) PetscCall(PetscDLLibraryAppend(PETSC_COMM_WORLD, &PetscDLLibrariesLoaded, dlib));
37487e5849SBarry Smith   }
383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
39487e5849SBarry Smith }
403fa76a5bSLisandro Dalcin #endif
413fa76a5bSLisandro Dalcin 
4260da17ecSBarry Smith #if defined(PETSC_USE_SINGLE_LIBRARY) && !(defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES))
4395c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode AOInitializePackage(void);
4495c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscSFInitializePackage(void);
457da51e29SSatish Balay   #if !defined(PETSC_USE_COMPLEX)
4695c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode CharacteristicInitializePackage(void);
477da51e29SSatish Balay   #endif
4895c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode ISInitializePackage(void);
4995c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode VecInitializePackage(void);
5095c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode MatInitializePackage(void);
5195c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode DMInitializePackage(void);
5295c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode PCInitializePackage(void);
5395c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode KSPInitializePackage(void);
5495c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode SNESInitializePackage(void);
5595c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode TSInitializePackage(void);
5660da17ecSBarry Smith PETSC_EXTERN PetscErrorCode TaoInitializePackage(void);
5760da17ecSBarry Smith #endif
58acff04ddSBarry Smith 
59e5c89e4eSSatish Balay /*
60e5c89e4eSSatish Balay     PetscInitialize_DynamicLibraries - Adds the default dynamic link libraries to the
61e5c89e4eSSatish Balay     search path.
62e5c89e4eSSatish Balay */
63d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode PetscInitialize_DynamicLibraries(void)
64d71ae5a4SJacob Faibussowitsch {
65487e5849SBarry Smith   char     *libname[32];
66e5c89e4eSSatish Balay   PetscInt  nmax, i;
6760da17ecSBarry Smith   PetscBool preload = PETSC_FALSE;
68540e20f2SPierre Jolivet #if defined(PETSC_HAVE_ELEMENTAL)
69540e20f2SPierre Jolivet   PetscBool PetscInitialized = PetscInitializeCalled;
70540e20f2SPierre Jolivet #endif
71e5c89e4eSSatish Balay 
7260154eb2SBarry Smith   PetscFunctionBegin;
7360da17ecSBarry Smith #if defined(PETSC_HAVE_THREADSAFETY)
7460da17ecSBarry Smith   /* These must be all initialized here because it is not safe for individual threads to call these initialize routines */
7560da17ecSBarry Smith   preload = PETSC_TRUE;
7660da17ecSBarry Smith #endif
7760da17ecSBarry Smith 
78e5c89e4eSSatish Balay   nmax = 32;
799566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetStringArray(NULL, NULL, "-dll_prepend", libname, &nmax, NULL));
80e5c89e4eSSatish Balay   for (i = 0; i < nmax; i++) {
819566063dSJacob Faibussowitsch     PetscCall(PetscDLLibraryPrepend(PETSC_COMM_WORLD, &PetscDLLibrariesLoaded, libname[i]));
829566063dSJacob Faibussowitsch     PetscCall(PetscFree(libname[i]));
83e5c89e4eSSatish Balay   }
84e5c89e4eSSatish Balay 
859566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(NULL, NULL, "-library_preload", &preload, NULL));
8660da17ecSBarry Smith   if (!preload) {
879566063dSJacob Faibussowitsch     PetscCall(PetscSysInitializePackage());
8860da17ecSBarry Smith   } else {
8960da17ecSBarry Smith #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES)
90aa2d57e9SJed Brown     PetscBool found;
9160154eb2SBarry Smith   #if defined(PETSC_USE_SINGLE_LIBRARY)
929566063dSJacob Faibussowitsch     PetscCall(PetscLoadDynamicLibrary("", &found));
9300045ab3SPierre Jolivet     PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc dynamic library. You cannot move the dynamic libraries!");
9460154eb2SBarry Smith   #else
959566063dSJacob Faibussowitsch     PetscCall(PetscLoadDynamicLibrary("sys", &found));
9600045ab3SPierre Jolivet     PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc Sys dynamic library. You cannot move the dynamic libraries!");
979566063dSJacob Faibussowitsch     PetscCall(PetscLoadDynamicLibrary("vec", &found));
9800045ab3SPierre Jolivet     PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc Vec dynamic library. You cannot move the dynamic libraries!");
999566063dSJacob Faibussowitsch     PetscCall(PetscLoadDynamicLibrary("mat", &found));
10000045ab3SPierre Jolivet     PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc Mat dynamic library. You cannot move the dynamic libraries!");
1019566063dSJacob Faibussowitsch     PetscCall(PetscLoadDynamicLibrary("dm", &found));
10200045ab3SPierre Jolivet     PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc DM dynamic library. You cannot move the dynamic libraries!");
1039566063dSJacob Faibussowitsch     PetscCall(PetscLoadDynamicLibrary("ksp", &found));
10400045ab3SPierre Jolivet     PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc KSP dynamic library. You cannot move the dynamic libraries!");
1059566063dSJacob Faibussowitsch     PetscCall(PetscLoadDynamicLibrary("snes", &found));
10600045ab3SPierre Jolivet     PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc SNES dynamic library. You cannot move the dynamic libraries!");
1079566063dSJacob Faibussowitsch     PetscCall(PetscLoadDynamicLibrary("ts", &found));
10800045ab3SPierre Jolivet     PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc TS dynamic library. You cannot move the dynamic libraries!");
1099566063dSJacob Faibussowitsch     PetscCall(PetscLoadDynamicLibrary("tao", &found));
11000045ab3SPierre Jolivet     PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate Tao dynamic library. You cannot move the dynamic libraries!");
111bb84e0fdSBarry Smith   #endif
11260da17ecSBarry Smith #else /* defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES) */
11360da17ecSBarry Smith   #if defined(PETSC_USE_SINGLE_LIBRARY)
1149566063dSJacob Faibussowitsch     PetscCall(AOInitializePackage());
1159566063dSJacob Faibussowitsch     PetscCall(PetscSFInitializePackage());
1167da51e29SSatish Balay     #if !defined(PETSC_USE_COMPLEX)
1179566063dSJacob Faibussowitsch     PetscCall(CharacteristicInitializePackage());
1187da51e29SSatish Balay     #endif
1199566063dSJacob Faibussowitsch     PetscCall(ISInitializePackage());
1209566063dSJacob Faibussowitsch     PetscCall(VecInitializePackage());
1219566063dSJacob Faibussowitsch     PetscCall(MatInitializePackage());
1229566063dSJacob Faibussowitsch     PetscCall(DMInitializePackage());
1239566063dSJacob Faibussowitsch     PetscCall(PCInitializePackage());
1249566063dSJacob Faibussowitsch     PetscCall(KSPInitializePackage());
1259566063dSJacob Faibussowitsch     PetscCall(SNESInitializePackage());
1269566063dSJacob Faibussowitsch     PetscCall(TSInitializePackage());
1279566063dSJacob Faibussowitsch     PetscCall(TaoInitializePackage());
12860da17ecSBarry Smith   #else
12960da17ecSBarry Smith     SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP, "Cannot use -library_preload with multiple static PETSc libraries");
13060da17ecSBarry Smith   #endif
13160da17ecSBarry Smith #endif /* defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES) */
13260da17ecSBarry Smith   }
13360da17ecSBarry Smith 
13460da17ecSBarry Smith #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES) && defined(PETSC_HAVE_BAMG)
13560da17ecSBarry Smith   {
13660da17ecSBarry Smith     PetscBool found;
1379566063dSJacob Faibussowitsch     PetscCall(PetscLoadDynamicLibrary("bamg", &found));
13800045ab3SPierre Jolivet     PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc BAMG dynamic library. You cannot move the dynamic libraries!");
13960da17ecSBarry Smith   }
14060da17ecSBarry Smith #endif
14160da17ecSBarry Smith 
14260da17ecSBarry Smith   nmax = 32;
1439566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetStringArray(NULL, NULL, "-dll_append", libname, &nmax, NULL));
14460da17ecSBarry Smith   for (i = 0; i < nmax; i++) {
1459566063dSJacob Faibussowitsch     PetscCall(PetscDLLibraryAppend(PETSC_COMM_WORLD, &PetscDLLibrariesLoaded, libname[i]));
1469566063dSJacob Faibussowitsch     PetscCall(PetscFree(libname[i]));
14760da17ecSBarry Smith   }
14860da17ecSBarry Smith 
149540e20f2SPierre Jolivet #if defined(PETSC_HAVE_ELEMENTAL)
150540e20f2SPierre Jolivet   /* in Fortran, PetscInitializeCalled is set to PETSC_TRUE before PetscInitialize_DynamicLibraries() */
151540e20f2SPierre Jolivet   /* in C, it is not the case, but the value is forced to PETSC_TRUE so that PetscRegisterFinalize() is called */
152540e20f2SPierre Jolivet   PetscInitializeCalled = PETSC_TRUE;
1539566063dSJacob Faibussowitsch   PetscCall(PetscElementalInitializePackage());
154540e20f2SPierre Jolivet   PetscInitializeCalled = PetscInitialized;
155540e20f2SPierre Jolivet #endif
1563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
157e5c89e4eSSatish Balay }
158e5c89e4eSSatish Balay 
159ebd79076SLisandro Dalcin /*
160ebd79076SLisandro Dalcin      PetscFinalize_DynamicLibraries - Closes the opened dynamic libraries.
161ebd79076SLisandro Dalcin */
162d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode PetscFinalize_DynamicLibraries(void)
163d71ae5a4SJacob Faibussowitsch {
164ace3abfcSBarry Smith   PetscBool flg = PETSC_FALSE;
165e5c89e4eSSatish Balay 
166ebd79076SLisandro Dalcin   PetscFunctionBegin;
1679566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(NULL, NULL, "-dll_view", &flg, NULL));
1689566063dSJacob Faibussowitsch   if (flg) PetscCall(PetscDLLibraryPrintPath(PetscDLLibrariesLoaded));
1699566063dSJacob Faibussowitsch   PetscCall(PetscDLLibraryClose(PetscDLLibrariesLoaded));
17002c9f0b5SLisandro Dalcin   PetscDLLibrariesLoaded = NULL;
1713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
172e5c89e4eSSatish Balay }
173e5c89e4eSSatish Balay 
1748434afd1SBarry Smith PETSC_HASH_MAP(HMapFunc, const char *, PetscVoidFn *, kh_str_hash_func, kh_str_hash_equal, NULL)
175ed170139SJacob Faibussowitsch 
176140e18c1SBarry Smith struct _n_PetscFunctionList {
177ed170139SJacob Faibussowitsch   PetscHMapFunc map;
178e5c89e4eSSatish Balay };
179e5c89e4eSSatish Balay 
180ed170139SJacob Faibussowitsch /* Keep a linked list of PetscFunctionLists so that we can destroy all the left-over ones. */
181ed170139SJacob Faibussowitsch typedef struct n_PetscFunctionListDLAll *PetscFunctionListDLAll;
182ed170139SJacob Faibussowitsch struct n_PetscFunctionListDLAll {
183ed170139SJacob Faibussowitsch   PetscFunctionList      data;
184ed170139SJacob Faibussowitsch   PetscFunctionListDLAll next;
185ed170139SJacob Faibussowitsch };
186e5c89e4eSSatish Balay 
187ed170139SJacob Faibussowitsch static PetscFunctionListDLAll dlallhead = NULL;
188ed170139SJacob Faibussowitsch 
189ed170139SJacob Faibussowitsch static PetscErrorCode PetscFunctionListDLAllPush_Private(PetscFunctionList fl)
190d71ae5a4SJacob Faibussowitsch {
1910e6b6b59SJacob Faibussowitsch   PetscFunctionBegin;
192ed170139SJacob Faibussowitsch   if (PetscDefined(USE_DEBUG) && !PetscDefined(HAVE_THREADSAFETY)) {
193ed170139SJacob Faibussowitsch     PetscFunctionListDLAll head;
194ed170139SJacob Faibussowitsch 
195ed170139SJacob Faibussowitsch     PetscCall(PetscNew(&head));
196ed170139SJacob Faibussowitsch     head->data = fl;
197ed170139SJacob Faibussowitsch     head->next = dlallhead;
198ed170139SJacob Faibussowitsch     dlallhead  = head;
199ed170139SJacob Faibussowitsch   }
2003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
201ed170139SJacob Faibussowitsch }
202ed170139SJacob Faibussowitsch 
203ed170139SJacob Faibussowitsch static PetscErrorCode PetscFunctionListDLAllPop_Private(PetscFunctionList fl)
204ed170139SJacob Faibussowitsch {
205ed170139SJacob Faibussowitsch   PetscFunctionBegin;
206ed170139SJacob Faibussowitsch   if (PetscDefined(USE_DEBUG) && !PetscDefined(HAVE_THREADSAFETY)) {
207ed170139SJacob Faibussowitsch     PetscFunctionListDLAll current = dlallhead, prev = NULL;
208ed170139SJacob Faibussowitsch 
209ed170139SJacob Faibussowitsch     /* Remove this entry from the main DL list (if it is in it) */
210ed170139SJacob Faibussowitsch     while (current) {
211ed170139SJacob Faibussowitsch       const PetscFunctionListDLAll next = current->next;
212ed170139SJacob Faibussowitsch 
213ed170139SJacob Faibussowitsch       if (current->data == fl) {
214ed170139SJacob Faibussowitsch         if (prev) {
215ed170139SJacob Faibussowitsch           // somewhere in the middle (or end) of the list
216ed170139SJacob Faibussowitsch           prev->next = next;
217ed170139SJacob Faibussowitsch         } else {
218ed170139SJacob Faibussowitsch           // prev = NULL implies current = dlallhead, so front of list
219ed170139SJacob Faibussowitsch           dlallhead = next;
220ed170139SJacob Faibussowitsch         }
221ed170139SJacob Faibussowitsch         PetscCall(PetscFree(current));
222ed170139SJacob Faibussowitsch         break;
223ed170139SJacob Faibussowitsch       }
224ed170139SJacob Faibussowitsch       prev    = current;
225ed170139SJacob Faibussowitsch       current = next;
226ed170139SJacob Faibussowitsch     }
227ed170139SJacob Faibussowitsch   }
2283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
229ed170139SJacob Faibussowitsch }
230ed170139SJacob Faibussowitsch 
2318434afd1SBarry Smith static PetscErrorCode PetscHMapFuncInsert_Private(PetscHMapFunc map, const char name[], PetscVoidFn *fnc)
232ed170139SJacob Faibussowitsch {
233ed170139SJacob Faibussowitsch   PetscHashIter it;
234ed170139SJacob Faibussowitsch   PetscBool     found;
235ed170139SJacob Faibussowitsch 
236ed170139SJacob Faibussowitsch   PetscFunctionBegin;
2374f572ea9SToby Isaac   PetscAssertPointer(name, 2);
238ed170139SJacob Faibussowitsch   if (fnc) PetscValidFunction(fnc, 3);
239ed170139SJacob Faibussowitsch   PetscCall(PetscHMapFuncFind(map, name, &it, &found));
240ed170139SJacob Faibussowitsch   if (fnc) {
241ed170139SJacob Faibussowitsch     if (found) {
242ed170139SJacob Faibussowitsch       PetscCall(PetscHMapFuncIterSet(map, it, fnc));
243ed170139SJacob Faibussowitsch     } else {
244ed170139SJacob Faibussowitsch       char *tmp_name;
245ed170139SJacob Faibussowitsch 
246ed170139SJacob Faibussowitsch       PetscCall(PetscStrallocpy(name, &tmp_name));
247ed170139SJacob Faibussowitsch       PetscCall(PetscHMapFuncSet(map, tmp_name, fnc));
248ed170139SJacob Faibussowitsch     }
249ed170139SJacob Faibussowitsch   } else if (found) {
250ed170139SJacob Faibussowitsch     const char *tmp_name;
251ed170139SJacob Faibussowitsch 
252ed170139SJacob Faibussowitsch     PetscHashIterGetKey(map, it, tmp_name);
253ed170139SJacob Faibussowitsch     PetscCall(PetscFree(tmp_name));
254ed170139SJacob Faibussowitsch     PetscCall(PetscHMapFuncIterDel(map, it));
255ed170139SJacob Faibussowitsch   }
2563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
257ed170139SJacob Faibussowitsch }
258ed170139SJacob Faibussowitsch 
259ed170139SJacob Faibussowitsch static PetscErrorCode PetscFunctionListCreate_Private(PetscInt size, PetscFunctionList *fl)
260ed170139SJacob Faibussowitsch {
261ed170139SJacob Faibussowitsch   PetscFunctionBegin;
2623ba16761SJacob Faibussowitsch   if (*fl) PetscFunctionReturn(PETSC_SUCCESS);
263ed170139SJacob Faibussowitsch   PetscCall(PetscNew(fl));
264ed170139SJacob Faibussowitsch   PetscCall(PetscHMapFuncCreateWithSize(size, &(*fl)->map));
265ed170139SJacob Faibussowitsch   PetscCall(PetscFunctionListDLAllPush_Private(*fl));
2663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2670e6b6b59SJacob Faibussowitsch }
2680e6b6b59SJacob Faibussowitsch 
269a240a19fSJed Brown /*MC
270140e18c1SBarry Smith   PetscFunctionListAdd - Given a routine and a string id, saves that routine in the
271e5c89e4eSSatish Balay   specified registry.
272e5c89e4eSSatish Balay 
273a240a19fSJed Brown   Synopsis:
274aaa7dc30SBarry Smith   #include <petscsys.h>
275b9fb364aSBarry Smith   PetscErrorCode PetscFunctionListAdd(PetscFunctionList *flist,const char name[],void (*fptr)(void))
276a240a19fSJed Brown 
277d4349b43SBarry Smith   Not Collective
278e5c89e4eSSatish Balay 
279e5c89e4eSSatish Balay   Input Parameters:
28010450e9eSJacob Faibussowitsch + fl   - pointer to function list object
281e5c89e4eSSatish Balay . name - string to identify routine
282a240a19fSJed Brown - fptr - function pointer
283e5c89e4eSSatish Balay 
28421532e8aSBarry Smith   Level: developer
28521532e8aSBarry Smith 
286e5c89e4eSSatish Balay   Notes:
28721532e8aSBarry Smith   To remove a registered routine, pass in a `NULL` `fptr`.
288e5c89e4eSSatish Balay 
289e5c89e4eSSatish Balay   Users who wish to register new classes for use by a particular PETSc
290811af0c4SBarry Smith   component (e.g., `SNES`) should generally call the registration routine
291811af0c4SBarry Smith   for that particular component (e.g., `SNESRegister()`) instead of
292811af0c4SBarry Smith   calling `PetscFunctionListAdd()` directly.
293e5c89e4eSSatish Balay 
29421532e8aSBarry Smith .seealso: `PetscFunctionListDestroy()`, `SNESRegister()`, `KSPRegister()`,`PetscFunctionListDuplicate()`
295db781477SPatrick Sanan           `PCRegister()`, `TSRegister()`, `PetscFunctionList`, `PetscObjectComposeFunction()`
296a240a19fSJed Brown M*/
2978434afd1SBarry Smith PetscErrorCode PetscFunctionListAdd_Private(PetscFunctionList *fl, const char name[], PetscVoidFn *fptr)
298d71ae5a4SJacob Faibussowitsch {
299e5c89e4eSSatish Balay   PetscFunctionBegin;
3004f572ea9SToby Isaac   PetscAssertPointer(fl, 1);
3014f572ea9SToby Isaac   if (name) PetscAssertPointer(name, 2);
30210450e9eSJacob Faibussowitsch   if (fptr) PetscValidFunction(fptr, 3);
303ebd2f95aSStefano Zampini   if (!fptr && !*fl) PetscFunctionReturn(PETSC_SUCCESS);
304ed170139SJacob Faibussowitsch   PetscCall(PetscFunctionListCreate_Private(0, fl));
30510450e9eSJacob Faibussowitsch   PetscCall(PetscHMapFuncInsert_Private((*fl)->map, name, fptr));
3063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
307e5c89e4eSSatish Balay }
308e5c89e4eSSatish Balay 
309ffeef943SBarry Smith /*@C
310140e18c1SBarry Smith   PetscFunctionListDestroy - Destroys a list of registered routines.
311e5c89e4eSSatish Balay 
312e5c89e4eSSatish Balay   Input Parameter:
313e5c89e4eSSatish Balay . fl - pointer to list
314e5c89e4eSSatish Balay 
315e5c89e4eSSatish Balay   Level: developer
316e5c89e4eSSatish Balay 
3170e6b6b59SJacob Faibussowitsch .seealso: `PetscFunctionListAdd()`, `PetscFunctionList`, `PetscFunctionListClear()`
318e5c89e4eSSatish Balay @*/
319d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFunctionListDestroy(PetscFunctionList *fl)
320d71ae5a4SJacob Faibussowitsch {
321e5c89e4eSSatish Balay   PetscFunctionBegin;
3223ba16761SJacob Faibussowitsch   if (!*fl) PetscFunctionReturn(PETSC_SUCCESS);
323ed170139SJacob Faibussowitsch   PetscCall(PetscFunctionListDLAllPop_Private(*fl));
324e5c89e4eSSatish Balay   /* free this list */
325ed170139SJacob Faibussowitsch   PetscCall(PetscFunctionListClear(*fl));
326ed170139SJacob Faibussowitsch   PetscCall(PetscHMapFuncDestroy(&(*fl)->map));
327ed170139SJacob Faibussowitsch   PetscCall(PetscFree(*fl));
3283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
329e5c89e4eSSatish Balay }
330e5c89e4eSSatish Balay 
331ed170139SJacob Faibussowitsch #define PetscHMapFuncForEach(__func_list__, __key_name__, __val_name__, ...) \
332ed170139SJacob Faibussowitsch   do { \
333ed170139SJacob Faibussowitsch     const PetscHMapFunc phmfi_map_ = (__func_list__)->map; \
334ed170139SJacob Faibussowitsch     PetscHashIter       phmfi_iter_; \
335ed170139SJacob Faibussowitsch \
336ed170139SJacob Faibussowitsch     PetscHashIterBegin(phmfi_map_, phmfi_iter_); \
337ed170139SJacob Faibussowitsch     while (!PetscHashIterAtEnd(phmfi_map_, phmfi_iter_)) { \
338ed170139SJacob Faibussowitsch       const char *PETSC_UNUSED  __key_name__; \
3398434afd1SBarry Smith       PetscVoidFn *PETSC_UNUSED __val_name__; \
340ed170139SJacob Faibussowitsch \
341ed170139SJacob Faibussowitsch       PetscHashIterGetKey(phmfi_map_, phmfi_iter_, __key_name__); \
342ed170139SJacob Faibussowitsch       PetscHashIterGetVal(phmfi_map_, phmfi_iter_, __val_name__); \
343ed170139SJacob Faibussowitsch       { \
344ed170139SJacob Faibussowitsch         __VA_ARGS__; \
345ed170139SJacob Faibussowitsch       } \
346ed170139SJacob Faibussowitsch       PetscHashIterNext(phmfi_map_, phmfi_iter_); \
347ed170139SJacob Faibussowitsch     } /* end while */ \
348ed170139SJacob Faibussowitsch   } while (0)
349ed170139SJacob Faibussowitsch 
350ffeef943SBarry Smith /*@C
3510e6b6b59SJacob Faibussowitsch   PetscFunctionListClear - Clear a `PetscFunctionList`
3520e6b6b59SJacob Faibussowitsch 
3530e6b6b59SJacob Faibussowitsch   Not Collective
3540e6b6b59SJacob Faibussowitsch 
3550e6b6b59SJacob Faibussowitsch   Input Parameter:
3560e6b6b59SJacob Faibussowitsch . fl - The `PetscFunctionList` to clear
3570e6b6b59SJacob Faibussowitsch 
35821532e8aSBarry Smith   Level: developer
35921532e8aSBarry Smith 
3600e6b6b59SJacob Faibussowitsch   Notes:
3610e6b6b59SJacob Faibussowitsch   This clears the contents of `fl` but does not deallocate the entries themselves.
3620e6b6b59SJacob Faibussowitsch 
3630e6b6b59SJacob Faibussowitsch .seealso: `PetscFunctionList`, `PetscFunctionListDestroy()`, `PetscFunctionListAdd()`
3640e6b6b59SJacob Faibussowitsch @*/
365d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFunctionListClear(PetscFunctionList fl)
366d71ae5a4SJacob Faibussowitsch {
3670e6b6b59SJacob Faibussowitsch   PetscFunctionBegin;
368ed170139SJacob Faibussowitsch   if (fl) {
369ed170139SJacob Faibussowitsch     PetscHMapFuncForEach(fl, name, func, PetscCall(PetscFree(name)));
370ed170139SJacob Faibussowitsch     PetscCall(PetscHMapFuncClear(fl->map));
3710e6b6b59SJacob Faibussowitsch   }
3723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3730e6b6b59SJacob Faibussowitsch }
3740e6b6b59SJacob Faibussowitsch 
375e5c89e4eSSatish Balay /*
3762e956fe4SStefano Zampini    Print registered PetscFunctionLists
377e5c89e4eSSatish Balay */
378d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFunctionListPrintAll(void)
379d71ae5a4SJacob Faibussowitsch {
380ed170139SJacob Faibussowitsch   PetscFunctionListDLAll current = dlallhead;
381e5c89e4eSSatish Balay 
382e5c89e4eSSatish Balay   PetscFunctionBegin;
383ed170139SJacob Faibussowitsch   if (current) PetscCall(PetscPrintf(PETSC_COMM_SELF, "[%d] Registered PetscFunctionLists\n", PetscGlobalRank));
384ed170139SJacob Faibussowitsch   while (current) {
385ed170139SJacob Faibussowitsch     PetscCall(PetscFunctionListPrintNonEmpty(current->data));
386ed170139SJacob Faibussowitsch     current = current->next;
38737e93019SBarry Smith   }
3883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
389e5c89e4eSSatish Balay }
390e5c89e4eSSatish Balay 
39110450e9eSJacob Faibussowitsch /*@C
39210450e9eSJacob Faibussowitsch   PetscFunctionListPrintNonEmpty - Print composed names for non `NULL` function pointers
3932e956fe4SStefano Zampini 
394cc4c1da9SBarry Smith   Logically Collective, No Fortran Support
395cc4c1da9SBarry Smith 
3962e956fe4SStefano Zampini   Input Parameter:
39710450e9eSJacob Faibussowitsch . fl - the function list
3982e956fe4SStefano Zampini 
3992e956fe4SStefano Zampini   Level: developer
4002e956fe4SStefano Zampini 
4012e956fe4SStefano Zampini .seealso: `PetscFunctionListAdd()`, `PetscFunctionList`, `PetscObjectQueryFunction()`
40210450e9eSJacob Faibussowitsch @*/
403d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFunctionListPrintNonEmpty(PetscFunctionList fl)
404d71ae5a4SJacob Faibussowitsch {
4052e956fe4SStefano Zampini   PetscFunctionBegin;
406ed170139SJacob Faibussowitsch   if (fl) {
407ed170139SJacob Faibussowitsch     // clang-format off
408ed170139SJacob Faibussowitsch     PetscHMapFuncForEach(
409ed170139SJacob Faibussowitsch       fl,
410ed170139SJacob Faibussowitsch       name, func,
411ed170139SJacob Faibussowitsch       PetscCall(PetscFPrintf(PETSC_COMM_SELF, PETSC_STDOUT, "[%d] function name: %s\n", PetscGlobalRank, name));
412ed170139SJacob Faibussowitsch     );
413ed170139SJacob Faibussowitsch     // clang-format on
4142e956fe4SStefano Zampini   }
4153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4162e956fe4SStefano Zampini }
4172e956fe4SStefano Zampini 
4182e956fe4SStefano Zampini /*MC
4191c9cd337SJed Brown   PetscFunctionListFind - Find function registered under given name
4201c9cd337SJed Brown 
421cc4c1da9SBarry Smith   Not Collective, No Fortran Support
422cc4c1da9SBarry Smith 
4231c9cd337SJed Brown   Synopsis:
424aaa7dc30SBarry Smith   #include <petscsys.h>
4251c9cd337SJed Brown   PetscErrorCode PetscFunctionListFind(PetscFunctionList flist,const char name[],void (**fptr)(void))
426e5c89e4eSSatish Balay 
427e5c89e4eSSatish Balay   Input Parameters:
42810450e9eSJacob Faibussowitsch + fl   - the function list
4291c9cd337SJed Brown - name - name registered for the function
430e5c89e4eSSatish Balay 
4312fe279fdSBarry Smith   Output Parameter:
43221532e8aSBarry Smith . fptr - the function pointer if name was found, else `NULL`
433e5c89e4eSSatish Balay 
434e5c89e4eSSatish Balay   Level: developer
435e5c89e4eSSatish Balay 
43621532e8aSBarry Smith .seealso: `PetscFunctionListAdd()`, `PetscFunctionList`, `PetscObjectQueryFunction()`, `PetscFunctionListDuplicate()`
4371c9cd337SJed Brown M*/
4388434afd1SBarry Smith PetscErrorCode PetscFunctionListFind_Private(PetscFunctionList fl, const char name[], PetscVoidFn **fptr)
439d71ae5a4SJacob Faibussowitsch {
440e5c89e4eSSatish Balay   PetscFunctionBegin;
4414f572ea9SToby Isaac   PetscAssertPointer(name, 2);
4424f572ea9SToby Isaac   PetscAssertPointer(fptr, 3);
44310450e9eSJacob Faibussowitsch   *fptr = NULL;
44410450e9eSJacob Faibussowitsch   if (fl) PetscCall(PetscHMapFuncGet(fl->map, name, fptr));
4453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
446e5c89e4eSSatish Balay }
447e5c89e4eSSatish Balay 
448ffeef943SBarry Smith /*@C
44920f4b53cSBarry Smith   PetscFunctionListView - prints out contents of a `PetscFunctionList`
450e5c89e4eSSatish Balay 
45120f4b53cSBarry Smith   Collective
452e5c89e4eSSatish Balay 
453e5c89e4eSSatish Balay   Input Parameters:
454e5c89e4eSSatish Balay + list   - the list of functions
45520f4b53cSBarry Smith - viewer - the `PetscViewer` used to view the `PetscFunctionList`
456e5c89e4eSSatish Balay 
457e5c89e4eSSatish Balay   Level: developer
458e5c89e4eSSatish Balay 
459db781477SPatrick Sanan .seealso: `PetscFunctionListAdd()`, `PetscFunctionListPrintTypes()`, `PetscFunctionList`
460e5c89e4eSSatish Balay @*/
461d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFunctionListView(PetscFunctionList list, PetscViewer viewer)
462d71ae5a4SJacob Faibussowitsch {
463*9f196a02SMartin Diehl   PetscBool isascii;
464e5c89e4eSSatish Balay 
465e5c89e4eSSatish Balay   PetscFunctionBegin;
4664f572ea9SToby Isaac   PetscAssertPointer(list, 1);
467ed170139SJacob Faibussowitsch   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PETSC_COMM_SELF, &viewer));
4680700a824SBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
469e5c89e4eSSatish Balay 
470*9f196a02SMartin Diehl   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
471*9f196a02SMartin Diehl   PetscCheck(isascii, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only ASCII viewer supported");
472ed170139SJacob Faibussowitsch   {
473ed170139SJacob Faibussowitsch     PetscInt size;
474e5c89e4eSSatish Balay 
475ed170139SJacob Faibussowitsch     PetscCall(PetscHMapFuncGetSize(list->map, &size));
476ed170139SJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "PetscFunctionList Object:\n"));
477ed170139SJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushTab(viewer));
478ed170139SJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "size: %" PetscInt_FMT "\n", size));
479ed170139SJacob Faibussowitsch     if (size) {
480ed170139SJacob Faibussowitsch       PetscInt count = 0;
481ed170139SJacob Faibussowitsch 
482ed170139SJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "functions:\n"));
483ed170139SJacob Faibussowitsch       PetscCall(PetscViewerASCIIPushTab(viewer));
484ed170139SJacob Faibussowitsch       PetscHMapFuncForEach(list, name, func, PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT ": %s\n", ++count, name)));
485ed170139SJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopTab(viewer));
486e5c89e4eSSatish Balay     }
487ed170139SJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopTab(viewer));
488ed170139SJacob Faibussowitsch   }
4893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
490e5c89e4eSSatish Balay }
491e5c89e4eSSatish Balay 
492065533a5SJed Brown /*@C
493811af0c4SBarry Smith   PetscFunctionListGet - Gets an array the contains the entries in `PetscFunctionList`, this is used
494e5c89e4eSSatish Balay   by help etc.
495e5c89e4eSSatish Balay 
496cc4c1da9SBarry Smith   Not Collective, No Fortran Support
497e5c89e4eSSatish Balay 
498e5c89e4eSSatish Balay   Input Parameter:
499e5c89e4eSSatish Balay . list - list of types
500e5c89e4eSSatish Balay 
501d8d19677SJose E. Roman   Output Parameters:
502e5c89e4eSSatish Balay + array - array of names
50321532e8aSBarry Smith - n     - length of `array`
50421532e8aSBarry Smith 
50521532e8aSBarry Smith   Level: developer
506e5c89e4eSSatish Balay 
507811af0c4SBarry Smith   Note:
508a3b724e8SBarry Smith   This allocates the array so that must be freed with `PetscFree()`. BUT the individual entries should not be freed.
509e5c89e4eSSatish Balay 
510db781477SPatrick Sanan .seealso: `PetscFunctionListAdd()`, `PetscFunctionList`
511e5c89e4eSSatish Balay @*/
512d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFunctionListGet(PetscFunctionList list, const char ***array, int *n)
513d71ae5a4SJacob Faibussowitsch {
514ed170139SJacob Faibussowitsch   PetscInt size = 0;
515e5c89e4eSSatish Balay 
516e5c89e4eSSatish Balay   PetscFunctionBegin;
5174f572ea9SToby Isaac   PetscAssertPointer(array, 2);
518ed170139SJacob Faibussowitsch   *array = NULL;
519ed170139SJacob Faibussowitsch   if (list) {
520ed170139SJacob Faibussowitsch     const PetscHMapFunc map = list->map;
521ed170139SJacob Faibussowitsch     PetscInt            off = 0;
522ed170139SJacob Faibussowitsch 
523ed170139SJacob Faibussowitsch     PetscCall(PetscHMapFuncGetSize(map, &size));
524ed170139SJacob Faibussowitsch     PetscCall(PetscMalloc1(size, (char ***)array));
525ed170139SJacob Faibussowitsch     PetscCall(PetscHMapFuncGetKeys(map, &off, *array));
526e5c89e4eSSatish Balay   }
527835f2295SStefano Zampini   PetscCall(PetscCIntCast(size, n));
5283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
529e5c89e4eSSatish Balay }
530e5c89e4eSSatish Balay 
531e5c89e4eSSatish Balay /*@C
532811af0c4SBarry Smith   PetscFunctionListPrintTypes - Prints the methods available in a list of functions
533e5c89e4eSSatish Balay 
534cc4c1da9SBarry Smith   Collective, No Fortran Support
535e5c89e4eSSatish Balay 
536e5c89e4eSSatish Balay   Input Parameters:
537811af0c4SBarry Smith + comm   - the communicator (usually `MPI_COMM_WORLD`)
53821532e8aSBarry Smith . fd     - file to print to, usually `stdout`
539e5c89e4eSSatish Balay . prefix - prefix to prepend to name (optional)
54021532e8aSBarry Smith . name   - option string (for example, `-ksp_type`)
541e5c89e4eSSatish Balay . text   - short description of the object (for example, "Krylov solvers")
54221532e8aSBarry Smith . man    - name of manual page that discusses the object (for example, `KSPCreate`)
5433cc1e11dSBarry Smith . list   - list of types
54444ef3d73SBarry Smith . def    - default (current) value
54544ef3d73SBarry Smith - newv   - new value
546e5c89e4eSSatish Balay 
547e5c89e4eSSatish Balay   Level: developer
548e5c89e4eSSatish Balay 
549db781477SPatrick Sanan .seealso: `PetscFunctionListAdd()`, `PetscFunctionList`
550e5c89e4eSSatish Balay @*/
551d71ae5a4SJacob 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[])
552d71ae5a4SJacob Faibussowitsch {
553e5c89e4eSSatish Balay   char p[64];
554e5c89e4eSSatish Balay 
555e5c89e4eSSatish Balay   PetscFunctionBegin;
556ed170139SJacob Faibussowitsch   (void)fd;
5579566063dSJacob Faibussowitsch   PetscCall(PetscStrncpy(p, "-", sizeof(p)));
5589566063dSJacob Faibussowitsch   if (prefix) PetscCall(PetscStrlcat(p, prefix, sizeof(p)));
559ed170139SJacob Faibussowitsch   PetscCall((*PetscHelpPrintf)(comm, "  %s%s <now %s : formerly %s>: %s (one of)", p, name + 1, newv, def, text));
560e5c89e4eSSatish Balay 
5618c7e48aeSJacob Faibussowitsch   if (list) PetscHMapFuncForEach(list, name, func, PetscCall((*PetscHelpPrintf)(comm, " %s", name)));
562ed170139SJacob Faibussowitsch   PetscCall((*PetscHelpPrintf)(comm, " (%s)\n", man));
5633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
564e5c89e4eSSatish Balay }
565e5c89e4eSSatish Balay 
566ffeef943SBarry Smith /*@C
56721532e8aSBarry Smith   PetscFunctionListDuplicate - Creates a new list from a given function list `PetscFunctionList`.
568e5c89e4eSSatish Balay 
5692fe279fdSBarry Smith   Input Parameter:
570e5c89e4eSSatish Balay . fl - pointer to list
571e5c89e4eSSatish Balay 
5722fe279fdSBarry Smith   Output Parameter:
57321532e8aSBarry Smith . nl - the new list (should point to `NULL` to start, otherwise appends)
574e5c89e4eSSatish Balay 
575e5c89e4eSSatish Balay   Level: developer
576e5c89e4eSSatish Balay 
577db781477SPatrick Sanan .seealso: `PetscFunctionList`, `PetscFunctionListAdd()`, `PetscFlistDestroy()`
578e5c89e4eSSatish Balay @*/
579d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFunctionListDuplicate(PetscFunctionList fl, PetscFunctionList *nl)
580d71ae5a4SJacob Faibussowitsch {
581e5c89e4eSSatish Balay   PetscFunctionBegin;
582ed170139SJacob Faibussowitsch   if (fl) {
583ed170139SJacob Faibussowitsch     PetscHMapFunc dup_map;
584ed170139SJacob Faibussowitsch 
585ed170139SJacob Faibussowitsch     if (!*nl) {
586ed170139SJacob Faibussowitsch       PetscInt n;
587ed170139SJacob Faibussowitsch 
588ed170139SJacob Faibussowitsch       PetscCall(PetscHMapFuncGetSize(fl->map, &n));
589ed170139SJacob Faibussowitsch       PetscCall(PetscFunctionListCreate_Private(n, nl));
590ed170139SJacob Faibussowitsch     }
591ed170139SJacob Faibussowitsch     dup_map = (*nl)->map;
592ed170139SJacob Faibussowitsch     PetscHMapFuncForEach(fl, name, func, PetscCall(PetscHMapFuncInsert_Private(dup_map, name, func)));
593e5c89e4eSSatish Balay   }
5943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
595e5c89e4eSSatish Balay }
596