xref: /petsc/src/sys/fileio/mprint.c (revision ae9b4142d2ca751b76c4cfd50549e9aa91b2b04f)
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 #undef __FUNCT__
25 #define __FUNCT__ "PetscFormatConvert"
26 PetscErrorCode PETSC_DLLEXPORT PetscFormatConvert(const char *format,char *newformat,PetscInt size)
27 {
28   PetscInt i = 0,j = 0;
29 
30   while (format[i] && i < size-1) {
31     if (format[i] == '%' && format[i+1] == 'D') {
32       newformat[j++] = '%';
33 #if defined(PETSC_USE_32BIT_INT)
34       newformat[j++] = 'd';
35 #else
36       newformat[j++] = 'l';
37       newformat[j++] = 'l';
38       newformat[j++] = 'd';
39 #endif
40       i += 2;
41     } else if (format[i] == '%' && format[i+1] >= '1' && format[i+1] <= '9' && format[i+2] == 'D') {
42       newformat[j++] = '%';
43       newformat[j++] = format[i+1];
44 #if defined(PETSC_USE_32BIT_INT)
45       newformat[j++] = 'd';
46 #else
47       newformat[j++] = 'l';
48       newformat[j++] = 'l';
49       newformat[j++] = 'd';
50 #endif
51       i += 3;
52     } else if (format[i] == '%' && format[i+1] == 'G') {
53       newformat[j++] = '%';
54 #if defined(PETSC_USE_INT)
55       newformat[j++] = 'd';
56 #elif !defined(PETSC_USE_LONG_DOUBLE)
57       newformat[j++] = 'g';
58 #else
59       newformat[j++] = 'L';
60       newformat[j++] = 'g';
61 #endif
62       i += 2;
63     }else {
64       newformat[j++] = format[i++];
65     }
66   }
67   newformat[j] = 0;
68   return 0;
69 }
70 
71 #undef __FUNCT__
72 #define __FUNCT__ "PetscVSNPrintf"
73 /*
74    No error handling because may be called by error handler
75 */
76 PetscErrorCode PETSC_DLLEXPORT PetscVSNPrintf(char *str,size_t len,const char *format,va_list Argp)
77 {
78   /* no malloc since may be called by error handler */
79   char           newformat[8*1024];
80   size_t         length;
81   PetscErrorCode ierr;
82 
83   PetscFormatConvert(format,newformat,8*1024);
84   ierr = PetscStrlen(newformat, &length);CHKERRQ(ierr);
85   if (length > len) {
86     newformat[len] = '\0';
87   }
88 #if defined(PETSC_HAVE_VPRINTF_CHAR)
89   vsprintf(str,newformat,(char *)Argp);
90 #else
91   vsprintf(str,newformat,Argp);
92 #endif
93   return 0;
94 }
95 
96 #undef __FUNCT__
97 #define __FUNCT__ "PetscVFPrintf"
98 /*
99    All PETSc standard out and error messages are sent through this function; so, in theory, this can
100    can be replaced with something that does not simply write to a file.
101 
102    Note: For error messages this may be called by a process, for regular standard out it is
103    called only by process 0 of a given communicator
104 
105    No error handling because may be called by error handler
106 */
107 PetscErrorCode PETSC_DLLEXPORT PetscVFPrintf(FILE *fd,const char *format,va_list Argp)
108 {
109   /* no malloc since may be called by error handler */
110   char     newformat[8*1024];
111 
112   PetscFormatConvert(format,newformat,8*1024);
113 #if defined(PETSC_HAVE_VPRINTF_CHAR)
114   vfprintf(fd,newformat,(char *)Argp);
115 #else
116   vfprintf(fd,newformat,Argp);
117   fflush(fd);
118 #endif
119   return 0;
120 }
121 
122 #undef __FUNCT__
123 #define __FUNCT__ "PetscSNPrintf"
124 /*@C
125     PetscSNPrintf - Prints to a string of given length
126 
127     Not Collective
128 
129     Input Parameters:
130 +   str - the string to print to
131 .   len - the length of str
132 .   format - the usual printf() format string
133 -   any arguments
134 
135    Level: intermediate
136 
137 .seealso: PetscSynchronizedFlush(), PetscSynchronizedFPrintf(), PetscFPrintf(), PetscVSNPrintf(),
138           PetscPrintf(), PetscViewerASCIIPrintf(), PetscViewerASCIISynchronizedPrintf()
139 @*/
140 PetscErrorCode PETSC_DLLEXPORT PetscSNPrintf(char *str,size_t len,const char format[],...)
141 {
142   PetscErrorCode ierr;
143   va_list        Argp;
144 
145   PetscFunctionBegin;
146   va_start(Argp,format);
147   ierr = PetscVSNPrintf(str,len,format,Argp);CHKERRQ(ierr);
148   PetscFunctionReturn(0);
149 }
150 
151 /* ----------------------------------------------------------------------- */
152 
153 PrintfQueue queue       = 0,queuebase = 0;
154 int         queuelength = 0;
155 FILE        *queuefile  = PETSC_NULL;
156 
157 #undef __FUNCT__
158 #define __FUNCT__ "PetscSynchronizedPrintf"
159 /*@C
160     PetscSynchronizedPrintf - Prints synchronized output from several processors.
161     Output of the first processor is followed by that of the second, etc.
162 
163     Not Collective
164 
165     Input Parameters:
166 +   comm - the communicator
167 -   format - the usual printf() format string
168 
169    Level: intermediate
170 
171     Notes:
172     REQUIRES a intervening call to PetscSynchronizedFlush() for the information
173     from all the processors to be printed.
174 
175     Fortran Note:
176     The call sequence is PetscSynchronizedPrintf(PetscViewer, character(*), PetscErrorCode ierr) from Fortran.
177     That is, you can only pass a single character string from Fortran.
178 
179     The length of the formatted message cannot exceed QUEUESTRINGSIZE characters.
180 
181 .seealso: PetscSynchronizedFlush(), PetscSynchronizedFPrintf(), PetscFPrintf(),
182           PetscPrintf(), PetscViewerASCIIPrintf(), PetscViewerASCIISynchronizedPrintf()
183 @*/
184 PetscErrorCode PETSC_DLLEXPORT PetscSynchronizedPrintf(MPI_Comm comm,const char format[],...)
185 {
186   PetscErrorCode ierr;
187   PetscMPIInt    rank;
188 
189   PetscFunctionBegin;
190   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
191 
192   /* First processor prints immediately to stdout */
193   if (!rank) {
194     va_list Argp;
195     va_start(Argp,format);
196     ierr = PetscVFPrintf(PETSC_STDOUT,format,Argp);CHKERRQ(ierr);
197     if (petsc_history) {
198       ierr = PetscVFPrintf(petsc_history,format,Argp);CHKERRQ(ierr);
199     }
200     va_end(Argp);
201   } else { /* other processors add to local queue */
202     va_list     Argp;
203     PrintfQueue next;
204 
205     ierr = PetscNew(struct _PrintfQueue,&next);CHKERRQ(ierr);
206     if (queue) {queue->next = next; queue = next; queue->next = 0;}
207     else       {queuebase   = queue = next;}
208     queuelength++;
209     va_start(Argp,format);
210     ierr = PetscMemzero(next->string,QUEUESTRINGSIZE);CHKERRQ(ierr);
211     ierr = PetscVSNPrintf(next->string,QUEUESTRINGSIZE,format,Argp);CHKERRQ(ierr);
212     va_end(Argp);
213   }
214 
215   PetscFunctionReturn(0);
216 }
217 
218 #undef __FUNCT__
219 #define __FUNCT__ "PetscSynchronizedFPrintf"
220 /*@C
221     PetscSynchronizedFPrintf - Prints synchronized output to the specified file from
222     several processors.  Output of the first processor is followed by that of the
223     second, etc.
224 
225     Not Collective
226 
227     Input Parameters:
228 +   comm - the communicator
229 .   fd - the file pointer
230 -   format - the usual printf() format string
231 
232     Level: intermediate
233 
234     Notes:
235     REQUIRES a intervening call to PetscSynchronizedFlush() for the information
236     from all the processors to be printed.
237 
238     The length of the formatted message cannot exceed QUEUESTRINGSIZE characters.
239 
240     Contributed by: Matthew Knepley
241 
242 .seealso: PetscSynchronizedPrintf(), PetscSynchronizedFlush(), PetscFPrintf(),
243           PetscFOpen(), PetscViewerASCIISynchronizedPrintf(), PetscViewerASCIIPrintf()
244 
245 @*/
246 PetscErrorCode PETSC_DLLEXPORT PetscSynchronizedFPrintf(MPI_Comm comm,FILE* fp,const char format[],...)
247 {
248   PetscErrorCode ierr;
249   PetscMPIInt    rank;
250 
251   PetscFunctionBegin;
252   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
253 
254   /* First processor prints immediately to fp */
255   if (!rank) {
256     va_list Argp;
257     va_start(Argp,format);
258     ierr = PetscVFPrintf(fp,format,Argp);CHKERRQ(ierr);
259     queuefile = fp;
260     if (petsc_history) {
261       ierr = PetscVFPrintf(petsc_history,format,Argp);CHKERRQ(ierr);
262     }
263     va_end(Argp);
264   } else { /* other processors add to local queue */
265     va_list     Argp;
266     PrintfQueue next;
267     ierr = PetscNew(struct _PrintfQueue,&next);CHKERRQ(ierr);
268     if (queue) {queue->next = next; queue = next; queue->next = 0;}
269     else       {queuebase   = queue = next;}
270     queuelength++;
271     va_start(Argp,format);
272     ierr = PetscMemzero(next->string,QUEUESTRINGSIZE);CHKERRQ(ierr);
273     ierr = PetscVSNPrintf(next->string,QUEUESTRINGSIZE,format,Argp);CHKERRQ(ierr);
274     va_end(Argp);
275   }
276   PetscFunctionReturn(0);
277 }
278 
279 #undef __FUNCT__
280 #define __FUNCT__ "PetscSynchronizedFlush"
281 /*@
282     PetscSynchronizedFlush - Flushes to the screen output from all processors
283     involved in previous PetscSynchronizedPrintf() calls.
284 
285     Collective on MPI_Comm
286 
287     Input Parameters:
288 .   comm - the communicator
289 
290     Level: intermediate
291 
292     Notes:
293     Usage of PetscSynchronizedPrintf() and PetscSynchronizedFPrintf() with
294     different MPI communicators REQUIRES an intervening call to PetscSynchronizedFlush().
295 
296 .seealso: PetscSynchronizedPrintf(), PetscFPrintf(), PetscPrintf(), PetscViewerASCIIPrintf(),
297           PetscViewerASCIISynchronizedPrintf()
298 @*/
299 PetscErrorCode PETSC_DLLEXPORT PetscSynchronizedFlush(MPI_Comm comm)
300 {
301   PetscErrorCode ierr;
302   PetscMPIInt    rank,size,tag,i,j,n;
303   char           message[QUEUESTRINGSIZE];
304   MPI_Status     status;
305   FILE           *fd;
306 
307   PetscFunctionBegin;
308   ierr = PetscCommDuplicate(comm,&comm,&tag);CHKERRQ(ierr);
309   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
310   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
311 
312   /* First processor waits for messages from all other processors */
313   if (!rank) {
314     if (queuefile) {
315       fd = queuefile;
316     } else {
317       fd = PETSC_STDOUT;
318     }
319     for (i=1; i<size; i++) {
320       ierr = MPI_Recv(&n,1,MPI_INT,i,tag,comm,&status);CHKERRQ(ierr);
321       for (j=0; j<n; j++) {
322         ierr = MPI_Recv(message,QUEUESTRINGSIZE,MPI_CHAR,i,tag,comm,&status);CHKERRQ(ierr);
323         ierr = PetscFPrintf(comm,fd,"%s",message);
324       }
325     }
326     queuefile = PETSC_NULL;
327   } else { /* other processors send queue to processor 0 */
328     PrintfQueue next = queuebase,previous;
329 
330     ierr = MPI_Send(&queuelength,1,MPI_INT,0,tag,comm);CHKERRQ(ierr);
331     for (i=0; i<queuelength; i++) {
332       ierr     = MPI_Send(next->string,QUEUESTRINGSIZE,MPI_CHAR,0,tag,comm);CHKERRQ(ierr);
333       previous = next;
334       next     = next->next;
335       ierr     = PetscFree(previous);CHKERRQ(ierr);
336     }
337     queue       = 0;
338     queuelength = 0;
339   }
340   ierr = PetscCommDestroy(&comm);CHKERRQ(ierr);
341   PetscFunctionReturn(0);
342 }
343 
344 /* ---------------------------------------------------------------------------------------*/
345 
346 #undef __FUNCT__
347 #define __FUNCT__ "PetscFPrintf"
348 /*@C
349     PetscFPrintf - Prints to a file, only from the first
350     processor in the communicator.
351 
352     Not Collective
353 
354     Input Parameters:
355 +   comm - the communicator
356 .   fd - the file pointer
357 -   format - the usual printf() format string
358 
359     Level: intermediate
360 
361     Fortran Note:
362     This routine is not supported in Fortran.
363 
364    Concepts: printing^in parallel
365    Concepts: printf^in parallel
366 
367 .seealso: PetscPrintf(), PetscSynchronizedPrintf(), PetscViewerASCIIPrintf(),
368           PetscViewerASCIISynchronizedPrintf(), PetscSynchronizedFlush()
369 @*/
370 PetscErrorCode PETSC_DLLEXPORT PetscFPrintf(MPI_Comm comm,FILE* fd,const char format[],...)
371 {
372   PetscErrorCode ierr;
373   PetscMPIInt    rank;
374 
375   PetscFunctionBegin;
376   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
377   if (!rank) {
378     va_list Argp;
379     va_start(Argp,format);
380     ierr = PetscVFPrintf(fd,format,Argp);CHKERRQ(ierr);
381     if (petsc_history) {
382       ierr = PetscVFPrintf(petsc_history,format,Argp);CHKERRQ(ierr);
383     }
384     va_end(Argp);
385   }
386   PetscFunctionReturn(0);
387 }
388 
389 #undef __FUNCT__
390 #define __FUNCT__ "PetscPrintf"
391 /*@C
392     PetscPrintf - Prints to standard out, only from the first
393     processor in the communicator.
394 
395     Not Collective
396 
397     Input Parameters:
398 +   comm - the communicator
399 -   format - the usual printf() format string
400 
401    Level: intermediate
402 
403     Fortran Note:
404     The call sequence is PetscPrintf(PetscViewer, character(*), PetscErrorCode ierr) from Fortran.
405     That is, you can only pass a single character string from Fortran.
406 
407    Notes: %A is replace with %g unless the value is < 1.e-12 when it is
408           replaced with < 1.e-12
409 
410    Concepts: printing^in parallel
411    Concepts: printf^in parallel
412 
413 .seealso: PetscFPrintf(), PetscSynchronizedPrintf()
414 @*/
415 PetscErrorCode PETSC_DLLEXPORT PetscPrintf(MPI_Comm comm,const char format[],...)
416 {
417   PetscErrorCode ierr;
418   PetscMPIInt    rank;
419   size_t         len;
420   char           *nformat,*sub1,*sub2;
421   PetscReal      value;
422 
423   PetscFunctionBegin;
424   if (!comm) comm = PETSC_COMM_WORLD;
425   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
426   if (!rank) {
427     va_list Argp;
428     va_start(Argp,format);
429 
430     ierr = PetscStrstr(format,"%A",&sub1);CHKERRQ(ierr);
431     if (sub1) {
432       ierr = PetscStrstr(format,"%",&sub2);CHKERRQ(ierr);
433       if (sub1 != sub2) SETERRQ(PETSC_ERR_ARG_WRONG,"%%A format must be first in format string");
434       ierr    = PetscStrlen(format,&len);CHKERRQ(ierr);
435       ierr    = PetscMalloc((len+16)*sizeof(char),&nformat);CHKERRQ(ierr);
436       ierr    = PetscStrcpy(nformat,format);CHKERRQ(ierr);
437       ierr    = PetscStrstr(nformat,"%",&sub2);CHKERRQ(ierr);
438       sub2[0] = 0;
439       value   = (double)va_arg(Argp,double);
440       if (PetscAbsReal(value) < 1.e-12) {
441         ierr    = PetscStrcat(nformat,"< 1.e-12");CHKERRQ(ierr);
442       } else {
443         ierr    = PetscStrcat(nformat,"%g");CHKERRQ(ierr);
444         va_end(Argp);
445         va_start(Argp,format);
446       }
447       ierr    = PetscStrcat(nformat,sub1+2);CHKERRQ(ierr);
448     } else {
449       nformat = (char*)format;
450     }
451     ierr = PetscVFPrintf(PETSC_STDOUT,nformat,Argp);CHKERRQ(ierr);
452     if (petsc_history) {
453       ierr = PetscVFPrintf(petsc_history,nformat,Argp);CHKERRQ(ierr);
454     }
455     va_end(Argp);
456     if (sub1) {ierr = PetscFree(nformat);CHKERRQ(ierr);}
457   }
458   PetscFunctionReturn(0);
459 }
460 
461 /* ---------------------------------------------------------------------------------------*/
462 #undef __FUNCT__
463 #define __FUNCT__ "PetscHelpPrintfDefault"
464 PetscErrorCode PETSC_DLLEXPORT PetscHelpPrintfDefault(MPI_Comm comm,const char format[],...)
465 {
466   PetscErrorCode ierr;
467   PetscMPIInt    rank;
468 
469   PetscFunctionBegin;
470   if (!comm) comm = PETSC_COMM_WORLD;
471   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
472   if (!rank) {
473     va_list Argp;
474     va_start(Argp,format);
475     ierr = PetscVFPrintf(PETSC_STDOUT,format,Argp);CHKERRQ(ierr);
476     if (petsc_history) {
477       ierr = PetscVFPrintf(petsc_history,format,Argp);CHKERRQ(ierr);
478     }
479     va_end(Argp);
480   }
481   PetscFunctionReturn(0);
482 }
483 
484 /* ---------------------------------------------------------------------------------------*/
485 
486 
487 #undef __FUNCT__
488 #define __FUNCT__ "PetscSynchronizedFGets"
489 /*@C
490     PetscSynchronizedFGets - Several processors all get the same line from a file.
491 
492     Collective on MPI_Comm
493 
494     Input Parameters:
495 +   comm - the communicator
496 .   fd - the file pointer
497 -   len - the length of the output buffer
498 
499     Output Parameter:
500 .   string - the line read from the file
501 
502     Level: intermediate
503 
504 .seealso: PetscSynchronizedPrintf(), PetscSynchronizedFlush(),
505           PetscFOpen(), PetscViewerASCIISynchronizedPrintf(), PetscViewerASCIIPrintf()
506 
507 @*/
508 PetscErrorCode PETSC_DLLEXPORT PetscSynchronizedFGets(MPI_Comm comm,FILE* fp,size_t len,char string[])
509 {
510   PetscErrorCode ierr;
511   PetscMPIInt    rank;
512 
513   PetscFunctionBegin;
514   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
515 
516   if (!rank) {
517     fgets(string,len,fp);
518   }
519   ierr = MPI_Bcast(string,len,MPI_BYTE,0,comm);CHKERRQ(ierr);
520   PetscFunctionReturn(0);
521 }
522