xref: /petsc/src/sys/fileio/sysio.c (revision 9860990e59c4c800a263b1f7b2b4653b5eba6a88)
1e5c89e4eSSatish Balay 
2e5c89e4eSSatish Balay /*
3e5c89e4eSSatish Balay    This file contains simple binary read/write routines.
4e5c89e4eSSatish Balay  */
5e5c89e4eSSatish Balay 
6c6db04a5SJed Brown #include <petscsys.h>
7e5c89e4eSSatish Balay #include <errno.h>
8e5c89e4eSSatish Balay #include <fcntl.h>
9e5c89e4eSSatish Balay #if defined(PETSC_HAVE_UNISTD_H)
10e5c89e4eSSatish Balay #include <unistd.h>
11e5c89e4eSSatish Balay #endif
12e5c89e4eSSatish Balay #if defined(PETSC_HAVE_IO_H)
13e5c89e4eSSatish Balay #include <io.h>
14e5c89e4eSSatish Balay #endif
15c6db04a5SJed Brown #include <petscbt.h>
16e5c89e4eSSatish Balay 
17d6a4318aSJed Brown const char *const PetscFileModes[] = {"READ","WRITE","APPEND","UPDATE","APPEND_UPDATE","PetscFileMode","PETSC_FILE_",0};
18d6a4318aSJed Brown 
196de02169SBarry Smith /* --------------------------------------------------------- */
20e5c89e4eSSatish Balay /*
216de02169SBarry Smith   PetscByteSwapEnum - Swap bytes in a  PETSc Enum
22e5c89e4eSSatish Balay 
23e5c89e4eSSatish Balay */
247087cfbeSBarry Smith PetscErrorCode  PetscByteSwapEnum(PetscEnum *buff,PetscInt n)
25e5c89e4eSSatish Balay {
266de02169SBarry Smith   PetscInt  i,j;
270b20345dSBarry Smith   PetscEnum tmp = ENUM_DUMMY;
28e0890e22SSatish Balay   char      *ptr1,*ptr2 = (char*)&tmp;
29e5c89e4eSSatish Balay 
30e5c89e4eSSatish Balay   PetscFunctionBegin;
31e5c89e4eSSatish Balay   for (j=0; j<n; j++) {
32e5c89e4eSSatish Balay     ptr1 = (char*)(buff + j);
33a297a907SKarl Rupp     for (i=0; i<(PetscInt)sizeof(PetscEnum); i++) ptr2[i] = ptr1[sizeof(PetscEnum)-1-i];
34a297a907SKarl Rupp     for (i=0; i<(PetscInt)sizeof(PetscEnum); i++) ptr1[i] = ptr2[i];
35e5c89e4eSSatish Balay   }
36e5c89e4eSSatish Balay   PetscFunctionReturn(0);
37e5c89e4eSSatish Balay }
386de02169SBarry Smith 
396de02169SBarry Smith /*
40acfcf0e5SJed Brown   PetscByteSwapBool - Swap bytes in a  PETSc Bool
416de02169SBarry Smith 
426de02169SBarry Smith */
437087cfbeSBarry Smith PetscErrorCode  PetscByteSwapBool(PetscBool *buff,PetscInt n)
446de02169SBarry Smith {
456de02169SBarry Smith   PetscInt  i,j;
46ace3abfcSBarry Smith   PetscBool tmp = PETSC_FALSE;
47e0890e22SSatish Balay   char      *ptr1,*ptr2 = (char*)&tmp;
486de02169SBarry Smith 
496de02169SBarry Smith   PetscFunctionBegin;
506de02169SBarry Smith   for (j=0; j<n; j++) {
516de02169SBarry Smith     ptr1 = (char*)(buff + j);
52a297a907SKarl Rupp     for (i=0; i<(PetscInt)sizeof(PetscBool); i++) ptr2[i] = ptr1[sizeof(PetscBool)-1-i];
53a297a907SKarl Rupp     for (i=0; i<(PetscInt)sizeof(PetscBool); i++) ptr1[i] = ptr2[i];
546de02169SBarry Smith   }
556de02169SBarry Smith   PetscFunctionReturn(0);
566de02169SBarry Smith }
576de02169SBarry Smith 
58bd1d2e58SBarry Smith /*
596de02169SBarry Smith   PetscByteSwapInt - Swap bytes in a  PETSc integer (which may be 32 or 64 bits)
60bd1d2e58SBarry Smith 
61bd1d2e58SBarry Smith */
627087cfbeSBarry Smith PetscErrorCode  PetscByteSwapInt(PetscInt *buff,PetscInt n)
63bd1d2e58SBarry Smith {
64bd1d2e58SBarry Smith   PetscInt i,j,tmp = 0;
65e0890e22SSatish Balay   char     *ptr1,*ptr2 = (char*)&tmp;
66bd1d2e58SBarry Smith 
67bd1d2e58SBarry Smith   PetscFunctionBegin;
68bd1d2e58SBarry Smith   for (j=0; j<n; j++) {
69bd1d2e58SBarry Smith     ptr1 = (char*)(buff + j);
70a297a907SKarl Rupp     for (i=0; i<(PetscInt)sizeof(PetscInt); i++) ptr2[i] = ptr1[sizeof(PetscInt)-1-i];
71a297a907SKarl Rupp     for (i=0; i<(PetscInt)sizeof(PetscInt); i++) ptr1[i] = ptr2[i];
72bd1d2e58SBarry Smith   }
73bd1d2e58SBarry Smith   PetscFunctionReturn(0);
74bd1d2e58SBarry Smith }
759e3e4c22SLisandro Dalcin 
769e3e4c22SLisandro Dalcin /*
779e3e4c22SLisandro Dalcin   PetscByteSwapInt64 - Swap bytes in a  PETSc integer (64 bits)
789e3e4c22SLisandro Dalcin 
799e3e4c22SLisandro Dalcin */
809e3e4c22SLisandro Dalcin PetscErrorCode  PetscByteSwapInt64(PetscInt64 *buff,PetscInt n)
819e3e4c22SLisandro Dalcin {
829e3e4c22SLisandro Dalcin   PetscInt   i,j;
839e3e4c22SLisandro Dalcin   PetscInt64 tmp = 0;
849e3e4c22SLisandro Dalcin   char       *ptr1,*ptr2 = (char*)&tmp;
859e3e4c22SLisandro Dalcin 
869e3e4c22SLisandro Dalcin   PetscFunctionBegin;
879e3e4c22SLisandro Dalcin   for (j=0; j<n; j++) {
889e3e4c22SLisandro Dalcin     ptr1 = (char*)(buff + j);
899e3e4c22SLisandro Dalcin     for (i=0; i<(PetscInt)sizeof(PetscInt64); i++) ptr2[i] = ptr1[sizeof(PetscInt64)-1-i];
909e3e4c22SLisandro Dalcin     for (i=0; i<(PetscInt)sizeof(PetscInt64); i++) ptr1[i] = ptr2[i];
919e3e4c22SLisandro Dalcin   }
929e3e4c22SLisandro Dalcin   PetscFunctionReturn(0);
939e3e4c22SLisandro Dalcin }
949e3e4c22SLisandro Dalcin 
95bd1d2e58SBarry Smith /* --------------------------------------------------------- */
96e5c89e4eSSatish Balay /*
97e5c89e4eSSatish Balay   PetscByteSwapShort - Swap bytes in a short
98e5c89e4eSSatish Balay */
997087cfbeSBarry Smith PetscErrorCode  PetscByteSwapShort(short *buff,PetscInt n)
100e5c89e4eSSatish Balay {
101e5c89e4eSSatish Balay   PetscInt i,j;
102e5c89e4eSSatish Balay   short    tmp;
103e5c89e4eSSatish Balay   char     *ptr1,*ptr2 = (char*)&tmp;
104e5c89e4eSSatish Balay 
105e5c89e4eSSatish Balay   PetscFunctionBegin;
106e5c89e4eSSatish Balay   for (j=0; j<n; j++) {
107e5c89e4eSSatish Balay     ptr1 = (char*)(buff + j);
108a297a907SKarl Rupp     for (i=0; i<(PetscInt) sizeof(short); i++) ptr2[i] = ptr1[sizeof(short)-1-i];
109a297a907SKarl Rupp     for (i=0; i<(PetscInt) sizeof(short); i++) ptr1[i] = ptr2[i];
110e5c89e4eSSatish Balay   }
111e5c89e4eSSatish Balay   PetscFunctionReturn(0);
112e5c89e4eSSatish Balay }
113972064b6SLisandro Dalcin /*
114972064b6SLisandro Dalcin   PetscByteSwapLong - Swap bytes in a long
115972064b6SLisandro Dalcin */
116972064b6SLisandro Dalcin PetscErrorCode  PetscByteSwapLong(long *buff,PetscInt n)
117972064b6SLisandro Dalcin {
118972064b6SLisandro Dalcin   PetscInt i,j;
119972064b6SLisandro Dalcin   long     tmp;
120972064b6SLisandro Dalcin   char     *ptr1,*ptr2 = (char*)&tmp;
121972064b6SLisandro Dalcin 
122972064b6SLisandro Dalcin   PetscFunctionBegin;
123972064b6SLisandro Dalcin   for (j=0; j<n; j++) {
124972064b6SLisandro Dalcin     ptr1 = (char*)(buff + j);
125972064b6SLisandro Dalcin     for (i=0; i<(PetscInt) sizeof(long); i++) ptr2[i] = ptr1[sizeof(long)-1-i];
126972064b6SLisandro Dalcin     for (i=0; i<(PetscInt) sizeof(long); i++) ptr1[i] = ptr2[i];
127972064b6SLisandro Dalcin   }
128972064b6SLisandro Dalcin   PetscFunctionReturn(0);
129972064b6SLisandro Dalcin }
130e5c89e4eSSatish Balay /* --------------------------------------------------------- */
131e5c89e4eSSatish Balay /*
1324caf0332SSatish Balay   PetscByteSwapReal - Swap bytes in a PetscReal
1334caf0332SSatish Balay */
1344caf0332SSatish Balay PetscErrorCode  PetscByteSwapReal(PetscReal *buff,PetscInt n)
1354caf0332SSatish Balay {
1364caf0332SSatish Balay   PetscInt  i,j;
1374caf0332SSatish Balay   PetscReal tmp,*buff1 = (PetscReal*)buff;
1384caf0332SSatish Balay   char      *ptr1,*ptr2 = (char*)&tmp;
1394caf0332SSatish Balay 
1404caf0332SSatish Balay   PetscFunctionBegin;
1414caf0332SSatish Balay   for (j=0; j<n; j++) {
1424caf0332SSatish Balay     ptr1 = (char*)(buff1 + j);
1434caf0332SSatish Balay     for (i=0; i<(PetscInt) sizeof(PetscReal); i++) ptr2[i] = ptr1[sizeof(PetscReal)-1-i];
1444caf0332SSatish Balay     for (i=0; i<(PetscInt) sizeof(PetscReal); i++) ptr1[i] = ptr2[i];
1454caf0332SSatish Balay   }
1464caf0332SSatish Balay   PetscFunctionReturn(0);
1474caf0332SSatish Balay }
1484caf0332SSatish Balay /* --------------------------------------------------------- */
1494caf0332SSatish Balay /*
15041f502e3SPatrick Sanan   PetscByteSwapScalar - Swap bytes in a PetscScalar
15141f502e3SPatrick Sanan   The complex case is dealt with with an array of PetscReal, twice as long.
152e5c89e4eSSatish Balay */
1537087cfbeSBarry Smith PetscErrorCode  PetscByteSwapScalar(PetscScalar *buff,PetscInt n)
154e5c89e4eSSatish Balay {
155e5c89e4eSSatish Balay   PetscInt  i,j;
156e5c89e4eSSatish Balay   PetscReal tmp,*buff1 = (PetscReal*)buff;
157e5c89e4eSSatish Balay   char      *ptr1,*ptr2 = (char*)&tmp;
158e5c89e4eSSatish Balay 
159e5c89e4eSSatish Balay   PetscFunctionBegin;
160e5c89e4eSSatish Balay #if defined(PETSC_USE_COMPLEX)
161e5c89e4eSSatish Balay   n *= 2;
162e5c89e4eSSatish Balay #endif
163e5c89e4eSSatish Balay   for (j=0; j<n; j++) {
164e5c89e4eSSatish Balay     ptr1 = (char*)(buff1 + j);
165a297a907SKarl Rupp     for (i=0; i<(PetscInt) sizeof(PetscReal); i++) ptr2[i] = ptr1[sizeof(PetscReal)-1-i];
166a297a907SKarl Rupp     for (i=0; i<(PetscInt) sizeof(PetscReal); i++) ptr1[i] = ptr2[i];
167e5c89e4eSSatish Balay   }
168e5c89e4eSSatish Balay   PetscFunctionReturn(0);
169e5c89e4eSSatish Balay }
170e5c89e4eSSatish Balay /* --------------------------------------------------------- */
171e5c89e4eSSatish Balay /*
172e5c89e4eSSatish Balay   PetscByteSwapDouble - Swap bytes in a double
173e5c89e4eSSatish Balay */
1747087cfbeSBarry Smith PetscErrorCode  PetscByteSwapDouble(double *buff,PetscInt n)
175e5c89e4eSSatish Balay {
176e5c89e4eSSatish Balay   PetscInt i,j;
177e5c89e4eSSatish Balay   double   tmp,*buff1 = (double*)buff;
178e5c89e4eSSatish Balay   char     *ptr1,*ptr2 = (char*)&tmp;
179e5c89e4eSSatish Balay 
180e5c89e4eSSatish Balay   PetscFunctionBegin;
181e5c89e4eSSatish Balay   for (j=0; j<n; j++) {
182e5c89e4eSSatish Balay     ptr1 = (char*)(buff1 + j);
183a297a907SKarl Rupp     for (i=0; i<(PetscInt) sizeof(double); i++) ptr2[i] = ptr1[sizeof(double)-1-i];
184a297a907SKarl Rupp     for (i=0; i<(PetscInt) sizeof(double); i++) ptr1[i] = ptr2[i];
185e5c89e4eSSatish Balay   }
186e5c89e4eSSatish Balay   PetscFunctionReturn(0);
187e5c89e4eSSatish Balay }
188e39fd77fSBarry Smith 
189e95bf02fSSatish Balay /*
190e95bf02fSSatish Balay   PetscByteSwapFloat - Swap bytes in a float
191e95bf02fSSatish Balay */
192e95bf02fSSatish Balay PetscErrorCode PetscByteSwapFloat(float *buff,PetscInt n)
193e95bf02fSSatish Balay {
194e95bf02fSSatish Balay   PetscInt i,j;
195e95bf02fSSatish Balay   float    tmp,*buff1 = (float*)buff;
196e95bf02fSSatish Balay   char     *ptr1,*ptr2 = (char*)&tmp;
197e95bf02fSSatish Balay 
198e95bf02fSSatish Balay   PetscFunctionBegin;
199e95bf02fSSatish Balay   for (j=0; j<n; j++) {
200e95bf02fSSatish Balay     ptr1 = (char*)(buff1 + j);
201a297a907SKarl Rupp     for (i=0; i<(PetscInt) sizeof(float); i++) ptr2[i] = ptr1[sizeof(float)-1-i];
202a297a907SKarl Rupp     for (i=0; i<(PetscInt) sizeof(float); i++) ptr1[i] = ptr2[i];
203e95bf02fSSatish Balay   }
204e95bf02fSSatish Balay   PetscFunctionReturn(0);
205e95bf02fSSatish Balay }
206e95bf02fSSatish Balay 
207e39fd77fSBarry Smith PetscErrorCode PetscByteSwap(void *data,PetscDataType pdtype,PetscInt count)
208e39fd77fSBarry Smith {
209e39fd77fSBarry Smith   PetscErrorCode ierr;
210e39fd77fSBarry Smith 
211e39fd77fSBarry Smith   PetscFunctionBegin;
212e39fd77fSBarry Smith   if      (pdtype == PETSC_INT)    {ierr = PetscByteSwapInt((PetscInt*)data,count);CHKERRQ(ierr);}
213e39fd77fSBarry Smith   else if (pdtype == PETSC_ENUM)   {ierr = PetscByteSwapEnum((PetscEnum*)data,count);CHKERRQ(ierr);}
214acfcf0e5SJed Brown   else if (pdtype == PETSC_BOOL)   {ierr = PetscByteSwapBool((PetscBool*)data,count);CHKERRQ(ierr);}
215e39fd77fSBarry Smith   else if (pdtype == PETSC_SCALAR) {ierr = PetscByteSwapScalar((PetscScalar*)data,count);CHKERRQ(ierr);}
2164caf0332SSatish Balay   else if (pdtype == PETSC_REAL)   {ierr = PetscByteSwapReal((PetscReal*)data,count);CHKERRQ(ierr);}
217*9860990eSLisandro Dalcin   else if (pdtype == PETSC_COMPLEX){ierr = PetscByteSwapReal((PetscReal*)data,2*count);CHKERRQ(ierr);}
2189e3e4c22SLisandro Dalcin   else if (pdtype == PETSC_INT64)  {ierr = PetscByteSwapInt64((PetscInt64*)data,count);CHKERRQ(ierr);}
219e39fd77fSBarry Smith   else if (pdtype == PETSC_DOUBLE) {ierr = PetscByteSwapDouble((double*)data,count);CHKERRQ(ierr);}
220e95bf02fSSatish Balay   else if (pdtype == PETSC_FLOAT)  {ierr = PetscByteSwapFloat((float*)data,count);CHKERRQ(ierr);}
221e39fd77fSBarry Smith   else if (pdtype == PETSC_SHORT)  {ierr = PetscByteSwapShort((short*)data,count);CHKERRQ(ierr);}
222972064b6SLisandro Dalcin   else if (pdtype == PETSC_LONG)   {ierr = PetscByteSwapLong((long*)data,count);CHKERRQ(ierr);}
223e39fd77fSBarry Smith   PetscFunctionReturn(0);
224e39fd77fSBarry Smith }
225e39fd77fSBarry Smith 
226*9860990eSLisandro Dalcin /*@C
227e5c89e4eSSatish Balay    PetscBinaryRead - Reads from a binary file.
228e5c89e4eSSatish Balay 
229e5c89e4eSSatish Balay    Not Collective
230e5c89e4eSSatish Balay 
231e5c89e4eSSatish Balay    Input Parameters:
232*9860990eSLisandro Dalcin +  fd - the file descriptor
233*9860990eSLisandro Dalcin .  num  - the maximum number of items to read
234*9860990eSLisandro Dalcin -  type - the type of items to read (PETSC_INT, PETSC_REAL, PETSC_SCALAR, etc.)
235e5c89e4eSSatish Balay 
236e5c89e4eSSatish Balay    Output Parameters:
237*9860990eSLisandro Dalcin +  data - the buffer
238*9860990eSLisandro Dalcin -  count - the number of items read, optional
239e5c89e4eSSatish Balay 
240e5c89e4eSSatish Balay 
241e5c89e4eSSatish Balay 
242e5c89e4eSSatish Balay    Level: developer
243e5c89e4eSSatish Balay 
244e5c89e4eSSatish Balay    Notes:
245*9860990eSLisandro Dalcin    If count is not provided and the number of items read is less than
246*9860990eSLisandro Dalcin    the maximum number of items to read, then this routine errors.
247*9860990eSLisandro Dalcin 
248e5c89e4eSSatish Balay    PetscBinaryRead() uses byte swapping to work on all machines; the files
249e5c89e4eSSatish Balay    are written to file ALWAYS using big-endian ordering. On small-endian machines the numbers
250e5c89e4eSSatish Balay    are converted to the small-endian format when they are read in from the file.
251e2e64c6bSBarry Smith    When PETSc is ./configure with --with-64bit-indices the integers are written to the
25254f21887SBarry Smith    file as 64 bit integers, this means they can only be read back in when the option --with-64bit-indices
25354f21887SBarry Smith    is used.
254e5c89e4eSSatish Balay 
255e5c89e4eSSatish Balay    Concepts: files^reading binary
256e5c89e4eSSatish Balay    Concepts: binary files^reading
257e5c89e4eSSatish Balay 
2584ebed01fSBarry Smith .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscViewerBinaryGetDescriptor(), PetscBinarySynchronizedWrite(),
2594ebed01fSBarry Smith           PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek()
260e5c89e4eSSatish Balay @*/
261*9860990eSLisandro Dalcin PetscErrorCode  PetscBinaryRead(int fd,void *data,PetscInt num,PetscInt *count,PetscDataType type)
262e5c89e4eSSatish Balay {
263*9860990eSLisandro Dalcin   size_t            typesize, m = (size_t) num, n = 0, maxblock = 65536;
264*9860990eSLisandro Dalcin   char              *p = (char*)data;
2657a881295SBarry Smith #if defined(PETSC_USE_REAL___FLOAT128)
266cba51d77SBarry Smith   PetscBool         readdouble = PETSC_FALSE;
267*9860990eSLisandro Dalcin   double            *pdouble;
2687a881295SBarry Smith #endif
2697a881295SBarry Smith #if !defined(PETSC_WORDS_BIGENDIAN)
270*9860990eSLisandro Dalcin   void              *ptmp = data;
271e5c89e4eSSatish Balay #endif
27205acbc63SBarry Smith   char              *fname = NULL;
273*9860990eSLisandro Dalcin   PetscErrorCode    ierr;
274e5c89e4eSSatish Balay 
275e5c89e4eSSatish Balay   PetscFunctionBegin;
276*9860990eSLisandro Dalcin   if (count) *count = 0;
277*9860990eSLisandro Dalcin   if (num < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Trying to read a negative amount of data %D",num);
278*9860990eSLisandro Dalcin   if (!num) PetscFunctionReturn(0);
279e5c89e4eSSatish Balay 
2802d53ad75SBarry Smith   if (type == PETSC_FUNCTION) {
2812d53ad75SBarry Smith     m     = 64;
2822d53ad75SBarry Smith     type  = PETSC_CHAR;
28305acbc63SBarry Smith     fname = (char*)malloc(m*sizeof(char));
284*9860990eSLisandro Dalcin     p     = (char*)fname;
2852d53ad75SBarry Smith #if !defined(PETSC_WORDS_BIGENDIAN)
2862d53ad75SBarry Smith     ptmp  = (void*)fname;
2872d53ad75SBarry Smith #endif
288*9860990eSLisandro Dalcin     if (!fname) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Cannot allocate space for function name");
2892d53ad75SBarry Smith   }
290*9860990eSLisandro Dalcin   if (type == PETSC_BIT_LOGICAL) m = PetscBTLength(m);
2912d53ad75SBarry Smith 
292*9860990eSLisandro Dalcin   ierr = PetscDataTypeGetSize(type,&typesize);CHKERRQ(ierr);
293e5c89e4eSSatish Balay 
2947a881295SBarry Smith #if defined(PETSC_USE_REAL___FLOAT128)
295c5929fdfSBarry Smith   ierr = PetscOptionsGetBool(NULL,NULL,"-binary_read_double",&readdouble,NULL);CHKERRQ(ierr);
2967a881295SBarry Smith   /* If using __float128 precision we still read in doubles from file */
297*9860990eSLisandro Dalcin   if ((type == PETSC_REAL || type == PETSC_COMPLEX) && readdouble) {
298*9860990eSLisandro Dalcin     PetscInt cnt = num * ((type == PETSC_REAL) ? 1 : 2);
299*9860990eSLisandro Dalcin     ierr = PetscMalloc1(cnt,&pdouble);CHKERRQ(ierr);
300*9860990eSLisandro Dalcin     p = (char*)pdouble;
301*9860990eSLisandro Dalcin     typesize /= 2;
3027a881295SBarry Smith   }
3037a881295SBarry Smith #endif
3047a881295SBarry Smith 
305*9860990eSLisandro Dalcin   m *= typesize;
306*9860990eSLisandro Dalcin 
307e5c89e4eSSatish Balay   while (m) {
308*9860990eSLisandro Dalcin     size_t len = (m < maxblock) ? m : maxblock;
309*9860990eSLisandro Dalcin     int    ret = (int)read(fd,p,len);
310*9860990eSLisandro Dalcin     if (ret < 0 && errno == EINTR) continue;
311*9860990eSLisandro Dalcin     if (!ret && len > 0) break; /* Proxy for EOF */
312*9860990eSLisandro Dalcin     if (ret < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_READ,"Error reading from file, errno %d",errno);
313*9860990eSLisandro Dalcin     m -= ret;
314*9860990eSLisandro Dalcin     p += ret;
315*9860990eSLisandro Dalcin     n += ret;
316e5c89e4eSSatish Balay   }
317*9860990eSLisandro Dalcin   if (m && !count) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_READ,"Read past end of file");
318*9860990eSLisandro Dalcin 
319*9860990eSLisandro Dalcin   num = (PetscInt)(n/typesize); /* Should we require `n % typesize == 0` ? */
320*9860990eSLisandro Dalcin   if (count) *count = num;      /* TODO: This is most likely wrong for PETSC_BIT_LOGICAL */
3217a881295SBarry Smith 
3227a881295SBarry Smith #if defined(PETSC_USE_REAL___FLOAT128)
323*9860990eSLisandro Dalcin   if ((type == PETSC_REAL || type == PETSC_COMPLEX) && readdouble) {
324*9860990eSLisandro Dalcin     PetscInt  i, cnt = num * ((type == PETSC_REAL) ? 1 : 2);
325*9860990eSLisandro Dalcin     PetscReal *preal = (PetscReal*)data;
3267a881295SBarry Smith #if !defined(PETSC_WORDS_BIGENDIAN)
327*9860990eSLisandro Dalcin     ierr = PetscByteSwapDouble(pdouble,cnt);CHKERRQ(ierr);
3287a881295SBarry Smith #endif
329*9860990eSLisandro Dalcin     for (i=0; i<cnt; i++) preal[i] = pdouble[i];
330*9860990eSLisandro Dalcin     ierr = PetscFree(pdouble);CHKERRQ(ierr);
3317a881295SBarry Smith     PetscFunctionReturn(0);
3327a881295SBarry Smith   }
3337a881295SBarry Smith #endif
3347a881295SBarry Smith 
335e5c89e4eSSatish Balay #if !defined(PETSC_WORDS_BIGENDIAN)
336*9860990eSLisandro Dalcin   ierr = PetscByteSwap(ptmp,type,num);CHKERRQ(ierr);
337e5c89e4eSSatish Balay #endif
338e5c89e4eSSatish Balay 
33905acbc63SBarry Smith   if (type == PETSC_FUNCTION) {
3402d53ad75SBarry Smith #if defined(PETSC_SERIALIZE_FUNCTIONS)
341*9860990eSLisandro Dalcin     ierr = PetscDLSym(NULL,fname,(void**)data);CHKERRQ(ierr);
3422d53ad75SBarry Smith #else
343*9860990eSLisandro Dalcin     *(void**)data = NULL;
3442d53ad75SBarry Smith #endif
34505acbc63SBarry Smith     free(fname);
3462d53ad75SBarry Smith   }
347e5c89e4eSSatish Balay   PetscFunctionReturn(0);
348e5c89e4eSSatish Balay }
349*9860990eSLisandro Dalcin 
350e30d2299SSatish Balay /*@
351e5c89e4eSSatish Balay    PetscBinaryWrite - Writes to a binary file.
352e5c89e4eSSatish Balay 
353e5c89e4eSSatish Balay    Not Collective
354e5c89e4eSSatish Balay 
355e5c89e4eSSatish Balay    Input Parameters:
356e5c89e4eSSatish Balay +  fd     - the file
357e5c89e4eSSatish Balay .  p      - the buffer
358e5c89e4eSSatish Balay .  n      - the number of items to write
359e5c89e4eSSatish Balay .  type   - the type of items to read (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)
360e5c89e4eSSatish Balay -  istemp - PETSC_FALSE if buffer data should be preserved, PETSC_TRUE otherwise.
361e5c89e4eSSatish Balay 
362e5c89e4eSSatish Balay    Level: advanced
363e5c89e4eSSatish Balay 
364e5c89e4eSSatish Balay    Notes:
365e5c89e4eSSatish Balay    PetscBinaryWrite() uses byte swapping to work on all machines; the files
366e5c89e4eSSatish Balay    are written using big-endian ordering to the file. On small-endian machines the numbers
367e5c89e4eSSatish Balay    are converted to the big-endian format when they are written to disk.
368e2e64c6bSBarry Smith    When PETSc is ./configure with --with-64bit-indices the integers are written to the
36954f21887SBarry Smith    file as 64 bit integers, this means they can only be read back in when the option --with-64bit-indices
37054f21887SBarry Smith    is used.
371e5c89e4eSSatish Balay 
37241f502e3SPatrick Sanan    If running with __float128 precision the output is in __float128 unless one uses the -binary_write_double option
3730da86b62SBarry Smith 
374e5c89e4eSSatish Balay    The Buffer p should be read-write buffer, and not static data.
375e5c89e4eSSatish Balay    This way, byte-swapping is done in-place, and then the buffer is
376e5c89e4eSSatish Balay    written to the file.
377e5c89e4eSSatish Balay 
378e5c89e4eSSatish Balay    This routine restores the original contents of the buffer, after
379e5c89e4eSSatish Balay    it is written to the file. This is done by byte-swapping in-place
380e5c89e4eSSatish Balay    the second time. If the flag istemp is set to PETSC_TRUE, the second
381e5c89e4eSSatish Balay    byte-swapping operation is not done, thus saving some computation,
382e5f36e38SBarry Smith    but the buffer is left corrupted.
383e5c89e4eSSatish Balay 
384300a7f5bSBarry Smith    Because byte-swapping may be done on the values in data it cannot be declared const
385300a7f5bSBarry Smith 
386e5c89e4eSSatish Balay    Concepts: files^writing binary
387e5c89e4eSSatish Balay    Concepts: binary files^writing
388e5c89e4eSSatish Balay 
3894ebed01fSBarry Smith .seealso: PetscBinaryRead(), PetscBinaryOpen(), PetscBinaryClose(), PetscViewerBinaryGetDescriptor(), PetscBinarySynchronizedWrite(),
3904ebed01fSBarry Smith           PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek()
391e5c89e4eSSatish Balay @*/
3927087cfbeSBarry Smith PetscErrorCode  PetscBinaryWrite(int fd,void *p,PetscInt n,PetscDataType type,PetscBool  istemp)
393e5c89e4eSSatish Balay {
394e5c89e4eSSatish Balay   char           *pp = (char*)p;
395e5c89e4eSSatish Balay   int            err,wsize;
396e5c89e4eSSatish Balay   size_t         m = (size_t)n,maxblock=65536;
397e5c89e4eSSatish Balay   PetscErrorCode ierr;
398f5351476SHong Zhang #if !defined(PETSC_WORDS_BIGENDIAN)
399e5c89e4eSSatish Balay   void           *ptmp = p;
400e5c89e4eSSatish Balay #endif
40105acbc63SBarry Smith   char           *fname = NULL;
4020da86b62SBarry Smith #if defined(PETSC_USE_REAL___FLOAT128)
403df40af56SBarry Smith   PetscBool      writedouble = PETSC_FALSE;
4040da86b62SBarry Smith   double         *ppp;
4050da86b62SBarry Smith   PetscReal      *pv;
4060da86b62SBarry Smith   PetscInt       i;
4070da86b62SBarry Smith #endif
40841f502e3SPatrick Sanan   PetscDataType  wtype = type;
409e5c89e4eSSatish Balay 
410e5c89e4eSSatish Balay   PetscFunctionBegin;
411e32f2f54SBarry Smith   if (n < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Trying to write a negative amount of data %D",n);
412e5c89e4eSSatish Balay   if (!n) PetscFunctionReturn(0);
413e5c89e4eSSatish Balay 
4142d53ad75SBarry Smith   if (type == PETSC_FUNCTION) {
4152d53ad75SBarry Smith #if defined(PETSC_SERIALIZE_FUNCTIONS)
4162d53ad75SBarry Smith     const char *fnametmp;
4172d53ad75SBarry Smith #endif
4182d53ad75SBarry Smith     m     = 64;
419e25ab156SSatish Balay     fname = (char*)malloc(m*sizeof(char));
42005acbc63SBarry Smith     if (!fname) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Cannot allocate space for function name");
42105acbc63SBarry Smith #if defined(PETSC_SERIALIZE_FUNCTIONS)
42205acbc63SBarry Smith     if (n > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Can only binary view a single function at a time");
42305acbc63SBarry Smith     ierr = PetscFPTFind(*(void**)p,&fnametmp);CHKERRQ(ierr);
42405acbc63SBarry Smith     ierr = PetscStrncpy(fname,fnametmp,m);CHKERRQ(ierr);
42505acbc63SBarry Smith #else
42605acbc63SBarry Smith     ierr = PetscStrncpy(fname,"",m);CHKERRQ(ierr);
42705acbc63SBarry Smith #endif
42801963f56SBarry Smith     wtype = PETSC_CHAR;
4292d53ad75SBarry Smith     pp    = (char*)fname;
4302d53ad75SBarry Smith #if !defined(PETSC_WORDS_BIGENDIAN)
4312d53ad75SBarry Smith     ptmp  = (void*)fname;
4322d53ad75SBarry Smith #endif
4332d53ad75SBarry Smith   }
4342d53ad75SBarry Smith 
4350da86b62SBarry Smith #if defined(PETSC_USE_REAL___FLOAT128)
4360da86b62SBarry Smith   ierr = PetscOptionsGetBool(NULL,NULL,"-binary_write_double",&writedouble,NULL);CHKERRQ(ierr);
4370da86b62SBarry Smith   /* If using __float128 precision we still write in doubles to file */
4384caf0332SSatish Balay   if ((type == PETSC_SCALAR || type == PETSC_REAL) && writedouble) {
43941f502e3SPatrick Sanan     wtype = PETSC_DOUBLE;
4400da86b62SBarry Smith     ierr = PetscMalloc1(n,&ppp);CHKERRQ(ierr);
4410da86b62SBarry Smith     pv = (PetscReal*)pp;
4420da86b62SBarry Smith     for (i=0; i<n; i++) {
4430da86b62SBarry Smith       ppp[i] = (double) pv[i];
4440da86b62SBarry Smith     }
4450da86b62SBarry Smith     pp   = (char*)ppp;
4460da86b62SBarry Smith     ptmp = (char*)ppp;
4470da86b62SBarry Smith   }
4480da86b62SBarry Smith #endif
4490da86b62SBarry Smith 
45041f502e3SPatrick Sanan   if (wtype == PETSC_INT)          m *= sizeof(PetscInt);
45141f502e3SPatrick Sanan   else if (wtype == PETSC_SCALAR)  m *= sizeof(PetscScalar);
4524caf0332SSatish Balay   else if (wtype == PETSC_REAL)    m *= sizeof(PetscReal);
45341f502e3SPatrick Sanan   else if (wtype == PETSC_DOUBLE)  m *= sizeof(double);
45441f502e3SPatrick Sanan   else if (wtype == PETSC_FLOAT)   m *= sizeof(float);
45541f502e3SPatrick Sanan   else if (wtype == PETSC_SHORT)   m *= sizeof(short);
456972064b6SLisandro Dalcin   else if (wtype == PETSC_LONG)    m *= sizeof(long);
45741f502e3SPatrick Sanan   else if (wtype == PETSC_CHAR)    m *= sizeof(char);
45841f502e3SPatrick Sanan   else if (wtype == PETSC_ENUM)    m *= sizeof(PetscEnum);
45941f502e3SPatrick Sanan   else if (wtype == PETSC_BOOL)    m *= sizeof(PetscBool);
4609e3e4c22SLisandro Dalcin   else if (wtype == PETSC_INT64)   m *= sizeof(PetscInt64);
46141f502e3SPatrick Sanan   else if (wtype == PETSC_BIT_LOGICAL) m = PetscBTLength(m)*sizeof(char);
462e32f2f54SBarry Smith   else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown type");
463e5c89e4eSSatish Balay 
464e5c89e4eSSatish Balay #if !defined(PETSC_WORDS_BIGENDIAN)
46541f502e3SPatrick Sanan   ierr = PetscByteSwap(ptmp,wtype,n);CHKERRQ(ierr);
466e5c89e4eSSatish Balay #endif
467e5c89e4eSSatish Balay 
468e5c89e4eSSatish Balay   while (m) {
469e5c89e4eSSatish Balay     wsize = (m < maxblock) ? m : maxblock;
470e5c89e4eSSatish Balay     err   = write(fd,pp,wsize);
471e5c89e4eSSatish Balay     if (err < 0 && errno == EINTR) continue;
47204102261SBarry Smith     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);
473e5c89e4eSSatish Balay     m  -= wsize;
474e5c89e4eSSatish Balay     pp += wsize;
475e5c89e4eSSatish Balay   }
476e5c89e4eSSatish Balay 
477b659c0ceSSatish Balay #if !defined(PETSC_WORDS_BIGENDIAN)
478e5c89e4eSSatish Balay   if (!istemp) {
47941f502e3SPatrick Sanan     ierr = PetscByteSwap(ptmp,wtype,n);CHKERRQ(ierr);
480e5c89e4eSSatish Balay   }
481e5c89e4eSSatish Balay #endif
48205acbc63SBarry Smith   if (type == PETSC_FUNCTION) {
48305acbc63SBarry Smith     free(fname);
48405acbc63SBarry Smith   }
4850da86b62SBarry Smith #if defined(PETSC_USE_REAL___FLOAT128)
4864caf0332SSatish Balay   if ((type == PETSC_SCALAR || type == PETSC_REAL) && writedouble) {
4870da86b62SBarry Smith     ierr = PetscFree(ppp);CHKERRQ(ierr);
4880da86b62SBarry Smith   }
4890da86b62SBarry Smith #endif
490e5c89e4eSSatish Balay   PetscFunctionReturn(0);
491e5c89e4eSSatish Balay }
492e5c89e4eSSatish Balay 
493e5c89e4eSSatish Balay /*@C
494e5c89e4eSSatish Balay    PetscBinaryOpen - Opens a PETSc binary file.
495e5c89e4eSSatish Balay 
496e5c89e4eSSatish Balay    Not Collective
497e5c89e4eSSatish Balay 
498e5c89e4eSSatish Balay    Input Parameters:
499e5c89e4eSSatish Balay +  name - filename
50045c64e65SBarry Smith -  type - type of binary file, one of FILE_MODE_READ, FILE_MODE_APPEND, FILE_MODE_WRITE
501e5c89e4eSSatish Balay 
502e5c89e4eSSatish Balay    Output Parameter:
503e5c89e4eSSatish Balay .  fd - the file
504e5c89e4eSSatish Balay 
505e5c89e4eSSatish Balay    Level: advanced
506e5c89e4eSSatish Balay 
507e5c89e4eSSatish Balay   Concepts: files^opening binary
508e5c89e4eSSatish Balay   Concepts: binary files^opening
509e5c89e4eSSatish Balay 
51095452b02SPatrick Sanan    Notes:
51195452b02SPatrick Sanan     Files access with PetscBinaryRead() and PetscBinaryWrite() are ALWAYS written in
512e5c89e4eSSatish Balay    big-endian format. This means the file can be accessed using PetscBinaryOpen() and
513e5c89e4eSSatish Balay    PetscBinaryRead() and PetscBinaryWrite() on any machine.
514e5c89e4eSSatish Balay 
5154ebed01fSBarry Smith .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscFileMode, PetscViewerFileSetMode(), PetscViewerBinaryGetDescriptor(),
5164ebed01fSBarry Smith           PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek()
51745c64e65SBarry Smith 
518e5c89e4eSSatish Balay @*/
5197087cfbeSBarry Smith PetscErrorCode  PetscBinaryOpen(const char name[],PetscFileMode mode,int *fd)
520e5c89e4eSSatish Balay {
521e5c89e4eSSatish Balay   PetscFunctionBegin;
522e5c89e4eSSatish Balay #if defined(PETSC_HAVE_O_BINARY)
52345c64e65SBarry Smith   if (mode == FILE_MODE_WRITE) {
524a297a907SKarl Rupp     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);
52545c64e65SBarry Smith   } else if (mode == FILE_MODE_READ) {
526a297a907SKarl Rupp     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);
52745c64e65SBarry Smith   } else if (mode == FILE_MODE_APPEND) {
528a297a907SKarl Rupp     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);
529e5c89e4eSSatish Balay #else
53045c64e65SBarry Smith   if (mode == FILE_MODE_WRITE) {
531a297a907SKarl Rupp     if ((*fd = creat(name,0666)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot create file for writing: %s",name);
53245c64e65SBarry Smith   } else if (mode == FILE_MODE_READ) {
533a297a907SKarl Rupp     if ((*fd = open(name,O_RDONLY,0)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file for reading: %s",name);
534e5c89e4eSSatish Balay   }
53545c64e65SBarry Smith   else if (mode == FILE_MODE_APPEND) {
536a297a907SKarl Rupp     if ((*fd = open(name,O_WRONLY,0)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file for writing: %s",name);
537e5c89e4eSSatish Balay #endif
538e32f2f54SBarry Smith   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown file mode");
539e5c89e4eSSatish Balay   PetscFunctionReturn(0);
540e5c89e4eSSatish Balay }
541e5c89e4eSSatish Balay 
542e30d2299SSatish Balay /*@
543e5c89e4eSSatish Balay    PetscBinaryClose - Closes a PETSc binary file.
544e5c89e4eSSatish Balay 
545e5c89e4eSSatish Balay    Not Collective
546e5c89e4eSSatish Balay 
547e5c89e4eSSatish Balay    Output Parameter:
548e5c89e4eSSatish Balay .  fd - the file
549e5c89e4eSSatish Balay 
550e5c89e4eSSatish Balay    Level: advanced
551e5c89e4eSSatish Balay 
5524ebed01fSBarry Smith .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
5534ebed01fSBarry Smith           PetscBinarySynchronizedSeek()
554e5c89e4eSSatish Balay @*/
5557087cfbeSBarry Smith PetscErrorCode  PetscBinaryClose(int fd)
556e5c89e4eSSatish Balay {
557e5c89e4eSSatish Balay   PetscFunctionBegin;
558e5c89e4eSSatish Balay   close(fd);
559e5c89e4eSSatish Balay   PetscFunctionReturn(0);
560e5c89e4eSSatish Balay }
561e5c89e4eSSatish Balay 
562e5c89e4eSSatish Balay 
563e8976759SBarry Smith /*@C
564e5c89e4eSSatish Balay    PetscBinarySeek - Moves the file pointer on a PETSc binary file.
565e5c89e4eSSatish Balay 
566e5c89e4eSSatish Balay    Not Collective
567e5c89e4eSSatish Balay 
568e5c89e4eSSatish Balay    Input Parameters:
569e5c89e4eSSatish Balay +  fd - the file
570ff553b35SMatthew Knepley .  off - number of bytes to move. Use PETSC_BINARY_INT_SIZE, PETSC_BINARY_SCALAR_SIZE,
571e5c89e4eSSatish Balay             etc. in your calculation rather than sizeof() to compute byte lengths.
572ff553b35SMatthew Knepley -  whence - if PETSC_BINARY_SEEK_SET then off is an absolute location in the file
573ff553b35SMatthew Knepley             if PETSC_BINARY_SEEK_CUR then off is an offset from the current location
574ff553b35SMatthew Knepley             if PETSC_BINARY_SEEK_END then off is an offset from the end of file
575e5c89e4eSSatish Balay 
576e5c89e4eSSatish Balay    Output Parameter:
577e5c89e4eSSatish Balay .   offset - new offset in file
578e5c89e4eSSatish Balay 
579e5c89e4eSSatish Balay    Level: developer
580e5c89e4eSSatish Balay 
581e5c89e4eSSatish Balay    Notes:
582e5c89e4eSSatish Balay    Integers are stored on the file as 32 long, regardless of whether
583e5c89e4eSSatish Balay    they are stored in the machine as 32 or 64, this means the same
584e5c89e4eSSatish Balay    binary file may be read on any machine. Hence you CANNOT use sizeof()
585e5c89e4eSSatish Balay    to determine the offset or location.
586e5c89e4eSSatish Balay 
587e5c89e4eSSatish Balay    Concepts: files^binary seeking
588e5c89e4eSSatish Balay    Concepts: binary files^seeking
589e5c89e4eSSatish Balay 
5904ebed01fSBarry Smith .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
5914ebed01fSBarry Smith           PetscBinarySynchronizedSeek()
592e5c89e4eSSatish Balay @*/
5937087cfbeSBarry Smith PetscErrorCode  PetscBinarySeek(int fd,off_t off,PetscBinarySeekType whence,off_t *offset)
594e5c89e4eSSatish Balay {
595e5c89e4eSSatish Balay   int iwhence = 0;
596e5c89e4eSSatish Balay 
597e5c89e4eSSatish Balay   PetscFunctionBegin;
598a297a907SKarl Rupp   if (whence == PETSC_BINARY_SEEK_SET) iwhence = SEEK_SET;
599a297a907SKarl Rupp   else if (whence == PETSC_BINARY_SEEK_CUR) iwhence = SEEK_CUR;
600a297a907SKarl Rupp   else if (whence == PETSC_BINARY_SEEK_END) iwhence = SEEK_END;
601a297a907SKarl Rupp   else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown seek location");
602e5c89e4eSSatish Balay #if defined(PETSC_HAVE_LSEEK)
603e5c89e4eSSatish Balay   *offset = lseek(fd,off,iwhence);
604e5c89e4eSSatish Balay #elif defined(PETSC_HAVE__LSEEK)
605e5c89e4eSSatish Balay   *offset = _lseek(fd,(long)off,iwhence);
606e5c89e4eSSatish Balay #else
607e32f2f54SBarry Smith   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS,"System does not have a way of seeking on a file");
608e5c89e4eSSatish Balay #endif
609e5c89e4eSSatish Balay   PetscFunctionReturn(0);
610e5c89e4eSSatish Balay }
611e5c89e4eSSatish Balay 
612e5c89e4eSSatish Balay /*@C
6131d280d73SBarry Smith    PetscBinarySynchronizedRead - Reads from a binary file.
614e5c89e4eSSatish Balay 
615e5c89e4eSSatish Balay    Collective on MPI_Comm
616e5c89e4eSSatish Balay 
617e5c89e4eSSatish Balay    Input Parameters:
618e5c89e4eSSatish Balay +  comm - the MPI communicator
619*9860990eSLisandro Dalcin .  fd - the file descriptor
620*9860990eSLisandro Dalcin .  num  - the maximum number of items to read
621*9860990eSLisandro Dalcin -  type - the type of items to read (PETSC_INT, PETSC_REAL, PETSC_SCALAR, etc.)
622e5c89e4eSSatish Balay 
623e5c89e4eSSatish Balay    Output Parameters:
624*9860990eSLisandro Dalcin +  data - the buffer
625*9860990eSLisandro Dalcin -  count - the number of items read, optional
626e5c89e4eSSatish Balay 
627e5c89e4eSSatish Balay    Level: developer
628e5c89e4eSSatish Balay 
629e5c89e4eSSatish Balay    Notes:
630e5c89e4eSSatish Balay    Does a PetscBinaryRead() followed by an MPI_Bcast()
631e5c89e4eSSatish Balay 
632*9860990eSLisandro Dalcin    If count is not provided and the number of items read is less than
633*9860990eSLisandro Dalcin    the maximum number of items to read, then this routine errors.
634*9860990eSLisandro Dalcin 
6351d280d73SBarry Smith    PetscBinarySynchronizedRead() uses byte swapping to work on all machines.
636e5c89e4eSSatish Balay    Integers are stored on the file as 32 long, regardless of whether
637e5c89e4eSSatish Balay    they are stored in the machine as 32 or 64, this means the same
638e5c89e4eSSatish Balay    binary file may be read on any machine.
639e5c89e4eSSatish Balay 
640e5c89e4eSSatish Balay    Concepts: files^synchronized reading of binary files
641e5c89e4eSSatish Balay    Concepts: binary files^reading, synchronized
642e5c89e4eSSatish Balay 
6434ebed01fSBarry Smith .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscBinaryRead(), PetscBinarySynchronizedWrite(),
6444ebed01fSBarry Smith           PetscBinarySynchronizedSeek()
645e5c89e4eSSatish Balay @*/
646*9860990eSLisandro Dalcin PetscErrorCode  PetscBinarySynchronizedRead(MPI_Comm comm,int fd,void *data,PetscInt num,PetscInt *count,PetscDataType type)
647e5c89e4eSSatish Balay {
648*9860990eSLisandro Dalcin   PetscErrorCode ierr;
649e5c89e4eSSatish Balay   PetscMPIInt    rank;
650e5c89e4eSSatish Balay   MPI_Datatype   mtype;
651*9860990eSLisandro Dalcin   PetscInt       ibuf[2] = {0, 0};
65205acbc63SBarry Smith   char           *fname = NULL;
653*9860990eSLisandro Dalcin   void           *fptr = NULL;
654e5c89e4eSSatish Balay 
655e5c89e4eSSatish Balay   PetscFunctionBegin;
6562d53ad75SBarry Smith   if (type == PETSC_FUNCTION) {
657*9860990eSLisandro Dalcin     num   = 64;
6582d53ad75SBarry Smith     type  = PETSC_CHAR;
659*9860990eSLisandro Dalcin     fname = (char*)malloc(num*sizeof(char));
660*9860990eSLisandro Dalcin     fptr  = data;
661*9860990eSLisandro Dalcin     data  = (void*)fname;
66205acbc63SBarry Smith     if (!fname) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Cannot allocate space for function name");
6632d53ad75SBarry Smith   }
6642d53ad75SBarry Smith 
665e5c89e4eSSatish Balay   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
666e5c89e4eSSatish Balay   if (!rank) {
667*9860990eSLisandro Dalcin     ibuf[0] = PetscBinaryRead(fd,data,num,count?&ibuf[1]:NULL,type);
668e5c89e4eSSatish Balay   }
669*9860990eSLisandro Dalcin   ierr = MPI_Bcast(ibuf,2,MPIU_INT,0,comm);CHKERRQ(ierr);
670*9860990eSLisandro Dalcin   ierr = (PetscErrorCode)ibuf[0];CHKERRQ(ierr);
671e5c89e4eSSatish Balay   ierr = PetscDataTypeToMPIDataType(type,&mtype);CHKERRQ(ierr);
672*9860990eSLisandro Dalcin   ierr = MPI_Bcast(data,count?ibuf[1]:num,mtype,0,comm);CHKERRQ(ierr);
673*9860990eSLisandro Dalcin   if (count) *count = ibuf[1];
6742d53ad75SBarry Smith 
675e366c363SBarry Smith   if (type == PETSC_FUNCTION) {
6762d53ad75SBarry Smith #if defined(PETSC_SERIALIZE_FUNCTIONS)
677*9860990eSLisandro Dalcin     ierr = PetscDLLibrarySym(PETSC_COMM_SELF,&PetscDLLibrariesLoaded,NULL,fname,(void**)fptr);CHKERRQ(ierr);
6782d53ad75SBarry Smith #else
679*9860990eSLisandro Dalcin     *(void**)fptr = NULL;
6802d53ad75SBarry Smith #endif
681e366c363SBarry Smith     free(fname);
6822d53ad75SBarry Smith   }
683e5c89e4eSSatish Balay   PetscFunctionReturn(0);
684e5c89e4eSSatish Balay }
685e5c89e4eSSatish Balay 
686e5c89e4eSSatish Balay /*@C
6871d280d73SBarry Smith    PetscBinarySynchronizedWrite - writes to a binary file.
688e5c89e4eSSatish Balay 
689e5c89e4eSSatish Balay    Collective on MPI_Comm
690e5c89e4eSSatish Balay 
691e5c89e4eSSatish Balay    Input Parameters:
692e5c89e4eSSatish Balay +  comm - the MPI communicator
693e5c89e4eSSatish Balay .  fd - the file
694e5c89e4eSSatish Balay .  n  - the number of items to write
695e5c89e4eSSatish Balay .  p - the buffer
696e5c89e4eSSatish Balay .  istemp - the buffer may be changed
697e5c89e4eSSatish Balay -  type - the type of items to write (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)
698e5c89e4eSSatish Balay 
699e5c89e4eSSatish Balay    Level: developer
700e5c89e4eSSatish Balay 
701e5c89e4eSSatish Balay    Notes:
702e5c89e4eSSatish Balay    Process 0 does a PetscBinaryWrite()
703e5c89e4eSSatish Balay 
7041d280d73SBarry Smith    PetscBinarySynchronizedWrite() uses byte swapping to work on all machines.
705e5c89e4eSSatish Balay    Integers are stored on the file as 32 long, regardless of whether
706e5c89e4eSSatish Balay    they are stored in the machine as 32 or 64, this means the same
707e5c89e4eSSatish Balay    binary file may be read on any machine.
708e5c89e4eSSatish Balay 
70995452b02SPatrick Sanan    Notes:
71095452b02SPatrick Sanan     because byte-swapping may be done on the values in data it cannot be declared const
711300a7f5bSBarry Smith 
7121d280d73SBarry Smith    WARNING: This is NOT like PetscSynchronizedFPrintf()! This routine ignores calls on all but process 0,
7131d280d73SBarry Smith    while PetscSynchronizedFPrintf() has all processes print their strings in order.
7141d280d73SBarry Smith 
715e5c89e4eSSatish Balay    Concepts: files^synchronized writing of binary files
716e5c89e4eSSatish Balay    Concepts: binary files^reading, synchronized
717e5c89e4eSSatish Balay 
7184ebed01fSBarry Smith .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscBinaryRead(), PetscBinarySynchronizedRead(),
7194ebed01fSBarry Smith           PetscBinarySynchronizedSeek()
720e5c89e4eSSatish Balay @*/
7217087cfbeSBarry Smith PetscErrorCode  PetscBinarySynchronizedWrite(MPI_Comm comm,int fd,void *p,PetscInt n,PetscDataType type,PetscBool istemp)
722e5c89e4eSSatish Balay {
723e5c89e4eSSatish Balay   PetscErrorCode ierr;
724e5c89e4eSSatish Balay   PetscMPIInt    rank;
725e5c89e4eSSatish Balay 
726e5c89e4eSSatish Balay   PetscFunctionBegin;
727e5c89e4eSSatish Balay   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
728e5c89e4eSSatish Balay   if (!rank) {
729e5c89e4eSSatish Balay     ierr = PetscBinaryWrite(fd,p,n,type,istemp);CHKERRQ(ierr);
730e5c89e4eSSatish Balay   }
731e5c89e4eSSatish Balay   PetscFunctionReturn(0);
732e5c89e4eSSatish Balay }
733e5c89e4eSSatish Balay 
734e5c89e4eSSatish Balay /*@C
7351d280d73SBarry Smith    PetscBinarySynchronizedSeek - Moves the file pointer on a PETSc binary file.
736e5c89e4eSSatish Balay 
737e5c89e4eSSatish Balay 
738e5c89e4eSSatish Balay    Input Parameters:
739e5c89e4eSSatish Balay +  fd - the file
740e5c89e4eSSatish Balay .  whence - if PETSC_BINARY_SEEK_SET then size is an absolute location in the file
741e5c89e4eSSatish Balay             if PETSC_BINARY_SEEK_CUR then size is offset from current location
742e5c89e4eSSatish Balay             if PETSC_BINARY_SEEK_END then size is offset from end of file
743e5c89e4eSSatish Balay -  off    - number of bytes to move. Use PETSC_BINARY_INT_SIZE, PETSC_BINARY_SCALAR_SIZE,
744e5c89e4eSSatish Balay             etc. in your calculation rather than sizeof() to compute byte lengths.
745e5c89e4eSSatish Balay 
746e5c89e4eSSatish Balay    Output Parameter:
747e5c89e4eSSatish Balay .   offset - new offset in file
748e5c89e4eSSatish Balay 
749e5c89e4eSSatish Balay    Level: developer
750e5c89e4eSSatish Balay 
751e5c89e4eSSatish Balay    Notes:
752e5c89e4eSSatish Balay    Integers are stored on the file as 32 long, regardless of whether
753e5c89e4eSSatish Balay    they are stored in the machine as 32 or 64, this means the same
754e5c89e4eSSatish Balay    binary file may be read on any machine. Hence you CANNOT use sizeof()
755e5c89e4eSSatish Balay    to determine the offset or location.
756e5c89e4eSSatish Balay 
757e5c89e4eSSatish Balay    Concepts: binary files^seeking
758e5c89e4eSSatish Balay    Concepts: files^seeking in binary
759e5c89e4eSSatish Balay 
7604ebed01fSBarry Smith .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
7614ebed01fSBarry Smith           PetscBinarySynchronizedSeek()
762e5c89e4eSSatish Balay @*/
7637087cfbeSBarry Smith PetscErrorCode  PetscBinarySynchronizedSeek(MPI_Comm comm,int fd,off_t off,PetscBinarySeekType whence,off_t *offset)
764e5c89e4eSSatish Balay {
765e5c89e4eSSatish Balay   PetscErrorCode ierr;
766e5c89e4eSSatish Balay   PetscMPIInt    rank;
767e5c89e4eSSatish Balay 
768e5c89e4eSSatish Balay   PetscFunctionBegin;
769e5c89e4eSSatish Balay   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
770e5c89e4eSSatish Balay   if (!rank) {
771e5c89e4eSSatish Balay     ierr = PetscBinarySeek(fd,off,whence,offset);CHKERRQ(ierr);
772e5c89e4eSSatish Balay   }
773e5c89e4eSSatish Balay   PetscFunctionReturn(0);
774e5c89e4eSSatish Balay }
775e5c89e4eSSatish Balay 
7760fc9d207SBarry Smith #if defined(PETSC_HAVE_MPIIO)
777e39fd77fSBarry Smith #if !defined(PETSC_WORDS_BIGENDIAN)
778e39fd77fSBarry Smith 
779951e3c8eSBarry Smith #if defined(PETSC_USE_PETSC_MPI_EXTERNAL32)
780e39fd77fSBarry Smith /*
781e39fd77fSBarry Smith       MPICH does not provide the external32 representation for MPI_File_set_view() so we need to provide the functions.
782e39fd77fSBarry Smith     These are set into MPI in PetscInitialize() via MPI_Register_datarep()
783e39fd77fSBarry Smith 
784e39fd77fSBarry Smith     Note I use PetscMPIInt for the MPI error codes since that is what MPI uses (instead of the standard PetscErrorCode)
785e39fd77fSBarry Smith 
786951e3c8eSBarry Smith     The next three routines are not used because MPICH does not support their use
787e39fd77fSBarry Smith 
788e39fd77fSBarry Smith */
7898cc058d9SJed Brown PETSC_EXTERN PetscMPIInt PetscDataRep_extent_fn(MPI_Datatype datatype,MPI_Aint *file_extent,void *extra_state)
790e39fd77fSBarry Smith {
791e39fd77fSBarry Smith   MPI_Aint    ub;
792e39fd77fSBarry Smith   PetscMPIInt ierr;
793e39fd77fSBarry Smith 
794e39fd77fSBarry Smith   ierr = MPI_Type_get_extent(datatype,&ub,file_extent);
795e39fd77fSBarry Smith   return ierr;
796e39fd77fSBarry Smith }
797e39fd77fSBarry Smith 
7988cc058d9SJed Brown PETSC_EXTERN PetscMPIInt PetscDataRep_read_conv_fn(void *userbuf, MPI_Datatype datatype,PetscMPIInt count,void *filebuf, MPI_Offset position,void *extra_state)
799e39fd77fSBarry Smith {
800e39fd77fSBarry Smith   PetscDataType pdtype;
801e39fd77fSBarry Smith   PetscMPIInt   ierr;
802e39fd77fSBarry Smith   size_t        dsize;
803e39fd77fSBarry Smith 
804e39fd77fSBarry Smith   ierr = PetscMPIDataTypeToPetscDataType(datatype,&pdtype);CHKERRQ(ierr);
805e39fd77fSBarry Smith   ierr = PetscDataTypeGetSize(pdtype,&dsize);CHKERRQ(ierr);
806e39fd77fSBarry Smith 
807e39fd77fSBarry Smith   /* offset is given in units of MPI_Datatype */
808e39fd77fSBarry Smith   userbuf = ((char*)userbuf) + dsize*position;
809e39fd77fSBarry Smith 
810e39fd77fSBarry Smith   ierr = PetscMemcpy(userbuf,filebuf,count*dsize);CHKERRQ(ierr);
811e39fd77fSBarry Smith   ierr = PetscByteSwap(userbuf,pdtype,count);CHKERRQ(ierr);
812e39fd77fSBarry Smith   return ierr;
813e39fd77fSBarry Smith }
814e39fd77fSBarry Smith 
815e39fd77fSBarry Smith PetscMPIInt PetscDataRep_write_conv_fn(void *userbuf, MPI_Datatype datatype,PetscMPIInt count,void *filebuf, MPI_Offset position,void *extra_state)
816e39fd77fSBarry Smith {
817e39fd77fSBarry Smith   PetscDataType pdtype;
818e39fd77fSBarry Smith   PetscMPIInt   ierr;
819e39fd77fSBarry Smith   size_t        dsize;
820e39fd77fSBarry Smith 
821e39fd77fSBarry Smith   ierr = PetscMPIDataTypeToPetscDataType(datatype,&pdtype);CHKERRQ(ierr);
822e39fd77fSBarry Smith   ierr = PetscDataTypeGetSize(pdtype,&dsize);CHKERRQ(ierr);
823e39fd77fSBarry Smith 
824e39fd77fSBarry Smith   /* offset is given in units of MPI_Datatype */
825e39fd77fSBarry Smith   userbuf = ((char*)userbuf) + dsize*position;
826e39fd77fSBarry Smith 
827e39fd77fSBarry Smith   ierr = PetscMemcpy(filebuf,userbuf,count*dsize);CHKERRQ(ierr);
828e39fd77fSBarry Smith   ierr = PetscByteSwap(filebuf,pdtype,count);CHKERRQ(ierr);
829e39fd77fSBarry Smith   return ierr;
830e39fd77fSBarry Smith }
831951e3c8eSBarry Smith #endif
832e39fd77fSBarry Smith 
833e39fd77fSBarry Smith PetscErrorCode MPIU_File_write_all(MPI_File fd,void *data,PetscMPIInt cnt,MPI_Datatype dtype,MPI_Status *status)
834e39fd77fSBarry Smith {
835e39fd77fSBarry Smith   PetscErrorCode ierr;
836e39fd77fSBarry Smith   PetscDataType  pdtype;
837e39fd77fSBarry Smith 
838e39fd77fSBarry Smith   PetscFunctionBegin;
839e39fd77fSBarry Smith   ierr = PetscMPIDataTypeToPetscDataType(dtype,&pdtype);CHKERRQ(ierr);
840e39fd77fSBarry Smith   ierr = PetscByteSwap(data,pdtype,cnt);CHKERRQ(ierr);
841e39fd77fSBarry Smith   ierr = MPI_File_write_all(fd,data,cnt,dtype,status);CHKERRQ(ierr);
842e39fd77fSBarry Smith   ierr = PetscByteSwap(data,pdtype,cnt);CHKERRQ(ierr);
843a6796414SBarry Smith   PetscFunctionReturn(0);
844e39fd77fSBarry Smith }
845e39fd77fSBarry Smith 
846e39fd77fSBarry Smith PetscErrorCode MPIU_File_read_all(MPI_File fd,void *data,PetscMPIInt cnt,MPI_Datatype dtype,MPI_Status *status)
847e39fd77fSBarry Smith {
848e39fd77fSBarry Smith   PetscErrorCode ierr;
849e39fd77fSBarry Smith   PetscDataType  pdtype;
850e39fd77fSBarry Smith 
851e39fd77fSBarry Smith   PetscFunctionBegin;
852e39fd77fSBarry Smith   ierr = PetscMPIDataTypeToPetscDataType(dtype,&pdtype);CHKERRQ(ierr);
853e39fd77fSBarry Smith   ierr = MPI_File_read_all(fd,data,cnt,dtype,status);CHKERRQ(ierr);
854e39fd77fSBarry Smith   ierr = PetscByteSwap(data,pdtype,cnt);CHKERRQ(ierr);
855a6796414SBarry Smith   PetscFunctionReturn(0);
856e39fd77fSBarry Smith }
857e39fd77fSBarry Smith #endif
858951e3c8eSBarry Smith #endif
859