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