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