Actual source code: reg.c
1: /*
2: Provides a general mechanism to allow one to register new routines in
3: dynamic libraries for many of the PETSc objects (including, e.g., KSP and PC).
4: */
5: #include petsc.h
6: #include petscsys.h
10: PetscErrorCode PetscFListGetPathAndFunction(const char name[],char *path[],char *function[])
11: {
13: char work[PETSC_MAX_PATH_LEN],*lfunction;
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: PetscErrorCode PetscInitialize_DynamicLibraries(void)
43: {
44: char *libname[32],libs[PETSC_MAX_PATH_LEN],dlib[PETSC_MAX_PATH_LEN];
46: PetscInt nmax,i;
47: PetscTruth found;
51: nmax = 32;
52: PetscOptionsGetStringArray(PETSC_NULL,"-dll_prepend",libname,&nmax,PETSC_NULL);
53: for (i=0; i<nmax; i++) {
54: PetscDLLibraryPrepend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libname[i]);
55: PetscFree(libname[i]);
56: }
58: PetscStrcpy(libs,PETSC_LIB_DIR);
59: PetscStrcat(libs,"/libpetsc");
60: PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
61: if (found) {
62: PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
63: } else {
64: 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);
65: }
67: PetscStrcpy(libs,PETSC_LIB_DIR);
68: PetscStrcat(libs,"/libpetscvec");
69: PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
70: if (found) {
71: PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
72: }
74: PetscStrcpy(libs,PETSC_LIB_DIR);
75: PetscStrcat(libs,"/libpetscmat");
76: PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
77: if (found) {
78: PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
79: }
81: PetscStrcpy(libs,PETSC_LIB_DIR);
82: PetscStrcat(libs,"/libpetscdm");
83: PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
84: if (found) {
85: PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
86: }
88: PetscStrcpy(libs,PETSC_LIB_DIR);
89: PetscStrcat(libs,"/libpetscksp");
90: PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
91: if (found) {
92: PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
93: }
95: PetscStrcpy(libs,PETSC_LIB_DIR);
96: PetscStrcat(libs,"/libpetscsnes");
97: PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
98: if (found) {
99: PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
100: }
102: PetscStrcpy(libs,PETSC_LIB_DIR);
103: PetscStrcat(libs,"/libpetscts");
104: PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
105: if (found) {
106: PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
107: }
109: PetscStrcpy(libs,PETSC_LIB_DIR);
110: PetscStrcat(libs,"/libpetscdm");
111: PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
112: if (found) {
113: PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
114: }
116: PetscStrcpy(libs,PETSC_LIB_DIR);
117: PetscStrcat(libs,"/libpetscmesh");
118: PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
119: if (found) {
120: PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
121: }
123: PetscStrcpy(libs,PETSC_LIB_DIR);
124: PetscStrcat(libs,"/libpetscgrid");
125: PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,&found);
126: if (found) {
127: PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libs);
128: }
130: nmax = 32;
131: PetscOptionsGetStringArray(PETSC_NULL,"-dll_append",libname,&nmax,PETSC_NULL);
132: for (i=0; i<nmax; i++) {
133: PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libname[i]);
134: PetscDLLibraryCCAAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libname[i]);
135: PetscFree(libname[i]);
136: }
138: return(0);
139: }
143: /*
144: PetscFinalize_DynamicLibraries - Closes the opened dynamic libraries.
145: */
146: PetscErrorCode PetscFinalize_DynamicLibraries(void)
147: {
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 PetscErrorCode PetscInitializePackage(char *);
166: PetscErrorCode PetscInitialize_DynamicLibraries(void)
167: {
171: /*
172: This just initializes the draw and viewer methods, since those
173: are ALWAYS available. The other classes are initialized the first
174: time an XXSetType() is called.
175: */
176: PetscInitializePackage(PETSC_NULL);
177: return(0);
178: }
181: PetscErrorCode PetscFinalize_DynamicLibraries(void)
182: {
185: return(0);
186: }
187: #endif
189: /* ------------------------------------------------------------------------------*/
190: struct _PetscFList {
191: void (*routine)(void); /* the routine */
192: char *path; /* path of link library containing routine */
193: char *name; /* string to identify routine */
194: char *rname; /* routine name in dynamic library */
195: PetscFList next; /* next pointer */
196: PetscFList next_list; /* used to maintain list of all lists for freeing */
197: };
199: /*
200: Keep a linked list of PetscFLists so that we can destroy all the left-over ones.
201: */
202: static PetscFList dlallhead = 0;
206: /*@C
207: PetscFListAddDynamic - Given a routine and a string id, saves that routine in the
208: specified registry.
210: Not Collective
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: To remove a registered routine, pass in a PETSC_NULL rname and fnc().
221: Users who wish to register new classes for use by a particular PETSc
222: component (e.g., SNES) should generally call the registration routine
223: for that particular component (e.g., SNESRegisterDynamic()) instead of
224: calling PetscFListAddDynamic() directly.
226: ${PETSC_ARCH}, ${PETSC_DIR}, ${PETSC_LIB_DIR}, ${BOPT}, or ${any environmental variable}
227: occuring in pathname will be replaced with appropriate values.
229: Level: developer
231: .seealso: PetscFListDestroy(), SNESRegisterDynamic(), KSPRegisterDynamic(),
232: PCRegisterDynamic(), TSRegisterDynamic(), PetscFList
233: @*/
234: PetscErrorCode PetscFListAdd(PetscFList *fl,const char name[],const char rname[],void (*fnc)(void))
235: {
236: PetscFList entry,ne;
238: char *fpath,*fname;
242: if (!*fl) {
243: PetscNew(struct _PetscFList,&entry);
244: PetscStrallocpy(name,&entry->name);
245: PetscFListGetPathAndFunction(rname,&fpath,&fname);
246: entry->path = fpath;
247: entry->rname = fname;
248: entry->routine = fnc;
249: entry->next = 0;
250: *fl = entry;
252: /* add this new list to list of all lists */
253: if (!dlallhead) {
254: dlallhead = *fl;
255: (*fl)->next_list = 0;
256: } else {
257: ne = dlallhead;
258: dlallhead = *fl;
259: (*fl)->next_list = ne;
260: }
261: } else {
262: /* search list to see if it is already there */
263: ne = *fl;
264: while (ne) {
265: PetscTruth founddup;
267: PetscStrcmp(ne->name,name,&founddup);
268: if (founddup) { /* found duplicate */
269: PetscFListGetPathAndFunction(rname,&fpath,&fname);
270: PetscStrfree(ne->path);
271: PetscStrfree(ne->rname);
272: ne->path = fpath;
273: ne->rname = fname;
274: ne->routine = fnc;
275: return(0);
276: }
277: if (ne->next) ne = ne->next; else break;
278: }
279: /* create new entry and add to end of list */
280: PetscNew(struct _PetscFList,&entry);
281: PetscStrallocpy(name,&entry->name);
282: PetscFListGetPathAndFunction(rname,&fpath,&fname);
283: entry->path = fpath;
284: entry->rname = fname;
285: entry->routine = fnc;
286: entry->next = 0;
287: ne->next = entry;
288: }
290: return(0);
291: }
295: /*@
296: PetscFListDestroy - Destroys a list of registered routines.
298: Input Parameter:
299: . fl - pointer to list
301: Level: developer
303: .seealso: PetscFListAddDynamic(), PetscFList
304: @*/
305: PetscErrorCode PetscFListDestroy(PetscFList *fl)
306: {
307: PetscFList next,entry,tmp = dlallhead;
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: + comm - processors looking for routine
375: . fl - pointer to list
376: - name - name string
378: Output Parameters:
379: . r - the routine
381: Level: developer
383: .seealso: PetscFListAddDynamic(), PetscFList
384: @*/
385: PetscErrorCode PetscFListFind(MPI_Comm comm,PetscFList fl,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(MPI_Comm comm,FILE *fd,const char prefix[],const char name[],const char text[],const char man[],PetscFList list)
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: }