Actual source code: sysio.c

  2: /* 
  3:    This file contains simple binary read/write routines.
  4:  */

  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>

 17: #if !defined(PETSC_WORDS_BIGENDIAN)

 19: /* --------------------------------------------------------- */
 22: /*
 23:   PetscByteSwapEnum - Swap bytes in a  PETSc Enum

 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: 
 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:   return(0);
 43: }

 47: /*
 48:   PetscByteSwapBool - Swap bytes in a  PETSc Bool

 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: 
 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:   return(0);
 68: }

 72: /*
 73:   PetscByteSwapInt - Swap bytes in a  PETSc integer (which may be 32 or 64 bits) 

 75: */
 76: PetscErrorCode  PetscByteSwapInt(PetscInt *buff,PetscInt n)
 77: {
 78:   PetscInt  i,j,tmp = 0;
 79:   char       *ptr1,*ptr2 = (char*)&tmp;
 80: 
 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:   return(0);
 92: }
 93: /* --------------------------------------------------------- */
 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;

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:   return(0);
116: }
117: /* --------------------------------------------------------- */
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;

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:   return(0);
144: }
145: /* --------------------------------------------------------- */
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;

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:   return(0);
168: }

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;

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:   return(0);
192: }

196: PetscErrorCode PetscByteSwap(void *data,PetscDataType pdtype,PetscInt count)
197: {

201:   if      (pdtype == PETSC_INT)    {PetscByteSwapInt((PetscInt*)data,count);}
202:   else if (pdtype == PETSC_ENUM)   {PetscByteSwapEnum((PetscEnum*)data,count);}
203:   else if (pdtype == PETSC_BOOL)   {PetscByteSwapBool((PetscBool*)data,count);}
204:   else if (pdtype == PETSC_SCALAR) {PetscByteSwapScalar((PetscScalar*)data,count);}
205:   else if (pdtype == PETSC_DOUBLE) {PetscByteSwapDouble((double*)data,count);}
206:   else if (pdtype == PETSC_FLOAT) {PetscByteSwapFloat((float*)data,count);}
207:   else if (pdtype == PETSC_SHORT)  {PetscByteSwapShort((short*)data,count);}
208:   return(0);
209: }

211: #endif
212: /* --------------------------------------------------------- */
215: /*@
216:    PetscBinaryRead - Reads from a binary file.

218:    Not Collective

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)

225:    Output Parameters:
226: .  p - the buffer



230:    Level: developer

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.

240:    Concepts: files^reading binary
241:    Concepts: binary files^reading

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

257:   if (!n) return(0);

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:   PetscByteSwap(ptmp,type,n);
281: #endif

283:   return(0);
284: }
285: /* --------------------------------------------------------- */
288: /*@
289:    PetscBinaryWrite - Writes to a binary file.

291:    Not Collective

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.

300:    Level: advanced

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.

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.

320:    Because byte-swapping may be done on the values in data it cannot be declared const

322:    Concepts: files^writing binary
323:    Concepts: binary files^writing

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)
335:   void           *ptmp = p;
336: #endif

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) return(0);

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");

353: #if !defined(PETSC_WORDS_BIGENDIAN)
354:   PetscByteSwap(ptmp,type,n);
355: #endif

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:   }

366: #if !defined(PETSC_WORDS_BIGENDIAN)
367:   if (!istemp) {
368:     PetscByteSwap(ptmp,type,n);
369:   }
370: #endif
371:   return(0);
372: }

376: /*@C
377:    PetscBinaryOpen - Opens a PETSc binary file.

379:    Not Collective

381:    Input Parameters:
382: +  name - filename
383: -  type - type of binary file, one of FILE_MODE_READ, FILE_MODE_APPEND, FILE_MODE_WRITE

385:    Output Parameter:
386: .  fd - the file

388:    Level: advanced

390:   Concepts: files^opening binary
391:   Concepts: binary files^opening

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.

397: .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscFileMode, PetscViewerFileSetMode(), PetscViewerBinaryGetDescriptor(), 
398:           PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek()

400: @*/
401: PetscErrorCode  PetscBinaryOpen(const char name[],PetscFileMode mode,int *fd)
402: {
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:   return(0);
434: }

438: /*@
439:    PetscBinaryClose - Closes a PETSc binary file.

441:    Not Collective

443:    Output Parameter:
444: .  fd - the file

446:    Level: advanced

448: .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
449:           PetscBinarySynchronizedSeek()
450: @*/
451: PetscErrorCode  PetscBinaryClose(int fd)
452: {
454:   close(fd);
455:   return(0);
456: }


