Actual source code: reg.c
1: /*$Id: reg.c,v 1.77 2001/09/07 20:08:26 bsmith Exp $*/
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.h
7: #include petscsys.h
9: #undef __FUNCT__
11: int PetscFListGetPathAndFunction(const char name[],char *path[],char *function[])
12: {
13: char work[256],*lfunction,ierr;
16: PetscStrncpy(work,name,256);
17: PetscStrchr(work,':',&lfunction);
18: if (lfunction != work && lfunction && lfunction[1] != ':') {
19: lfunction[0] = 0;
20: PetscStrallocpy(work,path);
21: PetscStrallocpy(lfunction+1,function);
22: } else {
23: *path = 0;
24: PetscStrallocpy(name,function);
25: }
26: return(0);
27: }
29: #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
31: /*
32: This is the list used by the DLRegister routines
33: */
34: PetscDLLibraryList DLLibrariesLoaded = 0;
36: #undef __FUNCT__
38: /*
39: PetscInitialize_DynamicLibraries - Adds the default dynamic link libraries to the
40: search path.
41: */
42: int PetscInitialize_DynamicLibraries(void)
43: {
44: char *libname[32],libs[PETSC_MAX_PATH_LEN],dlib[PETSC_MAX_PATH_LEN];
45: int nmax,i,ierr;
46: PetscTruth found;
50: nmax = 32;
51: PetscOptionsGetStringArray(PETSC_NULL,"-dll_prepend",libname,&nmax,PETSC_NULL);
52: for (i=0; i<nmax; i++) {
53: PetscDLLibraryPrepend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libname[i]);
54: PetscFree(libname[i]);
55: }
57: PetscStrcpy(libs,PETSC_LIB_DIR);
58: PetscStrcat(libs,"/libpetsc");
59: PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
60: if (found) {
61: PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
62: } else {
63: SETERRQ1(1,"Unable to locate PETSc dynamic library %s n You cannot move the dynamic libraries!n or remove USE_DYNAMIC_LIBRARIES from ${PETSC_DIR}/bmake/$PETSC_ARCH/petscconf.hn and rebuild libraries before moving",libs);
64: }
66: PetscStrcpy(libs,PETSC_LIB_DIR);
67: PetscStrcat(libs,"/libpetscvec");
68: PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
69: if (found) {
70: PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
71: }
73: PetscStrcpy(libs,PETSC_LIB_DIR);
74: PetscStrcat(libs,"/libpetscmat");
75: PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
76: if (found) {
77: PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
78: }
80: PetscStrcpy(libs,PETSC_LIB_DIR);
81: PetscStrcat(libs,"/libpetscdm");
82: PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
83: if (found) {
84: PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
85: }
87: PetscStrcpy(libs,PETSC_LIB_DIR);
88: PetscStrcat(libs,"/libpetscsles");
89: PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
90: if (found) {
91: PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
92: }
94: PetscStrcpy(libs,PETSC_LIB_DIR);
95: PetscStrcat(libs,"/libpetscsnes");
96: PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
97: if (found) {
98: PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
99: }
101: PetscStrcpy(libs,PETSC_LIB_DIR);
102: PetscStrcat(libs,"/libpetscts");
103: PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
104: if (found) {
105: PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
106: }
108: PetscStrcpy(libs,PETSC_LIB_DIR);
109: PetscStrcat(libs,"/libpetscdm");
110: PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
111: if (found) {
112: PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
113: }
115: PetscStrcpy(libs,PETSC_LIB_DIR);
116: PetscStrcat(libs,"/libpetscmesh");
117: PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
118: if (found) {
119: PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
120: }
122: PetscStrcpy(libs,PETSC_LIB_DIR);
123: PetscStrcat(libs,"/libpetscgrid");
124: PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
125: if (found) {
126: PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
127: }
129: PetscStrcpy(libs,PETSC_LIB_DIR);
130: PetscStrcat(libs,"/libpetscgsolver");
131: PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
132: if (found) {
133: PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
134: }
136: nmax = 32;
137: PetscOptionsGetStringArray(PETSC_NULL,"-dll_append",libname,&nmax,PETSC_NULL);
138: for (i=0; i<nmax; i++) {
139: PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libname[i]);
140: PetscDLLibraryCCAAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libname[i]);
141: PetscFree(libname[i]);
142: }
144: return(0);
145: }
147: #undef __FUNCT__
149: /*
150: PetscFinalize_DynamicLibraries - Closes the opened dynamic libraries.
151: */
152: int PetscFinalize_DynamicLibraries(void)
153: {
154: int ierr;
155: PetscTruth flg;
158: PetscOptionsHasName(PETSC_NULL,"-dll_view",&flg);
159: if (flg) {
160: PetscDLLibraryPrintPath();
161: }
162: PetscDLLibraryClose(DLLibrariesLoaded);
163: return(0);
164: }
166: #else /* not using dynamic libraries */
168: EXTERN int PetscInitializePackage(char *);
170: #undef __FUNCT__
172: int PetscInitialize_DynamicLibraries(void)
173: {
177: /*
178: This just initializes the draw and viewer methods, since those
179: are ALWAYS available. The other classes are initialized the first
180: time an XXSetType() is called.
181: */
182: PetscInitializePackage(PETSC_NULL);
183: return(0);
184: }
185: #undef __FUNCT__
187: int PetscFinalize_DynamicLibraries(void)
188: {
191: return(0);
192: }
193: #endif
195: /* ------------------------------------------------------------------------------*/
196: struct _PetscFList {
197: void (*routine)(void); /* the routine */
198: char *path; /* path of link library containing routine */
199: char *name; /* string to identify routine */
200: char *rname; /* routine name in dynamic library */
201: PetscFList next; /* next pointer */
202: PetscFList next_list; /* used to maintain list of all lists for freeing */
203: };
205: /*
206: Keep a linked list of PetscFLists so that we can destroy all the left-over ones.
207: */
208: static PetscFList dlallhead = 0;
210: #undef __FUNCT__
212: /*@C
213: PetscFListAddDynamic - Given a routine and a string id, saves that routine in the
214: specified registry.
216: Synopsis:
217: int PetscFListAddDynamic(PetscFList *fl,char *name,char *rname,int (*fnc)(void *))
219: Input Parameters:
220: + fl - pointer registry
221: . name - string to identify routine
222: . rname - routine name in dynamic library
223: - fnc - function pointer (optional if using dynamic libraries)
225: Notes:
226: Users who wish to register new methods for use by a particular PETSc
227: component (e.g., SNES) should generally call the registration routine
228: for that particular component (e.g., SNESRegisterDynamic()) instead of
229: calling PetscFListAddDynamic() directly.
231: ${PETSC_ARCH}, ${PETSC_DIR}, ${PETSC_LIB_DIR}, ${BOPT}, or ${any environmental variable}
232: occuring in pathname will be replaced with appropriate values.
234: Level: developer
236: .seealso: PetscFListDestroy(), SNESRegisterDynamic(), KSPRegisterDynamic(),
237: PCRegisterDynamic(), TSRegisterDynamic(), PetscFList
238: @*/
239: int PetscFListAdd(PetscFList *fl,const char name[],const char rname[],void (*fnc)(void))
240: {
241: PetscFList entry,ne;
242: int ierr;
243: char *fpath,*fname;
247: if (!*fl) {
248: ierr = PetscNew(struct _PetscFList,&entry);
249: ierr = PetscStrallocpy(name,&entry->name);
250: ierr = PetscFListGetPathAndFunction(rname,&fpath,&fname);
251: entry->path = fpath;
252: entry->rname = fname;
253: entry->routine = fnc;
254: entry->next = 0;
255: *fl = entry;
257: /* add this new list to list of all lists */
258: if (!dlallhead) {
259: dlallhead = *fl;
260: (*fl)->next_list = 0;
261: } else {
262: ne = dlallhead;
263: dlallhead = *fl;
264: (*fl)->next_list = ne;
265: }
266: } else {
267: /* search list to see if it is already there */
268: ne = *fl;
269: while (ne) {
270: PetscTruth founddup;
272: PetscStrcmp(ne->name,name,&founddup);
273: if (founddup) { /* found duplicate */
274: PetscFListGetPathAndFunction(rname,&fpath,&fname);
275: PetscStrfree(ne->path);
276: PetscStrfree(ne->rname);
277: ne->path = fpath;
278: ne->rname = fname;
279: ne->routine = fnc;
280: return(0);
281: }
282: if (ne->next) ne = ne->next; else break;
283: }
284: /* create new entry and add to end of list */
285: ierr = PetscNew(struct _PetscFList,&entry);
286: ierr = PetscStrallocpy(name,&entry->name);
287: ierr = PetscFListGetPathAndFunction(rname,&fpath,&fname);
288: entry->path = fpath;
289: entry->rname = fname;
290: entry->routine = fnc;
291: entry->next = 0;
292: ne->next = entry;
293: }
295: return(0);
296: }
298: #undef __FUNCT__
300: /*@
301: PetscFListDestroy - Destroys a list of registered routines.
303: Input Parameter:
304: . fl - pointer to list
306: Level: developer
308: .seealso: PetscFListAddDynamic(), PetscFList
309: @*/
310: int PetscFListDestroy(PetscFList *fl)
311: {
312: PetscFList next,entry,tmp = dlallhead;
313: int ierr;
316: if (!*fl) return(0);
318: if (!dlallhead) {
319: return(0);
320: }
322: /*
323: Remove this entry from the master DL list (if it is in it)
324: */
325: if (dlallhead == *fl) {
326: if (dlallhead->next_list) {
327: dlallhead = dlallhead->next_list;
328: } else {
329: dlallhead = 0;
330: }
331: } else {
332: while (tmp->next_list != *fl) {
333: tmp = tmp->next_list;
334: if (!tmp->next_list) break;
335: }
336: if (tmp->next_list) tmp->next_list = tmp->next_list->next_list;
337: }
339: /* free this list */
340: entry = *fl;
341: while (entry) {
342: next = entry->next;
343: PetscStrfree(entry->path);
344: PetscFree(entry->name);
345: PetscFree(entry->rname);
346: PetscFree(entry);
347: entry = next;
348: }
349: *fl = 0;
350: return(0);
351: }
353: /*
354: Destroys all the function lists that anyone has every registered, such as KSPList, VecList, etc.
355: */
356: #undef __FUNCT__
358: int PetscFListDestroyAll(void)
359: {
360: PetscFList tmp2,tmp1 = dlallhead;
361: int ierr;
364: while (tmp1) {
365: tmp2 = tmp1->next_list;
366: PetscFListDestroy(&tmp1);
367: tmp1 = tmp2;
368: }
369: dlallhead = 0;
370: return(0);
371: }
373: #undef __FUNCT__
375: /*@C
376: PetscFListFind - Given a name, finds the matching routine.
378: Input Parameters:
379: + comm - processors looking for routine
380: . fl - pointer to list
381: - name - name string
383: Output Parameters:
384: . r - the routine
386: Level: developer
388: .seealso: PetscFListAddDynamic(), PetscFList
389: @*/
390: int PetscFListFind(MPI_Comm comm,PetscFList fl,const char name[],void (**r)(void))
391: {
392: PetscFList entry = fl;
393: int ierr;
394: char *function,*path;
395: #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
396: char *newpath;
397: #endif
398: PetscTruth flg,f1,f2,f3;
399:
401: if (!name) SETERRQ(1,"Trying to find routine with null name");
403: *r = 0;
404: PetscFListGetPathAndFunction(name,&path,&function);
406: /*
407: If path then append it to search libraries
408: */
409: #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
410: if (path) {
411: PetscDLLibraryAppend(comm,&DLLibrariesLoaded,path);
412: }
413: #endif
415: while (entry) {
416: flg = PETSC_FALSE;
417: if (path && entry->path) {
418: PetscStrcmp(path,entry->path,&f1);
419: PetscStrcmp(function,entry->rname,&f2);
420: PetscStrcmp(function,entry->name,&f3);
421: flg = (PetscTruth) ((f1 && f2) || (f1 && f3));
422: } else if (!path) {
423: PetscStrcmp(function,entry->name,&f1);
424: PetscStrcmp(function,entry->rname,&f2);
425: flg = (PetscTruth) (f1 || f2);
426: } else {
427: PetscStrcmp(function,entry->name,&flg);
428: if (flg) {
429: PetscFree(function);
430: PetscStrallocpy(entry->rname,&function);
431: } else {
432: PetscStrcmp(function,entry->rname,&flg);
433: }
434: }
436: if (flg) {
438: if (entry->routine) {
439: *r = entry->routine;
440: PetscStrfree(path);
441: PetscFree(function);
442: return(0);
443: }
444:
445: if ((path && entry->path && f3) || (!path && f1)) { /* convert name of function (alias) to actual function name */
446: PetscFree(function);
447: PetscStrallocpy(entry->rname,&function);
448: }
450: /* it is not yet in memory so load from dynamic library */
451: #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
452: newpath = path;
453: if (!path) newpath = entry->path;
454: PetscDLLibrarySym(comm,&DLLibrariesLoaded,newpath,entry->rname,(void **)r);
455: if (*r) {
456: entry->routine = *r;
457: PetscStrfree(path);
458: PetscFree(function);
459: return(0);
460: } else {
461: PetscErrorPrintf("Unable to find function. Search path:n");
462: PetscDLLibraryPrintPath();
463: SETERRQ1(1,"Unable to find function:%s: either it is mis-spelled or dynamic library is not in path",entry->rname);
464: }
465: #endif
466: }
467: entry = entry->next;
468: }
470: #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
471: /* Function never registered; try for it anyway */
472: PetscDLLibrarySym(comm,&DLLibrariesLoaded,path,function,(void **)r);
473: PetscStrfree(path);
474: if (*r) {
475: PetscFListAddDynamic(&fl,name,name,r);
476: }
477: #endif
479: /*
480: Do not generate error, just end
481: PetscErrorPrintf("Function name: %sn",function);
482: PetscDLLibraryPrintPath();
483: SETERRQ(1,"Unable to find function: either it is mis-spelled or dynamic library is not in path");
484: */
486: PetscFree(function);
487: return(0);
488: }
490: #undef __FUNCT__
492: /*@
493: PetscFListView - prints out contents of an PetscFList
495: Collective over MPI_Comm
497: Input Parameters:
498: + list - the list of functions
499: - viewer - currently ignored
501: Level: developer
503: .seealso: PetscFListAddDynamic(), PetscFListPrintTypes(), PetscFList
504: @*/
505: int PetscFListView(PetscFList list,PetscViewer viewer)
506: {
507: int ierr;
508: PetscTruth isascii;
511: if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;
514:
515: PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&isascii);
516: if (!isascii) SETERRQ(1,"Only ASCII viewer supported");
518: while (list) {
519: if (list->path) {
520: PetscViewerASCIIPrintf(viewer," %s %s %sn",list->path,list->name,list->rname);
521: } else {
522: PetscViewerASCIIPrintf(viewer," %s %sn",list->name,list->rname);
523: }
524: list = list->next;
525: }
526: PetscViewerASCIIPrintf(viewer,"n");
527: return(0);
528: }
530: #undef __FUNCT__
532: /*@
533: PetscFListGet - Gets an array the contains the entries in PetscFList, this is used
534: by help etc.
536: Collective over MPI_Comm
538: Input Parameter:
539: . list - list of types
541: Output Parameter:
542: + array - array of names
543: - n - length of array
545: Notes:
546: This allocates the array so that must be freed. BUT the individual entries are
547: not copied so should not be freed.
549: Level: developer
551: .seealso: PetscFListAddDynamic(), PetscFList
552: @*/
553: int PetscFListGet(PetscFList list,char ***array,int *n)
554: {
555: int count = 0,ierr;
556: PetscFList klist = list;
559: while (list) {
560: list = list->next;
561: count++;
562: }
563: ierr = PetscMalloc((count+1)*sizeof(char *),array);
564: count = 0;
565: while (klist) {
566: (*array)[count] = klist->name;
567: klist = klist->next;
568: count++;
569: }
570: (*array)[count] = 0;
571: *n = count+1;
573: return(0);
574: }
577: #undef __FUNCT__
579: /*@C
580: PetscFListPrintTypes - Prints the methods available.
582: Collective over MPI_Comm
584: Input Parameters:
585: + comm - the communicator (usually MPI_COMM_WORLD)
586: . fd - file to print to, usually stdout
587: . prefix - prefix to prepend to name (optional)
588: . name - option string (for example, "-ksp_type")
589: . text - short description of the object (for example, "Krylov solvers")
590: . man - name of manual page that discusses the object (for example, "KSPCreate")
591: - list - list of types
593: Level: developer
595: .seealso: PetscFListAddDynamic(), PetscFList
596: @*/
597: int PetscFListPrintTypes(MPI_Comm comm,FILE *fd,const char prefix[],const char name[],char *text,char *man,PetscFList list)
598: {
599: int ierr,count = 0;
600: char p[64];
603: if (!fd) fd = stdout;
605: PetscStrcpy(p,"-");
606: if (prefix) {PetscStrcat(p,prefix);}
607: PetscFPrintf(comm,fd," %s%s %s:(one of)",p,name+1,text);
609: while (list) {
610: PetscFPrintf(comm,fd," %s",list->name);
611: list = list->next;
612: count++;
613: if (count == 8) {PetscFPrintf(comm,fd,"n ");}
614: }
615: PetscFPrintf(comm,fd," (%s)n",man);
616: return(0);
617: }
619: #undef __FUNCT__
621: /*@
622: PetscFListDuplicate - Creates a new list from a given object list.
624: Input Parameters:
625: . fl - pointer to list
627: Output Parameters:
628: . nl - the new list (should point to 0 to start, otherwise appends)
630: Level: developer
632: .seealso: PetscFList, PetscFListAdd(), PetscFlistDestroy()
634: @*/
635: int PetscFListDuplicate(PetscFList fl,PetscFList *nl)
636: {
637: int ierr;
638: char path[PETSC_MAX_PATH_LEN];
641: while (fl) {
642: /* this is silly, rebuild the complete pathname */
643: if (fl->path) {
644: PetscStrcpy(path,fl->path);
645: PetscStrcat(path,":");
646: PetscStrcat(path,fl->name);
647: } else {
648: PetscStrcpy(path,fl->name);
649: }
650: PetscFListAddDynamic(nl,path,fl->rname,fl->routine);
651: fl = fl->next;
652: }
653: return(0);
654: }
657: #undef __FUNCT__
659: /*
660: PetscFListConcat - joins name of a libary, and the path where it is located
661: into a single string.
663: Input Parameters:
664: . path - path to the library name.
665: . name - name of the library
667: Output Parameters:
668: . fullname - the name that is the union of the path and the library name,
669: delimited by a semicolon, i.e., path:name
671: Notes:
672: If the path is NULL, assumes that the name, specified also includes
673: the path as path:name
675: */
676: int PetscFListConcat(const char path[],const char name[],char fullname[])
677: {
680: if (path) {
681: PetscStrcpy(fullname,path);
682: PetscStrcat(fullname,":");
683: PetscStrcat(fullname,name);
684: } else {
685: PetscStrcpy(fullname,name);
686: }
687: return(0);
688: }