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