Actual source code: reg.c
petsc-3.3-p7 2013-05-11
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,sizeof work);
17: work[sizeof work - 1] = 0;
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: /*
31: This is the default list used by PETSc with the PetscDLLibrary register routines
32: */
33: PetscDLLibrary PetscDLLibrariesLoaded = 0;
35: #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
39: static PetscErrorCode PetscLoadDynamicLibrary(const char *name,PetscBool *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,&PetscDLLibrariesLoaded,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,&PetscDLLibrariesLoaded,dlib);
56: }
57: }
58: return(0);
59: }
61: #endif
65: /*
66: PetscInitialize_DynamicLibraries - Adds the default dynamic link libraries to the
67: search path.
68: */
69: PetscErrorCode PetscInitialize_DynamicLibraries(void)
70: {
71: char *libname[32];
73: PetscInt nmax,i;
74: #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
75: PetscBool found;
76: #endif
79: nmax = 32;
80: PetscOptionsGetStringArray(PETSC_NULL,"-dll_prepend",libname,&nmax,PETSC_NULL);
81: for (i=0; i<nmax; i++) {
82: PetscDLLibraryPrepend(PETSC_COMM_WORLD,&PetscDLLibrariesLoaded,libname[i]);
83: PetscFree(libname[i]);
84: }
86: #if !defined(PETSC_USE_DYNAMIC_LIBRARIES)
87: /*
88: This just initializes the most basic PETSc stuff.
90: The classes, from PetscDraw to PetscTS, are initialized the first
91: time an XXCreate() is called.
92: */
93: PetscSysInitializePackage(PETSC_NULL);
94: #else
95: #if defined(PETSC_USE_SINGLE_LIBRARY)
96: PetscLoadDynamicLibrary("",&found);
97: if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc dynamic library \n You cannot move the dynamic libraries!");
98: #else
99: PetscLoadDynamicLibrary("sys",&found);
100: if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc dynamic library \n You cannot move the dynamic libraries!");
101: PetscLoadDynamicLibrary("vec",&found);
102: if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc Vec dynamic library \n You cannot move the dynamic libraries!");
103: PetscLoadDynamicLibrary("mat",&found);
104: if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc Mat dynamic library \n You cannot move the dynamic libraries!");
105: PetscLoadDynamicLibrary("dm",&found);
106: if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc DM dynamic library \n You cannot move the dynamic libraries!");
107: PetscLoadDynamicLibrary("characteristic",&found);
108: if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc Characteristic dynamic library \n You cannot move the dynamic libraries!");
109: PetscLoadDynamicLibrary("ksp",&found);
110: if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc KSP dynamic library \n You cannot move the dynamic libraries!");
111: PetscLoadDynamicLibrary("snes",&found);
112: if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc SNES dynamic library \n You cannot move the dynamic libraries!");
113: PetscLoadDynamicLibrary("ts",&found);
114: if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc TS dynamic library \n You cannot move the dynamic libraries!");
115: #endif
117: PetscLoadDynamicLibrary("mesh",&found);
118: PetscLoadDynamicLibrary("contrib",&found);
119: #endif
121: nmax = 32;
122: PetscOptionsGetStringArray(PETSC_NULL,"-dll_append",libname,&nmax,PETSC_NULL);
123: for (i=0; i<nmax; i++) {
124: PetscDLLibraryAppend(PETSC_COMM_WORLD,&PetscDLLibrariesLoaded,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(PetscDLLibrariesLoaded); }
144: PetscDLLibraryClose(PetscDLLibrariesLoaded);
145: PetscDLLibrariesLoaded = 0;
146: return(0);
147: }
151: /* ------------------------------------------------------------------------------*/
152: struct _n_PetscFList {
153: void (*routine)(void); /* the routine */
154: char *path; /* path of link library containing routine */
155: char *name; /* string to identify routine */
156: char *rname; /* routine name in dynamic library */
157: PetscFList next; /* next pointer */
158: PetscFList next_list; /* used to maintain list of all lists for freeing */
159: };
161: /*
162: Keep a linked list of PetscFLists so that we can destroy all the left-over ones.
163: */
164: static PetscFList dlallhead = 0;
168: /*@C
169: PetscFListAdd - Given a routine and a string id, saves that routine in the
170: specified registry.
172: Not Collective
174: Input Parameters:
175: + fl - pointer registry
176: . name - string to identify routine
177: . rname - routine name in dynamic library
178: - fnc - function pointer (optional if using dynamic libraries)
180: Notes:
181: To remove a registered routine, pass in a PETSC_NULL rname and fnc().
183: Users who wish to register new classes for use by a particular PETSc
184: component (e.g., SNES) should generally call the registration routine
185: for that particular component (e.g., SNESRegisterDynamic()) instead of
186: calling PetscFListAdd() directly.
188: ${PETSC_ARCH}, ${PETSC_DIR}, ${PETSC_LIB_DIR}, or ${any environmental variable}
189: occuring in pathname will be replaced with appropriate values.
191: Level: developer
193: .seealso: PetscFListDestroy(), SNESRegisterDynamic(), KSPRegisterDynamic(),
194: PCRegisterDynamic(), TSRegisterDynamic(), PetscFList
195: @*/
196: PetscErrorCode PetscFListAdd(PetscFList *fl,const char name[],const char rname[],void (*fnc)(void))
197: {
198: PetscFList entry,ne;
200: char *fpath,*fname;
203: if (!*fl) {
204: PetscNew(struct _n_PetscFList,&entry);
205: PetscStrallocpy(name,&entry->name);
206: PetscFListGetPathAndFunction(rname,&fpath,&fname);
207: entry->path = fpath;
208: entry->rname = fname;
209: entry->routine = fnc;
210: entry->next = 0;
211: *fl = entry;
213: /* add this new list to list of all lists */
214: if (!dlallhead) {
215: dlallhead = *fl;
216: (*fl)->next_list = 0;
217: } else {
218: ne = dlallhead;
219: dlallhead = *fl;
220: (*fl)->next_list = ne;
221: }
222: } else {
223: /* search list to see if it is already there */
224: ne = *fl;
225: while (ne) {
226: PetscBool founddup;
228: PetscStrcmp(ne->name,name,&founddup);
229: if (founddup) { /* found duplicate */
230: PetscFListGetPathAndFunction(rname,&fpath,&fname);
231: PetscFree(ne->path);
232: PetscFree(ne->rname);
233: ne->path = fpath;
234: ne->rname = fname;
235: ne->routine = fnc;
236: return(0);
237: }
238: if (ne->next) ne = ne->next; else break;
239: }
240: /* create new entry and add to end of list */
241: PetscNew(struct _n_PetscFList,&entry);
242: PetscStrallocpy(name,&entry->name);
243: PetscFListGetPathAndFunction(rname,&fpath,&fname);
244: entry->path = fpath;
245: entry->rname = fname;
246: entry->routine = fnc;
247: entry->next = 0;
248: ne->next = entry;
249: }
250: return(0);
251: }
255: /*@
256: PetscFListDestroy - Destroys a list of registered routines.
258: Input Parameter:
259: . fl - pointer to list
261: Level: developer
263: .seealso: PetscFListAddDynamic(), PetscFList
264: @*/
265: PetscErrorCode PetscFListDestroy(PetscFList *fl)
266: {
267: PetscFList next,entry,tmp = dlallhead;
271: if (!*fl) return(0);
272: if (!dlallhead) return(0);
274: /*
275: Remove this entry from the master DL list (if it is in it)
276: */
277: if (dlallhead == *fl) {
278: if (dlallhead->next_list) {
279: dlallhead = dlallhead->next_list;
280: } else {
281: dlallhead = 0;
282: }
283: } else {
284: while (tmp->next_list != *fl) {
285: tmp = tmp->next_list;
286: if (!tmp->next_list) break;
287: }
288: if (tmp->next_list) tmp->next_list = tmp->next_list->next_list;
289: }
291: /* free this list */
292: entry = *fl;
293: while (entry) {
294: next = entry->next;
295: PetscFree(entry->path);
296: PetscFree(entry->name);
297: PetscFree(entry->rname);
298: PetscFree(entry);
299: entry = next;
300: }
301: *fl = 0;
302: return(0);
303: }
305: /*
306: Destroys all the function lists that anyone has every registered, such as KSPList, VecList, etc.
307: */
310: PetscErrorCode PetscFListDestroyAll(void)
311: {
312: PetscFList tmp2,tmp1 = dlallhead;
316: while (tmp1) {
317: tmp2 = tmp1->next_list;
318: PetscFListDestroy(&tmp1);
319: tmp1 = tmp2;
320: }
321: dlallhead = 0;
322: return(0);
323: }
327: /*@C
328: PetscFListFind - Given a name, finds the matching routine.
330: Input Parameters:
331: + fl - pointer to list
332: . comm - processors looking for routine
333: . name - name string
334: - searchlibraries - if not found in the list then search the dynamic libraries and executable for the symbol
336: Output Parameters:
337: . r - the routine
339: Level: developer
341: .seealso: PetscFListAddDynamic(), PetscFList
342: @*/
343: PetscErrorCode PetscFListFind(PetscFList fl,MPI_Comm comm,const char name[],PetscBool searchlibraries,void (**r)(void))
344: {
345: PetscFList entry = fl;
347: char *function,*path;
348: PetscBool flg,f1,f2,f3;
349: #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES)
350: char *newpath;
351: #endif
352:
354: if (!name) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Trying to find routine with null name");
356: *r = 0;
357: PetscFListGetPathAndFunction(name,&path,&function);
359: /*
360: If path then append it to search libraries
361: */
362: #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES)
363: if (path) {
364: PetscDLLibraryAppend(comm,&PetscDLLibrariesLoaded,path);
365: }
366: #endif
368: while (entry) {
369: flg = PETSC_FALSE;
370: if (path && entry->path) {
371: PetscStrcmp(path,entry->path,&f1);
372: PetscStrcmp(function,entry->rname,&f2);
373: PetscStrcmp(function,entry->name,&f3);
374: flg = (PetscBool) ((f1 && f2) || (f1 && f3));
375: } else if (!path) {
376: PetscStrcmp(function,entry->name,&f1);
377: PetscStrcmp(function,entry->rname,&f2);
378: flg = (PetscBool) (f1 || f2);
379: } else {
380: PetscStrcmp(function,entry->name,&flg);
381: if (flg) {
382: PetscFree(function);
383: PetscStrallocpy(entry->rname,&function);
384: } else {
385: PetscStrcmp(function,entry->rname,&flg);
386: }
387: }
389: if (flg) {
390: if (entry->routine) {
391: *r = entry->routine;
392: PetscFree(path);
393: PetscFree(function);
394: return(0);
395: }
396: if (!(entry->rname && entry->rname[0])) { /* The entry has been cleared */
397: PetscFree(function);
398: return(0);
399: }
400: if ((path && entry->path && f3) || (!path && f1)) { /* convert name of function (alias) to actual function name */
401: PetscFree(function);
402: PetscStrallocpy(entry->rname,&function);
403: }
405: /* it is not yet in memory so load from dynamic library */
406: #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES)
407: newpath = path;
408: if (!path) newpath = entry->path;
409: PetscDLLibrarySym(comm,&PetscDLLibrariesLoaded,newpath,entry->rname,(void **)r);
410: if (*r) {
411: entry->routine = *r;
412: PetscFree(path);
413: PetscFree(function);
414: return(0);
415: }
416: #endif
417: }
418: entry = entry->next;
419: }
421: #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES)
422: if (searchlibraries) {
423: /* Function never registered; try for it anyway */
424: PetscDLLibrarySym(comm,&PetscDLLibrariesLoaded,path,function,(void **)r);
425: PetscFree(path);
426: if (*r) {
427: PetscFListAdd(&fl,name,name,*r);
428: }
429: }
430: #endif
431: PetscFree(function);
432: return(0);
433: }
437: /*@
438: PetscFListView - prints out contents of an PetscFList
440: Collective over MPI_Comm
442: Input Parameters:
443: + list - the list of functions
444: - viewer - currently ignored
446: Level: developer
448: .seealso: PetscFListAddDynamic(), PetscFListPrintTypes(), PetscFList
449: @*/
450: PetscErrorCode PetscFListView(PetscFList list,PetscViewer viewer)
451: {
453: PetscBool iascii;
456: if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;
459:
460: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
461: if (!iascii) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only ASCII viewer supported");
463: while (list) {
464: if (list->path) {
465: PetscViewerASCIIPrintf(viewer," %s %s %s\n",list->path,list->name,list->rname);
466: } else {
467: PetscViewerASCIIPrintf(viewer," %s %s\n",list->name,list->rname);
468: }
469: list = list->next;
470: }
471: PetscViewerASCIIPrintf(viewer,"\n");
472: return(0);
473: }
477: /*@
478: PetscFListGet - Gets an array the contains the entries in PetscFList, this is used
479: by help etc.
481: Collective over MPI_Comm
483: Input Parameter:
484: . list - list of types
486: Output Parameter:
487: + array - array of names
488: - n - length of array
490: Notes:
491: This allocates the array so that must be freed. BUT the individual entries are
492: not copied so should not be freed.
494: Level: developer
496: .seealso: PetscFListAddDynamic(), PetscFList
497: @*/
498: PetscErrorCode PetscFListGet(PetscFList list,char ***array,int *n)
499: {
501: PetscInt count = 0;
502: PetscFList klist = list;
505: while (list) {
506: list = list->next;
507: count++;
508: }
509: PetscMalloc((count+1)*sizeof(char *),array);
510: count = 0;
511: while (klist) {
512: (*array)[count] = klist->name;
513: klist = klist->next;
514: count++;
515: }
516: (*array)[count] = 0;
517: *n = count+1;
518: return(0);
519: }
524: /*@C
525: PetscFListPrintTypes - Prints the methods available.
527: Collective over MPI_Comm
529: Input Parameters:
530: + comm - the communicator (usually MPI_COMM_WORLD)
531: . fd - file to print to, usually stdout
532: . prefix - prefix to prepend to name (optional)
533: . name - option string (for example, "-ksp_type")
534: . text - short description of the object (for example, "Krylov solvers")
535: . man - name of manual page that discusses the object (for example, "KSPCreate")
536: . list - list of types
537: - def - default (current) value
539: Level: developer
541: .seealso: PetscFListAddDynamic(), PetscFList
542: @*/
543: PetscErrorCode PetscFListPrintTypes(MPI_Comm comm,FILE *fd,const char prefix[],const char name[],const char text[],const char man[],PetscFList list,const char def[])
544: {
546: PetscInt count = 0;
547: char p[64];
550: if (!fd) fd = PETSC_STDOUT;
552: PetscStrcpy(p,"-");
553: if (prefix) {PetscStrcat(p,prefix);}
554: PetscFPrintf(comm,fd," %s%s <%s>: %s (one of)",p,name+1,def,text);
556: while (list) {
557: PetscFPrintf(comm,fd," %s",list->name);
558: list = list->next;
559: count++;
560: if (count == 8) {PetscFPrintf(comm,fd,"\n ");}
561: }
562: PetscFPrintf(comm,fd," (%s)\n",man);
563: return(0);
564: }
568: /*@
569: PetscFListDuplicate - Creates a new list from a given object list.
571: Input Parameters:
572: . fl - pointer to list
574: Output Parameters:
575: . nl - the new list (should point to 0 to start, otherwise appends)
577: Level: developer
579: .seealso: PetscFList, PetscFListAdd(), PetscFlistDestroy()
581: @*/
582: PetscErrorCode PetscFListDuplicate(PetscFList fl,PetscFList *nl)
583: {
585: char path[PETSC_MAX_PATH_LEN];
588: while (fl) {
589: /* this is silly, rebuild the complete pathname */
590: if (fl->path) {
591: PetscStrcpy(path,fl->path);
592: PetscStrcat(path,":");
593: PetscStrcat(path,fl->name);
594: } else {
595: PetscStrcpy(path,fl->name);
596: }
597: PetscFListAdd(nl,path,fl->rname,fl->routine);
598: fl = fl->next;
599: }
600: return(0);
601: }
606: /*
607: PetscFListConcat - joins name of a libary, and the path where it is located
608: into a single string.
610: Input Parameters:
611: . path - path to the library name.
612: . name - name of the library
614: Output Parameters:
615: . fullname - the name that is the union of the path and the library name,
616: delimited by a semicolon, i.e., path:name
618: Notes:
619: If the path is NULL, assumes that the name, specified also includes
620: the path as path:name
622: */
623: PetscErrorCode PetscFListConcat(const char path[],const char name[],char fullname[])
624: {
627: if (path) {
628: PetscStrcpy(fullname,path);
629: PetscStrcat(fullname,":");
630: PetscStrcat(fullname,name);
631: } else {
632: PetscStrcpy(fullname,name);
633: }
634: return(0);
635: }
639: /* ------------------------------------------------------------------------------*/
640: struct _n_PetscOpFList {
641: char *op; /* op name */
642: PetscInt numArgs; /* number of arguments to the operation */
643: char **argTypes; /* list of argument types */
644: PetscVoidFunction routine; /* the routine */
645: char *url; /* url naming the link library and the routine */
646: char *path; /* path of link library containing routine */
647: char *name; /* routine name in dynamic library */
648: PetscOpFList next; /* next pointer */
649: PetscOpFList next_list; /* used to maintain list of all lists for freeing */
650: };
652: /*
653: Keep a linked list of PetscOfFLists so that we can destroy all the left-over ones.
654: */
655: static PetscOpFList opallhead = 0;
659: /*@C
660: PetscOpFListAdd - Given a routine and a string id, saves that routine in the
661: specified registry.
663: Formally collective on comm.
665: Input Parameters:
666: + comm - processors adding the op
667: . fl - list of known ops
668: . url - routine locator (optional, if not using dynamic libraries and a nonempty fnc)
669: . fnc - function pointer (optional, if using dynamic libraries and a nonempty url)
670: . op - operation name
671: . numArgs - number of op arguments
672: - argTypes - list of argument type names (const char*)
674: Notes:
675: To remove a registered routine, pass in a PETSC_NULL url and fnc().
677: url can be of the form [/path/libname[.so.1.0]:]functionname[()] where items in [] denote optional
679: ${PETSC_ARCH}, ${PETSC_DIR}, ${PETSC_LIB_DIR}, or ${any environment variable}
680: occuring in url will be replaced with appropriate values.
682: Level: developer
684: .seealso: PetscOpFListDestroy(),PetscOpFList, PetscFListAdd(), PetscFList
685: @*/
686: PetscErrorCode PetscOpFListAdd(MPI_Comm comm, PetscOpFList *fl,const char url[],PetscVoidFunction fnc,const char op[], PetscInt numArgs, char* argTypes[])
687: {
688: PetscOpFList entry,e,ne;
690: char *fpath,*fname;
691: PetscInt i;
694: if (!*fl) {
695: PetscNew(struct _n_PetscOpFList,&entry);
696: PetscStrallocpy(op,&entry->op);
697: PetscStrallocpy(url,&(entry->url));
698: PetscFListGetPathAndFunction(url,&fpath,&fname);
699: entry->path = fpath;
700: entry->name = fname;
701: entry->routine = fnc;
702: entry->numArgs = numArgs;
703: if(numArgs) {
704: PetscMalloc(sizeof(char*)*numArgs, &(entry->argTypes));
705: for(i = 0; i < numArgs; ++i) {
706: PetscStrallocpy(argTypes[i], &(entry->argTypes[i]));
707: }
708: }
709: entry->next = 0;
710: *fl = entry;
712: /* add this new list to list of all lists */
713: if (!opallhead) {
714: opallhead = *fl;
715: (*fl)->next_list = 0;
716: } else {
717: ne = opallhead;
718: opallhead = *fl;
719: (*fl)->next_list = ne;
720: }
721: } else {
722: /* search list to see if it is already there */
723: e = PETSC_NULL;
724: ne = *fl;
725: while (ne) {
726: PetscBool match;
727: PetscStrcmp(ne->op,op,&match);
728: if(!match) goto next;
729: if(numArgs == ne->numArgs)
730: match = PETSC_TRUE;
731: else
732: match = PETSC_FALSE;
733: if(!match) goto next;
734: if(numArgs) {
735: for(i = 0; i < numArgs; ++i) {
736: PetscStrcmp(argTypes[i], ne->argTypes[i], &match);
737: if(!match) goto next;
738: }
739: }
740: if(!url && !fnc) {
741: /* remove this record */
742: if(e) e->next = ne->next;
743: PetscFree(ne->op);
744: PetscFree(ne->url);
745: PetscFree(ne->path);
746: PetscFree(ne->name);
747: if(numArgs) {
748: for(i = 0; i < numArgs; ++i) {
749: PetscFree(ne->argTypes[i]);
750: }
751: PetscFree(ne->argTypes);
752: }
753: PetscFree(ne);
754: }
755: else {
756: /* Replace url, fpath, fname and fnc. */
757: PetscStrallocpy(url, &(ne->url));
758: PetscFListGetPathAndFunction(url,&fpath,&fname);
759: PetscFree(ne->path);
760: PetscFree(ne->name);
761: ne->path = fpath;
762: ne->name = fname;
763: ne->routine = fnc;
764: }
765: return(0);
766: next: {e = ne; ne = ne->next;}
767: }
768: /* create new entry and add to end of list */
769: PetscNew(struct _n_PetscOpFList,&entry);
770: PetscStrallocpy(op,&entry->op);
771: entry->numArgs = numArgs;
772: if(numArgs) {
773: PetscMalloc(sizeof(char*)*numArgs, &(entry->argTypes));
774: for(i = 0; i < numArgs; ++i) {
775: PetscStrallocpy(argTypes[i], &(entry->argTypes[i]));
776: }
777: }
778: PetscStrallocpy(url, &(entry->url));
779: PetscFListGetPathAndFunction(url,&fpath,&fname);
780: entry->path = fpath;
781: entry->name = fname;
782: entry->routine = fnc;
783: entry->next = 0;
784: ne->next = entry;
785: }
786: return(0);
787: }
791: /*@C
792: PetscOpFListDestroy - Destroys a list of registered op routines.
794: Input Parameter:
795: . fl - pointer to list
797: Level: developer
799: .seealso: PetscOpFListAdd(), PetscOpFList
800: @*/
801: PetscErrorCode PetscOpFListDestroy(PetscOpFList *fl)
802: {
803: PetscOpFList next,entry,tmp;
804: PetscErrorCode ierr;
805: PetscInt i;
808: if (!*fl) return(0);
809: if (!opallhead) return(0);
811: /*
812: Remove this entry from the master Op list (if it is in it)
813: */
814: if (opallhead == *fl) {
815: if (opallhead->next_list) {
816: opallhead = opallhead->next_list;
817: } else {
818: opallhead = 0;
819: }
820: } else {
821: tmp = opallhead;
822: while (tmp->next_list != *fl) {
823: tmp = tmp->next_list;
824: if (!tmp->next_list) break;
825: }
826: if (tmp->next_list) tmp->next_list = tmp->next_list->next_list;
827: }
829: /* free this list */
830: entry = *fl;
831: while (entry) {
832: next = entry->next;
833: PetscFree(entry->op);
834: for(i = 0; i < entry->numArgs; ++i) {
835: PetscFree(entry->argTypes[i]);
836: }
837: PetscFree(entry->argTypes);
838: PetscFree(entry->url);
839: PetscFree(entry->path);
840: PetscFree(entry->name);
841: PetscFree(entry);
842: entry = next;
843: }
844: *fl = 0;
845: return(0);
846: }
848: /*
849: Destroys all the function lists that anyone has every registered, such as MatOpList, etc.
850: */
853: PetscErrorCode PetscOpFListDestroyAll(void)
854: {
855: PetscOpFList tmp2,tmp1 = opallhead;
859: while (tmp1) {
860: tmp2 = tmp1->next_list;
861: PetscOpFListDestroy(&tmp1);
862: tmp1 = tmp2;
863: }
864: opallhead = 0;
865: return(0);
866: }
870: /*@C
871: PetscOpFListFind - Given a name, finds the matching op routine.
872: Formally collective on comm.
874: Input Parameters:
875: + comm - processes looking for the op
876: . fl - pointer to list of known ops
877: . op - operation name
878: . numArgs - number of op arguments
879: - argTypes - list of argument type names
882: Output Parameters:
883: . r - routine implementing op with the given arg types
885: Level: developer
887: .seealso: PetscOpFListAdd(), PetscOpFList
888: @*/
889: PetscErrorCode PetscOpFListFind(MPI_Comm comm, PetscOpFList fl,PetscVoidFunction *r, const char* op, PetscInt numArgs, char* argTypes[])
890: {
891: PetscOpFList entry;
893: PetscBool match;
894: PetscInt i;
895:
898: if (!op) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Attempting to find operation with null name");
899: *r = PETSC_NULL;
900: match = PETSC_FALSE;
901: entry = fl;
902: while (entry) {
903: PetscStrcmp(entry->op,op,&match);
904: if(!match) goto next;
905: if(numArgs == entry->numArgs)
906: match = PETSC_TRUE;
907: else
908: match = PETSC_FALSE;
909: if(!match) goto next;
910: if(numArgs) {
911: for(i = 0; i < numArgs; ++i) {
912: PetscStrcmp(argTypes[i], entry->argTypes[i], &match);
913: if(!match) goto next;
914: }
915: }
916: break;
917: next: entry = entry->next;
918: }
919: if (match) {
920: if (entry->routine) {
921: *r = entry->routine;
922: }
923: #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES)
924: else {
925: /* it is not yet in memory so load from dynamic library */
926: PetscDLLibrarySym(comm,&PetscDLLibrariesLoaded,entry->path,entry->name,(void **)r);
927: if (*r) {
928: entry->routine = *r;
929: }
930: }
931: #endif
932: }
934: return(0);
935: }
939: /*@C
940: PetscOpFListView - prints out contents of a PetscOpFList
942: Collective on viewer
944: Input Parameters:
945: + list - the list of functions
946: - viewer - ASCII viewer Level: developer
948: .seealso: PetscOpFListAdd(), PetscOpFList
949: @*/
950: PetscErrorCode PetscOpFListView(PetscOpFList list,PetscViewer viewer)
951: {
953: PetscBool iascii;
954: PetscInt i;
957: if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;
960:
961: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
962: if (!iascii) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only ASCII viewer supported");
964: while (list) {
965: if (list->url) {
966: PetscViewerASCIIPrintf(viewer," %s: ",list->url);
967: }
968: PetscViewerASCIIPrintf(viewer, "%s(", list->op);
969: for(i = 0; i < list->numArgs;++i) {
970: if(i > 0) {
971: PetscViewerASCIIPrintf(viewer, ", ");
972: }
973: PetscViewerASCIIPrintf(viewer, "%s", list->argTypes[i]);
974: }
975: PetscViewerASCIIPrintf(viewer, ")\n");
976: list = list->next;
977: }
978: return(0);
979: }