461: /*@
462:    PetscBinarySeek - Moves the file pointer on a PETSc binary file.

464:    Not Collective

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

474:    Output Parameter:
475: .   offset - new offset in file

477:    Level: developer

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.

485:    Concepts: files^binary seeking
486:    Concepts: binary files^seeking

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;

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:   return(0);
513: }

517: /*@C
518:    PetscBinarySynchronizedRead - Reads from a binary file.

520:    Collective on MPI_Comm

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)

528:    Output Parameters:
529: .  p - the buffer

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

536:    Level: developer

538:    Notes: 
539:    Does a PetscBinaryRead() followed by an MPI_Bcast()

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.

546:    Concepts: files^synchronized reading of binary files
547:    Concepts: binary files^reading, synchronized

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: {
555:   PetscMPIInt    rank;
556:   MPI_Datatype   mtype;

559:   MPI_Comm_rank(comm,&rank);
560:   if (!rank) {
561:     PetscBinaryRead(fd,p,n,type);
562:   }
563:   PetscDataTypeToMPIDataType(type,&mtype);
564:   MPI_Bcast(p,n,mtype,0,comm);
565:   return(0);
566: }

570: /*@C
571:    PetscBinarySynchronizedWrite - writes to a binary file.

573:    Collective on MPI_Comm

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)

583:    Level: developer

585:    Notes: 
586:    Process 0 does a PetscBinaryWrite()

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.

593:    Notes: because byte-swapping may be done on the values in data it cannot be declared const

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.

598:    Concepts: files^synchronized writing of binary files
599:    Concepts: binary files^reading, synchronized

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: {
607:   PetscMPIInt    rank;

610:   MPI_Comm_rank(comm,&rank);
611:   if (!rank) {
612:     PetscBinaryWrite(fd,p,n,type,istemp);
613:   }
614:   return(0);
615: }

619: /*@C
620:    PetscBinarySynchronizedSeek - Moves the file pointer on a PETSc binary file.


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.

631:    Output Parameter:
632: .   offset - new offset in file

634:    Level: developer

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.

642:    Concepts: binary files^seeking
643:    Concepts: files^seeking in binary 

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: {
651:   PetscMPIInt    rank;

654:   MPI_Comm_rank(comm,&rank);
655:   if (!rank) {
656:     PetscBinarySeek(fd,off,whence,offset);
657:   }
658:   return(0);
659: }

661: #if defined(PETSC_HAVE_MPIIO)
662: #if !defined(PETSC_WORDS_BIGENDIAN)

664: #if defined(PETSC_USE_PETSC_MPI_EXTERNAL32)
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()

670:     Note I use PetscMPIInt for the MPI error codes since that is what MPI uses (instead of the standard PetscErrorCode)

672:     The next three routines are not used because MPICH does not support their use

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:   MPI_Type_get_extent(datatype,&ub,file_extent);
681:   return ierr;
682: }

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:   PetscMPIDataTypeToPetscDataType(datatype,&pdtype);
691:   PetscDataTypeGetSize(pdtype,&dsize);

693:   /* offset is given in units of MPI_Datatype */
694:   userbuf = ((char *)userbuf) + dsize*position;

696:   PetscMemcpy(userbuf,filebuf,count*dsize);
697:   PetscByteSwap(userbuf,pdtype,count);
698:   return ierr;
699: }

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:   PetscMPIDataTypeToPetscDataType(datatype,&pdtype);
708:   PetscDataTypeGetSize(pdtype,&dsize);

710:   /* offset is given in units of MPI_Datatype */
711:   userbuf = ((char *)userbuf) + dsize*position;

713:   PetscMemcpy(filebuf,userbuf,count*dsize);
714:   PetscByteSwap(filebuf,pdtype,count);
715:   return ierr;
716: }
718: #endif

722: PetscErrorCode MPIU_File_write_all(MPI_File fd,void *data,PetscMPIInt cnt,MPI_Datatype dtype,MPI_Status *status)
723: {
725:   PetscDataType  pdtype;

728:   PetscMPIDataTypeToPetscDataType(dtype,&pdtype);
729:   PetscByteSwap(data,pdtype,cnt);
730:   MPI_File_write_all(fd,data,cnt,dtype,status);
731:   PetscByteSwap(data,pdtype,cnt);
732:   return(0);
733: }

737: PetscErrorCode MPIU_File_read_all(MPI_File fd,void *data,PetscMPIInt cnt,MPI_Datatype dtype,MPI_Status *status)
738: {
740:   PetscDataType  pdtype;

743:   PetscMPIDataTypeToPetscDataType(dtype,&pdtype);
744:   MPI_File_read_all(fd,data,cnt,dtype,status);
745:   PetscByteSwap(data,pdtype,cnt);
746:   return(0);
747: }
748: #endif
749: #endif