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