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