Actual source code: sysio.c

petsc-3.3-p7 2013-05-11
  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: /* --------------------------------------------------------- */
 20: /*
 21:   PetscByteSwapEnum - Swap bytes in a  PETSc Enum

 23: */
 24: PetscErrorCode  PetscByteSwapEnum(PetscEnum *buff,PetscInt n)
 25: {
 26:   PetscInt   i,j;
 27:   PetscEnum   tmp = ENUM_DUMMY;
 28:   char       *ptr1,*ptr2 = (char*)&tmp;
 29: 
 31:   for (j=0; j<n; j++) {
 32:     ptr1 = (char*)(buff + j);
 33:     for (i=0; i<(PetscInt)sizeof(PetscEnum); i++) {
 34:       ptr2[i] = ptr1[sizeof(PetscEnum)-1-i];
 35:     }
 36:     for (i=0; i<(PetscInt)sizeof(PetscEnum); i++) {
 37:       ptr1[i] = ptr2[i];
 38:     }
 39:   }
 40:   return(0);
 41: }

 45: /*
 46:   PetscByteSwapBool - Swap bytes in a  PETSc Bool

 48: */
 49: PetscErrorCode  PetscByteSwapBool(PetscBool *buff,PetscInt n)
 50: {
 51:   PetscInt    i,j;
 52:   PetscBool   tmp = PETSC_FALSE;
 53:   char        *ptr1,*ptr2 = (char*)&tmp;
 54: 
 56:   for (j=0; j<n; j++) {
 57:     ptr1 = (char*)(buff + j);
 58:     for (i=0; i<(PetscInt)sizeof(PetscBool); i++) {
 59:       ptr2[i] = ptr1[sizeof(PetscBool)-1-i];
 60:     }
 61:     for (i=0; i<(PetscInt)sizeof(PetscBool); i++) {
 62:       ptr1[i] = ptr2[i];
 63:     }
 64:   }
 65:   return(0);
 66: }

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

 73: */
 74: PetscErrorCode  PetscByteSwapInt(PetscInt *buff,PetscInt n)
 75: {
 76:   PetscInt  i,j,tmp = 0;
 77:   char       *ptr1,*ptr2 = (char*)&tmp;
 78: 
 80:   for (j=0; j<n; j++) {
 81:     ptr1 = (char*)(buff + j);
 82:     for (i=0; i<(PetscInt)sizeof(PetscInt); i++) {
 83:       ptr2[i] = ptr1[sizeof(PetscInt)-1-i];
 84:     }
 85:     for (i=0; i<(PetscInt)sizeof(PetscInt); i++) {
 86:       ptr1[i] = ptr2[i];
 87:     }
 88:   }
 89:   return(0);
 90: }
 91: /* --------------------------------------------------------- */
 94: /*
 95:   PetscByteSwapShort - Swap bytes in a short
 96: */
 97: PetscErrorCode  PetscByteSwapShort(short *buff,PetscInt n)
 98: {
 99:   PetscInt   i,j;
100:   short      tmp;
101:   char       *ptr1,*ptr2 = (char*)&tmp;

104:   for (j=0; j<n; j++) {
105:     ptr1 = (char*)(buff + j);
106:     for (i=0; i<(PetscInt) sizeof(short); i++) {
107:       ptr2[i] = ptr1[sizeof(short)-1-i];
108:     }
109:     for (i=0; i<(PetscInt) sizeof(short); i++) {
110:       ptr1[i] = ptr2[i];
111:     }
112:   }
113:   return(0);
114: }
115: /* --------------------------------------------------------- */
118: /*
119:   PetscByteSwapScalar - Swap bytes in a double
120:   Complex is dealt with as if array of double twice as long.
121: */
122: PetscErrorCode  PetscByteSwapScalar(PetscScalar *buff,PetscInt n)
123: {
124:   PetscInt  i,j;
125:   PetscReal tmp,*buff1 = (PetscReal*)buff;
126:   char      *ptr1,*ptr2 = (char*)&tmp;

129: #if defined(PETSC_USE_COMPLEX)
130:   n *= 2;
131: #endif
132:   for (j=0; j<n; j++) {
133:     ptr1 = (char*)(buff1 + j);
134:     for (i=0; i<(PetscInt) sizeof(PetscReal); i++) {
135:       ptr2[i] = ptr1[sizeof(PetscReal)-1-i];
136:     }
137:     for (i=0; i<(PetscInt) sizeof(PetscReal); i++) {
138:       ptr1[i] = ptr2[i];
139:     }
140:   }
141:   return(0);
142: }
143: /* --------------------------------------------------------- */
146: /*
147:   PetscByteSwapDouble - Swap bytes in a double
148: */
149: PetscErrorCode  PetscByteSwapDouble(double *buff,PetscInt n)
150: {
151:   PetscInt i,j;
152:   double   tmp,*buff1 = (double*)buff;
153:   char     *ptr1,*ptr2 = (char*)&tmp;

156:   for (j=0; j<n; j++) {
157:     ptr1 = (char*)(buff1 + j);
158:     for (i=0; i<(PetscInt) sizeof(double); i++) {
159:       ptr2[i] = ptr1[sizeof(double)-1-i];
160:     }
161:     for (i=0; i<(PetscInt) sizeof(double); i++) {
162:       ptr1[i] = ptr2[i];
163:     }
164:   }
165:   return(0);
166: }

