Actual source code: reg.c
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>
7: #include <petscviewer.h>
9: /*
10: This is the default list used by PETSc with the PetscDLLibrary register routines
11: */
12: PetscDLLibrary PetscDLLibrariesLoaded = NULL;
14: #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES)
16: static PetscErrorCode PetscLoadDynamicLibrary(const char *name,PetscBool *found)
17: {
18: char libs[PETSC_MAX_PATH_LEN],dlib[PETSC_MAX_PATH_LEN];
20: PetscStrncpy(libs,"${PETSC_LIB_DIR}/libpetsc",sizeof(libs));
21: PetscStrlcat(libs,name,sizeof(libs));
22: PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,found);
23: if (*found) {
24: PetscDLLibraryAppend(PETSC_COMM_WORLD,&PetscDLLibrariesLoaded,dlib);
25: } else {
26: PetscStrncpy(libs,"${PETSC_DIR}/${PETSC_ARCH}/lib/libpetsc",sizeof(libs));
27: PetscStrlcat(libs,name,sizeof(libs));
28: PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,found);
29: if (*found) {
30: PetscDLLibraryAppend(PETSC_COMM_WORLD,&PetscDLLibrariesLoaded,dlib);
31: }
32: }
33: return 0;
34: }
35: #endif
37: #if defined(PETSC_USE_SINGLE_LIBRARY) && !(defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES))
38: PETSC_EXTERN PetscErrorCode AOInitializePackage(void);
39: PETSC_EXTERN PetscErrorCode PetscSFInitializePackage(void);
40: #if !defined(PETSC_USE_COMPLEX)
41: PETSC_EXTERN PetscErrorCode CharacteristicInitializePackage(void);
42: #endif
43: PETSC_EXTERN PetscErrorCode ISInitializePackage(void);
44: PETSC_EXTERN PetscErrorCode VecInitializePackage(void);
45: PETSC_EXTERN PetscErrorCode MatInitializePackage(void);
46: PETSC_EXTERN PetscErrorCode DMInitializePackage(void);
47: PETSC_EXTERN PetscErrorCode PCInitializePackage(void);
48: PETSC_EXTERN PetscErrorCode KSPInitializePackage(void);
49: PETSC_EXTERN PetscErrorCode SNESInitializePackage(void);
50: PETSC_EXTERN PetscErrorCode TSInitializePackage(void);
51: PETSC_EXTERN PetscErrorCode TaoInitializePackage(void);
52: #endif
53: #if defined(PETSC_HAVE_THREADSAFETY)
54: static MPI_Comm PETSC_COMM_WORLD_INNER = 0,PETSC_COMM_SELF_INNER = 0;
55: #endif
57: /*
58: PetscInitialize_DynamicLibraries - Adds the default dynamic link libraries to the
59: search path.
60: */
61: PETSC_INTERN PetscErrorCode PetscInitialize_DynamicLibraries(void)
62: {
63: char *libname[32];
64: PetscInt nmax,i;
65: PetscBool preload = PETSC_FALSE;
66: #if defined(PETSC_HAVE_ELEMENTAL)
67: PetscBool PetscInitialized = PetscInitializeCalled;
68: #endif
70: #if defined(PETSC_HAVE_THREADSAFETY)
71: /* These must be all initialized here because it is not safe for individual threads to call these initialize routines */
72: preload = PETSC_TRUE;
73: #endif
75: nmax = 32;
76: PetscOptionsGetStringArray(NULL,NULL,"-dll_prepend",libname,&nmax,NULL);
77: for (i=0; i<nmax; i++) {
78: PetscDLLibraryPrepend(PETSC_COMM_WORLD,&PetscDLLibrariesLoaded,libname[i]);
79: PetscFree(libname[i]);
80: }
82: PetscOptionsGetBool(NULL,NULL,"-library_preload",&preload,NULL);
83: if (!preload) {
84: PetscSysInitializePackage();
85: } else {
86: #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES)
87: PetscBool found;
88: #if defined(PETSC_USE_SINGLE_LIBRARY)
89: PetscLoadDynamicLibrary("",&found);
91: #else
92: PetscLoadDynamicLibrary("sys",&found);
94: PetscLoadDynamicLibrary("vec",&found);
96: PetscLoadDynamicLibrary("mat",&found);
98: PetscLoadDynamicLibrary("dm",&found);
100: PetscLoadDynamicLibrary("ksp",&found);
102: PetscLoadDynamicLibrary("snes",&found);
104: PetscLoadDynamicLibrary("ts",&found);
106: PetscLoadDynamicLibrary("tao",&found);
108: #endif
109: #else /* defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES) */
110: #if defined(PETSC_USE_SINGLE_LIBRARY)
111: AOInitializePackage();
112: PetscSFInitializePackage();
113: #if !defined(PETSC_USE_COMPLEX)
114: CharacteristicInitializePackage();
115: #endif
116: ISInitializePackage();
117: VecInitializePackage();
118: MatInitializePackage();
119: DMInitializePackage();
120: PCInitializePackage();
121: KSPInitializePackage();
122: SNESInitializePackage();
123: TSInitializePackage();
124: TaoInitializePackage();
125: #else
126: SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"Cannot use -library_preload with multiple static PETSc libraries");
127: #endif
128: #endif /* defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES) */
129: }
131: #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES) && defined(PETSC_HAVE_BAMG)
132: {
133: PetscBool found;
134: PetscLoadDynamicLibrary("bamg",&found);
136: }
137: #endif
139: nmax = 32;
140: PetscOptionsGetStringArray(NULL,NULL,"-dll_append",libname,&nmax,NULL);
141: for (i=0; i<nmax; i++) {
142: PetscDLLibraryAppend(PETSC_COMM_WORLD,&PetscDLLibrariesLoaded,libname[i]);
143: PetscFree(libname[i]);
144: }
146: #if defined(PETSC_HAVE_THREADSAFETY)
147: PetscCommDuplicate(PETSC_COMM_SELF,&PETSC_COMM_SELF_INNER,NULL);
148: PetscCommDuplicate(PETSC_COMM_WORLD,&PETSC_COMM_WORLD_INNER,NULL);
149: #endif
150: #if defined(PETSC_HAVE_ELEMENTAL)
151: /* in Fortran, PetscInitializeCalled is set to PETSC_TRUE before PetscInitialize_DynamicLibraries() */
152: /* in C, it is not the case, but the value is forced to PETSC_TRUE so that PetscRegisterFinalize() is called */
153: PetscInitializeCalled = PETSC_TRUE;
154: PetscElementalInitializePackage();
155: PetscInitializeCalled = PetscInitialized;
156: #endif
157: return 0;
158: }
160: /*
161: PetscFinalize_DynamicLibraries - Closes the opened dynamic libraries.
162: */
163: PETSC_INTERN PetscErrorCode PetscFinalize_DynamicLibraries(void)
164: {
165: PetscBool flg = PETSC_FALSE;
167: PetscOptionsGetBool(NULL,NULL,"-dll_view",&flg,NULL);
168: if (flg) PetscDLLibraryPrintPath(PetscDLLibrariesLoaded);
169: PetscDLLibraryClose(PetscDLLibrariesLoaded);
171: #if defined(PETSC_HAVE_THREADSAFETY)
172: PetscCommDestroy(&PETSC_COMM_SELF_INNER);
173: PetscCommDestroy(&PETSC_COMM_WORLD_INNER);
174: #endif
176: PetscDLLibrariesLoaded = NULL;
177: return 0;
178: }
180: /* ------------------------------------------------------------------------------*/
181: struct _n_PetscFunctionList {
182: void (*routine)(void); /* the routine */
183: char *name; /* string to identify routine */
184: PetscFunctionList next; /* next pointer */
185: PetscFunctionList next_list; /* used to maintain list of all lists for freeing */
186: };
188: /*
189: Keep a linked list of PetscFunctionLists so that we can destroy all the left-over ones.
190: */
191: static PetscFunctionList dlallhead = NULL;
193: /*MC
194: PetscFunctionListAdd - Given a routine and a string id, saves that routine in the
195: specified registry.
197: Synopsis:
198: #include <petscsys.h>
199: PetscErrorCode PetscFunctionListAdd(PetscFunctionList *flist,const char name[],void (*fptr)(void))
201: Not Collective
203: Input Parameters:
204: + flist - pointer to function list object
205: . name - string to identify routine
206: - fptr - function pointer
208: Notes:
209: To remove a registered routine, pass in a NULL fptr.
211: Users who wish to register new classes for use by a particular PETSc
212: component (e.g., SNES) should generally call the registration routine
213: for that particular component (e.g., SNESRegister()) instead of
214: calling PetscFunctionListAdd() directly.
216: Level: developer
218: .seealso: PetscFunctionListDestroy(), SNESRegister(), KSPRegister(),
219: PCRegister(), TSRegister(), PetscFunctionList, PetscObjectComposeFunction()
220: M*/
221: PETSC_EXTERN PetscErrorCode PetscFunctionListAdd_Private(PetscFunctionList *fl,const char name[],void (*fnc)(void))
222: {
223: PetscFunctionList entry,ne;
225: if (!*fl) {
226: PetscNew(&entry);
227: PetscStrallocpy(name,&entry->name);
228: entry->routine = fnc;
229: entry->next = NULL;
230: *fl = entry;
232: if (PetscDefined(USE_DEBUG)) {
233: /* add this new list to list of all lists */
234: if (!dlallhead) {
235: dlallhead = *fl;
236: (*fl)->next_list = NULL;
237: } else {
238: ne = dlallhead;
239: dlallhead = *fl;
240: (*fl)->next_list = ne;
241: }
242: }
244: } else {
245: /* search list to see if it is already there */
246: ne = *fl;
247: while (ne) {
248: PetscBool founddup;
250: PetscStrcmp(ne->name,name,&founddup);
251: if (founddup) { /* found duplicate */
252: ne->routine = fnc;
253: return 0;
254: }
255: if (ne->next) ne = ne->next;
256: else break;
257: }
258: /* create new entry and add to end of list */
259: PetscNew(&entry);
260: PetscStrallocpy(name,&entry->name);
261: entry->routine = fnc;
262: entry->next = NULL;
263: ne->next = entry;
264: }
265: return 0;
266: }
268: /*@
269: PetscFunctionListDestroy - Destroys a list of registered routines.
271: Input Parameter:
272: . fl - pointer to list
274: Level: developer
276: .seealso: PetscFunctionListAdd(), PetscFunctionList
277: @*/
278: PetscErrorCode PetscFunctionListDestroy(PetscFunctionList *fl)
279: {
280: PetscFunctionList next,entry,tmp = dlallhead;
282: if (!*fl) return 0;
284: /*
285: Remove this entry from the main DL list (if it is in it)
286: */
287: if (dlallhead == *fl) {
288: if (dlallhead->next_list) dlallhead = dlallhead->next_list;
289: else dlallhead = NULL;
290: } else if (tmp) {
291: while (tmp->next_list != *fl) {
292: tmp = tmp->next_list;
293: if (!tmp->next_list) break;
294: }
295: if (tmp->next_list) tmp->next_list = tmp->next_list->next_list;
296: }
298: /* free this list */
299: entry = *fl;
300: while (entry) {
301: next = entry->next;
302: PetscFree(entry->name);
303: PetscFree(entry);
304: entry = next;
305: }
306: *fl = NULL;
307: return 0;
308: }
310: /*
311: Print any PetscFunctionLists that have not be destroyed
312: */
313: PetscErrorCode PetscFunctionListPrintAll(void)
314: {
315: PetscFunctionList tmp = dlallhead;
317: if (tmp) {
318: PetscPrintf(PETSC_COMM_WORLD,"The following PetscFunctionLists were not destroyed\n");
319: }
320: while (tmp) {
321: PetscPrintf(PETSC_COMM_WORLD,"%s \n",tmp->name);
322: tmp = tmp->next_list;
323: }
324: return 0;
325: }
327: /*MC
328: PetscFunctionListFind - Find function registered under given name
330: Synopsis:
331: #include <petscsys.h>
332: PetscErrorCode PetscFunctionListFind(PetscFunctionList flist,const char name[],void (**fptr)(void))
334: Input Parameters:
335: + flist - pointer to list
336: - name - name registered for the function
338: Output Parameters:
339: . fptr - the function pointer if name was found, else NULL
341: Level: developer
343: .seealso: PetscFunctionListAdd(), PetscFunctionList, PetscObjectQueryFunction()
344: M*/
345: PETSC_EXTERN PetscErrorCode PetscFunctionListFind_Private(PetscFunctionList fl,const char name[],void (**r)(void))
346: {
347: PetscFunctionList entry = fl;
348: PetscBool flg;
352: *r = NULL;
353: while (entry) {
354: PetscStrcmp(name,entry->name,&flg);
355: if (flg) {
356: *r = entry->routine;
357: return 0;
358: }
359: entry = entry->next;
360: }
361: return 0;
362: }
364: /*@
365: PetscFunctionListView - prints out contents of an PetscFunctionList
367: Collective over MPI_Comm
369: Input Parameters:
370: + list - the list of functions
371: - viewer - currently ignored
373: Level: developer
375: .seealso: PetscFunctionListAdd(), PetscFunctionListPrintTypes(), PetscFunctionList
376: @*/
377: PetscErrorCode PetscFunctionListView(PetscFunctionList list,PetscViewer viewer)
378: {
379: PetscBool iascii;
381: if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;
385: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
388: while (list) {
389: PetscViewerASCIIPrintf(viewer," %s\n",list->name);
390: list = list->next;
391: }
392: PetscViewerASCIIPrintf(viewer,"\n");
393: return 0;
394: }
396: /*@C
397: PetscFunctionListGet - Gets an array the contains the entries in PetscFunctionList, this is used
398: by help etc.
400: Not Collective
402: Input Parameter:
403: . list - list of types
405: Output Parameters:
406: + array - array of names
407: - n - length of array
409: Notes:
410: This allocates the array so that must be freed. BUT the individual entries are
411: not copied so should not be freed.
413: Level: developer
415: .seealso: PetscFunctionListAdd(), PetscFunctionList
416: @*/
417: PetscErrorCode PetscFunctionListGet(PetscFunctionList list,const char ***array,int *n)
418: {
419: PetscInt count = 0;
420: PetscFunctionList klist = list;
422: while (list) {
423: list = list->next;
424: count++;
425: }
426: PetscMalloc1(count+1,(char***)array);
427: count = 0;
428: while (klist) {
429: (*array)[count] = klist->name;
430: klist = klist->next;
431: count++;
432: }
433: (*array)[count] = NULL;
434: *n = count+1;
435: return 0;
436: }
438: /*@C
439: PetscFunctionListPrintTypes - Prints the methods available.
441: Collective over MPI_Comm
443: Input Parameters:
444: + comm - the communicator (usually MPI_COMM_WORLD)
445: . fd - file to print to, usually stdout
446: . prefix - prefix to prepend to name (optional)
447: . name - option string (for example, "-ksp_type")
448: . text - short description of the object (for example, "Krylov solvers")
449: . man - name of manual page that discusses the object (for example, "KSPCreate")
450: . list - list of types
451: . def - default (current) value
452: - newv - new value
454: Level: developer
456: .seealso: PetscFunctionListAdd(), PetscFunctionList
457: @*/
458: 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[])
459: {
460: char p[64];
462: if (!fd) fd = PETSC_STDOUT;
464: PetscStrncpy(p,"-",sizeof(p));
465: if (prefix) PetscStrlcat(p,prefix,sizeof(p));
466: PetscFPrintf(comm,fd," %s%s <now %s : formerly %s>: %s (one of)",p,name+1,newv,def,text);
468: while (list) {
469: PetscFPrintf(comm,fd," %s",list->name);
470: list = list->next;
471: }
472: PetscFPrintf(comm,fd," (%s)\n",man);
473: return 0;
474: }
476: /*@
477: PetscFunctionListDuplicate - Creates a new list from a given object list.
479: Input Parameters:
480: . fl - pointer to list
482: Output Parameters:
483: . nl - the new list (should point to 0 to start, otherwise appends)
485: Level: developer
487: .seealso: PetscFunctionList, PetscFunctionListAdd(), PetscFlistDestroy()
489: @*/
490: PetscErrorCode PetscFunctionListDuplicate(PetscFunctionList fl,PetscFunctionList *nl)
491: {
492: while (fl) {
493: PetscFunctionListAdd(nl,fl->name,fl->routine);
494: fl = fl->next;
495: }
496: return 0;
497: }