Actual source code: reg.c
petsc-3.7.3 2016-08-01
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: extern PetscErrorCode CharacteristicInitializePackage(void);
46: extern PetscErrorCode ISInitializePackage(void);
47: extern PetscErrorCode VecInitializePackage(void);
48: extern PetscErrorCode MatInitializePackage(void);
49: extern PetscErrorCode DMInitializePackage(void);
50: extern PetscErrorCode PCInitializePackage(void);
51: extern PetscErrorCode KSPInitializePackage(void);
52: extern PetscErrorCode SNESInitializePackage(void);
53: extern PetscErrorCode TSInitializePackage(void);
54: static MPI_Comm PETSC_COMM_WORLD_INNER = 0,PETSC_COMM_SELF_INNER = 0;
55: #endif
59: /*
60: PetscInitialize_DynamicLibraries - Adds the default dynamic link libraries to the
61: search path.
62: */
63: PetscErrorCode PetscInitialize_DynamicLibraries(void)
64: {
65: char *libname[32];
67: PetscInt nmax,i;
68: #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES)
69: PetscBool preload;
70: #endif
73: nmax = 32;
74: PetscOptionsGetStringArray(NULL,NULL,"-dll_prepend",libname,&nmax,NULL);
75: for (i=0; i<nmax; i++) {
76: PetscDLLibraryPrepend(PETSC_COMM_WORLD,&PetscDLLibrariesLoaded,libname[i]);
77: PetscFree(libname[i]);
78: }
80: #if !defined(PETSC_HAVE_DYNAMIC_LIBRARIES)
81: /*
82: This just initializes the most basic PETSc stuff.
84: The classes, from PetscDraw to PetscTS, are initialized the first
85: time an XXCreate() is called.
86: */
87: PetscSysInitializePackage();
88: #else
89: preload = PETSC_FALSE;
90: PetscOptionsGetBool(NULL,NULL,"-dynamic_library_preload",&preload,NULL);
91: if (preload) {
92: PetscBool found;
93: #if defined(PETSC_USE_SINGLE_LIBRARY)
94: PetscLoadDynamicLibrary("",&found);
95: if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc dynamic library \n You cannot move the dynamic libraries!");
96: #else
97: PetscLoadDynamicLibrary("sys",&found);
98: if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc dynamic library \n You cannot move the dynamic libraries!");
99: PetscLoadDynamicLibrary("vec",&found);
100: if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc Vec dynamic library \n You cannot move the dynamic libraries!");
101: PetscLoadDynamicLibrary("mat",&found);
102: if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc Mat dynamic library \n You cannot move the dynamic libraries!");
103: PetscLoadDynamicLibrary("dm",&found);
104: if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc DM dynamic library \n You cannot move the dynamic libraries!");
105: PetscLoadDynamicLibrary("ksp",&found);
106: if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc KSP dynamic library \n You cannot move the dynamic libraries!");
107: PetscLoadDynamicLibrary("snes",&found);
108: if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc SNES dynamic library \n You cannot move the dynamic libraries!");
109: PetscLoadDynamicLibrary("ts",&found);
110: if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc TS dynamic library \n You cannot move the dynamic libraries!");
111: #endif
112: }
113: #endif
115: nmax = 32;
116: PetscOptionsGetStringArray(NULL,NULL,"-dll_append",libname,&nmax,NULL);
117: for (i=0; i<nmax; i++) {
118: PetscDLLibraryAppend(PETSC_COMM_WORLD,&PetscDLLibrariesLoaded,libname[i]);
119: PetscFree(libname[i]);
120: }
122: #if defined(PETSC_HAVE_THREADSAFETY)
123: /* These must be done here because it is not safe for individual threads to call these initialize routines */
124: AOInitializePackage();
125: PetscSFInitializePackage();
126: CharacteristicInitializePackage();
127: ISInitializePackage();
128: VecInitializePackage();
129: MatInitializePackage();
130: DMInitializePackage();
131: PCInitializePackage();
132: KSPInitializePackage();
133: SNESInitializePackage();
134: TSInitializePackage();
135: PetscCommDuplicate(PETSC_COMM_SELF,&PETSC_COMM_SELF_INNER,NULL);
136: PetscCommDuplicate(PETSC_COMM_WORLD,&PETSC_COMM_WORLD_INNER,NULL);
137: #endif
138: return(0);
139: }
143: /*
144: PetscFinalize_DynamicLibraries - Closes the opened dynamic libraries.
145: */
146: PetscErrorCode PetscFinalize_DynamicLibraries(void)
147: {
149: PetscBool flg = PETSC_FALSE;
152: PetscOptionsGetBool(NULL,NULL,"-dll_view",&flg,NULL);
153: if (flg) { PetscDLLibraryPrintPath(PetscDLLibrariesLoaded); }
154: PetscDLLibraryClose(PetscDLLibrariesLoaded);
156: #if defined(PETSC_HAVE_THREADSAFETY)
157: PetscCommDestroy(&PETSC_COMM_SELF_INNER);
158: PetscCommDestroy(&PETSC_COMM_WORLD_INNER);
159: #endif
161: PetscDLLibrariesLoaded = 0;
162: return(0);
163: }
167: /* ------------------------------------------------------------------------------*/
168: struct _n_PetscFunctionList {
169: void (*routine)(void); /* the routine */
170: char *name; /* string to identify routine */
171: PetscFunctionList next; /* next pointer */
172: PetscFunctionList next_list; /* used to maintain list of all lists for freeing */
173: };
175: /*
176: Keep a linked list of PetscFunctionLists so that we can destroy all the left-over ones.
177: */
178: static PetscFunctionList dlallhead = 0;
180: /*MC
181: PetscFunctionListAdd - Given a routine and a string id, saves that routine in the
182: specified registry.
184: Synopsis:
185: #include <petscsys.h>
186: PetscErrorCode PetscFunctionListAdd(PetscFunctionList *flist,const char name[],void (*fptr)(void))
188: Not Collective
190: Input Parameters:
191: + flist - pointer to function list object
192: . name - string to identify routine
193: - fptr - function pointer
195: Notes:
196: To remove a registered routine, pass in a NULL fptr.
198: Users who wish to register new classes for use by a particular PETSc
199: component (e.g., SNES) should generally call the registration routine
200: for that particular component (e.g., SNESRegister()) instead of
201: calling PetscFunctionListAdd() directly.
203: Level: developer
205: .seealso: PetscFunctionListDestroy(), SNESRegister(), KSPRegister(),
206: PCRegister(), TSRegister(), PetscFunctionList, PetscObjectComposeFunction()
207: M*/
210: PETSC_EXTERN PetscErrorCode PetscFunctionListAdd_Private(PetscFunctionList *fl,const char name[],void (*fnc)(void))
211: {
212: PetscFunctionList entry,ne;
213: PetscErrorCode ierr;
216: if (!*fl) {
217: PetscNew(&entry);
218: PetscStrallocpy(name,&entry->name);
219: entry->routine = fnc;
220: entry->next = 0;
221: *fl = entry;
223: #if defined(PETSC_USE_DEBUG)
224: /* add this new list to list of all lists */
225: if (!dlallhead) {
226: dlallhead = *fl;
227: (*fl)->next_list = 0;
228: } else {
229: ne = dlallhead;
230: dlallhead = *fl;
231: (*fl)->next_list = ne;
232: }
233: #endif
235: } else {
236: /* search list to see if it is already there */
237: ne = *fl;
238: while (ne) {
239: PetscBool founddup;
241: PetscStrcmp(ne->name,name,&founddup);
242: if (founddup) { /* found duplicate */
243: ne->routine = fnc;
244: return(0);
245: }
246: if (ne->next) ne = ne->next;
247: else break;
248: }
249: /* create new entry and add to end of list */
250: PetscNew(&entry);
251: PetscStrallocpy(name,&entry->name);
252: entry->routine = fnc;
253: entry->next = 0;
254: ne->next = entry;
255: }
256: return(0);
257: }
261: /*@
262: PetscFunctionListDestroy - Destroys a list of registered routines.
264: Input Parameter:
265: . fl - pointer to list
267: Level: developer
269: .seealso: PetscFunctionListAdd(), PetscFunctionList
270: @*/
271: PetscErrorCode PetscFunctionListDestroy(PetscFunctionList *fl)
272: {
273: PetscFunctionList next,entry,tmp = dlallhead;
274: PetscErrorCode ierr;
277: if (!*fl) return(0);
279: /*
280: Remove this entry from the master DL list (if it is in it)
281: */
282: if (dlallhead == *fl) {
283: if (dlallhead->next_list) dlallhead = dlallhead->next_list;
284: else dlallhead = NULL;
285: } else if (tmp) {
286: while (tmp->next_list != *fl) {
287: tmp = tmp->next_list;
288: if (!tmp->next_list) break;
289: }
290: if (tmp->next_list) tmp->next_list = tmp->next_list->next_list;
291: }
293: /* free this list */
294: entry = *fl;
295: while (entry) {
296: next = entry->next;
297: PetscFree(entry->name);
298: PetscFree(entry);
299: entry = next;
300: }
301: *fl = 0;
302: return(0);
303: }
305: /*
306: Print any PetscFunctionLists that have not be destroyed
307: */
310: PetscErrorCode PetscFunctionListPrintAll(void)
311: {
312: PetscFunctionList tmp = dlallhead;
313: PetscErrorCode ierr;
316: if (tmp) {
317: PetscPrintf(PETSC_COMM_WORLD,"The following PetscFunctionLists were not destroyed\n");
318: }
319: while (tmp) {
320: PetscPrintf(PETSC_COMM_WORLD,"%s \n",tmp->name);
321: tmp = tmp->next_list;
322: }
323: return(0);
324: }
326: /*MC
327: PetscFunctionListFind - Find function registered under given name
329: Synopsis:
330: #include <petscsys.h>
331: PetscErrorCode PetscFunctionListFind(PetscFunctionList flist,const char name[],void (**fptr)(void))
333: Input Parameters:
334: + flist - pointer to list
335: - name - name registered for the function
337: Output Parameters:
338: . fptr - the function pointer if name was found, else NULL
340: Level: developer
342: .seealso: PetscFunctionListAdd(), PetscFunctionList, PetscObjectQueryFunction()
343: M*/
346: PETSC_EXTERN PetscErrorCode PetscFunctionListFind_Private(PetscFunctionList fl,const char name[],void (**r)(void))
347: {
348: PetscFunctionList entry = fl;
349: PetscErrorCode ierr;
350: PetscBool flg;
353: if (!name) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Trying to find routine with null name");
355: *r = 0;
356: while (entry) {
357: PetscStrcmp(name,entry->name,&flg);
358: if (flg) {
359: *r = entry->routine;
360: return(0);
361: }
362: entry = entry->next;
363: }
364: return(0);
365: }
369: /*@
370: PetscFunctionListView - prints out contents of an PetscFunctionList
372: Collective over MPI_Comm
374: Input Parameters:
375: + list - the list of functions
376: - viewer - currently ignored
378: Level: developer
380: .seealso: PetscFunctionListAdd(), PetscFunctionListPrintTypes(), PetscFunctionList
381: @*/
382: PetscErrorCode PetscFunctionListView(PetscFunctionList list,PetscViewer viewer)
383: {
385: PetscBool iascii;
388: if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;
392: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
393: if (!iascii) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only ASCII viewer supported");
395: while (list) {
396: PetscViewerASCIIPrintf(viewer," %s\n",list->name);
397: list = list->next;
398: }
399: PetscViewerASCIIPrintf(viewer,"\n");
400: return(0);
401: }
405: /*@C
406: PetscFunctionListGet - Gets an array the contains the entries in PetscFunctionList, this is used
407: by help etc.
409: Not Collective
411: Input Parameter:
412: . list - list of types
414: Output Parameter:
415: + array - array of names
416: - n - length of array
418: Notes:
419: This allocates the array so that must be freed. BUT the individual entries are
420: not copied so should not be freed.
422: Level: developer
424: .seealso: PetscFunctionListAdd(), PetscFunctionList
425: @*/
426: PetscErrorCode PetscFunctionListGet(PetscFunctionList list,const char ***array,int *n)
427: {
428: PetscErrorCode ierr;
429: PetscInt count = 0;
430: PetscFunctionList klist = list;
433: while (list) {
434: list = list->next;
435: count++;
436: }
437: PetscMalloc1(count+1,array);
438: count = 0;
439: while (klist) {
440: (*array)[count] = klist->name;
441: klist = klist->next;
442: count++;
443: }
444: (*array)[count] = 0;
445: *n = count+1;
446: return(0);
447: }
452: /*@C
453: PetscFunctionListPrintTypes - Prints the methods available.
455: Collective over MPI_Comm
457: Input Parameters:
458: + comm - the communicator (usually MPI_COMM_WORLD)
459: . fd - file to print to, usually stdout
460: . prefix - prefix to prepend to name (optional)
461: . name - option string (for example, "-ksp_type")
462: . text - short description of the object (for example, "Krylov solvers")
463: . man - name of manual page that discusses the object (for example, "KSPCreate")
464: . list - list of types
465: - def - default (current) value
467: Level: developer
469: .seealso: PetscFunctionListAdd(), PetscFunctionList
470: @*/
471: PetscErrorCode PetscFunctionListPrintTypes(MPI_Comm comm,FILE *fd,const char prefix[],const char name[],const char text[],const char man[],PetscFunctionList list,const char def[])
472: {
474: char p[64];
477: if (!fd) fd = PETSC_STDOUT;
479: PetscStrcpy(p,"-");
480: if (prefix) {PetscStrcat(p,prefix);}
481: PetscFPrintf(comm,fd," %s%s <%s>: %s (one of)",p,name+1,def,text);
483: while (list) {
484: PetscFPrintf(comm,fd," %s",list->name);
485: list = list->next;
486: }
487: PetscFPrintf(comm,fd," (%s)\n",man);
488: return(0);
489: }
493: /*@
494: PetscFunctionListDuplicate - Creates a new list from a given object list.
496: Input Parameters:
497: . fl - pointer to list
499: Output Parameters:
500: . nl - the new list (should point to 0 to start, otherwise appends)
502: Level: developer
504: .seealso: PetscFunctionList, PetscFunctionListAdd(), PetscFlistDestroy()
506: @*/
507: PetscErrorCode PetscFunctionListDuplicate(PetscFunctionList fl,PetscFunctionList *nl)
508: {
512: while (fl) {
513: PetscFunctionListAdd(nl,fl->name,fl->routine);
514: fl = fl->next;
515: }
516: return(0);
517: }