xref: /petsc/src/sys/fileio/sysio.c (revision 02c9f0b548ed2228330a66acd2df0a92dd2a8bb1)
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 
17*02c9f0b5SLisandro Dalcin const char *const PetscFileModes[] = {"READ","WRITE","APPEND","UPDATE","APPEND_UPDATE","PetscFileMode","PETSC_FILE_",NULL};
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);}
2179860990eSLisandro 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 
2269860990eSLisandro Dalcin /*@C
227e5c89e4eSSatish Balay    PetscBinaryRead - Reads from a binary file.
228e5c89e4eSSatish Balay 
229e5c89e4eSSatish Balay    Not Collective
230e5c89e4eSSatish Balay 
231e5c89e4eSSatish Balay    Input Parameters:
2329860990eSLisandro Dalcin +  fd - the file descriptor
2339860990eSLisandro Dalcin .  num  - the maximum number of items to read
2349860990eSLisandro Dalcin -  type - the type of items to read (PETSC_INT, PETSC_REAL, PETSC_SCALAR, etc.)
235e5c89e4eSSatish Balay 
236e5c89e4eSSatish Balay    Output Parameters:
2379860990eSLisandro Dalcin +  data - the buffer
2389860990eSLisandro Dalcin -  count - the number of items read, optional
239e5c89e4eSSatish Balay 
240e5c89e4eSSatish Balay 
241e5c89e4eSSatish Balay 
242e5c89e4eSSatish Balay    Level: developer
243e5c89e4eSSatish Balay 
244e5c89e4eSSatish Balay    Notes:
2459860990eSLisandro Dalcin    If count is not provided and the number of items read is less than
2469860990eSLisandro Dalcin    the maximum number of items to read, then this routine errors.
2479860990eSLisandro 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 
2564ebed01fSBarry Smith .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscViewerBinaryGetDescriptor(), PetscBinarySynchronizedWrite(),
2574ebed01fSBarry Smith           PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek()
258e5c89e4eSSatish Balay @*/
2599860990eSLisandro Dalcin PetscErrorCode  PetscBinaryRead(int fd,void *data,PetscInt num,PetscInt *count,PetscDataType type)
260e5c89e4eSSatish Balay {
2619860990eSLisandro Dalcin   size_t            typesize, m = (size_t) num, n = 0, maxblock = 65536;
2629860990eSLisandro Dalcin   char              *p = (char*)data;
2637a881295SBarry Smith #if defined(PETSC_USE_REAL___FLOAT128)
264cba51d77SBarry Smith   PetscBool         readdouble = PETSC_FALSE;
2659860990eSLisandro Dalcin   double            *pdouble;
2667a881295SBarry Smith #endif
2679860990eSLisandro Dalcin   void              *ptmp = data;
26805acbc63SBarry Smith   char              *fname = NULL;
2699860990eSLisandro Dalcin   PetscErrorCode    ierr;
270e5c89e4eSSatish Balay 
271e5c89e4eSSatish Balay   PetscFunctionBegin;
2729860990eSLisandro Dalcin   if (count) *count = 0;
2739860990eSLisandro Dalcin   if (num < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Trying to read a negative amount of data %D",num);
2749860990eSLisandro Dalcin   if (!num) PetscFunctionReturn(0);
275e5c89e4eSSatish Balay 
2762d53ad75SBarry Smith   if (type == PETSC_FUNCTION) {
2772d53ad75SBarry Smith     m     = 64;
2782d53ad75SBarry Smith     type  = PETSC_CHAR;
27905acbc63SBarry Smith     fname = (char*)malloc(m*sizeof(char));
2809860990eSLisandro Dalcin     p     = (char*)fname;
2812d53ad75SBarry Smith     ptmp  = (void*)fname;
2829860990eSLisandro Dalcin     if (!fname) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Cannot allocate space for function name");
2832d53ad75SBarry Smith   }
2849860990eSLisandro Dalcin   if (type == PETSC_BIT_LOGICAL) m = PetscBTLength(m);
2852d53ad75SBarry Smith 
2869860990eSLisandro Dalcin   ierr = PetscDataTypeGetSize(type,&typesize);CHKERRQ(ierr);
287e5c89e4eSSatish Balay 
2887a881295SBarry Smith #if defined(PETSC_USE_REAL___FLOAT128)
289c5929fdfSBarry Smith   ierr = PetscOptionsGetBool(NULL,NULL,"-binary_read_double",&readdouble,NULL);CHKERRQ(ierr);
2907a881295SBarry Smith   /* If using __float128 precision we still read in doubles from file */
2919860990eSLisandro Dalcin   if ((type == PETSC_REAL || type == PETSC_COMPLEX) && readdouble) {
2929860990eSLisandro Dalcin     PetscInt cnt = num * ((type == PETSC_REAL) ? 1 : 2);
2939860990eSLisandro Dalcin     ierr = PetscMalloc1(cnt,&pdouble);CHKERRQ(ierr);
2949860990eSLisandro Dalcin     p = (char*)pdouble;
2959860990eSLisandro Dalcin     typesize /= 2;
2967a881295SBarry Smith   }
2977a881295SBarry Smith #endif
2987a881295SBarry Smith 
2999860990eSLisandro Dalcin   m *= typesize;
3009860990eSLisandro Dalcin 
301e5c89e4eSSatish Balay   while (m) {
3029860990eSLisandro Dalcin     size_t len = (m < maxblock) ? m : maxblock;
3039860990eSLisandro Dalcin     int    ret = (int)read(fd,p,len);
3049860990eSLisandro Dalcin     if (ret < 0 && errno == EINTR) continue;
3059860990eSLisandro Dalcin     if (!ret && len > 0) break; /* Proxy for EOF */
3069860990eSLisandro Dalcin     if (ret < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_READ,"Error reading from file, errno %d",errno);
3079860990eSLisandro Dalcin     m -= ret;
3089860990eSLisandro Dalcin     p += ret;
3099860990eSLisandro Dalcin     n += ret;
310e5c89e4eSSatish Balay   }
3119860990eSLisandro Dalcin   if (m && !count) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_READ,"Read past end of file");
3129860990eSLisandro Dalcin 
3139860990eSLisandro Dalcin   num = (PetscInt)(n/typesize); /* Should we require `n % typesize == 0` ? */
3149860990eSLisandro Dalcin   if (count) *count = num;      /* TODO: This is most likely wrong for PETSC_BIT_LOGICAL */
3157a881295SBarry Smith 
3167a881295SBarry Smith #if defined(PETSC_USE_REAL___FLOAT128)
3179860990eSLisandro Dalcin   if ((type == PETSC_REAL || type == PETSC_COMPLEX) && readdouble) {
3189860990eSLisandro Dalcin     PetscInt  i, cnt = num * ((type == PETSC_REAL) ? 1 : 2);
3199860990eSLisandro Dalcin     PetscReal *preal = (PetscReal*)data;
32030815ce0SLisandro Dalcin     if (!PetscBinaryBigEndian()) {ierr = PetscByteSwapDouble(pdouble,cnt);CHKERRQ(ierr);}
3219860990eSLisandro Dalcin     for (i=0; i<cnt; i++) preal[i] = pdouble[i];
3229860990eSLisandro Dalcin     ierr = PetscFree(pdouble);CHKERRQ(ierr);
3237a881295SBarry Smith     PetscFunctionReturn(0);
3247a881295SBarry Smith   }
3257a881295SBarry Smith #endif
3267a881295SBarry Smith 
32730815ce0SLisandro Dalcin   if (!PetscBinaryBigEndian()) {ierr = PetscByteSwap(ptmp,type,num);CHKERRQ(ierr);}
328e5c89e4eSSatish Balay 
32905acbc63SBarry Smith   if (type == PETSC_FUNCTION) {
3302d53ad75SBarry Smith #if defined(PETSC_SERIALIZE_FUNCTIONS)
3319860990eSLisandro Dalcin     ierr = PetscDLSym(NULL,fname,(void**)data);CHKERRQ(ierr);
3322d53ad75SBarry Smith #else
3339860990eSLisandro Dalcin     *(void**)data = NULL;
3342d53ad75SBarry Smith #endif
33505acbc63SBarry Smith     free(fname);
3362d53ad75SBarry Smith   }
337e5c89e4eSSatish Balay   PetscFunctionReturn(0);
338e5c89e4eSSatish Balay }
3399860990eSLisandro Dalcin 
340a9acdec7SBarry Smith /*@C
341e5c89e4eSSatish Balay    PetscBinaryWrite - Writes to a binary file.
342e5c89e4eSSatish Balay 
343e5c89e4eSSatish Balay    Not Collective
344e5c89e4eSSatish Balay 
345e5c89e4eSSatish Balay    Input Parameters:
346e5c89e4eSSatish Balay +  fd     - the file
347e5c89e4eSSatish Balay .  p      - the buffer
348e5c89e4eSSatish Balay .  n      - the number of items to write
349e5c89e4eSSatish Balay .  type   - the type of items to read (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)
350e5c89e4eSSatish Balay -  istemp - PETSC_FALSE if buffer data should be preserved, PETSC_TRUE otherwise.
351e5c89e4eSSatish Balay 
352e5c89e4eSSatish Balay    Level: advanced
353e5c89e4eSSatish Balay 
354e5c89e4eSSatish Balay    Notes:
355e5c89e4eSSatish Balay    PetscBinaryWrite() uses byte swapping to work on all machines; the files
356e5c89e4eSSatish Balay    are written using big-endian ordering to the file. On small-endian machines the numbers
357e5c89e4eSSatish Balay    are converted to the big-endian format when they are written to disk.
358e2e64c6bSBarry Smith    When PETSc is ./configure with --with-64bit-indices the integers are written to the
35954f21887SBarry Smith    file as 64 bit integers, this means they can only be read back in when the option --with-64bit-indices
36054f21887SBarry Smith    is used.
361e5c89e4eSSatish Balay 
36241f502e3SPatrick Sanan    If running with __float128 precision the output is in __float128 unless one uses the -binary_write_double option
3630da86b62SBarry Smith 
364e5c89e4eSSatish Balay    The Buffer p should be read-write buffer, and not static data.
365e5c89e4eSSatish Balay    This way, byte-swapping is done in-place, and then the buffer is
366e5c89e4eSSatish Balay    written to the file.
367e5c89e4eSSatish Balay 
368e5c89e4eSSatish Balay    This routine restores the original contents of the buffer, after
369e5c89e4eSSatish Balay    it is written to the file. This is done by byte-swapping in-place
370e5c89e4eSSatish Balay    the second time. If the flag istemp is set to PETSC_TRUE, the second
371e5c89e4eSSatish Balay    byte-swapping operation is not done, thus saving some computation,
372e5f36e38SBarry Smith    but the buffer is left corrupted.
373e5c89e4eSSatish Balay 
374300a7f5bSBarry Smith    Because byte-swapping may be done on the values in data it cannot be declared const
375300a7f5bSBarry Smith 
376e5c89e4eSSatish Balay 
3774ebed01fSBarry Smith .seealso: PetscBinaryRead(), PetscBinaryOpen(), PetscBinaryClose(), PetscViewerBinaryGetDescriptor(), PetscBinarySynchronizedWrite(),
3784ebed01fSBarry Smith           PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek()
379e5c89e4eSSatish Balay @*/
3807087cfbeSBarry Smith PetscErrorCode  PetscBinaryWrite(int fd,void *p,PetscInt n,PetscDataType type,PetscBool  istemp)
381e5c89e4eSSatish Balay {
382e5c89e4eSSatish Balay   char           *pp = (char*)p;
383e5c89e4eSSatish Balay   int            err,wsize;
384e5c89e4eSSatish Balay   size_t         m = (size_t)n,maxblock=65536;
385e5c89e4eSSatish Balay   PetscErrorCode ierr;
386e5c89e4eSSatish Balay   void           *ptmp = p;
38705acbc63SBarry Smith   char           *fname = NULL;
3880da86b62SBarry Smith #if defined(PETSC_USE_REAL___FLOAT128)
389df40af56SBarry Smith   PetscBool      writedouble = PETSC_FALSE;
3900da86b62SBarry Smith   double         *ppp;
3910da86b62SBarry Smith   PetscReal      *pv;
3920da86b62SBarry Smith   PetscInt       i;
3930da86b62SBarry Smith #endif
39441f502e3SPatrick Sanan   PetscDataType  wtype = type;
395e5c89e4eSSatish Balay 
396e5c89e4eSSatish Balay   PetscFunctionBegin;
397e32f2f54SBarry Smith   if (n < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Trying to write a negative amount of data %D",n);
398e5c89e4eSSatish Balay   if (!n) PetscFunctionReturn(0);
399e5c89e4eSSatish Balay 
4002d53ad75SBarry Smith   if (type == PETSC_FUNCTION) {
4012d53ad75SBarry Smith #if defined(PETSC_SERIALIZE_FUNCTIONS)
4022d53ad75SBarry Smith     const char *fnametmp;
4032d53ad75SBarry Smith #endif
4042d53ad75SBarry Smith     m     = 64;
405e25ab156SSatish Balay     fname = (char*)malloc(m*sizeof(char));
40605acbc63SBarry Smith     if (!fname) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Cannot allocate space for function name");
40705acbc63SBarry Smith #if defined(PETSC_SERIALIZE_FUNCTIONS)
40805acbc63SBarry Smith     if (n > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Can only binary view a single function at a time");
40905acbc63SBarry Smith     ierr = PetscFPTFind(*(void**)p,&fnametmp);CHKERRQ(ierr);
41005acbc63SBarry Smith     ierr = PetscStrncpy(fname,fnametmp,m);CHKERRQ(ierr);
41105acbc63SBarry Smith #else
41205acbc63SBarry Smith     ierr = PetscStrncpy(fname,"",m);CHKERRQ(ierr);
41305acbc63SBarry Smith #endif
41401963f56SBarry Smith     wtype = PETSC_CHAR;
4152d53ad75SBarry Smith     pp    = (char*)fname;
4162d53ad75SBarry Smith     ptmp  = (void*)fname;
4172d53ad75SBarry Smith   }
4182d53ad75SBarry Smith 
4190da86b62SBarry Smith #if defined(PETSC_USE_REAL___FLOAT128)
4200da86b62SBarry Smith   ierr = PetscOptionsGetBool(NULL,NULL,"-binary_write_double",&writedouble,NULL);CHKERRQ(ierr);
4210da86b62SBarry Smith   /* If using __float128 precision we still write in doubles to file */
4224caf0332SSatish Balay   if ((type == PETSC_SCALAR || type == PETSC_REAL) && writedouble) {
42341f502e3SPatrick Sanan     wtype = PETSC_DOUBLE;
4240da86b62SBarry Smith     ierr = PetscMalloc1(n,&ppp);CHKERRQ(ierr);
4250da86b62SBarry Smith     pv = (PetscReal*)pp;
4260da86b62SBarry Smith     for (i=0; i<n; i++) {
4270da86b62SBarry Smith       ppp[i] = (double) pv[i];
4280da86b62SBarry Smith     }
4290da86b62SBarry Smith     pp   = (char*)ppp;
4300da86b62SBarry Smith     ptmp = (char*)ppp;
4310da86b62SBarry Smith   }
4320da86b62SBarry Smith #endif
4330da86b62SBarry Smith 
43441f502e3SPatrick Sanan   if (wtype == PETSC_INT)          m *= sizeof(PetscInt);
43541f502e3SPatrick Sanan   else if (wtype == PETSC_SCALAR)  m *= sizeof(PetscScalar);
4364caf0332SSatish Balay   else if (wtype == PETSC_REAL)    m *= sizeof(PetscReal);
43741f502e3SPatrick Sanan   else if (wtype == PETSC_DOUBLE)  m *= sizeof(double);
43841f502e3SPatrick Sanan   else if (wtype == PETSC_FLOAT)   m *= sizeof(float);
43941f502e3SPatrick Sanan   else if (wtype == PETSC_SHORT)   m *= sizeof(short);
440972064b6SLisandro Dalcin   else if (wtype == PETSC_LONG)    m *= sizeof(long);
44141f502e3SPatrick Sanan   else if (wtype == PETSC_CHAR)    m *= sizeof(char);
44241f502e3SPatrick Sanan   else if (wtype == PETSC_ENUM)    m *= sizeof(PetscEnum);
44341f502e3SPatrick Sanan   else if (wtype == PETSC_BOOL)    m *= sizeof(PetscBool);
4449e3e4c22SLisandro Dalcin   else if (wtype == PETSC_INT64)   m *= sizeof(PetscInt64);
44541f502e3SPatrick Sanan   else if (wtype == PETSC_BIT_LOGICAL) m = PetscBTLength(m)*sizeof(char);
446e32f2f54SBarry Smith   else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown type");
447e5c89e4eSSatish Balay 
44830815ce0SLisandro Dalcin   if (!PetscBinaryBigEndian()) {ierr = PetscByteSwap(ptmp,wtype,n);CHKERRQ(ierr);}
449e5c89e4eSSatish Balay 
450e5c89e4eSSatish Balay   while (m) {
451e5c89e4eSSatish Balay     wsize = (m < maxblock) ? m : maxblock;
452e5c89e4eSSatish Balay     err   = write(fd,pp,wsize);
453e5c89e4eSSatish Balay     if (err < 0 && errno == EINTR) continue;
45404102261SBarry 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);
455e5c89e4eSSatish Balay     m  -= wsize;
456e5c89e4eSSatish Balay     pp += wsize;
457e5c89e4eSSatish Balay   }
458e5c89e4eSSatish Balay 
459e5c89e4eSSatish Balay   if (!istemp) {
46030815ce0SLisandro Dalcin     if (!PetscBinaryBigEndian()) {ierr = PetscByteSwap(ptmp,wtype,n);CHKERRQ(ierr);}
461e5c89e4eSSatish Balay   }
46205acbc63SBarry Smith   if (type == PETSC_FUNCTION) {
46305acbc63SBarry Smith     free(fname);
46405acbc63SBarry Smith   }
4650da86b62SBarry Smith #if defined(PETSC_USE_REAL___FLOAT128)
4664caf0332SSatish Balay   if ((type == PETSC_SCALAR || type == PETSC_REAL) && writedouble) {
4670da86b62SBarry Smith     ierr = PetscFree(ppp);CHKERRQ(ierr);
4680da86b62SBarry Smith   }
4690da86b62SBarry Smith #endif
470e5c89e4eSSatish Balay   PetscFunctionReturn(0);
471e5c89e4eSSatish Balay }
472e5c89e4eSSatish Balay 
473e5c89e4eSSatish Balay /*@C
474e5c89e4eSSatish Balay    PetscBinaryOpen - Opens a PETSc binary file.
475e5c89e4eSSatish Balay 
476e5c89e4eSSatish Balay    Not Collective
477e5c89e4eSSatish Balay 
478e5c89e4eSSatish Balay    Input Parameters:
479e5c89e4eSSatish Balay +  name - filename
48045c64e65SBarry Smith -  type - type of binary file, one of FILE_MODE_READ, FILE_MODE_APPEND, FILE_MODE_WRITE
481e5c89e4eSSatish Balay 
482e5c89e4eSSatish Balay    Output Parameter:
483e5c89e4eSSatish Balay .  fd - the file
484e5c89e4eSSatish Balay 
485e5c89e4eSSatish Balay    Level: advanced
486e5c89e4eSSatish Balay 
487e5c89e4eSSatish Balay 
48895452b02SPatrick Sanan    Notes:
48995452b02SPatrick Sanan     Files access with PetscBinaryRead() and PetscBinaryWrite() are ALWAYS written in
490e5c89e4eSSatish Balay    big-endian format. This means the file can be accessed using PetscBinaryOpen() and
491e5c89e4eSSatish Balay    PetscBinaryRead() and PetscBinaryWrite() on any machine.
492e5c89e4eSSatish Balay 
4934ebed01fSBarry Smith .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscFileMode, PetscViewerFileSetMode(), PetscViewerBinaryGetDescriptor(),
4944ebed01fSBarry Smith           PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek()
49545c64e65SBarry Smith 
496e5c89e4eSSatish Balay @*/
4977087cfbeSBarry Smith PetscErrorCode  PetscBinaryOpen(const char name[],PetscFileMode mode,int *fd)
498e5c89e4eSSatish Balay {
499e5c89e4eSSatish Balay   PetscFunctionBegin;
500e5c89e4eSSatish Balay #if defined(PETSC_HAVE_O_BINARY)
50145c64e65SBarry Smith   if (mode == FILE_MODE_WRITE) {
502a297a907SKarl 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);
50345c64e65SBarry Smith   } else if (mode == FILE_MODE_READ) {
504a297a907SKarl 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);
50545c64e65SBarry Smith   } else if (mode == FILE_MODE_APPEND) {
506a297a907SKarl 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);
507e5c89e4eSSatish Balay #else
50845c64e65SBarry Smith   if (mode == FILE_MODE_WRITE) {
509a297a907SKarl Rupp     if ((*fd = creat(name,0666)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot create file for writing: %s",name);
51045c64e65SBarry Smith   } else if (mode == FILE_MODE_READ) {
511a297a907SKarl Rupp     if ((*fd = open(name,O_RDONLY,0)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file for reading: %s",name);
512e5c89e4eSSatish Balay   }
51345c64e65SBarry Smith   else if (mode == FILE_MODE_APPEND) {
514a297a907SKarl Rupp     if ((*fd = open(name,O_WRONLY,0)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file for writing: %s",name);
515e5c89e4eSSatish Balay #endif
516e32f2f54SBarry Smith   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown file mode");
517e5c89e4eSSatish Balay   PetscFunctionReturn(0);
518e5c89e4eSSatish Balay }
519e5c89e4eSSatish Balay 
520e30d2299SSatish Balay /*@
521e5c89e4eSSatish Balay    PetscBinaryClose - Closes a PETSc binary file.
522e5c89e4eSSatish Balay 
523e5c89e4eSSatish Balay    Not Collective
524e5c89e4eSSatish Balay 
525e5c89e4eSSatish Balay    Output Parameter:
526e5c89e4eSSatish Balay .  fd - the file
527e5c89e4eSSatish Balay 
528e5c89e4eSSatish Balay    Level: advanced
529e5c89e4eSSatish Balay 
5304ebed01fSBarry Smith .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
5314ebed01fSBarry Smith           PetscBinarySynchronizedSeek()
532e5c89e4eSSatish Balay @*/
5337087cfbeSBarry Smith PetscErrorCode  PetscBinaryClose(int fd)
534e5c89e4eSSatish Balay {
535e5c89e4eSSatish Balay   PetscFunctionBegin;
536e5c89e4eSSatish Balay   close(fd);
537e5c89e4eSSatish Balay   PetscFunctionReturn(0);
538e5c89e4eSSatish Balay }
539e5c89e4eSSatish Balay 
540e5c89e4eSSatish Balay 
541e8976759SBarry Smith /*@C
542e5c89e4eSSatish Balay    PetscBinarySeek - Moves the file pointer on a PETSc binary file.
543e5c89e4eSSatish Balay 
544e5c89e4eSSatish Balay    Not Collective
545e5c89e4eSSatish Balay 
546e5c89e4eSSatish Balay    Input Parameters:
547e5c89e4eSSatish Balay +  fd - the file
548ff553b35SMatthew Knepley .  off - number of bytes to move. Use PETSC_BINARY_INT_SIZE, PETSC_BINARY_SCALAR_SIZE,
549e5c89e4eSSatish Balay             etc. in your calculation rather than sizeof() to compute byte lengths.
550ff553b35SMatthew Knepley -  whence - if PETSC_BINARY_SEEK_SET then off is an absolute location in the file
551ff553b35SMatthew Knepley             if PETSC_BINARY_SEEK_CUR then off is an offset from the current location
552ff553b35SMatthew Knepley             if PETSC_BINARY_SEEK_END then off is an offset from the end of file
553e5c89e4eSSatish Balay 
554e5c89e4eSSatish Balay    Output Parameter:
555e5c89e4eSSatish Balay .   offset - new offset in file
556e5c89e4eSSatish Balay 
557e5c89e4eSSatish Balay    Level: developer
558e5c89e4eSSatish Balay 
559e5c89e4eSSatish Balay    Notes:
560e5c89e4eSSatish Balay    Integers are stored on the file as 32 long, regardless of whether
561e5c89e4eSSatish Balay    they are stored in the machine as 32 or 64, this means the same
562e5c89e4eSSatish Balay    binary file may be read on any machine. Hence you CANNOT use sizeof()
563e5c89e4eSSatish Balay    to determine the offset or location.
564e5c89e4eSSatish Balay 
565e5c89e4eSSatish Balay 
5664ebed01fSBarry Smith .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
5674ebed01fSBarry Smith           PetscBinarySynchronizedSeek()
568e5c89e4eSSatish Balay @*/
5697087cfbeSBarry Smith PetscErrorCode  PetscBinarySeek(int fd,off_t off,PetscBinarySeekType whence,off_t *offset)
570e5c89e4eSSatish Balay {
571e5c89e4eSSatish Balay   int iwhence = 0;
572e5c89e4eSSatish Balay 
573e5c89e4eSSatish Balay   PetscFunctionBegin;
574a297a907SKarl Rupp   if (whence == PETSC_BINARY_SEEK_SET) iwhence = SEEK_SET;
575a297a907SKarl Rupp   else if (whence == PETSC_BINARY_SEEK_CUR) iwhence = SEEK_CUR;
576a297a907SKarl Rupp   else if (whence == PETSC_BINARY_SEEK_END) iwhence = SEEK_END;
577a297a907SKarl Rupp   else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown seek location");
578e5c89e4eSSatish Balay #if defined(PETSC_HAVE_LSEEK)
579e5c89e4eSSatish Balay   *offset = lseek(fd,off,iwhence);
580e5c89e4eSSatish Balay #elif defined(PETSC_HAVE__LSEEK)
581e5c89e4eSSatish Balay   *offset = _lseek(fd,(long)off,iwhence);
582e5c89e4eSSatish Balay #else
583e32f2f54SBarry Smith   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS,"System does not have a way of seeking on a file");
584e5c89e4eSSatish Balay #endif
585e5c89e4eSSatish Balay   PetscFunctionReturn(0);
586e5c89e4eSSatish Balay }
587e5c89e4eSSatish Balay 
588e5c89e4eSSatish Balay /*@C
5891d280d73SBarry Smith    PetscBinarySynchronizedRead - Reads from a binary file.
590e5c89e4eSSatish Balay 
591d083f849SBarry Smith    Collective
592e5c89e4eSSatish Balay 
593e5c89e4eSSatish Balay    Input Parameters:
594e5c89e4eSSatish Balay +  comm - the MPI communicator
5959860990eSLisandro Dalcin .  fd - the file descriptor
5969860990eSLisandro Dalcin .  num  - the maximum number of items to read
5979860990eSLisandro Dalcin -  type - the type of items to read (PETSC_INT, PETSC_REAL, PETSC_SCALAR, etc.)
598e5c89e4eSSatish Balay 
599e5c89e4eSSatish Balay    Output Parameters:
6009860990eSLisandro Dalcin +  data - the buffer
6019860990eSLisandro Dalcin -  count - the number of items read, optional
602e5c89e4eSSatish Balay 
603e5c89e4eSSatish Balay    Level: developer
604e5c89e4eSSatish Balay 
605e5c89e4eSSatish Balay    Notes:
606e5c89e4eSSatish Balay    Does a PetscBinaryRead() followed by an MPI_Bcast()
607e5c89e4eSSatish Balay 
6089860990eSLisandro Dalcin    If count is not provided and the number of items read is less than
6099860990eSLisandro Dalcin    the maximum number of items to read, then this routine errors.
6109860990eSLisandro Dalcin 
6111d280d73SBarry Smith    PetscBinarySynchronizedRead() uses byte swapping to work on all machines.
612e5c89e4eSSatish Balay    Integers are stored on the file as 32 long, regardless of whether
613e5c89e4eSSatish Balay    they are stored in the machine as 32 or 64, this means the same
614e5c89e4eSSatish Balay    binary file may be read on any machine.
615e5c89e4eSSatish Balay 
616e5c89e4eSSatish Balay 
6174ebed01fSBarry Smith .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscBinaryRead(), PetscBinarySynchronizedWrite(),
6184ebed01fSBarry Smith           PetscBinarySynchronizedSeek()
619e5c89e4eSSatish Balay @*/
6209860990eSLisandro Dalcin PetscErrorCode  PetscBinarySynchronizedRead(MPI_Comm comm,int fd,void *data,PetscInt num,PetscInt *count,PetscDataType type)
621e5c89e4eSSatish Balay {
6229860990eSLisandro Dalcin   PetscErrorCode ierr;
623e5c89e4eSSatish Balay   PetscMPIInt    rank;
624e5c89e4eSSatish Balay   MPI_Datatype   mtype;
6259860990eSLisandro Dalcin   PetscInt       ibuf[2] = {0, 0};
62605acbc63SBarry Smith   char           *fname = NULL;
6279860990eSLisandro Dalcin   void           *fptr = NULL;
628e5c89e4eSSatish Balay 
629e5c89e4eSSatish Balay   PetscFunctionBegin;
6302d53ad75SBarry Smith   if (type == PETSC_FUNCTION) {
6319860990eSLisandro Dalcin     num   = 64;
6322d53ad75SBarry Smith     type  = PETSC_CHAR;
6339860990eSLisandro Dalcin     fname = (char*)malloc(num*sizeof(char));
6349860990eSLisandro Dalcin     fptr  = data;
6359860990eSLisandro Dalcin     data  = (void*)fname;
63605acbc63SBarry Smith     if (!fname) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Cannot allocate space for function name");
6372d53ad75SBarry Smith   }
6382d53ad75SBarry Smith 
639e5c89e4eSSatish Balay   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
640e5c89e4eSSatish Balay   if (!rank) {
6419860990eSLisandro Dalcin     ibuf[0] = PetscBinaryRead(fd,data,num,count?&ibuf[1]:NULL,type);
642e5c89e4eSSatish Balay   }
6439860990eSLisandro Dalcin   ierr = MPI_Bcast(ibuf,2,MPIU_INT,0,comm);CHKERRQ(ierr);
6449860990eSLisandro Dalcin   ierr = (PetscErrorCode)ibuf[0];CHKERRQ(ierr);
645e5c89e4eSSatish Balay   ierr = PetscDataTypeToMPIDataType(type,&mtype);CHKERRQ(ierr);
6469860990eSLisandro Dalcin   ierr = MPI_Bcast(data,count?ibuf[1]:num,mtype,0,comm);CHKERRQ(ierr);
6479860990eSLisandro Dalcin   if (count) *count = ibuf[1];
6482d53ad75SBarry Smith 
649e366c363SBarry Smith   if (type == PETSC_FUNCTION) {
6502d53ad75SBarry Smith #if defined(PETSC_SERIALIZE_FUNCTIONS)
6519860990eSLisandro Dalcin     ierr = PetscDLLibrarySym(PETSC_COMM_SELF,&PetscDLLibrariesLoaded,NULL,fname,(void**)fptr);CHKERRQ(ierr);
6522d53ad75SBarry Smith #else
6539860990eSLisandro Dalcin     *(void**)fptr = NULL;
6542d53ad75SBarry Smith #endif
655e366c363SBarry Smith     free(fname);
6562d53ad75SBarry Smith   }
657e5c89e4eSSatish Balay   PetscFunctionReturn(0);
658e5c89e4eSSatish Balay }
659e5c89e4eSSatish Balay 
660e5c89e4eSSatish Balay /*@C
6611d280d73SBarry Smith    PetscBinarySynchronizedWrite - writes to a binary file.
662e5c89e4eSSatish Balay 
663d083f849SBarry Smith    Collective
664e5c89e4eSSatish Balay 
665e5c89e4eSSatish Balay    Input Parameters:
666e5c89e4eSSatish Balay +  comm - the MPI communicator
667e5c89e4eSSatish Balay .  fd - the file
668e5c89e4eSSatish Balay .  n  - the number of items to write
669e5c89e4eSSatish Balay .  p - the buffer
670e5c89e4eSSatish Balay .  istemp - the buffer may be changed
671e5c89e4eSSatish Balay -  type - the type of items to write (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)
672e5c89e4eSSatish Balay 
673e5c89e4eSSatish Balay    Level: developer
674e5c89e4eSSatish Balay 
675e5c89e4eSSatish Balay    Notes:
676e5c89e4eSSatish Balay    Process 0 does a PetscBinaryWrite()
677e5c89e4eSSatish Balay 
6781d280d73SBarry Smith    PetscBinarySynchronizedWrite() uses byte swapping to work on all machines.
679e5c89e4eSSatish Balay    Integers are stored on the file as 32 long, regardless of whether
680e5c89e4eSSatish Balay    they are stored in the machine as 32 or 64, this means the same
681e5c89e4eSSatish Balay    binary file may be read on any machine.
682e5c89e4eSSatish Balay 
68395452b02SPatrick Sanan    Notes:
68495452b02SPatrick Sanan     because byte-swapping may be done on the values in data it cannot be declared const
685300a7f5bSBarry Smith 
6861d280d73SBarry Smith    WARNING: This is NOT like PetscSynchronizedFPrintf()! This routine ignores calls on all but process 0,
6871d280d73SBarry Smith    while PetscSynchronizedFPrintf() has all processes print their strings in order.
6881d280d73SBarry Smith 
689e5c89e4eSSatish Balay 
6904ebed01fSBarry Smith .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscBinaryRead(), PetscBinarySynchronizedRead(),
6914ebed01fSBarry Smith           PetscBinarySynchronizedSeek()
692e5c89e4eSSatish Balay @*/
6937087cfbeSBarry Smith PetscErrorCode  PetscBinarySynchronizedWrite(MPI_Comm comm,int fd,void *p,PetscInt n,PetscDataType type,PetscBool istemp)
694e5c89e4eSSatish Balay {
695e5c89e4eSSatish Balay   PetscErrorCode ierr;
696e5c89e4eSSatish Balay   PetscMPIInt    rank;
697e5c89e4eSSatish Balay 
698e5c89e4eSSatish Balay   PetscFunctionBegin;
699e5c89e4eSSatish Balay   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
700e5c89e4eSSatish Balay   if (!rank) {
701e5c89e4eSSatish Balay     ierr = PetscBinaryWrite(fd,p,n,type,istemp);CHKERRQ(ierr);
702e5c89e4eSSatish Balay   }
703e5c89e4eSSatish Balay   PetscFunctionReturn(0);
704e5c89e4eSSatish Balay }
705e5c89e4eSSatish Balay 
706e5c89e4eSSatish Balay /*@C
7071d280d73SBarry Smith    PetscBinarySynchronizedSeek - Moves the file pointer on a PETSc binary file.
708e5c89e4eSSatish Balay 
709e5c89e4eSSatish Balay 
710e5c89e4eSSatish Balay    Input Parameters:
711e5c89e4eSSatish Balay +  fd - the file
712e5c89e4eSSatish Balay .  whence - if PETSC_BINARY_SEEK_SET then size is an absolute location in the file
713e5c89e4eSSatish Balay             if PETSC_BINARY_SEEK_CUR then size is offset from current location
714e5c89e4eSSatish Balay             if PETSC_BINARY_SEEK_END then size is offset from end of file
715e5c89e4eSSatish Balay -  off    - number of bytes to move. Use PETSC_BINARY_INT_SIZE, PETSC_BINARY_SCALAR_SIZE,
716e5c89e4eSSatish Balay             etc. in your calculation rather than sizeof() to compute byte lengths.
717e5c89e4eSSatish Balay 
718e5c89e4eSSatish Balay    Output Parameter:
719e5c89e4eSSatish Balay .   offset - new offset in file
720e5c89e4eSSatish Balay 
721e5c89e4eSSatish Balay    Level: developer
722e5c89e4eSSatish Balay 
723e5c89e4eSSatish Balay    Notes:
724e5c89e4eSSatish Balay    Integers are stored on the file as 32 long, regardless of whether
725e5c89e4eSSatish Balay    they are stored in the machine as 32 or 64, this means the same
726e5c89e4eSSatish Balay    binary file may be read on any machine. Hence you CANNOT use sizeof()
727e5c89e4eSSatish Balay    to determine the offset or location.
728e5c89e4eSSatish Balay 
729e5c89e4eSSatish Balay 
7304ebed01fSBarry Smith .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
7314ebed01fSBarry Smith           PetscBinarySynchronizedSeek()
732e5c89e4eSSatish Balay @*/
7337087cfbeSBarry Smith PetscErrorCode  PetscBinarySynchronizedSeek(MPI_Comm comm,int fd,off_t off,PetscBinarySeekType whence,off_t *offset)
734e5c89e4eSSatish Balay {
735e5c89e4eSSatish Balay   PetscErrorCode ierr;
736e5c89e4eSSatish Balay   PetscMPIInt    rank;
737e5c89e4eSSatish Balay 
738e5c89e4eSSatish Balay   PetscFunctionBegin;
739e5c89e4eSSatish Balay   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
740e5c89e4eSSatish Balay   if (!rank) {
741e5c89e4eSSatish Balay     ierr = PetscBinarySeek(fd,off,whence,offset);CHKERRQ(ierr);
742e5c89e4eSSatish Balay   }
743e5c89e4eSSatish Balay   PetscFunctionReturn(0);
744e5c89e4eSSatish Balay }
745e5c89e4eSSatish Balay 
7460fc9d207SBarry Smith #if defined(PETSC_HAVE_MPIIO)
747e39fd77fSBarry Smith 
748951e3c8eSBarry Smith #if defined(PETSC_USE_PETSC_MPI_EXTERNAL32)
749e39fd77fSBarry Smith /*
750e39fd77fSBarry Smith       MPICH does not provide the external32 representation for MPI_File_set_view() so we need to provide the functions.
751e39fd77fSBarry Smith     These are set into MPI in PetscInitialize() via MPI_Register_datarep()
752e39fd77fSBarry Smith 
753e39fd77fSBarry Smith     Note I use PetscMPIInt for the MPI error codes since that is what MPI uses (instead of the standard PetscErrorCode)
754e39fd77fSBarry Smith 
755951e3c8eSBarry Smith     The next three routines are not used because MPICH does not support their use
756e39fd77fSBarry Smith 
757e39fd77fSBarry Smith */
7588cc058d9SJed Brown PETSC_EXTERN PetscMPIInt PetscDataRep_extent_fn(MPI_Datatype datatype,MPI_Aint *file_extent,void *extra_state)
759e39fd77fSBarry Smith {
760e39fd77fSBarry Smith   MPI_Aint    ub;
761e39fd77fSBarry Smith   PetscMPIInt ierr;
762e39fd77fSBarry Smith 
763e39fd77fSBarry Smith   ierr = MPI_Type_get_extent(datatype,&ub,file_extent);
764e39fd77fSBarry Smith   return ierr;
765e39fd77fSBarry Smith }
766e39fd77fSBarry Smith 
7678cc058d9SJed Brown PETSC_EXTERN PetscMPIInt PetscDataRep_read_conv_fn(void *userbuf, MPI_Datatype datatype,PetscMPIInt count,void *filebuf, MPI_Offset position,void *extra_state)
768e39fd77fSBarry Smith {
769e39fd77fSBarry Smith   PetscDataType pdtype;
770e39fd77fSBarry Smith   PetscMPIInt   ierr;
771e39fd77fSBarry Smith   size_t        dsize;
772e39fd77fSBarry Smith 
773e39fd77fSBarry Smith   ierr = PetscMPIDataTypeToPetscDataType(datatype,&pdtype);CHKERRQ(ierr);
774e39fd77fSBarry Smith   ierr = PetscDataTypeGetSize(pdtype,&dsize);CHKERRQ(ierr);
775e39fd77fSBarry Smith 
776e39fd77fSBarry Smith   /* offset is given in units of MPI_Datatype */
777e39fd77fSBarry Smith   userbuf = ((char*)userbuf) + dsize*position;
778e39fd77fSBarry Smith 
779e39fd77fSBarry Smith   ierr = PetscMemcpy(userbuf,filebuf,count*dsize);CHKERRQ(ierr);
78030815ce0SLisandro Dalcin   if (!PetscBinaryBigEndian()) {ierr = PetscByteSwap(userbuf,pdtype,count);CHKERRQ(ierr);}
781e39fd77fSBarry Smith   return ierr;
782e39fd77fSBarry Smith }
783e39fd77fSBarry Smith 
784e39fd77fSBarry Smith PetscMPIInt PetscDataRep_write_conv_fn(void *userbuf, MPI_Datatype datatype,PetscMPIInt count,void *filebuf, MPI_Offset position,void *extra_state)
785e39fd77fSBarry Smith {
786e39fd77fSBarry Smith   PetscDataType pdtype;
787e39fd77fSBarry Smith   PetscMPIInt   ierr;
788e39fd77fSBarry Smith   size_t        dsize;
789e39fd77fSBarry Smith 
790e39fd77fSBarry Smith   ierr = PetscMPIDataTypeToPetscDataType(datatype,&pdtype);CHKERRQ(ierr);
791e39fd77fSBarry Smith   ierr = PetscDataTypeGetSize(pdtype,&dsize);CHKERRQ(ierr);
792e39fd77fSBarry Smith 
793e39fd77fSBarry Smith   /* offset is given in units of MPI_Datatype */
794e39fd77fSBarry Smith   userbuf = ((char*)userbuf) + dsize*position;
795e39fd77fSBarry Smith 
796e39fd77fSBarry Smith   ierr = PetscMemcpy(filebuf,userbuf,count*dsize);CHKERRQ(ierr);
79730815ce0SLisandro Dalcin   if (!PetscBinaryBigEndian()) {ierr = PetscByteSwap(filebuf,pdtype,count);CHKERRQ(ierr);}
798e39fd77fSBarry Smith   return ierr;
799e39fd77fSBarry Smith }
800951e3c8eSBarry Smith #endif
801e39fd77fSBarry Smith 
802e39fd77fSBarry Smith PetscErrorCode MPIU_File_write_all(MPI_File fd,void *data,PetscMPIInt cnt,MPI_Datatype dtype,MPI_Status *status)
803e39fd77fSBarry Smith {
804e39fd77fSBarry Smith   PetscDataType  pdtype;
80530815ce0SLisandro Dalcin   PetscErrorCode ierr;
80630815ce0SLisandro Dalcin 
807e39fd77fSBarry Smith 
808e39fd77fSBarry Smith   PetscFunctionBegin;
809e39fd77fSBarry Smith   ierr = PetscMPIDataTypeToPetscDataType(dtype,&pdtype);CHKERRQ(ierr);
81030815ce0SLisandro Dalcin   if (!PetscBinaryBigEndian()) {ierr = PetscByteSwap(data,pdtype,cnt);CHKERRQ(ierr);}
811e39fd77fSBarry Smith   ierr = MPI_File_write_all(fd,data,cnt,dtype,status);CHKERRQ(ierr);
81230815ce0SLisandro Dalcin   if (!PetscBinaryBigEndian()) {ierr = PetscByteSwap(data,pdtype,cnt);CHKERRQ(ierr);}
813a6796414SBarry Smith   PetscFunctionReturn(0);
814e39fd77fSBarry Smith }
815e39fd77fSBarry Smith 
816e39fd77fSBarry Smith PetscErrorCode MPIU_File_read_all(MPI_File fd,void *data,PetscMPIInt cnt,MPI_Datatype dtype,MPI_Status *status)
817e39fd77fSBarry Smith {
818e39fd77fSBarry Smith   PetscDataType  pdtype;
81930815ce0SLisandro Dalcin   PetscErrorCode ierr;
820e39fd77fSBarry Smith 
821e39fd77fSBarry Smith   PetscFunctionBegin;
822e39fd77fSBarry Smith   ierr = PetscMPIDataTypeToPetscDataType(dtype,&pdtype);CHKERRQ(ierr);
823e39fd77fSBarry Smith   ierr = MPI_File_read_all(fd,data,cnt,dtype,status);CHKERRQ(ierr);
82430815ce0SLisandro Dalcin   if (!PetscBinaryBigEndian()) {ierr = PetscByteSwap(data,pdtype,cnt);CHKERRQ(ierr);}
825a6796414SBarry Smith   PetscFunctionReturn(0);
826e39fd77fSBarry Smith }
82730815ce0SLisandro Dalcin 
828951e3c8eSBarry Smith #endif
829