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