xref: /petsc/src/sys/dll/reg.c (revision 1c9cd33768b1fd01403e37595b64fe66efc857ab)
1 
2 /*
3     Provides a general mechanism to allow one to register new routines in
4     dynamic libraries for many of the PETSc objects (including, e.g., KSP and PC).
5 */
6 #include <petsc-private/petscimpl.h>           /*I "petscsys.h" I*/
7 #include <petscviewer.h>
8 
9 /*
10     This is the default list used by PETSc with the PetscDLLibrary register routines
11 */
12 PetscDLLibrary PetscDLLibrariesLoaded = 0;
13 
14 #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
15 
16 #undef __FUNCT__
17 #define __FUNCT__ "PetscLoadDynamicLibrary"
18 static PetscErrorCode  PetscLoadDynamicLibrary(const char *name,PetscBool  *found)
19 {
20   char           libs[PETSC_MAX_PATH_LEN],dlib[PETSC_MAX_PATH_LEN];
21   PetscErrorCode ierr;
22 
23   PetscFunctionBegin;
24   ierr = PetscStrcpy(libs,"${PETSC_LIB_DIR}/libpetsc");CHKERRQ(ierr);
25   ierr = PetscStrcat(libs,name);CHKERRQ(ierr);
26   ierr = PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,found);CHKERRQ(ierr);
27   if (*found) {
28     ierr = PetscDLLibraryAppend(PETSC_COMM_WORLD,&PetscDLLibrariesLoaded,dlib);CHKERRQ(ierr);
29   } else {
30     ierr = PetscStrcpy(libs,"${PETSC_DIR}/${PETSC_ARCH}/lib/libpetsc");CHKERRQ(ierr);
31     ierr = PetscStrcat(libs,name);CHKERRQ(ierr);
32     ierr = PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,found);CHKERRQ(ierr);
33     if (*found) {
34       ierr = PetscDLLibraryAppend(PETSC_COMM_WORLD,&PetscDLLibrariesLoaded,dlib);CHKERRQ(ierr);
35     }
36   }
37   PetscFunctionReturn(0);
38 }
39 
40 #endif
41 
42 #undef __FUNCT__
43 #define __FUNCT__ "PetscInitialize_DynamicLibraries"
44 /*
45     PetscInitialize_DynamicLibraries - Adds the default dynamic link libraries to the
46     search path.
47 */
48 PetscErrorCode  PetscInitialize_DynamicLibraries(void)
49 {
50   char           *libname[32];
51   PetscErrorCode ierr;
52   PetscInt       nmax,i;
53 #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
54   PetscBool      found;
55 #endif
56 
57   PetscFunctionBegin;
58   nmax = 32;
59   ierr = PetscOptionsGetStringArray(NULL,"-dll_prepend",libname,&nmax,NULL);CHKERRQ(ierr);
60   for (i=0; i<nmax; i++) {
61     ierr = PetscDLLibraryPrepend(PETSC_COMM_WORLD,&PetscDLLibrariesLoaded,libname[i]);CHKERRQ(ierr);
62     ierr = PetscFree(libname[i]);CHKERRQ(ierr);
63   }
64 
65 #if !defined(PETSC_USE_DYNAMIC_LIBRARIES)
66   /*
67       This just initializes the most basic PETSc stuff.
68 
69     The classes, from PetscDraw to PetscTS, are initialized the first
70     time an XXCreate() is called.
71   */
72   ierr = PetscSysInitializePackage();CHKERRQ(ierr);
73 #else
74 #if defined(PETSC_USE_SINGLE_LIBRARY)
75   ierr = PetscLoadDynamicLibrary("",&found);CHKERRQ(ierr);
76   if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc dynamic library \n You cannot move the dynamic libraries!");
77 #else
78   ierr = PetscLoadDynamicLibrary("sys",&found);CHKERRQ(ierr);
79   if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc dynamic library \n You cannot move the dynamic libraries!");
80   ierr = PetscLoadDynamicLibrary("vec",&found);CHKERRQ(ierr);
81   if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc Vec dynamic library \n You cannot move the dynamic libraries!");
82   ierr = PetscLoadDynamicLibrary("mat",&found);CHKERRQ(ierr);
83   if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc Mat dynamic library \n You cannot move the dynamic libraries!");
84   ierr = PetscLoadDynamicLibrary("dm",&found);CHKERRQ(ierr);
85   if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc DM dynamic library \n You cannot move the dynamic libraries!");
86   ierr = PetscLoadDynamicLibrary("ksp",&found);CHKERRQ(ierr);
87   if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc KSP dynamic library \n You cannot move the dynamic libraries!");
88   ierr = PetscLoadDynamicLibrary("snes",&found);CHKERRQ(ierr);
89   if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc SNES dynamic library \n You cannot move the dynamic libraries!");
90   ierr = PetscLoadDynamicLibrary("ts",&found);CHKERRQ(ierr);
91   if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc TS dynamic library \n You cannot move the dynamic libraries!");
92 #endif
93 #endif
94 
95   nmax = 32;
96   ierr = PetscOptionsGetStringArray(NULL,"-dll_append",libname,&nmax,NULL);CHKERRQ(ierr);
97   for (i=0; i<nmax; i++) {
98     ierr = PetscDLLibraryAppend(PETSC_COMM_WORLD,&PetscDLLibrariesLoaded,libname[i]);CHKERRQ(ierr);
99     ierr = PetscFree(libname[i]);CHKERRQ(ierr);
100   }
101   PetscFunctionReturn(0);
102 }
103 
104 #undef __FUNCT__
105 #define __FUNCT__ "PetscFinalize_DynamicLibraries"
106 /*
107      PetscFinalize_DynamicLibraries - Closes the opened dynamic libraries.
108 */
109 PetscErrorCode PetscFinalize_DynamicLibraries(void)
110 {
111   PetscErrorCode ierr;
112   PetscBool      flg = PETSC_FALSE;
113 
114   PetscFunctionBegin;
115   ierr = PetscOptionsGetBool(NULL,"-dll_view",&flg,NULL);CHKERRQ(ierr);
116   if (flg) { ierr = PetscDLLibraryPrintPath(PetscDLLibrariesLoaded);CHKERRQ(ierr); }
117   ierr = PetscDLLibraryClose(PetscDLLibrariesLoaded);CHKERRQ(ierr);
118 
119   PetscDLLibrariesLoaded = 0;
120   PetscFunctionReturn(0);
121 }
122 
123 
124 
125 /* ------------------------------------------------------------------------------*/
126 struct _n_PetscFunctionList {
127   void              (*routine)(void);    /* the routine */
128   char              *name;               /* string to identify routine */
129   PetscFunctionList next;                /* next pointer */
130   PetscFunctionList next_list;           /* used to maintain list of all lists for freeing */
131 };
132 
133 /*
134      Keep a linked list of PetscFunctionLists so that we can destroy all the left-over ones.
135 */
136 static PetscFunctionList dlallhead = 0;
137 
138 #undef __FUNCT__
139 #define __FUNCT__ "PetscFunctionListAdd"
140 /*@C
141    PetscFunctionListAdd - Given a routine and a string id, saves that routine in the
142    specified registry.
143 
144      Not Collective
145 
146    Input Parameters:
147 +  fl    - pointer registry
148 .  name  - string to identify routine
149 -  fnc   - function pointer (optional if using dynamic libraries)
150 
151    Notes:
152    To remove a registered routine, pass in a NULL  fnc().
153 
154    Users who wish to register new classes for use by a particular PETSc
155    component (e.g., SNES) should generally call the registration routine
156    for that particular component (e.g., SNESRegister()) instead of
157    calling PetscFunctionListAdd() directly.
158 
159     Level: developer
160 
161 .seealso: PetscFunctionListDestroy(), SNESRegister(), KSPRegister(),
162           PCRegister(), TSRegister(), PetscFunctionList
163 @*/
164 PetscErrorCode  PetscFunctionListAdd(PetscFunctionList *fl,const char name[],void (*fnc)(void))
165 {
166   PetscFunctionList entry,ne;
167   PetscErrorCode    ierr;
168 
169   PetscFunctionBegin;
170   if (!*fl) {
171     ierr           = PetscNew(struct _n_PetscFunctionList,&entry);CHKERRQ(ierr);
172     ierr           = PetscStrallocpy(name,&entry->name);CHKERRQ(ierr);
173     entry->routine = fnc;
174     entry->next    = 0;
175     *fl            = entry;
176 
177     /* add this new list to list of all lists */
178     if (!dlallhead) {
179       dlallhead        = *fl;
180       (*fl)->next_list = 0;
181     } else {
182       ne               = dlallhead;
183       dlallhead        = *fl;
184       (*fl)->next_list = ne;
185     }
186   } else {
187     /* search list to see if it is already there */
188     ne = *fl;
189     while (ne) {
190       PetscBool founddup;
191 
192       ierr = PetscStrcmp(ne->name,name,&founddup);CHKERRQ(ierr);
193       if (founddup) { /* found duplicate */
194         ne->routine = fnc;
195         PetscFunctionReturn(0);
196       }
197       if (ne->next) ne = ne->next;
198       else break;
199     }
200     /* create new entry and add to end of list */
201     ierr           = PetscNew(struct _n_PetscFunctionList,&entry);CHKERRQ(ierr);
202     ierr           = PetscStrallocpy(name,&entry->name);CHKERRQ(ierr);
203     entry->routine = fnc;
204     entry->next    = 0;
205     ne->next       = entry;
206   }
207   PetscFunctionReturn(0);
208 }
209 
210 #undef __FUNCT__
211 #define __FUNCT__ "PetscFunctionListDestroy"
212 /*@
213     PetscFunctionListDestroy - Destroys a list of registered routines.
214 
215     Input Parameter:
216 .   fl  - pointer to list
217 
218     Level: developer
219 
220 .seealso: PetscFunctionListAddDynamic(), PetscFunctionList
221 @*/
222 PetscErrorCode  PetscFunctionListDestroy(PetscFunctionList *fl)
223 {
224   PetscFunctionList next,entry,tmp = dlallhead;
225   PetscErrorCode    ierr;
226 
227   PetscFunctionBegin;
228   if (!*fl) PetscFunctionReturn(0);
229   if (!dlallhead) PetscFunctionReturn(0);
230 
231   /*
232        Remove this entry from the master DL list (if it is in it)
233   */
234   if (dlallhead == *fl) {
235     if (dlallhead->next_list) dlallhead = dlallhead->next_list;
236     else dlallhead = 0;
237   } else {
238     while (tmp->next_list != *fl) {
239       tmp = tmp->next_list;
240       if (!tmp->next_list) break;
241     }
242     if (tmp->next_list) tmp->next_list = tmp->next_list->next_list;
243   }
244 
245   /* free this list */
246   entry = *fl;
247   while (entry) {
248     next  = entry->next;
249     ierr  = PetscFree(entry->name);CHKERRQ(ierr);
250     ierr  = PetscFree(entry);CHKERRQ(ierr);
251     entry = next;
252   }
253   *fl = 0;
254   PetscFunctionReturn(0);
255 }
256 
257 /*
258    Destroys all the function lists that anyone has every registered, such as KSPList, VecList, etc.
259 */
260 #undef __FUNCT__
261 #define __FUNCT__ "PetscFunctionListDestroyAll"
262 PetscErrorCode  PetscFunctionListDestroyAll(void)
263 {
264   PetscFunctionList tmp2,tmp1 = dlallhead;
265   PetscErrorCode    ierr;
266 
267   PetscFunctionBegin;
268   while (tmp1) {
269     tmp2 = tmp1->next_list;
270     ierr = PetscFunctionListDestroy(&tmp1);CHKERRQ(ierr);
271     tmp1 = tmp2;
272   }
273   dlallhead = 0;
274   PetscFunctionReturn(0);
275 }
276 
277 /*MC
278     PetscFunctionListFind - Find function registered under given name
279 
280     Synopsis:
281     #include "petscsys.h"
282     PetscErrorCode PetscFunctionListFind(PetscFunctionList flist,const char name[],void (**fptr)(void))
283 
284     Input Parameters:
285 +   flist   - pointer to list
286 -   name - name registered for the function
287 
288     Output Parameters:
289 .   fptr - the function pointer if name was found, else NULL
290 
291     Level: developer
292 
293 .seealso: PetscFunctionListAdd(), PetscFunctionList, PetscObjectQueryFunction()
294 M*/
295 #undef __FUNCT__
296 #define __FUNCT__ "PetscFunctionListFind_Private"
297 PETSC_EXTERN PetscErrorCode PetscFunctionListFind_Private(PetscFunctionList fl,const char name[],void (**r)(void))
298 {
299   PetscFunctionList entry = fl;
300   PetscErrorCode    ierr;
301   PetscBool         flg;
302 
303   PetscFunctionBegin;
304   if (!name) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Trying to find routine with null name");
305 
306   *r = 0;
307   while (entry) {
308     ierr = PetscStrcmp(name,entry->name,&flg);CHKERRQ(ierr);
309     if (flg) {
310       *r   = entry->routine;
311       PetscFunctionReturn(0);
312     }
313     entry = entry->next;
314   }
315   PetscFunctionReturn(0);
316 }
317 
318 #undef __FUNCT__
319 #define __FUNCT__ "PetscFunctionListView"
320 /*@
321    PetscFunctionListView - prints out contents of an PetscFunctionList
322 
323    Collective over MPI_Comm
324 
325    Input Parameters:
326 +  list - the list of functions
327 -  viewer - currently ignored
328 
329    Level: developer
330 
331 .seealso: PetscFunctionListAddDynamic(), PetscFunctionListPrintTypes(), PetscFunctionList
332 @*/
333 PetscErrorCode  PetscFunctionListView(PetscFunctionList list,PetscViewer viewer)
334 {
335   PetscErrorCode ierr;
336   PetscBool      iascii;
337 
338   PetscFunctionBegin;
339   if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;
340   PetscValidPointer(list,1);
341   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
342 
343   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
344   if (!iascii) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only ASCII viewer supported");
345 
346   while (list) {
347     ierr = PetscViewerASCIIPrintf(viewer," %s\n",list->name);CHKERRQ(ierr);
348     list = list->next;
349   }
350   ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
351   PetscFunctionReturn(0);
352 }
353 
354 #undef __FUNCT__
355 #define __FUNCT__ "PetscFunctionListGet"
356 /*@C
357    PetscFunctionListGet - Gets an array the contains the entries in PetscFunctionList, this is used
358          by help etc.
359 
360    Not Collective
361 
362    Input Parameter:
363 .  list   - list of types
364 
365    Output Parameter:
366 +  array - array of names
367 -  n - length of array
368 
369    Notes:
370        This allocates the array so that must be freed. BUT the individual entries are
371     not copied so should not be freed.
372 
373    Level: developer
374 
375 .seealso: PetscFunctionListAddDynamic(), PetscFunctionList
376 @*/
377 PetscErrorCode  PetscFunctionListGet(PetscFunctionList list,const char ***array,int *n)
378 {
379   PetscErrorCode    ierr;
380   PetscInt          count = 0;
381   PetscFunctionList klist = list;
382 
383   PetscFunctionBegin;
384   while (list) {
385     list = list->next;
386     count++;
387   }
388   ierr  = PetscMalloc((count+1)*sizeof(char*),array);CHKERRQ(ierr);
389   count = 0;
390   while (klist) {
391     (*array)[count] = klist->name;
392     klist           = klist->next;
393     count++;
394   }
395   (*array)[count] = 0;
396   *n              = count+1;
397   PetscFunctionReturn(0);
398 }
399 
400 
401 #undef __FUNCT__
402 #define __FUNCT__ "PetscFunctionListPrintTypes"
403 /*@C
404    PetscFunctionListPrintTypes - Prints the methods available.
405 
406    Collective over MPI_Comm
407 
408    Input Parameters:
409 +  comm   - the communicator (usually MPI_COMM_WORLD)
410 .  fd     - file to print to, usually stdout
411 .  prefix - prefix to prepend to name (optional)
412 .  name   - option string (for example, "-ksp_type")
413 .  text - short description of the object (for example, "Krylov solvers")
414 .  man - name of manual page that discusses the object (for example, "KSPCreate")
415 .  list   - list of types
416 -  def - default (current) value
417 
418    Level: developer
419 
420 .seealso: PetscFunctionListAddDynamic(), PetscFunctionList
421 @*/
422 PetscErrorCode  PetscFunctionListPrintTypes(MPI_Comm comm,FILE *fd,const char prefix[],const char name[],const char text[],const char man[],PetscFunctionList list,const char def[])
423 {
424   PetscErrorCode ierr;
425   PetscInt       count = 0;
426   char           p[64];
427 
428   PetscFunctionBegin;
429   if (!fd) fd = PETSC_STDOUT;
430 
431   ierr = PetscStrcpy(p,"-");CHKERRQ(ierr);
432   if (prefix) {ierr = PetscStrcat(p,prefix);CHKERRQ(ierr);}
433   ierr = PetscFPrintf(comm,fd,"  %s%s <%s>: %s (one of)",p,name+1,def,text);CHKERRQ(ierr);
434 
435   while (list) {
436     ierr = PetscFPrintf(comm,fd," %s",list->name);CHKERRQ(ierr);
437     list = list->next;
438     count++;
439     if (count == 8) {ierr = PetscFPrintf(comm,fd,"\n     ");CHKERRQ(ierr);}
440   }
441   ierr = PetscFPrintf(comm,fd," (%s)\n",man);CHKERRQ(ierr);
442   PetscFunctionReturn(0);
443 }
444 
445 #undef __FUNCT__
446 #define __FUNCT__ "PetscFunctionListDuplicate"
447 /*@
448     PetscFunctionListDuplicate - Creates a new list from a given object list.
449 
450     Input Parameters:
451 .   fl   - pointer to list
452 
453     Output Parameters:
454 .   nl - the new list (should point to 0 to start, otherwise appends)
455 
456     Level: developer
457 
458 .seealso: PetscFunctionList, PetscFunctionListAdd(), PetscFlistDestroy()
459 
460 @*/
461 PetscErrorCode  PetscFunctionListDuplicate(PetscFunctionList fl,PetscFunctionList *nl)
462 {
463   PetscErrorCode ierr;
464 
465   PetscFunctionBegin;
466   while (fl) {
467     ierr = PetscFunctionListAdd(nl,fl->name,fl->routine);CHKERRQ(ierr);
468     fl   = fl->next;
469   }
470   PetscFunctionReturn(0);
471 }
472 
473