Actual source code: reg.c
petsc-3.4.5 2014-06-29
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-private/petscimpl.h> /*I "petscsys.h" I*/
7: #include <petscviewer.h>
9: /*
10: This is the default list used by PETSc with the PetscDLLibrary register routines
11: */
12: PetscDLLibrary PetscDLLibrariesLoaded = 0;
14: #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
18: static PetscErrorCode PetscLoadDynamicLibrary(const char *name,PetscBool *found)
19: {
20: char libs[PETSC_MAX_PATH_LEN],dlib[PETSC_MAX_PATH_LEN];
24: PetscStrcpy(libs,"${PETSC_LIB_DIR}/libpetsc");
25: PetscStrcat(libs,name);
26: PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,found);
27: if (*found) {
28: PetscDLLibraryAppend(PETSC_COMM_WORLD,&PetscDLLibrariesLoaded,dlib);
29: } else {
30: PetscStrcpy(libs,"${PETSC_DIR}/${PETSC_ARCH}/lib/libpetsc");
31: PetscStrcat(libs,name);
32: PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,found);
33: if (*found) {
34: PetscDLLibraryAppend(PETSC_COMM_WORLD,&PetscDLLibrariesLoaded,dlib);
35: }
36: }
37: return(0);
38: }
40: #endif
44: /*
45: PetscInitialize_DynamicLibraries - Adds the default dynamic link libraries to the
46: search path.
47: */
48: PetscErrorCode PetscInitialize_DynamicLibraries(void)
49: {
50: char *libname[32];
52: PetscInt nmax,i;
53: #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
54: PetscBool found;
55: #endif
58: nmax = 32;
59: PetscOptionsGetStringArray(NULL,"-dll_prepend",libname,&nmax,NULL);
60: for (i=0; i<nmax; i++) {
61: PetscDLLibraryPrepend(PETSC_COMM_WORLD,&PetscDLLibrariesLoaded,libname[i]);
62: PetscFree(libname[i]);
63: }
65: #if !defined(PETSC_USE_DYNAMIC_LIBRARIES)
66: /*
67: This just initializes the most basic PETSc stuff.
69: The classes, from PetscDraw to PetscTS, are initialized the first
70: time an XXCreate() is called.
71: */
72: PetscSysInitializePackage();
73: #else
74: #if defined(PETSC_USE_SINGLE_LIBRARY)
75: PetscLoadDynamicLibrary("",&found);
76: if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc dynamic library \n You cannot move the dynamic libraries!");
77: #else
78: PetscLoadDynamicLibrary("sys",&found);
79: if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc dynamic library \n You cannot move the dynamic libraries!");
80: PetscLoadDynamicLibrary("vec",&found);
81: if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc Vec dynamic library \n You cannot move the dynamic libraries!");
82: PetscLoadDynamicLibrary("mat",&found);
83: if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc Mat dynamic library \n You cannot move the dynamic libraries!");
84: PetscLoadDynamicLibrary("dm",&found);
85: if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc DM dynamic library \n You cannot move the dynamic libraries!");
86: PetscLoadDynamicLibrary("ksp",&found);
87: if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc KSP dynamic library \n You cannot move the dynamic libraries!");
88: PetscLoadDynamicLibrary("snes",&found);
89: if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc SNES dynamic library \n You cannot move the dynamic libraries!");
90: PetscLoadDynamicLibrary("ts",&found);
91: if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc TS dynamic library \n You cannot move the dynamic libraries!");
92: #endif
93: #endif
95: nmax = 32;
96: PetscOptionsGetStringArray(NULL,"-dll_append",libname,&nmax,NULL);
97: for (i=0; i<nmax; i++) {
98: PetscDLLibraryAppend(PETSC_COMM_WORLD,&PetscDLLibrariesLoaded,libname[i]);
99: PetscFree(libname[i]);
100: }
101: return(0);
102: }
106: /*
107: PetscFinalize_DynamicLibraries - Closes the opened dynamic libraries.
108: */
109: PetscErrorCode PetscFinalize_DynamicLibraries(void)
110: {
112: PetscBool flg = PETSC_FALSE;
115: PetscOptionsGetBool(NULL,"-dll_view",&flg,NULL);
116: if (flg) { PetscDLLibraryPrintPath(PetscDLLibrariesLoaded); }
117: PetscDLLibraryClose(PetscDLLibrariesLoaded);
119: PetscDLLibrariesLoaded = 0;
120: return(0);
121: }
125: /* ------------------------------------------------------------------------------*/
126: struct _n_PetscFunctionList {
127: void (*routine)(void); /* the routine */
128: char *name; /* string to identify routine */
129: PetscFunctionList next; /* next pointer */
130: PetscFunctionList next_list; /* used to maintain list of all lists for freeing */
131: };
133: /*
134: Keep a linked list of PetscFunctionLists so that we can destroy all the left-over ones.
135: */
136: static PetscFunctionList dlallhead = 0;
138: /*MC
139: PetscFunctionListAdd - Given a routine and a string id, saves that routine in the
140: specified registry.
142: Synopsis:
143: #include "petscsys.h"
144: PetscErrorCode PetscFunctionListAdd(PetscFunctionList flist,const char name[],void (*fptr)(void))
146: Not Collective
148: Input Parameters:
149: + flist - pointer registry
150: . name - string to identify routine
151: - fptr - function pointer
153: Notes:
154: To remove a registered routine, pass in a NULL fptr.
156: Users who wish to register new classes for use by a particular PETSc
157: component (e.g., SNES) should generally call the registration routine
158: for that particular component (e.g., SNESRegister()) instead of
159: calling PetscFunctionListAdd() directly.
161: Level: developer
163: .seealso: PetscFunctionListDestroy(), SNESRegister(), KSPRegister(),
164: PCRegister(), TSRegister(), PetscFunctionList, PetscObjectComposeFunction()
165: M*/
168: PETSC_EXTERN PetscErrorCode PetscFunctionListAdd_Private(PetscFunctionList *fl,const char name[],void (*fnc)(void))
169: {
170: PetscFunctionList entry,ne;
171: PetscErrorCode ierr;
174: if (!*fl) {
175: PetscNew(struct _n_PetscFunctionList,&entry);
176: PetscStrallocpy(name,&entry->name);
177: entry->routine = fnc;
178: entry->next = 0;
179: *fl = entry;
181: /* add this new list to list of all lists */
182: if (!dlallhead) {
183: dlallhead = *fl;
184: (*fl)->next_list = 0;
185: } else {
186: ne = dlallhead;
187: dlallhead = *fl;
188: (*fl)->next_list = ne;
189: }
190: } else {
191: /* search list to see if it is already there */
192: ne = *fl;
193: while (ne) {
194: PetscBool founddup;
196: PetscStrcmp(ne->name,name,&founddup);
197: if (founddup) { /* found duplicate */
198: ne->routine = fnc;
199: return(0);
200: }
201: if (ne->next) ne = ne->next;
202: else break;
203: }
204: /* create new entry and add to end of list */
205: PetscNew(struct _n_PetscFunctionList,&entry);
206: PetscStrallocpy(name,&entry->name);
207: entry->routine = fnc;
208: entry->next = 0;
209: ne->next = entry;
210: }
211: return(0);
212: }
216: /*@
217: PetscFunctionListDestroy - Destroys a list of registered routines.
219: Input Parameter:
220: . fl - pointer to list
222: Level: developer
224: .seealso: PetscFunctionListAdd(), PetscFunctionList
225: @*/
226: PetscErrorCode PetscFunctionListDestroy(PetscFunctionList *fl)
227: {
228: PetscFunctionList next,entry,tmp = dlallhead;
229: PetscErrorCode ierr;
232: if (!*fl) return(0);
234: /*
235: Remove this entry from the master DL list (if it is in it)
236: */
237: if (dlallhead == *fl) {
238: if (dlallhead->next_list) dlallhead = dlallhead->next_list;
239: else dlallhead = NULL;
240: } else if (tmp) {
241: while (tmp->next_list != *fl) {
242: tmp = tmp->next_list;
243: if (!tmp->next_list) break;
244: }
245: if (tmp->next_list) tmp->next_list = tmp->next_list->next_list;
246: }
248: /* free this list */
249: entry = *fl;
250: while (entry) {
251: next = entry->next;
252: PetscFree(entry->name);
253: PetscFree(entry);
254: entry = next;
255: }
256: *fl = 0;
257: return(0);
258: }
260: /*
261: Print any PetscFunctionLists that have not be destroyed
262: */
265: PetscErrorCode PetscFunctionListPrintAll(void)
266: {
267: PetscFunctionList tmp = dlallhead;
268: PetscErrorCode ierr;
271: if (tmp) {
272: PetscPrintf(PETSC_COMM_WORLD,"The following PetscFunctionLists were not destroyed\n");
273: }
274: while (tmp) {
275: PetscPrintf(PETSC_COMM_WORLD,"%s \n",tmp->name);
276: tmp = tmp->next_list;
277: }
278: return(0);
279: }
281: /*MC
282: PetscFunctionListFind - Find function registered under given name
284: Synopsis:
285: #include "petscsys.h"
286: PetscErrorCode PetscFunctionListFind(PetscFunctionList flist,const char name[],void (**fptr)(void))
288: Input Parameters:
289: + flist - pointer to list
290: - name - name registered for the function
292: Output Parameters:
293: . fptr - the function pointer if name was found, else NULL
295: Level: developer
297: .seealso: PetscFunctionListAdd(), PetscFunctionList, PetscObjectQueryFunction()
298: M*/
301: PETSC_EXTERN PetscErrorCode PetscFunctionListFind_Private(PetscFunctionList fl,const char name[],void (**r)(void))
302: {
303: PetscFunctionList entry = fl;
304: PetscErrorCode ierr;
305: PetscBool flg;
308: if (!name) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Trying to find routine with null name");
310: *r = 0;
311: while (entry) {
312: PetscStrcmp(name,entry->name,&flg);
313: if (flg) {
314: *r = entry->routine;
315: return(0);
316: }
317: entry = entry->next;
318: }
319: return(0);
320: }
324: /*@
325: PetscFunctionListView - prints out contents of an PetscFunctionList
327: Collective over MPI_Comm
329: Input Parameters:
330: + list - the list of functions
331: - viewer - currently ignored
333: Level: developer
335: .seealso: PetscFunctionListAdd(), PetscFunctionListPrintTypes(), PetscFunctionList
336: @*/
337: PetscErrorCode PetscFunctionListView(PetscFunctionList list,PetscViewer viewer)
338: {
340: PetscBool iascii;
343: if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;
347: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
348: if (!iascii) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only ASCII viewer supported");
350: while (list) {
351: PetscViewerASCIIPrintf(viewer," %s\n",list->name);
352: list = list->next;
353: }
354: PetscViewerASCIIPrintf(viewer,"\n");
355: return(0);
356: }
360: /*@C
361: PetscFunctionListGet - Gets an array the contains the entries in PetscFunctionList, this is used
362: by help etc.
364: Not Collective
366: Input Parameter:
367: . list - list of types
369: Output Parameter:
370: + array - array of names
371: - n - length of array
373: Notes:
374: This allocates the array so that must be freed. BUT the individual entries are
375: not copied so should not be freed.
377: Level: developer
379: .seealso: PetscFunctionListAdd(), PetscFunctionList
380: @*/
381: PetscErrorCode PetscFunctionListGet(PetscFunctionList list,const char ***array,int *n)
382: {
383: PetscErrorCode ierr;
384: PetscInt count = 0;
385: PetscFunctionList klist = list;
388: while (list) {
389: list = list->next;
390: count++;
391: }
392: PetscMalloc((count+1)*sizeof(char*),array);
393: count = 0;
394: while (klist) {
395: (*array)[count] = klist->name;
396: klist = klist->next;
397: count++;
398: }
399: (*array)[count] = 0;
400: *n = count+1;
401: return(0);
402: }
407: /*@C
408: PetscFunctionListPrintTypes - Prints the methods available.
410: Collective over MPI_Comm
412: Input Parameters:
413: + comm - the communicator (usually MPI_COMM_WORLD)
414: . fd - file to print to, usually stdout
415: . prefix - prefix to prepend to name (optional)
416: . name - option string (for example, "-ksp_type")
417: . text - short description of the object (for example, "Krylov solvers")
418: . man - name of manual page that discusses the object (for example, "KSPCreate")
419: . list - list of types
420: - def - default (current) value
422: Level: developer
424: .seealso: PetscFunctionListAdd(), PetscFunctionList
425: @*/
426: PetscErrorCode PetscFunctionListPrintTypes(MPI_Comm comm,FILE *fd,const char prefix[],const char name[],const char text[],const char man[],PetscFunctionList list,const char def[])
427: {
429: PetscInt count = 0;
430: char p[64];
433: if (!fd) fd = PETSC_STDOUT;
435: PetscStrcpy(p,"-");
436: if (prefix) {PetscStrcat(p,prefix);}
437: PetscFPrintf(comm,fd," %s%s <%s>: %s (one of)",p,name+1,def,text);
439: while (list) {
440: PetscFPrintf(comm,fd," %s",list->name);
441: list = list->next;
442: count++;
443: if (count == 8) {PetscFPrintf(comm,fd,"\n ");}
444: }
445: PetscFPrintf(comm,fd," (%s)\n",man);
446: return(0);
447: }
451: /*@
452: PetscFunctionListDuplicate - Creates a new list from a given object list.
454: Input Parameters:
455: . fl - pointer to list
457: Output Parameters:
458: . nl - the new list (should point to 0 to start, otherwise appends)
460: Level: developer
462: .seealso: PetscFunctionList, PetscFunctionListAdd(), PetscFlistDestroy()
464: @*/
465: PetscErrorCode PetscFunctionListDuplicate(PetscFunctionList fl,PetscFunctionList *nl)
466: {
470: while (fl) {
471: PetscFunctionListAdd(nl,fl->name,fl->routine);
472: fl = fl->next;
473: }
474: return(0);
475: }