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