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