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