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:   #if defined(PETSC_LIB_NAME_SUFFIX)
 24:   PetscCall(PetscStrlcat(libs, PETSC_LIB_NAME_SUFFIX, sizeof(libs)));
 25:   #endif
 26:   PetscCall(PetscDLLibraryRetrieve(PETSC_COMM_WORLD, libs, dlib, 1024, found));
 27:   if (*found) {
 28:     PetscCall(PetscDLLibraryAppend(PETSC_COMM_WORLD, &PetscDLLibrariesLoaded, dlib));
 29:   } else {
 30:     PetscCall(PetscStrncpy(libs, "${PETSC_DIR}/${PETSC_ARCH}/lib/libpetsc", sizeof(libs)));
 31:     PetscCall(PetscStrlcat(libs, name, sizeof(libs)));
 32:   #if defined(PETSC_LIB_NAME_SUFFIX)
 33:     PetscCall(PetscStrlcat(libs, PETSC_LIB_NAME_SUFFIX, sizeof(libs)));
 34:   #endif
 35:     PetscCall(PetscDLLibraryRetrieve(PETSC_COMM_WORLD, libs, dlib, 1024, found));
 36:     if (*found) PetscCall(PetscDLLibraryAppend(PETSC_COMM_WORLD, &PetscDLLibrariesLoaded, dlib));
 37:   }
 38:   PetscFunctionReturn(PETSC_SUCCESS);
 39: }
 40: #endif

 42: #if defined(PETSC_USE_SINGLE_LIBRARY) && !(defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES))
 43: PETSC_EXTERN PetscErrorCode AOInitializePackage(void);
 44: PETSC_EXTERN PetscErrorCode PetscSFInitializePackage(void);
 45:   #if !defined(PETSC_USE_COMPLEX)
 46: PETSC_EXTERN PetscErrorCode CharacteristicInitializePackage(void);
 47:   #endif
 48: PETSC_EXTERN PetscErrorCode ISInitializePackage(void);
 49: PETSC_EXTERN PetscErrorCode VecInitializePackage(void);
 50: PETSC_EXTERN PetscErrorCode MatInitializePackage(void);
 51: PETSC_EXTERN PetscErrorCode DMInitializePackage(void);
 52: PETSC_EXTERN PetscErrorCode PCInitializePackage(void);
 53: PETSC_EXTERN PetscErrorCode KSPInitializePackage(void);
 54: PETSC_EXTERN PetscErrorCode SNESInitializePackage(void);
 55: PETSC_EXTERN PetscErrorCode TSInitializePackage(void);
 56: PETSC_EXTERN PetscErrorCode TaoInitializePackage(void);
 57: #endif

 59: /*
 60:     PetscInitialize_DynamicLibraries - Adds the default dynamic link libraries to the
 61:     search path.
 62: */
 63: PETSC_INTERN PetscErrorCode PetscInitialize_DynamicLibraries(void)
 64: {
 65:   char     *libname[32];
 66:   PetscInt  nmax, i;
 67:   PetscBool preload = PETSC_FALSE;
 68: #if defined(PETSC_HAVE_ELEMENTAL)
 69:   PetscBool PetscInitialized = PetscInitializeCalled;
 70: #endif

 72:   PetscFunctionBegin;
 73: #if defined(PETSC_HAVE_THREADSAFETY)
 74:   /* These must be all initialized here because it is not safe for individual threads to call these initialize routines */
 75:   preload = PETSC_TRUE;
 76: #endif

 78:   nmax = 32;
 79:   PetscCall(PetscOptionsGetStringArray(NULL, NULL, "-dll_prepend", libname, &nmax, NULL));
 80:   for (i = 0; i < nmax; i++) {
 81:     PetscCall(PetscDLLibraryPrepend(PETSC_COMM_WORLD, &PetscDLLibrariesLoaded, libname[i]));
 82:     PetscCall(PetscFree(libname[i]));
 83:   }

 85:   PetscCall(PetscOptionsGetBool(NULL, NULL, "-library_preload", &preload, NULL));
 86:   if (!preload) {
 87:     PetscCall(PetscSysInitializePackage());
 88:   } else {
 89: #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES)
 90:     PetscBool found;
 91:   #if defined(PETSC_USE_SINGLE_LIBRARY)
 92:     PetscCall(PetscLoadDynamicLibrary("", &found));
 93:     PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc dynamic library. You cannot move the dynamic libraries!");
 94:   #else
 95:     PetscCall(PetscLoadDynamicLibrary("sys", &found));
 96:     PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc Sys dynamic library. You cannot move the dynamic libraries!");
 97:     PetscCall(PetscLoadDynamicLibrary("vec", &found));
 98:     PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc Vec dynamic library. You cannot move the dynamic libraries!");
 99:     PetscCall(PetscLoadDynamicLibrary("mat", &found));
100:     PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc Mat dynamic library. You cannot move the dynamic libraries!");
101:     PetscCall(PetscLoadDynamicLibrary("dm", &found));
102:     PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc DM dynamic library. You cannot move the dynamic libraries!");
103:     PetscCall(PetscLoadDynamicLibrary("ksp", &found));
104:     PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc KSP dynamic library. You cannot move the dynamic libraries!");
105:     PetscCall(PetscLoadDynamicLibrary("snes", &found));
106:     PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc SNES dynamic library. You cannot move the dynamic libraries!");
107:     PetscCall(PetscLoadDynamicLibrary("ts", &found));
108:     PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc TS dynamic library. You cannot move the dynamic libraries!");
109:     PetscCall(PetscLoadDynamicLibrary("tao", &found));
110:     PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate Tao dynamic library. You cannot move the dynamic libraries!");
111:   #endif
112: #else /* defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES) */
113:   #if defined(PETSC_USE_SINGLE_LIBRARY)
114:     PetscCall(AOInitializePackage());
115:     PetscCall(PetscSFInitializePackage());
116:     #if !defined(PETSC_USE_COMPLEX)
117:     PetscCall(CharacteristicInitializePackage());
118:     #endif
119:     PetscCall(ISInitializePackage());
120:     PetscCall(VecInitializePackage());
121:     PetscCall(MatInitializePackage());
122:     PetscCall(DMInitializePackage());
123:     PetscCall(PCInitializePackage());
124:     PetscCall(KSPInitializePackage());
125:     PetscCall(SNESInitializePackage());
126:     PetscCall(TSInitializePackage());
127:     PetscCall(TaoInitializePackage());
128:   #else
129:     SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP, "Cannot use -library_preload with multiple static PETSc libraries");
130:   #endif
131: #endif /* defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES) */
132:   }

