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