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