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: }