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