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: PetscDLLibrary 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: CHKMEMQ;
311: if (!*fl) return(0);
313: if (!dlallhead) {
314: return(0);
315: }
317: /*
318: Remove this entry from the master DL list (if it is in it)
319: */
320: if (dlallhead == *fl) {
321: if (dlallhead->next_list) {
322: dlallhead = dlallhead->next_list;
323: } else {
324: dlallhead = 0;
325: }
326: } else {
327: while (tmp->next_list != *fl) {
328: tmp = tmp->next_list;
329: if (!tmp->next_list) break;
330: }
331: if (tmp->next_list) tmp->next_list = tmp->next_list->next_list;
332: }
334: /* free this list */
335: entry = *fl;
336: while (entry) {
337: next = entry->next;
338: PetscStrfree(entry->path);
339: PetscFree(entry->name);
340: PetscFree(entry->rname);
341: PetscFree(entry);
342: entry = next;
343: }
344: *fl = 0;
345: return(0);
346: }
348: /*
349: Destroys all the function lists that anyone has every registered, such as KSPList, VecList, etc.
350: */
353: PetscErrorCode PetscFListDestroyAll(void)
354: {
355: PetscFList tmp2,tmp1 = dlallhead;
359: while (tmp1) {
360: tmp2 = tmp1->next_list;
361: PetscFListDestroy(&tmp1);
362: tmp1 = tmp2;
363: }
364: dlallhead = 0;
365: return(0);
366: }
370: /*@C
371: PetscFListFind - Given a name, finds the matching routine.
373: Input Parameters:
374: + fl - pointer to list
375: . comm - processors looking for routine
376: - name - name string
378: Output Parameters:
379: . r - the routine
381: Level: developer
383: .seealso: PetscFListAddDynamic(), PetscFList
384: @*/
385: PetscErrorCode PetscFListFind(PetscFList fl,MPI_Comm comm,const char name[],void (**r)(void))
386: {
387: PetscFList entry = fl;
389: char *function,*path;
390: #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
391: char *newpath;
392: #endif
393: PetscTruth flg,f1,f2,f3;
394:
396: if (!name) SETERRQ(PETSC_ERR_ARG_NULL,"Trying to find routine with null name");
398: *r = 0;
399: PetscFListGetPathAndFunction(name,&path,&function);
401: /*
402: If path then append it to search libraries
403: */
404: #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
405: if (path) {
406: PetscDLLibraryAppend(comm,&DLLibrariesLoaded,path);
407: }
408: #endif
410: while (entry) {
411: flg = PETSC_FALSE;
412: if (path && entry->path) {
413: PetscStrcmp(path,entry->path,&f1);
414: PetscStrcmp(function,entry->rname,&f2);
415: PetscStrcmp(function,entry->name,&f3);
416: flg = (PetscTruth) ((f1 && f2) || (f1 && f3));
417: } else if (!path) {
418: PetscStrcmp(function,entry->name,&f1);
419: PetscStrcmp(function,entry->rname,&f2);
420: flg = (PetscTruth) (f1 || f2);
421: } else {
422: PetscStrcmp(function,entry->name,&flg);
423: if (flg) {
424: PetscFree(function);
425: PetscStrallocpy(entry->rname,&function);
426: } else {
427: PetscStrcmp(function,entry->rname,&flg);
428: }
429: }
431: if (flg) {
433: if (entry->routine) {
434: *r = entry->routine;
435: PetscStrfree(path);
436: PetscFree(function);
437: return(0);
438: }
439:
440: if ((path && entry->path && f3) || (!path && f1)) { /* convert name of function (alias) to actual function name */
441: PetscFree(function);
442: PetscStrallocpy(entry->rname,&function);
443: }
445: /* it is not yet in memory so load from dynamic library */
446: #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
447: newpath = path;
448: if (!path) newpath = entry->path;
449: PetscDLLibrarySym(comm,&DLLibrariesLoaded,newpath,entry->rname,(void **)r);
450: if (*r) {
451: entry->routine = *r;
452: PetscStrfree(path);
453: PetscFree(function);
454: return(0);
455: } else {
456: PetscErrorPrintf("Unable to find function. Search path:\n");
457: PetscDLLibraryPrintPath();
458: SETERRQ1(PETSC_ERR_PLIB,"Unable to find function:%s: either it is mis-spelled or dynamic library is not in path",entry->rname);
459: }
460: #endif
461: }
462: entry = entry->next;
463: }
465: #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
466: /* Function never registered; try for it anyway */
467: PetscDLLibrarySym(comm,&DLLibrariesLoaded,path,function,(void **)r);
468: PetscStrfree(path);
469: if (*r) {
470: PetscFListAdd(&fl,name,name,*r);
471: }
472: #endif
473: PetscFree(function);
474: return(0);
475: }
479: /*@
480: PetscFListView - prints out contents of an PetscFList
482: Collective over MPI_Comm
484: Input Parameters:
485: + list - the list of functions
486: - viewer - currently ignored
488: Level: developer
490: .seealso: PetscFListAddDynamic(), PetscFListPrintTypes(), PetscFList
491: @*/
492: PetscErrorCode PetscFListView(PetscFList list,PetscViewer viewer)
493: {
495: PetscTruth iascii;
498: if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;
501:
502: PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);
503: if (!iascii) SETERRQ(PETSC_ERR_SUP,"Only ASCII viewer supported");
505: while (list) {
506: if (list->path) {
507: PetscViewerASCIIPrintf(viewer," %s %s %s\n",list->path,list->name,list->rname);
508: } else {
509: PetscViewerASCIIPrintf(viewer," %s %s\n",list->name,list->rname);
510: }
511: list = list->next;
512: }
513: PetscViewerASCIIPrintf(viewer,"\n");
514: return(0);
515: }
519: /*@
520: PetscFListGet - Gets an array the contains the entries in PetscFList, this is used
521: by help etc.
523: Collective over MPI_Comm
525: Input Parameter:
526: . list - list of types
528: Output Parameter:
529: + array - array of names
530: - n - length of array
532: Notes:
533: This allocates the array so that must be freed. BUT the individual entries are
534: not copied so should not be freed.
536: Level: developer
538: .seealso: PetscFListAddDynamic(), PetscFList
539: @*/
540: PetscErrorCode PetscFListGet(PetscFList list,char ***array,int *n)
541: {
543: PetscInt count = 0;
544: PetscFList klist = list;
547: while (list) {
548: list = list->next;
549: count++;
550: }
551: PetscMalloc((count+1)*sizeof(char *),array);
552: count = 0;
553: while (klist) {
554: (*array)[count] = klist->name;
555: klist = klist->next;
556: count++;
557: }
558: (*array)[count] = 0;
559: *n = count+1;
561: return(0);
562: }
567: /*@C
568: PetscFListPrintTypes - Prints the methods available.
570: Collective over MPI_Comm
572: Input Parameters:
573: + comm - the communicator (usually MPI_COMM_WORLD)
574: . fd - file to print to, usually stdout
575: . prefix - prefix to prepend to name (optional)
576: . name - option string (for example, "-ksp_type")
577: . text - short description of the object (for example, "Krylov solvers")
578: . man - name of manual page that discusses the object (for example, "KSPCreate")
579: - list - list of types
581: Level: developer
583: .seealso: PetscFListAddDynamic(), PetscFList
584: @*/
585: PetscErrorCode PetscFListPrintTypes(PetscFList list,MPI_Comm comm,FILE *fd,const char prefix[],const char name[],const char text[],const char man[])
586: {
588: PetscInt count = 0;
589: char p[64];
592: if (!fd) fd = stdout;
594: PetscStrcpy(p,"-");
595: if (prefix) {PetscStrcat(p,prefix);}
596: PetscFPrintf(comm,fd," %s%s %s:(one of)",p,name+1,text);
598: while (list) {
599: PetscFPrintf(comm,fd," %s",list->name);
600: list = list->next;
601: count++;
602: if (count == 8) {PetscFPrintf(comm,fd,"\n ");}
603: }
604: PetscFPrintf(comm,fd," (%s)\n",man);
605: return(0);
606: }
610: /*@
611: PetscFListDuplicate - Creates a new list from a given object list.
613: Input Parameters:
614: . fl - pointer to list
616: Output Parameters:
617: . nl - the new list (should point to 0 to start, otherwise appends)
619: Level: developer
621: .seealso: PetscFList, PetscFListAdd(), PetscFlistDestroy()
623: @*/
624: PetscErrorCode PetscFListDuplicate(PetscFList fl,PetscFList *nl)
625: {
627: char path[PETSC_MAX_PATH_LEN];
630: while (fl) {
631: /* this is silly, rebuild the complete pathname */
632: if (fl->path) {
633: PetscStrcpy(path,fl->path);
634: PetscStrcat(path,":");
635: PetscStrcat(path,fl->name);
636: } else {
637: PetscStrcpy(path,fl->name);
638: }
639: PetscFListAdd(nl,path,fl->rname,fl->routine);
640: fl = fl->next;
641: }
642: return(0);
643: }
648: /*
649: PetscFListConcat - joins name of a libary, and the path where it is located
650: into a single string.
652: Input Parameters:
653: . path - path to the library name.
654: . name - name of the library
656: Output Parameters:
657: . fullname - the name that is the union of the path and the library name,
658: delimited by a semicolon, i.e., path:name
660: Notes:
661: If the path is NULL, assumes that the name, specified also includes
662: the path as path:name
664: */
665: PetscErrorCode PetscFListConcat(const char path[],const char name[],char fullname[])
666: {
669: if (path) {
670: PetscStrcpy(fullname,path);
671: PetscStrcat(fullname,":");
672: PetscStrcat(fullname,name);
673: } else {
674: PetscStrcpy(fullname,name);
675: }
676: return(0);
677: }