xref: /petsc/src/sys/fileio/mprint.c (revision cc4c1da905d89950b196b027190941013bd3e15a)
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 @*/
39*cc4c1da9SBarry 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 @*/
101*cc4c1da9SBarry 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 
154*cc4c1da9SBarry Smith   No Fortran Support
155*cc4c1da9SBarry 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 @*/
175*cc4c1da9SBarry 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 
284*cc4c1da9SBarry Smith   Fortran Note:
285*cc4c1da9SBarry Smith   Use `PetscFlush()`
286*cc4c1da9SBarry Smith 
287c69effb2SJacob Faibussowitsch .seealso: `PetscPrintf()`, `PetscFPrintf()`, `PetscVFPrintf()`, `PetscVSNPrintf()`
288c69effb2SJacob Faibussowitsch @*/
289c69effb2SJacob Faibussowitsch PetscErrorCode PetscFFlush(FILE *fd)
290c69effb2SJacob Faibussowitsch {
291c69effb2SJacob Faibussowitsch   PetscFunctionBegin;
2924f572ea9SToby Isaac   if (fd) PetscAssertPointer(fd, 1);
293c69effb2SJacob Faibussowitsch   // could also use PetscCallExternal() here, but since we can get additional error explanation
294c69effb2SJacob Faibussowitsch   // from strerror() we opted for a manual check
295bf31d2d3SBarry Smith   PetscCheck(0 == fflush(fd), PETSC_COMM_SELF, PETSC_ERR_FILE_WRITE, "Error in fflush() due to \"%s\"", strerror(errno));
296c69effb2SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
297c69effb2SJacob Faibussowitsch }
298c69effb2SJacob Faibussowitsch 
299c69effb2SJacob Faibussowitsch /*@C
300aec76313SJacob Faibussowitsch   PetscVFPrintfDefault -  All PETSc standard out and error messages are sent through this function; so, in theory, this can
301e5c89e4eSSatish Balay   can be replaced with something that does not simply write to a file.
302e5c89e4eSSatish Balay 
303*cc4c1da9SBarry Smith   No Fortran Support
304*cc4c1da9SBarry Smith 
30510450e9eSJacob Faibussowitsch   Input Parameters:
30610450e9eSJacob Faibussowitsch + fd     - the file descriptor to write to
30710450e9eSJacob Faibussowitsch . format - the format string to write with
30810450e9eSJacob Faibussowitsch - Argp   - the variable argument list of items to format and write
30910450e9eSJacob Faibussowitsch 
31010450e9eSJacob Faibussowitsch   Level: developer
31110450e9eSJacob Faibussowitsch 
31210450e9eSJacob Faibussowitsch   Note:
31310450e9eSJacob Faibussowitsch   For error messages this may be called by any MPI process, for regular standard out it is
31410450e9eSJacob Faibussowitsch   called only by MPI rank 0 of a given communicator
31510450e9eSJacob Faibussowitsch 
31610450e9eSJacob Faibussowitsch   Example Usage:
317c9a19010SBarry Smith   To use, write your own function for example,
318058c9ee1SBarry Smith .vb
319058c9ee1SBarry Smith    PetscErrorCode mypetscvfprintf(FILE *fd, const char format[], va_list Argp)
320058c9ee1SBarry Smith    {
321058c9ee1SBarry Smith      PetscErrorCode ierr;
322058c9ee1SBarry Smith 
323058c9ee1SBarry Smith      PetscFunctionBegin;
324058c9ee1SBarry Smith       if (fd != stdout && fd != stderr) {  handle regular files
325058c9ee1SBarry Smith          CHKERR(PetscVFPrintfDefault(fd,format,Argp));
326058c9ee1SBarry Smith      } else {
327058c9ee1SBarry Smith         char   buff[BIG];
328058c9ee1SBarry Smith         size_t length;
329058c9ee1SBarry Smith         PetscCall(PetscVSNPrintf(buff,BIG,format,&length,Argp));
330058c9ee1SBarry Smith         now send buff to whatever stream or whatever you want
331058c9ee1SBarry Smith     }
332058c9ee1SBarry Smith     PetscFunctionReturn(PETSC_SUCCESS);
333058c9ee1SBarry Smith    }
334058c9ee1SBarry Smith .ve
335058c9ee1SBarry Smith   then before the call to `PetscInitialize()` do the assignment `PetscVFPrintf = mypetscvfprintf`;
336058c9ee1SBarry Smith 
337aec76313SJacob Faibussowitsch   Developer Notes:
338058c9ee1SBarry Smith   This could be called by an error handler, if that happens then a recursion of the error handler may occur
339058c9ee1SBarry Smith   and a resulting crash
340c9a19010SBarry Smith 
341c69effb2SJacob Faibussowitsch .seealso: `PetscVSNPrintf()`, `PetscErrorPrintf()`, `PetscFFlush()`
342c9a19010SBarry Smith @*/
343*cc4c1da9SBarry Smith PetscErrorCode PetscVFPrintfDefault(FILE *fd, const char format[], va_list Argp)
344d71ae5a4SJacob Faibussowitsch {
34514416c0eSBarry Smith   char   str[PETSCDEFAULTBUFFERSIZE];
34614416c0eSBarry Smith   char  *buff = str;
34714416c0eSBarry Smith   size_t fullLength;
3481531940fSBarry Smith #if defined(PETSC_HAVE_VA_COPY)
34914416c0eSBarry Smith   va_list Argpcopy;
3501531940fSBarry Smith #endif
3511179db26SBarry Smith 
352eed5747fSBarry Smith   PetscFunctionBegin;
3531531940fSBarry Smith #if defined(PETSC_HAVE_VA_COPY)
35414416c0eSBarry Smith   va_copy(Argpcopy, Argp);
3551531940fSBarry Smith #endif
3569566063dSJacob Faibussowitsch   PetscCall(PetscVSNPrintf(str, sizeof(str), format, &fullLength, Argp));
35714416c0eSBarry Smith   if (fullLength > sizeof(str)) {
3589566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(fullLength, &buff));
3591531940fSBarry Smith #if defined(PETSC_HAVE_VA_COPY)
3609566063dSJacob Faibussowitsch     PetscCall(PetscVSNPrintf(buff, fullLength, format, NULL, Argpcopy));
3611531940fSBarry Smith #else
3621531940fSBarry Smith     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "C89 does not support va_copy() hence cannot print long strings with PETSc printing routines");
3631531940fSBarry Smith #endif
36414416c0eSBarry Smith   }
365eae3dc7dSJacob Faibussowitsch #if defined(PETSC_HAVE_VA_COPY)
366eae3dc7dSJacob Faibussowitsch   va_end(Argpcopy);
367eae3dc7dSJacob Faibussowitsch #endif
368c69effb2SJacob Faibussowitsch   {
3698c0ebe3fSBarry Smith     int err;
3708c0ebe3fSBarry Smith 
3718c0ebe3fSBarry Smith     // POSIX C sets errno but otherwise it may not be set for *printf() system calls
3728c0ebe3fSBarry Smith     // https://pubs.opengroup.org/onlinepubs/9699919799/functions/fprintf.html
3738c0ebe3fSBarry Smith     errno = 0;
3748c0ebe3fSBarry Smith     err   = fprintf(fd, "%s", buff);
375c69effb2SJacob Faibussowitsch     // cannot use PetscCallExternal() for fprintf since the return value is "number of
376c69effb2SJacob Faibussowitsch     // characters transmitted to the output stream" on success
3778c0ebe3fSBarry 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)");
378c69effb2SJacob Faibussowitsch   }
379c69effb2SJacob Faibussowitsch   PetscCall(PetscFFlush(fd));
38048a46eb9SPierre Jolivet   if (buff != str) PetscCall(PetscFree(buff));
3813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
382e5c89e4eSSatish Balay }
383e5c89e4eSSatish Balay 
3845b5bc046SBarry Smith /*@C
3855b5bc046SBarry Smith   PetscSNPrintf - Prints to a string of given length
3865b5bc046SBarry Smith 
387*cc4c1da9SBarry Smith   Not Collective, No Fortran Support
3885b5bc046SBarry Smith 
3895b5bc046SBarry Smith   Input Parameters:
39021532e8aSBarry Smith + len    - the length of `str`
39110450e9eSJacob Faibussowitsch - format - the usual `printf()` format string
3925b5bc046SBarry Smith 
39321532e8aSBarry Smith   Output Parameter:
39421532e8aSBarry Smith . str - the resulting string
39521532e8aSBarry Smith 
3965b5bc046SBarry Smith   Level: intermediate
3975b5bc046SBarry Smith 
398db781477SPatrick Sanan .seealso: `PetscSynchronizedFlush()`, `PetscSynchronizedFPrintf()`, `PetscFPrintf()`, `PetscVSNPrintf()`,
399c69effb2SJacob Faibussowitsch           `PetscPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIISynchronizedPrintf()`,
400c69effb2SJacob Faibussowitsch           `PetscVFPrintf()`, `PetscFFlush()`
4015b5bc046SBarry Smith @*/
402*cc4c1da9SBarry Smith PetscErrorCode PetscSNPrintf(char str[], size_t len, const char format[], ...)
403d71ae5a4SJacob Faibussowitsch {
404c9a19010SBarry Smith   size_t  fullLength;
4055b5bc046SBarry Smith   va_list Argp;
4065b5bc046SBarry Smith 
4075b5bc046SBarry Smith   PetscFunctionBegin;
4085b5bc046SBarry Smith   va_start(Argp, format);
4099566063dSJacob Faibussowitsch   PetscCall(PetscVSNPrintf(str, len, format, &fullLength, Argp));
410eae3dc7dSJacob Faibussowitsch   va_end(Argp);
4113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4125b5bc046SBarry Smith }
4135b5bc046SBarry Smith 
414257d2499SJed Brown /*@C
415058c9ee1SBarry Smith   PetscSNPrintfCount - Prints to a string of given length, returns count of characters printed
416257d2499SJed Brown 
417*cc4c1da9SBarry Smith   Not Collective, No Fortran Support
418257d2499SJed Brown 
419257d2499SJed Brown   Input Parameters:
42021532e8aSBarry Smith + len    - the length of `str`
421058c9ee1SBarry Smith . format - the usual `printf()` format string
42210450e9eSJacob Faibussowitsch - ...    - args to format
423257d2499SJed Brown 
42421532e8aSBarry Smith   Output Parameters:
42521532e8aSBarry Smith + str       - the resulting string
42621532e8aSBarry Smith - countused - number of characters printed
427cb398dd3SBarry Smith 
428257d2499SJed Brown   Level: intermediate
429257d2499SJed Brown 
430db781477SPatrick Sanan .seealso: `PetscSynchronizedFlush()`, `PetscSynchronizedFPrintf()`, `PetscFPrintf()`, `PetscVSNPrintf()`,
431db781477SPatrick Sanan           `PetscPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscSNPrintf()`, `PetscVFPrintf()`
432257d2499SJed Brown @*/
433*cc4c1da9SBarry Smith PetscErrorCode PetscSNPrintfCount(char str[], size_t len, const char format[], size_t *countused, ...)
434d71ae5a4SJacob Faibussowitsch {
435257d2499SJed Brown   va_list Argp;
436257d2499SJed Brown 
437257d2499SJed Brown   PetscFunctionBegin;
438257d2499SJed Brown   va_start(Argp, countused);
4399566063dSJacob Faibussowitsch   PetscCall(PetscVSNPrintf(str, len, format, countused, Argp));
440eae3dc7dSJacob Faibussowitsch   va_end(Argp);
4413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
442257d2499SJed Brown }
443257d2499SJed Brown 
44402c9f0b5SLisandro Dalcin PrintfQueue petsc_printfqueue = NULL, petsc_printfqueuebase = NULL;
445d30b0576SJed Brown int         petsc_printfqueuelength = 0;
446e5c89e4eSSatish Balay 
4478c509928SStefano Zampini static inline PetscErrorCode PetscVFPrintf_Private(FILE *fd, const char format[], va_list Argp)
448eae3dc7dSJacob Faibussowitsch {
449eae3dc7dSJacob Faibussowitsch   const PetscBool tee = (PetscBool)(petsc_history && (fd != petsc_history));
450eae3dc7dSJacob Faibussowitsch   va_list         cpy;
451eae3dc7dSJacob Faibussowitsch 
452eae3dc7dSJacob Faibussowitsch   PetscFunctionBegin;
453eae3dc7dSJacob Faibussowitsch   // must do this before we possibly consume Argp
454eae3dc7dSJacob Faibussowitsch   if (tee) va_copy(cpy, Argp);
455eae3dc7dSJacob Faibussowitsch   PetscCall((*PetscVFPrintf)(fd, format, Argp));
456eae3dc7dSJacob Faibussowitsch   if (tee) {
457eae3dc7dSJacob Faibussowitsch     PetscCall((*PetscVFPrintf)(petsc_history, format, cpy));
458eae3dc7dSJacob Faibussowitsch     va_end(cpy);
459eae3dc7dSJacob Faibussowitsch   }
460eae3dc7dSJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
461eae3dc7dSJacob Faibussowitsch }
462eae3dc7dSJacob Faibussowitsch 
4638c509928SStefano Zampini PETSC_INTERN PetscErrorCode PetscVFPrintf_Internal(FILE *fd, const char format[], ...)
4648c509928SStefano Zampini {
4658c509928SStefano Zampini   va_list Argp;
4668c509928SStefano Zampini 
4678c509928SStefano Zampini   PetscFunctionBegin;
4688c509928SStefano Zampini   va_start(Argp, format);
4698c509928SStefano Zampini   PetscCall(PetscVFPrintf_Private(fd, format, Argp));
4708c509928SStefano Zampini   va_end(Argp);
4718c509928SStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
4728c509928SStefano Zampini }
4738c509928SStefano Zampini 
474eae3dc7dSJacob Faibussowitsch static inline PetscErrorCode PetscSynchronizedFPrintf_Private(MPI_Comm comm, FILE *fp, const char format[], va_list Argp)
475eae3dc7dSJacob Faibussowitsch {
476eae3dc7dSJacob Faibussowitsch   PetscMPIInt rank;
477eae3dc7dSJacob Faibussowitsch   va_list     cpy;
478eae3dc7dSJacob Faibussowitsch 
479eae3dc7dSJacob Faibussowitsch   PetscFunctionBegin;
480eae3dc7dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
481eae3dc7dSJacob Faibussowitsch   /* First processor prints immediately to fp */
482eae3dc7dSJacob Faibussowitsch   if (rank == 0) {
483eae3dc7dSJacob Faibussowitsch     va_copy(cpy, Argp);
4848c509928SStefano Zampini     PetscCall(PetscVFPrintf_Private(fp, format, cpy));
485eae3dc7dSJacob Faibussowitsch     va_end(cpy);
486eae3dc7dSJacob Faibussowitsch   } else { /* other processors add to local queue */
487eae3dc7dSJacob Faibussowitsch     PrintfQueue next;
488eae3dc7dSJacob Faibussowitsch     size_t      fullLength = PETSCDEFAULTBUFFERSIZE;
489eae3dc7dSJacob Faibussowitsch 
490eae3dc7dSJacob Faibussowitsch     PetscCall(PetscNew(&next));
491eae3dc7dSJacob Faibussowitsch     if (petsc_printfqueue) {
492eae3dc7dSJacob Faibussowitsch       petsc_printfqueue->next = next;
493eae3dc7dSJacob Faibussowitsch       petsc_printfqueue       = next;
494eae3dc7dSJacob Faibussowitsch       petsc_printfqueue->next = NULL;
495eae3dc7dSJacob Faibussowitsch     } else petsc_printfqueuebase = petsc_printfqueue = next;
496eae3dc7dSJacob Faibussowitsch     petsc_printfqueuelength++;
497eae3dc7dSJacob Faibussowitsch     next->size   = 0;
498eae3dc7dSJacob Faibussowitsch     next->string = NULL;
499eae3dc7dSJacob Faibussowitsch     while (fullLength >= next->size) {
500eae3dc7dSJacob Faibussowitsch       next->size = fullLength + 1;
501eae3dc7dSJacob Faibussowitsch       PetscCall(PetscFree(next->string));
502eae3dc7dSJacob Faibussowitsch       PetscCall(PetscMalloc1(next->size, &next->string));
503eae3dc7dSJacob Faibussowitsch       PetscCall(PetscArrayzero(next->string, next->size));
504eae3dc7dSJacob Faibussowitsch       va_copy(cpy, Argp);
505eae3dc7dSJacob Faibussowitsch       PetscCall(PetscVSNPrintf(next->string, next->size, format, &fullLength, cpy));
506eae3dc7dSJacob Faibussowitsch       va_end(cpy);
507eae3dc7dSJacob Faibussowitsch     }
508eae3dc7dSJacob Faibussowitsch   }
509eae3dc7dSJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
510eae3dc7dSJacob Faibussowitsch }
511eae3dc7dSJacob Faibussowitsch 
512e5c89e4eSSatish Balay /*@C
5139c89aa79SPierre Jolivet   PetscSynchronizedPrintf - Prints synchronized output from multiple MPI processes.
514e5c89e4eSSatish Balay   Output of the first processor is followed by that of the second, etc.
515e5c89e4eSSatish Balay 
516e5c89e4eSSatish Balay   Not Collective
517e5c89e4eSSatish Balay 
518e5c89e4eSSatish Balay   Input Parameters:
519058c9ee1SBarry Smith + comm   - the MPI communicator
5206026c97aSBarry Smith - format - the usual `printf()` format string
521e5c89e4eSSatish Balay 
522e5c89e4eSSatish Balay   Level: intermediate
523e5c89e4eSSatish Balay 
524811af0c4SBarry Smith   Note:
525811af0c4SBarry Smith   REQUIRES a call to `PetscSynchronizedFlush()` by all the processes after the completion of the calls to `PetscSynchronizedPrintf()` for the information
526e5c89e4eSSatish Balay   from all the processors to be printed.
527e5c89e4eSSatish Balay 
528*cc4c1da9SBarry Smith   Fortran Note:
529058c9ee1SBarry Smith   The call sequence is `PetscSynchronizedPrintf`(`MPI_Comm`, `character`(*), `PetscErrorCode` ierr).
530e5c89e4eSSatish Balay   That is, you can only pass a single character string from Fortran.
531e5c89e4eSSatish Balay 
532db781477SPatrick Sanan .seealso: `PetscSynchronizedFlush()`, `PetscSynchronizedFPrintf()`, `PetscFPrintf()`,
533c69effb2SJacob Faibussowitsch           `PetscPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIISynchronizedPrintf()`,
534c69effb2SJacob Faibussowitsch           `PetscFFlush()`
535e5c89e4eSSatish Balay @*/
536d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSynchronizedPrintf(MPI_Comm comm, const char format[], ...)
537d71ae5a4SJacob Faibussowitsch {
538eae3dc7dSJacob Faibussowitsch   va_list Argp;
539e5c89e4eSSatish Balay 
540e5c89e4eSSatish Balay   PetscFunctionBegin;
541e5c89e4eSSatish Balay   va_start(Argp, format);
542eae3dc7dSJacob Faibussowitsch   PetscCall(PetscSynchronizedFPrintf_Private(comm, PETSC_STDOUT, format, Argp));
543e5c89e4eSSatish Balay   va_end(Argp);
5443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
545e5c89e4eSSatish Balay }
546e5c89e4eSSatish Balay 
547e5c89e4eSSatish Balay /*@C
548e5c89e4eSSatish Balay   PetscSynchronizedFPrintf - Prints synchronized output to the specified file from
54921532e8aSBarry Smith   several MPI processes.  Output of the first process is followed by that of the
550e5c89e4eSSatish Balay   second, etc.
551e5c89e4eSSatish Balay 
552e5c89e4eSSatish Balay   Not Collective
553e5c89e4eSSatish Balay 
554e5c89e4eSSatish Balay   Input Parameters:
555058c9ee1SBarry Smith + comm   - the MPI communicator
556*cc4c1da9SBarry Smith . fp     - the file pointer, `PETSC_STDOUT` or value obtained from `PetscFOpen()`
5576026c97aSBarry Smith - format - the usual `printf()` format string
558e5c89e4eSSatish Balay 
559e5c89e4eSSatish Balay   Level: intermediate
560e5c89e4eSSatish Balay 
561811af0c4SBarry Smith   Note:
562811af0c4SBarry Smith   REQUIRES a intervening call to `PetscSynchronizedFlush()` for the information
563e5c89e4eSSatish Balay   from all the processors to be printed.
564e5c89e4eSSatish Balay 
565*cc4c1da9SBarry Smith   Fortran Note:
566*cc4c1da9SBarry Smith   The call sequence is `PetscSynchronizedPrintf`(`MPI_Comm`, fp, `character`(*), `PetscErrorCode` ierr).
567*cc4c1da9SBarry Smith   That is, you can only pass a single character string from Fortran.
568*cc4c1da9SBarry Smith 
569db781477SPatrick Sanan .seealso: `PetscSynchronizedPrintf()`, `PetscSynchronizedFlush()`, `PetscFPrintf()`,
570c69effb2SJacob Faibussowitsch           `PetscFOpen()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
571c69effb2SJacob Faibussowitsch           `PetscFFlush()`
572e5c89e4eSSatish Balay @*/
573d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSynchronizedFPrintf(MPI_Comm comm, FILE *fp, const char format[], ...)
574d71ae5a4SJacob Faibussowitsch {
575eae3dc7dSJacob Faibussowitsch   va_list Argp;
576e5c89e4eSSatish Balay 
577e5c89e4eSSatish Balay   PetscFunctionBegin;
578e5c89e4eSSatish Balay   va_start(Argp, format);
579eae3dc7dSJacob Faibussowitsch   PetscCall(PetscSynchronizedFPrintf_Private(comm, fp, format, Argp));
580e5c89e4eSSatish Balay   va_end(Argp);
5813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
582e5c89e4eSSatish Balay }
583e5c89e4eSSatish Balay 
5840ec8b6e3SBarry Smith /*@C
585e5c89e4eSSatish Balay   PetscSynchronizedFlush - Flushes to the screen output from all processors
586811af0c4SBarry Smith   involved in previous `PetscSynchronizedPrintf()`/`PetscSynchronizedFPrintf()` calls.
587e5c89e4eSSatish Balay 
588d083f849SBarry Smith   Collective
589e5c89e4eSSatish Balay 
590e5c89e4eSSatish Balay   Input Parameters:
591058c9ee1SBarry Smith + comm - the MPI communicator
592a3b724e8SBarry Smith - fd   - the file pointer (valid on MPI rank 0 of the communicator), `PETSC_STDOUT` or value obtained from `PetscFOpen()`
593e5c89e4eSSatish Balay 
594e5c89e4eSSatish Balay   Level: intermediate
595e5c89e4eSSatish Balay 
596811af0c4SBarry Smith   Note:
597811af0c4SBarry Smith   If `PetscSynchronizedPrintf()` and/or `PetscSynchronizedFPrintf()` are called with
598811af0c4SBarry Smith   different MPI communicators there must be an intervening call to `PetscSynchronizedFlush()` between the calls with different MPI communicators.
599e5c89e4eSSatish Balay 
600db781477SPatrick Sanan .seealso: `PetscSynchronizedPrintf()`, `PetscFPrintf()`, `PetscPrintf()`, `PetscViewerASCIIPrintf()`,
601db781477SPatrick Sanan           `PetscViewerASCIISynchronizedPrintf()`
6020087d953SMatthew G. Knepley @*/
603d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSynchronizedFlush(MPI_Comm comm, FILE *fd)
604d71ae5a4SJacob Faibussowitsch {
60529a5cbdcSMatthew G. Knepley   PetscMPIInt rank, size, tag, i, j, n = 0, dummy = 0;
6062d609e63SMatthew Knepley   char       *message;
607e5c89e4eSSatish Balay   MPI_Status  status;
608e5c89e4eSSatish Balay 
609e5c89e4eSSatish Balay   PetscFunctionBegin;
6109566063dSJacob Faibussowitsch   PetscCall(PetscCommDuplicate(comm, &comm, &tag));
6119566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
6129566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
613e5c89e4eSSatish Balay 
614e5c89e4eSSatish Balay   /* First processor waits for messages from all other processors */
615dd400576SPatrick Sanan   if (rank == 0) {
6160ec8b6e3SBarry Smith     if (!fd) fd = PETSC_STDOUT;
617e5c89e4eSSatish Balay     for (i = 1; i < size; i++) {
6189f73f8ecSBarry Smith       /* to prevent a flood of messages to process zero, request each message separately */
6199566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Send(&dummy, 1, MPI_INT, i, tag, comm));
6209566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Recv(&n, 1, MPI_INT, i, tag, comm, &status));
621e5c89e4eSSatish Balay       for (j = 0; j < n; j++) {
62229a5cbdcSMatthew G. Knepley         PetscMPIInt size = 0;
6232d609e63SMatthew Knepley 
6249566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Recv(&size, 1, MPI_INT, i, tag, comm, &status));
6259566063dSJacob Faibussowitsch         PetscCall(PetscMalloc1(size, &message));
6269566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Recv(message, size, MPI_CHAR, i, tag, comm, &status));
6279566063dSJacob Faibussowitsch         PetscCall(PetscFPrintf(comm, fd, "%s", message));
6289566063dSJacob Faibussowitsch         PetscCall(PetscFree(message));
629e5c89e4eSSatish Balay       }
630e5c89e4eSSatish Balay     }
631e5c89e4eSSatish Balay   } else { /* other processors send queue to processor 0 */
632d30b0576SJed Brown     PrintfQueue next = petsc_printfqueuebase, previous;
633e5c89e4eSSatish Balay 
6349566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Recv(&dummy, 1, MPI_INT, 0, tag, comm, &status));
6359566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Send(&petsc_printfqueuelength, 1, MPI_INT, 0, tag, comm));
636d30b0576SJed Brown     for (i = 0; i < petsc_printfqueuelength; i++) {
6379566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Send(&next->size, 1, MPI_INT, 0, tag, comm));
6389566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Send(next->string, next->size, MPI_CHAR, 0, tag, comm));
639e5c89e4eSSatish Balay       previous = next;
640e5c89e4eSSatish Balay       next     = next->next;
6419566063dSJacob Faibussowitsch       PetscCall(PetscFree(previous->string));
6429566063dSJacob Faibussowitsch       PetscCall(PetscFree(previous));
643e5c89e4eSSatish Balay     }
64402c9f0b5SLisandro Dalcin     petsc_printfqueue       = NULL;
645d30b0576SJed Brown     petsc_printfqueuelength = 0;
646e5c89e4eSSatish Balay   }
6479566063dSJacob Faibussowitsch   PetscCall(PetscCommDestroy(&comm));
6483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
649e5c89e4eSSatish Balay }
650e5c89e4eSSatish Balay 
651e5c89e4eSSatish Balay /*@C
652e5c89e4eSSatish Balay   PetscFPrintf - Prints to a file, only from the first
65321532e8aSBarry Smith   MPI process in the communicator.
654e5c89e4eSSatish Balay 
655*cc4c1da9SBarry Smith   Not Collective
656e5c89e4eSSatish Balay 
657e5c89e4eSSatish Balay   Input Parameters:
658058c9ee1SBarry Smith + comm   - the MPI communicator
659*cc4c1da9SBarry Smith . fd     - the file pointer, `PETSC_STDOUT` or value obtained from `PetscFOpen()`
6606026c97aSBarry Smith - format - the usual `printf()` format string
661e5c89e4eSSatish Balay 
662e5c89e4eSSatish Balay   Level: intermediate
663e5c89e4eSSatish Balay 
664*cc4c1da9SBarry Smith   Fortran Note:
665*cc4c1da9SBarry Smith   The call sequence is `PetscFPrintf`(`MPI_Comm`, fp, `character`(*), `PetscErrorCode` ierr).
666*cc4c1da9SBarry Smith   That is, you can only pass a single character string from Fortran.
667*cc4c1da9SBarry Smith 
668aec76313SJacob Faibussowitsch   Developer Notes:
669058c9ee1SBarry Smith   This maybe, and is, called from PETSc error handlers and `PetscMallocValidate()` hence it does not use `PetscCallMPI()` which
670058c9ee1SBarry Smith   could recursively restart the malloc validation.
671058c9ee1SBarry Smith 
672db781477SPatrick Sanan .seealso: `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
673c69effb2SJacob Faibussowitsch           `PetscViewerASCIISynchronizedPrintf()`, `PetscSynchronizedFlush()`, `PetscFFlush()`
674e5c89e4eSSatish Balay @*/
675d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFPrintf(MPI_Comm comm, FILE *fd, const char format[], ...)
676d71ae5a4SJacob Faibussowitsch {
6778c509928SStefano Zampini   PetscMPIInt rank;
678eae3dc7dSJacob Faibussowitsch   va_list     Argp;
679e5c89e4eSSatish Balay 
680e5c89e4eSSatish Balay   PetscFunctionBegin;
6818c509928SStefano Zampini   PetscCallMPI(MPI_Comm_rank(comm, &rank));
6828c509928SStefano Zampini   if (PetscLikely(rank != 0)) PetscFunctionReturn(PETSC_SUCCESS);
683e5c89e4eSSatish Balay   va_start(Argp, format);
6848c509928SStefano Zampini   PetscCall(PetscVFPrintf_Private(fd, format, Argp));
685e5c89e4eSSatish Balay   va_end(Argp);
6863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
687e5c89e4eSSatish Balay }
688e5c89e4eSSatish Balay 
689e5c89e4eSSatish Balay /*@C
690e5c89e4eSSatish Balay   PetscPrintf - Prints to standard out, only from the first
69121532e8aSBarry Smith   MPI process in the communicator. Calls from other processes are ignored.
692e5c89e4eSSatish Balay 
693e5c89e4eSSatish Balay   Not Collective
694e5c89e4eSSatish Balay 
695e5c89e4eSSatish Balay   Input Parameters:
696e5c89e4eSSatish Balay + comm   - the communicator
697bfbbc7b7SBarry Smith - format - the usual `printf()` format string
698e5c89e4eSSatish Balay 
699e5c89e4eSSatish Balay   Level: intermediate
700e5c89e4eSSatish Balay 
701811af0c4SBarry Smith   Note:
702811af0c4SBarry Smith   Deprecated information: `PetscPrintf()` supports some format specifiers that are unique to PETSc.
703811af0c4SBarry Smith   See the manual page for `PetscFormatConvert()` for details.
704b2706f25SRichard Tran Mills 
705aec76313SJacob Faibussowitsch   Fortran Notes:
706811af0c4SBarry Smith   The call sequence is `PetscPrintf`(MPI_Comm, character(*), `PetscErrorCode` ierr) from Fortran.
707e5c89e4eSSatish Balay   That is, you can only pass a single character string from Fortran.
708e5c89e4eSSatish Balay 
709c69effb2SJacob Faibussowitsch .seealso: `PetscFPrintf()`, `PetscSynchronizedPrintf()`, `PetscFormatConvert()`, `PetscFFlush()`
710e5c89e4eSSatish Balay @*/
711d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscPrintf(MPI_Comm comm, const char format[], ...)
712d71ae5a4SJacob Faibussowitsch {
7138c509928SStefano Zampini   PetscMPIInt rank;
714eae3dc7dSJacob Faibussowitsch   va_list     Argp;
715e5c89e4eSSatish Balay 
716e5c89e4eSSatish Balay   PetscFunctionBegin;
7178c509928SStefano Zampini   PetscCallMPI(MPI_Comm_rank(comm, &rank));
7188c509928SStefano Zampini   if (PetscLikely(rank != 0)) PetscFunctionReturn(PETSC_SUCCESS);
719e5c89e4eSSatish Balay   va_start(Argp, format);
7208c509928SStefano Zampini   PetscCall(PetscVFPrintf_Private(PETSC_STDOUT, format, Argp));
721e5c89e4eSSatish Balay   va_end(Argp);
7223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
723e5c89e4eSSatish Balay }
724e5c89e4eSSatish Balay 
725d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscHelpPrintfDefault(MPI_Comm comm, const char format[], ...)
726d71ae5a4SJacob Faibussowitsch {
7278c509928SStefano Zampini   PetscMPIInt rank;
728eae3dc7dSJacob Faibussowitsch   va_list     Argp;
729e5c89e4eSSatish Balay 
730e5c89e4eSSatish Balay   PetscFunctionBegin;
7318c509928SStefano Zampini   PetscCallMPI(MPI_Comm_rank(comm, &rank));
7328c509928SStefano Zampini   if (PetscLikely(rank != 0)) PetscFunctionReturn(PETSC_SUCCESS);
733e5c89e4eSSatish Balay   va_start(Argp, format);
7348c509928SStefano Zampini   PetscCall(PetscVFPrintf_Private(PETSC_STDOUT, format, Argp));
735e5c89e4eSSatish Balay   va_end(Argp);
7363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
737e5c89e4eSSatish Balay }
738e5c89e4eSSatish Balay 
739e5c89e4eSSatish Balay /*@C
74021532e8aSBarry Smith   PetscSynchronizedFGets - Multiple MPI processes all get the same line from a file.
741e5c89e4eSSatish Balay 
742d083f849SBarry Smith   Collective
743e5c89e4eSSatish Balay 
744e5c89e4eSSatish Balay   Input Parameters:
74521532e8aSBarry Smith + comm - the MPI communicator
746aec76313SJacob Faibussowitsch . fp   - the file pointer
74721532e8aSBarry Smith - len  - the length of `string`
748e5c89e4eSSatish Balay 
749e5c89e4eSSatish Balay   Output Parameter:
75021532e8aSBarry Smith . string - the line read from the file, at end of file `string`[0] == 0
751e5c89e4eSSatish Balay 
752e5c89e4eSSatish Balay   Level: intermediate
753e5c89e4eSSatish Balay 
754db781477SPatrick Sanan .seealso: `PetscSynchronizedPrintf()`, `PetscSynchronizedFlush()`,
755db781477SPatrick Sanan           `PetscFOpen()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIPrintf()`
756e5c89e4eSSatish Balay @*/
757d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSynchronizedFGets(MPI_Comm comm, FILE *fp, size_t len, char string[])
758d71ae5a4SJacob Faibussowitsch {
759e5c89e4eSSatish Balay   PetscMPIInt rank;
760e5c89e4eSSatish Balay 
761e5c89e4eSSatish Balay   PetscFunctionBegin;
7629566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
76380971c97SJames Wright   if (rank == 0) {
764eae3dc7dSJacob Faibussowitsch     if (!fgets(string, len, fp)) {
765e31d4fa4SJed Brown       string[0] = 0;
766bf31d2d3SBarry Smith       PetscCheck(feof(fp), PETSC_COMM_SELF, PETSC_ERR_FILE_READ, "Error reading from file due to \"%s\"", strerror(errno));
767047b9c12SMatthew G Knepley     }
768238ccf28SShri Abhyankar   }
7699566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Bcast(string, len, MPI_BYTE, 0, comm));
7703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
771e5c89e4eSSatish Balay }
772238ccf28SShri Abhyankar 
773d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFormatRealArray(char buf[], size_t len, const char *fmt, PetscInt n, const PetscReal x[])
774d71ae5a4SJacob Faibussowitsch {
7751b5687a1SBarry Smith   PetscInt i;
7761b5687a1SBarry Smith   size_t   left, count;
7771b5687a1SBarry Smith   char    *p;
7781b5687a1SBarry Smith 
7791b5687a1SBarry Smith   PetscFunctionBegin;
7801b5687a1SBarry Smith   for (i = 0, p = buf, left = len; i < n; i++) {
7819566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintfCount(p, left, fmt, &count, (double)x[i]));
78208401ef6SPierre Jolivet     PetscCheck(count < left, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Insufficient space in buffer");
7831b5687a1SBarry Smith     left -= count;
7841b5687a1SBarry Smith     p += count - 1;
7851b5687a1SBarry Smith     *p++ = ' ';
7861b5687a1SBarry Smith   }
7871b5687a1SBarry Smith   p[i ? 0 : -1] = 0;
7883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7891b5687a1SBarry Smith }
790