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