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