134: #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES) && defined(PETSC_HAVE_BAMG)
135:   {
136:     PetscBool found;
137:     PetscCall(PetscLoadDynamicLibrary("bamg", &found));
138:     PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PETSc BAMG dynamic library. You cannot move the dynamic libraries!");
139:   }
140: #endif
141: #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES) && defined(PETSC_HAVE_PFLARE)
142:   {
143:     PetscBool found;
144:     PetscCall(PetscLoadDynamicLibrary("pflare", &found));
145:     PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to locate PFLARE dynamic library. You cannot move the dynamic libraries!");
146:   }
147: #endif

149:   nmax = 32;
150:   PetscCall(PetscOptionsGetStringArray(NULL, NULL, "-dll_append", libname, &nmax, NULL));
151:   for (i = 0; i < nmax; i++) {
152:     PetscCall(PetscDLLibraryAppend(PETSC_COMM_WORLD, &PetscDLLibrariesLoaded, libname[i]));
153:     PetscCall(PetscFree(libname[i]));
154:   }

156: #if defined(PETSC_HAVE_ELEMENTAL)
157:   /* in Fortran, PetscInitializeCalled is set to PETSC_TRUE before PetscInitialize_DynamicLibraries() */
158:   /* in C, it is not the case, but the value is forced to PETSC_TRUE so that PetscRegisterFinalize() is called */
159:   PetscInitializeCalled = PETSC_TRUE;
160:   PetscCall(PetscElementalInitializePackage());
161:   PetscInitializeCalled = PetscInitialized;
162: #endif
163:   PetscFunctionReturn(PETSC_SUCCESS);
164: }

