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