Actual source code: reg.c
petsc-3.7.7 2017-09-25
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_HAVE_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
42: #if defined(PETSC_HAVE_THREADSAFETY)
43: extern PetscErrorCode AOInitializePackage(void);
44: extern PetscErrorCode PetscSFInitializePackage(void);
45: #if !defined(PETSC_USE_COMPLEX)
46: extern PetscErrorCode CharacteristicInitializePackage(void);
47: #endif
48: extern PetscErrorCode ISInitializePackage(void);
49: extern PetscErrorCode VecInitializePackage(void);
50: extern PetscErrorCode MatInitializePackage(void);
51: extern PetscErrorCode DMInitializePackage(void);
52: extern PetscErrorCode PCInitializePackage(void);
53: extern PetscErrorCode KSPInitializePackage(void);
54: extern PetscErrorCode SNESInitializePackage(void);
55: extern PetscErrorCode TSInitializePackage(void);
56: static MPI_Comm PETSC_COMM_WORLD_INNER = 0,PETSC_COMM_SELF_INNER = 0;
57: #endif
61: /*
62: PetscInitialize_DynamicLibraries - Adds the default dynamic link libraries to the
63: search path.
64: */
65: PetscErrorCode PetscInitialize_DynamicLibraries(void)
66: {
67: char *libname[32];
69: PetscInt nmax,i;
70: #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES)
71: PetscBool preload;
72: #endif
75: nmax = 32;
76: PetscOptionsGetStringArray(NULL,NULL,"-dll_prepend",libname,&nmax,NULL);
77: for (i=0; i<nmax; i++) {
78: PetscDLLibraryPrepend(PETSC_COMM_WORLD,&PetscDLLibrariesLoaded,libname[i]);
79: PetscFree(libname[i]);
80: }
82: #if !defined(PETSC_HAVE_DYNAMIC_LIBRARIES)
83: /*
84: This just initializes the most basic PETSc stuff.
86: The classes, from PetscDraw to PetscTS, are initialized the first
87: time an XXCreate() is called.
88: */
89: PetscSysInitializePackage();
90: #else
91: preload = PETSC_FALSE;
92: PetscOptionsGetBool(NULL,NULL,"-dynamic_library_preload",&preload,NULL);
93: if (preload) {
94: PetscBool found;
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("ksp",&found);
108: if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc KSP dynamic library \n You cannot move the dynamic libraries!");
109: PetscLoadDynamicLibrary("snes",&found);
110: if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc SNES dynamic library \n You cannot move the dynamic libraries!");
111: PetscLoadDynamicLibrary("ts",&found);
112: if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc TS dynamic library \n You cannot move the dynamic libraries!");
113: #endif
114: }
115: #endif
117: nmax = 32;
118: PetscOptionsGetStringArray(NULL,NULL,"-dll_append",libname,&nmax,NULL);
119: for (i=0; i<nmax; i++) {
120: PetscDLLibraryAppend(PETSC_COMM_WORLD,&PetscDLLibrariesLoaded,libname[i]);
121: PetscFree(libname[i]);
122: }
124: #if defined(PETSC_HAVE_THREADSAFETY)
125: /* These must be done here because it is not safe for individual threads to call these initialize routines */
126: AOInitializePackage();
127: PetscSFInitializePackage();
128: #if !defined(PETSC_USE_COMPLEX)
129: CharacteristicInitializePackage();
130: #endif
131: ISInitializePackage();
132: VecInitializePackage();
133: MatInitializePackage();
134: DMInitializePackage();
135: PCInitializePackage();
136: KSPInitializePackage();
137: SNESInitializePackage();
138: TSInitializePackage();
139: PetscCommDuplicate(PETSC_COMM_SELF,&PETSC_COMM_SELF_INNER,NULL);
140: PetscCommDuplicate(PETSC_COMM_WORLD,&PETSC_COMM_WORLD_INNER,NULL);
141: #endif
142: return(0);
143: }
147: /*
148: PetscFinalize_DynamicLibraries - Closes the opened dynamic libraries.
149: */
150: PetscErrorCode PetscFinalize_DynamicLibraries(void)
151: {
153: PetscBool flg = PETSC_FALSE;
156: PetscOptionsGetBool(NULL,NULL,"-dll_view",&flg,NULL);
157: if (flg) { PetscDLLibraryPrintPath(PetscDLLibrariesLoaded); }
158: PetscDLLibraryClose(PetscDLLibrariesLoaded);
160: #if defined(PETSC_HAVE_THREADSAFETY)
161: PetscCommDestroy(&PETSC_COMM_SELF_INNER);
162: PetscCommDestroy(&PETSC_COMM_WORLD_INNER);
163: #endif
165: PetscDLLibrariesLoaded = 0;
166: return(0);
167: }
171: /* ------------------------------------------------------------------------------*/
172: struct _n_PetscFunctionList {
173: void (*routine)(void); /* the routine */
174: char *name; /* string to identify routine */
175: PetscFunctionList next; /* next pointer */
176: PetscFunctionList next_list; /* used to maintain list of all lists for freeing */
177: };
179: /*
180: Keep a linked list of PetscFunctionLists so that we can destroy all the left-over ones.
181: */
182: static PetscFunctionList dlallhead = 0;
184: /*MC
185: PetscFunctionListAdd - Given a routine and a string id, saves that routine in the
186: specified registry.
188: Synopsis:
189: #include <petscsys.h>
190: PetscErrorCode PetscFunctionListAdd(PetscFunctionList *flist,const char name[],void (*fptr)(void))
192: Not Collective
194: Input Parameters:
195: + flist - pointer to function list object
196: . name - string to identify routine
197: - fptr - function pointer
199: Notes:
200: To remove a registered routine, pass in a NULL fptr.
202: Users who wish to register new classes for use by a particular PETSc
203: component (e.g., SNES) should generally call the registration routine
204: for that particular component (e.g., SNESRegister()) instead of
205: calling PetscFunctionListAdd() directly.
207: Level: developer
209: .seealso: PetscFunctionListDestroy(), SNESRegister(), KSPRegister(),
210: PCRegister(), TSRegister(), PetscFunctionList, PetscObjectComposeFunction()
211: M*/
214: PETSC_EXTERN PetscErrorCode PetscFunctionListAdd_Private(PetscFunctionList *fl,const char name[],void (*fnc)(void))
215: {
216: PetscFunctionList entry,ne;
217: PetscErrorCode ierr;
220: if (!*fl) {
221: PetscNew(&entry);
222: PetscStrallocpy(name,&entry->name);
223: entry->routine = fnc;
224: entry->next = 0;
225: *fl = entry;
227: #if defined(PETSC_USE_DEBUG)
228: /* add this new list to list of all lists */
229: if (!dlallhead) {
230: dlallhead = *fl;
231: (*fl)->next_list = 0;
232: } else {
233: ne = dlallhead;
234: dlallhead = *fl;
235: (*fl)->next_list = ne;
236: }
237: #endif
239: } else {
240: /* search list to see if it is already there */
241: ne = *fl;
242: while (ne) {
243: PetscBool founddup;
245: PetscStrcmp(ne->name,name,&founddup);
246: if (founddup) { /* found duplicate */
247: ne->routine = fnc;
248: return(0);
249: }
250: if (ne->next) ne = ne->next;
251: else break;
252: }
253: /* create new entry and add to end of list */
254: PetscNew(&entry);
255: PetscStrallocpy(name,&entry->name);
256: entry->routine = fnc;
257: entry->next = 0;
258: ne->next = entry;
259: }
260: return(0);
261: }
265: /*@
266: PetscFunctionListDestroy - Destroys a list of registered routines.
268: Input Parameter:
269: . fl - pointer to list
271: Level: developer
273: .seealso: PetscFunctionListAdd(), PetscFunctionList
274: @*/
275: PetscErrorCode PetscFunctionListDestroy(PetscFunctionList *fl)
276: {
277: PetscFunctionList next,entry,tmp = dlallhead;
278: PetscErrorCode ierr;
281: if (!*fl) return(0);
283: /*
284: Remove this entry from the master DL list (if it is in it)
285: */
286: if (dlallhead == *fl) {
287: if (dlallhead->next_list) dlallhead = dlallhead->next_list;
288: else dlallhead = NULL;
289: } else if (tmp) {
290: while (tmp->next_list != *fl) {
291: tmp = tmp->next_list;
292: if (!tmp->next_list) break;
293: }
294: if (tmp->next_list) tmp->next_list = tmp->next_list->next_list;
295: }
297: /* free this list */
298: entry = *fl;
299: while (entry) {
300: next = entry->next;
301: PetscFree(entry->name);
302: PetscFree(entry);
303: entry = next;
304: }
305: *fl = 0;
306: return(0);
307: }
309: /*
310: Print any PetscFunctionLists that have not be destroyed
311: */
314: PetscErrorCode PetscFunctionListPrintAll(void)
315: {
316: PetscFunctionList tmp = dlallhead;
317: PetscErrorCode ierr;
320: if (tmp) {
321: PetscPrintf(PETSC_COMM_WORLD,"The following PetscFunctionLists were not destroyed\n");
322: }
323: while (tmp) {
324: PetscPrintf(PETSC_COMM_WORLD,"%s \n",tmp->name);
325: tmp = tmp->next_list;
326: }
327: return(0);
328: }
330: /*MC
331: PetscFunctionListFind - Find function registered under given name
333: Synopsis:
334: #include <petscsys.h>
335: PetscErrorCode PetscFunctionListFind(PetscFunctionList flist,const char name[],void (**fptr)(void))
337: Input Parameters:
338: + flist - pointer to list
339: - name - name registered for the function
341: Output Parameters:
342: . fptr - the function pointer if name was found, else NULL
344: Level: developer
346: .seealso: PetscFunctionListAdd(), PetscFunctionList, PetscObjectQueryFunction()
347: M*/
350: PETSC_EXTERN PetscErrorCode PetscFunctionListFind_Private(PetscFunctionList fl,const char name[],void (**r)(void))
351: {
352: PetscFunctionList entry = fl;
353: PetscErrorCode ierr;
354: PetscBool flg;
357: if (!name) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Trying to find routine with null name");
359: *r = 0;
360: while (entry) {
361: PetscStrcmp(name,entry->name,&flg);
362: if (flg) {
363: *r = entry->routine;
364: return(0);
365: }
366: entry = entry->next;
367: }
368: return(0);
369: }
373: /*@
374: PetscFunctionListView - prints out contents of an PetscFunctionList
376: Collective over MPI_Comm
378: Input Parameters:
379: + list - the list of functions
380: - viewer - currently ignored
382: Level: developer
384: .seealso: PetscFunctionListAdd(), PetscFunctionListPrintTypes(), PetscFunctionList
385: @*/
386: PetscErrorCode PetscFunctionListView(PetscFunctionList list,PetscViewer viewer)
387: {
389: PetscBool iascii;
392: if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;
396: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
397: if (!iascii) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only ASCII viewer supported");
399: while (list) {
400: PetscViewerASCIIPrintf(viewer," %s\n",list->name);
401: list = list->next;
402: }
403: PetscViewerASCIIPrintf(viewer,"\n");
404: return(0);
405: }
409: /*@C
410: PetscFunctionListGet - Gets an array the contains the entries in PetscFunctionList, this is used
411: by help etc.
413: Not Collective
415: Input Parameter:
416: . list - list of types
418: Output Parameter:
419: + array - array of names
420: - n - length of array
422: Notes:
423: This allocates the array so that must be freed. BUT the individual entries are
424: not copied so should not be freed.
426: Level: developer
428: .seealso: PetscFunctionListAdd(), PetscFunctionList
429: @*/
430: PetscErrorCode PetscFunctionListGet(PetscFunctionList list,const char ***array,int *n)
431: {
432: PetscErrorCode ierr;
433: PetscInt count = 0;
434: PetscFunctionList klist = list;
437: while (list) {
438: list = list->next;
439: count++;
440: }
441: PetscMalloc1(count+1,array);
442: count = 0;
443: while (klist) {
444: (*array)[count] = klist->name;
445: klist = klist->next;
446: count++;
447: }
448: (*array)[count] = 0;
449: *n = count+1;
450: return(0);
451: }
456: /*@C
457: PetscFunctionListPrintTypes - Prints the methods available.
459: Collective over MPI_Comm
461: Input Parameters:
462: + comm - the communicator (usually MPI_COMM_WORLD)
463: . fd - file to print to, usually stdout
464: . prefix - prefix to prepend to name (optional)
465: . name - option string (for example, "-ksp_type")
466: . text - short description of the object (for example, "Krylov solvers")
467: . man - name of manual page that discusses the object (for example, "KSPCreate")
468: . list - list of types
469: - def - default (current) value
471: Level: developer
473: .seealso: PetscFunctionListAdd(), PetscFunctionList
474: @*/
475: PetscErrorCode PetscFunctionListPrintTypes(MPI_Comm comm,FILE *fd,const char prefix[],const char name[],const char text[],const char man[],PetscFunctionList list,const char def[])
476: {
478: char p[64];
481: if (!fd) fd = PETSC_STDOUT;
483: PetscStrcpy(p,"-");
484: if (prefix) {PetscStrcat(p,prefix);}
485: PetscFPrintf(comm,fd," %s%s <%s>: %s (one of)",p,name+1,def,text);
487: while (list) {
488: PetscFPrintf(comm,fd," %s",list->name);
489: list = list->next;
490: }
491: PetscFPrintf(comm,fd," (%s)\n",man);
492: return(0);
493: }
497: /*@
498: PetscFunctionListDuplicate - Creates a new list from a given object list.
500: Input Parameters:
501: . fl - pointer to list
503: Output Parameters:
504: . nl - the new list (should point to 0 to start, otherwise appends)
506: Level: developer
508: .seealso: PetscFunctionList, PetscFunctionListAdd(), PetscFlistDestroy()
510: @*/
511: PetscErrorCode PetscFunctionListDuplicate(PetscFunctionList fl,PetscFunctionList *nl)
512: {
516: while (fl) {
517: PetscFunctionListAdd(nl,fl->name,fl->routine);
518: fl = fl->next;
519: }
520: return(0);
521: }