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