Date: 2013-07-02T14:38:47+00:00

Actual source code: sysio.c
petsc-3.4.2 2013-07-02

      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:   double            *ppp;
    224: #endif
    225: #if !defined(PETSC_WORDS_BIGENDIAN) || defined(PETSC_USE_REAL___FLOAT128)
    226:   PetscErrorCode    ierr;
    227: #endif
    228: #if !defined(PETSC_WORDS_BIGENDIAN)
    229:   void              *ptmp = p;
    230: #endif
    231:   char              fname[64];
    232:   PetscBool         functionload = PETSC_FALSE;

    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:     functionload = PETSC_TRUE;
    240:     m            = 64;
    241:     type         = PETSC_CHAR;
    242:     pp           = (char*)fname;
    243: #if !defined(PETSC_WORDS_BIGENDIAN)
    244:     ptmp         = (void*)fname;
    245: #endif
    246:   }

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

    259: #if defined(PETSC_USE_REAL___FLOAT128)
    260:   /* If using __float128 precision we still read in doubles from file */
    261:   if (type == PETSC_SCALAR) {
    262:     m    = m/2;
    263:     PetscMalloc(n*sizeof(double),&ppp);
    264:     pp   = (char*)ppp;
    265:   }
    266: #endif

    268:   while (m) {
    269:     wsize = (m < maxblock) ? m : maxblock;
    270:     err   = read(fd,pp,wsize);
    271:     if (err < 0 && errno == EINTR) continue;
    272:     if (!err && wsize > 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_READ,"Read past end of file");
    273:     if (err < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_READ,"Error reading from file, errno %d",errno);
    274:     m  -= err;
    275:     pp += err;
    276:   }

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

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

    295:   if (functionload) {
    296: #if defined(PETSC_SERIALIZE_FUNCTIONS)
    297:     PetscDLSym(NULL,fname,(void**)p);
    298: #else
    299:     *(void**)p = NULL;
    300: #endif
    301:   }
    302:   return(0);
    303: }
    304: /* --------------------------------------------------------- */
    307: /*@
    308:    PetscBinaryWrite - Writes to a binary file.

    310:    Not Collective

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

    319:    Level: advanced

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

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

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

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

    341:    Concepts: files^writing binary
    342:    Concepts: binary files^writing

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

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

    362:   if (type == PETSC_FUNCTION) {
    363: #if defined(PETSC_SERIALIZE_FUNCTIONS)
    364:     const char *fnametmp;

    366:     if (n > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Can only binary view a single function at a time");
    367:     PetscFPTFind(p,&fnametmp);
    368:     PetscStrncpy(fname,fnametmp,64);
    369: #else
    370:     PetscStrncpy(fname,"",64);
    371: #endif
    372:     m    = 64;
    373:     type = PETSC_CHAR;
    374:     pp   = (char*)fname;
    375: #if !defined(PETSC_WORDS_BIGENDIAN)
    376:     ptmp = (void*)fname;
    377: #endif
    378:   }

    380:   if (type == PETSC_INT)          m *= sizeof(PetscInt);
    381:   else if (type == PETSC_SCALAR)  m *= sizeof(PetscScalar);
    382:   else if (type == PETSC_DOUBLE)  m *= sizeof(double);
    383:   else if (type == PETSC_FLOAT)   m *= sizeof(float);
    384:   else if (type == PETSC_SHORT)   m *= sizeof(short);
    385:   else if (type == PETSC_CHAR)    m *= sizeof(char);
    386:   else if (type == PETSC_ENUM)    m *= sizeof(PetscEnum);
    387:   else if (type == PETSC_BOOL)   m *= sizeof(PetscBool);
    388:   else if (type == PETSC_BIT_LOGICAL) m = PetscBTLength(m)*sizeof(char);
    389:   else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown type");

    391: #if !defined(PETSC_WORDS_BIGENDIAN)
    392:   PetscByteSwap(ptmp,type,n);
    393: #endif

    395:   while (m) {
    396:     wsize = (m < maxblock) ? m : maxblock;
    397:     err   = write(fd,pp,wsize);
    398:     if (err < 0 && errno == EINTR) continue;
    399:     if (err != wsize) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_WRITE,"Error writing to file.");
    400:     m  -= wsize;
    401:     pp += wsize;
    402:   }

    404: #if !defined(PETSC_WORDS_BIGENDIAN)
    405:   if (!istemp) {
    406:     PetscByteSwap(ptmp,type,n);
    407:   }
    408: #endif
    409:   return(0);
    410: }

    414: /*@C
    415:    PetscBinaryOpen - Opens a PETSc binary file.

    417:    Not Collective

    419:    Input Parameters:
    420: +  name - filename
    421: -  type - type of binary file, one of FILE_MODE_READ, FILE_MODE_APPEND, FILE_MODE_WRITE

    423:    Output Parameter:
    424: .  fd - the file

    426:    Level: advanced

    428:   Concepts: files^opening binary
    429:   Concepts: binary files^opening

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

    435: .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscFileMode, PetscViewerFileSetMode(), PetscViewerBinaryGetDescriptor(),
    436:           PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek()

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

    464: /*@
    465:    PetscBinaryClose - Closes a PETSc binary file.

    467:    Not Collective

    469:    Output Parameter:
    470: .  fd - the file

    472:    Level: advanced

    474: .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
    475:           PetscBinarySynchronizedSeek()
    476: @*/
    477: PetscErrorCode  PetscBinaryClose(int fd)
    478: {
    480:   close(fd);
    481:   return(0);
    482: }

    487: /*@
    488:    PetscBinarySeek - Moves the file pointer on a PETSc binary file.

    490:    Not Collective

    492:    Input Parameters:
    493: +  fd - the file
    494: .  off - number of bytes to move. Use PETSC_BINARY_INT_SIZE, PETSC_BINARY_SCALAR_SIZE,
    495:             etc. in your calculation rather than sizeof() to compute byte lengths.
    496: -  whence - if PETSC_BINARY_SEEK_SET then off is an absolute location in the file
    497:             if PETSC_BINARY_SEEK_CUR then off is an offset from the current location
    498:             if PETSC_BINARY_SEEK_END then off is an offset from the end of file

    500:    Output Parameter:
    501: .   offset - new offset in file

    503:    Level: developer

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

    511:    Concepts: files^binary seeking
    512:    Concepts: binary files^seeking

    514: .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
    515:           PetscBinarySynchronizedSeek()
    516: @*/
    517: PetscErrorCode  PetscBinarySeek(int fd,off_t off,PetscBinarySeekType whence,off_t *offset)
    518: {
    519:   int iwhence = 0;

    522:   if (whence == PETSC_BINARY_SEEK_SET) iwhence = SEEK_SET;
    523:   else if (whence == PETSC_BINARY_SEEK_CUR) iwhence = SEEK_CUR;
    524:   else if (whence == PETSC_BINARY_SEEK_END) iwhence = SEEK_END;
    525:   else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown seek location");
    526: #if defined(PETSC_HAVE_LSEEK)
    527:   *offset = lseek(fd,off,iwhence);
    528: #elif defined(PETSC_HAVE__LSEEK)
    529:   *offset = _lseek(fd,(long)off,iwhence);
    530: #else
    531:   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS,"System does not have a way of seeking on a file");
    532: #endif
    533:   return(0);
    534: }

    538: /*@C
    539:    PetscBinarySynchronizedRead - Reads from a binary file.

    541:    Collective on MPI_Comm

    543:    Input Parameters:
    544: +  comm - the MPI communicator
    545: .  fd - the file
    546: .  n  - the number of items to read
    547: -  type - the type of items to read (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)

    549:    Output Parameters:
    550: .  p - the buffer

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

    557:    Level: developer

    559:    Notes:
    560:    Does a PetscBinaryRead() followed by an MPI_Bcast()

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

    567:    Concepts: files^synchronized reading of binary files
    568:    Concepts: binary files^reading, synchronized

    570: .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscBinaryRead(), PetscBinarySynchronizedWrite(),
    571:           PetscBinarySynchronizedSeek()
    572: @*/
    573: PetscErrorCode  PetscBinarySynchronizedRead(MPI_Comm comm,int fd,void *p,PetscInt n,PetscDataType type)
    574: {
    576:   PetscMPIInt    rank;
    577:   MPI_Datatype   mtype;
    578:   char           *fname;
    579:   PetscBool      functionload = PETSC_FALSE;
    580:   void           *ptmp        = NULL;

    583:   if (type == PETSC_FUNCTION) {
    584:     functionload = PETSC_TRUE;
    585:     n            = 64;
    586:     type         = PETSC_CHAR;
    587:     ptmp         = p;
    588:     /* warning memory leak */
    589:     fname        = (char*)malloc(64*sizeof(char));
    590:     p            = (void*)fname;
    591:   }

    593:   MPI_Comm_rank(comm,&rank);
    594:   if (!rank) {
    595:     PetscBinaryRead(fd,p,n,type);
    596:   }
    597:   PetscDataTypeToMPIDataType(type,&mtype);
    598:   MPI_Bcast(p,n,mtype,0,comm);

    600:   if (functionload) {
    601: #if defined(PETSC_SERIALIZE_FUNCTIONS)
    602:     PetscDLLibrarySym(PETSC_COMM_SELF,&PetscDLLibrariesLoaded,NULL,fname,(void**)ptmp);
    603: #else
    604:     *(void**)ptmp = NULL;
    605: #endif
    606:   }
    607:   return(0);
    608: }

    612: /*@C
    613:    PetscBinarySynchronizedWrite - writes to a binary file.

    615:    Collective on MPI_Comm

    617:    Input Parameters:
    618: +  comm - the MPI communicator
    619: .  fd - the file
    620: .  n  - the number of items to write
    621: .  p - the buffer
    622: .  istemp - the buffer may be changed
    623: -  type - the type of items to write (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)

    625:    Level: developer

    627:    Notes:
    628:    Process 0 does a PetscBinaryWrite()

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

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

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

    640:    Concepts: files^synchronized writing of binary files
    641:    Concepts: binary files^reading, synchronized

    643: .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscBinaryRead(), PetscBinarySynchronizedRead(),
    644:           PetscBinarySynchronizedSeek()
    645: @*/
    646: PetscErrorCode  PetscBinarySynchronizedWrite(MPI_Comm comm,int fd,void *p,PetscInt n,PetscDataType type,PetscBool istemp)
    647: {
    649:   PetscMPIInt    rank;

    652:   MPI_Comm_rank(comm,&rank);
    653:   if (!rank) {
    654:     PetscBinaryWrite(fd,p,n,type,istemp);
    655:   }
    656:   return(0);
    657: }

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

    665:    Input Parameters:
    666: +  fd - the file
    667: .  whence - if PETSC_BINARY_SEEK_SET then size is an absolute location in the file
    668:             if PETSC_BINARY_SEEK_CUR then size is offset from current location
    669:             if PETSC_BINARY_SEEK_END then size is offset from end of file
    670: -  off    - number of bytes to move. Use PETSC_BINARY_INT_SIZE, PETSC_BINARY_SCALAR_SIZE,
    671:             etc. in your calculation rather than sizeof() to compute byte lengths.

    673:    Output Parameter:
    674: .   offset - new offset in file

    676:    Level: developer

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

    684:    Concepts: binary files^seeking
    685:    Concepts: files^seeking in binary

    687: .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
    688:           PetscBinarySynchronizedSeek()
    689: @*/
    690: PetscErrorCode  PetscBinarySynchronizedSeek(MPI_Comm comm,int fd,off_t off,PetscBinarySeekType whence,off_t *offset)
    691: {
    693:   PetscMPIInt    rank;

    696:   MPI_Comm_rank(comm,&rank);
    697:   if (!rank) {
    698:     PetscBinarySeek(fd,off,whence,offset);
    699:   }
    700:   return(0);
    701: }

    703: #if defined(PETSC_HAVE_MPIIO)
    704: #if !defined(PETSC_WORDS_BIGENDIAN)

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

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

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

    715: */
    716: PETSC_EXTERN PetscMPIInt PetscDataRep_extent_fn(MPI_Datatype datatype,MPI_Aint *file_extent,void *extra_state)
    717: {
    718:   MPI_Aint    ub;
    719:   PetscMPIInt ierr;

    721:   MPI_Type_get_extent(datatype,&ub,file_extent);
    722:   return ierr;
    723: }

    725: PETSC_EXTERN PetscMPIInt PetscDataRep_read_conv_fn(void *userbuf, MPI_Datatype datatype,PetscMPIInt count,void *filebuf, MPI_Offset position,void *extra_state)
    726: {
    727:   PetscDataType pdtype;
    728:   PetscMPIInt   ierr;
    729:   size_t        dsize;

    731:   PetscMPIDataTypeToPetscDataType(datatype,&pdtype);
    732:   PetscDataTypeGetSize(pdtype,&dsize);

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

    737:   PetscMemcpy(userbuf,filebuf,count*dsize);
    738:   PetscByteSwap(userbuf,pdtype,count);
    739:   return ierr;
    740: }

    742: PetscMPIInt PetscDataRep_write_conv_fn(void *userbuf, MPI_Datatype datatype,PetscMPIInt count,void *filebuf, MPI_Offset position,void *extra_state)
    743: {
    744:   PetscDataType pdtype;
    745:   PetscMPIInt   ierr;
    746:   size_t        dsize;

    748:   PetscMPIDataTypeToPetscDataType(datatype,&pdtype);
    749:   PetscDataTypeGetSize(pdtype,&dsize);

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

    754:   PetscMemcpy(filebuf,userbuf,count*dsize);
    755:   PetscByteSwap(filebuf,pdtype,count);
    756:   return ierr;
    757: }
    758: #endif

    762: PetscErrorCode MPIU_File_write_all(MPI_File fd,void *data,PetscMPIInt cnt,MPI_Datatype dtype,MPI_Status *status)
    763: {
    765:   PetscDataType  pdtype;

    768:   PetscMPIDataTypeToPetscDataType(dtype,&pdtype);
    769:   PetscByteSwap(data,pdtype,cnt);
    770:   MPI_File_write_all(fd,data,cnt,dtype,status);
    771:   PetscByteSwap(data,pdtype,cnt);
    772:   return(0);
    773: }

    777: PetscErrorCode MPIU_File_read_all(MPI_File fd,void *data,PetscMPIInt cnt,MPI_Datatype dtype,MPI_Status *status)
    778: {
    780:   PetscDataType  pdtype;

    783:   PetscMPIDataTypeToPetscDataType(dtype,&pdtype);
    784:   MPI_File_read_all(fd,data,cnt,dtype,status);
    785:   PetscByteSwap(data,pdtype,cnt);
    786:   return(0);
    787: }
    788: #endif
    789: #endif