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, must be long enough to hold result

 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 is used by the test harness)

154:   No Fortran Support

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

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

165:   Level: developer

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.

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()`

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;

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

236: /*@C
237:   PetscFFlush - Flush a file stream

239:   Input Parameter:
240: . fd - The file stream handle

242:   Level: intermediate

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.

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

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

254:   Fortran Note:
255:   Use `PetscFlush()`

257: .seealso: `PetscPrintf()`, `PetscFPrintf()`, `PetscVFPrintf()`, `PetscVSNPrintf()`
258: @*/
259: PetscErrorCode PetscFFlush(FILE *fd)
260: {
261:   int err;

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

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.

279:   No Fortran Support

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

286:   Level: developer

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

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;

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`;

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

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

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;

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

360: /*@C
361:   PetscSNPrintf - Prints to a string of given length

363:   Not Collective, No Fortran Support

365:   Input Parameters:
366: + len    - the length of `str`
367: - format - the usual `printf()` format string

369:   Output Parameter:
370: . str - the resulting string

372:   Level: intermediate

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;

383:   PetscFunctionBegin;
384:   va_start(Argp, format);
385:   PetscCall(PetscVSNPrintf(str, len, format, &fullLength, Argp));
386:   va_end(Argp);
387:   PetscFunctionReturn(PETSC_SUCCESS);
388: }

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

393:   Not Collective, No Fortran Support

395:   Input Parameters:
396: + len    - the length of `str`
397: . format - the usual `printf()` format string
398: - ...    - args to format

400:   Output Parameters:
401: + str       - the resulting string
402: - countused - number of characters printed

404:   Level: intermediate

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;

413:   PetscFunctionBegin;
414:   va_start(Argp, countused);
415:   PetscCall(PetscVSNPrintf(str, len, format, countused, Argp));
416:   va_end(Argp);
417:   PetscFunctionReturn(PETSC_SUCCESS);
418: }

420: PrintfQueue petsc_printfqueue = NULL, petsc_printfqueuebase = NULL;
421: int         petsc_printfqueuelength = 0;

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;

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

439: PETSC_INTERN PetscErrorCode PetscVFPrintf_Internal(FILE *fd, const char format[], ...)
440: {
441:   va_list Argp;

443:   PetscFunctionBegin;
444:   va_start(Argp, format);
445:   PetscCall(PetscVFPrintf_Private(fd, format, Argp));
446:   va_end(Argp);
447:   PetscFunctionReturn(PETSC_SUCCESS);
448: }

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;

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;

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

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.

492:   Not Collective

494:   Input Parameters:
495: + comm   - the MPI communicator
496: - format - the usual `printf()` format string

498:   Level: intermediate

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.

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.

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;

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

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.

528:   Not Collective

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

535:   Level: intermediate

537:   Note:
538:   REQUIRES a intervening call to `PetscSynchronizedFlush()` for the information
539:   from all the processors to be printed.

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.

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;

553:   PetscFunctionBegin;
554:   va_start(Argp, format);
555:   PetscCall(PetscSynchronizedFPrintf_Private(comm, fp, format, Argp));
556:   va_end(Argp);
557:   PetscFunctionReturn(PETSC_SUCCESS);
558: }

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

564:   Collective

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()`

570:   Level: intermediate

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.

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;

585:   PetscFunctionBegin;
586:   PetscCall(PetscCommDuplicate(comm, &comm, &tag));
587:   PetscCallMPI(MPI_Comm_rank(comm, &rank));
588:   PetscCallMPI(MPI_Comm_size(comm, &size));

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;

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;

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

627: /*@C
628:   PetscFPrintf - Prints to a file, only from the first
629:   MPI process in the communicator.

631:   Not Collective

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

638:   Level: intermediate

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.

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.

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;

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

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

669:   Not Collective

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

675:   Level: intermediate

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

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.

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

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

701: PetscErrorCode PetscHelpPrintfDefault(MPI_Comm comm, const char format[], ...)
702: {
703:   PetscMPIInt rank;
704:   va_list     Argp;

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

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

718:   Collective

720:   Input Parameters:
721: + comm - the MPI communicator
722: . fp   - the file pointer
723: - len  - the length of `string`

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

728:   Level: intermediate

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;

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

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;

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