Actual source code: sysio.c

petsc-3.7.2 2016-06-05
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