xref: /petsc/src/sys/fileio/mprint.c (revision 3bf036e263fd78807e2931ff42d9ddcd8aae3fd4)
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 /*
25      Return the maximum expected new size of the format
26 */
27 #define PETSC_MAX_LENGTH_FORMAT(l) (l+l/8)
28 
29 #undef __FUNCT__
30 #define __FUNCT__ "PetscFormatConvert"
31 /*@C
32      PetscFormatConvert - Takes a PETSc format string and converts it to a reqular C format string
33 
34    Input Parameters:
35 +   format - the PETSc format string
36 .   newformat - the location to put the standard C format string values
37 -   size - the length of newformat
38 
39     Note: this exists so we can have the same code when PetscInt is either int or long long and PetscScalar is either __float128, double, or float
40 
41  Level: developer
42 
43 @*/
44 PetscErrorCode  PetscFormatConvert(const char *format,char *newformat,size_t size)
45 {
46   PetscInt i = 0,j = 0;
47 
48   PetscFunctionBegin;
49   while (format[i] && j < (PetscInt)size-1) {
50     if (format[i] == '%' && format[i+1] != '%') {
51       /* Find the letter */
52       for ( ; format[i] && format[i] <= '9'; i++) newformat[j++] = format[i];
53       switch (format[i]) {
54       case 'D':
55 #if !defined(PETSC_USE_64BIT_INDICES)
56         newformat[j++] = 'd';
57 #else
58         newformat[j++] = 'l';
59         newformat[j++] = 'l';
60         newformat[j++] = 'd';
61 #endif
62         break;
63       case 'G':
64 #if defined(PETSC_USE_REAL_DOUBLE) || defined(PETSC_USE_REAL_SINGLE)
65         newformat[j++] = 'g';
66 #elif defined(PETSC_USE_REAL___FLOAT128)
67         newformat[j++] = 'Q';
68         newformat[j++] = 'g';
69 #endif
70         break;
71       case 'F':
72 #if defined(PETSC_USE_REAL_DOUBLE) || defined(PETSC_USE_REAL_SINGLE)
73         newformat[j++] = 'f';
74 #elif defined(PETSC_USE_REAL_LONG_DOUBLE)
75         newformat[j++] = 'L';
76         newformat[j++] = 'f';
77 #elif defined(PETSC_USE_REAL___FLOAT128)
78         newformat[j++] = 'Q';
79         newformat[j++] = 'f';
80 #endif
81         break;
82       default:
83         newformat[j++] = format[i];
84         break;
85       }
86       i++;
87     } else {
88       newformat[j++] = format[i++];
89     }
90   }
91   newformat[j] = 0;
92   PetscFunctionReturn(0);
93 }
94 
95 #undef __FUNCT__
96 #define __FUNCT__ "PetscVSNPrintf"
97 /*@C
98      PetscVSNPrintf - The PETSc version of vsnprintf(). Converts a PETSc format string into a standard C format string and then puts all the
99        function arguments into a string using the format statement.
100 
101    Input Parameters:
102 +   str - location to put result
103 .   len - the amount of space in str
104 +   format - the PETSc format string
105 -   fullLength - the amount of space in str actually used.
106 
107     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
108       a recursion will occur and possible crash.
109 
110  Level: developer
111 
112 @*/
113 PetscErrorCode  PetscVSNPrintf(char *str,size_t len,const char *format,size_t *fullLength,va_list Argp)
114 {
115   char          *newformat;
116   char           formatbuf[8*1024];
117   size_t         oldLength,length;
118   int            fullLengthInt;
119   PetscErrorCode ierr;
120 
121   PetscFunctionBegin;
122   ierr = PetscStrlen(format, &oldLength);CHKERRQ(ierr);
123   if (oldLength < 8*1024) {
124     newformat = formatbuf;
125     oldLength = 8*1024-1;
126   } else {
127     oldLength = PETSC_MAX_LENGTH_FORMAT(oldLength);
128     ierr = PetscMalloc(oldLength * sizeof(char), &newformat);CHKERRQ(ierr);
129   }
130   PetscFormatConvert(format,newformat,oldLength);
131   ierr = PetscStrlen(newformat, &length);CHKERRQ(ierr);
132 #if 0
133   if (length > len) {
134     newformat[len] = '\0';
135   }
136 #endif
137 #if defined(PETSC_HAVE_VSNPRINTF_CHAR)
138   fullLengthInt = vsnprintf(str,len,newformat,(char *)Argp);
139 #elif defined(PETSC_HAVE_VSNPRINTF)
140   fullLengthInt = vsnprintf(str,len,newformat,Argp);
141 #elif defined(PETSC_HAVE__VSNPRINTF)
142   fullLengthInt = _vsnprintf(str,len,newformat,Argp);
143 #else
144 #error "vsnprintf not found"
145 #endif
146   if (fullLengthInt < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"vsnprintf() failed");
147   if (fullLength) *fullLength = (size_t)fullLengthInt;
148   if (oldLength >= 8*1024) {
149     ierr = PetscFree(newformat);CHKERRQ(ierr);
150   }
151   PetscFunctionReturn(0);
152 }
153 
154 #undef __FUNCT__
155 #define __FUNCT__ "PetscVFPrintfDefault"
156 /*@C
157      PetscVFPrintf -  All PETSc standard out and error messages are sent through this function; so, in theory, this can
158         can be replaced with something that does not simply write to a file.
159 
160       To use, write your own function for example,
161 $PetscErrorCode mypetscvfprintf(FILE *fd,const char format[],va_list Argp)
162 ${
163 $  PetscErrorCode ierr;
164 $
165 $  PetscFunctionBegin;
166 $   if (fd != stdout && fd != stderr) {  handle regular files
167 $      ierr = PetscVFPrintfDefault(fd,format,Argp);CHKERR(ierr);
168 $  } else {
169 $     char   buff[BIG];
170 $     size_t length;
171 $     ierr = PetscVSNPrintf(buff,BIG,format,&length,Argp);CHKERRQ(ierr);
172 $     now send buff to whatever stream or whatever you want
173 $ }
174 $ PetscFunctionReturn(0);
175 $}
176 then before the call to PetscInitialize() do the assignment
177 $    PetscVFPrintf = mypetscvfprintf;
178 
179       Notes: For error messages this may be called by any process, for regular standard out it is
180           called only by process 0 of a given communicator
181 
182       Developer Notes: this could be called by an error handler, if that happens then a recursion of the error handler may occur
183                        and a crash
184 
185   Level:  developer
186 
187 .seealso: PetscVSNPrintf(), PetscErrorPrintf()
188 
189 @*/
190 PetscErrorCode  PetscVFPrintfDefault(FILE *fd,const char *format,va_list Argp)
191 {
192   char           *newformat;
193   char           formatbuf[8*1024];
194   size_t         oldLength;
195   PetscErrorCode ierr;
196 
197   PetscFunctionBegin;
198   ierr = PetscStrlen(format, &oldLength);CHKERRQ(ierr);
199   if (oldLength < 8*1024) {
200     newformat = formatbuf;
201     oldLength = 8*1024-1;
202   } else {
203     oldLength = PETSC_MAX_LENGTH_FORMAT(oldLength);
204     ierr = PetscMalloc(oldLength * sizeof(char), &newformat);CHKERRQ(ierr);
205   }
206   ierr = PetscFormatConvert(format,newformat,oldLength);CHKERRQ(ierr);
207 
208 #if defined(PETSC_HAVE_VFPRINTF_CHAR)
209   vfprintf(fd,newformat,(char *)Argp);
210 #else
211   vfprintf(fd,newformat,Argp);
212 #endif
213   fflush(fd);
214   if (oldLength >= 8*1024) {
215     ierr = PetscFree(newformat);CHKERRQ(ierr);
216   }
217   PetscFunctionReturn(0);
218 }
219 
220 #undef __FUNCT__
221 #define __FUNCT__ "PetscSNPrintf"
222 /*@C
223     PetscSNPrintf - Prints to a string of given length
224 
225     Not Collective
226 
227     Input Parameters:
228 +   str - the string to print to
229 .   len - the length of str
230 .   format - the usual printf() format string
231 -   any arguments
232 
233    Level: intermediate
234 
235 .seealso: PetscSynchronizedFlush(), PetscSynchronizedFPrintf(), PetscFPrintf(), PetscVSNPrintf(),
236           PetscPrintf(), PetscViewerASCIIPrintf(), PetscViewerASCIISynchronizedPrintf()
237 @*/
238 PetscErrorCode  PetscSNPrintf(char *str,size_t len,const char format[],...)
239 {
240   PetscErrorCode ierr;
241   size_t         fullLength;
242   va_list        Argp;
243 
244   PetscFunctionBegin;
245   va_start(Argp,format);
246   ierr = PetscVSNPrintf(str,len,format,&fullLength,Argp);CHKERRQ(ierr);
247   PetscFunctionReturn(0);
248 }
249 
250 #undef __FUNCT__
251 #define __FUNCT__ "PetscSNPrintfCount"
252 /*@C
253     PetscSNPrintfCount - Prints to a string of given length, returns count
254 
255     Not Collective
256 
257     Input Parameters:
258 +   str - the string to print to
259 .   len - the length of str
260 .   format - the usual printf() format string
261 .   countused - number of characters used
262 -   any arguments
263 
264    Level: intermediate
265 
266 .seealso: PetscSynchronizedFlush(), PetscSynchronizedFPrintf(), PetscFPrintf(), PetscVSNPrintf(),
267           PetscPrintf(), PetscViewerASCIIPrintf(), PetscViewerASCIISynchronizedPrintf(), PetscSNPrintf()
268 @*/
269 PetscErrorCode  PetscSNPrintfCount(char *str,size_t len,const char format[],size_t *countused,...)
270 {
271   PetscErrorCode ierr;
272   va_list        Argp;
273 
274   PetscFunctionBegin;
275   va_start(Argp,countused);
276   ierr = PetscVSNPrintf(str,len,format,countused,Argp);CHKERRQ(ierr);
277   PetscFunctionReturn(0);
278 }
279 
280 /* ----------------------------------------------------------------------- */
281 
282 PrintfQueue petsc_printfqueue = 0,petsc_printfqueuebase = 0;
283 int         petsc_printfqueuelength = 0;
284 FILE        *petsc_printfqueuefile  = PETSC_NULL;
285 
286 #undef __FUNCT__
287 #define __FUNCT__ "PetscSynchronizedPrintf"
288 /*@C
289     PetscSynchronizedPrintf - Prints synchronized output from several processors.
290     Output of the first processor is followed by that of the second, etc.
291 
292     Not Collective
293 
294     Input Parameters:
295 +   comm - the communicator
296 -   format - the usual printf() format string
297 
298    Level: intermediate
299 
300     Notes:
301     REQUIRES a intervening call to PetscSynchronizedFlush() for the information
302     from all the processors to be printed.
303 
304     Fortran Note:
305     The call sequence is PetscSynchronizedPrintf(MPI_Comm, character(*), PetscErrorCode ierr) from Fortran.
306     That is, you can only pass a single character string from Fortran.
307 
308 .seealso: PetscSynchronizedFlush(), PetscSynchronizedFPrintf(), PetscFPrintf(),
309           PetscPrintf(), PetscViewerASCIIPrintf(), PetscViewerASCIISynchronizedPrintf()
310 @*/
311 PetscErrorCode  PetscSynchronizedPrintf(MPI_Comm comm,const char format[],...)
312 {
313   PetscErrorCode ierr;
314   PetscMPIInt    rank;
315 
316   PetscFunctionBegin;
317   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
318 
319   /* First processor prints immediately to stdout */
320   if (!rank) {
321     va_list Argp;
322     va_start(Argp,format);
323     ierr = (*PetscVFPrintf)(PETSC_STDOUT,format,Argp);CHKERRQ(ierr);
324     if (petsc_history) {
325       va_start(Argp,format);
326       ierr = (*PetscVFPrintf)(petsc_history,format,Argp);CHKERRQ(ierr);
327     }
328     va_end(Argp);
329   } else { /* other processors add to local queue */
330     va_list     Argp;
331     PrintfQueue next;
332     size_t      fullLength = 8191;
333 
334     ierr = PetscNew(struct _PrintfQueue,&next);CHKERRQ(ierr);
335     if (petsc_printfqueue) {petsc_printfqueue->next = next; petsc_printfqueue = next; petsc_printfqueue->next = 0;}
336     else                   {petsc_printfqueuebase   = petsc_printfqueue = next;}
337     petsc_printfqueuelength++;
338     next->size = -1;
339     while((PetscInt)fullLength >= next->size) {
340       next->size = fullLength+1;
341       ierr = PetscMalloc(next->size * sizeof(char), &next->string);CHKERRQ(ierr);
342       va_start(Argp,format);
343       ierr = PetscMemzero(next->string,next->size);CHKERRQ(ierr);
344       ierr = PetscVSNPrintf(next->string,next->size,format, &fullLength,Argp);CHKERRQ(ierr);
345       va_end(Argp);
346     }
347   }
348 
349   PetscFunctionReturn(0);
350 }
351 
352 #undef __FUNCT__
353 #define __FUNCT__ "PetscSynchronizedFPrintf"
354 /*@C
355     PetscSynchronizedFPrintf - Prints synchronized output to the specified file from
356     several processors.  Output of the first processor is followed by that of the
357     second, etc.
358 
359     Not Collective
360 
361     Input Parameters:
362 +   comm - the communicator
363 .   fd - the file pointer
364 -   format - the usual printf() format string
365 
366     Level: intermediate
367 
368     Notes:
369     REQUIRES a intervening call to PetscSynchronizedFlush() for the information
370     from all the processors to be printed.
371 
372 .seealso: PetscSynchronizedPrintf(), PetscSynchronizedFlush(), PetscFPrintf(),
373           PetscFOpen(), PetscViewerASCIISynchronizedPrintf(), PetscViewerASCIIPrintf()
374 
375 @*/
376 PetscErrorCode  PetscSynchronizedFPrintf(MPI_Comm comm,FILE* fp,const char format[],...)
377 {
378   PetscErrorCode ierr;
379   PetscMPIInt    rank;
380 
381   PetscFunctionBegin;
382   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
383 
384   /* First processor prints immediately to fp */
385   if (!rank) {
386     va_list Argp;
387     va_start(Argp,format);
388     ierr = (*PetscVFPrintf)(fp,format,Argp);CHKERRQ(ierr);
389     petsc_printfqueuefile = fp;
390     if (petsc_history && (fp !=petsc_history)) {
391       va_start(Argp,format);
392       ierr = (*PetscVFPrintf)(petsc_history,format,Argp);CHKERRQ(ierr);
393     }
394     va_end(Argp);
395   } else { /* other processors add to local queue */
396     va_list     Argp;
397     PrintfQueue next;
398     size_t      fullLength = 8191;
399     ierr = PetscNew(struct _PrintfQueue,&next);CHKERRQ(ierr);
400     if (petsc_printfqueue) {petsc_printfqueue->next = next; petsc_printfqueue = next; petsc_printfqueue->next = 0;}
401     else                   {petsc_printfqueuebase   = petsc_printfqueue = next;}
402     petsc_printfqueuelength++;
403     next->size = -1;
404     while((PetscInt)fullLength >= next->size) {
405       next->size = fullLength+1;
406       ierr = PetscMalloc(next->size * sizeof(char), &next->string);CHKERRQ(ierr);
407       va_start(Argp,format);
408       ierr = PetscMemzero(next->string,next->size);CHKERRQ(ierr);
409       ierr = PetscVSNPrintf(next->string,next->size,format,&fullLength,Argp);CHKERRQ(ierr);
410       va_end(Argp);
411     }
412   }
413   PetscFunctionReturn(0);
414 }
415 
416 #undef __FUNCT__
417 #define __FUNCT__ "PetscSynchronizedFlush"
418 /*@
419     PetscSynchronizedFlush - Flushes to the screen output from all processors
420     involved in previous PetscSynchronizedPrintf() calls.
421 
422     Collective on MPI_Comm
423 
424     Input Parameters:
425 .   comm - the communicator
426 
427     Level: intermediate
428 
429     Notes:
430     Usage of PetscSynchronizedPrintf() and PetscSynchronizedFPrintf() with
431     different MPI communicators REQUIRES an intervening call to PetscSynchronizedFlush().
432 
433 .seealso: PetscSynchronizedPrintf(), PetscFPrintf(), PetscPrintf(), PetscViewerASCIIPrintf(),
434           PetscViewerASCIISynchronizedPrintf()
435 @*/
436 PetscErrorCode  PetscSynchronizedFlush(MPI_Comm comm)
437 {
438   PetscErrorCode ierr;
439   PetscMPIInt    rank,size,tag,i,j,n,dummy = 0;
440   char          *message;
441   MPI_Status     status;
442   FILE           *fd;
443 
444   PetscFunctionBegin;
445   ierr = PetscCommDuplicate(comm,&comm,&tag);CHKERRQ(ierr);
446   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
447   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
448 
449   /* First processor waits for messages from all other processors */
450   if (!rank) {
451     if (petsc_printfqueuefile) {
452       fd = petsc_printfqueuefile;
453     } else {
454       fd = PETSC_STDOUT;
455     }
456     for (i=1; i<size; i++) {
457       /* to prevent a flood of messages to process zero, request each message separately */
458       ierr = MPI_Send(&dummy,1,MPI_INT,i,tag,comm);CHKERRQ(ierr);
459       ierr = MPI_Recv(&n,1,MPI_INT,i,tag,comm,&status);CHKERRQ(ierr);
460       for (j=0; j<n; j++) {
461         PetscMPIInt size;
462 
463         ierr = MPI_Recv(&size,1,MPI_INT,i,tag,comm,&status);CHKERRQ(ierr);
464         ierr = PetscMalloc(size * sizeof(char), &message);CHKERRQ(ierr);
465         ierr = MPI_Recv(message,size,MPI_CHAR,i,tag,comm,&status);CHKERRQ(ierr);
466         ierr = PetscFPrintf(comm,fd,"%s",message);CHKERRQ(ierr);
467         ierr = PetscFree(message);CHKERRQ(ierr);
468       }
469     }
470     petsc_printfqueuefile = PETSC_NULL;
471   } else { /* other processors send queue to processor 0 */
472     PrintfQueue next = petsc_printfqueuebase,previous;
473 
474     ierr = MPI_Recv(&dummy,1,MPI_INT,0,tag,comm,&status);CHKERRQ(ierr);
475     ierr = MPI_Send(&petsc_printfqueuelength,1,MPI_INT,0,tag,comm);CHKERRQ(ierr);
476     for (i=0; i<petsc_printfqueuelength; i++) {
477       ierr     = MPI_Send(&next->size,1,MPI_INT,0,tag,comm);CHKERRQ(ierr);
478       ierr     = MPI_Send(next->string,next->size,MPI_CHAR,0,tag,comm);CHKERRQ(ierr);
479       previous = next;
480       next     = next->next;
481       ierr     = PetscFree(previous->string);CHKERRQ(ierr);
482       ierr     = PetscFree(previous);CHKERRQ(ierr);
483     }
484     petsc_printfqueue       = 0;
485     petsc_printfqueuelength = 0;
486   }
487   ierr = PetscCommDestroy(&comm);CHKERRQ(ierr);
488   PetscFunctionReturn(0);
489 }
490 
491 /* ---------------------------------------------------------------------------------------*/
492 
493 #undef __FUNCT__
494 #define __FUNCT__ "PetscFPrintf"
495 /*@C
496     PetscFPrintf - Prints to a file, only from the first
497     processor in the communicator.
498 
499     Not Collective
500 
501     Input Parameters:
502 +   comm - the communicator
503 .   fd - the file pointer
504 -   format - the usual printf() format string
505 
506     Level: intermediate
507 
508     Fortran Note:
509     This routine is not supported in Fortran.
510 
511    Concepts: printing^in parallel
512    Concepts: printf^in parallel
513 
514 .seealso: PetscPrintf(), PetscSynchronizedPrintf(), PetscViewerASCIIPrintf(),
515           PetscViewerASCIISynchronizedPrintf(), PetscSynchronizedFlush()
516 @*/
517 PetscErrorCode  PetscFPrintf(MPI_Comm comm,FILE* fd,const char format[],...)
518 {
519   PetscErrorCode ierr;
520   PetscMPIInt    rank;
521 
522   PetscFunctionBegin;
523   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
524   if (!rank) {
525     va_list Argp;
526     va_start(Argp,format);
527     ierr = (*PetscVFPrintf)(fd,format,Argp);CHKERRQ(ierr);
528     if (petsc_history && (fd !=petsc_history)) {
529       va_start(Argp,format);
530       ierr = (*PetscVFPrintf)(petsc_history,format,Argp);CHKERRQ(ierr);
531       }
532     va_end(Argp);
533   }
534   PetscFunctionReturn(0);
535 }
536 
537 #undef __FUNCT__
538 #define __FUNCT__ "PetscPrintf"
539 /*@C
540     PetscPrintf - Prints to standard out, only from the first
541     processor in the communicator. Calls from other processes are ignored.
542 
543     Not Collective
544 
545     Input Parameters:
546 +   comm - the communicator
547 -   format - the usual printf() format string
548 
549    Level: intermediate
550 
551     Fortran Note:
552     The call sequence is PetscPrintf(MPI_Comm, character(*), PetscErrorCode ierr) from Fortran.
553     That is, you can only pass a single character string from Fortran.
554 
555    Concepts: printing^in parallel
556    Concepts: printf^in parallel
557 
558 .seealso: PetscFPrintf(), PetscSynchronizedPrintf()
559 @*/
560 PetscErrorCode  PetscPrintf(MPI_Comm comm,const char format[],...)
561 {
562   PetscErrorCode ierr;
563   PetscMPIInt    rank;
564 
565   PetscFunctionBegin;
566   if (!comm) comm = PETSC_COMM_WORLD;
567   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
568   if (!rank) {
569     va_list Argp;
570     va_start(Argp,format);
571     ierr = (*PetscVFPrintf)(PETSC_STDOUT,format,Argp);CHKERRQ(ierr);
572     if (petsc_history) {
573       va_start(Argp,format);
574       ierr = (*PetscVFPrintf)(petsc_history,format,Argp);CHKERRQ(ierr);
575     }
576     va_end(Argp);
577   }
578   PetscFunctionReturn(0);
579 }
580 
581 /* ---------------------------------------------------------------------------------------*/
582 #undef __FUNCT__
583 #define __FUNCT__ "PetscHelpPrintfDefault"
584 /*@C
585      PetscHelpPrintf -  All PETSc help messages are passing through this function. You can change how help messages are printed by
586         replacinng it  with something that does not simply write to a stdout.
587 
588       To use, write your own function for example,
589 $PetscErrorCode mypetschelpprintf(MPI_Comm comm,const char format[],....)
590 ${
591 $ PetscFunctionReturn(0);
592 $}
593 then before the call to PetscInitialize() do the assignment
594 $    PetscHelpPrintf = mypetschelpprintf;
595 
596   Note: the default routine used is called PetscHelpPrintfDefault().
597 
598   Level:  developer
599 
600 .seealso: PetscVSNPrintf(), PetscVFPrintf(), PetscErrorPrintf()
601 @*/
602 PetscErrorCode  PetscHelpPrintfDefault(MPI_Comm comm,const char format[],...)
603 {
604   PetscErrorCode ierr;
605   PetscMPIInt    rank;
606 
607   PetscFunctionBegin;
608   if (!comm) comm = PETSC_COMM_WORLD;
609   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
610   if (!rank) {
611     va_list Argp;
612     va_start(Argp,format);
613     ierr = (*PetscVFPrintf)(PETSC_STDOUT,format,Argp);CHKERRQ(ierr);
614     if (petsc_history) {
615       va_start(Argp,format);
616       ierr = (*PetscVFPrintf)(petsc_history,format,Argp);CHKERRQ(ierr);
617     }
618     va_end(Argp);
619   }
620   PetscFunctionReturn(0);
621 }
622 
623 /* ---------------------------------------------------------------------------------------*/
624 
625 
626 #undef __FUNCT__
627 #define __FUNCT__ "PetscSynchronizedFGets"
628 /*@C
629     PetscSynchronizedFGets - Several processors all get the same line from a file.
630 
631     Collective on MPI_Comm
632 
633     Input Parameters:
634 +   comm - the communicator
635 .   fd - the file pointer
636 -   len - the length of the output buffer
637 
638     Output Parameter:
639 .   string - the line read from the file
640 
641     Level: intermediate
642 
643 .seealso: PetscSynchronizedPrintf(), PetscSynchronizedFlush(),
644           PetscFOpen(), PetscViewerASCIISynchronizedPrintf(), PetscViewerASCIIPrintf()
645 
646 @*/
647 PetscErrorCode  PetscSynchronizedFGets(MPI_Comm comm,FILE* fp,size_t len,char string[])
648 {
649   PetscErrorCode ierr;
650   PetscMPIInt    rank;
651 
652   PetscFunctionBegin;
653   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
654 
655   if (!rank) {
656     char *ptr = fgets(string, len, fp);
657 
658     if (!ptr) {
659       if (feof(fp)) {
660         len = 0;
661       } else SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_FILE_READ, "Error reading from file: %d", errno);
662     }
663   }
664   ierr = MPI_Bcast(string,len,MPI_BYTE,0,comm);CHKERRQ(ierr);
665   PetscFunctionReturn(0);
666 }
667 
668 #if defined(PETSC_HAVE_MATLAB_ENGINE)
669 #include <mex.h>
670 #undef __FUNCT__
671 #define __FUNCT__ "PetscVFPrintf_Matlab"
672 PetscErrorCode  PetscVFPrintf_Matlab(FILE *fd,const char format[],va_list Argp)
673 {
674   PetscErrorCode ierr;
675 
676   PetscFunctionBegin;
677   if (fd != stdout && fd != stderr) { /* handle regular files */
678     ierr = PetscVFPrintfDefault(fd,format,Argp);CHKERRQ(ierr);
679   } else {
680     size_t len=8*1024,length;
681     char   buf[len];
682 
683     ierr = PetscVSNPrintf(buf,len,format,&length,Argp);CHKERRQ(ierr);
684     mexPrintf("%s",buf);
685  }
686  PetscFunctionReturn(0);
687 }
688 #endif
689 
690 #undef __FUNCT__
691 #define __FUNCT__ "PetscFormatStrip"
692 /*@C
693      PetscFormatStrip - Takes a PETSc format string and removes all numerical modifiers to % operations
694 
695    Input Parameters:
696 .   format - the PETSc format string
697 
698  Level: developer
699 
700 @*/
701 PetscErrorCode  PetscFormatStrip(char *format)
702 {
703   size_t   loc1 = 0, loc2 = 0;
704 
705   PetscFunctionBegin;
706   while (format[loc2]){
707     if (format[loc2] == '%') {
708       format[loc1++] = format[loc2++];
709       while (format[loc2] && ((format[loc2] >= '0' && format[loc2] <= '9') || format[loc2] == '.')) loc2++;
710     }
711     format[loc1++] = format[loc2++];
712   }
713   PetscFunctionReturn(0);
714 }
715 
716