Actual source code: mprint.c

  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;

 24: /*@C
 25:   PetscFormatConvertGetSize - Gets the length of a string needed to hold data converted with `PetscFormatConvert()` based on the format

 27:   No Fortran Support

 29:   Input Parameter:
 30: . format - the PETSc format string

 32:   Output Parameter:
 33: . size - the needed length of the new format

 35:   Level: developer

 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;

 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: }

 78: /*@C
 79:   PetscFormatConvert - converts %g to [|%g|] so that `PetscVSNPrintf()` can ensure all %g formatted numbers have a decimal point when printed.

 81:   No Fortran Support

 83:   Input Parameter:
 84: . format - the PETSc format string

 86:   Output Parameter:
 87: . newformat - the formatted string

 89:   Level: developer

 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.

 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.

 99: .seealso: `PetscFormatConvertGetSize()`, `PetscVSNPrintf()`, `PetscVFPrintf()`
100: @*/
101: PetscErrorCode PetscFormatConvert(const char *format, char *newformat)
102: {
103:   PetscInt i = 0, j = 0;

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: }

149: #define PETSCDEFAULTBUFFERSIZE 8 * 1024

151: /*@C
152:   PetscVSNPrintf - The PETSc version of `vsnprintf()`. Ensures that all `%g` formatted arguments' output contains the decimal point (which
153:   is used by the test harness)

155:   Input Parameters:
156: + str    - location to put result
157: . len    - the length of `str`
158: . format - the PETSc format string
159: - Argp   - the variable argument list to format

161:   Output Parameter:
162: . fullLength - the amount of space in `str` actually used.

164:   Level: developer

166:   Developer Notes:
167:   This function may be called from an error handler, if an error occurs when it is called by the error handler than likely
168:   a recursion will occur resulting in a crash of the program.

170:   If the length of the format string `format` is on the order of `PETSCDEFAULTBUFFERSIZE` (8 * 1024 bytes) or larger, this function will call `PetscMalloc()`

172: .seealso: `PetscFormatConvert()`, `PetscFormatConvertGetSize()`, `PetscErrorPrintf()`, `PetscVPrintf()`
173: @*/
174: PetscErrorCode PetscVSNPrintf(char *str, size_t len, const char *format, size_t *fullLength, va_list Argp)
175: {
176:   char  *newformat = NULL;
177:   char   formatbuf[PETSCDEFAULTBUFFERSIZE];
178:   size_t newLength;
179:   int    flen;

181:   PetscFunctionBegin;
182:   PetscCall(PetscFormatConvertGetSize(format, &newLength));
183:   if (newLength < sizeof(formatbuf)) {
184:     newformat = formatbuf;
185:     newLength = sizeof(formatbuf) - 1;
186:   } else {
187:     PetscCall(PetscMalloc1(newLength, &newformat));
188:   }
189:   PetscCall(PetscFormatConvert(format, newformat));
190: #if defined(PETSC_HAVE_VSNPRINTF)
191:   flen = vsnprintf(str, len, newformat, Argp);
192: #else
193:   #error "vsnprintf not found"
194: #endif
195:   if (newLength > sizeof(formatbuf) - 1) PetscCall(PetscFree(newformat));
196:   {
197:     PetscBool foundedot;
198:     size_t    cnt = 0, ncnt = 0, leng;
199:     PetscCall(PetscStrlen(str, &leng));
200:     if (leng > 4) {
201:       for (cnt = 0; cnt < leng - 4; cnt++) {
202:         if (str[cnt] == '[' && str[cnt + 1] == '|') {
203:           flen -= 4;
204:           cnt++;
205:           cnt++;
206:           foundedot = PETSC_FALSE;
207:           for (; cnt < leng - 1; cnt++) {
208:             if (str[cnt] == '|' && str[cnt + 1] == ']') {
209:               cnt++;
210:               if (!foundedot) str[ncnt++] = '.';
211:               ncnt--;
212:               break;
213:             } else {
214:               if (str[cnt] == 'e' || str[cnt] == '.') foundedot = PETSC_TRUE;
215:               str[ncnt++] = str[cnt];
216:             }
217:           }
218:         } else {
219:           str[ncnt] = str[cnt];
220:         }
221:         ncnt++;
222:       }
223:       while (cnt < leng) {
224:         str[ncnt] = str[cnt];
225:         ncnt++;
226:         cnt++;
227:       }
228:       str[ncnt] = 0;
229:     }
230:   }
231: #if defined(PETSC_HAVE_WINDOWS_H) && !defined(PETSC_HAVE__SET_OUTPUT_FORMAT)
232:   /* older Windows OS always produces e-+0np for floating point output; remove the extra 0 */
233:   {
234:     size_t cnt = 0, ncnt = 0, leng;
235:     PetscCall(PetscStrlen(str, &leng));
236:     if (leng > 5) {
237:       for (cnt = 0; cnt < leng - 4; cnt++) {
238:         if (str[cnt] == 'e' && (str[cnt + 1] == '-' || str[cnt + 1] == '+') && str[cnt + 2] == '0' && str[cnt + 3] >= '0' && str[cnt + 3] <= '9' && str[cnt + 4] >= '0' && str[cnt + 4] <= '9') {
239:           str[ncnt] = str[cnt];
240:           ncnt++;
241:           cnt++;
242:           str[ncnt] = str[cnt];
243:           ncnt++;
244:           cnt++;
245:           cnt++;
246:           str[ncnt] = str[cnt];
247:         } else {
248:           str[ncnt] = str[cnt];
249:         }
250:         ncnt++;
251:       }
252:       while (cnt < leng) {
253:         str[ncnt] = str[cnt];
254:         ncnt++;
255:         cnt++;
256:       }
257:       str[ncnt] = 0;
258:     }
259:   }
260: #endif
261:   if (fullLength) *fullLength = 1 + (size_t)flen;
262:   PetscFunctionReturn(PETSC_SUCCESS);
263: }

