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: PETSC_HASH_MAP(HMapFunc, const char *, PetscVoidFunction, kh_str_hash_func, kh_str_hash_equal, NULL)

171: struct _n_PetscFunctionList {
172:   PetscHMapFunc map;
173: };

175: /* Keep a linked list of PetscFunctionLists so that we can destroy all the left-over ones. */
176: typedef struct n_PetscFunctionListDLAll *PetscFunctionListDLAll;
177: struct n_PetscFunctionListDLAll {
178:   PetscFunctionList      data;
179:   PetscFunctionListDLAll next;
180: };

182: static PetscFunctionListDLAll dlallhead = NULL;

184: static PetscErrorCode PetscFunctionListDLAllPush_Private(PetscFunctionList fl)
185: {
186:   PetscFunctionBegin;
187:   if (PetscDefined(USE_DEBUG) && !PetscDefined(HAVE_THREADSAFETY)) {
188:     PetscFunctionListDLAll head;

190:     PetscCall(PetscNew(&head));
191:     head->data = fl;
192:     head->next = dlallhead;
193:     dlallhead  = head;
194:   }
195:   PetscFunctionReturn(PETSC_SUCCESS);
196: }

198: static PetscErrorCode PetscFunctionListDLAllPop_Private(PetscFunctionList fl)
199: {
200:   PetscFunctionBegin;
201:   if (PetscDefined(USE_DEBUG) && !PetscDefined(HAVE_THREADSAFETY)) {
202:     PetscFunctionListDLAll current = dlallhead, prev = NULL;

204:     /* Remove this entry from the main DL list (if it is in it) */
205:     while (current) {
206:       const PetscFunctionListDLAll next = current->next;

208:       if (current->data == fl) {
209:         if (prev) {
210:           // somewhere in the middle (or end) of the list
211:           prev->next = next;
212:         } else {
213:           // prev = NULL implies current = dlallhead, so front of list
214:           dlallhead = next;
215:         }
216:         PetscCall(PetscFree(current));
217:         break;
218:       }
219:       prev    = current;
220:       current = next;
221:     }
222:   }
223:   PetscFunctionReturn(PETSC_SUCCESS);
224: }

226: static PetscErrorCode PetscHMapFuncInsert_Private(PetscHMapFunc map, const char name[], PetscVoidFunction fnc)
227: {
228:   PetscHashIter it;
229:   PetscBool     found;

231:   PetscFunctionBegin;
234:   PetscCall(PetscHMapFuncFind(map, name, &it, &found));
235:   if (fnc) {
236:     if (found) {
237:       PetscCall(PetscHMapFuncIterSet(map, it, fnc));
238:     } else {
239:       char *tmp_name;

241:       PetscCall(PetscStrallocpy(name, &tmp_name));
242:       PetscCall(PetscHMapFuncSet(map, tmp_name, fnc));
243:     }
244:   } else if (found) {
245:     const char *tmp_name;

247:     PetscHashIterGetKey(map, it, tmp_name);
248:     PetscCall(PetscFree(tmp_name));
249:     PetscCall(PetscHMapFuncIterDel(map, it));
250:   }
251:   PetscFunctionReturn(PETSC_SUCCESS);
252: }

254: static PetscErrorCode PetscFunctionListCreate_Private(PetscInt size, PetscFunctionList *fl)
255: {
256:   PetscFunctionBegin;
257:   if (*fl) PetscFunctionReturn(PETSC_SUCCESS);
258:   PetscCall(PetscNew(fl));
259:   PetscCall(PetscHMapFuncCreateWithSize(size, &(*fl)->map));
260:   PetscCall(PetscFunctionListDLAllPush_Private(*fl));
261:   PetscFunctionReturn(PETSC_SUCCESS);
262: }

