Date: 2015-10-02T21:59:54+00:00

Actual source code: sysio.c
petsc-3.6.2 2015-10-02
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,"-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:    The Buffer p should be read-write buffer, and not static data.
    333:    This way, byte-swapping is done in-place, and then the buffer is
    334:    written to the file.

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

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

    344:    Concepts: files^writing binary
    345:    Concepts: binary files^writing

    347: .seealso: PetscBinaryRead(), PetscBinaryOpen(), PetscBinaryClose(), PetscViewerBinaryGetDescriptor(), PetscBinarySynchronizedWrite(),
    348:           PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek()
    349: @*/
    350: PetscErrorCode  PetscBinaryWrite(int fd,void *p,PetscInt n,PetscDataType type,PetscBool  istemp)
    351: {
    352:   char           *pp = (char*)p;
    353:   int            err,wsize;
    354:   size_t         m = (size_t)n,maxblock=65536;
    356: #if !defined(PETSC_WORDS_BIGENDIAN)
    357:   void           *ptmp = p;
    358: #endif
    359:   char           *fname = NULL;

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

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

    386:   if (type == PETSC_INT)          m *= sizeof(PetscInt);
    387:   else if (type == PETSC_SCALAR)  m *= sizeof(PetscScalar);
    388:   else if (type == PETSC_DOUBLE)  m *= sizeof(double);
    389:   else if (type == PETSC_FLOAT)   m *= sizeof(float);
    390:   else if (type == PETSC_SHORT)   m *= sizeof(short);
    391:   else if (type == PETSC_CHAR)    m *= sizeof(char);
    392:   else if (type == PETSC_ENUM)    m *= sizeof(PetscEnum);
    393:   else if (type == PETSC_BOOL)   m *= sizeof(PetscBool);
    394:   else if (type == PETSC_BIT_LOGICAL) m = PetscBTLength(m)*sizeof(char);
    395:   else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown type");

    397: #if !defined(PETSC_WORDS_BIGENDIAN)
    398:   PetscByteSwap(ptmp,type,n);
    399: #endif

    401:   while (m) {
    402:     wsize = (m < maxblock) ? m : maxblock;
    403:     err   = write(fd,pp,wsize);
    404:     if (err < 0 && errno == EINTR) continue;
    405:     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);
    406:     m  -= wsize;
    407:     pp += wsize;
    408:   }

    410: #if !defined(PETSC_WORDS_BIGENDIAN)
    411:   if (!istemp) {
    412:     PetscByteSwap(ptmp,type,n);
    413:   }
    414: #endif
    415:   if (type == PETSC_FUNCTION) {
    416:     free(fname);
    417:   }
    418:   return(0);
    419: }

    423: /*@C
    424:    PetscBinaryOpen - Opens a PETSc binary file.

    426:    Not Collective

    428:    Input Parameters:
    429: +  name - filename
    430: -  type - type of binary file, one of FILE_MODE_READ, FILE_MODE_APPEND, FILE_MODE_WRITE

    432:    Output Parameter:
    433: .  fd - the file

    435:    Level: advanced

    437:   Concepts: files^opening binary
    438:   Concepts: binary files^opening

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

    444: .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscFileMode, PetscViewerFileSetMode(), PetscViewerBinaryGetDescriptor(),
    445:           PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek()

    447: @*/
    448: PetscErrorCode  PetscBinaryOpen(const char name[],PetscFileMode mode,int *fd)
    449: {
    451: #if defined(PETSC_HAVE_O_BINARY)
    452:   if (mode == FILE_MODE_WRITE) {
    453:     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);
    454:   } else if (mode == FILE_MODE_READ) {
    455:     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);
    456:   } else if (mode == FILE_MODE_APPEND) {
    457:     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);
    458: #else
    459:   if (mode == FILE_MODE_WRITE) {
    460:     if ((*fd = creat(name,0666)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot create file for writing: %s",name);
    461:   } else if (mode == FILE_MODE_READ) {
    462:     if ((*fd = open(name,O_RDONLY,0)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file for reading: %s",name);
    463:   }
    464:   else if (mode == FILE_MODE_APPEND) {
    465:     if ((*fd = open(name,O_WRONLY,0)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file for writing: %s",name);
    466: #endif
    467:   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown file mode");
    468:   return(0);
    469: }

    473: /*@
    474:    PetscBinaryClose - Closes a PETSc binary file.

    476:    Not Collective

    478:    Output Parameter:
    479: .  fd - the file

    481:    Level: advanced

    483: .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
    484:           PetscBinarySynchronizedSeek()
    485: @*/
    486: PetscErrorCode  PetscBinaryClose(int fd)
    487: {
    489:   close(fd);
    490:   return(0);
    491: }

    496: /*@
    497:    PetscBinarySeek - Moves the file pointer on a PETSc binary file.

    499:    Not Collective

    501:    Input Parameters:
    502: +  fd - the file
    503: .  off - number of bytes to move. Use PETSC_BINARY_INT_SIZE, PETSC_BINARY_SCALAR_SIZE,
    504:             etc. in your calculation rather than sizeof() to compute byte lengths.
    505: -  whence - if PETSC_BINARY_SEEK_SET then off is an absolute location in the file
    506:             if PETSC_BINARY_SEEK_CUR then off is an offset from the current location
    507:             if PETSC_BINARY_SEEK_END then off is an offset from the end of file

    509:    Output Parameter:
    510: .   offset - new offset in file

    512:    Level: developer

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

    520:    Concepts: files^binary seeking
    521:    Concepts: binary files^seeking

    523: .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
    524:           PetscBinarySynchronizedSeek()
    525: @*/
    526: PetscErrorCode  PetscBinarySeek(int fd,off_t off,PetscBinarySeekType whence,off_t *offset)
    527: {
    528:   int iwhence = 0;

    531:   if (whence == PETSC_BINARY_SEEK_SET) iwhence = SEEK_SET;
    532:   else if (whence == PETSC_BINARY_SEEK_CUR) iwhence = SEEK_CUR;
    533:   else if (whence == PETSC_BINARY_SEEK_END) iwhence = SEEK_END;
    534:   else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown seek location");
    535: #if defined(PETSC_HAVE_LSEEK)
    536:   *offset = lseek(fd,off,iwhence);
    537: #elif defined(PETSC_HAVE__LSEEK)
    538:   *offset = _lseek(fd,(long)off,iwhence);
    539: #else
    540:   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS,"System does not have a way of seeking on a file");
    541: #endif
    542:   return(0);
    543: }

    547: /*@C
    548:    PetscBinarySynchronizedRead - Reads from a binary file.

    550:    Collective on MPI_Comm

    552:    Input Parameters:
    553: +  comm - the MPI communicator
    554: .  fd - the file
    555: .  n  - the number of items to read
    556: -  type - the type of items to read (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)

    558:    Output Parameters:
    559: .  p - the buffer

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

    566:    Level: developer

    568:    Notes:
    569:    Does a PetscBinaryRead() followed by an MPI_Bcast()

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

    576:    Concepts: files^synchronized reading of binary files
    577:    Concepts: binary files^reading, synchronized

    579: .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscBinaryRead(), PetscBinarySynchronizedWrite(),
    580:           PetscBinarySynchronizedSeek()
    581: @*/
    582: PetscErrorCode  PetscBinarySynchronizedRead(MPI_Comm comm,int fd,void *p,PetscInt n,PetscDataType type)
    583: {
    585:   PetscMPIInt    rank;
    586:   MPI_Datatype   mtype;
    587:   char           *fname = NULL;
    588:   void           *ptmp = NULL;

    591:   if (type == PETSC_FUNCTION) {
    592:     n            = 64;
    593:     type         = PETSC_CHAR;
    594:     ptmp         = p;
    595:     fname        = (char*)malloc(n*sizeof(char));
    596:     if (!fname) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Cannot allocate space for function name");
    597:     p            = (void*)fname;
    598:   }

    600:   MPI_Comm_rank(comm,&rank);
    601:   if (!rank) {
    602:     PetscBinaryRead(fd,p,n,type);
    603:   }
    604:   PetscDataTypeToMPIDataType(type,&mtype);
    605:   MPI_Bcast(p,n,mtype,0,comm);

    607:   if (type == PETSC_FUNCTION) {
    608: #if defined(PETSC_SERIALIZE_FUNCTIONS)
    609:     PetscDLLibrarySym(PETSC_COMM_SELF,&PetscDLLibrariesLoaded,NULL,fname,(void**)ptmp);
    610: #else
    611:     *(void**)ptmp = NULL;
    612: #endif
    613:     free(fname);
    614:   }
    615:   return(0);
    616: }

    620: /*@C
    621:    PetscBinarySynchronizedWrite - writes to a binary file.

    623:    Collective on MPI_Comm

    625:    Input Parameters:
    626: +  comm - the MPI communicator
    627: .  fd - the file
    628: .  n  - the number of items to write
    629: .  p - the buffer
    630: .  istemp - the buffer may be changed
    631: -  type - the type of items to write (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)

    633:    Level: developer

    635:    Notes:
    636:    Process 0 does a PetscBinaryWrite()

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

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

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

    648:    Concepts: files^synchronized writing of binary files
    649:    Concepts: binary files^reading, synchronized

    651: .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscBinaryRead(), PetscBinarySynchronizedRead(),
    652:           PetscBinarySynchronizedSeek()
    653: @*/
    654: PetscErrorCode  PetscBinarySynchronizedWrite(MPI_Comm comm,int fd,void *p,PetscInt n,PetscDataType type,PetscBool istemp)
    655: {
    657:   PetscMPIInt    rank;

    660:   MPI_Comm_rank(comm,&rank);
    661:   if (!rank) {
    662:     PetscBinaryWrite(fd,p,n,type,istemp);
    663:   }
    664:   return(0);
    665: }

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

    673:    Input Parameters:
    674: +  fd - the file
    675: .  whence - if PETSC_BINARY_SEEK_SET then size is an absolute location in the file
    676:             if PETSC_BINARY_SEEK_CUR then size is offset from current location
    677:             if PETSC_BINARY_SEEK_END then size is offset from end of file
    678: -  off    - number of bytes to move. Use PETSC_BINARY_INT_SIZE, PETSC_BINARY_SCALAR_SIZE,
    679:             etc. in your calculation rather than sizeof() to compute byte lengths.

    681:    Output Parameter:
    682: .   offset - new offset in file

    684:    Level: developer

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

    692:    Concepts: binary files^seeking
    693:    Concepts: files^seeking in binary

    695: .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
    696:           PetscBinarySynchronizedSeek()
    697: @*/
    698: PetscErrorCode  PetscBinarySynchronizedSeek(MPI_Comm comm,int fd,off_t off,PetscBinarySeekType whence,off_t *offset)
    699: {
    701:   PetscMPIInt    rank;

    704:   MPI_Comm_rank(comm,&rank);
    705:   if (!rank) {
    706:     PetscBinarySeek(fd,off,whence,offset);
    707:   }
    708:   return(0);
    709: }

    711: #if defined(PETSC_HAVE_MPIIO)
    712: #if !defined(PETSC_WORDS_BIGENDIAN)

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

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

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

    723: */
    724: PETSC_EXTERN PetscMPIInt PetscDataRep_extent_fn(MPI_Datatype datatype,MPI_Aint *file_extent,void *extra_state)
    725: {
    726:   MPI_Aint    ub;
    727:   PetscMPIInt ierr;

    729:   MPI_Type_get_extent(datatype,&ub,file_extent);
    730:   return ierr;
    731: }

    733: PETSC_EXTERN PetscMPIInt PetscDataRep_read_conv_fn(void *userbuf, MPI_Datatype datatype,PetscMPIInt count,void *filebuf, MPI_Offset position,void *extra_state)
    734: {
    735:   PetscDataType pdtype;
    736:   PetscMPIInt   ierr;
    737:   size_t        dsize;

    739:   PetscMPIDataTypeToPetscDataType(datatype,&pdtype);
    740:   PetscDataTypeGetSize(pdtype,&dsize);

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

    745:   PetscMemcpy(userbuf,filebuf,count*dsize);
    746:   PetscByteSwap(userbuf,pdtype,count);
    747:   return ierr;
    748: }

    750: PetscMPIInt PetscDataRep_write_conv_fn(void *userbuf, MPI_Datatype datatype,PetscMPIInt count,void *filebuf, MPI_Offset position,void *extra_state)
    751: {
    752:   PetscDataType pdtype;
    753:   PetscMPIInt   ierr;
    754:   size_t        dsize;

    756:   PetscMPIDataTypeToPetscDataType(datatype,&pdtype);
    757:   PetscDataTypeGetSize(pdtype,&dsize);

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

    762:   PetscMemcpy(filebuf,userbuf,count*dsize);
    763:   PetscByteSwap(filebuf,pdtype,count);
    764:   return ierr;
    765: }
    766: #endif

    770: PetscErrorCode MPIU_File_write_all(MPI_File fd,void *data,PetscMPIInt cnt,MPI_Datatype dtype,MPI_Status *status)
    771: {
    773:   PetscDataType  pdtype;

    776:   PetscMPIDataTypeToPetscDataType(dtype,&pdtype);
    777:   PetscByteSwap(data,pdtype,cnt);
    778:   MPI_File_write_all(fd,data,cnt,dtype,status);
    779:   PetscByteSwap(data,pdtype,cnt);
    780:   return(0);
    781: }

    785: PetscErrorCode MPIU_File_read_all(MPI_File fd,void *data,PetscMPIInt cnt,MPI_Datatype dtype,MPI_Status *status)
    786: {
    788:   PetscDataType  pdtype;

    791:   PetscMPIDataTypeToPetscDataType(dtype,&pdtype);
    792:   MPI_File_read_all(fd,data,cnt,dtype,status);
    793:   PetscByteSwap(data,pdtype,cnt);
    794:   return(0);
    795: }
    796: #endif
    797: #endif