265: /*@C
266:   PetscFFlush - Flush a file stream

268:   Input Parameter:
269: . fd - The file stream handle

271:   Level: intermediate

273:   Notes:
274:   For output streams (and for update streams on which the last operation was output), writes
275:   any unwritten data from the stream's buffer to the associated output device.

277:   For input streams (and for update streams on which the last operation was input), the
278:   behavior is undefined.

280:   If `fd` is `NULL`, all open output streams are flushed, including ones not directly
281:   accessible to the program.

283: .seealso: `PetscPrintf()`, `PetscFPrintf()`, `PetscVFPrintf()`, `PetscVSNPrintf()`
284: @*/
285: PetscErrorCode PetscFFlush(FILE *fd)
286: {
287:   PetscFunctionBegin;
288:   if (fd) PetscAssertPointer(fd, 1);
289:   // could also use PetscCallExternal() here, but since we can get additional error explanation
290:   // from strerror() we opted for a manual check
291:   PetscCheck(0 == fflush(fd), PETSC_COMM_SELF, PETSC_ERR_FILE_WRITE, "Error in fflush() due to \"%s\"", strerror(errno));
292:   PetscFunctionReturn(PETSC_SUCCESS);
293: }

295: /*@C
296:   PetscVFPrintfDefault -  All PETSc standard out and error messages are sent through this function; so, in theory, this can
297:   can be replaced with something that does not simply write to a file.

299:   Input Parameters:
300: + fd     - the file descriptor to write to
301: . format - the format string to write with
302: - Argp   - the variable argument list of items to format and write

304:   Level: developer

306:   Note:
307:   For error messages this may be called by any MPI process, for regular standard out it is
308:   called only by MPI rank 0 of a given communicator

310:   Example Usage:
311:   To use, write your own function for example,
312: .vb
313:    PetscErrorCode mypetscvfprintf(FILE *fd, const char format[], va_list Argp)
314:    {
315:      PetscErrorCode ierr;

317:      PetscFunctionBegin;
318:       if (fd != stdout && fd != stderr) {  handle regular files
319:          CHKERR(PetscVFPrintfDefault(fd,format,Argp));
320:      } else {
321:         char   buff[BIG];
322:         size_t length;
323:         PetscCall(PetscVSNPrintf(buff,BIG,format,&length,Argp));
324:         now send buff to whatever stream or whatever you want
325:     }
326:     PetscFunctionReturn(PETSC_SUCCESS);
327:    }
328: .ve
329:   then before the call to `PetscInitialize()` do the assignment `PetscVFPrintf = mypetscvfprintf`;

331:   Developer Notes:
332:   This could be called by an error handler, if that happens then a recursion of the error handler may occur
333:   and a resulting crash

335: .seealso: `PetscVSNPrintf()`, `PetscErrorPrintf()`, `PetscFFlush()`
336: @*/
337: PetscErrorCode PetscVFPrintfDefault(FILE *fd, const char *format, va_list Argp)
338: {
339:   char   str[PETSCDEFAULTBUFFERSIZE];
340:   char  *buff = str;
341:   size_t fullLength;
342: #if defined(PETSC_HAVE_VA_COPY)
343:   va_list Argpcopy;
344: #endif

346:   PetscFunctionBegin;
347: #if defined(PETSC_HAVE_VA_COPY)
348:   va_copy(Argpcopy, Argp);
349: #endif
350:   PetscCall(PetscVSNPrintf(str, sizeof(str), format, &fullLength, Argp));
351:   if (fullLength > sizeof(str)) {
352:     PetscCall(PetscMalloc1(fullLength, &buff));
353: #if defined(PETSC_HAVE_VA_COPY)
354:     PetscCall(PetscVSNPrintf(buff, fullLength, format, NULL, Argpcopy));
355: #else
356:     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "C89 does not support va_copy() hence cannot print long strings with PETSc printing routines");
357: #endif
358:   }
359: #if defined(PETSC_HAVE_VA_COPY)
360:   va_end(Argpcopy);
361: #endif
362:   {
363:     const int err = fprintf(fd, "%s", buff);
364:     // cannot use PetscCallExternal() for fprintf since the return value is "number of
365:     // characters transmitted to the output stream" on success
366:     PetscCheck(err >= 0, PETSC_COMM_SELF, PETSC_ERR_FILE_WRITE, "fprintf() returned error code %d", err);
367:   }
368:   PetscCall(PetscFFlush(fd));
369:   if (buff != str) PetscCall(PetscFree(buff));
370:   PetscFunctionReturn(PETSC_SUCCESS);
371: }

