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: #include <petsc/private/hashmap.h>
10: /*
11: This is the default list used by PETSc with the PetscDLLibrary register routines
12: */
13: PetscDLLibrary PetscDLLibrariesLoaded = NULL;
15: #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES)
17: static PetscErrorCode PetscLoadDynamicLibrary(const char *name, PetscBool *found)
18: {
19: char libs[PETSC_MAX_PATH_LEN], dlib[PETSC_MAX_PATH_LEN];
21: PetscFunctionBegin;
22: PetscCall(PetscStrncpy(libs, "${PETSC_LIB_DIR}/libpetsc", sizeof(libs)));
23: PetscCall(PetscStrlcat(libs, name, sizeof(libs)));
24: PetscCall(PetscDLLibraryRetrieve(PETSC_COMM_WORLD, libs, dlib, 1024, found));
25: if (*found) {
26: PetscCall(PetscDLLibraryAppend(PETSC_COMM_WORLD, &PetscDLLibrariesLoaded, dlib));
27: } else {
28: PetscCall(PetscStrncpy(libs, "${PETSC_DIR}/${PETSC_ARCH}/lib/libpetsc", sizeof(libs)));
29: PetscCall(PetscStrlcat(libs, name, sizeof(libs)));
30: PetscCall(PetscDLLibraryRetrieve(PETSC_COMM_WORLD, libs, dlib, 1024, found));
31: if (*found) PetscCall(PetscDLLibraryAppend(PETSC_COMM_WORLD, &PetscDLLibrariesLoaded, dlib));
32: }
33: PetscFunctionReturn(PETSC_SUCCESS);
34: }
35: #endif
37: #if defined(PETSC_USE_SINGLE_LIBRARY) && !(defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES))
38: PETSC_EXTERN PetscErrorCode AOInitializePackage(void);
39: PETSC_EXTERN PetscErrorCode PetscSFInitializePackage(void);
40: #if !defined(PETSC_USE_COMPLEX)
41: PETSC_EXTERN PetscErrorCode CharacteristicInitializePackage(void);
42: #endif
43: PETSC_EXTERN PetscErrorCode ISInitializePackage(void);
44: PETSC_EXTERN PetscErrorCode VecInitializePackage(void);
45: PETSC_EXTERN PetscErrorCode MatInitializePackage(void);
46: PETSC_EXTERN PetscErrorCode DMInitializePackage(void);
47: PETSC_EXTERN PetscErrorCode PCInitializePackage(void);
48: PETSC_EXTERN PetscErrorCode KSPInitializePackage(void);
49: PETSC_EXTERN PetscErrorCode SNESInitializePackage(void);
50: PETSC_EXTERN PetscErrorCode TSInitializePackage(void);
51: PETSC_EXTERN PetscErrorCode TaoInitializePackage(void);
52: #endif
54: /*
55: PetscInitialize_DynamicLibraries - Adds the default dynamic link libraries to the
56: search path.
57: */
58: PETSC_INTERN PetscErrorCode PetscInitialize_DynamicLibraries(void)
59: {
60: char *libname[32];
61: PetscInt nmax, i;
62: PetscBool preload = PETSC_FALSE;
63: #if defined(PETSC_HAVE_ELEMENTAL)
64: PetscBool PetscInitialized = PetscInitializeCalled;
65: #endif
67: PetscFunctionBegin;
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: PetscCall(PetscOptionsGetStringArray(NULL, NULL, "-dll_prepend", libname, &nmax, NULL));
75: for (i = 0; i < nmax; i++) {
76: PetscCall(PetscDLLibraryPrepend(PETSC_COMM_WORLD, &PetscDLLibrariesLoaded, libname[i]));
77: PetscCall(PetscFree(libname[i]));
78: }
80: PetscCall(PetscOptionsGetBool(NULL, NULL, "-library_preload", &preload, NULL));
81: if (!preload) {
82: PetscCall(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: PetscCall(PetscLoadDynamicLibrary("", &found));
88: PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc dynamic library \n You cannot move the dynamic libraries!");
89: #else
90: PetscCall(PetscLoadDynamicLibrary("sys", &found));
91: PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc dynamic library \n You cannot move the dynamic libraries!");
92: PetscCall(PetscLoadDynamicLibrary("vec", &found));
93: PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc Vec dynamic library \n You cannot move the dynamic libraries!");
94: PetscCall(PetscLoadDynamicLibrary("mat", &found));
95: PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc Mat dynamic library \n You cannot move the dynamic libraries!");
96: PetscCall(PetscLoadDynamicLibrary("dm", &found));
97: PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc DM dynamic library \n You cannot move the dynamic libraries!");
98: PetscCall(PetscLoadDynamicLibrary("ksp", &found));
99: PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc KSP dynamic library \n You cannot move the dynamic libraries!");
100: PetscCall(PetscLoadDynamicLibrary("snes", &found));
101: PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc SNES dynamic library \n You cannot move the dynamic libraries!");
102: PetscCall(PetscLoadDynamicLibrary("ts", &found));
103: PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc TS dynamic library \n You cannot move the dynamic libraries!");
104: PetscCall(PetscLoadDynamicLibrary("tao", &found));
105: PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate Tao dynamic library \n You cannot move the dynamic libraries!");
106: #endif
107: #else /* defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES) */
108: #if defined(PETSC_USE_SINGLE_LIBRARY)
109: PetscCall(AOInitializePackage());
110: PetscCall(PetscSFInitializePackage());
111: #if !defined(PETSC_USE_COMPLEX)
112: PetscCall(CharacteristicInitializePackage());
113: #endif
114: PetscCall(ISInitializePackage());
115: PetscCall(VecInitializePackage());
116: PetscCall(MatInitializePackage());
117: PetscCall(DMInitializePackage());
118: PetscCall(PCInitializePackage());
119: PetscCall(KSPInitializePackage());
120: PetscCall(SNESInitializePackage());
121: PetscCall(TSInitializePackage());
122: PetscCall(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: PetscCall(PetscLoadDynamicLibrary("bamg", &found));
133: PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc BAMG dynamic library \n You cannot move the dynamic libraries!");
134: }
135: #endif
137: nmax = 32;
138: PetscCall(PetscOptionsGetStringArray(NULL, NULL, "-dll_append", libname, &nmax, NULL));
139: for (i = 0; i < nmax; i++) {
140: PetscCall(PetscDLLibraryAppend(PETSC_COMM_WORLD, &PetscDLLibrariesLoaded, libname[i]));
141: PetscCall(PetscFree(libname[i]));
142: }
144: #if defined(PETSC_HAVE_ELEMENTAL)
145: /* in Fortran, PetscInitializeCalled is set to PETSC_TRUE before PetscInitialize_DynamicLibraries() */
146: /* in C, it is not the case, but the value is forced to PETSC_TRUE so that PetscRegisterFinalize() is called */
147: PetscInitializeCalled = PETSC_TRUE;
148: PetscCall(PetscElementalInitializePackage());
149: PetscInitializeCalled = PetscInitialized;
150: #endif
151: PetscFunctionReturn(PETSC_SUCCESS);
152: }
154: /*
155: PetscFinalize_DynamicLibraries - Closes the opened dynamic libraries.
156: */
157: PETSC_INTERN PetscErrorCode PetscFinalize_DynamicLibraries(void)
158: {
159: PetscBool flg = PETSC_FALSE;
161: PetscFunctionBegin;
162: PetscCall(PetscOptionsGetBool(NULL, NULL, "-dll_view", &flg, NULL));
163: if (flg) PetscCall(PetscDLLibraryPrintPath(PetscDLLibrariesLoaded));
164: PetscCall(PetscDLLibraryClose(PetscDLLibrariesLoaded));
165: PetscDLLibrariesLoaded = NULL;
166: PetscFunctionReturn(PETSC_SUCCESS);
167: }
169: /* ------------------------------------------------------------------------------*/
170: PETSC_HASH_MAP(HMapFunc, const char *, PetscVoidFunction, kh_str_hash_func, kh_str_hash_equal, NULL)
172: struct _n_PetscFunctionList {
173: PetscHMapFunc map;
174: };
176: /* Keep a linked list of PetscFunctionLists so that we can destroy all the left-over ones. */
177: typedef struct n_PetscFunctionListDLAll *PetscFunctionListDLAll;
178: struct n_PetscFunctionListDLAll {
179: PetscFunctionList data;
180: PetscFunctionListDLAll next;
181: };
183: static PetscFunctionListDLAll dlallhead = NULL;
185: static PetscErrorCode PetscFunctionListDLAllPush_Private(PetscFunctionList fl)
186: {
187: PetscFunctionBegin;
188: if (PetscDefined(USE_DEBUG) && !PetscDefined(HAVE_THREADSAFETY)) {
189: PetscFunctionListDLAll head;
191: PetscCall(PetscNew(&head));
192: head->data = fl;
193: head->next = dlallhead;
194: dlallhead = head;
195: }
196: PetscFunctionReturn(PETSC_SUCCESS);
197: }
199: static PetscErrorCode PetscFunctionListDLAllPop_Private(PetscFunctionList fl)
200: {
201: PetscFunctionBegin;
202: if (PetscDefined(USE_DEBUG) && !PetscDefined(HAVE_THREADSAFETY)) {
203: PetscFunctionListDLAll current = dlallhead, prev = NULL;
205: /* Remove this entry from the main DL list (if it is in it) */
206: while (current) {
207: const PetscFunctionListDLAll next = current->next;
209: if (current->data == fl) {
210: if (prev) {
211: // somewhere in the middle (or end) of the list
212: prev->next = next;
213: } else {
214: // prev = NULL implies current = dlallhead, so front of list
215: dlallhead = next;
216: }
217: PetscCall(PetscFree(current));
218: break;
219: }
220: prev = current;
221: current = next;
222: }
223: }
224: PetscFunctionReturn(PETSC_SUCCESS);
225: }
227: static PetscErrorCode PetscHMapFuncInsert_Private(PetscHMapFunc map, const char name[], PetscVoidFunction fnc)
228: {
229: PetscHashIter it;
230: PetscBool found;
232: PetscFunctionBegin;
235: PetscCall(PetscHMapFuncFind(map, name, &it, &found));
236: if (fnc) {
237: if (found) {
238: PetscCall(PetscHMapFuncIterSet(map, it, fnc));
239: } else {
240: char *tmp_name;
242: PetscCall(PetscStrallocpy(name, &tmp_name));
243: PetscCall(PetscHMapFuncSet(map, tmp_name, fnc));
244: }
245: } else if (found) {
246: const char *tmp_name;
248: PetscHashIterGetKey(map, it, tmp_name);
249: PetscCall(PetscFree(tmp_name));
250: PetscCall(PetscHMapFuncIterDel(map, it));
251: }
252: PetscFunctionReturn(PETSC_SUCCESS);
253: }
255: static PetscErrorCode PetscFunctionListCreate_Private(PetscInt size, PetscFunctionList *fl)
256: {
257: PetscFunctionBegin;
258: if (*fl) PetscFunctionReturn(PETSC_SUCCESS);
259: PetscCall(PetscNew(fl));
260: PetscCall(PetscHMapFuncCreateWithSize(size, &(*fl)->map));
261: PetscCall(PetscFunctionListDLAllPush_Private(*fl));
262: PetscFunctionReturn(PETSC_SUCCESS);
263: }
265: /*MC
266: PetscFunctionListAdd - Given a routine and a string id, saves that routine in the
267: specified registry.
269: Synopsis:
270: #include <petscsys.h>
271: PetscErrorCode PetscFunctionListAdd(PetscFunctionList *flist,const char name[],void (*fptr)(void))
273: Not Collective
275: Input Parameters:
276: + flist - pointer to function list object
277: . name - string to identify routine
278: - fptr - function pointer
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: Level: developer
290: .seealso: `PetscFunctionListDestroy()`, `SNESRegister()`, `KSPRegister()`,
291: `PCRegister()`, `TSRegister()`, `PetscFunctionList`, `PetscObjectComposeFunction()`
292: M*/
293: PetscErrorCode PetscFunctionListAdd_Private(PetscFunctionList *fl, const char name[], PetscVoidFunction fnc)
294: {
295: PetscFunctionBegin;
299: PetscCall(PetscFunctionListCreate_Private(0, fl));
300: PetscCall(PetscHMapFuncInsert_Private((*fl)->map, name, fnc));
301: PetscFunctionReturn(PETSC_SUCCESS);
302: }
304: /*@
305: PetscFunctionListDestroy - Destroys a list of registered routines.
307: Input Parameter:
308: . fl - pointer to list
310: Level: developer
312: .seealso: `PetscFunctionListAdd()`, `PetscFunctionList`, `PetscFunctionListClear()`
313: @*/
314: PetscErrorCode PetscFunctionListDestroy(PetscFunctionList *fl)
315: {
316: PetscFunctionBegin;
317: if (!*fl) PetscFunctionReturn(PETSC_SUCCESS);
318: PetscCall(PetscFunctionListDLAllPop_Private(*fl));
319: /* free this list */
320: PetscCall(PetscFunctionListClear(*fl));
321: PetscCall(PetscHMapFuncDestroy(&(*fl)->map));
322: PetscCall(PetscFree(*fl));
323: PetscFunctionReturn(PETSC_SUCCESS);
324: }
326: #define PetscHMapFuncForEach(__func_list__, __key_name__, __val_name__, ...) \
327: do { \
328: const PetscHMapFunc phmfi_map_ = (__func_list__)->map; \
329: PetscHashIter phmfi_iter_; \
330: \
331: PetscHashIterBegin(phmfi_map_, phmfi_iter_); \
332: while (!PetscHashIterAtEnd(phmfi_map_, phmfi_iter_)) { \
333: const char *PETSC_UNUSED __key_name__; \
334: PetscVoidFunction PETSC_UNUSED __val_name__; \
335: \
336: PetscHashIterGetKey(phmfi_map_, phmfi_iter_, __key_name__); \
337: PetscHashIterGetVal(phmfi_map_, phmfi_iter_, __val_name__); \
338: { \
339: __VA_ARGS__; \
340: } \
341: PetscHashIterNext(phmfi_map_, phmfi_iter_); \
342: } /* end while */ \
343: } while (0)
345: /*@
346: PetscFunctionListClear - Clear a `PetscFunctionList`
348: Not Collective
350: Input Parameter:
351: . fl - The `PetscFunctionList` to clear
353: Notes:
354: This clears the contents of `fl` but does not deallocate the entries themselves.
356: Level: developer
358: .seealso: `PetscFunctionList`, `PetscFunctionListDestroy()`, `PetscFunctionListAdd()`
359: @*/
360: PetscErrorCode PetscFunctionListClear(PetscFunctionList fl)
361: {
362: PetscFunctionBegin;
363: if (fl) {
364: PetscHMapFuncForEach(fl, name, func, PetscCall(PetscFree(name)));
365: PetscCall(PetscHMapFuncClear(fl->map));
366: }
367: PetscFunctionReturn(PETSC_SUCCESS);
368: }
370: /*
371: Print registered PetscFunctionLists
372: */
373: PetscErrorCode PetscFunctionListPrintAll(void)
374: {
375: PetscFunctionListDLAll current = dlallhead;
377: PetscFunctionBegin;
378: if (current) PetscCall(PetscPrintf(PETSC_COMM_SELF, "[%d] Registered PetscFunctionLists\n", PetscGlobalRank));
379: while (current) {
380: PetscCall(PetscFunctionListPrintNonEmpty(current->data));
381: current = current->next;
382: }
383: PetscFunctionReturn(PETSC_SUCCESS);
384: }
386: /*MC
387: PetscFunctionListNonEmpty - Print composed names for non null function pointers
389: Input Parameter:
390: . flist - pointer to list
392: Level: developer
394: .seealso: `PetscFunctionListAdd()`, `PetscFunctionList`, `PetscObjectQueryFunction()`
395: M*/
396: PetscErrorCode PetscFunctionListPrintNonEmpty(PetscFunctionList fl)
397: {
398: PetscFunctionBegin;
399: if (fl) {
400: // clang-format off
401: PetscHMapFuncForEach(
402: fl,
403: name, func,
404: PetscCall(PetscFPrintf(PETSC_COMM_SELF, PETSC_STDOUT, "[%d] function name: %s\n", PetscGlobalRank, name));
405: );
406: // clang-format on
407: }
408: PetscFunctionReturn(PETSC_SUCCESS);
409: }
411: /*MC
412: PetscFunctionListFind - Find function registered under given name
414: Synopsis:
415: #include <petscsys.h>
416: PetscErrorCode PetscFunctionListFind(PetscFunctionList flist,const char name[],void (**fptr)(void))
418: Input Parameters:
419: + flist - pointer to list
420: - name - name registered for the function
422: Output Parameters:
423: . fptr - the function pointer if name was found, else NULL
425: Level: developer
427: .seealso: `PetscFunctionListAdd()`, `PetscFunctionList`, `PetscObjectQueryFunction()`
428: M*/
429: PetscErrorCode PetscFunctionListFind_Private(PetscFunctionList fl, const char name[], PetscVoidFunction *r)
430: {
431: PetscFunctionBegin;
434: *r = NULL;
435: if (fl) PetscCall(PetscHMapFuncGet(fl->map, name, r));
436: PetscFunctionReturn(PETSC_SUCCESS);
437: }
439: /*@
440: PetscFunctionListView - prints out contents of an PetscFunctionList
442: Collective on `viewer`
444: Input Parameters:
445: + list - the list of functions
446: - viewer - the `PetscViewer` used to view the PetscFunctionList
448: Level: developer
450: .seealso: `PetscFunctionListAdd()`, `PetscFunctionListPrintTypes()`, `PetscFunctionList`
451: @*/
452: PetscErrorCode PetscFunctionListView(PetscFunctionList list, PetscViewer viewer)
453: {
454: PetscBool iascii;
456: PetscFunctionBegin;
458: if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PETSC_COMM_SELF, &viewer));
461: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
462: PetscCheck(iascii, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only ASCII viewer supported");
463: {
464: PetscInt size;
466: PetscCall(PetscHMapFuncGetSize(list->map, &size));
467: PetscCall(PetscViewerASCIIPrintf(viewer, "PetscFunctionList Object:\n"));
468: PetscCall(PetscViewerASCIIPushTab(viewer));
469: PetscCall(PetscViewerASCIIPrintf(viewer, "size: %" PetscInt_FMT "\n", size));
470: if (size) {
471: PetscInt count = 0;
473: PetscCall(PetscViewerASCIIPrintf(viewer, "functions:\n"));
474: PetscCall(PetscViewerASCIIPushTab(viewer));
475: PetscHMapFuncForEach(list, name, func, PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT ": %s\n", ++count, name)));
476: PetscCall(PetscViewerASCIIPopTab(viewer));
477: }
478: PetscCall(PetscViewerASCIIPopTab(viewer));
479: }
480: PetscFunctionReturn(PETSC_SUCCESS);
481: }
483: /*@C
484: PetscFunctionListGet - Gets an array the contains the entries in `PetscFunctionList`, this is used
485: by help etc.
487: Not Collective
489: Input Parameter:
490: . list - list of types
492: Output Parameters:
493: + array - array of names
494: - n - length of array
496: Note:
497: This allocates the array so that must be freed. BUT the individual entries are
498: not copied so should not be freed.
500: Level: developer
502: .seealso: `PetscFunctionListAdd()`, `PetscFunctionList`
503: @*/
504: PetscErrorCode PetscFunctionListGet(PetscFunctionList list, const char ***array, int *n)
505: {
506: PetscInt size = 0;
508: PetscFunctionBegin;
510: *array = NULL;
511: if (list) {
512: const PetscHMapFunc map = list->map;
513: PetscInt off = 0;
515: PetscCall(PetscHMapFuncGetSize(map, &size));
516: PetscCall(PetscMalloc1(size, (char ***)array));
517: PetscCall(PetscHMapFuncGetKeys(map, &off, *array));
518: }
519: *n = (int)size;
520: PetscFunctionReturn(PETSC_SUCCESS);
521: }
523: /*@C
524: PetscFunctionListPrintTypes - Prints the methods available in a list of functions
526: Collective over MPI_Comm
528: Input Parameters:
529: + comm - the communicator (usually `MPI_COMM_WORLD`)
530: . fd - file to print to, usually stdout
531: . prefix - prefix to prepend to name (optional)
532: . name - option string (for example, "-ksp_type")
533: . text - short description of the object (for example, "Krylov solvers")
534: . man - name of manual page that discusses the object (for example, "KSPCreate")
535: . list - list of types
536: . def - default (current) value
537: - newv - new value
539: Level: developer
541: .seealso: `PetscFunctionListAdd()`, `PetscFunctionList`
542: @*/
543: 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[])
544: {
545: char p[64];
547: PetscFunctionBegin;
548: (void)fd;
549: PetscCall(PetscStrncpy(p, "-", sizeof(p)));
550: if (prefix) PetscCall(PetscStrlcat(p, prefix, sizeof(p)));
551: PetscCall((*PetscHelpPrintf)(comm, " %s%s <now %s : formerly %s>: %s (one of)", p, name + 1, newv, def, text));
553: PetscHMapFuncForEach(list, name, func, PetscCall((*PetscHelpPrintf)(comm, " %s", name)));
554: PetscCall((*PetscHelpPrintf)(comm, " (%s)\n", man));
555: PetscFunctionReturn(PETSC_SUCCESS);
556: }
558: /*@
559: PetscFunctionListDuplicate - Creates a new list from a given object list.
561: Input Parameters:
562: . fl - pointer to list
564: Output Parameters:
565: . nl - the new list (should point to 0 to start, otherwise appends)
567: Level: developer
569: .seealso: `PetscFunctionList`, `PetscFunctionListAdd()`, `PetscFlistDestroy()`
570: @*/
571: PetscErrorCode PetscFunctionListDuplicate(PetscFunctionList fl, PetscFunctionList *nl)
572: {
573: PetscFunctionBegin;
574: if (fl) {
575: PetscHMapFunc dup_map;
577: if (!*nl) {
578: PetscInt n;
580: PetscCall(PetscHMapFuncGetSize(fl->map, &n));
581: PetscCall(PetscFunctionListCreate_Private(n, nl));
582: }
583: dup_map = (*nl)->map;
584: PetscHMapFuncForEach(fl, name, func, PetscCall(PetscHMapFuncInsert_Private(dup_map, name, func)));
585: }
586: PetscFunctionReturn(PETSC_SUCCESS);
587: }