1 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> /*I "petscsys.h" I*/ 7 #include <petscviewer.h> 8 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; 14 15 #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES) 16 17 static PetscErrorCode PetscLoadDynamicLibrary(const char *name, PetscBool *found) 18 { 19 char libs[PETSC_MAX_PATH_LEN], dlib[PETSC_MAX_PATH_LEN]; 20 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 36 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 53 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 66 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 72 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 } 79 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 } 128 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 136 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 } 143 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 } 153 154 /* 155 PetscFinalize_DynamicLibraries - Closes the opened dynamic libraries. 156 */ 157 PETSC_INTERN PetscErrorCode PetscFinalize_DynamicLibraries(void) 158 { 159 PetscBool flg = PETSC_FALSE; 160 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 } 168 169 PETSC_HASH_MAP(HMapFunc, const char *, PetscVoidFunction, kh_str_hash_func, kh_str_hash_equal, NULL) 170 171 struct _n_PetscFunctionList { 172 PetscHMapFunc map; 173 }; 174 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 }; 181 182 static PetscFunctionListDLAll dlallhead = NULL; 183 184 static PetscErrorCode PetscFunctionListDLAllPush_Private(PetscFunctionList fl) 185 { 186 PetscFunctionBegin; 187 if (PetscDefined(USE_DEBUG) && !PetscDefined(HAVE_THREADSAFETY)) { 188 PetscFunctionListDLAll head; 189 190 PetscCall(PetscNew(&head)); 191 head->data = fl; 192 head->next = dlallhead; 193 dlallhead = head; 194 } 195 PetscFunctionReturn(PETSC_SUCCESS); 196 } 197 198 static PetscErrorCode PetscFunctionListDLAllPop_Private(PetscFunctionList fl) 199 { 200 PetscFunctionBegin; 201 if (PetscDefined(USE_DEBUG) && !PetscDefined(HAVE_THREADSAFETY)) { 202 PetscFunctionListDLAll current = dlallhead, prev = NULL; 203 204 /* Remove this entry from the main DL list (if it is in it) */ 205 while (current) { 206 const PetscFunctionListDLAll next = current->next; 207 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 } 225 226 static PetscErrorCode PetscHMapFuncInsert_Private(PetscHMapFunc map, const char name[], PetscVoidFunction fnc) 227 { 228 PetscHashIter it; 229 PetscBool found; 230 231 PetscFunctionBegin; 232 PetscValidCharPointer(name, 2); 233 if (fnc) PetscValidFunction(fnc, 3); 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; 240 241 PetscCall(PetscStrallocpy(name, &tmp_name)); 242 PetscCall(PetscHMapFuncSet(map, tmp_name, fnc)); 243 } 244 } else if (found) { 245 const char *tmp_name; 246 247 PetscHashIterGetKey(map, it, tmp_name); 248 PetscCall(PetscFree(tmp_name)); 249 PetscCall(PetscHMapFuncIterDel(map, it)); 250 } 251 PetscFunctionReturn(PETSC_SUCCESS); 252 } 253 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 } 263 264 /*MC 265 PetscFunctionListAdd - Given a routine and a string id, saves that routine in the 266 specified registry. 267 268 Synopsis: 269 #include <petscsys.h> 270 PetscErrorCode PetscFunctionListAdd(PetscFunctionList *flist,const char name[],void (*fptr)(void)) 271 272 Not Collective 273 274 Input Parameters: 275 + flist - pointer to function list object 276 . name - string to identify routine 277 - fptr - function pointer 278 279 Level: developer 280 281 Notes: 282 To remove a registered routine, pass in a `NULL` `fptr`. 283 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. 288 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; 295 PetscValidPointer(fl, 1); 296 if (name) PetscValidCharPointer(name, 2); 297 if (fnc) PetscValidFunction(fnc, 3); 298 PetscCall(PetscFunctionListCreate_Private(0, fl)); 299 PetscCall(PetscHMapFuncInsert_Private((*fl)->map, name, fnc)); 300 PetscFunctionReturn(PETSC_SUCCESS); 301 } 302 303 /*@ 304 PetscFunctionListDestroy - Destroys a list of registered routines. 305 306 Input Parameter: 307 . fl - pointer to list 308 309 Level: developer 310 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 } 324 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) 343 344 /*@ 345 PetscFunctionListClear - Clear a `PetscFunctionList` 346 347 Not Collective 348 349 Input Parameter: 350 . fl - The `PetscFunctionList` to clear 351 352 Level: developer 353 354 Notes: 355 This clears the contents of `fl` but does not deallocate the entries themselves. 356 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 } 368 369 /* 370 Print registered PetscFunctionLists 371 */ 372 PetscErrorCode PetscFunctionListPrintAll(void) 373 { 374 PetscFunctionListDLAll current = dlallhead; 375 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 } 384 385 /*MC 386 PetscFunctionListNonEmpty - Print composed names for non `NULL` function pointers 387 388 Input Parameter: 389 . flist - pointer to list 390 391 Level: developer 392 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 } 409 410 /*MC 411 PetscFunctionListFind - Find function registered under given name 412 413 Synopsis: 414 #include <petscsys.h> 415 PetscErrorCode PetscFunctionListFind(PetscFunctionList flist,const char name[],void (**fptr)(void)) 416 417 Input Parameters: 418 + flist - pointer to list 419 - name - name registered for the function 420 421 Output Parameter: 422 . fptr - the function pointer if name was found, else `NULL` 423 424 Level: developer 425 426 .seealso: `PetscFunctionListAdd()`, `PetscFunctionList`, `PetscObjectQueryFunction()`, `PetscFunctionListDuplicate()` 427 M*/ 428 PetscErrorCode PetscFunctionListFind_Private(PetscFunctionList fl, const char name[], PetscVoidFunction *r) 429 { 430 PetscFunctionBegin; 431 PetscValidCharPointer(name, 2); 432 PetscValidPointer(r, 3); 433 *r = NULL; 434 if (fl) PetscCall(PetscHMapFuncGet(fl->map, name, r)); 435 PetscFunctionReturn(PETSC_SUCCESS); 436 } 437 438 /*@ 439 PetscFunctionListView - prints out contents of a `PetscFunctionList` 440 441 Collective 442 443 Input Parameters: 444 + list - the list of functions 445 - viewer - the `PetscViewer` used to view the `PetscFunctionList` 446 447 Level: developer 448 449 .seealso: `PetscFunctionListAdd()`, `PetscFunctionListPrintTypes()`, `PetscFunctionList` 450 @*/ 451 PetscErrorCode PetscFunctionListView(PetscFunctionList list, PetscViewer viewer) 452 { 453 PetscBool iascii; 454 455 PetscFunctionBegin; 456 PetscValidPointer(list, 1); 457 if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PETSC_COMM_SELF, &viewer)); 458 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 459 460 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 461 PetscCheck(iascii, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only ASCII viewer supported"); 462 { 463 PetscInt size; 464 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; 471 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 } 481 482 /*@C 483 PetscFunctionListGet - Gets an array the contains the entries in `PetscFunctionList`, this is used 484 by help etc. 485 486 Not Collective 487 488 Input Parameter: 489 . list - list of types 490 491 Output Parameters: 492 + array - array of names 493 - n - length of `array` 494 495 Level: developer 496 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. 500 501 .seealso: `PetscFunctionListAdd()`, `PetscFunctionList` 502 @*/ 503 PetscErrorCode PetscFunctionListGet(PetscFunctionList list, const char ***array, int *n) 504 { 505 PetscInt size = 0; 506 507 PetscFunctionBegin; 508 PetscValidPointer(array, 2); 509 *array = NULL; 510 if (list) { 511 const PetscHMapFunc map = list->map; 512 PetscInt off = 0; 513 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 } 521 522 /*@C 523 PetscFunctionListPrintTypes - Prints the methods available in a list of functions 524 525 Collective over MPI_Comm 526 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 537 538 Level: developer 539 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]; 545 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)); 551 552 if (list) PetscHMapFuncForEach(list, name, func, PetscCall((*PetscHelpPrintf)(comm, " %s", name))); 553 PetscCall((*PetscHelpPrintf)(comm, " (%s)\n", man)); 554 PetscFunctionReturn(PETSC_SUCCESS); 555 } 556 557 /*@ 558 PetscFunctionListDuplicate - Creates a new list from a given function list `PetscFunctionList`. 559 560 Input Parameter: 561 . fl - pointer to list 562 563 Output Parameter: 564 . nl - the new list (should point to `NULL` to start, otherwise appends) 565 566 Level: developer 567 568 .seealso: `PetscFunctionList`, `PetscFunctionListAdd()`, `PetscFlistDestroy()` 569 @*/ 570 PetscErrorCode PetscFunctionListDuplicate(PetscFunctionList fl, PetscFunctionList *nl) 571 { 572 PetscFunctionBegin; 573 if (fl) { 574 PetscHMapFunc dup_map; 575 576 if (!*nl) { 577 PetscInt n; 578 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 } 587