xref: /petsc/src/sys/fileio/mprint.c (revision 2709ce016fdb2fbd7a6f81b7d47efc68bb667c07)
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 PETSCSYS_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 PETSCSYS_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 PetscErrorCode PETSCSYS_DLLEXPORT PetscZopeLog(const char *format,va_list Argp)
119 {
120   /* no malloc since may be called by error handler */
121   char        newformat[8*1024];
122   char        log[8*1024];
123   char        logstart[] = " <<<log>>>";
124   size_t      len;
125   size_t      formatlen;
126 
127   PetscFormatConvert(format,newformat,8*1024);
128   PetscStrlen(logstart, &len);
129   PetscMemcpy(log, logstart, len);
130   PetscStrlen(newformat, &formatlen);
131   PetscMemcpy(&(log[len]), newformat, formatlen);
132   if (PETSC_ZOPEFD){
133 #if defined(PETSC_HAVE_VFPRINTF_CHAR)
134     vfprintf(PETSC_ZOPEFD,log,(char *)Argp);
135 #else
136     vfprintf(PETSC_ZOPEFD,log,Argp);
137 #endif
138     fflush(PETSC_ZOPEFD);
139   }
140   return 0;
141 }
142 
143 #undef __FUNCT__
144 #define __FUNCT__ "PetscVFPrintf"
145 /*
146    All PETSc standard out and error messages are sent through this function; so, in theory, this can
147    can be replaced with something that does not simply write to a file.
148 
149    Note: For error messages this may be called by a process, for regular standard out it is
150    called only by process 0 of a given communicator
151 
152    No error handling because may be called by error handler
153 */
154 PetscErrorCode PETSCSYS_DLLEXPORT PetscVFPrintfDefault(FILE *fd,const char *format,va_list Argp)
155 {
156   /* no malloc since may be called by error handler (assume no long messages in errors) */
157   char        *newformat;
158   char         formatbuf[8*1024];
159   size_t       oldLength;
160 
161   PetscStrlen(format, &oldLength);
162   if (oldLength < 8*1024) {
163     newformat = formatbuf;
164   } else {
165     (void)PetscMalloc((oldLength+1) * sizeof(char), &newformat);
166   }
167   PetscFormatConvert(format,newformat,oldLength+1);
168   if (PETSC_ZOPEFD && PETSC_ZOPEFD != PETSC_STDOUT){
169     va_list s;
170 #if defined(PETSC_HAVE_VA_COPY)
171     va_copy(s, Argp);
172 #elif defined(PETSC_HAVE___VA_COPY)
173     __va_copy(s, Argp);
174 #else
175     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS,"Zope not supported due to missing va_copy()");
176 #endif
177 
178 #if defined(PETSC_HAVE_VA_COPY) || defined(PETSC_HAVE___VA_COPY)
179 #if defined(PETSC_HAVE_VFPRINTF_CHAR)
180     vfprintf(PETSC_ZOPEFD,newformat,(char *)s);
181 #else
182     vfprintf(PETSC_ZOPEFD,newformat,s);
183 #endif
184     fflush(PETSC_ZOPEFD);
185 #endif
186   }
187 
188 #if defined(PETSC_HAVE_VFPRINTF_CHAR)
189   vfprintf(fd,newformat,(char *)Argp);
190 #else
191   vfprintf(fd,newformat,Argp);
192 #endif
193   fflush(fd);
194   if (oldLength >= 8*1024) {
195     if (PetscFree(newformat)) {};
196   }
197   return 0;
198 }
199 
200 #undef __FUNCT__
201 #define __FUNCT__ "PetscSNPrintf"
202 /*@C
203     PetscSNPrintf - Prints to a string of given length
204 
205     Not Collective
206 
207     Input Parameters:
208 +   str - the string to print to
209 .   len - the length of str
210 .   format - the usual printf() format string
211 -   any arguments
212 
213    Level: intermediate
214 
215 .seealso: PetscSynchronizedFlush(), PetscSynchronizedFPrintf(), PetscFPrintf(), PetscVSNPrintf(),
216           PetscPrintf(), PetscViewerASCIIPrintf(), PetscViewerASCIISynchronizedPrintf()
217 @*/
218 PetscErrorCode PETSCSYS_DLLEXPORT PetscSNPrintf(char *str,size_t len,const char format[],...)
219 {
220   PetscErrorCode ierr;
221   int            fullLength;
222   va_list        Argp;
223 
224   PetscFunctionBegin;
225   va_start(Argp,format);
226   ierr = PetscVSNPrintf(str,len,format,&fullLength,Argp);CHKERRQ(ierr);
227   PetscFunctionReturn(0);
228 }
229 
230 /* ----------------------------------------------------------------------- */
231 
232 PrintfQueue queue       = 0,queuebase = 0;
233 int         queuelength = 0;
234 FILE        *queuefile  = PETSC_NULL;
235 
236 #undef __FUNCT__
237 #define __FUNCT__ "PetscSynchronizedPrintf"
238 /*@C
239     PetscSynchronizedPrintf - Prints synchronized output from several processors.
240     Output of the first processor is followed by that of the second, etc.
241 
242     Not Collective
243 
244     Input Parameters:
245 +   comm - the communicator
246 -   format - the usual printf() format string
247 
248    Level: intermediate
249 
250     Notes:
251     REQUIRES a intervening call to PetscSynchronizedFlush() for the information
252     from all the processors to be printed.
253 
254     Fortran Note:
255     The call sequence is PetscSynchronizedPrintf(MPI_Comm, character(*), PetscErrorCode ierr) from Fortran.
256     That is, you can only pass a single character string from Fortran.
257 
258 .seealso: PetscSynchronizedFlush(), PetscSynchronizedFPrintf(), PetscFPrintf(),
259           PetscPrintf(), PetscViewerASCIIPrintf(), PetscViewerASCIISynchronizedPrintf()
260 @*/
261 PetscErrorCode PETSCSYS_DLLEXPORT PetscSynchronizedPrintf(MPI_Comm comm,const char format[],...)
262 {
263   PetscErrorCode ierr;
264   PetscMPIInt    rank;
265 
266   PetscFunctionBegin;
267   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
268 
269   /* First processor prints immediately to stdout */
270   if (!rank) {
271     va_list Argp;
272     va_start(Argp,format);
273     ierr = (*PetscVFPrintf)(PETSC_STDOUT,format,Argp);CHKERRQ(ierr);
274     if (petsc_history) {
275       ierr = (*PetscVFPrintf)(petsc_history,format,Argp);CHKERRQ(ierr);
276     }
277     va_end(Argp);
278   } else { /* other processors add to local queue */
279     va_list     Argp;
280     PrintfQueue next;
281     int         fullLength = 8191;
282 
283     ierr = PetscNew(struct _PrintfQueue,&next);CHKERRQ(ierr);
284     if (queue) {queue->next = next; queue = next; queue->next = 0;}
285     else       {queuebase   = queue = next;}
286     queuelength++;
287     next->size = -1;
288     while(fullLength >= next->size) {
289       next->size = fullLength+1;
290       ierr = PetscMalloc(next->size * sizeof(char), &next->string);CHKERRQ(ierr);
291       va_start(Argp,format);
292       ierr = PetscMemzero(next->string,next->size);CHKERRQ(ierr);
293       ierr = PetscVSNPrintf(next->string,next->size,format, &fullLength,Argp);CHKERRQ(ierr);
294       va_end(Argp);
295     }
296   }
297 
298   PetscFunctionReturn(0);
299 }
300 
301 #undef __FUNCT__
302 #define __FUNCT__ "PetscSynchronizedFPrintf"
303 /*@C
304     PetscSynchronizedFPrintf - Prints synchronized output to the specified file from
305     several processors.  Output of the first processor is followed by that of the
306     second, etc.
307 
308     Not Collective
309 
310     Input Parameters:
311 +   comm - the communicator
312 .   fd - the file pointer
313 -   format - the usual printf() format string
314 
315     Level: intermediate
316 
317     Notes:
318     REQUIRES a intervening call to PetscSynchronizedFlush() for the information
319     from all the processors to be printed.
320 
321 .seealso: PetscSynchronizedPrintf(), PetscSynchronizedFlush(), PetscFPrintf(),
322           PetscFOpen(), PetscViewerASCIISynchronizedPrintf(), PetscViewerASCIIPrintf()
323 
324 @*/
325 PetscErrorCode PETSCSYS_DLLEXPORT PetscSynchronizedFPrintf(MPI_Comm comm,FILE* fp,const char format[],...)
326 {
327   PetscErrorCode ierr;
328   PetscMPIInt    rank;
329 
330   PetscFunctionBegin;
331   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
332 
333   /* First processor prints immediately to fp */
334   if (!rank) {
335     va_list Argp;
336     va_start(Argp,format);
337     ierr = (*PetscVFPrintf)(fp,format,Argp);CHKERRQ(ierr);
338     queuefile = fp;
339     if (petsc_history) {
340       ierr = (*PetscVFPrintf)(petsc_history,format,Argp);CHKERRQ(ierr);
341     }
342     va_end(Argp);
343   } else { /* other processors add to local queue */
344     va_list     Argp;
345     PrintfQueue next;
346     int         fullLength = 8191;
347     ierr = PetscNew(struct _PrintfQueue,&next);CHKERRQ(ierr);
348     if (queue) {queue->next = next; queue = next; queue->next = 0;}
349     else       {queuebase   = queue = next;}
350     queuelength++;
351     next->size = -1;
352     while(fullLength >= next->size) {
353       next->size = fullLength+1;
354       ierr = PetscMalloc(next->size * sizeof(char), &next->string);CHKERRQ(ierr);
355       va_start(Argp,format);
356       ierr = PetscMemzero(next->string,next->size);CHKERRQ(ierr);
357       ierr = PetscVSNPrintf(next->string,next->size,format,&fullLength,Argp);CHKERRQ(ierr);
358       va_end(Argp);
359     }
360   }
361   PetscFunctionReturn(0);
362 }
363 
364 #undef __FUNCT__
365 #define __FUNCT__ "PetscSynchronizedFlush"
366 /*@
367     PetscSynchronizedFlush - Flushes to the screen output from all processors
368     involved in previous PetscSynchronizedPrintf() calls.
369 
370     Collective on MPI_Comm
371 
372     Input Parameters:
373 .   comm - the communicator
374 
375     Level: intermediate
376 
377     Notes:
378     Usage of PetscSynchronizedPrintf() and PetscSynchronizedFPrintf() with
379     different MPI communicators REQUIRES an intervening call to PetscSynchronizedFlush().
380 
381 .seealso: PetscSynchronizedPrintf(), PetscFPrintf(), PetscPrintf(), PetscViewerASCIIPrintf(),
382           PetscViewerASCIISynchronizedPrintf()
383 @*/
384 PetscErrorCode PETSCSYS_DLLEXPORT PetscSynchronizedFlush(MPI_Comm comm)
385 {
386   PetscErrorCode ierr;
387   PetscMPIInt    rank,size,tag,i,j,n,dummy;
388   char          *message;
389   MPI_Status     status;
390   FILE           *fd;
391 
392   PetscFunctionBegin;
393   ierr = PetscCommDuplicate(comm,&comm,&tag);CHKERRQ(ierr);
394   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
395   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
396 
397   /* First processor waits for messages from all other processors */
398   if (!rank) {
399     if (queuefile) {
400       fd = queuefile;
401     } else {
402       fd = PETSC_STDOUT;
403     }
404     for (i=1; i<size; i++) {
405       /* to prevent a flood of messages to process zero, request each message separately */
406       ierr = MPI_Send(&dummy,1,MPI_INT,i,tag,comm);CHKERRQ(ierr);
407       ierr = MPI_Recv(&n,1,MPI_INT,i,tag,comm,&status);CHKERRQ(ierr);
408       for (j=0; j<n; j++) {
409         PetscMPIInt 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_Recv(&dummy,1,MPI_INT,0,tag,comm,&status);CHKERRQ(ierr);
423     ierr = MPI_Send(&queuelength,1,MPI_INT,0,tag,comm);CHKERRQ(ierr);
424     for (i=0; i<queuelength; i++) {
425       ierr     = MPI_Send(&next->size,1,MPI_INT,0,tag,comm);CHKERRQ(ierr);
426       ierr     = MPI_Send(next->string,next->size,MPI_CHAR,0,tag,comm);CHKERRQ(ierr);
427       previous = next;
428       next     = next->next;
429       ierr     = PetscFree(previous->string);CHKERRQ(ierr);
430       ierr     = PetscFree(previous);CHKERRQ(ierr);
431     }
432     queue       = 0;
433     queuelength = 0;
434   }
435   ierr = PetscCommDestroy(&comm);CHKERRQ(ierr);
436   PetscFunctionReturn(0);
437 }
438 
439 /* ---------------------------------------------------------------------------------------*/
440 
441 #undef __FUNCT__
442 #define __FUNCT__ "PetscFPrintf"
443 /*@C
444     PetscFPrintf - Prints to a file, only from the first
445     processor in the communicator.
446 
447     Not Collective
448 
449     Input Parameters:
450 +   comm - the communicator
451 .   fd - the file pointer
452 -   format - the usual printf() format string
453 
454     Level: intermediate
455 
456     Fortran Note:
457     This routine is not supported in Fortran.
458 
459    Concepts: printing^in parallel
460    Concepts: printf^in parallel
461 
462 .seealso: PetscPrintf(), PetscSynchronizedPrintf(), PetscViewerASCIIPrintf(),
463           PetscViewerASCIISynchronizedPrintf(), PetscSynchronizedFlush()
464 @*/
465 PetscErrorCode PETSCSYS_DLLEXPORT PetscFPrintf(MPI_Comm comm,FILE* fd,const char format[],...)
466 {
467   PetscErrorCode ierr;
468   PetscMPIInt    rank;
469 
470   PetscFunctionBegin;
471   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
472   if (!rank) {
473     va_list Argp;
474     va_start(Argp,format);
475     ierr = (*PetscVFPrintf)(fd,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 #undef __FUNCT__
485 #define __FUNCT__ "PetscPrintf"
486 /*@C
487     PetscPrintf - Prints to standard out, only from the first
488     processor in the communicator.
489 
490     Not Collective
491 
492     Input Parameters:
493 +   comm - the communicator
494 -   format - the usual printf() format string
495 
496    Level: intermediate
497 
498     Fortran Note:
499     The call sequence is PetscPrintf(MPI_Comm, character(*), PetscErrorCode ierr) from Fortran.
500     That is, you can only pass a single character string from Fortran.
501 
502    Notes: %A is replace with %g unless the value is < 1.e-12 when it is
503           replaced with < 1.e-12
504 
505    Concepts: printing^in parallel
506    Concepts: printf^in parallel
507 
508 .seealso: PetscFPrintf(), PetscSynchronizedPrintf()
509 @*/
510 PetscErrorCode PETSCSYS_DLLEXPORT PetscPrintf(MPI_Comm comm,const char format[],...)
511 {
512   PetscErrorCode ierr;
513   PetscMPIInt    rank;
514   size_t         len;
515   char           *nformat,*sub1,*sub2;
516   PetscReal      value;
517 
518   PetscFunctionBegin;
519   if (!comm) comm = PETSC_COMM_WORLD;
520   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
521   if (!rank) {
522     va_list Argp;
523     va_start(Argp,format);
524 
525     ierr = PetscStrstr(format,"%A",&sub1);CHKERRQ(ierr);
526     if (sub1) {
527       ierr = PetscStrstr(format,"%",&sub2);CHKERRQ(ierr);
528       if (sub1 != sub2) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"%%A format must be first in format string");
529       ierr    = PetscStrlen(format,&len);CHKERRQ(ierr);
530       ierr    = PetscMalloc((len+16)*sizeof(char),&nformat);CHKERRQ(ierr);
531       ierr    = PetscStrcpy(nformat,format);CHKERRQ(ierr);
532       ierr    = PetscStrstr(nformat,"%",&sub2);CHKERRQ(ierr);
533       sub2[0] = 0;
534       value   = (double)va_arg(Argp,double);
535       if (PetscAbsReal(value) < 1.e-12) {
536         ierr    = PetscStrcat(nformat,"< 1.e-12");CHKERRQ(ierr);
537       } else {
538         ierr    = PetscStrcat(nformat,"%g");CHKERRQ(ierr);
539         va_end(Argp);
540         va_start(Argp,format);
541       }
542       ierr    = PetscStrcat(nformat,sub1+2);CHKERRQ(ierr);
543     } else {
544       nformat = (char*)format;
545     }
546     ierr = (*PetscVFPrintf)(PETSC_STDOUT,nformat,Argp);CHKERRQ(ierr);
547     if (petsc_history) {
548       ierr = (*PetscVFPrintf)(petsc_history,nformat,Argp);CHKERRQ(ierr);
549     }
550     va_end(Argp);
551     if (sub1) {ierr = PetscFree(nformat);CHKERRQ(ierr);}
552   }
553   PetscFunctionReturn(0);
554 }
555 
556 /* ---------------------------------------------------------------------------------------*/
557 #undef __FUNCT__
558 #define __FUNCT__ "PetscHelpPrintfDefault"
559 PetscErrorCode PETSCSYS_DLLEXPORT PetscHelpPrintfDefault(MPI_Comm comm,const char format[],...)
560 {
561   PetscErrorCode ierr;
562   PetscMPIInt    rank;
563 
564   PetscFunctionBegin;
565   if (!comm) comm = PETSC_COMM_WORLD;
566   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
567   if (!rank) {
568     va_list Argp;
569     va_start(Argp,format);
570     ierr = (*PetscVFPrintf)(PETSC_STDOUT,format,Argp);CHKERRQ(ierr);
571     if (petsc_history) {
572       ierr = (*PetscVFPrintf)(petsc_history,format,Argp);CHKERRQ(ierr);
573     }
574     va_end(Argp);
575   }
576   PetscFunctionReturn(0);
577 }
578 
579 /* ---------------------------------------------------------------------------------------*/
580 
581 
582 #undef __FUNCT__
583 #define __FUNCT__ "PetscSynchronizedFGets"
584 /*@C
585     PetscSynchronizedFGets - Several processors all get the same line from a file.
586 
587     Collective on MPI_Comm
588 
589     Input Parameters:
590 +   comm - the communicator
591 .   fd - the file pointer
592 -   len - the length of the output buffer
593 
594     Output Parameter:
595 .   string - the line read from the file
596 
597     Level: intermediate
598 
599 .seealso: PetscSynchronizedPrintf(), PetscSynchronizedFlush(),
600           PetscFOpen(), PetscViewerASCIISynchronizedPrintf(), PetscViewerASCIIPrintf()
601 
602 @*/
603 PetscErrorCode PETSCSYS_DLLEXPORT PetscSynchronizedFGets(MPI_Comm comm,FILE* fp,size_t len,char string[])
604 {
605   PetscErrorCode ierr;
606   PetscMPIInt    rank;
607   char           *str;
608 
609   PetscFunctionBegin;
610   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
611 
612   if (!rank) {
613     str = fgets(string,len,fp); /* Not very useful error behavior, but what is desired behavior for attempt to read at EOF? */
614   }
615   ierr = MPI_Bcast(string,len,MPI_BYTE,0,comm);CHKERRQ(ierr);
616   PetscFunctionReturn(0);
617 }
618