166: /*
167:      PetscFinalize_DynamicLibraries - Closes the opened dynamic libraries.
168: */
169: PETSC_INTERN PetscErrorCode PetscFinalize_DynamicLibraries(void)
170: {
171:   PetscBool flg = PETSC_FALSE;

173:   PetscFunctionBegin;
174:   PetscCall(PetscOptionsGetBool(NULL, NULL, "-dll_view", &flg, NULL));
175:   if (flg) PetscCall(PetscDLLibraryPrintPath(PetscDLLibrariesLoaded));
176:   PetscCall(PetscDLLibraryClose(PetscDLLibrariesLoaded));
177:   PetscDLLibrariesLoaded = NULL;
178:   PetscFunctionReturn(PETSC_SUCCESS);
179: }

181: PETSC_HASH_MAP(HMapFunc, const char *, PetscErrorCodeFn *, kh_str_hash_func, kh_str_hash_equal, NULL)

183: struct _n_PetscFunctionList {
184:   PetscHMapFunc map;
185: };

187: /* Keep a linked list of PetscFunctionLists so that we can destroy all the left-over ones. */
188: typedef struct n_PetscFunctionListDLAll *PetscFunctionListDLAll;
189: struct n_PetscFunctionListDLAll {
190:   PetscFunctionList      data;
191:   PetscFunctionListDLAll next;
192: };

194: static PetscFunctionListDLAll dlallhead = NULL;

196: static PetscErrorCode PetscFunctionListDLAllPush_Private(PetscFunctionList fl)
197: {
198:   PetscFunctionBegin;
199:   if (PetscDefined(USE_DEBUG) && !PetscDefined(HAVE_THREADSAFETY)) {
200:     PetscFunctionListDLAll head;

202:     PetscCall(PetscNew(&head));
203:     head->data = fl;
204:     head->next = dlallhead;
205:     dlallhead  = head;
206:   }
207:   PetscFunctionReturn(PETSC_SUCCESS);
208: }

210: static PetscErrorCode PetscFunctionListDLAllPop_Private(PetscFunctionList fl)
211: {
212:   PetscFunctionBegin;
213:   if (PetscDefined(USE_DEBUG) && !PetscDefined(HAVE_THREADSAFETY)) {
214:     PetscFunctionListDLAll current = dlallhead, prev = NULL;

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

220:       if (current->data == fl) {
221:         if (prev) {
222:           // somewhere in the middle (or end) of the list
223:           prev->next = next;
224:         } else {
225:           // prev = NULL implies current = dlallhead, so front of list
226:           dlallhead = next;
227:         }
228:         PetscCall(PetscFree(current));
229:         break;
230:       }
231:       prev    = current;
232:       current = next;
233:     }
234:   }
235:   PetscFunctionReturn(PETSC_SUCCESS);
236: }

238: static PetscErrorCode PetscHMapFuncInsert_Private(PetscHMapFunc map, const char name[], PetscErrorCodeFn *fnc)
239: {
240:   PetscHashIter it;
241:   PetscBool     found;

243:   PetscFunctionBegin;
244:   PetscAssertPointer(name, 2);
246:   PetscCall(PetscHMapFuncFind(map, name, &it, &found));
247:   if (fnc) {
248:     if (found) {
249:       PetscCall(PetscHMapFuncIterSet(map, it, fnc));
250:     } else {
251:       char *tmp_name;

253:       PetscCall(PetscStrallocpy(name, &tmp_name));
254:       PetscCall(PetscHMapFuncSet(map, tmp_name, fnc));
255:     }
256:   } else if (found) {
257:     const char *tmp_name;

259:     PetscHashIterGetKey(map, it, tmp_name);
260:     PetscCall(PetscFree(tmp_name));
261:     PetscCall(PetscHMapFuncIterDel(map, it));
262:   }
263:   PetscFunctionReturn(PETSC_SUCCESS);
264: }

266: static PetscErrorCode PetscFunctionListCreate_Private(PetscInt size, PetscFunctionList *fl)
267: {
268:   PetscFunctionBegin;
269:   if (*fl) PetscFunctionReturn(PETSC_SUCCESS);
270:   PetscCall(PetscNew(fl));
271:   PetscCall(PetscHMapFuncCreateWithSize(size, &(*fl)->map));
272:   PetscCall(PetscFunctionListDLAllPush_Private(*fl));
273:   PetscFunctionReturn(PETSC_SUCCESS);
274: }

