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