xref: /petsc/src/sys/fileio/sysio.c (revision fe8e7ddd93caa3d7f6fe6c2e358c1c3f5a39763e)
1e5c89e4eSSatish Balay /*
2e5c89e4eSSatish Balay    This file contains simple binary read/write routines.
3e5c89e4eSSatish Balay  */
4e5c89e4eSSatish Balay 
5c6db04a5SJed Brown #include <petscsys.h>
6cc843e7aSLisandro Dalcin #include <petscbt.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
15cc843e7aSLisandro Dalcin #if !defined(PETSC_HAVE_O_BINARY)
16cc843e7aSLisandro Dalcin   #define O_BINARY 0
17cc843e7aSLisandro Dalcin #endif
18e5c89e4eSSatish Balay 
1902c9f0b5SLisandro Dalcin const char *const PetscFileModes[] = {"READ", "WRITE", "APPEND", "UPDATE", "APPEND_UPDATE", "PetscFileMode", "PETSC_FILE_", NULL};
20d6a4318aSJed Brown 
21e5c89e4eSSatish Balay /*
226de02169SBarry Smith   PetscByteSwapEnum - Swap bytes in a  PETSc Enum
23e5c89e4eSSatish Balay 
24e5c89e4eSSatish Balay */
2566976f2fSJacob Faibussowitsch static PetscErrorCode PetscByteSwapEnum(PetscEnum *buff, PetscInt n)
26d71ae5a4SJacob Faibussowitsch {
276de02169SBarry Smith   PetscInt  i, j;
280b20345dSBarry Smith   PetscEnum tmp = ENUM_DUMMY;
29e0890e22SSatish Balay   char     *ptr1, *ptr2 = (char *)&tmp;
30e5c89e4eSSatish Balay 
31e5c89e4eSSatish Balay   PetscFunctionBegin;
32e5c89e4eSSatish Balay   for (j = 0; j < n; j++) {
33e5c89e4eSSatish Balay     ptr1 = (char *)(buff + j);
34a297a907SKarl Rupp     for (i = 0; i < (PetscInt)sizeof(PetscEnum); i++) ptr2[i] = ptr1[sizeof(PetscEnum) - 1 - i];
35a297a907SKarl Rupp     for (i = 0; i < (PetscInt)sizeof(PetscEnum); i++) ptr1[i] = ptr2[i];
36e5c89e4eSSatish Balay   }
373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
38e5c89e4eSSatish Balay }
396de02169SBarry Smith 
406de02169SBarry Smith /*
41acfcf0e5SJed Brown   PetscByteSwapBool - Swap bytes in a  PETSc Bool
426de02169SBarry Smith 
436de02169SBarry Smith */
4466976f2fSJacob Faibussowitsch static PetscErrorCode PetscByteSwapBool(PetscBool *buff, PetscInt n)
45d71ae5a4SJacob Faibussowitsch {
466de02169SBarry Smith   PetscInt  i, j;
47ace3abfcSBarry Smith   PetscBool tmp = PETSC_FALSE;
48e0890e22SSatish Balay   char     *ptr1, *ptr2 = (char *)&tmp;
496de02169SBarry Smith 
506de02169SBarry Smith   PetscFunctionBegin;
516de02169SBarry Smith   for (j = 0; j < n; j++) {
526de02169SBarry Smith     ptr1 = (char *)(buff + j);
53a297a907SKarl Rupp     for (i = 0; i < (PetscInt)sizeof(PetscBool); i++) ptr2[i] = ptr1[sizeof(PetscBool) - 1 - i];
54a297a907SKarl Rupp     for (i = 0; i < (PetscInt)sizeof(PetscBool); i++) ptr1[i] = ptr2[i];
556de02169SBarry Smith   }
563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
576de02169SBarry Smith }
586de02169SBarry Smith 
59bd1d2e58SBarry Smith /*
607de69702SBarry Smith   PetscByteSwapInt - Swap bytes in a  PETSc integer (which may be 32 or 64-bits)
61bd1d2e58SBarry Smith 
62bd1d2e58SBarry Smith */
6366976f2fSJacob Faibussowitsch static PetscErrorCode PetscByteSwapInt(PetscInt *buff, PetscInt n)
64d71ae5a4SJacob Faibussowitsch {
65bd1d2e58SBarry Smith   PetscInt i, j, tmp = 0;
66e0890e22SSatish Balay   char    *ptr1, *ptr2 = (char *)&tmp;
67bd1d2e58SBarry Smith 
68bd1d2e58SBarry Smith   PetscFunctionBegin;
69bd1d2e58SBarry Smith   for (j = 0; j < n; j++) {
70bd1d2e58SBarry Smith     ptr1 = (char *)(buff + j);
71a297a907SKarl Rupp     for (i = 0; i < (PetscInt)sizeof(PetscInt); i++) ptr2[i] = ptr1[sizeof(PetscInt) - 1 - i];
72a297a907SKarl Rupp     for (i = 0; i < (PetscInt)sizeof(PetscInt); i++) ptr1[i] = ptr2[i];
73bd1d2e58SBarry Smith   }
743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
75bd1d2e58SBarry Smith }
769e3e4c22SLisandro Dalcin 
779e3e4c22SLisandro Dalcin /*
787de69702SBarry Smith   PetscByteSwapInt64 - Swap bytes in a  PETSc integer (64-bits)
799e3e4c22SLisandro Dalcin 
809e3e4c22SLisandro Dalcin */
8166976f2fSJacob Faibussowitsch static PetscErrorCode PetscByteSwapInt64(PetscInt64 *buff, PetscInt n)
82d71ae5a4SJacob Faibussowitsch {
839e3e4c22SLisandro Dalcin   PetscInt   i, j;
849e3e4c22SLisandro Dalcin   PetscInt64 tmp = 0;
859e3e4c22SLisandro Dalcin   char      *ptr1, *ptr2 = (char *)&tmp;
869e3e4c22SLisandro Dalcin 
879e3e4c22SLisandro Dalcin   PetscFunctionBegin;
889e3e4c22SLisandro Dalcin   for (j = 0; j < n; j++) {
899e3e4c22SLisandro Dalcin     ptr1 = (char *)(buff + j);
909e3e4c22SLisandro Dalcin     for (i = 0; i < (PetscInt)sizeof(PetscInt64); i++) ptr2[i] = ptr1[sizeof(PetscInt64) - 1 - i];
919e3e4c22SLisandro Dalcin     for (i = 0; i < (PetscInt)sizeof(PetscInt64); i++) ptr1[i] = ptr2[i];
929e3e4c22SLisandro Dalcin   }
933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
949e3e4c22SLisandro Dalcin }
959e3e4c22SLisandro Dalcin 
96e5c89e4eSSatish Balay /*
973321ca25SJames Wright   PetscByteSwapInt32 - Swap bytes in a  PETSc integer (32-bits)
983321ca25SJames Wright 
993321ca25SJames Wright */
10066976f2fSJacob Faibussowitsch static PetscErrorCode PetscByteSwapInt32(PetscInt32 *buff, PetscInt n)
1013321ca25SJames Wright {
1023321ca25SJames Wright   PetscInt   i, j;
1033321ca25SJames Wright   PetscInt32 tmp = 0;
1043321ca25SJames Wright   char      *ptr1, *ptr2 = (char *)&tmp;
1053321ca25SJames Wright 
1063321ca25SJames Wright   PetscFunctionBegin;
1073321ca25SJames Wright   for (j = 0; j < n; j++) {
1083321ca25SJames Wright     ptr1 = (char *)(buff + j);
1093321ca25SJames Wright     for (i = 0; i < (PetscInt)sizeof(PetscInt32); i++) ptr2[i] = ptr1[sizeof(PetscInt32) - 1 - i];
1103321ca25SJames Wright     for (i = 0; i < (PetscInt)sizeof(PetscInt32); i++) ptr1[i] = ptr2[i];
1113321ca25SJames Wright   }
1123321ca25SJames Wright   PetscFunctionReturn(PETSC_SUCCESS);
1133321ca25SJames Wright }
1143321ca25SJames Wright 
1153321ca25SJames Wright /*
116e5c89e4eSSatish Balay   PetscByteSwapShort - Swap bytes in a short
117e5c89e4eSSatish Balay */
11866976f2fSJacob Faibussowitsch static PetscErrorCode PetscByteSwapShort(short *buff, PetscInt n)
119d71ae5a4SJacob Faibussowitsch {
120e5c89e4eSSatish Balay   PetscInt i, j;
121e5c89e4eSSatish Balay   short    tmp;
122e5c89e4eSSatish Balay   char    *ptr1, *ptr2 = (char *)&tmp;
123e5c89e4eSSatish Balay 
124e5c89e4eSSatish Balay   PetscFunctionBegin;
125e5c89e4eSSatish Balay   for (j = 0; j < n; j++) {
126e5c89e4eSSatish Balay     ptr1 = (char *)(buff + j);
127a297a907SKarl Rupp     for (i = 0; i < (PetscInt)sizeof(short); i++) ptr2[i] = ptr1[sizeof(short) - 1 - i];
128a297a907SKarl Rupp     for (i = 0; i < (PetscInt)sizeof(short); i++) ptr1[i] = ptr2[i];
129e5c89e4eSSatish Balay   }
1303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
131e5c89e4eSSatish Balay }
132972064b6SLisandro Dalcin /*
133972064b6SLisandro Dalcin   PetscByteSwapLong - Swap bytes in a long
134972064b6SLisandro Dalcin */
13566976f2fSJacob Faibussowitsch static PetscErrorCode PetscByteSwapLong(long *buff, PetscInt n)
136d71ae5a4SJacob Faibussowitsch {
137972064b6SLisandro Dalcin   PetscInt i, j;
138972064b6SLisandro Dalcin   long     tmp;
139972064b6SLisandro Dalcin   char    *ptr1, *ptr2 = (char *)&tmp;
140972064b6SLisandro Dalcin 
141972064b6SLisandro Dalcin   PetscFunctionBegin;
142972064b6SLisandro Dalcin   for (j = 0; j < n; j++) {
143972064b6SLisandro Dalcin     ptr1 = (char *)(buff + j);
144972064b6SLisandro Dalcin     for (i = 0; i < (PetscInt)sizeof(long); i++) ptr2[i] = ptr1[sizeof(long) - 1 - i];
145972064b6SLisandro Dalcin     for (i = 0; i < (PetscInt)sizeof(long); i++) ptr1[i] = ptr2[i];
146972064b6SLisandro Dalcin   }
1473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
148972064b6SLisandro Dalcin }
14921532e8aSBarry Smith 
150e5c89e4eSSatish Balay /*
1514caf0332SSatish Balay   PetscByteSwapReal - Swap bytes in a PetscReal
1524caf0332SSatish Balay */
15366976f2fSJacob Faibussowitsch static PetscErrorCode PetscByteSwapReal(PetscReal *buff, PetscInt n)
154d71ae5a4SJacob Faibussowitsch {
1554caf0332SSatish Balay   PetscInt  i, j;
1564caf0332SSatish Balay   PetscReal tmp, *buff1 = (PetscReal *)buff;
1574caf0332SSatish Balay   char     *ptr1, *ptr2 = (char *)&tmp;
1584caf0332SSatish Balay 
1594caf0332SSatish Balay   PetscFunctionBegin;
1604caf0332SSatish Balay   for (j = 0; j < n; j++) {
1614caf0332SSatish Balay     ptr1 = (char *)(buff1 + j);
1624caf0332SSatish Balay     for (i = 0; i < (PetscInt)sizeof(PetscReal); i++) ptr2[i] = ptr1[sizeof(PetscReal) - 1 - i];
1634caf0332SSatish Balay     for (i = 0; i < (PetscInt)sizeof(PetscReal); i++) ptr1[i] = ptr2[i];
1644caf0332SSatish Balay   }
1653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1664caf0332SSatish Balay }
16721532e8aSBarry Smith 
1684caf0332SSatish Balay /*
16941f502e3SPatrick Sanan   PetscByteSwapScalar - Swap bytes in a PetscScalar
17041f502e3SPatrick Sanan   The complex case is dealt with with an array of PetscReal, twice as long.
171e5c89e4eSSatish Balay */
17266976f2fSJacob Faibussowitsch static PetscErrorCode PetscByteSwapScalar(PetscScalar *buff, PetscInt n)
173d71ae5a4SJacob Faibussowitsch {
174e5c89e4eSSatish Balay   PetscInt  i, j;
175e5c89e4eSSatish Balay   PetscReal tmp, *buff1 = (PetscReal *)buff;
176e5c89e4eSSatish Balay   char     *ptr1, *ptr2 = (char *)&tmp;
177e5c89e4eSSatish Balay 
178e5c89e4eSSatish Balay   PetscFunctionBegin;
179e5c89e4eSSatish Balay #if defined(PETSC_USE_COMPLEX)
180e5c89e4eSSatish Balay   n *= 2;
181e5c89e4eSSatish Balay #endif
182e5c89e4eSSatish Balay   for (j = 0; j < n; j++) {
183e5c89e4eSSatish Balay     ptr1 = (char *)(buff1 + j);
184a297a907SKarl Rupp     for (i = 0; i < (PetscInt)sizeof(PetscReal); i++) ptr2[i] = ptr1[sizeof(PetscReal) - 1 - i];
185a297a907SKarl Rupp     for (i = 0; i < (PetscInt)sizeof(PetscReal); i++) ptr1[i] = ptr2[i];
186e5c89e4eSSatish Balay   }
1873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
188e5c89e4eSSatish Balay }
18921532e8aSBarry Smith 
190e5c89e4eSSatish Balay /*
191e5c89e4eSSatish Balay   PetscByteSwapDouble - Swap bytes in a double
192e5c89e4eSSatish Balay */
19366976f2fSJacob Faibussowitsch static PetscErrorCode PetscByteSwapDouble(double *buff, PetscInt n)
194d71ae5a4SJacob Faibussowitsch {
195e5c89e4eSSatish Balay   PetscInt i, j;
196e5c89e4eSSatish Balay   double   tmp, *buff1 = (double *)buff;
197e5c89e4eSSatish Balay   char    *ptr1, *ptr2 = (char *)&tmp;
198e5c89e4eSSatish Balay 
199e5c89e4eSSatish Balay   PetscFunctionBegin;
200e5c89e4eSSatish Balay   for (j = 0; j < n; j++) {
201e5c89e4eSSatish Balay     ptr1 = (char *)(buff1 + j);
202a297a907SKarl Rupp     for (i = 0; i < (PetscInt)sizeof(double); i++) ptr2[i] = ptr1[sizeof(double) - 1 - i];
203a297a907SKarl Rupp     for (i = 0; i < (PetscInt)sizeof(double); i++) ptr1[i] = ptr2[i];
204e5c89e4eSSatish Balay   }
2053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
206e5c89e4eSSatish Balay }
207e39fd77fSBarry Smith 
208e95bf02fSSatish Balay /*
209e95bf02fSSatish Balay   PetscByteSwapFloat - Swap bytes in a float
210e95bf02fSSatish Balay */
21166976f2fSJacob Faibussowitsch static PetscErrorCode PetscByteSwapFloat(float *buff, PetscInt n)
212d71ae5a4SJacob Faibussowitsch {
213e95bf02fSSatish Balay   PetscInt i, j;
214e95bf02fSSatish Balay   float    tmp, *buff1 = (float *)buff;
215e95bf02fSSatish Balay   char    *ptr1, *ptr2 = (char *)&tmp;
216e95bf02fSSatish Balay 
217e95bf02fSSatish Balay   PetscFunctionBegin;
218e95bf02fSSatish Balay   for (j = 0; j < n; j++) {
219e95bf02fSSatish Balay     ptr1 = (char *)(buff1 + j);
220a297a907SKarl Rupp     for (i = 0; i < (PetscInt)sizeof(float); i++) ptr2[i] = ptr1[sizeof(float) - 1 - i];
221a297a907SKarl Rupp     for (i = 0; i < (PetscInt)sizeof(float); i++) ptr1[i] = ptr2[i];
222e95bf02fSSatish Balay   }
2233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
224e95bf02fSSatish Balay }
225e95bf02fSSatish Balay 
226d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscByteSwap(void *data, PetscDataType pdtype, PetscInt count)
227d71ae5a4SJacob Faibussowitsch {
228e39fd77fSBarry Smith   PetscFunctionBegin;
2299566063dSJacob Faibussowitsch   if (pdtype == PETSC_INT) PetscCall(PetscByteSwapInt((PetscInt *)data, count));
2309566063dSJacob Faibussowitsch   else if (pdtype == PETSC_ENUM) PetscCall(PetscByteSwapEnum((PetscEnum *)data, count));
2319566063dSJacob Faibussowitsch   else if (pdtype == PETSC_BOOL) PetscCall(PetscByteSwapBool((PetscBool *)data, count));
2329566063dSJacob Faibussowitsch   else if (pdtype == PETSC_SCALAR) PetscCall(PetscByteSwapScalar((PetscScalar *)data, count));
2339566063dSJacob Faibussowitsch   else if (pdtype == PETSC_REAL) PetscCall(PetscByteSwapReal((PetscReal *)data, count));
2349566063dSJacob Faibussowitsch   else if (pdtype == PETSC_COMPLEX) PetscCall(PetscByteSwapReal((PetscReal *)data, 2 * count));
2359566063dSJacob Faibussowitsch   else if (pdtype == PETSC_INT64) PetscCall(PetscByteSwapInt64((PetscInt64 *)data, count));
2363321ca25SJames Wright   else if (pdtype == PETSC_INT32) PetscCall(PetscByteSwapInt32((PetscInt32 *)data, count));
2379566063dSJacob Faibussowitsch   else if (pdtype == PETSC_DOUBLE) PetscCall(PetscByteSwapDouble((double *)data, count));
2389566063dSJacob Faibussowitsch   else if (pdtype == PETSC_FLOAT) PetscCall(PetscByteSwapFloat((float *)data, count));
2399566063dSJacob Faibussowitsch   else if (pdtype == PETSC_SHORT) PetscCall(PetscByteSwapShort((short *)data, count));
2409566063dSJacob Faibussowitsch   else if (pdtype == PETSC_LONG) PetscCall(PetscByteSwapLong((long *)data, count));
241372de11fSJed Brown   else if (pdtype == PETSC_CHAR) PetscFunctionReturn(PETSC_SUCCESS);
2423321ca25SJames Wright   else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Unknown type: %d", pdtype);
2433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
244e39fd77fSBarry Smith }
245e39fd77fSBarry Smith 
2469860990eSLisandro Dalcin /*@C
247e5c89e4eSSatish Balay   PetscBinaryRead - Reads from a binary file.
248e5c89e4eSSatish Balay 
249e5c89e4eSSatish Balay   Not Collective
250e5c89e4eSSatish Balay 
251e5c89e4eSSatish Balay   Input Parameters:
2529860990eSLisandro Dalcin + fd   - the file descriptor
2539860990eSLisandro Dalcin . num  - the maximum number of items to read
254811af0c4SBarry Smith - type - the type of items to read (`PETSC_INT`, `PETSC_REAL`, `PETSC_SCALAR`, etc.)
255e5c89e4eSSatish Balay 
256e5c89e4eSSatish Balay   Output Parameters:
25721532e8aSBarry Smith + data  - the buffer, this is an array of the type that matches the value in `type`
2589860990eSLisandro Dalcin - count - the number of items read, optional
259e5c89e4eSSatish Balay 
260e5c89e4eSSatish Balay   Level: developer
261e5c89e4eSSatish Balay 
262e5c89e4eSSatish Balay   Notes:
26321532e8aSBarry Smith   If `count` is not provided and the number of items read is less than
2649860990eSLisandro Dalcin   the maximum number of items to read, then this routine errors.
2659860990eSLisandro Dalcin 
266811af0c4SBarry Smith   `PetscBinaryRead()` uses byte swapping to work on all machines; the files
26721532e8aSBarry Smith   are written ALWAYS using big-endian ordering. On little-endian machines the numbers
268f253e43cSLisandro Dalcin   are converted to the little-endian format when they are read in from the file.
26921532e8aSBarry Smith   When PETSc is ./configure with `--with-64-bit-indices` the integers are written to the
2707de69702SBarry Smith   file as 64-bit integers, this means they can only be read back in when the option `--with-64-bit-indices`
27154f21887SBarry Smith   is used.
272e5c89e4eSSatish Balay 
273db781477SPatrick Sanan .seealso: `PetscBinaryWrite()`, `PetscBinaryOpen()`, `PetscBinaryClose()`, `PetscViewerBinaryGetDescriptor()`, `PetscBinarySynchronizedWrite()`,
274db781477SPatrick Sanan           `PetscBinarySynchronizedRead()`, `PetscBinarySynchronizedSeek()`
275e5c89e4eSSatish Balay @*/
276d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscBinaryRead(int fd, void *data, PetscInt num, PetscInt *count, PetscDataType type)
277d71ae5a4SJacob Faibussowitsch {
2789860990eSLisandro Dalcin   size_t typesize, m = (size_t)num, n = 0, maxblock = 65536;
2799860990eSLisandro Dalcin   char  *p = (char *)data;
2807a881295SBarry Smith #if defined(PETSC_USE_REAL___FLOAT128)
281cba51d77SBarry Smith   PetscBool readdouble = PETSC_FALSE;
2829860990eSLisandro Dalcin   double   *pdouble;
2837a881295SBarry Smith #endif
2849860990eSLisandro Dalcin   void *ptmp  = data;
28505acbc63SBarry Smith   char *fname = NULL;
286e5c89e4eSSatish Balay 
287e5c89e4eSSatish Balay   PetscFunctionBegin;
2889860990eSLisandro Dalcin   if (count) *count = 0;
28908401ef6SPierre Jolivet   PetscCheck(num >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to read a negative amount of data %" PetscInt_FMT, num);
2903ba16761SJacob Faibussowitsch   if (!num) PetscFunctionReturn(PETSC_SUCCESS);
291e5c89e4eSSatish Balay 
2922d53ad75SBarry Smith   if (type == PETSC_FUNCTION) {
2932d53ad75SBarry Smith     m     = 64;
2942d53ad75SBarry Smith     type  = PETSC_CHAR;
29505acbc63SBarry Smith     fname = (char *)malloc(m * sizeof(char));
2969860990eSLisandro Dalcin     p     = (char *)fname;
2972d53ad75SBarry Smith     ptmp  = (void *)fname;
29828b400f6SJacob Faibussowitsch     PetscCheck(fname, PETSC_COMM_SELF, PETSC_ERR_MEM, "Cannot allocate space for function name");
2992d53ad75SBarry Smith   }
3009860990eSLisandro Dalcin   if (type == PETSC_BIT_LOGICAL) m = PetscBTLength(m);
3012d53ad75SBarry Smith 
3029566063dSJacob Faibussowitsch   PetscCall(PetscDataTypeGetSize(type, &typesize));
303e5c89e4eSSatish Balay 
3047a881295SBarry Smith #if defined(PETSC_USE_REAL___FLOAT128)
3059566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(NULL, NULL, "-binary_read_double", &readdouble, NULL));
3067a881295SBarry Smith   /* If using __float128 precision we still read in doubles from file */
3079860990eSLisandro Dalcin   if ((type == PETSC_REAL || type == PETSC_COMPLEX) && readdouble) {
3089860990eSLisandro Dalcin     PetscInt cnt = num * ((type == PETSC_REAL) ? 1 : 2);
3099566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(cnt, &pdouble));
3109860990eSLisandro Dalcin     p = (char *)pdouble;
3119860990eSLisandro Dalcin     typesize /= 2;
3127a881295SBarry Smith   }
3137a881295SBarry Smith #endif
3147a881295SBarry Smith 
3159860990eSLisandro Dalcin   m *= typesize;
3169860990eSLisandro Dalcin 
317e5c89e4eSSatish Balay   while (m) {
3189860990eSLisandro Dalcin     size_t len = (m < maxblock) ? m : maxblock;
3199860990eSLisandro Dalcin     int    ret = (int)read(fd, p, len);
3209860990eSLisandro Dalcin     if (ret < 0 && errno == EINTR) continue;
3219860990eSLisandro Dalcin     if (!ret && len > 0) break; /* Proxy for EOF */
322bf31d2d3SBarry Smith     PetscCheck(ret >= 0, PETSC_COMM_SELF, PETSC_ERR_FILE_READ, "Error reading from file due to \"%s\"", strerror(errno));
323ff9f933bSBarry Smith     m -= (size_t)ret;
3249860990eSLisandro Dalcin     p += ret;
325ff9f933bSBarry Smith     n += (size_t)ret;
326e5c89e4eSSatish Balay   }
32708401ef6SPierre Jolivet   PetscCheck(!m || count, PETSC_COMM_SELF, PETSC_ERR_FILE_READ, "Read past end of file");
3289860990eSLisandro Dalcin 
3299860990eSLisandro Dalcin   num = (PetscInt)(n / typesize); /* Should we require `n % typesize == 0` ? */
3309860990eSLisandro Dalcin   if (count) *count = num;        /* TODO: This is most likely wrong for PETSC_BIT_LOGICAL */
3317a881295SBarry Smith 
3327a881295SBarry Smith #if defined(PETSC_USE_REAL___FLOAT128)
3339860990eSLisandro Dalcin   if ((type == PETSC_REAL || type == PETSC_COMPLEX) && readdouble) {
3349860990eSLisandro Dalcin     PetscInt   i, cnt = num * ((type == PETSC_REAL) ? 1 : 2);
3359860990eSLisandro Dalcin     PetscReal *preal = (PetscReal *)data;
3369566063dSJacob Faibussowitsch     if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwapDouble(pdouble, cnt));
3379860990eSLisandro Dalcin     for (i = 0; i < cnt; i++) preal[i] = pdouble[i];
3389566063dSJacob Faibussowitsch     PetscCall(PetscFree(pdouble));
3393ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
3407a881295SBarry Smith   }
3417a881295SBarry Smith #endif
3427a881295SBarry Smith 
3439566063dSJacob Faibussowitsch   if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(ptmp, type, num));
344e5c89e4eSSatish Balay 
34505acbc63SBarry Smith   if (type == PETSC_FUNCTION) {
3462d53ad75SBarry Smith #if defined(PETSC_SERIALIZE_FUNCTIONS)
3479566063dSJacob Faibussowitsch     PetscCall(PetscDLSym(NULL, fname, (void **)data));
3482d53ad75SBarry Smith #else
3499860990eSLisandro Dalcin     *(void **)data = NULL;
3502d53ad75SBarry Smith #endif
35105acbc63SBarry Smith     free(fname);
3522d53ad75SBarry Smith   }
3533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
354e5c89e4eSSatish Balay }
3559860990eSLisandro Dalcin 
356a9acdec7SBarry Smith /*@C
357e5c89e4eSSatish Balay   PetscBinaryWrite - Writes to a binary file.
358e5c89e4eSSatish Balay 
359e5c89e4eSSatish Balay   Not Collective
360e5c89e4eSSatish Balay 
361e5c89e4eSSatish Balay   Input Parameters:
362e5c89e4eSSatish Balay + fd   - the file
36321532e8aSBarry Smith . p    - the buffer, an array of the type that matches the value in `type`
364e5c89e4eSSatish Balay . n    - the number of items to write
365811af0c4SBarry Smith - type - the type of items to read (`PETSC_INT`, `PETSC_REAL` or `PETSC_SCALAR`)
366e5c89e4eSSatish Balay 
367e5c89e4eSSatish Balay   Level: advanced
368e5c89e4eSSatish Balay 
369e5c89e4eSSatish Balay   Notes:
370811af0c4SBarry Smith   `PetscBinaryWrite()` uses byte swapping to work on all machines; the files
371f253e43cSLisandro Dalcin   are written using big-endian ordering to the file. On little-endian machines the numbers
372e5c89e4eSSatish Balay   are converted to the big-endian format when they are written to disk.
37321532e8aSBarry Smith   When PETSc is configured using `./configure with --with-64-bit-indices` the integers are written to the
3747de69702SBarry Smith   file as 64-bit integers, this means they can only be read back in when the option `--with-64-bit-indices`
37554f21887SBarry Smith   is used.
376e5c89e4eSSatish Balay 
37721532e8aSBarry Smith   If running with `__float128` precision the output of `PETSC_REAL` is in `__float128` unless one uses the `-binary_write_double` option
3780da86b62SBarry Smith 
379bfbbc7b7SBarry Smith   The buffer `p` should be read-write buffer, and not static data.
380e5c89e4eSSatish Balay   This way, byte-swapping is done in-place, and then the buffer is
381e5c89e4eSSatish Balay   written to the file.
382e5c89e4eSSatish Balay 
383e5c89e4eSSatish Balay   This routine restores the original contents of the buffer, after
384e5c89e4eSSatish Balay   it is written to the file. This is done by byte-swapping in-place
385f253e43cSLisandro Dalcin   the second time.
386e5c89e4eSSatish Balay 
387300a7f5bSBarry Smith   Because byte-swapping may be done on the values in data it cannot be declared const
388300a7f5bSBarry Smith 
389db781477SPatrick Sanan .seealso: `PetscBinaryRead()`, `PetscBinaryOpen()`, `PetscBinaryClose()`, `PetscViewerBinaryGetDescriptor()`, `PetscBinarySynchronizedWrite()`,
390db781477SPatrick Sanan           `PetscBinarySynchronizedRead()`, `PetscBinarySynchronizedSeek()`
391e5c89e4eSSatish Balay @*/
392d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscBinaryWrite(int fd, const void *p, PetscInt n, PetscDataType type)
393d71ae5a4SJacob Faibussowitsch {
394f253e43cSLisandro Dalcin   const char *pp = (char *)p;
395e5c89e4eSSatish Balay   int         err, wsize;
396e5c89e4eSSatish Balay   size_t      m = (size_t)n, maxblock = 65536;
397f253e43cSLisandro Dalcin   const void *ptmp  = p;
39805acbc63SBarry Smith   char       *fname = NULL;
3990da86b62SBarry Smith #if defined(PETSC_USE_REAL___FLOAT128)
400df40af56SBarry Smith   PetscBool  writedouble = PETSC_FALSE;
4010da86b62SBarry Smith   double    *ppp;
4020da86b62SBarry Smith   PetscReal *pv;
4030da86b62SBarry Smith   PetscInt   i;
4040da86b62SBarry Smith #endif
40541f502e3SPatrick Sanan   PetscDataType wtype = type;
406e5c89e4eSSatish Balay 
407e5c89e4eSSatish Balay   PetscFunctionBegin;
40808401ef6SPierre Jolivet   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to write a negative amount of data %" PetscInt_FMT, n);
4093ba16761SJacob Faibussowitsch   if (!n) PetscFunctionReturn(PETSC_SUCCESS);
410e5c89e4eSSatish Balay 
4112d53ad75SBarry Smith   if (type == PETSC_FUNCTION) {
4122d53ad75SBarry Smith #if defined(PETSC_SERIALIZE_FUNCTIONS)
4132d53ad75SBarry Smith     const char *fnametmp;
4142d53ad75SBarry Smith #endif
4152d53ad75SBarry Smith     m     = 64;
416e25ab156SSatish Balay     fname = (char *)malloc(m * sizeof(char));
41728b400f6SJacob Faibussowitsch     PetscCheck(fname, PETSC_COMM_SELF, PETSC_ERR_MEM, "Cannot allocate space for function name");
41805acbc63SBarry Smith #if defined(PETSC_SERIALIZE_FUNCTIONS)
41908401ef6SPierre Jolivet     PetscCheck(n <= 1, PETSC_COMM_SELF, PETSC_ERR_SUP, "Can only binary view a single function at a time");
4209566063dSJacob Faibussowitsch     PetscCall(PetscFPTFind(*(void **)p, &fnametmp));
4219566063dSJacob Faibussowitsch     PetscCall(PetscStrncpy(fname, fnametmp, m));
42205acbc63SBarry Smith #else
4239566063dSJacob Faibussowitsch     PetscCall(PetscStrncpy(fname, "", m));
42405acbc63SBarry Smith #endif
42501963f56SBarry Smith     wtype = PETSC_CHAR;
4262d53ad75SBarry Smith     pp    = (char *)fname;
4272d53ad75SBarry Smith     ptmp  = (void *)fname;
4282d53ad75SBarry Smith   }
4292d53ad75SBarry Smith 
4300da86b62SBarry Smith #if defined(PETSC_USE_REAL___FLOAT128)
4319566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(NULL, NULL, "-binary_write_double", &writedouble, NULL));
4320da86b62SBarry Smith   /* If using __float128 precision we still write in doubles to file */
433501ae109SJose E. Roman   if ((type == PETSC_SCALAR || type == PETSC_REAL || type == PETSC_COMPLEX) && writedouble) {
43441f502e3SPatrick Sanan     wtype = PETSC_DOUBLE;
4359566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(n, &ppp));
4360da86b62SBarry Smith     pv = (PetscReal *)pp;
437ad540459SPierre Jolivet     for (i = 0; i < n; i++) ppp[i] = (double)pv[i];
4380da86b62SBarry Smith     pp   = (char *)ppp;
4390da86b62SBarry Smith     ptmp = (char *)ppp;
4400da86b62SBarry Smith   }
4410da86b62SBarry Smith #endif
4420da86b62SBarry Smith 
44341f502e3SPatrick Sanan   if (wtype == PETSC_INT) m *= sizeof(PetscInt);
44441f502e3SPatrick Sanan   else if (wtype == PETSC_SCALAR) m *= sizeof(PetscScalar);
445501ae109SJose E. Roman #if defined(PETSC_HAVE_COMPLEX)
446501ae109SJose E. Roman   else if (wtype == PETSC_COMPLEX) m *= sizeof(PetscComplex);
447501ae109SJose E. Roman #endif
4484caf0332SSatish Balay   else if (wtype == PETSC_REAL) m *= sizeof(PetscReal);
44941f502e3SPatrick Sanan   else if (wtype == PETSC_DOUBLE) m *= sizeof(double);
45041f502e3SPatrick Sanan   else if (wtype == PETSC_FLOAT) m *= sizeof(float);
45141f502e3SPatrick Sanan   else if (wtype == PETSC_SHORT) m *= sizeof(short);
452972064b6SLisandro Dalcin   else if (wtype == PETSC_LONG) m *= sizeof(long);
45341f502e3SPatrick Sanan   else if (wtype == PETSC_CHAR) m *= sizeof(char);
45441f502e3SPatrick Sanan   else if (wtype == PETSC_ENUM) m *= sizeof(PetscEnum);
45541f502e3SPatrick Sanan   else if (wtype == PETSC_BOOL) m *= sizeof(PetscBool);
4569e3e4c22SLisandro Dalcin   else if (wtype == PETSC_INT64) m *= sizeof(PetscInt64);
4573321ca25SJames Wright   else if (wtype == PETSC_INT32) m *= sizeof(PetscInt32);
45841f502e3SPatrick Sanan   else if (wtype == PETSC_BIT_LOGICAL) m = PetscBTLength(m) * sizeof(char);
4593321ca25SJames Wright   else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Unknown type: %d", wtype);
460e5c89e4eSSatish Balay 
4619566063dSJacob Faibussowitsch   if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap((void *)ptmp, wtype, n));
462e5c89e4eSSatish Balay 
463e5c89e4eSSatish Balay   while (m) {
464e5c89e4eSSatish Balay     wsize = (m < maxblock) ? m : maxblock;
465e5c89e4eSSatish Balay     err   = write(fd, pp, wsize);
466e5c89e4eSSatish Balay     if (err < 0 && errno == EINTR) continue;
467bf31d2d3SBarry 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));
468e5c89e4eSSatish Balay     m -= wsize;
469e5c89e4eSSatish Balay     pp += wsize;
470e5c89e4eSSatish Balay   }
471e5c89e4eSSatish Balay 
4729566063dSJacob Faibussowitsch   if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap((void *)ptmp, wtype, n));
473f253e43cSLisandro Dalcin 
474ad540459SPierre Jolivet   if (type == PETSC_FUNCTION) free(fname);
4750da86b62SBarry Smith #if defined(PETSC_USE_REAL___FLOAT128)
47648a46eb9SPierre Jolivet   if ((type == PETSC_SCALAR || type == PETSC_REAL || type == PETSC_COMPLEX) && writedouble) PetscCall(PetscFree(ppp));
4770da86b62SBarry Smith #endif
4783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
479e5c89e4eSSatish Balay }
480e5c89e4eSSatish Balay 
481e5c89e4eSSatish Balay /*@C
482e5c89e4eSSatish Balay   PetscBinaryOpen - Opens a PETSc binary file.
483e5c89e4eSSatish Balay 
484e5c89e4eSSatish Balay   Not Collective
485e5c89e4eSSatish Balay 
486e5c89e4eSSatish Balay   Input Parameters:
487e5c89e4eSSatish Balay + name - filename
488*fe8e7dddSPierre Jolivet - mode - open mode of binary file, one of `FILE_MODE_READ`, `FILE_MODE_WRITE`, `FILE_MODE_APPEND`
489e5c89e4eSSatish Balay 
490e5c89e4eSSatish Balay   Output Parameter:
491e5c89e4eSSatish Balay . fd - the file
492e5c89e4eSSatish Balay 
493e5c89e4eSSatish Balay   Level: advanced
494e5c89e4eSSatish Balay 
495db781477SPatrick Sanan .seealso: `PetscBinaryRead()`, `PetscBinaryWrite()`, `PetscFileMode`, `PetscViewerFileSetMode()`, `PetscViewerBinaryGetDescriptor()`,
496db781477SPatrick Sanan           `PetscBinarySynchronizedWrite()`, `PetscBinarySynchronizedRead()`, `PetscBinarySynchronizedSeek()`
497e5c89e4eSSatish Balay @*/
498d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscBinaryOpen(const char name[], PetscFileMode mode, int *fd)
499d71ae5a4SJacob Faibussowitsch {
500e5c89e4eSSatish Balay   PetscFunctionBegin;
501cc843e7aSLisandro Dalcin   switch (mode) {
502d71ae5a4SJacob Faibussowitsch   case FILE_MODE_READ:
503d71ae5a4SJacob Faibussowitsch     *fd = open(name, O_BINARY | O_RDONLY, 0);
504d71ae5a4SJacob Faibussowitsch     break;
505d71ae5a4SJacob Faibussowitsch   case FILE_MODE_WRITE:
506d71ae5a4SJacob Faibussowitsch     *fd = open(name, O_BINARY | O_WRONLY | O_CREAT | O_TRUNC, 0666);
507d71ae5a4SJacob Faibussowitsch     break;
508d71ae5a4SJacob Faibussowitsch   case FILE_MODE_APPEND:
509d71ae5a4SJacob Faibussowitsch     *fd = open(name, O_BINARY | O_WRONLY | O_APPEND, 0);
510d71ae5a4SJacob Faibussowitsch     break;
511d71ae5a4SJacob Faibussowitsch   default:
512d71ae5a4SJacob Faibussowitsch     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Unsupported file mode %s", PetscFileModes[mode]);
513e5c89e4eSSatish Balay   }
514bf31d2d3SBarry 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));
5153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
516e5c89e4eSSatish Balay }
517e5c89e4eSSatish Balay 
518e30d2299SSatish Balay /*@
519e5c89e4eSSatish Balay   PetscBinaryClose - Closes a PETSc binary file.
520e5c89e4eSSatish Balay 
521e5c89e4eSSatish Balay   Not Collective
522e5c89e4eSSatish Balay 
523e5c89e4eSSatish Balay   Output Parameter:
524e5c89e4eSSatish Balay . fd - the file
525e5c89e4eSSatish Balay 
526e5c89e4eSSatish Balay   Level: advanced
527e5c89e4eSSatish Balay 
528db781477SPatrick Sanan .seealso: `PetscBinaryRead()`, `PetscBinaryWrite()`, `PetscBinaryOpen()`, `PetscBinarySynchronizedWrite()`, `PetscBinarySynchronizedRead()`,
529db781477SPatrick Sanan           `PetscBinarySynchronizedSeek()`
530e5c89e4eSSatish Balay @*/
531d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscBinaryClose(int fd)
532d71ae5a4SJacob Faibussowitsch {
533e5c89e4eSSatish Balay   PetscFunctionBegin;
534cc73adaaSBarry Smith   PetscCheck(!close(fd), PETSC_COMM_SELF, PETSC_ERR_SYS, "close() failed on file descriptor");
5353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
536e5c89e4eSSatish Balay }
537e5c89e4eSSatish Balay 
538e8976759SBarry Smith /*@C
539e5c89e4eSSatish Balay   PetscBinarySeek - Moves the file pointer on a PETSc binary file.
540e5c89e4eSSatish Balay 
541e5c89e4eSSatish Balay   Not Collective
542e5c89e4eSSatish Balay 
543e5c89e4eSSatish Balay   Input Parameters:
544e5c89e4eSSatish Balay + fd     - the file
545811af0c4SBarry Smith . off    - number of bytes to move. Use `PETSC_BINARY_INT_SIZE`, `PETSC_BINARY_SCALAR_SIZE`,
54621532e8aSBarry Smith             etc. in your calculation rather than `sizeof()` to compute byte lengths.
54716a05f60SBarry Smith - whence - see `PetscBinarySeekType` for possible values
548e5c89e4eSSatish Balay 
549e5c89e4eSSatish Balay   Output Parameter:
550e5c89e4eSSatish Balay . offset - new offset in file
551e5c89e4eSSatish Balay 
552e5c89e4eSSatish Balay   Level: developer
553e5c89e4eSSatish Balay 
55416a05f60SBarry Smith .seealso: `PetscBinaryRead()`, `PetscBinarySeekType`, `PetscBinaryWrite()`, `PetscBinaryOpen()`, `PetscBinarySynchronizedWrite()`, `PetscBinarySynchronizedRead()`,
555db781477SPatrick Sanan           `PetscBinarySynchronizedSeek()`
556e5c89e4eSSatish Balay @*/
557d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscBinarySeek(int fd, off_t off, PetscBinarySeekType whence, off_t *offset)
558d71ae5a4SJacob Faibussowitsch {
559e5c89e4eSSatish Balay   int iwhence = 0;
560e5c89e4eSSatish Balay 
561e5c89e4eSSatish Balay   PetscFunctionBegin;
562a297a907SKarl Rupp   if (whence == PETSC_BINARY_SEEK_SET) iwhence = SEEK_SET;
563a297a907SKarl Rupp   else if (whence == PETSC_BINARY_SEEK_CUR) iwhence = SEEK_CUR;
564a297a907SKarl Rupp   else if (whence == PETSC_BINARY_SEEK_END) iwhence = SEEK_END;
565a297a907SKarl Rupp   else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Unknown seek location");
566e5c89e4eSSatish Balay #if defined(PETSC_HAVE_LSEEK)
567e5c89e4eSSatish Balay   *offset = lseek(fd, off, iwhence);
568e5c89e4eSSatish Balay #elif defined(PETSC_HAVE__LSEEK)
569e5c89e4eSSatish Balay   *offset = _lseek(fd, (long)off, iwhence);
570e5c89e4eSSatish Balay #else
571e32f2f54SBarry Smith   SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP_SYS, "System does not have a way of seeking on a file");
572e5c89e4eSSatish Balay #endif
5733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
574e5c89e4eSSatish Balay }
575e5c89e4eSSatish Balay 
576e5c89e4eSSatish Balay /*@C
57721532e8aSBarry Smith   PetscBinarySynchronizedRead - Reads from a binary file, all MPI processes get the same values
578e5c89e4eSSatish Balay 
579d083f849SBarry Smith   Collective
580e5c89e4eSSatish Balay 
581e5c89e4eSSatish Balay   Input Parameters:
582e5c89e4eSSatish Balay + comm - the MPI communicator
5839860990eSLisandro Dalcin . fd   - the file descriptor
5849860990eSLisandro Dalcin . num  - the maximum number of items to read
585811af0c4SBarry Smith - type - the type of items to read (`PETSC_INT`, `PETSC_REAL`, `PETSC_SCALAR`, etc.)
586e5c89e4eSSatish Balay 
587e5c89e4eSSatish Balay   Output Parameters:
58821532e8aSBarry Smith + data  - the buffer, an array of the type that matches the value in `type`
5899860990eSLisandro Dalcin - count - the number of items read, optional
590e5c89e4eSSatish Balay 
591e5c89e4eSSatish Balay   Level: developer
592e5c89e4eSSatish Balay 
593e5c89e4eSSatish Balay   Notes:
594811af0c4SBarry Smith   Does a `PetscBinaryRead()` followed by an `MPI_Bcast()`
595e5c89e4eSSatish Balay 
59621532e8aSBarry Smith   If `count` is not provided and the number of items read is less than
5979860990eSLisandro Dalcin   the maximum number of items to read, then this routine errors.
5989860990eSLisandro Dalcin 
599811af0c4SBarry Smith   `PetscBinarySynchronizedRead()` uses byte swapping to work on all machines.
60021532e8aSBarry Smith   The files  are written using big-endian ordering to the file. On little-endian machines the numbers
60121532e8aSBarry Smith   are converted to the big-endian format when they are written to disk.
60221532e8aSBarry Smith   When PETSc is configured using `./configure with --with-64-bit-indices` the integers are written to the
6037de69702SBarry Smith   file as 64-bit integers, this means they can only be read back in when the option `--with-64-bit-indices`
60421532e8aSBarry Smith   is used.
605e5c89e4eSSatish Balay 
606db781477SPatrick Sanan .seealso: `PetscBinaryWrite()`, `PetscBinaryOpen()`, `PetscBinaryClose()`, `PetscBinaryRead()`, `PetscBinarySynchronizedWrite()`,
607db781477SPatrick Sanan           `PetscBinarySynchronizedSeek()`
608e5c89e4eSSatish Balay @*/
609d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscBinarySynchronizedRead(MPI_Comm comm, int fd, void *data, PetscInt num, PetscInt *count, PetscDataType type)
610d71ae5a4SJacob Faibussowitsch {
6118b8bf82cSBarry Smith   PetscMPIInt  rank, size;
612e5c89e4eSSatish Balay   MPI_Datatype mtype;
6139860990eSLisandro Dalcin   PetscInt     ibuf[2] = {0, 0};
61405acbc63SBarry Smith   char        *fname   = NULL;
6159860990eSLisandro Dalcin   void        *fptr    = NULL;
616e5c89e4eSSatish Balay 
617e5c89e4eSSatish Balay   PetscFunctionBegin;
6182d53ad75SBarry Smith   if (type == PETSC_FUNCTION) {
6199860990eSLisandro Dalcin     num   = 64;
6202d53ad75SBarry Smith     type  = PETSC_CHAR;
6219860990eSLisandro Dalcin     fname = (char *)malloc(num * sizeof(char));
6229860990eSLisandro Dalcin     fptr  = data;
6239860990eSLisandro Dalcin     data  = (void *)fname;
62428b400f6SJacob Faibussowitsch     PetscCheck(fname, PETSC_COMM_SELF, PETSC_ERR_MEM, "Cannot allocate space for function name");
6252d53ad75SBarry Smith   }
6262d53ad75SBarry Smith 
6279566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
6289566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
629ad540459SPierre Jolivet   if (rank == 0) ibuf[0] = PetscBinaryRead(fd, data, num, count ? &ibuf[1] : NULL, type);
6309566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Bcast(ibuf, 2, MPIU_INT, 0, comm));
6319566063dSJacob Faibussowitsch   PetscCall((PetscErrorCode)ibuf[0]);
6328b8bf82cSBarry Smith 
6338b8bf82cSBarry 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 */
6348b8bf82cSBarry Smith   if (size > 1) {
6359566063dSJacob Faibussowitsch     PetscCall(PetscDataTypeToMPIDataType(type, &mtype));
6369566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Bcast(data, count ? ibuf[1] : num, mtype, 0, comm));
6378b8bf82cSBarry Smith   }
6389860990eSLisandro Dalcin   if (count) *count = ibuf[1];
6392d53ad75SBarry Smith 
640e366c363SBarry Smith   if (type == PETSC_FUNCTION) {
6412d53ad75SBarry Smith #if defined(PETSC_SERIALIZE_FUNCTIONS)
6429566063dSJacob Faibussowitsch     PetscCall(PetscDLLibrarySym(PETSC_COMM_SELF, &PetscDLLibrariesLoaded, NULL, fname, (void **)fptr));
6432d53ad75SBarry Smith #else
6449860990eSLisandro Dalcin     *(void **)fptr = NULL;
6452d53ad75SBarry Smith #endif
646e366c363SBarry Smith     free(fname);
6472d53ad75SBarry Smith   }
6483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
649e5c89e4eSSatish Balay }
650e5c89e4eSSatish Balay 
651e5c89e4eSSatish Balay /*@C
6521d280d73SBarry Smith   PetscBinarySynchronizedWrite - writes to a binary file.
653e5c89e4eSSatish Balay 
654d083f849SBarry Smith   Collective
655e5c89e4eSSatish Balay 
656e5c89e4eSSatish Balay   Input Parameters:
657e5c89e4eSSatish Balay + comm - the MPI communicator
658e5c89e4eSSatish Balay . fd   - the file
659e5c89e4eSSatish Balay . n    - the number of items to write
66021532e8aSBarry Smith . p    - the buffer, an array of the type that matches the value in `type`
661811af0c4SBarry Smith - type - the type of items to write (`PETSC_INT`, `PETSC_REAL` or `PETSC_SCALAR`)
662e5c89e4eSSatish Balay 
663e5c89e4eSSatish Balay   Level: developer
664e5c89e4eSSatish Balay 
665e5c89e4eSSatish Balay   Notes:
66621532e8aSBarry Smith   MPI rank 0 does a `PetscBinaryWrite()` the values on other MPI processes are not used
667e5c89e4eSSatish Balay 
66821532e8aSBarry Smith   The files  are written using big-endian ordering to the file. On little-endian machines the numbers
66921532e8aSBarry Smith   are converted to the big-endian format when they are written to disk.
67021532e8aSBarry Smith   When PETSc is configured using `./configure with --with-64-bit-indices` the integers are written to the
6717de69702SBarry Smith   file as 64-bit integers, this means they can only be read back in when the option `--with-64-bit-indices`
67221532e8aSBarry Smith   is used.
673e5c89e4eSSatish Balay 
674811af0c4SBarry Smith   Because byte-swapping may be done on the values in data it cannot be declared const
675300a7f5bSBarry Smith 
676bfbbc7b7SBarry Smith   This is NOT like `PetscSynchronizedFPrintf()`! This routine ignores calls on all but MPI rank 0,
67721532e8aSBarry Smith   while `PetscSynchronizedFPrintf()` has all MPI processes print their strings in order.
6781d280d73SBarry Smith 
679db781477SPatrick Sanan .seealso: `PetscBinaryWrite()`, `PetscBinaryOpen()`, `PetscBinaryClose()`, `PetscBinaryRead()`, `PetscBinarySynchronizedRead()`,
680db781477SPatrick Sanan           `PetscBinarySynchronizedSeek()`
681e5c89e4eSSatish Balay @*/
682d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscBinarySynchronizedWrite(MPI_Comm comm, int fd, const void *p, PetscInt n, PetscDataType type)
683d71ae5a4SJacob Faibussowitsch {
684e5c89e4eSSatish Balay   PetscMPIInt rank;
685e5c89e4eSSatish Balay 
686e5c89e4eSSatish Balay   PetscFunctionBegin;
6879566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
68848a46eb9SPierre Jolivet   if (rank == 0) PetscCall(PetscBinaryWrite(fd, p, n, type));
6893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
690e5c89e4eSSatish Balay }
691e5c89e4eSSatish Balay 
692e5c89e4eSSatish Balay /*@C
6931d280d73SBarry Smith   PetscBinarySynchronizedSeek - Moves the file pointer on a PETSc binary file.
694e5c89e4eSSatish Balay 
695e5c89e4eSSatish Balay   Input Parameters:
69610450e9eSJacob Faibussowitsch + comm   - the communicator to read with
69710450e9eSJacob Faibussowitsch . fd     - the file
69816a05f60SBarry Smith . whence - see `PetscBinarySeekType` for possible values
699811af0c4SBarry Smith - off    - number of bytes to move. Use `PETSC_BINARY_INT_SIZE`, `PETSC_BINARY_SCALAR_SIZE`,
700811af0c4SBarry Smith             etc. in your calculation rather than `sizeof()` to compute byte lengths.
701e5c89e4eSSatish Balay 
702e5c89e4eSSatish Balay   Output Parameter:
703e5c89e4eSSatish Balay . offset - new offset in file
704e5c89e4eSSatish Balay 
705e5c89e4eSSatish Balay   Level: developer
706e5c89e4eSSatish Balay 
70716a05f60SBarry Smith .seealso: `PetscBinaryRead()`, `PetscBinarySeekType`, `PetscBinaryWrite()`, `PetscBinaryOpen()`, `PetscBinarySynchronizedWrite()`, `PetscBinarySynchronizedRead()`,
70842747ad1SJacob Faibussowitsch 
709e5c89e4eSSatish Balay @*/
710d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscBinarySynchronizedSeek(MPI_Comm comm, int fd, off_t off, PetscBinarySeekType whence, off_t *offset)
711d71ae5a4SJacob Faibussowitsch {
712e5c89e4eSSatish Balay   PetscMPIInt rank;
713e5c89e4eSSatish Balay 
714e5c89e4eSSatish Balay   PetscFunctionBegin;
7159566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
71648a46eb9SPierre Jolivet   if (rank == 0) PetscCall(PetscBinarySeek(fd, off, whence, offset));
7173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
718e5c89e4eSSatish Balay }
719e5c89e4eSSatish Balay 
7200fc9d207SBarry Smith #if defined(PETSC_HAVE_MPIIO)
721e39fd77fSBarry Smith 
722951e3c8eSBarry Smith   #if defined(PETSC_USE_PETSC_MPI_EXTERNAL32)
723e39fd77fSBarry Smith /*
724e39fd77fSBarry Smith       MPICH does not provide the external32 representation for MPI_File_set_view() so we need to provide the functions.
725e39fd77fSBarry Smith     These are set into MPI in PetscInitialize() via MPI_Register_datarep()
726e39fd77fSBarry Smith 
727e39fd77fSBarry Smith     Note I use PetscMPIInt for the MPI error codes since that is what MPI uses (instead of the standard PetscErrorCode)
728e39fd77fSBarry Smith 
729951e3c8eSBarry Smith     The next three routines are not used because MPICH does not support their use
730e39fd77fSBarry Smith 
731e39fd77fSBarry Smith */
732d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscMPIInt PetscDataRep_extent_fn(MPI_Datatype datatype, MPI_Aint *file_extent, void *extra_state)
733d71ae5a4SJacob Faibussowitsch {
734e39fd77fSBarry Smith   MPI_Aint    ub;
735e39fd77fSBarry Smith   PetscMPIInt ierr;
736e39fd77fSBarry Smith 
737e39fd77fSBarry Smith   ierr = MPI_Type_get_extent(datatype, &ub, file_extent);
738e39fd77fSBarry Smith   return ierr;
739e39fd77fSBarry Smith }
740e39fd77fSBarry Smith 
741d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscMPIInt PetscDataRep_read_conv_fn(void *userbuf, MPI_Datatype datatype, PetscMPIInt count, void *filebuf, MPI_Offset position, void *extra_state)
742d71ae5a4SJacob Faibussowitsch {
743e39fd77fSBarry Smith   PetscDataType pdtype;
744e39fd77fSBarry Smith   PetscMPIInt   ierr;
745e39fd77fSBarry Smith   size_t        dsize;
746e39fd77fSBarry Smith 
7479566063dSJacob Faibussowitsch   PetscCall(PetscMPIDataTypeToPetscDataType(datatype, &pdtype));
7489566063dSJacob Faibussowitsch   PetscCall(PetscDataTypeGetSize(pdtype, &dsize));
749e39fd77fSBarry Smith 
750e39fd77fSBarry Smith   /* offset is given in units of MPI_Datatype */
751e39fd77fSBarry Smith   userbuf = ((char *)userbuf) + dsize * position;
752e39fd77fSBarry Smith 
7539566063dSJacob Faibussowitsch   PetscCall(PetscMemcpy(userbuf, filebuf, count * dsize));
7549566063dSJacob Faibussowitsch   if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(userbuf, pdtype, count));
755e39fd77fSBarry Smith   return ierr;
756e39fd77fSBarry Smith }
757e39fd77fSBarry Smith 
758d71ae5a4SJacob Faibussowitsch PetscMPIInt PetscDataRep_write_conv_fn(void *userbuf, MPI_Datatype datatype, PetscMPIInt count, void *filebuf, MPI_Offset position, void *extra_state)
759d71ae5a4SJacob Faibussowitsch {
760e39fd77fSBarry Smith   PetscDataType pdtype;
761e39fd77fSBarry Smith   PetscMPIInt   ierr;
762e39fd77fSBarry Smith   size_t        dsize;
763e39fd77fSBarry Smith 
7649566063dSJacob Faibussowitsch   PetscCall(PetscMPIDataTypeToPetscDataType(datatype, &pdtype));
7659566063dSJacob Faibussowitsch   PetscCall(PetscDataTypeGetSize(pdtype, &dsize));
766e39fd77fSBarry Smith 
767e39fd77fSBarry Smith   /* offset is given in units of MPI_Datatype */
768e39fd77fSBarry Smith   userbuf = ((char *)userbuf) + dsize * position;
769e39fd77fSBarry Smith 
7709566063dSJacob Faibussowitsch   PetscCall(PetscMemcpy(filebuf, userbuf, count * dsize));
7719566063dSJacob Faibussowitsch   if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(filebuf, pdtype, count));
772e39fd77fSBarry Smith   return ierr;
773e39fd77fSBarry Smith }
774951e3c8eSBarry Smith   #endif
775e39fd77fSBarry Smith 
776d71ae5a4SJacob Faibussowitsch PetscErrorCode MPIU_File_write_all(MPI_File fd, void *data, PetscMPIInt cnt, MPI_Datatype dtype, MPI_Status *status)
777d71ae5a4SJacob Faibussowitsch {
778e39fd77fSBarry Smith   PetscDataType pdtype;
77930815ce0SLisandro Dalcin 
780e39fd77fSBarry Smith   PetscFunctionBegin;
7819566063dSJacob Faibussowitsch   PetscCall(PetscMPIDataTypeToPetscDataType(dtype, &pdtype));
7829566063dSJacob Faibussowitsch   if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(data, pdtype, cnt));
7839566063dSJacob Faibussowitsch   PetscCallMPI(MPI_File_write_all(fd, data, cnt, dtype, status));
7849566063dSJacob Faibussowitsch   if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(data, pdtype, cnt));
7853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
786e39fd77fSBarry Smith }
787e39fd77fSBarry Smith 
788d71ae5a4SJacob Faibussowitsch PetscErrorCode MPIU_File_read_all(MPI_File fd, void *data, PetscMPIInt cnt, MPI_Datatype dtype, MPI_Status *status)
789d71ae5a4SJacob Faibussowitsch {
790e39fd77fSBarry Smith   PetscDataType pdtype;
791e39fd77fSBarry Smith 
792e39fd77fSBarry Smith   PetscFunctionBegin;
7939566063dSJacob Faibussowitsch   PetscCall(PetscMPIDataTypeToPetscDataType(dtype, &pdtype));
7949566063dSJacob Faibussowitsch   PetscCallMPI(MPI_File_read_all(fd, data, cnt, dtype, status));
7959566063dSJacob Faibussowitsch   if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(data, pdtype, cnt));
7963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
797e39fd77fSBarry Smith }
79830815ce0SLisandro Dalcin 
799d71ae5a4SJacob Faibussowitsch PetscErrorCode MPIU_File_write_at(MPI_File fd, MPI_Offset off, void *data, PetscMPIInt cnt, MPI_Datatype dtype, MPI_Status *status)
800d71ae5a4SJacob Faibussowitsch {
801c4e82887SLisandro Dalcin   PetscDataType pdtype;
802c4e82887SLisandro Dalcin 
803c4e82887SLisandro Dalcin   PetscFunctionBegin;
8049566063dSJacob Faibussowitsch   PetscCall(PetscMPIDataTypeToPetscDataType(dtype, &pdtype));
8059566063dSJacob Faibussowitsch   if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(data, pdtype, cnt));
8069566063dSJacob Faibussowitsch   PetscCallMPI(MPI_File_write_at(fd, off, data, cnt, dtype, status));
8079566063dSJacob Faibussowitsch   if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(data, pdtype, cnt));
8083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
809c4e82887SLisandro Dalcin }
810c4e82887SLisandro Dalcin 
811d71ae5a4SJacob Faibussowitsch PetscErrorCode MPIU_File_read_at(MPI_File fd, MPI_Offset off, void *data, PetscMPIInt cnt, MPI_Datatype dtype, MPI_Status *status)
812d71ae5a4SJacob Faibussowitsch {
813c4e82887SLisandro Dalcin   PetscDataType pdtype;
814c4e82887SLisandro Dalcin 
815c4e82887SLisandro Dalcin   PetscFunctionBegin;
8169566063dSJacob Faibussowitsch   PetscCall(PetscMPIDataTypeToPetscDataType(dtype, &pdtype));
8179566063dSJacob Faibussowitsch   PetscCallMPI(MPI_File_read_at(fd, off, data, cnt, dtype, status));
8189566063dSJacob Faibussowitsch   if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(data, pdtype, cnt));
8193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
820c4e82887SLisandro Dalcin }
821c4e82887SLisandro Dalcin 
822d71ae5a4SJacob Faibussowitsch PetscErrorCode MPIU_File_write_at_all(MPI_File fd, MPI_Offset off, void *data, PetscMPIInt cnt, MPI_Datatype dtype, MPI_Status *status)
823d71ae5a4SJacob Faibussowitsch {
824c4e82887SLisandro Dalcin   PetscDataType pdtype;
825c4e82887SLisandro Dalcin 
826c4e82887SLisandro Dalcin   PetscFunctionBegin;
8279566063dSJacob Faibussowitsch   PetscCall(PetscMPIDataTypeToPetscDataType(dtype, &pdtype));
8289566063dSJacob Faibussowitsch   if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(data, pdtype, cnt));
8299566063dSJacob Faibussowitsch   PetscCallMPI(MPI_File_write_at_all(fd, off, data, cnt, dtype, status));
8309566063dSJacob Faibussowitsch   if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(data, pdtype, cnt));
8313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
832c4e82887SLisandro Dalcin }
833c4e82887SLisandro Dalcin 
834d71ae5a4SJacob Faibussowitsch PetscErrorCode MPIU_File_read_at_all(MPI_File fd, MPI_Offset off, void *data, PetscMPIInt cnt, MPI_Datatype dtype, MPI_Status *status)
835d71ae5a4SJacob Faibussowitsch {
836c4e82887SLisandro Dalcin   PetscDataType pdtype;
837c4e82887SLisandro Dalcin 
838c4e82887SLisandro Dalcin   PetscFunctionBegin;
8399566063dSJacob Faibussowitsch   PetscCall(PetscMPIDataTypeToPetscDataType(dtype, &pdtype));
8409566063dSJacob Faibussowitsch   PetscCallMPI(MPI_File_read_at_all(fd, off, data, cnt, dtype, status));
8419566063dSJacob Faibussowitsch   if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(data, pdtype, cnt));
8423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
843c4e82887SLisandro Dalcin }
844c4e82887SLisandro Dalcin 
845951e3c8eSBarry Smith #endif
846