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