xref: /petsc/src/sys/fileio/mprint.c (revision 009bbdc485cd9ad46be9940d3549e2dde9cdc322)
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   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     petsc_printfqueuefile = fp;
389     if (petsc_history && (fp !=petsc_history)) {
390       va_start(Argp,format);
391       ierr = (*PetscVFPrintf)(petsc_history,format,Argp);CHKERRQ(ierr);
392     }
393     va_end(Argp);
394   } else { /* other processors add to local queue */
395     va_list     Argp;
396     PrintfQueue next;
397     size_t      fullLength = 8191;
398     ierr = PetscNew(struct _PrintfQueue,&next);CHKERRQ(ierr);
399     if (petsc_printfqueue) {petsc_printfqueue->next = next; petsc_printfqueue = next; petsc_printfqueue->next = 0;}
400     else                   {petsc_printfqueuebase   = petsc_printfqueue = next;}
401     petsc_printfqueuelength++;
402     next->size = -1;
403     while ((PetscInt)fullLength >= next->size) {
404       next->size = fullLength+1;
405       ierr = PetscMalloc(next->size * sizeof(char), &next->string);CHKERRQ(ierr);
406       va_start(Argp,format);
407       ierr = PetscMemzero(next->string,next->size);CHKERRQ(ierr);
408       ierr = PetscVSNPrintf(next->string,next->size,format,&fullLength,Argp);CHKERRQ(ierr);
409       va_end(Argp);
410     }
411   }
412   PetscFunctionReturn(0);
413 }
414 
415 #undef __FUNCT__
416 #define __FUNCT__ "PetscSynchronizedFlush"
417 /*@
418     PetscSynchronizedFlush - Flushes to the screen output from all processors
419     involved in previous PetscSynchronizedPrintf() calls.
420 
421     Collective on MPI_Comm
422 
423     Input Parameters:
424 .   comm - the communicator
425 
426     Level: intermediate
427 
428     Notes:
429     Usage of PetscSynchronizedPrintf() and PetscSynchronizedFPrintf() with
430     different MPI communicators REQUIRES an intervening call to PetscSynchronizedFlush().
431 
432 .seealso: PetscSynchronizedPrintf(), PetscFPrintf(), PetscPrintf(), PetscViewerASCIIPrintf(),
433           PetscViewerASCIISynchronizedPrintf()
434 @*/
435 PetscErrorCode  PetscSynchronizedFlush(MPI_Comm comm)
436 {
437   PetscErrorCode ierr;
438   PetscMPIInt    rank,size,tag,i,j,n,dummy = 0;
439   char          *message;
440   MPI_Status     status;
441   FILE           *fd;
442 
443   PetscFunctionBegin;
444   ierr = PetscCommDuplicate(comm,&comm,&tag);CHKERRQ(ierr);
445   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
446   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
447 
448   /* First processor waits for messages from all other processors */
449   if (!rank) {
450     if (petsc_printfqueuefile) {
451       fd = petsc_printfqueuefile;
452     } else {
453       fd = PETSC_STDOUT;
454     }
455     for (i=1; i<size; i++) {
456       /* to prevent a flood of messages to process zero, request each message separately */
457       ierr = MPI_Send(&dummy,1,MPI_INT,i,tag,comm);CHKERRQ(ierr);
458       ierr = MPI_Recv(&n,1,MPI_INT,i,tag,comm,&status);CHKERRQ(ierr);
459       for (j=0; j<n; j++) {
460         PetscMPIInt size;
461 
462         ierr = MPI_Recv(&size,1,MPI_INT,i,tag,comm,&status);CHKERRQ(ierr);
463         ierr = PetscMalloc(size * sizeof(char), &message);CHKERRQ(ierr);
464         ierr = MPI_Recv(message,size,MPI_CHAR,i,tag,comm,&status);CHKERRQ(ierr);
465         ierr = PetscFPrintf(comm,fd,"%s",message);CHKERRQ(ierr);
466         ierr = PetscFree(message);CHKERRQ(ierr);
467       }
468     }
469     petsc_printfqueuefile = PETSC_NULL;
470   } else { /* other processors send queue to processor 0 */
471     PrintfQueue next = petsc_printfqueuebase,previous;
472 
473     ierr = MPI_Recv(&dummy,1,MPI_INT,0,tag,comm,&status);CHKERRQ(ierr);
474     ierr = MPI_Send(&petsc_printfqueuelength,1,MPI_INT,0,tag,comm);CHKERRQ(ierr);
475     for (i=0; i<petsc_printfqueuelength; i++) {
476       ierr     = MPI_Send(&next->size,1,MPI_INT,0,tag,comm);CHKERRQ(ierr);
477       ierr     = MPI_Send(next->string,next->size,MPI_CHAR,0,tag,comm);CHKERRQ(ierr);
478       previous = next;
479       next     = next->next;
480       ierr     = PetscFree(previous->string);CHKERRQ(ierr);
481       ierr     = PetscFree(previous);CHKERRQ(ierr);
482     }
483     petsc_printfqueue       = 0;
484     petsc_printfqueuelength = 0;
485   }
486   ierr = PetscCommDestroy(&comm);CHKERRQ(ierr);
487   PetscFunctionReturn(0);
488 }
489 
490 /* ---------------------------------------------------------------------------------------*/
491 
492 #undef __FUNCT__
493 #define __FUNCT__ "PetscFPrintf"
494 /*@C
495     PetscFPrintf - Prints to a file, only from the first
496     processor in the communicator.
497 
498     Not Collective
499 
500     Input Parameters:
501 +   comm - the communicator
502 .   fd - the file pointer
503 -   format - the usual printf() format string
504 
505     Level: intermediate
506 
507     Fortran Note:
508     This routine is not supported in Fortran.
509 
510    Concepts: printing^in parallel
511    Concepts: printf^in parallel
512 
513 .seealso: PetscPrintf(), PetscSynchronizedPrintf(), PetscViewerASCIIPrintf(),
514           PetscViewerASCIISynchronizedPrintf(), PetscSynchronizedFlush()
515 @*/
516 PetscErrorCode  PetscFPrintf(MPI_Comm comm,FILE* fd,const char format[],...)
517 {
518   PetscErrorCode ierr;
519   PetscMPIInt    rank;
520 
521   PetscFunctionBegin;
522   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
523   if (!rank) {
524     va_list Argp;
525     va_start(Argp,format);
526     ierr = (*PetscVFPrintf)(fd,format,Argp);CHKERRQ(ierr);
527     if (petsc_history && (fd !=petsc_history)) {
528       va_start(Argp,format);
529       ierr = (*PetscVFPrintf)(petsc_history,format,Argp);CHKERRQ(ierr);
530       }
531     va_end(Argp);
532   }
533   PetscFunctionReturn(0);
534 }
535 
536 #undef __FUNCT__
537 #define __FUNCT__ "PetscPrintf"
538 /*@C
539     PetscPrintf - Prints to standard out, only from the first
540     processor in the communicator. Calls from other processes are ignored.
541 
542     Not Collective
543 
544     Input Parameters:
545 +   comm - the communicator
546 -   format - the usual printf() format string
547 
548    Level: intermediate
549 
550     Fortran Note:
551     The call sequence is PetscPrintf(MPI_Comm, character(*), PetscErrorCode ierr) from Fortran.
552     That is, you can only pass a single character string from Fortran.
553 
554    Concepts: printing^in parallel
555    Concepts: printf^in parallel
556 
557 .seealso: PetscFPrintf(), PetscSynchronizedPrintf()
558 @*/
559 PetscErrorCode  PetscPrintf(MPI_Comm comm,const char format[],...)
560 {
561   PetscErrorCode ierr;
562   PetscMPIInt    rank;
563 
564   PetscFunctionBegin;
565   if (!comm) comm = PETSC_COMM_WORLD;
566   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
567   if (!rank) {
568     va_list Argp;
569     va_start(Argp,format);
570     ierr = (*PetscVFPrintf)(PETSC_STDOUT,format,Argp);CHKERRQ(ierr);
571     if (petsc_history) {
572       va_start(Argp,format);
573       ierr = (*PetscVFPrintf)(petsc_history,format,Argp);CHKERRQ(ierr);
574     }
575     va_end(Argp);
576   }
577   PetscFunctionReturn(0);
578 }
579 
580 /* ---------------------------------------------------------------------------------------*/
581 #undef __FUNCT__
582 #define __FUNCT__ "PetscHelpPrintfDefault"
583 /*@C
584      PetscHelpPrintf -  All PETSc help messages are passing through this function. You can change how help messages are printed by
585         replacinng it  with something that does not simply write to a stdout.
586 
587       To use, write your own function for example,
588 $PetscErrorCode mypetschelpprintf(MPI_Comm comm,const char format[],....)
589 ${
590 $ PetscFunctionReturn(0);
591 $}
592 then before the call to PetscInitialize() do the assignment
593 $    PetscHelpPrintf = mypetschelpprintf;
594 
595   Note: the default routine used is called PetscHelpPrintfDefault().
596 
597   Level:  developer
598 
599 .seealso: PetscVSNPrintf(), PetscVFPrintf(), PetscErrorPrintf()
600 @*/
601 PetscErrorCode  PetscHelpPrintfDefault(MPI_Comm comm,const char format[],...)
602 {
603   PetscErrorCode ierr;
604   PetscMPIInt    rank;
605 
606   PetscFunctionBegin;
607   if (!comm) comm = PETSC_COMM_WORLD;
608   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
609   if (!rank) {
610     va_list Argp;
611     va_start(Argp,format);
612     ierr = (*PetscVFPrintf)(PETSC_STDOUT,format,Argp);CHKERRQ(ierr);
613     if (petsc_history) {
614       va_start(Argp,format);
615       ierr = (*PetscVFPrintf)(petsc_history,format,Argp);CHKERRQ(ierr);
616     }
617     va_end(Argp);
618   }
619   PetscFunctionReturn(0);
620 }
621 
622 /* ---------------------------------------------------------------------------------------*/
623 
624 
625 #undef __FUNCT__
626 #define __FUNCT__ "PetscSynchronizedFGets"
627 /*@C
628     PetscSynchronizedFGets - Several processors all get the same line from a file.
629 
630     Collective on MPI_Comm
631 
632     Input Parameters:
633 +   comm - the communicator
634 .   fd - the file pointer
635 -   len - the length of the output buffer
636 
637     Output Parameter:
638 .   string - the line read from the file
639 
640     Level: intermediate
641 
642 .seealso: PetscSynchronizedPrintf(), PetscSynchronizedFlush(),
643           PetscFOpen(), PetscViewerASCIISynchronizedPrintf(), PetscViewerASCIIPrintf()
644 
645 @*/
646 PetscErrorCode  PetscSynchronizedFGets(MPI_Comm comm,FILE* fp,size_t len,char string[])
647 {
648   PetscErrorCode ierr;
649   PetscMPIInt    rank;
650 
651   PetscFunctionBegin;
652   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
653 
654   if (!rank) {
655     char *ptr = fgets(string, len, fp);
656 
657     if (!ptr) {
658       if (feof(fp)) {
659         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