1 #define PETSC_DLL 2 /* 3 Utilites routines to add simple ASCII IO capability. 4 */ 5 #include "../src/sys/fileio/mprint.h" 6 /* 7 If petsc_history is on, then all Petsc*Printf() results are saved 8 if the appropriate (usually .petschistory) file. 9 */ 10 extern FILE *petsc_history; 11 /* 12 Allows one to overwrite where standard out is sent. For example 13 PETSC_STDOUT = fopen("/dev/ttyXX","w") will cause all standard out 14 writes to go to terminal XX; assuming you have write permission there 15 */ 16 FILE *PETSC_STDOUT = 0; 17 /* 18 Allows one to overwrite where standard error is sent. For example 19 PETSC_STDERR = fopen("/dev/ttyXX","w") will cause all standard error 20 writes to go to terminal XX; assuming you have write permission there 21 */ 22 FILE *PETSC_STDERR = 0; 23 /* 24 Used to output to Zope 25 */ 26 FILE *PETSC_ZOPEFD = 0; 27 28 #undef __FUNCT__ 29 #define __FUNCT__ "PetscFormatConvert" 30 PetscErrorCode PETSCSYS_DLLEXPORT PetscFormatConvert(const char *format,char *newformat,PetscInt size) 31 { 32 PetscInt i = 0,j = 0; 33 34 while (format[i] && i < size-1) { 35 if (format[i] == '%' && format[i+1] == 'D') { 36 newformat[j++] = '%'; 37 #if !defined(PETSC_USE_64BIT_INDICES) 38 newformat[j++] = 'd'; 39 #else 40 newformat[j++] = 'l'; 41 newformat[j++] = 'l'; 42 newformat[j++] = 'd'; 43 #endif 44 i += 2; 45 } else if (format[i] == '%' && format[i+1] >= '1' && format[i+1] <= '9' && format[i+2] == 'D') { 46 newformat[j++] = '%'; 47 newformat[j++] = format[i+1]; 48 #if !defined(PETSC_USE_64BIT_INDICES) 49 newformat[j++] = 'd'; 50 #else 51 newformat[j++] = 'l'; 52 newformat[j++] = 'l'; 53 newformat[j++] = 'd'; 54 #endif 55 i += 3; 56 } else if (format[i] == '%' && format[i+1] == 'G') { 57 newformat[j++] = '%'; 58 #if defined(PETSC_USE_SCALAR_INT) 59 newformat[j++] = 'd'; 60 #elif !defined(PETSC_USE_SCALAR_LONG_DOUBLE) 61 newformat[j++] = 'g'; 62 #else 63 newformat[j++] = 'L'; 64 newformat[j++] = 'g'; 65 #endif 66 i += 2; 67 }else { 68 newformat[j++] = format[i++]; 69 } 70 } 71 newformat[j] = 0; 72 return 0; 73 } 74 75 #undef __FUNCT__ 76 #define __FUNCT__ "PetscVSNPrintf" 77 /* 78 No error handling because may be called by error handler 79 */ 80 PetscErrorCode PETSCSYS_DLLEXPORT PetscVSNPrintf(char *str,size_t len,const char *format,int *fullLength,va_list Argp) 81 { 82 /* no malloc since may be called by error handler */ 83 char *newformat; 84 char formatbuf[8*1024]; 85 size_t oldLength,length; 86 PetscErrorCode ierr; 87 88 ierr = PetscStrlen(format, &oldLength);CHKERRQ(ierr); 89 if (oldLength < 8*1024) { 90 newformat = formatbuf; 91 } else { 92 ierr = PetscMalloc((oldLength+1) * sizeof(char), &newformat);CHKERRQ(ierr); 93 } 94 PetscFormatConvert(format,newformat,oldLength+1); 95 ierr = PetscStrlen(newformat, &length);CHKERRQ(ierr); 96 #if 0 97 if (length > len) { 98 newformat[len] = '\0'; 99 } 100 #endif 101 #if defined(PETSC_HAVE_VSNPRINTF_CHAR) 102 *fullLength = vsnprintf(str,len,newformat,(char *)Argp); 103 #elif defined(PETSC_HAVE_VSNPRINTF) 104 *fullLength = vsnprintf(str,len,newformat,Argp); 105 #elif defined(PETSC_HAVE__VSNPRINTF) 106 *fullLength = _vsnprintf(str,len,newformat,Argp); 107 #else 108 #error "vsnprintf not found" 109 #endif 110 if (oldLength >= 8*1024) { 111 ierr = PetscFree(newformat);CHKERRQ(ierr); 112 } 113 return 0; 114 } 115 116 #undef __FUNCT__ 117 #define __FUNCT__ "PetscZopeLog" 118 PetscErrorCode PETSCSYS_DLLEXPORT PetscZopeLog(const char *format,va_list Argp) 119 { 120 /* no malloc since may be called by error handler */ 121 char newformat[8*1024]; 122 char log[8*1024]; 123 char logstart[] = " <<<log>>>"; 124 size_t len; 125 size_t formatlen; 126 127 PetscFormatConvert(format,newformat,8*1024); 128 PetscStrlen(logstart, &len); 129 PetscMemcpy(log, logstart, len); 130 PetscStrlen(newformat, &formatlen); 131 PetscMemcpy(&(log[len]), newformat, formatlen); 132 if (PETSC_ZOPEFD){ 133 #if defined(PETSC_HAVE_VFPRINTF_CHAR) 134 vfprintf(PETSC_ZOPEFD,log,(char *)Argp); 135 #else 136 vfprintf(PETSC_ZOPEFD,log,Argp); 137 #endif 138 fflush(PETSC_ZOPEFD); 139 } 140 return 0; 141 } 142 143 #undef __FUNCT__ 144 #define __FUNCT__ "PetscVFPrintf" 145 /* 146 All PETSc standard out and error messages are sent through this function; so, in theory, this can 147 can be replaced with something that does not simply write to a file. 148 149 Note: For error messages this may be called by a process, for regular standard out it is 150 called only by process 0 of a given communicator 151 152 No error handling because may be called by error handler 153 */ 154 PetscErrorCode PETSCSYS_DLLEXPORT PetscVFPrintfDefault(FILE *fd,const char *format,va_list Argp) 155 { 156 /* no malloc since may be called by error handler (assume no long messages in errors) */ 157 char *newformat; 158 char formatbuf[8*1024]; 159 size_t oldLength; 160 161 PetscStrlen(format, &oldLength); 162 if (oldLength < 8*1024) { 163 newformat = formatbuf; 164 } else { 165 (void)PetscMalloc((oldLength+1) * sizeof(char), &newformat); 166 } 167 PetscFormatConvert(format,newformat,oldLength+1); 168 if (PETSC_ZOPEFD && PETSC_ZOPEFD != PETSC_STDOUT){ 169 va_list s; 170 #if defined(PETSC_HAVE_VA_COPY) 171 va_copy(s, Argp); 172 #elif defined(PETSC_HAVE___VA_COPY) 173 __va_copy(s, Argp); 174 #else 175 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS,"Zope not supported due to missing va_copy()"); 176 #endif 177 178 #if defined(PETSC_HAVE_VA_COPY) || defined(PETSC_HAVE___VA_COPY) 179 #if defined(PETSC_HAVE_VFPRINTF_CHAR) 180 vfprintf(PETSC_ZOPEFD,newformat,(char *)s); 181 #else 182 vfprintf(PETSC_ZOPEFD,newformat,s); 183 #endif 184 fflush(PETSC_ZOPEFD); 185 #endif 186 } 187 188 #if defined(PETSC_HAVE_VFPRINTF_CHAR) 189 vfprintf(fd,newformat,(char *)Argp); 190 #else 191 vfprintf(fd,newformat,Argp); 192 #endif 193 fflush(fd); 194 if (oldLength >= 8*1024) { 195 if (PetscFree(newformat)) {}; 196 } 197 return 0; 198 } 199 200 #undef __FUNCT__ 201 #define __FUNCT__ "PetscSNPrintf" 202 /*@C 203 PetscSNPrintf - Prints to a string of given length 204 205 Not Collective 206 207 Input Parameters: 208 + str - the string to print to 209 . len - the length of str 210 . format - the usual printf() format string 211 - any arguments 212 213 Level: intermediate 214 215 .seealso: PetscSynchronizedFlush(), PetscSynchronizedFPrintf(), PetscFPrintf(), PetscVSNPrintf(), 216 PetscPrintf(), PetscViewerASCIIPrintf(), PetscViewerASCIISynchronizedPrintf() 217 @*/ 218 PetscErrorCode PETSCSYS_DLLEXPORT PetscSNPrintf(char *str,size_t len,const char format[],...) 219 { 220 PetscErrorCode ierr; 221 int fullLength; 222 va_list Argp; 223 224 PetscFunctionBegin; 225 va_start(Argp,format); 226 ierr = PetscVSNPrintf(str,len,format,&fullLength,Argp);CHKERRQ(ierr); 227 PetscFunctionReturn(0); 228 } 229 230 /* ----------------------------------------------------------------------- */ 231 232 PrintfQueue queue = 0,queuebase = 0; 233 int queuelength = 0; 234 FILE *queuefile = PETSC_NULL; 235 236 #undef __FUNCT__ 237 #define __FUNCT__ "PetscSynchronizedPrintf" 238 /*@C 239 PetscSynchronizedPrintf - Prints synchronized output from several processors. 240 Output of the first processor is followed by that of the second, etc. 241 242 Not Collective 243 244 Input Parameters: 245 + comm - the communicator 246 - format - the usual printf() format string 247 248 Level: intermediate 249 250 Notes: 251 REQUIRES a intervening call to PetscSynchronizedFlush() for the information 252 from all the processors to be printed. 253 254 Fortran Note: 255 The call sequence is PetscSynchronizedPrintf(MPI_Comm, character(*), PetscErrorCode ierr) from Fortran. 256 That is, you can only pass a single character string from Fortran. 257 258 .seealso: PetscSynchronizedFlush(), PetscSynchronizedFPrintf(), PetscFPrintf(), 259 PetscPrintf(), PetscViewerASCIIPrintf(), PetscViewerASCIISynchronizedPrintf() 260 @*/ 261 PetscErrorCode PETSCSYS_DLLEXPORT PetscSynchronizedPrintf(MPI_Comm comm,const char format[],...) 262 { 263 PetscErrorCode ierr; 264 PetscMPIInt rank; 265 266 PetscFunctionBegin; 267 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 268 269 /* First processor prints immediately to stdout */ 270 if (!rank) { 271 va_list Argp; 272 va_start(Argp,format); 273 ierr = (*PetscVFPrintf)(PETSC_STDOUT,format,Argp);CHKERRQ(ierr); 274 if (petsc_history) { 275 ierr = (*PetscVFPrintf)(petsc_history,format,Argp);CHKERRQ(ierr); 276 } 277 va_end(Argp); 278 } else { /* other processors add to local queue */ 279 va_list Argp; 280 PrintfQueue next; 281 int fullLength = 8191; 282 283 ierr = PetscNew(struct _PrintfQueue,&next);CHKERRQ(ierr); 284 if (queue) {queue->next = next; queue = next; queue->next = 0;} 285 else {queuebase = queue = next;} 286 queuelength++; 287 next->size = -1; 288 while(fullLength >= next->size) { 289 next->size = fullLength+1; 290 ierr = PetscMalloc(next->size * sizeof(char), &next->string);CHKERRQ(ierr); 291 va_start(Argp,format); 292 ierr = PetscMemzero(next->string,next->size);CHKERRQ(ierr); 293 ierr = PetscVSNPrintf(next->string,next->size,format, &fullLength,Argp);CHKERRQ(ierr); 294 va_end(Argp); 295 } 296 } 297 298 PetscFunctionReturn(0); 299 } 300 301 #undef __FUNCT__ 302 #define __FUNCT__ "PetscSynchronizedFPrintf" 303 /*@C 304 PetscSynchronizedFPrintf - Prints synchronized output to the specified file from 305 several processors. Output of the first processor is followed by that of the 306 second, etc. 307 308 Not Collective 309 310 Input Parameters: 311 + comm - the communicator 312 . fd - the file pointer 313 - format - the usual printf() format string 314 315 Level: intermediate 316 317 Notes: 318 REQUIRES a intervening call to PetscSynchronizedFlush() for the information 319 from all the processors to be printed. 320 321 .seealso: PetscSynchronizedPrintf(), PetscSynchronizedFlush(), PetscFPrintf(), 322 PetscFOpen(), PetscViewerASCIISynchronizedPrintf(), PetscViewerASCIIPrintf() 323 324 @*/ 325 PetscErrorCode PETSCSYS_DLLEXPORT PetscSynchronizedFPrintf(MPI_Comm comm,FILE* fp,const char format[],...) 326 { 327 PetscErrorCode ierr; 328 PetscMPIInt rank; 329 330 PetscFunctionBegin; 331 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 332 333 /* First processor prints immediately to fp */ 334 if (!rank) { 335 va_list Argp; 336 va_start(Argp,format); 337 ierr = (*PetscVFPrintf)(fp,format,Argp);CHKERRQ(ierr); 338 queuefile = fp; 339 if (petsc_history) { 340 ierr = (*PetscVFPrintf)(petsc_history,format,Argp);CHKERRQ(ierr); 341 } 342 va_end(Argp); 343 } else { /* other processors add to local queue */ 344 va_list Argp; 345 PrintfQueue next; 346 int fullLength = 8191; 347 ierr = PetscNew(struct _PrintfQueue,&next);CHKERRQ(ierr); 348 if (queue) {queue->next = next; queue = next; queue->next = 0;} 349 else {queuebase = queue = next;} 350 queuelength++; 351 next->size = -1; 352 while(fullLength >= next->size) { 353 next->size = fullLength+1; 354 ierr = PetscMalloc(next->size * sizeof(char), &next->string);CHKERRQ(ierr); 355 va_start(Argp,format); 356 ierr = PetscMemzero(next->string,next->size);CHKERRQ(ierr); 357 ierr = PetscVSNPrintf(next->string,next->size,format,&fullLength,Argp);CHKERRQ(ierr); 358 va_end(Argp); 359 } 360 } 361 PetscFunctionReturn(0); 362 } 363 364 #undef __FUNCT__ 365 #define __FUNCT__ "PetscSynchronizedFlush" 366 /*@ 367 PetscSynchronizedFlush - Flushes to the screen output from all processors 368 involved in previous PetscSynchronizedPrintf() calls. 369 370 Collective on MPI_Comm 371 372 Input Parameters: 373 . comm - the communicator 374 375 Level: intermediate 376 377 Notes: 378 Usage of PetscSynchronizedPrintf() and PetscSynchronizedFPrintf() with 379 different MPI communicators REQUIRES an intervening call to PetscSynchronizedFlush(). 380 381 .seealso: PetscSynchronizedPrintf(), PetscFPrintf(), PetscPrintf(), PetscViewerASCIIPrintf(), 382 PetscViewerASCIISynchronizedPrintf() 383 @*/ 384 PetscErrorCode PETSCSYS_DLLEXPORT PetscSynchronizedFlush(MPI_Comm comm) 385 { 386 PetscErrorCode ierr; 387 PetscMPIInt rank,size,tag,i,j,n,dummy; 388 char *message; 389 MPI_Status status; 390 FILE *fd; 391 392 PetscFunctionBegin; 393 ierr = PetscCommDuplicate(comm,&comm,&tag);CHKERRQ(ierr); 394 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 395 ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 396 397 /* First processor waits for messages from all other processors */ 398 if (!rank) { 399 if (queuefile) { 400 fd = queuefile; 401 } else { 402 fd = PETSC_STDOUT; 403 } 404 for (i=1; i<size; i++) { 405 /* to prevent a flood of messages to process zero, request each message separately */ 406 ierr = MPI_Send(&dummy,1,MPI_INT,i,tag,comm);CHKERRQ(ierr); 407 ierr = MPI_Recv(&n,1,MPI_INT,i,tag,comm,&status);CHKERRQ(ierr); 408 for (j=0; j<n; j++) { 409 PetscMPIInt size; 410 411 ierr = MPI_Recv(&size,1,MPI_INT,i,tag,comm,&status);CHKERRQ(ierr); 412 ierr = PetscMalloc(size * sizeof(char), &message);CHKERRQ(ierr); 413 ierr = MPI_Recv(message,size,MPI_CHAR,i,tag,comm,&status);CHKERRQ(ierr); 414 ierr = PetscFPrintf(comm,fd,"%s",message); 415 ierr = PetscFree(message);CHKERRQ(ierr); 416 } 417 } 418 queuefile = PETSC_NULL; 419 } else { /* other processors send queue to processor 0 */ 420 PrintfQueue next = queuebase,previous; 421 422 ierr = MPI_Recv(&dummy,1,MPI_INT,0,tag,comm,&status);CHKERRQ(ierr); 423 ierr = MPI_Send(&queuelength,1,MPI_INT,0,tag,comm);CHKERRQ(ierr); 424 for (i=0; i<queuelength; i++) { 425 ierr = MPI_Send(&next->size,1,MPI_INT,0,tag,comm);CHKERRQ(ierr); 426 ierr = MPI_Send(next->string,next->size,MPI_CHAR,0,tag,comm);CHKERRQ(ierr); 427 previous = next; 428 next = next->next; 429 ierr = PetscFree(previous->string);CHKERRQ(ierr); 430 ierr = PetscFree(previous);CHKERRQ(ierr); 431 } 432 queue = 0; 433 queuelength = 0; 434 } 435 ierr = PetscCommDestroy(&comm);CHKERRQ(ierr); 436 PetscFunctionReturn(0); 437 } 438 439 /* ---------------------------------------------------------------------------------------*/ 440 441 #undef __FUNCT__ 442 #define __FUNCT__ "PetscFPrintf" 443 /*@C 444 PetscFPrintf - Prints to a file, only from the first 445 processor in the communicator. 446 447 Not Collective 448 449 Input Parameters: 450 + comm - the communicator 451 . fd - the file pointer 452 - format - the usual printf() format string 453 454 Level: intermediate 455 456 Fortran Note: 457 This routine is not supported in Fortran. 458 459 Concepts: printing^in parallel 460 Concepts: printf^in parallel 461 462 .seealso: PetscPrintf(), PetscSynchronizedPrintf(), PetscViewerASCIIPrintf(), 463 PetscViewerASCIISynchronizedPrintf(), PetscSynchronizedFlush() 464 @*/ 465 PetscErrorCode PETSCSYS_DLLEXPORT PetscFPrintf(MPI_Comm comm,FILE* fd,const char format[],...) 466 { 467 PetscErrorCode ierr; 468 PetscMPIInt rank; 469 470 PetscFunctionBegin; 471 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 472 if (!rank) { 473 va_list Argp; 474 va_start(Argp,format); 475 ierr = (*PetscVFPrintf)(fd,format,Argp);CHKERRQ(ierr); 476 if (petsc_history) { 477 ierr = (*PetscVFPrintf)(petsc_history,format,Argp);CHKERRQ(ierr); 478 } 479 va_end(Argp); 480 } 481 PetscFunctionReturn(0); 482 } 483 484 #undef __FUNCT__ 485 #define __FUNCT__ "PetscPrintf" 486 /*@C 487 PetscPrintf - Prints to standard out, only from the first 488 processor in the communicator. 489 490 Not Collective 491 492 Input Parameters: 493 + comm - the communicator 494 - format - the usual printf() format string 495 496 Level: intermediate 497 498 Fortran Note: 499 The call sequence is PetscPrintf(MPI_Comm, character(*), PetscErrorCode ierr) from Fortran. 500 That is, you can only pass a single character string from Fortran. 501 502 Notes: %A is replace with %g unless the value is < 1.e-12 when it is 503 replaced with < 1.e-12 504 505 Concepts: printing^in parallel 506 Concepts: printf^in parallel 507 508 .seealso: PetscFPrintf(), PetscSynchronizedPrintf() 509 @*/ 510 PetscErrorCode PETSCSYS_DLLEXPORT PetscPrintf(MPI_Comm comm,const char format[],...) 511 { 512 PetscErrorCode ierr; 513 PetscMPIInt rank; 514 size_t len; 515 char *nformat,*sub1,*sub2; 516 PetscReal value; 517 518 PetscFunctionBegin; 519 if (!comm) comm = PETSC_COMM_WORLD; 520 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 521 if (!rank) { 522 va_list Argp; 523 va_start(Argp,format); 524 525 ierr = PetscStrstr(format,"%A",&sub1);CHKERRQ(ierr); 526 if (sub1) { 527 ierr = PetscStrstr(format,"%",&sub2);CHKERRQ(ierr); 528 if (sub1 != sub2) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"%%A format must be first in format string"); 529 ierr = PetscStrlen(format,&len);CHKERRQ(ierr); 530 ierr = PetscMalloc((len+16)*sizeof(char),&nformat);CHKERRQ(ierr); 531 ierr = PetscStrcpy(nformat,format);CHKERRQ(ierr); 532 ierr = PetscStrstr(nformat,"%",&sub2);CHKERRQ(ierr); 533 sub2[0] = 0; 534 value = (double)va_arg(Argp,double); 535 if (PetscAbsReal(value) < 1.e-12) { 536 ierr = PetscStrcat(nformat,"< 1.e-12");CHKERRQ(ierr); 537 } else { 538 ierr = PetscStrcat(nformat,"%g");CHKERRQ(ierr); 539 va_end(Argp); 540 va_start(Argp,format); 541 } 542 ierr = PetscStrcat(nformat,sub1+2);CHKERRQ(ierr); 543 } else { 544 nformat = (char*)format; 545 } 546 ierr = (*PetscVFPrintf)(PETSC_STDOUT,nformat,Argp);CHKERRQ(ierr); 547 if (petsc_history) { 548 ierr = (*PetscVFPrintf)(petsc_history,nformat,Argp);CHKERRQ(ierr); 549 } 550 va_end(Argp); 551 if (sub1) {ierr = PetscFree(nformat);CHKERRQ(ierr);} 552 } 553 PetscFunctionReturn(0); 554 } 555 556 /* ---------------------------------------------------------------------------------------*/ 557 #undef __FUNCT__ 558 #define __FUNCT__ "PetscHelpPrintfDefault" 559 PetscErrorCode PETSCSYS_DLLEXPORT PetscHelpPrintfDefault(MPI_Comm comm,const char format[],...) 560 { 561 PetscErrorCode ierr; 562 PetscMPIInt rank; 563 564 PetscFunctionBegin; 565 if (!comm) comm = PETSC_COMM_WORLD; 566 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 567 if (!rank) { 568 va_list Argp; 569 va_start(Argp,format); 570 ierr = (*PetscVFPrintf)(PETSC_STDOUT,format,Argp);CHKERRQ(ierr); 571 if (petsc_history) { 572 ierr = (*PetscVFPrintf)(petsc_history,format,Argp);CHKERRQ(ierr); 573 } 574 va_end(Argp); 575 } 576 PetscFunctionReturn(0); 577 } 578 579 /* ---------------------------------------------------------------------------------------*/ 580 581 582 #undef __FUNCT__ 583 #define __FUNCT__ "PetscSynchronizedFGets" 584 /*@C 585 PetscSynchronizedFGets - Several processors all get the same line from a file. 586 587 Collective on MPI_Comm 588 589 Input Parameters: 590 + comm - the communicator 591 . fd - the file pointer 592 - len - the length of the output buffer 593 594 Output Parameter: 595 . string - the line read from the file 596 597 Level: intermediate 598 599 .seealso: PetscSynchronizedPrintf(), PetscSynchronizedFlush(), 600 PetscFOpen(), PetscViewerASCIISynchronizedPrintf(), PetscViewerASCIIPrintf() 601 602 @*/ 603 PetscErrorCode PETSCSYS_DLLEXPORT PetscSynchronizedFGets(MPI_Comm comm,FILE* fp,size_t len,char string[]) 604 { 605 PetscErrorCode ierr; 606 PetscMPIInt rank; 607 char *str; 608 609 PetscFunctionBegin; 610 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 611 612 if (!rank) { 613 str = fgets(string,len,fp); /* Not very useful error behavior, but what is desired behavior for attempt to read at EOF? */ 614 } 615 ierr = MPI_Bcast(string,len,MPI_BYTE,0,comm);CHKERRQ(ierr); 616 PetscFunctionReturn(0); 617 } 618