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