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