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