xref: /petsc/src/sys/fileio/sysio.c (revision bb1d7374b64f295b2ed5ff23b89435d65e905a54)
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 #undef __FUNCT__
21 #define __FUNCT__ "PetscByteSwapEnum"
22 /*
23   PetscByteSwapEnum - Swap bytes in a  PETSc Enum
24 
25 */
26 PetscErrorCode  PetscByteSwapEnum(PetscEnum *buff,PetscInt n)
27 {
28   PetscInt  i,j;
29   PetscEnum tmp = ENUM_DUMMY;
30   char      *ptr1,*ptr2 = (char*)&tmp;
31 
32   PetscFunctionBegin;
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   PetscFunctionReturn(0);
39 }
40 
41 #undef __FUNCT__
42 #define __FUNCT__ "PetscByteSwapBool"
43 /*
44   PetscByteSwapBool - Swap bytes in a  PETSc Bool
45 
46 */
47 PetscErrorCode  PetscByteSwapBool(PetscBool *buff,PetscInt n)
48 {
49   PetscInt  i,j;
50   PetscBool tmp = PETSC_FALSE;
51   char      *ptr1,*ptr2 = (char*)&tmp;
52 
53   PetscFunctionBegin;
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   PetscFunctionReturn(0);
60 }
61 
62 #undef __FUNCT__
63 #define __FUNCT__ "PetscByteSwapInt"
64 /*
65   PetscByteSwapInt - Swap bytes in a  PETSc integer (which may be 32 or 64 bits)
66 
67 */
68 PetscErrorCode  PetscByteSwapInt(PetscInt *buff,PetscInt n)
69 {
70   PetscInt i,j,tmp = 0;
71   char     *ptr1,*ptr2 = (char*)&tmp;
72 
73   PetscFunctionBegin;
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   PetscFunctionReturn(0);
80 }
81 /* --------------------------------------------------------- */
82 #undef __FUNCT__
83 #define __FUNCT__ "PetscByteSwapShort"
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;
92 
93   PetscFunctionBegin;
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   PetscFunctionReturn(0);
100 }
101 /* --------------------------------------------------------- */
102 #undef __FUNCT__
103 #define __FUNCT__ "PetscByteSwapScalar"
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;
113 
114   PetscFunctionBegin;
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   PetscFunctionReturn(0);
124 }
125 /* --------------------------------------------------------- */
126 #undef __FUNCT__
127 #define __FUNCT__ "PetscByteSwapDouble"
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;
136 
137   PetscFunctionBegin;
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   PetscFunctionReturn(0);
144 }
145 
146 #undef __FUNCT__
147 #define __FUNCT__ "PetscByteSwapFloat"
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;
156 
157   PetscFunctionBegin;
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   PetscFunctionReturn(0);
164 }
165 
166 #undef __FUNCT__
167 #define __FUNCT__ "PetscByteSwap"
168 PetscErrorCode PetscByteSwap(void *data,PetscDataType pdtype,PetscInt count)
169 {
170   PetscErrorCode ierr;
171 
172   PetscFunctionBegin;
173   if      (pdtype == PETSC_INT)    {ierr = PetscByteSwapInt((PetscInt*)data,count);CHKERRQ(ierr);}
174   else if (pdtype == PETSC_ENUM)   {ierr = PetscByteSwapEnum((PetscEnum*)data,count);CHKERRQ(ierr);}
175   else if (pdtype == PETSC_BOOL)   {ierr = PetscByteSwapBool((PetscBool*)data,count);CHKERRQ(ierr);}
176   else if (pdtype == PETSC_SCALAR) {ierr = PetscByteSwapScalar((PetscScalar*)data,count);CHKERRQ(ierr);}
177   else if (pdtype == PETSC_DOUBLE) {ierr = PetscByteSwapDouble((double*)data,count);CHKERRQ(ierr);}
178   else if (pdtype == PETSC_FLOAT)  {ierr = PetscByteSwapFloat((float*)data,count);CHKERRQ(ierr);}
179   else if (pdtype == PETSC_SHORT)  {ierr = PetscByteSwapShort((short*)data,count);CHKERRQ(ierr);}
180   PetscFunctionReturn(0);
181 }
182 
183 /* --------------------------------------------------------- */
184 #undef __FUNCT__
185 #define __FUNCT__ "PetscBinaryRead"
186 /*@
187    PetscBinaryRead - Reads from a binary file.
188 
189    Not Collective
190 
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)
195 
196    Output Parameters:
197 .  p - the buffer
198 
199 
200 
201    Level: developer
202 
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.
210 
211    Concepts: files^reading binary
212    Concepts: binary files^reading
213 
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;
233 
234   PetscFunctionBegin;
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) PetscFunctionReturn(0);
237 
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   }
248 
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");
259 
260 #if defined(PETSC_USE_REAL___FLOAT128)
261   ierr = PetscOptionsGetBool(NULL,"-binary_read_double",&readdouble,NULL);CHKERRQ(ierr);
262   /* If using __float128 precision we still read in doubles from file */
263   if (type == PETSC_SCALAR && readdouble) {
264     m    = m/2;
265     ierr = PetscMalloc1(n,&ppp);CHKERRQ(ierr);
266     pp   = (char*)ppp;
267   }
268 #endif
269 
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   }
279 
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     ierr = PetscByteSwapDouble(ppp,n);CHKERRQ(ierr);
286 #endif
287     for (i=0; i<n; i++) pv[i] = ppp[i];
288     ierr = PetscFree(ppp);CHKERRQ(ierr);
289     PetscFunctionReturn(0);
290   }
291 #endif
292 
293 #if !defined(PETSC_WORDS_BIGENDIAN)
294   ierr = PetscByteSwap(ptmp,type,n);CHKERRQ(ierr);
295 #endif
296 
297   if (type == PETSC_FUNCTION) {
298 #if defined(PETSC_SERIALIZE_FUNCTIONS)
299     ierr = PetscDLSym(NULL,fname,(void**)p);CHKERRQ(ierr);
300 #else
301     *(void**)p = NULL;
302 #endif
303     free(fname);
304   }
305   PetscFunctionReturn(0);
306 }
307 /* --------------------------------------------------------- */
308 #undef __FUNCT__
309 #define __FUNCT__ "PetscBinaryWrite"
310 /*@
311    PetscBinaryWrite - Writes to a binary file.
312 
313    Not Collective
314 
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.
321 
322    Level: advanced
323 
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.
331 
332    The Buffer p should be read-write buffer, and not static data.
333    This way, byte-swapping is done in-place, and then the buffer is
334    written to the file.
335 
336    This routine restores the original contents of the buffer, after
337    it is written to the file. This is done by byte-swapping in-place
338    the second time. If the flag istemp is set to PETSC_TRUE, the second
339    byte-swapping operation is not done, thus saving some computation,
340    but the buffer is left corrupted.
341 
342    Because byte-swapping may be done on the values in data it cannot be declared const
343 
344    Concepts: files^writing binary
345    Concepts: binary files^writing
346 
347 .seealso: PetscBinaryRead(), PetscBinaryOpen(), PetscBinaryClose(), PetscViewerBinaryGetDescriptor(), PetscBinarySynchronizedWrite(),
348           PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek()
349 @*/
350 PetscErrorCode  PetscBinaryWrite(int fd,void *p,PetscInt n,PetscDataType type,PetscBool  istemp)
351 {
352   char           *pp = (char*)p;
353   int            err,wsize;
354   size_t         m = (size_t)n,maxblock=65536;
355   PetscErrorCode ierr;
356 #if !defined(PETSC_WORDS_BIGENDIAN)
357   void           *ptmp = p;
358 #endif
359   char           *fname = NULL;
360 
361   PetscFunctionBegin;
362   if (n < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Trying to write a negative amount of data %D",n);
363   if (!n) PetscFunctionReturn(0);
364 
365   if (type == PETSC_FUNCTION) {
366 #if defined(PETSC_SERIALIZE_FUNCTIONS)
367     const char *fnametmp;
368 #endif
369     m     = 64;
370     fname = (char*)malloc(m*sizeof(char));
371     if (!fname) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Cannot allocate space for function name");
372 #if defined(PETSC_SERIALIZE_FUNCTIONS)
373     if (n > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Can only binary view a single function at a time");
374     ierr = PetscFPTFind(*(void**)p,&fnametmp);CHKERRQ(ierr);
375     ierr = PetscStrncpy(fname,fnametmp,m);CHKERRQ(ierr);
376 #else
377     ierr = PetscStrncpy(fname,"",m);CHKERRQ(ierr);
378 #endif
379     type = PETSC_CHAR;
380     pp   = (char*)fname;
381 #if !defined(PETSC_WORDS_BIGENDIAN)
382     ptmp = (void*)fname;
383 #endif
384   }
385 
386   if (type == PETSC_INT)          m *= sizeof(PetscInt);
387   else if (type == PETSC_SCALAR)  m *= sizeof(PetscScalar);
388   else if (type == PETSC_DOUBLE)  m *= sizeof(double);
389   else if (type == PETSC_FLOAT)   m *= sizeof(float);
390   else if (type == PETSC_SHORT)   m *= sizeof(short);
391   else if (type == PETSC_CHAR)    m *= sizeof(char);
392   else if (type == PETSC_ENUM)    m *= sizeof(PetscEnum);
393   else if (type == PETSC_BOOL)   m *= sizeof(PetscBool);
394   else if (type == PETSC_BIT_LOGICAL) m = PetscBTLength(m)*sizeof(char);
395   else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown type");
396 
397 #if !defined(PETSC_WORDS_BIGENDIAN)
398   ierr = PetscByteSwap(ptmp,type,n);CHKERRQ(ierr);
399 #endif
400 
401   while (m) {
402     wsize = (m < maxblock) ? m : maxblock;
403     err   = write(fd,pp,wsize);
404     if (err < 0 && errno == EINTR) continue;
405     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);
406     m  -= wsize;
407     pp += wsize;
408   }
409 
410 #if !defined(PETSC_WORDS_BIGENDIAN)
411   if (!istemp) {
412     ierr = PetscByteSwap(ptmp,type,n);CHKERRQ(ierr);
413   }
414 #endif
415   if (type == PETSC_FUNCTION) {
416     free(fname);
417   }
418   PetscFunctionReturn(0);
419 }
420 
421 #undef __FUNCT__
422 #define __FUNCT__ "PetscBinaryOpen"
423 /*@C
424    PetscBinaryOpen - Opens a PETSc binary file.
425 
426    Not Collective
427 
428    Input Parameters:
429 +  name - filename
430 -  type - type of binary file, one of FILE_MODE_READ, FILE_MODE_APPEND, FILE_MODE_WRITE
431 
432    Output Parameter:
433 .  fd - the file
434 
435    Level: advanced
436 
437   Concepts: files^opening binary
438   Concepts: binary files^opening
439 
440    Notes: Files access with PetscBinaryRead() and PetscBinaryWrite() are ALWAYS written in
441    big-endian format. This means the file can be accessed using PetscBinaryOpen() and
442    PetscBinaryRead() and PetscBinaryWrite() on any machine.
443 
444 .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscFileMode, PetscViewerFileSetMode(), PetscViewerBinaryGetDescriptor(),
445           PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek()
446 
447 @*/
448 PetscErrorCode  PetscBinaryOpen(const char name[],PetscFileMode mode,int *fd)
449 {
450   PetscFunctionBegin;
451 #if defined(PETSC_HAVE_O_BINARY)
452   if (mode == FILE_MODE_WRITE) {
453     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);
454   } else if (mode == FILE_MODE_READ) {
455     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);
456   } else if (mode == FILE_MODE_APPEND) {
457     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);
458 #else
459   if (mode == FILE_MODE_WRITE) {
460     if ((*fd = creat(name,0666)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot create file for writing: %s",name);
461   } else if (mode == FILE_MODE_READ) {
462     if ((*fd = open(name,O_RDONLY,0)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file for reading: %s",name);
463   }
464   else if (mode == FILE_MODE_APPEND) {
465     if ((*fd = open(name,O_WRONLY,0)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file for writing: %s",name);
466 #endif
467   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown file mode");
468   PetscFunctionReturn(0);
469 }
470 
471 #undef __FUNCT__
472 #define __FUNCT__ "PetscBinaryClose"
473 /*@
474    PetscBinaryClose - Closes a PETSc binary file.
475 
476    Not Collective
477 
478    Output Parameter:
479 .  fd - the file
480 
481    Level: advanced
482 
483 .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
484           PetscBinarySynchronizedSeek()
485 @*/
486 PetscErrorCode  PetscBinaryClose(int fd)
487 {
488   PetscFunctionBegin;
489   close(fd);
490   PetscFunctionReturn(0);
491 }
492 
493 
494 #undef __FUNCT__
495 #define __FUNCT__ "PetscBinarySeek"
496 /*@
497    PetscBinarySeek - Moves the file pointer on a PETSc binary file.
498 
499    Not Collective
500 
501    Input Parameters:
502 +  fd - the file
503 .  off - number of bytes to move. Use PETSC_BINARY_INT_SIZE, PETSC_BINARY_SCALAR_SIZE,
504             etc. in your calculation rather than sizeof() to compute byte lengths.
505 -  whence - if PETSC_BINARY_SEEK_SET then off is an absolute location in the file
506             if PETSC_BINARY_SEEK_CUR then off is an offset from the current location
507             if PETSC_BINARY_SEEK_END then off is an offset from the end of file
508 
509    Output Parameter:
510 .   offset - new offset in file
511 
512    Level: developer
513 
514    Notes:
515    Integers are stored on the file as 32 long, regardless of whether
516    they are stored in the machine as 32 or 64, this means the same
517    binary file may be read on any machine. Hence you CANNOT use sizeof()
518    to determine the offset or location.
519 
520    Concepts: files^binary seeking
521    Concepts: binary files^seeking
522 
523 .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
524           PetscBinarySynchronizedSeek()
525 @*/
526 PetscErrorCode  PetscBinarySeek(int fd,off_t off,PetscBinarySeekType whence,off_t *offset)
527 {
528   int iwhence = 0;
529 
530   PetscFunctionBegin;
531   if (whence == PETSC_BINARY_SEEK_SET) iwhence = SEEK_SET;
532   else if (whence == PETSC_BINARY_SEEK_CUR) iwhence = SEEK_CUR;
533   else if (whence == PETSC_BINARY_SEEK_END) iwhence = SEEK_END;
534   else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown seek location");
535 #if defined(PETSC_HAVE_LSEEK)
536   *offset = lseek(fd,off,iwhence);
537 #elif defined(PETSC_HAVE__LSEEK)
538   *offset = _lseek(fd,(long)off,iwhence);
539 #else
540   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS,"System does not have a way of seeking on a file");
541 #endif
542   PetscFunctionReturn(0);
543 }
544 
545 #undef __FUNCT__
546 #define __FUNCT__ "PetscBinarySynchronizedRead"
547 /*@C
548    PetscBinarySynchronizedRead - Reads from a binary file.
549 
550    Collective on MPI_Comm
551 
552    Input Parameters:
553 +  comm - the MPI communicator
554 .  fd - the file
555 .  n  - the number of items to read
556 -  type - the type of items to read (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)
557 
558    Output Parameters:
559 .  p - the buffer
560 
561    Level: developer
562 
563    Notes:
564    Does a PetscBinaryRead() followed by an MPI_Bcast()
565 
566    PetscBinarySynchronizedRead() uses byte swapping to work on all machines.
567    Integers are stored on the file as 32 long, regardless of whether
568    they are stored in the machine as 32 or 64, this means the same
569    binary file may be read on any machine.
570 
571    Concepts: files^synchronized reading of binary files
572    Concepts: binary files^reading, synchronized
573 
574 .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscBinaryRead(), PetscBinarySynchronizedWrite(),
575           PetscBinarySynchronizedSeek()
576 @*/
577 PetscErrorCode  PetscBinarySynchronizedRead(MPI_Comm comm,int fd,void *p,PetscInt n,PetscDataType type)
578 {
579   PetscErrorCode ierr;
580   PetscMPIInt    rank;
581   MPI_Datatype   mtype;
582   char           *fname = NULL;
583   void           *ptmp = NULL;
584 
585   PetscFunctionBegin;
586   if (type == PETSC_FUNCTION) {
587     n            = 64;
588     type         = PETSC_CHAR;
589     ptmp         = p;
590     fname        = (char*)malloc(n*sizeof(char));
591     if (!fname) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Cannot allocate space for function name");
592     p            = (void*)fname;
593   }
594 
595   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
596   if (!rank) {
597     ierr = PetscBinaryRead(fd,p,n,type);CHKERRQ(ierr);
598   }
599   ierr = PetscDataTypeToMPIDataType(type,&mtype);CHKERRQ(ierr);
600   ierr = MPI_Bcast(p,n,mtype,0,comm);CHKERRQ(ierr);
601 
602   if (type == PETSC_FUNCTION) {
603 #if defined(PETSC_SERIALIZE_FUNCTIONS)
604     ierr = PetscDLLibrarySym(PETSC_COMM_SELF,&PetscDLLibrariesLoaded,NULL,fname,(void**)ptmp);CHKERRQ(ierr);
605 #else
606     *(void**)ptmp = NULL;
607 #endif
608     free(fname);
609   }
610   PetscFunctionReturn(0);
611 }
612 
613 #undef __FUNCT__
614 #define __FUNCT__ "PetscBinarySynchronizedWrite"
615 /*@C
616    PetscBinarySynchronizedWrite - writes to a binary file.
617 
618    Collective on MPI_Comm
619 
620    Input Parameters:
621 +  comm - the MPI communicator
622 .  fd - the file
623 .  n  - the number of items to write
624 .  p - the buffer
625 .  istemp - the buffer may be changed
626 -  type - the type of items to write (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)
627 
628    Level: developer
629 
630    Notes:
631    Process 0 does a PetscBinaryWrite()
632 
633    PetscBinarySynchronizedWrite() uses byte swapping to work on all machines.
634    Integers are stored on the file as 32 long, regardless of whether
635    they are stored in the machine as 32 or 64, this means the same
636    binary file may be read on any machine.
637 
638    Notes: because byte-swapping may be done on the values in data it cannot be declared const
639 
640    WARNING: This is NOT like PetscSynchronizedFPrintf()! This routine ignores calls on all but process 0,
641    while PetscSynchronizedFPrintf() has all processes print their strings in order.
642 
643    Concepts: files^synchronized writing of binary files
644    Concepts: binary files^reading, synchronized
645 
646 .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscBinaryRead(), PetscBinarySynchronizedRead(),
647           PetscBinarySynchronizedSeek()
648 @*/
649 PetscErrorCode  PetscBinarySynchronizedWrite(MPI_Comm comm,int fd,void *p,PetscInt n,PetscDataType type,PetscBool istemp)
650 {
651   PetscErrorCode ierr;
652   PetscMPIInt    rank;
653 
654   PetscFunctionBegin;
655   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
656   if (!rank) {
657     ierr = PetscBinaryWrite(fd,p,n,type,istemp);CHKERRQ(ierr);
658   }
659   PetscFunctionReturn(0);
660 }
661 
662 #undef __FUNCT__
663 #define __FUNCT__ "PetscBinarySynchronizedSeek"
664 /*@C
665    PetscBinarySynchronizedSeek - Moves the file pointer on a PETSc binary file.
666 
667 
668    Input Parameters:
669 +  fd - the file
670 .  whence - if PETSC_BINARY_SEEK_SET then size is an absolute location in the file
671             if PETSC_BINARY_SEEK_CUR then size is offset from current location
672             if PETSC_BINARY_SEEK_END then size is offset from end of file
673 -  off    - number of bytes to move. Use PETSC_BINARY_INT_SIZE, PETSC_BINARY_SCALAR_SIZE,
674             etc. in your calculation rather than sizeof() to compute byte lengths.
675 
676    Output Parameter:
677 .   offset - new offset in file
678 
679    Level: developer
680 
681    Notes:
682    Integers are stored on the file as 32 long, regardless of whether
683    they are stored in the machine as 32 or 64, this means the same
684    binary file may be read on any machine. Hence you CANNOT use sizeof()
685    to determine the offset or location.
686 
687    Concepts: binary files^seeking
688    Concepts: files^seeking in binary
689 
690 .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
691           PetscBinarySynchronizedSeek()
692 @*/
693 PetscErrorCode  PetscBinarySynchronizedSeek(MPI_Comm comm,int fd,off_t off,PetscBinarySeekType whence,off_t *offset)
694 {
695   PetscErrorCode ierr;
696   PetscMPIInt    rank;
697 
698   PetscFunctionBegin;
699   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
700   if (!rank) {
701     ierr = PetscBinarySeek(fd,off,whence,offset);CHKERRQ(ierr);
702   }
703   PetscFunctionReturn(0);
704 }
705 
706 #if defined(PETSC_HAVE_MPIIO)
707 #if !defined(PETSC_WORDS_BIGENDIAN)
708 
709 #if defined(PETSC_USE_PETSC_MPI_EXTERNAL32)
710 /*
711       MPICH does not provide the external32 representation for MPI_File_set_view() so we need to provide the functions.
712     These are set into MPI in PetscInitialize() via MPI_Register_datarep()
713 
714     Note I use PetscMPIInt for the MPI error codes since that is what MPI uses (instead of the standard PetscErrorCode)
715 
716     The next three routines are not used because MPICH does not support their use
717 
718 */
719 PETSC_EXTERN PetscMPIInt PetscDataRep_extent_fn(MPI_Datatype datatype,MPI_Aint *file_extent,void *extra_state)
720 {
721   MPI_Aint    ub;
722   PetscMPIInt ierr;
723 
724   ierr = MPI_Type_get_extent(datatype,&ub,file_extent);
725   return ierr;
726 }
727 
728 PETSC_EXTERN PetscMPIInt PetscDataRep_read_conv_fn(void *userbuf, MPI_Datatype datatype,PetscMPIInt count,void *filebuf, MPI_Offset position,void *extra_state)
729 {
730   PetscDataType pdtype;
731   PetscMPIInt   ierr;
732   size_t        dsize;
733 
734   ierr = PetscMPIDataTypeToPetscDataType(datatype,&pdtype);CHKERRQ(ierr);
735   ierr = PetscDataTypeGetSize(pdtype,&dsize);CHKERRQ(ierr);
736 
737   /* offset is given in units of MPI_Datatype */
738   userbuf = ((char*)userbuf) + dsize*position;
739 
740   ierr = PetscMemcpy(userbuf,filebuf,count*dsize);CHKERRQ(ierr);
741   ierr = PetscByteSwap(userbuf,pdtype,count);CHKERRQ(ierr);
742   return ierr;
743 }
744 
745 PetscMPIInt PetscDataRep_write_conv_fn(void *userbuf, MPI_Datatype datatype,PetscMPIInt count,void *filebuf, MPI_Offset position,void *extra_state)
746 {
747   PetscDataType pdtype;
748   PetscMPIInt   ierr;
749   size_t        dsize;
750 
751   ierr = PetscMPIDataTypeToPetscDataType(datatype,&pdtype);CHKERRQ(ierr);
752   ierr = PetscDataTypeGetSize(pdtype,&dsize);CHKERRQ(ierr);
753 
754   /* offset is given in units of MPI_Datatype */
755   userbuf = ((char*)userbuf) + dsize*position;
756 
757   ierr = PetscMemcpy(filebuf,userbuf,count*dsize);CHKERRQ(ierr);
758   ierr = PetscByteSwap(filebuf,pdtype,count);CHKERRQ(ierr);
759   return ierr;
760 }
761 #endif
762 
763 #undef __FUNCT__
764 #define __FUNCT__ "MPIU_File_write_all"
765 PetscErrorCode MPIU_File_write_all(MPI_File fd,void *data,PetscMPIInt cnt,MPI_Datatype dtype,MPI_Status *status)
766 {
767   PetscErrorCode ierr;
768   PetscDataType  pdtype;
769 
770   PetscFunctionBegin;
771   ierr = PetscMPIDataTypeToPetscDataType(dtype,&pdtype);CHKERRQ(ierr);
772   ierr = PetscByteSwap(data,pdtype,cnt);CHKERRQ(ierr);
773   ierr = MPI_File_write_all(fd,data,cnt,dtype,status);CHKERRQ(ierr);
774   ierr = PetscByteSwap(data,pdtype,cnt);CHKERRQ(ierr);
775   PetscFunctionReturn(0);
776 }
777 
778 #undef __FUNCT__
779 #define __FUNCT__ "MPIU_File_read_all"
780 PetscErrorCode MPIU_File_read_all(MPI_File fd,void *data,PetscMPIInt cnt,MPI_Datatype dtype,MPI_Status *status)
781 {
782   PetscErrorCode ierr;
783   PetscDataType  pdtype;
784 
785   PetscFunctionBegin;
786   ierr = PetscMPIDataTypeToPetscDataType(dtype,&pdtype);CHKERRQ(ierr);
787   ierr = MPI_File_read_all(fd,data,cnt,dtype,status);CHKERRQ(ierr);
788   ierr = PetscByteSwap(data,pdtype,cnt);CHKERRQ(ierr);
789   PetscFunctionReturn(0);
790 }
791 #endif
792 #endif
793