Actual source code: reg.c
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 = NULL;
14: #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES)
16: static PetscErrorCode PetscLoadDynamicLibrary(const char *name, PetscBool *found)
17: {
18: char libs[PETSC_MAX_PATH_LEN], dlib[PETSC_MAX_PATH_LEN];
20: PetscStrncpy(libs, "${PETSC_LIB_DIR}/libpetsc", sizeof(libs));
21: PetscStrlcat(libs, name, sizeof(libs));
22: PetscDLLibraryRetrieve(PETSC_COMM_WORLD, libs, dlib, 1024, found);
23: if (*found) {
24: PetscDLLibraryAppend(PETSC_COMM_WORLD, &PetscDLLibrariesLoaded, dlib);
25: } else {
26: PetscStrncpy(libs, "${PETSC_DIR}/${PETSC_ARCH}/lib/libpetsc", sizeof(libs));
27: PetscStrlcat(libs, name, sizeof(libs));
28: PetscDLLibraryRetrieve(PETSC_COMM_WORLD, libs, dlib, 1024, found);
29: if (*found) PetscDLLibraryAppend(PETSC_COMM_WORLD, &PetscDLLibrariesLoaded, dlib);
30: }
31: return 0;
32: }
33: #endif
35: #if defined(PETSC_USE_SINGLE_LIBRARY) && !(defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES))
36: PETSC_EXTERN PetscErrorCode AOInitializePackage(void);
37: PETSC_EXTERN PetscErrorCode PetscSFInitializePackage(void);
38: #if !defined(PETSC_USE_COMPLEX)
39: PETSC_EXTERN PetscErrorCode CharacteristicInitializePackage(void);
40: #endif
41: PETSC_EXTERN PetscErrorCode ISInitializePackage(void);
42: PETSC_EXTERN PetscErrorCode VecInitializePackage(void);
43: PETSC_EXTERN PetscErrorCode MatInitializePackage(void);
44: PETSC_EXTERN PetscErrorCode DMInitializePackage(void);
45: PETSC_EXTERN PetscErrorCode PCInitializePackage(void);
46: PETSC_EXTERN PetscErrorCode KSPInitializePackage(void);
47: PETSC_EXTERN PetscErrorCode SNESInitializePackage(void);
48: PETSC_EXTERN PetscErrorCode TSInitializePackage(void);
49: PETSC_EXTERN PetscErrorCode TaoInitializePackage(void);
50: #endif
51: #if defined(PETSC_HAVE_THREADSAFETY)
52: static MPI_Comm PETSC_COMM_WORLD_INNER = 0, PETSC_COMM_SELF_INNER = 0;
53: #endif
55: /*
56: PetscInitialize_DynamicLibraries - Adds the default dynamic link libraries to the
57: search path.
58: */
59: PETSC_INTERN PetscErrorCode PetscInitialize_DynamicLibraries(void)
60: {
61: char *libname[32];
62: PetscInt nmax, i;
63: PetscBool preload = PETSC_FALSE;
64: #if defined(PETSC_HAVE_ELEMENTAL)
65: PetscBool PetscInitialized = PetscInitializeCalled;
66: #endif
68: #if defined(PETSC_HAVE_THREADSAFETY)
69: /* These must be all initialized here because it is not safe for individual threads to call these initialize routines */
70: preload = PETSC_TRUE;
71: #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: PetscOptionsGetBool(NULL, NULL, "-library_preload", &preload, NULL);
81: if (!preload) {
82: PetscSysInitializePackage();
83: } else {
84: #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES)
85: PetscBool found;
86: #if defined(PETSC_USE_SINGLE_LIBRARY)
87: PetscLoadDynamicLibrary("", &found);
89: #else
90: PetscLoadDynamicLibrary("sys", &found);
92: PetscLoadDynamicLibrary("vec", &found);
94: PetscLoadDynamicLibrary("mat", &found);
96: PetscLoadDynamicLibrary("dm", &found);
98: PetscLoadDynamicLibrary("ksp", &found);
100: PetscLoadDynamicLibrary("snes", &found);
102: PetscLoadDynamicLibrary("ts", &found);
104: PetscLoadDynamicLibrary("tao", &found);
106: #endif
107: #else /* defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES) */
108: #if defined(PETSC_USE_SINGLE_LIBRARY)
109: AOInitializePackage();
110: PetscSFInitializePackage();
111: #if !defined(PETSC_USE_COMPLEX)
112: CharacteristicInitializePackage();
113: #endif
114: ISInitializePackage();
115: VecInitializePackage();
116: MatInitializePackage();
117: DMInitializePackage();
118: PCInitializePackage();
119: KSPInitializePackage();
120: SNESInitializePackage();
121: TSInitializePackage();
122: TaoInitializePackage();
123: #else
124: SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP, "Cannot use -library_preload with multiple static PETSc libraries");
125: #endif
126: #endif /* defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES) */
127: }
129: #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES) && defined(PETSC_HAVE_BAMG)
130: {
131: PetscBool found;
132: PetscLoadDynamicLibrary("bamg", &found);
134: }
135: #endif
137: nmax = 32;
138: PetscOptionsGetStringArray(NULL, NULL, "-dll_append", libname, &nmax, NULL);
139: for (i = 0; i < nmax; i++) {
140: PetscDLLibraryAppend(PETSC_COMM_WORLD, &PetscDLLibrariesLoaded, libname[i]);
141: PetscFree(libname[i]);
142: }
144: #if defined(PETSC_HAVE_THREADSAFETY)
145: PetscCommDuplicate(PETSC_COMM_SELF, &PETSC_COMM_SELF_INNER, NULL);
146: PetscCommDuplicate(PETSC_COMM_WORLD, &PETSC_COMM_WORLD_INNER, NULL);
147: #endif
148: #if defined(PETSC_HAVE_ELEMENTAL)
149: /* in Fortran, PetscInitializeCalled is set to PETSC_TRUE before PetscInitialize_DynamicLibraries() */
150: /* in C, it is not the case, but the value is forced to PETSC_TRUE so that PetscRegisterFinalize() is called */
151: PetscInitializeCalled = PETSC_TRUE;
152: PetscElementalInitializePackage();
153: PetscInitializeCalled = PetscInitialized;
154: #endif
155: return 0;
156: }
158: /*
159: PetscFinalize_DynamicLibraries - Closes the opened dynamic libraries.
160: */
161: PETSC_INTERN PetscErrorCode PetscFinalize_DynamicLibraries(void)
162: {
163: PetscBool flg = PETSC_FALSE;
165: PetscOptionsGetBool(NULL, NULL, "-dll_view", &flg, NULL);
166: if (flg) PetscDLLibraryPrintPath(PetscDLLibrariesLoaded);
167: PetscDLLibraryClose(PetscDLLibrariesLoaded);
169: #if defined(PETSC_HAVE_THREADSAFETY)
170: PetscCommDestroy(&PETSC_COMM_SELF_INNER);
171: PetscCommDestroy(&PETSC_COMM_WORLD_INNER);
172: #endif
174: PetscDLLibrariesLoaded = NULL;
175: return 0;
176: }
178: /* ------------------------------------------------------------------------------*/
179: struct _n_PetscFunctionList {
180: void (*routine)(void); /* the routine */
181: char *name; /* string to identify routine */
182: PetscFunctionList next; /* next pointer */
183: PetscFunctionList next_list; /* used to maintain list of all lists for freeing */
184: };
186: /*
187: Keep a linked list of PetscFunctionLists so that we can destroy all the left-over ones.
188: */
189: static PetscFunctionList dlallhead = NULL;
191: static PetscErrorCode PetscFunctionListCreateNode_Private(PetscFunctionList *entry, const char name[], void (*func)(void))
192: {
193: PetscNew(entry);
194: PetscStrallocpy(name, &(*entry)->name);
195: (*entry)->routine = func;
196: (*entry)->next = NULL;
197: return 0;
198: }
200: /*MC
201: PetscFunctionListAdd - Given a routine and a string id, saves that routine in the
202: specified registry.
204: Synopsis:
205: #include <petscsys.h>
206: PetscErrorCode PetscFunctionListAdd(PetscFunctionList *flist,const char name[],void (*fptr)(void))
208: Not Collective
210: Input Parameters:
211: + flist - pointer to function list object
212: . name - string to identify routine
213: - fptr - function pointer
215: Notes:
216: To remove a registered routine, pass in a NULL fptr.
218: Users who wish to register new classes for use by a particular PETSc
219: component (e.g., `SNES`) should generally call the registration routine
220: for that particular component (e.g., `SNESRegister()`) instead of
221: calling `PetscFunctionListAdd()` directly.
223: Level: developer
225: .seealso: `PetscFunctionListDestroy()`, `SNESRegister()`, `KSPRegister()`,
226: `PCRegister()`, `TSRegister()`, `PetscFunctionList`, `PetscObjectComposeFunction()`
227: M*/
228: PETSC_EXTERN PetscErrorCode PetscFunctionListAdd_Private(PetscFunctionList *fl, const char name[], void (*fnc)(void))
229: {
233: if (*fl) {
234: /* search list to see if it is already there */
235: PetscFunctionList empty_node = NULL;
236: PetscFunctionList ne = *fl;
238: while (1) {
239: PetscBool founddup;
241: PetscStrcmp(ne->name, name, &founddup);
242: if (founddup) {
243: /* found duplicate, clear it */
244: ne->routine = fnc;
245: if (!fnc) PetscFree(ne->name);
246: return 0;
247: }
249: if (!empty_node && !ne->routine && !ne->name) {
250: /* save the empty node for later */
251: empty_node = ne;
252: }
254: if (!ne->next) break; /* end of list */
255: ne = ne->next;
256: }
258: /* there was an empty entry we could grab, fill it and bail */
259: if (empty_node) {
260: empty_node->routine = fnc;
261: PetscStrallocpy(name, &empty_node->name);
262: } else {
263: /* create new entry at the end of list */
264: PetscFunctionListCreateNode_Private(&ne->next, name, fnc);
265: }
266: return 0;
267: }
269: /* we didn't have a list */
270: PetscFunctionListCreateNode_Private(fl, name, fnc);
271: if (PetscDefined(USE_DEBUG)) {
272: const PetscFunctionList head = dlallhead;
274: /* add this new list to list of all lists */
275: dlallhead = *fl;
276: (*fl)->next_list = head;
277: }
278: return 0;
279: }
281: /*@
282: PetscFunctionListDestroy - Destroys a list of registered routines.
284: Input Parameter:
285: . fl - pointer to list
287: Level: developer
289: .seealso: `PetscFunctionListAdd()`, `PetscFunctionList`, `PetscFunctionListClear()`
290: @*/
291: PetscErrorCode PetscFunctionListDestroy(PetscFunctionList *fl)
292: {
293: PetscFunctionList next, entry, tmp = dlallhead;
295: if (!*fl) return 0;
297: /*
298: Remove this entry from the main DL list (if it is in it)
299: */
300: if (dlallhead == *fl) {
301: if (dlallhead->next_list) dlallhead = dlallhead->next_list;
302: else dlallhead = NULL;
303: } else if (tmp) {
304: while (tmp->next_list != *fl) {
305: tmp = tmp->next_list;
306: if (!tmp->next_list) break;
307: }
308: if (tmp->next_list) tmp->next_list = tmp->next_list->next_list;
309: }
311: /* free this list */
312: entry = *fl;
313: while (entry) {
314: next = entry->next;
315: PetscFree(entry->name);
316: PetscFree(entry);
317: entry = next;
318: }
319: *fl = NULL;
320: return 0;
321: }
323: /*@
324: PetscFunctionListClear - Clear a `PetscFunctionList`
326: Not Collective
328: Input Parameter:
329: . fl - The `PetscFunctionList` to clear
331: Notes:
332: This clears the contents of `fl` but does not deallocate the entries themselves.
334: Level: developer
336: .seealso: `PetscFunctionList`, `PetscFunctionListDestroy()`, `PetscFunctionListAdd()`
337: @*/
338: PetscErrorCode PetscFunctionListClear(PetscFunctionList fl)
339: {
340: /* free the names and clear the routine but don't deallocate the node */
341: while (fl) {
342: PetscFree(fl->name);
343: fl->routine = NULL;
344: fl = fl->next;
345: }
346: return 0;
347: }
349: /*
350: Print registered PetscFunctionLists
351: */
352: PetscErrorCode PetscFunctionListPrintAll(void)
353: {
354: PetscFunctionList tmp = dlallhead;
356: if (tmp) PetscPrintf(PETSC_COMM_SELF, "[%d] Registered PetscFunctionLists\n", PetscGlobalRank);
357: while (tmp) {
358: PetscPrintf(PETSC_COMM_SELF, "[%d] %s\n", PetscGlobalRank, tmp->name);
359: tmp = tmp->next_list;
360: }
361: return 0;
362: }
364: /*MC
365: PetscFunctionListNonEmpty - Print composed names for non null function pointers
367: Input Parameter:
368: . flist - pointer to list
370: Level: developer
372: .seealso: `PetscFunctionListAdd()`, `PetscFunctionList`, `PetscObjectQueryFunction()`
373: M*/
374: PetscErrorCode PetscFunctionListPrintNonEmpty(PetscFunctionList fl)
375: {
376: while (fl) {
377: PetscFunctionList next = fl->next;
378: if (fl->routine) PetscPrintf(PETSC_COMM_SELF, "[%d] function name: %s\n", PetscGlobalRank, fl->name);
379: fl = next;
380: }
381: return 0;
382: }
384: /*MC
385: PetscFunctionListFind - Find function registered under given name
387: Synopsis:
388: #include <petscsys.h>
389: PetscErrorCode PetscFunctionListFind(PetscFunctionList flist,const char name[],void (**fptr)(void))
391: Input Parameters:
392: + flist - pointer to list
393: - name - name registered for the function
395: Output Parameters:
396: . fptr - the function pointer if name was found, else NULL
398: Level: developer
400: .seealso: `PetscFunctionListAdd()`, `PetscFunctionList`, `PetscObjectQueryFunction()`
401: M*/
402: PETSC_EXTERN PetscErrorCode PetscFunctionListFind_Private(PetscFunctionList fl, const char name[], void (**r)(void))
403: {
404: PetscFunctionList entry = fl;
408: while (entry) {
409: PetscBool flg;
411: PetscStrcmp(name, entry->name, &flg);
412: if (flg) {
413: *r = entry->routine;
414: return 0;
415: }
416: entry = entry->next;
417: }
418: *r = NULL;
419: return 0;
420: }
422: /*@
423: PetscFunctionListView - prints out contents of an PetscFunctionList
425: Collective over viewer
427: Input Parameters:
428: + list - the list of functions
429: - viewer - currently ignored
431: Level: developer
433: .seealso: `PetscFunctionListAdd()`, `PetscFunctionListPrintTypes()`, `PetscFunctionList`
434: @*/
435: PetscErrorCode PetscFunctionListView(PetscFunctionList list, PetscViewer viewer)
436: {
437: PetscBool iascii;
439: if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;
443: PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii);
446: while (list) {
447: PetscViewerASCIIPrintf(viewer, " %s\n", list->name);
448: list = list->next;
449: }
450: PetscViewerASCIIPrintf(viewer, "\n");
451: return 0;
452: }
454: /*@C
455: PetscFunctionListGet - Gets an array the contains the entries in `PetscFunctionList`, this is used
456: by help etc.
458: Not Collective
460: Input Parameter:
461: . list - list of types
463: Output Parameters:
464: + array - array of names
465: - n - length of array
467: Note:
468: This allocates the array so that must be freed. BUT the individual entries are
469: not copied so should not be freed.
471: Level: developer
473: .seealso: `PetscFunctionListAdd()`, `PetscFunctionList`
474: @*/
475: PetscErrorCode PetscFunctionListGet(PetscFunctionList list, const char ***array, int *n)
476: {
477: PetscInt count = 0;
478: PetscFunctionList klist = list;
480: while (list) {
481: list = list->next;
482: count++;
483: }
484: PetscMalloc1(count + 1, (char ***)array);
485: count = 0;
486: while (klist) {
487: (*array)[count] = klist->name;
488: klist = klist->next;
489: count++;
490: }
491: (*array)[count] = NULL;
492: *n = count + 1;
493: return 0;
494: }
496: /*@C
497: PetscFunctionListPrintTypes - Prints the methods available in a list of functions
499: Collective over MPI_Comm
501: Input Parameters:
502: + comm - the communicator (usually `MPI_COMM_WORLD`)
503: . fd - file to print to, usually stdout
504: . prefix - prefix to prepend to name (optional)
505: . name - option string (for example, "-ksp_type")
506: . text - short description of the object (for example, "Krylov solvers")
507: . man - name of manual page that discusses the object (for example, "KSPCreate")
508: . list - list of types
509: . def - default (current) value
510: - newv - new value
512: Level: developer
514: .seealso: `PetscFunctionListAdd()`, `PetscFunctionList`
515: @*/
516: PetscErrorCode PetscFunctionListPrintTypes(MPI_Comm comm, FILE *fd, const char prefix[], const char name[], const char text[], const char man[], PetscFunctionList list, const char def[], const char newv[])
517: {
518: char p[64];
520: if (!fd) fd = PETSC_STDOUT;
522: PetscStrncpy(p, "-", sizeof(p));
523: if (prefix) PetscStrlcat(p, prefix, sizeof(p));
524: PetscFPrintf(comm, fd, " %s%s <now %s : formerly %s>: %s (one of)", p, name + 1, newv, def, text);
526: while (list) {
527: PetscFPrintf(comm, fd, " %s", list->name);
528: list = list->next;
529: }
530: PetscFPrintf(comm, fd, " (%s)\n", man);
531: return 0;
532: }
534: /*@
535: PetscFunctionListDuplicate - Creates a new list from a given object list.
537: Input Parameters:
538: . fl - pointer to list
540: Output Parameters:
541: . nl - the new list (should point to 0 to start, otherwise appends)
543: Level: developer
545: .seealso: `PetscFunctionList`, `PetscFunctionListAdd()`, `PetscFlistDestroy()`
546: @*/
547: PetscErrorCode PetscFunctionListDuplicate(PetscFunctionList fl, PetscFunctionList *nl)
548: {
549: while (fl) {
550: PetscFunctionListAdd(nl, fl->name, fl->routine);
551: fl = fl->next;
552: }
553: return 0;
554: }