xref: /petsc/src/sys/fileio/sysio.c (revision ce0a2cd1da0658c2b28aad1be2e2c8e41567bece)
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 = ENUM_DUMMY;
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<(PetscInt)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 = PETSC_FALSE;
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<(PetscInt)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<(PetscInt)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<(PetscInt) 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<(PetscInt) 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<(PetscInt) 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    When PETSc is config/configure.py with --with-64bit-indices the integers are written to the
192    file as 64 bit integers, this means they can only be read back in when the option --with-64bit-indices
193    is used.
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    When PETSc is config/configure.py with --with-64bit-indices the integers are written to the
266    file as 64 bit integers, this means they can only be read back in when the option --with-64bit-indices
267    is used.
268 
269    The Buffer p should be read-write buffer, and not static data.
270    This way, byte-swapping is done in-place, and then the buffer is
271    written to the file.
272 
273    This routine restores the original contents of the buffer, after
274    it is written to the file. This is done by byte-swapping in-place
275    the second time. If the flag istemp is set to PETSC_TRUE, the second
276    byte-swapping operation is not done, thus saving some computation,
277    but the buffer corrupted is corrupted.
278 
279    Concepts: files^writing binary
280    Concepts: binary files^writing
281 
282 .seealso: PetscBinaryRead(), PetscBinaryOpen(), PetscBinaryClose(), PetscViewerBinaryGetDescriptor(), PetscBinarySynchronizedWrite(),
283           PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek()
284 @*/
285 PetscErrorCode PETSC_DLLEXPORT PetscBinaryWrite(int fd,void *p,PetscInt n,PetscDataType type,PetscTruth istemp)
286 {
287   char           *pp = (char*)p;
288   int            err,wsize;
289   size_t         m = (size_t)n,maxblock=65536;
290 #if !defined(PETSC_WORDS_BIGENDIAN)
291   PetscErrorCode ierr;
292   void           *ptmp = p;
293 #endif
294 
295   PetscFunctionBegin;
296   if (n < 0) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Trying to write a negative amount of data %D",n);
297   if (!n) PetscFunctionReturn(0);
298 
299   if (type == PETSC_INT)          m *= sizeof(PetscInt);
300   else if (type == PETSC_SCALAR)  m *= sizeof(PetscScalar);
301   else if (type == PETSC_DOUBLE)  m *= sizeof(double);
302   else if (type == PETSC_SHORT)   m *= sizeof(short);
303   else if (type == PETSC_CHAR)    m *= sizeof(char);
304   else if (type == PETSC_ENUM)    m *= sizeof(PetscEnum);
305   else if (type == PETSC_TRUTH)   m *= sizeof(PetscTruth);
306   else if (type == PETSC_LOGICAL) m = PetscBTLength(m)*sizeof(char);
307   else SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Unknown type");
308 
309 #if !defined(PETSC_WORDS_BIGENDIAN)
310   if      (type == PETSC_INT)    {ierr = PetscByteSwapInt((PetscInt*)ptmp,n);CHKERRQ(ierr);}
311   else if (type == PETSC_ENUM)   {ierr = PetscByteSwapEnum((PetscEnum*)ptmp,n);CHKERRQ(ierr);}
312   else if (type == PETSC_TRUTH)  {ierr = PetscByteSwapTruth((PetscTruth*)ptmp,n);CHKERRQ(ierr);}
313   else if (type == PETSC_SCALAR) {ierr = PetscByteSwapScalar((PetscScalar*)ptmp,n);CHKERRQ(ierr);}
314   else if (type == PETSC_DOUBLE) {ierr = PetscByteSwapDouble((double*)ptmp,n);CHKERRQ(ierr);}
315   else if (type == PETSC_SHORT)  {ierr = PetscByteSwapShort((short*)ptmp,n);CHKERRQ(ierr);}
316 #endif
317 
318   while (m) {
319     wsize = (m < maxblock) ? m : maxblock;
320     err = write(fd,pp,wsize);
321     if (err < 0 && errno == EINTR) continue;
322     if (err != wsize) SETERRQ(PETSC_ERR_FILE_WRITE,"Error writing to file.");
323     m -= wsize;
324     pp += wsize;
325   }
326 
327 #if !defined(PETSC_WORDS_BIGENDIAN)
328   if (!istemp) {
329     if      (type == PETSC_INT)    {ierr = PetscByteSwapInt((PetscInt*)ptmp,n);CHKERRQ(ierr);}
330     else if (type == PETSC_SCALAR) {ierr = PetscByteSwapScalar((PetscScalar*)ptmp,n);CHKERRQ(ierr);}
331     else if (type == PETSC_DOUBLE) {ierr = PetscByteSwapDouble((double*)ptmp,n);CHKERRQ(ierr);}
332     else if (type == PETSC_SHORT)  {ierr = PetscByteSwapShort((short*)ptmp,n);CHKERRQ(ierr);}
333     else if (type == PETSC_ENUM)   {ierr = PetscByteSwapEnum((PetscEnum*)ptmp,n);CHKERRQ(ierr);}
334     else if (type == PETSC_TRUTH)  {ierr = PetscByteSwapTruth((PetscTruth*)ptmp,n);CHKERRQ(ierr);}
335   }
336 #endif
337   PetscFunctionReturn(0);
338 }
339 
340 #undef __FUNCT__
341 #define __FUNCT__ "PetscBinaryOpen"
342 /*@C
343    PetscBinaryOpen - Opens a PETSc binary file.
344 
345    Not Collective
346 
347    Input Parameters:
348 +  name - filename
349 -  type - type of binary file, one of FILE_MODE_READ, FILE_MODE_APPEND, FILE_MODE_WRITE
350 
351    Output Parameter:
352 .  fd - the file
353 
354    Level: advanced
355 
356   Concepts: files^opening binary
357   Concepts: binary files^opening
358 
359    Notes: Files access with PetscBinaryRead() and PetscBinaryWrite() are ALWAYS written in
360    big-endian format. This means the file can be accessed using PetscBinaryOpen() and
361    PetscBinaryRead() and PetscBinaryWrite() on any machine.
362 
363 .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscFileMode, PetscViewerFileSetMode(), PetscViewerBinaryGetDescriptor(),
364           PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek()
365 
366 @*/
367 PetscErrorCode PETSC_DLLEXPORT PetscBinaryOpen(const char name[],PetscFileMode mode,int *fd)
368 {
369   PetscFunctionBegin;
370 #if defined(PETSC_HAVE_O_BINARY)
371   if (mode == FILE_MODE_WRITE) {
372     if ((*fd = open(name,O_WRONLY|O_CREAT|O_TRUNC|O_BINARY,0666)) == -1) {
373       SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot create file for writing: %s",name);
374     }
375   } else if (mode == FILE_MODE_READ) {
376     if ((*fd = open(name,O_RDONLY|O_BINARY,0)) == -1) {
377       SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot open file for reading: %s",name);
378     }
379   } else if (mode == FILE_MODE_APPEND) {
380     if ((*fd = open(name,O_WRONLY|O_BINARY,0)) == -1) {
381       SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot open file for writing: %s",name);
382     }
383 #else
384   if (mode == FILE_MODE_WRITE) {
385     if ((*fd = creat(name,0666)) == -1) {
386       SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot create file for writing: %s",name);
387     }
388   } else if (mode == FILE_MODE_READ) {
389     if ((*fd = open(name,O_RDONLY,0)) == -1) {
390       SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot open file for reading: %s",name);
391     }
392   }
393   else if (mode == FILE_MODE_APPEND) {
394     if ((*fd = open(name,O_WRONLY,0)) == -1) {
395       SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot open file for writing: %s",name);
396     }
397 #endif
398   } else SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Unknown file mode");
399   PetscFunctionReturn(0);
400 }
401 
402 #undef __FUNCT__
403 #define __FUNCT__ "PetscBinaryClose"
404 /*@
405    PetscBinaryClose - Closes a PETSc binary file.
406 
407    Not Collective
408 
409    Output Parameter:
410 .  fd - the file
411 
412    Level: advanced
413 
414 .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
415           PetscBinarySynchronizedSeek()
416 @*/
417 PetscErrorCode PETSC_DLLEXPORT PetscBinaryClose(int fd)
418 {
419   PetscFunctionBegin;
420   close(fd);
421   PetscFunctionReturn(0);
422 }
423 
424 
425 #undef __FUNCT__
426 #define __FUNCT__ "PetscBinarySeek"
427 /*@
428    PetscBinarySeek - Moves the file pointer on a PETSc binary file.
429 
430    Not Collective
431 
432    Input Parameters:
433 +  fd - the file
434 .  off - number of bytes to move. Use PETSC_BINARY_INT_SIZE, PETSC_BINARY_SCALAR_SIZE,
435             etc. in your calculation rather than sizeof() to compute byte lengths.
436 -  whence - if PETSC_BINARY_SEEK_SET then off is an absolute location in the file
437             if PETSC_BINARY_SEEK_CUR then off is an offset from the current location
438             if PETSC_BINARY_SEEK_END then off is an offset from the end of file
439 
440    Output Parameter:
441 .   offset - new offset in file
442 
443    Level: developer
444 
445    Notes:
446    Integers are stored on the file as 32 long, regardless of whether
447    they are stored in the machine as 32 or 64, this means the same
448    binary file may be read on any machine. Hence you CANNOT use sizeof()
449    to determine the offset or location.
450 
451    Concepts: files^binary seeking
452    Concepts: binary files^seeking
453 
454 .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
455           PetscBinarySynchronizedSeek()
456 @*/
457 PetscErrorCode PETSC_DLLEXPORT PetscBinarySeek(int fd,off_t off,PetscBinarySeekType whence,off_t *offset)
458 {
459   int iwhence = 0;
460 
461   PetscFunctionBegin;
462   if (whence == PETSC_BINARY_SEEK_SET) {
463     iwhence = SEEK_SET;
464   } else if (whence == PETSC_BINARY_SEEK_CUR) {
465     iwhence = SEEK_CUR;
466   } else if (whence == PETSC_BINARY_SEEK_END) {
467     iwhence = SEEK_END;
468   } else {
469     SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Unknown seek location");
470   }
471 #if defined(PETSC_HAVE_LSEEK)
472   *offset = lseek(fd,off,iwhence);
473 #elif defined(PETSC_HAVE__LSEEK)
474   *offset = _lseek(fd,(long)off,iwhence);
475 #else
476   SETERRQ(PETSC_ERR_SUP_SYS,"System does not have a way of seeking on a file");
477 #endif
478   PetscFunctionReturn(0);
479 }
480 
481 #undef __FUNCT__
482 #define __FUNCT__ "PetscBinarySynchronizedRead"
483 /*@C
484    PetscBinarySynchronizedRead - Reads from a binary file.
485 
486    Collective on MPI_Comm
487 
488    Input Parameters:
489 +  comm - the MPI communicator
490 .  fd - the file
491 .  n  - the number of items to read
492 -  type - the type of items to read (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)
493 
494    Output Parameters:
495 .  p - the buffer
496 
497    Options Database Key:
498 .   -binary_longints - indicates the file was generated on a Cray vector
499          machine (not the T3E/D) and the ints are stored as 64 bit
500          quantities, otherwise they are stored as 32 bit
501 
502    Level: developer
503 
504    Notes:
505    Does a PetscBinaryRead() followed by an MPI_Bcast()
506 
507    PetscBinarySynchronizedRead() uses byte swapping to work on all machines.
508    Integers are stored on the file as 32 long, regardless of whether
509    they are stored in the machine as 32 or 64, this means the same
510    binary file may be read on any machine.
511 
512    Concepts: files^synchronized reading of binary files
513    Concepts: binary files^reading, synchronized
514 
515 .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscBinaryRead(), PetscBinarySynchronizedWrite(),
516           PetscBinarySynchronizedSeek()
517 @*/
518 PetscErrorCode PETSC_DLLEXPORT PetscBinarySynchronizedRead(MPI_Comm comm,int fd,void *p,PetscInt n,PetscDataType type)
519 {
520   PetscErrorCode ierr;
521   PetscMPIInt    rank;
522   MPI_Datatype   mtype;
523 
524   PetscFunctionBegin;
525   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
526   if (!rank) {
527     ierr = PetscBinaryRead(fd,p,n,type);CHKERRQ(ierr);
528   }
529   ierr = PetscDataTypeToMPIDataType(type,&mtype);CHKERRQ(ierr);
530   ierr = MPI_Bcast(p,n,mtype,0,comm);CHKERRQ(ierr);
531   PetscFunctionReturn(0);
532 }
533 
534 #undef __FUNCT__
535 #define __FUNCT__ "PetscBinarySynchronizedWrite"
536 /*@C
537    PetscBinarySynchronizedWrite - writes to a binary file.
538 
539    Collective on MPI_Comm
540 
541    Input Parameters:
542 +  comm - the MPI communicator
543 .  fd - the file
544 .  n  - the number of items to write
545 .  p - the buffer
546 .  istemp - the buffer may be changed
547 -  type - the type of items to write (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)
548 
549    Level: developer
550 
551    Notes:
552    Process 0 does a PetscBinaryWrite()
553 
554    PetscBinarySynchronizedWrite() uses byte swapping to work on all machines.
555    Integers are stored on the file as 32 long, regardless of whether
556    they are stored in the machine as 32 or 64, this means the same
557    binary file may be read on any machine.
558 
559    WARNING: This is NOT like PetscSynchronizedFPrintf()! This routine ignores calls on all but process 0,
560    while PetscSynchronizedFPrintf() has all processes print their strings in order.
561 
562    Concepts: files^synchronized writing of binary files
563    Concepts: binary files^reading, synchronized
564 
565 .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscBinaryRead(), PetscBinarySynchronizedRead(),
566           PetscBinarySynchronizedSeek()
567 @*/
568 PetscErrorCode PETSC_DLLEXPORT PetscBinarySynchronizedWrite(MPI_Comm comm,int fd,void *p,PetscInt n,PetscDataType type,PetscTruth istemp)
569 {
570   PetscErrorCode ierr;
571   PetscMPIInt    rank;
572 
573   PetscFunctionBegin;
574   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
575   if (!rank) {
576     ierr = PetscBinaryWrite(fd,p,n,type,istemp);CHKERRQ(ierr);
577   }
578   PetscFunctionReturn(0);
579 }
580 
581 #undef __FUNCT__
582 #define __FUNCT__ "PetscBinarySynchronizedSeek"
583 /*@C
584    PetscBinarySynchronizedSeek - Moves the file pointer on a PETSc binary file.
585 
586 
587    Input Parameters:
588 +  fd - the file
589 .  whence - if PETSC_BINARY_SEEK_SET then size is an absolute location in the file
590             if PETSC_BINARY_SEEK_CUR then size is offset from current location
591             if PETSC_BINARY_SEEK_END then size is offset from end of file
592 -  off    - number of bytes to move. Use PETSC_BINARY_INT_SIZE, PETSC_BINARY_SCALAR_SIZE,
593             etc. in your calculation rather than sizeof() to compute byte lengths.
594 
595    Output Parameter:
596 .   offset - new offset in file
597 
598    Level: developer
599 
600    Notes:
601    Integers are stored on the file as 32 long, regardless of whether
602    they are stored in the machine as 32 or 64, this means the same
603    binary file may be read on any machine. Hence you CANNOT use sizeof()
604    to determine the offset or location.
605 
606    Concepts: binary files^seeking
607    Concepts: files^seeking in binary
608 
609 .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
610           PetscBinarySynchronizedSeek()
611 @*/
612 PetscErrorCode PETSC_DLLEXPORT PetscBinarySynchronizedSeek(MPI_Comm comm,int fd,off_t off,PetscBinarySeekType whence,off_t *offset)
613 {
614   PetscErrorCode ierr;
615   PetscMPIInt    rank;
616 
617   PetscFunctionBegin;
618   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
619   if (!rank) {
620     ierr = PetscBinarySeek(fd,off,whence,offset);CHKERRQ(ierr);
621   }
622   PetscFunctionReturn(0);
623 }
624 
625