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