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>
7: #include <petsc/private/hashmap.h>
8: /*
9: This is the default list used by PETSc with the PetscDLLibrary register routines
10: */
11: PetscDLLibrary PetscDLLibrariesLoaded = NULL;
13: #if PetscDefined(HAVE_DYNAMIC_LIBRARIES) && PetscDefined(USE_SHARED_LIBRARIES)
15: static PetscErrorCode PetscLoadDynamicLibrary(const char *name, PetscBool *found)
16: {
17: char libs[PETSC_MAX_PATH_LEN], dlib[PETSC_MAX_PATH_LEN];
19: PetscFunctionBegin;
20: PetscCall(PetscStrncpy(libs, "${PETSC_LIB_DIR}/libpetsc", sizeof(libs)));
21: PetscCall(PetscStrlcat(libs, name, sizeof(libs)));
22: #if defined(PETSC_LIB_NAME_SUFFIX)
23: PetscCall(PetscStrlcat(libs, PETSC_LIB_NAME_SUFFIX, sizeof(libs)));
24: #endif
25: PetscCall(PetscDLLibraryRetrieve(PETSC_COMM_WORLD, libs, dlib, 1024, found));
26: if (*found) {
27: PetscCall(PetscDLLibraryAppend(PETSC_COMM_WORLD, &PetscDLLibrariesLoaded, dlib));
28: } else {
29: PetscCall(PetscStrncpy(libs, "${PETSC_DIR}/${PETSC_ARCH}/lib/libpetsc", sizeof(libs)));
30: PetscCall(PetscStrlcat(libs, name, sizeof(libs)));
31: #if defined(PETSC_LIB_NAME_SUFFIX)
32: PetscCall(PetscStrlcat(libs, PETSC_LIB_NAME_SUFFIX, sizeof(libs)));
33: #endif
34: PetscCall(PetscDLLibraryRetrieve(PETSC_COMM_WORLD, libs, dlib, 1024, found));
35: if (*found) PetscCall(PetscDLLibraryAppend(PETSC_COMM_WORLD, &PetscDLLibrariesLoaded, dlib));
36: }
37: PetscFunctionReturn(PETSC_SUCCESS);
38: }
39: #endif
41: #if PetscDefined(USE_SINGLE_LIBRARY) && !(PetscDefined(HAVE_DYNAMIC_LIBRARIES) && PetscDefined(USE_SHARED_LIBRARIES))
42: PETSC_EXTERN PetscErrorCode AOInitializePackage(void);
43: PETSC_EXTERN PetscErrorCode PetscSFInitializePackage(void);
44: #if !PetscDefined(USE_COMPLEX)
45: PETSC_EXTERN PetscErrorCode CharacteristicInitializePackage(void);
46: #endif
47: PETSC_EXTERN PetscErrorCode ISInitializePackage(void);
48: PETSC_EXTERN PetscErrorCode VecInitializePackage(void);
49: PETSC_EXTERN PetscErrorCode MatInitializePackage(void);
50: PETSC_EXTERN PetscErrorCode DMInitializePackage(void);
51: PETSC_EXTERN PetscErrorCode PCInitializePackage(void);
52: PETSC_EXTERN PetscErrorCode KSPInitializePackage(void);
53: PETSC_EXTERN PetscErrorCode SNESInitializePackage(void);
54: PETSC_EXTERN PetscErrorCode TSInitializePackage(void);
55: PETSC_EXTERN PetscErrorCode TaoInitializePackage(void);
56: #endif
58: /*
59: PetscInitialize_DynamicLibraries - Adds the default dynamic link libraries to the
60: search path.
61: */
62: PETSC_INTERN PetscErrorCode PetscInitialize_DynamicLibraries(void)
63: {
64: char *libname[32];
65: PetscInt nmax;
66: PetscBool preload = PETSC_FALSE;
67: #if PetscDefined(HAVE_ELEMENTAL)
68: PetscBool PetscInitialized = PetscInitializeCalled;
69: #endif
71: PetscFunctionBegin;
72: #if PetscDefined(HAVE_THREADSAFETY)
73: /* These must be all initialized here because it is not safe for individual threads to call these initialize routines */
74: preload = PETSC_TRUE;
75: #endif
77: nmax = 32;
78: PetscCall(PetscOptionsGetStringArray(NULL, NULL, "-dll_prepend", libname, &nmax, NULL));
79: for (PetscInt i = 0; i < nmax; i++) {
80: PetscCall(PetscDLLibraryPrepend(PETSC_COMM_WORLD, &PetscDLLibrariesLoaded, libname[i]));
81: PetscCall(PetscFree(libname[i]));
82: }
84: PetscCall(PetscOptionsGetBool(NULL, NULL, "-library_preload", &preload, NULL));
85: if (!preload) {
86: PetscCall(PetscSysInitializePackage());
87: } else {
88: #if PetscDefined(HAVE_DYNAMIC_LIBRARIES) && PetscDefined(USE_SHARED_LIBRARIES)
89: PetscBool found;
90: #if PetscDefined(USE_SINGLE_LIBRARY)
91: PetscCall(PetscLoadDynamicLibrary("", &found));
92: PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc dynamic library. You cannot move the dynamic libraries!");
93: #else
94: PetscCall(PetscLoadDynamicLibrary("sys", &found));
95: PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc Sys dynamic library. You cannot move the dynamic libraries!");
96: PetscCall(PetscLoadDynamicLibrary("vec", &found));
97: PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc Vec dynamic library. You cannot move the dynamic libraries!");
98: PetscCall(PetscLoadDynamicLibrary("mat", &found));
99: PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc Mat dynamic library. You cannot move the dynamic libraries!");
100: PetscCall(PetscLoadDynamicLibrary("dm", &found));
101: PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc DM dynamic library. You cannot move the dynamic libraries!");
102: PetscCall(PetscLoadDynamicLibrary("ksp", &found));
103: PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc KSP dynamic library. You cannot move the dynamic libraries!");
104: PetscCall(PetscLoadDynamicLibrary("snes", &found));
105: PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc SNES dynamic library. You cannot move the dynamic libraries!");
106: PetscCall(PetscLoadDynamicLibrary("ts", &found));
107: PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc TS dynamic library. You cannot move the dynamic libraries!");
108: PetscCall(PetscLoadDynamicLibrary("tao", &found));
109: PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate Tao dynamic library. You cannot move the dynamic libraries!");
110: #endif
111: #else /* PetscDefined(HAVE_DYNAMIC_LIBRARIES) && PetscDefined(USE_SHARED_LIBRARIES) */
112: #if PetscDefined(USE_SINGLE_LIBRARY)
113: PetscCall(AOInitializePackage());
114: PetscCall(PetscSFInitializePackage());
115: #if !PetscDefined(USE_COMPLEX)
116: PetscCall(CharacteristicInitializePackage());
117: #endif
118: PetscCall(ISInitializePackage());
119: PetscCall(VecInitializePackage());
120: PetscCall(MatInitializePackage());
121: PetscCall(DMInitializePackage());
122: PetscCall(PCInitializePackage());
123: PetscCall(KSPInitializePackage());
124: PetscCall(SNESInitializePackage());
125: PetscCall(TSInitializePackage());
126: PetscCall(TaoInitializePackage());
127: #else
128: SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP, "Cannot use -library_preload with multiple static PETSc libraries");
129: #endif
130: #endif /* PetscDefined(HAVE_DYNAMIC_LIBRARIES) && PetscDefined(USE_SHARED_LIBRARIES) */
131: }
133: #if PetscDefined(HAVE_DYNAMIC_LIBRARIES) && PetscDefined(USE_SHARED_LIBRARIES) && PetscDefined(HAVE_BAMG)
134: {
135: PetscBool found;
136: PetscCall(PetscLoadDynamicLibrary("bamg", &found));
137: PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc BAMG dynamic library. You cannot move the dynamic libraries!");
138: }
139: #endif
140: #if PetscDefined(HAVE_DYNAMIC_LIBRARIES) && PetscDefined(USE_SHARED_LIBRARIES) && PetscDefined(HAVE_PFLARE)
141: {
142: PetscBool found;
143: PetscCall(PetscLoadDynamicLibrary("pflare", &found));
144: PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PFLARE dynamic library. You cannot move the dynamic libraries!");
145: }
146: #endif
148: nmax = 32;
149: PetscCall(PetscOptionsGetStringArray(NULL, NULL, "-dll_append", libname, &nmax, NULL));
150: for (PetscInt i = 0; i < nmax; i++) {
151: PetscCall(PetscDLLibraryAppend(PETSC_COMM_WORLD, &PetscDLLibrariesLoaded, libname[i]));
152: PetscCall(PetscFree(libname[i]));
153: }
155: #if PetscDefined(HAVE_ELEMENTAL)
156: /* in Fortran, PetscInitializeCalled is set to PETSC_TRUE before PetscInitialize_DynamicLibraries() */
157: /* in C, it is not the case, but the value is forced to PETSC_TRUE so that PetscRegisterFinalize() is called */
158: PetscInitializeCalled = PETSC_TRUE;
159: PetscCall(PetscElementalInitializePackage());
160: PetscInitializeCalled = PetscInitialized;
161: #endif
162: PetscFunctionReturn(PETSC_SUCCESS);
163: }
165: /*
166: PetscFinalize_DynamicLibraries - Closes the opened dynamic libraries.
167: */
168: PETSC_INTERN PetscErrorCode PetscFinalize_DynamicLibraries(void)
169: {
170: PetscBool flg = PETSC_FALSE;
172: PetscFunctionBegin;
173: PetscCall(PetscOptionsGetBool(NULL, NULL, "-dll_view", &flg, NULL));
174: if (flg) PetscCall(PetscDLLibraryPrintPath(PetscDLLibrariesLoaded));
175: PetscCall(PetscDLLibraryClose(PetscDLLibrariesLoaded));
176: PetscDLLibrariesLoaded = NULL;
177: PetscFunctionReturn(PETSC_SUCCESS);
178: }
180: PETSC_HASH_MAP(HMapFunc, const char *, PetscErrorCodeFn *, kh_str_hash_func, kh_str_hash_equal, NULL)
182: struct _n_PetscFunctionList {
183: PetscHMapFunc map;
184: };
186: /* Keep a linked list of PetscFunctionLists so that we can destroy all the left-over ones. */
187: typedef struct n_PetscFunctionListDLAll *PetscFunctionListDLAll;
188: struct n_PetscFunctionListDLAll {
189: PetscFunctionList data;
190: PetscFunctionListDLAll next;
191: };
193: static PetscFunctionListDLAll dlallhead = NULL;
195: static PetscErrorCode PetscFunctionListDLAllPush_Private(PetscFunctionList fl)
196: {
197: PetscFunctionBegin;
198: if (PetscDefined(USE_DEBUG) && !PetscDefined(HAVE_THREADSAFETY)) {
199: PetscFunctionListDLAll head;
201: PetscCall(PetscNew(&head));
202: head->data = fl;
203: head->next = dlallhead;
204: dlallhead = head;
205: }
206: PetscFunctionReturn(PETSC_SUCCESS);
207: }
209: static PetscErrorCode PetscFunctionListDLAllPop_Private(PetscFunctionList fl)
210: {
211: PetscFunctionBegin;
212: if (PetscDefined(USE_DEBUG) && !PetscDefined(HAVE_THREADSAFETY)) {
213: PetscFunctionListDLAll current = dlallhead, prev = NULL;
215: /* Remove this entry from the main DL list (if it is in it) */
216: while (current) {
217: const PetscFunctionListDLAll next = current->next;
219: if (current->data == fl) {
220: if (prev) {
221: // somewhere in the middle (or end) of the list
222: prev->next = next;
223: } else {
224: // prev = NULL implies current = dlallhead, so front of list
225: dlallhead = next;
226: }
227: PetscCall(PetscFree(current));
228: break;
229: }
230: prev = current;
231: current = next;
232: }
233: }
234: PetscFunctionReturn(PETSC_SUCCESS);
235: }
237: static PetscErrorCode PetscHMapFuncInsert_Private(PetscHMapFunc map, const char name[], PetscErrorCodeFn *fnc)
238: {
239: PetscHashIter it;
240: PetscBool found;
242: PetscFunctionBegin;
243: PetscAssertPointer(name, 2);
245: PetscCall(PetscHMapFuncFind(map, name, &it, &found));
246: if (fnc) {
247: if (found) {
248: PetscCall(PetscHMapFuncIterSet(map, it, fnc));
249: } else {
250: char *tmp_name;
252: PetscCall(PetscStrallocpy(name, &tmp_name));
253: PetscCall(PetscHMapFuncSet(map, tmp_name, fnc));
254: }
255: } else if (found) {
256: const char *tmp_name;
258: PetscHashIterGetKey(map, it, tmp_name);
259: PetscCall(PetscFree(tmp_name));
260: PetscCall(PetscHMapFuncIterDel(map, it));
261: }
262: PetscFunctionReturn(PETSC_SUCCESS);
263: }
265: static PetscErrorCode PetscFunctionListCreate_Private(PetscInt size, PetscFunctionList *fl)
266: {
267: PetscFunctionBegin;
268: if (*fl) PetscFunctionReturn(PETSC_SUCCESS);
269: PetscCall(PetscNew(fl));
270: PetscCall(PetscHMapFuncCreateWithSize(size, &(*fl)->map));
271: PetscCall(PetscFunctionListDLAllPush_Private(*fl));
272: PetscFunctionReturn(PETSC_SUCCESS);
273: }
275: PetscErrorCode PetscFunctionListAdd_Private(PetscFunctionList *fl, const char name[], PetscErrorCodeFn *fptr)
276: {
277: PetscFunctionBegin;
278: PetscAssertPointer(fl, 1);
279: if (name) PetscAssertPointer(name, 2);
281: if (!fptr && !*fl) PetscFunctionReturn(PETSC_SUCCESS);
282: PetscCall(PetscFunctionListCreate_Private(0, fl));
283: PetscCall(PetscHMapFuncInsert_Private((*fl)->map, name, fptr));
284: PetscFunctionReturn(PETSC_SUCCESS);
285: }
287: /*@
288: PetscFunctionListDestroy - Destroys a list of registered routines.
290: Input Parameter:
291: . fl - pointer to list
293: Level: developer
295: .seealso: `PetscFunctionListAdd()`, `PetscFunctionList`, `PetscFunctionListClear()`
296: @*/
297: PetscErrorCode PetscFunctionListDestroy(PetscFunctionList *fl)
298: {
299: PetscFunctionBegin;
300: if (!*fl) PetscFunctionReturn(PETSC_SUCCESS);
301: PetscCall(PetscFunctionListDLAllPop_Private(*fl));
302: /* free this list */
303: PetscCall(PetscFunctionListClear(*fl));
304: PetscCall(PetscHMapFuncDestroy(&(*fl)->map));
305: PetscCall(PetscFree(*fl));
306: PetscFunctionReturn(PETSC_SUCCESS);
307: }
309: #define PetscHMapFuncForEach(__func_list__, __key_name__, __val_name__, ...) \
310: do { \
311: const PetscHMapFunc phmfi_map_ = (__func_list__)->map; \
312: PetscHashIter phmfi_iter_; \
313: \
314: PetscHashIterBegin(phmfi_map_, phmfi_iter_); \
315: while (!PetscHashIterAtEnd(phmfi_map_, phmfi_iter_)) { \
316: const char *PETSC_UNUSED __key_name__; \
317: PetscErrorCodeFn *PETSC_UNUSED __val_name__; \
318: \
319: PetscHashIterGetKey(phmfi_map_, phmfi_iter_, __key_name__); \
320: PetscHashIterGetVal(phmfi_map_, phmfi_iter_, __val_name__); \
321: { \
322: __VA_ARGS__; \
323: } \
324: PetscHashIterNext(phmfi_map_, phmfi_iter_); \
325: } /* end while */ \
326: } while (0)
328: /*@
329: PetscFunctionListClear - Clear a `PetscFunctionList`
331: Not Collective
333: Input Parameter:
334: . fl - The `PetscFunctionList` to clear
336: Level: developer
338: Notes:
339: This clears the contents of `fl` but does not deallocate the entries themselves.
341: .seealso: `PetscFunctionList`, `PetscFunctionListDestroy()`, `PetscFunctionListAdd()`
342: @*/
343: PetscErrorCode PetscFunctionListClear(PetscFunctionList fl)
344: {
345: PetscFunctionBegin;
346: if (fl) {
347: PetscHMapFuncForEach(fl, name, func, PetscCall(PetscFree(name)));
348: PetscCall(PetscHMapFuncClear(fl->map));
349: }
350: PetscFunctionReturn(PETSC_SUCCESS);
351: }
353: /*@
354: PetscFunctionListPrintAll - Prints the names of all functions registered in every `PetscFunctionList` known to PETSc
356: Not Collective
358: Level: developer
360: Note:
361: Intended for debugging; iterates over the global list of registered `PetscFunctionList` objects and prints each
362: non-empty function name to `PETSC_COMM_SELF` on the calling MPI process.
364: .seealso: `PetscFunctionList`, `PetscFunctionListPrintNonEmpty()`, `PetscFunctionListAdd()`, `PetscFunctionListView()`
365: @*/
366: PetscErrorCode PetscFunctionListPrintAll(void)
367: {
368: PetscFunctionListDLAll current = dlallhead;
370: PetscFunctionBegin;
371: if (current) PetscCall(PetscPrintf(PETSC_COMM_SELF, "[%d] Registered PetscFunctionLists\n", PetscGlobalRank));
372: while (current) {
373: PetscCall(PetscFunctionListPrintNonEmpty(current->data));
374: current = current->next;
375: }
376: PetscFunctionReturn(PETSC_SUCCESS);
377: }
379: /*@
380: PetscFunctionListPrintNonEmpty - Print composed names for non `NULL` function pointers
382: Logically Collective, No Fortran Support
384: Input Parameter:
385: . fl - the function list
387: Level: developer
389: .seealso: `PetscFunctionListAdd()`, `PetscFunctionList`, `PetscObjectQueryFunction()`
390: @*/
391: PetscErrorCode PetscFunctionListPrintNonEmpty(PetscFunctionList fl)
392: {
393: PetscFunctionBegin;
394: if (fl) {
395: // clang-format off
396: PetscHMapFuncForEach(
397: fl,
398: name, func,
399: PetscCall(PetscFPrintf(PETSC_COMM_SELF, PETSC_STDOUT, "[%d] function name: %s\n", PetscGlobalRank, name));
400: );
401: // clang-format on
402: }
403: PetscFunctionReturn(PETSC_SUCCESS);
404: }
406: PetscErrorCode PetscFunctionListFind_Private(PetscFunctionList fl, const char name[], PetscErrorCodeFn **fptr)
407: {
408: PetscFunctionBegin;
409: PetscAssertPointer(name, 2);
410: PetscAssertPointer(fptr, 3);
411: *fptr = NULL;
412: if (fl) PetscCall(PetscHMapFuncGet(fl->map, name, fptr));
413: PetscFunctionReturn(PETSC_SUCCESS);
414: }
416: /*@
417: PetscFunctionListView - prints out contents of a `PetscFunctionList`
419: Collective
421: Input Parameters:
422: + list - the list of functions
423: - viewer - the `PetscViewer` used to view the `PetscFunctionList`
425: Level: developer
427: .seealso: `PetscFunctionListAdd()`, `PetscFunctionListPrintTypes()`, `PetscFunctionList`
428: @*/
429: PetscErrorCode PetscFunctionListView(PetscFunctionList list, PetscViewer viewer)
430: {
431: PetscBool isascii;
433: PetscFunctionBegin;
434: PetscAssertPointer(list, 1);
435: if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PETSC_COMM_SELF, &viewer));
438: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
439: PetscCheck(isascii, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only ASCII viewer supported");
440: {
441: PetscInt size;
443: PetscCall(PetscHMapFuncGetSize(list->map, &size));
444: PetscCall(PetscViewerASCIIPrintf(viewer, "PetscFunctionList Object:\n"));
445: PetscCall(PetscViewerASCIIPushTab(viewer));
446: PetscCall(PetscViewerASCIIPrintf(viewer, "size: %" PetscInt_FMT "\n", size));
447: if (size) {
448: PetscInt count = 0;
450: PetscCall(PetscViewerASCIIPrintf(viewer, "functions:\n"));
451: PetscCall(PetscViewerASCIIPushTab(viewer));
452: PetscHMapFuncForEach(list, name, func, PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT ": %s\n", ++count, name)));
453: PetscCall(PetscViewerASCIIPopTab(viewer));
454: }
455: PetscCall(PetscViewerASCIIPopTab(viewer));
456: }
457: PetscFunctionReturn(PETSC_SUCCESS);
458: }
460: /*@
461: PetscFunctionListGet - Gets an array the contains the entries in `PetscFunctionList`, this is used
462: by help etc.
464: Not Collective, No Fortran Support
466: Input Parameter:
467: . list - list of types
469: Output Parameters:
470: + array - array of names
471: - n - length of `array`
473: Level: developer
475: Note:
476: This allocates the array so that must be freed with `PetscFree()`. BUT the individual entries should not be freed.
478: .seealso: `PetscFunctionListAdd()`, `PetscFunctionList`
479: @*/
480: PetscErrorCode PetscFunctionListGet(PetscFunctionList list, const char ***array, int *n)
481: {
482: PetscInt size = 0;
484: PetscFunctionBegin;
485: PetscAssertPointer(array, 2);
486: *array = NULL;
487: if (list) {
488: const PetscHMapFunc map = list->map;
489: PetscInt off = 0;
491: PetscCall(PetscHMapFuncGetSize(map, &size));
492: PetscCall(PetscMalloc1(size, (char ***)array));
493: PetscCall(PetscHMapFuncGetKeys(map, &off, *array));
494: }
495: PetscCall(PetscCIntCast(size, n));
496: PetscFunctionReturn(PETSC_SUCCESS);
497: }
499: /*@
500: PetscFunctionListPrintTypes - Prints the methods available in a list of functions
502: Collective, No Fortran Support
504: Input Parameters:
505: + comm - the communicator (usually `MPI_COMM_WORLD`)
506: . fd - file to print to, usually `stdout`
507: . prefix - prefix to prepend to name (optional)
508: . name - option string (for example, `-ksp_type`)
509: . text - short description of the object (for example, "Krylov solvers")
510: . man - name of manual page that discusses the object (for example, `KSPCreate`)
511: . list - list of types
512: . def - default (current) value
513: - newv - new value
515: Level: developer
517: .seealso: `PetscFunctionListAdd()`, `PetscFunctionList`
518: @*/
519: 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[])
520: {
521: char p[64];
523: PetscFunctionBegin;
524: (void)fd;
525: PetscCall(PetscStrncpy(p, "-", sizeof(p)));
526: if (prefix) PetscCall(PetscStrlcat(p, prefix, sizeof(p)));
527: PetscCall((*PetscHelpPrintf)(comm, " %s%s <now %s : formerly %s>: %s (one of)", p, name + 1, newv, def, text));
529: if (list) PetscHMapFuncForEach(list, name, func, PetscCall((*PetscHelpPrintf)(comm, " %s", name)));
530: PetscCall((*PetscHelpPrintf)(comm, " (%s)\n", man));
531: PetscFunctionReturn(PETSC_SUCCESS);
532: }
534: /*@
535: PetscFunctionListDuplicate - Creates a new list from a given function list `PetscFunctionList`.
537: Input Parameter:
538: . fl - pointer to list
540: Output Parameter:
541: . nl - the new list (should point to `NULL` to start, otherwise appends)
543: Level: developer
545: .seealso: `PetscFunctionList`, `PetscFunctionListAdd()`, `PetscFlistDestroy()`
546: @*/
547: PetscErrorCode PetscFunctionListDuplicate(PetscFunctionList fl, PetscFunctionList *nl)
548: {
549: PetscFunctionBegin;
550: if (fl) {
551: PetscHMapFunc dup_map;
553: if (!*nl) {
554: PetscInt n;
556: PetscCall(PetscHMapFuncGetSize(fl->map, &n));
557: PetscCall(PetscFunctionListCreate_Private(n, nl));
558: }
559: dup_map = (*nl)->map;
560: PetscHMapFuncForEach(fl, name, func, PetscCall(PetscHMapFuncInsert_Private(dup_map, name, func)));
561: }
562: PetscFunctionReturn(PETSC_SUCCESS);
563: }