Actual source code: sysio.c

petsc-master 2019-09-18
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: }

 76: /*
 77:   PetscByteSwapInt64 - Swap bytes in a  PETSc integer (64 bits)

 79: */
 80: PetscErrorCode  PetscByteSwapInt64(PetscInt64 *buff,PetscInt n)
 81: {
 82:   PetscInt   i,j;
 83:   PetscInt64 tmp = 0;
 84:   char       *ptr1,*ptr2 = (char*)&tmp;

 87:   for (j=0; j<n; j++) {
 88:     ptr1 = (char*)(buff + j);
 89:     for (i=0; i<(PetscInt)sizeof(PetscInt64); i++) ptr2[i] = ptr1[sizeof(PetscInt64)-1-i];
 90:     for (i=0; i<(PetscInt)sizeof(PetscInt64); i++) ptr1[i] = ptr2[i];
 91:   }
 92:   return(0);
 93: }

 95: /* --------------------------------------------------------- */
 96: /*
 97:   PetscByteSwapShort - Swap bytes in a short
 98: */
 99: PetscErrorCode  PetscByteSwapShort(short *buff,PetscInt n)
100: {
101:   PetscInt i,j;
102:   short    tmp;
103:   char     *ptr1,*ptr2 = (char*)&tmp;

106:   for (j=0; j<n; j++) {
107:     ptr1 = (char*)(buff + j);
108:     for (i=0; i<(PetscInt) sizeof(short); i++) ptr2[i] = ptr1[sizeof(short)-1-i];
109:     for (i=0; i<(PetscInt) sizeof(short); i++) ptr1[i] = ptr2[i];
110:   }
111:   return(0);
112: }
113: /*
114:   PetscByteSwapLong - Swap bytes in a long
115: */
116: PetscErrorCode  PetscByteSwapLong(long *buff,PetscInt n)
117: {
118:   PetscInt i,j;
119:   long     tmp;
120:   char     *ptr1,*ptr2 = (char*)&tmp;

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

141:   for (j=0; j<n; j++) {
142:     ptr1 = (char*)(buff1 + j);
143:     for (i=0; i<(PetscInt) sizeof(PetscReal); i++) ptr2[i] = ptr1[sizeof(PetscReal)-1-i];
144:     for (i=0; i<(PetscInt) sizeof(PetscReal); i++) ptr1[i] = ptr2[i];
145:   }
146:   return(0);
147: }
148: /* --------------------------------------------------------- */
149: /*
150:   PetscByteSwapScalar - Swap bytes in a PetscScalar
151:   The complex case is dealt with with an array of PetscReal, twice as long.
152: */
153: PetscErrorCode  PetscByteSwapScalar(PetscScalar *buff,PetscInt n)
154: {
155:   PetscInt  i,j;
156:   PetscReal tmp,*buff1 = (PetscReal*)buff;
157:   char      *ptr1,*ptr2 = (char*)&tmp;

160: #if defined(PETSC_USE_COMPLEX)
161:   n *= 2;
162: #endif
163:   for (j=0; j<n; j++) {
164:     ptr1 = (char*)(buff1 + j);
165:     for (i=0; i<(PetscInt) sizeof(PetscReal); i++) ptr2[i] = ptr1[sizeof(PetscReal)-1-i];
166:     for (i=0; i<(PetscInt) sizeof(PetscReal); i++) ptr1[i] = ptr2[i];
167:   }
168:   return(0);
169: }
170: /* --------------------------------------------------------- */
171: /*
172:   PetscByteSwapDouble - Swap bytes in a double
173: */
174: PetscErrorCode  PetscByteSwapDouble(double *buff,PetscInt n)
175: {
176:   PetscInt i,j;
177:   double   tmp,*buff1 = (double*)buff;
178:   char     *ptr1,*ptr2 = (char*)&tmp;

181:   for (j=0; j<n; j++) {
182:     ptr1 = (char*)(buff1 + j);
183:     for (i=0; i<(PetscInt) sizeof(double); i++) ptr2[i] = ptr1[sizeof(double)-1-i];
184:     for (i=0; i<(PetscInt) sizeof(double); i++) ptr1[i] = ptr2[i];
185:   }
186:   return(0);
187: }

