1 /* 2 Utilites routines to add simple ASCII IO capability. 3 */ 4 #include <../src/sys/fileio/mprint.h> 5 #include <errno.h> 6 /* 7 If petsc_history is on, then all Petsc*Printf() results are saved 8 if the appropriate (usually .petschistory) file. 9 */ 10 PETSC_INTERN 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 = NULL; 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 = NULL; 23 24 /*@C 25 PetscFormatConvertGetSize - Gets the length of a string needed to hold format converted with PetscFormatConvert() 26 27 Input Parameter: 28 . format - the PETSc format string 29 30 Output Parameter: 31 . size - the needed length of the new format 32 33 Level: developer 34 35 .seealso: PetscFormatConvert(), PetscVSNPrintf(), PetscVFPrintf() 36 37 @*/ 38 PetscErrorCode PetscFormatConvertGetSize(const char *format,size_t *size) 39 { 40 size_t sz = 0; 41 PetscInt i = 0; 42 43 PetscFunctionBegin; 44 PetscValidCharPointer(format,1); 45 PetscValidPointer(size,2); 46 while (format[i]) { 47 if (format[i] == '%') { 48 if (format[i+1] == '%') { 49 i += 2; 50 sz += 2; 51 continue; 52 } 53 /* Find the letter */ 54 while (format[i] && (format[i] <= '9')) {++i;++sz;} 55 switch (format[i]) { 56 #if PetscDefined(USE_64BIT_INDICES) 57 case 'D': 58 sz += 2; 59 break; 60 #endif 61 case 'g': 62 sz += 4; 63 default: 64 break; 65 } 66 } 67 ++i; 68 ++sz; 69 } 70 *size = sz+1; /* space for NULL character */ 71 PetscFunctionReturn(0); 72 } 73 74 /*@C 75 PetscFormatConvert - Takes a PETSc format string and converts the %D to %d for 32 bit PETSc indices and %lld for 64 bit PETSc indices. Also 76 converts %g to [|%g|] so that PetscVSNPrintf() can easily insure all %g formatted numbers have a decimal point when printed. 77 78 Input Parameters: 79 + format - the PETSc format string 80 . newformat - the location to put the new format 81 - size - the length of newformat, you can use PetscFormatConvertGetSize() to compute the needed size 82 83 Note: this exists so we can have the same code when PetscInt is either int or long long int 84 85 Level: developer 86 87 .seealso: PetscFormatConvertGetSize(), PetscVSNPrintf(), PetscVFPrintf() 88 89 @*/ 90 PetscErrorCode PetscFormatConvert(const char *format,char *newformat) 91 { 92 PetscInt i = 0, j = 0; 93 94 PetscFunctionBegin; 95 while (format[i]) { 96 if (format[i] == '%' && format[i+1] == '%') { 97 newformat[j++] = format[i++]; 98 newformat[j++] = format[i++]; 99 } else if (format[i] == '%') { 100 if (format[i+1] == 'g') { 101 newformat[j++] = '['; 102 newformat[j++] = '|'; 103 } 104 /* Find the letter */ 105 for (; format[i] && format[i] <= '9'; i++) newformat[j++] = format[i]; 106 switch (format[i]) { 107 case 'D': 108 #if !defined(PETSC_USE_64BIT_INDICES) 109 newformat[j++] = 'd'; 110 #else 111 newformat[j++] = 'l'; 112 newformat[j++] = 'l'; 113 newformat[j++] = 'd'; 114 #endif 115 break; 116 case 'g': 117 newformat[j++] = format[i]; 118 if (format[i-1] == '%') { 119 newformat[j++] = '|'; 120 newformat[j++] = ']'; 121 } 122 break; 123 case 'G': 124 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"%%G format is no longer supported, use %%g and cast the argument to double"); 125 case 'F': 126 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"%%F format is no longer supported, use %%f and cast the argument to double"); 127 default: 128 newformat[j++] = format[i]; 129 break; 130 } 131 i++; 132 } else newformat[j++] = format[i++]; 133 } 134 newformat[j] = 0; 135 PetscFunctionReturn(0); 136 } 137 138 #define PETSCDEFAULTBUFFERSIZE 8*1024 139 140 /*@C 141 PetscVSNPrintf - The PETSc version of vsnprintf(). Converts a PETSc format string into a standard C format string and then puts all the 142 function arguments into a string using the format statement. 143 144 Input Parameters: 145 + str - location to put result 146 . len - the amount of space in str 147 + format - the PETSc format string 148 - fullLength - the amount of space in str actually used. 149 150 Developer Notes: 151 this function may be called from an error handler, if an error occurs when it is called by the error handler than likely 152 a recursion will occur and possible crash. 153 154 Level: developer 155 156 .seealso: PetscVSNPrintf(), PetscErrorPrintf(), PetscVPrintf() 157 158 @*/ 159 PetscErrorCode PetscVSNPrintf(char *str,size_t len,const char *format,size_t *fullLength,va_list Argp) 160 { 161 char *newformat = NULL; 162 char formatbuf[PETSCDEFAULTBUFFERSIZE]; 163 size_t newLength; 164 int flen; 165 166 PetscFunctionBegin; 167 PetscCall(PetscFormatConvertGetSize(format,&newLength)); 168 if (newLength < sizeof(formatbuf)) { 169 newformat = formatbuf; 170 newLength = sizeof(formatbuf)-1; 171 } else { 172 PetscCall(PetscMalloc1(newLength, &newformat)); 173 } 174 PetscCall(PetscFormatConvert(format,newformat)); 175 #if defined(PETSC_HAVE_VSNPRINTF) 176 flen = vsnprintf(str,len,newformat,Argp); 177 #else 178 #error "vsnprintf not found" 179 #endif 180 if (newLength > sizeof(formatbuf)-1) { 181 PetscCall(PetscFree(newformat)); 182 } 183 { 184 PetscBool foundedot; 185 size_t cnt = 0,ncnt = 0,leng; 186 PetscCall(PetscStrlen(str,&leng)); 187 if (leng > 4) { 188 for (cnt=0; cnt<leng-4; cnt++) { 189 if (str[cnt] == '[' && str[cnt+1] == '|') { 190 flen -= 4; 191 cnt++; cnt++; 192 foundedot = PETSC_FALSE; 193 for (; cnt<leng-1; cnt++) { 194 if (str[cnt] == '|' && str[cnt+1] == ']') { 195 cnt++; 196 if (!foundedot) str[ncnt++] = '.'; 197 ncnt--; 198 break; 199 } else { 200 if (str[cnt] == 'e' || str[cnt] == '.') foundedot = PETSC_TRUE; 201 str[ncnt++] = str[cnt]; 202 } 203 } 204 } else { 205 str[ncnt] = str[cnt]; 206 } 207 ncnt++; 208 } 209 while (cnt < leng) { 210 str[ncnt] = str[cnt]; ncnt++; cnt++; 211 } 212 str[ncnt] = 0; 213 } 214 } 215 #if defined(PETSC_HAVE_WINDOWS_H) && !defined(PETSC_HAVE__SET_OUTPUT_FORMAT) 216 /* older Windows OS always produces e-+0np for floating point output; remove the extra 0 */ 217 { 218 size_t cnt = 0,ncnt = 0,leng; 219 PetscCall(PetscStrlen(str,&leng)); 220 if (leng > 5) { 221 for (cnt=0; cnt<leng-4; cnt++) { 222 if (str[cnt] == 'e' && (str[cnt+1] == '-' || str[cnt+1] == '+') && str[cnt+2] == '0' && str[cnt+3] >= '0' && str[cnt+3] <= '9' && str[cnt+4] >= '0' && str[cnt+4] <= '9') { 223 str[ncnt] = str[cnt]; ncnt++; cnt++; 224 str[ncnt] = str[cnt]; ncnt++; cnt++; cnt++; 225 str[ncnt] = str[cnt]; 226 } else { 227 str[ncnt] = str[cnt]; 228 } 229 ncnt++; 230 } 231 while (cnt < leng) { 232 str[ncnt] = str[cnt]; ncnt++; cnt++; 233 } 234 str[ncnt] = 0; 235 } 236 } 237 #endif 238 if (fullLength) *fullLength = 1 + (size_t) flen; 239 PetscFunctionReturn(0); 240 } 241 242 /*@C 243 PetscVFPrintf - All PETSc standard out and error messages are sent through this function; so, in theory, this can 244 can be replaced with something that does not simply write to a file. 245 246 To use, write your own function for example, 247 $PetscErrorCode mypetscvfprintf(FILE *fd,const char format[],va_list Argp) 248 ${ 249 $ PetscErrorCode ierr; 250 $ 251 $ PetscFunctionBegin; 252 $ if (fd != stdout && fd != stderr) { handle regular files 253 $ CHKERR(PetscVFPrintfDefault(fd,format,Argp)); 254 $ } else { 255 $ char buff[BIG]; 256 $ size_t length; 257 $ PetscCall(PetscVSNPrintf(buff,BIG,format,&length,Argp)); 258 $ now send buff to whatever stream or whatever you want 259 $ } 260 $ PetscFunctionReturn(0); 261 $} 262 then before the call to PetscInitialize() do the assignment 263 $ PetscVFPrintf = mypetscvfprintf; 264 265 Notes: 266 For error messages this may be called by any process, for regular standard out it is 267 called only by process 0 of a given communicator 268 269 Developer Notes: 270 this could be called by an error handler, if that happens then a recursion of the error handler may occur 271 and a crash 272 273 Level: developer 274 275 .seealso: PetscVSNPrintf(), PetscErrorPrintf() 276 277 @*/ 278 PetscErrorCode PetscVFPrintfDefault(FILE *fd,const char *format,va_list Argp) 279 { 280 char str[PETSCDEFAULTBUFFERSIZE]; 281 char *buff = str; 282 size_t fullLength; 283 #if defined(PETSC_HAVE_VA_COPY) 284 va_list Argpcopy; 285 #endif 286 287 PetscFunctionBegin; 288 #if defined(PETSC_HAVE_VA_COPY) 289 va_copy(Argpcopy,Argp); 290 #endif 291 PetscCall(PetscVSNPrintf(str,sizeof(str),format,&fullLength,Argp)); 292 if (fullLength > sizeof(str)) { 293 PetscCall(PetscMalloc1(fullLength,&buff)); 294 #if defined(PETSC_HAVE_VA_COPY) 295 PetscCall(PetscVSNPrintf(buff,fullLength,format,NULL,Argpcopy)); 296 #else 297 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"C89 does not support va_copy() hence cannot print long strings with PETSc printing routines"); 298 #endif 299 } 300 fprintf(fd,"%s",buff); 301 fflush(fd); 302 if (buff != str) { 303 PetscCall(PetscFree(buff)); 304 } 305 PetscFunctionReturn(0); 306 } 307 308 /*@C 309 PetscSNPrintf - Prints to a string of given length 310 311 Not Collective 312 313 Input Parameters: 314 + str - the string to print to 315 . len - the length of str 316 . format - the usual printf() format string 317 - ... - any arguments that are to be printed, each much have an appropriate symbol in the format argument 318 319 Level: intermediate 320 321 .seealso: PetscSynchronizedFlush(), PetscSynchronizedFPrintf(), PetscFPrintf(), PetscVSNPrintf(), 322 PetscPrintf(), PetscViewerASCIIPrintf(), PetscViewerASCIISynchronizedPrintf(), PetscVFPrintf() 323 @*/ 324 PetscErrorCode PetscSNPrintf(char *str,size_t len,const char format[],...) 325 { 326 size_t fullLength; 327 va_list Argp; 328 329 PetscFunctionBegin; 330 va_start(Argp,format); 331 PetscCall(PetscVSNPrintf(str,len,format,&fullLength,Argp)); 332 PetscFunctionReturn(0); 333 } 334 335 /*@C 336 PetscSNPrintfCount - Prints to a string of given length, returns count 337 338 Not Collective 339 340 Input Parameters: 341 + str - the string to print to 342 . len - the length of str 343 . format - the usual printf() format string 344 - ... - any arguments that are to be printed, each much have an appropriate symbol in the format argument 345 346 Output Parameter: 347 . countused - number of characters used 348 349 Level: intermediate 350 351 .seealso: PetscSynchronizedFlush(), PetscSynchronizedFPrintf(), PetscFPrintf(), PetscVSNPrintf(), 352 PetscPrintf(), PetscViewerASCIIPrintf(), PetscViewerASCIISynchronizedPrintf(), PetscSNPrintf(), PetscVFPrintf() 353 @*/ 354 PetscErrorCode PetscSNPrintfCount(char *str,size_t len,const char format[],size_t *countused,...) 355 { 356 va_list Argp; 357 358 PetscFunctionBegin; 359 va_start(Argp,countused); 360 PetscCall(PetscVSNPrintf(str,len,format,countused,Argp)); 361 PetscFunctionReturn(0); 362 } 363 364 /* ----------------------------------------------------------------------- */ 365 366 PrintfQueue petsc_printfqueue = NULL,petsc_printfqueuebase = NULL; 367 int petsc_printfqueuelength = 0; 368 369 /*@C 370 PetscSynchronizedPrintf - Prints synchronized output from several processors. 371 Output of the first processor is followed by that of the second, etc. 372 373 Not Collective 374 375 Input Parameters: 376 + comm - the communicator 377 - format - the usual printf() format string 378 379 Level: intermediate 380 381 Notes: 382 REQUIRES a call to PetscSynchronizedFlush() by all the processes after the completion of the calls to PetscSynchronizedPrintf() for the information 383 from all the processors to be printed. 384 385 Fortran Note: 386 The call sequence is PetscSynchronizedPrintf(MPI_Comm, character(*), PetscErrorCode ierr) from Fortran. 387 That is, you can only pass a single character string from Fortran. 388 389 .seealso: PetscSynchronizedFlush(), PetscSynchronizedFPrintf(), PetscFPrintf(), 390 PetscPrintf(), PetscViewerASCIIPrintf(), PetscViewerASCIISynchronizedPrintf() 391 @*/ 392 PetscErrorCode PetscSynchronizedPrintf(MPI_Comm comm,const char format[],...) 393 { 394 PetscMPIInt rank; 395 396 PetscFunctionBegin; 397 PetscCheckFalse(comm == MPI_COMM_NULL,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Called with MPI_COMM_NULL, likely PetscObjectComm() failed"); 398 PetscCallMPI(MPI_Comm_rank(comm,&rank)); 399 400 /* First processor prints immediately to stdout */ 401 if (rank == 0) { 402 va_list Argp; 403 va_start(Argp,format); 404 PetscCall((*PetscVFPrintf)(PETSC_STDOUT,format,Argp)); 405 if (petsc_history) { 406 va_start(Argp,format); 407 PetscCall((*PetscVFPrintf)(petsc_history,format,Argp)); 408 } 409 va_end(Argp); 410 } else { /* other processors add to local queue */ 411 va_list Argp; 412 PrintfQueue next; 413 size_t fullLength = PETSCDEFAULTBUFFERSIZE; 414 415 PetscCall(PetscNew(&next)); 416 if (petsc_printfqueue) { 417 petsc_printfqueue->next = next; 418 petsc_printfqueue = next; 419 petsc_printfqueue->next = NULL; 420 } else petsc_printfqueuebase = petsc_printfqueue = next; 421 petsc_printfqueuelength++; 422 next->size = 0; 423 next->string = NULL; 424 while (fullLength >= next->size) { 425 next->size = fullLength+1; 426 PetscCall(PetscFree(next->string)); 427 PetscCall(PetscMalloc1(next->size, &next->string)); 428 va_start(Argp,format); 429 PetscCall(PetscArrayzero(next->string,next->size)); 430 PetscCall(PetscVSNPrintf(next->string,next->size,format, &fullLength,Argp)); 431 va_end(Argp); 432 } 433 } 434 PetscFunctionReturn(0); 435 } 436 437 /*@C 438 PetscSynchronizedFPrintf - Prints synchronized output to the specified file from 439 several processors. Output of the first processor is followed by that of the 440 second, etc. 441 442 Not Collective 443 444 Input Parameters: 445 + comm - the communicator 446 . fd - the file pointer 447 - format - the usual printf() format string 448 449 Level: intermediate 450 451 Notes: 452 REQUIRES a intervening call to PetscSynchronizedFlush() for the information 453 from all the processors to be printed. 454 455 .seealso: PetscSynchronizedPrintf(), PetscSynchronizedFlush(), PetscFPrintf(), 456 PetscFOpen(), PetscViewerASCIISynchronizedPrintf(), PetscViewerASCIIPrintf() 457 458 @*/ 459 PetscErrorCode PetscSynchronizedFPrintf(MPI_Comm comm,FILE *fp,const char format[],...) 460 { 461 PetscMPIInt rank; 462 463 PetscFunctionBegin; 464 PetscCheckFalse(comm == MPI_COMM_NULL,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Called with MPI_COMM_NULL, likely PetscObjectComm() failed"); 465 PetscCallMPI(MPI_Comm_rank(comm,&rank)); 466 467 /* First processor prints immediately to fp */ 468 if (rank == 0) { 469 va_list Argp; 470 va_start(Argp,format); 471 PetscCall((*PetscVFPrintf)(fp,format,Argp)); 472 if (petsc_history && (fp !=petsc_history)) { 473 va_start(Argp,format); 474 PetscCall((*PetscVFPrintf)(petsc_history,format,Argp)); 475 } 476 va_end(Argp); 477 } else { /* other processors add to local queue */ 478 va_list Argp; 479 PrintfQueue next; 480 size_t fullLength = PETSCDEFAULTBUFFERSIZE; 481 482 PetscCall(PetscNew(&next)); 483 if (petsc_printfqueue) { 484 petsc_printfqueue->next = next; 485 petsc_printfqueue = next; 486 petsc_printfqueue->next = NULL; 487 } else petsc_printfqueuebase = petsc_printfqueue = next; 488 petsc_printfqueuelength++; 489 next->size = 0; 490 next->string = NULL; 491 while (fullLength >= next->size) { 492 next->size = fullLength+1; 493 PetscCall(PetscFree(next->string)); 494 PetscCall(PetscMalloc1(next->size, &next->string)); 495 va_start(Argp,format); 496 PetscCall(PetscArrayzero(next->string,next->size)); 497 PetscCall(PetscVSNPrintf(next->string,next->size,format,&fullLength,Argp)); 498 va_end(Argp); 499 } 500 } 501 PetscFunctionReturn(0); 502 } 503 504 /*@C 505 PetscSynchronizedFlush - Flushes to the screen output from all processors 506 involved in previous PetscSynchronizedPrintf()/PetscSynchronizedFPrintf() calls. 507 508 Collective 509 510 Input Parameters: 511 + comm - the communicator 512 - fd - the file pointer (valid on process 0 of the communicator) 513 514 Level: intermediate 515 516 Notes: 517 If PetscSynchronizedPrintf() and/or PetscSynchronizedFPrintf() are called with 518 different MPI communicators there must be an intervening call to PetscSynchronizedFlush() between the calls with different MPI communicators. 519 520 From Fortran pass PETSC_STDOUT if the flush is for standard out; otherwise pass a value obtained from PetscFOpen() 521 522 .seealso: PetscSynchronizedPrintf(), PetscFPrintf(), PetscPrintf(), PetscViewerASCIIPrintf(), 523 PetscViewerASCIISynchronizedPrintf() 524 @*/ 525 PetscErrorCode PetscSynchronizedFlush(MPI_Comm comm,FILE *fd) 526 { 527 PetscMPIInt rank,size,tag,i,j,n = 0,dummy = 0; 528 char *message; 529 MPI_Status status; 530 531 PetscFunctionBegin; 532 PetscCall(PetscCommDuplicate(comm,&comm,&tag)); 533 PetscCallMPI(MPI_Comm_rank(comm,&rank)); 534 PetscCallMPI(MPI_Comm_size(comm,&size)); 535 536 /* First processor waits for messages from all other processors */ 537 if (rank == 0) { 538 if (!fd) fd = PETSC_STDOUT; 539 for (i=1; i<size; i++) { 540 /* to prevent a flood of messages to process zero, request each message separately */ 541 PetscCallMPI(MPI_Send(&dummy,1,MPI_INT,i,tag,comm)); 542 PetscCallMPI(MPI_Recv(&n,1,MPI_INT,i,tag,comm,&status)); 543 for (j=0; j<n; j++) { 544 PetscMPIInt size = 0; 545 546 PetscCallMPI(MPI_Recv(&size,1,MPI_INT,i,tag,comm,&status)); 547 PetscCall(PetscMalloc1(size, &message)); 548 PetscCallMPI(MPI_Recv(message,size,MPI_CHAR,i,tag,comm,&status)); 549 PetscCall(PetscFPrintf(comm,fd,"%s",message)); 550 PetscCall(PetscFree(message)); 551 } 552 } 553 } else { /* other processors send queue to processor 0 */ 554 PrintfQueue next = petsc_printfqueuebase,previous; 555 556 PetscCallMPI(MPI_Recv(&dummy,1,MPI_INT,0,tag,comm,&status)); 557 PetscCallMPI(MPI_Send(&petsc_printfqueuelength,1,MPI_INT,0,tag,comm)); 558 for (i=0; i<petsc_printfqueuelength; i++) { 559 PetscCallMPI(MPI_Send(&next->size,1,MPI_INT,0,tag,comm)); 560 PetscCallMPI(MPI_Send(next->string,next->size,MPI_CHAR,0,tag,comm)); 561 previous = next; 562 next = next->next; 563 PetscCall(PetscFree(previous->string)); 564 PetscCall(PetscFree(previous)); 565 } 566 petsc_printfqueue = NULL; 567 petsc_printfqueuelength = 0; 568 } 569 PetscCall(PetscCommDestroy(&comm)); 570 PetscFunctionReturn(0); 571 } 572 573 /* ---------------------------------------------------------------------------------------*/ 574 575 /*@C 576 PetscFPrintf - Prints to a file, only from the first 577 processor in the communicator. 578 579 Not Collective 580 581 Input Parameters: 582 + comm - the communicator 583 . fd - the file pointer 584 - format - the usual printf() format string 585 586 Level: intermediate 587 588 Fortran Note: 589 This routine is not supported in Fortran. 590 591 .seealso: PetscPrintf(), PetscSynchronizedPrintf(), PetscViewerASCIIPrintf(), 592 PetscViewerASCIISynchronizedPrintf(), PetscSynchronizedFlush() 593 @*/ 594 PetscErrorCode PetscFPrintf(MPI_Comm comm,FILE* fd,const char format[],...) 595 { 596 PetscMPIInt rank; 597 598 PetscFunctionBegin; 599 PetscCheckFalse(comm == MPI_COMM_NULL,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Called with MPI_COMM_NULL, likely PetscObjectComm() failed"); 600 PetscCallMPI(MPI_Comm_rank(comm,&rank)); 601 if (rank == 0) { 602 va_list Argp; 603 va_start(Argp,format); 604 PetscCall((*PetscVFPrintf)(fd,format,Argp)); 605 if (petsc_history && (fd !=petsc_history)) { 606 va_start(Argp,format); 607 PetscCall((*PetscVFPrintf)(petsc_history,format,Argp)); 608 } 609 va_end(Argp); 610 } 611 PetscFunctionReturn(0); 612 } 613 614 /*@C 615 PetscPrintf - Prints to standard out, only from the first 616 processor in the communicator. Calls from other processes are ignored. 617 618 Not Collective 619 620 Input Parameters: 621 + comm - the communicator 622 - format - the usual printf() format string 623 624 Level: intermediate 625 626 Notes: 627 PetscPrintf() supports some format specifiers that are unique to PETSc. 628 See the manual page for PetscFormatConvert() for details. 629 630 Fortran Note: 631 The call sequence is PetscPrintf(MPI_Comm, character(*), PetscErrorCode ierr) from Fortran. 632 That is, you can only pass a single character string from Fortran. 633 634 .seealso: PetscFPrintf(), PetscSynchronizedPrintf(), PetscFormatConvert() 635 @*/ 636 PetscErrorCode PetscPrintf(MPI_Comm comm,const char format[],...) 637 { 638 PetscMPIInt rank; 639 640 PetscFunctionBegin; 641 PetscCheckFalse(comm == MPI_COMM_NULL,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Called with MPI_COMM_NULL, likely PetscObjectComm() failed"); 642 PetscCallMPI(MPI_Comm_rank(comm,&rank)); 643 if (rank == 0) { 644 va_list Argp; 645 va_start(Argp,format); 646 PetscCall((*PetscVFPrintf)(PETSC_STDOUT,format,Argp)); 647 if (petsc_history) { 648 va_start(Argp,format); 649 PetscCall((*PetscVFPrintf)(petsc_history,format,Argp)); 650 } 651 va_end(Argp); 652 } 653 PetscFunctionReturn(0); 654 } 655 656 PetscErrorCode PetscHelpPrintfDefault(MPI_Comm comm,const char format[],...) 657 { 658 PetscMPIInt rank; 659 660 PetscFunctionBegin; 661 PetscCheckFalse(comm == MPI_COMM_NULL,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Called with MPI_COMM_NULL, likely PetscObjectComm() failed"); 662 PetscCallMPI(MPI_Comm_rank(comm,&rank)); 663 if (rank == 0) { 664 va_list Argp; 665 va_start(Argp,format); 666 PetscCall((*PetscVFPrintf)(PETSC_STDOUT,format,Argp)); 667 if (petsc_history) { 668 va_start(Argp,format); 669 PetscCall((*PetscVFPrintf)(petsc_history,format,Argp)); 670 } 671 va_end(Argp); 672 } 673 PetscFunctionReturn(0); 674 } 675 676 /* ---------------------------------------------------------------------------------------*/ 677 678 /*@C 679 PetscSynchronizedFGets - Several processors all get the same line from a file. 680 681 Collective 682 683 Input Parameters: 684 + comm - the communicator 685 . fd - the file pointer 686 - len - the length of the output buffer 687 688 Output Parameter: 689 . string - the line read from the file, at end of file string[0] == 0 690 691 Level: intermediate 692 693 .seealso: PetscSynchronizedPrintf(), PetscSynchronizedFlush(), 694 PetscFOpen(), PetscViewerASCIISynchronizedPrintf(), PetscViewerASCIIPrintf() 695 696 @*/ 697 PetscErrorCode PetscSynchronizedFGets(MPI_Comm comm,FILE *fp,size_t len,char string[]) 698 { 699 PetscMPIInt rank; 700 701 PetscFunctionBegin; 702 PetscCallMPI(MPI_Comm_rank(comm,&rank)); 703 704 if (rank == 0) { 705 char *ptr = fgets(string, len, fp); 706 707 if (!ptr) { 708 string[0] = 0; 709 PetscCheckFalse(!feof(fp),PETSC_COMM_SELF, PETSC_ERR_FILE_READ, "Error reading from file: %d", errno); 710 } 711 } 712 PetscCallMPI(MPI_Bcast(string,len,MPI_BYTE,0,comm)); 713 PetscFunctionReturn(0); 714 } 715 716 #if defined(PETSC_HAVE_CLOSURE) 717 int (^SwiftClosure)(const char*) = 0; 718 719 PetscErrorCode PetscVFPrintfToString(FILE *fd,const char format[],va_list Argp) 720 { 721 PetscFunctionBegin; 722 if (fd != stdout && fd != stderr) { /* handle regular files */ 723 PetscCall(PetscVFPrintfDefault(fd,format,Argp)); 724 } else { 725 size_t length; 726 char buff[PETSCDEFAULTBUFFERSIZE]; 727 728 PetscCall(PetscVSNPrintf(buff,sizeof(buff),format,&length,Argp)); 729 PetscCall(SwiftClosure(buff)); 730 } 731 PetscFunctionReturn(0); 732 } 733 734 /* 735 Provide a Swift function that processes all the PETSc calls to PetscVFPrintf() 736 */ 737 PetscErrorCode PetscVFPrintfSetClosure(int (^closure)(const char*)) 738 { 739 PetscVFPrintf = PetscVFPrintfToString; 740 SwiftClosure = closure; 741 return 0; 742 } 743 #endif 744 745 /*@C 746 PetscFormatStrip - Takes a PETSc format string and removes all numerical modifiers to % operations 747 748 Input Parameters: 749 . format - the PETSc format string 750 751 Level: developer 752 753 @*/ 754 PetscErrorCode PetscFormatStrip(char *format) 755 { 756 size_t loc1 = 0, loc2 = 0; 757 758 PetscFunctionBegin; 759 while (format[loc2]) { 760 if (format[loc2] == '%') { 761 format[loc1++] = format[loc2++]; 762 while (format[loc2] && ((format[loc2] >= '0' && format[loc2] <= '9') || format[loc2] == '.')) loc2++; 763 } 764 format[loc1++] = format[loc2++]; 765 } 766 PetscFunctionReturn(0); 767 } 768 769 PetscErrorCode PetscFormatRealArray(char buf[],size_t len,const char *fmt,PetscInt n,const PetscReal x[]) 770 { 771 PetscInt i; 772 size_t left,count; 773 char *p; 774 775 PetscFunctionBegin; 776 for (i=0,p=buf,left=len; i<n; i++) { 777 PetscCall(PetscSNPrintfCount(p,left,fmt,&count,(double)x[i])); 778 PetscCheckFalse(count >= left,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Insufficient space in buffer"); 779 left -= count; 780 p += count-1; 781 *p++ = ' '; 782 } 783 p[i ? 0 : -1] = 0; 784 PetscFunctionReturn(0); 785 } 786