373: /*@C
374:   PetscSNPrintf - Prints to a string of given length

376:   Not Collective

378:   Input Parameters:
379: + len    - the length of `str`
380: - format - the usual `printf()` format string

382:   Output Parameter:
383: . str - the resulting string

385:   Level: intermediate

387: .seealso: `PetscSynchronizedFlush()`, `PetscSynchronizedFPrintf()`, `PetscFPrintf()`, `PetscVSNPrintf()`,
388:           `PetscPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIISynchronizedPrintf()`,
389:           `PetscVFPrintf()`, `PetscFFlush()`
390: @*/
391: PetscErrorCode PetscSNPrintf(char *str, size_t len, const char format[], ...)
392: {
393:   size_t  fullLength;
394:   va_list Argp;

396:   PetscFunctionBegin;
397:   va_start(Argp, format);
398:   PetscCall(PetscVSNPrintf(str, len, format, &fullLength, Argp));
399:   va_end(Argp);
400:   PetscFunctionReturn(PETSC_SUCCESS);
401: }

403: /*@C
404:   PetscSNPrintfCount - Prints to a string of given length, returns count of characters printed

406:   Not Collective

408:   Input Parameters:
409: + len    - the length of `str`
410: . format - the usual `printf()` format string
411: - ...    - args to format

413:   Output Parameters:
414: + str       - the resulting string
415: - countused - number of characters printed

417:   Level: intermediate

419: .seealso: `PetscSynchronizedFlush()`, `PetscSynchronizedFPrintf()`, `PetscFPrintf()`, `PetscVSNPrintf()`,
420:           `PetscPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscSNPrintf()`, `PetscVFPrintf()`
421: @*/
422: PetscErrorCode PetscSNPrintfCount(char *str, size_t len, const char format[], size_t *countused, ...)
423: {
424:   va_list Argp;

426:   PetscFunctionBegin;
427:   va_start(Argp, countused);
428:   PetscCall(PetscVSNPrintf(str, len, format, countused, Argp));
429:   va_end(Argp);
430:   PetscFunctionReturn(PETSC_SUCCESS);
431: }

433: PrintfQueue petsc_printfqueue = NULL, petsc_printfqueuebase = NULL;
434: int         petsc_printfqueuelength = 0;

