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