xref: /petsc/src/sys/fileio/mprint.c (revision 0700a8246d308f50502909ba325e6169d3ee27eb)
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 
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_VFPRINTF_CHAR)
135   vfprintf(PETSC_ZOPEFD,log,(char *)Argp);
136 #else
137   vfprintf(PETSC_ZOPEFD,log,Argp);
138 #endif
139   fflush(PETSC_ZOPEFD);
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     (void)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_VA_COPY) || defined(PETSC_HAVE___VA_COPY)
181 #if defined(PETSC_HAVE_VFPRINTF_CHAR)
182     vfprintf(PETSC_ZOPEFD,newformat,(char *)s);
183 #else
184     vfprintf(PETSC_ZOPEFD,newformat,s);
185 #endif
186     fflush(PETSC_ZOPEFD);
187 #endif
188   }
189 
190 #if defined(PETSC_HAVE_VFPRINTF_CHAR)
191   vfprintf(fd,newformat,(char *)Argp);
192 #else
193   vfprintf(fd,newformat,Argp);
194 #endif
195   fflush(fd);
196   if (oldLength >= 8*1024) {
197     if (PetscFree(newformat)) {};
198   }
199   return 0;
200 }
201 
202 #undef __FUNCT__
203 #define __FUNCT__ "PetscSNPrintf"
204 /*@C
205     PetscSNPrintf - Prints to a string of given length
206 
207     Not Collective
208 
209     Input Parameters:
210 +   str - the string to print to
211 .   len - the length of str
212 .   format - the usual printf() format string
213 -   any arguments
214 
215    Level: intermediate
216 
217 .seealso: PetscSynchronizedFlush(), PetscSynchronizedFPrintf(), PetscFPrintf(), PetscVSNPrintf(),
218           PetscPrintf(), PetscViewerASCIIPrintf(), PetscViewerASCIISynchronizedPrintf()
219 @*/
220 PetscErrorCode PETSC_DLLEXPORT PetscSNPrintf(char *str,size_t len,const char format[],...)
221 {
222   PetscErrorCode ierr;
223   int            fullLength;
224   va_list        Argp;
225 
226   PetscFunctionBegin;
227   va_start(Argp,format);
228   ierr = PetscVSNPrintf(str,len,format,&fullLength,Argp);CHKERRQ(ierr);
229   PetscFunctionReturn(0);
230 }
231 
232 /* ----------------------------------------------------------------------- */
233 
234 PrintfQueue queue       = 0,queuebase = 0;
235 int         queuelength = 0;
236 FILE        *queuefile  = PETSC_NULL;
237 
238 #undef __FUNCT__
239 #define __FUNCT__ "PetscSynchronizedPrintf"
240 /*@C
241     PetscSynchronizedPrintf - Prints synchronized output from several processors.
242     Output of the first processor is followed by that of the second, etc.
243 
244     Not Collective
245 
246     Input Parameters:
247 +   comm - the communicator
248 -   format - the usual printf() format string
249 
250    Level: intermediate
251 
252     Notes:
253     REQUIRES a intervening call to PetscSynchronizedFlush() for the information
254     from all the processors to be printed.
255 
256     Fortran Note:
257     The call sequence is PetscSynchronizedPrintf(MPI_Comm, character(*), PetscErrorCode ierr) from Fortran.
258     That is, you can only pass a single character string from Fortran.
259 
260 .seealso: PetscSynchronizedFlush(), PetscSynchronizedFPrintf(), PetscFPrintf(),
261           PetscPrintf(), PetscViewerASCIIPrintf(), PetscViewerASCIISynchronizedPrintf()
262 @*/
263 PetscErrorCode PETSC_DLLEXPORT PetscSynchronizedPrintf(MPI_Comm comm,const char format[],...)
264 {
265   PetscErrorCode ierr;
266   PetscMPIInt    rank;
267 
268   PetscFunctionBegin;
269   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
270 
271   /* First processor prints immediately to stdout */
272   if (!rank) {
273     va_list Argp;
274     va_start(Argp,format);
275     ierr = (*PetscVFPrintf)(PETSC_STDOUT,format,Argp);CHKERRQ(ierr);
276     if (petsc_history) {
277       ierr = (*PetscVFPrintf)(petsc_history,format,Argp);CHKERRQ(ierr);
278     }
279     va_end(Argp);
280   } else { /* other processors add to local queue */
281     va_list     Argp;
282     PrintfQueue next;
283     int         fullLength = 8191;
284 
285     ierr = PetscNew(struct _PrintfQueue,&next);CHKERRQ(ierr);
286     if (queue) {queue->next = next; queue = next; queue->next = 0;}
287     else       {queuebase   = queue = next;}
288     queuelength++;
289     next->size = -1;
290     while(fullLength >= next->size) {
291       next->size = fullLength+1;
292       ierr = PetscMalloc(next->size * sizeof(char), &next->string);CHKERRQ(ierr);
293       va_start(Argp,format);
294       ierr = PetscMemzero(next->string,next->size);CHKERRQ(ierr);
295       ierr = PetscVSNPrintf(next->string,next->size,format, &fullLength,Argp);CHKERRQ(ierr);
296       va_end(Argp);
297     }
298   }
299 
300   PetscFunctionReturn(0);
301 }
302 
303 #undef __FUNCT__
304 #define __FUNCT__ "PetscSynchronizedFPrintf"
305 /*@C
306     PetscSynchronizedFPrintf - Prints synchronized output to the specified file from
307     several processors.  Output of the first processor is followed by that of the
308     second, etc.
309 
310     Not Collective
311 
312     Input Parameters:
313 +   comm - the communicator
314 .   fd - the file pointer
315 -   format - the usual printf() format string
316 
317     Level: intermediate
318 
319     Notes:
320     REQUIRES a intervening call to PetscSynchronizedFlush() for the information
321     from all the processors to be printed.
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(MPI_Comm, 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