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