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 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 } 302 303 /*@C 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 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) 343 344 /*@C 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 /*@C 386 PetscFunctionListPrintNonEmpty - Print composed names for non `NULL` function pointers 387 388 Logically Collective, No Fortran Support 389 390 Input Parameter: 391 . fl - the function list 392 393 Level: developer 394 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 } 411 412 /*MC 413 PetscFunctionListFind - Find function registered under given name 414 415 Not Collective, No Fortran Support 416 417 Synopsis: 418 #include <petscsys.h> 419 PetscErrorCode PetscFunctionListFind(PetscFunctionList flist,const char name[],void (**fptr)(void)) 420 421 Input Parameters: 422 + fl - the function list 423 - name - name registered for the function 424 425 Output Parameter: 426 . fptr - the function pointer if name was found, else `NULL` 427 428 Level: developer 429 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 } 441 442 /*@C 443 PetscFunctionListView - prints out contents of a `PetscFunctionList` 444 445 Collective 446 447 Input Parameters: 448 + list - the list of functions 449 - viewer - the `PetscViewer` used to view the `PetscFunctionList` 450 451 Level: developer 452 453 .seealso: `PetscFunctionListAdd()`, `PetscFunctionListPrintTypes()`, `PetscFunctionList` 454 @*/ 455 PetscErrorCode PetscFunctionListView(PetscFunctionList list, PetscViewer viewer) 456 { 457 PetscBool iascii; 458 459 PetscFunctionBegin; 460 PetscAssertPointer(list, 1); 461 if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PETSC_COMM_SELF, &viewer)); 462 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 463 464 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 465 PetscCheck(iascii, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only ASCII viewer supported"); 466 { 467 PetscInt size; 468 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; 475 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 } 485 486 /*@C 487 PetscFunctionListGet - Gets an array the contains the entries in `PetscFunctionList`, this is used 488 by help etc. 489 490 Not Collective, No Fortran Support 491 492 Input Parameter: 493 . list - list of types 494 495 Output Parameters: 496 + array - array of names 497 - n - length of `array` 498 499 Level: developer 500 501 Note: 502 This allocates the array so that must be freed with `PetscFree()`. BUT the individual entries should not be freed. 503 504 .seealso: `PetscFunctionListAdd()`, `PetscFunctionList` 505 @*/ 506 PetscErrorCode PetscFunctionListGet(PetscFunctionList list, const char ***array, int *n) 507 { 508 PetscInt size = 0; 509 510 PetscFunctionBegin; 511 PetscAssertPointer(array, 2); 512 *array = NULL; 513 if (list) { 514 const PetscHMapFunc map = list->map; 515 PetscInt off = 0; 516 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 } 524 525 /*@C 526 PetscFunctionListPrintTypes - Prints the methods available in a list of functions 527 528 Collective, No Fortran Support 529 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 540 541 Level: developer 542 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]; 548 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)); 554 555 if (list) PetscHMapFuncForEach(list, name, func, PetscCall((*PetscHelpPrintf)(comm, " %s", name))); 556 PetscCall((*PetscHelpPrintf)(comm, " (%s)\n", man)); 557 PetscFunctionReturn(PETSC_SUCCESS); 558 } 559 560 /*@C 561 PetscFunctionListDuplicate - Creates a new list from a given function list `PetscFunctionList`. 562 563 Input Parameter: 564 . fl - pointer to list 565 566 Output Parameter: 567 . nl - the new list (should point to `NULL` to start, otherwise appends) 568 569 Level: developer 570 571 .seealso: `PetscFunctionList`, `PetscFunctionListAdd()`, `PetscFlistDestroy()` 572 @*/ 573 PetscErrorCode PetscFunctionListDuplicate(PetscFunctionList fl, PetscFunctionList *nl) 574 { 575 PetscFunctionBegin; 576 if (fl) { 577 PetscHMapFunc dup_map; 578 579 if (!*nl) { 580 PetscInt n; 581 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 } 590