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 #undef __FUNCT__ 10 #define __FUNCT__ "PetscFunctionListGetPathAndFunction" 11 PetscErrorCode PetscFunctionListGetPathAndFunction(const char name[],char *path[],char *function[]) 12 { 13 PetscErrorCode ierr; 14 char work[PETSC_MAX_PATH_LEN],*lfunction; 15 16 PetscFunctionBegin; 17 ierr = PetscStrncpy(work,name,sizeof(work));CHKERRQ(ierr); 18 19 work[sizeof(work) - 1] = 0; 20 21 ierr = PetscStrchr(work,':',&lfunction);CHKERRQ(ierr); 22 if (lfunction != work && lfunction && lfunction[1] != ':') { 23 lfunction[0] = 0; 24 25 ierr = PetscStrallocpy(work,path);CHKERRQ(ierr); 26 ierr = PetscStrallocpy(lfunction+1,function);CHKERRQ(ierr); 27 } else { 28 *path = 0; 29 ierr = PetscStrallocpy(name,function);CHKERRQ(ierr); 30 } 31 PetscFunctionReturn(0); 32 } 33 34 /* 35 This is the default list used by PETSc with the PetscDLLibrary register routines 36 */ 37 PetscDLLibrary PetscDLLibrariesLoaded = 0; 38 39 #if defined(PETSC_USE_DYNAMIC_LIBRARIES) 40 41 #undef __FUNCT__ 42 #define __FUNCT__ "PetscLoadDynamicLibrary" 43 static PetscErrorCode PetscLoadDynamicLibrary(const char *name,PetscBool *found) 44 { 45 char libs[PETSC_MAX_PATH_LEN],dlib[PETSC_MAX_PATH_LEN]; 46 PetscErrorCode ierr; 47 48 PetscFunctionBegin; 49 ierr = PetscStrcpy(libs,"${PETSC_LIB_DIR}/libpetsc");CHKERRQ(ierr); 50 ierr = PetscStrcat(libs,name);CHKERRQ(ierr); 51 ierr = PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,found);CHKERRQ(ierr); 52 if (*found) { 53 ierr = PetscDLLibraryAppend(PETSC_COMM_WORLD,&PetscDLLibrariesLoaded,dlib);CHKERRQ(ierr); 54 } else { 55 ierr = PetscStrcpy(libs,"${PETSC_DIR}/${PETSC_ARCH}/lib/libpetsc");CHKERRQ(ierr); 56 ierr = PetscStrcat(libs,name);CHKERRQ(ierr); 57 ierr = PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,1024,found);CHKERRQ(ierr); 58 if (*found) { 59 ierr = PetscDLLibraryAppend(PETSC_COMM_WORLD,&PetscDLLibrariesLoaded,dlib);CHKERRQ(ierr); 60 } 61 } 62 PetscFunctionReturn(0); 63 } 64 65 #endif 66 67 #undef __FUNCT__ 68 #define __FUNCT__ "PetscInitialize_DynamicLibraries" 69 /* 70 PetscInitialize_DynamicLibraries - Adds the default dynamic link libraries to the 71 search path. 72 */ 73 PetscErrorCode PetscInitialize_DynamicLibraries(void) 74 { 75 char *libname[32]; 76 PetscErrorCode ierr; 77 PetscInt nmax,i; 78 #if defined(PETSC_USE_DYNAMIC_LIBRARIES) 79 PetscBool found; 80 #endif 81 82 PetscFunctionBegin; 83 nmax = 32; 84 ierr = PetscOptionsGetStringArray(NULL,"-dll_prepend",libname,&nmax,NULL);CHKERRQ(ierr); 85 for (i=0; i<nmax; i++) { 86 ierr = PetscDLLibraryPrepend(PETSC_COMM_WORLD,&PetscDLLibrariesLoaded,libname[i]);CHKERRQ(ierr); 87 ierr = PetscFree(libname[i]);CHKERRQ(ierr); 88 } 89 90 #if !defined(PETSC_USE_DYNAMIC_LIBRARIES) 91 /* 92 This just initializes the most basic PETSc stuff. 93 94 The classes, from PetscDraw to PetscTS, are initialized the first 95 time an XXCreate() is called. 96 */ 97 ierr = PetscSysInitializePackage(NULL);CHKERRQ(ierr); 98 #else 99 #if defined(PETSC_USE_SINGLE_LIBRARY) 100 ierr = PetscLoadDynamicLibrary("",&found);CHKERRQ(ierr); 101 if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc dynamic library \n You cannot move the dynamic libraries!"); 102 #else 103 ierr = PetscLoadDynamicLibrary("sys",&found);CHKERRQ(ierr); 104 if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc dynamic library \n You cannot move the dynamic libraries!"); 105 ierr = PetscLoadDynamicLibrary("vec",&found);CHKERRQ(ierr); 106 if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc Vec dynamic library \n You cannot move the dynamic libraries!"); 107 ierr = PetscLoadDynamicLibrary("mat",&found);CHKERRQ(ierr); 108 if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc Mat dynamic library \n You cannot move the dynamic libraries!"); 109 ierr = PetscLoadDynamicLibrary("dm",&found);CHKERRQ(ierr); 110 if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc DM dynamic library \n You cannot move the dynamic libraries!"); 111 ierr = PetscLoadDynamicLibrary("characteristic",&found);CHKERRQ(ierr); 112 if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc Characteristic dynamic library \n You cannot move the dynamic libraries!"); 113 ierr = PetscLoadDynamicLibrary("ksp",&found);CHKERRQ(ierr); 114 if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc KSP dynamic library \n You cannot move the dynamic libraries!"); 115 ierr = PetscLoadDynamicLibrary("snes",&found);CHKERRQ(ierr); 116 if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc SNES dynamic library \n You cannot move the dynamic libraries!"); 117 ierr = PetscLoadDynamicLibrary("ts",&found);CHKERRQ(ierr); 118 if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate PETSc TS dynamic library \n You cannot move the dynamic libraries!"); 119 #endif 120 121 ierr = PetscLoadDynamicLibrary("mesh",&found);CHKERRQ(ierr); 122 ierr = PetscLoadDynamicLibrary("contrib",&found);CHKERRQ(ierr); 123 #endif 124 125 nmax = 32; 126 ierr = PetscOptionsGetStringArray(NULL,"-dll_append",libname,&nmax,NULL);CHKERRQ(ierr); 127 for (i=0; i<nmax; i++) { 128 ierr = PetscDLLibraryAppend(PETSC_COMM_WORLD,&PetscDLLibrariesLoaded,libname[i]);CHKERRQ(ierr); 129 ierr = PetscFree(libname[i]);CHKERRQ(ierr); 130 } 131 PetscFunctionReturn(0); 132 } 133 134 #undef __FUNCT__ 135 #define __FUNCT__ "PetscFinalize_DynamicLibraries" 136 /* 137 PetscFinalize_DynamicLibraries - Closes the opened dynamic libraries. 138 */ 139 PetscErrorCode PetscFinalize_DynamicLibraries(void) 140 { 141 PetscErrorCode ierr; 142 PetscBool flg = PETSC_FALSE; 143 144 PetscFunctionBegin; 145 ierr = PetscOptionsGetBool(NULL,"-dll_view",&flg,NULL);CHKERRQ(ierr); 146 if (flg) { ierr = PetscDLLibraryPrintPath(PetscDLLibrariesLoaded);CHKERRQ(ierr); } 147 ierr = PetscDLLibraryClose(PetscDLLibrariesLoaded);CHKERRQ(ierr); 148 149 PetscDLLibrariesLoaded = 0; 150 PetscFunctionReturn(0); 151 } 152 153 154 155 /* ------------------------------------------------------------------------------*/ 156 struct _n_PetscFunctionList { 157 void (*routine)(void); /* the routine */ 158 char *path; /* path of link library containing routine */ 159 char *name; /* string to identify routine */ 160 char *rname; /* routine name in dynamic library */ 161 PetscFunctionList next; /* next pointer */ 162 PetscFunctionList next_list; /* used to maintain list of all lists for freeing */ 163 }; 164 165 /* 166 Keep a linked list of PetscFunctionLists so that we can destroy all the left-over ones. 167 */ 168 static PetscFunctionList dlallhead = 0; 169 170 #undef __FUNCT__ 171 #define __FUNCT__ "PetscFunctionListAdd" 172 /*@C 173 PetscFunctionListAdd - Given a routine and a string id, saves that routine in the 174 specified registry. 175 176 Formally Collective on MPI_Comm 177 178 Input Parameters: 179 + comm - the comm where this exists (currently not used) 180 . fl - pointer registry 181 . name - string to identify routine 182 . rname - routine name in dynamic library 183 - fnc - function pointer (optional if using dynamic libraries) 184 185 Notes: 186 To remove a registered routine, pass in a NULL rname and fnc(). 187 188 Users who wish to register new classes for use by a particular PETSc 189 component (e.g., SNES) should generally call the registration routine 190 for that particular component (e.g., SNESRegisterDynamic()) instead of 191 calling PetscFunctionListAdd() directly. 192 193 ${PETSC_ARCH}, ${PETSC_DIR}, ${PETSC_LIB_DIR}, or ${any environmental variable} 194 occuring in pathname will be replaced with appropriate values. 195 196 Level: developer 197 198 .seealso: PetscFunctionListDestroy(), SNESRegisterDynamic(), KSPRegisterDynamic(), 199 PCRegisterDynamic(), TSRegisterDynamic(), PetscFunctionList 200 @*/ 201 PetscErrorCode PetscFunctionListAdd(MPI_Comm comm,PetscFunctionList *fl,const char name[],const char rname[],void (*fnc)(void)) 202 { 203 PetscFunctionList entry,ne; 204 PetscErrorCode ierr; 205 char *fpath,*fname; 206 207 PetscFunctionBegin; 208 if (!*fl) { 209 ierr = PetscNew(struct _n_PetscFunctionList,&entry);CHKERRQ(ierr); 210 ierr = PetscStrallocpy(name,&entry->name);CHKERRQ(ierr); 211 ierr = PetscFunctionListGetPathAndFunction(rname,&fpath,&fname);CHKERRQ(ierr); 212 entry->path = fpath; 213 entry->rname = fname; 214 entry->routine = fnc; 215 entry->next = 0; 216 *fl = entry; 217 218 /* add this new list to list of all lists */ 219 if (!dlallhead) { 220 dlallhead = *fl; 221 (*fl)->next_list = 0; 222 } else { 223 ne = dlallhead; 224 dlallhead = *fl; 225 (*fl)->next_list = ne; 226 } 227 } else { 228 /* search list to see if it is already there */ 229 ne = *fl; 230 while (ne) { 231 PetscBool founddup; 232 233 ierr = PetscStrcmp(ne->name,name,&founddup);CHKERRQ(ierr); 234 if (founddup) { /* found duplicate */ 235 ierr = PetscFunctionListGetPathAndFunction(rname,&fpath,&fname);CHKERRQ(ierr); 236 ierr = PetscFree(ne->path);CHKERRQ(ierr); 237 ierr = PetscFree(ne->rname);CHKERRQ(ierr); 238 239 ne->path = fpath; 240 ne->rname = fname; 241 ne->routine = fnc; 242 PetscFunctionReturn(0); 243 } 244 if (ne->next) ne = ne->next; 245 else break; 246 } 247 /* create new entry and add to end of list */ 248 ierr = PetscNew(struct _n_PetscFunctionList,&entry);CHKERRQ(ierr); 249 ierr = PetscStrallocpy(name,&entry->name);CHKERRQ(ierr); 250 ierr = PetscFunctionListGetPathAndFunction(rname,&fpath,&fname);CHKERRQ(ierr); 251 entry->path = fpath; 252 entry->rname = fname; 253 entry->routine = fnc; 254 entry->next = 0; 255 ne->next = entry; 256 } 257 PetscFunctionReturn(0); 258 } 259 260 #undef __FUNCT__ 261 #define __FUNCT__ "PetscFunctionListDestroy" 262 /*@ 263 PetscFunctionListDestroy - Destroys a list of registered routines. 264 265 Input Parameter: 266 . fl - pointer to list 267 268 Level: developer 269 270 .seealso: PetscFunctionListAddDynamic(), PetscFunctionList 271 @*/ 272 PetscErrorCode PetscFunctionListDestroy(PetscFunctionList *fl) 273 { 274 PetscFunctionList next,entry,tmp = dlallhead; 275 PetscErrorCode ierr; 276 277 PetscFunctionBegin; 278 if (!*fl) PetscFunctionReturn(0); 279 if (!dlallhead) PetscFunctionReturn(0); 280 281 /* 282 Remove this entry from the master DL list (if it is in it) 283 */ 284 if (dlallhead == *fl) { 285 if (dlallhead->next_list) dlallhead = dlallhead->next_list; 286 else dlallhead = 0; 287 } else { 288 while (tmp->next_list != *fl) { 289 tmp = tmp->next_list; 290 if (!tmp->next_list) break; 291 } 292 if (tmp->next_list) tmp->next_list = tmp->next_list->next_list; 293 } 294 295 /* free this list */ 296 entry = *fl; 297 while (entry) { 298 next = entry->next; 299 ierr = PetscFree(entry->path);CHKERRQ(ierr); 300 ierr = PetscFree(entry->name);CHKERRQ(ierr); 301 ierr = PetscFree(entry->rname);CHKERRQ(ierr); 302 ierr = PetscFree(entry);CHKERRQ(ierr); 303 entry = next; 304 } 305 *fl = 0; 306 PetscFunctionReturn(0); 307 } 308 309 /* 310 Destroys all the function lists that anyone has every registered, such as KSPList, VecList, etc. 311 */ 312 #undef __FUNCT__ 313 #define __FUNCT__ "PetscFunctionListDestroyAll" 314 PetscErrorCode PetscFunctionListDestroyAll(void) 315 { 316 PetscFunctionList tmp2,tmp1 = dlallhead; 317 PetscErrorCode ierr; 318 319 PetscFunctionBegin; 320 while (tmp1) { 321 tmp2 = tmp1->next_list; 322 ierr = PetscFunctionListDestroy(&tmp1);CHKERRQ(ierr); 323 tmp1 = tmp2; 324 } 325 dlallhead = 0; 326 PetscFunctionReturn(0); 327 } 328 329 #undef __FUNCT__ 330 #define __FUNCT__ "PetscFunctionListFind" 331 /*@C 332 PetscFunctionListFind - Given a name, finds the matching routine. 333 334 Input Parameters: 335 + fl - pointer to list 336 . comm - processors looking for routine 337 . name - name string 338 - searchlibraries - if not found in the list then search the dynamic libraries and executable for the symbol 339 340 Output Parameters: 341 . r - the routine 342 343 Level: developer 344 345 .seealso: PetscFunctionListAddDynamic(), PetscFunctionList 346 @*/ 347 PetscErrorCode PetscFunctionListFind(MPI_Comm comm,PetscFunctionList fl,const char name[],PetscBool searchlibraries,void (**r)(void)) 348 { 349 PetscFunctionList entry = fl; 350 PetscErrorCode ierr; 351 char *function,*path; 352 PetscBool flg,f1,f2,f3; 353 #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES) 354 char *newpath; 355 #endif 356 357 PetscFunctionBegin; 358 if (!name) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Trying to find routine with null name"); 359 360 *r = 0; 361 ierr = PetscFunctionListGetPathAndFunction(name,&path,&function);CHKERRQ(ierr); 362 363 /* 364 If path then append it to search libraries 365 */ 366 #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES) 367 if (path) { 368 ierr = PetscDLLibraryAppend(comm,&PetscDLLibrariesLoaded,path);CHKERRQ(ierr); 369 } 370 #endif 371 372 while (entry) { 373 flg = PETSC_FALSE; 374 if (path && entry->path) { 375 ierr = PetscStrcmp(path,entry->path,&f1);CHKERRQ(ierr); 376 ierr = PetscStrcmp(function,entry->rname,&f2);CHKERRQ(ierr); 377 ierr = PetscStrcmp(function,entry->name,&f3);CHKERRQ(ierr); 378 flg = (PetscBool) ((f1 && f2) || (f1 && f3)); 379 } else if (!path) { 380 ierr = PetscStrcmp(function,entry->name,&f1);CHKERRQ(ierr); 381 ierr = PetscStrcmp(function,entry->rname,&f2);CHKERRQ(ierr); 382 flg = (PetscBool) (f1 || f2); 383 } else { 384 ierr = PetscStrcmp(function,entry->name,&flg);CHKERRQ(ierr); 385 if (flg) { 386 ierr = PetscFree(function);CHKERRQ(ierr); 387 ierr = PetscStrallocpy(entry->rname,&function);CHKERRQ(ierr); 388 } else { 389 ierr = PetscStrcmp(function,entry->rname,&flg);CHKERRQ(ierr); 390 } 391 } 392 393 if (flg) { 394 if (entry->routine) { 395 *r = entry->routine; 396 ierr = PetscFree(path);CHKERRQ(ierr); 397 ierr = PetscFree(function);CHKERRQ(ierr); 398 PetscFunctionReturn(0); 399 } 400 if (!(entry->rname && entry->rname[0])) { /* The entry has been cleared */ 401 ierr = PetscFree(function);CHKERRQ(ierr); 402 PetscFunctionReturn(0); 403 } 404 if ((path && entry->path && f3) || (!path && f1)) { /* convert name of function (alias) to actual function name */ 405 ierr = PetscFree(function);CHKERRQ(ierr); 406 ierr = PetscStrallocpy(entry->rname,&function);CHKERRQ(ierr); 407 } 408 409 /* it is not yet in memory so load from dynamic library */ 410 #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES) 411 newpath = path; 412 if (!path) newpath = entry->path; 413 ierr = PetscDLLibrarySym(comm,&PetscDLLibrariesLoaded,newpath,entry->rname,(void**)r);CHKERRQ(ierr); 414 if (*r) { 415 entry->routine = *r; 416 417 ierr = PetscFree(path);CHKERRQ(ierr); 418 ierr = PetscFree(function);CHKERRQ(ierr); 419 PetscFunctionReturn(0); 420 } 421 #endif 422 } 423 entry = entry->next; 424 } 425 426 #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES) 427 if (searchlibraries) { 428 /* Function never registered; try for it anyway */ 429 ierr = PetscDLLibrarySym(comm,&PetscDLLibrariesLoaded,path,function,(void**)r);CHKERRQ(ierr); 430 ierr = PetscFree(path);CHKERRQ(ierr); 431 if (*r) { 432 ierr = PetscFunctionListAdd(comm,&fl,name,name,*r);CHKERRQ(ierr); 433 } 434 } 435 #endif 436 ierr = PetscFree(function);CHKERRQ(ierr); 437 PetscFunctionReturn(0); 438 } 439 440 #undef __FUNCT__ 441 #define __FUNCT__ "PetscFunctionListView" 442 /*@ 443 PetscFunctionListView - prints out contents of an PetscFunctionList 444 445 Collective over MPI_Comm 446 447 Input Parameters: 448 + list - the list of functions 449 - viewer - currently ignored 450 451 Level: developer 452 453 .seealso: PetscFunctionListAddDynamic(), PetscFunctionListPrintTypes(), PetscFunctionList 454 @*/ 455 PetscErrorCode PetscFunctionListView(PetscFunctionList list,PetscViewer viewer) 456 { 457 PetscErrorCode ierr; 458 PetscBool iascii; 459 460 PetscFunctionBegin; 461 if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF; 462 PetscValidPointer(list,1); 463 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 464 465 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 466 if (!iascii) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only ASCII viewer supported"); 467 468 while (list) { 469 if (list->path) { 470 ierr = PetscViewerASCIIPrintf(viewer," %s %s %s\n",list->path,list->name,list->rname);CHKERRQ(ierr); 471 } else { 472 ierr = PetscViewerASCIIPrintf(viewer," %s %s\n",list->name,list->rname);CHKERRQ(ierr); 473 } 474 list = list->next; 475 } 476 ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr); 477 PetscFunctionReturn(0); 478 } 479 480 #undef __FUNCT__ 481 #define __FUNCT__ "PetscFunctionListGet" 482 /*@C 483 PetscFunctionListGet - Gets an array the contains the entries in PetscFunctionList, this is used 484 by help etc. 485 486 Collective over MPI_Comm 487 488 Input Parameter: 489 . list - list of types 490 491 Output Parameter: 492 + array - array of names 493 - n - length of array 494 495 Notes: 496 This allocates the array so that must be freed. BUT the individual entries are 497 not copied so should not be freed. 498 499 Level: developer 500 501 .seealso: PetscFunctionListAddDynamic(), PetscFunctionList 502 @*/ 503 PetscErrorCode PetscFunctionListGet(PetscFunctionList list,const char ***array,int *n) 504 { 505 PetscErrorCode ierr; 506 PetscInt count = 0; 507 PetscFunctionList klist = list; 508 509 PetscFunctionBegin; 510 while (list) { 511 list = list->next; 512 count++; 513 } 514 ierr = PetscMalloc((count+1)*sizeof(char*),array);CHKERRQ(ierr); 515 count = 0; 516 while (klist) { 517 (*array)[count] = klist->name; 518 klist = klist->next; 519 count++; 520 } 521 (*array)[count] = 0; 522 *n = count+1; 523 PetscFunctionReturn(0); 524 } 525 526 527 #undef __FUNCT__ 528 #define __FUNCT__ "PetscFunctionListPrintTypes" 529 /*@C 530 PetscFunctionListPrintTypes - Prints the methods available. 531 532 Collective over MPI_Comm 533 534 Input Parameters: 535 + comm - the communicator (usually MPI_COMM_WORLD) 536 . fd - file to print to, usually stdout 537 . prefix - prefix to prepend to name (optional) 538 . name - option string (for example, "-ksp_type") 539 . text - short description of the object (for example, "Krylov solvers") 540 . man - name of manual page that discusses the object (for example, "KSPCreate") 541 . list - list of types 542 - def - default (current) value 543 544 Level: developer 545 546 .seealso: PetscFunctionListAddDynamic(), PetscFunctionList 547 @*/ 548 PetscErrorCode PetscFunctionListPrintTypes(MPI_Comm comm,FILE *fd,const char prefix[],const char name[],const char text[],const char man[],PetscFunctionList list,const char def[]) 549 { 550 PetscErrorCode ierr; 551 PetscInt count = 0; 552 char p[64]; 553 554 PetscFunctionBegin; 555 if (!fd) fd = PETSC_STDOUT; 556 557 ierr = PetscStrcpy(p,"-");CHKERRQ(ierr); 558 if (prefix) {ierr = PetscStrcat(p,prefix);CHKERRQ(ierr);} 559 ierr = PetscFPrintf(comm,fd," %s%s <%s>: %s (one of)",p,name+1,def,text);CHKERRQ(ierr); 560 561 while (list) { 562 ierr = PetscFPrintf(comm,fd," %s",list->name);CHKERRQ(ierr); 563 list = list->next; 564 count++; 565 if (count == 8) {ierr = PetscFPrintf(comm,fd,"\n ");CHKERRQ(ierr);} 566 } 567 ierr = PetscFPrintf(comm,fd," (%s)\n",man);CHKERRQ(ierr); 568 PetscFunctionReturn(0); 569 } 570 571 #undef __FUNCT__ 572 #define __FUNCT__ "PetscFunctionListDuplicate" 573 /*@ 574 PetscFunctionListDuplicate - Creates a new list from a given object list. 575 576 Input Parameters: 577 . fl - pointer to list 578 579 Output Parameters: 580 . nl - the new list (should point to 0 to start, otherwise appends) 581 582 Level: developer 583 584 .seealso: PetscFunctionList, PetscFunctionListAdd(), PetscFlistDestroy() 585 586 @*/ 587 PetscErrorCode PetscFunctionListDuplicate(PetscFunctionList fl,PetscFunctionList *nl) 588 { 589 PetscErrorCode ierr; 590 char path[PETSC_MAX_PATH_LEN]; 591 592 PetscFunctionBegin; 593 while (fl) { 594 /* this is silly, rebuild the complete pathname */ 595 if (fl->path) { 596 ierr = PetscStrcpy(path,fl->path);CHKERRQ(ierr); 597 ierr = PetscStrcat(path,":");CHKERRQ(ierr); 598 ierr = PetscStrcat(path,fl->name);CHKERRQ(ierr); 599 } else { 600 ierr = PetscStrcpy(path,fl->name);CHKERRQ(ierr); 601 } 602 ierr = PetscFunctionListAdd(PETSC_COMM_WORLD,nl,path,fl->rname,fl->routine);CHKERRQ(ierr); 603 fl = fl->next; 604 } 605 PetscFunctionReturn(0); 606 } 607 608 609 #undef __FUNCT__ 610 #define __FUNCT__ "PetscFunctionListConcat" 611 /* 612 PetscFunctionListConcat - joins name of a libary, and the path where it is located 613 into a single string. 614 615 Input Parameters: 616 . path - path to the library name. 617 . name - name of the library 618 619 Output Parameters: 620 . fullname - the name that is the union of the path and the library name, 621 delimited by a semicolon, i.e., path:name 622 623 Notes: 624 If the path is NULL, assumes that the name, specified also includes 625 the path as path:name 626 627 */ 628 PetscErrorCode PetscFunctionListConcat(const char path[],const char name[],char fullname[]) 629 { 630 PetscErrorCode ierr; 631 632 PetscFunctionBegin; 633 if (path) { 634 ierr = PetscStrcpy(fullname,path);CHKERRQ(ierr); 635 ierr = PetscStrcat(fullname,":");CHKERRQ(ierr); 636 ierr = PetscStrcat(fullname,name);CHKERRQ(ierr); 637 } else { 638 ierr = PetscStrcpy(fullname,name);CHKERRQ(ierr); 639 } 640 PetscFunctionReturn(0); 641 } 642