170: /*
171:   PetscByteSwapFloat - Swap bytes in a float
172: */
173: PetscErrorCode PetscByteSwapFloat(float *buff,PetscInt n)
174: {
175:   PetscInt i,j;
176:   float   tmp,*buff1 = (float*)buff;
177:   char     *ptr1,*ptr2 = (char*)&tmp;

180:   for (j=0; j<n; j++) {
181:     ptr1 = (char*)(buff1 + j);
182:     for (i=0; i<(PetscInt) sizeof(float); i++) {
183:       ptr2[i] = ptr1[sizeof(float)-1-i];
184:     }
185:     for (i=0; i<(PetscInt) sizeof(float); i++) {
186:       ptr1[i] = ptr2[i];
187:     }
188:   }
189:   return(0);
190: }

194: PetscErrorCode PetscByteSwap(void *data,PetscDataType pdtype,PetscInt count)
195: {

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

209: /* --------------------------------------------------------- */
212: /*@
213:    PetscBinaryRead - Reads from a binary file.

215:    Not Collective

217:    Input Parameters:
218: +  fd - the file
219: .  n  - the number of items to read 
220: -  type - the type of items to read (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)

222:    Output Parameters:
223: .  p - the buffer



227:    Level: developer

229:    Notes: 
230:    PetscBinaryRead() uses byte swapping to work on all machines; the files
231:    are written to file ALWAYS using big-endian ordering. On small-endian machines the numbers
232:    are converted to the small-endian format when they are read in from the file.
233:    When PETSc is ./configure with --with-64bit-indices the integers are written to the
234:    file as 64 bit integers, this means they can only be read back in when the option --with-64bit-indices
235:    is used.

237:    Concepts: files^reading binary
238:    Concepts: binary files^reading

240: .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscViewerBinaryGetDescriptor(), PetscBinarySynchronizedWrite(),
241:           PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek()
242: @*/
243: PetscErrorCode  PetscBinaryRead(int fd,void *p,PetscInt n,PetscDataType type)
244: {
245:   int               wsize,err;
246:   size_t            m = (size_t) n,maxblock = 65536;
247:   char              *pp = (char*)p;
248: #if !defined(PETSC_WORDS_BIGENDIAN)
249:   PetscErrorCode    ierr;
250:   void              *ptmp = p;
251: #endif

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

256:   if (type == PETSC_INT)          m *= sizeof(PetscInt);
257:   else if (type == PETSC_SCALAR)  m *= sizeof(PetscScalar);
258:   else if (type == PETSC_DOUBLE)  m *= sizeof(double);
259:   else if (type == PETSC_FLOAT)   m *= sizeof(float);
260:   else if (type == PETSC_SHORT)   m *= sizeof(short);
261:   else if (type == PETSC_CHAR)    m *= sizeof(char);
262:   else if (type == PETSC_ENUM)    m *= sizeof(PetscEnum);
263:   else if (type == PETSC_BOOL)   m *= sizeof(PetscBool);
264:   else if (type == PETSC_BIT_LOGICAL) m  = PetscBTLength(m)*sizeof(char);
265:   else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown type");
266: 
267:   while (m) {
268:     wsize = (m < maxblock) ? m : maxblock;
269:     err = read(fd,pp,wsize);
270:     if (err < 0 && errno == EINTR) continue;
271:     if (!err && wsize > 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_READ,"Read past end of file");
272:     if (err < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_READ,"Error reading from file, errno %d",errno);
273:     m  -= err;
274:     pp += err;
275:   }
276: #if !defined(PETSC_WORDS_BIGENDIAN)
277:   PetscByteSwap(ptmp,type,n);
278: #endif

280:   return(0);
281: }
282: /* --------------------------------------------------------- */
285: /*@
286:    PetscBinaryWrite - Writes to a binary file.

288:    Not Collective

290:    Input Parameters:
291: +  fd     - the file
292: .  p      - the buffer
293: .  n      - the number of items to write
294: .  type   - the type of items to read (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)
295: -  istemp - PETSC_FALSE if buffer data should be preserved, PETSC_TRUE otherwise.

297:    Level: advanced

299:    Notes: 
300:    PetscBinaryWrite() uses byte swapping to work on all machines; the files
301:    are written using big-endian ordering to the file. On small-endian machines the numbers
302:    are converted to the big-endian format when they are written to disk.
303:    When PETSc is ./configure with --with-64bit-indices the integers are written to the
304:    file as 64 bit integers, this means they can only be read back in when the option --with-64bit-indices
305:    is used.

307:    The Buffer p should be read-write buffer, and not static data.
308:    This way, byte-swapping is done in-place, and then the buffer is
309:    written to the file.
310:    
311:    This routine restores the original contents of the buffer, after 
312:    it is written to the file. This is done by byte-swapping in-place 
313:    the second time. If the flag istemp is set to PETSC_TRUE, the second
314:    byte-swapping operation is not done, thus saving some computation,
315:    but the buffer is left corrupted.

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

319:    Concepts: files^writing binary
320:    Concepts: binary files^writing

322: .seealso: PetscBinaryRead(), PetscBinaryOpen(), PetscBinaryClose(), PetscViewerBinaryGetDescriptor(), PetscBinarySynchronizedWrite(), 
323:           PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek()
324: @*/
325: PetscErrorCode  PetscBinaryWrite(int fd,void *p,PetscInt n,PetscDataType type,PetscBool  istemp)
326: {
327:   char           *pp = (char*)p;
328:   int            err,wsize;
329:   size_t         m = (size_t)n,maxblock=65536;
330: #if !defined(PETSC_WORDS_BIGENDIAN)
332:   void           *ptmp = p;
333: #endif

336:   if (n < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Trying to write a negative amount of data %D",n);
337:   if (!n) return(0);

339:   if (type == PETSC_INT)          m *= sizeof(PetscInt);
340:   else if (type == PETSC_SCALAR)  m *= sizeof(PetscScalar);
341:   else if (type == PETSC_DOUBLE)  m *= sizeof(double);
342:   else if (type == PETSC_FLOAT)   m *= sizeof(float);
343:   else if (type == PETSC_SHORT)   m *= sizeof(short);
344:   else if (type == PETSC_CHAR)    m *= sizeof(char);
345:   else if (type == PETSC_ENUM)    m *= sizeof(PetscEnum);
346:   else if (type == PETSC_BOOL)   m *= sizeof(PetscBool);
347:   else if (type == PETSC_BIT_LOGICAL) m = PetscBTLength(m)*sizeof(char);
348:   else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown type");

350: #if !defined(PETSC_WORDS_BIGENDIAN)
351:   PetscByteSwap(ptmp,type,n);
352: #endif

354:   while (m) {
355:     wsize = (m < maxblock) ? m : maxblock;
356:     err = write(fd,pp,wsize);
357:     if (err < 0 && errno == EINTR) continue;
358:     if (err != wsize) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_WRITE,"Error writing to file.");
359:     m -= wsize;
360:     pp += wsize;
361:   }

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

373: /*@C
374:    PetscBinaryOpen - Opens a PETSc binary file.

376:    Not Collective

378:    Input Parameters:
379: +  name - filename
380: -  type - type of binary file, one of FILE_MODE_READ, FILE_MODE_APPEND, FILE_MODE_WRITE

382:    Output Parameter:
383: .  fd - the file

385:    Level: advanced

387:   Concepts: files^opening binary
388:   Concepts: binary files^opening

390:    Notes: Files access with PetscBinaryRead() and PetscBinaryWrite() are ALWAYS written in
391:    big-endian format. This means the file can be accessed using PetscBinaryOpen() and
392:    PetscBinaryRead() and PetscBinaryWrite() on any machine.

394: .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscFileMode, PetscViewerFileSetMode(), PetscViewerBinaryGetDescriptor(), 
395:           PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek()

397: @*/
398: PetscErrorCode  PetscBinaryOpen(const char name[],PetscFileMode mode,int *fd)
399: {
401: #if defined(PETSC_HAVE_O_BINARY) 
402:   if (mode == FILE_MODE_WRITE) {
403:     if ((*fd = open(name,O_WRONLY|O_CREAT|O_TRUNC|O_BINARY,0666)) == -1) {
404:       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot create file for writing: %s",name);
405:     }
406:   } else if (mode == FILE_MODE_READ) {
407:     if ((*fd = open(name,O_RDONLY|O_BINARY,0)) == -1) {
408:       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file for reading: %s",name);
409:     }
410:   } else if (mode == FILE_MODE_APPEND) {
411:     if ((*fd = open(name,O_WRONLY|O_BINARY,0)) == -1) {
412:       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file for writing: %s",name);
413:     }
414: #else
415:   if (mode == FILE_MODE_WRITE) {
416:     if ((*fd = creat(name,0666)) == -1) {
417:       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot create file for writing: %s",name);
418:     }
419:   } else if (mode == FILE_MODE_READ) {
420:     if ((*fd = open(name,O_RDONLY,0)) == -1) {
421:       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file for reading: %s",name);
422:     }
423:   }
424:   else if (mode == FILE_MODE_APPEND) {
425:     if ((*fd = open(name,O_WRONLY,0)) == -1) {
426:       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file for writing: %s",name);
427:     }
428: #endif
429:   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown file mode");
430:   return(0);
431: }

435: /*@
436:    PetscBinaryClose - Closes a PETSc binary file.

438:    Not Collective

440:    Output Parameter:
441: .  fd - the file

443:    Level: advanced

445: .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
446:           PetscBinarySynchronizedSeek()
447: @*/
448: PetscErrorCode  PetscBinaryClose(int fd)
449: {
451:   close(fd);
452:   return(0);
453: }


458: /*@
459:    PetscBinarySeek - Moves the file pointer on a PETSc binary file.

461:    Not Collective

463:    Input Parameters:
464: +  fd - the file
465: .  off - number of bytes to move. Use PETSC_BINARY_INT_SIZE, PETSC_BINARY_SCALAR_SIZE,
466:             etc. in your calculation rather than sizeof() to compute byte lengths.
467: -  whence - if PETSC_BINARY_SEEK_SET then off is an absolute location in the file
468:             if PETSC_BINARY_SEEK_CUR then off is an offset from the current location
469:             if PETSC_BINARY_SEEK_END then off is an offset from the end of file

471:    Output Parameter:
472: .   offset - new offset in file

474:    Level: developer

476:    Notes: 
477:    Integers are stored on the file as 32 long, regardless of whether
478:    they are stored in the machine as 32 or 64, this means the same
479:    binary file may be read on any machine. Hence you CANNOT use sizeof()
480:    to determine the offset or location.

482:    Concepts: files^binary seeking
483:    Concepts: binary files^seeking

485: .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
486:           PetscBinarySynchronizedSeek()
487: @*/
488: PetscErrorCode  PetscBinarySeek(int fd,off_t off,PetscBinarySeekType whence,off_t *offset)
489: {
490:   int iwhence = 0;

493:   if (whence == PETSC_BINARY_SEEK_SET) {
494:     iwhence = SEEK_SET;
495:   } else if (whence == PETSC_BINARY_SEEK_CUR) {
496:     iwhence = SEEK_CUR;
497:   } else if (whence == PETSC_BINARY_SEEK_END) {
498:     iwhence = SEEK_END;
499:   } else {
500:     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown seek location");
501:   }
502: #if defined(PETSC_HAVE_LSEEK)
503:   *offset = lseek(fd,off,iwhence);
504: #elif defined(PETSC_HAVE__LSEEK)
505:   *offset = _lseek(fd,(long)off,iwhence);
506: #else
507:   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS,"System does not have a way of seeking on a file");
508: #endif
509:   return(0);
510: }

514: /*@C
515:    PetscBinarySynchronizedRead - Reads from a binary file.

517:    Collective on MPI_Comm

519:    Input Parameters:
520: +  comm - the MPI communicator 
521: .  fd - the file
522: .  n  - the number of items to read 
523: -  type - the type of items to read (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)

525:    Output Parameters:
526: .  p - the buffer

528:    Options Database Key:
529: .   -binary_longints - indicates the file was generated on a Cray vector 
530:          machine (not the T3E/D) and the ints are stored as 64 bit 
531:          quantities, otherwise they are stored as 32 bit

533:    Level: developer

535:    Notes: 
536:    Does a PetscBinaryRead() followed by an MPI_Bcast()

538:    PetscBinarySynchronizedRead() uses byte swapping to work on all machines.
539:    Integers are stored on the file as 32 long, regardless of whether
540:    they are stored in the machine as 32 or 64, this means the same
541:    binary file may be read on any machine.

543:    Concepts: files^synchronized reading of binary files
544:    Concepts: binary files^reading, synchronized

546: .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscBinaryRead(), PetscBinarySynchronizedWrite(), 
547:           PetscBinarySynchronizedSeek()
548: @*/
549: PetscErrorCode  PetscBinarySynchronizedRead(MPI_Comm comm,int fd,void *p,PetscInt n,PetscDataType type)
550: {
552:   PetscMPIInt    rank;
553:   MPI_Datatype   mtype;

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

567: /*@C
568:    PetscBinarySynchronizedWrite - writes to a binary file.

570:    Collective on MPI_Comm

572:    Input Parameters:
573: +  comm - the MPI communicator 
574: .  fd - the file
575: .  n  - the number of items to write
576: .  p - the buffer
577: .  istemp - the buffer may be changed
578: -  type - the type of items to write (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)

580:    Level: developer

582:    Notes: 
583:    Process 0 does a PetscBinaryWrite()

585:    PetscBinarySynchronizedWrite() uses byte swapping to work on all machines.
586:    Integers are stored on the file as 32 long, regardless of whether
587:    they are stored in the machine as 32 or 64, this means the same
588:    binary file may be read on any machine.

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

592:    WARNING: This is NOT like PetscSynchronizedFPrintf()! This routine ignores calls on all but process 0,
593:    while PetscSynchronizedFPrintf() has all processes print their strings in order.

595:    Concepts: files^synchronized writing of binary files
596:    Concepts: binary files^reading, synchronized

598: .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscBinaryRead(), PetscBinarySynchronizedRead(),
599:           PetscBinarySynchronizedSeek()
600: @*/
601: PetscErrorCode  PetscBinarySynchronizedWrite(MPI_Comm comm,int fd,void *p,PetscInt n,PetscDataType type,PetscBool  istemp)
602: {
604:   PetscMPIInt    rank;

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

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


620:    Input Parameters:
621: +  fd - the file
622: .  whence - if PETSC_BINARY_SEEK_SET then size is an absolute location in the file
623:             if PETSC_BINARY_SEEK_CUR then size is offset from current location
624:             if PETSC_BINARY_SEEK_END then size is offset from end of file
625: -  off    - number of bytes to move. Use PETSC_BINARY_INT_SIZE, PETSC_BINARY_SCALAR_SIZE,
626:             etc. in your calculation rather than sizeof() to compute byte lengths.

628:    Output Parameter:
629: .   offset - new offset in file

631:    Level: developer

633:    Notes: 
634:    Integers are stored on the file as 32 long, regardless of whether
635:    they are stored in the machine as 32 or 64, this means the same
636:    binary file may be read on any machine. Hence you CANNOT use sizeof()
637:    to determine the offset or location.

639:    Concepts: binary files^seeking
640:    Concepts: files^seeking in binary 

642: .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
643:           PetscBinarySynchronizedSeek()
644: @*/
645: PetscErrorCode  PetscBinarySynchronizedSeek(MPI_Comm comm,int fd,off_t off,PetscBinarySeekType whence,off_t *offset)
646: {
648:   PetscMPIInt    rank;

651:   MPI_Comm_rank(comm,&rank);
652:   if (!rank) {
653:     PetscBinarySeek(fd,off,whence,offset);
654:   }
655:   return(0);
656: }

658: #if defined(PETSC_HAVE_MPIIO)
659: #if !defined(PETSC_WORDS_BIGENDIAN)

661: #if defined(PETSC_USE_PETSC_MPI_EXTERNAL32)
662: EXTERN_C_BEGIN
663: /*
664:       MPICH does not provide the external32 representation for MPI_File_set_view() so we need to provide the functions.
665:     These are set into MPI in PetscInitialize() via MPI_Register_datarep()

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

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

671: */
672: PetscMPIInt PetscDataRep_extent_fn(MPI_Datatype datatype,MPI_Aint *file_extent,void *extra_state)
673: {
674:   MPI_Aint    ub;
675:   PetscMPIInt ierr;
676: 
677:   MPI_Type_get_extent(datatype,&ub,file_extent);
678:   return ierr;
679: }

681: PetscMPIInt PetscDataRep_read_conv_fn(void *userbuf, MPI_Datatype datatype,PetscMPIInt count,void *filebuf, MPI_Offset position,void *extra_state)
682: {
683:   PetscDataType pdtype;
684:   PetscMPIInt   ierr;
685:   size_t        dsize;
686: 
687:   PetscMPIDataTypeToPetscDataType(datatype,&pdtype);
688:   PetscDataTypeGetSize(pdtype,&dsize);

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

693:   PetscMemcpy(userbuf,filebuf,count*dsize);
694:   PetscByteSwap(userbuf,pdtype,count);
695:   return ierr;
696: }

698: PetscMPIInt PetscDataRep_write_conv_fn(void *userbuf, MPI_Datatype datatype,PetscMPIInt count,void *filebuf, MPI_Offset position,void *extra_state)
699: {
700:   PetscDataType pdtype;
701:   PetscMPIInt   ierr;
702:   size_t        dsize;
703: 
704:   PetscMPIDataTypeToPetscDataType(datatype,&pdtype);
705:   PetscDataTypeGetSize(pdtype,&dsize);

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

710:   PetscMemcpy(filebuf,userbuf,count*dsize);
711:   PetscByteSwap(filebuf,pdtype,count);
712:   return ierr;
713: }
714: EXTERN_C_END
715: #endif

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

725:   PetscMPIDataTypeToPetscDataType(dtype,&pdtype);
726:   PetscByteSwap(data,pdtype,cnt);
727:   MPI_File_write_all(fd,data,cnt,dtype,status);
728:   PetscByteSwap(data,pdtype,cnt);
729:   return(0);
730: }

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

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