189: /*
190:   PetscByteSwapFloat - Swap bytes in a float
191: */
192: PetscErrorCode PetscByteSwapFloat(float *buff,PetscInt n)
193: {
194:   PetscInt i,j;
195:   float    tmp,*buff1 = (float*)buff;
196:   char     *ptr1,*ptr2 = (char*)&tmp;

199:   for (j=0; j<n; j++) {
200:     ptr1 = (char*)(buff1 + j);
201:     for (i=0; i<(PetscInt) sizeof(float); i++) ptr2[i] = ptr1[sizeof(float)-1-i];
202:     for (i=0; i<(PetscInt) sizeof(float); i++) ptr1[i] = ptr2[i];
203:   }
204:   return(0);
205: }

207: PetscErrorCode PetscByteSwap(void *data,PetscDataType pdtype,PetscInt count)
208: {

212:   if      (pdtype == PETSC_INT)    {PetscByteSwapInt((PetscInt*)data,count);}
213:   else if (pdtype == PETSC_ENUM)   {PetscByteSwapEnum((PetscEnum*)data,count);}
214:   else if (pdtype == PETSC_BOOL)   {PetscByteSwapBool((PetscBool*)data,count);}
215:   else if (pdtype == PETSC_SCALAR) {PetscByteSwapScalar((PetscScalar*)data,count);}
216:   else if (pdtype == PETSC_REAL)   {PetscByteSwapReal((PetscReal*)data,count);}
217:   else if (pdtype == PETSC_COMPLEX){PetscByteSwapReal((PetscReal*)data,2*count);}
218:   else if (pdtype == PETSC_INT64)  {PetscByteSwapInt64((PetscInt64*)data,count);}
219:   else if (pdtype == PETSC_DOUBLE) {PetscByteSwapDouble((double*)data,count);}
220:   else if (pdtype == PETSC_FLOAT)  {PetscByteSwapFloat((float*)data,count);}
221:   else if (pdtype == PETSC_SHORT)  {PetscByteSwapShort((short*)data,count);}
222:   else if (pdtype == PETSC_LONG)   {PetscByteSwapLong((long*)data,count);}
223:   return(0);
224: }

226: /*@C
227:    PetscBinaryRead - Reads from a binary file.

229:    Not Collective

231:    Input Parameters:
232: +  fd - the file descriptor
233: .  num  - the maximum number of items to read
234: -  type - the type of items to read (PETSC_INT, PETSC_REAL, PETSC_SCALAR, etc.)

236:    Output Parameters:
237: +  data - the buffer
238: -  count - the number of items read, optional



242:    Level: developer

244:    Notes:
245:    If count is not provided and the number of items read is less than
246:    the maximum number of items to read, then this routine errors.

248:    PetscBinaryRead() uses byte swapping to work on all machines; the files
249:    are written to file ALWAYS using big-endian ordering. On small-endian machines the numbers
250:    are converted to the small-endian format when they are read in from the file.
251:    When PETSc is ./configure with --with-64bit-indices the integers are written to the
252:    file as 64 bit integers, this means they can only be read back in when the option --with-64bit-indices
253:    is used.


256: .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscViewerBinaryGetDescriptor(), PetscBinarySynchronizedWrite(),
257:           PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek()
258: @*/
259: PetscErrorCode  PetscBinaryRead(int fd,void *data,PetscInt num,PetscInt *count,PetscDataType type)
260: {
261:   size_t            typesize, m = (size_t) num, n = 0, maxblock = 65536;
262:   char              *p = (char*)data;
263: #if defined(PETSC_USE_REAL___FLOAT128)
264:   PetscBool         readdouble = PETSC_FALSE;
265:   double            *pdouble;
266: #endif
267:   void              *ptmp = data;
268:   char              *fname = NULL;
269:   PetscErrorCode    ierr;

272:   if (count) *count = 0;
273:   if (num < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Trying to read a negative amount of data %D",num);
274:   if (!num) return(0);

276:   if (type == PETSC_FUNCTION) {
277:     m     = 64;
278:     type  = PETSC_CHAR;
279:     fname = (char*)malloc(m*sizeof(char));
280:     p     = (char*)fname;
281:     ptmp  = (void*)fname;
282:     if (!fname) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Cannot allocate space for function name");
283:   }
284:   if (type == PETSC_BIT_LOGICAL) m = PetscBTLength(m);

286:   PetscDataTypeGetSize(type,&typesize);

288: #if defined(PETSC_USE_REAL___FLOAT128)
289:   PetscOptionsGetBool(NULL,NULL,"-binary_read_double",&readdouble,NULL);
290:   /* If using __float128 precision we still read in doubles from file */
291:   if ((type == PETSC_REAL || type == PETSC_COMPLEX) && readdouble) {
292:     PetscInt cnt = num * ((type == PETSC_REAL) ? 1 : 2);
293:     PetscMalloc1(cnt,&pdouble);
294:     p = (char*)pdouble;
295:     typesize /= 2;
296:   }
297: #endif

299:   m *= typesize;

301:   while (m) {
302:     size_t len = (m < maxblock) ? m : maxblock;
303:     int    ret = (int)read(fd,p,len);
304:     if (ret < 0 && errno == EINTR) continue;
305:     if (!ret && len > 0) break; /* Proxy for EOF */
306:     if (ret < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_READ,"Error reading from file, errno %d",errno);
307:     m -= ret;
308:     p += ret;
309:     n += ret;
310:   }
311:   if (m && !count) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_READ,"Read past end of file");

313:   num = (PetscInt)(n/typesize); /* Should we require `n % typesize == 0` ? */
314:   if (count) *count = num;      /* TODO: This is most likely wrong for PETSC_BIT_LOGICAL */

316: #if defined(PETSC_USE_REAL___FLOAT128)
317:   if ((type == PETSC_REAL || type == PETSC_COMPLEX) && readdouble) {
318:     PetscInt  i, cnt = num * ((type == PETSC_REAL) ? 1 : 2);
319:     PetscReal *preal = (PetscReal*)data;
320:     if (!PetscBinaryBigEndian()) {PetscByteSwapDouble(pdouble,cnt);}
321:     for (i=0; i<cnt; i++) preal[i] = pdouble[i];
322:     PetscFree(pdouble);
323:     return(0);
324:   }
325: #endif

327:   if (!PetscBinaryBigEndian()) {PetscByteSwap(ptmp,type,num);}

329:   if (type == PETSC_FUNCTION) {
330: #if defined(PETSC_SERIALIZE_FUNCTIONS)
331:     PetscDLSym(NULL,fname,(void**)data);
332: #else
333:     *(void**)data = NULL;
334: #endif
335:     free(fname);
336:   }
337:   return(0);
338: }

