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