xref: /petsc/src/sys/fileio/sysio.c (revision 5607bdc5ff4a0a174f577d6f2adfb53fc0ebe0f0)
1c6db04a5SJed Brown #include <petscsys.h>
2cc843e7aSLisandro Dalcin #include <petscbt.h>
3e5c89e4eSSatish Balay #include <errno.h>
4e5c89e4eSSatish Balay #include <fcntl.h>
5e5c89e4eSSatish Balay #if defined(PETSC_HAVE_UNISTD_H)
6e5c89e4eSSatish Balay   #include <unistd.h>
7e5c89e4eSSatish Balay #endif
8e5c89e4eSSatish Balay #if defined(PETSC_HAVE_IO_H)
9e5c89e4eSSatish Balay   #include <io.h>
10e5c89e4eSSatish Balay #endif
11cc843e7aSLisandro Dalcin #if !defined(PETSC_HAVE_O_BINARY)
12cc843e7aSLisandro Dalcin   #define O_BINARY 0
13cc843e7aSLisandro Dalcin #endif
14e5c89e4eSSatish Balay 
1502c9f0b5SLisandro Dalcin const char *const PetscFileModes[] = {"READ", "WRITE", "APPEND", "UPDATE", "APPEND_UPDATE", "PetscFileMode", "PETSC_FILE_", NULL};
16d6a4318aSJed Brown 
17e5c89e4eSSatish Balay /*
186de02169SBarry Smith   PetscByteSwapEnum - Swap bytes in a  PETSc Enum
19e5c89e4eSSatish Balay 
20e5c89e4eSSatish Balay */
216497c311SBarry Smith static PetscErrorCode PetscByteSwapEnum(PetscEnum *buff, PetscCount n)
22d71ae5a4SJacob Faibussowitsch {
236497c311SBarry Smith   PetscCount i, j;
240b20345dSBarry Smith   PetscEnum  tmp = ENUM_DUMMY;
25e0890e22SSatish Balay   char      *ptr1, *ptr2 = (char *)&tmp;
26e5c89e4eSSatish Balay 
27e5c89e4eSSatish Balay   PetscFunctionBegin;
28e5c89e4eSSatish Balay   for (j = 0; j < n; j++) {
29e5c89e4eSSatish Balay     ptr1 = (char *)(buff + j);
306497c311SBarry Smith     for (i = 0; i < (PetscCount)sizeof(PetscEnum); i++) ptr2[i] = ptr1[sizeof(PetscEnum) - 1 - i];
316497c311SBarry Smith     for (i = 0; i < (PetscCount)sizeof(PetscEnum); i++) ptr1[i] = ptr2[i];
32e5c89e4eSSatish Balay   }
333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
34e5c89e4eSSatish Balay }
356de02169SBarry Smith 
366de02169SBarry Smith /*
37acfcf0e5SJed Brown   PetscByteSwapBool - Swap bytes in a  PETSc Bool
386de02169SBarry Smith 
396de02169SBarry Smith */
406497c311SBarry Smith static PetscErrorCode PetscByteSwapBool(PetscBool *buff, PetscCount n)
41d71ae5a4SJacob Faibussowitsch {
426497c311SBarry Smith   PetscCount i, j;
43ace3abfcSBarry Smith   PetscBool  tmp = PETSC_FALSE;
44e0890e22SSatish Balay   char      *ptr1, *ptr2 = (char *)&tmp;
456de02169SBarry Smith 
466de02169SBarry Smith   PetscFunctionBegin;
476de02169SBarry Smith   for (j = 0; j < n; j++) {
486de02169SBarry Smith     ptr1 = (char *)(buff + j);
496497c311SBarry Smith     for (i = 0; i < (PetscCount)sizeof(PetscBool); i++) ptr2[i] = ptr1[sizeof(PetscBool) - 1 - i];
506497c311SBarry Smith     for (i = 0; i < (PetscCount)sizeof(PetscBool); i++) ptr1[i] = ptr2[i];
516de02169SBarry Smith   }
523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
536de02169SBarry Smith }
546de02169SBarry Smith 
55bd1d2e58SBarry Smith /*
567de69702SBarry Smith   PetscByteSwapInt - Swap bytes in a  PETSc integer (which may be 32 or 64-bits)
57bd1d2e58SBarry Smith 
58bd1d2e58SBarry Smith */
596497c311SBarry Smith static PetscErrorCode PetscByteSwapInt(PetscInt *buff, PetscCount n)
60d71ae5a4SJacob Faibussowitsch {
616497c311SBarry Smith   PetscCount i, j;
626497c311SBarry Smith   PetscInt   tmp = 0;
63e0890e22SSatish Balay   char      *ptr1, *ptr2 = (char *)&tmp;
64bd1d2e58SBarry Smith 
65bd1d2e58SBarry Smith   PetscFunctionBegin;
66bd1d2e58SBarry Smith   for (j = 0; j < n; j++) {
67bd1d2e58SBarry Smith     ptr1 = (char *)(buff + j);
686497c311SBarry Smith     for (i = 0; i < (PetscCount)sizeof(PetscInt); i++) ptr2[i] = ptr1[sizeof(PetscInt) - 1 - i];
696497c311SBarry Smith     for (i = 0; i < (PetscCount)sizeof(PetscInt); i++) ptr1[i] = ptr2[i];
70bd1d2e58SBarry Smith   }
713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
72bd1d2e58SBarry Smith }
739e3e4c22SLisandro Dalcin 
749e3e4c22SLisandro Dalcin /*
757de69702SBarry Smith   PetscByteSwapInt64 - Swap bytes in a  PETSc integer (64-bits)
769e3e4c22SLisandro Dalcin 
779e3e4c22SLisandro Dalcin */
786497c311SBarry Smith static PetscErrorCode PetscByteSwapInt64(PetscInt64 *buff, PetscCount n)
79d71ae5a4SJacob Faibussowitsch {
806497c311SBarry Smith   PetscCount i, j;
819e3e4c22SLisandro Dalcin   PetscInt64 tmp = 0;
829e3e4c22SLisandro Dalcin   char      *ptr1, *ptr2 = (char *)&tmp;
839e3e4c22SLisandro Dalcin 
849e3e4c22SLisandro Dalcin   PetscFunctionBegin;
859e3e4c22SLisandro Dalcin   for (j = 0; j < n; j++) {
869e3e4c22SLisandro Dalcin     ptr1 = (char *)(buff + j);
876497c311SBarry Smith     for (i = 0; i < (PetscCount)sizeof(PetscInt64); i++) ptr2[i] = ptr1[sizeof(PetscInt64) - 1 - i];
886497c311SBarry Smith     for (i = 0; i < (PetscCount)sizeof(PetscInt64); i++) ptr1[i] = ptr2[i];
899e3e4c22SLisandro Dalcin   }
903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
919e3e4c22SLisandro Dalcin }
929e3e4c22SLisandro Dalcin 
93e5c89e4eSSatish Balay /*
943321ca25SJames Wright   PetscByteSwapInt32 - Swap bytes in a  PETSc integer (32-bits)
953321ca25SJames Wright 
963321ca25SJames Wright */
976497c311SBarry Smith static PetscErrorCode PetscByteSwapInt32(PetscInt32 *buff, PetscCount n)
983321ca25SJames Wright {
996497c311SBarry Smith   PetscCount i, j;
1003321ca25SJames Wright   PetscInt32 tmp = 0;
1013321ca25SJames Wright   char      *ptr1, *ptr2 = (char *)&tmp;
1023321ca25SJames Wright 
1033321ca25SJames Wright   PetscFunctionBegin;
1043321ca25SJames Wright   for (j = 0; j < n; j++) {
1053321ca25SJames Wright     ptr1 = (char *)(buff + j);
1066497c311SBarry Smith     for (i = 0; i < (PetscCount)sizeof(PetscInt32); i++) ptr2[i] = ptr1[sizeof(PetscInt32) - 1 - i];
1076497c311SBarry Smith     for (i = 0; i < (PetscCount)sizeof(PetscInt32); i++) ptr1[i] = ptr2[i];
1083321ca25SJames Wright   }
1093321ca25SJames Wright   PetscFunctionReturn(PETSC_SUCCESS);
1103321ca25SJames Wright }
1113321ca25SJames Wright 
1123321ca25SJames Wright /*
113e5c89e4eSSatish Balay   PetscByteSwapShort - Swap bytes in a short
114e5c89e4eSSatish Balay */
1156497c311SBarry Smith static PetscErrorCode PetscByteSwapShort(short *buff, PetscCount n)
116d71ae5a4SJacob Faibussowitsch {
1176497c311SBarry Smith   PetscCount i, j;
118e5c89e4eSSatish Balay   short      tmp;
119e5c89e4eSSatish Balay   char      *ptr1, *ptr2 = (char *)&tmp;
120e5c89e4eSSatish Balay 
121e5c89e4eSSatish Balay   PetscFunctionBegin;
122e5c89e4eSSatish Balay   for (j = 0; j < n; j++) {
123e5c89e4eSSatish Balay     ptr1 = (char *)(buff + j);
1246497c311SBarry Smith     for (i = 0; i < (PetscCount)sizeof(short); i++) ptr2[i] = ptr1[sizeof(short) - 1 - i];
1256497c311SBarry Smith     for (i = 0; i < (PetscCount)sizeof(short); i++) ptr1[i] = ptr2[i];
126e5c89e4eSSatish Balay   }
1273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
128e5c89e4eSSatish Balay }
129972064b6SLisandro Dalcin /*
130972064b6SLisandro Dalcin   PetscByteSwapLong - Swap bytes in a long
131972064b6SLisandro Dalcin */
1326497c311SBarry Smith static PetscErrorCode PetscByteSwapLong(long *buff, PetscCount n)
133d71ae5a4SJacob Faibussowitsch {
1346497c311SBarry Smith   PetscCount i, j;
135972064b6SLisandro Dalcin   long       tmp;
136972064b6SLisandro Dalcin   char      *ptr1, *ptr2 = (char *)&tmp;
137972064b6SLisandro Dalcin 
138972064b6SLisandro Dalcin   PetscFunctionBegin;
139972064b6SLisandro Dalcin   for (j = 0; j < n; j++) {
140972064b6SLisandro Dalcin     ptr1 = (char *)(buff + j);
1416497c311SBarry Smith     for (i = 0; i < (PetscCount)sizeof(long); i++) ptr2[i] = ptr1[sizeof(long) - 1 - i];
1426497c311SBarry Smith     for (i = 0; i < (PetscCount)sizeof(long); i++) ptr1[i] = ptr2[i];
143972064b6SLisandro Dalcin   }
1443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
145972064b6SLisandro Dalcin }
14621532e8aSBarry Smith 
147e5c89e4eSSatish Balay /*
1484caf0332SSatish Balay   PetscByteSwapReal - Swap bytes in a PetscReal
1494caf0332SSatish Balay */
1506497c311SBarry Smith static PetscErrorCode PetscByteSwapReal(PetscReal *buff, PetscCount n)
151d71ae5a4SJacob Faibussowitsch {
1526497c311SBarry Smith   PetscCount i, j;
1534caf0332SSatish Balay   PetscReal  tmp, *buff1 = (PetscReal *)buff;
1544caf0332SSatish Balay   char      *ptr1, *ptr2 = (char *)&tmp;
1554caf0332SSatish Balay 
1564caf0332SSatish Balay   PetscFunctionBegin;
1574caf0332SSatish Balay   for (j = 0; j < n; j++) {
1584caf0332SSatish Balay     ptr1 = (char *)(buff1 + j);
1596497c311SBarry Smith     for (i = 0; i < (PetscCount)sizeof(PetscReal); i++) ptr2[i] = ptr1[sizeof(PetscReal) - 1 - i];
1606497c311SBarry Smith     for (i = 0; i < (PetscCount)sizeof(PetscReal); i++) ptr1[i] = ptr2[i];
1614caf0332SSatish Balay   }
1623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1634caf0332SSatish Balay }
16421532e8aSBarry Smith 
1654caf0332SSatish Balay /*
16641f502e3SPatrick Sanan   PetscByteSwapScalar - Swap bytes in a PetscScalar
16715229ffcSPierre Jolivet   The complex case is dealt with an array of PetscReal, twice as long.
168e5c89e4eSSatish Balay */
1696497c311SBarry Smith static PetscErrorCode PetscByteSwapScalar(PetscScalar *buff, PetscCount n)
170d71ae5a4SJacob Faibussowitsch {
1716497c311SBarry Smith   PetscCount i, j;
172e5c89e4eSSatish Balay   PetscReal  tmp, *buff1 = (PetscReal *)buff;
173e5c89e4eSSatish Balay   char      *ptr1, *ptr2 = (char *)&tmp;
174e5c89e4eSSatish Balay 
175e5c89e4eSSatish Balay   PetscFunctionBegin;
176e5c89e4eSSatish Balay #if defined(PETSC_USE_COMPLEX)
177e5c89e4eSSatish Balay   n *= 2;
178e5c89e4eSSatish Balay #endif
179e5c89e4eSSatish Balay   for (j = 0; j < n; j++) {
180e5c89e4eSSatish Balay     ptr1 = (char *)(buff1 + j);
1816497c311SBarry Smith     for (i = 0; i < (PetscCount)sizeof(PetscReal); i++) ptr2[i] = ptr1[sizeof(PetscReal) - 1 - i];
1826497c311SBarry Smith     for (i = 0; i < (PetscCount)sizeof(PetscReal); i++) ptr1[i] = ptr2[i];
183e5c89e4eSSatish Balay   }
1843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
185e5c89e4eSSatish Balay }
18621532e8aSBarry Smith 
187e5c89e4eSSatish Balay /*
188e5c89e4eSSatish Balay   PetscByteSwapDouble - Swap bytes in a double
189e5c89e4eSSatish Balay */
1906497c311SBarry Smith static PetscErrorCode PetscByteSwapDouble(double *buff, PetscCount n)
191d71ae5a4SJacob Faibussowitsch {
1926497c311SBarry Smith   PetscCount i, j;
193e5c89e4eSSatish Balay   double     tmp, *buff1 = (double *)buff;
194e5c89e4eSSatish Balay   char      *ptr1, *ptr2 = (char *)&tmp;
195e5c89e4eSSatish Balay 
196e5c89e4eSSatish Balay   PetscFunctionBegin;
197e5c89e4eSSatish Balay   for (j = 0; j < n; j++) {
198e5c89e4eSSatish Balay     ptr1 = (char *)(buff1 + j);
1996497c311SBarry Smith     for (i = 0; i < (PetscCount)sizeof(double); i++) ptr2[i] = ptr1[sizeof(double) - 1 - i];
2006497c311SBarry Smith     for (i = 0; i < (PetscCount)sizeof(double); i++) ptr1[i] = ptr2[i];
201e5c89e4eSSatish Balay   }
2023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
203e5c89e4eSSatish Balay }
204e39fd77fSBarry Smith 
205e95bf02fSSatish Balay /*
206e95bf02fSSatish Balay   PetscByteSwapFloat - Swap bytes in a float
207e95bf02fSSatish Balay */
2086497c311SBarry Smith static PetscErrorCode PetscByteSwapFloat(float *buff, PetscCount n)
209d71ae5a4SJacob Faibussowitsch {
2106497c311SBarry Smith   PetscCount i, j;
211e95bf02fSSatish Balay   float      tmp, *buff1 = (float *)buff;
212e95bf02fSSatish Balay   char      *ptr1, *ptr2 = (char *)&tmp;
213e95bf02fSSatish Balay 
214e95bf02fSSatish Balay   PetscFunctionBegin;
215e95bf02fSSatish Balay   for (j = 0; j < n; j++) {
216e95bf02fSSatish Balay     ptr1 = (char *)(buff1 + j);
2176497c311SBarry Smith     for (i = 0; i < (PetscCount)sizeof(float); i++) ptr2[i] = ptr1[sizeof(float) - 1 - i];
2186497c311SBarry Smith     for (i = 0; i < (PetscCount)sizeof(float); i++) ptr1[i] = ptr2[i];
219e95bf02fSSatish Balay   }
2203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
221e95bf02fSSatish Balay }
222e95bf02fSSatish Balay 
2236497c311SBarry Smith PetscErrorCode PetscByteSwap(void *data, PetscDataType pdtype, PetscCount count)
224d71ae5a4SJacob Faibussowitsch {
225e39fd77fSBarry Smith   PetscFunctionBegin;
2269566063dSJacob Faibussowitsch   if (pdtype == PETSC_INT) PetscCall(PetscByteSwapInt((PetscInt *)data, count));
2279566063dSJacob Faibussowitsch   else if (pdtype == PETSC_ENUM) PetscCall(PetscByteSwapEnum((PetscEnum *)data, count));
2289566063dSJacob Faibussowitsch   else if (pdtype == PETSC_BOOL) PetscCall(PetscByteSwapBool((PetscBool *)data, count));
2299566063dSJacob Faibussowitsch   else if (pdtype == PETSC_SCALAR) PetscCall(PetscByteSwapScalar((PetscScalar *)data, count));
2309566063dSJacob Faibussowitsch   else if (pdtype == PETSC_REAL) PetscCall(PetscByteSwapReal((PetscReal *)data, count));
2319566063dSJacob Faibussowitsch   else if (pdtype == PETSC_COMPLEX) PetscCall(PetscByteSwapReal((PetscReal *)data, 2 * count));
2329566063dSJacob Faibussowitsch   else if (pdtype == PETSC_INT64) PetscCall(PetscByteSwapInt64((PetscInt64 *)data, count));
2336497c311SBarry Smith   else if (pdtype == PETSC_COUNT) PetscCall(PetscByteSwapInt64((PetscInt64 *)data, count));
2343321ca25SJames Wright   else if (pdtype == PETSC_INT32) PetscCall(PetscByteSwapInt32((PetscInt32 *)data, count));
2359566063dSJacob Faibussowitsch   else if (pdtype == PETSC_DOUBLE) PetscCall(PetscByteSwapDouble((double *)data, count));
2369566063dSJacob Faibussowitsch   else if (pdtype == PETSC_FLOAT) PetscCall(PetscByteSwapFloat((float *)data, count));
2379566063dSJacob Faibussowitsch   else if (pdtype == PETSC_SHORT) PetscCall(PetscByteSwapShort((short *)data, count));
2389566063dSJacob Faibussowitsch   else if (pdtype == PETSC_LONG) PetscCall(PetscByteSwapLong((long *)data, count));
239372de11fSJed Brown   else if (pdtype == PETSC_CHAR) PetscFunctionReturn(PETSC_SUCCESS);
2403321ca25SJames Wright   else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Unknown type: %d", pdtype);
2413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
242e39fd77fSBarry Smith }
243e39fd77fSBarry Smith 
2449860990eSLisandro Dalcin /*@C
245e5c89e4eSSatish Balay   PetscBinaryRead - Reads from a binary file.
246e5c89e4eSSatish Balay 
247e5c89e4eSSatish Balay   Not Collective
248e5c89e4eSSatish Balay 
249e5c89e4eSSatish Balay   Input Parameters:
2509860990eSLisandro Dalcin + fd   - the file descriptor
2519860990eSLisandro Dalcin . num  - the maximum number of items to read
252811af0c4SBarry Smith - type - the type of items to read (`PETSC_INT`, `PETSC_REAL`, `PETSC_SCALAR`, etc.)
253e5c89e4eSSatish Balay 
254e5c89e4eSSatish Balay   Output Parameters:
25521532e8aSBarry Smith + data  - the buffer, this is an array of the type that matches the value in `type`
2569860990eSLisandro Dalcin - count - the number of items read, optional
257e5c89e4eSSatish Balay 
258e5c89e4eSSatish Balay   Level: developer
259e5c89e4eSSatish Balay 
260e5c89e4eSSatish Balay   Notes:
26121532e8aSBarry Smith   If `count` is not provided and the number of items read is less than
2629860990eSLisandro Dalcin   the maximum number of items to read, then this routine errors.
2639860990eSLisandro Dalcin 
264811af0c4SBarry Smith   `PetscBinaryRead()` uses byte swapping to work on all machines; the files
26521532e8aSBarry Smith   are written ALWAYS using big-endian ordering. On little-endian machines the numbers
266f253e43cSLisandro Dalcin   are converted to the little-endian format when they are read in from the file.
26721532e8aSBarry Smith   When PETSc is ./configure with `--with-64-bit-indices` the integers are written to the
2687de69702SBarry Smith   file as 64-bit integers, this means they can only be read back in when the option `--with-64-bit-indices`
26954f21887SBarry Smith   is used.
270e5c89e4eSSatish Balay 
271cc4c1da9SBarry Smith   Fortran Note:
272cc4c1da9SBarry Smith   There are different functions for each datatype, for example `PetscBinaryReadInt()`
273cc4c1da9SBarry Smith 
274db781477SPatrick Sanan .seealso: `PetscBinaryWrite()`, `PetscBinaryOpen()`, `PetscBinaryClose()`, `PetscViewerBinaryGetDescriptor()`, `PetscBinarySynchronizedWrite()`,
275db781477SPatrick Sanan           `PetscBinarySynchronizedRead()`, `PetscBinarySynchronizedSeek()`
276e5c89e4eSSatish Balay @*/
2776497c311SBarry Smith PetscErrorCode PetscBinaryRead(int fd, void *data, PetscCount num, PetscInt *count, PetscDataType type)
278d71ae5a4SJacob Faibussowitsch {
2799860990eSLisandro Dalcin   size_t typesize, m = (size_t)num, n = 0, maxblock = 65536;
2809860990eSLisandro Dalcin   char  *p = (char *)data;
2817a881295SBarry Smith #if defined(PETSC_USE_REAL___FLOAT128)
282cba51d77SBarry Smith   PetscBool readdouble = PETSC_FALSE;
2839860990eSLisandro Dalcin   double   *pdouble;
2847a881295SBarry Smith #endif
2859860990eSLisandro Dalcin   void *ptmp  = data;
28605acbc63SBarry Smith   char *fname = NULL;
287e5c89e4eSSatish Balay 
288e5c89e4eSSatish Balay   PetscFunctionBegin;
2899860990eSLisandro Dalcin   if (count) *count = 0;
2906497c311SBarry Smith   PetscCheck(num >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to read a negative amount of data %" PetscCount_FMT, num);
2913ba16761SJacob Faibussowitsch   if (!num) PetscFunctionReturn(PETSC_SUCCESS);
292e5c89e4eSSatish Balay 
2932d53ad75SBarry Smith   if (type == PETSC_FUNCTION) {
2942d53ad75SBarry Smith     m     = 64;
2952d53ad75SBarry Smith     type  = PETSC_CHAR;
29605acbc63SBarry Smith     fname = (char *)malloc(m * sizeof(char));
2979860990eSLisandro Dalcin     p     = (char *)fname;
2982d53ad75SBarry Smith     ptmp  = (void *)fname;
29928b400f6SJacob Faibussowitsch     PetscCheck(fname, PETSC_COMM_SELF, PETSC_ERR_MEM, "Cannot allocate space for function name");
3002d53ad75SBarry Smith   }
3016497c311SBarry Smith   if (type == PETSC_BIT_LOGICAL) m = PetscBTLength(num);
3022d53ad75SBarry Smith 
3039566063dSJacob Faibussowitsch   PetscCall(PetscDataTypeGetSize(type, &typesize));
304e5c89e4eSSatish Balay 
3057a881295SBarry Smith #if defined(PETSC_USE_REAL___FLOAT128)
3069566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(NULL, NULL, "-binary_read_double", &readdouble, NULL));
3077a881295SBarry Smith   /* If using __float128 precision we still read in doubles from file */
3089860990eSLisandro Dalcin   if ((type == PETSC_REAL || type == PETSC_COMPLEX) && readdouble) {
3099860990eSLisandro Dalcin     PetscInt cnt = num * ((type == PETSC_REAL) ? 1 : 2);
3109566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(cnt, &pdouble));
3119860990eSLisandro Dalcin     p = (char *)pdouble;
3129860990eSLisandro Dalcin     typesize /= 2;
3137a881295SBarry Smith   }
3147a881295SBarry Smith #endif
3157a881295SBarry Smith 
3169860990eSLisandro Dalcin   m *= typesize;
3179860990eSLisandro Dalcin 
318e5c89e4eSSatish Balay   while (m) {
3199860990eSLisandro Dalcin     size_t len = (m < maxblock) ? m : maxblock;
3209860990eSLisandro Dalcin     int    ret = (int)read(fd, p, len);
3219860990eSLisandro Dalcin     if (ret < 0 && errno == EINTR) continue;
3229860990eSLisandro Dalcin     if (!ret && len > 0) break; /* Proxy for EOF */
323bf31d2d3SBarry Smith     PetscCheck(ret >= 0, PETSC_COMM_SELF, PETSC_ERR_FILE_READ, "Error reading from file due to \"%s\"", strerror(errno));
324ff9f933bSBarry Smith     m -= (size_t)ret;
3259860990eSLisandro Dalcin     p += ret;
326ff9f933bSBarry Smith     n += (size_t)ret;
327e5c89e4eSSatish Balay   }
32808401ef6SPierre Jolivet   PetscCheck(!m || count, PETSC_COMM_SELF, PETSC_ERR_FILE_READ, "Read past end of file");
3299860990eSLisandro Dalcin 
3306497c311SBarry Smith   num = n / typesize;                             /* Should we require `n % typesize == 0` ? */
3316497c311SBarry Smith   if (count) PetscCall(PetscIntCast(num, count)); /* TODO: This is most likely wrong for PETSC_BIT_LOGICAL */
3327a881295SBarry Smith 
3337a881295SBarry Smith #if defined(PETSC_USE_REAL___FLOAT128)
3349860990eSLisandro Dalcin   if ((type == PETSC_REAL || type == PETSC_COMPLEX) && readdouble) {
3359860990eSLisandro Dalcin     PetscInt   i, cnt = num * ((type == PETSC_REAL) ? 1 : 2);
3369860990eSLisandro Dalcin     PetscReal *preal = (PetscReal *)data;
3379566063dSJacob Faibussowitsch     if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwapDouble(pdouble, cnt));
3389860990eSLisandro Dalcin     for (i = 0; i < cnt; i++) preal[i] = pdouble[i];
3399566063dSJacob Faibussowitsch     PetscCall(PetscFree(pdouble));
3403ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
3417a881295SBarry Smith   }
3427a881295SBarry Smith #endif
3437a881295SBarry Smith 
3449566063dSJacob Faibussowitsch   if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(ptmp, type, num));
345e5c89e4eSSatish Balay 
34605acbc63SBarry Smith   if (type == PETSC_FUNCTION) {
3472d53ad75SBarry Smith #if defined(PETSC_SERIALIZE_FUNCTIONS)
3489566063dSJacob Faibussowitsch     PetscCall(PetscDLSym(NULL, fname, (void **)data));
3492d53ad75SBarry Smith #else
3509860990eSLisandro Dalcin     *(void **)data = NULL;
3512d53ad75SBarry Smith #endif
35205acbc63SBarry Smith     free(fname);
3532d53ad75SBarry Smith   }
3543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
355e5c89e4eSSatish Balay }
3569860990eSLisandro Dalcin 
357a9acdec7SBarry Smith /*@C
358e5c89e4eSSatish Balay   PetscBinaryWrite - Writes to a binary file.
359e5c89e4eSSatish Balay 
360e5c89e4eSSatish Balay   Not Collective
361e5c89e4eSSatish Balay 
362e5c89e4eSSatish Balay   Input Parameters:
363e5c89e4eSSatish Balay + fd   - the file
36421532e8aSBarry Smith . p    - the buffer, an array of the type that matches the value in `type`
365e5c89e4eSSatish Balay . n    - the number of items to write
366811af0c4SBarry Smith - type - the type of items to read (`PETSC_INT`, `PETSC_REAL` or `PETSC_SCALAR`)
367e5c89e4eSSatish Balay 
368e5c89e4eSSatish Balay   Level: advanced
369e5c89e4eSSatish Balay 
370e5c89e4eSSatish Balay   Notes:
371811af0c4SBarry Smith   `PetscBinaryWrite()` uses byte swapping to work on all machines; the files
372f253e43cSLisandro Dalcin   are written using big-endian ordering to the file. On little-endian machines the numbers
373e5c89e4eSSatish Balay   are converted to the big-endian format when they are written to disk.
37421532e8aSBarry Smith   When PETSc is configured using `./configure with --with-64-bit-indices` the integers are written to the
3757de69702SBarry Smith   file as 64-bit integers, this means they can only be read back in when the option `--with-64-bit-indices`
37654f21887SBarry Smith   is used.
377e5c89e4eSSatish Balay 
37821532e8aSBarry Smith   If running with `__float128` precision the output of `PETSC_REAL` is in `__float128` unless one uses the `-binary_write_double` option
3790da86b62SBarry Smith 
380bfbbc7b7SBarry Smith   The buffer `p` should be read-write buffer, and not static data.
381e5c89e4eSSatish Balay   This way, byte-swapping is done in-place, and then the buffer is
382e5c89e4eSSatish Balay   written to the file.
383e5c89e4eSSatish Balay 
384e5c89e4eSSatish Balay   This routine restores the original contents of the buffer, after
385e5c89e4eSSatish Balay   it is written to the file. This is done by byte-swapping in-place
386f253e43cSLisandro Dalcin   the second time.
387e5c89e4eSSatish Balay 
388300a7f5bSBarry Smith   Because byte-swapping may be done on the values in data it cannot be declared const
389300a7f5bSBarry Smith 
390cc4c1da9SBarry Smith   Fortran Note:
391cc4c1da9SBarry Smith   There are different functions for each datatype, for example `PetscBinaryWriteInt()`
392cc4c1da9SBarry Smith 
393db781477SPatrick Sanan .seealso: `PetscBinaryRead()`, `PetscBinaryOpen()`, `PetscBinaryClose()`, `PetscViewerBinaryGetDescriptor()`, `PetscBinarySynchronizedWrite()`,
394db781477SPatrick Sanan           `PetscBinarySynchronizedRead()`, `PetscBinarySynchronizedSeek()`
395e5c89e4eSSatish Balay @*/
3966497c311SBarry Smith PetscErrorCode PetscBinaryWrite(int fd, const void *p, PetscCount n, PetscDataType type)
397d71ae5a4SJacob Faibussowitsch {
398f253e43cSLisandro Dalcin   const char  *pp = (char *)p;
3996497c311SBarry Smith   size_t       err, m = (size_t)n, wsize;
4006497c311SBarry Smith   const size_t maxblock = 65536;
401f253e43cSLisandro Dalcin   const void  *ptmp     = p;
40205acbc63SBarry Smith   char        *fname    = NULL;
4030da86b62SBarry Smith #if defined(PETSC_USE_REAL___FLOAT128)
404df40af56SBarry Smith   PetscBool  writedouble = PETSC_FALSE;
4050da86b62SBarry Smith   double    *ppp;
4060da86b62SBarry Smith   PetscReal *pv;
4070da86b62SBarry Smith #endif
40841f502e3SPatrick Sanan   PetscDataType wtype = type;
409e5c89e4eSSatish Balay 
410e5c89e4eSSatish Balay   PetscFunctionBegin;
4116497c311SBarry Smith   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to write a negative amount of data %" PetscCount_FMT, n);
4123ba16761SJacob Faibussowitsch   if (!n) PetscFunctionReturn(PETSC_SUCCESS);
413e5c89e4eSSatish Balay 
4142d53ad75SBarry Smith   if (type == PETSC_FUNCTION) {
4152d53ad75SBarry Smith #if defined(PETSC_SERIALIZE_FUNCTIONS)
4162d53ad75SBarry Smith     const char *fnametmp;
4172d53ad75SBarry Smith #endif
4182d53ad75SBarry Smith     m     = 64;
419e25ab156SSatish Balay     fname = (char *)malloc(m * sizeof(char));
42028b400f6SJacob Faibussowitsch     PetscCheck(fname, PETSC_COMM_SELF, PETSC_ERR_MEM, "Cannot allocate space for function name");
42105acbc63SBarry Smith #if defined(PETSC_SERIALIZE_FUNCTIONS)
42208401ef6SPierre Jolivet     PetscCheck(n <= 1, PETSC_COMM_SELF, PETSC_ERR_SUP, "Can only binary view a single function at a time");
4239566063dSJacob Faibussowitsch     PetscCall(PetscFPTFind(*(void **)p, &fnametmp));
4249566063dSJacob Faibussowitsch     PetscCall(PetscStrncpy(fname, fnametmp, m));
42505acbc63SBarry Smith #else
4269566063dSJacob Faibussowitsch     PetscCall(PetscStrncpy(fname, "", m));
42705acbc63SBarry Smith #endif
42801963f56SBarry Smith     wtype = PETSC_CHAR;
4292d53ad75SBarry Smith     pp    = (char *)fname;
4302d53ad75SBarry Smith     ptmp  = (void *)fname;
4312d53ad75SBarry Smith   }
4322d53ad75SBarry Smith 
4330da86b62SBarry Smith #if defined(PETSC_USE_REAL___FLOAT128)
4349566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(NULL, NULL, "-binary_write_double", &writedouble, NULL));
4350da86b62SBarry Smith   /* If using __float128 precision we still write in doubles to file */
436501ae109SJose E. Roman   if ((type == PETSC_SCALAR || type == PETSC_REAL || type == PETSC_COMPLEX) && writedouble) {
43741f502e3SPatrick Sanan     wtype = PETSC_DOUBLE;
4389566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(n, &ppp));
4390da86b62SBarry Smith     pv = (PetscReal *)pp;
4406497c311SBarry Smith     for (PetscCount i = 0; i < n; i++) ppp[i] = (double)pv[i];
4410da86b62SBarry Smith     pp   = (char *)ppp;
4420da86b62SBarry Smith     ptmp = (char *)ppp;
4430da86b62SBarry Smith   }
4440da86b62SBarry Smith #endif
4450da86b62SBarry Smith 
44641f502e3SPatrick Sanan   if (wtype == PETSC_INT) m *= sizeof(PetscInt);
44741f502e3SPatrick Sanan   else if (wtype == PETSC_SCALAR) m *= sizeof(PetscScalar);
448501ae109SJose E. Roman #if defined(PETSC_HAVE_COMPLEX)
449501ae109SJose E. Roman   else if (wtype == PETSC_COMPLEX) m *= sizeof(PetscComplex);
450501ae109SJose E. Roman #endif
4514caf0332SSatish Balay   else if (wtype == PETSC_REAL) m *= sizeof(PetscReal);
45241f502e3SPatrick Sanan   else if (wtype == PETSC_DOUBLE) m *= sizeof(double);
45341f502e3SPatrick Sanan   else if (wtype == PETSC_FLOAT) m *= sizeof(float);
45441f502e3SPatrick Sanan   else if (wtype == PETSC_SHORT) m *= sizeof(short);
455972064b6SLisandro Dalcin   else if (wtype == PETSC_LONG) m *= sizeof(long);
45641f502e3SPatrick Sanan   else if (wtype == PETSC_CHAR) m *= sizeof(char);
45741f502e3SPatrick Sanan   else if (wtype == PETSC_ENUM) m *= sizeof(PetscEnum);
45841f502e3SPatrick Sanan   else if (wtype == PETSC_BOOL) m *= sizeof(PetscBool);
4599e3e4c22SLisandro Dalcin   else if (wtype == PETSC_INT64) m *= sizeof(PetscInt64);
4603321ca25SJames Wright   else if (wtype == PETSC_INT32) m *= sizeof(PetscInt32);
46141f502e3SPatrick Sanan   else if (wtype == PETSC_BIT_LOGICAL) m = PetscBTLength(m) * sizeof(char);
4623321ca25SJames Wright   else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Unknown type: %d", wtype);
463e5c89e4eSSatish Balay 
4649566063dSJacob Faibussowitsch   if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap((void *)ptmp, wtype, n));
465e5c89e4eSSatish Balay 
466e5c89e4eSSatish Balay   while (m) {
467e5c89e4eSSatish Balay     wsize = (m < maxblock) ? m : maxblock;
4686497c311SBarry Smith     err   = (size_t)write(fd, pp, wsize);
469*5607bdc5SPierre Jolivet     if (errno == EINTR) continue;
470bf31d2d3SBarry Smith     PetscCheck(err == wsize, PETSC_COMM_SELF, PETSC_ERR_FILE_WRITE, "Error writing to file total size %d err %d wsize %d due to \"%s\"", (int)n, (int)err, (int)wsize, strerror(errno));
471e5c89e4eSSatish Balay     m -= wsize;
472e5c89e4eSSatish Balay     pp += wsize;
473e5c89e4eSSatish Balay   }
474e5c89e4eSSatish Balay 
4759566063dSJacob Faibussowitsch   if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap((void *)ptmp, wtype, n));
476f253e43cSLisandro Dalcin 
477ad540459SPierre Jolivet   if (type == PETSC_FUNCTION) free(fname);
4780da86b62SBarry Smith #if defined(PETSC_USE_REAL___FLOAT128)
47948a46eb9SPierre Jolivet   if ((type == PETSC_SCALAR || type == PETSC_REAL || type == PETSC_COMPLEX) && writedouble) PetscCall(PetscFree(ppp));
4800da86b62SBarry Smith #endif
4813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
482e5c89e4eSSatish Balay }
483e5c89e4eSSatish Balay 
484cc4c1da9SBarry Smith /*@
485e5c89e4eSSatish Balay   PetscBinaryOpen - Opens a PETSc binary file.
486e5c89e4eSSatish Balay 
487e5c89e4eSSatish Balay   Not Collective
488e5c89e4eSSatish Balay 
489e5c89e4eSSatish Balay   Input Parameters:
490e5c89e4eSSatish Balay + name - filename
491fe8e7dddSPierre Jolivet - mode - open mode of binary file, one of `FILE_MODE_READ`, `FILE_MODE_WRITE`, `FILE_MODE_APPEND`
492e5c89e4eSSatish Balay 
493e5c89e4eSSatish Balay   Output Parameter:
494e5c89e4eSSatish Balay . fd - the file
495e5c89e4eSSatish Balay 
496e5c89e4eSSatish Balay   Level: advanced
497e5c89e4eSSatish Balay 
498db781477SPatrick Sanan .seealso: `PetscBinaryRead()`, `PetscBinaryWrite()`, `PetscFileMode`, `PetscViewerFileSetMode()`, `PetscViewerBinaryGetDescriptor()`,
499db781477SPatrick Sanan           `PetscBinarySynchronizedWrite()`, `PetscBinarySynchronizedRead()`, `PetscBinarySynchronizedSeek()`
500e5c89e4eSSatish Balay @*/
501d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscBinaryOpen(const char name[], PetscFileMode mode, int *fd)
502d71ae5a4SJacob Faibussowitsch {
503e5c89e4eSSatish Balay   PetscFunctionBegin;
504cc843e7aSLisandro Dalcin   switch (mode) {
505d71ae5a4SJacob Faibussowitsch   case FILE_MODE_READ:
506d71ae5a4SJacob Faibussowitsch     *fd = open(name, O_BINARY | O_RDONLY, 0);
507d71ae5a4SJacob Faibussowitsch     break;
508d71ae5a4SJacob Faibussowitsch   case FILE_MODE_WRITE:
509d71ae5a4SJacob Faibussowitsch     *fd = open(name, O_BINARY | O_WRONLY | O_CREAT | O_TRUNC, 0666);
510d71ae5a4SJacob Faibussowitsch     break;
511d71ae5a4SJacob Faibussowitsch   case FILE_MODE_APPEND:
512d71ae5a4SJacob Faibussowitsch     *fd = open(name, O_BINARY | O_WRONLY | O_APPEND, 0);
513d71ae5a4SJacob Faibussowitsch     break;
514d71ae5a4SJacob Faibussowitsch   default:
515d71ae5a4SJacob Faibussowitsch     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Unsupported file mode %s", PetscFileModes[mode]);
516e5c89e4eSSatish Balay   }
517bf31d2d3SBarry Smith   PetscCheck(*fd != -1, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Cannot open file %s for %s due to \"%s\"", name, PetscFileModes[mode], strerror(errno));
5183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
519e5c89e4eSSatish Balay }
520e5c89e4eSSatish Balay 
521e30d2299SSatish Balay /*@
522e5c89e4eSSatish Balay   PetscBinaryClose - Closes a PETSc binary file.
523e5c89e4eSSatish Balay 
524e5c89e4eSSatish Balay   Not Collective
525e5c89e4eSSatish Balay 
526e5c89e4eSSatish Balay   Output Parameter:
527e5c89e4eSSatish Balay . fd - the file
528e5c89e4eSSatish Balay 
529e5c89e4eSSatish Balay   Level: advanced
530e5c89e4eSSatish Balay 
531db781477SPatrick Sanan .seealso: `PetscBinaryRead()`, `PetscBinaryWrite()`, `PetscBinaryOpen()`, `PetscBinarySynchronizedWrite()`, `PetscBinarySynchronizedRead()`,
532db781477SPatrick Sanan           `PetscBinarySynchronizedSeek()`
533e5c89e4eSSatish Balay @*/
534d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscBinaryClose(int fd)
535d71ae5a4SJacob Faibussowitsch {
536e5c89e4eSSatish Balay   PetscFunctionBegin;
537cc73adaaSBarry Smith   PetscCheck(!close(fd), PETSC_COMM_SELF, PETSC_ERR_SYS, "close() failed on file descriptor");
5383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
539e5c89e4eSSatish Balay }
540e5c89e4eSSatish Balay 
541e8976759SBarry Smith /*@C
542e5c89e4eSSatish Balay   PetscBinarySeek - Moves the file pointer on a PETSc binary file.
543e5c89e4eSSatish Balay 
544cc4c1da9SBarry Smith   Not Collective, No Fortran Support
545e5c89e4eSSatish Balay 
546e5c89e4eSSatish Balay   Input Parameters:
547e5c89e4eSSatish Balay + fd     - the file
548811af0c4SBarry Smith . off    - number of bytes to move. Use `PETSC_BINARY_INT_SIZE`, `PETSC_BINARY_SCALAR_SIZE`,
54921532e8aSBarry Smith            etc. in your calculation rather than `sizeof()` to compute byte lengths.
55016a05f60SBarry Smith - whence - see `PetscBinarySeekType` for possible values
551e5c89e4eSSatish Balay 
552e5c89e4eSSatish Balay   Output Parameter:
553e5c89e4eSSatish Balay . offset - new offset in file
554e5c89e4eSSatish Balay 
555e5c89e4eSSatish Balay   Level: developer
556e5c89e4eSSatish Balay 
55716a05f60SBarry Smith .seealso: `PetscBinaryRead()`, `PetscBinarySeekType`, `PetscBinaryWrite()`, `PetscBinaryOpen()`, `PetscBinarySynchronizedWrite()`, `PetscBinarySynchronizedRead()`,
558db781477SPatrick Sanan           `PetscBinarySynchronizedSeek()`
559e5c89e4eSSatish Balay @*/
560d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscBinarySeek(int fd, off_t off, PetscBinarySeekType whence, off_t *offset)
561d71ae5a4SJacob Faibussowitsch {
562e5c89e4eSSatish Balay   int iwhence = 0;
563e5c89e4eSSatish Balay 
564e5c89e4eSSatish Balay   PetscFunctionBegin;
565a297a907SKarl Rupp   if (whence == PETSC_BINARY_SEEK_SET) iwhence = SEEK_SET;
566a297a907SKarl Rupp   else if (whence == PETSC_BINARY_SEEK_CUR) iwhence = SEEK_CUR;
567a297a907SKarl Rupp   else if (whence == PETSC_BINARY_SEEK_END) iwhence = SEEK_END;
568a297a907SKarl Rupp   else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Unknown seek location");
569e5c89e4eSSatish Balay #if defined(PETSC_HAVE_LSEEK)
570e5c89e4eSSatish Balay   *offset = lseek(fd, off, iwhence);
571e5c89e4eSSatish Balay #elif defined(PETSC_HAVE__LSEEK)
572e5c89e4eSSatish Balay   *offset = _lseek(fd, (long)off, iwhence);
573e5c89e4eSSatish Balay #else
574e32f2f54SBarry Smith   SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP_SYS, "System does not have a way of seeking on a file");
575e5c89e4eSSatish Balay #endif
5763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
577e5c89e4eSSatish Balay }
578e5c89e4eSSatish Balay 
579e5c89e4eSSatish Balay /*@C
58021532e8aSBarry Smith   PetscBinarySynchronizedRead - Reads from a binary file, all MPI processes get the same values
581e5c89e4eSSatish Balay 
582cc4c1da9SBarry Smith   Collective, No Fortran Support
583e5c89e4eSSatish Balay 
584e5c89e4eSSatish Balay   Input Parameters:
585e5c89e4eSSatish Balay + comm - the MPI communicator
5869860990eSLisandro Dalcin . fd   - the file descriptor
5879860990eSLisandro Dalcin . num  - the maximum number of items to read
588811af0c4SBarry Smith - type - the type of items to read (`PETSC_INT`, `PETSC_REAL`, `PETSC_SCALAR`, etc.)
589e5c89e4eSSatish Balay 
590e5c89e4eSSatish Balay   Output Parameters:
59121532e8aSBarry Smith + data  - the buffer, an array of the type that matches the value in `type`
5929860990eSLisandro Dalcin - count - the number of items read, optional
593e5c89e4eSSatish Balay 
594e5c89e4eSSatish Balay   Level: developer
595e5c89e4eSSatish Balay 
596e5c89e4eSSatish Balay   Notes:
597811af0c4SBarry Smith   Does a `PetscBinaryRead()` followed by an `MPI_Bcast()`
598e5c89e4eSSatish Balay 
59921532e8aSBarry Smith   If `count` is not provided and the number of items read is less than
6009860990eSLisandro Dalcin   the maximum number of items to read, then this routine errors.
6019860990eSLisandro Dalcin 
602811af0c4SBarry Smith   `PetscBinarySynchronizedRead()` uses byte swapping to work on all machines.
60321532e8aSBarry Smith   The files  are written using big-endian ordering to the file. On little-endian machines the numbers
60421532e8aSBarry Smith   are converted to the big-endian format when they are written to disk.
60521532e8aSBarry Smith   When PETSc is configured using `./configure with --with-64-bit-indices` the integers are written to the
6067de69702SBarry Smith   file as 64-bit integers, this means they can only be read back in when the option `--with-64-bit-indices`
60721532e8aSBarry Smith   is used.
608e5c89e4eSSatish Balay 
609db781477SPatrick Sanan .seealso: `PetscBinaryWrite()`, `PetscBinaryOpen()`, `PetscBinaryClose()`, `PetscBinaryRead()`, `PetscBinarySynchronizedWrite()`,
610db781477SPatrick Sanan           `PetscBinarySynchronizedSeek()`
611e5c89e4eSSatish Balay @*/
612d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscBinarySynchronizedRead(MPI_Comm comm, int fd, void *data, PetscInt num, PetscInt *count, PetscDataType type)
613d71ae5a4SJacob Faibussowitsch {
6148b8bf82cSBarry Smith   PetscMPIInt  rank, size;
615e5c89e4eSSatish Balay   MPI_Datatype mtype;
6169860990eSLisandro Dalcin   PetscInt     ibuf[2] = {0, 0};
61705acbc63SBarry Smith   char        *fname   = NULL;
6189860990eSLisandro Dalcin   void        *fptr    = NULL;
619e5c89e4eSSatish Balay 
620e5c89e4eSSatish Balay   PetscFunctionBegin;
6212d53ad75SBarry Smith   if (type == PETSC_FUNCTION) {
6229860990eSLisandro Dalcin     num   = 64;
6232d53ad75SBarry Smith     type  = PETSC_CHAR;
6249860990eSLisandro Dalcin     fname = (char *)malloc(num * sizeof(char));
6259860990eSLisandro Dalcin     fptr  = data;
6269860990eSLisandro Dalcin     data  = (void *)fname;
62728b400f6SJacob Faibussowitsch     PetscCheck(fname, PETSC_COMM_SELF, PETSC_ERR_MEM, "Cannot allocate space for function name");
6282d53ad75SBarry Smith   }
6292d53ad75SBarry Smith 
6309566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
6319566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
63280bff17dSBarry Smith   if (rank == 0) ibuf[0] = (PetscInt)PetscBinaryRead(fd, data, num, count ? &ibuf[1] : NULL, type);
6339566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Bcast(ibuf, 2, MPIU_INT, 0, comm));
6349566063dSJacob Faibussowitsch   PetscCall((PetscErrorCode)ibuf[0]);
6358b8bf82cSBarry Smith 
6368b8bf82cSBarry Smith   /* skip MPI call on potentially huge amounts of data when running with one process; this allows the amount of data to basically unlimited in that case */
6378b8bf82cSBarry Smith   if (size > 1) {
6386497c311SBarry Smith     PetscMPIInt cnt;
6396497c311SBarry Smith 
6406497c311SBarry Smith     PetscCall(PetscMPIIntCast(count ? ibuf[1] : num, &cnt));
6419566063dSJacob Faibussowitsch     PetscCall(PetscDataTypeToMPIDataType(type, &mtype));
6426497c311SBarry Smith     PetscCallMPI(MPI_Bcast(data, cnt, mtype, 0, comm));
6438b8bf82cSBarry Smith   }
6449860990eSLisandro Dalcin   if (count) *count = ibuf[1];
6452d53ad75SBarry Smith 
646e366c363SBarry Smith   if (type == PETSC_FUNCTION) {
6472d53ad75SBarry Smith #if defined(PETSC_SERIALIZE_FUNCTIONS)
6489566063dSJacob Faibussowitsch     PetscCall(PetscDLLibrarySym(PETSC_COMM_SELF, &PetscDLLibrariesLoaded, NULL, fname, (void **)fptr));
6492d53ad75SBarry Smith #else
6509860990eSLisandro Dalcin     *(void **)fptr = NULL;
6512d53ad75SBarry Smith #endif
652e366c363SBarry Smith     free(fname);
6532d53ad75SBarry Smith   }
6543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
655e5c89e4eSSatish Balay }
656e5c89e4eSSatish Balay 
657e5c89e4eSSatish Balay /*@C
6581d280d73SBarry Smith   PetscBinarySynchronizedWrite - writes to a binary file.
659e5c89e4eSSatish Balay 
660cc4c1da9SBarry Smith   Collective, No Fortran Support
661e5c89e4eSSatish Balay 
662e5c89e4eSSatish Balay   Input Parameters:
663e5c89e4eSSatish Balay + comm - the MPI communicator
664e5c89e4eSSatish Balay . fd   - the file
665e5c89e4eSSatish Balay . n    - the number of items to write
66621532e8aSBarry Smith . p    - the buffer, an array of the type that matches the value in `type`
667811af0c4SBarry Smith - type - the type of items to write (`PETSC_INT`, `PETSC_REAL` or `PETSC_SCALAR`)
668e5c89e4eSSatish Balay 
669e5c89e4eSSatish Balay   Level: developer
670e5c89e4eSSatish Balay 
671e5c89e4eSSatish Balay   Notes:
67221532e8aSBarry Smith   MPI rank 0 does a `PetscBinaryWrite()` the values on other MPI processes are not used
673e5c89e4eSSatish Balay 
67421532e8aSBarry Smith   The files  are written using big-endian ordering to the file. On little-endian machines the numbers
67521532e8aSBarry Smith   are converted to the big-endian format when they are written to disk.
67621532e8aSBarry Smith   When PETSc is configured using `./configure with --with-64-bit-indices` the integers are written to the
6777de69702SBarry Smith   file as 64-bit integers, this means they can only be read back in when the option `--with-64-bit-indices`
67821532e8aSBarry Smith   is used.
679e5c89e4eSSatish Balay 
680811af0c4SBarry Smith   Because byte-swapping may be done on the values in data it cannot be declared const
681300a7f5bSBarry Smith 
682bfbbc7b7SBarry Smith   This is NOT like `PetscSynchronizedFPrintf()`! This routine ignores calls on all but MPI rank 0,
68321532e8aSBarry Smith   while `PetscSynchronizedFPrintf()` has all MPI processes print their strings in order.
6841d280d73SBarry Smith 
685db781477SPatrick Sanan .seealso: `PetscBinaryWrite()`, `PetscBinaryOpen()`, `PetscBinaryClose()`, `PetscBinaryRead()`, `PetscBinarySynchronizedRead()`,
686db781477SPatrick Sanan           `PetscBinarySynchronizedSeek()`
687e5c89e4eSSatish Balay @*/
688d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscBinarySynchronizedWrite(MPI_Comm comm, int fd, const void *p, PetscInt n, PetscDataType type)
689d71ae5a4SJacob Faibussowitsch {
690e5c89e4eSSatish Balay   PetscMPIInt rank;
691e5c89e4eSSatish Balay 
692e5c89e4eSSatish Balay   PetscFunctionBegin;
6939566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
69448a46eb9SPierre Jolivet   if (rank == 0) PetscCall(PetscBinaryWrite(fd, p, n, type));
6953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
696e5c89e4eSSatish Balay }
697e5c89e4eSSatish Balay 
698e5c89e4eSSatish Balay /*@C
6991d280d73SBarry Smith   PetscBinarySynchronizedSeek - Moves the file pointer on a PETSc binary file.
700e5c89e4eSSatish Balay 
701cc4c1da9SBarry Smith   No Fortran Support
702cc4c1da9SBarry Smith 
703e5c89e4eSSatish Balay   Input Parameters:
70410450e9eSJacob Faibussowitsch + comm   - the communicator to read with
70510450e9eSJacob Faibussowitsch . fd     - the file
70616a05f60SBarry Smith . whence - see `PetscBinarySeekType` for possible values
707811af0c4SBarry Smith - off    - number of bytes to move. Use `PETSC_BINARY_INT_SIZE`, `PETSC_BINARY_SCALAR_SIZE`,
708811af0c4SBarry Smith             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 
71516a05f60SBarry Smith .seealso: `PetscBinaryRead()`, `PetscBinarySeekType`, `PetscBinaryWrite()`, `PetscBinaryOpen()`, `PetscBinarySynchronizedWrite()`, `PetscBinarySynchronizedRead()`,
71642747ad1SJacob Faibussowitsch 
717e5c89e4eSSatish Balay @*/
718d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscBinarySynchronizedSeek(MPI_Comm comm, int fd, off_t off, PetscBinarySeekType whence, off_t *offset)
719d71ae5a4SJacob Faibussowitsch {
720e5c89e4eSSatish Balay   PetscMPIInt rank;
721e5c89e4eSSatish Balay 
722e5c89e4eSSatish Balay   PetscFunctionBegin;
7239566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
72448a46eb9SPierre Jolivet   if (rank == 0) PetscCall(PetscBinarySeek(fd, off, whence, offset));
7253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
726e5c89e4eSSatish Balay }
727e5c89e4eSSatish Balay 
7280fc9d207SBarry Smith #if defined(PETSC_HAVE_MPIIO)
729e39fd77fSBarry Smith 
730951e3c8eSBarry Smith   #if defined(PETSC_USE_PETSC_MPI_EXTERNAL32)
731e39fd77fSBarry Smith /*
732e39fd77fSBarry Smith       MPICH does not provide the external32 representation for MPI_File_set_view() so we need to provide the functions.
733e39fd77fSBarry Smith     These are set into MPI in PetscInitialize() via MPI_Register_datarep()
734e39fd77fSBarry Smith 
735e39fd77fSBarry Smith     Note I use PetscMPIInt for the MPI error codes since that is what MPI uses (instead of the standard PetscErrorCode)
736e39fd77fSBarry Smith 
737951e3c8eSBarry Smith     The next three routines are not used because MPICH does not support their use
738e39fd77fSBarry Smith 
739e39fd77fSBarry Smith */
740d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscMPIInt PetscDataRep_extent_fn(MPI_Datatype datatype, MPI_Aint *file_extent, void *extra_state)
741d71ae5a4SJacob Faibussowitsch {
742e39fd77fSBarry Smith   MPI_Aint    ub;
743e39fd77fSBarry Smith   PetscMPIInt ierr;
744e39fd77fSBarry Smith 
745e39fd77fSBarry Smith   ierr = MPI_Type_get_extent(datatype, &ub, file_extent);
746e39fd77fSBarry Smith   return ierr;
747e39fd77fSBarry Smith }
748e39fd77fSBarry Smith 
749d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscMPIInt PetscDataRep_read_conv_fn(void *userbuf, MPI_Datatype datatype, PetscMPIInt count, void *filebuf, MPI_Offset position, void *extra_state)
750d71ae5a4SJacob Faibussowitsch {
751e39fd77fSBarry Smith   PetscDataType pdtype;
752e39fd77fSBarry Smith   PetscMPIInt   ierr;
753e39fd77fSBarry Smith   size_t        dsize;
754e39fd77fSBarry Smith 
7559566063dSJacob Faibussowitsch   PetscCall(PetscMPIDataTypeToPetscDataType(datatype, &pdtype));
7569566063dSJacob Faibussowitsch   PetscCall(PetscDataTypeGetSize(pdtype, &dsize));
757e39fd77fSBarry Smith 
758e39fd77fSBarry Smith   /* offset is given in units of MPI_Datatype */
759e39fd77fSBarry Smith   userbuf = ((char *)userbuf) + dsize * position;
760e39fd77fSBarry Smith 
7619566063dSJacob Faibussowitsch   PetscCall(PetscMemcpy(userbuf, filebuf, count * dsize));
7629566063dSJacob Faibussowitsch   if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(userbuf, pdtype, count));
763e39fd77fSBarry Smith   return ierr;
764e39fd77fSBarry Smith }
765e39fd77fSBarry Smith 
766d71ae5a4SJacob Faibussowitsch PetscMPIInt PetscDataRep_write_conv_fn(void *userbuf, MPI_Datatype datatype, PetscMPIInt count, void *filebuf, MPI_Offset position, void *extra_state)
767d71ae5a4SJacob Faibussowitsch {
768e39fd77fSBarry Smith   PetscDataType pdtype;
769e39fd77fSBarry Smith   PetscMPIInt   ierr;
770e39fd77fSBarry Smith   size_t        dsize;
771e39fd77fSBarry Smith 
7729566063dSJacob Faibussowitsch   PetscCall(PetscMPIDataTypeToPetscDataType(datatype, &pdtype));
7739566063dSJacob Faibussowitsch   PetscCall(PetscDataTypeGetSize(pdtype, &dsize));
774e39fd77fSBarry Smith 
775e39fd77fSBarry Smith   /* offset is given in units of MPI_Datatype */
776e39fd77fSBarry Smith   userbuf = ((char *)userbuf) + dsize * position;
777e39fd77fSBarry Smith 
7789566063dSJacob Faibussowitsch   PetscCall(PetscMemcpy(filebuf, userbuf, count * dsize));
7799566063dSJacob Faibussowitsch   if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(filebuf, pdtype, count));
780e39fd77fSBarry Smith   return ierr;
781e39fd77fSBarry Smith }
782951e3c8eSBarry Smith   #endif
783e39fd77fSBarry Smith 
784d71ae5a4SJacob Faibussowitsch PetscErrorCode MPIU_File_write_all(MPI_File fd, void *data, PetscMPIInt cnt, MPI_Datatype dtype, MPI_Status *status)
785d71ae5a4SJacob Faibussowitsch {
786e39fd77fSBarry Smith   PetscDataType pdtype;
78730815ce0SLisandro Dalcin 
788e39fd77fSBarry Smith   PetscFunctionBegin;
7899566063dSJacob Faibussowitsch   PetscCall(PetscMPIDataTypeToPetscDataType(dtype, &pdtype));
7909566063dSJacob Faibussowitsch   if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(data, pdtype, cnt));
7919566063dSJacob Faibussowitsch   PetscCallMPI(MPI_File_write_all(fd, data, cnt, dtype, status));
7929566063dSJacob Faibussowitsch   if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(data, pdtype, cnt));
7933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
794e39fd77fSBarry Smith }
795e39fd77fSBarry Smith 
796d71ae5a4SJacob Faibussowitsch PetscErrorCode MPIU_File_read_all(MPI_File fd, void *data, PetscMPIInt cnt, MPI_Datatype dtype, MPI_Status *status)
797d71ae5a4SJacob Faibussowitsch {
798e39fd77fSBarry Smith   PetscDataType pdtype;
799e39fd77fSBarry Smith 
800e39fd77fSBarry Smith   PetscFunctionBegin;
8019566063dSJacob Faibussowitsch   PetscCall(PetscMPIDataTypeToPetscDataType(dtype, &pdtype));
8029566063dSJacob Faibussowitsch   PetscCallMPI(MPI_File_read_all(fd, data, cnt, dtype, status));
8039566063dSJacob Faibussowitsch   if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(data, pdtype, cnt));
8043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
805e39fd77fSBarry Smith }
80630815ce0SLisandro Dalcin 
807d71ae5a4SJacob Faibussowitsch PetscErrorCode MPIU_File_write_at(MPI_File fd, MPI_Offset off, void *data, PetscMPIInt cnt, MPI_Datatype dtype, MPI_Status *status)
808d71ae5a4SJacob Faibussowitsch {
809c4e82887SLisandro Dalcin   PetscDataType pdtype;
810c4e82887SLisandro Dalcin 
811c4e82887SLisandro Dalcin   PetscFunctionBegin;
8129566063dSJacob Faibussowitsch   PetscCall(PetscMPIDataTypeToPetscDataType(dtype, &pdtype));
8139566063dSJacob Faibussowitsch   if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(data, pdtype, cnt));
8149566063dSJacob Faibussowitsch   PetscCallMPI(MPI_File_write_at(fd, off, data, cnt, dtype, status));
8159566063dSJacob Faibussowitsch   if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(data, pdtype, cnt));
8163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
817c4e82887SLisandro Dalcin }
818c4e82887SLisandro Dalcin 
819d71ae5a4SJacob Faibussowitsch PetscErrorCode MPIU_File_read_at(MPI_File fd, MPI_Offset off, void *data, PetscMPIInt cnt, MPI_Datatype dtype, MPI_Status *status)
820d71ae5a4SJacob Faibussowitsch {
821c4e82887SLisandro Dalcin   PetscDataType pdtype;
822c4e82887SLisandro Dalcin 
823c4e82887SLisandro Dalcin   PetscFunctionBegin;
8249566063dSJacob Faibussowitsch   PetscCall(PetscMPIDataTypeToPetscDataType(dtype, &pdtype));
8259566063dSJacob Faibussowitsch   PetscCallMPI(MPI_File_read_at(fd, off, data, cnt, dtype, status));
8269566063dSJacob Faibussowitsch   if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(data, pdtype, cnt));
8273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
828c4e82887SLisandro Dalcin }
829c4e82887SLisandro Dalcin 
830d71ae5a4SJacob Faibussowitsch PetscErrorCode MPIU_File_write_at_all(MPI_File fd, MPI_Offset off, void *data, PetscMPIInt cnt, MPI_Datatype dtype, MPI_Status *status)
831d71ae5a4SJacob Faibussowitsch {
832c4e82887SLisandro Dalcin   PetscDataType pdtype;
833c4e82887SLisandro Dalcin 
834c4e82887SLisandro Dalcin   PetscFunctionBegin;
8359566063dSJacob Faibussowitsch   PetscCall(PetscMPIDataTypeToPetscDataType(dtype, &pdtype));
8369566063dSJacob Faibussowitsch   if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(data, pdtype, cnt));
8379566063dSJacob Faibussowitsch   PetscCallMPI(MPI_File_write_at_all(fd, off, data, cnt, dtype, status));
8389566063dSJacob Faibussowitsch   if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(data, pdtype, cnt));
8393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
840c4e82887SLisandro Dalcin }
841c4e82887SLisandro Dalcin 
842d71ae5a4SJacob Faibussowitsch PetscErrorCode MPIU_File_read_at_all(MPI_File fd, MPI_Offset off, void *data, PetscMPIInt cnt, MPI_Datatype dtype, MPI_Status *status)
843d71ae5a4SJacob Faibussowitsch {
844c4e82887SLisandro Dalcin   PetscDataType pdtype;
845c4e82887SLisandro Dalcin 
846c4e82887SLisandro Dalcin   PetscFunctionBegin;
8479566063dSJacob Faibussowitsch   PetscCall(PetscMPIDataTypeToPetscDataType(dtype, &pdtype));
8489566063dSJacob Faibussowitsch   PetscCallMPI(MPI_File_read_at_all(fd, off, data, cnt, dtype, status));
8499566063dSJacob Faibussowitsch   if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(data, pdtype, cnt));
8503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
851c4e82887SLisandro Dalcin }
852c4e82887SLisandro Dalcin 
853951e3c8eSBarry Smith #endif
854