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