xref: /petsc/src/sys/fileio/mprint.c (revision a3b724e88d046d3fedf46cc78f622355d8be981f)
1e5c89e4eSSatish Balay /*
2da81f932SPierre Jolivet       Utilities routines to add simple ASCII IO capability.
3e5c89e4eSSatish Balay */
4c6db04a5SJed Brown #include <../src/sys/fileio/mprint.h>
579c0e996SJed Brown #include <errno.h>
6e5c89e4eSSatish Balay /*
7e5c89e4eSSatish Balay    If petsc_history is on, then all Petsc*Printf() results are saved
8e5c89e4eSSatish Balay    if the appropriate (usually .petschistory) file.
9e5c89e4eSSatish Balay */
1095c0884eSLisandro Dalcin PETSC_INTERN FILE *petsc_history;
11e5c89e4eSSatish Balay /*
12e5c89e4eSSatish Balay      Allows one to overwrite where standard out is sent. For example
135106ddf5SBarry Smith      PETSC_STDOUT = fopen("/dev/ttyXX","w") will cause all standard out
14e5c89e4eSSatish Balay      writes to go to terminal XX; assuming you have write permission there
15e5c89e4eSSatish Balay */
1602c9f0b5SLisandro Dalcin FILE *PETSC_STDOUT = NULL;
17ae9b4142SLisandro Dalcin /*
18ae9b4142SLisandro Dalcin      Allows one to overwrite where standard error is sent. For example
19ae9b4142SLisandro Dalcin      PETSC_STDERR = fopen("/dev/ttyXX","w") will cause all standard error
20ae9b4142SLisandro Dalcin      writes to go to terminal XX; assuming you have write permission there
21ae9b4142SLisandro Dalcin */
2202c9f0b5SLisandro Dalcin FILE *PETSC_STDERR = NULL;
23b13499bfSbcordonn 
24c9a19010SBarry Smith /*@C
2521532e8aSBarry Smith   PetscFormatConvertGetSize - Gets the length of a string needed to hold data converted with `PetscFormatConvert()` based on the format
26811af0c4SBarry Smith 
27058c9ee1SBarry Smith   No Fortran Support
28c9a19010SBarry Smith 
29d781fa04SBarry Smith   Input Parameter:
30d781fa04SBarry Smith . format - the PETSc format string
31c9a19010SBarry Smith 
32d781fa04SBarry Smith   Output Parameter:
33d781fa04SBarry Smith . size - the needed length of the new format
34c9a19010SBarry Smith 
35c9a19010SBarry Smith   Level: developer
36c9a19010SBarry Smith 
37db781477SPatrick Sanan .seealso: `PetscFormatConvert()`, `PetscVSNPrintf()`, `PetscVFPrintf()`
38c9a19010SBarry Smith @*/
39d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFormatConvertGetSize(const char *format, size_t *size)
40d71ae5a4SJacob Faibussowitsch {
413ca90d2dSJacob Faibussowitsch   size_t   sz = 0;
42d781fa04SBarry Smith   PetscInt i  = 0;
43d781fa04SBarry Smith 
44d781fa04SBarry Smith   PetscFunctionBegin;
454f572ea9SToby Isaac   PetscAssertPointer(format, 1);
464f572ea9SToby Isaac   PetscAssertPointer(size, 2);
47d781fa04SBarry Smith   while (format[i]) {
483ca90d2dSJacob Faibussowitsch     if (format[i] == '%') {
493ca90d2dSJacob Faibussowitsch       if (format[i + 1] == '%') {
503ca90d2dSJacob Faibussowitsch         i += 2;
513ca90d2dSJacob Faibussowitsch         sz += 2;
523ca90d2dSJacob Faibussowitsch         continue;
533ca90d2dSJacob Faibussowitsch       }
54d781fa04SBarry Smith       /* Find the letter */
559371c9d4SSatish Balay       while (format[i] && (format[i] <= '9')) {
569371c9d4SSatish Balay         ++i;
579371c9d4SSatish Balay         ++sz;
589371c9d4SSatish Balay       }
59d781fa04SBarry Smith       switch (format[i]) {
603ca90d2dSJacob Faibussowitsch #if PetscDefined(USE_64BIT_INDICES)
61d71ae5a4SJacob Faibussowitsch       case 'D':
62d71ae5a4SJacob Faibussowitsch         sz += 2;
63d71ae5a4SJacob Faibussowitsch         break;
64d781fa04SBarry Smith #endif
65d71ae5a4SJacob Faibussowitsch       case 'g':
66d71ae5a4SJacob Faibussowitsch         sz += 4;
67d71ae5a4SJacob Faibussowitsch       default:
68d71ae5a4SJacob Faibussowitsch         break;
69d781fa04SBarry Smith       }
70d781fa04SBarry Smith     }
713ca90d2dSJacob Faibussowitsch     ++i;
723ca90d2dSJacob Faibussowitsch     ++sz;
73d781fa04SBarry Smith   }
743ca90d2dSJacob Faibussowitsch   *size = sz + 1; /* space for NULL character */
753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
76d781fa04SBarry Smith }
77d781fa04SBarry Smith 
78d781fa04SBarry Smith /*@C
7910450e9eSJacob Faibussowitsch   PetscFormatConvert - converts %g to [|%g|] so that `PetscVSNPrintf()` can ensure all %g formatted numbers have a decimal point when printed.
80d781fa04SBarry Smith 
81058c9ee1SBarry Smith   No Fortran Support
82811af0c4SBarry Smith 
8310450e9eSJacob Faibussowitsch   Input Parameter:
8410450e9eSJacob Faibussowitsch . format - the PETSc format string
85d781fa04SBarry Smith 
8621532e8aSBarry Smith   Output Parameter:
87*a3b724e8SBarry Smith . newformat - the formatted string, must be long enough to hold result
8821532e8aSBarry Smith 
89d781fa04SBarry Smith   Level: developer
90d781fa04SBarry Smith 
91058c9ee1SBarry Smith   Note:
9210450e9eSJacob Faibussowitsch   The decimal point is then used by the `petscdiff` script so that differences in floating
9310450e9eSJacob Faibussowitsch   point number output is ignored in the test harness.
9410450e9eSJacob Faibussowitsch 
9510450e9eSJacob Faibussowitsch   Deprecated usage also converts the `%D` to `%d` for 32-bit PETSc indices and to `%lld` for
9610450e9eSJacob Faibussowitsch   64-bit PETSc indices. This feature is no longer used in PETSc code instead use %"
9710450e9eSJacob Faibussowitsch   PetscInt_FMT " in the format string.
98058c9ee1SBarry Smith 
99db781477SPatrick Sanan .seealso: `PetscFormatConvertGetSize()`, `PetscVSNPrintf()`, `PetscVFPrintf()`
100d781fa04SBarry Smith @*/
101d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFormatConvert(const char *format, char *newformat)
102d71ae5a4SJacob Faibussowitsch {
103e5c89e4eSSatish Balay   PetscInt i = 0, j = 0;
104e5c89e4eSSatish Balay 
105eed5747fSBarry Smith   PetscFunctionBegin;
106d781fa04SBarry Smith   while (format[i]) {
1072a1ad9caSBarry Smith     if (format[i] == '%' && format[i + 1] == '%') {
1082a1ad9caSBarry Smith       newformat[j++] = format[i++];
1092a1ad9caSBarry Smith       newformat[j++] = format[i++];
1102a1ad9caSBarry Smith     } else if (format[i] == '%') {
1118627564fSBarry Smith       if (format[i + 1] == 'g') {
1128627564fSBarry Smith         newformat[j++] = '[';
1138627564fSBarry Smith         newformat[j++] = '|';
1148627564fSBarry Smith       }
1157bc47156SJose Roman       /* Find the letter */
1167bc47156SJose Roman       for (; format[i] && format[i] <= '9'; i++) newformat[j++] = format[i];
1177bc47156SJose Roman       switch (format[i]) {
1187bc47156SJose Roman       case 'D':
1196de02169SBarry Smith #if !defined(PETSC_USE_64BIT_INDICES)
120e5c89e4eSSatish Balay         newformat[j++] = 'd';
121e5c89e4eSSatish Balay #else
122e5c89e4eSSatish Balay         newformat[j++] = 'l';
123e5c89e4eSSatish Balay         newformat[j++] = 'l';
124e5c89e4eSSatish Balay         newformat[j++] = 'd';
125e5c89e4eSSatish Balay #endif
1267bc47156SJose Roman         break;
1278627564fSBarry Smith       case 'g':
1288627564fSBarry Smith         newformat[j++] = format[i];
1298627564fSBarry Smith         if (format[i - 1] == '%') {
1308627564fSBarry Smith           newformat[j++] = '|';
1318627564fSBarry Smith           newformat[j++] = ']';
1328627564fSBarry Smith         }
1338627564fSBarry Smith         break;
134d71ae5a4SJacob Faibussowitsch       case 'G':
135d71ae5a4SJacob Faibussowitsch         SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "%%G format is no longer supported, use %%g and cast the argument to double");
136d71ae5a4SJacob Faibussowitsch       case 'F':
137d71ae5a4SJacob Faibussowitsch         SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "%%F format is no longer supported, use %%f and cast the argument to double");
138d71ae5a4SJacob Faibussowitsch       default:
139d71ae5a4SJacob Faibussowitsch         newformat[j++] = format[i];
140d71ae5a4SJacob Faibussowitsch         break;
1417bc47156SJose Roman       }
1427bc47156SJose Roman       i++;
143a297a907SKarl Rupp     } else newformat[j++] = format[i++];
144e5c89e4eSSatish Balay   }
145e5c89e4eSSatish Balay   newformat[j] = 0;
1463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
147e5c89e4eSSatish Balay }
148e5c89e4eSSatish Balay 
14914416c0eSBarry Smith #define PETSCDEFAULTBUFFERSIZE 8 * 1024
150d781fa04SBarry Smith 
151c9a19010SBarry Smith /*@C
1528c509928SStefano Zampini   PetscVSNPrintf - The PETSc version of `vsnprintf()`. Ensures that all `%g` formatted arguments' output contains the decimal point (which is used by the test harness)
153c9a19010SBarry Smith 
154c9a19010SBarry Smith   Input Parameters:
155c9a19010SBarry Smith + str    - location to put result
15621532e8aSBarry Smith . len    - the length of `str`
15710450e9eSJacob Faibussowitsch . format - the PETSc format string
15810450e9eSJacob Faibussowitsch - Argp   - the variable argument list to format
15921532e8aSBarry Smith 
16021532e8aSBarry Smith   Output Parameter:
16121532e8aSBarry Smith . fullLength - the amount of space in `str` actually used.
162c9a19010SBarry Smith 
163c9a19010SBarry Smith   Level: developer
164c9a19010SBarry Smith 
165aec76313SJacob Faibussowitsch   Developer Notes:
166058c9ee1SBarry Smith   This function may be called from an error handler, if an error occurs when it is called by the error handler than likely
167058c9ee1SBarry Smith   a recursion will occur resulting in a crash of the program.
168058c9ee1SBarry Smith 
16921532e8aSBarry Smith   If the length of the format string `format` is on the order of `PETSCDEFAULTBUFFERSIZE` (8 * 1024 bytes) or larger, this function will call `PetscMalloc()`
170058c9ee1SBarry Smith 
17142747ad1SJacob Faibussowitsch .seealso: `PetscFormatConvert()`, `PetscFormatConvertGetSize()`, `PetscErrorPrintf()`, `PetscVPrintf()`
172c9a19010SBarry Smith @*/
173d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscVSNPrintf(char *str, size_t len, const char *format, size_t *fullLength, va_list Argp)
174d71ae5a4SJacob Faibussowitsch {
175d781fa04SBarry Smith   char  *newformat = NULL;
17614416c0eSBarry Smith   char   formatbuf[PETSCDEFAULTBUFFERSIZE];
177d781fa04SBarry Smith   size_t newLength;
17814416c0eSBarry Smith   int    flen;
179e5c89e4eSSatish Balay 
180eed5747fSBarry Smith   PetscFunctionBegin;
1819566063dSJacob Faibussowitsch   PetscCall(PetscFormatConvertGetSize(format, &newLength));
18294217ebdSBarry Smith   if (newLength < sizeof(formatbuf)) {
183e2135aedSMatthew Knepley     newformat = formatbuf;
18494217ebdSBarry Smith     newLength = sizeof(formatbuf) - 1;
185e2135aedSMatthew Knepley   } else {
1869566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(newLength, &newformat));
187e2135aedSMatthew Knepley   }
1889566063dSJacob Faibussowitsch   PetscCall(PetscFormatConvert(format, newformat));
1897b9a2d1bSSatish Balay #if defined(PETSC_HAVE_VSNPRINTF)
190152b30f0SSatish Balay   flen = vsnprintf(str, len, newformat, Argp);
191e5c89e4eSSatish Balay #else
19289b07760SSatish Balay   #error "vsnprintf not found"
193e5c89e4eSSatish Balay #endif
19448a46eb9SPierre Jolivet   if (newLength > sizeof(formatbuf) - 1) PetscCall(PetscFree(newformat));
1958627564fSBarry Smith   {
1968627564fSBarry Smith     PetscBool foundedot;
1978627564fSBarry Smith     size_t    cnt = 0, ncnt = 0, leng;
1989566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(str, &leng));
19917ca8410SBarry Smith     if (leng > 4) {
2008627564fSBarry Smith       for (cnt = 0; cnt < leng - 4; cnt++) {
2018627564fSBarry Smith         if (str[cnt] == '[' && str[cnt + 1] == '|') {
202c540d043SBarry Smith           flen -= 4;
2039371c9d4SSatish Balay           cnt++;
2049371c9d4SSatish Balay           cnt++;
2058627564fSBarry Smith           foundedot = PETSC_FALSE;
2068627564fSBarry Smith           for (; cnt < leng - 1; cnt++) {
2078627564fSBarry Smith             if (str[cnt] == '|' && str[cnt + 1] == ']') {
2088627564fSBarry Smith               cnt++;
2098627564fSBarry Smith               if (!foundedot) str[ncnt++] = '.';
2108627564fSBarry Smith               ncnt--;
2118627564fSBarry Smith               break;
2128627564fSBarry Smith             } else {
2138627564fSBarry Smith               if (str[cnt] == 'e' || str[cnt] == '.') foundedot = PETSC_TRUE;
2148627564fSBarry Smith               str[ncnt++] = str[cnt];
2158627564fSBarry Smith             }
2168627564fSBarry Smith           }
2178627564fSBarry Smith         } else {
2188627564fSBarry Smith           str[ncnt] = str[cnt];
2198627564fSBarry Smith         }
2208627564fSBarry Smith         ncnt++;
2218627564fSBarry Smith       }
2228627564fSBarry Smith       while (cnt < leng) {
2239371c9d4SSatish Balay         str[ncnt] = str[cnt];
2249371c9d4SSatish Balay         ncnt++;
2259371c9d4SSatish Balay         cnt++;
2268627564fSBarry Smith       }
2278627564fSBarry Smith       str[ncnt] = 0;
2288627564fSBarry Smith     }
2298627564fSBarry Smith   }
230748e1b9dSBarry Smith #if defined(PETSC_HAVE_WINDOWS_H) && !defined(PETSC_HAVE__SET_OUTPUT_FORMAT)
231e51f71cfSBarry Smith   /* older Windows OS always produces e-+0np for floating point output; remove the extra 0 */
232748e1b9dSBarry Smith   {
233748e1b9dSBarry Smith     size_t cnt = 0, ncnt = 0, leng;
2349566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(str, &leng));
235748e1b9dSBarry Smith     if (leng > 5) {
236748e1b9dSBarry Smith       for (cnt = 0; cnt < leng - 4; cnt++) {
237e51f71cfSBarry Smith         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') {
2389371c9d4SSatish Balay           str[ncnt] = str[cnt];
2399371c9d4SSatish Balay           ncnt++;
2409371c9d4SSatish Balay           cnt++;
2419371c9d4SSatish Balay           str[ncnt] = str[cnt];
2429371c9d4SSatish Balay           ncnt++;
2439371c9d4SSatish Balay           cnt++;
2449371c9d4SSatish Balay           cnt++;
245e51f71cfSBarry Smith           str[ncnt] = str[cnt];
246748e1b9dSBarry Smith         } else {
247748e1b9dSBarry Smith           str[ncnt] = str[cnt];
248748e1b9dSBarry Smith         }
249748e1b9dSBarry Smith         ncnt++;
250748e1b9dSBarry Smith       }
251748e1b9dSBarry Smith       while (cnt < leng) {
2529371c9d4SSatish Balay         str[ncnt] = str[cnt];
2539371c9d4SSatish Balay         ncnt++;
2549371c9d4SSatish Balay         cnt++;
255748e1b9dSBarry Smith       }
256748e1b9dSBarry Smith       str[ncnt] = 0;
257748e1b9dSBarry Smith     }
258748e1b9dSBarry Smith   }
259748e1b9dSBarry Smith #endif
260c540d043SBarry Smith   if (fullLength) *fullLength = 1 + (size_t)flen;
2613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
262e5c89e4eSSatish Balay }
263e5c89e4eSSatish Balay 
264c9a19010SBarry Smith /*@C
265c69effb2SJacob Faibussowitsch   PetscFFlush - Flush a file stream
266c69effb2SJacob Faibussowitsch 
267c69effb2SJacob Faibussowitsch   Input Parameter:
268c69effb2SJacob Faibussowitsch . fd - The file stream handle
269c69effb2SJacob Faibussowitsch 
270c69effb2SJacob Faibussowitsch   Level: intermediate
271c69effb2SJacob Faibussowitsch 
272c69effb2SJacob Faibussowitsch   Notes:
273c69effb2SJacob Faibussowitsch   For output streams (and for update streams on which the last operation was output), writes
274c69effb2SJacob Faibussowitsch   any unwritten data from the stream's buffer to the associated output device.
275c69effb2SJacob Faibussowitsch 
276c69effb2SJacob Faibussowitsch   For input streams (and for update streams on which the last operation was input), the
277c69effb2SJacob Faibussowitsch   behavior is undefined.
278c69effb2SJacob Faibussowitsch 
279c69effb2SJacob Faibussowitsch   If `fd` is `NULL`, all open output streams are flushed, including ones not directly
280c69effb2SJacob Faibussowitsch   accessible to the program.
281c69effb2SJacob Faibussowitsch 
282c69effb2SJacob Faibussowitsch .seealso: `PetscPrintf()`, `PetscFPrintf()`, `PetscVFPrintf()`, `PetscVSNPrintf()`
283c69effb2SJacob Faibussowitsch @*/
284c69effb2SJacob Faibussowitsch PetscErrorCode PetscFFlush(FILE *fd)
285c69effb2SJacob Faibussowitsch {
286c69effb2SJacob Faibussowitsch   PetscFunctionBegin;
2874f572ea9SToby Isaac   if (fd) PetscAssertPointer(fd, 1);
288c69effb2SJacob Faibussowitsch   // could also use PetscCallExternal() here, but since we can get additional error explanation
289c69effb2SJacob Faibussowitsch   // from strerror() we opted for a manual check
290bf31d2d3SBarry Smith   PetscCheck(0 == fflush(fd), PETSC_COMM_SELF, PETSC_ERR_FILE_WRITE, "Error in fflush() due to \"%s\"", strerror(errno));
291c69effb2SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
292c69effb2SJacob Faibussowitsch }
293c69effb2SJacob Faibussowitsch 
294c69effb2SJacob Faibussowitsch /*@C
295aec76313SJacob Faibussowitsch   PetscVFPrintfDefault -  All PETSc standard out and error messages are sent through this function; so, in theory, this can
296e5c89e4eSSatish Balay   can be replaced with something that does not simply write to a file.
297e5c89e4eSSatish Balay 
29810450e9eSJacob Faibussowitsch   Input Parameters:
29910450e9eSJacob Faibussowitsch + fd     - the file descriptor to write to
30010450e9eSJacob Faibussowitsch . format - the format string to write with
30110450e9eSJacob Faibussowitsch - Argp   - the variable argument list of items to format and write
30210450e9eSJacob Faibussowitsch 
30310450e9eSJacob Faibussowitsch   Level: developer
30410450e9eSJacob Faibussowitsch 
30510450e9eSJacob Faibussowitsch   Note:
30610450e9eSJacob Faibussowitsch   For error messages this may be called by any MPI process, for regular standard out it is
30710450e9eSJacob Faibussowitsch   called only by MPI rank 0 of a given communicator
30810450e9eSJacob Faibussowitsch 
30910450e9eSJacob Faibussowitsch   Example Usage:
310c9a19010SBarry Smith   To use, write your own function for example,
311058c9ee1SBarry Smith .vb
312058c9ee1SBarry Smith    PetscErrorCode mypetscvfprintf(FILE *fd, const char format[], va_list Argp)
313058c9ee1SBarry Smith    {
314058c9ee1SBarry Smith      PetscErrorCode ierr;
315058c9ee1SBarry Smith 
316058c9ee1SBarry Smith      PetscFunctionBegin;
317058c9ee1SBarry Smith       if (fd != stdout && fd != stderr) {  handle regular files
318058c9ee1SBarry Smith          CHKERR(PetscVFPrintfDefault(fd,format,Argp));
319058c9ee1SBarry Smith      } else {
320058c9ee1SBarry Smith         char   buff[BIG];
321058c9ee1SBarry Smith         size_t length;
322058c9ee1SBarry Smith         PetscCall(PetscVSNPrintf(buff,BIG,format,&length,Argp));
323058c9ee1SBarry Smith         now send buff to whatever stream or whatever you want
324058c9ee1SBarry Smith     }
325058c9ee1SBarry Smith     PetscFunctionReturn(PETSC_SUCCESS);
326058c9ee1SBarry Smith    }
327058c9ee1SBarry Smith .ve
328058c9ee1SBarry Smith   then before the call to `PetscInitialize()` do the assignment `PetscVFPrintf = mypetscvfprintf`;
329058c9ee1SBarry Smith 
330aec76313SJacob Faibussowitsch   Developer Notes:
331058c9ee1SBarry Smith   This could be called by an error handler, if that happens then a recursion of the error handler may occur
332058c9ee1SBarry Smith   and a resulting crash
333c9a19010SBarry Smith 
334c69effb2SJacob Faibussowitsch .seealso: `PetscVSNPrintf()`, `PetscErrorPrintf()`, `PetscFFlush()`
335c9a19010SBarry Smith @*/
336d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscVFPrintfDefault(FILE *fd, const char *format, va_list Argp)
337d71ae5a4SJacob Faibussowitsch {
33814416c0eSBarry Smith   char   str[PETSCDEFAULTBUFFERSIZE];
33914416c0eSBarry Smith   char  *buff = str;
34014416c0eSBarry Smith   size_t fullLength;
3411531940fSBarry Smith #if defined(PETSC_HAVE_VA_COPY)
34214416c0eSBarry Smith   va_list Argpcopy;
3431531940fSBarry Smith #endif
3441179db26SBarry Smith 
345eed5747fSBarry Smith   PetscFunctionBegin;
3461531940fSBarry Smith #if defined(PETSC_HAVE_VA_COPY)
34714416c0eSBarry Smith   va_copy(Argpcopy, Argp);
3481531940fSBarry Smith #endif
3499566063dSJacob Faibussowitsch   PetscCall(PetscVSNPrintf(str, sizeof(str), format, &fullLength, Argp));
35014416c0eSBarry Smith   if (fullLength > sizeof(str)) {
3519566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(fullLength, &buff));
3521531940fSBarry Smith #if defined(PETSC_HAVE_VA_COPY)
3539566063dSJacob Faibussowitsch     PetscCall(PetscVSNPrintf(buff, fullLength, format, NULL, Argpcopy));
3541531940fSBarry Smith #else
3551531940fSBarry Smith     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "C89 does not support va_copy() hence cannot print long strings with PETSc printing routines");
3561531940fSBarry Smith #endif
35714416c0eSBarry Smith   }
358eae3dc7dSJacob Faibussowitsch #if defined(PETSC_HAVE_VA_COPY)
359eae3dc7dSJacob Faibussowitsch   va_end(Argpcopy);
360eae3dc7dSJacob Faibussowitsch #endif
361c69effb2SJacob Faibussowitsch   {
3628c0ebe3fSBarry Smith     int err;
3638c0ebe3fSBarry Smith 
3648c0ebe3fSBarry Smith     // POSIX C sets errno but otherwise it may not be set for *printf() system calls
3658c0ebe3fSBarry Smith     // https://pubs.opengroup.org/onlinepubs/9699919799/functions/fprintf.html
3668c0ebe3fSBarry Smith     errno = 0;
3678c0ebe3fSBarry Smith     err   = fprintf(fd, "%s", buff);
368c69effb2SJacob Faibussowitsch     // cannot use PetscCallExternal() for fprintf since the return value is "number of
369c69effb2SJacob Faibussowitsch     // characters transmitted to the output stream" on success
3708c0ebe3fSBarry Smith     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)");
371c69effb2SJacob Faibussowitsch   }
372c69effb2SJacob Faibussowitsch   PetscCall(PetscFFlush(fd));
37348a46eb9SPierre Jolivet   if (buff != str) PetscCall(PetscFree(buff));
3743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
375e5c89e4eSSatish Balay }
376e5c89e4eSSatish Balay 
3775b5bc046SBarry Smith /*@C
3785b5bc046SBarry Smith   PetscSNPrintf - Prints to a string of given length
3795b5bc046SBarry Smith 
3805b5bc046SBarry Smith   Not Collective
3815b5bc046SBarry Smith 
3825b5bc046SBarry Smith   Input Parameters:
38321532e8aSBarry Smith + len    - the length of `str`
38410450e9eSJacob Faibussowitsch - format - the usual `printf()` format string
3855b5bc046SBarry Smith 
38621532e8aSBarry Smith   Output Parameter:
38721532e8aSBarry Smith . str - the resulting string
38821532e8aSBarry Smith 
3895b5bc046SBarry Smith   Level: intermediate
3905b5bc046SBarry Smith 
391db781477SPatrick Sanan .seealso: `PetscSynchronizedFlush()`, `PetscSynchronizedFPrintf()`, `PetscFPrintf()`, `PetscVSNPrintf()`,
392c69effb2SJacob Faibussowitsch           `PetscPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIISynchronizedPrintf()`,
393c69effb2SJacob Faibussowitsch           `PetscVFPrintf()`, `PetscFFlush()`
3945b5bc046SBarry Smith @*/
395d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSNPrintf(char *str, size_t len, const char format[], ...)
396d71ae5a4SJacob Faibussowitsch {
397c9a19010SBarry Smith   size_t  fullLength;
3985b5bc046SBarry Smith   va_list Argp;
3995b5bc046SBarry Smith 
4005b5bc046SBarry Smith   PetscFunctionBegin;
4015b5bc046SBarry Smith   va_start(Argp, format);
4029566063dSJacob Faibussowitsch   PetscCall(PetscVSNPrintf(str, len, format, &fullLength, Argp));
403eae3dc7dSJacob Faibussowitsch   va_end(Argp);
4043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4055b5bc046SBarry Smith }
4065b5bc046SBarry Smith 
407257d2499SJed Brown /*@C
408058c9ee1SBarry Smith   PetscSNPrintfCount - Prints to a string of given length, returns count of characters printed
409257d2499SJed Brown 
410257d2499SJed Brown   Not Collective
411257d2499SJed Brown 
412257d2499SJed Brown   Input Parameters:
41321532e8aSBarry Smith + len    - the length of `str`
414058c9ee1SBarry Smith . format - the usual `printf()` format string
41510450e9eSJacob Faibussowitsch - ...    - args to format
416257d2499SJed Brown 
41721532e8aSBarry Smith   Output Parameters:
41821532e8aSBarry Smith + str       - the resulting string
41921532e8aSBarry Smith - countused - number of characters printed
420cb398dd3SBarry Smith 
421257d2499SJed Brown   Level: intermediate
422257d2499SJed Brown 
423db781477SPatrick Sanan .seealso: `PetscSynchronizedFlush()`, `PetscSynchronizedFPrintf()`, `PetscFPrintf()`, `PetscVSNPrintf()`,
424db781477SPatrick Sanan           `PetscPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscSNPrintf()`, `PetscVFPrintf()`
425257d2499SJed Brown @*/
426d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSNPrintfCount(char *str, size_t len, const char format[], size_t *countused, ...)
427d71ae5a4SJacob Faibussowitsch {
428257d2499SJed Brown   va_list Argp;
429257d2499SJed Brown 
430257d2499SJed Brown   PetscFunctionBegin;
431257d2499SJed Brown   va_start(Argp, countused);
4329566063dSJacob Faibussowitsch   PetscCall(PetscVSNPrintf(str, len, format, countused, Argp));
433eae3dc7dSJacob Faibussowitsch   va_end(Argp);
4343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
435257d2499SJed Brown }
436257d2499SJed Brown 
43702c9f0b5SLisandro Dalcin PrintfQueue petsc_printfqueue = NULL, petsc_printfqueuebase = NULL;
438d30b0576SJed Brown int         petsc_printfqueuelength = 0;
439e5c89e4eSSatish Balay 
4408c509928SStefano Zampini static inline PetscErrorCode PetscVFPrintf_Private(FILE *fd, const char format[], va_list Argp)
441eae3dc7dSJacob Faibussowitsch {
442eae3dc7dSJacob Faibussowitsch   const PetscBool tee = (PetscBool)(petsc_history && (fd != petsc_history));
443eae3dc7dSJacob Faibussowitsch   va_list         cpy;
444eae3dc7dSJacob Faibussowitsch 
445eae3dc7dSJacob Faibussowitsch   PetscFunctionBegin;
446eae3dc7dSJacob Faibussowitsch   // must do this before we possibly consume Argp
447eae3dc7dSJacob Faibussowitsch   if (tee) va_copy(cpy, Argp);
448eae3dc7dSJacob Faibussowitsch   PetscCall((*PetscVFPrintf)(fd, format, Argp));
449eae3dc7dSJacob Faibussowitsch   if (tee) {
450eae3dc7dSJacob Faibussowitsch     PetscCall((*PetscVFPrintf)(petsc_history, format, cpy));
451eae3dc7dSJacob Faibussowitsch     va_end(cpy);
452eae3dc7dSJacob Faibussowitsch   }
453eae3dc7dSJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
454eae3dc7dSJacob Faibussowitsch }
455eae3dc7dSJacob Faibussowitsch 
4568c509928SStefano Zampini PETSC_INTERN PetscErrorCode PetscVFPrintf_Internal(FILE *fd, const char format[], ...)
4578c509928SStefano Zampini {
4588c509928SStefano Zampini   va_list Argp;
4598c509928SStefano Zampini 
4608c509928SStefano Zampini   PetscFunctionBegin;
4618c509928SStefano Zampini   va_start(Argp, format);
4628c509928SStefano Zampini   PetscCall(PetscVFPrintf_Private(fd, format, Argp));
4638c509928SStefano Zampini   va_end(Argp);
4648c509928SStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
4658c509928SStefano Zampini }
4668c509928SStefano Zampini 
467eae3dc7dSJacob Faibussowitsch static inline PetscErrorCode PetscSynchronizedFPrintf_Private(MPI_Comm comm, FILE *fp, const char format[], va_list Argp)
468eae3dc7dSJacob Faibussowitsch {
469eae3dc7dSJacob Faibussowitsch   PetscMPIInt rank;
470eae3dc7dSJacob Faibussowitsch   va_list     cpy;
471eae3dc7dSJacob Faibussowitsch 
472eae3dc7dSJacob Faibussowitsch   PetscFunctionBegin;
473eae3dc7dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
474eae3dc7dSJacob Faibussowitsch   /* First processor prints immediately to fp */
475eae3dc7dSJacob Faibussowitsch   if (rank == 0) {
476eae3dc7dSJacob Faibussowitsch     va_copy(cpy, Argp);
4778c509928SStefano Zampini     PetscCall(PetscVFPrintf_Private(fp, format, cpy));
478eae3dc7dSJacob Faibussowitsch     va_end(cpy);
479eae3dc7dSJacob Faibussowitsch   } else { /* other processors add to local queue */
480eae3dc7dSJacob Faibussowitsch     PrintfQueue next;
481eae3dc7dSJacob Faibussowitsch     size_t      fullLength = PETSCDEFAULTBUFFERSIZE;
482eae3dc7dSJacob Faibussowitsch 
483eae3dc7dSJacob Faibussowitsch     PetscCall(PetscNew(&next));
484eae3dc7dSJacob Faibussowitsch     if (petsc_printfqueue) {
485eae3dc7dSJacob Faibussowitsch       petsc_printfqueue->next = next;
486eae3dc7dSJacob Faibussowitsch       petsc_printfqueue       = next;
487eae3dc7dSJacob Faibussowitsch       petsc_printfqueue->next = NULL;
488eae3dc7dSJacob Faibussowitsch     } else petsc_printfqueuebase = petsc_printfqueue = next;
489eae3dc7dSJacob Faibussowitsch     petsc_printfqueuelength++;
490eae3dc7dSJacob Faibussowitsch     next->size   = 0;
491eae3dc7dSJacob Faibussowitsch     next->string = NULL;
492eae3dc7dSJacob Faibussowitsch     while (fullLength >= next->size) {
493eae3dc7dSJacob Faibussowitsch       next->size = fullLength + 1;
494eae3dc7dSJacob Faibussowitsch       PetscCall(PetscFree(next->string));
495eae3dc7dSJacob Faibussowitsch       PetscCall(PetscMalloc1(next->size, &next->string));
496eae3dc7dSJacob Faibussowitsch       PetscCall(PetscArrayzero(next->string, next->size));
497eae3dc7dSJacob Faibussowitsch       va_copy(cpy, Argp);
498eae3dc7dSJacob Faibussowitsch       PetscCall(PetscVSNPrintf(next->string, next->size, format, &fullLength, cpy));
499eae3dc7dSJacob Faibussowitsch       va_end(cpy);
500eae3dc7dSJacob Faibussowitsch     }
501eae3dc7dSJacob Faibussowitsch   }
502eae3dc7dSJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
503eae3dc7dSJacob Faibussowitsch }
504eae3dc7dSJacob Faibussowitsch 
505e5c89e4eSSatish Balay /*@C
5069c89aa79SPierre Jolivet   PetscSynchronizedPrintf - Prints synchronized output from multiple MPI processes.
507e5c89e4eSSatish Balay   Output of the first processor is followed by that of the second, etc.
508e5c89e4eSSatish Balay 
509e5c89e4eSSatish Balay   Not Collective
510e5c89e4eSSatish Balay 
511e5c89e4eSSatish Balay   Input Parameters:
512058c9ee1SBarry Smith + comm   - the MPI communicator
5136026c97aSBarry Smith - format - the usual `printf()` format string
514e5c89e4eSSatish Balay 
515e5c89e4eSSatish Balay   Level: intermediate
516e5c89e4eSSatish Balay 
517811af0c4SBarry Smith   Note:
518811af0c4SBarry Smith   REQUIRES a call to `PetscSynchronizedFlush()` by all the processes after the completion of the calls to `PetscSynchronizedPrintf()` for the information
519e5c89e4eSSatish Balay   from all the processors to be printed.
520e5c89e4eSSatish Balay 
521aec76313SJacob Faibussowitsch   Fortran Notes:
522058c9ee1SBarry Smith   The call sequence is `PetscSynchronizedPrintf`(`MPI_Comm`, `character`(*), `PetscErrorCode` ierr).
523e5c89e4eSSatish Balay   That is, you can only pass a single character string from Fortran.
524e5c89e4eSSatish Balay 
525db781477SPatrick Sanan .seealso: `PetscSynchronizedFlush()`, `PetscSynchronizedFPrintf()`, `PetscFPrintf()`,
526c69effb2SJacob Faibussowitsch           `PetscPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIISynchronizedPrintf()`,
527c69effb2SJacob Faibussowitsch           `PetscFFlush()`
528e5c89e4eSSatish Balay @*/
529d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSynchronizedPrintf(MPI_Comm comm, const char format[], ...)
530d71ae5a4SJacob Faibussowitsch {
531eae3dc7dSJacob Faibussowitsch   va_list Argp;
532e5c89e4eSSatish Balay 
533e5c89e4eSSatish Balay   PetscFunctionBegin;
534e5c89e4eSSatish Balay   va_start(Argp, format);
535eae3dc7dSJacob Faibussowitsch   PetscCall(PetscSynchronizedFPrintf_Private(comm, PETSC_STDOUT, format, Argp));
536e5c89e4eSSatish Balay   va_end(Argp);
5373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
538e5c89e4eSSatish Balay }
539e5c89e4eSSatish Balay 
540e5c89e4eSSatish Balay /*@C
541e5c89e4eSSatish Balay   PetscSynchronizedFPrintf - Prints synchronized output to the specified file from
54221532e8aSBarry Smith   several MPI processes.  Output of the first process is followed by that of the
543e5c89e4eSSatish Balay   second, etc.
544e5c89e4eSSatish Balay 
545e5c89e4eSSatish Balay   Not Collective
546e5c89e4eSSatish Balay 
547e5c89e4eSSatish Balay   Input Parameters:
548058c9ee1SBarry Smith + comm   - the MPI communicator
549aec76313SJacob Faibussowitsch . fp     - the file pointer
5506026c97aSBarry Smith - format - the usual `printf()` format string
551e5c89e4eSSatish Balay 
552e5c89e4eSSatish Balay   Level: intermediate
553e5c89e4eSSatish Balay 
554811af0c4SBarry Smith   Note:
555811af0c4SBarry Smith   REQUIRES a intervening call to `PetscSynchronizedFlush()` for the information
556e5c89e4eSSatish Balay   from all the processors to be printed.
557e5c89e4eSSatish Balay 
558db781477SPatrick Sanan .seealso: `PetscSynchronizedPrintf()`, `PetscSynchronizedFlush()`, `PetscFPrintf()`,
559c69effb2SJacob Faibussowitsch           `PetscFOpen()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
560c69effb2SJacob Faibussowitsch           `PetscFFlush()`
561e5c89e4eSSatish Balay @*/
562d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSynchronizedFPrintf(MPI_Comm comm, FILE *fp, const char format[], ...)
563d71ae5a4SJacob Faibussowitsch {
564eae3dc7dSJacob Faibussowitsch   va_list Argp;
565e5c89e4eSSatish Balay 
566e5c89e4eSSatish Balay   PetscFunctionBegin;
567e5c89e4eSSatish Balay   va_start(Argp, format);
568eae3dc7dSJacob Faibussowitsch   PetscCall(PetscSynchronizedFPrintf_Private(comm, fp, format, Argp));
569e5c89e4eSSatish Balay   va_end(Argp);
5703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
571e5c89e4eSSatish Balay }
572e5c89e4eSSatish Balay 
5730ec8b6e3SBarry Smith /*@C
574e5c89e4eSSatish Balay   PetscSynchronizedFlush - Flushes to the screen output from all processors
575811af0c4SBarry Smith   involved in previous `PetscSynchronizedPrintf()`/`PetscSynchronizedFPrintf()` calls.
576e5c89e4eSSatish Balay 
577d083f849SBarry Smith   Collective
578e5c89e4eSSatish Balay 
579e5c89e4eSSatish Balay   Input Parameters:
580058c9ee1SBarry Smith + comm - the MPI communicator
581*a3b724e8SBarry Smith - fd   - the file pointer (valid on MPI rank 0 of the communicator), `PETSC_STDOUT` or value obtained from `PetscFOpen()`
582e5c89e4eSSatish Balay 
583e5c89e4eSSatish Balay   Level: intermediate
584e5c89e4eSSatish Balay 
585811af0c4SBarry Smith   Note:
586811af0c4SBarry Smith   If `PetscSynchronizedPrintf()` and/or `PetscSynchronizedFPrintf()` are called with
587811af0c4SBarry Smith   different MPI communicators there must be an intervening call to `PetscSynchronizedFlush()` between the calls with different MPI communicators.
588e5c89e4eSSatish Balay 
589aec76313SJacob Faibussowitsch   Fortran Notes:
590811af0c4SBarry Smith   Pass `PETSC_STDOUT` if the flush is for standard out; otherwise pass a value obtained from `PetscFOpen()`
591e50bf69fSBarry Smith 
592db781477SPatrick Sanan .seealso: `PetscSynchronizedPrintf()`, `PetscFPrintf()`, `PetscPrintf()`, `PetscViewerASCIIPrintf()`,
593db781477SPatrick Sanan           `PetscViewerASCIISynchronizedPrintf()`
5940087d953SMatthew G. Knepley @*/
595d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSynchronizedFlush(MPI_Comm comm, FILE *fd)
596d71ae5a4SJacob Faibussowitsch {
59729a5cbdcSMatthew G. Knepley   PetscMPIInt rank, size, tag, i, j, n = 0, dummy = 0;
5982d609e63SMatthew Knepley   char       *message;
599e5c89e4eSSatish Balay   MPI_Status  status;
600e5c89e4eSSatish Balay 
601e5c89e4eSSatish Balay   PetscFunctionBegin;
6029566063dSJacob Faibussowitsch   PetscCall(PetscCommDuplicate(comm, &comm, &tag));
6039566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
6049566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
605e5c89e4eSSatish Balay 
606e5c89e4eSSatish Balay   /* First processor waits for messages from all other processors */
607dd400576SPatrick Sanan   if (rank == 0) {
6080ec8b6e3SBarry Smith     if (!fd) fd = PETSC_STDOUT;
609e5c89e4eSSatish Balay     for (i = 1; i < size; i++) {
6109f73f8ecSBarry Smith       /* to prevent a flood of messages to process zero, request each message separately */
6119566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Send(&dummy, 1, MPI_INT, i, tag, comm));
6129566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Recv(&n, 1, MPI_INT, i, tag, comm, &status));
613e5c89e4eSSatish Balay       for (j = 0; j < n; j++) {
61429a5cbdcSMatthew G. Knepley         PetscMPIInt size = 0;
6152d609e63SMatthew Knepley 
6169566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Recv(&size, 1, MPI_INT, i, tag, comm, &status));
6179566063dSJacob Faibussowitsch         PetscCall(PetscMalloc1(size, &message));
6189566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Recv(message, size, MPI_CHAR, i, tag, comm, &status));
6199566063dSJacob Faibussowitsch         PetscCall(PetscFPrintf(comm, fd, "%s", message));
6209566063dSJacob Faibussowitsch         PetscCall(PetscFree(message));
621e5c89e4eSSatish Balay       }
622e5c89e4eSSatish Balay     }
623e5c89e4eSSatish Balay   } else { /* other processors send queue to processor 0 */
624d30b0576SJed Brown     PrintfQueue next = petsc_printfqueuebase, previous;
625e5c89e4eSSatish Balay 
6269566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Recv(&dummy, 1, MPI_INT, 0, tag, comm, &status));
6279566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Send(&petsc_printfqueuelength, 1, MPI_INT, 0, tag, comm));
628d30b0576SJed Brown     for (i = 0; i < petsc_printfqueuelength; i++) {
6299566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Send(&next->size, 1, MPI_INT, 0, tag, comm));
6309566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Send(next->string, next->size, MPI_CHAR, 0, tag, comm));
631e5c89e4eSSatish Balay       previous = next;
632e5c89e4eSSatish Balay       next     = next->next;
6339566063dSJacob Faibussowitsch       PetscCall(PetscFree(previous->string));
6349566063dSJacob Faibussowitsch       PetscCall(PetscFree(previous));
635e5c89e4eSSatish Balay     }
63602c9f0b5SLisandro Dalcin     petsc_printfqueue       = NULL;
637d30b0576SJed Brown     petsc_printfqueuelength = 0;
638e5c89e4eSSatish Balay   }
6399566063dSJacob Faibussowitsch   PetscCall(PetscCommDestroy(&comm));
6403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
641e5c89e4eSSatish Balay }
642e5c89e4eSSatish Balay 
643e5c89e4eSSatish Balay /*@C
644e5c89e4eSSatish Balay   PetscFPrintf - Prints to a file, only from the first
64521532e8aSBarry Smith   MPI process in the communicator.
646e5c89e4eSSatish Balay 
647cf53795eSBarry Smith   Not Collective; No Fortran Support
648e5c89e4eSSatish Balay 
649e5c89e4eSSatish Balay   Input Parameters:
650058c9ee1SBarry Smith + comm   - the MPI communicator
651e5c89e4eSSatish Balay . fd     - the file pointer
6526026c97aSBarry Smith - format - the usual `printf()` format string
653e5c89e4eSSatish Balay 
654e5c89e4eSSatish Balay   Level: intermediate
655e5c89e4eSSatish Balay 
656aec76313SJacob Faibussowitsch   Developer Notes:
657058c9ee1SBarry Smith   This maybe, and is, called from PETSc error handlers and `PetscMallocValidate()` hence it does not use `PetscCallMPI()` which
658058c9ee1SBarry Smith   could recursively restart the malloc validation.
659058c9ee1SBarry Smith 
660db781477SPatrick Sanan .seealso: `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
661c69effb2SJacob Faibussowitsch           `PetscViewerASCIISynchronizedPrintf()`, `PetscSynchronizedFlush()`, `PetscFFlush()`
662e5c89e4eSSatish Balay @*/
663d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFPrintf(MPI_Comm comm, FILE *fd, const char format[], ...)
664d71ae5a4SJacob Faibussowitsch {
6658c509928SStefano Zampini   PetscMPIInt rank;
666eae3dc7dSJacob Faibussowitsch   va_list     Argp;
667e5c89e4eSSatish Balay 
668e5c89e4eSSatish Balay   PetscFunctionBegin;
6698c509928SStefano Zampini   PetscCallMPI(MPI_Comm_rank(comm, &rank));
6708c509928SStefano Zampini   if (PetscLikely(rank != 0)) PetscFunctionReturn(PETSC_SUCCESS);
671e5c89e4eSSatish Balay   va_start(Argp, format);
6728c509928SStefano Zampini   PetscCall(PetscVFPrintf_Private(fd, format, Argp));
673e5c89e4eSSatish Balay   va_end(Argp);
6743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
675e5c89e4eSSatish Balay }
676e5c89e4eSSatish Balay 
677e5c89e4eSSatish Balay /*@C
678e5c89e4eSSatish Balay   PetscPrintf - Prints to standard out, only from the first
67921532e8aSBarry Smith   MPI process in the communicator. Calls from other processes are ignored.
680e5c89e4eSSatish Balay 
681e5c89e4eSSatish Balay   Not Collective
682e5c89e4eSSatish Balay 
683e5c89e4eSSatish Balay   Input Parameters:
684e5c89e4eSSatish Balay + comm   - the communicator
685bfbbc7b7SBarry Smith - format - the usual `printf()` format string
686e5c89e4eSSatish Balay 
687e5c89e4eSSatish Balay   Level: intermediate
688e5c89e4eSSatish Balay 
689811af0c4SBarry Smith   Note:
690811af0c4SBarry Smith   Deprecated information: `PetscPrintf()` supports some format specifiers that are unique to PETSc.
691811af0c4SBarry Smith   See the manual page for `PetscFormatConvert()` for details.
692b2706f25SRichard Tran Mills 
693aec76313SJacob Faibussowitsch   Fortran Notes:
694811af0c4SBarry Smith   The call sequence is `PetscPrintf`(MPI_Comm, character(*), `PetscErrorCode` ierr) from Fortran.
695e5c89e4eSSatish Balay   That is, you can only pass a single character string from Fortran.
696e5c89e4eSSatish Balay 
697c69effb2SJacob Faibussowitsch .seealso: `PetscFPrintf()`, `PetscSynchronizedPrintf()`, `PetscFormatConvert()`, `PetscFFlush()`
698e5c89e4eSSatish Balay @*/
699d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscPrintf(MPI_Comm comm, const char format[], ...)
700d71ae5a4SJacob Faibussowitsch {
7018c509928SStefano Zampini   PetscMPIInt rank;
702eae3dc7dSJacob Faibussowitsch   va_list     Argp;
703e5c89e4eSSatish Balay 
704e5c89e4eSSatish Balay   PetscFunctionBegin;
7058c509928SStefano Zampini   PetscCallMPI(MPI_Comm_rank(comm, &rank));
7068c509928SStefano Zampini   if (PetscLikely(rank != 0)) PetscFunctionReturn(PETSC_SUCCESS);
707e5c89e4eSSatish Balay   va_start(Argp, format);
7088c509928SStefano Zampini   PetscCall(PetscVFPrintf_Private(PETSC_STDOUT, format, Argp));
709e5c89e4eSSatish Balay   va_end(Argp);
7103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
711e5c89e4eSSatish Balay }
712e5c89e4eSSatish Balay 
713d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscHelpPrintfDefault(MPI_Comm comm, const char format[], ...)
714d71ae5a4SJacob Faibussowitsch {
7158c509928SStefano Zampini   PetscMPIInt rank;
716eae3dc7dSJacob Faibussowitsch   va_list     Argp;
717e5c89e4eSSatish Balay 
718e5c89e4eSSatish Balay   PetscFunctionBegin;
7198c509928SStefano Zampini   PetscCallMPI(MPI_Comm_rank(comm, &rank));
7208c509928SStefano Zampini   if (PetscLikely(rank != 0)) PetscFunctionReturn(PETSC_SUCCESS);
721e5c89e4eSSatish Balay   va_start(Argp, format);
7228c509928SStefano Zampini   PetscCall(PetscVFPrintf_Private(PETSC_STDOUT, format, Argp));
723e5c89e4eSSatish Balay   va_end(Argp);
7243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
725e5c89e4eSSatish Balay }
726e5c89e4eSSatish Balay 
727e5c89e4eSSatish Balay /*@C
72821532e8aSBarry Smith   PetscSynchronizedFGets - Multiple MPI processes all get the same line from a file.
729e5c89e4eSSatish Balay 
730d083f849SBarry Smith   Collective
731e5c89e4eSSatish Balay 
732e5c89e4eSSatish Balay   Input Parameters:
73321532e8aSBarry Smith + comm - the MPI communicator
734aec76313SJacob Faibussowitsch . fp   - the file pointer
73521532e8aSBarry Smith - len  - the length of `string`
736e5c89e4eSSatish Balay 
737e5c89e4eSSatish Balay   Output Parameter:
73821532e8aSBarry Smith . string - the line read from the file, at end of file `string`[0] == 0
739e5c89e4eSSatish Balay 
740e5c89e4eSSatish Balay   Level: intermediate
741e5c89e4eSSatish Balay 
742db781477SPatrick Sanan .seealso: `PetscSynchronizedPrintf()`, `PetscSynchronizedFlush()`,
743db781477SPatrick Sanan           `PetscFOpen()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIPrintf()`
744e5c89e4eSSatish Balay @*/
745d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSynchronizedFGets(MPI_Comm comm, FILE *fp, size_t len, char string[])
746d71ae5a4SJacob Faibussowitsch {
747e5c89e4eSSatish Balay   PetscMPIInt rank;
748e5c89e4eSSatish Balay 
749e5c89e4eSSatish Balay   PetscFunctionBegin;
7509566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
75180971c97SJames Wright   if (rank == 0) {
752eae3dc7dSJacob Faibussowitsch     if (!fgets(string, len, fp)) {
753e31d4fa4SJed Brown       string[0] = 0;
754bf31d2d3SBarry Smith       PetscCheck(feof(fp), PETSC_COMM_SELF, PETSC_ERR_FILE_READ, "Error reading from file due to \"%s\"", strerror(errno));
755047b9c12SMatthew G Knepley     }
756238ccf28SShri Abhyankar   }
7579566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Bcast(string, len, MPI_BYTE, 0, comm));
7583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
759e5c89e4eSSatish Balay }
760238ccf28SShri Abhyankar 
761d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFormatRealArray(char buf[], size_t len, const char *fmt, PetscInt n, const PetscReal x[])
762d71ae5a4SJacob Faibussowitsch {
7631b5687a1SBarry Smith   PetscInt i;
7641b5687a1SBarry Smith   size_t   left, count;
7651b5687a1SBarry Smith   char    *p;
7661b5687a1SBarry Smith 
7671b5687a1SBarry Smith   PetscFunctionBegin;
7681b5687a1SBarry Smith   for (i = 0, p = buf, left = len; i < n; i++) {
7699566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintfCount(p, left, fmt, &count, (double)x[i]));
77008401ef6SPierre Jolivet     PetscCheck(count < left, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Insufficient space in buffer");
7711b5687a1SBarry Smith     left -= count;
7721b5687a1SBarry Smith     p += count - 1;
7731b5687a1SBarry Smith     *p++ = ' ';
7741b5687a1SBarry Smith   }
7751b5687a1SBarry Smith   p[i ? 0 : -1] = 0;
7763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7771b5687a1SBarry Smith }
778