xref: /petsc/src/sys/fileio/mprint.c (revision 2205254efee3a00a594e5e2a3a70f74dcb40bc03)
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 newformat[j++] = format[i++];
88   }
89   newformat[j] = 0;
90   PetscFunctionReturn(0);
91 }
92 
93 #undef __FUNCT__
94 #define __FUNCT__ "PetscVSNPrintf"
95 /*@C
96      PetscVSNPrintf - The PETSc version of vsnprintf(). Converts a PETSc format string into a standard C format string and then puts all the
97        function arguments into a string using the format statement.
98 
99    Input Parameters:
100 +   str - location to put result
101 .   len - the amount of space in str
102 +   format - the PETSc format string
103 -   fullLength - the amount of space in str actually used.
104 
105     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
106       a recursion will occur and possible crash.
107 
108  Level: developer
109 
110 @*/
111 PetscErrorCode  PetscVSNPrintf(char *str,size_t len,const char *format,size_t *fullLength,va_list Argp)
112 {
113   char           *newformat;
114   char           formatbuf[8*1024];
115   size_t         oldLength,length;
116   int            fullLengthInt;
117   PetscErrorCode ierr;
118 
119   PetscFunctionBegin;
120   ierr = PetscStrlen(format, &oldLength);CHKERRQ(ierr);
121   if (oldLength < 8*1024) {
122     newformat = formatbuf;
123     oldLength = 8*1024-1;
124   } else {
125     oldLength = PETSC_MAX_LENGTH_FORMAT(oldLength);
126     ierr      = PetscMalloc(oldLength * sizeof(char), &newformat);CHKERRQ(ierr);
127   }
128   PetscFormatConvert(format,newformat,oldLength);
129   ierr = PetscStrlen(newformat, &length);CHKERRQ(ierr);
130 #if 0
131   if (length > len) newformat[len] = '\0';
132 #endif
133 #if defined(PETSC_HAVE_VSNPRINTF_CHAR)
134   fullLengthInt = vsnprintf(str,len,newformat,(char*)Argp);
135 #elif defined(PETSC_HAVE_VSNPRINTF)
136   fullLengthInt = vsnprintf(str,len,newformat,Argp);
137 #elif defined(PETSC_HAVE__VSNPRINTF)
138   fullLengthInt = _vsnprintf(str,len,newformat,Argp);
139 #else
140 #error "vsnprintf not found"
141 #endif
142   if (fullLengthInt < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"vsnprintf() failed");
143   if (fullLength) *fullLength = (size_t)fullLengthInt;
144   if (oldLength >= 8*1024) {
145     ierr = PetscFree(newformat);CHKERRQ(ierr);
146   }
147   PetscFunctionReturn(0);
148 }
149 
150 #undef __FUNCT__
151 #define __FUNCT__ "PetscVFPrintfDefault"
152 /*@C
153      PetscVFPrintf -  All PETSc standard out and error messages are sent through this function; so, in theory, this can
154         can be replaced with something that does not simply write to a file.
155 
156       To use, write your own function for example,
157 $PetscErrorCode mypetscvfprintf(FILE *fd,const char format[],va_list Argp)
158 ${
159 $  PetscErrorCode ierr;
160 $
161 $  PetscFunctionBegin;
162 $   if (fd != stdout && fd != stderr) {  handle regular files
163 $      ierr = PetscVFPrintfDefault(fd,format,Argp);CHKERR(ierr);
164 $  } else {
165 $     char   buff[BIG];
166 $     size_t length;
167 $     ierr = PetscVSNPrintf(buff,BIG,format,&length,Argp);CHKERRQ(ierr);
168 $     now send buff to whatever stream or whatever you want
169 $ }
170 $ PetscFunctionReturn(0);
171 $}
172 then before the call to PetscInitialize() do the assignment
173 $    PetscVFPrintf = mypetscvfprintf;
174 
175       Notes: For error messages this may be called by any process, for regular standard out it is
176           called only by process 0 of a given communicator
177 
178       Developer Notes: this could be called by an error handler, if that happens then a recursion of the error handler may occur
179                        and a crash
180 
181   Level:  developer
182 
183 .seealso: PetscVSNPrintf(), PetscErrorPrintf()
184 
185 @*/
186 PetscErrorCode  PetscVFPrintfDefault(FILE *fd,const char *format,va_list Argp)
187 {
188   char           *newformat;
189   char           formatbuf[8*1024];
190   size_t         oldLength;
191   PetscErrorCode ierr;
192 
193   PetscFunctionBegin;
194   ierr = PetscStrlen(format, &oldLength);CHKERRQ(ierr);
195   if (oldLength < 8*1024) {
196     newformat = formatbuf;
197     oldLength = 8*1024-1;
198   } else {
199     oldLength = PETSC_MAX_LENGTH_FORMAT(oldLength);
200     ierr      = PetscMalloc(oldLength * sizeof(char), &newformat);CHKERRQ(ierr);
201   }
202   ierr = PetscFormatConvert(format,newformat,oldLength);CHKERRQ(ierr);
203 
204 #if defined(PETSC_HAVE_VFPRINTF_CHAR)
205   vfprintf(fd,newformat,(char*)Argp);
206 #else
207   vfprintf(fd,newformat,Argp);
208 #endif
209   fflush(fd);
210   if (oldLength >= 8*1024) {
211     ierr = PetscFree(newformat);CHKERRQ(ierr);
212   }
213   PetscFunctionReturn(0);
214 }
215 
216 #undef __FUNCT__
217 #define __FUNCT__ "PetscSNPrintf"
218 /*@C
219     PetscSNPrintf - Prints to a string of given length
220 
221     Not Collective
222 
223     Input Parameters:
224 +   str - the string to print to
225 .   len - the length of str
226 .   format - the usual printf() format string
227 -   any arguments
228 
229    Level: intermediate
230 
231 .seealso: PetscSynchronizedFlush(), PetscSynchronizedFPrintf(), PetscFPrintf(), PetscVSNPrintf(),
232           PetscPrintf(), PetscViewerASCIIPrintf(), PetscViewerASCIISynchronizedPrintf()
233 @*/
234 PetscErrorCode  PetscSNPrintf(char *str,size_t len,const char format[],...)
235 {
236   PetscErrorCode ierr;
237   size_t         fullLength;
238   va_list        Argp;
239 
240   PetscFunctionBegin;
241   va_start(Argp,format);
242   ierr = PetscVSNPrintf(str,len,format,&fullLength,Argp);CHKERRQ(ierr);
243   PetscFunctionReturn(0);
244 }
245 
246 #undef __FUNCT__
247 #define __FUNCT__ "PetscSNPrintfCount"
248 /*@C
249     PetscSNPrintfCount - Prints to a string of given length, returns count
250 
251     Not Collective
252 
253     Input Parameters:
254 +   str - the string to print to
255 .   len - the length of str
256 .   format - the usual printf() format string
257 .   countused - number of characters used
258 -   any arguments
259 
260    Level: intermediate
261 
262 .seealso: PetscSynchronizedFlush(), PetscSynchronizedFPrintf(), PetscFPrintf(), PetscVSNPrintf(),
263           PetscPrintf(), PetscViewerASCIIPrintf(), PetscViewerASCIISynchronizedPrintf(), PetscSNPrintf()
264 @*/
265 PetscErrorCode  PetscSNPrintfCount(char *str,size_t len,const char format[],size_t *countused,...)
266 {
267   PetscErrorCode ierr;
268   va_list        Argp;
269 
270   PetscFunctionBegin;
271   va_start(Argp,countused);
272   ierr = PetscVSNPrintf(str,len,format,countused,Argp);CHKERRQ(ierr);
273   PetscFunctionReturn(0);
274 }
275 
276 /* ----------------------------------------------------------------------- */
277 
278 PrintfQueue petsc_printfqueue       = 0,petsc_printfqueuebase = 0;
279 int         petsc_printfqueuelength = 0;
280 FILE        *petsc_printfqueuefile  = PETSC_NULL;
281 
282 #undef __FUNCT__
283 #define __FUNCT__ "PetscSynchronizedPrintf"
284 /*@C
285     PetscSynchronizedPrintf - Prints synchronized output from several processors.
286     Output of the first processor is followed by that of the second, etc.
287 
288     Not Collective
289 
290     Input Parameters:
291 +   comm - the communicator
292 -   format - the usual printf() format string
293 
294    Level: intermediate
295 
296     Notes:
297     REQUIRES a intervening call to PetscSynchronizedFlush() for the information
298     from all the processors to be printed.
299 
300     Fortran Note:
301     The call sequence is PetscSynchronizedPrintf(MPI_Comm, character(*), PetscErrorCode ierr) from Fortran.
302     That is, you can only pass a single character string from Fortran.
303 
304 .seealso: PetscSynchronizedFlush(), PetscSynchronizedFPrintf(), PetscFPrintf(),
305           PetscPrintf(), PetscViewerASCIIPrintf(), PetscViewerASCIISynchronizedPrintf()
306 @*/
307 PetscErrorCode  PetscSynchronizedPrintf(MPI_Comm comm,const char format[],...)
308 {
309   PetscErrorCode ierr;
310   PetscMPIInt    rank;
311 
312   PetscFunctionBegin;
313   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
314 
315   /* First processor prints immediately to stdout */
316   if (!rank) {
317     va_list Argp;
318     va_start(Argp,format);
319     ierr = (*PetscVFPrintf)(PETSC_STDOUT,format,Argp);CHKERRQ(ierr);
320     if (petsc_history) {
321       va_start(Argp,format);
322       ierr = (*PetscVFPrintf)(petsc_history,format,Argp);CHKERRQ(ierr);
323     }
324     va_end(Argp);
325   } else { /* other processors add to local queue */
326     va_list     Argp;
327     PrintfQueue next;
328     size_t      fullLength = 8191;
329 
330     ierr = PetscNew(struct _PrintfQueue,&next);CHKERRQ(ierr);
331     if (petsc_printfqueue) {
332       petsc_printfqueue->next = next;
333       petsc_printfqueue       = next;
334       petsc_printfqueue->next = 0;
335     } else petsc_printfqueuebase = petsc_printfqueue = next;
336     petsc_printfqueuelength++;
337     next->size = -1;
338     while ((PetscInt)fullLength >= next->size) {
339       next->size = fullLength+1;
340 
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   PetscFunctionReturn(0);
349 }
350 
351 #undef __FUNCT__
352 #define __FUNCT__ "PetscSynchronizedFPrintf"
353 /*@C
354     PetscSynchronizedFPrintf - Prints synchronized output to the specified file from
355     several processors.  Output of the first processor is followed by that of the
356     second, etc.
357 
358     Not Collective
359 
360     Input Parameters:
361 +   comm - the communicator
362 .   fd - the file pointer
363 -   format - the usual printf() format string
364 
365     Level: intermediate
366 
367     Notes:
368     REQUIRES a intervening call to PetscSynchronizedFlush() for the information
369     from all the processors to be printed.
370 
371 .seealso: PetscSynchronizedPrintf(), PetscSynchronizedFlush(), PetscFPrintf(),
372           PetscFOpen(), PetscViewerASCIISynchronizedPrintf(), PetscViewerASCIIPrintf()
373 
374 @*/
375 PetscErrorCode  PetscSynchronizedFPrintf(MPI_Comm comm,FILE *fp,const char format[],...)
376 {
377   PetscErrorCode ierr;
378   PetscMPIInt    rank;
379 
380   PetscFunctionBegin;
381   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
382 
383   /* First processor prints immediately to fp */
384   if (!rank) {
385     va_list Argp;
386     va_start(Argp,format);
387     ierr = (*PetscVFPrintf)(fp,format,Argp);CHKERRQ(ierr);
388 
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) {
401       petsc_printfqueue->next = next;
402       petsc_printfqueue       = next;
403       petsc_printfqueue->next = 0;
404     } else petsc_printfqueuebase = petsc_printfqueue = next;
405     petsc_printfqueuelength++;
406     next->size = -1;
407     while ((PetscInt)fullLength >= next->size) {
408       next->size = fullLength+1;
409       ierr = PetscMalloc(next->size * sizeof(char), &next->string);CHKERRQ(ierr);
410       va_start(Argp,format);
411       ierr = PetscMemzero(next->string,next->size);CHKERRQ(ierr);
412       ierr = PetscVSNPrintf(next->string,next->size,format,&fullLength,Argp);CHKERRQ(ierr);
413       va_end(Argp);
414     }
415   }
416   PetscFunctionReturn(0);
417 }
418 
419 #undef __FUNCT__
420 #define __FUNCT__ "PetscSynchronizedFlush"
421 /*@
422     PetscSynchronizedFlush - Flushes to the screen output from all processors
423     involved in previous PetscSynchronizedPrintf() calls.
424 
425     Collective on MPI_Comm
426 
427     Input Parameters:
428 .   comm - the communicator
429 
430     Level: intermediate
431 
432     Notes:
433     Usage of PetscSynchronizedPrintf() and PetscSynchronizedFPrintf() with
434     different MPI communicators REQUIRES an intervening call to PetscSynchronizedFlush().
435 
436 .seealso: PetscSynchronizedPrintf(), PetscFPrintf(), PetscPrintf(), PetscViewerASCIIPrintf(),
437           PetscViewerASCIISynchronizedPrintf()
438 @*/
439 PetscErrorCode  PetscSynchronizedFlush(MPI_Comm comm)
440 {
441   PetscErrorCode ierr;
442   PetscMPIInt    rank,size,tag,i,j,n,dummy = 0;
443   char          *message;
444   MPI_Status     status;
445   FILE           *fd;
446 
447   PetscFunctionBegin;
448   ierr = PetscCommDuplicate(comm,&comm,&tag);CHKERRQ(ierr);
449   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
450   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
451 
452   /* First processor waits for messages from all other processors */
453   if (!rank) {
454     if (petsc_printfqueuefile) fd = petsc_printfqueuefile;
455     else fd = PETSC_STDOUT;
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)) len = 0;
660       else SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_FILE_READ, "Error reading from file: %d", errno);
661     }
662   }
663   ierr = MPI_Bcast(string,len,MPI_BYTE,0,comm);CHKERRQ(ierr);
664   PetscFunctionReturn(0);
665 }
666 
667 #if defined(PETSC_HAVE_MATLAB_ENGINE)
668 #include <mex.h>
669 #undef __FUNCT__
670 #define __FUNCT__ "PetscVFPrintf_Matlab"
671 PetscErrorCode  PetscVFPrintf_Matlab(FILE *fd,const char format[],va_list Argp)
672 {
673   PetscErrorCode ierr;
674 
675   PetscFunctionBegin;
676   if (fd != stdout && fd != stderr) { /* handle regular files */
677     ierr = PetscVFPrintfDefault(fd,format,Argp);CHKERRQ(ierr);
678   } else {
679     size_t len=8*1024,length;
680     char   buf[len];
681 
682     ierr = PetscVSNPrintf(buf,len,format,&length,Argp);CHKERRQ(ierr);
683     mexPrintf("%s",buf);
684   }
685   PetscFunctionReturn(0);
686 }
687 #endif
688 
689 #undef __FUNCT__
690 #define __FUNCT__ "PetscFormatStrip"
691 /*@C
692      PetscFormatStrip - Takes a PETSc format string and removes all numerical modifiers to % operations
693 
694    Input Parameters:
695 .   format - the PETSc format string
696 
697  Level: developer
698 
699 @*/
700 PetscErrorCode  PetscFormatStrip(char *format)
701 {
702   size_t loc1 = 0, loc2 = 0;
703 
704   PetscFunctionBegin;
705   while (format[loc2]) {
706     if (format[loc2] == '%') {
707       format[loc1++] = format[loc2++];
708       while (format[loc2] && ((format[loc2] >= '0' && format[loc2] <= '9') || format[loc2] == '.')) loc2++;
709     }
710     format[loc1++] = format[loc2++];
711   }
712   PetscFunctionReturn(0);
713 }
714 
715