xref: /petsc/src/sys/fileio/mprint.c (revision 058c9ee17c8425a054ff2d1155e2476af91a1bd1)
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
25811af0c4SBarry Smith      PetscFormatConvertGetSize - Gets the length of a string needed to hold format converted with `PetscFormatConvert()`
26811af0c4SBarry Smith 
27*058c9ee1SBarry 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
79*058c9ee1SBarry Smith      PetscFormatConvert - converts %g to [|%g|] so that `PetscVSNPrintf()` can ensure all %g formatted numbers have a decimal point when printed. The
80*058c9ee1SBarry 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 
82*058c9ee1SBarry Smith    No Fortran Support
83811af0c4SBarry Smith 
84d781fa04SBarry Smith    Input Parameters:
85d781fa04SBarry Smith +   format - the PETSc format string
86d781fa04SBarry Smith .   newformat - the location to put the new format
87811af0c4SBarry Smith -   size - the length of newformat, you can use `PetscFormatConvertGetSize()` to compute the needed size
88d781fa04SBarry Smith 
89d781fa04SBarry Smith    Level: developer
90d781fa04SBarry Smith 
91*058c9ee1SBarry Smith     Note:
92*058c9ee1SBarry Smith     Deprecated usage also converts the %D to %d for 32 bit PETSc indices and %lld for 64 bit PETSc indices. This feature is no
93*058c9ee1SBarry Smith     longer used in PETSc code instead use %" PetscInt_FMT " in the format string
94*058c9ee1SBarry Smith 
95db781477SPatrick Sanan .seealso: `PetscFormatConvertGetSize()`, `PetscVSNPrintf()`, `PetscVFPrintf()`
96d781fa04SBarry Smith @*/
97d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFormatConvert(const char *format, char *newformat)
98d71ae5a4SJacob Faibussowitsch {
99e5c89e4eSSatish Balay   PetscInt i = 0, j = 0;
100e5c89e4eSSatish Balay 
101eed5747fSBarry Smith   PetscFunctionBegin;
102d781fa04SBarry Smith   while (format[i]) {
1032a1ad9caSBarry Smith     if (format[i] == '%' && format[i + 1] == '%') {
1042a1ad9caSBarry Smith       newformat[j++] = format[i++];
1052a1ad9caSBarry Smith       newformat[j++] = format[i++];
1062a1ad9caSBarry Smith     } else if (format[i] == '%') {
1078627564fSBarry Smith       if (format[i + 1] == 'g') {
1088627564fSBarry Smith         newformat[j++] = '[';
1098627564fSBarry Smith         newformat[j++] = '|';
1108627564fSBarry Smith       }
1117bc47156SJose Roman       /* Find the letter */
1127bc47156SJose Roman       for (; format[i] && format[i] <= '9'; i++) newformat[j++] = format[i];
1137bc47156SJose Roman       switch (format[i]) {
1147bc47156SJose Roman       case 'D':
1156de02169SBarry Smith #if !defined(PETSC_USE_64BIT_INDICES)
116e5c89e4eSSatish Balay         newformat[j++] = 'd';
117e5c89e4eSSatish Balay #else
118e5c89e4eSSatish Balay         newformat[j++] = 'l';
119e5c89e4eSSatish Balay         newformat[j++] = 'l';
120e5c89e4eSSatish Balay         newformat[j++] = 'd';
121e5c89e4eSSatish Balay #endif
1227bc47156SJose Roman         break;
1238627564fSBarry Smith       case 'g':
1248627564fSBarry Smith         newformat[j++] = format[i];
1258627564fSBarry Smith         if (format[i - 1] == '%') {
1268627564fSBarry Smith           newformat[j++] = '|';
1278627564fSBarry Smith           newformat[j++] = ']';
1288627564fSBarry Smith         }
1298627564fSBarry Smith         break;
130d71ae5a4SJacob Faibussowitsch       case 'G':
131d71ae5a4SJacob Faibussowitsch         SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "%%G format is no longer supported, use %%g and cast the argument to double");
132d71ae5a4SJacob Faibussowitsch       case 'F':
133d71ae5a4SJacob Faibussowitsch         SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "%%F format is no longer supported, use %%f and cast the argument to double");
134d71ae5a4SJacob Faibussowitsch       default:
135d71ae5a4SJacob Faibussowitsch         newformat[j++] = format[i];
136d71ae5a4SJacob Faibussowitsch         break;
1377bc47156SJose Roman       }
1387bc47156SJose Roman       i++;
139a297a907SKarl Rupp     } else newformat[j++] = format[i++];
140e5c89e4eSSatish Balay   }
141e5c89e4eSSatish Balay   newformat[j] = 0;
1423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
143e5c89e4eSSatish Balay }
144e5c89e4eSSatish Balay 
14514416c0eSBarry Smith #define PETSCDEFAULTBUFFERSIZE 8 * 1024
146d781fa04SBarry Smith 
147c9a19010SBarry Smith /*@C
148*058c9ee1SBarry Smith      PetscVSNPrintf - The PETSc version of vsnprintf(). Ensures that all %g formatted arguments' output contains the decimal point (which
149*058c9ee1SBarry Smith      is used by the test harness)
150c9a19010SBarry Smith 
151c9a19010SBarry Smith    Input Parameters:
152c9a19010SBarry Smith +   str - location to put result
153c9a19010SBarry Smith .   len - the amount of space in str
154c9a19010SBarry Smith +   format - the PETSc format string
155c9a19010SBarry Smith -   fullLength - the amount of space in str actually used.
156c9a19010SBarry Smith 
157c9a19010SBarry Smith    Level: developer
158c9a19010SBarry Smith 
159*058c9ee1SBarry Smith    Developer Note:
160*058c9ee1SBarry Smith    This function may be called from an error handler, if an error occurs when it is called by the error handler than likely
161*058c9ee1SBarry Smith    a recursion will occur resulting in a crash of the program.
162*058c9ee1SBarry Smith 
163*058c9ee1SBarry Smith    If the length of the format string `format` is on the order of `PETSCDEFAULTBUFFERSIZE` (8*1024), unlikely, this function call will perform an `PetscMalloc()`
164*058c9ee1SBarry Smith 
165*058c9ee1SBarry Smith .seealso: `PetscFormatConvert()`, `PetscFormatConvertGetSize()`, `PetscVSNPrintf()`, `PetscErrorPrintf()`, `PetscVPrintf()`
166c9a19010SBarry Smith @*/
167d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscVSNPrintf(char *str, size_t len, const char *format, size_t *fullLength, va_list Argp)
168d71ae5a4SJacob Faibussowitsch {
169d781fa04SBarry Smith   char  *newformat = NULL;
17014416c0eSBarry Smith   char   formatbuf[PETSCDEFAULTBUFFERSIZE];
171d781fa04SBarry Smith   size_t newLength;
17214416c0eSBarry Smith   int    flen;
173e5c89e4eSSatish Balay 
174eed5747fSBarry Smith   PetscFunctionBegin;
1759566063dSJacob Faibussowitsch   PetscCall(PetscFormatConvertGetSize(format, &newLength));
17694217ebdSBarry Smith   if (newLength < sizeof(formatbuf)) {
177e2135aedSMatthew Knepley     newformat = formatbuf;
17894217ebdSBarry Smith     newLength = sizeof(formatbuf) - 1;
179e2135aedSMatthew Knepley   } else {
1809566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(newLength, &newformat));
181e2135aedSMatthew Knepley   }
1829566063dSJacob Faibussowitsch   PetscCall(PetscFormatConvert(format, newformat));
1837b9a2d1bSSatish Balay #if defined(PETSC_HAVE_VSNPRINTF)
184152b30f0SSatish Balay   flen = vsnprintf(str, len, newformat, Argp);
185e5c89e4eSSatish Balay #else
18689b07760SSatish Balay   #error "vsnprintf not found"
187e5c89e4eSSatish Balay #endif
18848a46eb9SPierre Jolivet   if (newLength > sizeof(formatbuf) - 1) PetscCall(PetscFree(newformat));
1898627564fSBarry Smith   {
1908627564fSBarry Smith     PetscBool foundedot;
1918627564fSBarry Smith     size_t    cnt = 0, ncnt = 0, leng;
1929566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(str, &leng));
19317ca8410SBarry Smith     if (leng > 4) {
1948627564fSBarry Smith       for (cnt = 0; cnt < leng - 4; cnt++) {
1958627564fSBarry Smith         if (str[cnt] == '[' && str[cnt + 1] == '|') {
196c540d043SBarry Smith           flen -= 4;
1979371c9d4SSatish Balay           cnt++;
1989371c9d4SSatish Balay           cnt++;
1998627564fSBarry Smith           foundedot = PETSC_FALSE;
2008627564fSBarry Smith           for (; cnt < leng - 1; cnt++) {
2018627564fSBarry Smith             if (str[cnt] == '|' && str[cnt + 1] == ']') {
2028627564fSBarry Smith               cnt++;
2038627564fSBarry Smith               if (!foundedot) str[ncnt++] = '.';
2048627564fSBarry Smith               ncnt--;
2058627564fSBarry Smith               break;
2068627564fSBarry Smith             } else {
2078627564fSBarry Smith               if (str[cnt] == 'e' || str[cnt] == '.') foundedot = PETSC_TRUE;
2088627564fSBarry Smith               str[ncnt++] = str[cnt];
2098627564fSBarry Smith             }
2108627564fSBarry Smith           }
2118627564fSBarry Smith         } else {
2128627564fSBarry Smith           str[ncnt] = str[cnt];
2138627564fSBarry Smith         }
2148627564fSBarry Smith         ncnt++;
2158627564fSBarry Smith       }
2168627564fSBarry Smith       while (cnt < leng) {
2179371c9d4SSatish Balay         str[ncnt] = str[cnt];
2189371c9d4SSatish Balay         ncnt++;
2199371c9d4SSatish Balay         cnt++;
2208627564fSBarry Smith       }
2218627564fSBarry Smith       str[ncnt] = 0;
2228627564fSBarry Smith     }
2238627564fSBarry Smith   }
224748e1b9dSBarry Smith #if defined(PETSC_HAVE_WINDOWS_H) && !defined(PETSC_HAVE__SET_OUTPUT_FORMAT)
225e51f71cfSBarry Smith   /* older Windows OS always produces e-+0np for floating point output; remove the extra 0 */
226748e1b9dSBarry Smith   {
227748e1b9dSBarry Smith     size_t cnt = 0, ncnt = 0, leng;
2289566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(str, &leng));
229748e1b9dSBarry Smith     if (leng > 5) {
230748e1b9dSBarry Smith       for (cnt = 0; cnt < leng - 4; cnt++) {
231e51f71cfSBarry 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') {
2329371c9d4SSatish Balay           str[ncnt] = str[cnt];
2339371c9d4SSatish Balay           ncnt++;
2349371c9d4SSatish Balay           cnt++;
2359371c9d4SSatish Balay           str[ncnt] = str[cnt];
2369371c9d4SSatish Balay           ncnt++;
2379371c9d4SSatish Balay           cnt++;
2389371c9d4SSatish Balay           cnt++;
239e51f71cfSBarry Smith           str[ncnt] = str[cnt];
240748e1b9dSBarry Smith         } else {
241748e1b9dSBarry Smith           str[ncnt] = str[cnt];
242748e1b9dSBarry Smith         }
243748e1b9dSBarry Smith         ncnt++;
244748e1b9dSBarry Smith       }
245748e1b9dSBarry Smith       while (cnt < leng) {
2469371c9d4SSatish Balay         str[ncnt] = str[cnt];
2479371c9d4SSatish Balay         ncnt++;
2489371c9d4SSatish Balay         cnt++;
249748e1b9dSBarry Smith       }
250748e1b9dSBarry Smith       str[ncnt] = 0;
251748e1b9dSBarry Smith     }
252748e1b9dSBarry Smith   }
253748e1b9dSBarry Smith #endif
254c540d043SBarry Smith   if (fullLength) *fullLength = 1 + (size_t)flen;
2553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
256e5c89e4eSSatish Balay }
257e5c89e4eSSatish Balay 
258c9a19010SBarry Smith /*@C
259c9a19010SBarry Smith      PetscVFPrintf -  All PETSc standard out and error messages are sent through this function; so, in theory, this can
260e5c89e4eSSatish Balay         can be replaced with something that does not simply write to a file.
261e5c89e4eSSatish Balay 
262c9a19010SBarry Smith       To use, write your own function for example,
263*058c9ee1SBarry Smith .vb
264*058c9ee1SBarry Smith    PetscErrorCode mypetscvfprintf(FILE *fd,const char format[],va_list Argp)
265*058c9ee1SBarry Smith    {
266*058c9ee1SBarry Smith      PetscErrorCode ierr;
267*058c9ee1SBarry Smith 
268*058c9ee1SBarry Smith      PetscFunctionBegin;
269*058c9ee1SBarry Smith       if (fd != stdout && fd != stderr) {  handle regular files
270*058c9ee1SBarry Smith          CHKERR(PetscVFPrintfDefault(fd,format,Argp));
271*058c9ee1SBarry Smith      } else {
272*058c9ee1SBarry Smith         char   buff[BIG];
273*058c9ee1SBarry Smith         size_t length;
274*058c9ee1SBarry Smith         PetscCall(PetscVSNPrintf(buff,BIG,format,&length,Argp));
275*058c9ee1SBarry Smith         now send buff to whatever stream or whatever you want
276*058c9ee1SBarry Smith     }
277*058c9ee1SBarry Smith     PetscFunctionReturn(PETSC_SUCCESS);
278*058c9ee1SBarry Smith    }
279*058c9ee1SBarry Smith .ve
280*058c9ee1SBarry Smith    then before the call to `PetscInitialize()` do the assignment `PetscVFPrintf = mypetscvfprintf`;
281*058c9ee1SBarry Smith 
282*058c9ee1SBarry Smith   Level:  developer
283c9a19010SBarry Smith 
284811af0c4SBarry Smith    Note:
28595452b02SPatrick Sanan    For error messages this may be called by any process, for regular standard out it is
286e5c89e4eSSatish Balay    called only by process 0 of a given communicator
287e5c89e4eSSatish Balay 
288811af0c4SBarry Smith    Developer Note:
289*058c9ee1SBarry Smith    This could be called by an error handler, if that happens then a recursion of the error handler may occur
290*058c9ee1SBarry Smith    and a resulting crash
291c9a19010SBarry Smith 
292db781477SPatrick Sanan .seealso: `PetscVSNPrintf()`, `PetscErrorPrintf()`
293c9a19010SBarry Smith @*/
294d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscVFPrintfDefault(FILE *fd, const char *format, va_list Argp)
295d71ae5a4SJacob Faibussowitsch {
29614416c0eSBarry Smith   char   str[PETSCDEFAULTBUFFERSIZE];
29714416c0eSBarry Smith   char  *buff = str;
29814416c0eSBarry Smith   size_t fullLength;
2991531940fSBarry Smith #if defined(PETSC_HAVE_VA_COPY)
30014416c0eSBarry Smith   va_list Argpcopy;
3011531940fSBarry Smith #endif
3021179db26SBarry Smith 
303eed5747fSBarry Smith   PetscFunctionBegin;
3041531940fSBarry Smith #if defined(PETSC_HAVE_VA_COPY)
30514416c0eSBarry Smith   va_copy(Argpcopy, Argp);
3061531940fSBarry Smith #endif
3079566063dSJacob Faibussowitsch   PetscCall(PetscVSNPrintf(str, sizeof(str), format, &fullLength, Argp));
30814416c0eSBarry Smith   if (fullLength > sizeof(str)) {
3099566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(fullLength, &buff));
3101531940fSBarry Smith #if defined(PETSC_HAVE_VA_COPY)
3119566063dSJacob Faibussowitsch     PetscCall(PetscVSNPrintf(buff, fullLength, format, NULL, Argpcopy));
3121531940fSBarry Smith #else
3131531940fSBarry Smith     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "C89 does not support va_copy() hence cannot print long strings with PETSc printing routines");
3141531940fSBarry Smith #endif
31514416c0eSBarry Smith   }
3162f613bf5SBarry Smith   fprintf(fd, "%s", buff);
3175a058713SBarry Smith   fflush(fd);
31848a46eb9SPierre Jolivet   if (buff != str) PetscCall(PetscFree(buff));
3193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
320e5c89e4eSSatish Balay }
321e5c89e4eSSatish Balay 
3225b5bc046SBarry Smith /*@C
3235b5bc046SBarry Smith     PetscSNPrintf - Prints to a string of given length
3245b5bc046SBarry Smith 
3255b5bc046SBarry Smith     Not Collective
3265b5bc046SBarry Smith 
3275b5bc046SBarry Smith     Input Parameters:
3285b5bc046SBarry Smith +   str - the string to print to
329*058c9ee1SBarry Smith .   len - the length of `str`
330*058c9ee1SBarry Smith .   format - the usual `printf()` format string
33110699b91SBarry Smith -   ... - any arguments that are to be printed, each much have an appropriate symbol in the format argument
3325b5bc046SBarry Smith 
3335b5bc046SBarry Smith    Level: intermediate
3345b5bc046SBarry Smith 
335db781477SPatrick Sanan .seealso: `PetscSynchronizedFlush()`, `PetscSynchronizedFPrintf()`, `PetscFPrintf()`, `PetscVSNPrintf()`,
336db781477SPatrick Sanan           `PetscPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscVFPrintf()`
3375b5bc046SBarry Smith @*/
338d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSNPrintf(char *str, size_t len, const char format[], ...)
339d71ae5a4SJacob Faibussowitsch {
340c9a19010SBarry Smith   size_t  fullLength;
3415b5bc046SBarry Smith   va_list Argp;
3425b5bc046SBarry Smith 
3435b5bc046SBarry Smith   PetscFunctionBegin;
3445b5bc046SBarry Smith   va_start(Argp, format);
3459566063dSJacob Faibussowitsch   PetscCall(PetscVSNPrintf(str, len, format, &fullLength, Argp));
3463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3475b5bc046SBarry Smith }
3485b5bc046SBarry Smith 
349257d2499SJed Brown /*@C
350*058c9ee1SBarry Smith     PetscSNPrintfCount - Prints to a string of given length, returns count of characters printed
351257d2499SJed Brown 
352257d2499SJed Brown     Not Collective
353257d2499SJed Brown 
354257d2499SJed Brown     Input Parameters:
355257d2499SJed Brown +   str - the string to print to
356*058c9ee1SBarry Smith .   len - the length of `str`
357*058c9ee1SBarry Smith .   format - the usual `printf()` format string
35810699b91SBarry Smith -   ... - any arguments that are to be printed, each much have an appropriate symbol in the format argument
359257d2499SJed Brown 
360cb398dd3SBarry Smith     Output Parameter:
361*058c9ee1SBarry Smith .   countused - number of characters printed
362cb398dd3SBarry Smith 
363257d2499SJed Brown    Level: intermediate
364257d2499SJed Brown 
365db781477SPatrick Sanan .seealso: `PetscSynchronizedFlush()`, `PetscSynchronizedFPrintf()`, `PetscFPrintf()`, `PetscVSNPrintf()`,
366db781477SPatrick Sanan           `PetscPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscSNPrintf()`, `PetscVFPrintf()`
367257d2499SJed Brown @*/
368d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSNPrintfCount(char *str, size_t len, const char format[], size_t *countused, ...)
369d71ae5a4SJacob Faibussowitsch {
370257d2499SJed Brown   va_list Argp;
371257d2499SJed Brown 
372257d2499SJed Brown   PetscFunctionBegin;
373257d2499SJed Brown   va_start(Argp, countused);
3749566063dSJacob Faibussowitsch   PetscCall(PetscVSNPrintf(str, len, format, countused, Argp));
3753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
376257d2499SJed Brown }
377257d2499SJed Brown 
378e5c89e4eSSatish Balay /* ----------------------------------------------------------------------- */
379e5c89e4eSSatish Balay 
38002c9f0b5SLisandro Dalcin PrintfQueue petsc_printfqueue = NULL, petsc_printfqueuebase = NULL;
381d30b0576SJed Brown int         petsc_printfqueuelength = 0;
382e5c89e4eSSatish Balay 
383e5c89e4eSSatish Balay /*@C
384e5c89e4eSSatish Balay     PetscSynchronizedPrintf - Prints synchronized output from several processors.
385e5c89e4eSSatish Balay     Output of the first processor is followed by that of the second, etc.
386e5c89e4eSSatish Balay 
387e5c89e4eSSatish Balay     Not Collective
388e5c89e4eSSatish Balay 
389e5c89e4eSSatish Balay     Input Parameters:
390*058c9ee1SBarry Smith +   comm - the MPI communicator
391e5c89e4eSSatish Balay -   format - the usual printf() format string
392e5c89e4eSSatish Balay 
393e5c89e4eSSatish Balay    Level: intermediate
394e5c89e4eSSatish Balay 
395811af0c4SBarry Smith     Note:
396811af0c4SBarry Smith     REQUIRES a call to `PetscSynchronizedFlush()` by all the processes after the completion of the calls to `PetscSynchronizedPrintf()` for the information
397e5c89e4eSSatish Balay     from all the processors to be printed.
398e5c89e4eSSatish Balay 
399e5c89e4eSSatish Balay     Fortran Note:
400*058c9ee1SBarry Smith     The call sequence is `PetscSynchronizedPrintf`(`MPI_Comm`, `character`(*), `PetscErrorCode` ierr).
401e5c89e4eSSatish Balay     That is, you can only pass a single character string from Fortran.
402e5c89e4eSSatish Balay 
403db781477SPatrick Sanan .seealso: `PetscSynchronizedFlush()`, `PetscSynchronizedFPrintf()`, `PetscFPrintf()`,
404db781477SPatrick Sanan           `PetscPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIISynchronizedPrintf()`
405e5c89e4eSSatish Balay @*/
406d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSynchronizedPrintf(MPI_Comm comm, const char format[], ...)
407d71ae5a4SJacob Faibussowitsch {
408e5c89e4eSSatish Balay   PetscMPIInt rank;
409e5c89e4eSSatish Balay 
410e5c89e4eSSatish Balay   PetscFunctionBegin;
41108401ef6SPierre Jolivet   PetscCheck(comm != MPI_COMM_NULL, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Called with MPI_COMM_NULL, likely PetscObjectComm() failed");
4129566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
413e5c89e4eSSatish Balay 
414e5c89e4eSSatish Balay   /* First processor prints immediately to stdout */
415dd400576SPatrick Sanan   if (rank == 0) {
416e5c89e4eSSatish Balay     va_list Argp;
417e5c89e4eSSatish Balay     va_start(Argp, format);
4189566063dSJacob Faibussowitsch     PetscCall((*PetscVFPrintf)(PETSC_STDOUT, format, Argp));
419e5c89e4eSSatish Balay     if (petsc_history) {
420cdc7d174SSatish Balay       va_start(Argp, format);
4219566063dSJacob Faibussowitsch       PetscCall((*PetscVFPrintf)(petsc_history, format, Argp));
422e5c89e4eSSatish Balay     }
423e5c89e4eSSatish Balay     va_end(Argp);
424e5c89e4eSSatish Balay   } else { /* other processors add to local queue */
425e5c89e4eSSatish Balay     va_list     Argp;
426e5c89e4eSSatish Balay     PrintfQueue next;
42714416c0eSBarry Smith     size_t      fullLength = PETSCDEFAULTBUFFERSIZE;
428e5c89e4eSSatish Balay 
4299566063dSJacob Faibussowitsch     PetscCall(PetscNew(&next));
430a297a907SKarl Rupp     if (petsc_printfqueue) {
431a297a907SKarl Rupp       petsc_printfqueue->next = next;
432a297a907SKarl Rupp       petsc_printfqueue       = next;
43302c9f0b5SLisandro Dalcin       petsc_printfqueue->next = NULL;
434a297a907SKarl Rupp     } else petsc_printfqueuebase = petsc_printfqueue = next;
435d30b0576SJed Brown     petsc_printfqueuelength++;
43694217ebdSBarry Smith     next->size   = 0;
43714416c0eSBarry Smith     next->string = NULL;
43894217ebdSBarry Smith     while (fullLength >= next->size) {
4392d609e63SMatthew Knepley       next->size = fullLength + 1;
4409566063dSJacob Faibussowitsch       PetscCall(PetscFree(next->string));
4419566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(next->size, &next->string));
442e5c89e4eSSatish Balay       va_start(Argp, format);
4439566063dSJacob Faibussowitsch       PetscCall(PetscArrayzero(next->string, next->size));
4449566063dSJacob Faibussowitsch       PetscCall(PetscVSNPrintf(next->string, next->size, format, &fullLength, Argp));
445e5c89e4eSSatish Balay       va_end(Argp);
446e5c89e4eSSatish Balay     }
4472d609e63SMatthew Knepley   }
4483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
449e5c89e4eSSatish Balay }
450e5c89e4eSSatish Balay 
451e5c89e4eSSatish Balay /*@C
452e5c89e4eSSatish Balay     PetscSynchronizedFPrintf - Prints synchronized output to the specified file from
453e5c89e4eSSatish Balay     several processors.  Output of the first processor is followed by that of the
454e5c89e4eSSatish Balay     second, etc.
455e5c89e4eSSatish Balay 
456e5c89e4eSSatish Balay     Not Collective
457e5c89e4eSSatish Balay 
458e5c89e4eSSatish Balay     Input Parameters:
459*058c9ee1SBarry Smith +   comm - the MPI communicator
460e5c89e4eSSatish Balay .   fd - the file pointer
461e5c89e4eSSatish Balay -   format - the usual printf() format string
462e5c89e4eSSatish Balay 
463e5c89e4eSSatish Balay     Level: intermediate
464e5c89e4eSSatish Balay 
465811af0c4SBarry Smith     Note:
466811af0c4SBarry Smith     REQUIRES a intervening call to `PetscSynchronizedFlush()` for the information
467e5c89e4eSSatish Balay     from all the processors to be printed.
468e5c89e4eSSatish Balay 
469db781477SPatrick Sanan .seealso: `PetscSynchronizedPrintf()`, `PetscSynchronizedFlush()`, `PetscFPrintf()`,
470db781477SPatrick Sanan           `PetscFOpen()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIPrintf()`
471e5c89e4eSSatish Balay @*/
472d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSynchronizedFPrintf(MPI_Comm comm, FILE *fp, const char format[], ...)
473d71ae5a4SJacob Faibussowitsch {
474e5c89e4eSSatish Balay   PetscMPIInt rank;
475e5c89e4eSSatish Balay 
476e5c89e4eSSatish Balay   PetscFunctionBegin;
47708401ef6SPierre Jolivet   PetscCheck(comm != MPI_COMM_NULL, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Called with MPI_COMM_NULL, likely PetscObjectComm() failed");
4789566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
479e5c89e4eSSatish Balay 
480e5c89e4eSSatish Balay   /* First processor prints immediately to fp */
481dd400576SPatrick Sanan   if (rank == 0) {
482e5c89e4eSSatish Balay     va_list Argp;
483e5c89e4eSSatish Balay     va_start(Argp, format);
4849566063dSJacob Faibussowitsch     PetscCall((*PetscVFPrintf)(fp, format, Argp));
485cdc7d174SSatish Balay     if (petsc_history && (fp != petsc_history)) {
486cdc7d174SSatish Balay       va_start(Argp, format);
4879566063dSJacob Faibussowitsch       PetscCall((*PetscVFPrintf)(petsc_history, format, Argp));
488e5c89e4eSSatish Balay     }
489e5c89e4eSSatish Balay     va_end(Argp);
490e5c89e4eSSatish Balay   } else { /* other processors add to local queue */
491e5c89e4eSSatish Balay     va_list     Argp;
492e5c89e4eSSatish Balay     PrintfQueue next;
49314416c0eSBarry Smith     size_t      fullLength = PETSCDEFAULTBUFFERSIZE;
49414416c0eSBarry Smith 
4959566063dSJacob Faibussowitsch     PetscCall(PetscNew(&next));
496a297a907SKarl Rupp     if (petsc_printfqueue) {
497a297a907SKarl Rupp       petsc_printfqueue->next = next;
498a297a907SKarl Rupp       petsc_printfqueue       = next;
49902c9f0b5SLisandro Dalcin       petsc_printfqueue->next = NULL;
500a297a907SKarl Rupp     } else petsc_printfqueuebase = petsc_printfqueue = next;
501d30b0576SJed Brown     petsc_printfqueuelength++;
50294217ebdSBarry Smith     next->size   = 0;
50314416c0eSBarry Smith     next->string = NULL;
50494217ebdSBarry Smith     while (fullLength >= next->size) {
5052d609e63SMatthew Knepley       next->size = fullLength + 1;
5069566063dSJacob Faibussowitsch       PetscCall(PetscFree(next->string));
5079566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(next->size, &next->string));
508e5c89e4eSSatish Balay       va_start(Argp, format);
5099566063dSJacob Faibussowitsch       PetscCall(PetscArrayzero(next->string, next->size));
5109566063dSJacob Faibussowitsch       PetscCall(PetscVSNPrintf(next->string, next->size, format, &fullLength, Argp));
511e5c89e4eSSatish Balay       va_end(Argp);
512e5c89e4eSSatish Balay     }
5132d609e63SMatthew Knepley   }
5143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
515e5c89e4eSSatish Balay }
516e5c89e4eSSatish Balay 
5170ec8b6e3SBarry Smith /*@C
518e5c89e4eSSatish Balay     PetscSynchronizedFlush - Flushes to the screen output from all processors
519811af0c4SBarry Smith     involved in previous `PetscSynchronizedPrintf()`/`PetscSynchronizedFPrintf()` calls.
520e5c89e4eSSatish Balay 
521d083f849SBarry Smith     Collective
522e5c89e4eSSatish Balay 
523e5c89e4eSSatish Balay     Input Parameters:
524*058c9ee1SBarry Smith +   comm - the MPI communicator
5250ec8b6e3SBarry Smith -   fd - the file pointer (valid on process 0 of the communicator)
526e5c89e4eSSatish Balay 
527e5c89e4eSSatish Balay     Level: intermediate
528e5c89e4eSSatish Balay 
529811af0c4SBarry Smith     Note:
530811af0c4SBarry Smith     If `PetscSynchronizedPrintf()` and/or `PetscSynchronizedFPrintf()` are called with
531811af0c4SBarry Smith     different MPI communicators there must be an intervening call to `PetscSynchronizedFlush()` between the calls with different MPI communicators.
532e5c89e4eSSatish Balay 
533811af0c4SBarry Smith     Fortran Note:
534811af0c4SBarry Smith     Pass `PETSC_STDOUT` if the flush is for standard out; otherwise pass a value obtained from `PetscFOpen()`
535e50bf69fSBarry Smith 
536db781477SPatrick Sanan .seealso: `PetscSynchronizedPrintf()`, `PetscFPrintf()`, `PetscPrintf()`, `PetscViewerASCIIPrintf()`,
537db781477SPatrick Sanan           `PetscViewerASCIISynchronizedPrintf()`
5380087d953SMatthew G. Knepley @*/
539d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSynchronizedFlush(MPI_Comm comm, FILE *fd)
540d71ae5a4SJacob Faibussowitsch {
54129a5cbdcSMatthew G. Knepley   PetscMPIInt rank, size, tag, i, j, n = 0, dummy = 0;
5422d609e63SMatthew Knepley   char       *message;
543e5c89e4eSSatish Balay   MPI_Status  status;
544e5c89e4eSSatish Balay 
545e5c89e4eSSatish Balay   PetscFunctionBegin;
5469566063dSJacob Faibussowitsch   PetscCall(PetscCommDuplicate(comm, &comm, &tag));
5479566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
5489566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
549e5c89e4eSSatish Balay 
550e5c89e4eSSatish Balay   /* First processor waits for messages from all other processors */
551dd400576SPatrick Sanan   if (rank == 0) {
5520ec8b6e3SBarry Smith     if (!fd) fd = PETSC_STDOUT;
553e5c89e4eSSatish Balay     for (i = 1; i < size; i++) {
5549f73f8ecSBarry Smith       /* to prevent a flood of messages to process zero, request each message separately */
5559566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Send(&dummy, 1, MPI_INT, i, tag, comm));
5569566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Recv(&n, 1, MPI_INT, i, tag, comm, &status));
557e5c89e4eSSatish Balay       for (j = 0; j < n; j++) {
55829a5cbdcSMatthew G. Knepley         PetscMPIInt size = 0;
5592d609e63SMatthew Knepley 
5609566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Recv(&size, 1, MPI_INT, i, tag, comm, &status));
5619566063dSJacob Faibussowitsch         PetscCall(PetscMalloc1(size, &message));
5629566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Recv(message, size, MPI_CHAR, i, tag, comm, &status));
5639566063dSJacob Faibussowitsch         PetscCall(PetscFPrintf(comm, fd, "%s", message));
5649566063dSJacob Faibussowitsch         PetscCall(PetscFree(message));
565e5c89e4eSSatish Balay       }
566e5c89e4eSSatish Balay     }
567e5c89e4eSSatish Balay   } else { /* other processors send queue to processor 0 */
568d30b0576SJed Brown     PrintfQueue next = petsc_printfqueuebase, previous;
569e5c89e4eSSatish Balay 
5709566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Recv(&dummy, 1, MPI_INT, 0, tag, comm, &status));
5719566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Send(&petsc_printfqueuelength, 1, MPI_INT, 0, tag, comm));
572d30b0576SJed Brown     for (i = 0; i < petsc_printfqueuelength; i++) {
5739566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Send(&next->size, 1, MPI_INT, 0, tag, comm));
5749566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Send(next->string, next->size, MPI_CHAR, 0, tag, comm));
575e5c89e4eSSatish Balay       previous = next;
576e5c89e4eSSatish Balay       next     = next->next;
5779566063dSJacob Faibussowitsch       PetscCall(PetscFree(previous->string));
5789566063dSJacob Faibussowitsch       PetscCall(PetscFree(previous));
579e5c89e4eSSatish Balay     }
58002c9f0b5SLisandro Dalcin     petsc_printfqueue       = NULL;
581d30b0576SJed Brown     petsc_printfqueuelength = 0;
582e5c89e4eSSatish Balay   }
5839566063dSJacob Faibussowitsch   PetscCall(PetscCommDestroy(&comm));
5843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
585e5c89e4eSSatish Balay }
586e5c89e4eSSatish Balay 
587e5c89e4eSSatish Balay /* ---------------------------------------------------------------------------------------*/
588e5c89e4eSSatish Balay 
589e5c89e4eSSatish Balay /*@C
590e5c89e4eSSatish Balay     PetscFPrintf - Prints to a file, only from the first
591e5c89e4eSSatish Balay     processor in the communicator.
592e5c89e4eSSatish Balay 
593cf53795eSBarry Smith     Not Collective; No Fortran Support
594e5c89e4eSSatish Balay 
595e5c89e4eSSatish Balay     Input Parameters:
596*058c9ee1SBarry Smith +   comm - the MPI communicator
597e5c89e4eSSatish Balay .   fd - the file pointer
598e5c89e4eSSatish Balay -   format - the usual printf() format string
599e5c89e4eSSatish Balay 
600e5c89e4eSSatish Balay     Level: intermediate
601e5c89e4eSSatish Balay 
602*058c9ee1SBarry Smith     Developer Note:
603*058c9ee1SBarry Smith     This maybe, and is, called from PETSc error handlers and `PetscMallocValidate()` hence it does not use `PetscCallMPI()` which
604*058c9ee1SBarry Smith     could recursively restart the malloc validation.
605*058c9ee1SBarry Smith 
606db781477SPatrick Sanan .seealso: `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
607db781477SPatrick Sanan           `PetscViewerASCIISynchronizedPrintf()`, `PetscSynchronizedFlush()`
608e5c89e4eSSatish Balay @*/
609d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFPrintf(MPI_Comm comm, FILE *fd, const char format[], ...)
610d71ae5a4SJacob Faibussowitsch {
611e5c89e4eSSatish Balay   PetscMPIInt rank;
612e5c89e4eSSatish Balay 
613e5c89e4eSSatish Balay   PetscFunctionBegin;
61408401ef6SPierre Jolivet   PetscCheck(comm != MPI_COMM_NULL, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Called with MPI_COMM_NULL, likely PetscObjectComm() failed");
6159566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
616dd400576SPatrick Sanan   if (rank == 0) {
617e5c89e4eSSatish Balay     va_list Argp;
618e5c89e4eSSatish Balay     va_start(Argp, format);
6199566063dSJacob Faibussowitsch     PetscCall((*PetscVFPrintf)(fd, format, Argp));
620cdc7d174SSatish Balay     if (petsc_history && (fd != petsc_history)) {
621cdc7d174SSatish Balay       va_start(Argp, format);
6229566063dSJacob Faibussowitsch       PetscCall((*PetscVFPrintf)(petsc_history, format, Argp));
623e5c89e4eSSatish Balay     }
624e5c89e4eSSatish Balay     va_end(Argp);
625e5c89e4eSSatish Balay   }
6263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
627e5c89e4eSSatish Balay }
628e5c89e4eSSatish Balay 
629e5c89e4eSSatish Balay /*@C
630e5c89e4eSSatish Balay     PetscPrintf - Prints to standard out, only from the first
631eed5747fSBarry Smith     processor in the communicator. Calls from other processes are ignored.
632e5c89e4eSSatish Balay 
633e5c89e4eSSatish Balay     Not Collective
634e5c89e4eSSatish Balay 
635e5c89e4eSSatish Balay     Input Parameters:
636e5c89e4eSSatish Balay +   comm - the communicator
637e5c89e4eSSatish Balay -   format - the usual printf() format string
638e5c89e4eSSatish Balay 
639e5c89e4eSSatish Balay     Level: intermediate
640e5c89e4eSSatish Balay 
641811af0c4SBarry Smith     Note:
642811af0c4SBarry Smith     Deprecated information: `PetscPrintf()` supports some format specifiers that are unique to PETSc.
643811af0c4SBarry Smith     See the manual page for `PetscFormatConvert()` for details.
644b2706f25SRichard Tran Mills 
645e5c89e4eSSatish Balay     Fortran Note:
646811af0c4SBarry Smith     The call sequence is `PetscPrintf`(MPI_Comm, character(*), `PetscErrorCode` ierr) from Fortran.
647e5c89e4eSSatish Balay     That is, you can only pass a single character string from Fortran.
648e5c89e4eSSatish Balay 
649db781477SPatrick Sanan .seealso: `PetscFPrintf()`, `PetscSynchronizedPrintf()`, `PetscFormatConvert()`
650e5c89e4eSSatish Balay @*/
651d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscPrintf(MPI_Comm comm, const char format[], ...)
652d71ae5a4SJacob Faibussowitsch {
653e5c89e4eSSatish Balay   PetscMPIInt rank;
654e5c89e4eSSatish Balay 
655e5c89e4eSSatish Balay   PetscFunctionBegin;
65608401ef6SPierre Jolivet   PetscCheck(comm != MPI_COMM_NULL, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Called with MPI_COMM_NULL, likely PetscObjectComm() failed");
6579566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
658dd400576SPatrick Sanan   if (rank == 0) {
659e5c89e4eSSatish Balay     va_list Argp;
660e5c89e4eSSatish Balay     va_start(Argp, format);
6619566063dSJacob Faibussowitsch     PetscCall((*PetscVFPrintf)(PETSC_STDOUT, format, Argp));
662e5c89e4eSSatish Balay     if (petsc_history) {
663cdc7d174SSatish Balay       va_start(Argp, format);
6649566063dSJacob Faibussowitsch       PetscCall((*PetscVFPrintf)(petsc_history, format, Argp));
665e5c89e4eSSatish Balay     }
666e5c89e4eSSatish Balay     va_end(Argp);
667e5c89e4eSSatish Balay   }
6683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
669e5c89e4eSSatish Balay }
670e5c89e4eSSatish Balay 
671d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscHelpPrintfDefault(MPI_Comm comm, const char format[], ...)
672d71ae5a4SJacob Faibussowitsch {
673e5c89e4eSSatish Balay   PetscMPIInt rank;
674e5c89e4eSSatish Balay 
675e5c89e4eSSatish Balay   PetscFunctionBegin;
67608401ef6SPierre Jolivet   PetscCheck(comm != MPI_COMM_NULL, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Called with MPI_COMM_NULL, likely PetscObjectComm() failed");
6779566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
678dd400576SPatrick Sanan   if (rank == 0) {
679e5c89e4eSSatish Balay     va_list Argp;
680e5c89e4eSSatish Balay     va_start(Argp, format);
6819566063dSJacob Faibussowitsch     PetscCall((*PetscVFPrintf)(PETSC_STDOUT, format, Argp));
682e5c89e4eSSatish Balay     if (petsc_history) {
683cdc7d174SSatish Balay       va_start(Argp, format);
6849566063dSJacob Faibussowitsch       PetscCall((*PetscVFPrintf)(petsc_history, format, Argp));
685e5c89e4eSSatish Balay     }
686e5c89e4eSSatish Balay     va_end(Argp);
687e5c89e4eSSatish Balay   }
6883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
689e5c89e4eSSatish Balay }
690e5c89e4eSSatish Balay 
691e5c89e4eSSatish Balay /* ---------------------------------------------------------------------------------------*/
692e5c89e4eSSatish Balay 
693e5c89e4eSSatish Balay /*@C
694e5c89e4eSSatish Balay     PetscSynchronizedFGets - Several processors all get the same line from a file.
695e5c89e4eSSatish Balay 
696d083f849SBarry Smith     Collective
697e5c89e4eSSatish Balay 
698e5c89e4eSSatish Balay     Input Parameters:
699e5c89e4eSSatish Balay +   comm - the communicator
700e5c89e4eSSatish Balay .   fd - the file pointer
701e5c89e4eSSatish Balay -   len - the length of the output buffer
702e5c89e4eSSatish Balay 
703e5c89e4eSSatish Balay     Output Parameter:
704e31d4fa4SJed Brown .   string - the line read from the file, at end of file string[0] == 0
705e5c89e4eSSatish Balay 
706e5c89e4eSSatish Balay     Level: intermediate
707e5c89e4eSSatish Balay 
708db781477SPatrick Sanan .seealso: `PetscSynchronizedPrintf()`, `PetscSynchronizedFlush()`,
709db781477SPatrick Sanan           `PetscFOpen()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIPrintf()`
710e5c89e4eSSatish Balay @*/
711d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSynchronizedFGets(MPI_Comm comm, FILE *fp, size_t len, char string[])
712d71ae5a4SJacob Faibussowitsch {
713e5c89e4eSSatish Balay   PetscMPIInt rank;
714e5c89e4eSSatish Balay 
715e5c89e4eSSatish Balay   PetscFunctionBegin;
7169566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
717e5c89e4eSSatish Balay 
718dd400576SPatrick Sanan   if (rank == 0) {
719047b9c12SMatthew G Knepley     char *ptr = fgets(string, len, fp);
720047b9c12SMatthew G Knepley 
721047b9c12SMatthew G Knepley     if (!ptr) {
722e31d4fa4SJed Brown       string[0] = 0;
72308401ef6SPierre Jolivet       PetscCheck(feof(fp), PETSC_COMM_SELF, PETSC_ERR_FILE_READ, "Error reading from file: %d", errno);
724047b9c12SMatthew G Knepley     }
725e5c89e4eSSatish Balay   }
7269566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Bcast(string, len, MPI_BYTE, 0, comm));
7273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
728e5c89e4eSSatish Balay }
729238ccf28SShri Abhyankar 
7308c74ee41SBarry Smith /*@C
7318c74ee41SBarry Smith      PetscFormatStrip - Takes a PETSc format string and removes all numerical modifiers to % operations
7328c74ee41SBarry Smith 
7338c74ee41SBarry Smith    Input Parameters:
7348c74ee41SBarry Smith .   format - the PETSc format string
7358c74ee41SBarry Smith 
7368c74ee41SBarry Smith  Level: developer
7378c74ee41SBarry Smith 
7388c74ee41SBarry Smith @*/
739d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFormatStrip(char *format)
740d71ae5a4SJacob Faibussowitsch {
7418c74ee41SBarry Smith   size_t loc1 = 0, loc2 = 0;
7428c74ee41SBarry Smith 
7438c74ee41SBarry Smith   PetscFunctionBegin;
7448c74ee41SBarry Smith   while (format[loc2]) {
7458c74ee41SBarry Smith     if (format[loc2] == '%') {
7468c74ee41SBarry Smith       format[loc1++] = format[loc2++];
7478c74ee41SBarry Smith       while (format[loc2] && ((format[loc2] >= '0' && format[loc2] <= '9') || format[loc2] == '.')) loc2++;
7488c74ee41SBarry Smith     }
7498c74ee41SBarry Smith     format[loc1++] = format[loc2++];
7508c74ee41SBarry Smith   }
7513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7528c74ee41SBarry Smith }
7538c74ee41SBarry Smith 
754d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFormatRealArray(char buf[], size_t len, const char *fmt, PetscInt n, const PetscReal x[])
755d71ae5a4SJacob Faibussowitsch {
7561b5687a1SBarry Smith   PetscInt i;
7571b5687a1SBarry Smith   size_t   left, count;
7581b5687a1SBarry Smith   char    *p;
7591b5687a1SBarry Smith 
7601b5687a1SBarry Smith   PetscFunctionBegin;
7611b5687a1SBarry Smith   for (i = 0, p = buf, left = len; i < n; i++) {
7629566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintfCount(p, left, fmt, &count, (double)x[i]));
76308401ef6SPierre Jolivet     PetscCheck(count < left, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Insufficient space in buffer");
7641b5687a1SBarry Smith     left -= count;
7651b5687a1SBarry Smith     p += count - 1;
7661b5687a1SBarry Smith     *p++ = ' ';
7671b5687a1SBarry Smith   }
7681b5687a1SBarry Smith   p[i ? 0 : -1] = 0;
7693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7701b5687a1SBarry Smith }
771