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