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