340: /*@C
341:    PetscBinaryWrite - Writes to a binary file.

343:    Not Collective

345:    Input Parameters:
346: +  fd     - the file
347: .  p      - the buffer
348: .  n      - the number of items to write
349: .  type   - the type of items to read (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)
350: -  istemp - PETSC_FALSE if buffer data should be preserved, PETSC_TRUE otherwise.

352:    Level: advanced

354:    Notes:
355:    PetscBinaryWrite() uses byte swapping to work on all machines; the files
356:    are written using big-endian ordering to the file. On small-endian machines the numbers
357:    are converted to the big-endian format when they are written to disk.
358:    When PETSc is ./configure with --with-64bit-indices the integers are written to the
359:    file as 64 bit integers, this means they can only be read back in when the option --with-64bit-indices
360:    is used.

362:    If running with __float128 precision the output is in __float128 unless one uses the -binary_write_double option

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

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

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


377: .seealso: PetscBinaryRead(), PetscBinaryOpen(), PetscBinaryClose(), PetscViewerBinaryGetDescriptor(), PetscBinarySynchronizedWrite(),
378:           PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek()
379: @*/
380: PetscErrorCode  PetscBinaryWrite(int fd,void *p,PetscInt n,PetscDataType type,PetscBool  istemp)
381: {
382:   char           *pp = (char*)p;
383:   int            err,wsize;
384:   size_t         m = (size_t)n,maxblock=65536;
386:   void           *ptmp = p;
387:   char           *fname = NULL;
388: #if defined(PETSC_USE_REAL___FLOAT128)
389:   PetscBool      writedouble = PETSC_FALSE;
390:   double         *ppp;
391:   PetscReal      *pv;
392:   PetscInt       i;
393: #endif
394:   PetscDataType  wtype = type;

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

400:   if (type == PETSC_FUNCTION) {
401: #if defined(PETSC_SERIALIZE_FUNCTIONS)
402:     const char *fnametmp;
403: #endif
404:     m     = 64;
405:     fname = (char*)malloc(m*sizeof(char));
406:     if (!fname) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Cannot allocate space for function name");
407: #if defined(PETSC_SERIALIZE_FUNCTIONS)
408:     if (n > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Can only binary view a single function at a time");
409:     PetscFPTFind(*(void**)p,&fnametmp);
410:     PetscStrncpy(fname,fnametmp,m);
411: #else
412:     PetscStrncpy(fname,"",m);
413: #endif
414:     wtype = PETSC_CHAR;
415:     pp    = (char*)fname;
416:     ptmp  = (void*)fname;
417:   }

419: #if defined(PETSC_USE_REAL___FLOAT128)
420:   PetscOptionsGetBool(NULL,NULL,"-binary_write_double",&writedouble,NULL);
421:   /* If using __float128 precision we still write in doubles to file */
422:   if ((type == PETSC_SCALAR || type == PETSC_REAL) && writedouble) {
423:     wtype = PETSC_DOUBLE;
424:     PetscMalloc1(n,&ppp);
425:     pv = (PetscReal*)pp;
426:     for (i=0; i<n; i++) {
427:       ppp[i] = (double) pv[i];
428:     }
429:     pp   = (char*)ppp;
430:     ptmp = (char*)ppp;
431:   }
432: #endif

434:   if (wtype == PETSC_INT)          m *= sizeof(PetscInt);
435:   else if (wtype == PETSC_SCALAR)  m *= sizeof(PetscScalar);
436:   else if (wtype == PETSC_REAL)    m *= sizeof(PetscReal);
437:   else if (wtype == PETSC_DOUBLE)  m *= sizeof(double);
438:   else if (wtype == PETSC_FLOAT)   m *= sizeof(float);
439:   else if (wtype == PETSC_SHORT)   m *= sizeof(short);
440:   else if (wtype == PETSC_LONG)    m *= sizeof(long);
441:   else if (wtype == PETSC_CHAR)    m *= sizeof(char);
442:   else if (wtype == PETSC_ENUM)    m *= sizeof(PetscEnum);
443:   else if (wtype == PETSC_BOOL)    m *= sizeof(PetscBool);
444:   else if (wtype == PETSC_INT64)   m *= sizeof(PetscInt64);
445:   else if (wtype == PETSC_BIT_LOGICAL) m = PetscBTLength(m)*sizeof(char);
446:   else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown type");

448:   if (!PetscBinaryBigEndian()) {PetscByteSwap(ptmp,wtype,n);}

450:   while (m) {
451:     wsize = (m < maxblock) ? m : maxblock;
452:     err   = write(fd,pp,wsize);
453:     if (err < 0 && errno == EINTR) continue;
454:     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);
455:     m  -= wsize;
456:     pp += wsize;
457:   }

459:   if (!istemp) {
460:     if (!PetscBinaryBigEndian()) {PetscByteSwap(ptmp,wtype,n);}
461:   }
462:   if (type == PETSC_FUNCTION) {
463:     free(fname);
464:   }
465: #if defined(PETSC_USE_REAL___FLOAT128)
466:   if ((type == PETSC_SCALAR || type == PETSC_REAL) && writedouble) {
467:     PetscFree(ppp);
468:   }
469: #endif
470:   return(0);
471: }

