Actual source code: sysio.c
petsc-3.10.5 2019-03-28
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: /* --------------------------------------------------------- */
     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;

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

     39: /*
     40:   PetscByteSwapBool - Swap bytes in a  PETSc Bool

     42: */
     43: PetscErrorCode  PetscByteSwapBool(PetscBool *buff,PetscInt n)
     44: {
     45:   PetscInt  i,j;
     46:   PetscBool tmp = PETSC_FALSE;
     47:   char      *ptr1,*ptr2 = (char*)&tmp;

     50:   for (j=0; j<n; j++) {
     51:     ptr1 = (char*)(buff + j);
     52:     for (i=0; i<(PetscInt)sizeof(PetscBool); i++) ptr2[i] = ptr1[sizeof(PetscBool)-1-i];
     53:     for (i=0; i<(PetscInt)sizeof(PetscBool); i++) ptr1[i] = ptr2[i];
     54:   }
     55:   return(0);
     56: }

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

     61: */
     62: PetscErrorCode  PetscByteSwapInt(PetscInt *buff,PetscInt n)
     63: {
     64:   PetscInt i,j,tmp = 0;
     65:   char     *ptr1,*ptr2 = (char*)&tmp;

     68:   for (j=0; j<n; j++) {
     69:     ptr1 = (char*)(buff + j);
     70:     for (i=0; i<(PetscInt)sizeof(PetscInt); i++) ptr2[i] = ptr1[sizeof(PetscInt)-1-i];
     71:     for (i=0; i<(PetscInt)sizeof(PetscInt); i++) ptr1[i] = ptr2[i];
     72:   }
     73:   return(0);
     74: }
     75: /* --------------------------------------------------------- */
     76: /*
     77:   PetscByteSwapShort - Swap bytes in a short
     78: */
     79: PetscErrorCode  PetscByteSwapShort(short *buff,PetscInt n)
     80: {
     81:   PetscInt i,j;
     82:   short    tmp;
     83:   char     *ptr1,*ptr2 = (char*)&tmp;

     86:   for (j=0; j<n; j++) {
     87:     ptr1 = (char*)(buff + j);
     88:     for (i=0; i<(PetscInt) sizeof(short); i++) ptr2[i] = ptr1[sizeof(short)-1-i];
     89:     for (i=0; i<(PetscInt) sizeof(short); i++) ptr1[i] = ptr2[i];
     90:   }
     91:   return(0);
     92: }
     93: /* --------------------------------------------------------- */
     94: /*
     95:   PetscByteSwapReal - Swap bytes in a PetscReal
     96: */
     97: PetscErrorCode  PetscByteSwapReal(PetscReal *buff,PetscInt n)
     98: {
     99:   PetscInt  i,j;
    100:   PetscReal tmp,*buff1 = (PetscReal*)buff;
    101:   char      *ptr1,*ptr2 = (char*)&tmp;

    104:   for (j=0; j<n; j++) {
    105:     ptr1 = (char*)(buff1 + j);
    106:     for (i=0; i<(PetscInt) sizeof(PetscReal); i++) ptr2[i] = ptr1[sizeof(PetscReal)-1-i];
    107:     for (i=0; i<(PetscInt) sizeof(PetscReal); i++) ptr1[i] = ptr2[i];
    108:   }
    109:   return(0);
    110: }
    111: /* --------------------------------------------------------- */
    112: /*
    113:   PetscByteSwapScalar - Swap bytes in a PetscScalar
    114:   The complex case is dealt with with an array of PetscReal, twice as long.
    115: */
    116: PetscErrorCode  PetscByteSwapScalar(PetscScalar *buff,PetscInt n)
    117: {
    118:   PetscInt  i,j;
    119:   PetscReal tmp,*buff1 = (PetscReal*)buff;
    120:   char      *ptr1,*ptr2 = (char*)&tmp;

    123: #if defined(PETSC_USE_COMPLEX)
    124:   n *= 2;
    125: #endif
    126:   for (j=0; j<n; j++) {
    127:     ptr1 = (char*)(buff1 + j);
    128:     for (i=0; i<(PetscInt) sizeof(PetscReal); i++) ptr2[i] = ptr1[sizeof(PetscReal)-1-i];
    129:     for (i=0; i<(PetscInt) sizeof(PetscReal); i++) ptr1[i] = ptr2[i];
    130:   }
    131:   return(0);
    132: }
    133: /* --------------------------------------------------------- */
    134: /*
    135:   PetscByteSwapDouble - Swap bytes in a double
    136: */
    137: PetscErrorCode  PetscByteSwapDouble(double *buff,PetscInt n)
    138: {
    139:   PetscInt i,j;
    140:   double   tmp,*buff1 = (double*)buff;
    141:   char     *ptr1,*ptr2 = (char*)&tmp;

    144:   for (j=0; j<n; j++) {
    145:     ptr1 = (char*)(buff1 + j);
    146:     for (i=0; i<(PetscInt) sizeof(double); i++) ptr2[i] = ptr1[sizeof(double)-1-i];
    147:     for (i=0; i<(PetscInt) sizeof(double); i++) ptr1[i] = ptr2[i];
    148:   }
    149:   return(0);
    150: }

    152: /*
    153:   PetscByteSwapFloat - Swap bytes in a float
    154: */
    155: PetscErrorCode PetscByteSwapFloat(float *buff,PetscInt n)
    156: {
    157:   PetscInt i,j;
    158:   float    tmp,*buff1 = (float*)buff;
    159:   char     *ptr1,*ptr2 = (char*)&tmp;

    162:   for (j=0; j<n; j++) {
    163:     ptr1 = (char*)(buff1 + j);
    164:     for (i=0; i<(PetscInt) sizeof(float); i++) ptr2[i] = ptr1[sizeof(float)-1-i];
    165:     for (i=0; i<(PetscInt) sizeof(float); i++) ptr1[i] = ptr2[i];
    166:   }
    167:   return(0);
    168: }

    170: PetscErrorCode PetscByteSwap(void *data,PetscDataType pdtype,PetscInt count)
    171: {

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

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

    190:    Not Collective

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

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

    202:    Level: developer

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

    212:    Concepts: files^reading binary
    213:    Concepts: binary files^reading

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

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

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

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

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

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

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

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

    299:   if (type == PETSC_FUNCTION) {
    300: #if defined(PETSC_SERIALIZE_FUNCTIONS)
    301:     PetscDLSym(NULL,fname,(void**)p);
    302: #else
    303:     *(void**)p = NULL;
    304: #endif
    305:     free(fname);
    306:   }
    307:   return(0);
    308: }
    309: /* --------------------------------------------------------- */
    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_write_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
    368:   PetscDataType  wtype = type;

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

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

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

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

    422: #if !defined(PETSC_WORDS_BIGENDIAN)
    423:   PetscByteSwap(ptmp,wtype,n);
    424: #endif

    426:   while (m) {
    427:     wsize = (m < maxblock) ? m : maxblock;
    428:     err   = write(fd,pp,wsize);
    429:     if (err < 0 && errno == EINTR) continue;
    430:     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);
    431:     m  -= wsize;
    432:     pp += wsize;
    433:   }

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

    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:
    469:     Files access with PetscBinaryRead() and PetscBinaryWrite() are ALWAYS written in
    470:    big-endian format. This means the file can be accessed using PetscBinaryOpen() and
    471:    PetscBinaryRead() and PetscBinaryWrite() on any machine.

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

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

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

    503:    Not Collective

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

    508:    Level: advanced

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

    521: /*@C
    522:    PetscBinarySeek - Moves the file pointer on a PETSc binary file.

    524:    Not Collective

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

    534:    Output Parameter:
    535: .   offset - new offset in file

    537:    Level: developer

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

    545:    Concepts: files^binary seeking
    546:    Concepts: binary files^seeking

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

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

    570: /*@C
    571:    PetscBinarySynchronizedRead - Reads from a binary file.

    573:    Collective on MPI_Comm

    575:    Input Parameters:
    576: +  comm - the MPI communicator
    577: .  fd - the file
    578: .  n  - the number of items to read
    579: -  type - the type of items to read (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)

    581:    Output Parameters:
    582: .  p - the buffer

    584:    Level: developer

    586:    Notes:
    587:    Does a PetscBinaryRead() followed by an MPI_Bcast()

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

    594:    Concepts: files^synchronized reading of binary files
    595:    Concepts: binary files^reading, synchronized

    597: .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscBinaryRead(), PetscBinarySynchronizedWrite(),
    598:           PetscBinarySynchronizedSeek()
    599: @*/
    600: PetscErrorCode  PetscBinarySynchronizedRead(MPI_Comm comm,int fd,void *p,PetscInt n,PetscDataType type)
    601: {
    602:   PetscErrorCode ierr,ierrp=0;
    603:   PetscMPIInt    rank;
    604:   MPI_Datatype   mtype;
    605:   char           *fname = NULL;
    606:   void           *ptmp = NULL;

    609:   if (type == PETSC_FUNCTION) {
    610:     n            = 64;
    611:     type         = PETSC_CHAR;
    612:     ptmp         = p;
    613:     fname        = (char*)malloc(n*sizeof(char));
    614:     if (!fname) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Cannot allocate space for function name");
    615:     p            = (void*)fname;
    616:   }

    618:   MPI_Comm_rank(comm,&rank);
    619:   if (!rank) {
    620:     ierrp = PetscBinaryRead(fd,p,n,type);
    621:   }
    622:   MPI_Bcast(&ierrp,1,MPI_INT,0,comm);
    623:   CHKERRQ(ierrp);
    624:   PetscDataTypeToMPIDataType(type,&mtype);
    625:   MPI_Bcast(p,n,mtype,0,comm);

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

    638: /*@C
    639:    PetscBinarySynchronizedWrite - writes to a binary file.

    641:    Collective on MPI_Comm

    643:    Input Parameters:
    644: +  comm - the MPI communicator
    645: .  fd - the file
    646: .  n  - the number of items to write
    647: .  p - the buffer
    648: .  istemp - the buffer may be changed
    649: -  type - the type of items to write (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)

    651:    Level: developer

    653:    Notes:
    654:    Process 0 does a PetscBinaryWrite()

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

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

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

    667:    Concepts: files^synchronized writing of binary files
    668:    Concepts: binary files^reading, synchronized

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

    679:   MPI_Comm_rank(comm,&rank);
    680:   if (!rank) {
    681:     PetscBinaryWrite(fd,p,n,type,istemp);
    682:   }
    683:   return(0);
    684: }

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

    690:    Input Parameters:
    691: +  fd - the file
    692: .  whence - if PETSC_BINARY_SEEK_SET then size is an absolute location in the file
    693:             if PETSC_BINARY_SEEK_CUR then size is offset from current location
    694:             if PETSC_BINARY_SEEK_END then size is offset from end of file
    695: -  off    - number of bytes to move. Use PETSC_BINARY_INT_SIZE, PETSC_BINARY_SCALAR_SIZE,
    696:             etc. in your calculation rather than sizeof() to compute byte lengths.

    698:    Output Parameter:
    699: .   offset - new offset in file

    701:    Level: developer

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

    709:    Concepts: binary files^seeking
    710:    Concepts: files^seeking in binary

    712: .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
    713:           PetscBinarySynchronizedSeek()
    714: @*/
    715: PetscErrorCode  PetscBinarySynchronizedSeek(MPI_Comm comm,int fd,off_t off,PetscBinarySeekType whence,off_t *offset)
    716: {
    718:   PetscMPIInt    rank;

    721:   MPI_Comm_rank(comm,&rank);
    722:   if (!rank) {
    723:     PetscBinarySeek(fd,off,whence,offset);
    724:   }
    725:   return(0);
    726: }

    728: #if defined(PETSC_HAVE_MPIIO)
    729: #if !defined(PETSC_WORDS_BIGENDIAN)

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

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

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

    740: */
    741: PETSC_EXTERN PetscMPIInt PetscDataRep_extent_fn(MPI_Datatype datatype,MPI_Aint *file_extent,void *extra_state)
    742: {
    743:   MPI_Aint    ub;
    744:   PetscMPIInt ierr;

    746:   MPI_Type_get_extent(datatype,&ub,file_extent);
    747:   return ierr;
    748: }

    750: PETSC_EXTERN PetscMPIInt PetscDataRep_read_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(userbuf,filebuf,count*dsize);
    763:   PetscByteSwap(userbuf,pdtype,count);
    764:   return ierr;
    765: }

    767: PetscMPIInt PetscDataRep_write_conv_fn(void *userbuf, MPI_Datatype datatype,PetscMPIInt count,void *filebuf, MPI_Offset position,void *extra_state)
    768: {
    769:   PetscDataType pdtype;
    770:   PetscMPIInt   ierr;
    771:   size_t        dsize;

    773:   PetscMPIDataTypeToPetscDataType(datatype,&pdtype);
    774:   PetscDataTypeGetSize(pdtype,&dsize);

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

    779:   PetscMemcpy(filebuf,userbuf,count*dsize);
    780:   PetscByteSwap(filebuf,pdtype,count);
    781:   return ierr;
    782: }
    783: #endif

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

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

    798: PetscErrorCode MPIU_File_read_all(MPI_File fd,void *data,PetscMPIInt cnt,MPI_Datatype dtype,MPI_Status *status)
    799: {
    801:   PetscDataType  pdtype;

    804:   PetscMPIDataTypeToPetscDataType(dtype,&pdtype);
    805:   MPI_File_read_all(fd,data,cnt,dtype,status);
    806:   PetscByteSwap(data,pdtype,cnt);
    807:   return(0);
    808: }
    809: #endif
    810: #endif