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