xref: /petsc/src/sys/fileio/mprint.c (revision f3fe499b4cc4d64bf04aa4f5e4963dcc4eb56541)
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_SCALAR_INT)
59       newformat[j++] = 'd';
60 #elif !defined(PETSC_USE_SCALAR_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_VSNPRINTF_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 PetscErrorCode PETSC_DLLEXPORT PetscZopeLog(const char *format,va_list Argp)
119 {
120   /* no malloc since may be called by error handler */
121   char        newformat[8*1024];
122   char        log[8*1024];
123   char        logstart[] = " <<<log>>>";
124   size_t      len;
125   size_t      formatlen;
126 
127   PetscFormatConvert(format,newformat,8*1024);
128   PetscStrlen(logstart, &len);
129   PetscMemcpy(log, logstart, len);
130   PetscStrlen(newformat, &formatlen);
131   PetscMemcpy(&(log[len]), newformat, formatlen);
132   if (PETSC_ZOPEFD){
133 #if defined(PETSC_HAVE_VFPRINTF_CHAR)
134     vfprintf(PETSC_ZOPEFD,log,(char *)Argp);
135 #else
136     vfprintf(PETSC_ZOPEFD,log,Argp);
137 #endif
138     fflush(PETSC_ZOPEFD);
139   }
140   return 0;
141 }
142 
143 #undef __FUNCT__
144 #define __FUNCT__ "PetscVFPrintf"
145 /*
146    All PETSc standard out and error messages are sent through this function; so, in theory, this can
147    can be replaced with something that does not simply write to a file.
148 
149    Note: For error messages this may be called by a process, for regular standard out it is
150    called only by process 0 of a given communicator
151 
152    No error handling because may be called by error handler
153 */
154 PetscErrorCode PETSC_DLLEXPORT PetscVFPrintfDefault(FILE *fd,const char *format,va_list Argp)
155 {
156   /* no malloc since may be called by error handler (assume no long messages in errors) */
157   char        *newformat;
158   char         formatbuf[8*1024];
159   size_t       oldLength;
160 
161   PetscStrlen(format, &oldLength);
162   if (oldLength < 8*1024) {
163     newformat = formatbuf;
164   } else {
165     (void)PetscMalloc((oldLength+1) * sizeof(char), &newformat);
166   }
167   PetscFormatConvert(format,newformat,oldLength+1);
168   if (PETSC_ZOPEFD && 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_COMM_SELF,PETSC_ERR_SUP_SYS,"Zope not supported due to missing va_copy()");
176 #endif
177 
178 #if defined(PETSC_HAVE_VA_COPY) || defined(PETSC_HAVE___VA_COPY)
179 #if defined(PETSC_HAVE_VFPRINTF_CHAR)
180     vfprintf(PETSC_ZOPEFD,newformat,(char *)s);
181 #else
182     vfprintf(PETSC_ZOPEFD,newformat,s);
183 #endif
184     fflush(PETSC_ZOPEFD);
185 #endif
186   }
187 
188 #if defined(PETSC_HAVE_VFPRINTF_CHAR)
189   vfprintf(fd,newformat,(char *)Argp);
190 #else
191   vfprintf(fd,newformat,Argp);
192 #endif
193   fflush(fd);
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(MPI_Comm, 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 .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(MPI_Comm, 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_COMM_SELF,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