xref: /petsc/src/sys/fileio/mprint.c (revision b13499bf4a0cc2a04269317e24cfa1cd9dad0b25)
1 #define PETSC_DLL
2 /*
3       Utilites routines to add simple ASCII IO capability.
4 */
5 #include "src/sys/fileio/mprint.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      Used to output to Zope
26 */
27 FILE *PETSC_ZOPEFD = 0;
28 
29 #undef __FUNCT__
30 #define __FUNCT__ "PetscFormatConvert"
31 PetscErrorCode PETSC_DLLEXPORT PetscFormatConvert(const char *format,char *newformat,PetscInt size)
32 {
33   PetscInt i = 0,j = 0;
34 
35   while (format[i] && i < size-1) {
36     if (format[i] == '%' && format[i+1] == 'D') {
37       newformat[j++] = '%';
38 #if defined(PETSC_USE_32BIT_INT)
39       newformat[j++] = 'd';
40 #else
41       newformat[j++] = 'l';
42       newformat[j++] = 'l';
43       newformat[j++] = 'd';
44 #endif
45       i += 2;
46     } else if (format[i] == '%' && format[i+1] >= '1' && format[i+1] <= '9' && format[i+2] == 'D') {
47       newformat[j++] = '%';
48       newformat[j++] = format[i+1];
49 #if defined(PETSC_USE_32BIT_INT)
50       newformat[j++] = 'd';
51 #else
52       newformat[j++] = 'l';
53       newformat[j++] = 'l';
54       newformat[j++] = 'd';
55 #endif
56       i += 3;
57     } else if (format[i] == '%' && format[i+1] == 'G') {
58       newformat[j++] = '%';
59 #if defined(PETSC_USE_INT)
60       newformat[j++] = 'd';
61 #elif !defined(PETSC_USE_LONG_DOUBLE)
62       newformat[j++] = 'g';
63 #else
64       newformat[j++] = 'L';
65       newformat[j++] = 'g';
66 #endif
67       i += 2;
68     }else {
69       newformat[j++] = format[i++];
70     }
71   }
72   newformat[j] = 0;
73   return 0;
74 }
75 
76 #undef __FUNCT__
77 #define __FUNCT__ "PetscVSNPrintf"
78 /*
79    No error handling because may be called by error handler
80 */
81 PetscErrorCode PETSC_DLLEXPORT PetscVSNPrintf(char *str,size_t len,const char *format,va_list Argp)
82 {
83   /* no malloc since may be called by error handler */
84   char           newformat[8*1024];
85   size_t         length;
86   PetscErrorCode ierr;
87 
88   PetscFormatConvert(format,newformat,8*1024);
89   ierr = PetscStrlen(newformat, &length);CHKERRQ(ierr);
90   if (length > len) {
91     newformat[len] = '\0';
92   }
93 #if defined(PETSC_HAVE_VPRINTF_CHAR)
94   vsprintf(str,newformat,(char *)Argp);
95 #else
96   vsprintf(str,newformat,Argp);
97 #endif
98   return 0;
99 }
100 
101 #undef __FUNCT__
102 #define __FUNCT__ "PetscVFPrintf"
103 /*
104    All PETSc standard out and error messages are sent through this function; so, in theory, this can
105    can be replaced with something that does not simply write to a file.
106 
107    Note: For error messages this may be called by a process, for regular standard out it is
108    called only by process 0 of a given communicator
109 
110    No error handling because may be called by error handler
111 */
112 PetscErrorCode PETSC_DLLEXPORT PetscVFPrintf(FILE *fd,const char *format,va_list Argp)
113 {
114   /* no malloc since may be called by error handler */
115   char     newformat[8*1024];
116 
117   extern FILE * PETSC_ZOPEFD;
118   PetscFormatConvert(format,newformat,8*1024);
119   if(PETSC_ZOPEFD != NULL && PETSC_ZOPEFD != PETSC_STDOUT){
120     va_list s;
121     va_copy(s, Argp);
122 #if defined(PETSC_HAVE_VPRINTF_CHAR)
123   vfprintf(PETSC_ZOPEFD,newformat,(char *)s);
124 #else
125   vfprintf(PETSC_ZOPEFD,newformat,s);
126   fflush(PETSC_ZOPEFD);
127 #endif
128 }
129 
130 #if defined(PETSC_HAVE_VPRINTF_CHAR)
131   vfprintf(fd,newformat,(char *)Argp);
132 #else
133   vfprintf(fd,newformat,Argp);
134   fflush(fd);
135 #endif
136 
137 
138   return 0;
139 }
140 
141 #undef __FUNCT__
142 #define __FUNCT__ "PetscSNPrintf"
143 /*@C
144     PetscSNPrintf - Prints to a string of given length
145 
146     Not Collective
147 
148     Input Parameters:
149 +   str - the string to print to
150 .   len - the length of str
151 .   format - the usual printf() format string
152 -   any arguments
153 
154    Level: intermediate
155 
156 .seealso: PetscSynchronizedFlush(), PetscSynchronizedFPrintf(), PetscFPrintf(), PetscVSNPrintf(),
157           PetscPrintf(), PetscViewerASCIIPrintf(), PetscViewerASCIISynchronizedPrintf()
158 @*/
159 PetscErrorCode PETSC_DLLEXPORT PetscSNPrintf(char *str,size_t len,const char format[],...)
160 {
161   PetscErrorCode ierr;
162   va_list        Argp;
163 
164   PetscFunctionBegin;
165   va_start(Argp,format);
166   ierr = PetscVSNPrintf(str,len,format,Argp);CHKERRQ(ierr);
167   PetscFunctionReturn(0);
168 }
169 
170 /* ----------------------------------------------------------------------- */
171 
172 PrintfQueue queue       = 0,queuebase = 0;
173 int         queuelength = 0;
174 FILE        *queuefile  = PETSC_NULL;
175 
176 #undef __FUNCT__
177 #define __FUNCT__ "PetscSynchronizedPrintf"
178 /*@C
179     PetscSynchronizedPrintf - Prints synchronized output from several processors.
180     Output of the first processor is followed by that of the second, etc.
181 
182     Not Collective
183 
184     Input Parameters:
185 +   comm - the communicator
186 -   format - the usual printf() format string
187 
188    Level: intermediate
189 
190     Notes:
191     REQUIRES a intervening call to PetscSynchronizedFlush() for the information
192     from all the processors to be printed.
193 
194     Fortran Note:
195     The call sequence is PetscSynchronizedPrintf(PetscViewer, character(*), PetscErrorCode ierr) from Fortran.
196     That is, you can only pass a single character string from Fortran.
197 
198     The length of the formatted message cannot exceed QUEUESTRINGSIZE characters.
199 
200 .seealso: PetscSynchronizedFlush(), PetscSynchronizedFPrintf(), PetscFPrintf(),
201           PetscPrintf(), PetscViewerASCIIPrintf(), PetscViewerASCIISynchronizedPrintf()
202 @*/
203 PetscErrorCode PETSC_DLLEXPORT PetscSynchronizedPrintf(MPI_Comm comm,const char format[],...)
204 {
205   PetscErrorCode ierr;
206   PetscMPIInt    rank;
207 
208   PetscFunctionBegin;
209   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
210 
211   /* First processor prints immediately to stdout */
212   if (!rank) {
213     va_list Argp;
214     va_start(Argp,format);
215     ierr = PetscVFPrintf(PETSC_STDOUT,format,Argp);CHKERRQ(ierr);
216     if (petsc_history) {
217       ierr = PetscVFPrintf(petsc_history,format,Argp);CHKERRQ(ierr);
218     }
219     va_end(Argp);
220   } else { /* other processors add to local queue */
221     va_list     Argp;
222     PrintfQueue next;
223 
224     ierr = PetscNew(struct _PrintfQueue,&next);CHKERRQ(ierr);
225     if (queue) {queue->next = next; queue = next; queue->next = 0;}
226     else       {queuebase   = queue = next;}
227     queuelength++;
228     va_start(Argp,format);
229     ierr = PetscMemzero(next->string,QUEUESTRINGSIZE);CHKERRQ(ierr);
230     ierr = PetscVSNPrintf(next->string,QUEUESTRINGSIZE,format,Argp);CHKERRQ(ierr);
231     va_end(Argp);
232   }
233 
234   PetscFunctionReturn(0);
235 }
236 
237 #undef __FUNCT__
238 #define __FUNCT__ "PetscSynchronizedFPrintf"
239 /*@C
240     PetscSynchronizedFPrintf - Prints synchronized output to the specified file from
241     several processors.  Output of the first processor is followed by that of the
242     second, etc.
243 
244     Not Collective
245 
246     Input Parameters:
247 +   comm - the communicator
248 .   fd - the file pointer
249 -   format - the usual printf() format string
250 
251     Level: intermediate
252 
253     Notes:
254     REQUIRES a intervening call to PetscSynchronizedFlush() for the information
255     from all the processors to be printed.
256 
257     The length of the formatted message cannot exceed QUEUESTRINGSIZE characters.
258 
259     Contributed by: Matthew Knepley
260 
261 .seealso: PetscSynchronizedPrintf(), PetscSynchronizedFlush(), PetscFPrintf(),
262           PetscFOpen(), PetscViewerASCIISynchronizedPrintf(), PetscViewerASCIIPrintf()
263 
264 @*/
265 PetscErrorCode PETSC_DLLEXPORT PetscSynchronizedFPrintf(MPI_Comm comm,FILE* fp,const char format[],...)
266 {
267   PetscErrorCode ierr;
268   PetscMPIInt    rank;
269 
270   PetscFunctionBegin;
271   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
272 
273   /* First processor prints immediately to fp */
274   if (!rank) {
275     va_list Argp;
276     va_start(Argp,format);
277     ierr = PetscVFPrintf(fp,format,Argp);CHKERRQ(ierr);
278     queuefile = fp;
279     if (petsc_history) {
280       ierr = PetscVFPrintf(petsc_history,format,Argp);CHKERRQ(ierr);
281     }
282     va_end(Argp);
283   } else { /* other processors add to local queue */
284     va_list     Argp;
285     PrintfQueue next;
286     ierr = PetscNew(struct _PrintfQueue,&next);CHKERRQ(ierr);
287     if (queue) {queue->next = next; queue = next; queue->next = 0;}
288     else       {queuebase   = queue = next;}
289     queuelength++;
290     va_start(Argp,format);
291     ierr = PetscMemzero(next->string,QUEUESTRINGSIZE);CHKERRQ(ierr);
292     ierr = PetscVSNPrintf(next->string,QUEUESTRINGSIZE,format,Argp);CHKERRQ(ierr);
293     va_end(Argp);
294   }
295   PetscFunctionReturn(0);
296 }
297 
298 #undef __FUNCT__
299 #define __FUNCT__ "PetscSynchronizedFlush"
300 /*@
301     PetscSynchronizedFlush - Flushes to the screen output from all processors
302     involved in previous PetscSynchronizedPrintf() calls.
303 
304     Collective on MPI_Comm
305 
306     Input Parameters:
307 .   comm - the communicator
308 
309     Level: intermediate
310 
311     Notes:
312     Usage of PetscSynchronizedPrintf() and PetscSynchronizedFPrintf() with
313     different MPI communicators REQUIRES an intervening call to PetscSynchronizedFlush().
314 
315 .seealso: PetscSynchronizedPrintf(), PetscFPrintf(), PetscPrintf(), PetscViewerASCIIPrintf(),
316           PetscViewerASCIISynchronizedPrintf()
317 @*/
318 PetscErrorCode PETSC_DLLEXPORT PetscSynchronizedFlush(MPI_Comm comm)
319 {
320   PetscErrorCode ierr;
321   PetscMPIInt    rank,size,tag,i,j,n;
322   char           message[QUEUESTRINGSIZE];
323   MPI_Status     status;
324   FILE           *fd;
325 
326   PetscFunctionBegin;
327   ierr = PetscCommDuplicate(comm,&comm,&tag);CHKERRQ(ierr);
328   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
329   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
330 
331   /* First processor waits for messages from all other processors */
332   if (!rank) {
333     if (queuefile) {
334       fd = queuefile;
335     } else {
336       fd = PETSC_STDOUT;
337     }
338     for (i=1; i<size; i++) {
339       ierr = MPI_Recv(&n,1,MPI_INT,i,tag,comm,&status);CHKERRQ(ierr);
340       for (j=0; j<n; j++) {
341         ierr = MPI_Recv(message,QUEUESTRINGSIZE,MPI_CHAR,i,tag,comm,&status);CHKERRQ(ierr);
342         ierr = PetscFPrintf(comm,fd,"%s",message);
343       }
344     }
345     queuefile = PETSC_NULL;
346   } else { /* other processors send queue to processor 0 */
347     PrintfQueue next = queuebase,previous;
348 
349     ierr = MPI_Send(&queuelength,1,MPI_INT,0,tag,comm);CHKERRQ(ierr);
350     for (i=0; i<queuelength; i++) {
351       ierr     = MPI_Send(next->string,QUEUESTRINGSIZE,MPI_CHAR,0,tag,comm);CHKERRQ(ierr);
352       previous = next;
353       next     = next->next;
354       ierr     = PetscFree(previous);CHKERRQ(ierr);
355     }
356     queue       = 0;
357     queuelength = 0;
358   }
359   ierr = PetscCommDestroy(&comm);CHKERRQ(ierr);
360   PetscFunctionReturn(0);
361 }
362 
363 /* ---------------------------------------------------------------------------------------*/
364 
365 #undef __FUNCT__
366 #define __FUNCT__ "PetscFPrintf"
367 /*@C
368     PetscFPrintf - Prints to a file, only from the first
369     processor in the communicator.
370 
371     Not Collective
372 
373     Input Parameters:
374 +   comm - the communicator
375 .   fd - the file pointer
376 -   format - the usual printf() format string
377 
378     Level: intermediate
379 
380     Fortran Note:
381     This routine is not supported in Fortran.
382 
383    Concepts: printing^in parallel
384    Concepts: printf^in parallel
385 
386 .seealso: PetscPrintf(), PetscSynchronizedPrintf(), PetscViewerASCIIPrintf(),
387           PetscViewerASCIISynchronizedPrintf(), PetscSynchronizedFlush()
388 @*/
389 PetscErrorCode PETSC_DLLEXPORT PetscFPrintf(MPI_Comm comm,FILE* fd,const char format[],...)
390 {
391   PetscErrorCode ierr;
392   PetscMPIInt    rank;
393 
394   PetscFunctionBegin;
395   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
396   if (!rank) {
397     va_list Argp;
398     va_start(Argp,format);
399     ierr = PetscVFPrintf(fd,format,Argp);CHKERRQ(ierr);
400     if (petsc_history) {
401       ierr = PetscVFPrintf(petsc_history,format,Argp);CHKERRQ(ierr);
402     }
403     va_end(Argp);
404   }
405   PetscFunctionReturn(0);
406 }
407 
408 #undef __FUNCT__
409 #define __FUNCT__ "PetscPrintf"
410 /*@C
411     PetscPrintf - Prints to standard out, only from the first
412     processor in the communicator.
413 
414     Not Collective
415 
416     Input Parameters:
417 +   comm - the communicator
418 -   format - the usual printf() format string
419 
420    Level: intermediate
421 
422     Fortran Note:
423     The call sequence is PetscPrintf(PetscViewer, character(*), PetscErrorCode ierr) from Fortran.
424     That is, you can only pass a single character string from Fortran.
425 
426    Notes: %A is replace with %g unless the value is < 1.e-12 when it is
427           replaced with < 1.e-12
428 
429    Concepts: printing^in parallel
430    Concepts: printf^in parallel
431 
432 .seealso: PetscFPrintf(), PetscSynchronizedPrintf()
433 @*/
434 PetscErrorCode PETSC_DLLEXPORT PetscPrintf(MPI_Comm comm,const char format[],...)
435 {
436   PetscErrorCode ierr;
437   PetscMPIInt    rank;
438   size_t         len;
439   char           *nformat,*sub1,*sub2;
440   PetscReal      value;
441 
442   PetscFunctionBegin;
443   if (!comm) comm = PETSC_COMM_WORLD;
444   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
445   if (!rank) {
446     va_list Argp;
447     va_start(Argp,format);
448 
449     ierr = PetscStrstr(format,"%A",&sub1);CHKERRQ(ierr);
450     if (sub1) {
451       ierr = PetscStrstr(format,"%",&sub2);CHKERRQ(ierr);
452       if (sub1 != sub2) SETERRQ(PETSC_ERR_ARG_WRONG,"%%A format must be first in format string");
453       ierr    = PetscStrlen(format,&len);CHKERRQ(ierr);
454       ierr    = PetscMalloc((len+16)*sizeof(char),&nformat);CHKERRQ(ierr);
455       ierr    = PetscStrcpy(nformat,format);CHKERRQ(ierr);
456       ierr    = PetscStrstr(nformat,"%",&sub2);CHKERRQ(ierr);
457       sub2[0] = 0;
458       value   = (double)va_arg(Argp,double);
459       if (PetscAbsReal(value) < 1.e-12) {
460         ierr    = PetscStrcat(nformat,"< 1.e-12");CHKERRQ(ierr);
461       } else {
462         ierr    = PetscStrcat(nformat,"%g");CHKERRQ(ierr);
463         va_end(Argp);
464         va_start(Argp,format);
465       }
466       ierr    = PetscStrcat(nformat,sub1+2);CHKERRQ(ierr);
467     } else {
468       nformat = (char*)format;
469     }
470     ierr = PetscVFPrintf(PETSC_STDOUT,nformat,Argp);CHKERRQ(ierr);
471     if (petsc_history) {
472       ierr = PetscVFPrintf(petsc_history,nformat,Argp);CHKERRQ(ierr);
473     }
474     va_end(Argp);
475     if (sub1) {ierr = PetscFree(nformat);CHKERRQ(ierr);}
476   }
477   PetscFunctionReturn(0);
478 }
479 
480 /* ---------------------------------------------------------------------------------------*/
481 #undef __FUNCT__
482 #define __FUNCT__ "PetscHelpPrintfDefault"
483 PetscErrorCode PETSC_DLLEXPORT PetscHelpPrintfDefault(MPI_Comm comm,const char format[],...)
484 {
485   PetscErrorCode ierr;
486   PetscMPIInt    rank;
487 
488   PetscFunctionBegin;
489   if (!comm) comm = PETSC_COMM_WORLD;
490   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
491   if (!rank) {
492     va_list Argp;
493     va_start(Argp,format);
494     ierr = PetscVFPrintf(PETSC_STDOUT,format,Argp);CHKERRQ(ierr);
495     if (petsc_history) {
496       ierr = PetscVFPrintf(petsc_history,format,Argp);CHKERRQ(ierr);
497     }
498     va_end(Argp);
499   }
500   PetscFunctionReturn(0);
501 }
502 
503 /* ---------------------------------------------------------------------------------------*/
504 
505 
506 #undef __FUNCT__
507 #define __FUNCT__ "PetscSynchronizedFGets"
508 /*@C
509     PetscSynchronizedFGets - Several processors all get the same line from a file.
510 
511     Collective on MPI_Comm
512 
513     Input Parameters:
514 +   comm - the communicator
515 .   fd - the file pointer
516 -   len - the length of the output buffer
517 
518     Output Parameter:
519 .   string - the line read from the file
520 
521     Level: intermediate
522 
523 .seealso: PetscSynchronizedPrintf(), PetscSynchronizedFlush(),
524           PetscFOpen(), PetscViewerASCIISynchronizedPrintf(), PetscViewerASCIIPrintf()
525 
526 @*/
527 PetscErrorCode PETSC_DLLEXPORT PetscSynchronizedFGets(MPI_Comm comm,FILE* fp,size_t len,char string[])
528 {
529   PetscErrorCode ierr;
530   PetscMPIInt    rank;
531 
532   PetscFunctionBegin;
533   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
534 
535   if (!rank) {
536     fgets(string,len,fp);
537   }
538   ierr = MPI_Bcast(string,len,MPI_BYTE,0,comm);CHKERRQ(ierr);
539   PetscFunctionReturn(0);
540 }
541