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