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