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