Actual source code: reg.c
petsc-3.9.4 2018-09-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 <petsc/private/petscimpl.h>
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) && defined(PETSC_USE_SHARED_LIBRARIES)
16: PetscErrorCode PetscLoadDynamicLibrary(const char *name,PetscBool *found)
17: {
18: char libs[PETSC_MAX_PATH_LEN],dlib[PETSC_MAX_PATH_LEN];
22: PetscStrncpy(libs,"${PETSC_LIB_DIR}/libpetsc",sizeof(libs));
23: PetscStrlcat(libs,name,sizeof(libs));
24: PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,found);
25: if (*found) {
26: PetscDLLibraryAppend(PETSC_COMM_WORLD,&PetscDLLibrariesLoaded,dlib);
27: } else {
28: PetscStrncpy(libs,"${PETSC_DIR}/${PETSC_ARCH}/lib/libpetsc",sizeof(libs));
29: PetscStrlcat(libs,name,sizeof(libs));
30: PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,found);
31: if (*found) {
32: PetscDLLibraryAppend(PETSC_COMM_WORLD,&PetscDLLibrariesLoaded,dlib);
33: }
34: }
35: return(0);
36: }
38: #endif
40: #if defined(PETSC_HAVE_THREADSAFETY)
41: extern PetscErrorCode AOInitializePackage(void);
42: extern PetscErrorCode PetscSFInitializePackage(void);
43: #if !defined(PETSC_USE_COMPLEX)
44: extern PetscErrorCode CharacteristicInitializePackage(void);
45: #endif
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
57: /*
58: PetscInitialize_DynamicLibraries - Adds the default dynamic link libraries to the
59: search path.
60: */
61: PetscErrorCode PetscInitialize_DynamicLibraries(void)
62: {
63: char *libname[32];
65: PetscInt nmax,i;
66: #if defined(PETSC_USE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES)
67: PetscBool preload;
68: #endif
71: nmax = 32;
72: PetscOptionsGetStringArray(NULL,NULL,"-dll_prepend",libname,&nmax,NULL);
73: for (i=0; i<nmax; i++) {
74: PetscDLLibraryPrepend(PETSC_COMM_WORLD,&PetscDLLibrariesLoaded,libname[i]);
75: PetscFree(libname[i]);
76: }
78: #if !defined(PETSC_USE_DYNAMIC_LIBRARIES) || !defined(PETSC_USE_SHARED_LIBRARIES)
79: /*
80: This just initializes the most basic PETSc stuff.
82: The classes, from PetscDraw to PetscTS, are initialized the first
83: time an XXCreate() is called.
84: */
85: PetscSysInitializePackage();
86: #else
87: preload = PETSC_FALSE;
88: PetscOptionsGetBool(NULL,NULL,"-dynamic_library_preload",&preload,NULL);
89: if (preload) {
90: PetscBool found;
91: #if defined(PETSC_USE_SINGLE_LIBRARY)
92: PetscLoadDynamicLibrary("",&found);
93: if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc dynamic library \n You cannot move the dynamic libraries!");
94: #else
95: PetscLoadDynamicLibrary("sys",&found);
96: if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc dynamic library \n You cannot move the dynamic libraries!");
97: PetscLoadDynamicLibrary("vec",&found);
98: if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc Vec dynamic library \n You cannot move the dynamic libraries!");
99: PetscLoadDynamicLibrary("mat",&found);
100: if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc Mat dynamic library \n You cannot move the dynamic libraries!");
101: PetscLoadDynamicLibrary("dm",&found);
102: if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc DM dynamic library \n You cannot move the dynamic libraries!");
103: PetscLoadDynamicLibrary("ksp",&found);
104: if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc KSP dynamic library \n You cannot move the dynamic libraries!");
105: PetscLoadDynamicLibrary("snes",&found);
106: if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc SNES dynamic library \n You cannot move the dynamic libraries!");
107: PetscLoadDynamicLibrary("ts",&found);
108: if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc TS dynamic library \n You cannot move the dynamic libraries!");
109: #endif
110: }
111: #endif
113: nmax = 32;
114: PetscOptionsGetStringArray(NULL,NULL,"-dll_append",libname,&nmax,NULL);
115: for (i=0; i<nmax; i++) {
116: PetscDLLibraryAppend(PETSC_COMM_WORLD,&PetscDLLibrariesLoaded,libname[i]);
117: PetscFree(libname[i]);
118: }
120: #if defined(PETSC_HAVE_THREADSAFETY)
121: /* These must be done here because it is not safe for individual threads to call these initialize routines */
122: AOInitializePackage();
123: PetscSFInitializePackage();
124: #if !defined(PETSC_USE_COMPLEX)
125: CharacteristicInitializePackage();
126: #endif
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: }
141: /*
142: PetscFinalize_DynamicLibraries - Closes the opened dynamic libraries.
143: */
144: PetscErrorCode PetscFinalize_DynamicLibraries(void)
145: {
147: PetscBool flg = PETSC_FALSE;
150: PetscOptionsGetBool(NULL,NULL,"-dll_view",&flg,NULL);
151: if (flg) { PetscDLLibraryPrintPath(PetscDLLibrariesLoaded); }
152: PetscDLLibraryClose(PetscDLLibrariesLoaded);
154: #if defined(PETSC_HAVE_THREADSAFETY)
155: PetscCommDestroy(&PETSC_COMM_SELF_INNER);
156: PetscCommDestroy(&PETSC_COMM_WORLD_INNER);
157: #endif
159: PetscDLLibrariesLoaded = 0;
160: return(0);
161: }
165: /* ------------------------------------------------------------------------------*/
166: struct _n_PetscFunctionList {
167: void (*routine)(void); /* the routine */
168: char *name; /* string to identify routine */
169: PetscFunctionList next; /* next pointer */
170: PetscFunctionList next_list; /* used to maintain list of all lists for freeing */
171: };
173: /*
174: Keep a linked list of PetscFunctionLists so that we can destroy all the left-over ones.
175: */
176: static PetscFunctionList dlallhead = 0;
178: /*MC
179: PetscFunctionListAdd - Given a routine and a string id, saves that routine in the
180: specified registry.
182: Synopsis:
183: #include <petscsys.h>
184: PetscErrorCode PetscFunctionListAdd(PetscFunctionList *flist,const char name[],void (*fptr)(void))
186: Not Collective
188: Input Parameters:
189: + flist - pointer to function list object
190: . name - string to identify routine
191: - fptr - function pointer
193: Notes:
194: To remove a registered routine, pass in a NULL fptr.
196: Users who wish to register new classes for use by a particular PETSc
197: component (e.g., SNES) should generally call the registration routine
198: for that particular component (e.g., SNESRegister()) instead of
199: calling PetscFunctionListAdd() directly.
201: Level: developer
203: .seealso: PetscFunctionListDestroy(), SNESRegister(), KSPRegister(),
204: PCRegister(), TSRegister(), PetscFunctionList, PetscObjectComposeFunction()
205: M*/
206: PETSC_EXTERN PetscErrorCode PetscFunctionListAdd_Private(PetscFunctionList *fl,const char name[],void (*fnc)(void))
207: {
208: PetscFunctionList entry,ne;
209: PetscErrorCode ierr;
212: if (!*fl) {
213: PetscNew(&entry);
214: PetscStrallocpy(name,&entry->name);
215: entry->routine = fnc;
216: entry->next = 0;
217: *fl = entry;
219: #if defined(PETSC_USE_DEBUG)
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: #endif
231: } else {
232: /* search list to see if it is already there */
233: ne = *fl;
234: while (ne) {
235: PetscBool founddup;
237: PetscStrcmp(ne->name,name,&founddup);
238: if (founddup) { /* found duplicate */
239: ne->routine = fnc;
240: return(0);
241: }
242: if (ne->next) ne = ne->next;
243: else break;
244: }
245: /* create new entry and add to end of list */
246: PetscNew(&entry);
247: PetscStrallocpy(name,&entry->name);
248: entry->routine = fnc;
249: entry->next = 0;
250: ne->next = entry;
251: }
252: return(0);
253: }
255: /*@
256: PetscFunctionListDestroy - Destroys a list of registered routines.
258: Input Parameter:
259: . fl - pointer to list
261: Level: developer
263: .seealso: PetscFunctionListAdd(), PetscFunctionList
264: @*/
265: PetscErrorCode PetscFunctionListDestroy(PetscFunctionList *fl)
266: {
267: PetscFunctionList next,entry,tmp = dlallhead;
268: PetscErrorCode ierr;
271: if (!*fl) return(0);
273: /*
274: Remove this entry from the master DL list (if it is in it)
275: */
276: if (dlallhead == *fl) {
277: if (dlallhead->next_list) dlallhead = dlallhead->next_list;
278: else dlallhead = NULL;
279: } else if (tmp) {
280: while (tmp->next_list != *fl) {
281: tmp = tmp->next_list;
282: if (!tmp->next_list) break;
283: }
284: if (tmp->next_list) tmp->next_list = tmp->next_list->next_list;
285: }
287: /* free this list */
288: entry = *fl;
289: while (entry) {
290: next = entry->next;
291: PetscFree(entry->name);
292: PetscFree(entry);
293: entry = next;
294: }
295: *fl = 0;
296: return(0);
297: }
299: /*
300: Print any PetscFunctionLists that have not be destroyed
301: */
302: PetscErrorCode PetscFunctionListPrintAll(void)
303: {
304: PetscFunctionList tmp = dlallhead;
305: PetscErrorCode ierr;
308: if (tmp) {
309: PetscPrintf(PETSC_COMM_WORLD,"The following PetscFunctionLists were not destroyed\n");
310: }
311: while (tmp) {
312: PetscPrintf(PETSC_COMM_WORLD,"%s \n",tmp->name);
313: tmp = tmp->next_list;
314: }
315: return(0);
316: }
318: /*MC
319: PetscFunctionListFind - Find function registered under given name
321: Synopsis:
322: #include <petscsys.h>
323: PetscErrorCode PetscFunctionListFind(PetscFunctionList flist,const char name[],void (**fptr)(void))
325: Input Parameters:
326: + flist - pointer to list
327: - name - name registered for the function
329: Output Parameters:
330: . fptr - the function pointer if name was found, else NULL
332: Level: developer
334: .seealso: PetscFunctionListAdd(), PetscFunctionList, PetscObjectQueryFunction()
335: M*/
336: PETSC_EXTERN PetscErrorCode PetscFunctionListFind_Private(PetscFunctionList fl,const char name[],void (**r)(void))
337: {
338: PetscFunctionList entry = fl;
339: PetscErrorCode ierr;
340: PetscBool flg;
343: if (!name) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Trying to find routine with null name");
345: *r = 0;
346: while (entry) {
347: PetscStrcmp(name,entry->name,&flg);
348: if (flg) {
349: *r = entry->routine;
350: return(0);
351: }
352: entry = entry->next;
353: }
354: return(0);
355: }
357: /*@
358: PetscFunctionListView - prints out contents of an PetscFunctionList
360: Collective over MPI_Comm
362: Input Parameters:
363: + list - the list of functions
364: - viewer - currently ignored
366: Level: developer
368: .seealso: PetscFunctionListAdd(), PetscFunctionListPrintTypes(), PetscFunctionList
369: @*/
370: PetscErrorCode PetscFunctionListView(PetscFunctionList list,PetscViewer viewer)
371: {
373: PetscBool iascii;
376: if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;
380: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
381: if (!iascii) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only ASCII viewer supported");
383: while (list) {
384: PetscViewerASCIIPrintf(viewer," %s\n",list->name);
385: list = list->next;
386: }
387: PetscViewerASCIIPrintf(viewer,"\n");
388: return(0);
389: }
391: /*@C
392: PetscFunctionListGet - Gets an array the contains the entries in PetscFunctionList, this is used
393: by help etc.
395: Not Collective
397: Input Parameter:
398: . list - list of types
400: Output Parameter:
401: + array - array of names
402: - n - length of array
404: Notes:
405: This allocates the array so that must be freed. BUT the individual entries are
406: not copied so should not be freed.
408: Level: developer
410: .seealso: PetscFunctionListAdd(), PetscFunctionList
411: @*/
412: PetscErrorCode PetscFunctionListGet(PetscFunctionList list,const char ***array,int *n)
413: {
414: PetscErrorCode ierr;
415: PetscInt count = 0;
416: PetscFunctionList klist = list;
419: while (list) {
420: list = list->next;
421: count++;
422: }
423: PetscMalloc1(count+1,(char***)array);
424: count = 0;
425: while (klist) {
426: (*array)[count] = klist->name;
427: klist = klist->next;
428: count++;
429: }
430: (*array)[count] = 0;
431: *n = count+1;
432: return(0);
433: }
436: /*@C
437: PetscFunctionListPrintTypes - Prints the methods available.
439: Collective over MPI_Comm
441: Input Parameters:
442: + comm - the communicator (usually MPI_COMM_WORLD)
443: . fd - file to print to, usually stdout
444: . prefix - prefix to prepend to name (optional)
445: . name - option string (for example, "-ksp_type")
446: . text - short description of the object (for example, "Krylov solvers")
447: . man - name of manual page that discusses the object (for example, "KSPCreate")
448: . list - list of types
449: - def - default (current) value
451: Level: developer
453: .seealso: PetscFunctionListAdd(), PetscFunctionList
454: @*/
455: PetscErrorCode PetscFunctionListPrintTypes(MPI_Comm comm,FILE *fd,const char prefix[],const char name[],const char text[],const char man[],PetscFunctionList list,const char def[])
456: {
458: char p[64];
461: if (!fd) fd = PETSC_STDOUT;
463: PetscStrncpy(p,"-",sizeof(p));
464: if (prefix) {PetscStrlcat(p,prefix,sizeof(p));}
465: PetscFPrintf(comm,fd," %s%s <%s>: %s (one of)",p,name+1,def,text);
467: while (list) {
468: PetscFPrintf(comm,fd," %s",list->name);
469: list = list->next;
470: }
471: PetscFPrintf(comm,fd," (%s)\n",man);
472: return(0);
473: }
475: /*@
476: PetscFunctionListDuplicate - Creates a new list from a given object list.
478: Input Parameters:
479: . fl - pointer to list
481: Output Parameters:
482: . nl - the new list (should point to 0 to start, otherwise appends)
484: Level: developer
486: .seealso: PetscFunctionList, PetscFunctionListAdd(), PetscFlistDestroy()
488: @*/
489: PetscErrorCode PetscFunctionListDuplicate(PetscFunctionList fl,PetscFunctionList *nl)
490: {
494: while (fl) {
495: PetscFunctionListAdd(nl,fl->name,fl->routine);
496: fl = fl->next;
497: }
498: return(0);
499: }