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 /* 10 This is the default list used by PETSc with the PetscDLLibrary register routines 11 */ 12 PetscDLLibrary PetscDLLibrariesLoaded = 0; 13 14 #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES) 15 16 #undef __FUNCT__ 17 #define __FUNCT__ "PetscLoadDynamicLibrary" 18 static PetscErrorCode PetscLoadDynamicLibrary(const char *name,PetscBool *found) 19 { 20 char libs[PETSC_MAX_PATH_LEN],dlib[PETSC_MAX_PATH_LEN]; 21 PetscErrorCode ierr; 22 23 PetscFunctionBegin; 24 ierr = PetscStrcpy(libs,"${PETSC_LIB_DIR}/libpetsc");CHKERRQ(ierr); 25 ierr = PetscStrcat(libs,name);CHKERRQ(ierr); 26 ierr = PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,found);CHKERRQ(ierr); 27 if (*found) { 28 ierr = PetscDLLibraryAppend(PETSC_COMM_WORLD,&PetscDLLibrariesLoaded,dlib);CHKERRQ(ierr); 29 } else { 30 ierr = PetscStrcpy(libs,"${PETSC_DIR}/${PETSC_ARCH}/lib/libpetsc");CHKERRQ(ierr); 31 ierr = PetscStrcat(libs,name);CHKERRQ(ierr); 32 ierr = PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,found);CHKERRQ(ierr); 33 if (*found) { 34 ierr = PetscDLLibraryAppend(PETSC_COMM_WORLD,&PetscDLLibrariesLoaded,dlib);CHKERRQ(ierr); 35 } 36 } 37 PetscFunctionReturn(0); 38 } 39 40 #endif 41 42 #define PETSC_HAVE_THREADSAFETY 1 43 #if defined(PETSC_HAVE_THREADSAFETY) 44 static MPI_Comm PETSC_COMM_WORLD_INNER,PETSC_COMM_SELF_INNER; 45 #endif 46 47 #undef __FUNCT__ 48 #define __FUNCT__ "PetscInitialize_DynamicLibraries" 49 /* 50 PetscInitialize_DynamicLibraries - Adds the default dynamic link libraries to the 51 search path. 52 */ 53 PetscErrorCode PetscInitialize_DynamicLibraries(void) 54 { 55 char *libname[32]; 56 PetscErrorCode ierr; 57 PetscInt nmax,i; 58 #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES) 59 PetscBool preload; 60 #endif 61 62 PetscFunctionBegin; 63 nmax = 32; 64 ierr = PetscOptionsGetStringArray(NULL,"-dll_prepend",libname,&nmax,NULL);CHKERRQ(ierr); 65 for (i=0; i<nmax; i++) { 66 ierr = PetscDLLibraryPrepend(PETSC_COMM_WORLD,&PetscDLLibrariesLoaded,libname[i]);CHKERRQ(ierr); 67 ierr = PetscFree(libname[i]);CHKERRQ(ierr); 68 } 69 70 #if !defined(PETSC_HAVE_DYNAMIC_LIBRARIES) 71 /* 72 This just initializes the most basic PETSc stuff. 73 74 The classes, from PetscDraw to PetscTS, are initialized the first 75 time an XXCreate() is called. 76 */ 77 ierr = PetscSysInitializePackage();CHKERRQ(ierr); 78 #else 79 preload = PETSC_FALSE; 80 ierr = PetscOptionsGetBool(NULL,"-dynamic_library_preload",&preload,NULL);CHKERRQ(ierr); 81 if (preload) { 82 PetscBool found; 83 #if defined(PETSC_USE_SINGLE_LIBRARY) 84 ierr = PetscLoadDynamicLibrary("",&found);CHKERRQ(ierr); 85 if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc dynamic library \n You cannot move the dynamic libraries!"); 86 #else 87 ierr = PetscLoadDynamicLibrary("sys",&found);CHKERRQ(ierr); 88 if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc dynamic library \n You cannot move the dynamic libraries!"); 89 ierr = PetscLoadDynamicLibrary("vec",&found);CHKERRQ(ierr); 90 if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc Vec dynamic library \n You cannot move the dynamic libraries!"); 91 ierr = PetscLoadDynamicLibrary("mat",&found);CHKERRQ(ierr); 92 if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc Mat dynamic library \n You cannot move the dynamic libraries!"); 93 ierr = PetscLoadDynamicLibrary("dm",&found);CHKERRQ(ierr); 94 if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc DM dynamic library \n You cannot move the dynamic libraries!"); 95 ierr = PetscLoadDynamicLibrary("ksp",&found);CHKERRQ(ierr); 96 if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc KSP dynamic library \n You cannot move the dynamic libraries!"); 97 ierr = PetscLoadDynamicLibrary("snes",&found);CHKERRQ(ierr); 98 if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc SNES dynamic library \n You cannot move the dynamic libraries!"); 99 ierr = PetscLoadDynamicLibrary("ts",&found);CHKERRQ(ierr); 100 if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc TS dynamic library \n You cannot move the dynamic libraries!"); 101 #endif 102 } 103 #endif 104 105 nmax = 32; 106 ierr = PetscOptionsGetStringArray(NULL,"-dll_append",libname,&nmax,NULL);CHKERRQ(ierr); 107 for (i=0; i<nmax; i++) { 108 ierr = PetscDLLibraryAppend(PETSC_COMM_WORLD,&PetscDLLibrariesLoaded,libname[i]);CHKERRQ(ierr); 109 ierr = PetscFree(libname[i]);CHKERRQ(ierr); 110 } 111 112 #if defined(PETSC_HAVE_THREADSAFETY) 113 ierr = PetscThreadCommInitializePackage();CHKERRQ(ierr); 114 ierr = PetscThreadCommWorldInitialize();CHKERRQ(ierr); 115 ierr = AOInitializePackage();CHKERRQ(ierr); 116 ierr = PetscSFInitializePackage();CHKERRQ(ierr); 117 ierr = CharacteristicInitializePackage();CHKERRQ(ierr); 118 ierr = ISInitializePackage();CHKERRQ(ierr); 119 ierr = VecInitializePackage();CHKERRQ(ierr); 120 ierr = MatInitializePackage();CHKERRQ(ierr); 121 ierr = DMInitializePackage();CHKERRQ(ierr); 122 ierr = PCInitializePackage();CHKERRQ(ierr); 123 ierr = KSPInitializePackage();CHKERRQ(ierr); 124 ierr = SNESInitializePackage();CHKERRQ(ierr); 125 ierr = TSInitializePackage();CHKERRQ(ierr); 126 ierr = PetscCommDuplicate(PETSC_COMM_SELF,&PETSC_COMM_SELF_INNER,NULL);CHKERRQ(ierr); 127 ierr = PetscCommDuplicate(PETSC_COMM_WORLD,&PETSC_COMM_WORLD_INNER,NULL);CHKERRQ(ierr); 128 #endif 129 PetscFunctionReturn(0); 130 } 131 132 #undef __FUNCT__ 133 #define __FUNCT__ "PetscFinalize_DynamicLibraries" 134 /* 135 PetscFinalize_DynamicLibraries - Closes the opened dynamic libraries. 136 */ 137 PetscErrorCode PetscFinalize_DynamicLibraries(void) 138 { 139 PetscErrorCode ierr; 140 PetscBool flg = PETSC_FALSE; 141 142 PetscFunctionBegin; 143 ierr = PetscOptionsGetBool(NULL,"-dll_view",&flg,NULL);CHKERRQ(ierr); 144 if (flg) { ierr = PetscDLLibraryPrintPath(PetscDLLibrariesLoaded);CHKERRQ(ierr); } 145 ierr = PetscDLLibraryClose(PetscDLLibrariesLoaded);CHKERRQ(ierr); 146 147 #if defined(PETSC_HAVE_THREADSAFETY) 148 ierr = PetscCommDestroy(&PETSC_COMM_SELF_INNER);CHKERRQ(ierr); 149 ierr = PetscCommDestroy(&PETSC_COMM_WORLD_INNER);CHKERRQ(ierr); 150 #endif 151 152 PetscDLLibrariesLoaded = 0; 153 PetscFunctionReturn(0); 154 } 155 156 157 158 /* ------------------------------------------------------------------------------*/ 159 struct _n_PetscFunctionList { 160 void (*routine)(void); /* the routine */ 161 char *name; /* string to identify routine */ 162 PetscFunctionList next; /* next pointer */ 163 PetscFunctionList next_list; /* used to maintain list of all lists for freeing */ 164 }; 165 166 /* 167 Keep a linked list of PetscFunctionLists so that we can destroy all the left-over ones. 168 */ 169 static PetscFunctionList dlallhead = 0; 170 171 /*MC 172 PetscFunctionListAdd - Given a routine and a string id, saves that routine in the 173 specified registry. 174 175 Synopsis: 176 #include <petscsys.h> 177 PetscErrorCode PetscFunctionListAdd(PetscFunctionList flist,const char name[],void (*fptr)(void)) 178 179 Not Collective 180 181 Input Parameters: 182 + flist - pointer registry 183 . name - string to identify routine 184 - fptr - function pointer 185 186 Notes: 187 To remove a registered routine, pass in a NULL fptr. 188 189 Users who wish to register new classes for use by a particular PETSc 190 component (e.g., SNES) should generally call the registration routine 191 for that particular component (e.g., SNESRegister()) instead of 192 calling PetscFunctionListAdd() directly. 193 194 Level: developer 195 196 .seealso: PetscFunctionListDestroy(), SNESRegister(), KSPRegister(), 197 PCRegister(), TSRegister(), PetscFunctionList, PetscObjectComposeFunction() 198 M*/ 199 #undef __FUNCT__ 200 #define __FUNCT__ "PetscFunctionListAdd_Private" 201 PETSC_EXTERN PetscErrorCode PetscFunctionListAdd_Private(PetscFunctionList *fl,const char name[],void (*fnc)(void)) 202 { 203 PetscFunctionList entry,ne; 204 PetscErrorCode ierr; 205 206 PetscFunctionBegin; 207 if (!*fl) { 208 ierr = PetscNew(&entry);CHKERRQ(ierr); 209 ierr = PetscStrallocpy(name,&entry->name);CHKERRQ(ierr); 210 entry->routine = fnc; 211 entry->next = 0; 212 *fl = entry; 213 214 #if defined(PETSC_USE_LOG) 215 /* add this new list to list of all lists */ 216 if (!dlallhead) { 217 dlallhead = *fl; 218 (*fl)->next_list = 0; 219 } else { 220 ne = dlallhead; 221 dlallhead = *fl; 222 (*fl)->next_list = ne; 223 } 224 #endif 225 226 } else { 227 /* search list to see if it is already there */ 228 ne = *fl; 229 while (ne) { 230 PetscBool founddup; 231 232 ierr = PetscStrcmp(ne->name,name,&founddup);CHKERRQ(ierr); 233 if (founddup) { /* found duplicate */ 234 ne->routine = fnc; 235 PetscFunctionReturn(0); 236 } 237 if (ne->next) ne = ne->next; 238 else break; 239 } 240 /* create new entry and add to end of list */ 241 ierr = PetscNew(&entry);CHKERRQ(ierr); 242 ierr = PetscStrallocpy(name,&entry->name);CHKERRQ(ierr); 243 entry->routine = fnc; 244 entry->next = 0; 245 ne->next = entry; 246 } 247 PetscFunctionReturn(0); 248 } 249 250 #undef __FUNCT__ 251 #define __FUNCT__ "PetscFunctionListDestroy" 252 /*@ 253 PetscFunctionListDestroy - Destroys a list of registered routines. 254 255 Input Parameter: 256 . fl - pointer to list 257 258 Level: developer 259 260 .seealso: PetscFunctionListAdd(), PetscFunctionList 261 @*/ 262 PetscErrorCode PetscFunctionListDestroy(PetscFunctionList *fl) 263 { 264 PetscFunctionList next,entry,tmp = dlallhead; 265 PetscErrorCode ierr; 266 267 PetscFunctionBegin; 268 if (!*fl) PetscFunctionReturn(0); 269 270 /* 271 Remove this entry from the master DL list (if it is in it) 272 */ 273 if (dlallhead == *fl) { 274 if (dlallhead->next_list) dlallhead = dlallhead->next_list; 275 else dlallhead = NULL; 276 } else if (tmp) { 277 while (tmp->next_list != *fl) { 278 tmp = tmp->next_list; 279 if (!tmp->next_list) break; 280 } 281 if (tmp->next_list) tmp->next_list = tmp->next_list->next_list; 282 } 283 284 /* free this list */ 285 entry = *fl; 286 while (entry) { 287 next = entry->next; 288 ierr = PetscFree(entry->name);CHKERRQ(ierr); 289 ierr = PetscFree(entry);CHKERRQ(ierr); 290 entry = next; 291 } 292 *fl = 0; 293 PetscFunctionReturn(0); 294 } 295 296 /* 297 Print any PetscFunctionLists that have not be destroyed 298 */ 299 #undef __FUNCT__ 300 #define __FUNCT__ "PetscFunctionListPrintAll" 301 PetscErrorCode PetscFunctionListPrintAll(void) 302 { 303 PetscFunctionList tmp = dlallhead; 304 PetscErrorCode ierr; 305 306 PetscFunctionBegin; 307 if (tmp) { 308 ierr = PetscPrintf(PETSC_COMM_WORLD,"The following PetscFunctionLists were not destroyed\n");CHKERRQ(ierr); 309 } 310 while (tmp) { 311 ierr = PetscPrintf(PETSC_COMM_WORLD,"%s \n",tmp->name);CHKERRQ(ierr); 312 tmp = tmp->next_list; 313 } 314 PetscFunctionReturn(0); 315 } 316 317 /*MC 318 PetscFunctionListFind - Find function registered under given name 319 320 Synopsis: 321 #include <petscsys.h> 322 PetscErrorCode PetscFunctionListFind(PetscFunctionList flist,const char name[],void (**fptr)(void)) 323 324 Input Parameters: 325 + flist - pointer to list 326 - name - name registered for the function 327 328 Output Parameters: 329 . fptr - the function pointer if name was found, else NULL 330 331 Level: developer 332 333 .seealso: PetscFunctionListAdd(), PetscFunctionList, PetscObjectQueryFunction() 334 M*/ 335 #undef __FUNCT__ 336 #define __FUNCT__ "PetscFunctionListFind_Private" 337 PETSC_EXTERN PetscErrorCode PetscFunctionListFind_Private(PetscFunctionList fl,const char name[],void (**r)(void)) 338 { 339 PetscFunctionList entry = fl; 340 PetscErrorCode ierr; 341 PetscBool flg; 342 343 PetscFunctionBegin; 344 if (!name) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Trying to find routine with null name"); 345 346 *r = 0; 347 while (entry) { 348 ierr = PetscStrcmp(name,entry->name,&flg);CHKERRQ(ierr); 349 if (flg) { 350 *r = entry->routine; 351 PetscFunctionReturn(0); 352 } 353 entry = entry->next; 354 } 355 PetscFunctionReturn(0); 356 } 357 358 #undef __FUNCT__ 359 #define __FUNCT__ "PetscFunctionListView" 360 /*@ 361 PetscFunctionListView - prints out contents of an PetscFunctionList 362 363 Collective over MPI_Comm 364 365 Input Parameters: 366 + list - the list of functions 367 - viewer - currently ignored 368 369 Level: developer 370 371 .seealso: PetscFunctionListAdd(), PetscFunctionListPrintTypes(), PetscFunctionList 372 @*/ 373 PetscErrorCode PetscFunctionListView(PetscFunctionList list,PetscViewer viewer) 374 { 375 PetscErrorCode ierr; 376 PetscBool iascii; 377 378 PetscFunctionBegin; 379 if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF; 380 PetscValidPointer(list,1); 381 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 382 383 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 384 if (!iascii) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only ASCII viewer supported"); 385 386 while (list) { 387 ierr = PetscViewerASCIIPrintf(viewer," %s\n",list->name);CHKERRQ(ierr); 388 list = list->next; 389 } 390 ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr); 391 PetscFunctionReturn(0); 392 } 393 394 #undef __FUNCT__ 395 #define __FUNCT__ "PetscFunctionListGet" 396 /*@C 397 PetscFunctionListGet - Gets an array the contains the entries in PetscFunctionList, this is used 398 by help etc. 399 400 Not Collective 401 402 Input Parameter: 403 . list - list of types 404 405 Output Parameter: 406 + array - array of names 407 - n - length of array 408 409 Notes: 410 This allocates the array so that must be freed. BUT the individual entries are 411 not copied so should not be freed. 412 413 Level: developer 414 415 .seealso: PetscFunctionListAdd(), PetscFunctionList 416 @*/ 417 PetscErrorCode PetscFunctionListGet(PetscFunctionList list,const char ***array,int *n) 418 { 419 PetscErrorCode ierr; 420 PetscInt count = 0; 421 PetscFunctionList klist = list; 422 423 PetscFunctionBegin; 424 while (list) { 425 list = list->next; 426 count++; 427 } 428 ierr = PetscMalloc1(count+1,array);CHKERRQ(ierr); 429 count = 0; 430 while (klist) { 431 (*array)[count] = klist->name; 432 klist = klist->next; 433 count++; 434 } 435 (*array)[count] = 0; 436 *n = count+1; 437 PetscFunctionReturn(0); 438 } 439 440 441 #undef __FUNCT__ 442 #define __FUNCT__ "PetscFunctionListPrintTypes" 443 /*@C 444 PetscFunctionListPrintTypes - Prints the methods available. 445 446 Collective over MPI_Comm 447 448 Input Parameters: 449 + comm - the communicator (usually MPI_COMM_WORLD) 450 . fd - file to print to, usually stdout 451 . prefix - prefix to prepend to name (optional) 452 . name - option string (for example, "-ksp_type") 453 . text - short description of the object (for example, "Krylov solvers") 454 . man - name of manual page that discusses the object (for example, "KSPCreate") 455 . list - list of types 456 - def - default (current) value 457 458 Level: developer 459 460 .seealso: PetscFunctionListAdd(), PetscFunctionList 461 @*/ 462 PetscErrorCode PetscFunctionListPrintTypes(MPI_Comm comm,FILE *fd,const char prefix[],const char name[],const char text[],const char man[],PetscFunctionList list,const char def[]) 463 { 464 PetscErrorCode ierr; 465 PetscInt count = 0; 466 char p[64]; 467 468 PetscFunctionBegin; 469 if (!fd) fd = PETSC_STDOUT; 470 471 ierr = PetscStrcpy(p,"-");CHKERRQ(ierr); 472 if (prefix) {ierr = PetscStrcat(p,prefix);CHKERRQ(ierr);} 473 ierr = PetscFPrintf(comm,fd," %s%s <%s>: %s (one of)",p,name+1,def,text);CHKERRQ(ierr); 474 475 while (list) { 476 ierr = PetscFPrintf(comm,fd," %s",list->name);CHKERRQ(ierr); 477 list = list->next; 478 count++; 479 if (count == 8) {ierr = PetscFPrintf(comm,fd,"\n ");CHKERRQ(ierr);} 480 } 481 ierr = PetscFPrintf(comm,fd," (%s)\n",man);CHKERRQ(ierr); 482 PetscFunctionReturn(0); 483 } 484 485 #undef __FUNCT__ 486 #define __FUNCT__ "PetscFunctionListDuplicate" 487 /*@ 488 PetscFunctionListDuplicate - Creates a new list from a given object list. 489 490 Input Parameters: 491 . fl - pointer to list 492 493 Output Parameters: 494 . nl - the new list (should point to 0 to start, otherwise appends) 495 496 Level: developer 497 498 .seealso: PetscFunctionList, PetscFunctionListAdd(), PetscFlistDestroy() 499 500 @*/ 501 PetscErrorCode PetscFunctionListDuplicate(PetscFunctionList fl,PetscFunctionList *nl) 502 { 503 PetscErrorCode ierr; 504 505 PetscFunctionBegin; 506 while (fl) { 507 ierr = PetscFunctionListAdd(nl,fl->name,fl->routine);CHKERRQ(ierr); 508 fl = fl->next; 509 } 510 PetscFunctionReturn(0); 511 } 512 513