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