276: /*MC
277:   PetscFunctionListAdd - Given a routine and a string id, saves that routine in the
278:   specified registry.

280:   Synopsis:
281: #include <petscsys.h>
282:   PetscErrorCode PetscFunctionListAdd(PetscFunctionList *flist, const char name[], PetscErrorCodeFn *fptr)

284:   Not Collective

286:   Input Parameters:
287: + fl   - pointer to function list object
288: . name - string to identify routine
289: - fptr - function pointer

291:   Level: developer

293:   Notes:
294:   To remove a registered routine, pass in a `NULL` `fptr`.

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

301: .seealso: `PetscFunctionListDestroy()`, `SNESRegister()`, `KSPRegister()`,`PetscFunctionListDuplicate()`
302:           `PCRegister()`, `TSRegister()`, `PetscFunctionList`, `PetscObjectComposeFunction()`
303: M*/
304: PetscErrorCode PetscFunctionListAdd_Private(PetscFunctionList *fl, const char name[], PetscErrorCodeFn *fptr)
305: {
306:   PetscFunctionBegin;
307:   PetscAssertPointer(fl, 1);
308:   if (name) PetscAssertPointer(name, 2);
310:   if (!fptr && !*fl) PetscFunctionReturn(PETSC_SUCCESS);
311:   PetscCall(PetscFunctionListCreate_Private(0, fl));
312:   PetscCall(PetscHMapFuncInsert_Private((*fl)->map, name, fptr));
313:   PetscFunctionReturn(PETSC_SUCCESS);
314: }

316: /*@C
317:   PetscFunctionListDestroy - Destroys a list of registered routines.

319:   Input Parameter:
320: . fl - pointer to list

322:   Level: developer

324: .seealso: `PetscFunctionListAdd()`, `PetscFunctionList`, `PetscFunctionListClear()`
325: @*/
326: PetscErrorCode PetscFunctionListDestroy(PetscFunctionList *fl)
327: {
328:   PetscFunctionBegin;
329:   if (!*fl) PetscFunctionReturn(PETSC_SUCCESS);
330:   PetscCall(PetscFunctionListDLAllPop_Private(*fl));
331:   /* free this list */
332:   PetscCall(PetscFunctionListClear(*fl));
333:   PetscCall(PetscHMapFuncDestroy(&(*fl)->map));
334:   PetscCall(PetscFree(*fl));
335:   PetscFunctionReturn(PETSC_SUCCESS);
336: }

338: #define PetscHMapFuncForEach(__func_list__, __key_name__, __val_name__, ...) \
339:   do { \
340:     const PetscHMapFunc phmfi_map_ = (__func_list__)->map; \
341:     PetscHashIter       phmfi_iter_; \
342: \
343:     PetscHashIterBegin(phmfi_map_, phmfi_iter_); \
344:     while (!PetscHashIterAtEnd(phmfi_map_, phmfi_iter_)) { \
345:       const char *PETSC_UNUSED       __key_name__; \
346:       PetscErrorCodeFn *PETSC_UNUSED __val_name__; \
347: \
348:       PetscHashIterGetKey(phmfi_map_, phmfi_iter_, __key_name__); \
349:       PetscHashIterGetVal(phmfi_map_, phmfi_iter_, __val_name__); \
350:       { \
351:         __VA_ARGS__; \
352:       } \
353:       PetscHashIterNext(phmfi_map_, phmfi_iter_); \
354:     } /* end while */ \
355:   } while (0)

357: /*@C
358:   PetscFunctionListClear - Clear a `PetscFunctionList`

360:   Not Collective

362:   Input Parameter:
363: . fl - The `PetscFunctionList` to clear

365:   Level: developer

367:   Notes:
368:   This clears the contents of `fl` but does not deallocate the entries themselves.

370: .seealso: `PetscFunctionList`, `PetscFunctionListDestroy()`, `PetscFunctionListAdd()`
371: @*/
372: PetscErrorCode PetscFunctionListClear(PetscFunctionList fl)
373: {
374:   PetscFunctionBegin;
375:   if (fl) {
376:     PetscHMapFuncForEach(fl, name, func, PetscCall(PetscFree(name)));
377:     PetscCall(PetscHMapFuncClear(fl->map));
378:   }
379:   PetscFunctionReturn(PETSC_SUCCESS);
380: }

