xref: /petsc/src/sys/fileio/sysio.c (revision e6e75211d226c622f451867f53ce5d558649ff4f)
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    Options Database Key:
562 .   -binary_longints - indicates the file was generated on a Cray vector
563          machine (not the T3E/D) and the ints are stored as 64 bit
564          quantities, otherwise they are stored as 32 bit
565 
566    Level: developer
567 
568    Notes:
569    Does a PetscBinaryRead() followed by an MPI_Bcast()
570 
571    PetscBinarySynchronizedRead() uses byte swapping to work on all machines.
572    Integers are stored on the file as 32 long, regardless of whether
573    they are stored in the machine as 32 or 64, this means the same
574    binary file may be read on any machine.
575 
576    Concepts: files^synchronized reading of binary files
577    Concepts: binary files^reading, synchronized
578 
579 .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscBinaryRead(), PetscBinarySynchronizedWrite(),
580           PetscBinarySynchronizedSeek()
581 @*/
582 PetscErrorCode  PetscBinarySynchronizedRead(MPI_Comm comm,int fd,void *p,PetscInt n,PetscDataType type)
583 {
584   PetscErrorCode ierr;
585   PetscMPIInt    rank;
586   MPI_Datatype   mtype;
587   char           *fname = NULL;
588   void           *ptmp = NULL;
589 
590   PetscFunctionBegin;
591   if (type == PETSC_FUNCTION) {
592     n            = 64;
593     type         = PETSC_CHAR;
594     ptmp         = p;
595     fname        = (char*)malloc(n*sizeof(char));
596     if (!fname) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Cannot allocate space for function name");
597     p            = (void*)fname;
598   }
599 
600   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
601   if (!rank) {
602     ierr = PetscBinaryRead(fd,p,n,type);CHKERRQ(ierr);
603   }
604   ierr = PetscDataTypeToMPIDataType(type,&mtype);CHKERRQ(ierr);
605   ierr = MPI_Bcast(p,n,mtype,0,comm);CHKERRQ(ierr);
606 
607   if (type == PETSC_FUNCTION) {
608 #if defined(PETSC_SERIALIZE_FUNCTIONS)
609     ierr = PetscDLLibrarySym(PETSC_COMM_SELF,&PetscDLLibrariesLoaded,NULL,fname,(void**)ptmp);CHKERRQ(ierr);
610 #else
611     *(void**)ptmp = NULL;
612 #endif
613     free(fname);
614   }
615   PetscFunctionReturn(0);
616 }
617 
618 #undef __FUNCT__
619 #define __FUNCT__ "PetscBinarySynchronizedWrite"
620 /*@C
621    PetscBinarySynchronizedWrite - writes to a binary file.
622 
623    Collective on MPI_Comm
624 
625    Input Parameters:
626 +  comm - the MPI communicator
627 .  fd - the file
628 .  n  - the number of items to write
629 .  p - the buffer
630 .  istemp - the buffer may be changed
631 -  type - the type of items to write (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)
632 
633    Level: developer
634 
635    Notes:
636    Process 0 does a PetscBinaryWrite()
637 
638    PetscBinarySynchronizedWrite() uses byte swapping to work on all machines.
639    Integers are stored on the file as 32 long, regardless of whether
640    they are stored in the machine as 32 or 64, this means the same
641    binary file may be read on any machine.
642 
643    Notes: because byte-swapping may be done on the values in data it cannot be declared const
644 
645    WARNING: This is NOT like PetscSynchronizedFPrintf()! This routine ignores calls on all but process 0,
646    while PetscSynchronizedFPrintf() has all processes print their strings in order.
647 
648    Concepts: files^synchronized writing of binary files
649    Concepts: binary files^reading, synchronized
650 
651 .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscBinaryRead(), PetscBinarySynchronizedRead(),
652           PetscBinarySynchronizedSeek()
653 @*/
654 PetscErrorCode  PetscBinarySynchronizedWrite(MPI_Comm comm,int fd,void *p,PetscInt n,PetscDataType type,PetscBool istemp)
655 {
656   PetscErrorCode ierr;
657   PetscMPIInt    rank;
658 
659   PetscFunctionBegin;
660   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
661   if (!rank) {
662     ierr = PetscBinaryWrite(fd,p,n,type,istemp);CHKERRQ(ierr);
663   }
664   PetscFunctionReturn(0);
665 }
666 
667 #undef __FUNCT__
668 #define __FUNCT__ "PetscBinarySynchronizedSeek"
669 /*@C
670    PetscBinarySynchronizedSeek - Moves the file pointer on a PETSc binary file.
671 
672 
673    Input Parameters:
674 +  fd - the file
675 .  whence - if PETSC_BINARY_SEEK_SET then size is an absolute location in the file
676             if PETSC_BINARY_SEEK_CUR then size is offset from current location
677             if PETSC_BINARY_SEEK_END then size is offset from end of file
678 -  off    - number of bytes to move. Use PETSC_BINARY_INT_SIZE, PETSC_BINARY_SCALAR_SIZE,
679             etc. in your calculation rather than sizeof() to compute byte lengths.
680 
681    Output Parameter:
682 .   offset - new offset in file
683 
684    Level: developer
685 
686    Notes:
687    Integers are stored on the file as 32 long, regardless of whether
688    they are stored in the machine as 32 or 64, this means the same
689    binary file may be read on any machine. Hence you CANNOT use sizeof()
690    to determine the offset or location.
691 
692    Concepts: binary files^seeking
693    Concepts: files^seeking in binary
694 
695 .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
696           PetscBinarySynchronizedSeek()
697 @*/
698 PetscErrorCode  PetscBinarySynchronizedSeek(MPI_Comm comm,int fd,off_t off,PetscBinarySeekType whence,off_t *offset)
699 {
700   PetscErrorCode ierr;
701   PetscMPIInt    rank;
702 
703   PetscFunctionBegin;
704   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
705   if (!rank) {
706     ierr = PetscBinarySeek(fd,off,whence,offset);CHKERRQ(ierr);
707   }
708   PetscFunctionReturn(0);
709 }
710 
711 #if defined(PETSC_HAVE_MPIIO)
712 #if !defined(PETSC_WORDS_BIGENDIAN)
713 
714 #if defined(PETSC_USE_PETSC_MPI_EXTERNAL32)
715 /*
716       MPICH does not provide the external32 representation for MPI_File_set_view() so we need to provide the functions.
717     These are set into MPI in PetscInitialize() via MPI_Register_datarep()
718 
719     Note I use PetscMPIInt for the MPI error codes since that is what MPI uses (instead of the standard PetscErrorCode)
720 
721     The next three routines are not used because MPICH does not support their use
722 
723 */
724 PETSC_EXTERN PetscMPIInt PetscDataRep_extent_fn(MPI_Datatype datatype,MPI_Aint *file_extent,void *extra_state)
725 {
726   MPI_Aint    ub;
727   PetscMPIInt ierr;
728 
729   ierr = MPI_Type_get_extent(datatype,&ub,file_extent);
730   return ierr;
731 }
732 
733 PETSC_EXTERN PetscMPIInt PetscDataRep_read_conv_fn(void *userbuf, MPI_Datatype datatype,PetscMPIInt count,void *filebuf, MPI_Offset position,void *extra_state)
734 {
735   PetscDataType pdtype;
736   PetscMPIInt   ierr;
737   size_t        dsize;
738 
739   ierr = PetscMPIDataTypeToPetscDataType(datatype,&pdtype);CHKERRQ(ierr);
740   ierr = PetscDataTypeGetSize(pdtype,&dsize);CHKERRQ(ierr);
741 
742   /* offset is given in units of MPI_Datatype */
743   userbuf = ((char*)userbuf) + dsize*position;
744 
745   ierr = PetscMemcpy(userbuf,filebuf,count*dsize);CHKERRQ(ierr);
746   ierr = PetscByteSwap(userbuf,pdtype,count);CHKERRQ(ierr);
747   return ierr;
748 }
749 
750 PetscMPIInt PetscDataRep_write_conv_fn(void *userbuf, MPI_Datatype datatype,PetscMPIInt count,void *filebuf, MPI_Offset position,void *extra_state)
751 {
752   PetscDataType pdtype;
753   PetscMPIInt   ierr;
754   size_t        dsize;
755 
756   ierr = PetscMPIDataTypeToPetscDataType(datatype,&pdtype);CHKERRQ(ierr);
757   ierr = PetscDataTypeGetSize(pdtype,&dsize);CHKERRQ(ierr);
758 
759   /* offset is given in units of MPI_Datatype */
760   userbuf = ((char*)userbuf) + dsize*position;
761 
762   ierr = PetscMemcpy(filebuf,userbuf,count*dsize);CHKERRQ(ierr);
763   ierr = PetscByteSwap(filebuf,pdtype,count);CHKERRQ(ierr);
764   return ierr;
765 }
766 #endif
767 
768 #undef __FUNCT__
769 #define __FUNCT__ "MPIU_File_write_all"
770 PetscErrorCode MPIU_File_write_all(MPI_File fd,void *data,PetscMPIInt cnt,MPI_Datatype dtype,MPI_Status *status)
771 {
772   PetscErrorCode ierr;
773   PetscDataType  pdtype;
774 
775   PetscFunctionBegin;
776   ierr = PetscMPIDataTypeToPetscDataType(dtype,&pdtype);CHKERRQ(ierr);
777   ierr = PetscByteSwap(data,pdtype,cnt);CHKERRQ(ierr);
778   ierr = MPI_File_write_all(fd,data,cnt,dtype,status);CHKERRQ(ierr);
779   ierr = PetscByteSwap(data,pdtype,cnt);CHKERRQ(ierr);
780   PetscFunctionReturn(0);
781 }
782 
783 #undef __FUNCT__
784 #define __FUNCT__ "MPIU_File_read_all"
785 PetscErrorCode MPIU_File_read_all(MPI_File fd,void *data,PetscMPIInt cnt,MPI_Datatype dtype,MPI_Status *status)
786 {
787   PetscErrorCode ierr;
788   PetscDataType  pdtype;
789 
790   PetscFunctionBegin;
791   ierr = PetscMPIDataTypeToPetscDataType(dtype,&pdtype);CHKERRQ(ierr);
792   ierr = MPI_File_read_all(fd,data,cnt,dtype,status);CHKERRQ(ierr);
793   ierr = PetscByteSwap(data,pdtype,cnt);CHKERRQ(ierr);
794   PetscFunctionReturn(0);
795 }
796 #endif
797 #endif
798