Actual source code: reg.c
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 <petscsys.h> /*I "petscsys.h" I*/
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: /*
30: This is the default list used by PETSc with the PetscDLLibrary register routines
31: */
32: PetscDLLibrary DLLibrariesLoaded = 0;
34: #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
38: static PetscErrorCode PetscLoadDynamicLibrary(const char *name,PetscBool *found)
39: {
40: char libs[PETSC_MAX_PATH_LEN],dlib[PETSC_MAX_PATH_LEN];
44: PetscStrcpy(libs,"${PETSC_LIB_DIR}/libpetsc");
45: PetscStrcat(libs,name);
46: PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,found);
47: if (*found) {
48: PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,dlib);
49: } else {
50: PetscStrcpy(libs,"${PETSC_DIR}/${PETSC_ARCH}/lib/libpetsc");
51: PetscStrcat(libs,name);
52: PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,found);
53: if (*found) {
54: PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,dlib);
55: }
56: }
57: return(0);
58: }
60: #endif
64: /*
65: PetscInitialize_DynamicLibraries - Adds the default dynamic link libraries to the
66: search path.
67: */
68: PetscErrorCode PetscInitialize_DynamicLibraries(void)
69: {
70: char *libname[32];
72: PetscInt nmax,i;
73: #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
74: PetscBool found;
75: #endif
78: nmax = 32;
79: PetscOptionsGetStringArray(PETSC_NULL,"-dll_prepend",libname,&nmax,PETSC_NULL);
80: for (i=0; i<nmax; i++) {
81: PetscDLLibraryPrepend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libname[i]);
82: PetscFree(libname[i]);
83: }
85: #if !defined(PETSC_USE_DYNAMIC_LIBRARIES)
86: /*
87: This just initializes the most basic PETSc stuff.
89: The classes, from PetscDraw to PetscTS, are initialized the first
90: time an XXCreate() is called.
91: */
92: PetscSysInitializePackage(PETSC_NULL);
93: #else
94: #if defined(PETSC_USE_SINGLE_LIBRARY)
95: PetscLoadDynamicLibrary("",&found);
96: if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc dynamic library \n You cannot move the dynamic libraries!");
97: #else
98: PetscLoadDynamicLibrary("sys",&found);
99: if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc dynamic library \n You cannot move the dynamic libraries!");
100: PetscLoadDynamicLibrary("vec",&found);
101: if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc Vec dynamic library \n You cannot move the dynamic libraries!");
102: PetscLoadDynamicLibrary("mat",&found);
103: if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc Mat dynamic library \n You cannot move the dynamic libraries!");
104: PetscLoadDynamicLibrary("dm",&found);
105: if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc DM dynamic library \n You cannot move the dynamic libraries!");
106: PetscLoadDynamicLibrary("characteristic",&found);
107: if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc Characteristic dynamic library \n You cannot move the dynamic libraries!");
108: PetscLoadDynamicLibrary("ksp",&found);
109: if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc KSP dynamic library \n You cannot move the dynamic libraries!");
110: PetscLoadDynamicLibrary("snes",&found);
111: if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc SNES dynamic library \n You cannot move the dynamic libraries!");
112: PetscLoadDynamicLibrary("ts",&found);
113: if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc TS dynamic library \n You cannot move the dynamic libraries!");
114: #endif
116: PetscLoadDynamicLibrary("mesh",&found);
117: PetscLoadDynamicLibrary("contrib",&found);
118: #endif
120: nmax = 32;
121: PetscOptionsGetStringArray(PETSC_NULL,"-dll_append",libname,&nmax,PETSC_NULL);
122: for (i=0; i<nmax; i++) {
123: PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libname[i]);
124: PetscDLLibraryCCAAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libname[i]);
125: PetscFree(libname[i]);
126: }
128: return(0);
129: }
133: /*
134: PetscFinalize_DynamicLibraries - Closes the opened dynamic libraries.
135: */
136: PetscErrorCode PetscFinalize_DynamicLibraries(void)
137: {
139: PetscBool flg = PETSC_FALSE;
142: PetscOptionsGetBool(PETSC_NULL,"-dll_view",&flg,PETSC_NULL);
143: if (flg) { PetscDLLibraryPrintPath(DLLibrariesLoaded); }
144: PetscDLLibraryClose(DLLibrariesLoaded);
145: DLLibrariesLoaded = 0;
146: return(0);
147: }
149: /* ------------------------------------------------------------------------------*/
150: struct _n_PetscFList {
151: void (*routine)(void); /* the routine */
152: char *path; /* path of link library containing routine */
153: char *name; /* string to identify routine */
154: char *rname; /* routine name in dynamic library */
155: PetscFList next; /* next pointer */
156: PetscFList next_list; /* used to maintain list of all lists for freeing */
157: };
159: /*
160: Keep a linked list of PetscFLists so that we can destroy all the left-over ones.
161: */
162: static PetscFList dlallhead = 0;
166: /*@C
167: PetscFListAddDynamic - Given a routine and a string id, saves that routine in the
168: specified registry.
170: Not Collective
172: Input Parameters:
173: + fl - pointer registry
174: . name - string to identify routine
175: . rname - routine name in dynamic library
176: - fnc - function pointer (optional if using dynamic libraries)
178: Notes:
179: To remove a registered routine, pass in a PETSC_NULL rname and fnc().
181: Users who wish to register new classes for use by a particular PETSc
182: component (e.g., SNES) should generally call the registration routine
183: for that particular component (e.g., SNESRegisterDynamic()) instead of
184: calling PetscFListAddDynamic() directly.
186: ${PETSC_ARCH}, ${PETSC_DIR}, ${PETSC_LIB_DIR}, or ${any environmental variable}
187: occuring in pathname will be replaced with appropriate values.
189: Level: developer
191: .seealso: PetscFListDestroy(), SNESRegisterDynamic(), KSPRegisterDynamic(),
192: PCRegisterDynamic(), TSRegisterDynamic(), PetscFList
193: @*/
194: PetscErrorCode PetscFListAdd(PetscFList *fl,const char name[],const char rname[],void (*fnc)(void))
195: {
196: PetscFList entry,ne;
198: char *fpath,*fname;
201: if (!*fl) {
202: PetscNew(struct _n_PetscFList,&entry);
203: PetscStrallocpy(name,&entry->name);
204: PetscFListGetPathAndFunction(rname,&fpath,&fname);
205: entry->path = fpath;
206: entry->rname = fname;
207: entry->routine = fnc;
208: entry->next = 0;
209: *fl = entry;
211: /* add this new list to list of all lists */
212: if (!dlallhead) {
213: dlallhead = *fl;
214: (*fl)->next_list = 0;
215: } else {
216: ne = dlallhead;
217: dlallhead = *fl;
218: (*fl)->next_list = ne;
219: }
220: } else {
221: /* search list to see if it is already there */
222: ne = *fl;
223: while (ne) {
224: PetscBool founddup;
226: PetscStrcmp(ne->name,name,&founddup);
227: if (founddup) { /* found duplicate */
228: PetscFListGetPathAndFunction(rname,&fpath,&fname);
229: PetscFree(ne->path);
230: PetscFree(ne->rname);
231: ne->path = fpath;
232: ne->rname = fname;
233: ne->routine = fnc;
234: return(0);
235: }
236: if (ne->next) ne = ne->next; else break;
237: }
238: /* create new entry and add to end of list */
239: PetscNew(struct _n_PetscFList,&entry);
240: PetscStrallocpy(name,&entry->name);
241: PetscFListGetPathAndFunction(rname,&fpath,&fname);
242: entry->path = fpath;
243: entry->rname = fname;
244: entry->routine = fnc;
245: entry->next = 0;
246: ne->next = entry;
247: }
248: return(0);
249: }
253: /*@
254: PetscFListDestroy - Destroys a list of registered routines.
256: Input Parameter:
257: . fl - pointer to list
259: Level: developer
261: .seealso: PetscFListAddDynamic(), PetscFList
262: @*/
263: PetscErrorCode PetscFListDestroy(PetscFList *fl)
264: {
265: PetscFList next,entry,tmp = dlallhead;
269: if (!*fl) return(0);
270: if (!dlallhead) return(0);
272: /*
273: Remove this entry from the master DL list (if it is in it)
274: */
275: if (dlallhead == *fl) {
276: if (dlallhead->next_list) {
277: dlallhead = dlallhead->next_list;
278: } else {
279: dlallhead = 0;
280: }
281: } else {
282: while (tmp->next_list != *fl) {
283: tmp = tmp->next_list;
284: if (!tmp->next_list) break;
285: }
286: if (tmp->next_list) tmp->next_list = tmp->next_list->next_list;
287: }
289: /* free this list */
290: entry = *fl;
291: while (entry) {
292: next = entry->next;
293: PetscFree(entry->path);
294: PetscFree(entry->name);
295: PetscFree(entry->rname);
296: PetscFree(entry);
297: entry = next;
298: }
299: *fl = 0;
300: return(0);
301: }
303: /*
304: Destroys all the function lists that anyone has every registered, such as KSPList, VecList, etc.
305: */
308: PetscErrorCode PetscFListDestroyAll(void)
309: {
310: PetscFList tmp2,tmp1 = dlallhead;
314: while (tmp1) {
315: tmp2 = tmp1->next_list;
316: PetscFListDestroy(&tmp1);
317: tmp1 = tmp2;
318: }
319: dlallhead = 0;
320: return(0);
321: }
325: /*@C
326: PetscFListFind - Given a name, finds the matching routine.
328: Input Parameters:
329: + fl - pointer to list
330: . comm - processors looking for routine
331: . name - name string
332: - searchlibraries - if not found in the list then search the dynamic libraries and executable for the symbol
334: Output Parameters:
335: . r - the routine
337: Level: developer
339: .seealso: PetscFListAddDynamic(), PetscFList
340: @*/
341: PetscErrorCode PetscFListFind(PetscFList fl,MPI_Comm comm,const char name[],PetscBool searchlibraries,void (**r)(void))
342: {
343: PetscFList entry = fl;
345: char *function,*path;
346: PetscBool flg,f1,f2,f3;
347: #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES)
348: char *newpath;
349: #endif
350:
352: if (!name) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Trying to find routine with null name");
354: *r = 0;
355: PetscFListGetPathAndFunction(name,&path,&function);
357: /*
358: If path then append it to search libraries
359: */
360: #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES)
361: if (path) {
362: PetscDLLibraryAppend(comm,&DLLibrariesLoaded,path);
363: }
364: #endif
366: while (entry) {
367: flg = PETSC_FALSE;
368: if (path && entry->path) {
369: PetscStrcmp(path,entry->path,&f1);
370: PetscStrcmp(function,entry->rname,&f2);
371: PetscStrcmp(function,entry->name,&f3);
372: flg = (PetscBool) ((f1 && f2) || (f1 && f3));
373: } else if (!path) {
374: PetscStrcmp(function,entry->name,&f1);
375: PetscStrcmp(function,entry->rname,&f2);
376: flg = (PetscBool) (f1 || f2);
377: } else {
378: PetscStrcmp(function,entry->name,&flg);
379: if (flg) {
380: PetscFree(function);
381: PetscStrallocpy(entry->rname,&function);
382: } else {
383: PetscStrcmp(function,entry->rname,&flg);
384: }
385: }
387: if (flg) {
388: if (entry->routine) {
389: *r = entry->routine;
390: PetscFree(path);
391: PetscFree(function);
392: return(0);
393: }
394: if (!(entry->rname && entry->rname[0])) { /* The entry has been cleared */
395: PetscFree(function);
396: return(0);
397: }
398: if ((path && entry->path && f3) || (!path && f1)) { /* convert name of function (alias) to actual function name */
399: PetscFree(function);
400: PetscStrallocpy(entry->rname,&function);
401: }
403: /* it is not yet in memory so load from dynamic library */
404: #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES)
405: newpath = path;
406: if (!path) newpath = entry->path;
407: PetscDLLibrarySym(comm,&DLLibrariesLoaded,newpath,entry->rname,(void **)r);
408: if (*r) {
409: entry->routine = *r;
410: PetscFree(path);
411: PetscFree(function);
412: return(0);
413: }
414: #endif
415: }
416: entry = entry->next;
417: }
419: #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES)
420: if (searchlibraries) {
421: /* Function never registered; try for it anyway */
422: PetscDLLibrarySym(comm,&DLLibrariesLoaded,path,function,(void **)r);
423: PetscFree(path);
424: if (*r) {
425: PetscFListAdd(&fl,name,name,*r);
426: }
427: }
428: #endif
429: PetscFree(function);
430: return(0);
431: }
435: /*@
436: PetscFListView - prints out contents of an PetscFList
438: Collective over MPI_Comm
440: Input Parameters:
441: + list - the list of functions
442: - viewer - currently ignored
444: Level: developer
446: .seealso: PetscFListAddDynamic(), PetscFListPrintTypes(), PetscFList
447: @*/
448: PetscErrorCode PetscFListView(PetscFList list,PetscViewer viewer)
449: {
451: PetscBool iascii;
454: if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;
457:
458: PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
459: if (!iascii) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only ASCII viewer supported");
461: while (list) {
462: if (list->path) {
463: PetscViewerASCIIPrintf(viewer," %s %s %s\n",list->path,list->name,list->rname);
464: } else {
465: PetscViewerASCIIPrintf(viewer," %s %s\n",list->name,list->rname);
466: }
467: list = list->next;
468: }
469: PetscViewerASCIIPrintf(viewer,"\n");
470: return(0);
471: }
475: /*@
476: PetscFListGet - Gets an array the contains the entries in PetscFList, this is used
477: by help etc.
479: Collective over MPI_Comm
481: Input Parameter:
482: . list - list of types
484: Output Parameter:
485: + array - array of names
486: - n - length of array
488: Notes:
489: This allocates the array so that must be freed. BUT the individual entries are
490: not copied so should not be freed.
492: Level: developer
494: .seealso: PetscFListAddDynamic(), PetscFList
495: @*/
496: PetscErrorCode PetscFListGet(PetscFList list,char ***array,int *n)
497: {
499: PetscInt count = 0;
500: PetscFList klist = list;
503: while (list) {
504: list = list->next;
505: count++;
506: }
507: PetscMalloc((count+1)*sizeof(char *),array);
508: count = 0;
509: while (klist) {
510: (*array)[count] = klist->name;
511: klist = klist->next;
512: count++;
513: }
514: (*array)[count] = 0;
515: *n = count+1;
516: return(0);
517: }
522: /*@C
523: PetscFListPrintTypes - Prints the methods available.
525: Collective over MPI_Comm
527: Input Parameters:
528: + comm - the communicator (usually MPI_COMM_WORLD)
529: . fd - file to print to, usually stdout
530: . prefix - prefix to prepend to name (optional)
531: . name - option string (for example, "-ksp_type")
532: . text - short description of the object (for example, "Krylov solvers")
533: . man - name of manual page that discusses the object (for example, "KSPCreate")
534: . list - list of types
535: - def - default (current) value
537: Level: developer
539: .seealso: PetscFListAddDynamic(), PetscFList
540: @*/
541: PetscErrorCode PetscFListPrintTypes(MPI_Comm comm,FILE *fd,const char prefix[],const char name[],const char text[],const char man[],PetscFList list,const char def[])
542: {
544: PetscInt count = 0;
545: char p[64];
548: if (!fd) fd = PETSC_STDOUT;
550: PetscStrcpy(p,"-");
551: if (prefix) {PetscStrcat(p,prefix);}
552: PetscFPrintf(comm,fd," %s%s <%s>: %s (one of)",p,name+1,def,text);
554: while (list) {
555: PetscFPrintf(comm,fd," %s",list->name);
556: list = list->next;
557: count++;
558: if (count == 8) {PetscFPrintf(comm,fd,"\n ");}
559: }
560: PetscFPrintf(comm,fd," (%s)\n",man);
561: return(0);
562: }
566: /*@
567: PetscFListDuplicate - Creates a new list from a given object list.
569: Input Parameters:
570: . fl - pointer to list
572: Output Parameters:
573: . nl - the new list (should point to 0 to start, otherwise appends)
575: Level: developer
577: .seealso: PetscFList, PetscFListAdd(), PetscFlistDestroy()
579: @*/
580: PetscErrorCode PetscFListDuplicate(PetscFList fl,PetscFList *nl)
581: {
583: char path[PETSC_MAX_PATH_LEN];
586: while (fl) {
587: /* this is silly, rebuild the complete pathname */
588: if (fl->path) {
589: PetscStrcpy(path,fl->path);
590: PetscStrcat(path,":");
591: PetscStrcat(path,fl->name);
592: } else {
593: PetscStrcpy(path,fl->name);
594: }
595: PetscFListAdd(nl,path,fl->rname,fl->routine);
596: fl = fl->next;
597: }
598: return(0);
599: }
604: /*
605: PetscFListConcat - joins name of a libary, and the path where it is located
606: into a single string.
608: Input Parameters:
609: . path - path to the library name.
610: . name - name of the library
612: Output Parameters:
613: . fullname - the name that is the union of the path and the library name,
614: delimited by a semicolon, i.e., path:name
616: Notes:
617: If the path is NULL, assumes that the name, specified also includes
618: the path as path:name
620: */
621: PetscErrorCode PetscFListConcat(const char path[],const char name[],char fullname[])
622: {
625: if (path) {
626: PetscStrcpy(fullname,path);
627: PetscStrcat(fullname,":");
628: PetscStrcat(fullname,name);
629: } else {
630: PetscStrcpy(fullname,name);
631: }
632: return(0);
633: }