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