xref: /petsc/src/sys/fileio/sysio.c (revision 0e9bae810fdaeb60e2713eaa8ddb89f42e079fd1)
1 
2 /*
3    This file contains simple binary read/write routines.
4  */
5 
6 #include <petscsys.h>
7 #include <errno.h>
8 #include <fcntl.h>
9 #if defined(PETSC_HAVE_UNISTD_H)
10 #include <unistd.h>
11 #endif
12 #if defined (PETSC_HAVE_IO_H)
13 #include <io.h>
14 #endif
15 #include <petscbt.h>
16 
17 /* --------------------------------------------------------- */
18 #undef __FUNCT__
19 #define __FUNCT__ "PetscByteSwapEnum"
20 /*
21   PetscByteSwapEnum - Swap bytes in a  PETSc Enum
22 
23 */
24 PetscErrorCode  PetscByteSwapEnum(PetscEnum *buff,PetscInt n)
25 {
26   PetscInt   i,j;
27   PetscEnum   tmp = ENUM_DUMMY;
28   char       *ptr1,*ptr2 = (char*)&tmp;
29 
30   PetscFunctionBegin;
31   for (j=0; j<n; j++) {
32     ptr1 = (char*)(buff + j);
33     for (i=0; i<(PetscInt)sizeof(PetscEnum); i++) {
34       ptr2[i] = ptr1[sizeof(PetscEnum)-1-i];
35     }
36     for (i=0; i<(PetscInt)sizeof(PetscEnum); i++) {
37       ptr1[i] = ptr2[i];
38     }
39   }
40   PetscFunctionReturn(0);
41 }
42 
43 #undef __FUNCT__
44 #define __FUNCT__ "PetscByteSwapBool"
45 /*
46   PetscByteSwapBool - Swap bytes in a  PETSc Bool
47 
48 */
49 PetscErrorCode  PetscByteSwapBool(PetscBool *buff,PetscInt n)
50 {
51   PetscInt    i,j;
52   PetscBool   tmp = PETSC_FALSE;
53   char        *ptr1,*ptr2 = (char*)&tmp;
54 
55   PetscFunctionBegin;
56   for (j=0; j<n; j++) {
57     ptr1 = (char*)(buff + j);
58     for (i=0; i<(PetscInt)sizeof(PetscBool); i++) {
59       ptr2[i] = ptr1[sizeof(PetscBool)-1-i];
60     }
61     for (i=0; i<(PetscInt)sizeof(PetscBool); i++) {
62       ptr1[i] = ptr2[i];
63     }
64   }
65   PetscFunctionReturn(0);
66 }
67 
68 #undef __FUNCT__
69 #define __FUNCT__ "PetscByteSwapInt"
70 /*
71   PetscByteSwapInt - Swap bytes in a  PETSc integer (which may be 32 or 64 bits)
72 
73 */
74 PetscErrorCode  PetscByteSwapInt(PetscInt *buff,PetscInt n)
75 {
76   PetscInt  i,j,tmp = 0;
77   char       *ptr1,*ptr2 = (char*)&tmp;
78 
79   PetscFunctionBegin;
80   for (j=0; j<n; j++) {
81     ptr1 = (char*)(buff + j);
82     for (i=0; i<(PetscInt)sizeof(PetscInt); i++) {
83       ptr2[i] = ptr1[sizeof(PetscInt)-1-i];
84     }
85     for (i=0; i<(PetscInt)sizeof(PetscInt); i++) {
86       ptr1[i] = ptr2[i];
87     }
88   }
89   PetscFunctionReturn(0);
90 }
91 /* --------------------------------------------------------- */
92 #undef __FUNCT__
93 #define __FUNCT__ "PetscByteSwapShort"
94 /*
95   PetscByteSwapShort - Swap bytes in a short
96 */
97 PetscErrorCode  PetscByteSwapShort(short *buff,PetscInt n)
98 {
99   PetscInt   i,j;
100   short      tmp;
101   char       *ptr1,*ptr2 = (char*)&tmp;
102 
103   PetscFunctionBegin;
104   for (j=0; j<n; j++) {
105     ptr1 = (char*)(buff + j);
106     for (i=0; i<(PetscInt) sizeof(short); i++) {
107       ptr2[i] = ptr1[sizeof(short)-1-i];
108     }
109     for (i=0; i<(PetscInt) sizeof(short); i++) {
110       ptr1[i] = ptr2[i];
111     }
112   }
113   PetscFunctionReturn(0);
114 }
115 /* --------------------------------------------------------- */
116 #undef __FUNCT__
117 #define __FUNCT__ "PetscByteSwapScalar"
118 /*
119   PetscByteSwapScalar - Swap bytes in a double
120   Complex is dealt with as if array of double twice as long.
121 */
122 PetscErrorCode  PetscByteSwapScalar(PetscScalar *buff,PetscInt n)
123 {
124   PetscInt  i,j;
125   PetscReal tmp,*buff1 = (PetscReal*)buff;
126   char      *ptr1,*ptr2 = (char*)&tmp;
127 
128   PetscFunctionBegin;
129 #if defined(PETSC_USE_COMPLEX)
130   n *= 2;
131 #endif
132   for (j=0; j<n; j++) {
133     ptr1 = (char*)(buff1 + j);
134     for (i=0; i<(PetscInt) sizeof(PetscReal); i++) {
135       ptr2[i] = ptr1[sizeof(PetscReal)-1-i];
136     }
137     for (i=0; i<(PetscInt) sizeof(PetscReal); i++) {
138       ptr1[i] = ptr2[i];
139     }
140   }
141   PetscFunctionReturn(0);
142 }
143 /* --------------------------------------------------------- */
144 #undef __FUNCT__
145 #define __FUNCT__ "PetscByteSwapDouble"
146 /*
147   PetscByteSwapDouble - Swap bytes in a double
148 */
149 PetscErrorCode  PetscByteSwapDouble(double *buff,PetscInt n)
150 {
151   PetscInt i,j;
152   double   tmp,*buff1 = (double*)buff;
153   char     *ptr1,*ptr2 = (char*)&tmp;
154 
155   PetscFunctionBegin;
156   for (j=0; j<n; j++) {
157     ptr1 = (char*)(buff1 + j);
158     for (i=0; i<(PetscInt) sizeof(double); i++) {
159       ptr2[i] = ptr1[sizeof(double)-1-i];
160     }
161     for (i=0; i<(PetscInt) sizeof(double); i++) {
162       ptr1[i] = ptr2[i];
163     }
164   }
165   PetscFunctionReturn(0);
166 }
167 
168 #undef __FUNCT__
169 #define __FUNCT__ "PetscByteSwapFloat"
170 /*
171   PetscByteSwapFloat - Swap bytes in a float
172 */
173 PetscErrorCode PetscByteSwapFloat(float *buff,PetscInt n)
174 {
175   PetscInt i,j;
176   float   tmp,*buff1 = (float*)buff;
177   char     *ptr1,*ptr2 = (char*)&tmp;
178 
179   PetscFunctionBegin;
180   for (j=0; j<n; j++) {
181     ptr1 = (char*)(buff1 + j);
182     for (i=0; i<(PetscInt) sizeof(float); i++) {
183       ptr2[i] = ptr1[sizeof(float)-1-i];
184     }
185     for (i=0; i<(PetscInt) sizeof(float); i++) {
186       ptr1[i] = ptr2[i];
187     }
188   }
189   PetscFunctionReturn(0);
190 }
191 
192 #undef __FUNCT__
193 #define __FUNCT__ "PetscByteSwap"
194 PetscErrorCode PetscByteSwap(void *data,PetscDataType pdtype,PetscInt count)
195 {
196   PetscErrorCode ierr;
197 
198   PetscFunctionBegin;
199   if      (pdtype == PETSC_INT)    {ierr = PetscByteSwapInt((PetscInt*)data,count);CHKERRQ(ierr);}
200   else if (pdtype == PETSC_ENUM)   {ierr = PetscByteSwapEnum((PetscEnum*)data,count);CHKERRQ(ierr);}
201   else if (pdtype == PETSC_BOOL)   {ierr = PetscByteSwapBool((PetscBool*)data,count);CHKERRQ(ierr);}
202   else if (pdtype == PETSC_SCALAR) {ierr = PetscByteSwapScalar((PetscScalar*)data,count);CHKERRQ(ierr);}
203   else if (pdtype == PETSC_DOUBLE) {ierr = PetscByteSwapDouble((double*)data,count);CHKERRQ(ierr);}
204   else if (pdtype == PETSC_FLOAT) {ierr = PetscByteSwapFloat((float*)data,count);CHKERRQ(ierr);}
205   else if (pdtype == PETSC_SHORT)  {ierr = PetscByteSwapShort((short*)data,count);CHKERRQ(ierr);}
206   PetscFunctionReturn(0);
207 }
208 
209 /* --------------------------------------------------------- */
210 #undef __FUNCT__
211 #define __FUNCT__ "PetscBinaryRead"
212 /*@
213    PetscBinaryRead - Reads from a binary file.
214 
215    Not Collective
216 
217    Input Parameters:
218 +  fd - the file
219 .  n  - the number of items to read
220 -  type - the type of items to read (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)
221 
222    Output Parameters:
223 .  p - the buffer
224 
225 
226 
227    Level: developer
228 
229    Notes:
230    PetscBinaryRead() uses byte swapping to work on all machines; the files
231    are written to file ALWAYS using big-endian ordering. On small-endian machines the numbers
232    are converted to the small-endian format when they are read in from the file.
233    When PETSc is ./configure with --with-64bit-indices the integers are written to the
234    file as 64 bit integers, this means they can only be read back in when the option --with-64bit-indices
235    is used.
236 
237    Concepts: files^reading binary
238    Concepts: binary files^reading
239 
240 .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscViewerBinaryGetDescriptor(), PetscBinarySynchronizedWrite(),
241           PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek()
242 @*/
243 PetscErrorCode  PetscBinaryRead(int fd,void *p,PetscInt n,PetscDataType type)
244 {
245   int               wsize,err;
246   size_t            m = (size_t) n,maxblock = 65536;
247   char              *pp = (char*)p;
248 #if defined(PETSC_USE_REAL___FLOAT128)
249   double            *ppp;
250 #endif
251 #if !defined(PETSC_WORDS_BIGENDIAN) || defined(PETSC_USE_REAL___FLOAT128)
252   PetscErrorCode    ierr;
253 #endif
254 #if !defined(PETSC_WORDS_BIGENDIAN)
255   void              *ptmp = p;
256 #endif
257 
258   PetscFunctionBegin;
259   if (!n) PetscFunctionReturn(0);
260 
261   if (type == PETSC_INT)          m *= sizeof(PetscInt);
262   else if (type == PETSC_SCALAR)  m *= sizeof(PetscScalar);
263   else if (type == PETSC_DOUBLE)  m *= sizeof(double);
264   else if (type == PETSC_FLOAT)   m *= sizeof(float);
265   else if (type == PETSC_SHORT)   m *= sizeof(short);
266   else if (type == PETSC_CHAR)    m *= sizeof(char);
267   else if (type == PETSC_ENUM)    m *= sizeof(PetscEnum);
268   else if (type == PETSC_BOOL)   m *= sizeof(PetscBool);
269   else if (type == PETSC_BIT_LOGICAL) m  = PetscBTLength(m)*sizeof(char);
270   else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown type");
271 
272 #if defined(PETSC_USE_REAL___FLOAT128)
273   /* If using __float128 precision we still read in doubles from file */
274   if (type == PETSC_SCALAR) {
275     m    = m/2;
276     ierr = PetscMalloc(n*sizeof(double),&ppp);CHKERRQ(ierr);
277     pp   = (char*)ppp;
278   }
279 #endif
280 
281   while (m) {
282     wsize = (m < maxblock) ? m : maxblock;
283     err = read(fd,pp,wsize);
284     if (err < 0 && errno == EINTR) continue;
285     if (!err && wsize > 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_READ,"Read past end of file");
286     if (err < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_READ,"Error reading from file, errno %d",errno);
287     m  -= err;
288     pp += err;
289   }
290 
291 #if defined(PETSC_USE_REAL___FLOAT128)
292   if (type == PETSC_SCALAR) {
293     PetscScalar *pv = (PetscScalar*) p;
294     PetscInt    i;
295 #if !defined(PETSC_WORDS_BIGENDIAN)
296     ierr = PetscByteSwapDouble(ppp,n);CHKERRQ(ierr);
297 #endif
298     for (i=0; i<n; i++) {
299       pv[i] = ppp[i];
300     }
301     ierr = PetscFree(ppp);CHKERRQ(ierr);
302     PetscFunctionReturn(0);
303   }
304 #endif
305 
306 #if !defined(PETSC_WORDS_BIGENDIAN)
307   ierr = PetscByteSwap(ptmp,type,n);CHKERRQ(ierr);
308 #endif
309 
310   PetscFunctionReturn(0);
311 }
312 /* --------------------------------------------------------- */
313 #undef __FUNCT__
314 #define __FUNCT__ "PetscBinaryWrite"
315 /*@
316    PetscBinaryWrite - Writes to a binary file.
317 
318    Not Collective
319 
320    Input Parameters:
321 +  fd     - the file
322 .  p      - the buffer
323 .  n      - the number of items to write
324 .  type   - the type of items to read (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)
325 -  istemp - PETSC_FALSE if buffer data should be preserved, PETSC_TRUE otherwise.
326 
327    Level: advanced
328 
329    Notes:
330    PetscBinaryWrite() uses byte swapping to work on all machines; the files
331    are written using big-endian ordering to the file. On small-endian machines the numbers
332    are converted to the big-endian format when they are written to disk.
333    When PETSc is ./configure with --with-64bit-indices the integers are written to the
334    file as 64 bit integers, this means they can only be read back in when the option --with-64bit-indices
335    is used.
336 
337    The Buffer p should be read-write buffer, and not static data.
338    This way, byte-swapping is done in-place, and then the buffer is
339    written to the file.
340 
341    This routine restores the original contents of the buffer, after
342    it is written to the file. This is done by byte-swapping in-place
343    the second time. If the flag istemp is set to PETSC_TRUE, the second
344    byte-swapping operation is not done, thus saving some computation,
345    but the buffer is left corrupted.
346 
347    Because byte-swapping may be done on the values in data it cannot be declared const
348 
349    Concepts: files^writing binary
350    Concepts: binary files^writing
351 
352 .seealso: PetscBinaryRead(), PetscBinaryOpen(), PetscBinaryClose(), PetscViewerBinaryGetDescriptor(), PetscBinarySynchronizedWrite(),
353           PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek()
354 @*/
355 PetscErrorCode  PetscBinaryWrite(int fd,void *p,PetscInt n,PetscDataType type,PetscBool  istemp)
356 {
357   char           *pp = (char*)p;
358   int            err,wsize;
359   size_t         m = (size_t)n,maxblock=65536;
360 #if !defined(PETSC_WORDS_BIGENDIAN)
361   PetscErrorCode ierr;
362   void           *ptmp = p;
363 #endif
364 
365   PetscFunctionBegin;
366   if (n < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Trying to write a negative amount of data %D",n);
367   if (!n) PetscFunctionReturn(0);
368 
369   if (type == PETSC_INT)          m *= sizeof(PetscInt);
370   else if (type == PETSC_SCALAR)  m *= sizeof(PetscScalar);
371   else if (type == PETSC_DOUBLE)  m *= sizeof(double);
372   else if (type == PETSC_FLOAT)   m *= sizeof(float);
373   else if (type == PETSC_SHORT)   m *= sizeof(short);
374   else if (type == PETSC_CHAR)    m *= sizeof(char);
375   else if (type == PETSC_ENUM)    m *= sizeof(PetscEnum);
376   else if (type == PETSC_BOOL)   m *= sizeof(PetscBool);
377   else if (type == PETSC_BIT_LOGICAL) m = PetscBTLength(m)*sizeof(char);
378   else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown type");
379 
380 #if !defined(PETSC_WORDS_BIGENDIAN)
381   ierr = PetscByteSwap(ptmp,type,n);CHKERRQ(ierr);
382 #endif
383 
384   while (m) {
385     wsize = (m < maxblock) ? m : maxblock;
386     err = write(fd,pp,wsize);
387     if (err < 0 && errno == EINTR) continue;
388     if (err != wsize) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_WRITE,"Error writing to file.");
389     m -= wsize;
390     pp += wsize;
391   }
392 
393 #if !defined(PETSC_WORDS_BIGENDIAN)
394   if (!istemp) {
395     ierr = PetscByteSwap(ptmp,type,n);CHKERRQ(ierr);
396   }
397 #endif
398   PetscFunctionReturn(0);
399 }
400 
401 #undef __FUNCT__
402 #define __FUNCT__ "PetscBinaryOpen"
403 /*@C
404    PetscBinaryOpen - Opens a PETSc binary file.
405 
406    Not Collective
407 
408    Input Parameters:
409 +  name - filename
410 -  type - type of binary file, one of FILE_MODE_READ, FILE_MODE_APPEND, FILE_MODE_WRITE
411 
412    Output Parameter:
413 .  fd - the file
414 
415    Level: advanced
416 
417   Concepts: files^opening binary
418   Concepts: binary files^opening
419 
420    Notes: Files access with PetscBinaryRead() and PetscBinaryWrite() are ALWAYS written in
421    big-endian format. This means the file can be accessed using PetscBinaryOpen() and
422    PetscBinaryRead() and PetscBinaryWrite() on any machine.
423 
424 .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscFileMode, PetscViewerFileSetMode(), PetscViewerBinaryGetDescriptor(),
425           PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek()
426 
427 @*/
428 PetscErrorCode  PetscBinaryOpen(const char name[],PetscFileMode mode,int *fd)
429 {
430   PetscFunctionBegin;
431 #if defined(PETSC_HAVE_O_BINARY)
432   if (mode == FILE_MODE_WRITE) {
433     if ((*fd = open(name,O_WRONLY|O_CREAT|O_TRUNC|O_BINARY,0666)) == -1) {
434       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot create file for writing: %s",name);
435     }
436   } else if (mode == FILE_MODE_READ) {
437     if ((*fd = open(name,O_RDONLY|O_BINARY,0)) == -1) {
438       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file for reading: %s",name);
439     }
440   } else if (mode == FILE_MODE_APPEND) {
441     if ((*fd = open(name,O_WRONLY|O_BINARY,0)) == -1) {
442       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file for writing: %s",name);
443     }
444 #else
445   if (mode == FILE_MODE_WRITE) {
446     if ((*fd = creat(name,0666)) == -1) {
447       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot create file for writing: %s",name);
448     }
449   } else if (mode == FILE_MODE_READ) {
450     if ((*fd = open(name,O_RDONLY,0)) == -1) {
451       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file for reading: %s",name);
452     }
453   }
454   else if (mode == FILE_MODE_APPEND) {
455     if ((*fd = open(name,O_WRONLY,0)) == -1) {
456       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file for writing: %s",name);
457     }
458 #endif
459   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown file mode");
460   PetscFunctionReturn(0);
461 }
462 
463 #undef __FUNCT__
464 #define __FUNCT__ "PetscBinaryClose"
465 /*@
466    PetscBinaryClose - Closes a PETSc binary file.
467 
468    Not Collective
469 
470    Output Parameter:
471 .  fd - the file
472 
473    Level: advanced
474 
475 .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
476           PetscBinarySynchronizedSeek()
477 @*/
478 PetscErrorCode  PetscBinaryClose(int fd)
479 {
480   PetscFunctionBegin;
481   close(fd);
482   PetscFunctionReturn(0);
483 }
484 
485 
486 #undef __FUNCT__
487 #define __FUNCT__ "PetscBinarySeek"
488 /*@
489    PetscBinarySeek - Moves the file pointer on a PETSc binary file.
490 
491    Not Collective
492 
493    Input Parameters:
494 +  fd - the file
495 .  off - number of bytes to move. Use PETSC_BINARY_INT_SIZE, PETSC_BINARY_SCALAR_SIZE,
496             etc. in your calculation rather than sizeof() to compute byte lengths.
497 -  whence - if PETSC_BINARY_SEEK_SET then off is an absolute location in the file
498             if PETSC_BINARY_SEEK_CUR then off is an offset from the current location
499             if PETSC_BINARY_SEEK_END then off is an offset from the end of file
500 
501    Output Parameter:
502 .   offset - new offset in file
503 
504    Level: developer
505 
506    Notes:
507    Integers are stored on the file as 32 long, regardless of whether
508    they are stored in the machine as 32 or 64, this means the same
509    binary file may be read on any machine. Hence you CANNOT use sizeof()
510    to determine the offset or location.
511 
512    Concepts: files^binary seeking
513    Concepts: binary files^seeking
514 
515 .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
516           PetscBinarySynchronizedSeek()
517 @*/
518 PetscErrorCode  PetscBinarySeek(int fd,off_t off,PetscBinarySeekType whence,off_t *offset)
519 {
520   int iwhence = 0;
521 
522   PetscFunctionBegin;
523   if (whence == PETSC_BINARY_SEEK_SET) {
524     iwhence = SEEK_SET;
525   } else if (whence == PETSC_BINARY_SEEK_CUR) {
526     iwhence = SEEK_CUR;
527   } else if (whence == PETSC_BINARY_SEEK_END) {
528     iwhence = SEEK_END;
529   } else {
530     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown seek location");
531   }
532 #if defined(PETSC_HAVE_LSEEK)
533   *offset = lseek(fd,off,iwhence);
534 #elif defined(PETSC_HAVE__LSEEK)
535   *offset = _lseek(fd,(long)off,iwhence);
536 #else
537   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS,"System does not have a way of seeking on a file");
538 #endif
539   PetscFunctionReturn(0);
540 }
541 
542 #undef __FUNCT__
543 #define __FUNCT__ "PetscBinarySynchronizedRead"
544 /*@C
545    PetscBinarySynchronizedRead - Reads from a binary file.
546 
547    Collective on MPI_Comm
548 
549    Input Parameters:
550 +  comm - the MPI communicator
551 .  fd - the file
552 .  n  - the number of items to read
553 -  type - the type of items to read (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)
554 
555    Output Parameters:
556 .  p - the buffer
557 
558    Options Database Key:
559 .   -binary_longints - indicates the file was generated on a Cray vector
560          machine (not the T3E/D) and the ints are stored as 64 bit
561          quantities, otherwise they are stored as 32 bit
562 
563    Level: developer
564 
565    Notes:
566    Does a PetscBinaryRead() followed by an MPI_Bcast()
567 
568    PetscBinarySynchronizedRead() uses byte swapping to work on all machines.
569    Integers are stored on the file as 32 long, regardless of whether
570    they are stored in the machine as 32 or 64, this means the same
571    binary file may be read on any machine.
572 
573    Concepts: files^synchronized reading of binary files
574    Concepts: binary files^reading, synchronized
575 
576 .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscBinaryRead(), PetscBinarySynchronizedWrite(),
577           PetscBinarySynchronizedSeek()
578 @*/
579 PetscErrorCode  PetscBinarySynchronizedRead(MPI_Comm comm,int fd,void *p,PetscInt n,PetscDataType type)
580 {
581   PetscErrorCode ierr;
582   PetscMPIInt    rank;
583   MPI_Datatype   mtype;
584 
585   PetscFunctionBegin;
586   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
587   if (!rank) {
588     ierr = PetscBinaryRead(fd,p,n,type);CHKERRQ(ierr);
589   }
590   ierr = PetscDataTypeToMPIDataType(type,&mtype);CHKERRQ(ierr);
591   ierr = MPI_Bcast(p,n,mtype,0,comm);CHKERRQ(ierr);
592   PetscFunctionReturn(0);
593 }
594 
595 #undef __FUNCT__
596 #define __FUNCT__ "PetscBinarySynchronizedWrite"
597 /*@C
598    PetscBinarySynchronizedWrite - writes to a binary file.
599 
600    Collective on MPI_Comm
601 
602    Input Parameters:
603 +  comm - the MPI communicator
604 .  fd - the file
605 .  n  - the number of items to write
606 .  p - the buffer
607 .  istemp - the buffer may be changed
608 -  type - the type of items to write (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)
609 
610    Level: developer
611 
612    Notes:
613    Process 0 does a PetscBinaryWrite()
614 
615    PetscBinarySynchronizedWrite() uses byte swapping to work on all machines.
616    Integers are stored on the file as 32 long, regardless of whether
617    they are stored in the machine as 32 or 64, this means the same
618    binary file may be read on any machine.
619 
620    Notes: because byte-swapping may be done on the values in data it cannot be declared const
621 
622    WARNING: This is NOT like PetscSynchronizedFPrintf()! This routine ignores calls on all but process 0,
623    while PetscSynchronizedFPrintf() has all processes print their strings in order.
624 
625    Concepts: files^synchronized writing of binary files
626    Concepts: binary files^reading, synchronized
627 
628 .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscBinaryRead(), PetscBinarySynchronizedRead(),
629           PetscBinarySynchronizedSeek()
630 @*/
631 PetscErrorCode  PetscBinarySynchronizedWrite(MPI_Comm comm,int fd,void *p,PetscInt n,PetscDataType type,PetscBool  istemp)
632 {
633   PetscErrorCode ierr;
634   PetscMPIInt    rank;
635 
636   PetscFunctionBegin;
637   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
638   if (!rank) {
639     ierr = PetscBinaryWrite(fd,p,n,type,istemp);CHKERRQ(ierr);
640   }
641   PetscFunctionReturn(0);
642 }
643 
644 #undef __FUNCT__
645 #define __FUNCT__ "PetscBinarySynchronizedSeek"
646 /*@C
647    PetscBinarySynchronizedSeek - Moves the file pointer on a PETSc binary file.
648 
649 
650    Input Parameters:
651 +  fd - the file
652 .  whence - if PETSC_BINARY_SEEK_SET then size is an absolute location in the file
653             if PETSC_BINARY_SEEK_CUR then size is offset from current location
654             if PETSC_BINARY_SEEK_END then size is offset from end of file
655 -  off    - number of bytes to move. Use PETSC_BINARY_INT_SIZE, PETSC_BINARY_SCALAR_SIZE,
656             etc. in your calculation rather than sizeof() to compute byte lengths.
657 
658    Output Parameter:
659 .   offset - new offset in file
660 
661    Level: developer
662 
663    Notes:
664    Integers are stored on the file as 32 long, regardless of whether
665    they are stored in the machine as 32 or 64, this means the same
666    binary file may be read on any machine. Hence you CANNOT use sizeof()
667    to determine the offset or location.
668 
669    Concepts: binary files^seeking
670    Concepts: files^seeking in binary
671 
672 .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
673           PetscBinarySynchronizedSeek()
674 @*/
675 PetscErrorCode  PetscBinarySynchronizedSeek(MPI_Comm comm,int fd,off_t off,PetscBinarySeekType whence,off_t *offset)
676 {
677   PetscErrorCode ierr;
678   PetscMPIInt    rank;
679 
680   PetscFunctionBegin;
681   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
682   if (!rank) {
683     ierr = PetscBinarySeek(fd,off,whence,offset);CHKERRQ(ierr);
684   }
685   PetscFunctionReturn(0);
686 }
687 
688 #if defined(PETSC_HAVE_MPIIO)
689 #if !defined(PETSC_WORDS_BIGENDIAN)
690 
691 #if defined(PETSC_USE_PETSC_MPI_EXTERNAL32)
692 EXTERN_C_BEGIN
693 /*
694       MPICH does not provide the external32 representation for MPI_File_set_view() so we need to provide the functions.
695     These are set into MPI in PetscInitialize() via MPI_Register_datarep()
696 
697     Note I use PetscMPIInt for the MPI error codes since that is what MPI uses (instead of the standard PetscErrorCode)
698 
699     The next three routines are not used because MPICH does not support their use
700 
701 */
702 PetscMPIInt PetscDataRep_extent_fn(MPI_Datatype datatype,MPI_Aint *file_extent,void *extra_state)
703 {
704   MPI_Aint    ub;
705   PetscMPIInt ierr;
706 
707   ierr = MPI_Type_get_extent(datatype,&ub,file_extent);
708   return ierr;
709 }
710 
711 PetscMPIInt PetscDataRep_read_conv_fn(void *userbuf, MPI_Datatype datatype,PetscMPIInt count,void *filebuf, MPI_Offset position,void *extra_state)
712 {
713   PetscDataType pdtype;
714   PetscMPIInt   ierr;
715   size_t        dsize;
716 
717   ierr = PetscMPIDataTypeToPetscDataType(datatype,&pdtype);CHKERRQ(ierr);
718   ierr = PetscDataTypeGetSize(pdtype,&dsize);CHKERRQ(ierr);
719 
720   /* offset is given in units of MPI_Datatype */
721   userbuf = ((char *)userbuf) + dsize*position;
722 
723   ierr = PetscMemcpy(userbuf,filebuf,count*dsize);CHKERRQ(ierr);
724   ierr = PetscByteSwap(userbuf,pdtype,count);CHKERRQ(ierr);
725   return ierr;
726 }
727 
728 PetscMPIInt PetscDataRep_write_conv_fn(void *userbuf, MPI_Datatype datatype,PetscMPIInt count,void *filebuf, MPI_Offset position,void *extra_state)
729 {
730   PetscDataType pdtype;
731   PetscMPIInt   ierr;
732   size_t        dsize;
733 
734   ierr = PetscMPIDataTypeToPetscDataType(datatype,&pdtype);CHKERRQ(ierr);
735   ierr = PetscDataTypeGetSize(pdtype,&dsize);CHKERRQ(ierr);
736 
737   /* offset is given in units of MPI_Datatype */
738   userbuf = ((char *)userbuf) + dsize*position;
739 
740   ierr = PetscMemcpy(filebuf,userbuf,count*dsize);CHKERRQ(ierr);
741   ierr = PetscByteSwap(filebuf,pdtype,count);CHKERRQ(ierr);
742   return ierr;
743 }
744 EXTERN_C_END
745 #endif
746 
747 #undef __FUNCT__
748 #define __FUNCT__ "MPIU_File_write_all"
749 PetscErrorCode MPIU_File_write_all(MPI_File fd,void *data,PetscMPIInt cnt,MPI_Datatype dtype,MPI_Status *status)
750 {
751   PetscErrorCode ierr;
752   PetscDataType  pdtype;
753 
754   PetscFunctionBegin;
755   ierr = PetscMPIDataTypeToPetscDataType(dtype,&pdtype);CHKERRQ(ierr);
756   ierr = PetscByteSwap(data,pdtype,cnt);CHKERRQ(ierr);
757   ierr = MPI_File_write_all(fd,data,cnt,dtype,status);CHKERRQ(ierr);
758   ierr = PetscByteSwap(data,pdtype,cnt);CHKERRQ(ierr);
759   PetscFunctionReturn(0);
760 }
761 
762 #undef __FUNCT__
763 #define __FUNCT__ "MPIU_File_read_all"
764 PetscErrorCode MPIU_File_read_all(MPI_File fd,void *data,PetscMPIInt cnt,MPI_Datatype dtype,MPI_Status *status)
765 {
766   PetscErrorCode ierr;
767   PetscDataType  pdtype;
768 
769   PetscFunctionBegin;
770   ierr = PetscMPIDataTypeToPetscDataType(dtype,&pdtype);CHKERRQ(ierr);
771   ierr = MPI_File_read_all(fd,data,cnt,dtype,status);CHKERRQ(ierr);
772   ierr = PetscByteSwap(data,pdtype,cnt);CHKERRQ(ierr);
773   PetscFunctionReturn(0);
774 }
775 #endif
776 #endif
777