xref: /petsc/src/sys/fileio/mprint.c (revision 2baa9ef6816826e6b4e7775b5d1339a2a014d97e)
1 /*
2       Utilites routines to add simple ASCII IO capability.
3 */
4 #include <../src/sys/fileio/mprint.h>
5 #include <errno.h>
6 /*
7    If petsc_history is on, then all Petsc*Printf() results are saved
8    if the appropriate (usually .petschistory) file.
9 */
10 extern FILE *petsc_history;
11 /*
12      Allows one to overwrite where standard out is sent. For example
13      PETSC_STDOUT = fopen("/dev/ttyXX","w") will cause all standard out
14      writes to go to terminal XX; assuming you have write permission there
15 */
16 FILE *PETSC_STDOUT = 0;
17 /*
18      Allows one to overwrite where standard error is sent. For example
19      PETSC_STDERR = fopen("/dev/ttyXX","w") will cause all standard error
20      writes to go to terminal XX; assuming you have write permission there
21 */
22 FILE *PETSC_STDERR = 0;
23 
24 /*@C
25      PetscFormatConvertGetSize - Gets the length of a string needed to hold format converted with PetscFormatConvert()
26 
27    Input Parameter:
28 .   format - the PETSc format string
29 
30    Output Parameter:
31 .   size - the needed length of the new format
32 
33  Level: developer
34 
35 .seealso: PetscFormatConvert(), PetscVSNPrintf(), PetscVFPrintf()
36 
37 @*/
38 PetscErrorCode PetscFormatConvertGetSize(const char *format,size_t *size)
39 {
40   PetscInt i = 0;
41 
42   PetscFunctionBegin;
43   *size = 0;
44   while (format[i]) {
45     if (format[i] == '%' && format[i+1] == '%') {
46       i++; i++; *size += 2;
47     } else if (format[i] == '%') {
48       /* Find the letter */
49       for (; format[i] && format[i] <= '9'; i++,(*size += 1));
50       switch (format[i]) {
51       case 'D':
52 #if defined(PETSC_USE_64BIT_INDICES)
53         *size += 2;
54 #endif
55         break;
56       case 'g':
57         *size += 4;
58         break;
59       default:
60         break;
61       }
62       *size += 1;
63       i++;
64     } else {
65       i++;
66       *size += 1;
67     }
68   }
69   *size += 1; /* space for NULL character */
70   PetscFunctionReturn(0);
71 }
72 
73 /*@C
74      PetscFormatConvert - Takes a PETSc format string and converts the %D to %d for 32 bit PETSc indices and %lld for 64 bit PETSc indices. Also
75                         converts %g to [|%g|] so that PetscVSNPrintf() can easily insure all %g formatted numbers have a decimal point when printed.
76 
77    Input Parameters:
78 +   format - the PETSc format string
79 .   newformat - the location to put the new format
80 -   size - the length of newformat, you can use PetscFormatConvertGetSize() to compute the needed size
81 
82     Note: this exists so we can have the same code when PetscInt is either int or long long int
83 
84  Level: developer
85 
86 .seealso: PetscFormatConvertGetSize(), PetscVSNPrintf(), PetscVFPrintf()
87 
88 @*/
89 PetscErrorCode PetscFormatConvert(const char *format,char *newformat)
90 {
91   PetscInt i = 0, j = 0;
92 
93   PetscFunctionBegin;
94   while (format[i]) {
95     if (format[i] == '%' && format[i+1] == '%') {
96       newformat[j++] = format[i++];
97       newformat[j++] = format[i++];
98     } else if (format[i] == '%') {
99       if (format[i+1] == 'g') {
100         newformat[j++] = '[';
101         newformat[j++] = '|';
102       }
103       /* Find the letter */
104       for (; format[i] && format[i] <= '9'; i++) newformat[j++] = format[i];
105       switch (format[i]) {
106       case 'D':
107 #if !defined(PETSC_USE_64BIT_INDICES)
108         newformat[j++] = 'd';
109 #else
110         newformat[j++] = 'l';
111         newformat[j++] = 'l';
112         newformat[j++] = 'd';
113 #endif
114         break;
115       case 'g':
116         newformat[j++] = format[i];
117         if (format[i-1] == '%') {
118           newformat[j++] = '|';
119           newformat[j++] = ']';
120         }
121         break;
122       case 'G':
123         SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"%%G format is no longer supported, use %%g and cast the argument to double");
124         break;
125       case 'F':
126         SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"%%F format is no longer supported, use %%f and cast the argument to double");
127         break;
128       default:
129         newformat[j++] = format[i];
130         break;
131       }
132       i++;
133     } else newformat[j++] = format[i++];
134   }
135   newformat[j] = 0;
136   PetscFunctionReturn(0);
137 }
138 
139 #define PETSCDEFAULTBUFFERSIZE 8*1024
140 
141 /*@C
142      PetscVSNPrintf - The PETSc version of vsnprintf(). Converts a PETSc format string into a standard C format string and then puts all the
143        function arguments into a string using the format statement.
144 
145    Input Parameters:
146 +   str - location to put result
147 .   len - the amount of space in str
148 +   format - the PETSc format string
149 -   fullLength - the amount of space in str actually used.
150 
151     Developer Notes: this function may be called from an error handler, if an error occurs when it is called by the error handler than likely
152       a recursion will occur and possible crash.
153 
154  Level: developer
155 
156 .seealso: PetscVSNPrintf(), PetscErrorPrintf(), PetscVPrintf()
157 
158 @*/
159 PetscErrorCode PetscVSNPrintf(char *str,size_t len,const char *format,size_t *fullLength,va_list Argp)
160 {
161   char           *newformat = NULL;
162   char           formatbuf[PETSCDEFAULTBUFFERSIZE];
163   size_t         newLength;
164   PetscErrorCode ierr;
165   int            flen;
166 
167   PetscFunctionBegin;
168   ierr = PetscFormatConvertGetSize(format,&newLength);CHKERRQ(ierr);
169   if (newLength < PETSCDEFAULTBUFFERSIZE) {
170     newformat = formatbuf;
171     newLength = PETSCDEFAULTBUFFERSIZE-1;
172   } else {
173     ierr      = PetscMalloc1(newLength, &newformat);CHKERRQ(ierr);
174   }
175   ierr = PetscFormatConvert(format,newformat);CHKERRQ(ierr);
176 #if defined(PETSC_HAVE_VSNPRINTF_CHAR)
177   flen = (size_t) vsnprintf(str,len,newformat,(char*)Argp);
178 #elif defined(PETSC_HAVE_VSNPRINTF)
179   flen = (size_t) vsnprintf(str,len,newformat,Argp);
180 #elif defined(PETSC_HAVE__VSNPRINTF)
181   flen = (size_t) _vsnprintf(str,len,newformat,Argp);
182 #else
183 #error "vsnprintf not found"
184 #endif
185   if (fullLength) *fullLength = 1 + (size_t) flen;
186   if (newLength > PETSCDEFAULTBUFFERSIZE-1) {
187     ierr = PetscFree(newformat);CHKERRQ(ierr);
188   }
189   {
190     PetscBool foundedot;
191     size_t cnt = 0,ncnt = 0,leng;
192     ierr = PetscStrlen(str,&leng);CHKERRQ(ierr);
193     if (leng > 4) {
194       for (cnt=0; cnt<leng-4; cnt++) {
195         if (str[cnt] == '[' && str[cnt+1] == '|'){
196            cnt++; cnt++;
197            foundedot = PETSC_FALSE;
198            for (; cnt<leng-1; cnt++) {
199              if (str[cnt] == '|' && str[cnt+1] == ']'){
200                cnt++;
201                if (!foundedot) str[ncnt++] = '.';
202                ncnt--;
203                break;
204              } else {
205                if (str[cnt] == 'e' || str[cnt] == '.') foundedot = PETSC_TRUE;
206                str[ncnt++] = str[cnt];
207              }
208            }
209         } else {
210           str[ncnt] = str[cnt];
211         }
212         ncnt++;
213       }
214       while (cnt < leng) {
215         str[ncnt] = str[cnt]; ncnt++; cnt++;
216       }
217       str[ncnt] = 0;
218     }
219   }
220 #if defined(PETSC_HAVE_WINDOWS_H) && !defined(PETSC_HAVE__SET_OUTPUT_FORMAT)
221   /* older Windows OS always produces e-+0np for floating point output; remove the extra 0 */
222   {
223     size_t cnt = 0,ncnt = 0,leng;
224     ierr = PetscStrlen(str,&leng);CHKERRQ(ierr);
225     if (leng > 5) {
226       for (cnt=0; cnt<leng-4; cnt++) {
227         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') {
228           str[ncnt] = str[cnt]; ncnt++; cnt++;
229           str[ncnt] = str[cnt]; ncnt++; cnt++; cnt++;
230           str[ncnt] = str[cnt];
231         } else {
232           str[ncnt] = str[cnt];
233         }
234         ncnt++;
235       }
236       while (cnt < leng) {
237         str[ncnt] = str[cnt]; ncnt++; cnt++;
238       }
239       str[ncnt] = 0;
240     }
241   }
242 #endif
243   PetscFunctionReturn(0);
244 }
245 
246 /*@C
247      PetscVFPrintf -  All PETSc standard out and error messages are sent through this function; so, in theory, this can
248         can be replaced with something that does not simply write to a file.
249 
250       To use, write your own function for example,
251 $PetscErrorCode mypetscvfprintf(FILE *fd,const char format[],va_list Argp)
252 ${
253 $  PetscErrorCode ierr;
254 $
255 $  PetscFunctionBegin;
256 $   if (fd != stdout && fd != stderr) {  handle regular files
257 $      ierr = PetscVFPrintfDefault(fd,format,Argp);CHKERR(ierr);
258 $  } else {
259 $     char   buff[BIG];
260 $     size_t length;
261 $     ierr = PetscVSNPrintf(buff,BIG,format,&length,Argp);CHKERRQ(ierr);
262 $     now send buff to whatever stream or whatever you want
263 $ }
264 $ PetscFunctionReturn(0);
265 $}
266 then before the call to PetscInitialize() do the assignment
267 $    PetscVFPrintf = mypetscvfprintf;
268 
269       Notes: For error messages this may be called by any process, for regular standard out it is
270           called only by process 0 of a given communicator
271 
272       Developer Notes: this could be called by an error handler, if that happens then a recursion of the error handler may occur
273                        and a crash
274 
275   Level:  developer
276 
277 .seealso: PetscVSNPrintf(), PetscErrorPrintf()
278 
279 @*/
280 PetscErrorCode PetscVFPrintfDefault(FILE *fd,const char *format,va_list Argp)
281 {
282   char           str[PETSCDEFAULTBUFFERSIZE];
283   char           *buff = str;
284   size_t         fullLength;
285   PetscErrorCode ierr;
286 #if defined(PETSC_HAVE_VA_COPY)
287   va_list        Argpcopy;
288 #endif
289 
290   PetscFunctionBegin;
291 #if defined(PETSC_HAVE_VA_COPY)
292   va_copy(Argpcopy,Argp);
293 #endif
294   ierr = PetscVSNPrintf(str,sizeof(str),format,&fullLength,Argp);CHKERRQ(ierr);
295   if (fullLength > sizeof(str)) {
296     ierr = PetscMalloc1(fullLength,&buff);CHKERRQ(ierr);
297 #if defined(PETSC_HAVE_VA_COPY)
298     ierr = PetscVSNPrintf(buff,fullLength,format,NULL,Argpcopy);CHKERRQ(ierr);
299 #else
300     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"C89 does not support va_copy() hence cannot print long strings with PETSc printing routines");
301 #endif
302   }
303   fprintf(fd,"%s",buff);CHKERRQ(ierr);
304   fflush(fd);
305   if (buff != str) {
306     ierr = PetscFree(buff);CHKERRQ(ierr);
307   }
308   PetscFunctionReturn(0);
309 }
310 
311 /*@C
312     PetscSNPrintf - Prints to a string of given length
313 
314     Not Collective
315 
316     Input Parameters:
317 +   str - the string to print to
318 .   len - the length of str
319 .   format - the usual printf() format string
320 -   any arguments
321 
322    Level: intermediate
323 
324 .seealso: PetscSynchronizedFlush(), PetscSynchronizedFPrintf(), PetscFPrintf(), PetscVSNPrintf(),
325           PetscPrintf(), PetscViewerASCIIPrintf(), PetscViewerASCIISynchronizedPrintf(), PetscVFPrintf()
326 @*/
327 PetscErrorCode PetscSNPrintf(char *str,size_t len,const char format[],...)
328 {
329   PetscErrorCode ierr;
330   size_t         fullLength;
331   va_list        Argp;
332 
333   PetscFunctionBegin;
334   va_start(Argp,format);
335   ierr = PetscVSNPrintf(str,len,format,&fullLength,Argp);CHKERRQ(ierr);
336   PetscFunctionReturn(0);
337 }
338 
339 /*@C
340     PetscSNPrintfCount - Prints to a string of given length, returns count
341 
342     Not Collective
343 
344     Input Parameters:
345 +   str - the string to print to
346 .   len - the length of str
347 .   format - the usual printf() format string
348 .   countused - number of characters used
349 -   any arguments
350 
351    Level: intermediate
352 
353 .seealso: PetscSynchronizedFlush(), PetscSynchronizedFPrintf(), PetscFPrintf(), PetscVSNPrintf(),
354           PetscPrintf(), PetscViewerASCIIPrintf(), PetscViewerASCIISynchronizedPrintf(), PetscSNPrintf(), PetscVFPrintf()
355 @*/
356 PetscErrorCode PetscSNPrintfCount(char *str,size_t len,const char format[],size_t *countused,...)
357 {
358   PetscErrorCode ierr;
359   va_list        Argp;
360 
361   PetscFunctionBegin;
362   va_start(Argp,countused);
363   ierr = PetscVSNPrintf(str,len,format,countused,Argp);CHKERRQ(ierr);
364   PetscFunctionReturn(0);
365 }
366 
367 /* ----------------------------------------------------------------------- */
368 
369 PrintfQueue petsc_printfqueue       = 0,petsc_printfqueuebase = 0;
370 int         petsc_printfqueuelength = 0;
371 
372 /*@C
373     PetscSynchronizedPrintf - Prints synchronized output from several processors.
374     Output of the first processor is followed by that of the second, etc.
375 
376     Not Collective
377 
378     Input Parameters:
379 +   comm - the communicator
380 -   format - the usual printf() format string
381 
382    Level: intermediate
383 
384     Notes:
385     REQUIRES a call to PetscSynchronizedFlush() by all the processes after the completion of the calls to PetscSynchronizedPrintf() for the information
386     from all the processors to be printed.
387 
388     Fortran Note:
389     The call sequence is PetscSynchronizedPrintf(MPI_Comm, character(*), PetscErrorCode ierr) from Fortran.
390     That is, you can only pass a single character string from Fortran.
391 
392 .seealso: PetscSynchronizedFlush(), PetscSynchronizedFPrintf(), PetscFPrintf(),
393           PetscPrintf(), PetscViewerASCIIPrintf(), PetscViewerASCIISynchronizedPrintf()
394 @*/
395 PetscErrorCode PetscSynchronizedPrintf(MPI_Comm comm,const char format[],...)
396 {
397   PetscErrorCode ierr;
398   PetscMPIInt    rank;
399 
400   PetscFunctionBegin;
401   if (comm == MPI_COMM_NULL) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Called with MPI_COMM_NULL, likely PetscObjectComm() failed");
402   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
403 
404   /* First processor prints immediately to stdout */
405   if (!rank) {
406     va_list Argp;
407     va_start(Argp,format);
408     ierr = (*PetscVFPrintf)(PETSC_STDOUT,format,Argp);CHKERRQ(ierr);
409     if (petsc_history) {
410       va_start(Argp,format);
411       ierr = (*PetscVFPrintf)(petsc_history,format,Argp);CHKERRQ(ierr);
412     }
413     va_end(Argp);
414   } else { /* other processors add to local queue */
415     va_list     Argp;
416     PrintfQueue next;
417     size_t      fullLength = PETSCDEFAULTBUFFERSIZE;
418 
419     ierr = PetscNew(&next);CHKERRQ(ierr);
420     if (petsc_printfqueue) {
421       petsc_printfqueue->next = next;
422       petsc_printfqueue       = next;
423       petsc_printfqueue->next = 0;
424     } else petsc_printfqueuebase = petsc_printfqueue = next;
425     petsc_printfqueuelength++;
426     next->size   = -1;
427     next->string = NULL;
428     while ((PetscInt)fullLength >= next->size) {
429       next->size = fullLength+1;
430       ierr = PetscFree(next->string);CHKERRQ(ierr);
431       ierr = PetscMalloc1(next->size, &next->string);CHKERRQ(ierr);
432       va_start(Argp,format);
433       ierr = PetscMemzero(next->string,next->size);CHKERRQ(ierr);
434       ierr = PetscVSNPrintf(next->string,next->size,format, &fullLength,Argp);CHKERRQ(ierr);
435       va_end(Argp);
436     }
437   }
438   PetscFunctionReturn(0);
439 }
440 
441 /*@C
442     PetscSynchronizedFPrintf - Prints synchronized output to the specified file from
443     several processors.  Output of the first processor is followed by that of the
444     second, etc.
445 
446     Not Collective
447 
448     Input Parameters:
449 +   comm - the communicator
450 .   fd - the file pointer
451 -   format - the usual printf() format string
452 
453     Level: intermediate
454 
455     Notes:
456     REQUIRES a intervening call to PetscSynchronizedFlush() for the information
457     from all the processors to be printed.
458 
459 .seealso: PetscSynchronizedPrintf(), PetscSynchronizedFlush(), PetscFPrintf(),
460           PetscFOpen(), PetscViewerASCIISynchronizedPrintf(), PetscViewerASCIIPrintf()
461 
462 @*/
463 PetscErrorCode PetscSynchronizedFPrintf(MPI_Comm comm,FILE *fp,const char format[],...)
464 {
465   PetscErrorCode ierr;
466   PetscMPIInt    rank;
467 
468   PetscFunctionBegin;
469   if (comm == MPI_COMM_NULL) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Called with MPI_COMM_NULL, likely PetscObjectComm() failed");
470   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
471 
472   /* First processor prints immediately to fp */
473   if (!rank) {
474     va_list Argp;
475     va_start(Argp,format);
476     ierr = (*PetscVFPrintf)(fp,format,Argp);CHKERRQ(ierr);
477     if (petsc_history && (fp !=petsc_history)) {
478       va_start(Argp,format);
479       ierr = (*PetscVFPrintf)(petsc_history,format,Argp);CHKERRQ(ierr);
480     }
481     va_end(Argp);
482   } else { /* other processors add to local queue */
483     va_list     Argp;
484     PrintfQueue next;
485     size_t      fullLength = PETSCDEFAULTBUFFERSIZE;
486 
487     ierr = PetscNew(&next);CHKERRQ(ierr);
488     if (petsc_printfqueue) {
489       petsc_printfqueue->next = next;
490       petsc_printfqueue       = next;
491       petsc_printfqueue->next = 0;
492     } else petsc_printfqueuebase = petsc_printfqueue = next;
493     petsc_printfqueuelength++;
494     next->size   = -1;
495     next->string = NULL;
496     while ((PetscInt)fullLength >= next->size) {
497       next->size = fullLength+1;
498       ierr = PetscFree(next->string);CHKERRQ(ierr);
499       ierr = PetscMalloc1(next->size, &next->string);CHKERRQ(ierr);
500       va_start(Argp,format);
501       ierr = PetscMemzero(next->string,next->size);CHKERRQ(ierr);
502       ierr = PetscVSNPrintf(next->string,next->size,format,&fullLength,Argp);CHKERRQ(ierr);
503       va_end(Argp);
504     }
505   }
506   PetscFunctionReturn(0);
507 }
508 
509 /*@C
510     PetscSynchronizedFlush - Flushes to the screen output from all processors
511     involved in previous PetscSynchronizedPrintf()/PetscSynchronizedFPrintf() calls.
512 
513     Collective on MPI_Comm
514 
515     Input Parameters:
516 +   comm - the communicator
517 -   fd - the file pointer (valid on process 0 of the communicator)
518 
519     Level: intermediate
520 
521     Notes:
522     If PetscSynchronizedPrintf() and/or PetscSynchronizedFPrintf() are called with
523     different MPI communicators there must be an intervening call to PetscSynchronizedFlush() between the calls with different MPI communicators.
524 
525     From Fortran pass PETSC_STDOUT if the flush is for standard out; otherwise pass a value obtained from PetscFOpen()
526 
527 .seealso: PetscSynchronizedPrintf(), PetscFPrintf(), PetscPrintf(), PetscViewerASCIIPrintf(),
528           PetscViewerASCIISynchronizedPrintf()
529 @*/
530 PetscErrorCode PetscSynchronizedFlush(MPI_Comm comm,FILE *fd)
531 {
532   PetscErrorCode ierr;
533   PetscMPIInt    rank,size,tag,i,j,n = 0,dummy = 0;
534   char          *message;
535   MPI_Status     status;
536 
537   PetscFunctionBegin;
538   ierr = PetscCommDuplicate(comm,&comm,&tag);CHKERRQ(ierr);
539   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
540   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
541 
542   /* First processor waits for messages from all other processors */
543   if (!rank) {
544     if (!fd) fd = PETSC_STDOUT;
545     for (i=1; i<size; i++) {
546       /* to prevent a flood of messages to process zero, request each message separately */
547       ierr = MPI_Send(&dummy,1,MPI_INT,i,tag,comm);CHKERRQ(ierr);
548       ierr = MPI_Recv(&n,1,MPI_INT,i,tag,comm,&status);CHKERRQ(ierr);
549       for (j=0; j<n; j++) {
550         PetscMPIInt size = 0;
551 
552         ierr = MPI_Recv(&size,1,MPI_INT,i,tag,comm,&status);CHKERRQ(ierr);
553         ierr = PetscMalloc1(size, &message);CHKERRQ(ierr);
554         ierr = MPI_Recv(message,size,MPI_CHAR,i,tag,comm,&status);CHKERRQ(ierr);
555         ierr = PetscFPrintf(comm,fd,"%s",message);CHKERRQ(ierr);
556         ierr = PetscFree(message);CHKERRQ(ierr);
557       }
558     }
559   } else { /* other processors send queue to processor 0 */
560     PrintfQueue next = petsc_printfqueuebase,previous;
561 
562     ierr = MPI_Recv(&dummy,1,MPI_INT,0,tag,comm,&status);CHKERRQ(ierr);
563     ierr = MPI_Send(&petsc_printfqueuelength,1,MPI_INT,0,tag,comm);CHKERRQ(ierr);
564     for (i=0; i<petsc_printfqueuelength; i++) {
565       ierr     = MPI_Send(&next->size,1,MPI_INT,0,tag,comm);CHKERRQ(ierr);
566       ierr     = MPI_Send(next->string,next->size,MPI_CHAR,0,tag,comm);CHKERRQ(ierr);
567       previous = next;
568       next     = next->next;
569       ierr     = PetscFree(previous->string);CHKERRQ(ierr);
570       ierr     = PetscFree(previous);CHKERRQ(ierr);
571     }
572     petsc_printfqueue       = 0;
573     petsc_printfqueuelength = 0;
574   }
575   ierr = PetscCommDestroy(&comm);CHKERRQ(ierr);
576   PetscFunctionReturn(0);
577 }
578 
579 /* ---------------------------------------------------------------------------------------*/
580 
581 /*@C
582     PetscFPrintf - Prints to a file, only from the first
583     processor in the communicator.
584 
585     Not Collective
586 
587     Input Parameters:
588 +   comm - the communicator
589 .   fd - the file pointer
590 -   format - the usual printf() format string
591 
592     Level: intermediate
593 
594     Fortran Note:
595     This routine is not supported in Fortran.
596 
597    Concepts: printing^in parallel
598    Concepts: printf^in parallel
599 
600 .seealso: PetscPrintf(), PetscSynchronizedPrintf(), PetscViewerASCIIPrintf(),
601           PetscViewerASCIISynchronizedPrintf(), PetscSynchronizedFlush()
602 @*/
603 PetscErrorCode PetscFPrintf(MPI_Comm comm,FILE* fd,const char format[],...)
604 {
605   PetscErrorCode ierr;
606   PetscMPIInt    rank;
607 
608   PetscFunctionBegin;
609   if (comm == MPI_COMM_NULL) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Called with MPI_COMM_NULL, likely PetscObjectComm() failed");
610   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
611   if (!rank) {
612     va_list Argp;
613     va_start(Argp,format);
614     ierr = (*PetscVFPrintf)(fd,format,Argp);CHKERRQ(ierr);
615     if (petsc_history && (fd !=petsc_history)) {
616       va_start(Argp,format);
617       ierr = (*PetscVFPrintf)(petsc_history,format,Argp);CHKERRQ(ierr);
618     }
619     va_end(Argp);
620   }
621   PetscFunctionReturn(0);
622 }
623 
624 /*@C
625     PetscPrintf - Prints to standard out, only from the first
626     processor in the communicator. Calls from other processes are ignored.
627 
628     Not Collective
629 
630     Input Parameters:
631 +   comm - the communicator
632 -   format - the usual printf() format string
633 
634    Level: intermediate
635 
636     Fortran Note:
637     The call sequence is PetscPrintf(MPI_Comm, character(*), PetscErrorCode ierr) from Fortran.
638     That is, you can only pass a single character string from Fortran.
639 
640    Concepts: printing^in parallel
641    Concepts: printf^in parallel
642 
643 .seealso: PetscFPrintf(), PetscSynchronizedPrintf()
644 @*/
645 PetscErrorCode PetscPrintf(MPI_Comm comm,const char format[],...)
646 {
647   PetscErrorCode ierr;
648   PetscMPIInt    rank;
649 
650   PetscFunctionBegin;
651   if (comm == MPI_COMM_NULL) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Called with MPI_COMM_NULL, likely PetscObjectComm() failed");
652   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
653   if (!rank) {
654     va_list Argp;
655     va_start(Argp,format);
656     ierr = (*PetscVFPrintf)(PETSC_STDOUT,format,Argp);CHKERRQ(ierr);
657     if (petsc_history) {
658       va_start(Argp,format);
659       ierr = (*PetscVFPrintf)(petsc_history,format,Argp);CHKERRQ(ierr);
660     }
661     va_end(Argp);
662   }
663   PetscFunctionReturn(0);
664 }
665 
666 /* ---------------------------------------------------------------------------------------*/
667 /*@C
668      PetscHelpPrintf -  All PETSc help messages are passing through this function. You can change how help messages are printed by
669         replacinng it  with something that does not simply write to a stdout.
670 
671       To use, write your own function for example,
672 $PetscErrorCode mypetschelpprintf(MPI_Comm comm,const char format[],....)
673 ${
674 $ PetscFunctionReturn(0);
675 $}
676 then before the call to PetscInitialize() do the assignment
677 $    PetscHelpPrintf = mypetschelpprintf;
678 
679   Note: the default routine used is called PetscHelpPrintfDefault().
680 
681   Level:  developer
682 
683 .seealso: PetscVSNPrintf(), PetscVFPrintf(), PetscErrorPrintf()
684 @*/
685 PetscErrorCode PetscHelpPrintfDefault(MPI_Comm comm,const char format[],...)
686 {
687   PetscErrorCode ierr;
688   PetscMPIInt    rank;
689 
690   PetscFunctionBegin;
691   if (comm == MPI_COMM_NULL) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Called with MPI_COMM_NULL, likely PetscObjectComm() failed");
692   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
693   if (!rank) {
694     va_list Argp;
695     va_start(Argp,format);
696     ierr = (*PetscVFPrintf)(PETSC_STDOUT,format,Argp);CHKERRQ(ierr);
697     if (petsc_history) {
698       va_start(Argp,format);
699       ierr = (*PetscVFPrintf)(petsc_history,format,Argp);CHKERRQ(ierr);
700     }
701     va_end(Argp);
702   }
703   PetscFunctionReturn(0);
704 }
705 
706 /* ---------------------------------------------------------------------------------------*/
707 
708 
709 /*@C
710     PetscSynchronizedFGets - Several processors all get the same line from a file.
711 
712     Collective on MPI_Comm
713 
714     Input Parameters:
715 +   comm - the communicator
716 .   fd - the file pointer
717 -   len - the length of the output buffer
718 
719     Output Parameter:
720 .   string - the line read from the file, at end of file string[0] == 0
721 
722     Level: intermediate
723 
724 .seealso: PetscSynchronizedPrintf(), PetscSynchronizedFlush(),
725           PetscFOpen(), PetscViewerASCIISynchronizedPrintf(), PetscViewerASCIIPrintf()
726 
727 @*/
728 PetscErrorCode PetscSynchronizedFGets(MPI_Comm comm,FILE *fp,size_t len,char string[])
729 {
730   PetscErrorCode ierr;
731   PetscMPIInt    rank;
732 
733   PetscFunctionBegin;
734   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
735 
736   if (!rank) {
737     char *ptr = fgets(string, len, fp);
738 
739     if (!ptr) {
740       string[0] = 0;
741       if (!feof(fp)) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_FILE_READ, "Error reading from file: %d", errno);
742     }
743   }
744   ierr = MPI_Bcast(string,len,MPI_BYTE,0,comm);CHKERRQ(ierr);
745   PetscFunctionReturn(0);
746 }
747 
748 #if defined(PETSC_HAVE_CLOSURES)
749 int (^SwiftClosure)(const char*) = 0;
750 
751 PetscErrorCode PetscVFPrintfToString(FILE *fd,const char format[],va_list Argp)
752 {
753   PetscErrorCode ierr;
754 
755   PetscFunctionBegin;
756   if (fd != stdout && fd != stderr) { /* handle regular files */
757     ierr = PetscVFPrintfDefault(fd,format,Argp);CHKERRQ(ierr);
758   } else {
759     size_t length;
760     char   buff[PETSCDEFAULTBUFFERSIZE];
761 
762     ierr = PetscVSNPrintf(buf,size(buff),format,&length,Argp);CHKERRQ(ierr);
763     ierr = SwiftClosure(buff);CHKERRQ(ierr);
764   }
765   PetscFunctionReturn(0);
766 }
767 
768 /*
769    Provide a Swift function that processes all the PETSc calls to PetscVFPrintf()
770 */
771 PetscErrorCode PetscVFPrintfSetClosure(int (^closure)(const char*))
772 {
773   PetscVFPrintf = PetscVFPrintfToString;
774   SwiftClosure  = closure;
775   return 0;
776 }
777 #endif
778 
779 #if defined(PETSC_HAVE_MATLAB_ENGINE)
780 #include <mex.h>
781 PetscErrorCode PetscVFPrintf_Matlab(FILE *fd,const char format[],va_list Argp)
782 {
783   PetscErrorCode ierr;
784 
785   PetscFunctionBegin;
786   if (fd != stdout && fd != stderr) { /* handle regular files */
787     ierr = PetscVFPrintfDefault(fd,format,Argp);CHKERRQ(ierr);
788   } else {
789     size_t length;
790     char   buff[length];
791 
792     ierr = PetscVSNPrintf(buff,sizeof(buff),format,&length,Argp);CHKERRQ(ierr);
793     mexPrintf("%s",buff);
794   }
795   PetscFunctionReturn(0);
796 }
797 #endif
798 
799 /*@C
800      PetscFormatStrip - Takes a PETSc format string and removes all numerical modifiers to % operations
801 
802    Input Parameters:
803 .   format - the PETSc format string
804 
805  Level: developer
806 
807 @*/
808 PetscErrorCode PetscFormatStrip(char *format)
809 {
810   size_t loc1 = 0, loc2 = 0;
811 
812   PetscFunctionBegin;
813   while (format[loc2]) {
814     if (format[loc2] == '%') {
815       format[loc1++] = format[loc2++];
816       while (format[loc2] && ((format[loc2] >= '0' && format[loc2] <= '9') || format[loc2] == '.')) loc2++;
817     }
818     format[loc1++] = format[loc2++];
819   }
820   PetscFunctionReturn(0);
821 }
822 
823 PetscErrorCode PetscFormatRealArray(char buf[],size_t len,const char *fmt,PetscInt n,const PetscReal x[])
824 {
825   PetscErrorCode ierr;
826   PetscInt       i;
827   size_t         left,count;
828   char           *p;
829 
830   PetscFunctionBegin;
831   for (i=0,p=buf,left=len; i<n; i++) {
832     ierr = PetscSNPrintfCount(p,left,fmt,&count,(double)x[i]);CHKERRQ(ierr);
833     if (count >= left) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Insufficient space in buffer");
834     left -= count;
835     p    += count-1;
836     *p++  = ' ';
837   }
838   p[i ? 0 : -1] = 0;
839   PetscFunctionReturn(0);
840 }
841