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> /*I "petscsys.h" I*/ 6 #include <petscviewer.h> 7 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; 13 14 #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES) 15 16 static PetscErrorCode PetscLoadDynamicLibrary(const char *name, PetscBool *found) 17 { 18 char libs[PETSC_MAX_PATH_LEN], dlib[PETSC_MAX_PATH_LEN]; 19 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 35 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 52 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 65 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 71 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 } 78 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 } 127 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 135 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 } 142 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 } 152 153 /* 154 PetscFinalize_DynamicLibraries - Closes the opened dynamic libraries. 155 */ 156 PETSC_INTERN PetscErrorCode PetscFinalize_DynamicLibraries(void) 157 { 158 PetscBool flg = PETSC_FALSE; 159 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 } 167 168 PETSC_HASH_MAP(HMapFunc, const char *, PetscVoidFn *, kh_str_hash_func, kh_str_hash_equal, NULL) 169 170 struct _n_PetscFunctionList { 171 PetscHMapFunc map; 172 }; 173 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 }; 180 181 static PetscFunctionListDLAll dlallhead = NULL; 182 183 static PetscErrorCode PetscFunctionListDLAllPush_Private(PetscFunctionList fl) 184 { 185 PetscFunctionBegin; 186 if (PetscDefined(USE_DEBUG) && !PetscDefined(HAVE_THREADSAFETY)) { 187 PetscFunctionListDLAll head; 188 189 PetscCall(PetscNew(&head)); 190 head->data = fl; 191 head->next = dlallhead; 192 dlallhead = head; 193 } 194 PetscFunctionReturn(PETSC_SUCCESS); 195 } 196 197 static PetscErrorCode PetscFunctionListDLAllPop_Private(PetscFunctionList fl) 198 { 199 PetscFunctionBegin; 200 if (PetscDefined(USE_DEBUG) && !PetscDefined(HAVE_THREADSAFETY)) { 201 PetscFunctionListDLAll current = dlallhead, prev = NULL; 202 203 /* Remove this entry from the main DL list (if it is in it) */ 204 while (current) { 205 const PetscFunctionListDLAll next = current->next; 206 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 } 224 225 static PetscErrorCode PetscHMapFuncInsert_Private(PetscHMapFunc map, const char name[], PetscVoidFn *fnc) 226 { 227 PetscHashIter it; 228 PetscBool found; 229 230 PetscFunctionBegin; 231 PetscAssertPointer(name, 2); 232 if (fnc) PetscValidFunction(fnc, 3); 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; 239 240 PetscCall(PetscStrallocpy(name, &tmp_name)); 241 PetscCall(PetscHMapFuncSet(map, tmp_name, fnc)); 242 } 243 } else if (found) { 244 const char *tmp_name; 245 246 PetscHashIterGetKey(map, it, tmp_name); 247 PetscCall(PetscFree(tmp_name)); 248 PetscCall(PetscHMapFuncIterDel(map, it)); 249 } 250 PetscFunctionReturn(PETSC_SUCCESS); 251 } 252 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 } 262 263 /*MC 264 PetscFunctionListAdd - Given a routine and a string id, saves that routine in the 265 specified registry. 266 267 Synopsis: 268 #include <petscsys.h> 269 PetscErrorCode PetscFunctionListAdd(PetscFunctionList *flist,const char name[],void (*fptr)(void)) 270 271 Not Collective 272 273 Input Parameters: 274 + fl - pointer to function list object 275 . name - string to identify routine 276 - fptr - function pointer 277 278 Level: developer 279 280 Notes: 281 To remove a registered routine, pass in a `NULL` `fptr`. 282 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. 287 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); 296 if (fptr) PetscValidFunction(fptr, 3); 297 PetscCall(PetscFunctionListCreate_Private(0, fl)); 298 PetscCall(PetscHMapFuncInsert_Private((*fl)->map, name, fptr)); 299 PetscFunctionReturn(PETSC_SUCCESS); 300 } 301 302 /*@ 303 PetscFunctionListDestroy - Destroys a list of registered routines. 304 305 Input Parameter: 306 . fl - pointer to list 307 308 Level: developer 309 310 .seealso: `PetscFunctionListAdd()`, `PetscFunctionList`, `PetscFunctionListClear()` 311 @*/ 312 PetscErrorCode PetscFunctionListDestroy(PetscFunctionList *fl) 313 { 314 PetscFunctionBegin; 315 if (!*fl) PetscFunctionReturn(PETSC_SUCCESS); 316 PetscCall(PetscFunctionListDLAllPop_Private(*fl)); 317 /* free this list */ 318 PetscCall(PetscFunctionListClear(*fl)); 319 PetscCall(PetscHMapFuncDestroy(&(*fl)->map)); 320 PetscCall(PetscFree(*fl)); 321 PetscFunctionReturn(PETSC_SUCCESS); 322 } 323 324 #define PetscHMapFuncForEach(__func_list__, __key_name__, __val_name__, ...) \ 325 do { \ 326 const PetscHMapFunc phmfi_map_ = (__func_list__)->map; \ 327 PetscHashIter phmfi_iter_; \ 328 \ 329 PetscHashIterBegin(phmfi_map_, phmfi_iter_); \ 330 while (!PetscHashIterAtEnd(phmfi_map_, phmfi_iter_)) { \ 331 const char *PETSC_UNUSED __key_name__; \ 332 PetscVoidFn *PETSC_UNUSED __val_name__; \ 333 \ 334 PetscHashIterGetKey(phmfi_map_, phmfi_iter_, __key_name__); \ 335 PetscHashIterGetVal(phmfi_map_, phmfi_iter_, __val_name__); \ 336 { \ 337 __VA_ARGS__; \ 338 } \ 339 PetscHashIterNext(phmfi_map_, phmfi_iter_); \ 340 } /* end while */ \ 341 } while (0) 342 343 /*@ 344 PetscFunctionListClear - Clear a `PetscFunctionList` 345 346 Not Collective 347 348 Input Parameter: 349 . fl - The `PetscFunctionList` to clear 350 351 Level: developer 352 353 Notes: 354 This clears the contents of `fl` but does not deallocate the entries themselves. 355 356 .seealso: `PetscFunctionList`, `PetscFunctionListDestroy()`, `PetscFunctionListAdd()` 357 @*/ 358 PetscErrorCode PetscFunctionListClear(PetscFunctionList fl) 359 { 360 PetscFunctionBegin; 361 if (fl) { 362 PetscHMapFuncForEach(fl, name, func, PetscCall(PetscFree(name))); 363 PetscCall(PetscHMapFuncClear(fl->map)); 364 } 365 PetscFunctionReturn(PETSC_SUCCESS); 366 } 367 368 /* 369 Print registered PetscFunctionLists 370 */ 371 PetscErrorCode PetscFunctionListPrintAll(void) 372 { 373 PetscFunctionListDLAll current = dlallhead; 374 375 PetscFunctionBegin; 376 if (current) PetscCall(PetscPrintf(PETSC_COMM_SELF, "[%d] Registered PetscFunctionLists\n", PetscGlobalRank)); 377 while (current) { 378 PetscCall(PetscFunctionListPrintNonEmpty(current->data)); 379 current = current->next; 380 } 381 PetscFunctionReturn(PETSC_SUCCESS); 382 } 383 384 /*@C 385 PetscFunctionListPrintNonEmpty - Print composed names for non `NULL` function pointers 386 387 Input Parameter: 388 . fl - the function list 389 390 Level: developer 391 392 .seealso: `PetscFunctionListAdd()`, `PetscFunctionList`, `PetscObjectQueryFunction()` 393 @*/ 394 PetscErrorCode PetscFunctionListPrintNonEmpty(PetscFunctionList fl) 395 { 396 PetscFunctionBegin; 397 if (fl) { 398 // clang-format off 399 PetscHMapFuncForEach( 400 fl, 401 name, func, 402 PetscCall(PetscFPrintf(PETSC_COMM_SELF, PETSC_STDOUT, "[%d] function name: %s\n", PetscGlobalRank, name)); 403 ); 404 // clang-format on 405 } 406 PetscFunctionReturn(PETSC_SUCCESS); 407 } 408 409 /*MC 410 PetscFunctionListFind - Find function registered under given name 411 412 Synopsis: 413 #include <petscsys.h> 414 PetscErrorCode PetscFunctionListFind(PetscFunctionList flist,const char name[],void (**fptr)(void)) 415 416 Input Parameters: 417 + fl - the function list 418 - name - name registered for the function 419 420 Output Parameter: 421 . fptr - the function pointer if name was found, else `NULL` 422 423 Level: developer 424 425 .seealso: `PetscFunctionListAdd()`, `PetscFunctionList`, `PetscObjectQueryFunction()`, `PetscFunctionListDuplicate()` 426 M*/ 427 PetscErrorCode PetscFunctionListFind_Private(PetscFunctionList fl, const char name[], PetscVoidFn **fptr) 428 { 429 PetscFunctionBegin; 430 PetscAssertPointer(name, 2); 431 PetscAssertPointer(fptr, 3); 432 *fptr = NULL; 433 if (fl) PetscCall(PetscHMapFuncGet(fl->map, name, fptr)); 434 PetscFunctionReturn(PETSC_SUCCESS); 435 } 436 437 /*@ 438 PetscFunctionListView - prints out contents of a `PetscFunctionList` 439 440 Collective 441 442 Input Parameters: 443 + list - the list of functions 444 - viewer - the `PetscViewer` used to view the `PetscFunctionList` 445 446 Level: developer 447 448 .seealso: `PetscFunctionListAdd()`, `PetscFunctionListPrintTypes()`, `PetscFunctionList` 449 @*/ 450 PetscErrorCode PetscFunctionListView(PetscFunctionList list, PetscViewer viewer) 451 { 452 PetscBool iascii; 453 454 PetscFunctionBegin; 455 PetscAssertPointer(list, 1); 456 if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PETSC_COMM_SELF, &viewer)); 457 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 458 459 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 460 PetscCheck(iascii, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only ASCII viewer supported"); 461 { 462 PetscInt size; 463 464 PetscCall(PetscHMapFuncGetSize(list->map, &size)); 465 PetscCall(PetscViewerASCIIPrintf(viewer, "PetscFunctionList Object:\n")); 466 PetscCall(PetscViewerASCIIPushTab(viewer)); 467 PetscCall(PetscViewerASCIIPrintf(viewer, "size: %" PetscInt_FMT "\n", size)); 468 if (size) { 469 PetscInt count = 0; 470 471 PetscCall(PetscViewerASCIIPrintf(viewer, "functions:\n")); 472 PetscCall(PetscViewerASCIIPushTab(viewer)); 473 PetscHMapFuncForEach(list, name, func, PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT ": %s\n", ++count, name))); 474 PetscCall(PetscViewerASCIIPopTab(viewer)); 475 } 476 PetscCall(PetscViewerASCIIPopTab(viewer)); 477 } 478 PetscFunctionReturn(PETSC_SUCCESS); 479 } 480 481 /*@C 482 PetscFunctionListGet - Gets an array the contains the entries in `PetscFunctionList`, this is used 483 by help etc. 484 485 Not Collective 486 487 Input Parameter: 488 . list - list of types 489 490 Output Parameters: 491 + array - array of names 492 - n - length of `array` 493 494 Level: developer 495 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. 499 500 .seealso: `PetscFunctionListAdd()`, `PetscFunctionList` 501 @*/ 502 PetscErrorCode PetscFunctionListGet(PetscFunctionList list, const char ***array, int *n) 503 { 504 PetscInt size = 0; 505 506 PetscFunctionBegin; 507 PetscAssertPointer(array, 2); 508 *array = NULL; 509 if (list) { 510 const PetscHMapFunc map = list->map; 511 PetscInt off = 0; 512 513 PetscCall(PetscHMapFuncGetSize(map, &size)); 514 PetscCall(PetscMalloc1(size, (char ***)array)); 515 PetscCall(PetscHMapFuncGetKeys(map, &off, *array)); 516 } 517 *n = (int)size; 518 PetscFunctionReturn(PETSC_SUCCESS); 519 } 520 521 /*@C 522 PetscFunctionListPrintTypes - Prints the methods available in a list of functions 523 524 Collective 525 526 Input Parameters: 527 + comm - the communicator (usually `MPI_COMM_WORLD`) 528 . fd - file to print to, usually `stdout` 529 . prefix - prefix to prepend to name (optional) 530 . name - option string (for example, `-ksp_type`) 531 . text - short description of the object (for example, "Krylov solvers") 532 . man - name of manual page that discusses the object (for example, `KSPCreate`) 533 . list - list of types 534 . def - default (current) value 535 - newv - new value 536 537 Level: developer 538 539 .seealso: `PetscFunctionListAdd()`, `PetscFunctionList` 540 @*/ 541 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[]) 542 { 543 char p[64]; 544 545 PetscFunctionBegin; 546 (void)fd; 547 PetscCall(PetscStrncpy(p, "-", sizeof(p))); 548 if (prefix) PetscCall(PetscStrlcat(p, prefix, sizeof(p))); 549 PetscCall((*PetscHelpPrintf)(comm, " %s%s <now %s : formerly %s>: %s (one of)", p, name + 1, newv, def, text)); 550 551 if (list) PetscHMapFuncForEach(list, name, func, PetscCall((*PetscHelpPrintf)(comm, " %s", name))); 552 PetscCall((*PetscHelpPrintf)(comm, " (%s)\n", man)); 553 PetscFunctionReturn(PETSC_SUCCESS); 554 } 555 556 /*@ 557 PetscFunctionListDuplicate - Creates a new list from a given function list `PetscFunctionList`. 558 559 Input Parameter: 560 . fl - pointer to list 561 562 Output Parameter: 563 . nl - the new list (should point to `NULL` to start, otherwise appends) 564 565 Level: developer 566 567 .seealso: `PetscFunctionList`, `PetscFunctionListAdd()`, `PetscFlistDestroy()` 568 @*/ 569 PetscErrorCode PetscFunctionListDuplicate(PetscFunctionList fl, PetscFunctionList *nl) 570 { 571 PetscFunctionBegin; 572 if (fl) { 573 PetscHMapFunc dup_map; 574 575 if (!*nl) { 576 PetscInt n; 577 578 PetscCall(PetscHMapFuncGetSize(fl->map, &n)); 579 PetscCall(PetscFunctionListCreate_Private(n, nl)); 580 } 581 dup_map = (*nl)->map; 582 PetscHMapFuncForEach(fl, name, func, PetscCall(PetscHMapFuncInsert_Private(dup_map, name, func))); 583 } 584 PetscFunctionReturn(PETSC_SUCCESS); 585 } 586