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