xref: /petsc/src/sys/dll/reg.c (revision 1a1499c8e13c12f02cf4c59cfd6b0cfcce01ae9b)
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_HAVE_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_HAVE_DYNAMIC_LIBRARIES)
54   PetscBool      preload;
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_HAVE_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   preload = PETSC_FALSE;
75   ierr = PetscOptionsGetBool(NULL,"-dynamic_library_preload",&preload,NULL);CHKERRQ(ierr);
76   if (preload) {
77     PetscBool found;
78 #if defined(PETSC_USE_SINGLE_LIBRARY)
79     ierr = PetscLoadDynamicLibrary("",&found);CHKERRQ(ierr);
80     if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc dynamic library \n You cannot move the dynamic libraries!");
81 #else
82     ierr = PetscLoadDynamicLibrary("sys",&found);CHKERRQ(ierr);
83     if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc dynamic library \n You cannot move the dynamic libraries!");
84     ierr = PetscLoadDynamicLibrary("vec",&found);CHKERRQ(ierr);
85     if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc Vec dynamic library \n You cannot move the dynamic libraries!");
86     ierr = PetscLoadDynamicLibrary("mat",&found);CHKERRQ(ierr);
87     if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc Mat dynamic library \n You cannot move the dynamic libraries!");
88     ierr = PetscLoadDynamicLibrary("dm",&found);CHKERRQ(ierr);
89     if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc DM dynamic library \n You cannot move the dynamic libraries!");
90     ierr = PetscLoadDynamicLibrary("ksp",&found);CHKERRQ(ierr);
91     if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc KSP dynamic library \n You cannot move the dynamic libraries!");
92     ierr = PetscLoadDynamicLibrary("snes",&found);CHKERRQ(ierr);
93     if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc SNES dynamic library \n You cannot move the dynamic libraries!");
94     ierr = PetscLoadDynamicLibrary("ts",&found);CHKERRQ(ierr);
95     if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc TS dynamic library \n You cannot move the dynamic libraries!");
96 #endif
97   }
98 #endif
99 
100   nmax = 32;
101   ierr = PetscOptionsGetStringArray(NULL,"-dll_append",libname,&nmax,NULL);CHKERRQ(ierr);
102   for (i=0; i<nmax; i++) {
103     ierr = PetscDLLibraryAppend(PETSC_COMM_WORLD,&PetscDLLibrariesLoaded,libname[i]);CHKERRQ(ierr);
104     ierr = PetscFree(libname[i]);CHKERRQ(ierr);
105   }
106 
107   ierr = PetscThreadCommInitializePackage();CHKERRQ(ierr);
108   ierr = PetscThreadCommWorldInitialize();CHKERRQ(ierr);
109   ierr = AOInitializePackage();CHKERRQ(ierr);
110   ierr = PetscSFInitializePackage();CHKERRQ(ierr);
111   ierr = CharacteristicInitializePackage();CHKERRQ(ierr);
112   ierr = ISInitializePackage();CHKERRQ(ierr);
113   ierr = VecInitializePackage();CHKERRQ(ierr);
114   ierr = MatInitializePackage();CHKERRQ(ierr);
115   ierr = DMInitializePackage();CHKERRQ(ierr);
116   ierr = PCInitializePackage();CHKERRQ(ierr);
117   ierr = KSPInitializePackage();CHKERRQ(ierr);
118   ierr = SNESInitializePackage();CHKERRQ(ierr);
119   ierr = TSInitializePackage();CHKERRQ(ierr);
120   {
121     MPI_Comm comm;
122     ierr = PetscCommDuplicate(PETSC_COMM_SELF,&comm,NULL);CHKERRQ(ierr);
123     ierr = PetscCommDuplicate(PETSC_COMM_WORLD,&comm,NULL);CHKERRQ(ierr);
124   }
125   PetscFunctionReturn(0);
126 }
127 
128 #undef __FUNCT__
129 #define __FUNCT__ "PetscFinalize_DynamicLibraries"
130 /*
131      PetscFinalize_DynamicLibraries - Closes the opened dynamic libraries.
132 */
133 PetscErrorCode PetscFinalize_DynamicLibraries(void)
134 {
135   PetscErrorCode ierr;
136   PetscBool      flg = PETSC_FALSE;
137 
138   PetscFunctionBegin;
139   ierr = PetscOptionsGetBool(NULL,"-dll_view",&flg,NULL);CHKERRQ(ierr);
140   if (flg) { ierr = PetscDLLibraryPrintPath(PetscDLLibrariesLoaded);CHKERRQ(ierr); }
141   ierr = PetscDLLibraryClose(PetscDLLibrariesLoaded);CHKERRQ(ierr);
142 
143   PetscDLLibrariesLoaded = 0;
144   PetscFunctionReturn(0);
145 }
146 
147 
148 
149 /* ------------------------------------------------------------------------------*/
150 struct _n_PetscFunctionList {
151   void              (*routine)(void);    /* the routine */
152   char              *name;               /* string to identify routine */
153   PetscFunctionList next;                /* next pointer */
154   PetscFunctionList next_list;           /* used to maintain list of all lists for freeing */
155 };
156 
157 /*
158      Keep a linked list of PetscFunctionLists so that we can destroy all the left-over ones.
159 */
160 static PetscFunctionList dlallhead = 0;
161 
162 /*MC
163    PetscFunctionListAdd - Given a routine and a string id, saves that routine in the
164    specified registry.
165 
166    Synopsis:
167    #include <petscsys.h>
168    PetscErrorCode PetscFunctionListAdd(PetscFunctionList flist,const char name[],void (*fptr)(void))
169 
170    Not Collective
171 
172    Input Parameters:
173 +  flist - pointer registry
174 .  name - string to identify routine
175 -  fptr - function pointer
176 
177    Notes:
178    To remove a registered routine, pass in a NULL fptr.
179 
180    Users who wish to register new classes for use by a particular PETSc
181    component (e.g., SNES) should generally call the registration routine
182    for that particular component (e.g., SNESRegister()) instead of
183    calling PetscFunctionListAdd() directly.
184 
185     Level: developer
186 
187 .seealso: PetscFunctionListDestroy(), SNESRegister(), KSPRegister(),
188           PCRegister(), TSRegister(), PetscFunctionList, PetscObjectComposeFunction()
189 M*/
190 #undef __FUNCT__
191 #define __FUNCT__ "PetscFunctionListAdd_Private"
192 PETSC_EXTERN PetscErrorCode PetscFunctionListAdd_Private(PetscFunctionList *fl,const char name[],void (*fnc)(void))
193 {
194   PetscFunctionList entry,ne;
195   PetscErrorCode    ierr;
196 
197   PetscFunctionBegin;
198   if (!*fl) {
199     ierr           = PetscNew(&entry);CHKERRQ(ierr);
200     ierr           = PetscStrallocpy(name,&entry->name);CHKERRQ(ierr);
201     entry->routine = fnc;
202     entry->next    = 0;
203     *fl            = entry;
204 
205 #if defined(PETSC_USE_LOG)
206     /* add this new list to list of all lists */
207     if (!dlallhead) {
208       dlallhead        = *fl;
209       (*fl)->next_list = 0;
210     } else {
211       ne               = dlallhead;
212       dlallhead        = *fl;
213       (*fl)->next_list = ne;
214     }
215 #endif
216 
217   } else {
218     /* search list to see if it is already there */
219     ne = *fl;
220     while (ne) {
221       PetscBool founddup;
222 
223       ierr = PetscStrcmp(ne->name,name,&founddup);CHKERRQ(ierr);
224       if (founddup) { /* found duplicate */
225         ne->routine = fnc;
226         PetscFunctionReturn(0);
227       }
228       if (ne->next) ne = ne->next;
229       else break;
230     }
231     /* create new entry and add to end of list */
232     ierr           = PetscNew(&entry);CHKERRQ(ierr);
233     ierr           = PetscStrallocpy(name,&entry->name);CHKERRQ(ierr);
234     entry->routine = fnc;
235     entry->next    = 0;
236     ne->next       = entry;
237   }
238   PetscFunctionReturn(0);
239 }
240 
241 #undef __FUNCT__
242 #define __FUNCT__ "PetscFunctionListDestroy"
243 /*@
244     PetscFunctionListDestroy - Destroys a list of registered routines.
245 
246     Input Parameter:
247 .   fl  - pointer to list
248 
249     Level: developer
250 
251 .seealso: PetscFunctionListAdd(), PetscFunctionList
252 @*/
253 PetscErrorCode  PetscFunctionListDestroy(PetscFunctionList *fl)
254 {
255   PetscFunctionList next,entry,tmp = dlallhead;
256   PetscErrorCode    ierr;
257 
258   PetscFunctionBegin;
259   if (!*fl) PetscFunctionReturn(0);
260 
261   /*
262        Remove this entry from the master DL list (if it is in it)
263   */
264   if (dlallhead == *fl) {
265     if (dlallhead->next_list) dlallhead = dlallhead->next_list;
266     else dlallhead = NULL;
267   } else if (tmp) {
268     while (tmp->next_list != *fl) {
269       tmp = tmp->next_list;
270       if (!tmp->next_list) break;
271     }
272     if (tmp->next_list) tmp->next_list = tmp->next_list->next_list;
273   }
274 
275   /* free this list */
276   entry = *fl;
277   while (entry) {
278     next  = entry->next;
279     ierr  = PetscFree(entry->name);CHKERRQ(ierr);
280     ierr  = PetscFree(entry);CHKERRQ(ierr);
281     entry = next;
282   }
283   *fl = 0;
284   PetscFunctionReturn(0);
285 }
286 
287 /*
288    Print any PetscFunctionLists that have not be destroyed
289 */
290 #undef __FUNCT__
291 #define __FUNCT__ "PetscFunctionListPrintAll"
292 PetscErrorCode  PetscFunctionListPrintAll(void)
293 {
294   PetscFunctionList tmp = dlallhead;
295   PetscErrorCode    ierr;
296 
297   PetscFunctionBegin;
298   if (tmp) {
299     ierr = PetscPrintf(PETSC_COMM_WORLD,"The following PetscFunctionLists were not destroyed\n");CHKERRQ(ierr);
300   }
301   while (tmp) {
302     ierr = PetscPrintf(PETSC_COMM_WORLD,"%s \n",tmp->name);CHKERRQ(ierr);
303     tmp = tmp->next_list;
304   }
305   PetscFunctionReturn(0);
306 }
307 
308 /*MC
309     PetscFunctionListFind - Find function registered under given name
310 
311     Synopsis:
312     #include <petscsys.h>
313     PetscErrorCode PetscFunctionListFind(PetscFunctionList flist,const char name[],void (**fptr)(void))
314 
315     Input Parameters:
316 +   flist   - pointer to list
317 -   name - name registered for the function
318 
319     Output Parameters:
320 .   fptr - the function pointer if name was found, else NULL
321 
322     Level: developer
323 
324 .seealso: PetscFunctionListAdd(), PetscFunctionList, PetscObjectQueryFunction()
325 M*/
326 #undef __FUNCT__
327 #define __FUNCT__ "PetscFunctionListFind_Private"
328 PETSC_EXTERN PetscErrorCode PetscFunctionListFind_Private(PetscFunctionList fl,const char name[],void (**r)(void))
329 {
330   PetscFunctionList entry = fl;
331   PetscErrorCode    ierr;
332   PetscBool         flg;
333 
334   PetscFunctionBegin;
335   if (!name) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Trying to find routine with null name");
336 
337   *r = 0;
338   while (entry) {
339     ierr = PetscStrcmp(name,entry->name,&flg);CHKERRQ(ierr);
340     if (flg) {
341       *r   = entry->routine;
342       PetscFunctionReturn(0);
343     }
344     entry = entry->next;
345   }
346   PetscFunctionReturn(0);
347 }
348 
349 #undef __FUNCT__
350 #define __FUNCT__ "PetscFunctionListView"
351 /*@
352    PetscFunctionListView - prints out contents of an PetscFunctionList
353 
354    Collective over MPI_Comm
355 
356    Input Parameters:
357 +  list - the list of functions
358 -  viewer - currently ignored
359 
360    Level: developer
361 
362 .seealso: PetscFunctionListAdd(), PetscFunctionListPrintTypes(), PetscFunctionList
363 @*/
364 PetscErrorCode  PetscFunctionListView(PetscFunctionList list,PetscViewer viewer)
365 {
366   PetscErrorCode ierr;
367   PetscBool      iascii;
368 
369   PetscFunctionBegin;
370   if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;
371   PetscValidPointer(list,1);
372   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
373 
374   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
375   if (!iascii) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only ASCII viewer supported");
376 
377   while (list) {
378     ierr = PetscViewerASCIIPrintf(viewer," %s\n",list->name);CHKERRQ(ierr);
379     list = list->next;
380   }
381   ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
382   PetscFunctionReturn(0);
383 }
384 
385 #undef __FUNCT__
386 #define __FUNCT__ "PetscFunctionListGet"
387 /*@C
388    PetscFunctionListGet - Gets an array the contains the entries in PetscFunctionList, this is used
389          by help etc.
390 
391    Not Collective
392 
393    Input Parameter:
394 .  list   - list of types
395 
396    Output Parameter:
397 +  array - array of names
398 -  n - length of array
399 
400    Notes:
401        This allocates the array so that must be freed. BUT the individual entries are
402     not copied so should not be freed.
403 
404    Level: developer
405 
406 .seealso: PetscFunctionListAdd(), PetscFunctionList
407 @*/
408 PetscErrorCode  PetscFunctionListGet(PetscFunctionList list,const char ***array,int *n)
409 {
410   PetscErrorCode    ierr;
411   PetscInt          count = 0;
412   PetscFunctionList klist = list;
413 
414   PetscFunctionBegin;
415   while (list) {
416     list = list->next;
417     count++;
418   }
419   ierr  = PetscMalloc1(count+1,array);CHKERRQ(ierr);
420   count = 0;
421   while (klist) {
422     (*array)[count] = klist->name;
423     klist           = klist->next;
424     count++;
425   }
426   (*array)[count] = 0;
427   *n              = count+1;
428   PetscFunctionReturn(0);
429 }
430 
431 
432 #undef __FUNCT__
433 #define __FUNCT__ "PetscFunctionListPrintTypes"
434 /*@C
435    PetscFunctionListPrintTypes - Prints the methods available.
436 
437    Collective over MPI_Comm
438 
439    Input Parameters:
440 +  comm   - the communicator (usually MPI_COMM_WORLD)
441 .  fd     - file to print to, usually stdout
442 .  prefix - prefix to prepend to name (optional)
443 .  name   - option string (for example, "-ksp_type")
444 .  text - short description of the object (for example, "Krylov solvers")
445 .  man - name of manual page that discusses the object (for example, "KSPCreate")
446 .  list   - list of types
447 -  def - default (current) value
448 
449    Level: developer
450 
451 .seealso: PetscFunctionListAdd(), PetscFunctionList
452 @*/
453 PetscErrorCode  PetscFunctionListPrintTypes(MPI_Comm comm,FILE *fd,const char prefix[],const char name[],const char text[],const char man[],PetscFunctionList list,const char def[])
454 {
455   PetscErrorCode ierr;
456   PetscInt       count = 0;
457   char           p[64];
458 
459   PetscFunctionBegin;
460   if (!fd) fd = PETSC_STDOUT;
461 
462   ierr = PetscStrcpy(p,"-");CHKERRQ(ierr);
463   if (prefix) {ierr = PetscStrcat(p,prefix);CHKERRQ(ierr);}
464   ierr = PetscFPrintf(comm,fd,"  %s%s <%s>: %s (one of)",p,name+1,def,text);CHKERRQ(ierr);
465 
466   while (list) {
467     ierr = PetscFPrintf(comm,fd," %s",list->name);CHKERRQ(ierr);
468     list = list->next;
469     count++;
470     if (count == 8) {ierr = PetscFPrintf(comm,fd,"\n     ");CHKERRQ(ierr);}
471   }
472   ierr = PetscFPrintf(comm,fd," (%s)\n",man);CHKERRQ(ierr);
473   PetscFunctionReturn(0);
474 }
475 
476 #undef __FUNCT__
477 #define __FUNCT__ "PetscFunctionListDuplicate"
478 /*@
479     PetscFunctionListDuplicate - Creates a new list from a given object list.
480 
481     Input Parameters:
482 .   fl   - pointer to list
483 
484     Output Parameters:
485 .   nl - the new list (should point to 0 to start, otherwise appends)
486 
487     Level: developer
488 
489 .seealso: PetscFunctionList, PetscFunctionListAdd(), PetscFlistDestroy()
490 
491 @*/
492 PetscErrorCode  PetscFunctionListDuplicate(PetscFunctionList fl,PetscFunctionList *nl)
493 {
494   PetscErrorCode ierr;
495 
496   PetscFunctionBegin;
497   while (fl) {
498     ierr = PetscFunctionListAdd(nl,fl->name,fl->routine);CHKERRQ(ierr);
499     fl   = fl->next;
500   }
501   PetscFunctionReturn(0);
502 }
503 
504