xref: /petsc/src/sys/fileio/sysio.c (revision 95cbbfd359aa2cc7e96afc77b64e4c0540dc7b23)
1 
2 /*
3    This file contains simple binary read/write routines.
4  */
5 
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>
16 
17 const char *const PetscFileModes[] = {"READ","WRITE","APPEND","UPDATE","APPEND_UPDATE","PetscFileMode","PETSC_FILE_",0};
18 
19 /* --------------------------------------------------------- */
20 /*
21   PetscByteSwapEnum - Swap bytes in a  PETSc Enum
22 
23 */
24 PetscErrorCode  PetscByteSwapEnum(PetscEnum *buff,PetscInt n)
25 {
26   PetscInt  i,j;
27   PetscEnum tmp = ENUM_DUMMY;
28   char      *ptr1,*ptr2 = (char*)&tmp;
29 
30   PetscFunctionBegin;
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   PetscFunctionReturn(0);
37 }
38 
39 /*
40   PetscByteSwapBool - Swap bytes in a  PETSc Bool
41 
42 */
43 PetscErrorCode  PetscByteSwapBool(PetscBool *buff,PetscInt n)
44 {
45   PetscInt  i,j;
46   PetscBool tmp = PETSC_FALSE;
47   char      *ptr1,*ptr2 = (char*)&tmp;
48 
49   PetscFunctionBegin;
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   PetscFunctionReturn(0);
56 }
57 
58 /*
59   PetscByteSwapInt - Swap bytes in a  PETSc integer (which may be 32 or 64 bits)
60 
61 */
62 PetscErrorCode  PetscByteSwapInt(PetscInt *buff,PetscInt n)
63 {
64   PetscInt i,j,tmp = 0;
65   char     *ptr1,*ptr2 = (char*)&tmp;
66 
67   PetscFunctionBegin;
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   PetscFunctionReturn(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;
84 
85   PetscFunctionBegin;
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   PetscFunctionReturn(0);
92 }
93 /*
94   PetscByteSwapLong - Swap bytes in a long
95 */
96 PetscErrorCode  PetscByteSwapLong(long *buff,PetscInt n)
97 {
98   PetscInt i,j;
99   long     tmp;
100   char     *ptr1,*ptr2 = (char*)&tmp;
101 
102   PetscFunctionBegin;
103   for (j=0; j<n; j++) {
104     ptr1 = (char*)(buff + j);
105     for (i=0; i<(PetscInt) sizeof(long); i++) ptr2[i] = ptr1[sizeof(long)-1-i];
106     for (i=0; i<(PetscInt) sizeof(long); i++) ptr1[i] = ptr2[i];
107   }
108   PetscFunctionReturn(0);
109 }
110 /* --------------------------------------------------------- */
111 /*
112   PetscByteSwapReal - Swap bytes in a PetscReal
113 */
114 PetscErrorCode  PetscByteSwapReal(PetscReal *buff,PetscInt n)
115 {
116   PetscInt  i,j;
117   PetscReal tmp,*buff1 = (PetscReal*)buff;
118   char      *ptr1,*ptr2 = (char*)&tmp;
119 
120   PetscFunctionBegin;
121   for (j=0; j<n; j++) {
122     ptr1 = (char*)(buff1 + j);
123     for (i=0; i<(PetscInt) sizeof(PetscReal); i++) ptr2[i] = ptr1[sizeof(PetscReal)-1-i];
124     for (i=0; i<(PetscInt) sizeof(PetscReal); i++) ptr1[i] = ptr2[i];
125   }
126   PetscFunctionReturn(0);
127 }
128 /* --------------------------------------------------------- */
129 /*
130   PetscByteSwapScalar - Swap bytes in a PetscScalar
131   The complex case is dealt with with an array of PetscReal, twice as long.
132 */
133 PetscErrorCode  PetscByteSwapScalar(PetscScalar *buff,PetscInt n)
134 {
135   PetscInt  i,j;
136   PetscReal tmp,*buff1 = (PetscReal*)buff;
137   char      *ptr1,*ptr2 = (char*)&tmp;
138 
139   PetscFunctionBegin;
140 #if defined(PETSC_USE_COMPLEX)
141   n *= 2;
142 #endif
143   for (j=0; j<n; j++) {
144     ptr1 = (char*)(buff1 + j);
145     for (i=0; i<(PetscInt) sizeof(PetscReal); i++) ptr2[i] = ptr1[sizeof(PetscReal)-1-i];
146     for (i=0; i<(PetscInt) sizeof(PetscReal); i++) ptr1[i] = ptr2[i];
147   }
148   PetscFunctionReturn(0);
149 }
150 /* --------------------------------------------------------- */
151 /*
152   PetscByteSwapDouble - Swap bytes in a double
153 */
154 PetscErrorCode  PetscByteSwapDouble(double *buff,PetscInt n)
155 {
156   PetscInt i,j;
157   double   tmp,*buff1 = (double*)buff;
158   char     *ptr1,*ptr2 = (char*)&tmp;
159 
160   PetscFunctionBegin;
161   for (j=0; j<n; j++) {
162     ptr1 = (char*)(buff1 + j);
163     for (i=0; i<(PetscInt) sizeof(double); i++) ptr2[i] = ptr1[sizeof(double)-1-i];
164     for (i=0; i<(PetscInt) sizeof(double); i++) ptr1[i] = ptr2[i];
165   }
166   PetscFunctionReturn(0);
167 }
168 
169 /*
170   PetscByteSwapFloat - Swap bytes in a float
171 */
172 PetscErrorCode PetscByteSwapFloat(float *buff,PetscInt n)
173 {
174   PetscInt i,j;
175   float    tmp,*buff1 = (float*)buff;
176   char     *ptr1,*ptr2 = (char*)&tmp;
177 
178   PetscFunctionBegin;
179   for (j=0; j<n; j++) {
180     ptr1 = (char*)(buff1 + j);
181     for (i=0; i<(PetscInt) sizeof(float); i++) ptr2[i] = ptr1[sizeof(float)-1-i];
182     for (i=0; i<(PetscInt) sizeof(float); i++) ptr1[i] = ptr2[i];
183   }
184   PetscFunctionReturn(0);
185 }
186 
187 PetscErrorCode PetscByteSwap(void *data,PetscDataType pdtype,PetscInt count)
188 {
189   PetscErrorCode ierr;
190 
191   PetscFunctionBegin;
192   if      (pdtype == PETSC_INT)    {ierr = PetscByteSwapInt((PetscInt*)data,count);CHKERRQ(ierr);}
193   else if (pdtype == PETSC_ENUM)   {ierr = PetscByteSwapEnum((PetscEnum*)data,count);CHKERRQ(ierr);}
194   else if (pdtype == PETSC_BOOL)   {ierr = PetscByteSwapBool((PetscBool*)data,count);CHKERRQ(ierr);}
195   else if (pdtype == PETSC_SCALAR) {ierr = PetscByteSwapScalar((PetscScalar*)data,count);CHKERRQ(ierr);}
196   else if (pdtype == PETSC_REAL)   {ierr = PetscByteSwapReal((PetscReal*)data,count);CHKERRQ(ierr);}
197   else if (pdtype == PETSC_DOUBLE) {ierr = PetscByteSwapDouble((double*)data,count);CHKERRQ(ierr);}
198   else if (pdtype == PETSC_FLOAT)  {ierr = PetscByteSwapFloat((float*)data,count);CHKERRQ(ierr);}
199   else if (pdtype == PETSC_SHORT)  {ierr = PetscByteSwapShort((short*)data,count);CHKERRQ(ierr);}
200   else if (pdtype == PETSC_LONG)   {ierr = PetscByteSwapLong((long*)data,count);CHKERRQ(ierr);}
201   PetscFunctionReturn(0);
202 }
203 
204 /* --------------------------------------------------------- */
205 /*@
206    PetscBinaryRead - Reads from a binary file.
207 
208    Not Collective
209 
210    Input Parameters:
211 +  fd - the file
212 .  n  - the number of items to read
213 -  type - the type of items to read (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)
214 
215    Output Parameters:
216 .  p - the buffer
217 
218 
219 
220    Level: developer
221 
222    Notes:
223    PetscBinaryRead() uses byte swapping to work on all machines; the files
224    are written to file ALWAYS using big-endian ordering. On small-endian machines the numbers
225    are converted to the small-endian format when they are read in from the file.
226    When PETSc is ./configure with --with-64bit-indices the integers are written to the
227    file as 64 bit integers, this means they can only be read back in when the option --with-64bit-indices
228    is used.
229 
230    Concepts: files^reading binary
231    Concepts: binary files^reading
232 
233 .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscViewerBinaryGetDescriptor(), PetscBinarySynchronizedWrite(),
234           PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek()
235 @*/
236 PetscErrorCode  PetscBinaryRead(int fd,void *p,PetscInt n,PetscDataType type)
237 {
238   int               wsize,err;
239   size_t            m = (size_t) n,maxblock = 65536;
240   char              *pp = (char*)p;
241 #if defined(PETSC_USE_REAL___FLOAT128)
242   PetscBool         readdouble = PETSC_FALSE;
243   double            *ppp;
244 #endif
245 #if !defined(PETSC_WORDS_BIGENDIAN) || defined(PETSC_USE_REAL___FLOAT128)
246   PetscErrorCode    ierr;
247 #endif
248 #if !defined(PETSC_WORDS_BIGENDIAN)
249   void              *ptmp = p;
250 #endif
251   char              *fname = NULL;
252 
253   PetscFunctionBegin;
254   if (n < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Trying to write a negative amount of data %D",n);
255   if (!n) PetscFunctionReturn(0);
256 
257   if (type == PETSC_FUNCTION) {
258     m            = 64;
259     type         = PETSC_CHAR;
260     fname        = (char*) malloc(m*sizeof(char));
261     if (!fname) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Cannot allocate space for function name");
262     pp           = (char*)fname;
263 #if !defined(PETSC_WORDS_BIGENDIAN)
264     ptmp         = (void*)fname;
265 #endif
266   }
267 
268   if (type == PETSC_INT)          m *= sizeof(PetscInt);
269   else if (type == PETSC_SCALAR)  m *= sizeof(PetscScalar);
270   else if (type == PETSC_REAL)    m *= sizeof(PetscReal);
271   else if (type == PETSC_DOUBLE)  m *= sizeof(double);
272   else if (type == PETSC_FLOAT)   m *= sizeof(float);
273   else if (type == PETSC_SHORT)   m *= sizeof(short);
274   else if (type == PETSC_LONG)    m *= sizeof(long);
275   else if (type == PETSC_CHAR)    m *= sizeof(char);
276   else if (type == PETSC_ENUM)    m *= sizeof(PetscEnum);
277   else if (type == PETSC_BOOL)    m *= sizeof(PetscBool);
278   else if (type == PETSC_BIT_LOGICAL) m  = PetscBTLength(m)*sizeof(char);
279   else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown type");
280 
281 #if defined(PETSC_USE_REAL___FLOAT128)
282   ierr = PetscOptionsGetBool(NULL,NULL,"-binary_read_double",&readdouble,NULL);CHKERRQ(ierr);
283   /* If using __float128 precision we still read in doubles from file */
284   if ((type == PETSC_SCALAR || type == PETSC_REAL) && readdouble) {
285     m    = m/2;
286     ierr = PetscMalloc1(n,&ppp);CHKERRQ(ierr);
287     pp   = (char*)ppp;
288   }
289 #endif
290 
291   while (m) {
292     wsize = (m < maxblock) ? m : maxblock;
293     err   = read(fd,pp,wsize);
294     if (err < 0 && errno == EINTR) continue;
295     if (!err && wsize > 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_READ,"Read past end of file");
296     if (err < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_READ,"Error reading from file, errno %d",errno);
297     m  -= err;
298     pp += err;
299   }
300 
301 #if defined(PETSC_USE_REAL___FLOAT128)
302   if ((type == PETSC_SCALAR || type == PETSC_REAL) && readdouble) {
303     PetscScalar *pv = (PetscScalar*) p;
304     PetscInt    i;
305 #if !defined(PETSC_WORDS_BIGENDIAN)
306     ierr = PetscByteSwapDouble(ppp,n);CHKERRQ(ierr);
307 #endif
308     for (i=0; i<n; i++) pv[i] = ppp[i];
309     ierr = PetscFree(ppp);CHKERRQ(ierr);
310     PetscFunctionReturn(0);
311   }
312 #endif
313 
314 #if !defined(PETSC_WORDS_BIGENDIAN)
315   ierr = PetscByteSwap(ptmp,type,n);CHKERRQ(ierr);
316 #endif
317 
318   if (type == PETSC_FUNCTION) {
319 #if defined(PETSC_SERIALIZE_FUNCTIONS)
320     ierr = PetscDLSym(NULL,fname,(void**)p);CHKERRQ(ierr);
321 #else
322     *(void**)p = NULL;
323 #endif
324     free(fname);
325   }
326   PetscFunctionReturn(0);
327 }
328 /* --------------------------------------------------------- */
329 /*@
330    PetscBinaryWrite - Writes to a binary file.
331 
332    Not Collective
333 
334    Input Parameters:
335 +  fd     - the file
336 .  p      - the buffer
337 .  n      - the number of items to write
338 .  type   - the type of items to read (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)
339 -  istemp - PETSC_FALSE if buffer data should be preserved, PETSC_TRUE otherwise.
340 
341    Level: advanced
342 
343    Notes:
344    PetscBinaryWrite() uses byte swapping to work on all machines; the files
345    are written using big-endian ordering to the file. On small-endian machines the numbers
346    are converted to the big-endian format when they are written to disk.
347    When PETSc is ./configure with --with-64bit-indices the integers are written to the
348    file as 64 bit integers, this means they can only be read back in when the option --with-64bit-indices
349    is used.
350 
351    If running with __float128 precision the output is in __float128 unless one uses the -binary_write_double option
352 
353    The Buffer p should be read-write buffer, and not static data.
354    This way, byte-swapping is done in-place, and then the buffer is
355    written to the file.
356 
357    This routine restores the original contents of the buffer, after
358    it is written to the file. This is done by byte-swapping in-place
359    the second time. If the flag istemp is set to PETSC_TRUE, the second
360    byte-swapping operation is not done, thus saving some computation,
361    but the buffer is left corrupted.
362 
363    Because byte-swapping may be done on the values in data it cannot be declared const
364 
365    Concepts: files^writing binary
366    Concepts: binary files^writing
367 
368 .seealso: PetscBinaryRead(), PetscBinaryOpen(), PetscBinaryClose(), PetscViewerBinaryGetDescriptor(), PetscBinarySynchronizedWrite(),
369           PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek()
370 @*/
371 PetscErrorCode  PetscBinaryWrite(int fd,void *p,PetscInt n,PetscDataType type,PetscBool  istemp)
372 {
373   char           *pp = (char*)p;
374   int            err,wsize;
375   size_t         m = (size_t)n,maxblock=65536;
376   PetscErrorCode ierr;
377 #if !defined(PETSC_WORDS_BIGENDIAN)
378   void           *ptmp = p;
379 #endif
380   char           *fname = NULL;
381 #if defined(PETSC_USE_REAL___FLOAT128)
382   PetscBool      writedouble = PETSC_FALSE;
383   double         *ppp;
384   PetscReal      *pv;
385   PetscInt       i;
386 #endif
387   PetscDataType  wtype = type;
388 
389   PetscFunctionBegin;
390   if (n < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Trying to write a negative amount of data %D",n);
391   if (!n) PetscFunctionReturn(0);
392 
393   if (type == PETSC_FUNCTION) {
394 #if defined(PETSC_SERIALIZE_FUNCTIONS)
395     const char *fnametmp;
396 #endif
397     m     = 64;
398     fname = (char*)malloc(m*sizeof(char));
399     if (!fname) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Cannot allocate space for function name");
400 #if defined(PETSC_SERIALIZE_FUNCTIONS)
401     if (n > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Can only binary view a single function at a time");
402     ierr = PetscFPTFind(*(void**)p,&fnametmp);CHKERRQ(ierr);
403     ierr = PetscStrncpy(fname,fnametmp,m);CHKERRQ(ierr);
404 #else
405     ierr = PetscStrncpy(fname,"",m);CHKERRQ(ierr);
406 #endif
407     wtype = PETSC_CHAR;
408     pp    = (char*)fname;
409 #if !defined(PETSC_WORDS_BIGENDIAN)
410     ptmp  = (void*)fname;
411 #endif
412   }
413 
414 #if defined(PETSC_USE_REAL___FLOAT128)
415   ierr = PetscOptionsGetBool(NULL,NULL,"-binary_write_double",&writedouble,NULL);CHKERRQ(ierr);
416   /* If using __float128 precision we still write in doubles to file */
417   if ((type == PETSC_SCALAR || type == PETSC_REAL) && writedouble) {
418     wtype = PETSC_DOUBLE;
419     ierr = PetscMalloc1(n,&ppp);CHKERRQ(ierr);
420     pv = (PetscReal*)pp;
421     for (i=0; i<n; i++) {
422       ppp[i] = (double) pv[i];
423     }
424     pp   = (char*)ppp;
425     ptmp = (char*)ppp;
426   }
427 #endif
428 
429   if (wtype == PETSC_INT)          m *= sizeof(PetscInt);
430   else if (wtype == PETSC_SCALAR)  m *= sizeof(PetscScalar);
431   else if (wtype == PETSC_REAL)    m *= sizeof(PetscReal);
432   else if (wtype == PETSC_DOUBLE)  m *= sizeof(double);
433   else if (wtype == PETSC_FLOAT)   m *= sizeof(float);
434   else if (wtype == PETSC_SHORT)   m *= sizeof(short);
435   else if (wtype == PETSC_LONG)    m *= sizeof(long);
436   else if (wtype == PETSC_CHAR)    m *= sizeof(char);
437   else if (wtype == PETSC_ENUM)    m *= sizeof(PetscEnum);
438   else if (wtype == PETSC_BOOL)    m *= sizeof(PetscBool);
439   else if (wtype == PETSC_BIT_LOGICAL) m = PetscBTLength(m)*sizeof(char);
440   else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown type");
441 
442 #if !defined(PETSC_WORDS_BIGENDIAN)
443   ierr = PetscByteSwap(ptmp,wtype,n);CHKERRQ(ierr);
444 #endif
445 
446   while (m) {
447     wsize = (m < maxblock) ? m : maxblock;
448     err   = write(fd,pp,wsize);
449     if (err < 0 && errno == EINTR) continue;
450     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);
451     m  -= wsize;
452     pp += wsize;
453   }
454 
455 #if !defined(PETSC_WORDS_BIGENDIAN)
456   if (!istemp) {
457     ierr = PetscByteSwap(ptmp,wtype,n);CHKERRQ(ierr);
458   }
459 #endif
460   if (type == PETSC_FUNCTION) {
461     free(fname);
462   }
463 #if defined(PETSC_USE_REAL___FLOAT128)
464   if ((type == PETSC_SCALAR || type == PETSC_REAL) && writedouble) {
465     ierr = PetscFree(ppp);CHKERRQ(ierr);
466   }
467 #endif
468   PetscFunctionReturn(0);
469 }
470 
471 /*@C
472    PetscBinaryOpen - Opens a PETSc binary file.
473 
474    Not Collective
475 
476    Input Parameters:
477 +  name - filename
478 -  type - type of binary file, one of FILE_MODE_READ, FILE_MODE_APPEND, FILE_MODE_WRITE
479 
480    Output Parameter:
481 .  fd - the file
482 
483    Level: advanced
484 
485   Concepts: files^opening binary
486   Concepts: binary files^opening
487 
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.
492 
493 .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscFileMode, PetscViewerFileSetMode(), PetscViewerBinaryGetDescriptor(),
494           PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek()
495 
496 @*/
497 PetscErrorCode  PetscBinaryOpen(const char name[],PetscFileMode mode,int *fd)
498 {
499   PetscFunctionBegin;
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   PetscFunctionReturn(0);
518 }
519 
520 /*@
521    PetscBinaryClose - Closes a PETSc binary file.
522 
523    Not Collective
524 
525    Output Parameter:
526 .  fd - the file
527 
528    Level: advanced
529 
530 .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
531           PetscBinarySynchronizedSeek()
532 @*/
533 PetscErrorCode  PetscBinaryClose(int fd)
534 {
535   PetscFunctionBegin;
536   close(fd);
537   PetscFunctionReturn(0);
538 }
539 
540 
541 /*@C
542    PetscBinarySeek - Moves the file pointer on a PETSc binary file.
543 
544    Not Collective
545 
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
553 
554    Output Parameter:
555 .   offset - new offset in file
556 
557    Level: developer
558 
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.
564 
565    Concepts: files^binary seeking
566    Concepts: binary files^seeking
567 
568 .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
569           PetscBinarySynchronizedSeek()
570 @*/
571 PetscErrorCode  PetscBinarySeek(int fd,off_t off,PetscBinarySeekType whence,off_t *offset)
572 {
573   int iwhence = 0;
574 
575   PetscFunctionBegin;
576   if (whence == PETSC_BINARY_SEEK_SET) iwhence = SEEK_SET;
577   else if (whence == PETSC_BINARY_SEEK_CUR) iwhence = SEEK_CUR;
578   else if (whence == PETSC_BINARY_SEEK_END) iwhence = SEEK_END;
579   else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown seek location");
580 #if defined(PETSC_HAVE_LSEEK)
581   *offset = lseek(fd,off,iwhence);
582 #elif defined(PETSC_HAVE__LSEEK)
583   *offset = _lseek(fd,(long)off,iwhence);
584 #else
585   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS,"System does not have a way of seeking on a file");
586 #endif
587   PetscFunctionReturn(0);
588 }
589 
590 /*@C
591    PetscBinarySynchronizedRead - Reads from a binary file.
592 
593    Collective on MPI_Comm
594 
595    Input Parameters:
596 +  comm - the MPI communicator
597 .  fd - the file
598 .  n  - the number of items to read
599 -  type - the type of items to read (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)
600 
601    Output Parameters:
602 .  p - the buffer
603 
604    Level: developer
605 
606    Notes:
607    Does a PetscBinaryRead() followed by an MPI_Bcast()
608 
609    PetscBinarySynchronizedRead() uses byte swapping to work on all machines.
610    Integers are stored on the file as 32 long, regardless of whether
611    they are stored in the machine as 32 or 64, this means the same
612    binary file may be read on any machine.
613 
614    Concepts: files^synchronized reading of binary files
615    Concepts: binary files^reading, synchronized
616 
617 .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscBinaryRead(), PetscBinarySynchronizedWrite(),
618           PetscBinarySynchronizedSeek()
619 @*/
620 PetscErrorCode  PetscBinarySynchronizedRead(MPI_Comm comm,int fd,void *p,PetscInt n,PetscDataType type)
621 {
622   PetscErrorCode ierr,ierrp=0;
623   PetscMPIInt    rank;
624   MPI_Datatype   mtype;
625   char           *fname = NULL;
626   void           *ptmp = NULL;
627 
628   PetscFunctionBegin;
629   if (type == PETSC_FUNCTION) {
630     n            = 64;
631     type         = PETSC_CHAR;
632     ptmp         = p;
633     fname        = (char*)malloc(n*sizeof(char));
634     if (!fname) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Cannot allocate space for function name");
635     p            = (void*)fname;
636   }
637 
638   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
639   if (!rank) {
640     ierrp = PetscBinaryRead(fd,p,n,type);
641   }
642   ierr = MPI_Bcast(&ierrp,1,MPI_INT,0,comm);CHKERRQ(ierr);
643   CHKERRQ(ierrp);
644   ierr = PetscDataTypeToMPIDataType(type,&mtype);CHKERRQ(ierr);
645   ierr = MPI_Bcast(p,n,mtype,0,comm);CHKERRQ(ierr);
646 
647   if (type == PETSC_FUNCTION) {
648 #if defined(PETSC_SERIALIZE_FUNCTIONS)
649     ierr = PetscDLLibrarySym(PETSC_COMM_SELF,&PetscDLLibrariesLoaded,NULL,fname,(void**)ptmp);CHKERRQ(ierr);
650 #else
651     *(void**)ptmp = NULL;
652 #endif
653     free(fname);
654   }
655   PetscFunctionReturn(0);
656 }
657 
658 /*@C
659    PetscBinarySynchronizedWrite - writes to a binary file.
660 
661    Collective on MPI_Comm
662 
663    Input Parameters:
664 +  comm - the MPI communicator
665 .  fd - the file
666 .  n  - the number of items to write
667 .  p - the buffer
668 .  istemp - the buffer may be changed
669 -  type - the type of items to write (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)
670 
671    Level: developer
672 
673    Notes:
674    Process 0 does a PetscBinaryWrite()
675 
676    PetscBinarySynchronizedWrite() uses byte swapping to work on all machines.
677    Integers are stored on the file as 32 long, regardless of whether
678    they are stored in the machine as 32 or 64, this means the same
679    binary file may be read on any machine.
680 
681    Notes:
682     because byte-swapping may be done on the values in data it cannot be declared const
683 
684    WARNING: This is NOT like PetscSynchronizedFPrintf()! This routine ignores calls on all but process 0,
685    while PetscSynchronizedFPrintf() has all processes print their strings in order.
686 
687    Concepts: files^synchronized writing of binary files
688    Concepts: binary files^reading, synchronized
689 
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 {
695   PetscErrorCode ierr;
696   PetscMPIInt    rank;
697 
698   PetscFunctionBegin;
699   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
700   if (!rank) {
701     ierr = PetscBinaryWrite(fd,p,n,type,istemp);CHKERRQ(ierr);
702   }
703   PetscFunctionReturn(0);
704 }
705 
706 /*@C
707    PetscBinarySynchronizedSeek - Moves the file pointer on a PETSc binary file.
708 
709 
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.
717 
718    Output Parameter:
719 .   offset - new offset in file
720 
721    Level: developer
722 
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.
728 
729    Concepts: binary files^seeking
730    Concepts: files^seeking in binary
731 
732 .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
733           PetscBinarySynchronizedSeek()
734 @*/
735 PetscErrorCode  PetscBinarySynchronizedSeek(MPI_Comm comm,int fd,off_t off,PetscBinarySeekType whence,off_t *offset)
736 {
737   PetscErrorCode ierr;
738   PetscMPIInt    rank;
739 
740   PetscFunctionBegin;
741   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
742   if (!rank) {
743     ierr = PetscBinarySeek(fd,off,whence,offset);CHKERRQ(ierr);
744   }
745   PetscFunctionReturn(0);
746 }
747 
748 #if defined(PETSC_HAVE_MPIIO)
749 #if !defined(PETSC_WORDS_BIGENDIAN)
750 
751 #if defined(PETSC_USE_PETSC_MPI_EXTERNAL32)
752 /*
753       MPICH does not provide the external32 representation for MPI_File_set_view() so we need to provide the functions.
754     These are set into MPI in PetscInitialize() via MPI_Register_datarep()
755 
756     Note I use PetscMPIInt for the MPI error codes since that is what MPI uses (instead of the standard PetscErrorCode)
757 
758     The next three routines are not used because MPICH does not support their use
759 
760 */
761 PETSC_EXTERN PetscMPIInt PetscDataRep_extent_fn(MPI_Datatype datatype,MPI_Aint *file_extent,void *extra_state)
762 {
763   MPI_Aint    ub;
764   PetscMPIInt ierr;
765 
766   ierr = MPI_Type_get_extent(datatype,&ub,file_extent);
767   return ierr;
768 }
769 
770 PETSC_EXTERN PetscMPIInt PetscDataRep_read_conv_fn(void *userbuf, MPI_Datatype datatype,PetscMPIInt count,void *filebuf, MPI_Offset position,void *extra_state)
771 {
772   PetscDataType pdtype;
773   PetscMPIInt   ierr;
774   size_t        dsize;
775 
776   ierr = PetscMPIDataTypeToPetscDataType(datatype,&pdtype);CHKERRQ(ierr);
777   ierr = PetscDataTypeGetSize(pdtype,&dsize);CHKERRQ(ierr);
778 
779   /* offset is given in units of MPI_Datatype */
780   userbuf = ((char*)userbuf) + dsize*position;
781 
782   ierr = PetscMemcpy(userbuf,filebuf,count*dsize);CHKERRQ(ierr);
783   ierr = PetscByteSwap(userbuf,pdtype,count);CHKERRQ(ierr);
784   return ierr;
785 }
786 
787 PetscMPIInt PetscDataRep_write_conv_fn(void *userbuf, MPI_Datatype datatype,PetscMPIInt count,void *filebuf, MPI_Offset position,void *extra_state)
788 {
789   PetscDataType pdtype;
790   PetscMPIInt   ierr;
791   size_t        dsize;
792 
793   ierr = PetscMPIDataTypeToPetscDataType(datatype,&pdtype);CHKERRQ(ierr);
794   ierr = PetscDataTypeGetSize(pdtype,&dsize);CHKERRQ(ierr);
795 
796   /* offset is given in units of MPI_Datatype */
797   userbuf = ((char*)userbuf) + dsize*position;
798 
799   ierr = PetscMemcpy(filebuf,userbuf,count*dsize);CHKERRQ(ierr);
800   ierr = PetscByteSwap(filebuf,pdtype,count);CHKERRQ(ierr);
801   return ierr;
802 }
803 #endif
804 
805 PetscErrorCode MPIU_File_write_all(MPI_File fd,void *data,PetscMPIInt cnt,MPI_Datatype dtype,MPI_Status *status)
806 {
807   PetscErrorCode ierr;
808   PetscDataType  pdtype;
809 
810   PetscFunctionBegin;
811   ierr = PetscMPIDataTypeToPetscDataType(dtype,&pdtype);CHKERRQ(ierr);
812   ierr = PetscByteSwap(data,pdtype,cnt);CHKERRQ(ierr);
813   ierr = MPI_File_write_all(fd,data,cnt,dtype,status);CHKERRQ(ierr);
814   ierr = PetscByteSwap(data,pdtype,cnt);CHKERRQ(ierr);
815   PetscFunctionReturn(0);
816 }
817 
818 PetscErrorCode MPIU_File_read_all(MPI_File fd,void *data,PetscMPIInt cnt,MPI_Datatype dtype,MPI_Status *status)
819 {
820   PetscErrorCode ierr;
821   PetscDataType  pdtype;
822 
823   PetscFunctionBegin;
824   ierr = PetscMPIDataTypeToPetscDataType(dtype,&pdtype);CHKERRQ(ierr);
825   ierr = MPI_File_read_all(fd,data,cnt,dtype,status);CHKERRQ(ierr);
826   ierr = PetscByteSwap(data,pdtype,cnt);CHKERRQ(ierr);
827   PetscFunctionReturn(0);
828 }
829 #endif
830 #endif
831