264: /*MC
265:    PetscFunctionListAdd - Given a routine and a string id, saves that routine in the
266:    specified registry.

268:    Synopsis:
269: #include <petscsys.h>
270:    PetscErrorCode PetscFunctionListAdd(PetscFunctionList *flist,const char name[],void (*fptr)(void))

272:    Not Collective

274:    Input Parameters:
275: +  flist - pointer to function list object
276: .  name - string to identify routine
277: -  fptr - function pointer

279:     Level: developer

281:    Notes:
282:    To remove a registered routine, pass in a `NULL` `fptr`.

284:    Users who wish to register new classes for use by a particular PETSc
285:    component (e.g., `SNES`) should generally call the registration routine
286:    for that particular component (e.g., `SNESRegister()`) instead of
287:    calling `PetscFunctionListAdd()` directly.

289: .seealso: `PetscFunctionListDestroy()`, `SNESRegister()`, `KSPRegister()`,`PetscFunctionListDuplicate()`
290:           `PCRegister()`, `TSRegister()`, `PetscFunctionList`, `PetscObjectComposeFunction()`
291: M*/
292: PetscErrorCode PetscFunctionListAdd_Private(PetscFunctionList *fl, const char name[], PetscVoidFunction fnc)
293: {
294:   PetscFunctionBegin;
298:   PetscCall(PetscFunctionListCreate_Private(0, fl));
299:   PetscCall(PetscHMapFuncInsert_Private((*fl)->map, name, fnc));
300:   PetscFunctionReturn(PETSC_SUCCESS);
301: }

303: /*@
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:       PetscVoidFunction 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: /*@
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: /*MC
386:     PetscFunctionListNonEmpty - Print composed names for non `NULL` function pointers

388:     Input Parameter:
389: .   flist   - pointer to list

391:     Level: developer

393: .seealso: `PetscFunctionListAdd()`, `PetscFunctionList`, `PetscObjectQueryFunction()`
394: M*/
395: PetscErrorCode PetscFunctionListPrintNonEmpty(PetscFunctionList fl)
396: {
397:   PetscFunctionBegin;
398:   if (fl) {
399:     // clang-format off
400:     PetscHMapFuncForEach(
401:       fl,
402:       name, func,
403:       PetscCall(PetscFPrintf(PETSC_COMM_SELF, PETSC_STDOUT, "[%d] function name: %s\n", PetscGlobalRank, name));
404:     );
405:     // clang-format on
406:   }
407:   PetscFunctionReturn(PETSC_SUCCESS);
408: }

410: /*MC
411:     PetscFunctionListFind - Find function registered under given name

413:     Synopsis:
414: #include <petscsys.h>
415:     PetscErrorCode PetscFunctionListFind(PetscFunctionList flist,const char name[],void (**fptr)(void))

417:     Input Parameters:
418: +   flist   - pointer to list
419: -   name - name registered for the function

421:     Output Parameter:
422: .   fptr - the function pointer if name was found, else `NULL`

424:     Level: developer

426: .seealso: `PetscFunctionListAdd()`, `PetscFunctionList`, `PetscObjectQueryFunction()`, `PetscFunctionListDuplicate()`
427: M*/
428: PetscErrorCode PetscFunctionListFind_Private(PetscFunctionList fl, const char name[], PetscVoidFunction *r)
429: {
430:   PetscFunctionBegin;
433:   *r = NULL;
434:   if (fl) PetscCall(PetscHMapFuncGet(fl->map, name, r));
435:   PetscFunctionReturn(PETSC_SUCCESS);
436: }

438: /*@
439:    PetscFunctionListView - prints out contents of a `PetscFunctionList`

441:    Collective

443:    Input Parameters:
444: +  list - the list of functions
445: -  viewer - the `PetscViewer` used to view the `PetscFunctionList`

447:    Level: developer

449: .seealso: `PetscFunctionListAdd()`, `PetscFunctionListPrintTypes()`, `PetscFunctionList`
450: @*/
451: PetscErrorCode PetscFunctionListView(PetscFunctionList list, PetscViewer viewer)
452: {
453:   PetscBool iascii;

455:   PetscFunctionBegin;
457:   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PETSC_COMM_SELF, &viewer));

460:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
461:   PetscCheck(iascii, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only ASCII viewer supported");
462:   {
463:     PetscInt size;

465:     PetscCall(PetscHMapFuncGetSize(list->map, &size));
466:     PetscCall(PetscViewerASCIIPrintf(viewer, "PetscFunctionList Object:\n"));
467:     PetscCall(PetscViewerASCIIPushTab(viewer));
468:     PetscCall(PetscViewerASCIIPrintf(viewer, "size: %" PetscInt_FMT "\n", size));
469:     if (size) {
470:       PetscInt count = 0;

472:       PetscCall(PetscViewerASCIIPrintf(viewer, "functions:\n"));
473:       PetscCall(PetscViewerASCIIPushTab(viewer));
474:       PetscHMapFuncForEach(list, name, func, PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT ": %s\n", ++count, name)));
475:       PetscCall(PetscViewerASCIIPopTab(viewer));
476:     }
477:     PetscCall(PetscViewerASCIIPopTab(viewer));
478:   }
479:   PetscFunctionReturn(PETSC_SUCCESS);
480: }

