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
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;
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.h\n 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,"/libpetscksp");
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: nmax = 32;
130: PetscOptionsGetStringArray(PETSC_NULL,"-dll_append",libname,&nmax,PETSC_NULL);
131: for (i=0; i<nmax; i++) {
132: PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libname[i]);
133: PetscDLLibraryCCAAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libname[i]);
134: PetscFree(libname[i]);
135: }
137: return(0);
138: }
142: /*
143: PetscFinalize_DynamicLibraries - Closes the opened dynamic libraries.
144: */
145: int PetscFinalize_DynamicLibraries(void)
146: {
147: int ierr;
148: PetscTruth flg;
151: PetscOptionsHasName(PETSC_NULL,"-dll_view",&flg);
152: if (flg) {
153: PetscDLLibraryPrintPath();
154: }
155: PetscDLLibraryClose(DLLibrariesLoaded);
156: return(0);
157: }
159: #else /* not using dynamic libraries */
161: EXTERN int PetscInitializePackage(char *);
165: int PetscInitialize_DynamicLibraries(void)
166: {
170: /*
171: This just initializes the draw and viewer methods, since those
172: are ALWAYS available. The other classes are initialized the first
173: time an XXSetType() is called.
174: */
175: PetscInitializePackage(PETSC_NULL);
176: return(0);
177: }
180: int PetscFinalize_DynamicLibraries(void)
181: {
184: return(0);
185: }
186: #endif
188: /* ------------------------------------------------------------------------------*/
189: struct _PetscFList {
190: void (*routine)(void); /* the routine */
191: char *path; /* path of link library containing routine */
192: char *name; /* string to identify routine */
193: char *rname; /* routine name in dynamic library */
194: PetscFList next; /* next pointer */
195: PetscFList next_list; /* used to maintain list of all lists for freeing */
196: };
198: /*
199: Keep a linked list of PetscFLists so that we can destroy all the left-over ones.
200: */
201: static PetscFList dlallhead = 0;
205: /*@C
206: PetscFListAddDynamic - Given a routine and a string id, saves that routine in the
207: specified registry.
209: Synopsis:
210: int PetscFListAddDynamic(PetscFList *fl,char *name,char *rname,int (*fnc)(void *))
212: Input Parameters:
213: + fl - pointer registry
214: . name - string to identify routine
215: . rname - routine name in dynamic library
216: - fnc - function pointer (optional if using dynamic libraries)
218: Notes:
219: Users who wish to register new methods for use by a particular PETSc
220: component (e.g., SNES) should generally call the registration routine
221: for that particular component (e.g., SNESRegisterDynamic()) instead of
222: calling PetscFListAddDynamic() directly.
224: ${PETSC_ARCH}, ${PETSC_DIR}, ${PETSC_LIB_DIR}, ${BOPT}, or ${any environmental variable}
225: occuring in pathname will be replaced with appropriate values.
227: Level: developer
229: .seealso: PetscFListDestroy(), SNESRegisterDynamic(), KSPRegisterDynamic(),
230: PCRegisterDynamic(), TSRegisterDynamic(), PetscFList
231: @*/
232: int PetscFListAdd(PetscFList *fl,const char name[],const char rname[],void (*fnc)(void))
233: {
234: PetscFList entry,ne;
235: int ierr;
236: char *fpath,*fname;
240: if (!*fl) {
241: PetscNew(struct _PetscFList,&entry);
242: PetscStrallocpy(name,&entry->name);
243: PetscFListGetPathAndFunction(rname,&fpath,&fname);
244: entry->path = fpath;
245: entry->rname = fname;
246: entry->routine = fnc;
247: entry->next = 0;
248: *fl = entry;
250: /* add this new list to list of all lists */
251: if (!dlallhead) {
252: dlallhead = *fl;
253: (*fl)->next_list = 0;
254: } else {
255: ne = dlallhead;
256: dlallhead = *fl;
257: (*fl)->next_list = ne;
258: }
259: } else {
260: /* search list to see if it is already there */
261: ne = *fl;
262: while (ne) {
263: PetscTruth founddup;
265: PetscStrcmp(ne->name,name,&founddup);
266: if (founddup) { /* found duplicate */
267: PetscFListGetPathAndFunction(rname,&fpath,&fname);
268: PetscStrfree(ne->path);
269: PetscStrfree(ne->rname);
270: ne->path = fpath;
271: ne->rname = fname;
272: ne->routine = fnc;
273: return(0);
274: }
275: if (ne->next) ne = ne->next; else break;
276: }
277: /* create new entry and add to end of list */
278: PetscNew(struct _PetscFList,&entry);
279: PetscStrallocpy(name,&entry->name);
280: PetscFListGetPathAndFunction(rname,&fpath,&fname);
281: entry->path = fpath;
282: entry->rname = fname;
283: entry->routine = fnc;
284: entry->next = 0;
285: ne->next = entry;
286: }
288: return(0);
289: }
293: /*@
294: PetscFListDestroy - Destroys a list of registered routines.
296: Input Parameter:
297: . fl - pointer to list
299: Level: developer
301: .seealso: PetscFListAddDynamic(), PetscFList
302: @*/
303: int PetscFListDestroy(PetscFList *fl)
304: {
305: PetscFList next,entry,tmp = dlallhead;
306: int ierr;
309: if (!*fl) return(0);
311: if (!dlallhead) {
312: return(0);
313: }
315: /*
316: Remove this entry from the master DL list (if it is in it)
317: */
318: if (dlallhead == *fl) {
319: if (dlallhead->next_list) {
320: dlallhead = dlallhead->next_list;
321: } else {
322: dlallhead = 0;
323: }
324: } else {
325: while (tmp->next_list != *fl) {
326: tmp = tmp->next_list;
327: if (!tmp->next_list) break;
328: }
329: if (tmp->next_list) tmp->next_list = tmp->next_list->next_list;
330: }
332: /* free this list */
333: entry = *fl;
334: while (entry) {
335: next = entry->next;
336: PetscStrfree(entry->path);
337: PetscFree(entry->name);
338: PetscFree(entry->rname);
339: PetscFree(entry);
340: entry = next;
341: }
342: *fl = 0;
343: return(0);
344: }
346: /*
347: Destroys all the function lists that anyone has every registered, such as KSPList, VecList, etc.
348: */
351: int PetscFListDestroyAll(void)
352: {
353: PetscFList tmp2,tmp1 = dlallhead;
354: int ierr;
357: while (tmp1) {
358: tmp2 = tmp1->next_list;
359: PetscFListDestroy(&tmp1);
360: tmp1 = tmp2;
361: }
362: dlallhead = 0;
363: return(0);
364: }
368: /*@C
369: PetscFListFind - Given a name, finds the matching routine.
371: Input Parameters:
372: + comm - processors looking for routine
373: . fl - pointer to list
374: - name - name string
376: Output Parameters:
377: . r - the routine
379: Level: developer
381: .seealso: PetscFListAddDynamic(), PetscFList
382: @*/
383: int PetscFListFind(MPI_Comm comm,PetscFList fl,const char name[],void (**r)(void))
384: {
385: PetscFList entry = fl;
386: int ierr;
387: char *function,*path;
388: #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
389: char *newpath;
390: #endif
391: PetscTruth flg,f1,f2,f3;
392:
394: if (!name) SETERRQ(1,"Trying to find routine with null name");
396: *r = 0;
397: PetscFListGetPathAndFunction(name,&path,&function);
399: /*
400: If path then append it to search libraries
401: */
402: #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
403: if (path) {
404: PetscDLLibraryAppend(comm,&DLLibrariesLoaded,path);
405: }
406: #endif
408: while (entry) {
409: flg = PETSC_FALSE;
410: if (path && entry->path) {
411: PetscStrcmp(path,entry->path,&f1);
412: PetscStrcmp(function,entry->rname,&f2);
413: PetscStrcmp(function,entry->name,&f3);
414: flg = (PetscTruth) ((f1 && f2) || (f1 && f3));
415: } else if (!path) {
416: PetscStrcmp(function,entry->name,&f1);
417: PetscStrcmp(function,entry->rname,&f2);
418: flg = (PetscTruth) (f1 || f2);
419: } else {
420: PetscStrcmp(function,entry->name,&flg);
421: if (flg) {
422: PetscFree(function);
423: PetscStrallocpy(entry->rname,&function);
424: } else {
425: PetscStrcmp(function,entry->rname,&flg);
426: }
427: }
429: if (flg) {
431: if (entry->routine) {
432: *r = entry->routine;
433: PetscStrfree(path);
434: PetscFree(function);
435: return(0);
436: }
437:
438: if ((path && entry->path && f3) || (!path && f1)) { /* convert name of function (alias) to actual function name */
439: PetscFree(function);
440: PetscStrallocpy(entry->rname,&function);
441: }
443: /* it is not yet in memory so load from dynamic library */
444: #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
445: newpath = path;
446: if (!path) newpath = entry->path;
447: PetscDLLibrarySym(comm,&DLLibrariesLoaded,newpath,entry->rname,(void **)r);
448: if (*r) {
449: entry->routine = *r;
450: PetscStrfree(path);
451: PetscFree(function);
452: return(0);
453: } else {
454: PetscErrorPrintf("Unable to find function. Search path:\n");
455: PetscDLLibraryPrintPath();
456: SETERRQ1(1,"Unable to find function:%s: either it is mis-spelled or dynamic library is not in path",entry->rname);
457: }
458: #endif
459: }
460: entry = entry->next;
461: }
463: #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
464: /* Function never registered; try for it anyway */
465: PetscDLLibrarySym(comm,&DLLibrariesLoaded,path,function,(void **)r);
466: PetscStrfree(path);
467: if (*r) {
468: PetscFListAdd(&fl,name,name,*r);
469: }
470: #endif
472: /*
473: Do not generate error, just end
474: PetscErrorPrintf("Function name: %s\n",function);
475: PetscDLLibraryPrintPath();
476: SETERRQ(1,"Unable to find function: either it is mis-spelled or dynamic library is not in path");
477: */
479: PetscFree(function);
480: return(0);
481: }
485: /*@
486: PetscFListView - prints out contents of an PetscFList
488: Collective over MPI_Comm
490: Input Parameters:
491: + list - the list of functions
492: - viewer - currently ignored
494: Level: developer
496: .seealso: PetscFListAddDynamic(), PetscFListPrintTypes(), PetscFList
497: @*/
498: int PetscFListView(PetscFList list,PetscViewer viewer)
499: {
500: int ierr;
501: PetscTruth isascii;
504: if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;
507:
508: PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&isascii);
509: if (!isascii) SETERRQ(1,"Only ASCII viewer supported");
511: while (list) {
512: if (list->path) {
513: PetscViewerASCIIPrintf(viewer," %s %s %s\n",list->path,list->name,list->rname);
514: } else {
515: PetscViewerASCIIPrintf(viewer," %s %s\n",list->name,list->rname);
516: }
517: list = list->next;
518: }
519: PetscViewerASCIIPrintf(viewer,"\n");
520: return(0);
521: }
525: /*@
526: PetscFListGet - Gets an array the contains the entries in PetscFList, this is used
527: by help etc.
529: Collective over MPI_Comm
531: Input Parameter:
532: . list - list of types
534: Output Parameter:
535: + array - array of names
536: - n - length of array
538: Notes:
539: This allocates the array so that must be freed. BUT the individual entries are
540: not copied so should not be freed.
542: Level: developer
544: .seealso: PetscFListAddDynamic(), PetscFList
545: @*/
546: int PetscFListGet(PetscFList list,char ***array,int *n)
547: {
548: int count = 0,ierr;
549: PetscFList klist = list;
552: while (list) {
553: list = list->next;
554: count++;
555: }
556: PetscMalloc((count+1)*sizeof(char *),array);
557: count = 0;
558: while (klist) {
559: (*array)[count] = klist->name;
560: klist = klist->next;
561: count++;
562: }
563: (*array)[count] = 0;
564: *n = count+1;
566: return(0);
567: }
572: /*@C
573: PetscFListPrintTypes - Prints the methods available.
575: Collective over MPI_Comm
577: Input Parameters:
578: + comm - the communicator (usually MPI_COMM_WORLD)
579: . fd - file to print to, usually stdout
580: . prefix - prefix to prepend to name (optional)
581: . name - option string (for example, "-ksp_type")
582: . text - short description of the object (for example, "Krylov solvers")
583: . man - name of manual page that discusses the object (for example, "KSPCreate")
584: - list - list of types
586: Level: developer
588: .seealso: PetscFListAddDynamic(), PetscFList
589: @*/
590: int PetscFListPrintTypes(MPI_Comm comm,FILE *fd,const char prefix[],const char name[],const char text[],const char man[],PetscFList list)
591: {
592: int ierr,count = 0;
593: char p[64];
596: if (!fd) fd = stdout;
598: PetscStrcpy(p,"-");
599: if (prefix) {PetscStrcat(p,prefix);}
600: PetscFPrintf(comm,fd," %s%s %s:(one of)",p,name+1,text);
602: while (list) {
603: PetscFPrintf(comm,fd," %s",list->name);
604: list = list->next;
605: count++;
606: if (count == 8) {PetscFPrintf(comm,fd,"\n ");}
607: }
608: PetscFPrintf(comm,fd," (%s)\n",man);
609: return(0);
610: }
614: /*@
615: PetscFListDuplicate - Creates a new list from a given object list.
617: Input Parameters:
618: . fl - pointer to list
620: Output Parameters:
621: . nl - the new list (should point to 0 to start, otherwise appends)
623: Level: developer
625: .seealso: PetscFList, PetscFListAdd(), PetscFlistDestroy()
627: @*/
628: int PetscFListDuplicate(PetscFList fl,PetscFList *nl)
629: {
630: int ierr;
631: char path[PETSC_MAX_PATH_LEN];
634: while (fl) {
635: /* this is silly, rebuild the complete pathname */
636: if (fl->path) {
637: PetscStrcpy(path,fl->path);
638: PetscStrcat(path,":");
639: PetscStrcat(path,fl->name);
640: } else {
641: PetscStrcpy(path,fl->name);
642: }
643: PetscFListAdd(nl,path,fl->rname,fl->routine);
644: fl = fl->next;
645: }
646: return(0);
647: }
652: /*
653: PetscFListConcat - joins name of a libary, and the path where it is located
654: into a single string.
656: Input Parameters:
657: . path - path to the library name.
658: . name - name of the library
660: Output Parameters:
661: . fullname - the name that is the union of the path and the library name,
662: delimited by a semicolon, i.e., path:name
664: Notes:
665: If the path is NULL, assumes that the name, specified also includes
666: the path as path:name
668: */
669: int PetscFListConcat(const char path[],const char name[],char fullname[])
670: {
673: if (path) {
674: PetscStrcpy(fullname,path);
675: PetscStrcat(fullname,":");
676: PetscStrcat(fullname,name);
677: } else {
678: PetscStrcpy(fullname,name);
679: }
680: return(0);
681: }