xref: /petsc/src/sys/dll/reg.c (revision 665c2ded495bb9782a7454dcfef3abf1536c3670)
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 */
6afcb2eb5SJed Brown #include <petsc-private/petscimpl.h>           /*I "petscsys.h" I*/
7*665c2dedSJed Brown #include <petscviewer.h>
8e5c89e4eSSatish Balay 
9e5c89e4eSSatish Balay #undef __FUNCT__
10140e18c1SBarry Smith #define __FUNCT__ "PetscFunctionListGetPathAndFunction"
11140e18c1SBarry Smith PetscErrorCode  PetscFunctionListGetPathAndFunction(const char name[],char *path[],char *function[])
12e5c89e4eSSatish Balay {
13e5c89e4eSSatish Balay   PetscErrorCode ierr;
14e5c89e4eSSatish Balay   char           work[PETSC_MAX_PATH_LEN],*lfunction;
15e5c89e4eSSatish Balay 
16e5c89e4eSSatish Balay   PetscFunctionBegin;
178caf3d72SBarry Smith   ierr = PetscStrncpy(work,name,sizeof(work));CHKERRQ(ierr);
18a297a907SKarl Rupp 
198caf3d72SBarry Smith   work[sizeof(work) - 1] = 0;
20a297a907SKarl Rupp 
21e5c89e4eSSatish Balay   ierr = PetscStrchr(work,':',&lfunction);CHKERRQ(ierr);
22e5c89e4eSSatish Balay   if (lfunction != work && lfunction && lfunction[1] != ':') {
23e5c89e4eSSatish Balay     lfunction[0] = 0;
24a297a907SKarl Rupp 
25e5c89e4eSSatish Balay     ierr = PetscStrallocpy(work,path);CHKERRQ(ierr);
26e5c89e4eSSatish Balay     ierr = PetscStrallocpy(lfunction+1,function);CHKERRQ(ierr);
27e5c89e4eSSatish Balay   } else {
28e5c89e4eSSatish Balay     *path = 0;
29e5c89e4eSSatish Balay     ierr  = PetscStrallocpy(name,function);CHKERRQ(ierr);
30e5c89e4eSSatish Balay   }
31e5c89e4eSSatish Balay   PetscFunctionReturn(0);
32e5c89e4eSSatish Balay }
33e5c89e4eSSatish Balay 
343fa76a5bSLisandro Dalcin /*
353fa76a5bSLisandro Dalcin     This is the default list used by PETSc with the PetscDLLibrary register routines
363fa76a5bSLisandro Dalcin */
37d44a1e48SBarry Smith PetscDLLibrary PetscDLLibrariesLoaded = 0;
383fa76a5bSLisandro Dalcin 
39ebd79076SLisandro Dalcin #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
40ebd79076SLisandro Dalcin 
41e5c89e4eSSatish Balay #undef __FUNCT__
42487e5849SBarry Smith #define __FUNCT__ "PetscLoadDynamicLibrary"
437087cfbeSBarry Smith static PetscErrorCode  PetscLoadDynamicLibrary(const char *name,PetscBool  *found)
44487e5849SBarry Smith {
45487e5849SBarry Smith   char           libs[PETSC_MAX_PATH_LEN],dlib[PETSC_MAX_PATH_LEN];
46487e5849SBarry Smith   PetscErrorCode ierr;
47487e5849SBarry Smith 
48487e5849SBarry Smith   PetscFunctionBegin;
49487e5849SBarry Smith   ierr = PetscStrcpy(libs,"${PETSC_LIB_DIR}/libpetsc");CHKERRQ(ierr);
50487e5849SBarry Smith   ierr = PetscStrcat(libs,name);CHKERRQ(ierr);
51487e5849SBarry Smith   ierr = PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,found);CHKERRQ(ierr);
52487e5849SBarry Smith   if (*found) {
53d44a1e48SBarry Smith     ierr = PetscDLLibraryAppend(PETSC_COMM_WORLD,&PetscDLLibrariesLoaded,dlib);CHKERRQ(ierr);
54487e5849SBarry Smith   } else {
55487e5849SBarry Smith     ierr = PetscStrcpy(libs,"${PETSC_DIR}/${PETSC_ARCH}/lib/libpetsc");CHKERRQ(ierr);
56487e5849SBarry Smith     ierr = PetscStrcat(libs,name);CHKERRQ(ierr);
57487e5849SBarry Smith     ierr = PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,found);CHKERRQ(ierr);
58487e5849SBarry Smith     if (*found) {
59d44a1e48SBarry Smith       ierr = PetscDLLibraryAppend(PETSC_COMM_WORLD,&PetscDLLibrariesLoaded,dlib);CHKERRQ(ierr);
60487e5849SBarry Smith     }
61487e5849SBarry Smith   }
62487e5849SBarry Smith   PetscFunctionReturn(0);
63487e5849SBarry Smith }
64487e5849SBarry Smith 
653fa76a5bSLisandro Dalcin #endif
663fa76a5bSLisandro Dalcin 
67487e5849SBarry Smith #undef __FUNCT__
68e5c89e4eSSatish Balay #define __FUNCT__ "PetscInitialize_DynamicLibraries"
69e5c89e4eSSatish Balay /*
70e5c89e4eSSatish Balay     PetscInitialize_DynamicLibraries - Adds the default dynamic link libraries to the
71e5c89e4eSSatish Balay     search path.
72e5c89e4eSSatish Balay */
737087cfbeSBarry Smith PetscErrorCode  PetscInitialize_DynamicLibraries(void)
74e5c89e4eSSatish Balay {
75487e5849SBarry Smith   char           *libname[32];
76e5c89e4eSSatish Balay   PetscErrorCode ierr;
77e5c89e4eSSatish Balay   PetscInt       nmax,i;
783fa76a5bSLisandro Dalcin #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
79ace3abfcSBarry Smith   PetscBool      found;
803fa76a5bSLisandro Dalcin #endif
81e5c89e4eSSatish Balay 
8260154eb2SBarry Smith   PetscFunctionBegin;
83e5c89e4eSSatish Balay   nmax = 32;
840298fd71SBarry Smith   ierr = PetscOptionsGetStringArray(NULL,"-dll_prepend",libname,&nmax,NULL);CHKERRQ(ierr);
85e5c89e4eSSatish Balay   for (i=0; i<nmax; i++) {
86d44a1e48SBarry Smith     ierr = PetscDLLibraryPrepend(PETSC_COMM_WORLD,&PetscDLLibrariesLoaded,libname[i]);CHKERRQ(ierr);
87e5c89e4eSSatish Balay     ierr = PetscFree(libname[i]);CHKERRQ(ierr);
88e5c89e4eSSatish Balay   }
89e5c89e4eSSatish Balay 
903fa76a5bSLisandro Dalcin #if !defined(PETSC_USE_DYNAMIC_LIBRARIES)
913fa76a5bSLisandro Dalcin   /*
923fa76a5bSLisandro Dalcin       This just initializes the most basic PETSc stuff.
933fa76a5bSLisandro Dalcin 
943fa76a5bSLisandro Dalcin     The classes, from PetscDraw to PetscTS, are initialized the first
953fa76a5bSLisandro Dalcin     time an XXCreate() is called.
963fa76a5bSLisandro Dalcin   */
970298fd71SBarry Smith   ierr = PetscSysInitializePackage(NULL);CHKERRQ(ierr);
983fa76a5bSLisandro Dalcin #else
9960154eb2SBarry Smith #if defined(PETSC_USE_SINGLE_LIBRARY)
100487e5849SBarry Smith   ierr = PetscLoadDynamicLibrary("",&found);CHKERRQ(ierr);
101e32f2f54SBarry Smith   if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc dynamic library \n You cannot move the dynamic libraries!");
10260154eb2SBarry Smith #else
10360154eb2SBarry Smith   ierr = PetscLoadDynamicLibrary("sys",&found);CHKERRQ(ierr);
10460154eb2SBarry Smith   if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc dynamic library \n You cannot move the dynamic libraries!");
105487e5849SBarry Smith   ierr = PetscLoadDynamicLibrary("vec",&found);CHKERRQ(ierr);
106e32f2f54SBarry Smith   if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc Vec dynamic library \n You cannot move the dynamic libraries!");
107487e5849SBarry Smith   ierr = PetscLoadDynamicLibrary("mat",&found);CHKERRQ(ierr);
108e32f2f54SBarry Smith   if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc Mat dynamic library \n You cannot move the dynamic libraries!");
109487e5849SBarry Smith   ierr = PetscLoadDynamicLibrary("dm",&found);CHKERRQ(ierr);
110e32f2f54SBarry Smith   if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc DM dynamic library \n You cannot move the dynamic libraries!");
11160154eb2SBarry Smith   ierr = PetscLoadDynamicLibrary("characteristic",&found);CHKERRQ(ierr);
11260154eb2SBarry Smith   if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc Characteristic dynamic library \n You cannot move the dynamic libraries!");
113487e5849SBarry Smith   ierr = PetscLoadDynamicLibrary("ksp",&found);CHKERRQ(ierr);
114e32f2f54SBarry Smith   if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc KSP dynamic library \n You cannot move the dynamic libraries!");
115487e5849SBarry Smith   ierr = PetscLoadDynamicLibrary("snes",&found);CHKERRQ(ierr);
116e32f2f54SBarry Smith   if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc SNES dynamic library \n You cannot move the dynamic libraries!");
117487e5849SBarry Smith   ierr = PetscLoadDynamicLibrary("ts",&found);CHKERRQ(ierr);
118e32f2f54SBarry Smith   if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc TS dynamic library \n You cannot move the dynamic libraries!");
119bb84e0fdSBarry Smith #endif
120e5c89e4eSSatish Balay 
121487e5849SBarry Smith   ierr = PetscLoadDynamicLibrary("mesh",&found);CHKERRQ(ierr);
122487e5849SBarry Smith   ierr = PetscLoadDynamicLibrary("contrib",&found);CHKERRQ(ierr);
1233fa76a5bSLisandro Dalcin #endif
124e5c89e4eSSatish Balay 
125e5c89e4eSSatish Balay   nmax = 32;
1260298fd71SBarry Smith   ierr = PetscOptionsGetStringArray(NULL,"-dll_append",libname,&nmax,NULL);CHKERRQ(ierr);
127e5c89e4eSSatish Balay   for (i=0; i<nmax; i++) {
128d44a1e48SBarry Smith     ierr = PetscDLLibraryAppend(PETSC_COMM_WORLD,&PetscDLLibrariesLoaded,libname[i]);CHKERRQ(ierr);
129e5c89e4eSSatish Balay     ierr = PetscFree(libname[i]);CHKERRQ(ierr);
130e5c89e4eSSatish Balay   }
131e5c89e4eSSatish Balay   PetscFunctionReturn(0);
132e5c89e4eSSatish Balay }
133e5c89e4eSSatish Balay 
134e5c89e4eSSatish Balay #undef __FUNCT__
135e5c89e4eSSatish Balay #define __FUNCT__ "PetscFinalize_DynamicLibraries"
136ebd79076SLisandro Dalcin /*
137ebd79076SLisandro Dalcin      PetscFinalize_DynamicLibraries - Closes the opened dynamic libraries.
138ebd79076SLisandro Dalcin */
139e5c89e4eSSatish Balay PetscErrorCode PetscFinalize_DynamicLibraries(void)
140e5c89e4eSSatish Balay {
141ebd79076SLisandro Dalcin   PetscErrorCode ierr;
142ace3abfcSBarry Smith   PetscBool      flg = PETSC_FALSE;
143e5c89e4eSSatish Balay 
144ebd79076SLisandro Dalcin   PetscFunctionBegin;
1450298fd71SBarry Smith   ierr = PetscOptionsGetBool(NULL,"-dll_view",&flg,NULL);CHKERRQ(ierr);
146d44a1e48SBarry Smith   if (flg) { ierr = PetscDLLibraryPrintPath(PetscDLLibrariesLoaded);CHKERRQ(ierr); }
147d44a1e48SBarry Smith   ierr = PetscDLLibraryClose(PetscDLLibrariesLoaded);CHKERRQ(ierr);
148a297a907SKarl Rupp 
149d44a1e48SBarry Smith   PetscDLLibrariesLoaded = 0;
150e5c89e4eSSatish Balay   PetscFunctionReturn(0);
151e5c89e4eSSatish Balay }
152e5c89e4eSSatish Balay 
153e4d1774bSDmitry Karpeev 
154e4d1774bSDmitry Karpeev 
155e5c89e4eSSatish Balay /* ------------------------------------------------------------------------------*/
156140e18c1SBarry Smith struct _n_PetscFunctionList {
157e5c89e4eSSatish Balay   void              (*routine)(void);    /* the routine */
158e5c89e4eSSatish Balay   char              *path;               /* path of link library containing routine */
159e5c89e4eSSatish Balay   char              *name;               /* string to identify routine */
160e5c89e4eSSatish Balay   char              *rname;              /* routine name in dynamic library */
161140e18c1SBarry Smith   PetscFunctionList next;                /* next pointer */
162140e18c1SBarry Smith   PetscFunctionList next_list;           /* used to maintain list of all lists for freeing */
163e5c89e4eSSatish Balay };
164e5c89e4eSSatish Balay 
165e5c89e4eSSatish Balay /*
166140e18c1SBarry Smith      Keep a linked list of PetscFunctionLists so that we can destroy all the left-over ones.
167e5c89e4eSSatish Balay */
168140e18c1SBarry Smith static PetscFunctionList dlallhead = 0;
169e5c89e4eSSatish Balay 
170e5c89e4eSSatish Balay #undef __FUNCT__
171140e18c1SBarry Smith #define __FUNCT__ "PetscFunctionListAdd"
172e5c89e4eSSatish Balay /*@C
173140e18c1SBarry Smith    PetscFunctionListAdd - Given a routine and a string id, saves that routine in the
174e5c89e4eSSatish Balay    specified registry.
175e5c89e4eSSatish Balay 
1766d75e210SBarry Smith      Formally Collective on MPI_Comm
177e5c89e4eSSatish Balay 
178e5c89e4eSSatish Balay    Input Parameters:
1796d75e210SBarry Smith +  comm  - the comm where this exists (currently not used)
1806d75e210SBarry Smith .  fl    - pointer registry
181e5c89e4eSSatish Balay .  name  - string to identify routine
182e5c89e4eSSatish Balay .  rname - routine name in dynamic library
183e5c89e4eSSatish Balay -  fnc   - function pointer (optional if using dynamic libraries)
184e5c89e4eSSatish Balay 
185e5c89e4eSSatish Balay    Notes:
1860298fd71SBarry Smith    To remove a registered routine, pass in a NULL rname and fnc().
187e5c89e4eSSatish Balay 
188e5c89e4eSSatish Balay    Users who wish to register new classes for use by a particular PETSc
189e5c89e4eSSatish Balay    component (e.g., SNES) should generally call the registration routine
190e5c89e4eSSatish Balay    for that particular component (e.g., SNESRegisterDynamic()) instead of
191140e18c1SBarry Smith    calling PetscFunctionListAdd() directly.
192e5c89e4eSSatish Balay 
193e5c89e4eSSatish Balay    ${PETSC_ARCH}, ${PETSC_DIR}, ${PETSC_LIB_DIR}, or ${any environmental variable}
194e5c89e4eSSatish Balay   occuring in pathname will be replaced with appropriate values.
195e5c89e4eSSatish Balay 
196e5c89e4eSSatish Balay    Level: developer
197e5c89e4eSSatish Balay 
198140e18c1SBarry Smith .seealso: PetscFunctionListDestroy(), SNESRegisterDynamic(), KSPRegisterDynamic(),
199140e18c1SBarry Smith           PCRegisterDynamic(), TSRegisterDynamic(), PetscFunctionList
200e5c89e4eSSatish Balay @*/
201140e18c1SBarry Smith PetscErrorCode  PetscFunctionListAdd(MPI_Comm comm,PetscFunctionList *fl,const char name[],const char rname[],void (*fnc)(void))
202e5c89e4eSSatish Balay {
203140e18c1SBarry Smith   PetscFunctionList entry,ne;
204e5c89e4eSSatish Balay   PetscErrorCode    ierr;
205e5c89e4eSSatish Balay   char              *fpath,*fname;
206e5c89e4eSSatish Balay 
207e5c89e4eSSatish Balay   PetscFunctionBegin;
208e5c89e4eSSatish Balay   if (!*fl) {
209140e18c1SBarry Smith     ierr           = PetscNew(struct _n_PetscFunctionList,&entry);CHKERRQ(ierr);
210e5c89e4eSSatish Balay     ierr           = PetscStrallocpy(name,&entry->name);CHKERRQ(ierr);
211140e18c1SBarry Smith     ierr           = PetscFunctionListGetPathAndFunction(rname,&fpath,&fname);CHKERRQ(ierr);
212e5c89e4eSSatish Balay     entry->path    = fpath;
213e5c89e4eSSatish Balay     entry->rname   = fname;
214e5c89e4eSSatish Balay     entry->routine = fnc;
215e5c89e4eSSatish Balay     entry->next    = 0;
216e5c89e4eSSatish Balay     *fl            = entry;
217e5c89e4eSSatish Balay 
218e5c89e4eSSatish Balay     /* add this new list to list of all lists */
219e5c89e4eSSatish Balay     if (!dlallhead) {
220e5c89e4eSSatish Balay       dlallhead        = *fl;
221e5c89e4eSSatish Balay       (*fl)->next_list = 0;
222e5c89e4eSSatish Balay     } else {
223e5c89e4eSSatish Balay       ne               = dlallhead;
224e5c89e4eSSatish Balay       dlallhead        = *fl;
225e5c89e4eSSatish Balay       (*fl)->next_list = ne;
226e5c89e4eSSatish Balay     }
227e5c89e4eSSatish Balay   } else {
228e5c89e4eSSatish Balay     /* search list to see if it is already there */
229e5c89e4eSSatish Balay     ne = *fl;
230e5c89e4eSSatish Balay     while (ne) {
231ace3abfcSBarry Smith       PetscBool founddup;
232e5c89e4eSSatish Balay 
233e5c89e4eSSatish Balay       ierr = PetscStrcmp(ne->name,name,&founddup);CHKERRQ(ierr);
234e5c89e4eSSatish Balay       if (founddup) { /* found duplicate */
235140e18c1SBarry Smith         ierr = PetscFunctionListGetPathAndFunction(rname,&fpath,&fname);CHKERRQ(ierr);
236503cfb0cSBarry Smith         ierr = PetscFree(ne->path);CHKERRQ(ierr);
237503cfb0cSBarry Smith         ierr = PetscFree(ne->rname);CHKERRQ(ierr);
238a297a907SKarl Rupp 
239e5c89e4eSSatish Balay         ne->path    = fpath;
240e5c89e4eSSatish Balay         ne->rname   = fname;
241e5c89e4eSSatish Balay         ne->routine = fnc;
242e5c89e4eSSatish Balay         PetscFunctionReturn(0);
243e5c89e4eSSatish Balay       }
244a297a907SKarl Rupp       if (ne->next) ne = ne->next;
245a297a907SKarl Rupp       else break;
246e5c89e4eSSatish Balay     }
247e5c89e4eSSatish Balay     /* create new entry and add to end of list */
248140e18c1SBarry Smith     ierr           = PetscNew(struct _n_PetscFunctionList,&entry);CHKERRQ(ierr);
249e5c89e4eSSatish Balay     ierr           = PetscStrallocpy(name,&entry->name);CHKERRQ(ierr);
250140e18c1SBarry Smith     ierr           = PetscFunctionListGetPathAndFunction(rname,&fpath,&fname);CHKERRQ(ierr);
251e5c89e4eSSatish Balay     entry->path    = fpath;
252e5c89e4eSSatish Balay     entry->rname   = fname;
253e5c89e4eSSatish Balay     entry->routine = fnc;
254e5c89e4eSSatish Balay     entry->next    = 0;
255e5c89e4eSSatish Balay     ne->next       = entry;
256e5c89e4eSSatish Balay   }
257e5c89e4eSSatish Balay   PetscFunctionReturn(0);
258e5c89e4eSSatish Balay }
259e5c89e4eSSatish Balay 
260e5c89e4eSSatish Balay #undef __FUNCT__
261140e18c1SBarry Smith #define __FUNCT__ "PetscFunctionListDestroy"
262e5c89e4eSSatish Balay /*@
263140e18c1SBarry Smith     PetscFunctionListDestroy - Destroys a list of registered routines.
264e5c89e4eSSatish Balay 
265e5c89e4eSSatish Balay     Input Parameter:
266e5c89e4eSSatish Balay .   fl  - pointer to list
267e5c89e4eSSatish Balay 
268e5c89e4eSSatish Balay     Level: developer
269e5c89e4eSSatish Balay 
270140e18c1SBarry Smith .seealso: PetscFunctionListAddDynamic(), PetscFunctionList
271e5c89e4eSSatish Balay @*/
272140e18c1SBarry Smith PetscErrorCode  PetscFunctionListDestroy(PetscFunctionList *fl)
273e5c89e4eSSatish Balay {
274140e18c1SBarry Smith   PetscFunctionList next,entry,tmp = dlallhead;
275e5c89e4eSSatish Balay   PetscErrorCode    ierr;
276e5c89e4eSSatish Balay 
277e5c89e4eSSatish Balay   PetscFunctionBegin;
2781441b1d3SBarry Smith   if (!*fl) PetscFunctionReturn(0);
27960154eb2SBarry Smith   if (!dlallhead) PetscFunctionReturn(0);
280e5c89e4eSSatish Balay 
281e5c89e4eSSatish Balay   /*
282e5c89e4eSSatish Balay        Remove this entry from the master DL list (if it is in it)
283e5c89e4eSSatish Balay   */
2841441b1d3SBarry Smith   if (dlallhead == *fl) {
285a297a907SKarl Rupp     if (dlallhead->next_list) dlallhead = dlallhead->next_list;
286a297a907SKarl Rupp     else dlallhead = 0;
287e5c89e4eSSatish Balay   } else {
2881441b1d3SBarry Smith     while (tmp->next_list != *fl) {
289e5c89e4eSSatish Balay       tmp = tmp->next_list;
290e5c89e4eSSatish Balay       if (!tmp->next_list) break;
291e5c89e4eSSatish Balay     }
292e5c89e4eSSatish Balay     if (tmp->next_list) tmp->next_list = tmp->next_list->next_list;
293e5c89e4eSSatish Balay   }
294e5c89e4eSSatish Balay 
295e5c89e4eSSatish Balay   /* free this list */
2961441b1d3SBarry Smith   entry = *fl;
297e5c89e4eSSatish Balay   while (entry) {
298e5c89e4eSSatish Balay     next  = entry->next;
299503cfb0cSBarry Smith     ierr  = PetscFree(entry->path);CHKERRQ(ierr);
300e5c89e4eSSatish Balay     ierr  = PetscFree(entry->name);CHKERRQ(ierr);
301e5c89e4eSSatish Balay     ierr  = PetscFree(entry->rname);CHKERRQ(ierr);
302e5c89e4eSSatish Balay     ierr  = PetscFree(entry);CHKERRQ(ierr);
303e5c89e4eSSatish Balay     entry = next;
304e5c89e4eSSatish Balay   }
3051441b1d3SBarry Smith   *fl = 0;
306e5c89e4eSSatish Balay   PetscFunctionReturn(0);
307e5c89e4eSSatish Balay }
308e5c89e4eSSatish Balay 
309e5c89e4eSSatish Balay /*
310e5c89e4eSSatish Balay    Destroys all the function lists that anyone has every registered, such as KSPList, VecList, etc.
311e5c89e4eSSatish Balay */
312e5c89e4eSSatish Balay #undef __FUNCT__
313140e18c1SBarry Smith #define __FUNCT__ "PetscFunctionListDestroyAll"
314140e18c1SBarry Smith PetscErrorCode  PetscFunctionListDestroyAll(void)
315e5c89e4eSSatish Balay {
316140e18c1SBarry Smith   PetscFunctionList tmp2,tmp1 = dlallhead;
317e5c89e4eSSatish Balay   PetscErrorCode    ierr;
318e5c89e4eSSatish Balay 
319e5c89e4eSSatish Balay   PetscFunctionBegin;
320e5c89e4eSSatish Balay   while (tmp1) {
321e5c89e4eSSatish Balay     tmp2 = tmp1->next_list;
322140e18c1SBarry Smith     ierr = PetscFunctionListDestroy(&tmp1);CHKERRQ(ierr);
323e5c89e4eSSatish Balay     tmp1 = tmp2;
324e5c89e4eSSatish Balay   }
325e5c89e4eSSatish Balay   dlallhead = 0;
326e5c89e4eSSatish Balay   PetscFunctionReturn(0);
327e5c89e4eSSatish Balay }
328e5c89e4eSSatish Balay 
329e5c89e4eSSatish Balay #undef __FUNCT__
330140e18c1SBarry Smith #define __FUNCT__ "PetscFunctionListFind"
331e5c89e4eSSatish Balay /*@C
332140e18c1SBarry Smith     PetscFunctionListFind - Given a name, finds the matching routine.
333e5c89e4eSSatish Balay 
334e5c89e4eSSatish Balay     Input Parameters:
3351d280d73SBarry Smith +   fl   - pointer to list
3361d280d73SBarry Smith .   comm - processors looking for routine
3374b91b6eaSBarry Smith .   name - name string
3384b91b6eaSBarry Smith -   searchlibraries - if not found in the list then search the dynamic libraries and executable for the symbol
339e5c89e4eSSatish Balay 
340e5c89e4eSSatish Balay     Output Parameters:
341e5c89e4eSSatish Balay .   r - the routine
342e5c89e4eSSatish Balay 
343e5c89e4eSSatish Balay     Level: developer
344e5c89e4eSSatish Balay 
345140e18c1SBarry Smith .seealso: PetscFunctionListAddDynamic(), PetscFunctionList
346e5c89e4eSSatish Balay @*/
347140e18c1SBarry Smith PetscErrorCode  PetscFunctionListFind(MPI_Comm comm,PetscFunctionList fl,const char name[],PetscBool searchlibraries,void (**r)(void))
348e5c89e4eSSatish Balay {
349140e18c1SBarry Smith   PetscFunctionList entry = fl;
350e5c89e4eSSatish Balay   PetscErrorCode    ierr;
351e5c89e4eSSatish Balay   char              *function,*path;
352ace3abfcSBarry Smith   PetscBool         flg,f1,f2,f3;
3530598bfebSBarry Smith #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES)
354e5c89e4eSSatish Balay   char              *newpath;
355e5c89e4eSSatish Balay #endif
356e5c89e4eSSatish Balay 
357e5c89e4eSSatish Balay   PetscFunctionBegin;
358e32f2f54SBarry Smith   if (!name) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Trying to find routine with null name");
359e5c89e4eSSatish Balay 
360e5c89e4eSSatish Balay   *r = 0;
361140e18c1SBarry Smith   ierr = PetscFunctionListGetPathAndFunction(name,&path,&function);CHKERRQ(ierr);
362e5c89e4eSSatish Balay 
363e5c89e4eSSatish Balay   /*
364e5c89e4eSSatish Balay         If path then append it to search libraries
365e5c89e4eSSatish Balay   */
3660598bfebSBarry Smith #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES)
367e5c89e4eSSatish Balay   if (path) {
368d44a1e48SBarry Smith     ierr = PetscDLLibraryAppend(comm,&PetscDLLibrariesLoaded,path);CHKERRQ(ierr);
369e5c89e4eSSatish Balay   }
370e5c89e4eSSatish Balay #endif
371e5c89e4eSSatish Balay 
372e5c89e4eSSatish Balay   while (entry) {
373e5c89e4eSSatish Balay     flg = PETSC_FALSE;
374e5c89e4eSSatish Balay     if (path && entry->path) {
375e5c89e4eSSatish Balay       ierr = PetscStrcmp(path,entry->path,&f1);CHKERRQ(ierr);
376e5c89e4eSSatish Balay       ierr = PetscStrcmp(function,entry->rname,&f2);CHKERRQ(ierr);
377e5c89e4eSSatish Balay       ierr = PetscStrcmp(function,entry->name,&f3);CHKERRQ(ierr);
378ace3abfcSBarry Smith       flg  =  (PetscBool) ((f1 && f2) || (f1 && f3));
379e5c89e4eSSatish Balay     } else if (!path) {
380e5c89e4eSSatish Balay       ierr = PetscStrcmp(function,entry->name,&f1);CHKERRQ(ierr);
381e5c89e4eSSatish Balay       ierr = PetscStrcmp(function,entry->rname,&f2);CHKERRQ(ierr);
382ace3abfcSBarry Smith       flg  =  (PetscBool) (f1 || f2);
383e5c89e4eSSatish Balay     } else {
384e5c89e4eSSatish Balay       ierr = PetscStrcmp(function,entry->name,&flg);CHKERRQ(ierr);
385e5c89e4eSSatish Balay       if (flg) {
386e5c89e4eSSatish Balay         ierr = PetscFree(function);CHKERRQ(ierr);
387e5c89e4eSSatish Balay         ierr = PetscStrallocpy(entry->rname,&function);CHKERRQ(ierr);
388e5c89e4eSSatish Balay       } else {
389e5c89e4eSSatish Balay         ierr = PetscStrcmp(function,entry->rname,&flg);CHKERRQ(ierr);
390e5c89e4eSSatish Balay       }
391e5c89e4eSSatish Balay     }
392e5c89e4eSSatish Balay 
393e5c89e4eSSatish Balay     if (flg) {
394e5c89e4eSSatish Balay       if (entry->routine) {
395e5c89e4eSSatish Balay         *r   = entry->routine;
396503cfb0cSBarry Smith         ierr = PetscFree(path);CHKERRQ(ierr);
397e5c89e4eSSatish Balay         ierr = PetscFree(function);CHKERRQ(ierr);
398e5c89e4eSSatish Balay         PetscFunctionReturn(0);
399e5c89e4eSSatish Balay       }
4005629bde7SJed Brown       if (!(entry->rname && entry->rname[0])) { /* The entry has been cleared */
4015629bde7SJed Brown         ierr = PetscFree(function);CHKERRQ(ierr);
4025629bde7SJed Brown         PetscFunctionReturn(0);
4035629bde7SJed Brown       }
404e5c89e4eSSatish Balay       if ((path && entry->path && f3) || (!path && f1)) { /* convert name of function (alias) to actual function name */
405e5c89e4eSSatish Balay         ierr = PetscFree(function);CHKERRQ(ierr);
406e5c89e4eSSatish Balay         ierr = PetscStrallocpy(entry->rname,&function);CHKERRQ(ierr);
407e5c89e4eSSatish Balay       }
408e5c89e4eSSatish Balay 
409e5c89e4eSSatish Balay       /* it is not yet in memory so load from dynamic library */
4100598bfebSBarry Smith #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES)
411e5c89e4eSSatish Balay       newpath = path;
412e5c89e4eSSatish Balay       if (!path) newpath = entry->path;
413d44a1e48SBarry Smith       ierr = PetscDLLibrarySym(comm,&PetscDLLibrariesLoaded,newpath,entry->rname,(void**)r);CHKERRQ(ierr);
414e5c89e4eSSatish Balay       if (*r) {
415e5c89e4eSSatish Balay         entry->routine = *r;
416a297a907SKarl Rupp 
417503cfb0cSBarry Smith         ierr = PetscFree(path);CHKERRQ(ierr);
418e5c89e4eSSatish Balay         ierr = PetscFree(function);CHKERRQ(ierr);
419e5c89e4eSSatish Balay         PetscFunctionReturn(0);
420e5c89e4eSSatish Balay       }
421e5c89e4eSSatish Balay #endif
422e5c89e4eSSatish Balay     }
423e5c89e4eSSatish Balay     entry = entry->next;
424e5c89e4eSSatish Balay   }
425e5c89e4eSSatish Balay 
4260598bfebSBarry Smith #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES)
4274b91b6eaSBarry Smith   if (searchlibraries) {
428e5c89e4eSSatish Balay     /* Function never registered; try for it anyway */
429d44a1e48SBarry Smith     ierr = PetscDLLibrarySym(comm,&PetscDLLibrariesLoaded,path,function,(void**)r);CHKERRQ(ierr);
430503cfb0cSBarry Smith     ierr = PetscFree(path);CHKERRQ(ierr);
431e5c89e4eSSatish Balay     if (*r) {
432140e18c1SBarry Smith       ierr = PetscFunctionListAdd(comm,&fl,name,name,*r);CHKERRQ(ierr);
433e5c89e4eSSatish Balay     }
4344b91b6eaSBarry Smith   }
435e5c89e4eSSatish Balay #endif
436e5c89e4eSSatish Balay   ierr = PetscFree(function);CHKERRQ(ierr);
437e5c89e4eSSatish Balay   PetscFunctionReturn(0);
438e5c89e4eSSatish Balay }
439e5c89e4eSSatish Balay 
440e5c89e4eSSatish Balay #undef __FUNCT__
441140e18c1SBarry Smith #define __FUNCT__ "PetscFunctionListView"
442e5c89e4eSSatish Balay /*@
443140e18c1SBarry Smith    PetscFunctionListView - prints out contents of an PetscFunctionList
444e5c89e4eSSatish Balay 
445e5c89e4eSSatish Balay    Collective over MPI_Comm
446e5c89e4eSSatish Balay 
447e5c89e4eSSatish Balay    Input Parameters:
448e5c89e4eSSatish Balay +  list - the list of functions
449e5c89e4eSSatish Balay -  viewer - currently ignored
450e5c89e4eSSatish Balay 
451e5c89e4eSSatish Balay    Level: developer
452e5c89e4eSSatish Balay 
453140e18c1SBarry Smith .seealso: PetscFunctionListAddDynamic(), PetscFunctionListPrintTypes(), PetscFunctionList
454e5c89e4eSSatish Balay @*/
455140e18c1SBarry Smith PetscErrorCode  PetscFunctionListView(PetscFunctionList list,PetscViewer viewer)
456e5c89e4eSSatish Balay {
457e5c89e4eSSatish Balay   PetscErrorCode ierr;
458ace3abfcSBarry Smith   PetscBool      iascii;
459e5c89e4eSSatish Balay 
460e5c89e4eSSatish Balay   PetscFunctionBegin;
461e5c89e4eSSatish Balay   if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;
462e5c89e4eSSatish Balay   PetscValidPointer(list,1);
4630700a824SBarry Smith   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
464e5c89e4eSSatish Balay 
465251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
466e32f2f54SBarry Smith   if (!iascii) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only ASCII viewer supported");
467e5c89e4eSSatish Balay 
468e5c89e4eSSatish Balay   while (list) {
469e5c89e4eSSatish Balay     if (list->path) {
470e5c89e4eSSatish Balay       ierr = PetscViewerASCIIPrintf(viewer," %s %s %s\n",list->path,list->name,list->rname);CHKERRQ(ierr);
471e5c89e4eSSatish Balay     } else {
472e5c89e4eSSatish Balay       ierr = PetscViewerASCIIPrintf(viewer," %s %s\n",list->name,list->rname);CHKERRQ(ierr);
473e5c89e4eSSatish Balay     }
474e5c89e4eSSatish Balay     list = list->next;
475e5c89e4eSSatish Balay   }
476e5c89e4eSSatish Balay   ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
477e5c89e4eSSatish Balay   PetscFunctionReturn(0);
478e5c89e4eSSatish Balay }
479e5c89e4eSSatish Balay 
480e5c89e4eSSatish Balay #undef __FUNCT__
481140e18c1SBarry Smith #define __FUNCT__ "PetscFunctionListGet"
482065533a5SJed Brown /*@C
483140e18c1SBarry Smith    PetscFunctionListGet - Gets an array the contains the entries in PetscFunctionList, this is used
484e5c89e4eSSatish Balay          by help etc.
485e5c89e4eSSatish Balay 
486e5c89e4eSSatish Balay    Collective over MPI_Comm
487e5c89e4eSSatish Balay 
488e5c89e4eSSatish Balay    Input Parameter:
489e5c89e4eSSatish Balay .  list   - list of types
490e5c89e4eSSatish Balay 
491e5c89e4eSSatish Balay    Output Parameter:
492e5c89e4eSSatish Balay +  array - array of names
493e5c89e4eSSatish Balay -  n - length of array
494e5c89e4eSSatish Balay 
495e5c89e4eSSatish Balay    Notes:
496e5c89e4eSSatish Balay        This allocates the array so that must be freed. BUT the individual entries are
497e5c89e4eSSatish Balay     not copied so should not be freed.
498e5c89e4eSSatish Balay 
499e5c89e4eSSatish Balay    Level: developer
500e5c89e4eSSatish Balay 
501140e18c1SBarry Smith .seealso: PetscFunctionListAddDynamic(), PetscFunctionList
502e5c89e4eSSatish Balay @*/
503140e18c1SBarry Smith PetscErrorCode  PetscFunctionListGet(PetscFunctionList list,const char ***array,int *n)
504e5c89e4eSSatish Balay {
505e5c89e4eSSatish Balay   PetscErrorCode    ierr;
506e5c89e4eSSatish Balay   PetscInt          count = 0;
507140e18c1SBarry Smith   PetscFunctionList klist = list;
508e5c89e4eSSatish Balay 
509e5c89e4eSSatish Balay   PetscFunctionBegin;
510e5c89e4eSSatish Balay   while (list) {
511e5c89e4eSSatish Balay     list = list->next;
512e5c89e4eSSatish Balay     count++;
513e5c89e4eSSatish Balay   }
514e5c89e4eSSatish Balay   ierr  = PetscMalloc((count+1)*sizeof(char*),array);CHKERRQ(ierr);
515e5c89e4eSSatish Balay   count = 0;
516e5c89e4eSSatish Balay   while (klist) {
517e5c89e4eSSatish Balay     (*array)[count] = klist->name;
518e5c89e4eSSatish Balay     klist           = klist->next;
519e5c89e4eSSatish Balay     count++;
520e5c89e4eSSatish Balay   }
521e5c89e4eSSatish Balay   (*array)[count] = 0;
522e5c89e4eSSatish Balay   *n              = count+1;
523e5c89e4eSSatish Balay   PetscFunctionReturn(0);
524e5c89e4eSSatish Balay }
525e5c89e4eSSatish Balay 
526e5c89e4eSSatish Balay 
527e5c89e4eSSatish Balay #undef __FUNCT__
528140e18c1SBarry Smith #define __FUNCT__ "PetscFunctionListPrintTypes"
529e5c89e4eSSatish Balay /*@C
530140e18c1SBarry Smith    PetscFunctionListPrintTypes - Prints the methods available.
531e5c89e4eSSatish Balay 
532e5c89e4eSSatish Balay    Collective over MPI_Comm
533e5c89e4eSSatish Balay 
534e5c89e4eSSatish Balay    Input Parameters:
535e5c89e4eSSatish Balay +  comm   - the communicator (usually MPI_COMM_WORLD)
536e5c89e4eSSatish Balay .  fd     - file to print to, usually stdout
537e5c89e4eSSatish Balay .  prefix - prefix to prepend to name (optional)
538e5c89e4eSSatish Balay .  name   - option string (for example, "-ksp_type")
539e5c89e4eSSatish Balay .  text - short description of the object (for example, "Krylov solvers")
540e5c89e4eSSatish Balay .  man - name of manual page that discusses the object (for example, "KSPCreate")
5413cc1e11dSBarry Smith .  list   - list of types
5423cc1e11dSBarry Smith -  def - default (current) value
543e5c89e4eSSatish Balay 
544e5c89e4eSSatish Balay    Level: developer
545e5c89e4eSSatish Balay 
546140e18c1SBarry Smith .seealso: PetscFunctionListAddDynamic(), PetscFunctionList
547e5c89e4eSSatish Balay @*/
548140e18c1SBarry Smith PetscErrorCode  PetscFunctionListPrintTypes(MPI_Comm comm,FILE *fd,const char prefix[],const char name[],const char text[],const char man[],PetscFunctionList list,const char def[])
549e5c89e4eSSatish Balay {
550e5c89e4eSSatish Balay   PetscErrorCode ierr;
551e5c89e4eSSatish Balay   PetscInt       count = 0;
552e5c89e4eSSatish Balay   char           p[64];
553e5c89e4eSSatish Balay 
554e5c89e4eSSatish Balay   PetscFunctionBegin;
555da9f1d6bSBarry Smith   if (!fd) fd = PETSC_STDOUT;
556e5c89e4eSSatish Balay 
557e5c89e4eSSatish Balay   ierr = PetscStrcpy(p,"-");CHKERRQ(ierr);
558e5c89e4eSSatish Balay   if (prefix) {ierr = PetscStrcat(p,prefix);CHKERRQ(ierr);}
5593cc1e11dSBarry Smith   ierr = PetscFPrintf(comm,fd,"  %s%s <%s>: %s (one of)",p,name+1,def,text);CHKERRQ(ierr);
560e5c89e4eSSatish Balay 
561e5c89e4eSSatish Balay   while (list) {
562e5c89e4eSSatish Balay     ierr = PetscFPrintf(comm,fd," %s",list->name);CHKERRQ(ierr);
563e5c89e4eSSatish Balay     list = list->next;
564e5c89e4eSSatish Balay     count++;
565e5c89e4eSSatish Balay     if (count == 8) {ierr = PetscFPrintf(comm,fd,"\n     ");CHKERRQ(ierr);}
566e5c89e4eSSatish Balay   }
567e5c89e4eSSatish Balay   ierr = PetscFPrintf(comm,fd," (%s)\n",man);CHKERRQ(ierr);
568e5c89e4eSSatish Balay   PetscFunctionReturn(0);
569e5c89e4eSSatish Balay }
570e5c89e4eSSatish Balay 
571e5c89e4eSSatish Balay #undef __FUNCT__
572140e18c1SBarry Smith #define __FUNCT__ "PetscFunctionListDuplicate"
573e5c89e4eSSatish Balay /*@
574140e18c1SBarry Smith     PetscFunctionListDuplicate - Creates a new list from a given object list.
575e5c89e4eSSatish Balay 
576e5c89e4eSSatish Balay     Input Parameters:
577e5c89e4eSSatish Balay .   fl   - pointer to list
578e5c89e4eSSatish Balay 
579e5c89e4eSSatish Balay     Output Parameters:
580e5c89e4eSSatish Balay .   nl - the new list (should point to 0 to start, otherwise appends)
581e5c89e4eSSatish Balay 
582e5c89e4eSSatish Balay     Level: developer
583e5c89e4eSSatish Balay 
584140e18c1SBarry Smith .seealso: PetscFunctionList, PetscFunctionListAdd(), PetscFlistDestroy()
585e5c89e4eSSatish Balay 
586e5c89e4eSSatish Balay @*/
587140e18c1SBarry Smith PetscErrorCode  PetscFunctionListDuplicate(PetscFunctionList fl,PetscFunctionList *nl)
588e5c89e4eSSatish Balay {
589e5c89e4eSSatish Balay   PetscErrorCode ierr;
590e5c89e4eSSatish Balay   char           path[PETSC_MAX_PATH_LEN];
591e5c89e4eSSatish Balay 
592e5c89e4eSSatish Balay   PetscFunctionBegin;
593e5c89e4eSSatish Balay   while (fl) {
594e5c89e4eSSatish Balay     /* this is silly, rebuild the complete pathname */
595e5c89e4eSSatish Balay     if (fl->path) {
596e5c89e4eSSatish Balay       ierr = PetscStrcpy(path,fl->path);CHKERRQ(ierr);
597e5c89e4eSSatish Balay       ierr = PetscStrcat(path,":");CHKERRQ(ierr);
598e5c89e4eSSatish Balay       ierr = PetscStrcat(path,fl->name);CHKERRQ(ierr);
599e5c89e4eSSatish Balay     } else {
600e5c89e4eSSatish Balay       ierr = PetscStrcpy(path,fl->name);CHKERRQ(ierr);
601e5c89e4eSSatish Balay     }
602140e18c1SBarry Smith     ierr = PetscFunctionListAdd(PETSC_COMM_WORLD,nl,path,fl->rname,fl->routine);CHKERRQ(ierr);
603e5c89e4eSSatish Balay     fl   = fl->next;
604e5c89e4eSSatish Balay   }
605e5c89e4eSSatish Balay   PetscFunctionReturn(0);
606e5c89e4eSSatish Balay }
607e5c89e4eSSatish Balay 
608e5c89e4eSSatish Balay 
609e5c89e4eSSatish Balay #undef __FUNCT__
610140e18c1SBarry Smith #define __FUNCT__ "PetscFunctionListConcat"
611e5c89e4eSSatish Balay /*
612140e18c1SBarry Smith     PetscFunctionListConcat - joins name of a libary, and the path where it is located
613e5c89e4eSSatish Balay     into a single string.
614e5c89e4eSSatish Balay 
615e5c89e4eSSatish Balay     Input Parameters:
616e5c89e4eSSatish Balay .   path   - path to the library name.
617e5c89e4eSSatish Balay .   name   - name of the library
618e5c89e4eSSatish Balay 
619e5c89e4eSSatish Balay     Output Parameters:
620e5c89e4eSSatish Balay .   fullname - the name that is the union of the path and the library name,
621e5c89e4eSSatish Balay                delimited by a semicolon, i.e., path:name
622e5c89e4eSSatish Balay 
623e5c89e4eSSatish Balay     Notes:
624e5c89e4eSSatish Balay     If the path is NULL, assumes that the name, specified also includes
625e5c89e4eSSatish Balay     the path as path:name
626e5c89e4eSSatish Balay 
627e5c89e4eSSatish Balay */
628140e18c1SBarry Smith PetscErrorCode  PetscFunctionListConcat(const char path[],const char name[],char fullname[])
629e5c89e4eSSatish Balay {
630e5c89e4eSSatish Balay   PetscErrorCode ierr;
6315fd66863SKarl Rupp 
632e5c89e4eSSatish Balay   PetscFunctionBegin;
633e5c89e4eSSatish Balay   if (path) {
634e5c89e4eSSatish Balay     ierr = PetscStrcpy(fullname,path);CHKERRQ(ierr);
635e5c89e4eSSatish Balay     ierr = PetscStrcat(fullname,":");CHKERRQ(ierr);
636e5c89e4eSSatish Balay     ierr = PetscStrcat(fullname,name);CHKERRQ(ierr);
637e5c89e4eSSatish Balay   } else {
638e5c89e4eSSatish Balay     ierr = PetscStrcpy(fullname,name);CHKERRQ(ierr);
639e5c89e4eSSatish Balay   }
640e5c89e4eSSatish Balay   PetscFunctionReturn(0);
641e5c89e4eSSatish Balay }
642