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