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