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: static PetscErrorCode PetscLoadDynamicLibrary(const char *name,PetscTruth *found)
40: {
41: char libs[PETSC_MAX_PATH_LEN],dlib[PETSC_MAX_PATH_LEN];
45: PetscStrcpy(libs,"${PETSC_LIB_DIR}/libpetsc");
46: PetscStrcat(libs,name);
47: PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,found);
48: if (*found) {
49: PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,dlib);
50: } else {
51: PetscStrcpy(libs,"${PETSC_DIR}/${PETSC_ARCH}/lib/libpetsc");
52: PetscStrcat(libs,name);
53: PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,found);
54: if (*found) {
55: PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,dlib);
56: }
57: }
58: return(0);
59: }
63: /*
64: PetscInitialize_DynamicLibraries - Adds the default dynamic link libraries to the
65: search path.
66: */
67: PetscErrorCode PetscInitialize_DynamicLibraries(void)
68: {
69: char *libname[32];
71: PetscInt nmax,i;
72: PetscTruth found;
76: nmax = 32;
77: PetscOptionsGetStringArray(PETSC_NULL,"-dll_prepend",libname,&nmax,PETSC_NULL);
78: for (i=0; i<nmax; i++) {
79: PetscDLLibraryPrepend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libname[i]);
80: PetscFree(libname[i]);
81: }
83: PetscLoadDynamicLibrary("",&found);
84: if (!found) SETERRQ(PETSC_ERR_FILE_OPEN,"Unable to locate PETSc dynamic library \n You cannot move the dynamic libraries!");
85: PetscLoadDynamicLibrary("vec",&found);
86: if (!found) SETERRQ(PETSC_ERR_FILE_OPEN,"Unable to locate PETSc dynamic library \n You cannot move the dynamic libraries!");
87: PetscLoadDynamicLibrary("mat",&found);
88: if (!found) SETERRQ(PETSC_ERR_FILE_OPEN,"Unable to locate PETSc dynamic library \n You cannot move the dynamic libraries!");
89: PetscLoadDynamicLibrary("dm",&found);
90: if (!found) SETERRQ(PETSC_ERR_FILE_OPEN,"Unable to locate PETSc dynamic library \n You cannot move the dynamic libraries!");
91: PetscLoadDynamicLibrary("ksp",&found);
92: if (!found) SETERRQ(PETSC_ERR_FILE_OPEN,"Unable to locate PETSc dynamic library \n You cannot move the dynamic libraries!");
93: PetscLoadDynamicLibrary("snes",&found);
94: if (!found) SETERRQ(PETSC_ERR_FILE_OPEN,"Unable to locate PETSc dynamic library \n You cannot move the dynamic libraries!");
95: PetscLoadDynamicLibrary("ts",&found);
96: if (!found) SETERRQ(PETSC_ERR_FILE_OPEN,"Unable to locate PETSc dynamic library \n You cannot move the dynamic libraries!");
98: PetscLoadDynamicLibrary("mesh",&found);
99: PetscLoadDynamicLibrary("contrib",&found);
101: nmax = 32;
102: PetscOptionsGetStringArray(PETSC_NULL,"-dll_append",libname,&nmax,PETSC_NULL);
103: for (i=0; i<nmax; i++) {
104: PetscDLLibraryAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libname[i]);
105: PetscDLLibraryCCAAppend(PETSC_COMM_WORLD,&DLLibrariesLoaded,libname[i]);
106: PetscFree(libname[i]);
107: }
108: return(0);
109: }
113: /*
114: PetscFinalize_DynamicLibraries - Closes the opened dynamic libraries.
115: */
116: PetscErrorCode PetscFinalize_DynamicLibraries(void)
117: {
119: PetscTruth flg;
122: PetscOptionsHasName(PETSC_NULL,"-dll_view",&flg);
123: if (flg) {
124: PetscDLLibraryPrintPath();
125: }
126: PetscDLLibraryClose(DLLibrariesLoaded);
127: return(0);
128: }
130: #else /* not using dynamic libraries */
134: PetscErrorCode PetscInitialize_DynamicLibraries(void)
135: {
139: /*
140: This just initializes the draw and viewer methods, since those
141: are ALWAYS available. The other classes are initialized the first
142: time an XXSetType() is called.
143: */
144: PetscInitializePackage(PETSC_NULL);
145: return(0);
146: }
149: PetscErrorCode PetscFinalize_DynamicLibraries(void)
150: {
153: return(0);
154: }
155: #endif
157: /* ------------------------------------------------------------------------------*/
158: struct _n_PetscFList {
159: void (*routine)(void); /* the routine */
160: char *path; /* path of link library containing routine */
161: char *name; /* string to identify routine */
162: char *rname; /* routine name in dynamic library */
163: PetscFList next; /* next pointer */
164: PetscFList next_list; /* used to maintain list of all lists for freeing */
165: };
167: /*
168: Keep a linked list of PetscFLists so that we can destroy all the left-over ones.
169: */
170: static PetscFList dlallhead = 0;
174: /*@C
175: PetscFListAddDynamic - Given a routine and a string id, saves that routine in the
176: specified registry.
178: Not Collective
180: Input Parameters:
181: + fl - pointer registry
182: . name - string to identify routine
183: . rname - routine name in dynamic library
184: - fnc - function pointer (optional if using dynamic libraries)
186: Notes:
187: To remove a registered routine, pass in a PETSC_NULL rname and fnc().
189: Users who wish to register new classes for use by a particular PETSc
190: component (e.g., SNES) should generally call the registration routine
191: for that particular component (e.g., SNESRegisterDynamic()) instead of
192: calling PetscFListAddDynamic() directly.
194: ${PETSC_ARCH}, ${PETSC_DIR}, ${PETSC_LIB_DIR}, or ${any environmental variable}
195: occuring in pathname will be replaced with appropriate values.
197: Level: developer
199: .seealso: PetscFListDestroy(), SNESRegisterDynamic(), KSPRegisterDynamic(),
200: PCRegisterDynamic(), TSRegisterDynamic(), PetscFList
201: @*/
202: PetscErrorCode PetscFListAdd(PetscFList *fl,const char name[],const char rname[],void (*fnc)(void))
203: {
204: PetscFList entry,ne;
206: char *fpath,*fname;
210: if (!*fl) {
211: PetscNew(struct _n_PetscFList,&entry);
212: PetscStrallocpy(name,&entry->name);
213: PetscFListGetPathAndFunction(rname,&fpath,&fname);
214: entry->path = fpath;
215: entry->rname = fname;
216: entry->routine = fnc;
217: entry->next = 0;
218: *fl = entry;
220: /* add this new list to list of all lists */
221: if (!dlallhead) {
222: dlallhead = *fl;
223: (*fl)->next_list = 0;
224: } else {
225: ne = dlallhead;
226: dlallhead = *fl;
227: (*fl)->next_list = ne;
228: }
229: } else {
230: /* search list to see if it is already there */
231: ne = *fl;
232: while (ne) {
233: PetscTruth founddup;
235: PetscStrcmp(ne->name,name,&founddup);
236: if (founddup) { /* found duplicate */
237: PetscFListGetPathAndFunction(rname,&fpath,&fname);
238: PetscStrfree(ne->path);
239: PetscStrfree(ne->rname);
240: ne->path = fpath;
241: ne->rname = fname;
242: ne->routine = fnc;
243: return(0);
244: }
245: if (ne->next) ne = ne->next; else break;
246: }
247: /* create new entry and add to end of list */
248: PetscNew(struct _n_PetscFList,&entry);
249: PetscStrallocpy(name,&entry->name);
250: PetscFListGetPathAndFunction(rname,&fpath,&fname);
251: entry->path = fpath;
252: entry->rname = fname;
253: entry->routine = fnc;
254: entry->next = 0;
255: ne->next = entry;
256: }
258: return(0);
259: }
263: /*@
264: PetscFListDestroy - Destroys a list of registered routines.
266: Input Parameter:
267: . fl - pointer to list
269: Level: developer
271: .seealso: PetscFListAddDynamic(), PetscFList
272: @*/
273: PetscErrorCode PetscFListDestroy(PetscFList *fl)
274: {
275: PetscFList next,entry,tmp = dlallhead;
279: CHKMEMQ;
280: if (!*fl) return(0);
282: if (!dlallhead) {
283: return(0);
284: }
286: /*
287: Remove this entry from the master DL list (if it is in it)
288: */
289: if (dlallhead == *fl) {
290: if (dlallhead->next_list) {
291: dlallhead = dlallhead->next_list;
292: } else {
293: dlallhead = 0;
294: }
295: } else {
296: while (tmp->next_list != *fl) {
297: tmp = tmp->next_list;
298: if (!tmp->next_list) break;
299: }
300: if (tmp->next_list) tmp->next_list = tmp->next_list->next_list;
301: }
303: /* free this list */
304: entry = *fl;
305: while (entry) {
306: next = entry->next;
307: PetscStrfree(entry->path);
308: PetscFree(entry->name);
309: PetscFree(entry->rname);
310: PetscFree(entry);
311: entry = next;
312: }
313: *fl = 0;
314: return(0);
315: }
317: /*
318: Destroys all the function lists that anyone has every registered, such as KSPList, VecList, etc.
319: */
322: PetscErrorCode PetscFListDestroyAll(void)
323: {
324: PetscFList tmp2,tmp1 = dlallhead;
328: while (tmp1) {
329: tmp2 = tmp1->next_list;
330: PetscFListDestroy(&tmp1);
331: tmp1 = tmp2;
332: }
333: dlallhead = 0;
334: return(0);
335: }
339: /*@C
340: PetscFListFind - Given a name, finds the matching routine.
342: Input Parameters:
343: + fl - pointer to list
344: . comm - processors looking for routine
345: - name - name string
347: Output Parameters:
348: . r - the routine
350: Level: developer
352: .seealso: PetscFListAddDynamic(), PetscFList
353: @*/
354: PetscErrorCode PetscFListFind(PetscFList fl,MPI_Comm comm,const char name[],void (**r)(void))
355: {
356: PetscFList entry = fl;
358: char *function,*path;
359: #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
360: char *newpath;
361: #endif
362: PetscTruth flg,f1,f2,f3;
363:
365: if (!name) SETERRQ(PETSC_ERR_ARG_NULL,"Trying to find routine with null name");
367: *r = 0;
368: PetscFListGetPathAndFunction(name,&path,&function);
370: /*
371: If path then append it to search libraries
372: */
373: #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
374: if (path) {
375: PetscDLLibraryAppend(comm,&DLLibrariesLoaded,path);
376: }
377: #endif
379: while (entry) {
380: flg = PETSC_FALSE;
381: if (path && entry->path) {
382: PetscStrcmp(path,entry->path,&f1);
383: PetscStrcmp(function,entry->rname,&f2);
384: PetscStrcmp(function,entry->name,&f3);
385: flg = (PetscTruth) ((f1 && f2) || (f1 && f3));
386: } else if (!path) {
387: PetscStrcmp(function,entry->name,&f1);
388: PetscStrcmp(function,entry->rname,&f2);
389: flg = (PetscTruth) (f1 || f2);
390: } else {
391: PetscStrcmp(function,entry->name,&flg);
392: if (flg) {
393: PetscFree(function);
394: PetscStrallocpy(entry->rname,&function);
395: } else {
396: PetscStrcmp(function,entry->rname,&flg);
397: }
398: }
400: if (flg) {
402: if (entry->routine) {
403: *r = entry->routine;
404: PetscStrfree(path);
405: PetscFree(function);
406: return(0);
407: }
408:
409: if ((path && entry->path && f3) || (!path && f1)) { /* convert name of function (alias) to actual function name */
410: PetscFree(function);
411: PetscStrallocpy(entry->rname,&function);
412: }
414: /* it is not yet in memory so load from dynamic library */
415: #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
416: newpath = path;
417: if (!path) newpath = entry->path;
418: PetscDLLibrarySym(comm,&DLLibrariesLoaded,newpath,entry->rname,(void **)r);
419: if (*r) {
420: entry->routine = *r;
421: PetscStrfree(path);
422: PetscFree(function);
423: return(0);
424: } else {
425: (*PetscErrorPrintf)("Unable to find function. Search path:\n");
426: PetscDLLibraryPrintPath();
427: SETERRQ1(PETSC_ERR_PLIB,"Unable to find function:%s: either it is mis-spelled or dynamic library is not in path",entry->rname);
428: }
429: #endif
430: }
431: entry = entry->next;
432: }
434: #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
435: /* Function never registered; try for it anyway */
436: PetscDLLibrarySym(comm,&DLLibrariesLoaded,path,function,(void **)r);
437: PetscStrfree(path);
438: if (*r) {
439: PetscFListAdd(&fl,name,name,*r);
440: }
441: #endif
442: PetscFree(function);
443: return(0);
444: }
448: /*@
449: PetscFListView - prints out contents of an PetscFList
451: Collective over MPI_Comm
453: Input Parameters:
454: + list - the list of functions
455: - viewer - currently ignored
457: Level: developer
459: .seealso: PetscFListAddDynamic(), PetscFListPrintTypes(), PetscFList
460: @*/
461: PetscErrorCode PetscFListView(PetscFList list,PetscViewer viewer)
462: {
464: PetscTruth iascii;
467: if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;
470:
471: PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);
472: if (!iascii) SETERRQ(PETSC_ERR_SUP,"Only ASCII viewer supported");
474: while (list) {
475: if (list->path) {
476: PetscViewerASCIIPrintf(viewer," %s %s %s\n",list->path,list->name,list->rname);
477: } else {
478: PetscViewerASCIIPrintf(viewer," %s %s\n",list->name,list->rname);
479: }
480: list = list->next;
481: }
482: PetscViewerASCIIPrintf(viewer,"\n");
483: return(0);
484: }
488: /*@
489: PetscFListGet - Gets an array the contains the entries in PetscFList, this is used
490: by help etc.
492: Collective over MPI_Comm
494: Input Parameter:
495: . list - list of types
497: Output Parameter:
498: + array - array of names
499: - n - length of array
501: Notes:
502: This allocates the array so that must be freed. BUT the individual entries are
503: not copied so should not be freed.
505: Level: developer
507: .seealso: PetscFListAddDynamic(), PetscFList
508: @*/
509: PetscErrorCode PetscFListGet(PetscFList list,char ***array,int *n)
510: {
512: PetscInt count = 0;
513: PetscFList klist = list;
516: while (list) {
517: list = list->next;
518: count++;
519: }
520: PetscMalloc((count+1)*sizeof(char *),array);
521: count = 0;
522: while (klist) {
523: (*array)[count] = klist->name;
524: klist = klist->next;
525: count++;
526: }
527: (*array)[count] = 0;
528: *n = count+1;
530: return(0);
531: }
536: /*@C
537: PetscFListPrintTypes - Prints the methods available.
539: Collective over MPI_Comm
541: Input Parameters:
542: + comm - the communicator (usually MPI_COMM_WORLD)
543: . fd - file to print to, usually stdout
544: . prefix - prefix to prepend to name (optional)
545: . name - option string (for example, "-ksp_type")
546: . text - short description of the object (for example, "Krylov solvers")
547: . man - name of manual page that discusses the object (for example, "KSPCreate")
548: - list - list of types
550: Level: developer
552: .seealso: PetscFListAddDynamic(), PetscFList
553: @*/
554: PetscErrorCode PetscFListPrintTypes(PetscFList list,MPI_Comm comm,FILE *fd,const char prefix[],const char name[],const char text[],const char man[])
555: {
557: PetscInt count = 0;
558: char p[64];
561: if (!fd) fd = PETSC_STDOUT;
563: PetscStrcpy(p,"-");
564: if (prefix) {PetscStrcat(p,prefix);}
565: PetscFPrintf(comm,fd," %s%s %s:(one of)",p,name+1,text);
567: while (list) {
568: PetscFPrintf(comm,fd," %s",list->name);
569: list = list->next;
570: count++;
571: if (count == 8) {PetscFPrintf(comm,fd,"\n ");}
572: }
573: PetscFPrintf(comm,fd," (%s)\n",man);
574: return(0);
575: }
579: /*@
580: PetscFListDuplicate - Creates a new list from a given object list.
582: Input Parameters:
583: . fl - pointer to list
585: Output Parameters:
586: . nl - the new list (should point to 0 to start, otherwise appends)
588: Level: developer
590: .seealso: PetscFList, PetscFListAdd(), PetscFlistDestroy()
592: @*/
593: PetscErrorCode PetscFListDuplicate(PetscFList fl,PetscFList *nl)
594: {
596: char path[PETSC_MAX_PATH_LEN];
599: while (fl) {
600: /* this is silly, rebuild the complete pathname */
601: if (fl->path) {
602: PetscStrcpy(path,fl->path);
603: PetscStrcat(path,":");
604: PetscStrcat(path,fl->name);
605: } else {
606: PetscStrcpy(path,fl->name);
607: }
608: PetscFListAdd(nl,path,fl->rname,fl->routine);
609: fl = fl->next;
610: }
611: return(0);
612: }
617: /*
618: PetscFListConcat - joins name of a libary, and the path where it is located
619: into a single string.
621: Input Parameters:
622: . path - path to the library name.
623: . name - name of the library
625: Output Parameters:
626: . fullname - the name that is the union of the path and the library name,
627: delimited by a semicolon, i.e., path:name
629: Notes:
630: If the path is NULL, assumes that the name, specified also includes
631: the path as path:name
633: */
634: PetscErrorCode PetscFListConcat(const char path[],const char name[],char fullname[])
635: {
638: if (path) {
639: PetscStrcpy(fullname,path);
640: PetscStrcat(fullname,":");
641: PetscStrcat(fullname,name);
642: } else {
643: PetscStrcpy(fullname,name);
644: }
645: return(0);
646: }