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: int PetscFListGetPathAndFunction(const char name[],char *path[],char *function[])
10: {
11: char work[256],*lfunction,ierr;
14: PetscStrncpy(work,name,256);
15: PetscStrchr(work,':',&lfunction);
16: if (lfunction != work && lfunction && lfunction[1] != ':') {
17: lfunction[0] = 0;
18: PetscStrallocpy(work,path);
19: PetscStrallocpy(lfunction+1,function);
20: } else {
21: *path = 0;
22: PetscStrallocpy(name,function);
23: }
24: return(0);
25: }
27: #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
29: /*
30: This is the list used by the DLRegister routines
31: */
32: PetscDLLibraryList DLLibrariesLoaded = 0;
34: /*
35: PetscInitialize_DynamicLibraries - Adds the default dynamic link libraries to the
36: search path.
37: */
38: int PetscInitialize_DynamicLibraries(void)
39: {
40: char *libname[32],libs[256],dlib[1024];
41: int nmax,i,ierr;
42: PetscTruth found;
46: nmax = 32;
47: PetscOptionsGetStringArray(PETSC_NULL,"-dll_prepend",libname,&nmax,PETSC_NULL);
48: for (i=0; i<nmax; i++) {
49: PetscDLLibraryPrepend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libname[i]);
50: PetscFree(libname[i]);
51: }
53: PetscStrcpy(libs,PETSC_LIB_DIR);
54: PetscStrcat(libs,"/libpetsc");
55: PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
56: if (found) {
57: PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
58: } else {
59: 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);
60: }
62: PetscStrcpy(libs,PETSC_LIB_DIR);
63: PetscStrcat(libs,"/libpetscvec");
64: PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
65: if (found) {
66: PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
67: }
69: PetscStrcpy(libs,PETSC_LIB_DIR);
70: PetscStrcat(libs,"/libpetscmat");
71: PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
72: if (found) {
73: PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
74: }
76: PetscStrcpy(libs,PETSC_LIB_DIR);
77: PetscStrcat(libs,"/libpetscdm");
78: PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
79: if (found) {
80: PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
81: }
83: PetscStrcpy(libs,PETSC_LIB_DIR);
84: PetscStrcat(libs,"/libpetscsles");
85: PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
86: if (found) {
87: PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
88: }
90: PetscStrcpy(libs,PETSC_LIB_DIR);
91: PetscStrcat(libs,"/libpetscsnes");
92: PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
93: if (found) {
94: PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
95: }
97: PetscStrcpy(libs,PETSC_LIB_DIR);
98: PetscStrcat(libs,"/libpetscts");
99: PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
100: if (found) {
101: PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
102: }
104: PetscStrcpy(libs,PETSC_LIB_DIR);
105: PetscStrcat(libs,"/libpetscdm");
106: PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
107: if (found) {
108: PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
109: }
111: PetscStrcpy(libs,PETSC_LIB_DIR);
112: PetscStrcat(libs,"/libpetscmesh");
113: PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
114: if (found) {
115: PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
116: }
118: PetscStrcpy(libs,PETSC_LIB_DIR);
119: PetscStrcat(libs,"/libpetscgrid");
120: PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
121: if (found) {
122: PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
123: }
125: PetscStrcpy(libs,PETSC_LIB_DIR);
126: PetscStrcat(libs,"/libpetscgsolver");
127: PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
128: if (found) {
129: PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
130: }
132: nmax = 32;
133: PetscOptionsGetStringArray(PETSC_NULL,"-dll_append",libname,&nmax,PETSC_NULL);
134: for (i=0; i<nmax; i++) {
135: PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libname[i]);
136: PetscDLLibraryCCAAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libname[i]);
137: PetscFree(libname[i]);
138: }
140: return(0);
141: }
143: /*
144: PetscFinalize_DynamicLibraries - Closes the opened dynamic libraries.
145: */
146: int PetscFinalize_DynamicLibraries(void)
147: {
148: int ierr;
149: PetscTruth flg;
152: PetscOptionsHasName(PETSC_NULL,"-dll_view",&flg);
153: if (flg) {
154: PetscDLLibraryPrintPath();
155: }
156: PetscDLLibraryClose(DLLibrariesLoaded);
157: return(0);
158: }
160: #else /* not using dynamic libraries */
162: EXTERN int PetscInitializePackage(char *);
164: int PetscInitialize_DynamicLibraries(void)
165: {
169: /*
170: This just initializes the draw and viewer methods, since those
171: are ALWAYS available. The other classes are initialized the first
172: time an XXSetType() is called.
173: */
174: PetscInitializePackage(PETSC_NULL);
175: return(0);
176: }
177: int PetscFinalize_DynamicLibraries(void)
178: {
181: return(0);
182: }
183: #endif
185: /* ------------------------------------------------------------------------------*/
186: struct _PetscFList {
187: void (*routine)(void); /* the routine */
188: char *path; /* path of link library containing routine */
189: char *name; /* string to identify routine */
190: char *rname; /* routine name in dynamic library */
191: PetscFList next; /* next pointer */
192: PetscFList next_list; /* used to maintain list of all lists for freeing */
193: };
195: /*
196: Keep a linked list of PetscFLists so that we can destroy all the left-over ones.
197: */
198: static PetscFList dlallhead = 0;
200: /*@C
201: PetscFListAddDynamic - Given a routine and a string id, saves that routine in the
202: specified registry.
204: Synopsis:
205: int PetscFListAddDynamic(PetscFList *fl,char *name,char *rname,int (*fnc)(void *))
207: Input Parameters:
208: + fl - pointer registry
209: . name - string to identify routine
210: . rname - routine name in dynamic library
211: - fnc - function pointer (optional if using dynamic libraries)
213: Notes:
214: Users who wish to register new methods for use by a particular PETSc
215: component (e.g., SNES) should generally call the registration routine
216: for that particular component (e.g., SNESRegisterDynamic()) instead of
217: calling PetscFListAddDynamic() directly.
219: ${PETSC_ARCH}, ${PETSC_DIR}, ${PETSC_LIB_DIR}, ${BOPT}, or ${any environmental variable}
220: occuring in pathname will be replaced with appropriate values.
222: Level: developer
224: .seealso: PetscFListDestroy(), SNESRegisterDynamic(), KSPRegisterDynamic(),
225: PCRegisterDynamic(), TSRegisterDynamic(), PetscFList
226: @*/
227: int PetscFListAdd(PetscFList *fl,const char name[],const char rname[],void (*fnc)(void))
228: {
229: PetscFList entry,ne;
230: int ierr;
231: char *fpath,*fname;
235: if (!*fl) {
236: ierr = PetscNew(struct _PetscFList,&entry);
237: ierr = PetscStrallocpy(name,&entry->name);
238: ierr = PetscFListGetPathAndFunction(rname,&fpath,&fname);
239: entry->path = fpath;
240: entry->rname = fname;
241: entry->routine = fnc;
242: entry->next = 0;
243: *fl = entry;
245: /* add this new list to list of all lists */
246: if (!dlallhead) {
247: dlallhead = *fl;
248: (*fl)->next_list = 0;
249: } else {
250: ne = dlallhead;
251: dlallhead = *fl;
252: (*fl)->next_list = ne;
253: }
254: } else {
255: /* search list to see if it is already there */
256: ne = *fl;
257: while (ne) {
258: PetscTruth founddup;
260: PetscStrcmp(ne->name,name,&founddup);
261: if (founddup) { /* found duplicate */
262: PetscFListGetPathAndFunction(rname,&fpath,&fname);
263: PetscStrfree(ne->path);
264: PetscStrfree(ne->rname);
265: ne->path = fpath;
266: ne->rname = fname;
267: ne->routine = fnc;
268: return(0);
269: }
270: if (ne->next) ne = ne->next; else break;
271: }
272: /* create new entry and add to end of list */
273: ierr = PetscNew(struct _PetscFList,&entry);
274: ierr = PetscStrallocpy(name,&entry->name);
275: ierr = PetscFListGetPathAndFunction(rname,&fpath,&fname);
276: entry->path = fpath;
277: entry->rname = fname;
278: entry->routine = fnc;
279: entry->next = 0;
280: ne->next = entry;
281: }
283: return(0);
284: }
286: /*@
287: PetscFListDestroy - Destroys a list of registered routines.
289: Input Parameter:
290: . fl - pointer to list
292: Level: developer
294: .seealso: PetscFListAddDynamic(), PetscFList
295: @*/
296: int PetscFListDestroy(PetscFList *fl)
297: {
298: PetscFList next,entry,tmp = dlallhead;
299: int ierr;
302: if (!*fl) return(0);
304: if (!dlallhead) {
305: return(0);
306: }
308: /*
309: Remove this entry from the master DL list (if it is in it)
310: */
311: if (dlallhead == *fl) {
312: if (dlallhead->next_list) {
313: dlallhead = dlallhead->next_list;
314: } else {
315: dlallhead = 0;
316: }
317: } else {
318: while (tmp->next_list != *fl) {
319: tmp = tmp->next_list;
320: if (!tmp->next_list) break;
321: }
322: if (tmp->next_list) tmp->next_list = tmp->next_list->next_list;
323: }
325: /* free this list */
326: entry = *fl;
327: while (entry) {
328: next = entry->next;
329: PetscStrfree(entry->path);
330: PetscFree(entry->name);
331: PetscFree(entry->rname);
332: PetscFree(entry);
333: entry = next;
334: }
335: *fl = 0;
336: return(0);
337: }
339: /*
340: Destroys all the function lists that anyone has every registered, such as KSPList, VecList, etc.
341: */
342: int PetscFListDestroyAll(void)
343: {
344: PetscFList tmp2,tmp1 = dlallhead;
345: int ierr;
348: while (tmp1) {
349: tmp2 = tmp1->next_list;
350: PetscFListDestroy(&tmp1);
351: tmp1 = tmp2;
352: }
353: dlallhead = 0;
354: return(0);
355: }
357: /*@C
358: PetscFListFind - Given a name, finds the matching routine.
360: Input Parameters:
361: + comm - processors looking for routine
362: . fl - pointer to list
363: - name - name string
365: Output Parameters:
366: . r - the routine
368: Level: developer
370: .seealso: PetscFListAddDynamic(), PetscFList
371: @*/
372: int PetscFListFind(MPI_Comm comm,PetscFList fl,const char name[],void (**r)(void))
373: {
374: PetscFList entry = fl;
375: int ierr;
376: char *function,*path;
377: #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
378: char *newpath;
379: #endif
380: PetscTruth flg,f1,f2,f3;
381:
383: if (!name) SETERRQ(1,"Trying to find routine with null name");
385: *r = 0;
386: PetscFListGetPathAndFunction(name,&path,&function);
388: /*
389: If path then append it to search libraries
390: */
391: #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
392: if (path) {
393: PetscDLLibraryAppend(comm,&DLLibrariesLoaded,path);
394: }
395: #endif
397: while (entry) {
398: flg = PETSC_FALSE;
399: if (path && entry->path) {
400: PetscStrcmp(path,entry->path,&f1);
401: PetscStrcmp(function,entry->rname,&f2);
402: PetscStrcmp(function,entry->name,&f3);
403: flg = (PetscTruth) ((f1 && f2) || (f1 && f3));
404: } else if (!path) {
405: PetscStrcmp(function,entry->name,&f1);
406: PetscStrcmp(function,entry->rname,&f2);
407: flg = (PetscTruth) (f1 || f2);
408: } else {
409: PetscStrcmp(function,entry->name,&flg);
410: if (flg) {
411: PetscFree(function);
412: PetscStrallocpy(entry->rname,&function);
413: } else {
414: PetscStrcmp(function,entry->rname,&flg);
415: }
416: }
418: if (flg) {
420: if (entry->routine) {
421: *r = entry->routine;
422: PetscStrfree(path);
423: PetscFree(function);
424: return(0);
425: }
426:
427: if ((path && entry->path && f3) || (!path && f1)) { /* convert name of function (alias) to actual function name */
428: PetscFree(function);
429: PetscStrallocpy(entry->rname,&function);
430: }
432: /* it is not yet in memory so load from dynamic library */
433: #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
434: newpath = path;
435: if (!path) newpath = entry->path;
436: PetscDLLibrarySym(comm,&DLLibrariesLoaded,newpath,entry->rname,(void **)r);
437: if (*r) {
438: entry->routine = *r;
439: PetscStrfree(path);
440: PetscFree(function);
441: return(0);
442: } else {
443: PetscErrorPrintf("Unable to find function. Search path:n");
444: PetscDLLibraryPrintPath();
445: SETERRQ1(1,"Unable to find function:%s: either it is mis-spelled or dynamic library is not in path",entry->rname);
446: }
447: #endif
448: }
449: entry = entry->next;
450: }
452: #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
453: /* Function never registered; try for it anyway */
454: PetscDLLibrarySym(comm,&DLLibrariesLoaded,path,function,(void **)r);
455: PetscStrfree(path);
456: if (*r) {
457: PetscFListAddDynamic(&fl,name,name,r);
458: }
459: #endif
461: /*
462: Do not generate error, just end
463: PetscErrorPrintf("Function name: %sn",function);
464: PetscDLLibraryPrintPath();
465: SETERRQ(1,"Unable to find function: either it is mis-spelled or dynamic library is not in path");
466: */
468: PetscFree(function);
469: return(0);
470: }
472: /*@
473: PetscFListView - prints out contents of an PetscFList
475: Collective over MPI_Comm
477: Input Parameters:
478: + list - the list of functions
479: - viewer - currently ignored
481: Level: developer
483: .seealso: PetscFListAddDynamic(), PetscFListPrintTypes(), PetscFList
484: @*/
485: int PetscFListView(PetscFList list,PetscViewer viewer)
486: {
487: int ierr;
488: PetscTruth isascii;
491: if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;
494:
495: PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&isascii);
496: if (!isascii) SETERRQ(1,"Only ASCII viewer supported");
498: while (list) {
499: if (list->path) {
500: PetscViewerASCIIPrintf(viewer," %s %s %sn",list->path,list->name,list->rname);
501: } else {
502: PetscViewerASCIIPrintf(viewer," %s %sn",list->name,list->rname);
503: }
504: list = list->next;
505: }
506: PetscViewerASCIIPrintf(viewer,"n");
507: return(0);
508: }
510: /*@
511: PetscFListGet - Gets an array the contains the entries in PetscFList, this is used
512: by help etc.
514: Collective over MPI_Comm
516: Input Parameter:
517: . list - list of types
519: Output Parameter:
520: + array - array of names
521: - n - length of array
523: Notes:
524: This allocates the array so that must be freed. BUT the individual entries are
525: not copied so should not be freed.
527: Level: developer
529: .seealso: PetscFListAddDynamic(), PetscFList
530: @*/
531: int PetscFListGet(PetscFList list,char ***array,int *n)
532: {
533: int count = 0,ierr;
534: PetscFList klist = list;
537: while (list) {
538: list = list->next;
539: count++;
540: }
541: ierr = PetscMalloc((count+1)*sizeof(char *),array);
542: count = 0;
543: while (klist) {
544: (*array)[count] = klist->name;
545: klist = klist->next;
546: count++;
547: }
548: (*array)[count] = 0;
549: *n = count+1;
551: return(0);
552: }
555: /*@C
556: PetscFListPrintTypes - Prints the methods available.
558: Collective over MPI_Comm
560: Input Parameters:
561: + comm - the communicator (usually MPI_COMM_WORLD)
562: . fd - file to print to, usually stdout
563: . prefix - prefix to prepend to name (optional)
564: . name - option string (for example, "-ksp_type")
565: . text - short description of the object (for example, "Krylov solvers")
566: . man - name of manual page that discusses the object (for example, "KSPCreate")
567: - list - list of types
569: Level: developer
571: .seealso: PetscFListAddDynamic(), PetscFList
572: @*/
573: int PetscFListPrintTypes(MPI_Comm comm,FILE *fd,const char prefix[],const char name[],char *text,char *man,PetscFList list)
574: {
575: int ierr,count = 0;
576: char p[64];
579: if (!fd) fd = stdout;
581: PetscStrcpy(p,"-");
582: if (prefix) {PetscStrcat(p,prefix);}
583: PetscFPrintf(comm,fd," %s%s %s:(one of)",p,name+1,text);
585: while (list) {
586: PetscFPrintf(comm,fd," %s",list->name);
587: list = list->next;
588: count++;
589: if (count == 8) {PetscFPrintf(comm,fd,"n ");}
590: }
591: PetscFPrintf(comm,fd," (see manual page %s)n",man);
592: return(0);
593: }
595: /*@
596: PetscFListDuplicate - Creates a new list from a given object list.
598: Input Parameters:
599: . fl - pointer to list
601: Output Parameters:
602: . nl - the new list (should point to 0 to start, otherwise appends)
604: Level: developer
606: .seealso: PetscFList, PetscFListAdd(), PetscFlistDestroy()
608: @*/
609: int PetscFListDuplicate(PetscFList fl,PetscFList *nl)
610: {
611: int ierr;
612: char path[1024];
615: while (fl) {
616: /* this is silly, rebuild the complete pathname */
617: if (fl->path) {
618: PetscStrcpy(path,fl->path);
619: PetscStrcat(path,":");
620: PetscStrcat(path,fl->name);
621: } else {
622: PetscStrcpy(path,fl->name);
623: }
624: PetscFListAddDynamic(nl,path,fl->rname,fl->routine);
625: fl = fl->next;
626: }
627: return(0);
628: }
631: /*
632: PetscFListConcat - joins name of a libary, and the path where it is located
633: into a single string.
635: Input Parameters:
636: . path - path to the library name.
637: . name - name of the library
639: Output Parameters:
640: . fullname - the name that is the union of the path and the library name,
641: delimited by a semicolon, i.e., path:name
643: Notes:
644: If the path is NULL, assumes that the name, specified also includes
645: the path as path:name
647: */
648: int PetscFListConcat(const char path[],const char name[],char fullname[])
649: {
652: if (path) {
653: PetscStrcpy(fullname,path);
654: PetscStrcat(fullname,":");
655: PetscStrcat(fullname,name);
656: } else {
657: PetscStrcpy(fullname,name);
658: }
659: return(0);
660: }