382: /*
383:    Print registered PetscFunctionLists
384: */
385: PetscErrorCode PetscFunctionListPrintAll(void)
386: {
387:   PetscFunctionListDLAll current = dlallhead;

389:   PetscFunctionBegin;
390:   if (current) PetscCall(PetscPrintf(PETSC_COMM_SELF, "[%d] Registered PetscFunctionLists\n", PetscGlobalRank));
391:   while (current) {
392:     PetscCall(PetscFunctionListPrintNonEmpty(current->data));
393:     current = current->next;
394:   }
395:   PetscFunctionReturn(PETSC_SUCCESS);
396: }

398: /*@C
399:   PetscFunctionListPrintNonEmpty - Print composed names for non `NULL` function pointers

401:   Logically Collective, No Fortran Support

403:   Input Parameter:
404: . fl - the function list

406:   Level: developer

408: .seealso: `PetscFunctionListAdd()`, `PetscFunctionList`, `PetscObjectQueryFunction()`
409: @*/
410: PetscErrorCode PetscFunctionListPrintNonEmpty(PetscFunctionList fl)
411: {
412:   PetscFunctionBegin;
413:   if (fl) {
414:     // clang-format off
415:     PetscHMapFuncForEach(
416:       fl,
417:       name, func,
418:       PetscCall(PetscFPrintf(PETSC_COMM_SELF, PETSC_STDOUT, "[%d] function name: %s\n", PetscGlobalRank, name));
419:     );
420:     // clang-format on
421:   }
422:   PetscFunctionReturn(PETSC_SUCCESS);
423: }

425: /*MC
426:   PetscFunctionListFind - Find function registered under given name

428:   Not Collective, No Fortran Support

430:   Synopsis:
431: #include <petscsys.h>
432:   PetscErrorCode PetscFunctionListFind(PetscFunctionList flist, const char name[], PetscErrorCodeFn **fptr)

434:   Input Parameters:
435: + fl   - the function list
436: - name - name registered for the function

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

441:   Level: developer

443: .seealso: `PetscFunctionListAdd()`, `PetscFunctionList`, `PetscObjectQueryFunction()`, `PetscFunctionListDuplicate()`
444: M*/
445: PetscErrorCode PetscFunctionListFind_Private(PetscFunctionList fl, const char name[], PetscErrorCodeFn **fptr)
446: {
447:   PetscFunctionBegin;
448:   PetscAssertPointer(name, 2);
449:   PetscAssertPointer(fptr, 3);
450:   *fptr = NULL;
451:   if (fl) PetscCall(PetscHMapFuncGet(fl->map, name, fptr));
452:   PetscFunctionReturn(PETSC_SUCCESS);
453: }

455: /*@C
456:   PetscFunctionListView - prints out contents of a `PetscFunctionList`

458:   Collective

460:   Input Parameters:
461: + list   - the list of functions
462: - viewer - the `PetscViewer` used to view the `PetscFunctionList`

464:   Level: developer

466: .seealso: `PetscFunctionListAdd()`, `PetscFunctionListPrintTypes()`, `PetscFunctionList`
467: @*/
468: PetscErrorCode PetscFunctionListView(PetscFunctionList list, PetscViewer viewer)
469: {
470:   PetscBool isascii;

472:   PetscFunctionBegin;
473:   PetscAssertPointer(list, 1);
474:   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PETSC_COMM_SELF, &viewer));

477:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
478:   PetscCheck(isascii, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only ASCII viewer supported");
479:   {
480:     PetscInt size;

482:     PetscCall(PetscHMapFuncGetSize(list->map, &size));
483:     PetscCall(PetscViewerASCIIPrintf(viewer, "PetscFunctionList Object:\n"));
484:     PetscCall(PetscViewerASCIIPushTab(viewer));
485:     PetscCall(PetscViewerASCIIPrintf(viewer, "size: %" PetscInt_FMT "\n", size));
486:     if (size) {
487:       PetscInt count = 0;

489:       PetscCall(PetscViewerASCIIPrintf(viewer, "functions:\n"));
490:       PetscCall(PetscViewerASCIIPushTab(viewer));
491:       PetscHMapFuncForEach(list, name, func, PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT ": %s\n", ++count, name)));
492:       PetscCall(PetscViewerASCIIPopTab(viewer));
493:     }
494:     PetscCall(PetscViewerASCIIPopTab(viewer));
495:   }
496:   PetscFunctionReturn(PETSC_SUCCESS);
497: }

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

503:   Not Collective, No Fortran Support

505:   Input Parameter:
506: . list - list of types

508:   Output Parameters:
509: + array - array of names
510: - n     - length of `array`

512:   Level: developer

514:   Note:
515:   This allocates the array so that must be freed with `PetscFree()`. BUT the individual entries should not be freed.

517: .seealso: `PetscFunctionListAdd()`, `PetscFunctionList`
518: @*/
519: PetscErrorCode PetscFunctionListGet(PetscFunctionList list, const char ***array, int *n)
520: {
521:   PetscInt size = 0;

523:   PetscFunctionBegin;
524:   PetscAssertPointer(array, 2);
525:   *array = NULL;
526:   if (list) {
527:     const PetscHMapFunc map = list->map;
528:     PetscInt            off = 0;

530:     PetscCall(PetscHMapFuncGetSize(map, &size));
531:     PetscCall(PetscMalloc1(size, (char ***)array));
532:     PetscCall(PetscHMapFuncGetKeys(map, &off, *array));
533:   }
534:   PetscCall(PetscCIntCast(size, n));
535:   PetscFunctionReturn(PETSC_SUCCESS);
536: }

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

541:   Collective, No Fortran Support

543:   Input Parameters:
544: + comm   - the communicator (usually `MPI_COMM_WORLD`)
545: . fd     - file to print to, usually `stdout`
546: . prefix - prefix to prepend to name (optional)
547: . name   - option string (for example, `-ksp_type`)
548: . text   - short description of the object (for example, "Krylov solvers")
549: . man    - name of manual page that discusses the object (for example, `KSPCreate`)
550: . list   - list of types
551: . def    - default (current) value
552: - newv   - new value

554:   Level: developer

556: .seealso: `PetscFunctionListAdd()`, `PetscFunctionList`
557: @*/
558: 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[])
559: {
560:   char p[64];

562:   PetscFunctionBegin;
563:   (void)fd;
564:   PetscCall(PetscStrncpy(p, "-", sizeof(p)));
565:   if (prefix) PetscCall(PetscStrlcat(p, prefix, sizeof(p)));
566:   PetscCall((*PetscHelpPrintf)(comm, "  %s%s <now %s : formerly %s>: %s (one of)", p, name + 1, newv, def, text));

568:   if (list) PetscHMapFuncForEach(list, name, func, PetscCall((*PetscHelpPrintf)(comm, " %s", name)));
569:   PetscCall((*PetscHelpPrintf)(comm, " (%s)\n", man));
570:   PetscFunctionReturn(PETSC_SUCCESS);
571: }

573: /*@C
574:   PetscFunctionListDuplicate - Creates a new list from a given function list `PetscFunctionList`.

576:   Input Parameter:
577: . fl - pointer to list

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

582:   Level: developer

584: .seealso: `PetscFunctionList`, `PetscFunctionListAdd()`, `PetscFlistDestroy()`
585: @*/
586: PetscErrorCode PetscFunctionListDuplicate(PetscFunctionList fl, PetscFunctionList *nl)
587: {
588:   PetscFunctionBegin;
589:   if (fl) {
590:     PetscHMapFunc dup_map;

592:     if (!*nl) {
593:       PetscInt n;

595:       PetscCall(PetscHMapFuncGetSize(fl->map, &n));
596:       PetscCall(PetscFunctionListCreate_Private(n, nl));
597:     }
598:     dup_map = (*nl)->map;
599:     PetscHMapFuncForEach(fl, name, func, PetscCall(PetscHMapFuncInsert_Private(dup_map, name, func)));
600:   }
601:   PetscFunctionReturn(PETSC_SUCCESS);
602: }