Actual source code: reg.c
1: /*
2: Provides a general mechanism to allow one to register new routines in
3: dynamic libraries for many of the PETSc objects (including, e.g., KSP and PC).
4: */
5: #include <petsc/private/petscimpl.h>
6: #include <petscviewer.h>
8: #include <petsc/private/hashmap.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: PetscFunctionBegin;
21: PetscCall(PetscStrncpy(libs, "${PETSC_LIB_DIR}/libpetsc", sizeof(libs)));
22: PetscCall(PetscStrlcat(libs, name, sizeof(libs)));
23: #if defined(PETSC_LIB_NAME_SUFFIX)
24: PetscCall(PetscStrlcat(libs, PETSC_LIB_NAME_SUFFIX, sizeof(libs)));
25: #endif
26: PetscCall(PetscDLLibraryRetrieve(PETSC_COMM_WORLD, libs, dlib, 1024, found));
27: if (*found) {
28: PetscCall(PetscDLLibraryAppend(PETSC_COMM_WORLD, &PetscDLLibrariesLoaded, dlib));
29: } else {
30: PetscCall(PetscStrncpy(libs, "${PETSC_DIR}/${PETSC_ARCH}/lib/libpetsc", sizeof(libs)));
31: PetscCall(PetscStrlcat(libs, name, sizeof(libs)));
32: #if defined(PETSC_LIB_NAME_SUFFIX)
33: PetscCall(PetscStrlcat(libs, PETSC_LIB_NAME_SUFFIX, sizeof(libs)));
34: #endif
35: PetscCall(PetscDLLibraryRetrieve(PETSC_COMM_WORLD, libs, dlib, 1024, found));
36: if (*found) PetscCall(PetscDLLibraryAppend(PETSC_COMM_WORLD, &PetscDLLibrariesLoaded, dlib));
37: }
38: PetscFunctionReturn(PETSC_SUCCESS);
39: }
40: #endif
42: #if defined(PETSC_USE_SINGLE_LIBRARY) && !(defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES))
43: PETSC_EXTERN PetscErrorCode AOInitializePackage(void);
44: PETSC_EXTERN PetscErrorCode PetscSFInitializePackage(void);
45: #if !defined(PETSC_USE_COMPLEX)
46: PETSC_EXTERN PetscErrorCode CharacteristicInitializePackage(void);
47: #endif
48: PETSC_EXTERN PetscErrorCode ISInitializePackage(void);
49: PETSC_EXTERN PetscErrorCode VecInitializePackage(void);
50: PETSC_EXTERN PetscErrorCode MatInitializePackage(void);
51: PETSC_EXTERN PetscErrorCode DMInitializePackage(void);
52: PETSC_EXTERN PetscErrorCode PCInitializePackage(void);
53: PETSC_EXTERN PetscErrorCode KSPInitializePackage(void);
54: PETSC_EXTERN PetscErrorCode SNESInitializePackage(void);
55: PETSC_EXTERN PetscErrorCode TSInitializePackage(void);
56: PETSC_EXTERN PetscErrorCode TaoInitializePackage(void);
57: #endif
59: /*
60: PetscInitialize_DynamicLibraries - Adds the default dynamic link libraries to the
61: search path.
62: */
63: PETSC_INTERN PetscErrorCode PetscInitialize_DynamicLibraries(void)
64: {
65: char *libname[32];
66: PetscInt nmax, i;
67: PetscBool preload = PETSC_FALSE;
68: #if defined(PETSC_HAVE_ELEMENTAL)
69: PetscBool PetscInitialized = PetscInitializeCalled;
70: #endif
72: PetscFunctionBegin;
73: #if defined(PETSC_HAVE_THREADSAFETY)
74: /* These must be all initialized here because it is not safe for individual threads to call these initialize routines */
75: preload = PETSC_TRUE;
76: #endif
78: nmax = 32;
79: PetscCall(PetscOptionsGetStringArray(NULL, NULL, "-dll_prepend", libname, &nmax, NULL));
80: for (i = 0; i < nmax; i++) {
81: PetscCall(PetscDLLibraryPrepend(PETSC_COMM_WORLD, &PetscDLLibrariesLoaded, libname[i]));
82: PetscCall(PetscFree(libname[i]));
83: }
85: PetscCall(PetscOptionsGetBool(NULL, NULL, "-library_preload", &preload, NULL));
86: if (!preload) {
87: PetscCall(PetscSysInitializePackage());
88: } else {
89: #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES)
90: PetscBool found;
91: #if defined(PETSC_USE_SINGLE_LIBRARY)
92: PetscCall(PetscLoadDynamicLibrary("", &found));
93: PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc dynamic library. You cannot move the dynamic libraries!");
94: #else
95: PetscCall(PetscLoadDynamicLibrary("sys", &found));
96: PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc Sys dynamic library. You cannot move the dynamic libraries!");
97: PetscCall(PetscLoadDynamicLibrary("vec", &found));
98: PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc Vec dynamic library. You cannot move the dynamic libraries!");
99: PetscCall(PetscLoadDynamicLibrary("mat", &found));
100: PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc Mat dynamic library. You cannot move the dynamic libraries!");
101: PetscCall(PetscLoadDynamicLibrary("dm", &found));
102: PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc DM dynamic library. You cannot move the dynamic libraries!");
103: PetscCall(PetscLoadDynamicLibrary("ksp", &found));
104: PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc KSP dynamic library. You cannot move the dynamic libraries!");
105: PetscCall(PetscLoadDynamicLibrary("snes", &found));
106: PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc SNES dynamic library. You cannot move the dynamic libraries!");
107: PetscCall(PetscLoadDynamicLibrary("ts", &found));
108: PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc TS dynamic library. You cannot move the dynamic libraries!");
109: PetscCall(PetscLoadDynamicLibrary("tao", &found));
110: PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate Tao dynamic library. You cannot move the dynamic libraries!");
111: #endif
112: #else /* defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES) */
113: #if defined(PETSC_USE_SINGLE_LIBRARY)
114: PetscCall(AOInitializePackage());
115: PetscCall(PetscSFInitializePackage());
116: #if !defined(PETSC_USE_COMPLEX)
117: PetscCall(CharacteristicInitializePackage());
118: #endif
119: PetscCall(ISInitializePackage());
120: PetscCall(VecInitializePackage());
121: PetscCall(MatInitializePackage());
122: PetscCall(DMInitializePackage());
123: PetscCall(PCInitializePackage());
124: PetscCall(KSPInitializePackage());
125: PetscCall(SNESInitializePackage());
126: PetscCall(TSInitializePackage());
127: PetscCall(TaoInitializePackage());
128: #else
129: SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP, "Cannot use -library_preload with multiple static PETSc libraries");
130: #endif
131: #endif /* defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES) */
132: }
134: #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES) && defined(PETSC_HAVE_BAMG)
135: {
136: PetscBool found;
137: PetscCall(PetscLoadDynamicLibrary("bamg", &found));
138: PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc BAMG dynamic library. You cannot move the dynamic libraries!");
139: }
140: #endif
141: #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES) && defined(PETSC_HAVE_PFLARE)
142: {
143: PetscBool found;
144: PetscCall(PetscLoadDynamicLibrary("pflare", &found));
145: PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PFLARE dynamic library. You cannot move the dynamic libraries!");
146: }
147: #endif
149: nmax = 32;
150: PetscCall(PetscOptionsGetStringArray(NULL, NULL, "-dll_append", libname, &nmax, NULL));
151: for (i = 0; i < nmax; i++) {
152: PetscCall(PetscDLLibraryAppend(PETSC_COMM_WORLD, &PetscDLLibrariesLoaded, libname[i]));
153: PetscCall(PetscFree(libname[i]));
154: }
156: #if defined(PETSC_HAVE_ELEMENTAL)
157: /* in Fortran, PetscInitializeCalled is set to PETSC_TRUE before PetscInitialize_DynamicLibraries() */
158: /* in C, it is not the case, but the value is forced to PETSC_TRUE so that PetscRegisterFinalize() is called */
159: PetscInitializeCalled = PETSC_TRUE;
160: PetscCall(PetscElementalInitializePackage());
161: PetscInitializeCalled = PetscInitialized;
162: #endif
163: PetscFunctionReturn(PETSC_SUCCESS);
164: }
166: /*
167: PetscFinalize_DynamicLibraries - Closes the opened dynamic libraries.
168: */
169: PETSC_INTERN PetscErrorCode PetscFinalize_DynamicLibraries(void)
170: {
171: PetscBool flg = PETSC_FALSE;
173: PetscFunctionBegin;
174: PetscCall(PetscOptionsGetBool(NULL, NULL, "-dll_view", &flg, NULL));
175: if (flg) PetscCall(PetscDLLibraryPrintPath(PetscDLLibrariesLoaded));
176: PetscCall(PetscDLLibraryClose(PetscDLLibrariesLoaded));
177: PetscDLLibrariesLoaded = NULL;
178: PetscFunctionReturn(PETSC_SUCCESS);
179: }
181: PETSC_HASH_MAP(HMapFunc, const char *, PetscErrorCodeFn *, kh_str_hash_func, kh_str_hash_equal, NULL)
183: struct _n_PetscFunctionList {
184: PetscHMapFunc map;
185: };
187: /* Keep a linked list of PetscFunctionLists so that we can destroy all the left-over ones. */
188: typedef struct n_PetscFunctionListDLAll *PetscFunctionListDLAll;
189: struct n_PetscFunctionListDLAll {
190: PetscFunctionList data;
191: PetscFunctionListDLAll next;
192: };
194: static PetscFunctionListDLAll dlallhead = NULL;
196: static PetscErrorCode PetscFunctionListDLAllPush_Private(PetscFunctionList fl)
197: {
198: PetscFunctionBegin;
199: if (PetscDefined(USE_DEBUG) && !PetscDefined(HAVE_THREADSAFETY)) {
200: PetscFunctionListDLAll head;
202: PetscCall(PetscNew(&head));
203: head->data = fl;
204: head->next = dlallhead;
205: dlallhead = head;
206: }
207: PetscFunctionReturn(PETSC_SUCCESS);
208: }
210: static PetscErrorCode PetscFunctionListDLAllPop_Private(PetscFunctionList fl)
211: {
212: PetscFunctionBegin;
213: if (PetscDefined(USE_DEBUG) && !PetscDefined(HAVE_THREADSAFETY)) {
214: PetscFunctionListDLAll current = dlallhead, prev = NULL;
216: /* Remove this entry from the main DL list (if it is in it) */
217: while (current) {
218: const PetscFunctionListDLAll next = current->next;
220: if (current->data == fl) {
221: if (prev) {
222: // somewhere in the middle (or end) of the list
223: prev->next = next;
224: } else {
225: // prev = NULL implies current = dlallhead, so front of list
226: dlallhead = next;
227: }
228: PetscCall(PetscFree(current));
229: break;
230: }
231: prev = current;
232: current = next;
233: }
234: }
235: PetscFunctionReturn(PETSC_SUCCESS);
236: }
238: static PetscErrorCode PetscHMapFuncInsert_Private(PetscHMapFunc map, const char name[], PetscErrorCodeFn *fnc)
239: {
240: PetscHashIter it;
241: PetscBool found;
243: PetscFunctionBegin;
244: PetscAssertPointer(name, 2);
246: PetscCall(PetscHMapFuncFind(map, name, &it, &found));
247: if (fnc) {
248: if (found) {
249: PetscCall(PetscHMapFuncIterSet(map, it, fnc));
250: } else {
251: char *tmp_name;
253: PetscCall(PetscStrallocpy(name, &tmp_name));
254: PetscCall(PetscHMapFuncSet(map, tmp_name, fnc));
255: }
256: } else if (found) {
257: const char *tmp_name;
259: PetscHashIterGetKey(map, it, tmp_name);
260: PetscCall(PetscFree(tmp_name));
261: PetscCall(PetscHMapFuncIterDel(map, it));
262: }
263: PetscFunctionReturn(PETSC_SUCCESS);
264: }
266: static PetscErrorCode PetscFunctionListCreate_Private(PetscInt size, PetscFunctionList *fl)
267: {
268: PetscFunctionBegin;
269: if (*fl) PetscFunctionReturn(PETSC_SUCCESS);
270: PetscCall(PetscNew(fl));
271: PetscCall(PetscHMapFuncCreateWithSize(size, &(*fl)->map));
272: PetscCall(PetscFunctionListDLAllPush_Private(*fl));
273: PetscFunctionReturn(PETSC_SUCCESS);
274: }
276: /*MC
277: PetscFunctionListAdd - Given a routine and a string id, saves that routine in the
278: specified registry.
280: Synopsis:
281: #include <petscsys.h>
282: PetscErrorCode PetscFunctionListAdd(PetscFunctionList *flist, const char name[], PetscErrorCodeFn *fptr)
284: Not Collective
286: Input Parameters:
287: + fl - pointer to function list object
288: . name - string to identify routine
289: - fptr - function pointer
291: Level: developer
293: Notes:
294: To remove a registered routine, pass in a `NULL` `fptr`.
296: Users who wish to register new classes for use by a particular PETSc
297: component (e.g., `SNES`) should generally call the registration routine
298: for that particular component (e.g., `SNESRegister()`) instead of
299: calling `PetscFunctionListAdd()` directly.
301: .seealso: `PetscFunctionListDestroy()`, `SNESRegister()`, `KSPRegister()`,`PetscFunctionListDuplicate()`
302: `PCRegister()`, `TSRegister()`, `PetscFunctionList`, `PetscObjectComposeFunction()`
303: M*/
304: PetscErrorCode PetscFunctionListAdd_Private(PetscFunctionList *fl, const char name[], PetscErrorCodeFn *fptr)
305: {
306: PetscFunctionBegin;
307: PetscAssertPointer(fl, 1);
308: if (name) PetscAssertPointer(name, 2);
310: if (!fptr && !*fl) PetscFunctionReturn(PETSC_SUCCESS);
311: PetscCall(PetscFunctionListCreate_Private(0, fl));
312: PetscCall(PetscHMapFuncInsert_Private((*fl)->map, name, fptr));
313: PetscFunctionReturn(PETSC_SUCCESS);
314: }
316: /*@C
317: PetscFunctionListDestroy - Destroys a list of registered routines.
319: Input Parameter:
320: . fl - pointer to list
322: Level: developer
324: .seealso: `PetscFunctionListAdd()`, `PetscFunctionList`, `PetscFunctionListClear()`
325: @*/
326: PetscErrorCode PetscFunctionListDestroy(PetscFunctionList *fl)
327: {
328: PetscFunctionBegin;
329: if (!*fl) PetscFunctionReturn(PETSC_SUCCESS);
330: PetscCall(PetscFunctionListDLAllPop_Private(*fl));
331: /* free this list */
332: PetscCall(PetscFunctionListClear(*fl));
333: PetscCall(PetscHMapFuncDestroy(&(*fl)->map));
334: PetscCall(PetscFree(*fl));
335: PetscFunctionReturn(PETSC_SUCCESS);
336: }
338: #define PetscHMapFuncForEach(__func_list__, __key_name__, __val_name__, ...) \
339: do { \
340: const PetscHMapFunc phmfi_map_ = (__func_list__)->map; \
341: PetscHashIter phmfi_iter_; \
342: \
343: PetscHashIterBegin(phmfi_map_, phmfi_iter_); \
344: while (!PetscHashIterAtEnd(phmfi_map_, phmfi_iter_)) { \
345: const char *PETSC_UNUSED __key_name__; \
346: PetscErrorCodeFn *PETSC_UNUSED __val_name__; \
347: \
348: PetscHashIterGetKey(phmfi_map_, phmfi_iter_, __key_name__); \
349: PetscHashIterGetVal(phmfi_map_, phmfi_iter_, __val_name__); \
350: { \
351: __VA_ARGS__; \
352: } \
353: PetscHashIterNext(phmfi_map_, phmfi_iter_); \
354: } /* end while */ \
355: } while (0)
357: /*@C
358: PetscFunctionListClear - Clear a `PetscFunctionList`
360: Not Collective
362: Input Parameter:
363: . fl - The `PetscFunctionList` to clear
365: Level: developer
367: Notes:
368: This clears the contents of `fl` but does not deallocate the entries themselves.
370: .seealso: `PetscFunctionList`, `PetscFunctionListDestroy()`, `PetscFunctionListAdd()`
371: @*/
372: PetscErrorCode PetscFunctionListClear(PetscFunctionList fl)
373: {
374: PetscFunctionBegin;
375: if (fl) {
376: PetscHMapFuncForEach(fl, name, func, PetscCall(PetscFree(name)));
377: PetscCall(PetscHMapFuncClear(fl->map));
378: }
379: PetscFunctionReturn(PETSC_SUCCESS);
380: }
382: /*
383: Print registered PetscFunctionLists
384: */
385: PetscErrorCode PetscFunctionListPrintAll(void)
386: {
387: PetscFunctionListDLAll current = dlallhead;
389: PetscFunctionBegin;
390: if (current) PetscCall(PetscPrintf(PETSC_COMM_SELF, "[%d] Registered PetscFunctionLists\n", PetscGlobalRank));
391: while (current) {
392: PetscCall(PetscFunctionListPrintNonEmpty(current->data));
393: current = current->next;
394: }
395: PetscFunctionReturn(PETSC_SUCCESS);
396: }
398: /*@C
399: PetscFunctionListPrintNonEmpty - Print composed names for non `NULL` function pointers
401: Logically Collective, No Fortran Support
403: Input Parameter:
404: . fl - the function list
406: Level: developer
408: .seealso: `PetscFunctionListAdd()`, `PetscFunctionList`, `PetscObjectQueryFunction()`
409: @*/
410: PetscErrorCode PetscFunctionListPrintNonEmpty(PetscFunctionList fl)
411: {
412: PetscFunctionBegin;
413: if (fl) {
414: // clang-format off
415: PetscHMapFuncForEach(
416: fl,
417: name, func,
418: PetscCall(PetscFPrintf(PETSC_COMM_SELF, PETSC_STDOUT, "[%d] function name: %s\n", PetscGlobalRank, name));
419: );
420: // clang-format on
421: }
422: PetscFunctionReturn(PETSC_SUCCESS);
423: }
425: /*MC
426: PetscFunctionListFind - Find function registered under given name
428: Not Collective, No Fortran Support
430: Synopsis:
431: #include <petscsys.h>
432: PetscErrorCode PetscFunctionListFind(PetscFunctionList flist, const char name[], PetscErrorCodeFn **fptr)
434: Input Parameters:
435: + fl - the function list
436: - name - name registered for the function
438: Output Parameter:
439: . fptr - the function pointer if name was found, else `NULL`
441: Level: developer
443: .seealso: `PetscFunctionListAdd()`, `PetscFunctionList`, `PetscObjectQueryFunction()`, `PetscFunctionListDuplicate()`
444: M*/
445: PetscErrorCode PetscFunctionListFind_Private(PetscFunctionList fl, const char name[], PetscErrorCodeFn **fptr)
446: {
447: PetscFunctionBegin;
448: PetscAssertPointer(name, 2);
449: PetscAssertPointer(fptr, 3);
450: *fptr = NULL;
451: if (fl) PetscCall(PetscHMapFuncGet(fl->map, name, fptr));
452: PetscFunctionReturn(PETSC_SUCCESS);
453: }
455: /*@C
456: PetscFunctionListView - prints out contents of a `PetscFunctionList`
458: Collective
460: Input Parameters:
461: + list - the list of functions
462: - viewer - the `PetscViewer` used to view the `PetscFunctionList`
464: Level: developer
466: .seealso: `PetscFunctionListAdd()`, `PetscFunctionListPrintTypes()`, `PetscFunctionList`
467: @*/
468: PetscErrorCode PetscFunctionListView(PetscFunctionList list, PetscViewer viewer)
469: {
470: PetscBool isascii;
472: PetscFunctionBegin;
473: PetscAssertPointer(list, 1);
474: if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PETSC_COMM_SELF, &viewer));
477: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
478: PetscCheck(isascii, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only ASCII viewer supported");
479: {
480: PetscInt size;
482: PetscCall(PetscHMapFuncGetSize(list->map, &size));
483: PetscCall(PetscViewerASCIIPrintf(viewer, "PetscFunctionList Object:\n"));
484: PetscCall(PetscViewerASCIIPushTab(viewer));
485: PetscCall(PetscViewerASCIIPrintf(viewer, "size: %" PetscInt_FMT "\n", size));
486: if (size) {
487: PetscInt count = 0;
489: PetscCall(PetscViewerASCIIPrintf(viewer, "functions:\n"));
490: PetscCall(PetscViewerASCIIPushTab(viewer));
491: PetscHMapFuncForEach(list, name, func, PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT ": %s\n", ++count, name)));
492: PetscCall(PetscViewerASCIIPopTab(viewer));
493: }
494: PetscCall(PetscViewerASCIIPopTab(viewer));
495: }
496: PetscFunctionReturn(PETSC_SUCCESS);
497: }
499: /*@C
500: PetscFunctionListGet - Gets an array the contains the entries in `PetscFunctionList`, this is used
501: by help etc.
503: Not Collective, No Fortran Support
505: Input Parameter:
506: . list - list of types
508: Output Parameters:
509: + array - array of names
510: - n - length of `array`
512: Level: developer
514: Note:
515: This allocates the array so that must be freed with `PetscFree()`. BUT the individual entries should not be freed.
517: .seealso: `PetscFunctionListAdd()`, `PetscFunctionList`
518: @*/
519: PetscErrorCode PetscFunctionListGet(PetscFunctionList list, const char ***array, int *n)
520: {
521: PetscInt size = 0;
523: PetscFunctionBegin;
524: PetscAssertPointer(array, 2);
525: *array = NULL;
526: if (list) {
527: const PetscHMapFunc map = list->map;
528: PetscInt off = 0;
530: PetscCall(PetscHMapFuncGetSize(map, &size));
531: PetscCall(PetscMalloc1(size, (char ***)array));
532: PetscCall(PetscHMapFuncGetKeys(map, &off, *array));
533: }
534: PetscCall(PetscCIntCast(size, n));
535: PetscFunctionReturn(PETSC_SUCCESS);
536: }
538: /*@C
539: PetscFunctionListPrintTypes - Prints the methods available in a list of functions
541: Collective, No Fortran Support
543: Input Parameters:
544: + comm - the communicator (usually `MPI_COMM_WORLD`)
545: . fd - file to print to, usually `stdout`
546: . prefix - prefix to prepend to name (optional)
547: . name - option string (for example, `-ksp_type`)
548: . text - short description of the object (for example, "Krylov solvers")
549: . man - name of manual page that discusses the object (for example, `KSPCreate`)
550: . list - list of types
551: . def - default (current) value
552: - newv - new value
554: Level: developer
556: .seealso: `PetscFunctionListAdd()`, `PetscFunctionList`
557: @*/
558: 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[])
559: {
560: char p[64];
562: PetscFunctionBegin;
563: (void)fd;
564: PetscCall(PetscStrncpy(p, "-", sizeof(p)));
565: if (prefix) PetscCall(PetscStrlcat(p, prefix, sizeof(p)));
566: PetscCall((*PetscHelpPrintf)(comm, " %s%s <now %s : formerly %s>: %s (one of)", p, name + 1, newv, def, text));
568: if (list) PetscHMapFuncForEach(list, name, func, PetscCall((*PetscHelpPrintf)(comm, " %s", name)));
569: PetscCall((*PetscHelpPrintf)(comm, " (%s)\n", man));
570: PetscFunctionReturn(PETSC_SUCCESS);
571: }
573: /*@C
574: PetscFunctionListDuplicate - Creates a new list from a given function list `PetscFunctionList`.
576: Input Parameter:
577: . fl - pointer to list
579: Output Parameter:
580: . nl - the new list (should point to `NULL` to start, otherwise appends)
582: Level: developer
584: .seealso: `PetscFunctionList`, `PetscFunctionListAdd()`, `PetscFlistDestroy()`
585: @*/
586: PetscErrorCode PetscFunctionListDuplicate(PetscFunctionList fl, PetscFunctionList *nl)
587: {
588: PetscFunctionBegin;
589: if (fl) {
590: PetscHMapFunc dup_map;
592: if (!*nl) {
593: PetscInt n;
595: PetscCall(PetscHMapFuncGetSize(fl->map, &n));
596: PetscCall(PetscFunctionListCreate_Private(n, nl));
597: }
598: dup_map = (*nl)->map;
599: PetscHMapFuncForEach(fl, name, func, PetscCall(PetscHMapFuncInsert_Private(dup_map, name, func)));
600: }
601: PetscFunctionReturn(PETSC_SUCCESS);
602: }