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