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