xref: /petsc/src/sys/fileio/sysio.c (revision c0174eb74783e1ccfa817272a5782dd72b4cfcef)
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_WORDS_BIGENDIAN)
249   PetscErrorCode    ierr;
250   void              *ptmp = p;
251 #endif
252 
253   PetscFunctionBegin;
254   if (!n) PetscFunctionReturn(0);
255 
256   if (type == PETSC_INT)          m *= sizeof(PetscInt);
257   else if (type == PETSC_SCALAR)  m *= sizeof(PetscScalar);
258   else if (type == PETSC_DOUBLE)  m *= sizeof(double);
259   else if (type == PETSC_FLOAT)   m *= sizeof(float);
260   else if (type == PETSC_SHORT)   m *= sizeof(short);
261   else if (type == PETSC_CHAR)    m *= sizeof(char);
262   else if (type == PETSC_ENUM)    m *= sizeof(PetscEnum);
263   else if (type == PETSC_BOOL)   m *= sizeof(PetscBool);
264   else if (type == PETSC_BIT_LOGICAL) m  = PetscBTLength(m)*sizeof(char);
265   else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown type");
266 
267   while (m) {
268     wsize = (m < maxblock) ? m : maxblock;
269     err = read(fd,pp,wsize);
270     if (err < 0 && errno == EINTR) continue;
271     if (!err && wsize > 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_READ,"Read past end of file");
272     if (err < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_READ,"Error reading from file, errno %d",errno);
273     m  -= err;
274     pp += err;
275   }
276 #if !defined(PETSC_WORDS_BIGENDIAN)
277   ierr = PetscByteSwap(ptmp,type,n);CHKERRQ(ierr);
278 #endif
279 
280   PetscFunctionReturn(0);
281 }
282 /* --------------------------------------------------------- */
283 #undef __FUNCT__
284 #define __FUNCT__ "PetscBinaryWrite"
285 /*@
286    PetscBinaryWrite - Writes to a binary file.
287 
288    Not Collective
289 
290    Input Parameters:
291 +  fd     - the file
292 .  p      - the buffer
293 .  n      - the number of items to write
294 .  type   - the type of items to read (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)
295 -  istemp - PETSC_FALSE if buffer data should be preserved, PETSC_TRUE otherwise.
296 
297    Level: advanced
298 
299    Notes:
300    PetscBinaryWrite() uses byte swapping to work on all machines; the files
301    are written using big-endian ordering to the file. On small-endian machines the numbers
302    are converted to the big-endian format when they are written to disk.
303    When PETSc is ./configure with --with-64bit-indices the integers are written to the
304    file as 64 bit integers, this means they can only be read back in when the option --with-64bit-indices
305    is used.
306 
307    The Buffer p should be read-write buffer, and not static data.
308    This way, byte-swapping is done in-place, and then the buffer is
309    written to the file.
310 
311    This routine restores the original contents of the buffer, after
312    it is written to the file. This is done by byte-swapping in-place
313    the second time. If the flag istemp is set to PETSC_TRUE, the second
314    byte-swapping operation is not done, thus saving some computation,
315    but the buffer is left corrupted.
316 
317    Because byte-swapping may be done on the values in data it cannot be declared const
318 
319    Concepts: files^writing binary
320    Concepts: binary files^writing
321 
322 .seealso: PetscBinaryRead(), PetscBinaryOpen(), PetscBinaryClose(), PetscViewerBinaryGetDescriptor(), PetscBinarySynchronizedWrite(),
323           PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek()
324 @*/
325 PetscErrorCode  PetscBinaryWrite(int fd,void *p,PetscInt n,PetscDataType type,PetscBool  istemp)
326 {
327   char           *pp = (char*)p;
328   int            err,wsize;
329   size_t         m = (size_t)n,maxblock=65536;
330 #if !defined(PETSC_WORDS_BIGENDIAN)
331   PetscErrorCode ierr;
332   void           *ptmp = p;
333 #endif
334 
335   PetscFunctionBegin;
336   if (n < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Trying to write a negative amount of data %D",n);
337   if (!n) PetscFunctionReturn(0);
338 
339   if (type == PETSC_INT)          m *= sizeof(PetscInt);
340   else if (type == PETSC_SCALAR)  m *= sizeof(PetscScalar);
341   else if (type == PETSC_DOUBLE)  m *= sizeof(double);
342   else if (type == PETSC_FLOAT)   m *= sizeof(float);
343   else if (type == PETSC_SHORT)   m *= sizeof(short);
344   else if (type == PETSC_CHAR)    m *= sizeof(char);
345   else if (type == PETSC_ENUM)    m *= sizeof(PetscEnum);
346   else if (type == PETSC_BOOL)   m *= sizeof(PetscBool);
347   else if (type == PETSC_BIT_LOGICAL) m = PetscBTLength(m)*sizeof(char);
348   else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown type");
349 
350 #if !defined(PETSC_WORDS_BIGENDIAN)
351   ierr = PetscByteSwap(ptmp,type,n);CHKERRQ(ierr);
352 #endif
353 
354   while (m) {
355     wsize = (m < maxblock) ? m : maxblock;
356     err = write(fd,pp,wsize);
357     if (err < 0 && errno == EINTR) continue;
358     if (err != wsize) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_WRITE,"Error writing to file.");
359     m -= wsize;
360     pp += wsize;
361   }
362 
363 #if !defined(PETSC_WORDS_BIGENDIAN)
364   if (!istemp) {
365     ierr = PetscByteSwap(ptmp,type,n);CHKERRQ(ierr);
366   }
367 #endif
368   PetscFunctionReturn(0);
369 }
370 
371 #undef __FUNCT__
372 #define __FUNCT__ "PetscBinaryOpen"
373 /*@C
374    PetscBinaryOpen - Opens a PETSc binary file.
375 
376    Not Collective
377 
378    Input Parameters:
379 +  name - filename
380 -  type - type of binary file, one of FILE_MODE_READ, FILE_MODE_APPEND, FILE_MODE_WRITE
381 
382    Output Parameter:
383 .  fd - the file
384 
385    Level: advanced
386 
387   Concepts: files^opening binary
388   Concepts: binary files^opening
389 
390    Notes: Files access with PetscBinaryRead() and PetscBinaryWrite() are ALWAYS written in
391    big-endian format. This means the file can be accessed using PetscBinaryOpen() and
392    PetscBinaryRead() and PetscBinaryWrite() on any machine.
393 
394 .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscFileMode, PetscViewerFileSetMode(), PetscViewerBinaryGetDescriptor(),
395           PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek()
396 
397 @*/
398 PetscErrorCode  PetscBinaryOpen(const char name[],PetscFileMode mode,int *fd)
399 {
400   PetscFunctionBegin;
401 #if defined(PETSC_HAVE_O_BINARY)
402   if (mode == FILE_MODE_WRITE) {
403     if ((*fd = open(name,O_WRONLY|O_CREAT|O_TRUNC|O_BINARY,0666)) == -1) {
404       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot create file for writing: %s",name);
405     }
406   } else if (mode == FILE_MODE_READ) {
407     if ((*fd = open(name,O_RDONLY|O_BINARY,0)) == -1) {
408       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file for reading: %s",name);
409     }
410   } else if (mode == FILE_MODE_APPEND) {
411     if ((*fd = open(name,O_WRONLY|O_BINARY,0)) == -1) {
412       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file for writing: %s",name);
413     }
414 #else
415   if (mode == FILE_MODE_WRITE) {
416     if ((*fd = creat(name,0666)) == -1) {
417       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot create file for writing: %s",name);
418     }
419   } else if (mode == FILE_MODE_READ) {
420     if ((*fd = open(name,O_RDONLY,0)) == -1) {
421       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file for reading: %s",name);
422     }
423   }
424   else if (mode == FILE_MODE_APPEND) {
425     if ((*fd = open(name,O_WRONLY,0)) == -1) {
426       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file for writing: %s",name);
427     }
428 #endif
429   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown file mode");
430   PetscFunctionReturn(0);
431 }
432 
433 #undef __FUNCT__
434 #define __FUNCT__ "PetscBinaryClose"
435 /*@
436    PetscBinaryClose - Closes a PETSc binary file.
437 
438    Not Collective
439 
440    Output Parameter:
441 .  fd - the file
442 
443    Level: advanced
444 
445 .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
446           PetscBinarySynchronizedSeek()
447 @*/
448 PetscErrorCode  PetscBinaryClose(int fd)
449 {
450   PetscFunctionBegin;
451   close(fd);
452   PetscFunctionReturn(0);
453 }
454 
455 
456 #undef __FUNCT__
457 #define __FUNCT__ "PetscBinarySeek"
458 /*@
459    PetscBinarySeek - Moves the file pointer on a PETSc binary file.
460 
461    Not Collective
462 
463    Input Parameters:
464 +  fd - the file
465 .  off - number of bytes to move. Use PETSC_BINARY_INT_SIZE, PETSC_BINARY_SCALAR_SIZE,
466             etc. in your calculation rather than sizeof() to compute byte lengths.
467 -  whence - if PETSC_BINARY_SEEK_SET then off is an absolute location in the file
468             if PETSC_BINARY_SEEK_CUR then off is an offset from the current location
469             if PETSC_BINARY_SEEK_END then off is an offset from the end of file
470 
471    Output Parameter:
472 .   offset - new offset in file
473 
474    Level: developer
475 
476    Notes:
477    Integers are stored on the file as 32 long, regardless of whether
478    they are stored in the machine as 32 or 64, this means the same
479    binary file may be read on any machine. Hence you CANNOT use sizeof()
480    to determine the offset or location.
481 
482    Concepts: files^binary seeking
483    Concepts: binary files^seeking
484 
485 .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
486           PetscBinarySynchronizedSeek()
487 @*/
488 PetscErrorCode  PetscBinarySeek(int fd,off_t off,PetscBinarySeekType whence,off_t *offset)
489 {
490   int iwhence = 0;
491 
492   PetscFunctionBegin;
493   if (whence == PETSC_BINARY_SEEK_SET) {
494     iwhence = SEEK_SET;
495   } else if (whence == PETSC_BINARY_SEEK_CUR) {
496     iwhence = SEEK_CUR;
497   } else if (whence == PETSC_BINARY_SEEK_END) {
498     iwhence = SEEK_END;
499   } else {
500     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown seek location");
501   }
502 #if defined(PETSC_HAVE_LSEEK)
503   *offset = lseek(fd,off,iwhence);
504 #elif defined(PETSC_HAVE__LSEEK)
505   *offset = _lseek(fd,(long)off,iwhence);
506 #else
507   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS,"System does not have a way of seeking on a file");
508 #endif
509   PetscFunctionReturn(0);
510 }
511 
512 #undef __FUNCT__
513 #define __FUNCT__ "PetscBinarySynchronizedRead"
514 /*@C
515    PetscBinarySynchronizedRead - Reads from a binary file.
516 
517    Collective on MPI_Comm
518 
519    Input Parameters:
520 +  comm - the MPI communicator
521 .  fd - the file
522 .  n  - the number of items to read
523 -  type - the type of items to read (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)
524 
525    Output Parameters:
526 .  p - the buffer
527 
528    Options Database Key:
529 .   -binary_longints - indicates the file was generated on a Cray vector
530          machine (not the T3E/D) and the ints are stored as 64 bit
531          quantities, otherwise they are stored as 32 bit
532 
533    Level: developer
534 
535    Notes:
536    Does a PetscBinaryRead() followed by an MPI_Bcast()
537 
538    PetscBinarySynchronizedRead() uses byte swapping to work on all machines.
539    Integers are stored on the file as 32 long, regardless of whether
540    they are stored in the machine as 32 or 64, this means the same
541    binary file may be read on any machine.
542 
543    Concepts: files^synchronized reading of binary files
544    Concepts: binary files^reading, synchronized
545 
546 .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscBinaryRead(), PetscBinarySynchronizedWrite(),
547           PetscBinarySynchronizedSeek()
548 @*/
549 PetscErrorCode  PetscBinarySynchronizedRead(MPI_Comm comm,int fd,void *p,PetscInt n,PetscDataType type)
550 {
551   PetscErrorCode ierr;
552   PetscMPIInt    rank;
553   MPI_Datatype   mtype;
554 
555   PetscFunctionBegin;
556   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
557   if (!rank) {
558     ierr = PetscBinaryRead(fd,p,n,type);CHKERRQ(ierr);
559   }
560   ierr = PetscDataTypeToMPIDataType(type,&mtype);CHKERRQ(ierr);
561   ierr = MPI_Bcast(p,n,mtype,0,comm);CHKERRQ(ierr);
562   PetscFunctionReturn(0);
563 }
564 
565 #undef __FUNCT__
566 #define __FUNCT__ "PetscBinarySynchronizedWrite"
567 /*@C
568    PetscBinarySynchronizedWrite - writes to a binary file.
569 
570    Collective on MPI_Comm
571 
572    Input Parameters:
573 +  comm - the MPI communicator
574 .  fd - the file
575 .  n  - the number of items to write
576 .  p - the buffer
577 .  istemp - the buffer may be changed
578 -  type - the type of items to write (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)
579 
580    Level: developer
581 
582    Notes:
583    Process 0 does a PetscBinaryWrite()
584 
585    PetscBinarySynchronizedWrite() uses byte swapping to work on all machines.
586    Integers are stored on the file as 32 long, regardless of whether
587    they are stored in the machine as 32 or 64, this means the same
588    binary file may be read on any machine.
589 
590    Notes: because byte-swapping may be done on the values in data it cannot be declared const
591 
592    WARNING: This is NOT like PetscSynchronizedFPrintf()! This routine ignores calls on all but process 0,
593    while PetscSynchronizedFPrintf() has all processes print their strings in order.
594 
595    Concepts: files^synchronized writing of binary files
596    Concepts: binary files^reading, synchronized
597 
598 .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscBinaryRead(), PetscBinarySynchronizedRead(),
599           PetscBinarySynchronizedSeek()
600 @*/
601 PetscErrorCode  PetscBinarySynchronizedWrite(MPI_Comm comm,int fd,void *p,PetscInt n,PetscDataType type,PetscBool  istemp)
602 {
603   PetscErrorCode ierr;
604   PetscMPIInt    rank;
605 
606   PetscFunctionBegin;
607   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
608   if (!rank) {
609     ierr = PetscBinaryWrite(fd,p,n,type,istemp);CHKERRQ(ierr);
610   }
611   PetscFunctionReturn(0);
612 }
613 
614 #undef __FUNCT__
615 #define __FUNCT__ "PetscBinarySynchronizedSeek"
616 /*@C
617    PetscBinarySynchronizedSeek - Moves the file pointer on a PETSc binary file.
618 
619 
620    Input Parameters:
621 +  fd - the file
622 .  whence - if PETSC_BINARY_SEEK_SET then size is an absolute location in the file
623             if PETSC_BINARY_SEEK_CUR then size is offset from current location
624             if PETSC_BINARY_SEEK_END then size is offset from end of file
625 -  off    - number of bytes to move. Use PETSC_BINARY_INT_SIZE, PETSC_BINARY_SCALAR_SIZE,
626             etc. in your calculation rather than sizeof() to compute byte lengths.
627 
628    Output Parameter:
629 .   offset - new offset in file
630 
631    Level: developer
632 
633    Notes:
634    Integers are stored on the file as 32 long, regardless of whether
635    they are stored in the machine as 32 or 64, this means the same
636    binary file may be read on any machine. Hence you CANNOT use sizeof()
637    to determine the offset or location.
638 
639    Concepts: binary files^seeking
640    Concepts: files^seeking in binary
641 
642 .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
643           PetscBinarySynchronizedSeek()
644 @*/
645 PetscErrorCode  PetscBinarySynchronizedSeek(MPI_Comm comm,int fd,off_t off,PetscBinarySeekType whence,off_t *offset)
646 {
647   PetscErrorCode ierr;
648   PetscMPIInt    rank;
649 
650   PetscFunctionBegin;
651   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
652   if (!rank) {
653     ierr = PetscBinarySeek(fd,off,whence,offset);CHKERRQ(ierr);
654   }
655   PetscFunctionReturn(0);
656 }
657 
658 #if defined(PETSC_HAVE_MPIIO)
659 #if !defined(PETSC_WORDS_BIGENDIAN)
660 
661 #if defined(PETSC_USE_PETSC_MPI_EXTERNAL32)
662 EXTERN_C_BEGIN
663 /*
664       MPICH does not provide the external32 representation for MPI_File_set_view() so we need to provide the functions.
665     These are set into MPI in PetscInitialize() via MPI_Register_datarep()
666 
667     Note I use PetscMPIInt for the MPI error codes since that is what MPI uses (instead of the standard PetscErrorCode)
668 
669     The next three routines are not used because MPICH does not support their use
670 
671 */
672 PetscMPIInt PetscDataRep_extent_fn(MPI_Datatype datatype,MPI_Aint *file_extent,void *extra_state)
673 {
674   MPI_Aint    ub;
675   PetscMPIInt ierr;
676 
677   ierr = MPI_Type_get_extent(datatype,&ub,file_extent);
678   return ierr;
679 }
680 
681 PetscMPIInt PetscDataRep_read_conv_fn(void *userbuf, MPI_Datatype datatype,PetscMPIInt count,void *filebuf, MPI_Offset position,void *extra_state)
682 {
683   PetscDataType pdtype;
684   PetscMPIInt   ierr;
685   size_t        dsize;
686 
687   ierr = PetscMPIDataTypeToPetscDataType(datatype,&pdtype);CHKERRQ(ierr);
688   ierr = PetscDataTypeGetSize(pdtype,&dsize);CHKERRQ(ierr);
689 
690   /* offset is given in units of MPI_Datatype */
691   userbuf = ((char *)userbuf) + dsize*position;
692 
693   ierr = PetscMemcpy(userbuf,filebuf,count*dsize);CHKERRQ(ierr);
694   ierr = PetscByteSwap(userbuf,pdtype,count);CHKERRQ(ierr);
695   return ierr;
696 }
697 
698 PetscMPIInt PetscDataRep_write_conv_fn(void *userbuf, MPI_Datatype datatype,PetscMPIInt count,void *filebuf, MPI_Offset position,void *extra_state)
699 {
700   PetscDataType pdtype;
701   PetscMPIInt   ierr;
702   size_t        dsize;
703 
704   ierr = PetscMPIDataTypeToPetscDataType(datatype,&pdtype);CHKERRQ(ierr);
705   ierr = PetscDataTypeGetSize(pdtype,&dsize);CHKERRQ(ierr);
706 
707   /* offset is given in units of MPI_Datatype */
708   userbuf = ((char *)userbuf) + dsize*position;
709 
710   ierr = PetscMemcpy(filebuf,userbuf,count*dsize);CHKERRQ(ierr);
711   ierr = PetscByteSwap(filebuf,pdtype,count);CHKERRQ(ierr);
712   return ierr;
713 }
714 EXTERN_C_END
715 #endif
716 
717 #undef __FUNCT__
718 #define __FUNCT__ "MPIU_File_write_all"
719 PetscErrorCode MPIU_File_write_all(MPI_File fd,void *data,PetscMPIInt cnt,MPI_Datatype dtype,MPI_Status *status)
720 {
721   PetscErrorCode ierr;
722   PetscDataType  pdtype;
723 
724   PetscFunctionBegin;
725   ierr = PetscMPIDataTypeToPetscDataType(dtype,&pdtype);CHKERRQ(ierr);
726   ierr = PetscByteSwap(data,pdtype,cnt);CHKERRQ(ierr);
727   ierr = MPI_File_write_all(fd,data,cnt,dtype,status);CHKERRQ(ierr);
728   ierr = PetscByteSwap(data,pdtype,cnt);CHKERRQ(ierr);
729   PetscFunctionReturn(0);
730 }
731 
732 #undef __FUNCT__
733 #define __FUNCT__ "MPIU_File_read_all"
734 PetscErrorCode MPIU_File_read_all(MPI_File fd,void *data,PetscMPIInt cnt,MPI_Datatype dtype,MPI_Status *status)
735 {
736   PetscErrorCode ierr;
737   PetscDataType  pdtype;
738 
739   PetscFunctionBegin;
740   ierr = PetscMPIDataTypeToPetscDataType(dtype,&pdtype);CHKERRQ(ierr);
741   ierr = MPI_File_read_all(fd,data,cnt,dtype,status);CHKERRQ(ierr);
742   ierr = PetscByteSwap(data,pdtype,cnt);CHKERRQ(ierr);
743   PetscFunctionReturn(0);
744 }
745 #endif
746 #endif
747