482: /*@C
483:    PetscFunctionListGet - Gets an array the contains the entries in `PetscFunctionList`, this is used
484:          by help etc.

486:    Not Collective

488:    Input Parameter:
489: .  list   - list of types

491:    Output Parameters:
492: +  array - array of names
493: -  n - length of `array`

495:    Level: developer

497:    Note:
498:        This allocates the array so that must be freed. BUT the individual entries are
499:     not copied so should not be freed.

501: .seealso: `PetscFunctionListAdd()`, `PetscFunctionList`
502: @*/
503: PetscErrorCode PetscFunctionListGet(PetscFunctionList list, const char ***array, int *n)
504: {
505:   PetscInt size = 0;

507:   PetscFunctionBegin;
509:   *array = NULL;
510:   if (list) {
511:     const PetscHMapFunc map = list->map;
512:     PetscInt            off = 0;

514:     PetscCall(PetscHMapFuncGetSize(map, &size));
515:     PetscCall(PetscMalloc1(size, (char ***)array));
516:     PetscCall(PetscHMapFuncGetKeys(map, &off, *array));
517:   }
518:   *n = (int)size;
519:   PetscFunctionReturn(PETSC_SUCCESS);
520: }

522: /*@C
523:    PetscFunctionListPrintTypes - Prints the methods available in a list of functions

525:    Collective over MPI_Comm

527:    Input Parameters:
528: +  comm   - the communicator (usually `MPI_COMM_WORLD`)
529: .  fd     - file to print to, usually `stdout`
530: .  prefix - prefix to prepend to name (optional)
531: .  name   - option string (for example, `-ksp_type`)
532: .  text - short description of the object (for example, "Krylov solvers")
533: .  man - name of manual page that discusses the object (for example, `KSPCreate`)
534: .  list   - list of types
535: .  def - default (current) value
536: -  newv - new value

538:    Level: developer

540: .seealso: `PetscFunctionListAdd()`, `PetscFunctionList`
541: @*/
542: 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[])
543: {
544:   char p[64];

546:   PetscFunctionBegin;
547:   (void)fd;
548:   PetscCall(PetscStrncpy(p, "-", sizeof(p)));
549:   if (prefix) PetscCall(PetscStrlcat(p, prefix, sizeof(p)));
550:   PetscCall((*PetscHelpPrintf)(comm, "  %s%s <now %s : formerly %s>: %s (one of)", p, name + 1, newv, def, text));

552:   if (list) PetscHMapFuncForEach(list, name, func, PetscCall((*PetscHelpPrintf)(comm, " %s", name)));
553:   PetscCall((*PetscHelpPrintf)(comm, " (%s)\n", man));
554:   PetscFunctionReturn(PETSC_SUCCESS);
555: }

557: /*@
558:     PetscFunctionListDuplicate - Creates a new list from a given function list `PetscFunctionList`.

560:     Input Parameter:
561: .   fl   - pointer to list

563:     Output Parameter:
564: .   nl - the new list (should point to `NULL` to start, otherwise appends)

566:     Level: developer

568: .seealso: `PetscFunctionList`, `PetscFunctionListAdd()`, `PetscFlistDestroy()`
569: @*/
570: PetscErrorCode PetscFunctionListDuplicate(PetscFunctionList fl, PetscFunctionList *nl)
571: {
572:   PetscFunctionBegin;
573:   if (fl) {
574:     PetscHMapFunc dup_map;

576:     if (!*nl) {
577:       PetscInt n;

579:       PetscCall(PetscHMapFuncGetSize(fl->map, &n));
580:       PetscCall(PetscFunctionListCreate_Private(n, nl));
581:     }
582:     dup_map = (*nl)->map;
583:     PetscHMapFuncForEach(fl, name, func, PetscCall(PetscHMapFuncInsert_Private(dup_map, name, func)));
584:   }
585:   PetscFunctionReturn(PETSC_SUCCESS);
586: }