xref: /petsc/src/sys/fileio/mprint.c (revision 33ff13ce85662abd4b859ebe9815d8a1164ce8ca)
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 @*/
39cc4c1da9SBarry Smith 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:
87a3b724e8SBarry 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 @*/
101cc4c1da9SBarry Smith 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 
154cc4c1da9SBarry Smith   No Fortran Support
155cc4c1da9SBarry Smith 
156c9a19010SBarry Smith   Input Parameters:
157c9a19010SBarry Smith + str    - location to put result
15821532e8aSBarry Smith . len    - the length of `str`
15910450e9eSJacob Faibussowitsch . format - the PETSc format string
16010450e9eSJacob Faibussowitsch - Argp   - the variable argument list to format
16121532e8aSBarry Smith 
16221532e8aSBarry Smith   Output Parameter:
16321532e8aSBarry Smith . fullLength - the amount of space in `str` actually used.
164c9a19010SBarry Smith 
165c9a19010SBarry Smith   Level: developer
166c9a19010SBarry Smith 
167aec76313SJacob Faibussowitsch   Developer Notes:
168058c9ee1SBarry Smith   This function may be called from an error handler, if an error occurs when it is called by the error handler than likely
169058c9ee1SBarry Smith   a recursion will occur resulting in a crash of the program.
170058c9ee1SBarry Smith 
17121532e8aSBarry 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()`
172058c9ee1SBarry Smith 
17342747ad1SJacob Faibussowitsch .seealso: `PetscFormatConvert()`, `PetscFormatConvertGetSize()`, `PetscErrorPrintf()`, `PetscVPrintf()`
174c9a19010SBarry Smith @*/
175cc4c1da9SBarry Smith PetscErrorCode PetscVSNPrintf(char str[], size_t len, const char format[], size_t *fullLength, va_list Argp)
176d71ae5a4SJacob Faibussowitsch {
177d781fa04SBarry Smith   char  *newformat = NULL;
17814416c0eSBarry Smith   char   formatbuf[PETSCDEFAULTBUFFERSIZE];
179d781fa04SBarry Smith   size_t newLength;
18014416c0eSBarry Smith   int    flen;
181e5c89e4eSSatish Balay 
182eed5747fSBarry Smith   PetscFunctionBegin;
1839566063dSJacob Faibussowitsch   PetscCall(PetscFormatConvertGetSize(format, &newLength));
18494217ebdSBarry Smith   if (newLength < sizeof(formatbuf)) {
185e2135aedSMatthew Knepley     newformat = formatbuf;
18694217ebdSBarry Smith     newLength = sizeof(formatbuf) - 1;
187e2135aedSMatthew Knepley   } else {
1889566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(newLength, &newformat));
189e2135aedSMatthew Knepley   }
1909566063dSJacob Faibussowitsch   PetscCall(PetscFormatConvert(format, newformat));
1917b9a2d1bSSatish Balay #if defined(PETSC_HAVE_VSNPRINTF)
192152b30f0SSatish Balay   flen = vsnprintf(str, len, newformat, Argp);
193e5c89e4eSSatish Balay #else
19489b07760SSatish Balay   #error "vsnprintf not found"
195e5c89e4eSSatish Balay #endif
19648a46eb9SPierre Jolivet   if (newLength > sizeof(formatbuf) - 1) PetscCall(PetscFree(newformat));
1978627564fSBarry Smith   {
1988627564fSBarry Smith     PetscBool foundedot;
1998627564fSBarry Smith     size_t    cnt = 0, ncnt = 0, leng;
2009566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(str, &leng));
20117ca8410SBarry Smith     if (leng > 4) {
2028627564fSBarry Smith       for (cnt = 0; cnt < leng - 4; cnt++) {
2038627564fSBarry Smith         if (str[cnt] == '[' && str[cnt + 1] == '|') {
204c540d043SBarry Smith           flen -= 4;
2059371c9d4SSatish Balay           cnt++;
2069371c9d4SSatish Balay           cnt++;
2078627564fSBarry Smith           foundedot = PETSC_FALSE;
2088627564fSBarry Smith           for (; cnt < leng - 1; cnt++) {
2098627564fSBarry Smith             if (str[cnt] == '|' && str[cnt + 1] == ']') {
2108627564fSBarry Smith               cnt++;
2118627564fSBarry Smith               if (!foundedot) str[ncnt++] = '.';
2128627564fSBarry Smith               ncnt--;
2138627564fSBarry Smith               break;
2148627564fSBarry Smith             } else {
2158627564fSBarry Smith               if (str[cnt] == 'e' || str[cnt] == '.') foundedot = PETSC_TRUE;
2168627564fSBarry Smith               str[ncnt++] = str[cnt];
2178627564fSBarry Smith             }
2188627564fSBarry Smith           }
2198627564fSBarry Smith         } else {
2208627564fSBarry Smith           str[ncnt] = str[cnt];
2218627564fSBarry Smith         }
2228627564fSBarry Smith         ncnt++;
2238627564fSBarry Smith       }
2248627564fSBarry Smith       while (cnt < leng) {
2259371c9d4SSatish Balay         str[ncnt] = str[cnt];
2269371c9d4SSatish Balay         ncnt++;
2279371c9d4SSatish Balay         cnt++;
2288627564fSBarry Smith       }
2298627564fSBarry Smith       str[ncnt] = 0;
2308627564fSBarry Smith     }
2318627564fSBarry Smith   }
232748e1b9dSBarry Smith #if defined(PETSC_HAVE_WINDOWS_H) && !defined(PETSC_HAVE__SET_OUTPUT_FORMAT)
233e51f71cfSBarry Smith   /* older Windows OS always produces e-+0np for floating point output; remove the extra 0 */
234748e1b9dSBarry Smith   {
235748e1b9dSBarry Smith     size_t cnt = 0, ncnt = 0, leng;
2369566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(str, &leng));
237748e1b9dSBarry Smith     if (leng > 5) {
238748e1b9dSBarry Smith       for (cnt = 0; cnt < leng - 4; cnt++) {
239e51f71cfSBarry 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') {
2409371c9d4SSatish Balay           str[ncnt] = str[cnt];
2419371c9d4SSatish Balay           ncnt++;
2429371c9d4SSatish Balay           cnt++;
2439371c9d4SSatish Balay           str[ncnt] = str[cnt];
2449371c9d4SSatish Balay           ncnt++;
2459371c9d4SSatish Balay           cnt++;
2469371c9d4SSatish Balay           cnt++;
247e51f71cfSBarry Smith           str[ncnt] = str[cnt];
248748e1b9dSBarry Smith         } else {
249748e1b9dSBarry Smith           str[ncnt] = str[cnt];
250748e1b9dSBarry Smith         }
251748e1b9dSBarry Smith         ncnt++;
252748e1b9dSBarry Smith       }
253748e1b9dSBarry Smith       while (cnt < leng) {
2549371c9d4SSatish Balay         str[ncnt] = str[cnt];
2559371c9d4SSatish Balay         ncnt++;
2569371c9d4SSatish Balay         cnt++;
257748e1b9dSBarry Smith       }
258748e1b9dSBarry Smith       str[ncnt] = 0;
259748e1b9dSBarry Smith     }
260748e1b9dSBarry Smith   }
261748e1b9dSBarry Smith #endif
262c540d043SBarry Smith   if (fullLength) *fullLength = 1 + (size_t)flen;
2633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
264e5c89e4eSSatish Balay }
265e5c89e4eSSatish Balay 
266c9a19010SBarry Smith /*@C
267c69effb2SJacob Faibussowitsch   PetscFFlush - Flush a file stream
268c69effb2SJacob Faibussowitsch 
269c69effb2SJacob Faibussowitsch   Input Parameter:
270c69effb2SJacob Faibussowitsch . fd - The file stream handle
271c69effb2SJacob Faibussowitsch 
272c69effb2SJacob Faibussowitsch   Level: intermediate
273c69effb2SJacob Faibussowitsch 
274c69effb2SJacob Faibussowitsch   Notes:
275c69effb2SJacob Faibussowitsch   For output streams (and for update streams on which the last operation was output), writes
276c69effb2SJacob Faibussowitsch   any unwritten data from the stream's buffer to the associated output device.
277c69effb2SJacob Faibussowitsch 
278c69effb2SJacob Faibussowitsch   For input streams (and for update streams on which the last operation was input), the
279c69effb2SJacob Faibussowitsch   behavior is undefined.
280c69effb2SJacob Faibussowitsch 
281c69effb2SJacob Faibussowitsch   If `fd` is `NULL`, all open output streams are flushed, including ones not directly
282c69effb2SJacob Faibussowitsch   accessible to the program.
283c69effb2SJacob Faibussowitsch 
284cc4c1da9SBarry Smith   Fortran Note:
285cc4c1da9SBarry Smith   Use `PetscFlush()`
286cc4c1da9SBarry Smith 
287c69effb2SJacob Faibussowitsch .seealso: `PetscPrintf()`, `PetscFPrintf()`, `PetscVFPrintf()`, `PetscVSNPrintf()`
288c69effb2SJacob Faibussowitsch @*/
289c69effb2SJacob Faibussowitsch PetscErrorCode PetscFFlush(FILE *fd)
290c69effb2SJacob Faibussowitsch {
291*33ff13ceSLisandro Dalcin   int err;
292*33ff13ceSLisandro Dalcin 
293c69effb2SJacob Faibussowitsch   PetscFunctionBegin;
2944f572ea9SToby Isaac   if (fd) PetscAssertPointer(fd, 1);
295*33ff13ceSLisandro Dalcin   err = fflush(fd);
296*33ff13ceSLisandro Dalcin #if !defined(PETSC_MISSING_SIGPIPE) && defined(EPIPE) && defined(ECONNRESET)
297*33ff13ceSLisandro Dalcin   if (fd && err && (errno == EPIPE || errno == ECONNRESET)) err = 0; /* ignore error, rely on SIGPIPE */
298*33ff13ceSLisandro Dalcin #endif
299c69effb2SJacob Faibussowitsch   // could also use PetscCallExternal() here, but since we can get additional error explanation
300c69effb2SJacob Faibussowitsch   // from strerror() we opted for a manual check
301*33ff13ceSLisandro Dalcin   PetscCheck(0 == err, PETSC_COMM_SELF, PETSC_ERR_FILE_WRITE, "Error in fflush() due to \"%s\"", strerror(errno));
302c69effb2SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
303c69effb2SJacob Faibussowitsch }
304c69effb2SJacob Faibussowitsch 
305c69effb2SJacob Faibussowitsch /*@C
306aec76313SJacob Faibussowitsch   PetscVFPrintfDefault -  All PETSc standard out and error messages are sent through this function; so, in theory, this can
307e5c89e4eSSatish Balay   can be replaced with something that does not simply write to a file.
308e5c89e4eSSatish Balay 
309cc4c1da9SBarry Smith   No Fortran Support
310cc4c1da9SBarry Smith 
31110450e9eSJacob Faibussowitsch   Input Parameters:
31210450e9eSJacob Faibussowitsch + fd     - the file descriptor to write to
31310450e9eSJacob Faibussowitsch . format - the format string to write with
31410450e9eSJacob Faibussowitsch - Argp   - the variable argument list of items to format and write
31510450e9eSJacob Faibussowitsch 
31610450e9eSJacob Faibussowitsch   Level: developer
31710450e9eSJacob Faibussowitsch 
31810450e9eSJacob Faibussowitsch   Note:
31910450e9eSJacob Faibussowitsch   For error messages this may be called by any MPI process, for regular standard out it is
32010450e9eSJacob Faibussowitsch   called only by MPI rank 0 of a given communicator
32110450e9eSJacob Faibussowitsch 
32210450e9eSJacob Faibussowitsch   Example Usage:
323c9a19010SBarry Smith   To use, write your own function for example,
324058c9ee1SBarry Smith .vb
325058c9ee1SBarry Smith    PetscErrorCode mypetscvfprintf(FILE *fd, const char format[], va_list Argp)
326058c9ee1SBarry Smith    {
327058c9ee1SBarry Smith      PetscErrorCode ierr;
328058c9ee1SBarry Smith 
329058c9ee1SBarry Smith      PetscFunctionBegin;
330058c9ee1SBarry Smith       if (fd != stdout && fd != stderr) {  handle regular files
331058c9ee1SBarry Smith          CHKERR(PetscVFPrintfDefault(fd,format,Argp));
332058c9ee1SBarry Smith      } else {
333058c9ee1SBarry Smith         char   buff[BIG];
334058c9ee1SBarry Smith         size_t length;
335058c9ee1SBarry Smith         PetscCall(PetscVSNPrintf(buff,BIG,format,&length,Argp));
336058c9ee1SBarry Smith         now send buff to whatever stream or whatever you want
337058c9ee1SBarry Smith     }
338058c9ee1SBarry Smith     PetscFunctionReturn(PETSC_SUCCESS);
339058c9ee1SBarry Smith    }
340058c9ee1SBarry Smith .ve
341058c9ee1SBarry Smith   then before the call to `PetscInitialize()` do the assignment `PetscVFPrintf = mypetscvfprintf`;
342058c9ee1SBarry Smith 
343aec76313SJacob Faibussowitsch   Developer Notes:
344058c9ee1SBarry Smith   This could be called by an error handler, if that happens then a recursion of the error handler may occur
345058c9ee1SBarry Smith   and a resulting crash
346c9a19010SBarry Smith 
347c69effb2SJacob Faibussowitsch .seealso: `PetscVSNPrintf()`, `PetscErrorPrintf()`, `PetscFFlush()`
348c9a19010SBarry Smith @*/
349cc4c1da9SBarry Smith PetscErrorCode PetscVFPrintfDefault(FILE *fd, const char format[], va_list Argp)
350d71ae5a4SJacob Faibussowitsch {
35114416c0eSBarry Smith   char   str[PETSCDEFAULTBUFFERSIZE];
35214416c0eSBarry Smith   char  *buff = str;
35314416c0eSBarry Smith   size_t fullLength;
3541531940fSBarry Smith #if defined(PETSC_HAVE_VA_COPY)
35514416c0eSBarry Smith   va_list Argpcopy;
3561531940fSBarry Smith #endif
3571179db26SBarry Smith 
358eed5747fSBarry Smith   PetscFunctionBegin;
3591531940fSBarry Smith #if defined(PETSC_HAVE_VA_COPY)
36014416c0eSBarry Smith   va_copy(Argpcopy, Argp);
3611531940fSBarry Smith #endif
3629566063dSJacob Faibussowitsch   PetscCall(PetscVSNPrintf(str, sizeof(str), format, &fullLength, Argp));
36314416c0eSBarry Smith   if (fullLength > sizeof(str)) {
3649566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(fullLength, &buff));
3651531940fSBarry Smith #if defined(PETSC_HAVE_VA_COPY)
3669566063dSJacob Faibussowitsch     PetscCall(PetscVSNPrintf(buff, fullLength, format, NULL, Argpcopy));
3671531940fSBarry Smith #else
3681531940fSBarry Smith     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "C89 does not support va_copy() hence cannot print long strings with PETSc printing routines");
3691531940fSBarry Smith #endif
37014416c0eSBarry Smith   }
371eae3dc7dSJacob Faibussowitsch #if defined(PETSC_HAVE_VA_COPY)
372eae3dc7dSJacob Faibussowitsch   va_end(Argpcopy);
373eae3dc7dSJacob Faibussowitsch #endif
374c69effb2SJacob Faibussowitsch   {
3758c0ebe3fSBarry Smith     int err;
3768c0ebe3fSBarry Smith 
3778c0ebe3fSBarry Smith     // POSIX C sets errno but otherwise it may not be set for *printf() system calls
3788c0ebe3fSBarry Smith     // https://pubs.opengroup.org/onlinepubs/9699919799/functions/fprintf.html
3798c0ebe3fSBarry Smith     errno = 0;
3808c0ebe3fSBarry Smith     err   = fprintf(fd, "%s", buff);
381c69effb2SJacob Faibussowitsch     // cannot use PetscCallExternal() for fprintf since the return value is "number of
382c69effb2SJacob Faibussowitsch     // characters transmitted to the output stream" on success
3838c0ebe3fSBarry 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)");
384c69effb2SJacob Faibussowitsch   }
385c69effb2SJacob Faibussowitsch   PetscCall(PetscFFlush(fd));
38648a46eb9SPierre Jolivet   if (buff != str) PetscCall(PetscFree(buff));
3873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
388e5c89e4eSSatish Balay }
389e5c89e4eSSatish Balay 
3905b5bc046SBarry Smith /*@C
3915b5bc046SBarry Smith   PetscSNPrintf - Prints to a string of given length
3925b5bc046SBarry Smith 
393cc4c1da9SBarry Smith   Not Collective, No Fortran Support
3945b5bc046SBarry Smith 
3955b5bc046SBarry Smith   Input Parameters:
39621532e8aSBarry Smith + len    - the length of `str`
39710450e9eSJacob Faibussowitsch - format - the usual `printf()` format string
3985b5bc046SBarry Smith 
39921532e8aSBarry Smith   Output Parameter:
40021532e8aSBarry Smith . str - the resulting string
40121532e8aSBarry Smith 
4025b5bc046SBarry Smith   Level: intermediate
4035b5bc046SBarry Smith 
404db781477SPatrick Sanan .seealso: `PetscSynchronizedFlush()`, `PetscSynchronizedFPrintf()`, `PetscFPrintf()`, `PetscVSNPrintf()`,
405c69effb2SJacob Faibussowitsch           `PetscPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIISynchronizedPrintf()`,
406c69effb2SJacob Faibussowitsch           `PetscVFPrintf()`, `PetscFFlush()`
4075b5bc046SBarry Smith @*/
408cc4c1da9SBarry Smith PetscErrorCode PetscSNPrintf(char str[], size_t len, const char format[], ...)
409d71ae5a4SJacob Faibussowitsch {
410c9a19010SBarry Smith   size_t  fullLength;
4115b5bc046SBarry Smith   va_list Argp;
4125b5bc046SBarry Smith 
4135b5bc046SBarry Smith   PetscFunctionBegin;
4145b5bc046SBarry Smith   va_start(Argp, format);
4159566063dSJacob Faibussowitsch   PetscCall(PetscVSNPrintf(str, len, format, &fullLength, Argp));
416eae3dc7dSJacob Faibussowitsch   va_end(Argp);
4173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4185b5bc046SBarry Smith }
4195b5bc046SBarry Smith 
420257d2499SJed Brown /*@C
421058c9ee1SBarry Smith   PetscSNPrintfCount - Prints to a string of given length, returns count of characters printed
422257d2499SJed Brown 
423cc4c1da9SBarry Smith   Not Collective, No Fortran Support
424257d2499SJed Brown 
425257d2499SJed Brown   Input Parameters:
42621532e8aSBarry Smith + len    - the length of `str`
427058c9ee1SBarry Smith . format - the usual `printf()` format string
42810450e9eSJacob Faibussowitsch - ...    - args to format
429257d2499SJed Brown 
43021532e8aSBarry Smith   Output Parameters:
43121532e8aSBarry Smith + str       - the resulting string
43221532e8aSBarry Smith - countused - number of characters printed
433cb398dd3SBarry Smith 
434257d2499SJed Brown   Level: intermediate
435257d2499SJed Brown 
436db781477SPatrick Sanan .seealso: `PetscSynchronizedFlush()`, `PetscSynchronizedFPrintf()`, `PetscFPrintf()`, `PetscVSNPrintf()`,
437db781477SPatrick Sanan           `PetscPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscSNPrintf()`, `PetscVFPrintf()`
438257d2499SJed Brown @*/
439cc4c1da9SBarry Smith PetscErrorCode PetscSNPrintfCount(char str[], size_t len, const char format[], size_t *countused, ...)
440d71ae5a4SJacob Faibussowitsch {
441257d2499SJed Brown   va_list Argp;
442257d2499SJed Brown 
443257d2499SJed Brown   PetscFunctionBegin;
444257d2499SJed Brown   va_start(Argp, countused);
4459566063dSJacob Faibussowitsch   PetscCall(PetscVSNPrintf(str, len, format, countused, Argp));
446eae3dc7dSJacob Faibussowitsch   va_end(Argp);
4473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
448257d2499SJed Brown }
449257d2499SJed Brown 
45002c9f0b5SLisandro Dalcin PrintfQueue petsc_printfqueue = NULL, petsc_printfqueuebase = NULL;
451d30b0576SJed Brown int         petsc_printfqueuelength = 0;
452e5c89e4eSSatish Balay 
4538c509928SStefano Zampini static inline PetscErrorCode PetscVFPrintf_Private(FILE *fd, const char format[], va_list Argp)
454eae3dc7dSJacob Faibussowitsch {
455eae3dc7dSJacob Faibussowitsch   const PetscBool tee = (PetscBool)(petsc_history && (fd != petsc_history));
456eae3dc7dSJacob Faibussowitsch   va_list         cpy;
457eae3dc7dSJacob Faibussowitsch 
458eae3dc7dSJacob Faibussowitsch   PetscFunctionBegin;
459eae3dc7dSJacob Faibussowitsch   // must do this before we possibly consume Argp
460eae3dc7dSJacob Faibussowitsch   if (tee) va_copy(cpy, Argp);
461eae3dc7dSJacob Faibussowitsch   PetscCall((*PetscVFPrintf)(fd, format, Argp));
462eae3dc7dSJacob Faibussowitsch   if (tee) {
463eae3dc7dSJacob Faibussowitsch     PetscCall((*PetscVFPrintf)(petsc_history, format, cpy));
464eae3dc7dSJacob Faibussowitsch     va_end(cpy);
465eae3dc7dSJacob Faibussowitsch   }
466eae3dc7dSJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
467eae3dc7dSJacob Faibussowitsch }
468eae3dc7dSJacob Faibussowitsch 
4698c509928SStefano Zampini PETSC_INTERN PetscErrorCode PetscVFPrintf_Internal(FILE *fd, const char format[], ...)
4708c509928SStefano Zampini {
4718c509928SStefano Zampini   va_list Argp;
4728c509928SStefano Zampini 
4738c509928SStefano Zampini   PetscFunctionBegin;
4748c509928SStefano Zampini   va_start(Argp, format);
4758c509928SStefano Zampini   PetscCall(PetscVFPrintf_Private(fd, format, Argp));
4768c509928SStefano Zampini   va_end(Argp);
4778c509928SStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
4788c509928SStefano Zampini }
4798c509928SStefano Zampini 
480eae3dc7dSJacob Faibussowitsch static inline PetscErrorCode PetscSynchronizedFPrintf_Private(MPI_Comm comm, FILE *fp, const char format[], va_list Argp)
481eae3dc7dSJacob Faibussowitsch {
482eae3dc7dSJacob Faibussowitsch   PetscMPIInt rank;
483eae3dc7dSJacob Faibussowitsch   va_list     cpy;
484eae3dc7dSJacob Faibussowitsch 
485eae3dc7dSJacob Faibussowitsch   PetscFunctionBegin;
486eae3dc7dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
487eae3dc7dSJacob Faibussowitsch   /* First processor prints immediately to fp */
488eae3dc7dSJacob Faibussowitsch   if (rank == 0) {
489eae3dc7dSJacob Faibussowitsch     va_copy(cpy, Argp);
4908c509928SStefano Zampini     PetscCall(PetscVFPrintf_Private(fp, format, cpy));
491eae3dc7dSJacob Faibussowitsch     va_end(cpy);
492eae3dc7dSJacob Faibussowitsch   } else { /* other processors add to local queue */
493eae3dc7dSJacob Faibussowitsch     PrintfQueue next;
494eae3dc7dSJacob Faibussowitsch     size_t      fullLength = PETSCDEFAULTBUFFERSIZE;
495eae3dc7dSJacob Faibussowitsch 
496eae3dc7dSJacob Faibussowitsch     PetscCall(PetscNew(&next));
497eae3dc7dSJacob Faibussowitsch     if (petsc_printfqueue) {
498eae3dc7dSJacob Faibussowitsch       petsc_printfqueue->next = next;
499eae3dc7dSJacob Faibussowitsch       petsc_printfqueue       = next;
500eae3dc7dSJacob Faibussowitsch       petsc_printfqueue->next = NULL;
501eae3dc7dSJacob Faibussowitsch     } else petsc_printfqueuebase = petsc_printfqueue = next;
502eae3dc7dSJacob Faibussowitsch     petsc_printfqueuelength++;
503eae3dc7dSJacob Faibussowitsch     next->size   = 0;
504eae3dc7dSJacob Faibussowitsch     next->string = NULL;
505eae3dc7dSJacob Faibussowitsch     while (fullLength >= next->size) {
506eae3dc7dSJacob Faibussowitsch       next->size = fullLength + 1;
507eae3dc7dSJacob Faibussowitsch       PetscCall(PetscFree(next->string));
508eae3dc7dSJacob Faibussowitsch       PetscCall(PetscMalloc1(next->size, &next->string));
509eae3dc7dSJacob Faibussowitsch       PetscCall(PetscArrayzero(next->string, next->size));
510eae3dc7dSJacob Faibussowitsch       va_copy(cpy, Argp);
511eae3dc7dSJacob Faibussowitsch       PetscCall(PetscVSNPrintf(next->string, next->size, format, &fullLength, cpy));
512eae3dc7dSJacob Faibussowitsch       va_end(cpy);
513eae3dc7dSJacob Faibussowitsch     }
514eae3dc7dSJacob Faibussowitsch   }
515eae3dc7dSJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
516eae3dc7dSJacob Faibussowitsch }
517eae3dc7dSJacob Faibussowitsch 
518e5c89e4eSSatish Balay /*@C
5199c89aa79SPierre Jolivet   PetscSynchronizedPrintf - Prints synchronized output from multiple MPI processes.
520e5c89e4eSSatish Balay   Output of the first processor is followed by that of the second, etc.
521e5c89e4eSSatish Balay 
522e5c89e4eSSatish Balay   Not Collective
523e5c89e4eSSatish Balay 
524e5c89e4eSSatish Balay   Input Parameters:
525058c9ee1SBarry Smith + comm   - the MPI communicator
5266026c97aSBarry Smith - format - the usual `printf()` format string
527e5c89e4eSSatish Balay 
528e5c89e4eSSatish Balay   Level: intermediate
529e5c89e4eSSatish Balay 
530811af0c4SBarry Smith   Note:
531811af0c4SBarry Smith   REQUIRES a call to `PetscSynchronizedFlush()` by all the processes after the completion of the calls to `PetscSynchronizedPrintf()` for the information
532e5c89e4eSSatish Balay   from all the processors to be printed.
533e5c89e4eSSatish Balay 
534cc4c1da9SBarry Smith   Fortran Note:
535058c9ee1SBarry Smith   The call sequence is `PetscSynchronizedPrintf`(`MPI_Comm`, `character`(*), `PetscErrorCode` ierr).
536e5c89e4eSSatish Balay   That is, you can only pass a single character string from Fortran.
537e5c89e4eSSatish Balay 
538db781477SPatrick Sanan .seealso: `PetscSynchronizedFlush()`, `PetscSynchronizedFPrintf()`, `PetscFPrintf()`,
539c69effb2SJacob Faibussowitsch           `PetscPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIISynchronizedPrintf()`,
540c69effb2SJacob Faibussowitsch           `PetscFFlush()`
541e5c89e4eSSatish Balay @*/
542d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSynchronizedPrintf(MPI_Comm comm, const char format[], ...)
543d71ae5a4SJacob Faibussowitsch {
544eae3dc7dSJacob Faibussowitsch   va_list Argp;
545e5c89e4eSSatish Balay 
546e5c89e4eSSatish Balay   PetscFunctionBegin;
547e5c89e4eSSatish Balay   va_start(Argp, format);
548eae3dc7dSJacob Faibussowitsch   PetscCall(PetscSynchronizedFPrintf_Private(comm, PETSC_STDOUT, format, Argp));
549e5c89e4eSSatish Balay   va_end(Argp);
5503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
551e5c89e4eSSatish Balay }
552e5c89e4eSSatish Balay 
553e5c89e4eSSatish Balay /*@C
554e5c89e4eSSatish Balay   PetscSynchronizedFPrintf - Prints synchronized output to the specified file from
55521532e8aSBarry Smith   several MPI processes.  Output of the first process is followed by that of the
556e5c89e4eSSatish Balay   second, etc.
557e5c89e4eSSatish Balay 
558e5c89e4eSSatish Balay   Not Collective
559e5c89e4eSSatish Balay 
560e5c89e4eSSatish Balay   Input Parameters:
561058c9ee1SBarry Smith + comm   - the MPI communicator
562cc4c1da9SBarry Smith . fp     - the file pointer, `PETSC_STDOUT` or value obtained from `PetscFOpen()`
5636026c97aSBarry Smith - format - the usual `printf()` format string
564e5c89e4eSSatish Balay 
565e5c89e4eSSatish Balay   Level: intermediate
566e5c89e4eSSatish Balay 
567811af0c4SBarry Smith   Note:
568811af0c4SBarry Smith   REQUIRES a intervening call to `PetscSynchronizedFlush()` for the information
569e5c89e4eSSatish Balay   from all the processors to be printed.
570e5c89e4eSSatish Balay 
571cc4c1da9SBarry Smith   Fortran Note:
572cc4c1da9SBarry Smith   The call sequence is `PetscSynchronizedPrintf`(`MPI_Comm`, fp, `character`(*), `PetscErrorCode` ierr).
573cc4c1da9SBarry Smith   That is, you can only pass a single character string from Fortran.
574cc4c1da9SBarry Smith 
575db781477SPatrick Sanan .seealso: `PetscSynchronizedPrintf()`, `PetscSynchronizedFlush()`, `PetscFPrintf()`,
576c69effb2SJacob Faibussowitsch           `PetscFOpen()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
577c69effb2SJacob Faibussowitsch           `PetscFFlush()`
578e5c89e4eSSatish Balay @*/
579d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSynchronizedFPrintf(MPI_Comm comm, FILE *fp, const char format[], ...)
580d71ae5a4SJacob Faibussowitsch {
581eae3dc7dSJacob Faibussowitsch   va_list Argp;
582e5c89e4eSSatish Balay 
583e5c89e4eSSatish Balay   PetscFunctionBegin;
584e5c89e4eSSatish Balay   va_start(Argp, format);
585eae3dc7dSJacob Faibussowitsch   PetscCall(PetscSynchronizedFPrintf_Private(comm, fp, format, Argp));
586e5c89e4eSSatish Balay   va_end(Argp);
5873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
588e5c89e4eSSatish Balay }
589e5c89e4eSSatish Balay 
5900ec8b6e3SBarry Smith /*@C
591e5c89e4eSSatish Balay   PetscSynchronizedFlush - Flushes to the screen output from all processors
592811af0c4SBarry Smith   involved in previous `PetscSynchronizedPrintf()`/`PetscSynchronizedFPrintf()` calls.
593e5c89e4eSSatish Balay 
594d083f849SBarry Smith   Collective
595e5c89e4eSSatish Balay 
596e5c89e4eSSatish Balay   Input Parameters:
597058c9ee1SBarry Smith + comm - the MPI communicator
598a3b724e8SBarry Smith - fd   - the file pointer (valid on MPI rank 0 of the communicator), `PETSC_STDOUT` or value obtained from `PetscFOpen()`
599e5c89e4eSSatish Balay 
600e5c89e4eSSatish Balay   Level: intermediate
601e5c89e4eSSatish Balay 
602811af0c4SBarry Smith   Note:
603811af0c4SBarry Smith   If `PetscSynchronizedPrintf()` and/or `PetscSynchronizedFPrintf()` are called with
604811af0c4SBarry Smith   different MPI communicators there must be an intervening call to `PetscSynchronizedFlush()` between the calls with different MPI communicators.
605e5c89e4eSSatish Balay 
606db781477SPatrick Sanan .seealso: `PetscSynchronizedPrintf()`, `PetscFPrintf()`, `PetscPrintf()`, `PetscViewerASCIIPrintf()`,
607db781477SPatrick Sanan           `PetscViewerASCIISynchronizedPrintf()`
6080087d953SMatthew G. Knepley @*/
609d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSynchronizedFlush(MPI_Comm comm, FILE *fd)
610d71ae5a4SJacob Faibussowitsch {
61129a5cbdcSMatthew G. Knepley   PetscMPIInt rank, size, tag, i, j, n = 0, dummy = 0;
6122d609e63SMatthew Knepley   char       *message;
613e5c89e4eSSatish Balay   MPI_Status  status;
614e5c89e4eSSatish Balay 
615e5c89e4eSSatish Balay   PetscFunctionBegin;
6169566063dSJacob Faibussowitsch   PetscCall(PetscCommDuplicate(comm, &comm, &tag));
6179566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
6189566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
619e5c89e4eSSatish Balay 
620e5c89e4eSSatish Balay   /* First processor waits for messages from all other processors */
621dd400576SPatrick Sanan   if (rank == 0) {
6220ec8b6e3SBarry Smith     if (!fd) fd = PETSC_STDOUT;
623e5c89e4eSSatish Balay     for (i = 1; i < size; i++) {
6249f73f8ecSBarry Smith       /* to prevent a flood of messages to process zero, request each message separately */
6259566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Send(&dummy, 1, MPI_INT, i, tag, comm));
6269566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Recv(&n, 1, MPI_INT, i, tag, comm, &status));
627e5c89e4eSSatish Balay       for (j = 0; j < n; j++) {
62829a5cbdcSMatthew G. Knepley         PetscMPIInt size = 0;
6292d609e63SMatthew Knepley 
6309566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Recv(&size, 1, MPI_INT, i, tag, comm, &status));
6319566063dSJacob Faibussowitsch         PetscCall(PetscMalloc1(size, &message));
6329566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Recv(message, size, MPI_CHAR, i, tag, comm, &status));
6339566063dSJacob Faibussowitsch         PetscCall(PetscFPrintf(comm, fd, "%s", message));
6349566063dSJacob Faibussowitsch         PetscCall(PetscFree(message));
635e5c89e4eSSatish Balay       }
636e5c89e4eSSatish Balay     }
637e5c89e4eSSatish Balay   } else { /* other processors send queue to processor 0 */
638d30b0576SJed Brown     PrintfQueue next = petsc_printfqueuebase, previous;
639e5c89e4eSSatish Balay 
6409566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Recv(&dummy, 1, MPI_INT, 0, tag, comm, &status));
6419566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Send(&petsc_printfqueuelength, 1, MPI_INT, 0, tag, comm));
642d30b0576SJed Brown     for (i = 0; i < petsc_printfqueuelength; i++) {
6439566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Send(&next->size, 1, MPI_INT, 0, tag, comm));
6446497c311SBarry Smith       PetscCallMPI(MPI_Send(next->string, (PetscMPIInt)next->size, MPI_CHAR, 0, tag, comm));
645e5c89e4eSSatish Balay       previous = next;
646e5c89e4eSSatish Balay       next     = next->next;
6479566063dSJacob Faibussowitsch       PetscCall(PetscFree(previous->string));
6489566063dSJacob Faibussowitsch       PetscCall(PetscFree(previous));
649e5c89e4eSSatish Balay     }
65002c9f0b5SLisandro Dalcin     petsc_printfqueue       = NULL;
651d30b0576SJed Brown     petsc_printfqueuelength = 0;
652e5c89e4eSSatish Balay   }
6539566063dSJacob Faibussowitsch   PetscCall(PetscCommDestroy(&comm));
6543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
655e5c89e4eSSatish Balay }
656e5c89e4eSSatish Balay 
657e5c89e4eSSatish Balay /*@C
658e5c89e4eSSatish Balay   PetscFPrintf - Prints to a file, only from the first
65921532e8aSBarry Smith   MPI process in the communicator.
660e5c89e4eSSatish Balay 
661cc4c1da9SBarry Smith   Not Collective
662e5c89e4eSSatish Balay 
663e5c89e4eSSatish Balay   Input Parameters:
664058c9ee1SBarry Smith + comm   - the MPI communicator
665cc4c1da9SBarry Smith . fd     - the file pointer, `PETSC_STDOUT` or value obtained from `PetscFOpen()`
6666026c97aSBarry Smith - format - the usual `printf()` format string
667e5c89e4eSSatish Balay 
668e5c89e4eSSatish Balay   Level: intermediate
669e5c89e4eSSatish Balay 
670cc4c1da9SBarry Smith   Fortran Note:
671cc4c1da9SBarry Smith   The call sequence is `PetscFPrintf`(`MPI_Comm`, fp, `character`(*), `PetscErrorCode` ierr).
672cc4c1da9SBarry Smith   That is, you can only pass a single character string from Fortran.
673cc4c1da9SBarry Smith 
674aec76313SJacob Faibussowitsch   Developer Notes:
675058c9ee1SBarry Smith   This maybe, and is, called from PETSc error handlers and `PetscMallocValidate()` hence it does not use `PetscCallMPI()` which
676058c9ee1SBarry Smith   could recursively restart the malloc validation.
677058c9ee1SBarry Smith 
678db781477SPatrick Sanan .seealso: `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
679c69effb2SJacob Faibussowitsch           `PetscViewerASCIISynchronizedPrintf()`, `PetscSynchronizedFlush()`, `PetscFFlush()`
680e5c89e4eSSatish Balay @*/
681d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFPrintf(MPI_Comm comm, FILE *fd, const char format[], ...)
682d71ae5a4SJacob Faibussowitsch {
6838c509928SStefano Zampini   PetscMPIInt rank;
684eae3dc7dSJacob Faibussowitsch   va_list     Argp;
685e5c89e4eSSatish Balay 
686e5c89e4eSSatish Balay   PetscFunctionBegin;
6878c509928SStefano Zampini   PetscCallMPI(MPI_Comm_rank(comm, &rank));
6888c509928SStefano Zampini   if (PetscLikely(rank != 0)) PetscFunctionReturn(PETSC_SUCCESS);
689e5c89e4eSSatish Balay   va_start(Argp, format);
6908c509928SStefano Zampini   PetscCall(PetscVFPrintf_Private(fd, format, Argp));
691e5c89e4eSSatish Balay   va_end(Argp);
6923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
693e5c89e4eSSatish Balay }
694e5c89e4eSSatish Balay 
695e5c89e4eSSatish Balay /*@C
696e5c89e4eSSatish Balay   PetscPrintf - Prints to standard out, only from the first
69721532e8aSBarry Smith   MPI process in the communicator. Calls from other processes are ignored.
698e5c89e4eSSatish Balay 
699e5c89e4eSSatish Balay   Not Collective
700e5c89e4eSSatish Balay 
701e5c89e4eSSatish Balay   Input Parameters:
702e5c89e4eSSatish Balay + comm   - the communicator
703bfbbc7b7SBarry Smith - format - the usual `printf()` format string
704e5c89e4eSSatish Balay 
705e5c89e4eSSatish Balay   Level: intermediate
706e5c89e4eSSatish Balay 
707811af0c4SBarry Smith   Note:
708811af0c4SBarry Smith   Deprecated information: `PetscPrintf()` supports some format specifiers that are unique to PETSc.
709811af0c4SBarry Smith   See the manual page for `PetscFormatConvert()` for details.
710b2706f25SRichard Tran Mills 
711aec76313SJacob Faibussowitsch   Fortran Notes:
712811af0c4SBarry Smith   The call sequence is `PetscPrintf`(MPI_Comm, character(*), `PetscErrorCode` ierr) from Fortran.
713e5c89e4eSSatish Balay   That is, you can only pass a single character string from Fortran.
714e5c89e4eSSatish Balay 
715c69effb2SJacob Faibussowitsch .seealso: `PetscFPrintf()`, `PetscSynchronizedPrintf()`, `PetscFormatConvert()`, `PetscFFlush()`
716e5c89e4eSSatish Balay @*/
717d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscPrintf(MPI_Comm comm, const char format[], ...)
718d71ae5a4SJacob Faibussowitsch {
7198c509928SStefano Zampini   PetscMPIInt rank;
720eae3dc7dSJacob Faibussowitsch   va_list     Argp;
721e5c89e4eSSatish Balay 
722e5c89e4eSSatish Balay   PetscFunctionBegin;
7238c509928SStefano Zampini   PetscCallMPI(MPI_Comm_rank(comm, &rank));
7248c509928SStefano Zampini   if (PetscLikely(rank != 0)) PetscFunctionReturn(PETSC_SUCCESS);
725e5c89e4eSSatish Balay   va_start(Argp, format);
7268c509928SStefano Zampini   PetscCall(PetscVFPrintf_Private(PETSC_STDOUT, format, Argp));
727e5c89e4eSSatish Balay   va_end(Argp);
7283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
729e5c89e4eSSatish Balay }
730e5c89e4eSSatish Balay 
731d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscHelpPrintfDefault(MPI_Comm comm, const char format[], ...)
732d71ae5a4SJacob Faibussowitsch {
7338c509928SStefano Zampini   PetscMPIInt rank;
734eae3dc7dSJacob Faibussowitsch   va_list     Argp;
735e5c89e4eSSatish Balay 
736e5c89e4eSSatish Balay   PetscFunctionBegin;
7378c509928SStefano Zampini   PetscCallMPI(MPI_Comm_rank(comm, &rank));
7388c509928SStefano Zampini   if (PetscLikely(rank != 0)) PetscFunctionReturn(PETSC_SUCCESS);
739e5c89e4eSSatish Balay   va_start(Argp, format);
7408c509928SStefano Zampini   PetscCall(PetscVFPrintf_Private(PETSC_STDOUT, format, Argp));
741e5c89e4eSSatish Balay   va_end(Argp);
7423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
743e5c89e4eSSatish Balay }
744e5c89e4eSSatish Balay 
745e5c89e4eSSatish Balay /*@C
74621532e8aSBarry Smith   PetscSynchronizedFGets - Multiple MPI processes all get the same line from a file.
747e5c89e4eSSatish Balay 
748d083f849SBarry Smith   Collective
749e5c89e4eSSatish Balay 
750e5c89e4eSSatish Balay   Input Parameters:
75121532e8aSBarry Smith + comm - the MPI communicator
752aec76313SJacob Faibussowitsch . fp   - the file pointer
75321532e8aSBarry Smith - len  - the length of `string`
754e5c89e4eSSatish Balay 
755e5c89e4eSSatish Balay   Output Parameter:
75621532e8aSBarry Smith . string - the line read from the file, at end of file `string`[0] == 0
757e5c89e4eSSatish Balay 
758e5c89e4eSSatish Balay   Level: intermediate
759e5c89e4eSSatish Balay 
760db781477SPatrick Sanan .seealso: `PetscSynchronizedPrintf()`, `PetscSynchronizedFlush()`,
761db781477SPatrick Sanan           `PetscFOpen()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIPrintf()`
762e5c89e4eSSatish Balay @*/
763d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSynchronizedFGets(MPI_Comm comm, FILE *fp, size_t len, char string[])
764d71ae5a4SJacob Faibussowitsch {
765e5c89e4eSSatish Balay   PetscMPIInt rank;
766e5c89e4eSSatish Balay 
767e5c89e4eSSatish Balay   PetscFunctionBegin;
7689566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
76980971c97SJames Wright   if (rank == 0) {
7706497c311SBarry Smith     if (!fgets(string, (int)len, fp)) {
771e31d4fa4SJed Brown       string[0] = 0;
772bf31d2d3SBarry Smith       PetscCheck(feof(fp), PETSC_COMM_SELF, PETSC_ERR_FILE_READ, "Error reading from file due to \"%s\"", strerror(errno));
773047b9c12SMatthew G Knepley     }
774238ccf28SShri Abhyankar   }
7756497c311SBarry Smith   PetscCallMPI(MPI_Bcast(string, (PetscMPIInt)len, MPI_BYTE, 0, comm));
7763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
777e5c89e4eSSatish Balay }
778238ccf28SShri Abhyankar 
779d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFormatRealArray(char buf[], size_t len, const char *fmt, PetscInt n, const PetscReal x[])
780d71ae5a4SJacob Faibussowitsch {
7811b5687a1SBarry Smith   PetscInt i;
7821b5687a1SBarry Smith   size_t   left, count;
7831b5687a1SBarry Smith   char    *p;
7841b5687a1SBarry Smith 
7851b5687a1SBarry Smith   PetscFunctionBegin;
7861b5687a1SBarry Smith   for (i = 0, p = buf, left = len; i < n; i++) {
7879566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintfCount(p, left, fmt, &count, (double)x[i]));
78808401ef6SPierre Jolivet     PetscCheck(count < left, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Insufficient space in buffer");
7891b5687a1SBarry Smith     left -= count;
7901b5687a1SBarry Smith     p += count - 1;
7911b5687a1SBarry Smith     *p++ = ' ';
7921b5687a1SBarry Smith   }
7931b5687a1SBarry Smith   p[i ? 0 : -1] = 0;
7943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7951b5687a1SBarry Smith }
796