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];
22: PetscStrncpy(libs,"${PETSC_LIB_DIR}/libpetsc",sizeof(libs));
23: PetscStrlcat(libs,name,sizeof(libs));
24: PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,found);
25: if (*found) {
26: PetscDLLibraryAppend(PETSC_COMM_WORLD,&PetscDLLibrariesLoaded,dlib);
27: } else {
28: PetscStrncpy(libs,"${PETSC_DIR}/${PETSC_ARCH}/lib/libpetsc",sizeof(libs));
29: PetscStrlcat(libs,name,sizeof(libs));
30: PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,found);
31: if (*found) {
32: PetscDLLibraryAppend(PETSC_COMM_WORLD,&PetscDLLibrariesLoaded,dlib);
33: }
34: }
35: return(0);
36: }
37: #endif
39: #if defined(PETSC_USE_SINGLE_LIBRARY) && !(defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES))
40: PETSC_EXTERN PetscErrorCode AOInitializePackage(void);
41: PETSC_EXTERN PetscErrorCode PetscSFInitializePackage(void);
42: #if !defined(PETSC_USE_COMPLEX)
43: PETSC_EXTERN PetscErrorCode CharacteristicInitializePackage(void);
44: #endif
45: PETSC_EXTERN PetscErrorCode ISInitializePackage(void);
46: PETSC_EXTERN PetscErrorCode VecInitializePackage(void);
47: PETSC_EXTERN PetscErrorCode MatInitializePackage(void);
48: PETSC_EXTERN PetscErrorCode DMInitializePackage(void);
49: PETSC_EXTERN PetscErrorCode PCInitializePackage(void);
50: PETSC_EXTERN PetscErrorCode KSPInitializePackage(void);
51: PETSC_EXTERN PetscErrorCode SNESInitializePackage(void);
52: PETSC_EXTERN PetscErrorCode TSInitializePackage(void);
53: PETSC_EXTERN PetscErrorCode TaoInitializePackage(void);
54: #endif
55: #if defined(PETSC_HAVE_THREADSAFETY)
56: static MPI_Comm PETSC_COMM_WORLD_INNER = 0,PETSC_COMM_SELF_INNER = 0;
57: #endif
59: /*
60: PetscInitialize_DynamicLibraries - Adds the default dynamic link libraries to the
61: search path.
62: */
63: PETSC_INTERN PetscErrorCode PetscInitialize_DynamicLibraries(void)
64: {
65: char *libname[32];
67: PetscInt nmax,i;
68: PetscBool preload = PETSC_FALSE;
69: #if defined(PETSC_HAVE_ELEMENTAL)
70: PetscBool PetscInitialized = PetscInitializeCalled;
71: #endif
74: #if defined(PETSC_HAVE_THREADSAFETY)
75: /* These must be all initialized here because it is not safe for individual threads to call these initialize routines */
76: preload = PETSC_TRUE;
77: #endif
79: nmax = 32;
80: PetscOptionsGetStringArray(NULL,NULL,"-dll_prepend",libname,&nmax,NULL);
81: for (i=0; i<nmax; i++) {
82: PetscDLLibraryPrepend(PETSC_COMM_WORLD,&PetscDLLibrariesLoaded,libname[i]);
83: PetscFree(libname[i]);
84: }
86: PetscOptionsGetBool(NULL,NULL,"-library_preload",&preload,NULL);
87: if (!preload) {
88: PetscSysInitializePackage();
89: } else {
90: #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES)
91: PetscBool found;
92: #if defined(PETSC_USE_SINGLE_LIBRARY)
93: PetscLoadDynamicLibrary("",&found);
94: if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc dynamic library \n You cannot move the dynamic libraries!");
95: #else
96: PetscLoadDynamicLibrary("sys",&found);
97: if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc dynamic library \n You cannot move the dynamic libraries!");
98: PetscLoadDynamicLibrary("vec",&found);
99: if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc Vec dynamic library \n You cannot move the dynamic libraries!");
100: PetscLoadDynamicLibrary("mat",&found);
101: if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc Mat dynamic library \n You cannot move the dynamic libraries!");
102: PetscLoadDynamicLibrary("dm",&found);
103: if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc DM dynamic library \n You cannot move the dynamic libraries!");
104: PetscLoadDynamicLibrary("ksp",&found);
105: if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc KSP dynamic library \n You cannot move the dynamic libraries!");
106: PetscLoadDynamicLibrary("snes",&found);
107: if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc SNES dynamic library \n You cannot move the dynamic libraries!");
108: PetscLoadDynamicLibrary("ts",&found);
109: if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc TS dynamic library \n You cannot move the dynamic libraries!");
110: PetscLoadDynamicLibrary("tao",&found);
111: if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate Tao dynamic library \n You cannot move the dynamic libraries!");
112: #endif
113: #else /* defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES) */
114: #if defined(PETSC_USE_SINGLE_LIBRARY)
115: AOInitializePackage();
116: PetscSFInitializePackage();
117: #if !defined(PETSC_USE_COMPLEX)
118: CharacteristicInitializePackage();
119: #endif
120: ISInitializePackage();
121: VecInitializePackage();
122: MatInitializePackage();
123: DMInitializePackage();
124: PCInitializePackage();
125: KSPInitializePackage();
126: SNESInitializePackage();
127: TSInitializePackage();
128: TaoInitializePackage();
129: #else
130: SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"Cannot use -library_preload with multiple static PETSc libraries");
131: #endif
132: #endif /* defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES) */
133: }
135: #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES) && defined(PETSC_HAVE_BAMG)
136: {
137: PetscBool found;
138: PetscLoadDynamicLibrary("bamg",&found);
139: if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc BAMG dynamic library \n You cannot move the dynamic libraries!");
140: }
141: #endif
143: nmax = 32;
144: PetscOptionsGetStringArray(NULL,NULL,"-dll_append",libname,&nmax,NULL);
145: for (i=0; i<nmax; i++) {
146: PetscDLLibraryAppend(PETSC_COMM_WORLD,&PetscDLLibrariesLoaded,libname[i]);
147: PetscFree(libname[i]);
148: }
150: #if defined(PETSC_HAVE_THREADSAFETY)
151: PetscCommDuplicate(PETSC_COMM_SELF,&PETSC_COMM_SELF_INNER,NULL);
152: PetscCommDuplicate(PETSC_COMM_WORLD,&PETSC_COMM_WORLD_INNER,NULL);
153: #endif
154: #if defined(PETSC_HAVE_ELEMENTAL)
155: /* in Fortran, PetscInitializeCalled is set to PETSC_TRUE before PetscInitialize_DynamicLibraries() */
156: /* in C, it is not the case, but the value is forced to PETSC_TRUE so that PetscRegisterFinalize() is called */
157: PetscInitializeCalled = PETSC_TRUE;
158: PetscElementalInitializePackage();
159: PetscInitializeCalled = PetscInitialized;
160: #endif
161: return(0);
162: }
164: /*
165: PetscFinalize_DynamicLibraries - Closes the opened dynamic libraries.
166: */
167: PETSC_INTERN PetscErrorCode PetscFinalize_DynamicLibraries(void)
168: {
170: PetscBool flg = PETSC_FALSE;
173: PetscOptionsGetBool(NULL,NULL,"-dll_view",&flg,NULL);
174: if (flg) { PetscDLLibraryPrintPath(PetscDLLibrariesLoaded); }
175: PetscDLLibraryClose(PetscDLLibrariesLoaded);
177: #if defined(PETSC_HAVE_THREADSAFETY)
178: PetscCommDestroy(&PETSC_COMM_SELF_INNER);
179: PetscCommDestroy(&PETSC_COMM_WORLD_INNER);
180: #endif
182: PetscDLLibrariesLoaded = NULL;
183: return(0);
184: }
186: /* ------------------------------------------------------------------------------*/
187: struct _n_PetscFunctionList {
188: void (*routine)(void); /* the routine */
189: char *name; /* string to identify routine */
190: PetscFunctionList next; /* next pointer */
191: PetscFunctionList next_list; /* used to maintain list of all lists for freeing */
192: };
194: /*
195: Keep a linked list of PetscFunctionLists so that we can destroy all the left-over ones.
196: */
197: static PetscFunctionList dlallhead = NULL;
199: /*MC
200: PetscFunctionListAdd - Given a routine and a string id, saves that routine in the
201: specified registry.
203: Synopsis:
204: #include <petscsys.h>
205: PetscErrorCode PetscFunctionListAdd(PetscFunctionList *flist,const char name[],void (*fptr)(void))
207: Not Collective
209: Input Parameters:
210: + flist - pointer to function list object
211: . name - string to identify routine
212: - fptr - function pointer
214: Notes:
215: To remove a registered routine, pass in a NULL fptr.
217: Users who wish to register new classes for use by a particular PETSc
218: component (e.g., SNES) should generally call the registration routine
219: for that particular component (e.g., SNESRegister()) instead of
220: calling PetscFunctionListAdd() directly.
222: Level: developer
224: .seealso: PetscFunctionListDestroy(), SNESRegister(), KSPRegister(),
225: PCRegister(), TSRegister(), PetscFunctionList, PetscObjectComposeFunction()
226: M*/
227: PETSC_EXTERN PetscErrorCode PetscFunctionListAdd_Private(PetscFunctionList *fl,const char name[],void (*fnc)(void))
228: {
229: PetscFunctionList entry,ne;
230: PetscErrorCode ierr;
233: if (!*fl) {
234: PetscNew(&entry);
235: PetscStrallocpy(name,&entry->name);
236: entry->routine = fnc;
237: entry->next = NULL;
238: *fl = entry;
240: if (PetscDefined(USE_DEBUG)) {
241: /* add this new list to list of all lists */
242: if (!dlallhead) {
243: dlallhead = *fl;
244: (*fl)->next_list = NULL;
245: } else {
246: ne = dlallhead;
247: dlallhead = *fl;
248: (*fl)->next_list = ne;
249: }
250: }
252: } else {
253: /* search list to see if it is already there */
254: ne = *fl;
255: while (ne) {
256: PetscBool founddup;
258: PetscStrcmp(ne->name,name,&founddup);
259: if (founddup) { /* found duplicate */
260: ne->routine = fnc;
261: return(0);
262: }
263: if (ne->next) ne = ne->next;
264: else break;
265: }
266: /* create new entry and add to end of list */
267: PetscNew(&entry);
268: PetscStrallocpy(name,&entry->name);
269: entry->routine = fnc;
270: entry->next = NULL;
271: ne->next = entry;
272: }
273: return(0);
274: }
276: /*@
277: PetscFunctionListDestroy - Destroys a list of registered routines.
279: Input Parameter:
280: . fl - pointer to list
282: Level: developer
284: .seealso: PetscFunctionListAdd(), PetscFunctionList
285: @*/
286: PetscErrorCode PetscFunctionListDestroy(PetscFunctionList *fl)
287: {
288: PetscFunctionList next,entry,tmp = dlallhead;
289: PetscErrorCode ierr;
292: if (!*fl) return(0);
294: /*
295: Remove this entry from the main DL list (if it is in it)
296: */
297: if (dlallhead == *fl) {
298: if (dlallhead->next_list) dlallhead = dlallhead->next_list;
299: else dlallhead = NULL;
300: } else if (tmp) {
301: while (tmp->next_list != *fl) {
302: tmp = tmp->next_list;
303: if (!tmp->next_list) break;
304: }
305: if (tmp->next_list) tmp->next_list = tmp->next_list->next_list;
306: }
308: /* free this list */
309: entry = *fl;
310: while (entry) {
311: next = entry->next;
312: PetscFree(entry->name);
313: PetscFree(entry);
314: entry = next;
315: }
316: *fl = NULL;
317: return(0);
318: }
320: /*
321: Print any PetscFunctionLists that have not be destroyed
322: */
323: PetscErrorCode PetscFunctionListPrintAll(void)
324: {
325: PetscFunctionList tmp = dlallhead;
326: PetscErrorCode ierr;
329: if (tmp) {
330: PetscPrintf(PETSC_COMM_WORLD,"The following PetscFunctionLists were not destroyed\n");
331: }
332: while (tmp) {
333: PetscPrintf(PETSC_COMM_WORLD,"%s \n",tmp->name);
334: tmp = tmp->next_list;
335: }
336: return(0);
337: }
339: /*MC
340: PetscFunctionListFind - Find function registered under given name
342: Synopsis:
343: #include <petscsys.h>
344: PetscErrorCode PetscFunctionListFind(PetscFunctionList flist,const char name[],void (**fptr)(void))
346: Input Parameters:
347: + flist - pointer to list
348: - name - name registered for the function
350: Output Parameters:
351: . fptr - the function pointer if name was found, else NULL
353: Level: developer
355: .seealso: PetscFunctionListAdd(), PetscFunctionList, PetscObjectQueryFunction()
356: M*/
357: PETSC_EXTERN PetscErrorCode PetscFunctionListFind_Private(PetscFunctionList fl,const char name[],void (**r)(void))
358: {
359: PetscFunctionList entry = fl;
360: PetscErrorCode ierr;
361: PetscBool flg;
364: if (!name) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Trying to find routine with null name");
366: *r = NULL;
367: while (entry) {
368: PetscStrcmp(name,entry->name,&flg);
369: if (flg) {
370: *r = entry->routine;
371: return(0);
372: }
373: entry = entry->next;
374: }
375: return(0);
376: }
378: /*@
379: PetscFunctionListView - prints out contents of an PetscFunctionList
381: Collective over MPI_Comm
383: Input Parameters:
384: + list - the list of functions
385: - viewer - currently ignored
387: Level: developer
389: .seealso: PetscFunctionListAdd(), PetscFunctionListPrintTypes(), PetscFunctionList
390: @*/
391: PetscErrorCode PetscFunctionListView(PetscFunctionList list,PetscViewer viewer)
392: {
394: PetscBool iascii;
397: if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;
401: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
402: if (!iascii) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only ASCII viewer supported");
404: while (list) {
405: PetscViewerASCIIPrintf(viewer," %s\n",list->name);
406: list = list->next;
407: }
408: PetscViewerASCIIPrintf(viewer,"\n");
409: return(0);
410: }
412: /*@C
413: PetscFunctionListGet - Gets an array the contains the entries in PetscFunctionList, this is used
414: by help etc.
416: Not Collective
418: Input Parameter:
419: . list - list of types
421: Output Parameters:
422: + array - array of names
423: - n - length of array
425: Notes:
426: This allocates the array so that must be freed. BUT the individual entries are
427: not copied so should not be freed.
429: Level: developer
431: .seealso: PetscFunctionListAdd(), PetscFunctionList
432: @*/
433: PetscErrorCode PetscFunctionListGet(PetscFunctionList list,const char ***array,int *n)
434: {
435: PetscErrorCode ierr;
436: PetscInt count = 0;
437: PetscFunctionList klist = list;
440: while (list) {
441: list = list->next;
442: count++;
443: }
444: PetscMalloc1(count+1,(char***)array);
445: count = 0;
446: while (klist) {
447: (*array)[count] = klist->name;
448: klist = klist->next;
449: count++;
450: }
451: (*array)[count] = NULL;
452: *n = count+1;
453: return(0);
454: }
456: /*@C
457: PetscFunctionListPrintTypes - Prints the methods available.
459: Collective over MPI_Comm
461: Input Parameters:
462: + comm - the communicator (usually MPI_COMM_WORLD)
463: . fd - file to print to, usually stdout
464: . prefix - prefix to prepend to name (optional)
465: . name - option string (for example, "-ksp_type")
466: . text - short description of the object (for example, "Krylov solvers")
467: . man - name of manual page that discusses the object (for example, "KSPCreate")
468: . list - list of types
469: . def - default (current) value
470: - newv - new value
472: Level: developer
474: .seealso: PetscFunctionListAdd(), PetscFunctionList
475: @*/
476: 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[])
477: {
479: char p[64];
482: if (!fd) fd = PETSC_STDOUT;
484: PetscStrncpy(p,"-",sizeof(p));
485: if (prefix) {PetscStrlcat(p,prefix,sizeof(p));}
486: PetscFPrintf(comm,fd," %s%s <now %s : formerly %s>: %s (one of)",p,name+1,newv,def,text);
488: while (list) {
489: PetscFPrintf(comm,fd," %s",list->name);
490: list = list->next;
491: }
492: PetscFPrintf(comm,fd," (%s)\n",man);
493: return(0);
494: }
496: /*@
497: PetscFunctionListDuplicate - Creates a new list from a given object list.
499: Input Parameters:
500: . fl - pointer to list
502: Output Parameters:
503: . nl - the new list (should point to 0 to start, otherwise appends)
505: Level: developer
507: .seealso: PetscFunctionList, PetscFunctionListAdd(), PetscFlistDestroy()
509: @*/
510: PetscErrorCode PetscFunctionListDuplicate(PetscFunctionList fl,PetscFunctionList *nl)
511: {
515: while (fl) {
516: PetscFunctionListAdd(nl,fl->name,fl->routine);
517: fl = fl->next;
518: }
519: return(0);
520: }