xref: /petsc/src/sys/fileio/mprint.c (revision aec76313382a76d73a95f2051cbe4b1eab55c1c7)
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;
453ca90d2dSJacob Faibussowitsch   PetscValidCharPointer(format, 1);
463ca90d2dSJacob Faibussowitsch   PetscValidPointer(size, 2);
47d781fa04SBarry Smith   while (format[i]) {
483ca90d2dSJacob Faibussowitsch     if (format[i] == '%') {
493ca90d2dSJacob Faibussowitsch       if (format[i + 1] == '%') {
503ca90d2dSJacob Faibussowitsch         i += 2;
513ca90d2dSJacob Faibussowitsch         sz += 2;
523ca90d2dSJacob Faibussowitsch         continue;
533ca90d2dSJacob Faibussowitsch       }
54d781fa04SBarry Smith       /* Find the letter */
559371c9d4SSatish Balay       while (format[i] && (format[i] <= '9')) {
569371c9d4SSatish Balay         ++i;
579371c9d4SSatish Balay         ++sz;
589371c9d4SSatish Balay       }
59d781fa04SBarry Smith       switch (format[i]) {
603ca90d2dSJacob Faibussowitsch #if PetscDefined(USE_64BIT_INDICES)
61d71ae5a4SJacob Faibussowitsch       case 'D':
62d71ae5a4SJacob Faibussowitsch         sz += 2;
63d71ae5a4SJacob Faibussowitsch         break;
64d781fa04SBarry Smith #endif
65d71ae5a4SJacob Faibussowitsch       case 'g':
66d71ae5a4SJacob Faibussowitsch         sz += 4;
67d71ae5a4SJacob Faibussowitsch       default:
68d71ae5a4SJacob Faibussowitsch         break;
69d781fa04SBarry Smith       }
70d781fa04SBarry Smith     }
713ca90d2dSJacob Faibussowitsch     ++i;
723ca90d2dSJacob Faibussowitsch     ++sz;
73d781fa04SBarry Smith   }
743ca90d2dSJacob Faibussowitsch   *size = sz + 1; /* space for NULL character */
753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
76d781fa04SBarry Smith }
77d781fa04SBarry Smith 
78d781fa04SBarry Smith /*@C
79058c9ee1SBarry Smith   PetscFormatConvert - converts %g to [|%g|] so that `PetscVSNPrintf()` can ensure all %g formatted numbers have a decimal point when printed. The
80058c9ee1SBarry Smith   decimal point is then used by the `petscdiff` script so that differences in floating point number output is ignored in the test harness.
81d781fa04SBarry Smith 
82058c9ee1SBarry Smith   No Fortran Support
83811af0c4SBarry Smith 
84d781fa04SBarry Smith   Input Parameters:
85d781fa04SBarry Smith + format - the PETSc format string
86811af0c4SBarry Smith -   size - the length of newformat, you can use `PetscFormatConvertGetSize()` to compute the needed size
87d781fa04SBarry Smith 
8821532e8aSBarry Smith   Output Parameter:
8921532e8aSBarry Smith . newformat - the new format
9021532e8aSBarry Smith 
91d781fa04SBarry Smith   Level: developer
92d781fa04SBarry Smith 
93058c9ee1SBarry Smith   Note:
947de69702SBarry Smith   Deprecated usage also converts the `%D` to `%d` for 32-bit PETSc indices and to `%lld` for 64-bit PETSc indices. This feature is no
95058c9ee1SBarry Smith   longer used in PETSc code instead use %" PetscInt_FMT " in the format string
96058c9ee1SBarry Smith 
97db781477SPatrick Sanan .seealso: `PetscFormatConvertGetSize()`, `PetscVSNPrintf()`, `PetscVFPrintf()`
98d781fa04SBarry Smith @*/
99d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFormatConvert(const char *format, char *newformat)
100d71ae5a4SJacob Faibussowitsch {
101e5c89e4eSSatish Balay   PetscInt i = 0, j = 0;
102e5c89e4eSSatish Balay 
103eed5747fSBarry Smith   PetscFunctionBegin;
104d781fa04SBarry Smith   while (format[i]) {
1052a1ad9caSBarry Smith     if (format[i] == '%' && format[i + 1] == '%') {
1062a1ad9caSBarry Smith       newformat[j++] = format[i++];
1072a1ad9caSBarry Smith       newformat[j++] = format[i++];
1082a1ad9caSBarry Smith     } else if (format[i] == '%') {
1098627564fSBarry Smith       if (format[i + 1] == 'g') {
1108627564fSBarry Smith         newformat[j++] = '[';
1118627564fSBarry Smith         newformat[j++] = '|';
1128627564fSBarry Smith       }
1137bc47156SJose Roman       /* Find the letter */
1147bc47156SJose Roman       for (; format[i] && format[i] <= '9'; i++) newformat[j++] = format[i];
1157bc47156SJose Roman       switch (format[i]) {
1167bc47156SJose Roman       case 'D':
1176de02169SBarry Smith #if !defined(PETSC_USE_64BIT_INDICES)
118e5c89e4eSSatish Balay         newformat[j++] = 'd';
119e5c89e4eSSatish Balay #else
120e5c89e4eSSatish Balay         newformat[j++] = 'l';
121e5c89e4eSSatish Balay         newformat[j++] = 'l';
122e5c89e4eSSatish Balay         newformat[j++] = 'd';
123e5c89e4eSSatish Balay #endif
1247bc47156SJose Roman         break;
1258627564fSBarry Smith       case 'g':
1268627564fSBarry Smith         newformat[j++] = format[i];
1278627564fSBarry Smith         if (format[i - 1] == '%') {
1288627564fSBarry Smith           newformat[j++] = '|';
1298627564fSBarry Smith           newformat[j++] = ']';
1308627564fSBarry Smith         }
1318627564fSBarry Smith         break;
132d71ae5a4SJacob Faibussowitsch       case 'G':
133d71ae5a4SJacob Faibussowitsch         SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "%%G format is no longer supported, use %%g and cast the argument to double");
134d71ae5a4SJacob Faibussowitsch       case 'F':
135d71ae5a4SJacob Faibussowitsch         SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "%%F format is no longer supported, use %%f and cast the argument to double");
136d71ae5a4SJacob Faibussowitsch       default:
137d71ae5a4SJacob Faibussowitsch         newformat[j++] = format[i];
138d71ae5a4SJacob Faibussowitsch         break;
1397bc47156SJose Roman       }
1407bc47156SJose Roman       i++;
141a297a907SKarl Rupp     } else newformat[j++] = format[i++];
142e5c89e4eSSatish Balay   }
143e5c89e4eSSatish Balay   newformat[j] = 0;
1443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
145e5c89e4eSSatish Balay }
146e5c89e4eSSatish Balay 
14714416c0eSBarry Smith #define PETSCDEFAULTBUFFERSIZE 8 * 1024
148d781fa04SBarry Smith 
149c9a19010SBarry Smith /*@C
1506026c97aSBarry Smith   PetscVSNPrintf - The PETSc version of `vsnprintf()`. Ensures that all `%g` formatted arguments' output contains the decimal point (which
151058c9ee1SBarry Smith   is used by the test harness)
152c9a19010SBarry Smith 
153c9a19010SBarry Smith   Input Parameters:
154c9a19010SBarry Smith + str    - location to put result
15521532e8aSBarry Smith . len    - the length of `str`
15621532e8aSBarry Smith - format - the PETSc format string
15721532e8aSBarry Smith 
15821532e8aSBarry Smith   Output Parameter:
15921532e8aSBarry Smith . fullLength - the amount of space in `str` actually used.
160c9a19010SBarry Smith 
161c9a19010SBarry Smith   Level: developer
162c9a19010SBarry Smith 
163*aec76313SJacob Faibussowitsch   Developer Notes:
164058c9ee1SBarry Smith   This function may be called from an error handler, if an error occurs when it is called by the error handler than likely
165058c9ee1SBarry Smith   a recursion will occur resulting in a crash of the program.
166058c9ee1SBarry Smith 
16721532e8aSBarry Smith   If the length of the format string `format` is on the order of `PETSCDEFAULTBUFFERSIZE` (8 * 1024 bytes) or larger, this function will call `PetscMalloc()`
168058c9ee1SBarry Smith 
169058c9ee1SBarry Smith .seealso: `PetscFormatConvert()`, `PetscFormatConvertGetSize()`, `PetscVSNPrintf()`, `PetscErrorPrintf()`, `PetscVPrintf()`
170c9a19010SBarry Smith @*/
171d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscVSNPrintf(char *str, size_t len, const char *format, size_t *fullLength, va_list Argp)
172d71ae5a4SJacob Faibussowitsch {
173d781fa04SBarry Smith   char  *newformat = NULL;
17414416c0eSBarry Smith   char   formatbuf[PETSCDEFAULTBUFFERSIZE];
175d781fa04SBarry Smith   size_t newLength;
17614416c0eSBarry Smith   int    flen;
177e5c89e4eSSatish Balay 
178eed5747fSBarry Smith   PetscFunctionBegin;
1799566063dSJacob Faibussowitsch   PetscCall(PetscFormatConvertGetSize(format, &newLength));
18094217ebdSBarry Smith   if (newLength < sizeof(formatbuf)) {
181e2135aedSMatthew Knepley     newformat = formatbuf;
18294217ebdSBarry Smith     newLength = sizeof(formatbuf) - 1;
183e2135aedSMatthew Knepley   } else {
1849566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(newLength, &newformat));
185e2135aedSMatthew Knepley   }
1869566063dSJacob Faibussowitsch   PetscCall(PetscFormatConvert(format, newformat));
1877b9a2d1bSSatish Balay #if defined(PETSC_HAVE_VSNPRINTF)
188152b30f0SSatish Balay   flen = vsnprintf(str, len, newformat, Argp);
189e5c89e4eSSatish Balay #else
19089b07760SSatish Balay   #error "vsnprintf not found"
191e5c89e4eSSatish Balay #endif
19248a46eb9SPierre Jolivet   if (newLength > sizeof(formatbuf) - 1) PetscCall(PetscFree(newformat));
1938627564fSBarry Smith   {
1948627564fSBarry Smith     PetscBool foundedot;
1958627564fSBarry Smith     size_t    cnt = 0, ncnt = 0, leng;
1969566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(str, &leng));
19717ca8410SBarry Smith     if (leng > 4) {
1988627564fSBarry Smith       for (cnt = 0; cnt < leng - 4; cnt++) {
1998627564fSBarry Smith         if (str[cnt] == '[' && str[cnt + 1] == '|') {
200c540d043SBarry Smith           flen -= 4;
2019371c9d4SSatish Balay           cnt++;
2029371c9d4SSatish Balay           cnt++;
2038627564fSBarry Smith           foundedot = PETSC_FALSE;
2048627564fSBarry Smith           for (; cnt < leng - 1; cnt++) {
2058627564fSBarry Smith             if (str[cnt] == '|' && str[cnt + 1] == ']') {
2068627564fSBarry Smith               cnt++;
2078627564fSBarry Smith               if (!foundedot) str[ncnt++] = '.';
2088627564fSBarry Smith               ncnt--;
2098627564fSBarry Smith               break;
2108627564fSBarry Smith             } else {
2118627564fSBarry Smith               if (str[cnt] == 'e' || str[cnt] == '.') foundedot = PETSC_TRUE;
2128627564fSBarry Smith               str[ncnt++] = str[cnt];
2138627564fSBarry Smith             }
2148627564fSBarry Smith           }
2158627564fSBarry Smith         } else {
2168627564fSBarry Smith           str[ncnt] = str[cnt];
2178627564fSBarry Smith         }
2188627564fSBarry Smith         ncnt++;
2198627564fSBarry Smith       }
2208627564fSBarry Smith       while (cnt < leng) {
2219371c9d4SSatish Balay         str[ncnt] = str[cnt];
2229371c9d4SSatish Balay         ncnt++;
2239371c9d4SSatish Balay         cnt++;
2248627564fSBarry Smith       }
2258627564fSBarry Smith       str[ncnt] = 0;
2268627564fSBarry Smith     }
2278627564fSBarry Smith   }
228748e1b9dSBarry Smith #if defined(PETSC_HAVE_WINDOWS_H) && !defined(PETSC_HAVE__SET_OUTPUT_FORMAT)
229e51f71cfSBarry Smith   /* older Windows OS always produces e-+0np for floating point output; remove the extra 0 */
230748e1b9dSBarry Smith   {
231748e1b9dSBarry Smith     size_t cnt = 0, ncnt = 0, leng;
2329566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(str, &leng));
233748e1b9dSBarry Smith     if (leng > 5) {
234748e1b9dSBarry Smith       for (cnt = 0; cnt < leng - 4; cnt++) {
235e51f71cfSBarry Smith         if (str[cnt] == 'e' && (str[cnt + 1] == '-' || str[cnt + 1] == '+') && str[cnt + 2] == '0' && str[cnt + 3] >= '0' && str[cnt + 3] <= '9' && str[cnt + 4] >= '0' && str[cnt + 4] <= '9') {
2369371c9d4SSatish Balay           str[ncnt] = str[cnt];
2379371c9d4SSatish Balay           ncnt++;
2389371c9d4SSatish Balay           cnt++;
2399371c9d4SSatish Balay           str[ncnt] = str[cnt];
2409371c9d4SSatish Balay           ncnt++;
2419371c9d4SSatish Balay           cnt++;
2429371c9d4SSatish Balay           cnt++;
243e51f71cfSBarry Smith           str[ncnt] = str[cnt];
244748e1b9dSBarry Smith         } else {
245748e1b9dSBarry Smith           str[ncnt] = str[cnt];
246748e1b9dSBarry Smith         }
247748e1b9dSBarry Smith         ncnt++;
248748e1b9dSBarry Smith       }
249748e1b9dSBarry Smith       while (cnt < leng) {
2509371c9d4SSatish Balay         str[ncnt] = str[cnt];
2519371c9d4SSatish Balay         ncnt++;
2529371c9d4SSatish Balay         cnt++;
253748e1b9dSBarry Smith       }
254748e1b9dSBarry Smith       str[ncnt] = 0;
255748e1b9dSBarry Smith     }
256748e1b9dSBarry Smith   }
257748e1b9dSBarry Smith #endif
258c540d043SBarry Smith   if (fullLength) *fullLength = 1 + (size_t)flen;
2593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
260e5c89e4eSSatish Balay }
261e5c89e4eSSatish Balay 
262c9a19010SBarry Smith /*@C
263c69effb2SJacob Faibussowitsch   PetscFFlush - Flush a file stream
264c69effb2SJacob Faibussowitsch 
265c69effb2SJacob Faibussowitsch   Input Parameter:
266c69effb2SJacob Faibussowitsch . fd - The file stream handle
267c69effb2SJacob Faibussowitsch 
268c69effb2SJacob Faibussowitsch   Level: intermediate
269c69effb2SJacob Faibussowitsch 
270c69effb2SJacob Faibussowitsch   Notes:
271c69effb2SJacob Faibussowitsch   For output streams (and for update streams on which the last operation was output), writes
272c69effb2SJacob Faibussowitsch   any unwritten data from the stream's buffer to the associated output device.
273c69effb2SJacob Faibussowitsch 
274c69effb2SJacob Faibussowitsch   For input streams (and for update streams on which the last operation was input), the
275c69effb2SJacob Faibussowitsch   behavior is undefined.
276c69effb2SJacob Faibussowitsch 
277c69effb2SJacob Faibussowitsch   If `fd` is `NULL`, all open output streams are flushed, including ones not directly
278c69effb2SJacob Faibussowitsch   accessible to the program.
279c69effb2SJacob Faibussowitsch 
280c69effb2SJacob Faibussowitsch .seealso: `PetscPrintf()`, `PetscFPrintf()`, `PetscVFPrintf()`, `PetscVSNPrintf()`
281c69effb2SJacob Faibussowitsch @*/
282c69effb2SJacob Faibussowitsch PetscErrorCode PetscFFlush(FILE *fd)
283c69effb2SJacob Faibussowitsch {
284c69effb2SJacob Faibussowitsch   PetscFunctionBegin;
285c69effb2SJacob Faibussowitsch   if (fd) PetscValidPointer(fd, 1);
286c69effb2SJacob Faibussowitsch   // could also use PetscCallExternal() here, but since we can get additional error explanation
287c69effb2SJacob Faibussowitsch   // from strerror() we opted for a manual check
288bf31d2d3SBarry Smith   PetscCheck(0 == fflush(fd), PETSC_COMM_SELF, PETSC_ERR_FILE_WRITE, "Error in fflush() due to \"%s\"", strerror(errno));
289c69effb2SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
290c69effb2SJacob Faibussowitsch }
291c69effb2SJacob Faibussowitsch 
292c69effb2SJacob Faibussowitsch /*@C
293*aec76313SJacob Faibussowitsch   PetscVFPrintfDefault -  All PETSc standard out and error messages are sent through this function; so, in theory, this can
294e5c89e4eSSatish Balay   can be replaced with something that does not simply write to a file.
295e5c89e4eSSatish Balay 
296c9a19010SBarry Smith   To use, write your own function for example,
297058c9ee1SBarry Smith .vb
298058c9ee1SBarry Smith    PetscErrorCode mypetscvfprintf(FILE *fd, const char format[], va_list Argp)
299058c9ee1SBarry Smith    {
300058c9ee1SBarry Smith      PetscErrorCode ierr;
301058c9ee1SBarry Smith 
302058c9ee1SBarry Smith      PetscFunctionBegin;
303058c9ee1SBarry Smith       if (fd != stdout && fd != stderr) {  handle regular files
304058c9ee1SBarry Smith          CHKERR(PetscVFPrintfDefault(fd,format,Argp));
305058c9ee1SBarry Smith      } else {
306058c9ee1SBarry Smith         char   buff[BIG];
307058c9ee1SBarry Smith         size_t length;
308058c9ee1SBarry Smith         PetscCall(PetscVSNPrintf(buff,BIG,format,&length,Argp));
309058c9ee1SBarry Smith         now send buff to whatever stream or whatever you want
310058c9ee1SBarry Smith     }
311058c9ee1SBarry Smith     PetscFunctionReturn(PETSC_SUCCESS);
312058c9ee1SBarry Smith    }
313058c9ee1SBarry Smith .ve
314058c9ee1SBarry Smith   then before the call to `PetscInitialize()` do the assignment `PetscVFPrintf = mypetscvfprintf`;
315058c9ee1SBarry Smith 
316058c9ee1SBarry Smith   Level: developer
317c9a19010SBarry Smith 
318811af0c4SBarry Smith   Note:
31921532e8aSBarry Smith   For error messages this may be called by any MPI process, for regular standard out it is
32021532e8aSBarry Smith   called only by MPI rank 0 of a given communicator
321e5c89e4eSSatish Balay 
322*aec76313SJacob Faibussowitsch   Developer Notes:
323058c9ee1SBarry Smith   This could be called by an error handler, if that happens then a recursion of the error handler may occur
324058c9ee1SBarry Smith   and a resulting crash
325c9a19010SBarry Smith 
326c69effb2SJacob Faibussowitsch .seealso: `PetscVSNPrintf()`, `PetscErrorPrintf()`, `PetscFFlush()`
327c9a19010SBarry Smith @*/
328d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscVFPrintfDefault(FILE *fd, const char *format, va_list Argp)
329d71ae5a4SJacob Faibussowitsch {
33014416c0eSBarry Smith   char   str[PETSCDEFAULTBUFFERSIZE];
33114416c0eSBarry Smith   char  *buff = str;
33214416c0eSBarry Smith   size_t fullLength;
3331531940fSBarry Smith #if defined(PETSC_HAVE_VA_COPY)
33414416c0eSBarry Smith   va_list Argpcopy;
3351531940fSBarry Smith #endif
3361179db26SBarry Smith 
337eed5747fSBarry Smith   PetscFunctionBegin;
3381531940fSBarry Smith #if defined(PETSC_HAVE_VA_COPY)
33914416c0eSBarry Smith   va_copy(Argpcopy, Argp);
3401531940fSBarry Smith #endif
3419566063dSJacob Faibussowitsch   PetscCall(PetscVSNPrintf(str, sizeof(str), format, &fullLength, Argp));
34214416c0eSBarry Smith   if (fullLength > sizeof(str)) {
3439566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(fullLength, &buff));
3441531940fSBarry Smith #if defined(PETSC_HAVE_VA_COPY)
3459566063dSJacob Faibussowitsch     PetscCall(PetscVSNPrintf(buff, fullLength, format, NULL, Argpcopy));
3461531940fSBarry Smith #else
3471531940fSBarry Smith     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "C89 does not support va_copy() hence cannot print long strings with PETSc printing routines");
3481531940fSBarry Smith #endif
34914416c0eSBarry Smith   }
350eae3dc7dSJacob Faibussowitsch #if defined(PETSC_HAVE_VA_COPY)
351eae3dc7dSJacob Faibussowitsch   va_end(Argpcopy);
352eae3dc7dSJacob Faibussowitsch #endif
353c69effb2SJacob Faibussowitsch   {
354c69effb2SJacob Faibussowitsch     const int err = fprintf(fd, "%s", buff);
355c69effb2SJacob Faibussowitsch     // cannot use PetscCallExternal() for fprintf since the return value is "number of
356c69effb2SJacob Faibussowitsch     // characters transmitted to the output stream" on success
357c69effb2SJacob Faibussowitsch     PetscCheck(err >= 0, PETSC_COMM_SELF, PETSC_ERR_FILE_WRITE, "fprintf() returned error code %d", err);
358c69effb2SJacob Faibussowitsch   }
359c69effb2SJacob Faibussowitsch   PetscCall(PetscFFlush(fd));
36048a46eb9SPierre Jolivet   if (buff != str) PetscCall(PetscFree(buff));
3613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
362e5c89e4eSSatish Balay }
363e5c89e4eSSatish Balay 
3645b5bc046SBarry Smith /*@C
3655b5bc046SBarry Smith   PetscSNPrintf - Prints to a string of given length
3665b5bc046SBarry Smith 
3675b5bc046SBarry Smith   Not Collective
3685b5bc046SBarry Smith 
3695b5bc046SBarry Smith   Input Parameters:
37021532e8aSBarry Smith + len    - the length of `str`
371058c9ee1SBarry Smith . format - the usual `printf()` format string
37210699b91SBarry Smith -   ... - any arguments that are to be printed, each much have an appropriate symbol in the format argument
3735b5bc046SBarry Smith 
37421532e8aSBarry Smith   Output Parameter:
37521532e8aSBarry Smith . str - the resulting string
37621532e8aSBarry Smith 
3775b5bc046SBarry Smith   Level: intermediate
3785b5bc046SBarry Smith 
379db781477SPatrick Sanan .seealso: `PetscSynchronizedFlush()`, `PetscSynchronizedFPrintf()`, `PetscFPrintf()`, `PetscVSNPrintf()`,
380c69effb2SJacob Faibussowitsch           `PetscPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIISynchronizedPrintf()`,
381c69effb2SJacob Faibussowitsch           `PetscVFPrintf()`, `PetscFFlush()`
3825b5bc046SBarry Smith @*/
383d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSNPrintf(char *str, size_t len, const char format[], ...)
384d71ae5a4SJacob Faibussowitsch {
385c9a19010SBarry Smith   size_t  fullLength;
3865b5bc046SBarry Smith   va_list Argp;
3875b5bc046SBarry Smith 
3885b5bc046SBarry Smith   PetscFunctionBegin;
3895b5bc046SBarry Smith   va_start(Argp, format);
3909566063dSJacob Faibussowitsch   PetscCall(PetscVSNPrintf(str, len, format, &fullLength, Argp));
391eae3dc7dSJacob Faibussowitsch   va_end(Argp);
3923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3935b5bc046SBarry Smith }
3945b5bc046SBarry Smith 
395257d2499SJed Brown /*@C
396058c9ee1SBarry Smith   PetscSNPrintfCount - Prints to a string of given length, returns count of characters printed
397257d2499SJed Brown 
398257d2499SJed Brown   Not Collective
399257d2499SJed Brown 
400257d2499SJed Brown   Input Parameters:
40121532e8aSBarry Smith + len    - the length of `str`
402058c9ee1SBarry Smith . format - the usual `printf()` format string
40310699b91SBarry Smith -   ... - any arguments that are to be printed, each much have an appropriate symbol in the format argument
404257d2499SJed Brown 
40521532e8aSBarry Smith   Output Parameters:
40621532e8aSBarry Smith + str       - the resulting string
40721532e8aSBarry Smith - countused - number of characters printed
408cb398dd3SBarry Smith 
409257d2499SJed Brown   Level: intermediate
410257d2499SJed Brown 
411db781477SPatrick Sanan .seealso: `PetscSynchronizedFlush()`, `PetscSynchronizedFPrintf()`, `PetscFPrintf()`, `PetscVSNPrintf()`,
412db781477SPatrick Sanan           `PetscPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscSNPrintf()`, `PetscVFPrintf()`
413257d2499SJed Brown @*/
414d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSNPrintfCount(char *str, size_t len, const char format[], size_t *countused, ...)
415d71ae5a4SJacob Faibussowitsch {
416257d2499SJed Brown   va_list Argp;
417257d2499SJed Brown 
418257d2499SJed Brown   PetscFunctionBegin;
419257d2499SJed Brown   va_start(Argp, countused);
4209566063dSJacob Faibussowitsch   PetscCall(PetscVSNPrintf(str, len, format, countused, Argp));
421eae3dc7dSJacob Faibussowitsch   va_end(Argp);
4223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
423257d2499SJed Brown }
424257d2499SJed Brown 
42502c9f0b5SLisandro Dalcin PrintfQueue petsc_printfqueue = NULL, petsc_printfqueuebase = NULL;
426d30b0576SJed Brown int         petsc_printfqueuelength = 0;
427e5c89e4eSSatish Balay 
428eae3dc7dSJacob Faibussowitsch static inline PetscErrorCode PetscVFPrintf_Private(MPI_Comm comm, FILE *fd, const char format[], va_list Argp)
429eae3dc7dSJacob Faibussowitsch {
430eae3dc7dSJacob Faibussowitsch   const PetscBool tee = (PetscBool)(petsc_history && (fd != petsc_history));
431eae3dc7dSJacob Faibussowitsch   PetscMPIInt     rank;
432eae3dc7dSJacob Faibussowitsch   va_list         cpy;
433eae3dc7dSJacob Faibussowitsch 
434eae3dc7dSJacob Faibussowitsch   PetscFunctionBegin;
435eae3dc7dSJacob Faibussowitsch   PetscCheck(comm != MPI_COMM_NULL, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Called with MPI_COMM_NULL, likely PetscObjectComm() failed");
436eae3dc7dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
437eae3dc7dSJacob Faibussowitsch   if (PetscLikely(rank != 0)) PetscFunctionReturn(PETSC_SUCCESS);
438eae3dc7dSJacob Faibussowitsch   // must do this before we possibly consume Argp
439eae3dc7dSJacob Faibussowitsch   if (tee) va_copy(cpy, Argp);
440eae3dc7dSJacob Faibussowitsch   PetscCall((*PetscVFPrintf)(fd, format, Argp));
441eae3dc7dSJacob Faibussowitsch   if (tee) {
442eae3dc7dSJacob Faibussowitsch     PetscCall((*PetscVFPrintf)(petsc_history, format, cpy));
443eae3dc7dSJacob Faibussowitsch     va_end(cpy);
444eae3dc7dSJacob Faibussowitsch   }
445eae3dc7dSJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
446eae3dc7dSJacob Faibussowitsch }
447eae3dc7dSJacob Faibussowitsch 
448eae3dc7dSJacob Faibussowitsch static inline PetscErrorCode PetscSynchronizedFPrintf_Private(MPI_Comm comm, FILE *fp, const char format[], va_list Argp)
449eae3dc7dSJacob Faibussowitsch {
450eae3dc7dSJacob Faibussowitsch   PetscMPIInt rank;
451eae3dc7dSJacob Faibussowitsch   va_list     cpy;
452eae3dc7dSJacob Faibussowitsch 
453eae3dc7dSJacob Faibussowitsch   PetscFunctionBegin;
454eae3dc7dSJacob Faibussowitsch   PetscCheck(comm != MPI_COMM_NULL, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Called with MPI_COMM_NULL, likely PetscObjectComm() failed");
455eae3dc7dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
456eae3dc7dSJacob Faibussowitsch   /* First processor prints immediately to fp */
457eae3dc7dSJacob Faibussowitsch   if (rank == 0) {
458eae3dc7dSJacob Faibussowitsch     va_copy(cpy, Argp);
459eae3dc7dSJacob Faibussowitsch     PetscCall(PetscVFPrintf_Private(comm, fp, format, cpy));
460eae3dc7dSJacob Faibussowitsch     va_end(cpy);
461eae3dc7dSJacob Faibussowitsch   } else { /* other processors add to local queue */
462eae3dc7dSJacob Faibussowitsch     PrintfQueue next;
463eae3dc7dSJacob Faibussowitsch     size_t      fullLength = PETSCDEFAULTBUFFERSIZE;
464eae3dc7dSJacob Faibussowitsch 
465eae3dc7dSJacob Faibussowitsch     PetscCall(PetscNew(&next));
466eae3dc7dSJacob Faibussowitsch     if (petsc_printfqueue) {
467eae3dc7dSJacob Faibussowitsch       petsc_printfqueue->next = next;
468eae3dc7dSJacob Faibussowitsch       petsc_printfqueue       = next;
469eae3dc7dSJacob Faibussowitsch       petsc_printfqueue->next = NULL;
470eae3dc7dSJacob Faibussowitsch     } else petsc_printfqueuebase = petsc_printfqueue = next;
471eae3dc7dSJacob Faibussowitsch     petsc_printfqueuelength++;
472eae3dc7dSJacob Faibussowitsch     next->size   = 0;
473eae3dc7dSJacob Faibussowitsch     next->string = NULL;
474eae3dc7dSJacob Faibussowitsch     while (fullLength >= next->size) {
475eae3dc7dSJacob Faibussowitsch       next->size = fullLength + 1;
476eae3dc7dSJacob Faibussowitsch       PetscCall(PetscFree(next->string));
477eae3dc7dSJacob Faibussowitsch       PetscCall(PetscMalloc1(next->size, &next->string));
478eae3dc7dSJacob Faibussowitsch       PetscCall(PetscArrayzero(next->string, next->size));
479eae3dc7dSJacob Faibussowitsch       va_copy(cpy, Argp);
480eae3dc7dSJacob Faibussowitsch       PetscCall(PetscVSNPrintf(next->string, next->size, format, &fullLength, cpy));
481eae3dc7dSJacob Faibussowitsch       va_end(cpy);
482eae3dc7dSJacob Faibussowitsch     }
483eae3dc7dSJacob Faibussowitsch   }
484eae3dc7dSJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
485eae3dc7dSJacob Faibussowitsch }
486eae3dc7dSJacob Faibussowitsch 
487e5c89e4eSSatish Balay /*@C
4889c89aa79SPierre Jolivet   PetscSynchronizedPrintf - Prints synchronized output from multiple MPI processes.
489e5c89e4eSSatish Balay   Output of the first processor is followed by that of the second, etc.
490e5c89e4eSSatish Balay 
491e5c89e4eSSatish Balay   Not Collective
492e5c89e4eSSatish Balay 
493e5c89e4eSSatish Balay   Input Parameters:
494058c9ee1SBarry Smith + comm   - the MPI communicator
4956026c97aSBarry Smith - format - the usual `printf()` format string
496e5c89e4eSSatish Balay 
497e5c89e4eSSatish Balay   Level: intermediate
498e5c89e4eSSatish Balay 
499811af0c4SBarry Smith   Note:
500811af0c4SBarry Smith   REQUIRES a call to `PetscSynchronizedFlush()` by all the processes after the completion of the calls to `PetscSynchronizedPrintf()` for the information
501e5c89e4eSSatish Balay   from all the processors to be printed.
502e5c89e4eSSatish Balay 
503*aec76313SJacob Faibussowitsch   Fortran Notes:
504058c9ee1SBarry Smith   The call sequence is `PetscSynchronizedPrintf`(`MPI_Comm`, `character`(*), `PetscErrorCode` ierr).
505e5c89e4eSSatish Balay   That is, you can only pass a single character string from Fortran.
506e5c89e4eSSatish Balay 
507db781477SPatrick Sanan .seealso: `PetscSynchronizedFlush()`, `PetscSynchronizedFPrintf()`, `PetscFPrintf()`,
508c69effb2SJacob Faibussowitsch           `PetscPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIISynchronizedPrintf()`,
509c69effb2SJacob Faibussowitsch           `PetscFFlush()`
510e5c89e4eSSatish Balay @*/
511d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSynchronizedPrintf(MPI_Comm comm, const char format[], ...)
512d71ae5a4SJacob Faibussowitsch {
513eae3dc7dSJacob Faibussowitsch   va_list Argp;
514e5c89e4eSSatish Balay 
515e5c89e4eSSatish Balay   PetscFunctionBegin;
516e5c89e4eSSatish Balay   va_start(Argp, format);
517eae3dc7dSJacob Faibussowitsch   PetscCall(PetscSynchronizedFPrintf_Private(comm, PETSC_STDOUT, format, Argp));
518e5c89e4eSSatish Balay   va_end(Argp);
5193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
520e5c89e4eSSatish Balay }
521e5c89e4eSSatish Balay 
522e5c89e4eSSatish Balay /*@C
523e5c89e4eSSatish Balay   PetscSynchronizedFPrintf - Prints synchronized output to the specified file from
52421532e8aSBarry Smith   several MPI processes.  Output of the first process is followed by that of the
525e5c89e4eSSatish Balay   second, etc.
526e5c89e4eSSatish Balay 
527e5c89e4eSSatish Balay   Not Collective
528e5c89e4eSSatish Balay 
529e5c89e4eSSatish Balay   Input Parameters:
530058c9ee1SBarry Smith + comm   - the MPI communicator
531*aec76313SJacob Faibussowitsch . fp     - the file pointer
5326026c97aSBarry Smith - format - the usual `printf()` format string
533e5c89e4eSSatish Balay 
534e5c89e4eSSatish Balay   Level: intermediate
535e5c89e4eSSatish Balay 
536811af0c4SBarry Smith   Note:
537811af0c4SBarry Smith   REQUIRES a intervening call to `PetscSynchronizedFlush()` for the information
538e5c89e4eSSatish Balay   from all the processors to be printed.
539e5c89e4eSSatish Balay 
540db781477SPatrick Sanan .seealso: `PetscSynchronizedPrintf()`, `PetscSynchronizedFlush()`, `PetscFPrintf()`,
541c69effb2SJacob Faibussowitsch           `PetscFOpen()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
542c69effb2SJacob Faibussowitsch           `PetscFFlush()`
543e5c89e4eSSatish Balay @*/
544d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSynchronizedFPrintf(MPI_Comm comm, FILE *fp, const char format[], ...)
545d71ae5a4SJacob Faibussowitsch {
546eae3dc7dSJacob Faibussowitsch   va_list Argp;
547e5c89e4eSSatish Balay 
548e5c89e4eSSatish Balay   PetscFunctionBegin;
549e5c89e4eSSatish Balay   va_start(Argp, format);
550eae3dc7dSJacob Faibussowitsch   PetscCall(PetscSynchronizedFPrintf_Private(comm, fp, format, Argp));
551e5c89e4eSSatish Balay   va_end(Argp);
5523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
553e5c89e4eSSatish Balay }
554e5c89e4eSSatish Balay 
5550ec8b6e3SBarry Smith /*@C
556e5c89e4eSSatish Balay   PetscSynchronizedFlush - Flushes to the screen output from all processors
557811af0c4SBarry Smith   involved in previous `PetscSynchronizedPrintf()`/`PetscSynchronizedFPrintf()` calls.
558e5c89e4eSSatish Balay 
559d083f849SBarry Smith   Collective
560e5c89e4eSSatish Balay 
561e5c89e4eSSatish Balay   Input Parameters:
562058c9ee1SBarry Smith + comm - the MPI communicator
56321532e8aSBarry Smith - fd   - the file pointer (valid on MPI rank 0 of the communicator)
564e5c89e4eSSatish Balay 
565e5c89e4eSSatish Balay   Level: intermediate
566e5c89e4eSSatish Balay 
567811af0c4SBarry Smith   Note:
568811af0c4SBarry Smith   If `PetscSynchronizedPrintf()` and/or `PetscSynchronizedFPrintf()` are called with
569811af0c4SBarry Smith   different MPI communicators there must be an intervening call to `PetscSynchronizedFlush()` between the calls with different MPI communicators.
570e5c89e4eSSatish Balay 
571*aec76313SJacob Faibussowitsch   Fortran Notes:
572811af0c4SBarry Smith   Pass `PETSC_STDOUT` if the flush is for standard out; otherwise pass a value obtained from `PetscFOpen()`
573e50bf69fSBarry Smith 
574db781477SPatrick Sanan .seealso: `PetscSynchronizedPrintf()`, `PetscFPrintf()`, `PetscPrintf()`, `PetscViewerASCIIPrintf()`,
575db781477SPatrick Sanan           `PetscViewerASCIISynchronizedPrintf()`
5760087d953SMatthew G. Knepley @*/
577d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSynchronizedFlush(MPI_Comm comm, FILE *fd)
578d71ae5a4SJacob Faibussowitsch {
57929a5cbdcSMatthew G. Knepley   PetscMPIInt rank, size, tag, i, j, n = 0, dummy = 0;
5802d609e63SMatthew Knepley   char       *message;
581e5c89e4eSSatish Balay   MPI_Status  status;
582e5c89e4eSSatish Balay 
583e5c89e4eSSatish Balay   PetscFunctionBegin;
5849566063dSJacob Faibussowitsch   PetscCall(PetscCommDuplicate(comm, &comm, &tag));
5859566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
5869566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
587e5c89e4eSSatish Balay 
588e5c89e4eSSatish Balay   /* First processor waits for messages from all other processors */
589dd400576SPatrick Sanan   if (rank == 0) {
5900ec8b6e3SBarry Smith     if (!fd) fd = PETSC_STDOUT;
591e5c89e4eSSatish Balay     for (i = 1; i < size; i++) {
5929f73f8ecSBarry Smith       /* to prevent a flood of messages to process zero, request each message separately */
5939566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Send(&dummy, 1, MPI_INT, i, tag, comm));
5949566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Recv(&n, 1, MPI_INT, i, tag, comm, &status));
595e5c89e4eSSatish Balay       for (j = 0; j < n; j++) {
59629a5cbdcSMatthew G. Knepley         PetscMPIInt size = 0;
5972d609e63SMatthew Knepley 
5989566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Recv(&size, 1, MPI_INT, i, tag, comm, &status));
5999566063dSJacob Faibussowitsch         PetscCall(PetscMalloc1(size, &message));
6009566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Recv(message, size, MPI_CHAR, i, tag, comm, &status));
6019566063dSJacob Faibussowitsch         PetscCall(PetscFPrintf(comm, fd, "%s", message));
6029566063dSJacob Faibussowitsch         PetscCall(PetscFree(message));
603e5c89e4eSSatish Balay       }
604e5c89e4eSSatish Balay     }
605e5c89e4eSSatish Balay   } else { /* other processors send queue to processor 0 */
606d30b0576SJed Brown     PrintfQueue next = petsc_printfqueuebase, previous;
607e5c89e4eSSatish Balay 
6089566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Recv(&dummy, 1, MPI_INT, 0, tag, comm, &status));
6099566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Send(&petsc_printfqueuelength, 1, MPI_INT, 0, tag, comm));
610d30b0576SJed Brown     for (i = 0; i < petsc_printfqueuelength; i++) {
6119566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Send(&next->size, 1, MPI_INT, 0, tag, comm));
6129566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Send(next->string, next->size, MPI_CHAR, 0, tag, comm));
613e5c89e4eSSatish Balay       previous = next;
614e5c89e4eSSatish Balay       next     = next->next;
6159566063dSJacob Faibussowitsch       PetscCall(PetscFree(previous->string));
6169566063dSJacob Faibussowitsch       PetscCall(PetscFree(previous));
617e5c89e4eSSatish Balay     }
61802c9f0b5SLisandro Dalcin     petsc_printfqueue       = NULL;
619d30b0576SJed Brown     petsc_printfqueuelength = 0;
620e5c89e4eSSatish Balay   }
6219566063dSJacob Faibussowitsch   PetscCall(PetscCommDestroy(&comm));
6223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
623e5c89e4eSSatish Balay }
624e5c89e4eSSatish Balay 
625e5c89e4eSSatish Balay /*@C
626e5c89e4eSSatish Balay   PetscFPrintf - Prints to a file, only from the first
62721532e8aSBarry Smith   MPI process in the communicator.
628e5c89e4eSSatish Balay 
629cf53795eSBarry Smith   Not Collective; No Fortran Support
630e5c89e4eSSatish Balay 
631e5c89e4eSSatish Balay   Input Parameters:
632058c9ee1SBarry Smith + comm   - the MPI communicator
633e5c89e4eSSatish Balay . fd     - the file pointer
6346026c97aSBarry Smith - format - the usual `printf()` format string
635e5c89e4eSSatish Balay 
636e5c89e4eSSatish Balay   Level: intermediate
637e5c89e4eSSatish Balay 
638*aec76313SJacob Faibussowitsch   Developer Notes:
639058c9ee1SBarry Smith   This maybe, and is, called from PETSc error handlers and `PetscMallocValidate()` hence it does not use `PetscCallMPI()` which
640058c9ee1SBarry Smith   could recursively restart the malloc validation.
641058c9ee1SBarry Smith 
642db781477SPatrick Sanan .seealso: `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
643c69effb2SJacob Faibussowitsch           `PetscViewerASCIISynchronizedPrintf()`, `PetscSynchronizedFlush()`, `PetscFFlush()`
644e5c89e4eSSatish Balay @*/
645d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFPrintf(MPI_Comm comm, FILE *fd, const char format[], ...)
646d71ae5a4SJacob Faibussowitsch {
647eae3dc7dSJacob Faibussowitsch   va_list Argp;
648e5c89e4eSSatish Balay 
649e5c89e4eSSatish Balay   PetscFunctionBegin;
650e5c89e4eSSatish Balay   va_start(Argp, format);
651eae3dc7dSJacob Faibussowitsch   PetscCall(PetscVFPrintf_Private(comm, fd, format, Argp));
652e5c89e4eSSatish Balay   va_end(Argp);
6533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
654e5c89e4eSSatish Balay }
655e5c89e4eSSatish Balay 
656e5c89e4eSSatish Balay /*@C
657e5c89e4eSSatish Balay   PetscPrintf - Prints to standard out, only from the first
65821532e8aSBarry Smith   MPI process in the communicator. Calls from other processes are ignored.
659e5c89e4eSSatish Balay 
660e5c89e4eSSatish Balay   Not Collective
661e5c89e4eSSatish Balay 
662e5c89e4eSSatish Balay   Input Parameters:
663e5c89e4eSSatish Balay + comm   - the communicator
664bfbbc7b7SBarry Smith - format - the usual `printf()` format string
665e5c89e4eSSatish Balay 
666e5c89e4eSSatish Balay   Level: intermediate
667e5c89e4eSSatish Balay 
668811af0c4SBarry Smith   Note:
669811af0c4SBarry Smith   Deprecated information: `PetscPrintf()` supports some format specifiers that are unique to PETSc.
670811af0c4SBarry Smith   See the manual page for `PetscFormatConvert()` for details.
671b2706f25SRichard Tran Mills 
672*aec76313SJacob Faibussowitsch   Fortran Notes:
673811af0c4SBarry Smith   The call sequence is `PetscPrintf`(MPI_Comm, character(*), `PetscErrorCode` ierr) from Fortran.
674e5c89e4eSSatish Balay   That is, you can only pass a single character string from Fortran.
675e5c89e4eSSatish Balay 
676c69effb2SJacob Faibussowitsch .seealso: `PetscFPrintf()`, `PetscSynchronizedPrintf()`, `PetscFormatConvert()`, `PetscFFlush()`
677e5c89e4eSSatish Balay @*/
678d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscPrintf(MPI_Comm comm, const char format[], ...)
679d71ae5a4SJacob Faibussowitsch {
680eae3dc7dSJacob Faibussowitsch   va_list Argp;
681e5c89e4eSSatish Balay 
682e5c89e4eSSatish Balay   PetscFunctionBegin;
683e5c89e4eSSatish Balay   va_start(Argp, format);
684eae3dc7dSJacob Faibussowitsch   PetscCall(PetscVFPrintf_Private(comm, PETSC_STDOUT, format, Argp));
685e5c89e4eSSatish Balay   va_end(Argp);
6863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
687e5c89e4eSSatish Balay }
688e5c89e4eSSatish Balay 
689d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscHelpPrintfDefault(MPI_Comm comm, const char format[], ...)
690d71ae5a4SJacob Faibussowitsch {
691eae3dc7dSJacob Faibussowitsch   va_list Argp;
692e5c89e4eSSatish Balay 
693e5c89e4eSSatish Balay   PetscFunctionBegin;
694e5c89e4eSSatish Balay   va_start(Argp, format);
695eae3dc7dSJacob Faibussowitsch   PetscCall(PetscVFPrintf_Private(comm, PETSC_STDOUT, format, Argp));
696e5c89e4eSSatish Balay   va_end(Argp);
6973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
698e5c89e4eSSatish Balay }
699e5c89e4eSSatish Balay 
700e5c89e4eSSatish Balay /*@C
70121532e8aSBarry Smith   PetscSynchronizedFGets - Multiple MPI processes all get the same line from a file.
702e5c89e4eSSatish Balay 
703d083f849SBarry Smith   Collective
704e5c89e4eSSatish Balay 
705e5c89e4eSSatish Balay   Input Parameters:
70621532e8aSBarry Smith + comm - the MPI communicator
707*aec76313SJacob Faibussowitsch . fp   - the file pointer
70821532e8aSBarry Smith - len  - the length of `string`
709e5c89e4eSSatish Balay 
710e5c89e4eSSatish Balay   Output Parameter:
71121532e8aSBarry Smith . string - the line read from the file, at end of file `string`[0] == 0
712e5c89e4eSSatish Balay 
713e5c89e4eSSatish Balay   Level: intermediate
714e5c89e4eSSatish Balay 
715db781477SPatrick Sanan .seealso: `PetscSynchronizedPrintf()`, `PetscSynchronizedFlush()`,
716db781477SPatrick Sanan           `PetscFOpen()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIPrintf()`
717e5c89e4eSSatish Balay @*/
718d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSynchronizedFGets(MPI_Comm comm, FILE *fp, size_t len, char string[])
719d71ae5a4SJacob Faibussowitsch {
720e5c89e4eSSatish Balay   PetscMPIInt rank;
721e5c89e4eSSatish Balay 
722e5c89e4eSSatish Balay   PetscFunctionBegin;
7239566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
72480971c97SJames Wright   if (rank == 0) {
725eae3dc7dSJacob Faibussowitsch     if (!fgets(string, len, fp)) {
726e31d4fa4SJed Brown       string[0] = 0;
727bf31d2d3SBarry Smith       PetscCheck(feof(fp), PETSC_COMM_SELF, PETSC_ERR_FILE_READ, "Error reading from file due to \"%s\"", strerror(errno));
728047b9c12SMatthew G Knepley     }
729238ccf28SShri Abhyankar   }
7309566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Bcast(string, len, MPI_BYTE, 0, comm));
7313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
732e5c89e4eSSatish Balay }
733238ccf28SShri Abhyankar 
7348c74ee41SBarry Smith /*@C
73521532e8aSBarry Smith   PetscFormatStrip - Takes a PETSc format string and removes all numerical modifiers to `%` operations
7368c74ee41SBarry Smith 
7372fe279fdSBarry Smith   Input Parameter:
7388c74ee41SBarry Smith . format - the PETSc format string
7398c74ee41SBarry Smith 
7408c74ee41SBarry Smith   Level: developer
7418c74ee41SBarry Smith @*/
742d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFormatStrip(char *format)
743d71ae5a4SJacob Faibussowitsch {
7448c74ee41SBarry Smith   size_t loc1 = 0, loc2 = 0;
7458c74ee41SBarry Smith 
7468c74ee41SBarry Smith   PetscFunctionBegin;
7478c74ee41SBarry Smith   while (format[loc2]) {
7488c74ee41SBarry Smith     if (format[loc2] == '%') {
7498c74ee41SBarry Smith       format[loc1++] = format[loc2++];
7508c74ee41SBarry Smith       while (format[loc2] && ((format[loc2] >= '0' && format[loc2] <= '9') || format[loc2] == '.')) loc2++;
7518c74ee41SBarry Smith     }
7528c74ee41SBarry Smith     format[loc1++] = format[loc2++];
7538c74ee41SBarry Smith   }
7543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7558c74ee41SBarry Smith }
7568c74ee41SBarry Smith 
757d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFormatRealArray(char buf[], size_t len, const char *fmt, PetscInt n, const PetscReal x[])
758d71ae5a4SJacob Faibussowitsch {
7591b5687a1SBarry Smith   PetscInt i;
7601b5687a1SBarry Smith   size_t   left, count;
7611b5687a1SBarry Smith   char    *p;
7621b5687a1SBarry Smith 
7631b5687a1SBarry Smith   PetscFunctionBegin;
7641b5687a1SBarry Smith   for (i = 0, p = buf, left = len; i < n; i++) {
7659566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintfCount(p, left, fmt, &count, (double)x[i]));
76608401ef6SPierre Jolivet     PetscCheck(count < left, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Insufficient space in buffer");
7671b5687a1SBarry Smith     left -= count;
7681b5687a1SBarry Smith     p += count - 1;
7691b5687a1SBarry Smith     *p++ = ' ';
7701b5687a1SBarry Smith   }
7711b5687a1SBarry Smith   p[i ? 0 : -1] = 0;
7723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7731b5687a1SBarry Smith }
774