xref: /petsc/src/sys/fileio/mprint.c (revision 8c0ebe3f314cf67915f90ec3698bc9986dd4a309)
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:
8710450e9eSJacob Faibussowitsch . newformat - the formatted string
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
1526026c97aSBarry Smith   PetscVSNPrintf - The PETSc version of `vsnprintf()`. Ensures that all `%g` formatted arguments' output contains the decimal point (which
153058c9ee1SBarry Smith   is used by the test harness)
154c9a19010SBarry Smith 
155c9a19010SBarry Smith   Input Parameters:
156c9a19010SBarry Smith + str    - location to put result
15721532e8aSBarry Smith . len    - the length of `str`
15810450e9eSJacob Faibussowitsch . format - the PETSc format string
15910450e9eSJacob Faibussowitsch - Argp   - the variable argument list to format
16021532e8aSBarry Smith 
16121532e8aSBarry Smith   Output Parameter:
16221532e8aSBarry Smith . fullLength - the amount of space in `str` actually used.
163c9a19010SBarry Smith 
164c9a19010SBarry Smith   Level: developer
165c9a19010SBarry Smith 
166aec76313SJacob Faibussowitsch   Developer Notes:
167058c9ee1SBarry Smith   This function may be called from an error handler, if an error occurs when it is called by the error handler than likely
168058c9ee1SBarry Smith   a recursion will occur resulting in a crash of the program.
169058c9ee1SBarry Smith 
17021532e8aSBarry 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()`
171058c9ee1SBarry Smith 
17242747ad1SJacob Faibussowitsch .seealso: `PetscFormatConvert()`, `PetscFormatConvertGetSize()`, `PetscErrorPrintf()`, `PetscVPrintf()`
173c9a19010SBarry Smith @*/
174d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscVSNPrintf(char *str, size_t len, const char *format, size_t *fullLength, va_list Argp)
175d71ae5a4SJacob Faibussowitsch {
176d781fa04SBarry Smith   char  *newformat = NULL;
17714416c0eSBarry Smith   char   formatbuf[PETSCDEFAULTBUFFERSIZE];
178d781fa04SBarry Smith   size_t newLength;
17914416c0eSBarry Smith   int    flen;
180e5c89e4eSSatish Balay 
181eed5747fSBarry Smith   PetscFunctionBegin;
1829566063dSJacob Faibussowitsch   PetscCall(PetscFormatConvertGetSize(format, &newLength));
18394217ebdSBarry Smith   if (newLength < sizeof(formatbuf)) {
184e2135aedSMatthew Knepley     newformat = formatbuf;
18594217ebdSBarry Smith     newLength = sizeof(formatbuf) - 1;
186e2135aedSMatthew Knepley   } else {
1879566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(newLength, &newformat));
188e2135aedSMatthew Knepley   }
1899566063dSJacob Faibussowitsch   PetscCall(PetscFormatConvert(format, newformat));
1907b9a2d1bSSatish Balay #if defined(PETSC_HAVE_VSNPRINTF)
191152b30f0SSatish Balay   flen = vsnprintf(str, len, newformat, Argp);
192e5c89e4eSSatish Balay #else
19389b07760SSatish Balay   #error "vsnprintf not found"
194e5c89e4eSSatish Balay #endif
19548a46eb9SPierre Jolivet   if (newLength > sizeof(formatbuf) - 1) PetscCall(PetscFree(newformat));
1968627564fSBarry Smith   {
1978627564fSBarry Smith     PetscBool foundedot;
1988627564fSBarry Smith     size_t    cnt = 0, ncnt = 0, leng;
1999566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(str, &leng));
20017ca8410SBarry Smith     if (leng > 4) {
2018627564fSBarry Smith       for (cnt = 0; cnt < leng - 4; cnt++) {
2028627564fSBarry Smith         if (str[cnt] == '[' && str[cnt + 1] == '|') {
203c540d043SBarry Smith           flen -= 4;
2049371c9d4SSatish Balay           cnt++;
2059371c9d4SSatish Balay           cnt++;
2068627564fSBarry Smith           foundedot = PETSC_FALSE;
2078627564fSBarry Smith           for (; cnt < leng - 1; cnt++) {
2088627564fSBarry Smith             if (str[cnt] == '|' && str[cnt + 1] == ']') {
2098627564fSBarry Smith               cnt++;
2108627564fSBarry Smith               if (!foundedot) str[ncnt++] = '.';
2118627564fSBarry Smith               ncnt--;
2128627564fSBarry Smith               break;
2138627564fSBarry Smith             } else {
2148627564fSBarry Smith               if (str[cnt] == 'e' || str[cnt] == '.') foundedot = PETSC_TRUE;
2158627564fSBarry Smith               str[ncnt++] = str[cnt];
2168627564fSBarry Smith             }
2178627564fSBarry Smith           }
2188627564fSBarry Smith         } else {
2198627564fSBarry Smith           str[ncnt] = str[cnt];
2208627564fSBarry Smith         }
2218627564fSBarry Smith         ncnt++;
2228627564fSBarry Smith       }
2238627564fSBarry Smith       while (cnt < leng) {
2249371c9d4SSatish Balay         str[ncnt] = str[cnt];
2259371c9d4SSatish Balay         ncnt++;
2269371c9d4SSatish Balay         cnt++;
2278627564fSBarry Smith       }
2288627564fSBarry Smith       str[ncnt] = 0;
2298627564fSBarry Smith     }
2308627564fSBarry Smith   }
231748e1b9dSBarry Smith #if defined(PETSC_HAVE_WINDOWS_H) && !defined(PETSC_HAVE__SET_OUTPUT_FORMAT)
232e51f71cfSBarry Smith   /* older Windows OS always produces e-+0np for floating point output; remove the extra 0 */
233748e1b9dSBarry Smith   {
234748e1b9dSBarry Smith     size_t cnt = 0, ncnt = 0, leng;
2359566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(str, &leng));
236748e1b9dSBarry Smith     if (leng > 5) {
237748e1b9dSBarry Smith       for (cnt = 0; cnt < leng - 4; cnt++) {
238e51f71cfSBarry 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') {
2399371c9d4SSatish Balay           str[ncnt] = str[cnt];
2409371c9d4SSatish Balay           ncnt++;
2419371c9d4SSatish Balay           cnt++;
2429371c9d4SSatish Balay           str[ncnt] = str[cnt];
2439371c9d4SSatish Balay           ncnt++;
2449371c9d4SSatish Balay           cnt++;
2459371c9d4SSatish Balay           cnt++;
246e51f71cfSBarry Smith           str[ncnt] = str[cnt];
247748e1b9dSBarry Smith         } else {
248748e1b9dSBarry Smith           str[ncnt] = str[cnt];
249748e1b9dSBarry Smith         }
250748e1b9dSBarry Smith         ncnt++;
251748e1b9dSBarry Smith       }
252748e1b9dSBarry Smith       while (cnt < leng) {
2539371c9d4SSatish Balay         str[ncnt] = str[cnt];
2549371c9d4SSatish Balay         ncnt++;
2559371c9d4SSatish Balay         cnt++;
256748e1b9dSBarry Smith       }
257748e1b9dSBarry Smith       str[ncnt] = 0;
258748e1b9dSBarry Smith     }
259748e1b9dSBarry Smith   }
260748e1b9dSBarry Smith #endif
261c540d043SBarry Smith   if (fullLength) *fullLength = 1 + (size_t)flen;
2623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
263e5c89e4eSSatish Balay }
264e5c89e4eSSatish Balay 
265c9a19010SBarry Smith /*@C
266c69effb2SJacob Faibussowitsch   PetscFFlush - Flush a file stream
267c69effb2SJacob Faibussowitsch 
268c69effb2SJacob Faibussowitsch   Input Parameter:
269c69effb2SJacob Faibussowitsch . fd - The file stream handle
270c69effb2SJacob Faibussowitsch 
271c69effb2SJacob Faibussowitsch   Level: intermediate
272c69effb2SJacob Faibussowitsch 
273c69effb2SJacob Faibussowitsch   Notes:
274c69effb2SJacob Faibussowitsch   For output streams (and for update streams on which the last operation was output), writes
275c69effb2SJacob Faibussowitsch   any unwritten data from the stream's buffer to the associated output device.
276c69effb2SJacob Faibussowitsch 
277c69effb2SJacob Faibussowitsch   For input streams (and for update streams on which the last operation was input), the
278c69effb2SJacob Faibussowitsch   behavior is undefined.
279c69effb2SJacob Faibussowitsch 
280c69effb2SJacob Faibussowitsch   If `fd` is `NULL`, all open output streams are flushed, including ones not directly
281c69effb2SJacob Faibussowitsch   accessible to the program.
282c69effb2SJacob Faibussowitsch 
283c69effb2SJacob Faibussowitsch .seealso: `PetscPrintf()`, `PetscFPrintf()`, `PetscVFPrintf()`, `PetscVSNPrintf()`
284c69effb2SJacob Faibussowitsch @*/
285c69effb2SJacob Faibussowitsch PetscErrorCode PetscFFlush(FILE *fd)
286c69effb2SJacob Faibussowitsch {
287c69effb2SJacob Faibussowitsch   PetscFunctionBegin;
2884f572ea9SToby Isaac   if (fd) PetscAssertPointer(fd, 1);
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
291bf31d2d3SBarry Smith   PetscCheck(0 == fflush(fd), PETSC_COMM_SELF, PETSC_ERR_FILE_WRITE, "Error in fflush() due to \"%s\"", strerror(errno));
292c69effb2SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
293c69effb2SJacob Faibussowitsch }
294c69effb2SJacob Faibussowitsch 
295c69effb2SJacob Faibussowitsch /*@C
296aec76313SJacob Faibussowitsch   PetscVFPrintfDefault -  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 
29910450e9eSJacob Faibussowitsch   Input Parameters:
30010450e9eSJacob Faibussowitsch + fd     - the file descriptor to write to
30110450e9eSJacob Faibussowitsch . format - the format string to write with
30210450e9eSJacob Faibussowitsch - Argp   - the variable argument list of items to format and write
30310450e9eSJacob Faibussowitsch 
30410450e9eSJacob Faibussowitsch   Level: developer
30510450e9eSJacob Faibussowitsch 
30610450e9eSJacob Faibussowitsch   Note:
30710450e9eSJacob Faibussowitsch   For error messages this may be called by any MPI process, for regular standard out it is
30810450e9eSJacob Faibussowitsch   called only by MPI rank 0 of a given communicator
30910450e9eSJacob Faibussowitsch 
31010450e9eSJacob Faibussowitsch   Example Usage:
311c9a19010SBarry Smith   To use, write your own function for example,
312058c9ee1SBarry Smith .vb
313058c9ee1SBarry Smith    PetscErrorCode mypetscvfprintf(FILE *fd, const char format[], va_list Argp)
314058c9ee1SBarry Smith    {
315058c9ee1SBarry Smith      PetscErrorCode ierr;
316058c9ee1SBarry Smith 
317058c9ee1SBarry Smith      PetscFunctionBegin;
318058c9ee1SBarry Smith       if (fd != stdout && fd != stderr) {  handle regular files
319058c9ee1SBarry Smith          CHKERR(PetscVFPrintfDefault(fd,format,Argp));
320058c9ee1SBarry Smith      } else {
321058c9ee1SBarry Smith         char   buff[BIG];
322058c9ee1SBarry Smith         size_t length;
323058c9ee1SBarry Smith         PetscCall(PetscVSNPrintf(buff,BIG,format,&length,Argp));
324058c9ee1SBarry Smith         now send buff to whatever stream or whatever you want
325058c9ee1SBarry Smith     }
326058c9ee1SBarry Smith     PetscFunctionReturn(PETSC_SUCCESS);
327058c9ee1SBarry Smith    }
328058c9ee1SBarry Smith .ve
329058c9ee1SBarry Smith   then before the call to `PetscInitialize()` do the assignment `PetscVFPrintf = mypetscvfprintf`;
330058c9ee1SBarry Smith 
331aec76313SJacob Faibussowitsch   Developer Notes:
332058c9ee1SBarry Smith   This could be called by an error handler, if that happens then a recursion of the error handler may occur
333058c9ee1SBarry Smith   and a resulting crash
334c9a19010SBarry Smith 
335c69effb2SJacob Faibussowitsch .seealso: `PetscVSNPrintf()`, `PetscErrorPrintf()`, `PetscFFlush()`
336c9a19010SBarry Smith @*/
337d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscVFPrintfDefault(FILE *fd, const char *format, va_list Argp)
338d71ae5a4SJacob Faibussowitsch {
33914416c0eSBarry Smith   char   str[PETSCDEFAULTBUFFERSIZE];
34014416c0eSBarry Smith   char  *buff = str;
34114416c0eSBarry Smith   size_t fullLength;
3421531940fSBarry Smith #if defined(PETSC_HAVE_VA_COPY)
34314416c0eSBarry Smith   va_list Argpcopy;
3441531940fSBarry Smith #endif
3451179db26SBarry Smith 
346eed5747fSBarry Smith   PetscFunctionBegin;
3471531940fSBarry Smith #if defined(PETSC_HAVE_VA_COPY)
34814416c0eSBarry Smith   va_copy(Argpcopy, Argp);
3491531940fSBarry Smith #endif
3509566063dSJacob Faibussowitsch   PetscCall(PetscVSNPrintf(str, sizeof(str), format, &fullLength, Argp));
35114416c0eSBarry Smith   if (fullLength > sizeof(str)) {
3529566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(fullLength, &buff));
3531531940fSBarry Smith #if defined(PETSC_HAVE_VA_COPY)
3549566063dSJacob Faibussowitsch     PetscCall(PetscVSNPrintf(buff, fullLength, format, NULL, Argpcopy));
3551531940fSBarry Smith #else
3561531940fSBarry Smith     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "C89 does not support va_copy() hence cannot print long strings with PETSc printing routines");
3571531940fSBarry Smith #endif
35814416c0eSBarry Smith   }
359eae3dc7dSJacob Faibussowitsch #if defined(PETSC_HAVE_VA_COPY)
360eae3dc7dSJacob Faibussowitsch   va_end(Argpcopy);
361eae3dc7dSJacob Faibussowitsch #endif
362c69effb2SJacob Faibussowitsch   {
363*8c0ebe3fSBarry Smith     int err;
364*8c0ebe3fSBarry Smith 
365*8c0ebe3fSBarry Smith     // POSIX C sets errno but otherwise it may not be set for *printf() system calls
366*8c0ebe3fSBarry Smith     // https://pubs.opengroup.org/onlinepubs/9699919799/functions/fprintf.html
367*8c0ebe3fSBarry Smith     errno = 0;
368*8c0ebe3fSBarry Smith     err   = fprintf(fd, "%s", buff);
369c69effb2SJacob Faibussowitsch     // cannot use PetscCallExternal() for fprintf since the return value is "number of
370c69effb2SJacob Faibussowitsch     // characters transmitted to the output stream" on success
371*8c0ebe3fSBarry 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)");
372c69effb2SJacob Faibussowitsch   }
373c69effb2SJacob Faibussowitsch   PetscCall(PetscFFlush(fd));
37448a46eb9SPierre Jolivet   if (buff != str) PetscCall(PetscFree(buff));
3753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
376e5c89e4eSSatish Balay }
377e5c89e4eSSatish Balay 
3785b5bc046SBarry Smith /*@C
3795b5bc046SBarry Smith   PetscSNPrintf - Prints to a string of given length
3805b5bc046SBarry Smith 
3815b5bc046SBarry Smith   Not Collective
3825b5bc046SBarry Smith 
3835b5bc046SBarry Smith   Input Parameters:
38421532e8aSBarry Smith + len    - the length of `str`
38510450e9eSJacob Faibussowitsch - format - the usual `printf()` format string
3865b5bc046SBarry Smith 
38721532e8aSBarry Smith   Output Parameter:
38821532e8aSBarry Smith . str - the resulting string
38921532e8aSBarry Smith 
3905b5bc046SBarry Smith   Level: intermediate
3915b5bc046SBarry Smith 
392db781477SPatrick Sanan .seealso: `PetscSynchronizedFlush()`, `PetscSynchronizedFPrintf()`, `PetscFPrintf()`, `PetscVSNPrintf()`,
393c69effb2SJacob Faibussowitsch           `PetscPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIISynchronizedPrintf()`,
394c69effb2SJacob Faibussowitsch           `PetscVFPrintf()`, `PetscFFlush()`
3955b5bc046SBarry Smith @*/
396d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSNPrintf(char *str, size_t len, const char format[], ...)
397d71ae5a4SJacob Faibussowitsch {
398c9a19010SBarry Smith   size_t  fullLength;
3995b5bc046SBarry Smith   va_list Argp;
4005b5bc046SBarry Smith 
4015b5bc046SBarry Smith   PetscFunctionBegin;
4025b5bc046SBarry Smith   va_start(Argp, format);
4039566063dSJacob Faibussowitsch   PetscCall(PetscVSNPrintf(str, len, format, &fullLength, Argp));
404eae3dc7dSJacob Faibussowitsch   va_end(Argp);
4053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4065b5bc046SBarry Smith }
4075b5bc046SBarry Smith 
408257d2499SJed Brown /*@C
409058c9ee1SBarry Smith   PetscSNPrintfCount - Prints to a string of given length, returns count of characters printed
410257d2499SJed Brown 
411257d2499SJed Brown   Not Collective
412257d2499SJed Brown 
413257d2499SJed Brown   Input Parameters:
41421532e8aSBarry Smith + len    - the length of `str`
415058c9ee1SBarry Smith . format - the usual `printf()` format string
41610450e9eSJacob Faibussowitsch - ...    - args to format
417257d2499SJed Brown 
41821532e8aSBarry Smith   Output Parameters:
41921532e8aSBarry Smith + str       - the resulting string
42021532e8aSBarry Smith - countused - number of characters printed
421cb398dd3SBarry Smith 
422257d2499SJed Brown   Level: intermediate
423257d2499SJed Brown 
424db781477SPatrick Sanan .seealso: `PetscSynchronizedFlush()`, `PetscSynchronizedFPrintf()`, `PetscFPrintf()`, `PetscVSNPrintf()`,
425db781477SPatrick Sanan           `PetscPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscSNPrintf()`, `PetscVFPrintf()`
426257d2499SJed Brown @*/
427d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSNPrintfCount(char *str, size_t len, const char format[], size_t *countused, ...)
428d71ae5a4SJacob Faibussowitsch {
429257d2499SJed Brown   va_list Argp;
430257d2499SJed Brown 
431257d2499SJed Brown   PetscFunctionBegin;
432257d2499SJed Brown   va_start(Argp, countused);
4339566063dSJacob Faibussowitsch   PetscCall(PetscVSNPrintf(str, len, format, countused, Argp));
434eae3dc7dSJacob Faibussowitsch   va_end(Argp);
4353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
436257d2499SJed Brown }
437257d2499SJed Brown 
43802c9f0b5SLisandro Dalcin PrintfQueue petsc_printfqueue = NULL, petsc_printfqueuebase = NULL;
439d30b0576SJed Brown int         petsc_printfqueuelength = 0;
440e5c89e4eSSatish Balay 
441eae3dc7dSJacob Faibussowitsch static inline PetscErrorCode PetscVFPrintf_Private(MPI_Comm comm, FILE *fd, const char format[], va_list Argp)
442eae3dc7dSJacob Faibussowitsch {
443eae3dc7dSJacob Faibussowitsch   const PetscBool tee = (PetscBool)(petsc_history && (fd != petsc_history));
444eae3dc7dSJacob Faibussowitsch   PetscMPIInt     rank;
445eae3dc7dSJacob Faibussowitsch   va_list         cpy;
446eae3dc7dSJacob Faibussowitsch 
447eae3dc7dSJacob Faibussowitsch   PetscFunctionBegin;
448eae3dc7dSJacob Faibussowitsch   PetscCheck(comm != MPI_COMM_NULL, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Called with MPI_COMM_NULL, likely PetscObjectComm() failed");
449eae3dc7dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
450eae3dc7dSJacob Faibussowitsch   if (PetscLikely(rank != 0)) PetscFunctionReturn(PETSC_SUCCESS);
451eae3dc7dSJacob Faibussowitsch   // must do this before we possibly consume Argp
452eae3dc7dSJacob Faibussowitsch   if (tee) va_copy(cpy, Argp);
453eae3dc7dSJacob Faibussowitsch   PetscCall((*PetscVFPrintf)(fd, format, Argp));
454eae3dc7dSJacob Faibussowitsch   if (tee) {
455eae3dc7dSJacob Faibussowitsch     PetscCall((*PetscVFPrintf)(petsc_history, format, cpy));
456eae3dc7dSJacob Faibussowitsch     va_end(cpy);
457eae3dc7dSJacob Faibussowitsch   }
458eae3dc7dSJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
459eae3dc7dSJacob Faibussowitsch }
460eae3dc7dSJacob Faibussowitsch 
461eae3dc7dSJacob Faibussowitsch static inline PetscErrorCode PetscSynchronizedFPrintf_Private(MPI_Comm comm, FILE *fp, const char format[], va_list Argp)
462eae3dc7dSJacob Faibussowitsch {
463eae3dc7dSJacob Faibussowitsch   PetscMPIInt rank;
464eae3dc7dSJacob Faibussowitsch   va_list     cpy;
465eae3dc7dSJacob Faibussowitsch 
466eae3dc7dSJacob Faibussowitsch   PetscFunctionBegin;
467eae3dc7dSJacob Faibussowitsch   PetscCheck(comm != MPI_COMM_NULL, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Called with MPI_COMM_NULL, likely PetscObjectComm() failed");
468eae3dc7dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
469eae3dc7dSJacob Faibussowitsch   /* First processor prints immediately to fp */
470eae3dc7dSJacob Faibussowitsch   if (rank == 0) {
471eae3dc7dSJacob Faibussowitsch     va_copy(cpy, Argp);
472eae3dc7dSJacob Faibussowitsch     PetscCall(PetscVFPrintf_Private(comm, fp, format, cpy));
473eae3dc7dSJacob Faibussowitsch     va_end(cpy);
474eae3dc7dSJacob Faibussowitsch   } else { /* other processors add to local queue */
475eae3dc7dSJacob Faibussowitsch     PrintfQueue next;
476eae3dc7dSJacob Faibussowitsch     size_t      fullLength = PETSCDEFAULTBUFFERSIZE;
477eae3dc7dSJacob Faibussowitsch 
478eae3dc7dSJacob Faibussowitsch     PetscCall(PetscNew(&next));
479eae3dc7dSJacob Faibussowitsch     if (petsc_printfqueue) {
480eae3dc7dSJacob Faibussowitsch       petsc_printfqueue->next = next;
481eae3dc7dSJacob Faibussowitsch       petsc_printfqueue       = next;
482eae3dc7dSJacob Faibussowitsch       petsc_printfqueue->next = NULL;
483eae3dc7dSJacob Faibussowitsch     } else petsc_printfqueuebase = petsc_printfqueue = next;
484eae3dc7dSJacob Faibussowitsch     petsc_printfqueuelength++;
485eae3dc7dSJacob Faibussowitsch     next->size   = 0;
486eae3dc7dSJacob Faibussowitsch     next->string = NULL;
487eae3dc7dSJacob Faibussowitsch     while (fullLength >= next->size) {
488eae3dc7dSJacob Faibussowitsch       next->size = fullLength + 1;
489eae3dc7dSJacob Faibussowitsch       PetscCall(PetscFree(next->string));
490eae3dc7dSJacob Faibussowitsch       PetscCall(PetscMalloc1(next->size, &next->string));
491eae3dc7dSJacob Faibussowitsch       PetscCall(PetscArrayzero(next->string, next->size));
492eae3dc7dSJacob Faibussowitsch       va_copy(cpy, Argp);
493eae3dc7dSJacob Faibussowitsch       PetscCall(PetscVSNPrintf(next->string, next->size, format, &fullLength, cpy));
494eae3dc7dSJacob Faibussowitsch       va_end(cpy);
495eae3dc7dSJacob Faibussowitsch     }
496eae3dc7dSJacob Faibussowitsch   }
497eae3dc7dSJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
498eae3dc7dSJacob Faibussowitsch }
499eae3dc7dSJacob Faibussowitsch 
500e5c89e4eSSatish Balay /*@C
5019c89aa79SPierre Jolivet   PetscSynchronizedPrintf - Prints synchronized output from multiple MPI processes.
502e5c89e4eSSatish Balay   Output of the first processor is followed by that of the second, etc.
503e5c89e4eSSatish Balay 
504e5c89e4eSSatish Balay   Not Collective
505e5c89e4eSSatish Balay 
506e5c89e4eSSatish Balay   Input Parameters:
507058c9ee1SBarry Smith + comm   - the MPI communicator
5086026c97aSBarry Smith - format - the usual `printf()` format string
509e5c89e4eSSatish Balay 
510e5c89e4eSSatish Balay   Level: intermediate
511e5c89e4eSSatish Balay 
512811af0c4SBarry Smith   Note:
513811af0c4SBarry Smith   REQUIRES a call to `PetscSynchronizedFlush()` by all the processes after the completion of the calls to `PetscSynchronizedPrintf()` for the information
514e5c89e4eSSatish Balay   from all the processors to be printed.
515e5c89e4eSSatish Balay 
516aec76313SJacob Faibussowitsch   Fortran Notes:
517058c9ee1SBarry Smith   The call sequence is `PetscSynchronizedPrintf`(`MPI_Comm`, `character`(*), `PetscErrorCode` ierr).
518e5c89e4eSSatish Balay   That is, you can only pass a single character string from Fortran.
519e5c89e4eSSatish Balay 
520db781477SPatrick Sanan .seealso: `PetscSynchronizedFlush()`, `PetscSynchronizedFPrintf()`, `PetscFPrintf()`,
521c69effb2SJacob Faibussowitsch           `PetscPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIISynchronizedPrintf()`,
522c69effb2SJacob Faibussowitsch           `PetscFFlush()`
523e5c89e4eSSatish Balay @*/
524d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSynchronizedPrintf(MPI_Comm comm, const char format[], ...)
525d71ae5a4SJacob Faibussowitsch {
526eae3dc7dSJacob Faibussowitsch   va_list Argp;
527e5c89e4eSSatish Balay 
528e5c89e4eSSatish Balay   PetscFunctionBegin;
529e5c89e4eSSatish Balay   va_start(Argp, format);
530eae3dc7dSJacob Faibussowitsch   PetscCall(PetscSynchronizedFPrintf_Private(comm, PETSC_STDOUT, format, Argp));
531e5c89e4eSSatish Balay   va_end(Argp);
5323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
533e5c89e4eSSatish Balay }
534e5c89e4eSSatish Balay 
535e5c89e4eSSatish Balay /*@C
536e5c89e4eSSatish Balay   PetscSynchronizedFPrintf - Prints synchronized output to the specified file from
53721532e8aSBarry Smith   several MPI processes.  Output of the first process is followed by that of the
538e5c89e4eSSatish Balay   second, etc.
539e5c89e4eSSatish Balay 
540e5c89e4eSSatish Balay   Not Collective
541e5c89e4eSSatish Balay 
542e5c89e4eSSatish Balay   Input Parameters:
543058c9ee1SBarry Smith + comm   - the MPI communicator
544aec76313SJacob Faibussowitsch . fp     - the file pointer
5456026c97aSBarry Smith - format - the usual `printf()` format string
546e5c89e4eSSatish Balay 
547e5c89e4eSSatish Balay   Level: intermediate
548e5c89e4eSSatish Balay 
549811af0c4SBarry Smith   Note:
550811af0c4SBarry Smith   REQUIRES a intervening call to `PetscSynchronizedFlush()` for the information
551e5c89e4eSSatish Balay   from all the processors to be printed.
552e5c89e4eSSatish Balay 
553db781477SPatrick Sanan .seealso: `PetscSynchronizedPrintf()`, `PetscSynchronizedFlush()`, `PetscFPrintf()`,
554c69effb2SJacob Faibussowitsch           `PetscFOpen()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
555c69effb2SJacob Faibussowitsch           `PetscFFlush()`
556e5c89e4eSSatish Balay @*/
557d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSynchronizedFPrintf(MPI_Comm comm, FILE *fp, const char format[], ...)
558d71ae5a4SJacob Faibussowitsch {
559eae3dc7dSJacob Faibussowitsch   va_list Argp;
560e5c89e4eSSatish Balay 
561e5c89e4eSSatish Balay   PetscFunctionBegin;
562e5c89e4eSSatish Balay   va_start(Argp, format);
563eae3dc7dSJacob Faibussowitsch   PetscCall(PetscSynchronizedFPrintf_Private(comm, fp, format, Argp));
564e5c89e4eSSatish Balay   va_end(Argp);
5653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
566e5c89e4eSSatish Balay }
567e5c89e4eSSatish Balay 
5680ec8b6e3SBarry Smith /*@C
569e5c89e4eSSatish Balay   PetscSynchronizedFlush - Flushes to the screen output from all processors
570811af0c4SBarry Smith   involved in previous `PetscSynchronizedPrintf()`/`PetscSynchronizedFPrintf()` calls.
571e5c89e4eSSatish Balay 
572d083f849SBarry Smith   Collective
573e5c89e4eSSatish Balay 
574e5c89e4eSSatish Balay   Input Parameters:
575058c9ee1SBarry Smith + comm - the MPI communicator
57621532e8aSBarry Smith - fd   - the file pointer (valid on MPI rank 0 of the communicator)
577e5c89e4eSSatish Balay 
578e5c89e4eSSatish Balay   Level: intermediate
579e5c89e4eSSatish Balay 
580811af0c4SBarry Smith   Note:
581811af0c4SBarry Smith   If `PetscSynchronizedPrintf()` and/or `PetscSynchronizedFPrintf()` are called with
582811af0c4SBarry Smith   different MPI communicators there must be an intervening call to `PetscSynchronizedFlush()` between the calls with different MPI communicators.
583e5c89e4eSSatish Balay 
584aec76313SJacob Faibussowitsch   Fortran Notes:
585811af0c4SBarry Smith   Pass `PETSC_STDOUT` if the flush is for standard out; otherwise pass a value obtained from `PetscFOpen()`
586e50bf69fSBarry Smith 
587db781477SPatrick Sanan .seealso: `PetscSynchronizedPrintf()`, `PetscFPrintf()`, `PetscPrintf()`, `PetscViewerASCIIPrintf()`,
588db781477SPatrick Sanan           `PetscViewerASCIISynchronizedPrintf()`
5890087d953SMatthew G. Knepley @*/
590d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSynchronizedFlush(MPI_Comm comm, FILE *fd)
591d71ae5a4SJacob Faibussowitsch {
59229a5cbdcSMatthew G. Knepley   PetscMPIInt rank, size, tag, i, j, n = 0, dummy = 0;
5932d609e63SMatthew Knepley   char       *message;
594e5c89e4eSSatish Balay   MPI_Status  status;
595e5c89e4eSSatish Balay 
596e5c89e4eSSatish Balay   PetscFunctionBegin;
5979566063dSJacob Faibussowitsch   PetscCall(PetscCommDuplicate(comm, &comm, &tag));
5989566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
5999566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
600e5c89e4eSSatish Balay 
601e5c89e4eSSatish Balay   /* First processor waits for messages from all other processors */
602dd400576SPatrick Sanan   if (rank == 0) {
6030ec8b6e3SBarry Smith     if (!fd) fd = PETSC_STDOUT;
604e5c89e4eSSatish Balay     for (i = 1; i < size; i++) {
6059f73f8ecSBarry Smith       /* to prevent a flood of messages to process zero, request each message separately */
6069566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Send(&dummy, 1, MPI_INT, i, tag, comm));
6079566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Recv(&n, 1, MPI_INT, i, tag, comm, &status));
608e5c89e4eSSatish Balay       for (j = 0; j < n; j++) {
60929a5cbdcSMatthew G. Knepley         PetscMPIInt size = 0;
6102d609e63SMatthew Knepley 
6119566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Recv(&size, 1, MPI_INT, i, tag, comm, &status));
6129566063dSJacob Faibussowitsch         PetscCall(PetscMalloc1(size, &message));
6139566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Recv(message, size, MPI_CHAR, i, tag, comm, &status));
6149566063dSJacob Faibussowitsch         PetscCall(PetscFPrintf(comm, fd, "%s", message));
6159566063dSJacob Faibussowitsch         PetscCall(PetscFree(message));
616e5c89e4eSSatish Balay       }
617e5c89e4eSSatish Balay     }
618e5c89e4eSSatish Balay   } else { /* other processors send queue to processor 0 */
619d30b0576SJed Brown     PrintfQueue next = petsc_printfqueuebase, previous;
620e5c89e4eSSatish Balay 
6219566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Recv(&dummy, 1, MPI_INT, 0, tag, comm, &status));
6229566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Send(&petsc_printfqueuelength, 1, MPI_INT, 0, tag, comm));
623d30b0576SJed Brown     for (i = 0; i < petsc_printfqueuelength; i++) {
6249566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Send(&next->size, 1, MPI_INT, 0, tag, comm));
6259566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Send(next->string, next->size, MPI_CHAR, 0, tag, comm));
626e5c89e4eSSatish Balay       previous = next;
627e5c89e4eSSatish Balay       next     = next->next;
6289566063dSJacob Faibussowitsch       PetscCall(PetscFree(previous->string));
6299566063dSJacob Faibussowitsch       PetscCall(PetscFree(previous));
630e5c89e4eSSatish Balay     }
63102c9f0b5SLisandro Dalcin     petsc_printfqueue       = NULL;
632d30b0576SJed Brown     petsc_printfqueuelength = 0;
633e5c89e4eSSatish Balay   }
6349566063dSJacob Faibussowitsch   PetscCall(PetscCommDestroy(&comm));
6353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
636e5c89e4eSSatish Balay }
637e5c89e4eSSatish Balay 
638e5c89e4eSSatish Balay /*@C
639e5c89e4eSSatish Balay   PetscFPrintf - Prints to a file, only from the first
64021532e8aSBarry Smith   MPI process in the communicator.
641e5c89e4eSSatish Balay 
642cf53795eSBarry Smith   Not Collective; No Fortran Support
643e5c89e4eSSatish Balay 
644e5c89e4eSSatish Balay   Input Parameters:
645058c9ee1SBarry Smith + comm   - the MPI communicator
646e5c89e4eSSatish Balay . fd     - the file pointer
6476026c97aSBarry Smith - format - the usual `printf()` format string
648e5c89e4eSSatish Balay 
649e5c89e4eSSatish Balay   Level: intermediate
650e5c89e4eSSatish Balay 
651aec76313SJacob Faibussowitsch   Developer Notes:
652058c9ee1SBarry Smith   This maybe, and is, called from PETSc error handlers and `PetscMallocValidate()` hence it does not use `PetscCallMPI()` which
653058c9ee1SBarry Smith   could recursively restart the malloc validation.
654058c9ee1SBarry Smith 
655db781477SPatrick Sanan .seealso: `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
656c69effb2SJacob Faibussowitsch           `PetscViewerASCIISynchronizedPrintf()`, `PetscSynchronizedFlush()`, `PetscFFlush()`
657e5c89e4eSSatish Balay @*/
658d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFPrintf(MPI_Comm comm, FILE *fd, const char format[], ...)
659d71ae5a4SJacob Faibussowitsch {
660eae3dc7dSJacob Faibussowitsch   va_list Argp;
661e5c89e4eSSatish Balay 
662e5c89e4eSSatish Balay   PetscFunctionBegin;
663e5c89e4eSSatish Balay   va_start(Argp, format);
664eae3dc7dSJacob Faibussowitsch   PetscCall(PetscVFPrintf_Private(comm, fd, format, Argp));
665e5c89e4eSSatish Balay   va_end(Argp);
6663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
667e5c89e4eSSatish Balay }
668e5c89e4eSSatish Balay 
669e5c89e4eSSatish Balay /*@C
670e5c89e4eSSatish Balay   PetscPrintf - Prints to standard out, only from the first
67121532e8aSBarry Smith   MPI process in the communicator. Calls from other processes are ignored.
672e5c89e4eSSatish Balay 
673e5c89e4eSSatish Balay   Not Collective
674e5c89e4eSSatish Balay 
675e5c89e4eSSatish Balay   Input Parameters:
676e5c89e4eSSatish Balay + comm   - the communicator
677bfbbc7b7SBarry Smith - format - the usual `printf()` format string
678e5c89e4eSSatish Balay 
679e5c89e4eSSatish Balay   Level: intermediate
680e5c89e4eSSatish Balay 
681811af0c4SBarry Smith   Note:
682811af0c4SBarry Smith   Deprecated information: `PetscPrintf()` supports some format specifiers that are unique to PETSc.
683811af0c4SBarry Smith   See the manual page for `PetscFormatConvert()` for details.
684b2706f25SRichard Tran Mills 
685aec76313SJacob Faibussowitsch   Fortran Notes:
686811af0c4SBarry Smith   The call sequence is `PetscPrintf`(MPI_Comm, character(*), `PetscErrorCode` ierr) from Fortran.
687e5c89e4eSSatish Balay   That is, you can only pass a single character string from Fortran.
688e5c89e4eSSatish Balay 
689c69effb2SJacob Faibussowitsch .seealso: `PetscFPrintf()`, `PetscSynchronizedPrintf()`, `PetscFormatConvert()`, `PetscFFlush()`
690e5c89e4eSSatish Balay @*/
691d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscPrintf(MPI_Comm comm, const char format[], ...)
692d71ae5a4SJacob Faibussowitsch {
693eae3dc7dSJacob Faibussowitsch   va_list Argp;
694e5c89e4eSSatish Balay 
695e5c89e4eSSatish Balay   PetscFunctionBegin;
696e5c89e4eSSatish Balay   va_start(Argp, format);
697eae3dc7dSJacob Faibussowitsch   PetscCall(PetscVFPrintf_Private(comm, PETSC_STDOUT, format, Argp));
698e5c89e4eSSatish Balay   va_end(Argp);
6993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
700e5c89e4eSSatish Balay }
701e5c89e4eSSatish Balay 
702d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscHelpPrintfDefault(MPI_Comm comm, const char format[], ...)
703d71ae5a4SJacob Faibussowitsch {
704eae3dc7dSJacob Faibussowitsch   va_list Argp;
705e5c89e4eSSatish Balay 
706e5c89e4eSSatish Balay   PetscFunctionBegin;
707e5c89e4eSSatish Balay   va_start(Argp, format);
708eae3dc7dSJacob Faibussowitsch   PetscCall(PetscVFPrintf_Private(comm, PETSC_STDOUT, format, Argp));
709e5c89e4eSSatish Balay   va_end(Argp);
7103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
711e5c89e4eSSatish Balay }
712e5c89e4eSSatish Balay 
713e5c89e4eSSatish Balay /*@C
71421532e8aSBarry Smith   PetscSynchronizedFGets - Multiple MPI processes all get the same line from a file.
715e5c89e4eSSatish Balay 
716d083f849SBarry Smith   Collective
717e5c89e4eSSatish Balay 
718e5c89e4eSSatish Balay   Input Parameters:
71921532e8aSBarry Smith + comm - the MPI communicator
720aec76313SJacob Faibussowitsch . fp   - the file pointer
72121532e8aSBarry Smith - len  - the length of `string`
722e5c89e4eSSatish Balay 
723e5c89e4eSSatish Balay   Output Parameter:
72421532e8aSBarry Smith . string - the line read from the file, at end of file `string`[0] == 0
725e5c89e4eSSatish Balay 
726e5c89e4eSSatish Balay   Level: intermediate
727e5c89e4eSSatish Balay 
728db781477SPatrick Sanan .seealso: `PetscSynchronizedPrintf()`, `PetscSynchronizedFlush()`,
729db781477SPatrick Sanan           `PetscFOpen()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIPrintf()`
730e5c89e4eSSatish Balay @*/
731d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSynchronizedFGets(MPI_Comm comm, FILE *fp, size_t len, char string[])
732d71ae5a4SJacob Faibussowitsch {
733e5c89e4eSSatish Balay   PetscMPIInt rank;
734e5c89e4eSSatish Balay 
735e5c89e4eSSatish Balay   PetscFunctionBegin;
7369566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
73780971c97SJames Wright   if (rank == 0) {
738eae3dc7dSJacob Faibussowitsch     if (!fgets(string, len, fp)) {
739e31d4fa4SJed Brown       string[0] = 0;
740bf31d2d3SBarry Smith       PetscCheck(feof(fp), PETSC_COMM_SELF, PETSC_ERR_FILE_READ, "Error reading from file due to \"%s\"", strerror(errno));
741047b9c12SMatthew G Knepley     }
742238ccf28SShri Abhyankar   }
7439566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Bcast(string, len, MPI_BYTE, 0, comm));
7443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
745e5c89e4eSSatish Balay }
746238ccf28SShri Abhyankar 
747d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFormatRealArray(char buf[], size_t len, const char *fmt, PetscInt n, const PetscReal x[])
748d71ae5a4SJacob Faibussowitsch {
7491b5687a1SBarry Smith   PetscInt i;
7501b5687a1SBarry Smith   size_t   left, count;
7511b5687a1SBarry Smith   char    *p;
7521b5687a1SBarry Smith 
7531b5687a1SBarry Smith   PetscFunctionBegin;
7541b5687a1SBarry Smith   for (i = 0, p = buf, left = len; i < n; i++) {
7559566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintfCount(p, left, fmt, &count, (double)x[i]));
75608401ef6SPierre Jolivet     PetscCheck(count < left, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Insufficient space in buffer");
7571b5687a1SBarry Smith     left -= count;
7581b5687a1SBarry Smith     p += count - 1;
7591b5687a1SBarry Smith     *p++ = ' ';
7601b5687a1SBarry Smith   }
7611b5687a1SBarry Smith   p[i ? 0 : -1] = 0;
7623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7631b5687a1SBarry Smith }
764