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