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 328 PetscFunctionBegin; 329 if (fd != stdout && fd != stderr) { handle regular files 330 CHKERR(PetscVFPrintfDefault(fd,format,Argp)); 331 } else { 332 char buff[BIG]; 333 size_t length; 334 PetscCall(PetscVSNPrintf(buff,BIG,format,&length,Argp)); 335 now send buff to whatever stream or whatever you want 336 } 337 PetscFunctionReturn(PETSC_SUCCESS); 338 } 339 .ve 340 then before the call to `PetscInitialize()` do the assignment `PetscVFPrintf = mypetscvfprintf`; 341 342 Developer Notes: 343 This could be called by an error handler, if that happens then a recursion of the error handler may occur 344 and a resulting crash 345 346 .seealso: `PetscVSNPrintf()`, `PetscErrorPrintf()`, `PetscFFlush()` 347 @*/ 348 PetscErrorCode PetscVFPrintfDefault(FILE *fd, const char format[], va_list Argp) 349 { 350 char str[PETSCDEFAULTBUFFERSIZE]; 351 char *buff = str; 352 size_t fullLength; 353 #if defined(PETSC_HAVE_VA_COPY) 354 va_list Argpcopy; 355 #endif 356 357 PetscFunctionBegin; 358 #if defined(PETSC_HAVE_VA_COPY) 359 va_copy(Argpcopy, Argp); 360 #endif 361 PetscCall(PetscVSNPrintf(str, sizeof(str), format, &fullLength, Argp)); 362 if (fullLength > sizeof(str)) { 363 PetscCall(PetscMalloc1(fullLength, &buff)); 364 #if defined(PETSC_HAVE_VA_COPY) 365 PetscCall(PetscVSNPrintf(buff, fullLength, format, NULL, Argpcopy)); 366 #else 367 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "C89 does not support va_copy() hence cannot print long strings with PETSc printing routines"); 368 #endif 369 } 370 #if defined(PETSC_HAVE_VA_COPY) 371 va_end(Argpcopy); 372 #endif 373 { 374 int err; 375 376 // POSIX C sets errno but otherwise it may not be set for *printf() system calls 377 // https://pubs.opengroup.org/onlinepubs/9699919799/functions/fprintf.html 378 errno = 0; 379 err = fprintf(fd, "%s", buff); 380 // cannot use PetscCallExternal() for fprintf since the return value is "number of 381 // characters transmitted to the output stream" on success 382 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)"); 383 } 384 PetscCall(PetscFFlush(fd)); 385 if (buff != str) PetscCall(PetscFree(buff)); 386 PetscFunctionReturn(PETSC_SUCCESS); 387 } 388 389 /*@C 390 PetscSNPrintf - Prints to a string of given length 391 392 Not Collective, No Fortran Support 393 394 Input Parameters: 395 + len - the length of `str` 396 - format - the usual `printf()` format string 397 398 Output Parameter: 399 . str - the resulting string 400 401 Level: intermediate 402 403 .seealso: `PetscSynchronizedFlush()`, `PetscSynchronizedFPrintf()`, `PetscFPrintf()`, `PetscVSNPrintf()`, 404 `PetscPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIISynchronizedPrintf()`, 405 `PetscVFPrintf()`, `PetscFFlush()` 406 @*/ 407 PetscErrorCode PetscSNPrintf(char str[], size_t len, const char format[], ...) 408 { 409 size_t fullLength; 410 va_list Argp; 411 412 PetscFunctionBegin; 413 va_start(Argp, format); 414 PetscCall(PetscVSNPrintf(str, len, format, &fullLength, Argp)); 415 va_end(Argp); 416 PetscFunctionReturn(PETSC_SUCCESS); 417 } 418 419 /*@C 420 PetscSNPrintfCount - Prints to a string of given length, returns count of characters printed 421 422 Not Collective, No Fortran Support 423 424 Input Parameters: 425 + len - the length of `str` 426 . format - the usual `printf()` format string 427 - ... - args to format 428 429 Output Parameters: 430 + str - the resulting string 431 - countused - number of characters printed 432 433 Level: intermediate 434 435 .seealso: `PetscSynchronizedFlush()`, `PetscSynchronizedFPrintf()`, `PetscFPrintf()`, `PetscVSNPrintf()`, 436 `PetscPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscSNPrintf()`, `PetscVFPrintf()` 437 @*/ 438 PetscErrorCode PetscSNPrintfCount(char str[], size_t len, const char format[], size_t *countused, ...) 439 { 440 va_list Argp; 441 442 PetscFunctionBegin; 443 va_start(Argp, countused); 444 PetscCall(PetscVSNPrintf(str, len, format, countused, Argp)); 445 va_end(Argp); 446 PetscFunctionReturn(PETSC_SUCCESS); 447 } 448 449 PrintfQueue petsc_printfqueue = NULL, petsc_printfqueuebase = NULL; 450 int petsc_printfqueuelength = 0; 451 452 static inline PetscErrorCode PetscVFPrintf_Private(FILE *fd, const char format[], va_list Argp) 453 { 454 const PetscBool tee = (PetscBool)(petsc_history && (fd != petsc_history)); 455 va_list cpy; 456 457 PetscFunctionBegin; 458 // must do this before we possibly consume Argp 459 if (tee) va_copy(cpy, Argp); 460 PetscCall((*PetscVFPrintf)(fd, format, Argp)); 461 if (tee) { 462 PetscCall((*PetscVFPrintf)(petsc_history, format, cpy)); 463 va_end(cpy); 464 } 465 PetscFunctionReturn(PETSC_SUCCESS); 466 } 467 468 PETSC_INTERN PetscErrorCode PetscVFPrintf_Internal(FILE *fd, const char format[], ...) 469 { 470 va_list Argp; 471 472 PetscFunctionBegin; 473 va_start(Argp, format); 474 PetscCall(PetscVFPrintf_Private(fd, format, Argp)); 475 va_end(Argp); 476 PetscFunctionReturn(PETSC_SUCCESS); 477 } 478 479 static inline PetscErrorCode PetscSynchronizedFPrintf_Private(MPI_Comm comm, FILE *fp, const char format[], va_list Argp) 480 { 481 PetscMPIInt rank; 482 va_list cpy; 483 484 PetscFunctionBegin; 485 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 486 /* First processor prints immediately to fp */ 487 if (rank == 0) { 488 va_copy(cpy, Argp); 489 PetscCall(PetscVFPrintf_Private(fp, format, cpy)); 490 va_end(cpy); 491 } else { /* other processors add to local queue */ 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 PetscCall(PetscArrayzero(next->string, next->size)); 509 va_copy(cpy, Argp); 510 PetscCall(PetscVSNPrintf(next->string, next->size, format, &fullLength, cpy)); 511 va_end(cpy); 512 } 513 } 514 PetscFunctionReturn(PETSC_SUCCESS); 515 } 516 517 /*@C 518 PetscSynchronizedPrintf - Prints synchronized output from multiple MPI processes. 519 Output of the first processor is followed by that of the second, etc. 520 521 Not Collective 522 523 Input Parameters: 524 + comm - the MPI communicator 525 - format - the usual `printf()` format string 526 527 Level: intermediate 528 529 Note: 530 REQUIRES a call to `PetscSynchronizedFlush()` by all the processes after the completion of the calls to `PetscSynchronizedPrintf()` for the information 531 from all the processors to be printed. 532 533 Fortran Note: 534 The call sequence is `PetscSynchronizedPrintf`(`MPI_Comm`, `character`(*), `PetscErrorCode` ierr). 535 That is, you can only pass a single character string from Fortran. 536 537 .seealso: `PetscSynchronizedFlush()`, `PetscSynchronizedFPrintf()`, `PetscFPrintf()`, 538 `PetscPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIISynchronizedPrintf()`, 539 `PetscFFlush()` 540 @*/ 541 PetscErrorCode PetscSynchronizedPrintf(MPI_Comm comm, const char format[], ...) 542 { 543 va_list Argp; 544 545 PetscFunctionBegin; 546 va_start(Argp, format); 547 PetscCall(PetscSynchronizedFPrintf_Private(comm, PETSC_STDOUT, format, Argp)); 548 va_end(Argp); 549 PetscFunctionReturn(PETSC_SUCCESS); 550 } 551 552 /*@C 553 PetscSynchronizedFPrintf - Prints synchronized output to the specified file from 554 several MPI processes. Output of the first process is followed by that of the 555 second, etc. 556 557 Not Collective 558 559 Input Parameters: 560 + comm - the MPI communicator 561 . fp - the file pointer, `PETSC_STDOUT` or value obtained from `PetscFOpen()` 562 - format - the usual `printf()` format string 563 564 Level: intermediate 565 566 Note: 567 REQUIRES a intervening call to `PetscSynchronizedFlush()` for the information 568 from all the processors to be printed. 569 570 Fortran Note: 571 The call sequence is `PetscSynchronizedPrintf`(`MPI_Comm`, fp, `character`(*), `PetscErrorCode` ierr). 572 That is, you can only pass a single character string from Fortran. 573 574 .seealso: `PetscSynchronizedPrintf()`, `PetscSynchronizedFlush()`, `PetscFPrintf()`, 575 `PetscFOpen()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, 576 `PetscFFlush()` 577 @*/ 578 PetscErrorCode PetscSynchronizedFPrintf(MPI_Comm comm, FILE *fp, const char format[], ...) 579 { 580 va_list Argp; 581 582 PetscFunctionBegin; 583 va_start(Argp, format); 584 PetscCall(PetscSynchronizedFPrintf_Private(comm, fp, format, Argp)); 585 va_end(Argp); 586 PetscFunctionReturn(PETSC_SUCCESS); 587 } 588 589 /*@C 590 PetscSynchronizedFlush - Flushes to the screen output from all processors 591 involved in previous `PetscSynchronizedPrintf()`/`PetscSynchronizedFPrintf()` calls. 592 593 Collective 594 595 Input Parameters: 596 + comm - the MPI communicator 597 - fd - the file pointer (valid on MPI rank 0 of the communicator), `PETSC_STDOUT` or value obtained from `PetscFOpen()` 598 599 Level: intermediate 600 601 Note: 602 If `PetscSynchronizedPrintf()` and/or `PetscSynchronizedFPrintf()` are called with 603 different MPI communicators there must be an intervening call to `PetscSynchronizedFlush()` between the calls with different MPI communicators. 604 605 .seealso: `PetscSynchronizedPrintf()`, `PetscFPrintf()`, `PetscPrintf()`, `PetscViewerASCIIPrintf()`, 606 `PetscViewerASCIISynchronizedPrintf()` 607 @*/ 608 PetscErrorCode PetscSynchronizedFlush(MPI_Comm comm, FILE *fd) 609 { 610 PetscMPIInt rank, size, tag, i, j, n = 0, dummy = 0; 611 char *message; 612 MPI_Status status; 613 614 PetscFunctionBegin; 615 PetscCall(PetscCommDuplicate(comm, &comm, &tag)); 616 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 617 PetscCallMPI(MPI_Comm_size(comm, &size)); 618 619 /* First processor waits for messages from all other processors */ 620 if (rank == 0) { 621 if (!fd) fd = PETSC_STDOUT; 622 for (i = 1; i < size; i++) { 623 /* to prevent a flood of messages to process zero, request each message separately */ 624 PetscCallMPI(MPI_Send(&dummy, 1, MPI_INT, i, tag, comm)); 625 PetscCallMPI(MPI_Recv(&n, 1, MPI_INT, i, tag, comm, &status)); 626 for (j = 0; j < n; j++) { 627 PetscMPIInt size = 0; 628 629 PetscCallMPI(MPI_Recv(&size, 1, MPI_INT, i, tag, comm, &status)); 630 PetscCall(PetscMalloc1(size, &message)); 631 PetscCallMPI(MPI_Recv(message, size, MPI_CHAR, i, tag, comm, &status)); 632 PetscCall(PetscFPrintf(comm, fd, "%s", message)); 633 PetscCall(PetscFree(message)); 634 } 635 } 636 } else { /* other processors send queue to processor 0 */ 637 PrintfQueue next = petsc_printfqueuebase, previous; 638 639 PetscCallMPI(MPI_Recv(&dummy, 1, MPI_INT, 0, tag, comm, &status)); 640 PetscCallMPI(MPI_Send(&petsc_printfqueuelength, 1, MPI_INT, 0, tag, comm)); 641 for (i = 0; i < petsc_printfqueuelength; i++) { 642 PetscCallMPI(MPI_Send(&next->size, 1, MPI_INT, 0, tag, comm)); 643 PetscCallMPI(MPI_Send(next->string, (PetscMPIInt)next->size, MPI_CHAR, 0, tag, comm)); 644 previous = next; 645 next = next->next; 646 PetscCall(PetscFree(previous->string)); 647 PetscCall(PetscFree(previous)); 648 } 649 petsc_printfqueue = NULL; 650 petsc_printfqueuelength = 0; 651 } 652 PetscCall(PetscCommDestroy(&comm)); 653 PetscFunctionReturn(PETSC_SUCCESS); 654 } 655 656 /*@C 657 PetscFPrintf - Prints to a file, only from the first 658 MPI process in the communicator. 659 660 Not Collective 661 662 Input Parameters: 663 + comm - the MPI communicator 664 . fd - the file pointer, `PETSC_STDOUT` or value obtained from `PetscFOpen()` 665 - format - the usual `printf()` format string 666 667 Level: intermediate 668 669 Fortran Note: 670 The call sequence is `PetscFPrintf`(`MPI_Comm`, fp, `character`(*), `PetscErrorCode` ierr). 671 That is, you can only pass a single character string from Fortran. 672 673 Developer Notes: 674 This maybe, and is, called from PETSc error handlers and `PetscMallocValidate()` hence it does not use `PetscCallMPI()` which 675 could recursively restart the malloc validation. 676 677 .seealso: `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, 678 `PetscViewerASCIISynchronizedPrintf()`, `PetscSynchronizedFlush()`, `PetscFFlush()` 679 @*/ 680 PetscErrorCode PetscFPrintf(MPI_Comm comm, FILE *fd, const char format[], ...) 681 { 682 PetscMPIInt rank; 683 va_list Argp; 684 685 PetscFunctionBegin; 686 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 687 if (PetscLikely(rank != 0)) PetscFunctionReturn(PETSC_SUCCESS); 688 va_start(Argp, format); 689 PetscCall(PetscVFPrintf_Private(fd, format, Argp)); 690 va_end(Argp); 691 PetscFunctionReturn(PETSC_SUCCESS); 692 } 693 694 /*@C 695 PetscPrintf - Prints to standard out, only from the first 696 MPI process in the communicator. Calls from other processes are ignored. 697 698 Not Collective 699 700 Input Parameters: 701 + comm - the communicator 702 - format - the usual `printf()` format string 703 704 Level: intermediate 705 706 Note: 707 Deprecated information: `PetscPrintf()` supports some format specifiers that are unique to PETSc. 708 See the manual page for `PetscFormatConvert()` for details. 709 710 Fortran Notes: 711 The call sequence is `PetscPrintf`(MPI_Comm, character(*), `PetscErrorCode` ierr) from Fortran. 712 That is, you can only pass a single character string from Fortran. 713 714 .seealso: `PetscFPrintf()`, `PetscSynchronizedPrintf()`, `PetscFormatConvert()`, `PetscFFlush()` 715 @*/ 716 PetscErrorCode PetscPrintf(MPI_Comm comm, const char format[], ...) 717 { 718 PetscMPIInt rank; 719 va_list Argp; 720 721 PetscFunctionBegin; 722 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 723 if (PetscLikely(rank != 0)) PetscFunctionReturn(PETSC_SUCCESS); 724 va_start(Argp, format); 725 PetscCall(PetscVFPrintf_Private(PETSC_STDOUT, format, Argp)); 726 va_end(Argp); 727 PetscFunctionReturn(PETSC_SUCCESS); 728 } 729 730 PetscErrorCode PetscHelpPrintfDefault(MPI_Comm comm, const char format[], ...) 731 { 732 PetscMPIInt rank; 733 va_list Argp; 734 735 PetscFunctionBegin; 736 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 737 if (PetscLikely(rank != 0)) PetscFunctionReturn(PETSC_SUCCESS); 738 va_start(Argp, format); 739 PetscCall(PetscVFPrintf_Private(PETSC_STDOUT, format, Argp)); 740 va_end(Argp); 741 PetscFunctionReturn(PETSC_SUCCESS); 742 } 743 744 /*@C 745 PetscSynchronizedFGets - Multiple MPI processes all get the same line from a file. 746 747 Collective 748 749 Input Parameters: 750 + comm - the MPI communicator 751 . fp - the file pointer 752 - len - the length of `string` 753 754 Output Parameter: 755 . string - the line read from the file, at end of file `string`[0] == 0 756 757 Level: intermediate 758 759 .seealso: `PetscSynchronizedPrintf()`, `PetscSynchronizedFlush()`, 760 `PetscFOpen()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIPrintf()` 761 @*/ 762 PetscErrorCode PetscSynchronizedFGets(MPI_Comm comm, FILE *fp, size_t len, char string[]) 763 { 764 PetscMPIInt rank; 765 766 PetscFunctionBegin; 767 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 768 if (rank == 0) { 769 if (!fgets(string, (int)len, fp)) { 770 string[0] = 0; 771 PetscCheck(feof(fp), PETSC_COMM_SELF, PETSC_ERR_FILE_READ, "Error reading from file due to \"%s\"", strerror(errno)); 772 } 773 } 774 PetscCallMPI(MPI_Bcast(string, (PetscMPIInt)len, MPI_BYTE, 0, comm)); 775 PetscFunctionReturn(PETSC_SUCCESS); 776 } 777 778 PetscErrorCode PetscFormatRealArray(char buf[], size_t len, const char *fmt, PetscInt n, const PetscReal x[]) 779 { 780 PetscInt i; 781 size_t left, count; 782 char *p; 783 784 PetscFunctionBegin; 785 for (i = 0, p = buf, left = len; i < n; i++) { 786 PetscCall(PetscSNPrintfCount(p, left, fmt, &count, (double)x[i])); 787 PetscCheck(count < left, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Insufficient space in buffer"); 788 left -= count; 789 p += count - 1; 790 *p++ = ' '; 791 } 792 p[i ? 0 : -1] = 0; 793 PetscFunctionReturn(PETSC_SUCCESS); 794 } 795