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