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