Actual source code: sysio.c
petsc-3.7.1 2016-05-15
Report Typos and Errors

      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: const char *const PetscFileModes[] = {"READ","WRITE","APPEND","UPDATE","APPEND_UPDATE","PetscFileMode","PETSC_FILE_",0};

     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;

     33:   for (j=0; j<n; j++) {
     34:     ptr1 = (char*)(buff + j);
     35:     for (i=0; i<(PetscInt)sizeof(PetscEnum); i++) ptr2[i] = ptr1[sizeof(PetscEnum)-1-i];
     36:     for (i=0; i<(PetscInt)sizeof(PetscEnum); i++) ptr1[i] = ptr2[i];
     37:   }
     38:   return(0);
     39: }

     43: /*
     44:   PetscByteSwapBool - Swap bytes in a  PETSc Bool

     46: */
     47: PetscErrorCode  PetscByteSwapBool(PetscBool *buff,PetscInt n)
     48: {
     49:   PetscInt  i,j;
     50:   PetscBool tmp = PETSC_FALSE;
     51:   char      *ptr1,*ptr2 = (char*)&tmp;

     54:   for (j=0; j<n; j++) {
     55:     ptr1 = (char*)(buff + j);
     56:     for (i=0; i<(PetscInt)sizeof(PetscBool); i++) ptr2[i] = ptr1[sizeof(PetscBool)-1-i];
     57:     for (i=0; i<(PetscInt)sizeof(PetscBool); i++) ptr1[i] = ptr2[i];
     58:   }
     59:   return(0);
     60: }

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

     67: */
     68: PetscErrorCode  PetscByteSwapInt(PetscInt *buff,PetscInt n)
     69: {
     70:   PetscInt i,j,tmp = 0;
     71:   char     *ptr1,*ptr2 = (char*)&tmp;

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

     94:   for (j=0; j<n; j++) {
     95:     ptr1 = (char*)(buff + j);
     96:     for (i=0; i<(PetscInt) sizeof(short); i++) ptr2[i] = ptr1[sizeof(short)-1-i];
     97:     for (i=0; i<(PetscInt) sizeof(short); i++) ptr1[i] = ptr2[i];
     98:   }
     99:   return(0);
    100: }
    101: /* --------------------------------------------------------- */
    104: /*
    105:   PetscByteSwapScalar - Swap bytes in a double
    106:   Complex is dealt with as if array of double twice as long.
    107: */
    108: PetscErrorCode  PetscByteSwapScalar(PetscScalar *buff,PetscInt n)
    109: {
    110:   PetscInt  i,j;
    111:   PetscReal tmp,*buff1 = (PetscReal*)buff;
    112:   char      *ptr1,*ptr2 = (char*)&tmp;

    115: #if defined(PETSC_USE_COMPLEX)
    116:   n *= 2;
    117: #endif
    118:   for (j=0; j<n; j++) {
    119:     ptr1 = (char*)(buff1 + j);
    120:     for (i=0; i<(PetscInt) sizeof(PetscReal); i++) ptr2[i] = ptr1[sizeof(PetscReal)-1-i];
    121:     for (i=0; i<(PetscInt) sizeof(PetscReal); i++) ptr1[i] = ptr2[i];
    122:   }
    123:   return(0);
    124: }
    125: /* --------------------------------------------------------- */
    128: /*
    129:   PetscByteSwapDouble - Swap bytes in a double
    130: */
    131: PetscErrorCode  PetscByteSwapDouble(double *buff,PetscInt n)
    132: {
    133:   PetscInt i,j;
    134:   double   tmp,*buff1 = (double*)buff;
    135:   char     *ptr1,*ptr2 = (char*)&tmp;

    138:   for (j=0; j<n; j++) {
    139:     ptr1 = (char*)(buff1 + j);
    140:     for (i=0; i<(PetscInt) sizeof(double); i++) ptr2[i] = ptr1[sizeof(double)-1-i];
    141:     for (i=0; i<(PetscInt) sizeof(double); i++) ptr1[i] = ptr2[i];
    142:   }
    143:   return(0);
    144: }

    148: /*
    149:   PetscByteSwapFloat - Swap bytes in a float
    150: */
    151: PetscErrorCode PetscByteSwapFloat(float *buff,PetscInt n)
    152: {
    153:   PetscInt i,j;
    154:   float    tmp,*buff1 = (float*)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(float); i++) ptr2[i] = ptr1[sizeof(float)-1-i];
    161:     for (i=0; i<(PetscInt) sizeof(float); i++) ptr1[i] = ptr2[i];
    162:   }
    163:   return(0);
    164: }

    168: PetscErrorCode PetscByteSwap(void *data,PetscDataType pdtype,PetscInt count)
    169: {

    173:   if      (pdtype == PETSC_INT)    {PetscByteSwapInt((PetscInt*)data,count);}
    174:   else if (pdtype == PETSC_ENUM)   {PetscByteSwapEnum((PetscEnum*)data,count);}
    175:   else if (pdtype == PETSC_BOOL)   {PetscByteSwapBool((PetscBool*)data,count);}
    176:   else if (pdtype == PETSC_SCALAR) {PetscByteSwapScalar((PetscScalar*)data,count);}
    177:   else if (pdtype == PETSC_DOUBLE) {PetscByteSwapDouble((double*)data,count);}
    178:   else if (pdtype == PETSC_FLOAT)  {PetscByteSwapFloat((float*)data,count);}
    179:   else if (pdtype == PETSC_SHORT)  {PetscByteSwapShort((short*)data,count);}
    180:   return(0);
    181: }

    183: /* --------------------------------------------------------- */
    186: /*@
    187:    PetscBinaryRead - Reads from a binary file.

    189:    Not Collective

    191:    Input Parameters:
    192: +  fd - the file
    193: .  n  - the number of items to read
    194: -  type - the type of items to read (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)

    196:    Output Parameters:
    197: .  p - the buffer

    201:    Level: developer

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

    211:    Concepts: files^reading binary
    212:    Concepts: binary files^reading

    214: .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscViewerBinaryGetDescriptor(), PetscBinarySynchronizedWrite(),
    215:           PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek()
    216: @*/
    217: PetscErrorCode  PetscBinaryRead(int fd,void *p,PetscInt n,PetscDataType type)
    218: {
    219:   int               wsize,err;
    220:   size_t            m = (size_t) n,maxblock = 65536;
    221:   char              *pp = (char*)p;
    222: #if defined(PETSC_USE_REAL___FLOAT128)
    223:   PetscBool         readdouble = PETSC_FALSE;
    224:   double            *ppp;
    225: #endif
    226: #if !defined(PETSC_WORDS_BIGENDIAN) || defined(PETSC_USE_REAL___FLOAT128)
    227:   PetscErrorCode    ierr;
    228: #endif
    229: #if !defined(PETSC_WORDS_BIGENDIAN)
    230:   void              *ptmp = p;
    231: #endif
    232:   char              *fname = NULL;

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

    238:   if (type == PETSC_FUNCTION) {
    239:     m            = 64;
    240:     type         = PETSC_CHAR;
    241:     fname        = (char*) malloc(m*sizeof(char));
    242:     if (!fname) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Cannot allocate space for function name");
    243:     pp           = (char*)fname;
    244: #if !defined(PETSC_WORDS_BIGENDIAN)
    245:     ptmp         = (void*)fname;
    246: #endif
    247:   }

    249:   if (type == PETSC_INT)          m *= sizeof(PetscInt);
    250:   else if (type == PETSC_SCALAR)  m *= sizeof(PetscScalar);
    251:   else if (type == PETSC_DOUBLE)  m *= sizeof(double);
    252:   else if (type == PETSC_FLOAT)   m *= sizeof(float);
    253:   else if (type == PETSC_SHORT)   m *= sizeof(short);
    254:   else if (type == PETSC_CHAR)    m *= sizeof(char);
    255:   else if (type == PETSC_ENUM)    m *= sizeof(PetscEnum);
    256:   else if (type == PETSC_BOOL)   m *= sizeof(PetscBool);
    257:   else if (type == PETSC_BIT_LOGICAL) m  = PetscBTLength(m)*sizeof(char);
    258:   else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown type");

    260: #if defined(PETSC_USE_REAL___FLOAT128)
    261:   PetscOptionsGetBool(NULL,NULL,"-binary_read_double",&readdouble,NULL);
    262:   /* If using __float128 precision we still read in doubles from file */
    263:   if (type == PETSC_SCALAR && readdouble) {
    264:     m    = m/2;
    265:     PetscMalloc1(n,&ppp);
    266:     pp   = (char*)ppp;
    267:   }
    268: #endif

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

    280: #if defined(PETSC_USE_REAL___FLOAT128)
    281:   if (type == PETSC_SCALAR && readdouble) {
    282:     PetscScalar *pv = (PetscScalar*) p;
    283:     PetscInt    i;
    284: #if !defined(PETSC_WORDS_BIGENDIAN)
    285:     PetscByteSwapDouble(ppp,n);
    286: #endif
    287:     for (i=0; i<n; i++) pv[i] = ppp[i];
    288:     PetscFree(ppp);
    289:     return(0);
    290:   }
    291: #endif

    293: #if !defined(PETSC_WORDS_BIGENDIAN)
    294:   PetscByteSwap(ptmp,type,n);
    295: #endif

    297:   if (type == PETSC_FUNCTION) {
    298: #if defined(PETSC_SERIALIZE_FUNCTIONS)
    299:     PetscDLSym(NULL,fname,(void**)p);
    300: #else
    301:     *(void**)p = NULL;
    302: #endif
    303:     free(fname);
    304:   }
    305:   return(0);
    306: }
    307: /* --------------------------------------------------------- */
    310: /*@
    311:    PetscBinaryWrite - Writes to a binary file.

    313:    Not Collective

    315:    Input Parameters:
    316: +  fd     - the file
    317: .  p      - the buffer
    318: .  n      - the number of items to write
    319: .  type   - the type of items to read (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)
    320: -  istemp - PETSC_FALSE if buffer data should be preserved, PETSC_TRUE otherwise.

    322:    Level: advanced

    324:    Notes:
    325:    PetscBinaryWrite() uses byte swapping to work on all machines; the files
    326:    are written using big-endian ordering to the file. On small-endian machines the numbers
    327:    are converted to the big-endian format when they are written to disk.
    328:    When PETSc is ./configure with --with-64bit-indices the integers are written to the
    329:    file as 64 bit integers, this means they can only be read back in when the option --with-64bit-indices
    330:    is used.

    332:    If running with __float128 precision the output is in __float128 unless one uses the -binary_read_double option

    334:    The Buffer p should be read-write buffer, and not static data.
    335:    This way, byte-swapping is done in-place, and then the buffer is
    336:    written to the file.

    338:    This routine restores the original contents of the buffer, after
    339:    it is written to the file. This is done by byte-swapping in-place
    340:    the second time. If the flag istemp is set to PETSC_TRUE, the second
    341:    byte-swapping operation is not done, thus saving some computation,
    342:    but the buffer is left corrupted.

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

    346:    Concepts: files^writing binary
    347:    Concepts: binary files^writing

    349: .seealso: PetscBinaryRead(), PetscBinaryOpen(), PetscBinaryClose(), PetscViewerBinaryGetDescriptor(), PetscBinarySynchronizedWrite(),
    350:           PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek()
    351: @*/
    352: PetscErrorCode  PetscBinaryWrite(int fd,void *p,PetscInt n,PetscDataType type,PetscBool  istemp)
    353: {
    354:   char           *pp = (char*)p;
    355:   int            err,wsize;
    356:   size_t         m = (size_t)n,maxblock=65536;
    358: #if !defined(PETSC_WORDS_BIGENDIAN)
    359:   void           *ptmp = p;
    360: #endif
    361:   char           *fname = NULL;
    362: #if defined(PETSC_USE_REAL___FLOAT128)
    363:   PetscBool      writedouble = PETSC_FALSE;
    364:   double         *ppp;
    365:   PetscReal      *pv;
    366:   PetscInt       i;
    367: #endif

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

    373:   if (type == PETSC_FUNCTION) {
    374: #if defined(PETSC_SERIALIZE_FUNCTIONS)
    375:     const char *fnametmp;
    376: #endif
    377:     m     = 64;
    378:     fname = (char*)malloc(m*sizeof(char));
    379:     if (!fname) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Cannot allocate space for function name");
    380: #if defined(PETSC_SERIALIZE_FUNCTIONS)
    381:     if (n > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Can only binary view a single function at a time");
    382:     PetscFPTFind(*(void**)p,&fnametmp);
    383:     PetscStrncpy(fname,fnametmp,m);
    384: #else
    385:     PetscStrncpy(fname,"",m);
    386: #endif
    387:     type = PETSC_CHAR;
    388:     pp   = (char*)fname;
    389: #if !defined(PETSC_WORDS_BIGENDIAN)
    390:     ptmp = (void*)fname;
    391: #endif
    392:   }

    394: #if defined(PETSC_USE_REAL___FLOAT128)
    395:   PetscOptionsGetBool(NULL,NULL,"-binary_write_double",&writedouble,NULL);
    396:   /* If using __float128 precision we still write in doubles to file */
    397:   if (type == PETSC_SCALAR && writedouble) {
    398:     m    = m/2;
    399:     PetscMalloc1(n,&ppp);
    400:     pv = (PetscReal*)pp;
    401:     for (i=0; i<n; i++) {
    402:       ppp[i] = (double) pv[i];
    403:     }
    404:     pp   = (char*)ppp;
    405:     ptmp = (char*)ppp;
    406:   }
    407: #endif

    409:   if (type == PETSC_INT)          m *= sizeof(PetscInt);
    410:   else if (type == PETSC_SCALAR)  m *= sizeof(PetscScalar);
    411:   else if (type == PETSC_DOUBLE)  m *= sizeof(double);
    412:   else if (type == PETSC_FLOAT)   m *= sizeof(float);
    413:   else if (type == PETSC_SHORT)   m *= sizeof(short);
    414:   else if (type == PETSC_CHAR)    m *= sizeof(char);
    415:   else if (type == PETSC_ENUM)    m *= sizeof(PetscEnum);
    416:   else if (type == PETSC_BOOL)   m *= sizeof(PetscBool);
    417:   else if (type == PETSC_BIT_LOGICAL) m = PetscBTLength(m)*sizeof(char);
    418:   else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown type");

    420: #if !defined(PETSC_WORDS_BIGENDIAN)
    421:   PetscByteSwap(ptmp,type,n);
    422: #endif

    424:   while (m) {
    425:     wsize = (m < maxblock) ? m : maxblock;
    426:     err   = write(fd,pp,wsize);
    427:     if (err < 0 && errno == EINTR) continue;
    428:     if (err != wsize) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_FILE_WRITE,"Error writing to file total size %d err %d wsize %d",(int)n,(int)err,(int)wsize);
    429:     m  -= wsize;
    430:     pp += wsize;
    431:   }

    433: #if !defined(PETSC_WORDS_BIGENDIAN)
    434:   if (!istemp) {
    435:     PetscByteSwap(ptmp,type,n);
    436:   }
    437: #endif
    438:   if (type == PETSC_FUNCTION) {
    439:     free(fname);
    440:   }
    441: #if defined(PETSC_USE_REAL___FLOAT128)
    442:   if (type == PETSC_SCALAR && writedouble) {
    443:     PetscFree(ppp);
    444:   }
    445: #endif
    446:   return(0);
    447: }

    451: /*@C
    452:    PetscBinaryOpen - Opens a PETSc binary file.

    454:    Not Collective

    456:    Input Parameters:
    457: +  name - filename
    458: -  type - type of binary file, one of FILE_MODE_READ, FILE_MODE_APPEND, FILE_MODE_WRITE

    460:    Output Parameter:
    461: .  fd - the file

    463:    Level: advanced

    465:   Concepts: files^opening binary
    466:   Concepts: binary files^opening

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

    472: .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscFileMode, PetscViewerFileSetMode(), PetscViewerBinaryGetDescriptor(),
    473:           PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek()

    475: @*/
    476: PetscErrorCode  PetscBinaryOpen(const char name[],PetscFileMode mode,int *fd)
    477: {
    479: #if defined(PETSC_HAVE_O_BINARY)
    480:   if (mode == FILE_MODE_WRITE) {
    481:     if ((*fd = open(name,O_WRONLY|O_CREAT|O_TRUNC|O_BINARY,0666)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot create file for writing: %s",name);
    482:   } else if (mode == FILE_MODE_READ) {
    483:     if ((*fd = open(name,O_RDONLY|O_BINARY,0)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file for reading: %s",name);
    484:   } else if (mode == FILE_MODE_APPEND) {
    485:     if ((*fd = open(name,O_WRONLY|O_BINARY,0)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file for writing: %s",name);
    486: #else
    487:   if (mode == FILE_MODE_WRITE) {
    488:     if ((*fd = creat(name,0666)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot create file for writing: %s",name);
    489:   } else if (mode == FILE_MODE_READ) {
    490:     if ((*fd = open(name,O_RDONLY,0)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file for reading: %s",name);
    491:   }
    492:   else if (mode == FILE_MODE_APPEND) {
    493:     if ((*fd = open(name,O_WRONLY,0)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file for writing: %s",name);
    494: #endif
    495:   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown file mode");
    496:   return(0);
    497: }

    501: /*@
    502:    PetscBinaryClose - Closes a PETSc binary file.

    504:    Not Collective

    506:    Output Parameter:
    507: .  fd - the file

    509:    Level: advanced

    511: .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
    512:           PetscBinarySynchronizedSeek()
    513: @*/
    514: PetscErrorCode  PetscBinaryClose(int fd)
    515: {
    517:   close(fd);
    518:   return(0);
    519: }

    524: /*@
    525:    PetscBinarySeek - Moves the file pointer on a PETSc binary file.

    527:    Not Collective

    529:    Input Parameters:
    530: +  fd - the file
    531: .  off - number of bytes to move. Use PETSC_BINARY_INT_SIZE, PETSC_BINARY_SCALAR_SIZE,
    532:             etc. in your calculation rather than sizeof() to compute byte lengths.
    533: -  whence - if PETSC_BINARY_SEEK_SET then off is an absolute location in the file
    534:             if PETSC_BINARY_SEEK_CUR then off is an offset from the current location
    535:             if PETSC_BINARY_SEEK_END then off is an offset from the end of file

    537:    Output Parameter:
    538: .   offset - new offset in file

    540:    Level: developer

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

    548:    Concepts: files^binary seeking
    549:    Concepts: binary files^seeking

    551: .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
    552:           PetscBinarySynchronizedSeek()
    553: @*/
    554: PetscErrorCode  PetscBinarySeek(int fd,off_t off,PetscBinarySeekType whence,off_t *offset)
    555: {
    556:   int iwhence = 0;

    559:   if (whence == PETSC_BINARY_SEEK_SET) iwhence = SEEK_SET;
    560:   else if (whence == PETSC_BINARY_SEEK_CUR) iwhence = SEEK_CUR;
    561:   else if (whence == PETSC_BINARY_SEEK_END) iwhence = SEEK_END;
    562:   else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown seek location");
    563: #if defined(PETSC_HAVE_LSEEK)
    564:   *offset = lseek(fd,off,iwhence);
    565: #elif defined(PETSC_HAVE__LSEEK)
    566:   *offset = _lseek(fd,(long)off,iwhence);
    567: #else
    568:   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS,"System does not have a way of seeking on a file");
    569: #endif
    570:   return(0);
    571: }

    575: /*@C
    576:    PetscBinarySynchronizedRead - Reads from a binary file.

    578:    Collective on MPI_Comm

    580:    Input Parameters:
    581: +  comm - the MPI communicator
    582: .  fd - the file
    583: .  n  - the number of items to read
    584: -  type - the type of items to read (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)

    586:    Output Parameters:
    587: .  p - the buffer

    589:    Level: developer

    591:    Notes:
    592:    Does a PetscBinaryRead() followed by an MPI_Bcast()

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

    599:    Concepts: files^synchronized reading of binary files
    600:    Concepts: binary files^reading, synchronized

    602: .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscBinaryRead(), PetscBinarySynchronizedWrite(),
    603:           PetscBinarySynchronizedSeek()
    604: @*/
    605: PetscErrorCode  PetscBinarySynchronizedRead(MPI_Comm comm,int fd,void *p,PetscInt n,PetscDataType type)
    606: {
    608:   PetscMPIInt    rank;
    609:   MPI_Datatype   mtype;
    610:   char           *fname = NULL;
    611:   void           *ptmp = NULL;

    614:   if (type == PETSC_FUNCTION) {
    615:     n            = 64;
    616:     type         = PETSC_CHAR;
    617:     ptmp         = p;
    618:     fname        = (char*)malloc(n*sizeof(char));
    619:     if (!fname) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Cannot allocate space for function name");
    620:     p            = (void*)fname;
    621:   }

    623:   MPI_Comm_rank(comm,&rank);
    624:   if (!rank) {
    625:     PetscBinaryRead(fd,p,n,type);
    626:   }
    627:   PetscDataTypeToMPIDataType(type,&mtype);
    628:   MPI_Bcast(p,n,mtype,0,comm);

    630:   if (type == PETSC_FUNCTION) {
    631: #if defined(PETSC_SERIALIZE_FUNCTIONS)
    632:     PetscDLLibrarySym(PETSC_COMM_SELF,&PetscDLLibrariesLoaded,NULL,fname,(void**)ptmp);
    633: #else
    634:     *(void**)ptmp = NULL;
    635: #endif
    636:     free(fname);
    637:   }
    638:   return(0);
    639: }

    643: /*@C
    644:    PetscBinarySynchronizedWrite - writes to a binary file.

    646:    Collective on MPI_Comm

    648:    Input Parameters:
    649: +  comm - the MPI communicator
    650: .  fd - the file
    651: .  n  - the number of items to write
    652: .  p - the buffer
    653: .  istemp - the buffer may be changed
    654: -  type - the type of items to write (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)

    656:    Level: developer

    658:    Notes:
    659:    Process 0 does a PetscBinaryWrite()

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

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

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

    671:    Concepts: files^synchronized writing of binary files
    672:    Concepts: binary files^reading, synchronized

    674: .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscBinaryRead(), PetscBinarySynchronizedRead(),
    675:           PetscBinarySynchronizedSeek()
    676: @*/
    677: PetscErrorCode  PetscBinarySynchronizedWrite(MPI_Comm comm,int fd,void *p,PetscInt n,PetscDataType type,PetscBool istemp)
    678: {
    680:   PetscMPIInt    rank;

    683:   MPI_Comm_rank(comm,&rank);
    684:   if (!rank) {
    685:     PetscBinaryWrite(fd,p,n,type,istemp);
    686:   }
    687:   return(0);
    688: }

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

    696:    Input Parameters:
    697: +  fd - the file
    698: .  whence - if PETSC_BINARY_SEEK_SET then size is an absolute location in the file
    699:             if PETSC_BINARY_SEEK_CUR then size is offset from current location
    700:             if PETSC_BINARY_SEEK_END then size is offset from end of file
    701: -  off    - number of bytes to move. Use PETSC_BINARY_INT_SIZE, PETSC_BINARY_SCALAR_SIZE,
    702:             etc. in your calculation rather than sizeof() to compute byte lengths.

    704:    Output Parameter:
    705: .   offset - new offset in file

    707:    Level: developer

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

    715:    Concepts: binary files^seeking
    716:    Concepts: files^seeking in binary

    718: .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
    719:           PetscBinarySynchronizedSeek()
    720: @*/
    721: PetscErrorCode  PetscBinarySynchronizedSeek(MPI_Comm comm,int fd,off_t off,PetscBinarySeekType whence,off_t *offset)
    722: {
    724:   PetscMPIInt    rank;

    727:   MPI_Comm_rank(comm,&rank);
    728:   if (!rank) {
    729:     PetscBinarySeek(fd,off,whence,offset);
    730:   }
    731:   return(0);
    732: }

    734: #if defined(PETSC_HAVE_MPIIO)
    735: #if !defined(PETSC_WORDS_BIGENDIAN)

    737: #if defined(PETSC_USE_PETSC_MPI_EXTERNAL32)
    738: /*
    739:       MPICH does not provide the external32 representation for MPI_File_set_view() so we need to provide the functions.
    740:     These are set into MPI in PetscInitialize() via MPI_Register_datarep()

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

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

    746: */
    747: PETSC_EXTERN PetscMPIInt PetscDataRep_extent_fn(MPI_Datatype datatype,MPI_Aint *file_extent,void *extra_state)
    748: {
    749:   MPI_Aint    ub;
    750:   PetscMPIInt ierr;

    752:   MPI_Type_get_extent(datatype,&ub,file_extent);
    753:   return ierr;
    754: }

    756: PETSC_EXTERN PetscMPIInt PetscDataRep_read_conv_fn(void *userbuf, MPI_Datatype datatype,PetscMPIInt count,void *filebuf, MPI_Offset position,void *extra_state)
    757: {
    758:   PetscDataType pdtype;
    759:   PetscMPIInt   ierr;
    760:   size_t        dsize;

    762:   PetscMPIDataTypeToPetscDataType(datatype,&pdtype);
    763:   PetscDataTypeGetSize(pdtype,&dsize);

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

    768:   PetscMemcpy(userbuf,filebuf,count*dsize);
    769:   PetscByteSwap(userbuf,pdtype,count);
    770:   return ierr;
    771: }

    773: PetscMPIInt PetscDataRep_write_conv_fn(void *userbuf, MPI_Datatype datatype,PetscMPIInt count,void *filebuf, MPI_Offset position,void *extra_state)
    774: {
    775:   PetscDataType pdtype;
    776:   PetscMPIInt   ierr;
    777:   size_t        dsize;

    779:   PetscMPIDataTypeToPetscDataType(datatype,&pdtype);
    780:   PetscDataTypeGetSize(pdtype,&dsize);

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

    785:   PetscMemcpy(filebuf,userbuf,count*dsize);
    786:   PetscByteSwap(filebuf,pdtype,count);
    787:   return ierr;
    788: }
    789: #endif

    793: PetscErrorCode MPIU_File_write_all(MPI_File fd,void *data,PetscMPIInt cnt,MPI_Datatype dtype,MPI_Status *status)
    794: {
    796:   PetscDataType  pdtype;

    799:   PetscMPIDataTypeToPetscDataType(dtype,&pdtype);
    800:   PetscByteSwap(data,pdtype,cnt);
    801:   MPI_File_write_all(fd,data,cnt,dtype,status);
    802:   PetscByteSwap(data,pdtype,cnt);
    803:   return(0);
    804: }

    808: PetscErrorCode MPIU_File_read_all(MPI_File fd,void *data,PetscMPIInt cnt,MPI_Datatype dtype,MPI_Status *status)
    809: {
    811:   PetscDataType  pdtype;

    814:   PetscMPIDataTypeToPetscDataType(dtype,&pdtype);
    815:   MPI_File_read_all(fd,data,cnt,dtype,status);
    816:   PetscByteSwap(data,pdtype,cnt);
    817:   return(0);
    818: }
    819: #endif
    820: #endif