xref: /petsc/src/sys/fileio/mprint.c (revision 21532e8a5a1a1e7911222ee0f2ed1e65b4f3f1d8)
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
25*21532e8aSBarry 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;
453ca90d2dSJacob Faibussowitsch   PetscValidCharPointer(format, 1);
463ca90d2dSJacob Faibussowitsch   PetscValidPointer(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
79058c9ee1SBarry Smith      PetscFormatConvert - converts %g to [|%g|] so that `PetscVSNPrintf()` can ensure all %g formatted numbers have a decimal point when printed. The
80058c9ee1SBarry Smith      decimal point is then used by the `petscdiff` script so that differences in floating point number output is ignored in the test harness.
81d781fa04SBarry Smith 
82058c9ee1SBarry Smith    No Fortran Support
83811af0c4SBarry Smith 
84d781fa04SBarry Smith    Input Parameters:
85d781fa04SBarry Smith +   format - the PETSc format string
86811af0c4SBarry Smith -   size - the length of newformat, you can use `PetscFormatConvertGetSize()` to compute the needed size
87d781fa04SBarry Smith 
88*21532e8aSBarry Smith    Output Parameter:
89*21532e8aSBarry Smith .   newformat - the new format
90*21532e8aSBarry Smith 
91d781fa04SBarry Smith    Level: developer
92d781fa04SBarry Smith 
93058c9ee1SBarry Smith     Note:
94*21532e8aSBarry Smith     Deprecated usage also converts the `%D` to `%d` for 32 bit PETSc indices and to `%lld` for 64 bit PETSc indices. This feature is no
95058c9ee1SBarry Smith     longer used in PETSc code instead use %" PetscInt_FMT " in the format string
96058c9ee1SBarry Smith 
97db781477SPatrick Sanan .seealso: `PetscFormatConvertGetSize()`, `PetscVSNPrintf()`, `PetscVFPrintf()`
98d781fa04SBarry Smith @*/
99d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFormatConvert(const char *format, char *newformat)
100d71ae5a4SJacob Faibussowitsch {
101e5c89e4eSSatish Balay   PetscInt i = 0, j = 0;
102e5c89e4eSSatish Balay 
103eed5747fSBarry Smith   PetscFunctionBegin;
104d781fa04SBarry Smith   while (format[i]) {
1052a1ad9caSBarry Smith     if (format[i] == '%' && format[i + 1] == '%') {
1062a1ad9caSBarry Smith       newformat[j++] = format[i++];
1072a1ad9caSBarry Smith       newformat[j++] = format[i++];
1082a1ad9caSBarry Smith     } else if (format[i] == '%') {
1098627564fSBarry Smith       if (format[i + 1] == 'g') {
1108627564fSBarry Smith         newformat[j++] = '[';
1118627564fSBarry Smith         newformat[j++] = '|';
1128627564fSBarry Smith       }
1137bc47156SJose Roman       /* Find the letter */
1147bc47156SJose Roman       for (; format[i] && format[i] <= '9'; i++) newformat[j++] = format[i];
1157bc47156SJose Roman       switch (format[i]) {
1167bc47156SJose Roman       case 'D':
1176de02169SBarry Smith #if !defined(PETSC_USE_64BIT_INDICES)
118e5c89e4eSSatish Balay         newformat[j++] = 'd';
119e5c89e4eSSatish Balay #else
120e5c89e4eSSatish Balay         newformat[j++] = 'l';
121e5c89e4eSSatish Balay         newformat[j++] = 'l';
122e5c89e4eSSatish Balay         newformat[j++] = 'd';
123e5c89e4eSSatish Balay #endif
1247bc47156SJose Roman         break;
1258627564fSBarry Smith       case 'g':
1268627564fSBarry Smith         newformat[j++] = format[i];
1278627564fSBarry Smith         if (format[i - 1] == '%') {
1288627564fSBarry Smith           newformat[j++] = '|';
1298627564fSBarry Smith           newformat[j++] = ']';
1308627564fSBarry Smith         }
1318627564fSBarry Smith         break;
132d71ae5a4SJacob Faibussowitsch       case 'G':
133d71ae5a4SJacob Faibussowitsch         SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "%%G format is no longer supported, use %%g and cast the argument to double");
134d71ae5a4SJacob Faibussowitsch       case 'F':
135d71ae5a4SJacob Faibussowitsch         SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "%%F format is no longer supported, use %%f and cast the argument to double");
136d71ae5a4SJacob Faibussowitsch       default:
137d71ae5a4SJacob Faibussowitsch         newformat[j++] = format[i];
138d71ae5a4SJacob Faibussowitsch         break;
1397bc47156SJose Roman       }
1407bc47156SJose Roman       i++;
141a297a907SKarl Rupp     } else newformat[j++] = format[i++];
142e5c89e4eSSatish Balay   }
143e5c89e4eSSatish Balay   newformat[j] = 0;
1443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
145e5c89e4eSSatish Balay }
146e5c89e4eSSatish Balay 
14714416c0eSBarry Smith #define PETSCDEFAULTBUFFERSIZE 8 * 1024
148d781fa04SBarry Smith 
149c9a19010SBarry Smith /*@C
1506026c97aSBarry Smith      PetscVSNPrintf - The PETSc version of `vsnprintf()`. Ensures that all `%g` formatted arguments' output contains the decimal point (which
151058c9ee1SBarry Smith      is used by the test harness)
152c9a19010SBarry Smith 
153c9a19010SBarry Smith    Input Parameters:
154c9a19010SBarry Smith +   str - location to put result
155*21532e8aSBarry Smith .   len - the length of `str`
156*21532e8aSBarry Smith -   format - the PETSc format string
157*21532e8aSBarry Smith 
158*21532e8aSBarry Smith     Output Parameter:
159*21532e8aSBarry Smith .   fullLength - the amount of space in `str` actually used.
160c9a19010SBarry Smith 
161c9a19010SBarry Smith    Level: developer
162c9a19010SBarry Smith 
163058c9ee1SBarry Smith    Developer Note:
164058c9ee1SBarry Smith    This function may be called from an error handler, if an error occurs when it is called by the error handler than likely
165058c9ee1SBarry Smith    a recursion will occur resulting in a crash of the program.
166058c9ee1SBarry Smith 
167*21532e8aSBarry 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()`
168058c9ee1SBarry Smith 
169058c9ee1SBarry Smith .seealso: `PetscFormatConvert()`, `PetscFormatConvertGetSize()`, `PetscVSNPrintf()`, `PetscErrorPrintf()`, `PetscVPrintf()`
170c9a19010SBarry Smith @*/
171d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscVSNPrintf(char *str, size_t len, const char *format, size_t *fullLength, va_list Argp)
172d71ae5a4SJacob Faibussowitsch {
173d781fa04SBarry Smith   char  *newformat = NULL;
17414416c0eSBarry Smith   char   formatbuf[PETSCDEFAULTBUFFERSIZE];
175d781fa04SBarry Smith   size_t newLength;
17614416c0eSBarry Smith   int    flen;
177e5c89e4eSSatish Balay 
178eed5747fSBarry Smith   PetscFunctionBegin;
1799566063dSJacob Faibussowitsch   PetscCall(PetscFormatConvertGetSize(format, &newLength));
18094217ebdSBarry Smith   if (newLength < sizeof(formatbuf)) {
181e2135aedSMatthew Knepley     newformat = formatbuf;
18294217ebdSBarry Smith     newLength = sizeof(formatbuf) - 1;
183e2135aedSMatthew Knepley   } else {
1849566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(newLength, &newformat));
185e2135aedSMatthew Knepley   }
1869566063dSJacob Faibussowitsch   PetscCall(PetscFormatConvert(format, newformat));
1877b9a2d1bSSatish Balay #if defined(PETSC_HAVE_VSNPRINTF)
188152b30f0SSatish Balay   flen = vsnprintf(str, len, newformat, Argp);
189e5c89e4eSSatish Balay #else
19089b07760SSatish Balay   #error "vsnprintf not found"
191e5c89e4eSSatish Balay #endif
19248a46eb9SPierre Jolivet   if (newLength > sizeof(formatbuf) - 1) PetscCall(PetscFree(newformat));
1938627564fSBarry Smith   {
1948627564fSBarry Smith     PetscBool foundedot;
1958627564fSBarry Smith     size_t    cnt = 0, ncnt = 0, leng;
1969566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(str, &leng));
19717ca8410SBarry Smith     if (leng > 4) {
1988627564fSBarry Smith       for (cnt = 0; cnt < leng - 4; cnt++) {
1998627564fSBarry Smith         if (str[cnt] == '[' && str[cnt + 1] == '|') {
200c540d043SBarry Smith           flen -= 4;
2019371c9d4SSatish Balay           cnt++;
2029371c9d4SSatish Balay           cnt++;
2038627564fSBarry Smith           foundedot = PETSC_FALSE;
2048627564fSBarry Smith           for (; cnt < leng - 1; cnt++) {
2058627564fSBarry Smith             if (str[cnt] == '|' && str[cnt + 1] == ']') {
2068627564fSBarry Smith               cnt++;
2078627564fSBarry Smith               if (!foundedot) str[ncnt++] = '.';
2088627564fSBarry Smith               ncnt--;
2098627564fSBarry Smith               break;
2108627564fSBarry Smith             } else {
2118627564fSBarry Smith               if (str[cnt] == 'e' || str[cnt] == '.') foundedot = PETSC_TRUE;
2128627564fSBarry Smith               str[ncnt++] = str[cnt];
2138627564fSBarry Smith             }
2148627564fSBarry Smith           }
2158627564fSBarry Smith         } else {
2168627564fSBarry Smith           str[ncnt] = str[cnt];
2178627564fSBarry Smith         }
2188627564fSBarry Smith         ncnt++;
2198627564fSBarry Smith       }
2208627564fSBarry Smith       while (cnt < leng) {
2219371c9d4SSatish Balay         str[ncnt] = str[cnt];
2229371c9d4SSatish Balay         ncnt++;
2239371c9d4SSatish Balay         cnt++;
2248627564fSBarry Smith       }
2258627564fSBarry Smith       str[ncnt] = 0;
2268627564fSBarry Smith     }
2278627564fSBarry Smith   }
228748e1b9dSBarry Smith #if defined(PETSC_HAVE_WINDOWS_H) && !defined(PETSC_HAVE__SET_OUTPUT_FORMAT)
229e51f71cfSBarry Smith   /* older Windows OS always produces e-+0np for floating point output; remove the extra 0 */
230748e1b9dSBarry Smith   {
231748e1b9dSBarry Smith     size_t cnt = 0, ncnt = 0, leng;
2329566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(str, &leng));
233748e1b9dSBarry Smith     if (leng > 5) {
234748e1b9dSBarry Smith       for (cnt = 0; cnt < leng - 4; cnt++) {
235e51f71cfSBarry 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') {
2369371c9d4SSatish Balay           str[ncnt] = str[cnt];
2379371c9d4SSatish Balay           ncnt++;
2389371c9d4SSatish Balay           cnt++;
2399371c9d4SSatish Balay           str[ncnt] = str[cnt];
2409371c9d4SSatish Balay           ncnt++;
2419371c9d4SSatish Balay           cnt++;
2429371c9d4SSatish Balay           cnt++;
243e51f71cfSBarry Smith           str[ncnt] = str[cnt];
244748e1b9dSBarry Smith         } else {
245748e1b9dSBarry Smith           str[ncnt] = str[cnt];
246748e1b9dSBarry Smith         }
247748e1b9dSBarry Smith         ncnt++;
248748e1b9dSBarry Smith       }
249748e1b9dSBarry Smith       while (cnt < leng) {
2509371c9d4SSatish Balay         str[ncnt] = str[cnt];
2519371c9d4SSatish Balay         ncnt++;
2529371c9d4SSatish Balay         cnt++;
253748e1b9dSBarry Smith       }
254748e1b9dSBarry Smith       str[ncnt] = 0;
255748e1b9dSBarry Smith     }
256748e1b9dSBarry Smith   }
257748e1b9dSBarry Smith #endif
258c540d043SBarry Smith   if (fullLength) *fullLength = 1 + (size_t)flen;
2593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
260e5c89e4eSSatish Balay }
261e5c89e4eSSatish Balay 
262c9a19010SBarry Smith /*@C
263c69effb2SJacob Faibussowitsch   PetscFFlush - Flush a file stream
264c69effb2SJacob Faibussowitsch 
265c69effb2SJacob Faibussowitsch   Input Parameter:
266c69effb2SJacob Faibussowitsch . fd - The file stream handle
267c69effb2SJacob Faibussowitsch 
268c69effb2SJacob Faibussowitsch   Level: intermediate
269c69effb2SJacob Faibussowitsch 
270c69effb2SJacob Faibussowitsch   Notes:
271c69effb2SJacob Faibussowitsch   For output streams (and for update streams on which the last operation was output), writes
272c69effb2SJacob Faibussowitsch   any unwritten data from the stream's buffer to the associated output device.
273c69effb2SJacob Faibussowitsch 
274c69effb2SJacob Faibussowitsch   For input streams (and for update streams on which the last operation was input), the
275c69effb2SJacob Faibussowitsch   behavior is undefined.
276c69effb2SJacob Faibussowitsch 
277c69effb2SJacob Faibussowitsch   If `fd` is `NULL`, all open output streams are flushed, including ones not directly
278c69effb2SJacob Faibussowitsch   accessible to the program.
279c69effb2SJacob Faibussowitsch 
280c69effb2SJacob Faibussowitsch .seealso: `PetscPrintf()`, `PetscFPrintf()`, `PetscVFPrintf()`, `PetscVSNPrintf()`
281c69effb2SJacob Faibussowitsch @*/
282c69effb2SJacob Faibussowitsch PetscErrorCode PetscFFlush(FILE *fd)
283c69effb2SJacob Faibussowitsch {
284c69effb2SJacob Faibussowitsch   int ret;
285c69effb2SJacob Faibussowitsch 
286c69effb2SJacob Faibussowitsch   PetscFunctionBegin;
287c69effb2SJacob Faibussowitsch   if (fd) PetscValidPointer(fd, 1);
288c69effb2SJacob Faibussowitsch   ret = fflush(fd);
289c69effb2SJacob Faibussowitsch   // could also use PetscCallExternal() here, but since we can get additional error explanation
290c69effb2SJacob Faibussowitsch   // from strerror() we opted for a manual check
291c69effb2SJacob Faibussowitsch   PetscCheck(ret == 0, PETSC_COMM_SELF, PETSC_ERR_FILE_WRITE, "Error in fflush(): error code %d (%s)", ret, strerror(errno));
292c69effb2SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
293c69effb2SJacob Faibussowitsch }
294c69effb2SJacob Faibussowitsch 
295c69effb2SJacob Faibussowitsch /*@C
296c9a19010SBarry Smith      PetscVFPrintf -  All PETSc standard out and error messages are sent through this function; so, in theory, this can
297e5c89e4eSSatish Balay         can be replaced with something that does not simply write to a file.
298e5c89e4eSSatish Balay 
299c9a19010SBarry Smith       To use, write your own function for example,
300058c9ee1SBarry Smith .vb
301058c9ee1SBarry Smith    PetscErrorCode mypetscvfprintf(FILE *fd, const char format[], va_list Argp)
302058c9ee1SBarry Smith    {
303058c9ee1SBarry Smith      PetscErrorCode ierr;
304058c9ee1SBarry Smith 
305058c9ee1SBarry Smith      PetscFunctionBegin;
306058c9ee1SBarry Smith       if (fd != stdout && fd != stderr) {  handle regular files
307058c9ee1SBarry Smith          CHKERR(PetscVFPrintfDefault(fd,format,Argp));
308058c9ee1SBarry Smith      } else {
309058c9ee1SBarry Smith         char   buff[BIG];
310058c9ee1SBarry Smith         size_t length;
311058c9ee1SBarry Smith         PetscCall(PetscVSNPrintf(buff,BIG,format,&length,Argp));
312058c9ee1SBarry Smith         now send buff to whatever stream or whatever you want
313058c9ee1SBarry Smith     }
314058c9ee1SBarry Smith     PetscFunctionReturn(PETSC_SUCCESS);
315058c9ee1SBarry Smith    }
316058c9ee1SBarry Smith .ve
317058c9ee1SBarry Smith    then before the call to `PetscInitialize()` do the assignment `PetscVFPrintf = mypetscvfprintf`;
318058c9ee1SBarry Smith 
319058c9ee1SBarry Smith   Level:  developer
320c9a19010SBarry Smith 
321811af0c4SBarry Smith    Note:
322*21532e8aSBarry Smith    For error messages this may be called by any MPI process, for regular standard out it is
323*21532e8aSBarry Smith    called only by MPI rank 0 of a given communicator
324e5c89e4eSSatish Balay 
325811af0c4SBarry Smith    Developer Note:
326058c9ee1SBarry Smith    This could be called by an error handler, if that happens then a recursion of the error handler may occur
327058c9ee1SBarry Smith    and a resulting crash
328c9a19010SBarry Smith 
329c69effb2SJacob Faibussowitsch .seealso: `PetscVSNPrintf()`, `PetscErrorPrintf()`, `PetscFFlush()`
330c9a19010SBarry Smith @*/
331d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscVFPrintfDefault(FILE *fd, const char *format, va_list Argp)
332d71ae5a4SJacob Faibussowitsch {
33314416c0eSBarry Smith   char   str[PETSCDEFAULTBUFFERSIZE];
33414416c0eSBarry Smith   char  *buff = str;
33514416c0eSBarry Smith   size_t fullLength;
3361531940fSBarry Smith #if defined(PETSC_HAVE_VA_COPY)
33714416c0eSBarry Smith   va_list Argpcopy;
3381531940fSBarry Smith #endif
3391179db26SBarry Smith 
340eed5747fSBarry Smith   PetscFunctionBegin;
3411531940fSBarry Smith #if defined(PETSC_HAVE_VA_COPY)
34214416c0eSBarry Smith   va_copy(Argpcopy, Argp);
3431531940fSBarry Smith #endif
3449566063dSJacob Faibussowitsch   PetscCall(PetscVSNPrintf(str, sizeof(str), format, &fullLength, Argp));
34514416c0eSBarry Smith   if (fullLength > sizeof(str)) {
3469566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(fullLength, &buff));
3471531940fSBarry Smith #if defined(PETSC_HAVE_VA_COPY)
3489566063dSJacob Faibussowitsch     PetscCall(PetscVSNPrintf(buff, fullLength, format, NULL, Argpcopy));
3491531940fSBarry Smith #else
3501531940fSBarry Smith     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "C89 does not support va_copy() hence cannot print long strings with PETSc printing routines");
3511531940fSBarry Smith #endif
35214416c0eSBarry Smith   }
353eae3dc7dSJacob Faibussowitsch #if defined(PETSC_HAVE_VA_COPY)
354eae3dc7dSJacob Faibussowitsch   va_end(Argpcopy);
355eae3dc7dSJacob Faibussowitsch #endif
356c69effb2SJacob Faibussowitsch   {
357c69effb2SJacob Faibussowitsch     const int err = fprintf(fd, "%s", buff);
358c69effb2SJacob Faibussowitsch     // cannot use PetscCallExternal() for fprintf since the return value is "number of
359c69effb2SJacob Faibussowitsch     // characters transmitted to the output stream" on success
360c69effb2SJacob Faibussowitsch     PetscCheck(err >= 0, PETSC_COMM_SELF, PETSC_ERR_FILE_WRITE, "fprintf() returned error code %d", err);
361c69effb2SJacob Faibussowitsch   }
362c69effb2SJacob Faibussowitsch   PetscCall(PetscFFlush(fd));
36348a46eb9SPierre Jolivet   if (buff != str) PetscCall(PetscFree(buff));
3643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
365e5c89e4eSSatish Balay }
366e5c89e4eSSatish Balay 
3675b5bc046SBarry Smith /*@C
3685b5bc046SBarry Smith     PetscSNPrintf - Prints to a string of given length
3695b5bc046SBarry Smith 
3705b5bc046SBarry Smith     Not Collective
3715b5bc046SBarry Smith 
3725b5bc046SBarry Smith     Input Parameters:
373*21532e8aSBarry Smith +   len - the length of `str`
374058c9ee1SBarry Smith .   format - the usual `printf()` format string
37510699b91SBarry Smith -   ... - any arguments that are to be printed, each much have an appropriate symbol in the format argument
3765b5bc046SBarry Smith 
377*21532e8aSBarry Smith     Output Parameter:
378*21532e8aSBarry Smith .   str - the resulting string
379*21532e8aSBarry Smith 
3805b5bc046SBarry Smith    Level: intermediate
3815b5bc046SBarry Smith 
382db781477SPatrick Sanan .seealso: `PetscSynchronizedFlush()`, `PetscSynchronizedFPrintf()`, `PetscFPrintf()`, `PetscVSNPrintf()`,
383c69effb2SJacob Faibussowitsch           `PetscPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIISynchronizedPrintf()`,
384c69effb2SJacob Faibussowitsch           `PetscVFPrintf()`, `PetscFFlush()`
3855b5bc046SBarry Smith @*/
386d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSNPrintf(char *str, size_t len, const char format[], ...)
387d71ae5a4SJacob Faibussowitsch {
388c9a19010SBarry Smith   size_t  fullLength;
3895b5bc046SBarry Smith   va_list Argp;
3905b5bc046SBarry Smith 
3915b5bc046SBarry Smith   PetscFunctionBegin;
3925b5bc046SBarry Smith   va_start(Argp, format);
3939566063dSJacob Faibussowitsch   PetscCall(PetscVSNPrintf(str, len, format, &fullLength, Argp));
394eae3dc7dSJacob Faibussowitsch   va_end(Argp);
3953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3965b5bc046SBarry Smith }
3975b5bc046SBarry Smith 
398257d2499SJed Brown /*@C
399058c9ee1SBarry Smith     PetscSNPrintfCount - Prints to a string of given length, returns count of characters printed
400257d2499SJed Brown 
401257d2499SJed Brown     Not Collective
402257d2499SJed Brown 
403257d2499SJed Brown     Input Parameters:
404*21532e8aSBarry Smith +   len - the length of `str`
405058c9ee1SBarry Smith .   format - the usual `printf()` format string
40610699b91SBarry Smith -   ... - any arguments that are to be printed, each much have an appropriate symbol in the format argument
407257d2499SJed Brown 
408*21532e8aSBarry Smith     Output Parameters:
409*21532e8aSBarry Smith +   str - the resulting string
410*21532e8aSBarry Smith -   countused - number of characters printed
411cb398dd3SBarry Smith 
412257d2499SJed Brown    Level: intermediate
413257d2499SJed Brown 
414db781477SPatrick Sanan .seealso: `PetscSynchronizedFlush()`, `PetscSynchronizedFPrintf()`, `PetscFPrintf()`, `PetscVSNPrintf()`,
415db781477SPatrick Sanan           `PetscPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscSNPrintf()`, `PetscVFPrintf()`
416257d2499SJed Brown @*/
417d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSNPrintfCount(char *str, size_t len, const char format[], size_t *countused, ...)
418d71ae5a4SJacob Faibussowitsch {
419257d2499SJed Brown   va_list Argp;
420257d2499SJed Brown 
421257d2499SJed Brown   PetscFunctionBegin;
422257d2499SJed Brown   va_start(Argp, countused);
4239566063dSJacob Faibussowitsch   PetscCall(PetscVSNPrintf(str, len, format, countused, Argp));
424eae3dc7dSJacob Faibussowitsch   va_end(Argp);
4253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
426257d2499SJed Brown }
427257d2499SJed Brown 
42802c9f0b5SLisandro Dalcin PrintfQueue petsc_printfqueue = NULL, petsc_printfqueuebase = NULL;
429d30b0576SJed Brown int         petsc_printfqueuelength = 0;
430e5c89e4eSSatish Balay 
431eae3dc7dSJacob Faibussowitsch static inline PetscErrorCode PetscVFPrintf_Private(MPI_Comm comm, FILE *fd, const char format[], va_list Argp)
432eae3dc7dSJacob Faibussowitsch {
433eae3dc7dSJacob Faibussowitsch   const PetscBool tee = (PetscBool)(petsc_history && (fd != petsc_history));
434eae3dc7dSJacob Faibussowitsch   PetscMPIInt     rank;
435eae3dc7dSJacob Faibussowitsch   va_list         cpy;
436eae3dc7dSJacob Faibussowitsch 
437eae3dc7dSJacob Faibussowitsch   PetscFunctionBegin;
438eae3dc7dSJacob Faibussowitsch   PetscCheck(comm != MPI_COMM_NULL, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Called with MPI_COMM_NULL, likely PetscObjectComm() failed");
439eae3dc7dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
440eae3dc7dSJacob Faibussowitsch   if (PetscLikely(rank != 0)) PetscFunctionReturn(PETSC_SUCCESS);
441eae3dc7dSJacob Faibussowitsch   // must do this before we possibly consume Argp
442eae3dc7dSJacob Faibussowitsch   if (tee) va_copy(cpy, Argp);
443eae3dc7dSJacob Faibussowitsch   PetscCall((*PetscVFPrintf)(fd, format, Argp));
444eae3dc7dSJacob Faibussowitsch   if (tee) {
445eae3dc7dSJacob Faibussowitsch     PetscCall((*PetscVFPrintf)(petsc_history, format, cpy));
446eae3dc7dSJacob Faibussowitsch     va_end(cpy);
447eae3dc7dSJacob Faibussowitsch   }
448eae3dc7dSJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
449eae3dc7dSJacob Faibussowitsch }
450eae3dc7dSJacob Faibussowitsch 
451eae3dc7dSJacob Faibussowitsch static inline PetscErrorCode PetscSynchronizedFPrintf_Private(MPI_Comm comm, FILE *fp, const char format[], va_list Argp)
452eae3dc7dSJacob Faibussowitsch {
453eae3dc7dSJacob Faibussowitsch   PetscMPIInt rank;
454eae3dc7dSJacob Faibussowitsch   va_list     cpy;
455eae3dc7dSJacob Faibussowitsch 
456eae3dc7dSJacob Faibussowitsch   PetscFunctionBegin;
457eae3dc7dSJacob Faibussowitsch   PetscCheck(comm != MPI_COMM_NULL, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Called with MPI_COMM_NULL, likely PetscObjectComm() failed");
458eae3dc7dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
459eae3dc7dSJacob Faibussowitsch   /* First processor prints immediately to fp */
460eae3dc7dSJacob Faibussowitsch   if (rank == 0) {
461eae3dc7dSJacob Faibussowitsch     va_copy(cpy, Argp);
462eae3dc7dSJacob Faibussowitsch     PetscCall(PetscVFPrintf_Private(comm, fp, format, cpy));
463eae3dc7dSJacob Faibussowitsch     va_end(cpy);
464eae3dc7dSJacob Faibussowitsch   } else { /* other processors add to local queue */
465eae3dc7dSJacob Faibussowitsch     PrintfQueue next;
466eae3dc7dSJacob Faibussowitsch     size_t      fullLength = PETSCDEFAULTBUFFERSIZE;
467eae3dc7dSJacob Faibussowitsch 
468eae3dc7dSJacob Faibussowitsch     PetscCall(PetscNew(&next));
469eae3dc7dSJacob Faibussowitsch     if (petsc_printfqueue) {
470eae3dc7dSJacob Faibussowitsch       petsc_printfqueue->next = next;
471eae3dc7dSJacob Faibussowitsch       petsc_printfqueue       = next;
472eae3dc7dSJacob Faibussowitsch       petsc_printfqueue->next = NULL;
473eae3dc7dSJacob Faibussowitsch     } else petsc_printfqueuebase = petsc_printfqueue = next;
474eae3dc7dSJacob Faibussowitsch     petsc_printfqueuelength++;
475eae3dc7dSJacob Faibussowitsch     next->size   = 0;
476eae3dc7dSJacob Faibussowitsch     next->string = NULL;
477eae3dc7dSJacob Faibussowitsch     while (fullLength >= next->size) {
478eae3dc7dSJacob Faibussowitsch       next->size = fullLength + 1;
479eae3dc7dSJacob Faibussowitsch       PetscCall(PetscFree(next->string));
480eae3dc7dSJacob Faibussowitsch       PetscCall(PetscMalloc1(next->size, &next->string));
481eae3dc7dSJacob Faibussowitsch       PetscCall(PetscArrayzero(next->string, next->size));
482eae3dc7dSJacob Faibussowitsch       va_copy(cpy, Argp);
483eae3dc7dSJacob Faibussowitsch       PetscCall(PetscVSNPrintf(next->string, next->size, format, &fullLength, cpy));
484eae3dc7dSJacob Faibussowitsch       va_end(cpy);
485eae3dc7dSJacob Faibussowitsch     }
486eae3dc7dSJacob Faibussowitsch   }
487eae3dc7dSJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
488eae3dc7dSJacob Faibussowitsch }
489eae3dc7dSJacob Faibussowitsch 
490e5c89e4eSSatish Balay /*@C
491*21532e8aSBarry Smith     PetscSynchronizedPrintf - Prints synchronized output from multple MPI processes.
492e5c89e4eSSatish Balay     Output of the first processor is followed by that of the second, etc.
493e5c89e4eSSatish Balay 
494e5c89e4eSSatish Balay     Not Collective
495e5c89e4eSSatish Balay 
496e5c89e4eSSatish Balay     Input Parameters:
497058c9ee1SBarry Smith +   comm - the MPI communicator
4986026c97aSBarry Smith -   format - the usual `printf()` format string
499e5c89e4eSSatish Balay 
500e5c89e4eSSatish Balay    Level: intermediate
501e5c89e4eSSatish Balay 
502811af0c4SBarry Smith     Note:
503811af0c4SBarry Smith     REQUIRES a call to `PetscSynchronizedFlush()` by all the processes after the completion of the calls to `PetscSynchronizedPrintf()` for the information
504e5c89e4eSSatish Balay     from all the processors to be printed.
505e5c89e4eSSatish Balay 
506e5c89e4eSSatish Balay     Fortran Note:
507058c9ee1SBarry Smith     The call sequence is `PetscSynchronizedPrintf`(`MPI_Comm`, `character`(*), `PetscErrorCode` ierr).
508e5c89e4eSSatish Balay     That is, you can only pass a single character string from Fortran.
509e5c89e4eSSatish Balay 
510db781477SPatrick Sanan .seealso: `PetscSynchronizedFlush()`, `PetscSynchronizedFPrintf()`, `PetscFPrintf()`,
511c69effb2SJacob Faibussowitsch           `PetscPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIISynchronizedPrintf()`,
512c69effb2SJacob Faibussowitsch           `PetscFFlush()`
513e5c89e4eSSatish Balay @*/
514d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSynchronizedPrintf(MPI_Comm comm, const char format[], ...)
515d71ae5a4SJacob Faibussowitsch {
516eae3dc7dSJacob Faibussowitsch   va_list Argp;
517e5c89e4eSSatish Balay 
518e5c89e4eSSatish Balay   PetscFunctionBegin;
519e5c89e4eSSatish Balay   va_start(Argp, format);
520eae3dc7dSJacob Faibussowitsch   PetscCall(PetscSynchronizedFPrintf_Private(comm, PETSC_STDOUT, format, Argp));
521e5c89e4eSSatish Balay   va_end(Argp);
5223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
523e5c89e4eSSatish Balay }
524e5c89e4eSSatish Balay 
525e5c89e4eSSatish Balay /*@C
526e5c89e4eSSatish Balay     PetscSynchronizedFPrintf - Prints synchronized output to the specified file from
527*21532e8aSBarry Smith     several MPI processes.  Output of the first process is followed by that of the
528e5c89e4eSSatish Balay     second, etc.
529e5c89e4eSSatish Balay 
530e5c89e4eSSatish Balay     Not Collective
531e5c89e4eSSatish Balay 
532e5c89e4eSSatish Balay     Input Parameters:
533058c9ee1SBarry Smith +   comm - the MPI communicator
534e5c89e4eSSatish Balay .   fd - the file pointer
5356026c97aSBarry Smith -   format - the usual `printf()` format string
536e5c89e4eSSatish Balay 
537e5c89e4eSSatish Balay     Level: intermediate
538e5c89e4eSSatish Balay 
539811af0c4SBarry Smith     Note:
540811af0c4SBarry Smith     REQUIRES a intervening call to `PetscSynchronizedFlush()` for the information
541e5c89e4eSSatish Balay     from all the processors to be printed.
542e5c89e4eSSatish Balay 
543db781477SPatrick Sanan .seealso: `PetscSynchronizedPrintf()`, `PetscSynchronizedFlush()`, `PetscFPrintf()`,
544c69effb2SJacob Faibussowitsch           `PetscFOpen()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
545c69effb2SJacob Faibussowitsch           `PetscFFlush()`
546e5c89e4eSSatish Balay @*/
547d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSynchronizedFPrintf(MPI_Comm comm, FILE *fp, const char format[], ...)
548d71ae5a4SJacob Faibussowitsch {
549eae3dc7dSJacob Faibussowitsch   va_list Argp;
550e5c89e4eSSatish Balay 
551e5c89e4eSSatish Balay   PetscFunctionBegin;
552e5c89e4eSSatish Balay   va_start(Argp, format);
553eae3dc7dSJacob Faibussowitsch   PetscCall(PetscSynchronizedFPrintf_Private(comm, fp, format, Argp));
554e5c89e4eSSatish Balay   va_end(Argp);
5553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
556e5c89e4eSSatish Balay }
557e5c89e4eSSatish Balay 
5580ec8b6e3SBarry Smith /*@C
559e5c89e4eSSatish Balay     PetscSynchronizedFlush - Flushes to the screen output from all processors
560811af0c4SBarry Smith     involved in previous `PetscSynchronizedPrintf()`/`PetscSynchronizedFPrintf()` calls.
561e5c89e4eSSatish Balay 
562d083f849SBarry Smith     Collective
563e5c89e4eSSatish Balay 
564e5c89e4eSSatish Balay     Input Parameters:
565058c9ee1SBarry Smith +   comm - the MPI communicator
566*21532e8aSBarry Smith -   fd - the file pointer (valid on MPI rank 0 of the communicator)
567e5c89e4eSSatish Balay 
568e5c89e4eSSatish Balay     Level: intermediate
569e5c89e4eSSatish Balay 
570811af0c4SBarry Smith     Note:
571811af0c4SBarry Smith     If `PetscSynchronizedPrintf()` and/or `PetscSynchronizedFPrintf()` are called with
572811af0c4SBarry Smith     different MPI communicators there must be an intervening call to `PetscSynchronizedFlush()` between the calls with different MPI communicators.
573e5c89e4eSSatish Balay 
574811af0c4SBarry Smith     Fortran Note:
575811af0c4SBarry Smith     Pass `PETSC_STDOUT` if the flush is for standard out; otherwise pass a value obtained from `PetscFOpen()`
576e50bf69fSBarry Smith 
577db781477SPatrick Sanan .seealso: `PetscSynchronizedPrintf()`, `PetscFPrintf()`, `PetscPrintf()`, `PetscViewerASCIIPrintf()`,
578db781477SPatrick Sanan           `PetscViewerASCIISynchronizedPrintf()`
5790087d953SMatthew G. Knepley @*/
580d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSynchronizedFlush(MPI_Comm comm, FILE *fd)
581d71ae5a4SJacob Faibussowitsch {
58229a5cbdcSMatthew G. Knepley   PetscMPIInt rank, size, tag, i, j, n = 0, dummy = 0;
5832d609e63SMatthew Knepley   char       *message;
584e5c89e4eSSatish Balay   MPI_Status  status;
585e5c89e4eSSatish Balay 
586e5c89e4eSSatish Balay   PetscFunctionBegin;
5879566063dSJacob Faibussowitsch   PetscCall(PetscCommDuplicate(comm, &comm, &tag));
5889566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
5899566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
590e5c89e4eSSatish Balay 
591e5c89e4eSSatish Balay   /* First processor waits for messages from all other processors */
592dd400576SPatrick Sanan   if (rank == 0) {
5930ec8b6e3SBarry Smith     if (!fd) fd = PETSC_STDOUT;
594e5c89e4eSSatish Balay     for (i = 1; i < size; i++) {
5959f73f8ecSBarry Smith       /* to prevent a flood of messages to process zero, request each message separately */
5969566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Send(&dummy, 1, MPI_INT, i, tag, comm));
5979566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Recv(&n, 1, MPI_INT, i, tag, comm, &status));
598e5c89e4eSSatish Balay       for (j = 0; j < n; j++) {
59929a5cbdcSMatthew G. Knepley         PetscMPIInt size = 0;
6002d609e63SMatthew Knepley 
6019566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Recv(&size, 1, MPI_INT, i, tag, comm, &status));
6029566063dSJacob Faibussowitsch         PetscCall(PetscMalloc1(size, &message));
6039566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Recv(message, size, MPI_CHAR, i, tag, comm, &status));
6049566063dSJacob Faibussowitsch         PetscCall(PetscFPrintf(comm, fd, "%s", message));
6059566063dSJacob Faibussowitsch         PetscCall(PetscFree(message));
606e5c89e4eSSatish Balay       }
607e5c89e4eSSatish Balay     }
608e5c89e4eSSatish Balay   } else { /* other processors send queue to processor 0 */
609d30b0576SJed Brown     PrintfQueue next = petsc_printfqueuebase, previous;
610e5c89e4eSSatish Balay 
6119566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Recv(&dummy, 1, MPI_INT, 0, tag, comm, &status));
6129566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Send(&petsc_printfqueuelength, 1, MPI_INT, 0, tag, comm));
613d30b0576SJed Brown     for (i = 0; i < petsc_printfqueuelength; i++) {
6149566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Send(&next->size, 1, MPI_INT, 0, tag, comm));
6159566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Send(next->string, next->size, MPI_CHAR, 0, tag, comm));
616e5c89e4eSSatish Balay       previous = next;
617e5c89e4eSSatish Balay       next     = next->next;
6189566063dSJacob Faibussowitsch       PetscCall(PetscFree(previous->string));
6199566063dSJacob Faibussowitsch       PetscCall(PetscFree(previous));
620e5c89e4eSSatish Balay     }
62102c9f0b5SLisandro Dalcin     petsc_printfqueue       = NULL;
622d30b0576SJed Brown     petsc_printfqueuelength = 0;
623e5c89e4eSSatish Balay   }
6249566063dSJacob Faibussowitsch   PetscCall(PetscCommDestroy(&comm));
6253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
626e5c89e4eSSatish Balay }
627e5c89e4eSSatish Balay 
628e5c89e4eSSatish Balay /*@C
629e5c89e4eSSatish Balay     PetscFPrintf - Prints to a file, only from the first
630*21532e8aSBarry Smith     MPI process in the communicator.
631e5c89e4eSSatish Balay 
632cf53795eSBarry Smith     Not Collective; No Fortran Support
633e5c89e4eSSatish Balay 
634e5c89e4eSSatish Balay     Input Parameters:
635058c9ee1SBarry Smith +   comm - the MPI communicator
636e5c89e4eSSatish Balay .   fd - the file pointer
6376026c97aSBarry Smith -   format - the usual `printf()` format string
638e5c89e4eSSatish Balay 
639e5c89e4eSSatish Balay     Level: intermediate
640e5c89e4eSSatish Balay 
641058c9ee1SBarry Smith     Developer Note:
642058c9ee1SBarry Smith     This maybe, and is, called from PETSc error handlers and `PetscMallocValidate()` hence it does not use `PetscCallMPI()` which
643058c9ee1SBarry Smith     could recursively restart the malloc validation.
644058c9ee1SBarry Smith 
645db781477SPatrick Sanan .seealso: `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
646c69effb2SJacob Faibussowitsch           `PetscViewerASCIISynchronizedPrintf()`, `PetscSynchronizedFlush()`, `PetscFFlush()`
647e5c89e4eSSatish Balay @*/
648d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFPrintf(MPI_Comm comm, FILE *fd, const char format[], ...)
649d71ae5a4SJacob Faibussowitsch {
650eae3dc7dSJacob Faibussowitsch   va_list Argp;
651e5c89e4eSSatish Balay 
652e5c89e4eSSatish Balay   PetscFunctionBegin;
653e5c89e4eSSatish Balay   va_start(Argp, format);
654eae3dc7dSJacob Faibussowitsch   PetscCall(PetscVFPrintf_Private(comm, fd, format, Argp));
655e5c89e4eSSatish Balay   va_end(Argp);
6563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
657e5c89e4eSSatish Balay }
658e5c89e4eSSatish Balay 
659e5c89e4eSSatish Balay /*@C
660e5c89e4eSSatish Balay     PetscPrintf - Prints to standard out, only from the first
661*21532e8aSBarry Smith     MPI process in the communicator. Calls from other processes are ignored.
662e5c89e4eSSatish Balay 
663e5c89e4eSSatish Balay     Not Collective
664e5c89e4eSSatish Balay 
665e5c89e4eSSatish Balay     Input Parameters:
666e5c89e4eSSatish Balay +   comm - the communicator
667bfbbc7b7SBarry Smith -   format - the usual `printf()` format string
668e5c89e4eSSatish Balay 
669e5c89e4eSSatish Balay     Level: intermediate
670e5c89e4eSSatish Balay 
671811af0c4SBarry Smith     Note:
672811af0c4SBarry Smith     Deprecated information: `PetscPrintf()` supports some format specifiers that are unique to PETSc.
673811af0c4SBarry Smith     See the manual page for `PetscFormatConvert()` for details.
674b2706f25SRichard Tran Mills 
675e5c89e4eSSatish Balay     Fortran Note:
676811af0c4SBarry Smith     The call sequence is `PetscPrintf`(MPI_Comm, character(*), `PetscErrorCode` ierr) from Fortran.
677e5c89e4eSSatish Balay     That is, you can only pass a single character string from Fortran.
678e5c89e4eSSatish Balay 
679c69effb2SJacob Faibussowitsch .seealso: `PetscFPrintf()`, `PetscSynchronizedPrintf()`, `PetscFormatConvert()`, `PetscFFlush()`
680e5c89e4eSSatish Balay @*/
681d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscPrintf(MPI_Comm comm, const char format[], ...)
682d71ae5a4SJacob Faibussowitsch {
683eae3dc7dSJacob Faibussowitsch   va_list Argp;
684e5c89e4eSSatish Balay 
685e5c89e4eSSatish Balay   PetscFunctionBegin;
686e5c89e4eSSatish Balay   va_start(Argp, format);
687eae3dc7dSJacob Faibussowitsch   PetscCall(PetscVFPrintf_Private(comm, PETSC_STDOUT, format, Argp));
688e5c89e4eSSatish Balay   va_end(Argp);
6893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
690e5c89e4eSSatish Balay }
691e5c89e4eSSatish Balay 
692d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscHelpPrintfDefault(MPI_Comm comm, const char format[], ...)
693d71ae5a4SJacob Faibussowitsch {
694eae3dc7dSJacob Faibussowitsch   va_list Argp;
695e5c89e4eSSatish Balay 
696e5c89e4eSSatish Balay   PetscFunctionBegin;
697e5c89e4eSSatish Balay   va_start(Argp, format);
698eae3dc7dSJacob Faibussowitsch   PetscCall(PetscVFPrintf_Private(comm, PETSC_STDOUT, format, Argp));
699e5c89e4eSSatish Balay   va_end(Argp);
7003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
701e5c89e4eSSatish Balay }
702e5c89e4eSSatish Balay 
703e5c89e4eSSatish Balay /*@C
704*21532e8aSBarry Smith     PetscSynchronizedFGets - Multiple MPI processes all get the same line from a file.
705e5c89e4eSSatish Balay 
706d083f849SBarry Smith     Collective
707e5c89e4eSSatish Balay 
708e5c89e4eSSatish Balay     Input Parameters:
709*21532e8aSBarry Smith +   comm - the MPI communicator
710e5c89e4eSSatish Balay .   fd - the file pointer
711*21532e8aSBarry Smith -   len - the length of `string`
712e5c89e4eSSatish Balay 
713e5c89e4eSSatish Balay     Output Parameter:
714*21532e8aSBarry Smith .   string - the line read from the file, at end of file `string`[0] == 0
715e5c89e4eSSatish Balay 
716e5c89e4eSSatish Balay     Level: intermediate
717e5c89e4eSSatish Balay 
718db781477SPatrick Sanan .seealso: `PetscSynchronizedPrintf()`, `PetscSynchronizedFlush()`,
719db781477SPatrick Sanan           `PetscFOpen()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIPrintf()`
720e5c89e4eSSatish Balay @*/
721d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSynchronizedFGets(MPI_Comm comm, FILE *fp, size_t len, char string[])
722d71ae5a4SJacob Faibussowitsch {
723e5c89e4eSSatish Balay   PetscMPIInt rank;
724e5c89e4eSSatish Balay 
725e5c89e4eSSatish Balay   PetscFunctionBegin;
7269566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
727eae3dc7dSJacob Faibussowitsch   if (rank != 0) PetscFunctionReturn(PETSC_SUCCESS);
728eae3dc7dSJacob Faibussowitsch   if (!fgets(string, len, fp)) {
729e31d4fa4SJed Brown     string[0] = 0;
73008401ef6SPierre Jolivet     PetscCheck(feof(fp), PETSC_COMM_SELF, PETSC_ERR_FILE_READ, "Error reading from file: %d", errno);
731047b9c12SMatthew G Knepley   }
7329566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Bcast(string, len, MPI_BYTE, 0, comm));
7333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
734e5c89e4eSSatish Balay }
735238ccf28SShri Abhyankar 
7368c74ee41SBarry Smith /*@C
737*21532e8aSBarry Smith      PetscFormatStrip - Takes a PETSc format string and removes all numerical modifiers to `%` operations
7388c74ee41SBarry Smith 
7392fe279fdSBarry Smith    Input Parameter:
7408c74ee41SBarry Smith .   format - the PETSc format string
7418c74ee41SBarry Smith 
7428c74ee41SBarry Smith    Level: developer
7438c74ee41SBarry Smith @*/
744d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFormatStrip(char *format)
745d71ae5a4SJacob Faibussowitsch {
7468c74ee41SBarry Smith   size_t loc1 = 0, loc2 = 0;
7478c74ee41SBarry Smith 
7488c74ee41SBarry Smith   PetscFunctionBegin;
7498c74ee41SBarry Smith   while (format[loc2]) {
7508c74ee41SBarry Smith     if (format[loc2] == '%') {
7518c74ee41SBarry Smith       format[loc1++] = format[loc2++];
7528c74ee41SBarry Smith       while (format[loc2] && ((format[loc2] >= '0' && format[loc2] <= '9') || format[loc2] == '.')) loc2++;
7538c74ee41SBarry Smith     }
7548c74ee41SBarry Smith     format[loc1++] = format[loc2++];
7558c74ee41SBarry Smith   }
7563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7578c74ee41SBarry Smith }
7588c74ee41SBarry Smith 
759d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFormatRealArray(char buf[], size_t len, const char *fmt, PetscInt n, const PetscReal x[])
760d71ae5a4SJacob Faibussowitsch {
7611b5687a1SBarry Smith   PetscInt i;
7621b5687a1SBarry Smith   size_t   left, count;
7631b5687a1SBarry Smith   char    *p;
7641b5687a1SBarry Smith 
7651b5687a1SBarry Smith   PetscFunctionBegin;
7661b5687a1SBarry Smith   for (i = 0, p = buf, left = len; i < n; i++) {
7679566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintfCount(p, left, fmt, &count, (double)x[i]));
76808401ef6SPierre Jolivet     PetscCheck(count < left, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Insufficient space in buffer");
7691b5687a1SBarry Smith     left -= count;
7701b5687a1SBarry Smith     p += count - 1;
7711b5687a1SBarry Smith     *p++ = ' ';
7721b5687a1SBarry Smith   }
7731b5687a1SBarry Smith   p[i ? 0 : -1] = 0;
7743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7751b5687a1SBarry Smith }
776