473: /*@C
474:    PetscBinaryOpen - Opens a PETSc binary file.

476:    Not Collective

478:    Input Parameters:
479: +  name - filename
480: -  type - type of binary file, one of FILE_MODE_READ, FILE_MODE_APPEND, FILE_MODE_WRITE

482:    Output Parameter:
483: .  fd - the file

485:    Level: advanced


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

493: .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscFileMode, PetscViewerFileSetMode(), PetscViewerBinaryGetDescriptor(),
494:           PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek()

496: @*/
497: PetscErrorCode  PetscBinaryOpen(const char name[],PetscFileMode mode,int *fd)
498: {
500: #if defined(PETSC_HAVE_O_BINARY)
501:   if (mode == FILE_MODE_WRITE) {
502:     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);
503:   } else if (mode == FILE_MODE_READ) {
504:     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);
505:   } else if (mode == FILE_MODE_APPEND) {
506:     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);
507: #else
508:   if (mode == FILE_MODE_WRITE) {
509:     if ((*fd = creat(name,0666)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot create file for writing: %s",name);
510:   } else if (mode == FILE_MODE_READ) {
511:     if ((*fd = open(name,O_RDONLY,0)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file for reading: %s",name);
512:   }
513:   else if (mode == FILE_MODE_APPEND) {
514:     if ((*fd = open(name,O_WRONLY,0)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file for writing: %s",name);
515: #endif
516:   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown file mode");
517:   return(0);
518: }

520: /*@
521:    PetscBinaryClose - Closes a PETSc binary file.

523:    Not Collective

525:    Output Parameter:
526: .  fd - the file

528:    Level: advanced

530: .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
531:           PetscBinarySynchronizedSeek()
532: @*/
533: PetscErrorCode  PetscBinaryClose(int fd)
534: {
536:   close(fd);
537:   return(0);
538: }


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

544:    Not Collective

546:    Input Parameters:
547: +  fd - the file
548: .  off - number of bytes to move. Use PETSC_BINARY_INT_SIZE, PETSC_BINARY_SCALAR_SIZE,
549:             etc. in your calculation rather than sizeof() to compute byte lengths.
550: -  whence - if PETSC_BINARY_SEEK_SET then off is an absolute location in the file
551:             if PETSC_BINARY_SEEK_CUR then off is an offset from the current location
552:             if PETSC_BINARY_SEEK_END then off is an offset from the end of file

554:    Output Parameter:
555: .   offset - new offset in file

557:    Level: developer

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


566: .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
567:           PetscBinarySynchronizedSeek()
568: @*/
569: PetscErrorCode  PetscBinarySeek(int fd,off_t off,PetscBinarySeekType whence,off_t *offset)
570: {
571:   int iwhence = 0;

574:   if (whence == PETSC_BINARY_SEEK_SET) iwhence = SEEK_SET;
575:   else if (whence == PETSC_BINARY_SEEK_CUR) iwhence = SEEK_CUR;
576:   else if (whence == PETSC_BINARY_SEEK_END) iwhence = SEEK_END;
577:   else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown seek location");
578: #if defined(PETSC_HAVE_LSEEK)
579:   *offset = lseek(fd,off,iwhence);
580: #elif defined(PETSC_HAVE__LSEEK)
581:   *offset = _lseek(fd,(long)off,iwhence);
582: #else
583:   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS,"System does not have a way of seeking on a file");
584: #endif
585:   return(0);
586: }

588: /*@C
589:    PetscBinarySynchronizedRead - Reads from a binary file.

591:    Collective

593:    Input Parameters:
594: +  comm - the MPI communicator
595: .  fd - the file descriptor
596: .  num  - the maximum number of items to read
597: -  type - the type of items to read (PETSC_INT, PETSC_REAL, PETSC_SCALAR, etc.)

599:    Output Parameters:
600: +  data - the buffer
601: -  count - the number of items read, optional

603:    Level: developer

605:    Notes:
606:    Does a PetscBinaryRead() followed by an MPI_Bcast()

608:    If count is not provided and the number of items read is less than
609:    the maximum number of items to read, then this routine errors.

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


617: .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscBinaryRead(), PetscBinarySynchronizedWrite(),
618:           PetscBinarySynchronizedSeek()
619: @*/
620: PetscErrorCode  PetscBinarySynchronizedRead(MPI_Comm comm,int fd,void *data,PetscInt num,PetscInt *count,PetscDataType type)
621: {
623:   PetscMPIInt    rank;
624:   MPI_Datatype   mtype;
625:   PetscInt       ibuf[2] = {0, 0};
626:   char           *fname = NULL;
627:   void           *fptr = NULL;

630:   if (type == PETSC_FUNCTION) {
631:     num   = 64;
632:     type  = PETSC_CHAR;
633:     fname = (char*)malloc(num*sizeof(char));
634:     fptr  = data;
635:     data  = (void*)fname;
636:     if (!fname) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Cannot allocate space for function name");
637:   }

639:   MPI_Comm_rank(comm,&rank);
640:   if (!rank) {
641:     ibuf[0] = PetscBinaryRead(fd,data,num,count?&ibuf[1]:NULL,type);
642:   }
643:   MPI_Bcast(ibuf,2,MPIU_INT,0,comm);
644:   (PetscErrorCode)ibuf[0];
645:   PetscDataTypeToMPIDataType(type,&mtype);
646:   MPI_Bcast(data,count?ibuf[1]:num,mtype,0,comm);
647:   if (count) *count = ibuf[1];

649:   if (type == PETSC_FUNCTION) {
650: #if defined(PETSC_SERIALIZE_FUNCTIONS)
651:     PetscDLLibrarySym(PETSC_COMM_SELF,&PetscDLLibrariesLoaded,NULL,fname,(void**)fptr);
652: #else
653:     *(void**)fptr = NULL;
654: #endif
655:     free(fname);
656:   }
657:   return(0);
658: }

660: /*@C
661:    PetscBinarySynchronizedWrite - writes to a binary file.

663:    Collective

665:    Input Parameters:
666: +  comm - the MPI communicator
667: .  fd - the file
668: .  n  - the number of items to write
669: .  p - the buffer
670: .  istemp - the buffer may be changed
671: -  type - the type of items to write (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)

673:    Level: developer

675:    Notes:
676:    Process 0 does a PetscBinaryWrite()

678:    PetscBinarySynchronizedWrite() uses byte swapping to work on all machines.
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.

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

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


690: .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscBinaryRead(), PetscBinarySynchronizedRead(),
691:           PetscBinarySynchronizedSeek()
692: @*/
693: PetscErrorCode  PetscBinarySynchronizedWrite(MPI_Comm comm,int fd,void *p,PetscInt n,PetscDataType type,PetscBool istemp)
694: {
696:   PetscMPIInt    rank;

699:   MPI_Comm_rank(comm,&rank);
700:   if (!rank) {
701:     PetscBinaryWrite(fd,p,n,type,istemp);
702:   }
703:   return(0);
704: }

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


710:    Input Parameters:
711: +  fd - the file
712: .  whence - if PETSC_BINARY_SEEK_SET then size is an absolute location in the file
713:             if PETSC_BINARY_SEEK_CUR then size is offset from current location
714:             if PETSC_BINARY_SEEK_END then size is offset from end of file
715: -  off    - number of bytes to move. Use PETSC_BINARY_INT_SIZE, PETSC_BINARY_SCALAR_SIZE,
716:             etc. in your calculation rather than sizeof() to compute byte lengths.

718:    Output Parameter:
719: .   offset - new offset in file

721:    Level: developer

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


730: .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
731:           PetscBinarySynchronizedSeek()
732: @*/
733: PetscErrorCode  PetscBinarySynchronizedSeek(MPI_Comm comm,int fd,off_t off,PetscBinarySeekType whence,off_t *offset)
734: {
736:   PetscMPIInt    rank;

739:   MPI_Comm_rank(comm,&rank);
740:   if (!rank) {
741:     PetscBinarySeek(fd,off,whence,offset);
742:   }
743:   return(0);
744: }

746: #if defined(PETSC_HAVE_MPIIO)

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

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

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

757: */
758: PETSC_EXTERN PetscMPIInt PetscDataRep_extent_fn(MPI_Datatype datatype,MPI_Aint *file_extent,void *extra_state)
759: {
760:   MPI_Aint    ub;
761:   PetscMPIInt ierr;

763:   MPI_Type_get_extent(datatype,&ub,file_extent);
764:   return ierr;
765: }

767: PETSC_EXTERN PetscMPIInt PetscDataRep_read_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(userbuf,filebuf,count*dsize);
780:   if (!PetscBinaryBigEndian()) {PetscByteSwap(userbuf,pdtype,count);}
781:   return ierr;
782: }

784: PetscMPIInt PetscDataRep_write_conv_fn(void *userbuf, MPI_Datatype datatype,PetscMPIInt count,void *filebuf, MPI_Offset position,void *extra_state)
785: {
786:   PetscDataType pdtype;
787:   PetscMPIInt   ierr;
788:   size_t        dsize;

790:   PetscMPIDataTypeToPetscDataType(datatype,&pdtype);
791:   PetscDataTypeGetSize(pdtype,&dsize);

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

796:   PetscMemcpy(filebuf,userbuf,count*dsize);
797:   if (!PetscBinaryBigEndian()) {PetscByteSwap(filebuf,pdtype,count);}
798:   return ierr;
799: }
800: #endif

802: PetscErrorCode MPIU_File_write_all(MPI_File fd,void *data,PetscMPIInt cnt,MPI_Datatype dtype,MPI_Status *status)
803: {
804:   PetscDataType  pdtype;


809:   PetscMPIDataTypeToPetscDataType(dtype,&pdtype);
810:   if (!PetscBinaryBigEndian()) {PetscByteSwap(data,pdtype,cnt);}
811:   MPI_File_write_all(fd,data,cnt,dtype,status);
812:   if (!PetscBinaryBigEndian()) {PetscByteSwap(data,pdtype,cnt);}
813:   return(0);
814: }

816: PetscErrorCode MPIU_File_read_all(MPI_File fd,void *data,PetscMPIInt cnt,MPI_Datatype dtype,MPI_Status *status)
817: {
818:   PetscDataType  pdtype;

822:   PetscMPIDataTypeToPetscDataType(dtype,&pdtype);
823:   MPI_File_read_all(fd,data,cnt,dtype,status);
824:   if (!PetscBinaryBigEndian()) {PetscByteSwap(data,pdtype,cnt);}
825:   return(0);
826: }

828: #endif