Actual source code: sysio.c

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

 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_INT64)  {PetscByteSwapInt64((PetscInt64*)data,count);}
218:   else if (pdtype == PETSC_DOUBLE) {PetscByteSwapDouble((double*)data,count);}
219:   else if (pdtype == PETSC_FLOAT)  {PetscByteSwapFloat((float*)data,count);}
220:   else if (pdtype == PETSC_SHORT)  {PetscByteSwapShort((short*)data,count);}
221:   else if (pdtype == PETSC_LONG)   {PetscByteSwapLong((long*)data,count);}
222:   return(0);
223: }

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

229:    Not Collective

231:    Input Parameters:
232: +  fd - the file
233: .  n  - the number of items to read
234: -  type - the type of items to read (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)

236:    Output Parameters:
237: .  p - the buffer



241:    Level: developer

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

251:    Concepts: files^reading binary
252:    Concepts: binary files^reading

254: .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscViewerBinaryGetDescriptor(), PetscBinarySynchronizedWrite(),
255:           PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek()
256: @*/
257: PetscErrorCode  PetscBinaryRead(int fd,void *p,PetscInt n,PetscDataType type)
258: {
259:   int               wsize,err;
260:   size_t            m = (size_t) n,maxblock = 65536;
261:   char              *pp = (char*)p;
262: #if defined(PETSC_USE_REAL___FLOAT128)
263:   PetscBool         readdouble = PETSC_FALSE;
264:   double            *ppp;
265: #endif
266: #if !defined(PETSC_WORDS_BIGENDIAN) || defined(PETSC_USE_REAL___FLOAT128)
267:   PetscErrorCode    ierr;
268: #endif
269: #if !defined(PETSC_WORDS_BIGENDIAN)
270:   void              *ptmp = p;
271: #endif
272:   char              *fname = NULL;

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

278:   if (type == PETSC_FUNCTION) {
279:     m            = 64;
280:     type         = PETSC_CHAR;
281:     fname        = (char*) malloc(m*sizeof(char));
282:     if (!fname) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Cannot allocate space for function name");
283:     pp           = (char*)fname;
284: #if !defined(PETSC_WORDS_BIGENDIAN)
285:     ptmp         = (void*)fname;
286: #endif
287:   }

289:   if (type == PETSC_INT)          m *= sizeof(PetscInt);
290:   else if (type == PETSC_SCALAR)  m *= sizeof(PetscScalar);
291:   else if (type == PETSC_REAL)    m *= sizeof(PetscReal);
292:   else if (type == PETSC_DOUBLE)  m *= sizeof(double);
293:   else if (type == PETSC_FLOAT)   m *= sizeof(float);
294:   else if (type == PETSC_SHORT)   m *= sizeof(short);
295:   else if (type == PETSC_LONG)    m *= sizeof(long);
296:   else if (type == PETSC_CHAR)    m *= sizeof(char);
297:   else if (type == PETSC_ENUM)    m *= sizeof(PetscEnum);
298:   else if (type == PETSC_BOOL)    m *= sizeof(PetscBool);
299:   else if (type == PETSC_INT64)   m *= sizeof(PetscInt64);
300:   else if (type == PETSC_BIT_LOGICAL) m  = PetscBTLength(m)*sizeof(char);
301:   else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown type");

303: #if defined(PETSC_USE_REAL___FLOAT128)
304:   PetscOptionsGetBool(NULL,NULL,"-binary_read_double",&readdouble,NULL);
305:   /* If using __float128 precision we still read in doubles from file */
306:   if ((type == PETSC_SCALAR || type == PETSC_REAL) && readdouble) {
307:     m    = m/2;
308:     PetscMalloc1(n,&ppp);
309:     pp   = (char*)ppp;
310:   }
311: #endif

313:   while (m) {
314:     wsize = (m < maxblock) ? m : maxblock;
315:     err   = read(fd,pp,wsize);
316:     if (err < 0 && errno == EINTR) continue;
317:     if (!err && wsize > 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_READ,"Read past end of file");
318:     if (err < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_READ,"Error reading from file, errno %d",errno);
319:     m  -= err;
320:     pp += err;
321:   }

323: #if defined(PETSC_USE_REAL___FLOAT128)
324:   if ((type == PETSC_SCALAR || type == PETSC_REAL) && readdouble) {
325:     PetscScalar *pv = (PetscScalar*) p;
326:     PetscInt    i;
327: #if !defined(PETSC_WORDS_BIGENDIAN)
328:     PetscByteSwapDouble(ppp,n);
329: #endif
330:     for (i=0; i<n; i++) pv[i] = ppp[i];
331:     PetscFree(ppp);
332:     return(0);
333:   }
334: #endif

336: #if !defined(PETSC_WORDS_BIGENDIAN)
337:   PetscByteSwap(ptmp,type,n);
338: #endif

340:   if (type == PETSC_FUNCTION) {
341: #if defined(PETSC_SERIALIZE_FUNCTIONS)
342:     PetscDLSym(NULL,fname,(void**)p);
343: #else
344:     *(void**)p = NULL;
345: #endif
346:     free(fname);
347:   }
348:   return(0);
349: }
350: /* --------------------------------------------------------- */
351: /*@
352:    PetscBinaryWrite - Writes to a binary file.

354:    Not Collective

356:    Input Parameters:
357: +  fd     - the file
358: .  p      - the buffer
359: .  n      - the number of items to write
360: .  type   - the type of items to read (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)
361: -  istemp - PETSC_FALSE if buffer data should be preserved, PETSC_TRUE otherwise.

363:    Level: advanced

365:    Notes:
366:    PetscBinaryWrite() uses byte swapping to work on all machines; the files
367:    are written using big-endian ordering to the file. On small-endian machines the numbers
368:    are converted to the big-endian format when they are written to disk.
369:    When PETSc is ./configure with --with-64bit-indices the integers are written to the
370:    file as 64 bit integers, this means they can only be read back in when the option --with-64bit-indices
371:    is used.

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

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

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

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

387:    Concepts: files^writing binary
388:    Concepts: binary files^writing

390: .seealso: PetscBinaryRead(), PetscBinaryOpen(), PetscBinaryClose(), PetscViewerBinaryGetDescriptor(), PetscBinarySynchronizedWrite(),
391:           PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek()
392: @*/
393: PetscErrorCode  PetscBinaryWrite(int fd,void *p,PetscInt n,PetscDataType type,PetscBool  istemp)
394: {
395:   char           *pp = (char*)p;
396:   int            err,wsize;
397:   size_t         m = (size_t)n,maxblock=65536;
399: #if !defined(PETSC_WORDS_BIGENDIAN)
400:   void           *ptmp = p;
401: #endif
402:   char           *fname = NULL;
403: #if defined(PETSC_USE_REAL___FLOAT128)
404:   PetscBool      writedouble = PETSC_FALSE;
405:   double         *ppp;
406:   PetscReal      *pv;
407:   PetscInt       i;
408: #endif
409:   PetscDataType  wtype = type;

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

415:   if (type == PETSC_FUNCTION) {
416: #if defined(PETSC_SERIALIZE_FUNCTIONS)
417:     const char *fnametmp;
418: #endif
419:     m     = 64;
420:     fname = (char*)malloc(m*sizeof(char));
421:     if (!fname) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Cannot allocate space for function name");
422: #if defined(PETSC_SERIALIZE_FUNCTIONS)
423:     if (n > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Can only binary view a single function at a time");
424:     PetscFPTFind(*(void**)p,&fnametmp);
425:     PetscStrncpy(fname,fnametmp,m);
426: #else
427:     PetscStrncpy(fname,"",m);
428: #endif
429:     wtype = PETSC_CHAR;
430:     pp    = (char*)fname;
431: #if !defined(PETSC_WORDS_BIGENDIAN)
432:     ptmp  = (void*)fname;
433: #endif
434:   }

436: #if defined(PETSC_USE_REAL___FLOAT128)
437:   PetscOptionsGetBool(NULL,NULL,"-binary_write_double",&writedouble,NULL);
438:   /* If using __float128 precision we still write in doubles to file */
439:   if ((type == PETSC_SCALAR || type == PETSC_REAL) && writedouble) {
440:     wtype = PETSC_DOUBLE;
441:     PetscMalloc1(n,&ppp);
442:     pv = (PetscReal*)pp;
443:     for (i=0; i<n; i++) {
444:       ppp[i] = (double) pv[i];
445:     }
446:     pp   = (char*)ppp;
447:     ptmp = (char*)ppp;
448:   }
449: #endif

451:   if (wtype == PETSC_INT)          m *= sizeof(PetscInt);
452:   else if (wtype == PETSC_SCALAR)  m *= sizeof(PetscScalar);
453:   else if (wtype == PETSC_REAL)    m *= sizeof(PetscReal);
454:   else if (wtype == PETSC_DOUBLE)  m *= sizeof(double);
455:   else if (wtype == PETSC_FLOAT)   m *= sizeof(float);
456:   else if (wtype == PETSC_SHORT)   m *= sizeof(short);
457:   else if (wtype == PETSC_LONG)    m *= sizeof(long);
458:   else if (wtype == PETSC_CHAR)    m *= sizeof(char);
459:   else if (wtype == PETSC_ENUM)    m *= sizeof(PetscEnum);
460:   else if (wtype == PETSC_BOOL)    m *= sizeof(PetscBool);
461:   else if (wtype == PETSC_INT64)   m *= sizeof(PetscInt64);
462:   else if (wtype == PETSC_BIT_LOGICAL) m = PetscBTLength(m)*sizeof(char);
463:   else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown type");

465: #if !defined(PETSC_WORDS_BIGENDIAN)
466:   PetscByteSwap(ptmp,wtype,n);
467: #endif

469:   while (m) {
470:     wsize = (m < maxblock) ? m : maxblock;
471:     err   = write(fd,pp,wsize);
472:     if (err < 0 && errno == EINTR) continue;
473:     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);
474:     m  -= wsize;
475:     pp += wsize;
476:   }

478: #if !defined(PETSC_WORDS_BIGENDIAN)
479:   if (!istemp) {
480:     PetscByteSwap(ptmp,wtype,n);
481:   }
482: #endif
483:   if (type == PETSC_FUNCTION) {
484:     free(fname);
485:   }
486: #if defined(PETSC_USE_REAL___FLOAT128)
487:   if ((type == PETSC_SCALAR || type == PETSC_REAL) && writedouble) {
488:     PetscFree(ppp);
489:   }
490: #endif
491:   return(0);
492: }

