xref: /petsc/src/sys/fileio/sysio.c (revision f253e43cc674c8507d337bbb5ef3ec57f9e3fddc)
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 
1702c9f0b5SLisandro 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    Level: developer
241e5c89e4eSSatish Balay 
242e5c89e4eSSatish Balay    Notes:
2439860990eSLisandro Dalcin    If count is not provided and the number of items read is less than
2449860990eSLisandro Dalcin    the maximum number of items to read, then this routine errors.
2459860990eSLisandro Dalcin 
246e5c89e4eSSatish Balay    PetscBinaryRead() uses byte swapping to work on all machines; the files
247*f253e43cSLisandro Dalcin    are written to file ALWAYS using big-endian ordering. On little-endian machines the numbers
248*f253e43cSLisandro Dalcin    are converted to the little-endian format when they are read in from the file.
249*f253e43cSLisandro Dalcin    When PETSc is ./configure with --with-64-bit-indices the integers are written to the
250*f253e43cSLisandro Dalcin    file as 64 bit integers, this means they can only be read back in when the option --with-64-bit-indices
25154f21887SBarry Smith    is used.
252e5c89e4eSSatish Balay 
2534ebed01fSBarry Smith .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscViewerBinaryGetDescriptor(), PetscBinarySynchronizedWrite(),
2544ebed01fSBarry Smith           PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek()
255e5c89e4eSSatish Balay @*/
2569860990eSLisandro Dalcin PetscErrorCode  PetscBinaryRead(int fd,void *data,PetscInt num,PetscInt *count,PetscDataType type)
257e5c89e4eSSatish Balay {
2589860990eSLisandro Dalcin   size_t            typesize, m = (size_t) num, n = 0, maxblock = 65536;
2599860990eSLisandro Dalcin   char              *p = (char*)data;
2607a881295SBarry Smith #if defined(PETSC_USE_REAL___FLOAT128)
261cba51d77SBarry Smith   PetscBool         readdouble = PETSC_FALSE;
2629860990eSLisandro Dalcin   double            *pdouble;
2637a881295SBarry Smith #endif
2649860990eSLisandro Dalcin   void              *ptmp = data;
26505acbc63SBarry Smith   char              *fname = NULL;
2669860990eSLisandro Dalcin   PetscErrorCode    ierr;
267e5c89e4eSSatish Balay 
268e5c89e4eSSatish Balay   PetscFunctionBegin;
2699860990eSLisandro Dalcin   if (count) *count = 0;
2709860990eSLisandro Dalcin   if (num < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Trying to read a negative amount of data %D",num);
2719860990eSLisandro Dalcin   if (!num) PetscFunctionReturn(0);
272e5c89e4eSSatish Balay 
2732d53ad75SBarry Smith   if (type == PETSC_FUNCTION) {
2742d53ad75SBarry Smith     m     = 64;
2752d53ad75SBarry Smith     type  = PETSC_CHAR;
27605acbc63SBarry Smith     fname = (char*)malloc(m*sizeof(char));
2779860990eSLisandro Dalcin     p     = (char*)fname;
2782d53ad75SBarry Smith     ptmp  = (void*)fname;
2799860990eSLisandro Dalcin     if (!fname) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Cannot allocate space for function name");
2802d53ad75SBarry Smith   }
2819860990eSLisandro Dalcin   if (type == PETSC_BIT_LOGICAL) m = PetscBTLength(m);
2822d53ad75SBarry Smith 
2839860990eSLisandro Dalcin   ierr = PetscDataTypeGetSize(type,&typesize);CHKERRQ(ierr);
284e5c89e4eSSatish Balay 
2857a881295SBarry Smith #if defined(PETSC_USE_REAL___FLOAT128)
286c5929fdfSBarry Smith   ierr = PetscOptionsGetBool(NULL,NULL,"-binary_read_double",&readdouble,NULL);CHKERRQ(ierr);
2877a881295SBarry Smith   /* If using __float128 precision we still read in doubles from file */
2889860990eSLisandro Dalcin   if ((type == PETSC_REAL || type == PETSC_COMPLEX) && readdouble) {
2899860990eSLisandro Dalcin     PetscInt cnt = num * ((type == PETSC_REAL) ? 1 : 2);
2909860990eSLisandro Dalcin     ierr = PetscMalloc1(cnt,&pdouble);CHKERRQ(ierr);
2919860990eSLisandro Dalcin     p = (char*)pdouble;
2929860990eSLisandro Dalcin     typesize /= 2;
2937a881295SBarry Smith   }
2947a881295SBarry Smith #endif
2957a881295SBarry Smith 
2969860990eSLisandro Dalcin   m *= typesize;
2979860990eSLisandro Dalcin 
298e5c89e4eSSatish Balay   while (m) {
2999860990eSLisandro Dalcin     size_t len = (m < maxblock) ? m : maxblock;
3009860990eSLisandro Dalcin     int    ret = (int)read(fd,p,len);
3019860990eSLisandro Dalcin     if (ret < 0 && errno == EINTR) continue;
3029860990eSLisandro Dalcin     if (!ret && len > 0) break; /* Proxy for EOF */
3039860990eSLisandro Dalcin     if (ret < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_READ,"Error reading from file, errno %d",errno);
3049860990eSLisandro Dalcin     m -= ret;
3059860990eSLisandro Dalcin     p += ret;
3069860990eSLisandro Dalcin     n += ret;
307e5c89e4eSSatish Balay   }
3089860990eSLisandro Dalcin   if (m && !count) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_READ,"Read past end of file");
3099860990eSLisandro Dalcin 
3109860990eSLisandro Dalcin   num = (PetscInt)(n/typesize); /* Should we require `n % typesize == 0` ? */
3119860990eSLisandro Dalcin   if (count) *count = num;      /* TODO: This is most likely wrong for PETSC_BIT_LOGICAL */
3127a881295SBarry Smith 
3137a881295SBarry Smith #if defined(PETSC_USE_REAL___FLOAT128)
3149860990eSLisandro Dalcin   if ((type == PETSC_REAL || type == PETSC_COMPLEX) && readdouble) {
3159860990eSLisandro Dalcin     PetscInt  i, cnt = num * ((type == PETSC_REAL) ? 1 : 2);
3169860990eSLisandro Dalcin     PetscReal *preal = (PetscReal*)data;
31730815ce0SLisandro Dalcin     if (!PetscBinaryBigEndian()) {ierr = PetscByteSwapDouble(pdouble,cnt);CHKERRQ(ierr);}
3189860990eSLisandro Dalcin     for (i=0; i<cnt; i++) preal[i] = pdouble[i];
3199860990eSLisandro Dalcin     ierr = PetscFree(pdouble);CHKERRQ(ierr);
3207a881295SBarry Smith     PetscFunctionReturn(0);
3217a881295SBarry Smith   }
3227a881295SBarry Smith #endif
3237a881295SBarry Smith 
32430815ce0SLisandro Dalcin   if (!PetscBinaryBigEndian()) {ierr = PetscByteSwap(ptmp,type,num);CHKERRQ(ierr);}
325e5c89e4eSSatish Balay 
32605acbc63SBarry Smith   if (type == PETSC_FUNCTION) {
3272d53ad75SBarry Smith #if defined(PETSC_SERIALIZE_FUNCTIONS)
3289860990eSLisandro Dalcin     ierr = PetscDLSym(NULL,fname,(void**)data);CHKERRQ(ierr);
3292d53ad75SBarry Smith #else
3309860990eSLisandro Dalcin     *(void**)data = NULL;
3312d53ad75SBarry Smith #endif
33205acbc63SBarry Smith     free(fname);
3332d53ad75SBarry Smith   }
334e5c89e4eSSatish Balay   PetscFunctionReturn(0);
335e5c89e4eSSatish Balay }
3369860990eSLisandro Dalcin 
337a9acdec7SBarry Smith /*@C
338e5c89e4eSSatish Balay    PetscBinaryWrite - Writes to a binary file.
339e5c89e4eSSatish Balay 
340e5c89e4eSSatish Balay    Not Collective
341e5c89e4eSSatish Balay 
342e5c89e4eSSatish Balay    Input Parameters:
343e5c89e4eSSatish Balay +  fd     - the file
344e5c89e4eSSatish Balay .  p      - the buffer
345e5c89e4eSSatish Balay .  n      - the number of items to write
346*f253e43cSLisandro Dalcin -  type   - the type of items to read (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)
347e5c89e4eSSatish Balay 
348e5c89e4eSSatish Balay    Level: advanced
349e5c89e4eSSatish Balay 
350e5c89e4eSSatish Balay    Notes:
351e5c89e4eSSatish Balay    PetscBinaryWrite() uses byte swapping to work on all machines; the files
352*f253e43cSLisandro Dalcin    are written using big-endian ordering to the file. On little-endian machines the numbers
353e5c89e4eSSatish Balay    are converted to the big-endian format when they are written to disk.
354*f253e43cSLisandro Dalcin    When PETSc is ./configure with --with-64-bit-indices the integers are written to the
355*f253e43cSLisandro Dalcin    file as 64 bit integers, this means they can only be read back in when the option --with-64-bit-indices
35654f21887SBarry Smith    is used.
357e5c89e4eSSatish Balay 
35841f502e3SPatrick Sanan    If running with __float128 precision the output is in __float128 unless one uses the -binary_write_double option
3590da86b62SBarry Smith 
360e5c89e4eSSatish Balay    The Buffer p should be read-write buffer, and not static data.
361e5c89e4eSSatish Balay    This way, byte-swapping is done in-place, and then the buffer is
362e5c89e4eSSatish Balay    written to the file.
363e5c89e4eSSatish Balay 
364e5c89e4eSSatish Balay    This routine restores the original contents of the buffer, after
365e5c89e4eSSatish Balay    it is written to the file. This is done by byte-swapping in-place
366*f253e43cSLisandro Dalcin    the second time.
367e5c89e4eSSatish Balay 
368300a7f5bSBarry Smith    Because byte-swapping may be done on the values in data it cannot be declared const
369300a7f5bSBarry Smith 
370e5c89e4eSSatish Balay 
3714ebed01fSBarry Smith .seealso: PetscBinaryRead(), PetscBinaryOpen(), PetscBinaryClose(), PetscViewerBinaryGetDescriptor(), PetscBinarySynchronizedWrite(),
3724ebed01fSBarry Smith           PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek()
373e5c89e4eSSatish Balay @*/
374*f253e43cSLisandro Dalcin PetscErrorCode  PetscBinaryWrite(int fd,const void *p,PetscInt n,PetscDataType type)
375e5c89e4eSSatish Balay {
376*f253e43cSLisandro Dalcin   const char     *pp = (char*)p;
377e5c89e4eSSatish Balay   int            err,wsize;
378e5c89e4eSSatish Balay   size_t         m = (size_t)n,maxblock=65536;
379e5c89e4eSSatish Balay   PetscErrorCode ierr;
380*f253e43cSLisandro Dalcin   const void     *ptmp = p;
38105acbc63SBarry Smith   char           *fname = NULL;
3820da86b62SBarry Smith #if defined(PETSC_USE_REAL___FLOAT128)
383df40af56SBarry Smith   PetscBool      writedouble = PETSC_FALSE;
3840da86b62SBarry Smith   double         *ppp;
3850da86b62SBarry Smith   PetscReal      *pv;
3860da86b62SBarry Smith   PetscInt       i;
3870da86b62SBarry Smith #endif
38841f502e3SPatrick Sanan   PetscDataType  wtype = type;
389e5c89e4eSSatish Balay 
390e5c89e4eSSatish Balay   PetscFunctionBegin;
391e32f2f54SBarry Smith   if (n < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Trying to write a negative amount of data %D",n);
392e5c89e4eSSatish Balay   if (!n) PetscFunctionReturn(0);
393e5c89e4eSSatish Balay 
3942d53ad75SBarry Smith   if (type == PETSC_FUNCTION) {
3952d53ad75SBarry Smith #if defined(PETSC_SERIALIZE_FUNCTIONS)
3962d53ad75SBarry Smith     const char *fnametmp;
3972d53ad75SBarry Smith #endif
3982d53ad75SBarry Smith     m     = 64;
399e25ab156SSatish Balay     fname = (char*)malloc(m*sizeof(char));
40005acbc63SBarry Smith     if (!fname) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Cannot allocate space for function name");
40105acbc63SBarry Smith #if defined(PETSC_SERIALIZE_FUNCTIONS)
40205acbc63SBarry Smith     if (n > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Can only binary view a single function at a time");
40305acbc63SBarry Smith     ierr = PetscFPTFind(*(void**)p,&fnametmp);CHKERRQ(ierr);
40405acbc63SBarry Smith     ierr = PetscStrncpy(fname,fnametmp,m);CHKERRQ(ierr);
40505acbc63SBarry Smith #else
40605acbc63SBarry Smith     ierr = PetscStrncpy(fname,"",m);CHKERRQ(ierr);
40705acbc63SBarry Smith #endif
40801963f56SBarry Smith     wtype = PETSC_CHAR;
4092d53ad75SBarry Smith     pp    = (char*)fname;
4102d53ad75SBarry Smith     ptmp  = (void*)fname;
4112d53ad75SBarry Smith   }
4122d53ad75SBarry Smith 
4130da86b62SBarry Smith #if defined(PETSC_USE_REAL___FLOAT128)
4140da86b62SBarry Smith   ierr = PetscOptionsGetBool(NULL,NULL,"-binary_write_double",&writedouble,NULL);CHKERRQ(ierr);
4150da86b62SBarry Smith   /* If using __float128 precision we still write in doubles to file */
4164caf0332SSatish Balay   if ((type == PETSC_SCALAR || type == PETSC_REAL) && writedouble) {
41741f502e3SPatrick Sanan     wtype = PETSC_DOUBLE;
4180da86b62SBarry Smith     ierr = PetscMalloc1(n,&ppp);CHKERRQ(ierr);
4190da86b62SBarry Smith     pv = (PetscReal*)pp;
4200da86b62SBarry Smith     for (i=0; i<n; i++) {
4210da86b62SBarry Smith       ppp[i] = (double) pv[i];
4220da86b62SBarry Smith     }
4230da86b62SBarry Smith     pp   = (char*)ppp;
4240da86b62SBarry Smith     ptmp = (char*)ppp;
4250da86b62SBarry Smith   }
4260da86b62SBarry Smith #endif
4270da86b62SBarry Smith 
42841f502e3SPatrick Sanan   if (wtype == PETSC_INT)          m *= sizeof(PetscInt);
42941f502e3SPatrick Sanan   else if (wtype == PETSC_SCALAR)  m *= sizeof(PetscScalar);
4304caf0332SSatish Balay   else if (wtype == PETSC_REAL)    m *= sizeof(PetscReal);
43141f502e3SPatrick Sanan   else if (wtype == PETSC_DOUBLE)  m *= sizeof(double);
43241f502e3SPatrick Sanan   else if (wtype == PETSC_FLOAT)   m *= sizeof(float);
43341f502e3SPatrick Sanan   else if (wtype == PETSC_SHORT)   m *= sizeof(short);
434972064b6SLisandro Dalcin   else if (wtype == PETSC_LONG)    m *= sizeof(long);
43541f502e3SPatrick Sanan   else if (wtype == PETSC_CHAR)    m *= sizeof(char);
43641f502e3SPatrick Sanan   else if (wtype == PETSC_ENUM)    m *= sizeof(PetscEnum);
43741f502e3SPatrick Sanan   else if (wtype == PETSC_BOOL)    m *= sizeof(PetscBool);
4389e3e4c22SLisandro Dalcin   else if (wtype == PETSC_INT64)   m *= sizeof(PetscInt64);
43941f502e3SPatrick Sanan   else if (wtype == PETSC_BIT_LOGICAL) m = PetscBTLength(m)*sizeof(char);
440e32f2f54SBarry Smith   else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown type");
441e5c89e4eSSatish Balay 
442*f253e43cSLisandro Dalcin   if (!PetscBinaryBigEndian()) {ierr = PetscByteSwap((void*)ptmp,wtype,n);CHKERRQ(ierr);}
443e5c89e4eSSatish Balay 
444e5c89e4eSSatish Balay   while (m) {
445e5c89e4eSSatish Balay     wsize = (m < maxblock) ? m : maxblock;
446e5c89e4eSSatish Balay     err   = write(fd,pp,wsize);
447e5c89e4eSSatish Balay     if (err < 0 && errno == EINTR) continue;
44804102261SBarry 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);
449e5c89e4eSSatish Balay     m  -= wsize;
450e5c89e4eSSatish Balay     pp += wsize;
451e5c89e4eSSatish Balay   }
452e5c89e4eSSatish Balay 
453*f253e43cSLisandro Dalcin   if (!PetscBinaryBigEndian()) {ierr = PetscByteSwap((void*)ptmp,wtype,n);CHKERRQ(ierr);}
454*f253e43cSLisandro Dalcin 
45505acbc63SBarry Smith   if (type == PETSC_FUNCTION) {
45605acbc63SBarry Smith     free(fname);
45705acbc63SBarry Smith   }
4580da86b62SBarry Smith #if defined(PETSC_USE_REAL___FLOAT128)
4594caf0332SSatish Balay   if ((type == PETSC_SCALAR || type == PETSC_REAL) && writedouble) {
4600da86b62SBarry Smith     ierr = PetscFree(ppp);CHKERRQ(ierr);
4610da86b62SBarry Smith   }
4620da86b62SBarry Smith #endif
463e5c89e4eSSatish Balay   PetscFunctionReturn(0);
464e5c89e4eSSatish Balay }
465e5c89e4eSSatish Balay 
466e5c89e4eSSatish Balay /*@C
467e5c89e4eSSatish Balay    PetscBinaryOpen - Opens a PETSc binary file.
468e5c89e4eSSatish Balay 
469e5c89e4eSSatish Balay    Not Collective
470e5c89e4eSSatish Balay 
471e5c89e4eSSatish Balay    Input Parameters:
472e5c89e4eSSatish Balay +  name - filename
47345c64e65SBarry Smith -  type - type of binary file, one of FILE_MODE_READ, FILE_MODE_APPEND, FILE_MODE_WRITE
474e5c89e4eSSatish Balay 
475e5c89e4eSSatish Balay    Output Parameter:
476e5c89e4eSSatish Balay .  fd - the file
477e5c89e4eSSatish Balay 
478e5c89e4eSSatish Balay    Level: advanced
479e5c89e4eSSatish Balay 
480e5c89e4eSSatish Balay 
48195452b02SPatrick Sanan    Notes:
48295452b02SPatrick Sanan     Files access with PetscBinaryRead() and PetscBinaryWrite() are ALWAYS written in
483e5c89e4eSSatish Balay    big-endian format. This means the file can be accessed using PetscBinaryOpen() and
484e5c89e4eSSatish Balay    PetscBinaryRead() and PetscBinaryWrite() on any machine.
485e5c89e4eSSatish Balay 
4864ebed01fSBarry Smith .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscFileMode, PetscViewerFileSetMode(), PetscViewerBinaryGetDescriptor(),
4874ebed01fSBarry Smith           PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek()
48845c64e65SBarry Smith 
489e5c89e4eSSatish Balay @*/
4907087cfbeSBarry Smith PetscErrorCode  PetscBinaryOpen(const char name[],PetscFileMode mode,int *fd)
491e5c89e4eSSatish Balay {
492e5c89e4eSSatish Balay   PetscFunctionBegin;
493e5c89e4eSSatish Balay #if defined(PETSC_HAVE_O_BINARY)
49445c64e65SBarry Smith   if (mode == FILE_MODE_WRITE) {
495a297a907SKarl 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);
49645c64e65SBarry Smith   } else if (mode == FILE_MODE_READ) {
497a297a907SKarl 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);
49845c64e65SBarry Smith   } else if (mode == FILE_MODE_APPEND) {
499a297a907SKarl 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);
500e5c89e4eSSatish Balay #else
50145c64e65SBarry Smith   if (mode == FILE_MODE_WRITE) {
502a297a907SKarl Rupp     if ((*fd = creat(name,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,0)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file for reading: %s",name);
505e5c89e4eSSatish Balay   }
50645c64e65SBarry Smith   else if (mode == FILE_MODE_APPEND) {
507a297a907SKarl Rupp     if ((*fd = open(name,O_WRONLY,0)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file for writing: %s",name);
508e5c89e4eSSatish Balay #endif
509e32f2f54SBarry Smith   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown file mode");
510e5c89e4eSSatish Balay   PetscFunctionReturn(0);
511e5c89e4eSSatish Balay }
512e5c89e4eSSatish Balay 
513e30d2299SSatish Balay /*@
514e5c89e4eSSatish Balay    PetscBinaryClose - Closes a PETSc binary file.
515e5c89e4eSSatish Balay 
516e5c89e4eSSatish Balay    Not Collective
517e5c89e4eSSatish Balay 
518e5c89e4eSSatish Balay    Output Parameter:
519e5c89e4eSSatish Balay .  fd - the file
520e5c89e4eSSatish Balay 
521e5c89e4eSSatish Balay    Level: advanced
522e5c89e4eSSatish Balay 
5234ebed01fSBarry Smith .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
5244ebed01fSBarry Smith           PetscBinarySynchronizedSeek()
525e5c89e4eSSatish Balay @*/
5267087cfbeSBarry Smith PetscErrorCode  PetscBinaryClose(int fd)
527e5c89e4eSSatish Balay {
528e5c89e4eSSatish Balay   PetscFunctionBegin;
529e5c89e4eSSatish Balay   close(fd);
530e5c89e4eSSatish Balay   PetscFunctionReturn(0);
531e5c89e4eSSatish Balay }
532e5c89e4eSSatish Balay 
533e5c89e4eSSatish Balay 
534e8976759SBarry Smith /*@C
535e5c89e4eSSatish Balay    PetscBinarySeek - Moves the file pointer on a PETSc binary file.
536e5c89e4eSSatish Balay 
537e5c89e4eSSatish Balay    Not Collective
538e5c89e4eSSatish Balay 
539e5c89e4eSSatish Balay    Input Parameters:
540e5c89e4eSSatish Balay +  fd - the file
541ff553b35SMatthew Knepley .  off - number of bytes to move. Use PETSC_BINARY_INT_SIZE, PETSC_BINARY_SCALAR_SIZE,
542e5c89e4eSSatish Balay             etc. in your calculation rather than sizeof() to compute byte lengths.
543ff553b35SMatthew Knepley -  whence - if PETSC_BINARY_SEEK_SET then off is an absolute location in the file
544ff553b35SMatthew Knepley             if PETSC_BINARY_SEEK_CUR then off is an offset from the current location
545ff553b35SMatthew Knepley             if PETSC_BINARY_SEEK_END then off is an offset from the end of file
546e5c89e4eSSatish Balay 
547e5c89e4eSSatish Balay    Output Parameter:
548e5c89e4eSSatish Balay .   offset - new offset in file
549e5c89e4eSSatish Balay 
550e5c89e4eSSatish Balay    Level: developer
551e5c89e4eSSatish Balay 
552e5c89e4eSSatish Balay    Notes:
553e5c89e4eSSatish Balay    Integers are stored on the file as 32 long, regardless of whether
554e5c89e4eSSatish Balay    they are stored in the machine as 32 or 64, this means the same
555e5c89e4eSSatish Balay    binary file may be read on any machine. Hence you CANNOT use sizeof()
556e5c89e4eSSatish Balay    to determine the offset or location.
557e5c89e4eSSatish Balay 
558e5c89e4eSSatish Balay 
5594ebed01fSBarry Smith .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
5604ebed01fSBarry Smith           PetscBinarySynchronizedSeek()
561e5c89e4eSSatish Balay @*/
5627087cfbeSBarry Smith PetscErrorCode  PetscBinarySeek(int fd,off_t off,PetscBinarySeekType whence,off_t *offset)
563e5c89e4eSSatish Balay {
564e5c89e4eSSatish Balay   int iwhence = 0;
565e5c89e4eSSatish Balay 
566e5c89e4eSSatish Balay   PetscFunctionBegin;
567a297a907SKarl Rupp   if (whence == PETSC_BINARY_SEEK_SET) iwhence = SEEK_SET;
568a297a907SKarl Rupp   else if (whence == PETSC_BINARY_SEEK_CUR) iwhence = SEEK_CUR;
569a297a907SKarl Rupp   else if (whence == PETSC_BINARY_SEEK_END) iwhence = SEEK_END;
570a297a907SKarl Rupp   else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown seek location");
571e5c89e4eSSatish Balay #if defined(PETSC_HAVE_LSEEK)
572e5c89e4eSSatish Balay   *offset = lseek(fd,off,iwhence);
573e5c89e4eSSatish Balay #elif defined(PETSC_HAVE__LSEEK)
574e5c89e4eSSatish Balay   *offset = _lseek(fd,(long)off,iwhence);
575e5c89e4eSSatish Balay #else
576e32f2f54SBarry Smith   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS,"System does not have a way of seeking on a file");
577e5c89e4eSSatish Balay #endif
578e5c89e4eSSatish Balay   PetscFunctionReturn(0);
579e5c89e4eSSatish Balay }
580e5c89e4eSSatish Balay 
581e5c89e4eSSatish Balay /*@C
5821d280d73SBarry Smith    PetscBinarySynchronizedRead - Reads from a binary file.
583e5c89e4eSSatish Balay 
584d083f849SBarry Smith    Collective
585e5c89e4eSSatish Balay 
586e5c89e4eSSatish Balay    Input Parameters:
587e5c89e4eSSatish Balay +  comm - the MPI communicator
5889860990eSLisandro Dalcin .  fd - the file descriptor
5899860990eSLisandro Dalcin .  num  - the maximum number of items to read
5909860990eSLisandro Dalcin -  type - the type of items to read (PETSC_INT, PETSC_REAL, PETSC_SCALAR, etc.)
591e5c89e4eSSatish Balay 
592e5c89e4eSSatish Balay    Output Parameters:
5939860990eSLisandro Dalcin +  data - the buffer
5949860990eSLisandro Dalcin -  count - the number of items read, optional
595e5c89e4eSSatish Balay 
596e5c89e4eSSatish Balay    Level: developer
597e5c89e4eSSatish Balay 
598e5c89e4eSSatish Balay    Notes:
599e5c89e4eSSatish Balay    Does a PetscBinaryRead() followed by an MPI_Bcast()
600e5c89e4eSSatish Balay 
6019860990eSLisandro Dalcin    If count is not provided and the number of items read is less than
6029860990eSLisandro Dalcin    the maximum number of items to read, then this routine errors.
6039860990eSLisandro Dalcin 
6041d280d73SBarry Smith    PetscBinarySynchronizedRead() uses byte swapping to work on all machines.
605e5c89e4eSSatish Balay    Integers are stored on the file as 32 long, regardless of whether
606e5c89e4eSSatish Balay    they are stored in the machine as 32 or 64, this means the same
607e5c89e4eSSatish Balay    binary file may be read on any machine.
608e5c89e4eSSatish Balay 
609e5c89e4eSSatish Balay 
6104ebed01fSBarry Smith .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscBinaryRead(), PetscBinarySynchronizedWrite(),
6114ebed01fSBarry Smith           PetscBinarySynchronizedSeek()
612e5c89e4eSSatish Balay @*/
6139860990eSLisandro Dalcin PetscErrorCode  PetscBinarySynchronizedRead(MPI_Comm comm,int fd,void *data,PetscInt num,PetscInt *count,PetscDataType type)
614e5c89e4eSSatish Balay {
6159860990eSLisandro Dalcin   PetscErrorCode ierr;
616e5c89e4eSSatish Balay   PetscMPIInt    rank;
617e5c89e4eSSatish Balay   MPI_Datatype   mtype;
6189860990eSLisandro Dalcin   PetscInt       ibuf[2] = {0, 0};
61905acbc63SBarry Smith   char           *fname = NULL;
6209860990eSLisandro Dalcin   void           *fptr = NULL;
621e5c89e4eSSatish Balay 
622e5c89e4eSSatish Balay   PetscFunctionBegin;
6232d53ad75SBarry Smith   if (type == PETSC_FUNCTION) {
6249860990eSLisandro Dalcin     num   = 64;
6252d53ad75SBarry Smith     type  = PETSC_CHAR;
6269860990eSLisandro Dalcin     fname = (char*)malloc(num*sizeof(char));
6279860990eSLisandro Dalcin     fptr  = data;
6289860990eSLisandro Dalcin     data  = (void*)fname;
62905acbc63SBarry Smith     if (!fname) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Cannot allocate space for function name");
6302d53ad75SBarry Smith   }
6312d53ad75SBarry Smith 
632e5c89e4eSSatish Balay   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
633e5c89e4eSSatish Balay   if (!rank) {
6349860990eSLisandro Dalcin     ibuf[0] = PetscBinaryRead(fd,data,num,count?&ibuf[1]:NULL,type);
635e5c89e4eSSatish Balay   }
6369860990eSLisandro Dalcin   ierr = MPI_Bcast(ibuf,2,MPIU_INT,0,comm);CHKERRQ(ierr);
6379860990eSLisandro Dalcin   ierr = (PetscErrorCode)ibuf[0];CHKERRQ(ierr);
638e5c89e4eSSatish Balay   ierr = PetscDataTypeToMPIDataType(type,&mtype);CHKERRQ(ierr);
6399860990eSLisandro Dalcin   ierr = MPI_Bcast(data,count?ibuf[1]:num,mtype,0,comm);CHKERRQ(ierr);
6409860990eSLisandro Dalcin   if (count) *count = ibuf[1];
6412d53ad75SBarry Smith 
642e366c363SBarry Smith   if (type == PETSC_FUNCTION) {
6432d53ad75SBarry Smith #if defined(PETSC_SERIALIZE_FUNCTIONS)
6449860990eSLisandro Dalcin     ierr = PetscDLLibrarySym(PETSC_COMM_SELF,&PetscDLLibrariesLoaded,NULL,fname,(void**)fptr);CHKERRQ(ierr);
6452d53ad75SBarry Smith #else
6469860990eSLisandro Dalcin     *(void**)fptr = NULL;
6472d53ad75SBarry Smith #endif
648e366c363SBarry Smith     free(fname);
6492d53ad75SBarry Smith   }
650e5c89e4eSSatish Balay   PetscFunctionReturn(0);
651e5c89e4eSSatish Balay }
652e5c89e4eSSatish Balay 
653e5c89e4eSSatish Balay /*@C
6541d280d73SBarry Smith    PetscBinarySynchronizedWrite - writes to a binary file.
655e5c89e4eSSatish Balay 
656d083f849SBarry Smith    Collective
657e5c89e4eSSatish Balay 
658e5c89e4eSSatish Balay    Input Parameters:
659e5c89e4eSSatish Balay +  comm - the MPI communicator
660e5c89e4eSSatish Balay .  fd - the file
661e5c89e4eSSatish Balay .  n  - the number of items to write
662e5c89e4eSSatish Balay .  p - the buffer
663e5c89e4eSSatish Balay -  type - the type of items to write (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)
664e5c89e4eSSatish Balay 
665e5c89e4eSSatish Balay    Level: developer
666e5c89e4eSSatish Balay 
667e5c89e4eSSatish Balay    Notes:
668e5c89e4eSSatish Balay    Process 0 does a PetscBinaryWrite()
669e5c89e4eSSatish Balay 
6701d280d73SBarry Smith    PetscBinarySynchronizedWrite() uses byte swapping to work on all machines.
671e5c89e4eSSatish Balay    Integers are stored on the file as 32 long, regardless of whether
672e5c89e4eSSatish Balay    they are stored in the machine as 32 or 64, this means the same
673e5c89e4eSSatish Balay    binary file may be read on any machine.
674e5c89e4eSSatish Balay 
67595452b02SPatrick Sanan    Notes:
67695452b02SPatrick Sanan     because byte-swapping may be done on the values in data it cannot be declared const
677300a7f5bSBarry Smith 
6781d280d73SBarry Smith    WARNING: This is NOT like PetscSynchronizedFPrintf()! This routine ignores calls on all but process 0,
6791d280d73SBarry Smith    while PetscSynchronizedFPrintf() has all processes print their strings in order.
6801d280d73SBarry Smith 
681e5c89e4eSSatish Balay 
6824ebed01fSBarry Smith .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscBinaryRead(), PetscBinarySynchronizedRead(),
6834ebed01fSBarry Smith           PetscBinarySynchronizedSeek()
684e5c89e4eSSatish Balay @*/
685*f253e43cSLisandro Dalcin PetscErrorCode  PetscBinarySynchronizedWrite(MPI_Comm comm,int fd,const void *p,PetscInt n,PetscDataType type)
686e5c89e4eSSatish Balay {
687e5c89e4eSSatish Balay   PetscErrorCode ierr;
688e5c89e4eSSatish Balay   PetscMPIInt    rank;
689e5c89e4eSSatish Balay 
690e5c89e4eSSatish Balay   PetscFunctionBegin;
691e5c89e4eSSatish Balay   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
692e5c89e4eSSatish Balay   if (!rank) {
693*f253e43cSLisandro Dalcin     ierr = PetscBinaryWrite(fd,p,n,type);CHKERRQ(ierr);
694e5c89e4eSSatish Balay   }
695e5c89e4eSSatish Balay   PetscFunctionReturn(0);
696e5c89e4eSSatish Balay }
697e5c89e4eSSatish Balay 
698e5c89e4eSSatish Balay /*@C
6991d280d73SBarry Smith    PetscBinarySynchronizedSeek - Moves the file pointer on a PETSc binary file.
700e5c89e4eSSatish Balay 
701e5c89e4eSSatish Balay 
702e5c89e4eSSatish Balay    Input Parameters:
703e5c89e4eSSatish Balay +  fd - the file
704e5c89e4eSSatish Balay .  whence - if PETSC_BINARY_SEEK_SET then size is an absolute location in the file
705e5c89e4eSSatish Balay             if PETSC_BINARY_SEEK_CUR then size is offset from current location
706e5c89e4eSSatish Balay             if PETSC_BINARY_SEEK_END then size is offset from end of file
707e5c89e4eSSatish Balay -  off    - number of bytes to move. Use PETSC_BINARY_INT_SIZE, PETSC_BINARY_SCALAR_SIZE,
708e5c89e4eSSatish Balay             etc. in your calculation rather than sizeof() to compute byte lengths.
709e5c89e4eSSatish Balay 
710e5c89e4eSSatish Balay    Output Parameter:
711e5c89e4eSSatish Balay .   offset - new offset in file
712e5c89e4eSSatish Balay 
713e5c89e4eSSatish Balay    Level: developer
714e5c89e4eSSatish Balay 
715e5c89e4eSSatish Balay    Notes:
716e5c89e4eSSatish Balay    Integers are stored on the file as 32 long, regardless of whether
717e5c89e4eSSatish Balay    they are stored in the machine as 32 or 64, this means the same
718e5c89e4eSSatish Balay    binary file may be read on any machine. Hence you CANNOT use sizeof()
719e5c89e4eSSatish Balay    to determine the offset or location.
720e5c89e4eSSatish Balay 
721e5c89e4eSSatish Balay 
7224ebed01fSBarry Smith .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
7234ebed01fSBarry Smith           PetscBinarySynchronizedSeek()
724e5c89e4eSSatish Balay @*/
7257087cfbeSBarry Smith PetscErrorCode  PetscBinarySynchronizedSeek(MPI_Comm comm,int fd,off_t off,PetscBinarySeekType whence,off_t *offset)
726e5c89e4eSSatish Balay {
727e5c89e4eSSatish Balay   PetscErrorCode ierr;
728e5c89e4eSSatish Balay   PetscMPIInt    rank;
729e5c89e4eSSatish Balay 
730e5c89e4eSSatish Balay   PetscFunctionBegin;
731e5c89e4eSSatish Balay   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
732e5c89e4eSSatish Balay   if (!rank) {
733e5c89e4eSSatish Balay     ierr = PetscBinarySeek(fd,off,whence,offset);CHKERRQ(ierr);
734e5c89e4eSSatish Balay   }
735e5c89e4eSSatish Balay   PetscFunctionReturn(0);
736e5c89e4eSSatish Balay }
737e5c89e4eSSatish Balay 
7380fc9d207SBarry Smith #if defined(PETSC_HAVE_MPIIO)
739e39fd77fSBarry Smith 
740951e3c8eSBarry Smith #if defined(PETSC_USE_PETSC_MPI_EXTERNAL32)
741e39fd77fSBarry Smith /*
742e39fd77fSBarry Smith       MPICH does not provide the external32 representation for MPI_File_set_view() so we need to provide the functions.
743e39fd77fSBarry Smith     These are set into MPI in PetscInitialize() via MPI_Register_datarep()
744e39fd77fSBarry Smith 
745e39fd77fSBarry Smith     Note I use PetscMPIInt for the MPI error codes since that is what MPI uses (instead of the standard PetscErrorCode)
746e39fd77fSBarry Smith 
747951e3c8eSBarry Smith     The next three routines are not used because MPICH does not support their use
748e39fd77fSBarry Smith 
749e39fd77fSBarry Smith */
7508cc058d9SJed Brown PETSC_EXTERN PetscMPIInt PetscDataRep_extent_fn(MPI_Datatype datatype,MPI_Aint *file_extent,void *extra_state)
751e39fd77fSBarry Smith {
752e39fd77fSBarry Smith   MPI_Aint    ub;
753e39fd77fSBarry Smith   PetscMPIInt ierr;
754e39fd77fSBarry Smith 
755e39fd77fSBarry Smith   ierr = MPI_Type_get_extent(datatype,&ub,file_extent);
756e39fd77fSBarry Smith   return ierr;
757e39fd77fSBarry Smith }
758e39fd77fSBarry Smith 
7598cc058d9SJed Brown PETSC_EXTERN PetscMPIInt PetscDataRep_read_conv_fn(void *userbuf, MPI_Datatype datatype,PetscMPIInt count,void *filebuf, MPI_Offset position,void *extra_state)
760e39fd77fSBarry Smith {
761e39fd77fSBarry Smith   PetscDataType pdtype;
762e39fd77fSBarry Smith   PetscMPIInt   ierr;
763e39fd77fSBarry Smith   size_t        dsize;
764e39fd77fSBarry Smith 
765e39fd77fSBarry Smith   ierr = PetscMPIDataTypeToPetscDataType(datatype,&pdtype);CHKERRQ(ierr);
766e39fd77fSBarry Smith   ierr = PetscDataTypeGetSize(pdtype,&dsize);CHKERRQ(ierr);
767e39fd77fSBarry Smith 
768e39fd77fSBarry Smith   /* offset is given in units of MPI_Datatype */
769e39fd77fSBarry Smith   userbuf = ((char*)userbuf) + dsize*position;
770e39fd77fSBarry Smith 
771e39fd77fSBarry Smith   ierr = PetscMemcpy(userbuf,filebuf,count*dsize);CHKERRQ(ierr);
77230815ce0SLisandro Dalcin   if (!PetscBinaryBigEndian()) {ierr = PetscByteSwap(userbuf,pdtype,count);CHKERRQ(ierr);}
773e39fd77fSBarry Smith   return ierr;
774e39fd77fSBarry Smith }
775e39fd77fSBarry Smith 
776e39fd77fSBarry Smith PetscMPIInt PetscDataRep_write_conv_fn(void *userbuf, MPI_Datatype datatype,PetscMPIInt count,void *filebuf, MPI_Offset position,void *extra_state)
777e39fd77fSBarry Smith {
778e39fd77fSBarry Smith   PetscDataType pdtype;
779e39fd77fSBarry Smith   PetscMPIInt   ierr;
780e39fd77fSBarry Smith   size_t        dsize;
781e39fd77fSBarry Smith 
782e39fd77fSBarry Smith   ierr = PetscMPIDataTypeToPetscDataType(datatype,&pdtype);CHKERRQ(ierr);
783e39fd77fSBarry Smith   ierr = PetscDataTypeGetSize(pdtype,&dsize);CHKERRQ(ierr);
784e39fd77fSBarry Smith 
785e39fd77fSBarry Smith   /* offset is given in units of MPI_Datatype */
786e39fd77fSBarry Smith   userbuf = ((char*)userbuf) + dsize*position;
787e39fd77fSBarry Smith 
788e39fd77fSBarry Smith   ierr = PetscMemcpy(filebuf,userbuf,count*dsize);CHKERRQ(ierr);
78930815ce0SLisandro Dalcin   if (!PetscBinaryBigEndian()) {ierr = PetscByteSwap(filebuf,pdtype,count);CHKERRQ(ierr);}
790e39fd77fSBarry Smith   return ierr;
791e39fd77fSBarry Smith }
792951e3c8eSBarry Smith #endif
793e39fd77fSBarry Smith 
794e39fd77fSBarry Smith PetscErrorCode MPIU_File_write_all(MPI_File fd,void *data,PetscMPIInt cnt,MPI_Datatype dtype,MPI_Status *status)
795e39fd77fSBarry Smith {
796e39fd77fSBarry Smith   PetscDataType  pdtype;
79730815ce0SLisandro Dalcin   PetscErrorCode ierr;
79830815ce0SLisandro Dalcin 
799e39fd77fSBarry Smith 
800e39fd77fSBarry Smith   PetscFunctionBegin;
801e39fd77fSBarry Smith   ierr = PetscMPIDataTypeToPetscDataType(dtype,&pdtype);CHKERRQ(ierr);
80230815ce0SLisandro Dalcin   if (!PetscBinaryBigEndian()) {ierr = PetscByteSwap(data,pdtype,cnt);CHKERRQ(ierr);}
803e39fd77fSBarry Smith   ierr = MPI_File_write_all(fd,data,cnt,dtype,status);CHKERRQ(ierr);
80430815ce0SLisandro Dalcin   if (!PetscBinaryBigEndian()) {ierr = PetscByteSwap(data,pdtype,cnt);CHKERRQ(ierr);}
805a6796414SBarry Smith   PetscFunctionReturn(0);
806e39fd77fSBarry Smith }
807e39fd77fSBarry Smith 
808e39fd77fSBarry Smith PetscErrorCode MPIU_File_read_all(MPI_File fd,void *data,PetscMPIInt cnt,MPI_Datatype dtype,MPI_Status *status)
809e39fd77fSBarry Smith {
810e39fd77fSBarry Smith   PetscDataType  pdtype;
81130815ce0SLisandro Dalcin   PetscErrorCode ierr;
812e39fd77fSBarry Smith 
813e39fd77fSBarry Smith   PetscFunctionBegin;
814e39fd77fSBarry Smith   ierr = PetscMPIDataTypeToPetscDataType(dtype,&pdtype);CHKERRQ(ierr);
815e39fd77fSBarry Smith   ierr = MPI_File_read_all(fd,data,cnt,dtype,status);CHKERRQ(ierr);
81630815ce0SLisandro Dalcin   if (!PetscBinaryBigEndian()) {ierr = PetscByteSwap(data,pdtype,cnt);CHKERRQ(ierr);}
817a6796414SBarry Smith   PetscFunctionReturn(0);
818e39fd77fSBarry Smith }
81930815ce0SLisandro Dalcin 
820c4e82887SLisandro Dalcin PetscErrorCode MPIU_File_write_at(MPI_File fd,MPI_Offset off,void *data,PetscMPIInt cnt,MPI_Datatype dtype,MPI_Status *status)
821c4e82887SLisandro Dalcin {
822c4e82887SLisandro Dalcin   PetscDataType  pdtype;
823c4e82887SLisandro Dalcin   PetscErrorCode ierr;
824c4e82887SLisandro Dalcin 
825c4e82887SLisandro Dalcin 
826c4e82887SLisandro Dalcin   PetscFunctionBegin;
827c4e82887SLisandro Dalcin   ierr = PetscMPIDataTypeToPetscDataType(dtype,&pdtype);CHKERRQ(ierr);
828c4e82887SLisandro Dalcin   if (!PetscBinaryBigEndian()) {ierr = PetscByteSwap(data,pdtype,cnt);CHKERRQ(ierr);}
829c4e82887SLisandro Dalcin   ierr = MPI_File_write_at(fd,off,data,cnt,dtype,status);CHKERRQ(ierr);
830c4e82887SLisandro Dalcin   if (!PetscBinaryBigEndian()) {ierr = PetscByteSwap(data,pdtype,cnt);CHKERRQ(ierr);}
831c4e82887SLisandro Dalcin   PetscFunctionReturn(0);
832c4e82887SLisandro Dalcin }
833c4e82887SLisandro Dalcin 
834c4e82887SLisandro Dalcin PetscErrorCode MPIU_File_read_at(MPI_File fd,MPI_Offset off,void *data,PetscMPIInt cnt,MPI_Datatype dtype,MPI_Status *status)
835c4e82887SLisandro Dalcin {
836c4e82887SLisandro Dalcin   PetscDataType  pdtype;
837c4e82887SLisandro Dalcin   PetscErrorCode ierr;
838c4e82887SLisandro Dalcin 
839c4e82887SLisandro Dalcin   PetscFunctionBegin;
840c4e82887SLisandro Dalcin   ierr = PetscMPIDataTypeToPetscDataType(dtype,&pdtype);CHKERRQ(ierr);
841c4e82887SLisandro Dalcin   ierr = MPI_File_read_at(fd,off,data,cnt,dtype,status);CHKERRQ(ierr);
842c4e82887SLisandro Dalcin   if (!PetscBinaryBigEndian()) {ierr = PetscByteSwap(data,pdtype,cnt);CHKERRQ(ierr);}
843c4e82887SLisandro Dalcin   PetscFunctionReturn(0);
844c4e82887SLisandro Dalcin }
845c4e82887SLisandro Dalcin 
846c4e82887SLisandro Dalcin PetscErrorCode MPIU_File_write_at_all(MPI_File fd,MPI_Offset off,void *data,PetscMPIInt cnt,MPI_Datatype dtype,MPI_Status *status)
847c4e82887SLisandro Dalcin {
848c4e82887SLisandro Dalcin   PetscDataType  pdtype;
849c4e82887SLisandro Dalcin   PetscErrorCode ierr;
850c4e82887SLisandro Dalcin 
851c4e82887SLisandro Dalcin 
852c4e82887SLisandro Dalcin   PetscFunctionBegin;
853c4e82887SLisandro Dalcin   ierr = PetscMPIDataTypeToPetscDataType(dtype,&pdtype);CHKERRQ(ierr);
854c4e82887SLisandro Dalcin   if (!PetscBinaryBigEndian()) {ierr = PetscByteSwap(data,pdtype,cnt);CHKERRQ(ierr);}
855c4e82887SLisandro Dalcin   ierr = MPI_File_write_at_all(fd,off,data,cnt,dtype,status);CHKERRQ(ierr);
856c4e82887SLisandro Dalcin   if (!PetscBinaryBigEndian()) {ierr = PetscByteSwap(data,pdtype,cnt);CHKERRQ(ierr);}
857c4e82887SLisandro Dalcin   PetscFunctionReturn(0);
858c4e82887SLisandro Dalcin }
859c4e82887SLisandro Dalcin 
860c4e82887SLisandro Dalcin PetscErrorCode MPIU_File_read_at_all(MPI_File fd,MPI_Offset off,void *data,PetscMPIInt cnt,MPI_Datatype dtype,MPI_Status *status)
861c4e82887SLisandro Dalcin {
862c4e82887SLisandro Dalcin   PetscDataType  pdtype;
863c4e82887SLisandro Dalcin   PetscErrorCode ierr;
864c4e82887SLisandro Dalcin 
865c4e82887SLisandro Dalcin   PetscFunctionBegin;
866c4e82887SLisandro Dalcin   ierr = PetscMPIDataTypeToPetscDataType(dtype,&pdtype);CHKERRQ(ierr);
867c4e82887SLisandro Dalcin   ierr = MPI_File_read_at_all(fd,off,data,cnt,dtype,status);CHKERRQ(ierr);
868c4e82887SLisandro Dalcin   if (!PetscBinaryBigEndian()) {ierr = PetscByteSwap(data,pdtype,cnt);CHKERRQ(ierr);}
869c4e82887SLisandro Dalcin   PetscFunctionReturn(0);
870c4e82887SLisandro Dalcin }
871c4e82887SLisandro Dalcin 
872951e3c8eSBarry Smith #endif
873