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