Actual source code: reg.c
1: #define PETSC_DLL
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: PetscErrorCode PetscFListGetPathAndFunction(const char name[],char *path[],char *function[])
12: {
14: char work[PETSC_MAX_PATH_LEN],*lfunction;
17: PetscStrncpy(work,name,256);
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: #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
32: /*
33: This is the list used by the DLRegister routines
34: */
35: PetscDLLibraryList DLLibrariesLoaded = 0;
39: /*
40: PetscInitialize_DynamicLibraries - Adds the default dynamic link libraries to the
41: search path.
42: */
43: PetscErrorCode PetscInitialize_DynamicLibraries(void)
44: {
45: char *libname[32],libs[PETSC_MAX_PATH_LEN],dlib[PETSC_MAX_PATH_LEN];
47: PetscInt nmax,i;
48: PetscTruth found;
52: nmax = 32;
53: PetscOptionsGetStringArray(PETSC_NULL,"-dll_prepend",libname,&nmax,PETSC_NULL);
54: for (i=0; i<nmax; i++) {
55: PetscDLLibraryPrepend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libname[i]);
56: PetscFree(libname[i]);
57: }
59: PetscStrcpy(libs,"${PETSC_LIB_DIR}");
60: PetscStrcat(libs,"/libpetsc");
61: PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
62: if (found) {
63: PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
64: } else {
65: SETERRQ1(PETSC_ERR_FILE_OPEN,"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);
66: }
68: PetscStrcpy(libs,"${PETSC_LIB_DIR}");
69: PetscStrcat(libs,"/libpetscvec");
70: PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
71: if (found) {
72: PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
73: }
75: PetscStrcpy(libs,"${PETSC_LIB_DIR}");
76: PetscStrcat(libs,"/libpetscmat");
77: PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
78: if (found) {
79: PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
80: }
82: PetscStrcpy(libs,"${PETSC_LIB_DIR}");
83: PetscStrcat(libs,"/libpetscdm");
84: PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
85: if (found) {
86: PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
87: }
89: PetscStrcpy(libs,"${PETSC_LIB_DIR}");
90: PetscStrcat(libs,"/libpetscksp");
91: PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
92: if (found) {
93: PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
94: }
96: PetscStrcpy(libs,"${PETSC_LIB_DIR}");
97: PetscStrcat(libs,"/libpetscsnes");
98: PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
99: if (found) {
100: PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
101: }
103: PetscStrcpy(libs,"${PETSC_LIB_DIR}");
104: PetscStrcat(libs,"/libpetscts");
105: PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
106: if (found) {
107: PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
108: }
110: PetscStrcpy(libs,"${PETSC_LIB_DIR}");
111: PetscStrcat(libs,"/libpetscdm");
112: PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
113: if (found) {
114: PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
115: }
117: PetscStrcpy(libs,"${PETSC_LIB_DIR}");
118: PetscStrcat(libs,"/libpetscmesh");
119: PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
120: if (found) {
121: PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
122: }
124: PetscStrcpy(libs,"${PETSC_LIB_DIR}");
125: PetscStrcat(libs,"/libpetsccontrib");
126: PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
127: if (found) {
128: PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
129: }
131: nmax = 32;
132: PetscOptionsGetStringArray(PETSC_NULL,"-dll_append",libname,&nmax,PETSC_NULL);
133: for (i=0; i<nmax; i++) {
134: PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libname[i]);
135: PetscDLLibraryCCAAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libname[i]);
136: PetscFree(libname[i]);
137: }
139: return(0);
140: }
144: /*
145: PetscFinalize_DynamicLibraries - Closes the opened dynamic libraries.
146: */
147: PetscErrorCode PetscFinalize_DynamicLibraries(void)
148: {
150: PetscTruth flg;
153: PetscOptionsHasName(PETSC_NULL,"-dll_view",&flg);
154: if (flg) {
155: PetscDLLibraryPrintPath();
156: }
157: PetscDLLibraryClose(DLLibrariesLoaded);
158: return(0);
159: }
161: #else /* not using dynamic libraries */
165: PetscErrorCode 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: PetscErrorCode PetscFinalize_DynamicLibraries(void)
181: {
184: return(0);
185: }
186: #endif
188: /* ------------------------------------------------------------------------------*/
189: struct _n_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: Not Collective
211: Input Parameters:
212: + fl - pointer registry
213: . name - string to identify routine
214: . rname - routine name in dynamic library
215: - fnc - function pointer (optional if using dynamic libraries)
217: Notes:
218: To remove a registered routine, pass in a PETSC_NULL rname and fnc().
220: Users who wish to register new classes for use by a particular PETSc
221: component (e.g., SNES) should generally call the registration routine
222: for that particular component (e.g., SNESRegisterDynamic()) instead of
223: calling PetscFListAddDynamic() directly.
225: ${PETSC_ARCH}, ${PETSC_DIR}, ${PETSC_LIB_DIR}, or ${any environmental variable}
226: occuring in pathname will be replaced with appropriate values.
228: Level: developer
230: .seealso: PetscFListDestroy(), SNESRegisterDynamic(), KSPRegisterDynamic(),
231: PCRegisterDynamic(), TSRegisterDynamic(), PetscFList
232: @*/
233: PetscErrorCode PetscFListAdd(PetscFList *fl,const char name[],const char rname[],void (*fnc)(void))
234: {
235: PetscFList entry,ne;
237: char *fpath,*fname;
241: if (!*fl) {
242: PetscNew(struct _n_PetscFList,&entry);
243: PetscStrallocpy(name,&entry->name);
244: PetscFListGetPathAndFunction(rname,&fpath,&fname);
245: entry->path = fpath;
246: entry->rname = fname;
247: entry->routine = fnc;
248: entry->next = 0;
249: *fl = entry;
251: /* add this new list to list of all lists */
252: if (!dlallhead) {
253: dlallhead = *fl;
254: (*fl)->next_list = 0;
255: } else {
256: ne = dlallhead;
257: dlallhead = *fl;
258: (*fl)->next_list = ne;
259: }
260: } else {
261: /* search list to see if it is already there */
262: ne = *fl;
263: while (ne) {
264: PetscTruth founddup;
266: PetscStrcmp(ne->name,name,&founddup);
267: if (founddup) { /* found duplicate */
268: PetscFListGetPathAndFunction(rname,&fpath,&fname);
269: PetscStrfree(ne->path);
270: PetscStrfree(ne->rname);
271: ne->path = fpath;
272: ne->rname = fname;
273: ne->routine = fnc;
274: return(0);
275: }
276: if (ne->next) ne = ne->next; else break;
277: }
278: /* create new entry and add to end of list */
279: PetscNew(struct _n_PetscFList,&entry);
280: PetscStrallocpy(name,&entry->name);
281: PetscFListGetPathAndFunction(rname,&fpath,&fname);
282: entry->path = fpath;
283: entry->rname = fname;
284: entry->routine = fnc;
285: entry->next = 0;
286: ne->next = entry;
287: }
289: return(0);
290: }
294: /*@
295: PetscFListDestroy - Destroys a list of registered routines.
297: Input Parameter:
298: . fl - pointer to list
300: Level: developer
302: .seealso: PetscFListAddDynamic(), PetscFList
303: @*/
304: PetscErrorCode PetscFListDestroy(PetscFList *fl)
305: {
306: PetscFList next,entry,tmp = dlallhead;
310: if (!*fl) return(0);
312: if (!dlallhead) {
313: return(0);
314: }
316: /*
317: Remove this entry from the master DL list (if it is in it)
318: */
319: if (dlallhead == *fl) {
320: if (dlallhead->next_list) {
321: dlallhead = dlallhead->next_list;
322: } else {
323: dlallhead = 0;
324: }
325: } else {
326: while (tmp->next_list != *fl) {
327: tmp = tmp->next_list;
328: if (!tmp->next_list) break;
329: }
330: if (tmp->next_list) tmp->next_list = tmp->next_list->next_list;
331: }
333: /* free this list */
334: entry = *fl;
335: while (entry) {
336: next = entry->next;
337: PetscStrfree(entry->path);
338: PetscFree(entry->name);
339: PetscFree(entry->rname);
340: PetscFree(entry);
341: entry = next;
342: }
343: *fl = 0;
344: return(0);
345: }
347: /*
348: Destroys all the function lists that anyone has every registered, such as KSPList, VecList, etc.
349: */
352: PetscErrorCode PetscFListDestroyAll(void)
353: {
354: PetscFList tmp2,tmp1 = dlallhead;
358: while (tmp1) {
359: tmp2 = tmp1->next_list;
360: PetscFListDestroy(&tmp1);
361: tmp1 = tmp2;
362: }
363: dlallhead = 0;
364: return(0);
365: }
369: /*@C
370: PetscFListFind - Given a name, finds the matching routine.
372: Input Parameters:
373: + comm - processors looking for routine
374: . fl - pointer to list
375: - name - name string
377: Output Parameters:
378: . r - the routine
380: Level: developer
382: .seealso: PetscFListAddDynamic(), PetscFList
383: @*/
384: PetscErrorCode PetscFListFind(MPI_Comm comm,PetscFList fl,const char name[],void (**r)(void))
385: {
386: PetscFList entry = fl;
388: char *function,*path;
389: #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
390: char *newpath;
391: #endif
392: PetscTruth flg,f1,f2,f3;
393:
395: if (!name) SETERRQ(PETSC_ERR_ARG_NULL,"Trying to find routine with null name");
397: *r = 0;
398: PetscFListGetPathAndFunction(name,&path,&function);
400: /*
401: If path then append it to search libraries
402: */
403: #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
404: if (path) {
405: PetscDLLibraryAppend(comm,&DLLibrariesLoaded,path);
406: }
407: #endif
409: while (entry) {
410: flg = PETSC_FALSE;
411: if (path && entry->path) {
412: PetscStrcmp(path,entry->path,&f1);
413: PetscStrcmp(function,entry->rname,&f2);
414: PetscStrcmp(function,entry->name,&f3);
415: flg = (PetscTruth) ((f1 && f2) || (f1 && f3));
416: } else if (!path) {
417: PetscStrcmp(function,entry->name,&f1);
418: PetscStrcmp(function,entry->rname,&f2);
419: flg = (PetscTruth) (f1 || f2);
420: } else {
421: PetscStrcmp(function,entry->name,&flg);
422: if (flg) {
423: PetscFree(function);
424: PetscStrallocpy(entry->rname,&function);
425: } else {
426: PetscStrcmp(function,entry->rname,&flg);
427: }
428: }
430: if (flg) {
432: if (entry->routine) {
433: *r = entry->routine;
434: PetscStrfree(path);
435: PetscFree(function);
436: return(0);
437: }
438:
439: if ((path && entry->path && f3) || (!path && f1)) { /* convert name of function (alias) to actual function name */
440: PetscFree(function);
441: PetscStrallocpy(entry->rname,&function);
442: }
444: /* it is not yet in memory so load from dynamic library */
445: #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
446: newpath = path;
447: if (!path) newpath = entry->path;
448: PetscDLLibrarySym(comm,&DLLibrariesLoaded,newpath,entry->rname,(void **)r);
449: if (*r) {
450: entry->routine = *r;
451: PetscStrfree(path);
452: PetscFree(function);
453: return(0);
454: } else {
455: PetscErrorPrintf("Unable to find function. Search path:\n");
456: PetscDLLibraryPrintPath();
457: SETERRQ1(PETSC_ERR_PLIB,"Unable to find function:%s: either it is mis-spelled or dynamic library is not in path",entry->rname);
458: }
459: #endif
460: }
461: entry = entry->next;
462: }
464: #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
465: /* Function never registered; try for it anyway */
466: PetscDLLibrarySym(comm,&DLLibrariesLoaded,path,function,(void **)r);
467: PetscStrfree(path);
468: if (*r) {
469: PetscFListAdd(&fl,name,name,*r);
470: }
471: #endif
472: PetscFree(function);
473: return(0);
474: }
478: /*@
479: PetscFListView - prints out contents of an PetscFList
481: Collective over MPI_Comm
483: Input Parameters:
484: + list - the list of functions
485: - viewer - currently ignored
487: Level: developer
489: .seealso: PetscFListAddDynamic(), PetscFListPrintTypes(), PetscFList
490: @*/
491: PetscErrorCode PetscFListView(PetscFList list,PetscViewer viewer)
492: {
494: PetscTruth iascii;
497: if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;
500:
501: PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);
502: if (!iascii) SETERRQ(PETSC_ERR_SUP,"Only ASCII viewer supported");
504: while (list) {
505: if (list->path) {
506: PetscViewerASCIIPrintf(viewer," %s %s %s\n",list->path,list->name,list->rname);
507: } else {
508: PetscViewerASCIIPrintf(viewer," %s %s\n",list->name,list->rname);
509: }
510: list = list->next;
511: }
512: PetscViewerASCIIPrintf(viewer,"\n");
513: return(0);
514: }
518: /*@
519: PetscFListGet - Gets an array the contains the entries in PetscFList, this is used
520: by help etc.
522: Collective over MPI_Comm
524: Input Parameter:
525: . list - list of types
527: Output Parameter:
528: + array - array of names
529: - n - length of array
531: Notes:
532: This allocates the array so that must be freed. BUT the individual entries are
533: not copied so should not be freed.
535: Level: developer
537: .seealso: PetscFListAddDynamic(), PetscFList
538: @*/
539: PetscErrorCode PetscFListGet(PetscFList list,char ***array,int *n)
540: {
542: PetscInt count = 0;
543: PetscFList klist = list;
546: while (list) {
547: list = list->next;
548: count++;
549: }
550: PetscMalloc((count+1)*sizeof(char *),array);
551: count = 0;
552: while (klist) {
553: (*array)[count] = klist->name;
554: klist = klist->next;
555: count++;
556: }
557: (*array)[count] = 0;
558: *n = count+1;
560: return(0);
561: }
566: /*@C
567: PetscFListPrintTypes - Prints the methods available.
569: Collective over MPI_Comm
571: Input Parameters:
572: + comm - the communicator (usually MPI_COMM_WORLD)
573: . fd - file to print to, usually stdout
574: . prefix - prefix to prepend to name (optional)
575: . name - option string (for example, "-ksp_type")
576: . text - short description of the object (for example, "Krylov solvers")
577: . man - name of manual page that discusses the object (for example, "KSPCreate")
578: - list - list of types
580: Level: developer
582: .seealso: PetscFListAddDynamic(), PetscFList
583: @*/
584: PetscErrorCode PetscFListPrintTypes(MPI_Comm comm,FILE *fd,const char prefix[],const char name[],const char text[],const char man[],PetscFList list)
585: {
587: PetscInt count = 0;
588: char p[64];
591: if (!fd) fd = stdout;
593: PetscStrcpy(p,"-");
594: if (prefix) {PetscStrcat(p,prefix);}
595: PetscFPrintf(comm,fd," %s%s %s:(one of)",p,name+1,text);
597: while (list) {
598: PetscFPrintf(comm,fd," %s",list->name);
599: list = list->next;
600: count++;
601: if (count == 8) {PetscFPrintf(comm,fd,"\n ");}
602: }
603: PetscFPrintf(comm,fd," (%s)\n",man);
604: return(0);
605: }
609: /*@
610: PetscFListDuplicate - Creates a new list from a given object list.
612: Input Parameters:
613: . fl - pointer to list
615: Output Parameters:
616: . nl - the new list (should point to 0 to start, otherwise appends)
618: Level: developer
620: .seealso: PetscFList, PetscFListAdd(), PetscFlistDestroy()
622: @*/
623: PetscErrorCode PetscFListDuplicate(PetscFList fl,PetscFList *nl)
624: {
626: char path[PETSC_MAX_PATH_LEN];
629: while (fl) {
630: /* this is silly, rebuild the complete pathname */
631: if (fl->path) {
632: PetscStrcpy(path,fl->path);
633: PetscStrcat(path,":");
634: PetscStrcat(path,fl->name);
635: } else {
636: PetscStrcpy(path,fl->name);
637: }
638: PetscFListAdd(nl,path,fl->rname,fl->routine);
639: fl = fl->next;
640: }
641: return(0);
642: }
647: /*
648: PetscFListConcat - joins name of a libary, and the path where it is located
649: into a single string.
651: Input Parameters:
652: . path - path to the library name.
653: . name - name of the library
655: Output Parameters:
656: . fullname - the name that is the union of the path and the library name,
657: delimited by a semicolon, i.e., path:name
659: Notes:
660: If the path is NULL, assumes that the name, specified also includes
661: the path as path:name
663: */
664: PetscErrorCode PetscFListConcat(const char path[],const char name[],char fullname[])
665: {
668: if (path) {
669: PetscStrcpy(fullname,path);
670: PetscStrcat(fullname,":");
671: PetscStrcat(fullname,name);
672: } else {
673: PetscStrcpy(fullname,name);
674: }
675: return(0);
676: }