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