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