436: static inline PetscErrorCode PetscVFPrintf_Private(MPI_Comm comm, FILE *fd, const char format[], va_list Argp)
437: {
438:   const PetscBool tee = (PetscBool)(petsc_history && (fd != petsc_history));
439:   PetscMPIInt     rank;
440:   va_list         cpy;

442:   PetscFunctionBegin;
443:   PetscCheck(comm != MPI_COMM_NULL, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Called with MPI_COMM_NULL, likely PetscObjectComm() failed");
444:   PetscCallMPI(MPI_Comm_rank(comm, &rank));
445:   if (PetscLikely(rank != 0)) PetscFunctionReturn(PETSC_SUCCESS);
446:   // must do this before we possibly consume Argp
447:   if (tee) va_copy(cpy, Argp);
448:   PetscCall((*PetscVFPrintf)(fd, format, Argp));
449:   if (tee) {
450:     PetscCall((*PetscVFPrintf)(petsc_history, format, cpy));
451:     va_end(cpy);
452:   }
453:   PetscFunctionReturn(PETSC_SUCCESS);
454: }

456: static inline PetscErrorCode PetscSynchronizedFPrintf_Private(MPI_Comm comm, FILE *fp, const char format[], va_list Argp)
457: {
458:   PetscMPIInt rank;
459:   va_list     cpy;

461:   PetscFunctionBegin;
462:   PetscCheck(comm != MPI_COMM_NULL, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Called with MPI_COMM_NULL, likely PetscObjectComm() failed");
463:   PetscCallMPI(MPI_Comm_rank(comm, &rank));
464:   /* First processor prints immediately to fp */
465:   if (rank == 0) {
466:     va_copy(cpy, Argp);
467:     PetscCall(PetscVFPrintf_Private(comm, fp, format, cpy));
468:     va_end(cpy);
469:   } else { /* other processors add to local queue */
470:     PrintfQueue next;
471:     size_t      fullLength = PETSCDEFAULTBUFFERSIZE;

473:     PetscCall(PetscNew(&next));
474:     if (petsc_printfqueue) {
475:       petsc_printfqueue->next = next;
476:       petsc_printfqueue       = next;
477:       petsc_printfqueue->next = NULL;
478:     } else petsc_printfqueuebase = petsc_printfqueue = next;
479:     petsc_printfqueuelength++;
480:     next->size   = 0;
481:     next->string = NULL;
482:     while (fullLength >= next->size) {
483:       next->size = fullLength + 1;
484:       PetscCall(PetscFree(next->string));
485:       PetscCall(PetscMalloc1(next->size, &next->string));
486:       PetscCall(PetscArrayzero(next->string, next->size));
487:       va_copy(cpy, Argp);
488:       PetscCall(PetscVSNPrintf(next->string, next->size, format, &fullLength, cpy));
489:       va_end(cpy);
490:     }
491:   }
492:   PetscFunctionReturn(PETSC_SUCCESS);
493: }

495: /*@C
496:   PetscSynchronizedPrintf - Prints synchronized output from multiple MPI processes.
497:   Output of the first processor is followed by that of the second, etc.

499:   Not Collective

501:   Input Parameters:
502: + comm   - the MPI communicator
503: - format - the usual `printf()` format string

505:   Level: intermediate

507:   Note:
508:   REQUIRES a call to `PetscSynchronizedFlush()` by all the processes after the completion of the calls to `PetscSynchronizedPrintf()` for the information
509:   from all the processors to be printed.

511:   Fortran Notes:
512:   The call sequence is `PetscSynchronizedPrintf`(`MPI_Comm`, `character`(*), `PetscErrorCode` ierr).
513:   That is, you can only pass a single character string from Fortran.

515: .seealso: `PetscSynchronizedFlush()`, `PetscSynchronizedFPrintf()`, `PetscFPrintf()`,
516:           `PetscPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIISynchronizedPrintf()`,
517:           `PetscFFlush()`
518: @*/
519: PetscErrorCode PetscSynchronizedPrintf(MPI_Comm comm, const char format[], ...)
520: {
521:   va_list Argp;

523:   PetscFunctionBegin;
524:   va_start(Argp, format);
525:   PetscCall(PetscSynchronizedFPrintf_Private(comm, PETSC_STDOUT, format, Argp));
526:   va_end(Argp);
527:   PetscFunctionReturn(PETSC_SUCCESS);
528: }

530: /*@C
531:   PetscSynchronizedFPrintf - Prints synchronized output to the specified file from
532:   several MPI processes.  Output of the first process is followed by that of the
533:   second, etc.

535:   Not Collective

537:   Input Parameters:
538: + comm   - the MPI communicator
539: . fp     - the file pointer
540: - format - the usual `printf()` format string

542:   Level: intermediate

544:   Note:
545:   REQUIRES a intervening call to `PetscSynchronizedFlush()` for the information
546:   from all the processors to be printed.

548: .seealso: `PetscSynchronizedPrintf()`, `PetscSynchronizedFlush()`, `PetscFPrintf()`,
549:           `PetscFOpen()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
550:           `PetscFFlush()`
551: @*/
552: PetscErrorCode PetscSynchronizedFPrintf(MPI_Comm comm, FILE *fp, const char format[], ...)
553: {
554:   va_list Argp;

556:   PetscFunctionBegin;
557:   va_start(Argp, format);
558:   PetscCall(PetscSynchronizedFPrintf_Private(comm, fp, format, Argp));
559:   va_end(Argp);
560:   PetscFunctionReturn(PETSC_SUCCESS);
561: }

563: /*@C
564:   PetscSynchronizedFlush - Flushes to the screen output from all processors
565:   involved in previous `PetscSynchronizedPrintf()`/`PetscSynchronizedFPrintf()` calls.

567:   Collective

569:   Input Parameters:
570: + comm - the MPI communicator
571: - fd   - the file pointer (valid on MPI rank 0 of the communicator)

573:   Level: intermediate

575:   Note:
576:   If `PetscSynchronizedPrintf()` and/or `PetscSynchronizedFPrintf()` are called with
577:   different MPI communicators there must be an intervening call to `PetscSynchronizedFlush()` between the calls with different MPI communicators.

579:   Fortran Notes:
580:   Pass `PETSC_STDOUT` if the flush is for standard out; otherwise pass a value obtained from `PetscFOpen()`

582: .seealso: `PetscSynchronizedPrintf()`, `PetscFPrintf()`, `PetscPrintf()`, `PetscViewerASCIIPrintf()`,
583:           `PetscViewerASCIISynchronizedPrintf()`
584: @*/
585: PetscErrorCode PetscSynchronizedFlush(MPI_Comm comm, FILE *fd)
586: {
587:   PetscMPIInt rank, size, tag, i, j, n = 0, dummy = 0;
588:   char       *message;
589:   MPI_Status  status;

591:   PetscFunctionBegin;
592:   PetscCall(PetscCommDuplicate(comm, &comm, &tag));
593:   PetscCallMPI(MPI_Comm_rank(comm, &rank));
594:   PetscCallMPI(MPI_Comm_size(comm, &size));

596:   /* First processor waits for messages from all other processors */
597:   if (rank == 0) {
598:     if (!fd) fd = PETSC_STDOUT;
599:     for (i = 1; i < size; i++) {
600:       /* to prevent a flood of messages to process zero, request each message separately */
601:       PetscCallMPI(MPI_Send(&dummy, 1, MPI_INT, i, tag, comm));
602:       PetscCallMPI(MPI_Recv(&n, 1, MPI_INT, i, tag, comm, &status));
603:       for (j = 0; j < n; j++) {
604:         PetscMPIInt size = 0;

606:         PetscCallMPI(MPI_Recv(&size, 1, MPI_INT, i, tag, comm, &status));
607:         PetscCall(PetscMalloc1(size, &message));
608:         PetscCallMPI(MPI_Recv(message, size, MPI_CHAR, i, tag, comm, &status));
609:         PetscCall(PetscFPrintf(comm, fd, "%s", message));
610:         PetscCall(PetscFree(message));
611:       }
612:     }
613:   } else { /* other processors send queue to processor 0 */
614:     PrintfQueue next = petsc_printfqueuebase, previous;

616:     PetscCallMPI(MPI_Recv(&dummy, 1, MPI_INT, 0, tag, comm, &status));
617:     PetscCallMPI(MPI_Send(&petsc_printfqueuelength, 1, MPI_INT, 0, tag, comm));
618:     for (i = 0; i < petsc_printfqueuelength; i++) {
619:       PetscCallMPI(MPI_Send(&next->size, 1, MPI_INT, 0, tag, comm));
620:       PetscCallMPI(MPI_Send(next->string, next->size, MPI_CHAR, 0, tag, comm));
621:       previous = next;
622:       next     = next->next;
623:       PetscCall(PetscFree(previous->string));
624:       PetscCall(PetscFree(previous));
625:     }
626:     petsc_printfqueue       = NULL;
627:     petsc_printfqueuelength = 0;
628:   }
629:   PetscCall(PetscCommDestroy(&comm));
630:   PetscFunctionReturn(PETSC_SUCCESS);
631: }

633: /*@C
634:   PetscFPrintf - Prints to a file, only from the first
635:   MPI process in the communicator.

637:   Not Collective; No Fortran Support

639:   Input Parameters:
640: + comm   - the MPI communicator
641: . fd     - the file pointer
642: - format - the usual `printf()` format string

644:   Level: intermediate

646:   Developer Notes:
647:   This maybe, and is, called from PETSc error handlers and `PetscMallocValidate()` hence it does not use `PetscCallMPI()` which
648:   could recursively restart the malloc validation.

650: .seealso: `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
651:           `PetscViewerASCIISynchronizedPrintf()`, `PetscSynchronizedFlush()`, `PetscFFlush()`
652: @*/
653: PetscErrorCode PetscFPrintf(MPI_Comm comm, FILE *fd, const char format[], ...)
654: {
655:   va_list Argp;

657:   PetscFunctionBegin;
658:   va_start(Argp, format);
659:   PetscCall(PetscVFPrintf_Private(comm, fd, format, Argp));
660:   va_end(Argp);
661:   PetscFunctionReturn(PETSC_SUCCESS);
662: }

664: /*@C
665:   PetscPrintf - Prints to standard out, only from the first
666:   MPI process in the communicator. Calls from other processes are ignored.

668:   Not Collective

670:   Input Parameters:
671: + comm   - the communicator
672: - format - the usual `printf()` format string

674:   Level: intermediate

676:   Note:
677:   Deprecated information: `PetscPrintf()` supports some format specifiers that are unique to PETSc.
678:   See the manual page for `PetscFormatConvert()` for details.

680:   Fortran Notes:
681:   The call sequence is `PetscPrintf`(MPI_Comm, character(*), `PetscErrorCode` ierr) from Fortran.
682:   That is, you can only pass a single character string from Fortran.

684: .seealso: `PetscFPrintf()`, `PetscSynchronizedPrintf()`, `PetscFormatConvert()`, `PetscFFlush()`
685: @*/
686: PetscErrorCode PetscPrintf(MPI_Comm comm, const char format[], ...)
687: {
688:   va_list Argp;

690:   PetscFunctionBegin;
691:   va_start(Argp, format);
692:   PetscCall(PetscVFPrintf_Private(comm, PETSC_STDOUT, format, Argp));
693:   va_end(Argp);
694:   PetscFunctionReturn(PETSC_SUCCESS);
695: }

697: PetscErrorCode PetscHelpPrintfDefault(MPI_Comm comm, const char format[], ...)
698: {
699:   va_list Argp;

701:   PetscFunctionBegin;
702:   va_start(Argp, format);
703:   PetscCall(PetscVFPrintf_Private(comm, PETSC_STDOUT, format, Argp));
704:   va_end(Argp);
705:   PetscFunctionReturn(PETSC_SUCCESS);
706: }

708: /*@C
709:   PetscSynchronizedFGets - Multiple MPI processes all get the same line from a file.

711:   Collective

713:   Input Parameters:
714: + comm - the MPI communicator
715: . fp   - the file pointer
716: - len  - the length of `string`

718:   Output Parameter:
719: . string - the line read from the file, at end of file `string`[0] == 0

721:   Level: intermediate

723: .seealso: `PetscSynchronizedPrintf()`, `PetscSynchronizedFlush()`,
724:           `PetscFOpen()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIPrintf()`
725: @*/
726: PetscErrorCode PetscSynchronizedFGets(MPI_Comm comm, FILE *fp, size_t len, char string[])
727: {
728:   PetscMPIInt rank;

730:   PetscFunctionBegin;
731:   PetscCallMPI(MPI_Comm_rank(comm, &rank));
732:   if (rank == 0) {
733:     if (!fgets(string, len, fp)) {
734:       string[0] = 0;
735:       PetscCheck(feof(fp), PETSC_COMM_SELF, PETSC_ERR_FILE_READ, "Error reading from file due to \"%s\"", strerror(errno));
736:     }
737:   }
738:   PetscCallMPI(MPI_Bcast(string, len, MPI_BYTE, 0, comm));
739:   PetscFunctionReturn(PETSC_SUCCESS);
740: }

742: PetscErrorCode PetscFormatRealArray(char buf[], size_t len, const char *fmt, PetscInt n, const PetscReal x[])
743: {
744:   PetscInt i;
745:   size_t   left, count;
746:   char    *p;

748:   PetscFunctionBegin;
749:   for (i = 0, p = buf, left = len; i < n; i++) {
750:     PetscCall(PetscSNPrintfCount(p, left, fmt, &count, (double)x[i]));
751:     PetscCheck(count < left, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Insufficient space in buffer");
752:     left -= count;
753:     p += count - 1;
754:     *p++ = ' ';
755:   }
756:   p[i ? 0 : -1] = 0;
757:   PetscFunctionReturn(PETSC_SUCCESS);
758: }