xref: /petsc/src/sys/fileio/sysio.c (revision fd705b320d8d44969be9ca25a36dbdd35fbe8e12)
1 #define PETSC_DLL
2 
3 /*
4    This file contains simple binary read/write routines.
5  */
6 
7 #include "petsc.h"
8 #include "petscsys.h"     /*I          "petscsys.h"    I*/
9 
10 #include <errno.h>
11 #include <fcntl.h>
12 #if defined(PETSC_HAVE_UNISTD_H)
13 #include <unistd.h>
14 #endif
15 #if defined (PETSC_HAVE_IO_H)
16 #include <io.h>
17 #endif
18 #include "petscbt.h"
19 
20 #if (PETSC_SIZEOF_INT == 8)
21 #define PetscInt32 short
22 #else
23 #define PetscInt32 int
24 #endif
25 
26 #if !defined(PETSC_WORDS_BIGENDIAN)
27 
28 #undef __FUNCT__
29 #define __FUNCT__ "PetscByteSwapInt"
30 /*
31   PetscByteSwapInt - Swap bytes in a 32 bit integer. NOT a PetscInt! Note that PETSc binary read and write
32       always store and read only 32 bit integers! (See PetscBinaryRead(), PetscBinaryWrite()).
33 
34 */
35 PetscErrorCode PETSC_DLLEXPORT PetscByteSwapInt(PetscInt32 *buff,PetscInt n)
36 {
37   PetscInt  i,j,tmp = 0;
38   PetscInt  *tptr = &tmp;                /* Need to access tmp indirectly to get */
39   char      *ptr1,*ptr2 = (char*)&tmp; /* arround the bug in DEC-ALPHA g++ */
40 
41   PetscFunctionBegin;
42   for (j=0; j<n; j++) {
43     ptr1 = (char*)(buff + j);
44     for (i=0; i<(int)sizeof(PetscInt32); i++) {
45       ptr2[i] = ptr1[sizeof(PetscInt32)-1-i];
46     }
47     buff[j] = *tptr;
48   }
49   PetscFunctionReturn(0);
50 }
51 /* --------------------------------------------------------- */
52 #undef __FUNCT__
53 #define __FUNCT__ "PetscByteSwapShort"
54 /*
55   PetscByteSwapShort - Swap bytes in a short
56 */
57 PetscErrorCode PETSC_DLLEXPORT PetscByteSwapShort(short *buff,PetscInt n)
58 {
59   PetscInt   i,j;
60   short      tmp;
61   short      *tptr = &tmp;           /* take care pf bug in DEC-ALPHA g++ */
62   char       *ptr1,*ptr2 = (char*)&tmp;
63 
64   PetscFunctionBegin;
65   for (j=0; j<n; j++) {
66     ptr1 = (char*)(buff + j);
67     for (i=0; i<(int) sizeof(short); i++) {
68       ptr2[i] = ptr1[sizeof(int)-1-i];
69     }
70     buff[j] = *tptr;
71   }
72   PetscFunctionReturn(0);
73 }
74 /* --------------------------------------------------------- */
75 #undef __FUNCT__
76 #define __FUNCT__ "PetscByteSwapScalar"
77 /*
78   PetscByteSwapScalar - Swap bytes in a double
79   Complex is dealt with as if array of double twice as long.
80 */
81 PetscErrorCode PETSC_DLLEXPORT PetscByteSwapScalar(PetscScalar *buff,PetscInt n)
82 {
83   PetscInt  i,j;
84   PetscReal tmp,*buff1 = (PetscReal*)buff;
85   PetscReal *tptr = &tmp;          /* take care pf bug in DEC-ALPHA g++ */
86   char      *ptr1,*ptr2 = (char*)&tmp;
87 
88   PetscFunctionBegin;
89 #if defined(PETSC_USE_COMPLEX)
90   n *= 2;
91 #endif
92   for (j=0; j<n; j++) {
93     ptr1 = (char*)(buff1 + j);
94     for (i=0; i<(int) sizeof(PetscReal); i++) {
95       ptr2[i] = ptr1[sizeof(PetscReal)-1-i];
96     }
97     buff1[j] = *tptr;
98   }
99   PetscFunctionReturn(0);
100 }
101 /* --------------------------------------------------------- */
102 #undef __FUNCT__
103 #define __FUNCT__ "PetscByteSwapDouble"
104 /*
105   PetscByteSwapDouble - Swap bytes in a double
106 */
107 PetscErrorCode PETSC_DLLEXPORT PetscByteSwapDouble(double *buff,PetscInt n)
108 {
109   PetscInt i,j;
110   double   tmp,*buff1 = (double*)buff;
111   double   *tptr = &tmp;          /* take care pf bug in DEC-ALPHA g++ */
112   char     *ptr1,*ptr2 = (char*)&tmp;
113 
114   PetscFunctionBegin;
115   for (j=0; j<n; j++) {
116     ptr1 = (char*)(buff1 + j);
117     for (i=0; i<(int) sizeof(double); i++) {
118       ptr2[i] = ptr1[sizeof(double)-1-i];
119     }
120     buff1[j] = *tptr;
121   }
122   PetscFunctionReturn(0);
123 }
124 #endif
125 /* --------------------------------------------------------- */
126 #undef __FUNCT__
127 #define __FUNCT__ "PetscBinaryRead"
128 /*@
129    PetscBinaryRead - Reads from a binary file.
130 
131    Not Collective
132 
133    Input Parameters:
134 +  fd - the file
135 .  n  - the number of items to read
136 -  type - the type of items to read (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)
137 
138    Output Parameters:
139 .  p - the buffer
140 
141 
142 
143    Level: developer
144 
145    Notes:
146    PetscBinaryRead() uses byte swapping to work on all machines; the files
147    are written to file ALWAYS using big-endian ordering. On small-endian machines the numbers
148    are converted to the small-endian format when they are read in from the file.
149    Integers are stored on the file as 32 bits long, regardless of whether
150    they are stored in the machine as 32 bits or 64 bits, this means the same
151    binary file may be read on any machine.
152 
153    Concepts: files^reading binary
154    Concepts: binary files^reading
155 
156 .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscViewerBinaryGetDescriptor(), PetscBinarySynchronizedWrite(),
157           PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek()
158 @*/
159 PetscErrorCode PETSC_DLLEXPORT PetscBinaryRead(int fd,void *p,PetscInt n,PetscDataType type)
160 {
161 #if (PETSC_SIZEOF_INT == 8) || defined(PETSC_USE_64BIT_INDICES) || !defined(PETSC_WORDS_BIGENDIAN)
162   PetscErrorCode    ierr;
163 #endif
164   int               wsize,err;
165   size_t            m = (size_t) n,maxblock = 65536;
166   char              *pp = (char*)p;
167 #if (PETSC_SIZEOF_INT == 8) || !defined(PETSC_WORDS_BIGENDIAN) || defined(PETSC_USE_64BIT_INDICES)
168   void              *ptmp = p;
169 #endif
170 
171   PetscFunctionBegin;
172   if (!n) PetscFunctionReturn(0);
173 
174   if (type == PETSC_INT){
175     m   *= sizeof(PetscInt32);
176 #if (PETSC_SIZEOF_INT == 8) || defined(PETSC_USE_64BIT_INDICES)
177     /* read them in as 32 bit ints, later stretch into ints */
178     ierr = PetscMalloc(m,&pp);CHKERRQ(ierr);
179     ptmp = (void*)pp;
180 #endif
181   }
182   else if (type == PETSC_SCALAR)  m *= sizeof(PetscScalar);
183   else if (type == PETSC_DOUBLE)  m *= sizeof(double);
184   else if (type == PETSC_SHORT)   m *= sizeof(short);
185   else if (type == PETSC_CHAR)    m *= sizeof(char);
186   else if (type == PETSC_ENUM)    m *= sizeof(PetscEnum);
187   else if (type == PETSC_TRUTH)   m *= sizeof(PetscTruth);
188   else if (type == PETSC_LOGICAL) m  = PetscBTLength(m)*sizeof(char);
189   else SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Unknown type");
190 
191   while (m) {
192     wsize = (m < maxblock) ? m : maxblock;
193     err = read(fd,pp,wsize);
194     if (err < 0 && errno == EINTR) continue;
195     if (!err && wsize > 0) SETERRQ(PETSC_ERR_FILE_READ,"Read past end of file");
196     if (err < 0) SETERRQ1(PETSC_ERR_FILE_READ,"Error reading from file, errno %d",errno);
197     m  -= err;
198     pp += err;
199   }
200 #if !defined(PETSC_WORDS_BIGENDIAN)
201   if      (type == PETSC_INT)    {ierr = PetscByteSwapInt((PetscInt32*)ptmp,n);CHKERRQ(ierr);}
202   else if (type == PETSC_ENUM)   {ierr = PetscByteSwapInt((PetscInt32*)ptmp,n);CHKERRQ(ierr);}
203   else if (type == PETSC_TRUTH)  {ierr = PetscByteSwapInt((PetscInt32*)ptmp,n);CHKERRQ(ierr);}
204   else if (type == PETSC_SCALAR) {ierr = PetscByteSwapScalar((PetscScalar*)ptmp,n);CHKERRQ(ierr);}
205   else if (type == PETSC_DOUBLE) {ierr = PetscByteSwapDouble((double*)ptmp,n);CHKERRQ(ierr);}
206   else if (type == PETSC_SHORT)  {ierr = PetscByteSwapShort((short*)ptmp,n);CHKERRQ(ierr);}
207 #endif
208 
209 #if (PETSC_SIZEOF_INT == 8) || defined(PETSC_USE_64BIT_INDICES)
210   if (type == PETSC_INT) {
211     PetscInt   *p_int = (PetscInt*)p,i;
212     PetscInt32 *p_short = (PetscInt32 *)ptmp;
213     for (i=0; i<n; i++) {
214       p_int[i] = (PetscInt)p_short[i];
215     }
216     ierr = PetscFree(ptmp);CHKERRQ(ierr);
217   }
218 #endif
219   PetscFunctionReturn(0);
220 }
221 /* --------------------------------------------------------- */
222 #undef __FUNCT__
223 #define __FUNCT__ "PetscBinaryWrite"
224 /*@
225    PetscBinaryWrite - Writes to a binary file.
226 
227    Not Collective
228 
229    Input Parameters:
230 +  fd     - the file
231 .  p      - the buffer
232 .  n      - the number of items to write
233 .  type   - the type of items to read (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)
234 -  istemp - PETSC_FALSE if buffer data should be preserved, PETSC_TRUE otherwise.
235 
236    Level: advanced
237 
238    Notes:
239    PetscBinaryWrite() uses byte swapping to work on all machines; the files
240    are written using big-endian ordering to the file. On small-endian machines the numbers
241    are converted to the big-endian format when they are written to disk.
242    Integers are stored on the file as 32 bits long, regardless of whether
243    they are stored in the machine as 32 bits or 64 bits, this means the same
244    binary file may be read on any machine. It also means that 64 bit integers larger than
245    roughly 2 billion are TRUNCATED/WRONG when written to the file.
246 
247    The Buffer p should be read-write buffer, and not static data.
248    This way, byte-swapping is done in-place, and then the buffer is
249    written to the file.
250 
251    This routine restores the original contents of the buffer, after
252    it is written to the file. This is done by byte-swapping in-place
253    the second time. If the flag istemp is set to PETSC_TRUE, the second
254    byte-swapping operation is not done, thus saving some computation,
255    but the buffer corrupted is corrupted.
256 
257    Concepts: files^writing binary
258    Concepts: binary files^writing
259 
260 .seealso: PetscBinaryRead(), PetscBinaryOpen(), PetscBinaryClose(), PetscViewerBinaryGetDescriptor(), PetscBinarySynchronizedWrite(),
261           PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek()
262 @*/
263 PetscErrorCode PETSC_DLLEXPORT PetscBinaryWrite(int fd,void *p,PetscInt n,PetscDataType type,PetscTruth istemp)
264 {
265   char           *pp = (char*)p;
266   int            err,wsize;
267   size_t         m = (size_t)n,maxblock=65536;
268 #if !defined(PETSC_WORDS_BIGENDIAN) || (PETSC_SIZEOF_INT == 8) ||  defined(PETSC_USE_64BIT_INDICES)
269   PetscErrorCode ierr;
270   void           *ptmp = p;
271 #endif
272 
273   PetscFunctionBegin;
274   if (n < 0) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Trying to write a negative amount of data %D",n);
275   if (!n) PetscFunctionReturn(0);
276 
277   if (type == PETSC_INT){
278     m   *= sizeof(PetscInt32);
279 #if (PETSC_SIZEOF_INT == 8) || defined(PETSC_USE_64BIT_INDICES)
280     PetscInt   *p_int = (PetscInt*)p,i;
281     PetscInt32 *p_short;
282     ierr    = PetscMalloc(m,&pp);CHKERRQ(ierr);
283     ptmp    = (void*)pp;
284     p_short = (PetscInt32*)pp;
285 
286     for (i=0; i<n; i++) {
287       p_short[i] = (PetscInt32) p_int[i];
288     }
289     istemp = PETSC_TRUE;
290 #endif
291   }
292   else if (type == PETSC_SCALAR)  m *= sizeof(PetscScalar);
293   else if (type == PETSC_DOUBLE)  m *= sizeof(double);
294   else if (type == PETSC_SHORT)   m *= sizeof(short);
295   else if (type == PETSC_CHAR)    m *= sizeof(char);
296   else if (type == PETSC_ENUM)    m *= sizeof(PetscEnum);
297   else if (type == PETSC_TRUTH)   m *= sizeof(PetscTruth);
298   else if (type == PETSC_LOGICAL) m = PetscBTLength(m)*sizeof(char);
299   else SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Unknown type");
300 
301 #if !defined(PETSC_WORDS_BIGENDIAN)
302   if      (type == PETSC_INT)    {ierr = PetscByteSwapInt((PetscInt32*)ptmp,n);CHKERRQ(ierr);}
303   else if (type == PETSC_ENUM)   {ierr = PetscByteSwapInt((PetscInt32*)ptmp,n);CHKERRQ(ierr);}
304   else if (type == PETSC_TRUTH)  {ierr = PetscByteSwapInt((PetscInt32*)ptmp,n);CHKERRQ(ierr);}
305   else if (type == PETSC_SCALAR) {ierr = PetscByteSwapScalar((PetscScalar*)ptmp,n);CHKERRQ(ierr);}
306   else if (type == PETSC_DOUBLE) {ierr = PetscByteSwapDouble((double*)ptmp,n);CHKERRQ(ierr);}
307   else if (type == PETSC_SHORT)  {ierr = PetscByteSwapShort((short*)ptmp,n);CHKERRQ(ierr);}
308 #endif
309 
310   while (m) {
311     wsize = (m < maxblock) ? m : maxblock;
312     err = write(fd,pp,wsize);
313     if (err < 0 && errno == EINTR) continue;
314     if (err != wsize) SETERRQ(PETSC_ERR_FILE_WRITE,"Error writing to file.");
315     m -= wsize;
316     pp += wsize;
317   }
318 
319 #if !defined(PETSC_WORDS_BIGENDIAN)
320   if (!istemp) {
321     if      (type == PETSC_SCALAR) {ierr = PetscByteSwapScalar((PetscScalar*)ptmp,n);CHKERRQ(ierr);}
322     else if (type == PETSC_DOUBLE) {ierr = PetscByteSwapDouble((double*)ptmp,n);CHKERRQ(ierr);}
323     else if (type == PETSC_SHORT)  {ierr = PetscByteSwapShort((short*)ptmp,n);CHKERRQ(ierr);}
324     else if (type == PETSC_INT)    {ierr = PetscByteSwapInt((PetscInt32*)ptmp,n);CHKERRQ(ierr);}
325     else if (type == PETSC_ENUM)   {ierr = PetscByteSwapInt((PetscInt32*)ptmp,n);CHKERRQ(ierr);}
326     else if (type == PETSC_TRUTH)  {ierr = PetscByteSwapInt((PetscInt32*)ptmp,n);CHKERRQ(ierr);}
327   }
328 #endif
329 
330 #if (PETSC_SIZEOF_INT == 8) || defined(PETSC_USE_64BIT_INDICES)
331   if (type == PETSC_INT){
332     ierr = PetscFree(ptmp);CHKERRQ(ierr);
333   }
334 #endif
335   PetscFunctionReturn(0);
336 }
337 
338 #undef __FUNCT__
339 #define __FUNCT__ "PetscBinaryOpen"
340 /*@C
341    PetscBinaryOpen - Opens a PETSc binary file.
342 
343    Not Collective
344 
345    Input Parameters:
346 +  name - filename
347 -  type - type of binary file, one of FILE_MODE_READ, FILE_MODE_APPEND, FILE_MODE_WRITE
348 
349    Output Parameter:
350 .  fd - the file
351 
352    Level: advanced
353 
354   Concepts: files^opening binary
355   Concepts: binary files^opening
356 
357    Notes: Files access with PetscBinaryRead() and PetscBinaryWrite() are ALWAYS written in
358    big-endian format. This means the file can be accessed using PetscBinaryOpen() and
359    PetscBinaryRead() and PetscBinaryWrite() on any machine.
360 
361 .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscFileMode, PetscViewerFileSetMode(), PetscViewerBinaryGetDescriptor(),
362           PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek()
363 
364 @*/
365 PetscErrorCode PETSC_DLLEXPORT PetscBinaryOpen(const char name[],PetscFileMode mode,int *fd)
366 {
367   PetscFunctionBegin;
368 #if defined(PETSC_HAVE_O_BINARY)
369   if (mode == FILE_MODE_WRITE) {
370     if ((*fd = open(name,O_WRONLY|O_CREAT|O_TRUNC|O_BINARY,0666)) == -1) {
371       SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot create file for writing: %s",name);
372     }
373   } else if (mode == FILE_MODE_READ) {
374     if ((*fd = open(name,O_RDONLY|O_BINARY,0)) == -1) {
375       SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot open file for reading: %s",name);
376     }
377   } else if (mode == FILE_MODE_APPEND) {
378     if ((*fd = open(name,O_WRONLY|O_BINARY,0)) == -1) {
379       SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot open file for writing: %s",name);
380     }
381 #else
382   if (mode == FILE_MODE_WRITE) {
383     if ((*fd = creat(name,0666)) == -1) {
384       SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot create file for writing: %s",name);
385     }
386   } else if (mode == FILE_MODE_READ) {
387     if ((*fd = open(name,O_RDONLY,0)) == -1) {
388       SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot open file for reading: %s",name);
389     }
390   }
391   else if (mode == FILE_MODE_APPEND) {
392     if ((*fd = open(name,O_WRONLY,0)) == -1) {
393       SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot open file for writing: %s",name);
394     }
395 #endif
396   } else SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Unknown file mode");
397   PetscFunctionReturn(0);
398 }
399 
400 #undef __FUNCT__
401 #define __FUNCT__ "PetscBinaryClose"
402 /*@
403    PetscBinaryClose - Closes a PETSc binary file.
404 
405    Not Collective
406 
407    Output Parameter:
408 .  fd - the file
409 
410    Level: advanced
411 
412 .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
413           PetscBinarySynchronizedSeek()
414 @*/
415 PetscErrorCode PETSC_DLLEXPORT PetscBinaryClose(int fd)
416 {
417   PetscFunctionBegin;
418   close(fd);
419   PetscFunctionReturn(0);
420 }
421 
422 
423 #undef __FUNCT__
424 #define __FUNCT__ "PetscBinarySeek"
425 /*@
426    PetscBinarySeek - Moves the file pointer on a PETSc binary file.
427 
428    Not Collective
429 
430    Input Parameters:
431 +  fd - the file
432 .  off - number of bytes to move. Use PETSC_BINARY_INT_SIZE, PETSC_BINARY_SCALAR_SIZE,
433             etc. in your calculation rather than sizeof() to compute byte lengths.
434 -  whence - if PETSC_BINARY_SEEK_SET then off is an absolute location in the file
435             if PETSC_BINARY_SEEK_CUR then off is an offset from the current location
436             if PETSC_BINARY_SEEK_END then off is an offset from the end of file
437 
438    Output Parameter:
439 .   offset - new offset in file
440 
441    Level: developer
442 
443    Notes:
444    Integers are stored on the file as 32 long, regardless of whether
445    they are stored in the machine as 32 or 64, this means the same
446    binary file may be read on any machine. Hence you CANNOT use sizeof()
447    to determine the offset or location.
448 
449    Concepts: files^binary seeking
450    Concepts: binary files^seeking
451 
452 .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
453           PetscBinarySynchronizedSeek()
454 @*/
455 PetscErrorCode PETSC_DLLEXPORT PetscBinarySeek(int fd,off_t off,PetscBinarySeekType whence,off_t *offset)
456 {
457   int iwhence = 0;
458 
459   PetscFunctionBegin;
460   if (whence == PETSC_BINARY_SEEK_SET) {
461     iwhence = SEEK_SET;
462   } else if (whence == PETSC_BINARY_SEEK_CUR) {
463     iwhence = SEEK_CUR;
464   } else if (whence == PETSC_BINARY_SEEK_END) {
465     iwhence = SEEK_END;
466   } else {
467     SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Unknown seek location");
468   }
469 #if defined(PETSC_HAVE_LSEEK)
470   *offset = lseek(fd,off,iwhence);
471 #elif defined(PETSC_HAVE__LSEEK)
472   *offset = _lseek(fd,(long)off,iwhence);
473 #else
474   SETERRQ(PETSC_ERR_SUP_SYS,"System does not have a way of seeking on a file");
475 #endif
476   PetscFunctionReturn(0);
477 }
478 
479 #undef __FUNCT__
480 #define __FUNCT__ "PetscBinarySynchronizedRead"
481 /*@C
482    PetscBinarySynchronizedRead - Reads from a binary file.
483 
484    Collective on MPI_Comm
485 
486    Input Parameters:
487 +  comm - the MPI communicator
488 .  fd - the file
489 .  n  - the number of items to read
490 -  type - the type of items to read (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)
491 
492    Output Parameters:
493 .  p - the buffer
494 
495    Options Database Key:
496 .   -binary_longints - indicates the file was generated on a Cray vector
497          machine (not the T3E/D) and the ints are stored as 64 bit
498          quantities, otherwise they are stored as 32 bit
499 
500    Level: developer
501 
502    Notes:
503    Does a PetscBinaryRead() followed by an MPI_Bcast()
504 
505    PetscBinarySynchronizedRead() uses byte swapping to work on all machines.
506    Integers are stored on the file as 32 long, regardless of whether
507    they are stored in the machine as 32 or 64, this means the same
508    binary file may be read on any machine.
509 
510    Concepts: files^synchronized reading of binary files
511    Concepts: binary files^reading, synchronized
512 
513 .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscBinaryRead(), PetscBinarySynchronizedWrite(),
514           PetscBinarySynchronizedSeek()
515 @*/
516 PetscErrorCode PETSC_DLLEXPORT PetscBinarySynchronizedRead(MPI_Comm comm,int fd,void *p,PetscInt n,PetscDataType type)
517 {
518   PetscErrorCode ierr;
519   PetscMPIInt    rank;
520   MPI_Datatype   mtype;
521 
522   PetscFunctionBegin;
523   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
524   if (!rank) {
525     ierr = PetscBinaryRead(fd,p,n,type);CHKERRQ(ierr);
526   }
527   ierr = PetscDataTypeToMPIDataType(type,&mtype);CHKERRQ(ierr);
528   ierr = MPI_Bcast(p,n,mtype,0,comm);CHKERRQ(ierr);
529   PetscFunctionReturn(0);
530 }
531 
532 #undef __FUNCT__
533 #define __FUNCT__ "PetscBinarySynchronizedWrite"
534 /*@C
535    PetscBinarySynchronizedWrite - writes to a binary file.
536 
537    Collective on MPI_Comm
538 
539    Input Parameters:
540 +  comm - the MPI communicator
541 .  fd - the file
542 .  n  - the number of items to write
543 .  p - the buffer
544 .  istemp - the buffer may be changed
545 -  type - the type of items to write (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)
546 
547    Level: developer
548 
549    Notes:
550    Process 0 does a PetscBinaryWrite()
551 
552    PetscBinarySynchronizedWrite() uses byte swapping to work on all machines.
553    Integers are stored on the file as 32 long, regardless of whether
554    they are stored in the machine as 32 or 64, this means the same
555    binary file may be read on any machine.
556 
557    WARNING: This is NOT like PetscSynchronizedFPrintf()! This routine ignores calls on all but process 0,
558    while PetscSynchronizedFPrintf() has all processes print their strings in order.
559 
560    Concepts: files^synchronized writing of binary files
561    Concepts: binary files^reading, synchronized
562 
563 .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscBinaryRead(), PetscBinarySynchronizedRead(),
564           PetscBinarySynchronizedSeek()
565 @*/
566 PetscErrorCode PETSC_DLLEXPORT PetscBinarySynchronizedWrite(MPI_Comm comm,int fd,void *p,PetscInt n,PetscDataType type,PetscTruth istemp)
567 {
568   PetscErrorCode ierr;
569   PetscMPIInt    rank;
570 
571   PetscFunctionBegin;
572   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
573   if (!rank) {
574     ierr = PetscBinaryWrite(fd,p,n,type,istemp);CHKERRQ(ierr);
575   }
576   PetscFunctionReturn(0);
577 }
578 
579 #undef __FUNCT__
580 #define __FUNCT__ "PetscBinarySynchronizedSeek"
581 /*@C
582    PetscBinarySynchronizedSeek - Moves the file pointer on a PETSc binary file.
583 
584 
585    Input Parameters:
586 +  fd - the file
587 .  whence - if PETSC_BINARY_SEEK_SET then size is an absolute location in the file
588             if PETSC_BINARY_SEEK_CUR then size is offset from current location
589             if PETSC_BINARY_SEEK_END then size is offset from end of file
590 -  off    - number of bytes to move. Use PETSC_BINARY_INT_SIZE, PETSC_BINARY_SCALAR_SIZE,
591             etc. in your calculation rather than sizeof() to compute byte lengths.
592 
593    Output Parameter:
594 .   offset - new offset in file
595 
596    Level: developer
597 
598    Notes:
599    Integers are stored on the file as 32 long, regardless of whether
600    they are stored in the machine as 32 or 64, this means the same
601    binary file may be read on any machine. Hence you CANNOT use sizeof()
602    to determine the offset or location.
603 
604    Concepts: binary files^seeking
605    Concepts: files^seeking in binary
606 
607 .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
608           PetscBinarySynchronizedSeek()
609 @*/
610 PetscErrorCode PETSC_DLLEXPORT PetscBinarySynchronizedSeek(MPI_Comm comm,int fd,off_t off,PetscBinarySeekType whence,off_t *offset)
611 {
612   PetscErrorCode ierr;
613   PetscMPIInt    rank;
614 
615   PetscFunctionBegin;
616   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
617   if (!rank) {
618     ierr = PetscBinarySeek(fd,off,whence,offset);CHKERRQ(ierr);
619   }
620   PetscFunctionReturn(0);
621 }
622 
623