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 <petscsys.h> /*I "petscsys.h" I*/
10: PetscErrorCode PetscFListGetPathAndFunction(const char name[],char *path[],char *function[])
11: {
13: char work[PETSC_MAX_PATH_LEN],*lfunction;
16: PetscStrncpy(work,name,sizeof work);
17: work[sizeof work - 1] = 0;
18: PetscStrchr(work,':',&lfunction);
19: if (lfunction != work && lfunction && lfunction[1] != ':') {
20: lfunction[0] = 0;
21: PetscStrallocpy(work,path);
22: PetscStrallocpy(lfunction+1,function);
23: } else {
24: *path = 0;
25: PetscStrallocpy(name,function);
26: }
27: return(0);
28: }
30: /*
31: This is the default list used by PETSc with the PetscDLLibrary register routines
32: */
33: PetscDLLibrary DLLibrariesLoaded = 0;
35: #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
39: static PetscErrorCode PetscLoadDynamicLibrary(const char *name,PetscBool *found)
40: {
41: char libs[PETSC_MAX_PATH_LEN],dlib[PETSC_MAX_PATH_LEN];
45: PetscStrcpy(libs,"${PETSC_LIB_DIR}/libpetsc");
46: PetscStrcat(libs,name);
47: PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,found);
48: if (*found) {
49: PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,dlib);
50: } else {
51: PetscStrcpy(libs,"${PETSC_DIR}/${PETSC_ARCH}/lib/libpetsc");
52: PetscStrcat(libs,name);
53: PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,found);
54: if (*found) {
55: PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,dlib);
56: }
57: }
58: return(0);
59: }
61: #endif
65: /*
66: PetscInitialize_DynamicLibraries - Adds the default dynamic link libraries to the
67: search path.
68: */
69: PetscErrorCode PetscInitialize_DynamicLibraries(void)
70: {
71: char *libname[32];
73: PetscInt nmax,i;
74: #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
75: PetscBool found;
76: #endif
79: nmax = 32;
80: PetscOptionsGetStringArray(PETSC_NULL,"-dll_prepend",libname,&nmax,PETSC_NULL);
81: for (i=0; i<nmax; i++) {
82: PetscDLLibraryPrepend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libname[i]);
83: PetscFree(libname[i]);
84: }
86: #if !defined(PETSC_USE_DYNAMIC_LIBRARIES)
87: /*
88: This just initializes the most basic PETSc stuff.
90: The classes, from PetscDraw to PetscTS, are initialized the first
91: time an XXCreate() is called.
92: */
93: PetscSysInitializePackage(PETSC_NULL);
94: #else
95: #if defined(PETSC_USE_SINGLE_LIBRARY)
96: PetscLoadDynamicLibrary("",&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: #else
99: PetscLoadDynamicLibrary("sys",&found);
100: if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc dynamic library \n You cannot move the dynamic libraries!");
101: PetscLoadDynamicLibrary("vec",&found);
102: if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc Vec dynamic library \n You cannot move the dynamic libraries!");
103: PetscLoadDynamicLibrary("mat",&found);
104: if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc Mat dynamic library \n You cannot move the dynamic libraries!");
105: PetscLoadDynamicLibrary("dm",&found);
106: if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc DM dynamic library \n You cannot move the dynamic libraries!");
107: PetscLoadDynamicLibrary("characteristic",&found);
108: if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc Characteristic dynamic library \n You cannot move the dynamic libraries!");
109: PetscLoadDynamicLibrary("ksp",&found);
110: if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc KSP dynamic library \n You cannot move the dynamic libraries!");
111: PetscLoadDynamicLibrary("snes",&found);
112: if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc SNES dynamic library \n You cannot move the dynamic libraries!");
113: PetscLoadDynamicLibrary("ts",&found);
114: if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc TS dynamic library \n You cannot move the dynamic libraries!");
115: #endif
117: PetscLoadDynamicLibrary("mesh",&found);
118: PetscLoadDynamicLibrary("contrib",&found);
119: #endif
121: nmax = 32;
122: PetscOptionsGetStringArray(PETSC_NULL,"-dll_append",libname,&nmax,PETSC_NULL);
123: for (i=0; i<nmax; i++) {
124: PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libname[i]);
125: PetscDLLibraryCCAAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libname[i]);
126: PetscFree(libname[i]);
127: }
129: return(0);
130: }
134: /*
135: PetscFinalize_DynamicLibraries - Closes the opened dynamic libraries.
136: */
137: PetscErrorCode PetscFinalize_DynamicLibraries(void)
138: {
140: PetscBool flg = PETSC_FALSE;
143: PetscOptionsGetBool(PETSC_NULL,"-dll_view",&flg,PETSC_NULL);
144: if (flg) { PetscDLLibraryPrintPath(DLLibrariesLoaded); }
145: PetscDLLibraryClose(DLLibrariesLoaded);
146: DLLibrariesLoaded = 0;
147: return(0);
148: }
150: /* ------------------------------------------------------------------------------*/
151: struct _n_PetscFList {
152: void (*routine)(void); /* the routine */
153: char *path; /* path of link library containing routine */
154: char *name; /* string to identify routine */
155: char *rname; /* routine name in dynamic library */
156: PetscFList next; /* next pointer */
157: PetscFList next_list; /* used to maintain list of all lists for freeing */
158: };
160: /*
161: Keep a linked list of PetscFLists so that we can destroy all the left-over ones.
162: */
163: static PetscFList dlallhead = 0;
167: /*@C
168: PetscFListAddDynamic - Given a routine and a string id, saves that routine in the
169: specified registry.
171: Not Collective
173: Input Parameters:
174: + fl - pointer registry
175: . name - string to identify routine
176: . rname - routine name in dynamic library
177: - fnc - function pointer (optional if using dynamic libraries)
179: Notes:
180: To remove a registered routine, pass in a PETSC_NULL rname and fnc().
182: Users who wish to register new classes for use by a particular PETSc
183: component (e.g., SNES) should generally call the registration routine
184: for that particular component (e.g., SNESRegisterDynamic()) instead of
185: calling PetscFListAddDynamic() directly.
187: ${PETSC_ARCH}, ${PETSC_DIR}, ${PETSC_LIB_DIR}, or ${any environmental variable}
188: occuring in pathname will be replaced with appropriate values.
190: Level: developer
192: .seealso: PetscFListDestroy(), SNESRegisterDynamic(), KSPRegisterDynamic(),
193: PCRegisterDynamic(), TSRegisterDynamic(), PetscFList
194: @*/
195: PetscErrorCode PetscFListAdd(PetscFList *fl,const char name[],const char rname[],void (*fnc)(void))
196: {
197: PetscFList entry,ne;
199: char *fpath,*fname;
202: if (!*fl) {
203: PetscNew(struct _n_PetscFList,&entry);
204: PetscStrallocpy(name,&entry->name);
205: PetscFListGetPathAndFunction(rname,&fpath,&fname);
206: entry->path = fpath;
207: entry->rname = fname;
208: entry->routine = fnc;
209: entry->next = 0;
210: *fl = entry;
212: /* add this new list to list of all lists */
213: if (!dlallhead) {
214: dlallhead = *fl;
215: (*fl)->next_list = 0;
216: } else {
217: ne = dlallhead;
218: dlallhead = *fl;
219: (*fl)->next_list = ne;
220: }
221: } else {
222: /* search list to see if it is already there */
223: ne = *fl;
224: while (ne) {
225: PetscBool founddup;
227: PetscStrcmp(ne->name,name,&founddup);
228: if (founddup) { /* found duplicate */
229: PetscFListGetPathAndFunction(rname,&fpath,&fname);
230: PetscFree(ne->path);
231: PetscFree(ne->rname);
232: ne->path = fpath;
233: ne->rname = fname;
234: ne->routine = fnc;
235: return(0);
236: }
237: if (ne->next) ne = ne->next; else break;
238: }
239: /* create new entry and add to end of list */
240: PetscNew(struct _n_PetscFList,&entry);
241: PetscStrallocpy(name,&entry->name);
242: PetscFListGetPathAndFunction(rname,&fpath,&fname);
243: entry->path = fpath;
244: entry->rname = fname;
245: entry->routine = fnc;
246: entry->next = 0;
247: ne->next = entry;
248: }
249: return(0);
250: }
254: /*@
255: PetscFListDestroy - Destroys a list of registered routines.
257: Input Parameter:
258: . fl - pointer to list
260: Level: developer
262: .seealso: PetscFListAddDynamic(), PetscFList
263: @*/
264: PetscErrorCode PetscFListDestroy(PetscFList *fl)
265: {
266: PetscFList next,entry,tmp = dlallhead;
270: if (!*fl) return(0);
271: if (!dlallhead) return(0);
273: /*
274: Remove this entry from the master DL list (if it is in it)
275: */
276: if (dlallhead == *fl) {
277: if (dlallhead->next_list) {
278: dlallhead = dlallhead->next_list;
279: } else {
280: dlallhead = 0;
281: }
282: } else {
283: while (tmp->next_list != *fl) {
284: tmp = tmp->next_list;
285: if (!tmp->next_list) break;
286: }
287: if (tmp->next_list) tmp->next_list = tmp->next_list->next_list;
288: }
290: /* free this list */
291: entry = *fl;
292: while (entry) {
293: next = entry->next;
294: PetscFree(entry->path);
295: PetscFree(entry->name);
296: PetscFree(entry->rname);
297: PetscFree(entry);
298: entry = next;
299: }
300: *fl = 0;
301: return(0);
302: }
304: /*
305: Destroys all the function lists that anyone has every registered, such as KSPList, VecList, etc.
306: */
309: PetscErrorCode PetscFListDestroyAll(void)
310: {
311: PetscFList tmp2,tmp1 = dlallhead;
315: while (tmp1) {
316: tmp2 = tmp1->next_list;
317: PetscFListDestroy(&tmp1);
318: tmp1 = tmp2;
319: }
320: dlallhead = 0;
321: return(0);
322: }
326: /*@C
327: PetscFListFind - Given a name, finds the matching routine.
329: Input Parameters:
330: + fl - pointer to list
331: . comm - processors looking for routine
332: . name - name string
333: - searchlibraries - if not found in the list then search the dynamic libraries and executable for the symbol
335: Output Parameters:
336: . r - the routine
338: Level: developer
340: .seealso: PetscFListAddDynamic(), PetscFList
341: @*/
342: PetscErrorCode PetscFListFind(PetscFList fl,MPI_Comm comm,const char name[],PetscBool searchlibraries,void (**r)(void))
343: {
344: PetscFList entry = fl;
346: char *function,*path;
347: PetscBool flg,f1,f2,f3;
348: #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES)
349: char *newpath;
350: #endif
351:
353: if (!name) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Trying to find routine with null name");
355: *r = 0;
356: PetscFListGetPathAndFunction(name,&path,&function);
358: /*
359: If path then append it to search libraries
360: */
361: #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES)
362: if (path) {
363: PetscDLLibraryAppend(comm,&DLLibrariesLoaded,path);
364: }
365: #endif
367: while (entry) {
368: flg = PETSC_FALSE;
369: if (path && entry->path) {
370: PetscStrcmp(path,entry->path,&f1);
371: PetscStrcmp(function,entry->rname,&f2);
372: PetscStrcmp(function,entry->name,&f3);
373: flg = (PetscBool) ((f1 && f2) || (f1 && f3));
374: } else if (!path) {
375: PetscStrcmp(function,entry->name,&f1);
376: PetscStrcmp(function,entry->rname,&f2);
377: flg = (PetscBool) (f1 || f2);
378: } else {
379: PetscStrcmp(function,entry->name,&flg);
380: if (flg) {
381: PetscFree(function);
382: PetscStrallocpy(entry->rname,&function);
383: } else {
384: PetscStrcmp(function,entry->rname,&flg);
385: }
386: }
388: if (flg) {
389: if (entry->routine) {
390: *r = entry->routine;
391: PetscFree(path);
392: PetscFree(function);
393: return(0);
394: }
395: if (!(entry->rname && entry->rname[0])) { /* The entry has been cleared */
396: PetscFree(function);
397: return(0);
398: }
399: if ((path && entry->path && f3) || (!path && f1)) { /* convert name of function (alias) to actual function name */
400: PetscFree(function);
401: PetscStrallocpy(entry->rname,&function);
402: }
404: /* it is not yet in memory so load from dynamic library */
405: #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES)
406: newpath = path;
407: if (!path) newpath = entry->path;
408: PetscDLLibrarySym(comm,&DLLibrariesLoaded,newpath,entry->rname,(void **)r);
409: if (*r) {
410: entry->routine = *r;
411: PetscFree(path);
412: PetscFree(function);
413: return(0);
414: }
415: #endif
416: }
417: entry = entry->next;
418: }
420: #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES)
421: if (searchlibraries) {
422: /* Function never registered; try for it anyway */
423: PetscDLLibrarySym(comm,&DLLibrariesLoaded,path,function,(void **)r);
424: PetscFree(path);
425: if (*r) {
426: PetscFListAdd(&fl,name,name,*r);
427: }
428: }
429: #endif
430: PetscFree(function);
431: return(0);
432: }
436: /*@
437: PetscFListView - prints out contents of an PetscFList
439: Collective over MPI_Comm
441: Input Parameters:
442: + list - the list of functions
443: - viewer - currently ignored
445: Level: developer
447: .seealso: PetscFListAddDynamic(), PetscFListPrintTypes(), PetscFList
448: @*/
449: PetscErrorCode PetscFListView(PetscFList list,PetscViewer viewer)
450: {
452: PetscBool iascii;
455: if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;
458:
459: PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
460: if (!iascii) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only ASCII viewer supported");
462: while (list) {
463: if (list->path) {
464: PetscViewerASCIIPrintf(viewer," %s %s %s\n",list->path,list->name,list->rname);
465: } else {
466: PetscViewerASCIIPrintf(viewer," %s %s\n",list->name,list->rname);
467: }
468: list = list->next;
469: }
470: PetscViewerASCIIPrintf(viewer,"\n");
471: return(0);
472: }
476: /*@
477: PetscFListGet - Gets an array the contains the entries in PetscFList, this is used
478: by help etc.
480: Collective over MPI_Comm
482: Input Parameter:
483: . list - list of types
485: Output Parameter:
486: + array - array of names
487: - n - length of array
489: Notes:
490: This allocates the array so that must be freed. BUT the individual entries are
491: not copied so should not be freed.
493: Level: developer
495: .seealso: PetscFListAddDynamic(), PetscFList
496: @*/
497: PetscErrorCode PetscFListGet(PetscFList list,char ***array,int *n)
498: {
500: PetscInt count = 0;
501: PetscFList klist = list;
504: while (list) {
505: list = list->next;
506: count++;
507: }
508: PetscMalloc((count+1)*sizeof(char *),array);
509: count = 0;
510: while (klist) {
511: (*array)[count] = klist->name;
512: klist = klist->next;
513: count++;
514: }
515: (*array)[count] = 0;
516: *n = count+1;
517: return(0);
518: }
523: /*@C
524: PetscFListPrintTypes - Prints the methods available.
526: Collective over MPI_Comm
528: Input Parameters:
529: + comm - the communicator (usually MPI_COMM_WORLD)
530: . fd - file to print to, usually stdout
531: . prefix - prefix to prepend to name (optional)
532: . name - option string (for example, "-ksp_type")
533: . text - short description of the object (for example, "Krylov solvers")
534: . man - name of manual page that discusses the object (for example, "KSPCreate")
535: . list - list of types
536: - def - default (current) value
538: Level: developer
540: .seealso: PetscFListAddDynamic(), PetscFList
541: @*/
542: PetscErrorCode PetscFListPrintTypes(MPI_Comm comm,FILE *fd,const char prefix[],const char name[],const char text[],const char man[],PetscFList list,const char def[])
543: {
545: PetscInt count = 0;
546: char p[64];
549: if (!fd) fd = PETSC_STDOUT;
551: PetscStrcpy(p,"-");
552: if (prefix) {PetscStrcat(p,prefix);}
553: PetscFPrintf(comm,fd," %s%s <%s>: %s (one of)",p,name+1,def,text);
555: while (list) {
556: PetscFPrintf(comm,fd," %s",list->name);
557: list = list->next;
558: count++;
559: if (count == 8) {PetscFPrintf(comm,fd,"\n ");}
560: }
561: PetscFPrintf(comm,fd," (%s)\n",man);
562: return(0);
563: }
567: /*@
568: PetscFListDuplicate - Creates a new list from a given object list.
570: Input Parameters:
571: . fl - pointer to list
573: Output Parameters:
574: . nl - the new list (should point to 0 to start, otherwise appends)
576: Level: developer
578: .seealso: PetscFList, PetscFListAdd(), PetscFlistDestroy()
580: @*/
581: PetscErrorCode PetscFListDuplicate(PetscFList fl,PetscFList *nl)
582: {
584: char path[PETSC_MAX_PATH_LEN];
587: while (fl) {
588: /* this is silly, rebuild the complete pathname */
589: if (fl->path) {
590: PetscStrcpy(path,fl->path);
591: PetscStrcat(path,":");
592: PetscStrcat(path,fl->name);
593: } else {
594: PetscStrcpy(path,fl->name);
595: }
596: PetscFListAdd(nl,path,fl->rname,fl->routine);
597: fl = fl->next;
598: }
599: return(0);
600: }
605: /*
606: PetscFListConcat - joins name of a libary, and the path where it is located
607: into a single string.
609: Input Parameters:
610: . path - path to the library name.
611: . name - name of the library
613: Output Parameters:
614: . fullname - the name that is the union of the path and the library name,
615: delimited by a semicolon, i.e., path:name
617: Notes:
618: If the path is NULL, assumes that the name, specified also includes
619: the path as path:name
621: */
622: PetscErrorCode PetscFListConcat(const char path[],const char name[],char fullname[])
623: {
626: if (path) {
627: PetscStrcpy(fullname,path);
628: PetscStrcat(fullname,":");
629: PetscStrcat(fullname,name);
630: } else {
631: PetscStrcpy(fullname,name);
632: }
633: return(0);
634: }