494: /*@C
495:    PetscBinaryOpen - Opens a PETSc binary file.

497:    Not Collective

499:    Input Parameters:
500: +  name - filename
501: -  type - type of binary file, one of FILE_MODE_READ, FILE_MODE_APPEND, FILE_MODE_WRITE

503:    Output Parameter:
504: .  fd - the file

506:    Level: advanced

508:   Concepts: files^opening binary
509:   Concepts: binary files^opening

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

516: .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscFileMode, PetscViewerFileSetMode(), PetscViewerBinaryGetDescriptor(),
517:           PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek()

519: @*/
520: PetscErrorCode  PetscBinaryOpen(const char name[],PetscFileMode mode,int *fd)
521: {
523: #if defined(PETSC_HAVE_O_BINARY)
524:   if (mode == FILE_MODE_WRITE) {
525:     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);
526:   } else if (mode == FILE_MODE_READ) {
527:     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);
528:   } else if (mode == FILE_MODE_APPEND) {
529:     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);
530: #else
531:   if (mode == FILE_MODE_WRITE) {
532:     if ((*fd = creat(name,0666)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot create file for writing: %s",name);
533:   } else if (mode == FILE_MODE_READ) {
534:     if ((*fd = open(name,O_RDONLY,0)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file for reading: %s",name);
535:   }
536:   else if (mode == FILE_MODE_APPEND) {
537:     if ((*fd = open(name,O_WRONLY,0)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file for writing: %s",name);
538: #endif
539:   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown file mode");
540:   return(0);
541: }

543: /*@
544:    PetscBinaryClose - Closes a PETSc binary file.

546:    Not Collective

548:    Output Parameter:
549: .  fd - the file

551:    Level: advanced

553: .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
554:           PetscBinarySynchronizedSeek()
555: @*/
556: PetscErrorCode  PetscBinaryClose(int fd)
557: {
559:   close(fd);
560:   return(0);
561: }


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

567:    Not Collective

569:    Input Parameters:
570: +  fd - the file
571: .  off - number of bytes to move. Use PETSC_BINARY_INT_SIZE, PETSC_BINARY_SCALAR_SIZE,
572:             etc. in your calculation rather than sizeof() to compute byte lengths.
573: -  whence - if PETSC_BINARY_SEEK_SET then off is an absolute location in the file
574:             if PETSC_BINARY_SEEK_CUR then off is an offset from the current location
575:             if PETSC_BINARY_SEEK_END then off is an offset from the end of file

577:    Output Parameter:
578: .   offset - new offset in file

580:    Level: developer

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

588:    Concepts: files^binary seeking
589:    Concepts: binary files^seeking

591: .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
592:           PetscBinarySynchronizedSeek()
593: @*/
594: PetscErrorCode  PetscBinarySeek(int fd,off_t off,PetscBinarySeekType whence,off_t *offset)
595: {
596:   int iwhence = 0;

599:   if (whence == PETSC_BINARY_SEEK_SET) iwhence = SEEK_SET;
600:   else if (whence == PETSC_BINARY_SEEK_CUR) iwhence = SEEK_CUR;
601:   else if (whence == PETSC_BINARY_SEEK_END) iwhence = SEEK_END;
602:   else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown seek location");
603: #if defined(PETSC_HAVE_LSEEK)
604:   *offset = lseek(fd,off,iwhence);
605: #elif defined(PETSC_HAVE__LSEEK)
606:   *offset = _lseek(fd,(long)off,iwhence);
607: #else
608:   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS,"System does not have a way of seeking on a file");
609: #endif
610:   return(0);
611: }

613: /*@C
614:    PetscBinarySynchronizedRead - Reads from a binary file.

616:    Collective on MPI_Comm

618:    Input Parameters:
619: +  comm - the MPI communicator
620: .  fd - the file
621: .  n  - the number of items to read
622: -  type - the type of items to read (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)

624:    Output Parameters:
625: .  p - the buffer

627:    Level: developer

629:    Notes:
630:    Does a PetscBinaryRead() followed by an MPI_Bcast()

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

637:    Concepts: files^synchronized reading of binary files
638:    Concepts: binary files^reading, synchronized

640: .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscBinaryRead(), PetscBinarySynchronizedWrite(),
641:           PetscBinarySynchronizedSeek()
642: @*/
643: PetscErrorCode  PetscBinarySynchronizedRead(MPI_Comm comm,int fd,void *p,PetscInt n,PetscDataType type)
644: {
645:   PetscErrorCode ierr,ierrp=0;
646:   PetscMPIInt    rank;
647:   MPI_Datatype   mtype;
648:   char           *fname = NULL;
649:   void           *ptmp = NULL;

652:   if (type == PETSC_FUNCTION) {
653:     n            = 64;
654:     type         = PETSC_CHAR;
655:     ptmp         = p;
656:     fname        = (char*)malloc(n*sizeof(char));
657:     if (!fname) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Cannot allocate space for function name");
658:     p            = (void*)fname;
659:   }

661:   MPI_Comm_rank(comm,&rank);
662:   if (!rank) {
663:     ierrp = PetscBinaryRead(fd,p,n,type);
664:   }
665:   MPI_Bcast(&ierrp,1,MPI_INT,0,comm);
666:   CHKERRQ(ierrp);
667:   PetscDataTypeToMPIDataType(type,&mtype);
668:   MPI_Bcast(p,n,mtype,0,comm);

670:   if (type == PETSC_FUNCTION) {
671: #if defined(PETSC_SERIALIZE_FUNCTIONS)
672:     PetscDLLibrarySym(PETSC_COMM_SELF,&PetscDLLibrariesLoaded,NULL,fname,(void**)ptmp);
673: #else
674:     *(void**)ptmp = NULL;
675: #endif
676:     free(fname);
677:   }
678:   return(0);
679: }

681: /*@C
682:    PetscBinarySynchronizedWrite - writes to a binary file.

684:    Collective on MPI_Comm

686:    Input Parameters:
687: +  comm - the MPI communicator
688: .  fd - the file
689: .  n  - the number of items to write
690: .  p - the buffer
691: .  istemp - the buffer may be changed
692: -  type - the type of items to write (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)

694:    Level: developer

696:    Notes:
697:    Process 0 does a PetscBinaryWrite()

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

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

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

710:    Concepts: files^synchronized writing of binary files
711:    Concepts: binary files^reading, synchronized

713: .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscBinaryRead(), PetscBinarySynchronizedRead(),
714:           PetscBinarySynchronizedSeek()
715: @*/
716: PetscErrorCode  PetscBinarySynchronizedWrite(MPI_Comm comm,int fd,void *p,PetscInt n,PetscDataType type,PetscBool istemp)
717: {
719:   PetscMPIInt    rank;

722:   MPI_Comm_rank(comm,&rank);
723:   if (!rank) {
724:     PetscBinaryWrite(fd,p,n,type,istemp);
725:   }
726:   return(0);
727: }

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


733:    Input Parameters:
734: +  fd - the file
735: .  whence - if PETSC_BINARY_SEEK_SET then size is an absolute location in the file
736:             if PETSC_BINARY_SEEK_CUR then size is offset from current location
737:             if PETSC_BINARY_SEEK_END then size is offset from end of file
738: -  off    - number of bytes to move. Use PETSC_BINARY_INT_SIZE, PETSC_BINARY_SCALAR_SIZE,
739:             etc. in your calculation rather than sizeof() to compute byte lengths.

741:    Output Parameter:
742: .   offset - new offset in file

744:    Level: developer

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

752:    Concepts: binary files^seeking
753:    Concepts: files^seeking in binary

755: .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
756:           PetscBinarySynchronizedSeek()
757: @*/
758: PetscErrorCode  PetscBinarySynchronizedSeek(MPI_Comm comm,int fd,off_t off,PetscBinarySeekType whence,off_t *offset)
759: {
761:   PetscMPIInt    rank;

764:   MPI_Comm_rank(comm,&rank);
765:   if (!rank) {
766:     PetscBinarySeek(fd,off,whence,offset);
767:   }
768:   return(0);
769: }

771: #if defined(PETSC_HAVE_MPIIO)
772: #if !defined(PETSC_WORDS_BIGENDIAN)

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

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

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

783: */
784: PETSC_EXTERN PetscMPIInt PetscDataRep_extent_fn(MPI_Datatype datatype,MPI_Aint *file_extent,void *extra_state)
785: {
786:   MPI_Aint    ub;
787:   PetscMPIInt ierr;

789:   MPI_Type_get_extent(datatype,&ub,file_extent);
790:   return ierr;
791: }

793: PETSC_EXTERN PetscMPIInt PetscDataRep_read_conv_fn(void *userbuf, MPI_Datatype datatype,PetscMPIInt count,void *filebuf, MPI_Offset position,void *extra_state)
794: {
795:   PetscDataType pdtype;
796:   PetscMPIInt   ierr;
797:   size_t        dsize;

799:   PetscMPIDataTypeToPetscDataType(datatype,&pdtype);
800:   PetscDataTypeGetSize(pdtype,&dsize);

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

805:   PetscMemcpy(userbuf,filebuf,count*dsize);
806:   PetscByteSwap(userbuf,pdtype,count);
807:   return ierr;
808: }

810: PetscMPIInt PetscDataRep_write_conv_fn(void *userbuf, MPI_Datatype datatype,PetscMPIInt count,void *filebuf, MPI_Offset position,void *extra_state)
811: {
812:   PetscDataType pdtype;
813:   PetscMPIInt   ierr;
814:   size_t        dsize;

816:   PetscMPIDataTypeToPetscDataType(datatype,&pdtype);
817:   PetscDataTypeGetSize(pdtype,&dsize);

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

822:   PetscMemcpy(filebuf,userbuf,count*dsize);
823:   PetscByteSwap(filebuf,pdtype,count);
824:   return ierr;
825: }
826: #endif

828: PetscErrorCode MPIU_File_write_all(MPI_File fd,void *data,PetscMPIInt cnt,MPI_Datatype dtype,MPI_Status *status)
829: {
831:   PetscDataType  pdtype;

834:   PetscMPIDataTypeToPetscDataType(dtype,&pdtype);
835:   PetscByteSwap(data,pdtype,cnt);
836:   MPI_File_write_all(fd,data,cnt,dtype,status);
837:   PetscByteSwap(data,pdtype,cnt);
838:   return(0);
839: }

841: PetscErrorCode MPIU_File_read_all(MPI_File fd,void *data,PetscMPIInt cnt,MPI_Datatype dtype,MPI_Status *status)
842: {
844:   PetscDataType  pdtype;

847:   PetscMPIDataTypeToPetscDataType(dtype,&pdtype);
848:   MPI_File_read_all(fd,data,cnt,dtype,status);
849:   PetscByteSwap(data,pdtype,cnt);
850:   return(0);
851: }
852: #endif
853: #endif