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