xref: /petsc/src/sys/fileio/sysio.c (revision cc4c1da905d89950b196b027190941013bd3e15a)
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
17015229ffcSPierre Jolivet   The complex case is dealt 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 
273*cc4c1da9SBarry Smith   Fortran Note:
274*cc4c1da9SBarry Smith   There are different functions for each datatype, for example `PetscBinaryReadInt()`
275*cc4c1da9SBarry Smith 
276db781477SPatrick Sanan .seealso: `PetscBinaryWrite()`, `PetscBinaryOpen()`, `PetscBinaryClose()`, `PetscViewerBinaryGetDescriptor()`, `PetscBinarySynchronizedWrite()`,
277db781477SPatrick Sanan           `PetscBinarySynchronizedRead()`, `PetscBinarySynchronizedSeek()`
278e5c89e4eSSatish Balay @*/
279d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscBinaryRead(int fd, void *data, PetscInt num, PetscInt *count, PetscDataType type)
280d71ae5a4SJacob Faibussowitsch {
2819860990eSLisandro Dalcin   size_t typesize, m = (size_t)num, n = 0, maxblock = 65536;
2829860990eSLisandro Dalcin   char  *p = (char *)data;
2837a881295SBarry Smith #if defined(PETSC_USE_REAL___FLOAT128)
284cba51d77SBarry Smith   PetscBool readdouble = PETSC_FALSE;
2859860990eSLisandro Dalcin   double   *pdouble;
2867a881295SBarry Smith #endif
2879860990eSLisandro Dalcin   void *ptmp  = data;
28805acbc63SBarry Smith   char *fname = NULL;
289e5c89e4eSSatish Balay 
290e5c89e4eSSatish Balay   PetscFunctionBegin;
2919860990eSLisandro Dalcin   if (count) *count = 0;
29208401ef6SPierre Jolivet   PetscCheck(num >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to read a negative amount of data %" PetscInt_FMT, num);
2933ba16761SJacob Faibussowitsch   if (!num) PetscFunctionReturn(PETSC_SUCCESS);
294e5c89e4eSSatish Balay 
2952d53ad75SBarry Smith   if (type == PETSC_FUNCTION) {
2962d53ad75SBarry Smith     m     = 64;
2972d53ad75SBarry Smith     type  = PETSC_CHAR;
29805acbc63SBarry Smith     fname = (char *)malloc(m * sizeof(char));
2999860990eSLisandro Dalcin     p     = (char *)fname;
3002d53ad75SBarry Smith     ptmp  = (void *)fname;
30128b400f6SJacob Faibussowitsch     PetscCheck(fname, PETSC_COMM_SELF, PETSC_ERR_MEM, "Cannot allocate space for function name");
3022d53ad75SBarry Smith   }
3039860990eSLisandro Dalcin   if (type == PETSC_BIT_LOGICAL) m = PetscBTLength(m);
3042d53ad75SBarry Smith 
3059566063dSJacob Faibussowitsch   PetscCall(PetscDataTypeGetSize(type, &typesize));
306e5c89e4eSSatish Balay 
3077a881295SBarry Smith #if defined(PETSC_USE_REAL___FLOAT128)
3089566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(NULL, NULL, "-binary_read_double", &readdouble, NULL));
3097a881295SBarry Smith   /* If using __float128 precision we still read in doubles from file */
3109860990eSLisandro Dalcin   if ((type == PETSC_REAL || type == PETSC_COMPLEX) && readdouble) {
3119860990eSLisandro Dalcin     PetscInt cnt = num * ((type == PETSC_REAL) ? 1 : 2);
3129566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(cnt, &pdouble));
3139860990eSLisandro Dalcin     p = (char *)pdouble;
3149860990eSLisandro Dalcin     typesize /= 2;
3157a881295SBarry Smith   }
3167a881295SBarry Smith #endif
3177a881295SBarry Smith 
3189860990eSLisandro Dalcin   m *= typesize;
3199860990eSLisandro Dalcin 
320e5c89e4eSSatish Balay   while (m) {
3219860990eSLisandro Dalcin     size_t len = (m < maxblock) ? m : maxblock;
3229860990eSLisandro Dalcin     int    ret = (int)read(fd, p, len);
3239860990eSLisandro Dalcin     if (ret < 0 && errno == EINTR) continue;
3249860990eSLisandro Dalcin     if (!ret && len > 0) break; /* Proxy for EOF */
325bf31d2d3SBarry Smith     PetscCheck(ret >= 0, PETSC_COMM_SELF, PETSC_ERR_FILE_READ, "Error reading from file due to \"%s\"", strerror(errno));
326ff9f933bSBarry Smith     m -= (size_t)ret;
3279860990eSLisandro Dalcin     p += ret;
328ff9f933bSBarry Smith     n += (size_t)ret;
329e5c89e4eSSatish Balay   }
33008401ef6SPierre Jolivet   PetscCheck(!m || count, PETSC_COMM_SELF, PETSC_ERR_FILE_READ, "Read past end of file");
3319860990eSLisandro Dalcin 
3329860990eSLisandro Dalcin   num = (PetscInt)(n / typesize); /* Should we require `n % typesize == 0` ? */
3339860990eSLisandro Dalcin   if (count) *count = num;        /* TODO: This is most likely wrong for PETSC_BIT_LOGICAL */
3347a881295SBarry Smith 
3357a881295SBarry Smith #if defined(PETSC_USE_REAL___FLOAT128)
3369860990eSLisandro Dalcin   if ((type == PETSC_REAL || type == PETSC_COMPLEX) && readdouble) {
3379860990eSLisandro Dalcin     PetscInt   i, cnt = num * ((type == PETSC_REAL) ? 1 : 2);
3389860990eSLisandro Dalcin     PetscReal *preal = (PetscReal *)data;
3399566063dSJacob Faibussowitsch     if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwapDouble(pdouble, cnt));
3409860990eSLisandro Dalcin     for (i = 0; i < cnt; i++) preal[i] = pdouble[i];
3419566063dSJacob Faibussowitsch     PetscCall(PetscFree(pdouble));
3423ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
3437a881295SBarry Smith   }
3447a881295SBarry Smith #endif
3457a881295SBarry Smith 
3469566063dSJacob Faibussowitsch   if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(ptmp, type, num));
347e5c89e4eSSatish Balay 
34805acbc63SBarry Smith   if (type == PETSC_FUNCTION) {
3492d53ad75SBarry Smith #if defined(PETSC_SERIALIZE_FUNCTIONS)
3509566063dSJacob Faibussowitsch     PetscCall(PetscDLSym(NULL, fname, (void **)data));
3512d53ad75SBarry Smith #else
3529860990eSLisandro Dalcin     *(void **)data = NULL;
3532d53ad75SBarry Smith #endif
35405acbc63SBarry Smith     free(fname);
3552d53ad75SBarry Smith   }
3563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
357e5c89e4eSSatish Balay }
3589860990eSLisandro Dalcin 
359a9acdec7SBarry Smith /*@C
360e5c89e4eSSatish Balay   PetscBinaryWrite - Writes to a binary file.
361e5c89e4eSSatish Balay 
362e5c89e4eSSatish Balay   Not Collective
363e5c89e4eSSatish Balay 
364e5c89e4eSSatish Balay   Input Parameters:
365e5c89e4eSSatish Balay + fd   - the file
36621532e8aSBarry Smith . p    - the buffer, an array of the type that matches the value in `type`
367e5c89e4eSSatish Balay . n    - the number of items to write
368811af0c4SBarry Smith - type - the type of items to read (`PETSC_INT`, `PETSC_REAL` or `PETSC_SCALAR`)
369e5c89e4eSSatish Balay 
370e5c89e4eSSatish Balay   Level: advanced
371e5c89e4eSSatish Balay 
372e5c89e4eSSatish Balay   Notes:
373811af0c4SBarry Smith   `PetscBinaryWrite()` uses byte swapping to work on all machines; the files
374f253e43cSLisandro Dalcin   are written using big-endian ordering to the file. On little-endian machines the numbers
375e5c89e4eSSatish Balay   are converted to the big-endian format when they are written to disk.
37621532e8aSBarry Smith   When PETSc is configured using `./configure with --with-64-bit-indices` the integers are written to the
3777de69702SBarry Smith   file as 64-bit integers, this means they can only be read back in when the option `--with-64-bit-indices`
37854f21887SBarry Smith   is used.
379e5c89e4eSSatish Balay 
38021532e8aSBarry Smith   If running with `__float128` precision the output of `PETSC_REAL` is in `__float128` unless one uses the `-binary_write_double` option
3810da86b62SBarry Smith 
382bfbbc7b7SBarry Smith   The buffer `p` should be read-write buffer, and not static data.
383e5c89e4eSSatish Balay   This way, byte-swapping is done in-place, and then the buffer is
384e5c89e4eSSatish Balay   written to the file.
385e5c89e4eSSatish Balay 
386e5c89e4eSSatish Balay   This routine restores the original contents of the buffer, after
387e5c89e4eSSatish Balay   it is written to the file. This is done by byte-swapping in-place
388f253e43cSLisandro Dalcin   the second time.
389e5c89e4eSSatish Balay 
390300a7f5bSBarry Smith   Because byte-swapping may be done on the values in data it cannot be declared const
391300a7f5bSBarry Smith 
392*cc4c1da9SBarry Smith   Fortran Note:
393*cc4c1da9SBarry Smith   There are different functions for each datatype, for example `PetscBinaryWriteInt()`
394*cc4c1da9SBarry Smith 
395db781477SPatrick Sanan .seealso: `PetscBinaryRead()`, `PetscBinaryOpen()`, `PetscBinaryClose()`, `PetscViewerBinaryGetDescriptor()`, `PetscBinarySynchronizedWrite()`,
396db781477SPatrick Sanan           `PetscBinarySynchronizedRead()`, `PetscBinarySynchronizedSeek()`
397e5c89e4eSSatish Balay @*/
398d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscBinaryWrite(int fd, const void *p, PetscInt n, PetscDataType type)
399d71ae5a4SJacob Faibussowitsch {
400f253e43cSLisandro Dalcin   const char *pp = (char *)p;
401e5c89e4eSSatish Balay   int         err, wsize;
402e5c89e4eSSatish Balay   size_t      m = (size_t)n, maxblock = 65536;
403f253e43cSLisandro Dalcin   const void *ptmp  = p;
40405acbc63SBarry Smith   char       *fname = NULL;
4050da86b62SBarry Smith #if defined(PETSC_USE_REAL___FLOAT128)
406df40af56SBarry Smith   PetscBool  writedouble = PETSC_FALSE;
4070da86b62SBarry Smith   double    *ppp;
4080da86b62SBarry Smith   PetscReal *pv;
4090da86b62SBarry Smith   PetscInt   i;
4100da86b62SBarry Smith #endif
41141f502e3SPatrick Sanan   PetscDataType wtype = type;
412e5c89e4eSSatish Balay 
413e5c89e4eSSatish Balay   PetscFunctionBegin;
41408401ef6SPierre Jolivet   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to write a negative amount of data %" PetscInt_FMT, n);
4153ba16761SJacob Faibussowitsch   if (!n) PetscFunctionReturn(PETSC_SUCCESS);
416e5c89e4eSSatish Balay 
4172d53ad75SBarry Smith   if (type == PETSC_FUNCTION) {
4182d53ad75SBarry Smith #if defined(PETSC_SERIALIZE_FUNCTIONS)
4192d53ad75SBarry Smith     const char *fnametmp;
4202d53ad75SBarry Smith #endif
4212d53ad75SBarry Smith     m     = 64;
422e25ab156SSatish Balay     fname = (char *)malloc(m * sizeof(char));
42328b400f6SJacob Faibussowitsch     PetscCheck(fname, PETSC_COMM_SELF, PETSC_ERR_MEM, "Cannot allocate space for function name");
42405acbc63SBarry Smith #if defined(PETSC_SERIALIZE_FUNCTIONS)
42508401ef6SPierre Jolivet     PetscCheck(n <= 1, PETSC_COMM_SELF, PETSC_ERR_SUP, "Can only binary view a single function at a time");
4269566063dSJacob Faibussowitsch     PetscCall(PetscFPTFind(*(void **)p, &fnametmp));
4279566063dSJacob Faibussowitsch     PetscCall(PetscStrncpy(fname, fnametmp, m));
42805acbc63SBarry Smith #else
4299566063dSJacob Faibussowitsch     PetscCall(PetscStrncpy(fname, "", m));
43005acbc63SBarry Smith #endif
43101963f56SBarry Smith     wtype = PETSC_CHAR;
4322d53ad75SBarry Smith     pp    = (char *)fname;
4332d53ad75SBarry Smith     ptmp  = (void *)fname;
4342d53ad75SBarry Smith   }
4352d53ad75SBarry Smith 
4360da86b62SBarry Smith #if defined(PETSC_USE_REAL___FLOAT128)
4379566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(NULL, NULL, "-binary_write_double", &writedouble, NULL));
4380da86b62SBarry Smith   /* If using __float128 precision we still write in doubles to file */
439501ae109SJose E. Roman   if ((type == PETSC_SCALAR || type == PETSC_REAL || type == PETSC_COMPLEX) && writedouble) {
44041f502e3SPatrick Sanan     wtype = PETSC_DOUBLE;
4419566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(n, &ppp));
4420da86b62SBarry Smith     pv = (PetscReal *)pp;
443ad540459SPierre Jolivet     for (i = 0; i < n; i++) ppp[i] = (double)pv[i];
4440da86b62SBarry Smith     pp   = (char *)ppp;
4450da86b62SBarry Smith     ptmp = (char *)ppp;
4460da86b62SBarry Smith   }
4470da86b62SBarry Smith #endif
4480da86b62SBarry Smith 
44941f502e3SPatrick Sanan   if (wtype == PETSC_INT) m *= sizeof(PetscInt);
45041f502e3SPatrick Sanan   else if (wtype == PETSC_SCALAR) m *= sizeof(PetscScalar);
451501ae109SJose E. Roman #if defined(PETSC_HAVE_COMPLEX)
452501ae109SJose E. Roman   else if (wtype == PETSC_COMPLEX) m *= sizeof(PetscComplex);
453501ae109SJose E. Roman #endif
4544caf0332SSatish Balay   else if (wtype == PETSC_REAL) m *= sizeof(PetscReal);
45541f502e3SPatrick Sanan   else if (wtype == PETSC_DOUBLE) m *= sizeof(double);
45641f502e3SPatrick Sanan   else if (wtype == PETSC_FLOAT) m *= sizeof(float);
45741f502e3SPatrick Sanan   else if (wtype == PETSC_SHORT) m *= sizeof(short);
458972064b6SLisandro Dalcin   else if (wtype == PETSC_LONG) m *= sizeof(long);
45941f502e3SPatrick Sanan   else if (wtype == PETSC_CHAR) m *= sizeof(char);
46041f502e3SPatrick Sanan   else if (wtype == PETSC_ENUM) m *= sizeof(PetscEnum);
46141f502e3SPatrick Sanan   else if (wtype == PETSC_BOOL) m *= sizeof(PetscBool);
4629e3e4c22SLisandro Dalcin   else if (wtype == PETSC_INT64) m *= sizeof(PetscInt64);
4633321ca25SJames Wright   else if (wtype == PETSC_INT32) m *= sizeof(PetscInt32);
46441f502e3SPatrick Sanan   else if (wtype == PETSC_BIT_LOGICAL) m = PetscBTLength(m) * sizeof(char);
4653321ca25SJames Wright   else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Unknown type: %d", wtype);
466e5c89e4eSSatish Balay 
4679566063dSJacob Faibussowitsch   if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap((void *)ptmp, wtype, n));
468e5c89e4eSSatish Balay 
469e5c89e4eSSatish Balay   while (m) {
470e5c89e4eSSatish Balay     wsize = (m < maxblock) ? m : maxblock;
471e5c89e4eSSatish Balay     err   = write(fd, pp, wsize);
472e5c89e4eSSatish Balay     if (err < 0 && errno == EINTR) continue;
473bf31d2d3SBarry 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));
474e5c89e4eSSatish Balay     m -= wsize;
475e5c89e4eSSatish Balay     pp += wsize;
476e5c89e4eSSatish Balay   }
477e5c89e4eSSatish Balay 
4789566063dSJacob Faibussowitsch   if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap((void *)ptmp, wtype, n));
479f253e43cSLisandro Dalcin 
480ad540459SPierre Jolivet   if (type == PETSC_FUNCTION) free(fname);
4810da86b62SBarry Smith #if defined(PETSC_USE_REAL___FLOAT128)
48248a46eb9SPierre Jolivet   if ((type == PETSC_SCALAR || type == PETSC_REAL || type == PETSC_COMPLEX) && writedouble) PetscCall(PetscFree(ppp));
4830da86b62SBarry Smith #endif
4843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
485e5c89e4eSSatish Balay }
486e5c89e4eSSatish Balay 
487*cc4c1da9SBarry Smith /*@
488e5c89e4eSSatish Balay   PetscBinaryOpen - Opens a PETSc binary file.
489e5c89e4eSSatish Balay 
490e5c89e4eSSatish Balay   Not Collective
491e5c89e4eSSatish Balay 
492e5c89e4eSSatish Balay   Input Parameters:
493e5c89e4eSSatish Balay + name - filename
494fe8e7dddSPierre Jolivet - mode - open mode of binary file, one of `FILE_MODE_READ`, `FILE_MODE_WRITE`, `FILE_MODE_APPEND`
495e5c89e4eSSatish Balay 
496e5c89e4eSSatish Balay   Output Parameter:
497e5c89e4eSSatish Balay . fd - the file
498e5c89e4eSSatish Balay 
499e5c89e4eSSatish Balay   Level: advanced
500e5c89e4eSSatish Balay 
501db781477SPatrick Sanan .seealso: `PetscBinaryRead()`, `PetscBinaryWrite()`, `PetscFileMode`, `PetscViewerFileSetMode()`, `PetscViewerBinaryGetDescriptor()`,
502db781477SPatrick Sanan           `PetscBinarySynchronizedWrite()`, `PetscBinarySynchronizedRead()`, `PetscBinarySynchronizedSeek()`
503e5c89e4eSSatish Balay @*/
504d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscBinaryOpen(const char name[], PetscFileMode mode, int *fd)
505d71ae5a4SJacob Faibussowitsch {
506e5c89e4eSSatish Balay   PetscFunctionBegin;
507cc843e7aSLisandro Dalcin   switch (mode) {
508d71ae5a4SJacob Faibussowitsch   case FILE_MODE_READ:
509d71ae5a4SJacob Faibussowitsch     *fd = open(name, O_BINARY | O_RDONLY, 0);
510d71ae5a4SJacob Faibussowitsch     break;
511d71ae5a4SJacob Faibussowitsch   case FILE_MODE_WRITE:
512d71ae5a4SJacob Faibussowitsch     *fd = open(name, O_BINARY | O_WRONLY | O_CREAT | O_TRUNC, 0666);
513d71ae5a4SJacob Faibussowitsch     break;
514d71ae5a4SJacob Faibussowitsch   case FILE_MODE_APPEND:
515d71ae5a4SJacob Faibussowitsch     *fd = open(name, O_BINARY | O_WRONLY | O_APPEND, 0);
516d71ae5a4SJacob Faibussowitsch     break;
517d71ae5a4SJacob Faibussowitsch   default:
518d71ae5a4SJacob Faibussowitsch     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Unsupported file mode %s", PetscFileModes[mode]);
519e5c89e4eSSatish Balay   }
520bf31d2d3SBarry 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));
5213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
522e5c89e4eSSatish Balay }
523e5c89e4eSSatish Balay 
524e30d2299SSatish Balay /*@
525e5c89e4eSSatish Balay   PetscBinaryClose - Closes a PETSc binary file.
526e5c89e4eSSatish Balay 
527e5c89e4eSSatish Balay   Not Collective
528e5c89e4eSSatish Balay 
529e5c89e4eSSatish Balay   Output Parameter:
530e5c89e4eSSatish Balay . fd - the file
531e5c89e4eSSatish Balay 
532e5c89e4eSSatish Balay   Level: advanced
533e5c89e4eSSatish Balay 
534db781477SPatrick Sanan .seealso: `PetscBinaryRead()`, `PetscBinaryWrite()`, `PetscBinaryOpen()`, `PetscBinarySynchronizedWrite()`, `PetscBinarySynchronizedRead()`,
535db781477SPatrick Sanan           `PetscBinarySynchronizedSeek()`
536e5c89e4eSSatish Balay @*/
537d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscBinaryClose(int fd)
538d71ae5a4SJacob Faibussowitsch {
539e5c89e4eSSatish Balay   PetscFunctionBegin;
540cc73adaaSBarry Smith   PetscCheck(!close(fd), PETSC_COMM_SELF, PETSC_ERR_SYS, "close() failed on file descriptor");
5413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
542e5c89e4eSSatish Balay }
543e5c89e4eSSatish Balay 
544e8976759SBarry Smith /*@C
545e5c89e4eSSatish Balay   PetscBinarySeek - Moves the file pointer on a PETSc binary file.
546e5c89e4eSSatish Balay 
547*cc4c1da9SBarry Smith   Not Collective, No Fortran Support
548e5c89e4eSSatish Balay 
549e5c89e4eSSatish Balay   Input Parameters:
550e5c89e4eSSatish Balay + fd     - the file
551811af0c4SBarry Smith . off    - number of bytes to move. Use `PETSC_BINARY_INT_SIZE`, `PETSC_BINARY_SCALAR_SIZE`,
55221532e8aSBarry Smith            etc. in your calculation rather than `sizeof()` to compute byte lengths.
55316a05f60SBarry Smith - whence - see `PetscBinarySeekType` for possible values
554e5c89e4eSSatish Balay 
555e5c89e4eSSatish Balay   Output Parameter:
556e5c89e4eSSatish Balay . offset - new offset in file
557e5c89e4eSSatish Balay 
558e5c89e4eSSatish Balay   Level: developer
559e5c89e4eSSatish Balay 
56016a05f60SBarry Smith .seealso: `PetscBinaryRead()`, `PetscBinarySeekType`, `PetscBinaryWrite()`, `PetscBinaryOpen()`, `PetscBinarySynchronizedWrite()`, `PetscBinarySynchronizedRead()`,
561db781477SPatrick Sanan           `PetscBinarySynchronizedSeek()`
562e5c89e4eSSatish Balay @*/
563d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscBinarySeek(int fd, off_t off, PetscBinarySeekType whence, off_t *offset)
564d71ae5a4SJacob Faibussowitsch {
565e5c89e4eSSatish Balay   int iwhence = 0;
566e5c89e4eSSatish Balay 
567e5c89e4eSSatish Balay   PetscFunctionBegin;
568a297a907SKarl Rupp   if (whence == PETSC_BINARY_SEEK_SET) iwhence = SEEK_SET;
569a297a907SKarl Rupp   else if (whence == PETSC_BINARY_SEEK_CUR) iwhence = SEEK_CUR;
570a297a907SKarl Rupp   else if (whence == PETSC_BINARY_SEEK_END) iwhence = SEEK_END;
571a297a907SKarl Rupp   else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Unknown seek location");
572e5c89e4eSSatish Balay #if defined(PETSC_HAVE_LSEEK)
573e5c89e4eSSatish Balay   *offset = lseek(fd, off, iwhence);
574e5c89e4eSSatish Balay #elif defined(PETSC_HAVE__LSEEK)
575e5c89e4eSSatish Balay   *offset = _lseek(fd, (long)off, iwhence);
576e5c89e4eSSatish Balay #else
577e32f2f54SBarry Smith   SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP_SYS, "System does not have a way of seeking on a file");
578e5c89e4eSSatish Balay #endif
5793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
580e5c89e4eSSatish Balay }
581e5c89e4eSSatish Balay 
582e5c89e4eSSatish Balay /*@C
58321532e8aSBarry Smith   PetscBinarySynchronizedRead - Reads from a binary file, all MPI processes get the same values
584e5c89e4eSSatish Balay 
585*cc4c1da9SBarry Smith   Collective, No Fortran Support
586e5c89e4eSSatish Balay 
587e5c89e4eSSatish Balay   Input Parameters:
588e5c89e4eSSatish Balay + comm - the MPI communicator
5899860990eSLisandro Dalcin . fd   - the file descriptor
5909860990eSLisandro Dalcin . num  - the maximum number of items to read
591811af0c4SBarry Smith - type - the type of items to read (`PETSC_INT`, `PETSC_REAL`, `PETSC_SCALAR`, etc.)
592e5c89e4eSSatish Balay 
593e5c89e4eSSatish Balay   Output Parameters:
59421532e8aSBarry Smith + data  - the buffer, an array of the type that matches the value in `type`
5959860990eSLisandro Dalcin - count - the number of items read, optional
596e5c89e4eSSatish Balay 
597e5c89e4eSSatish Balay   Level: developer
598e5c89e4eSSatish Balay 
599e5c89e4eSSatish Balay   Notes:
600811af0c4SBarry Smith   Does a `PetscBinaryRead()` followed by an `MPI_Bcast()`
601e5c89e4eSSatish Balay 
60221532e8aSBarry Smith   If `count` is not provided and the number of items read is less than
6039860990eSLisandro Dalcin   the maximum number of items to read, then this routine errors.
6049860990eSLisandro Dalcin 
605811af0c4SBarry Smith   `PetscBinarySynchronizedRead()` uses byte swapping to work on all machines.
60621532e8aSBarry Smith   The files  are written using big-endian ordering to the file. On little-endian machines the numbers
60721532e8aSBarry Smith   are converted to the big-endian format when they are written to disk.
60821532e8aSBarry Smith   When PETSc is configured using `./configure with --with-64-bit-indices` the integers are written to the
6097de69702SBarry Smith   file as 64-bit integers, this means they can only be read back in when the option `--with-64-bit-indices`
61021532e8aSBarry Smith   is used.
611e5c89e4eSSatish Balay 
612db781477SPatrick Sanan .seealso: `PetscBinaryWrite()`, `PetscBinaryOpen()`, `PetscBinaryClose()`, `PetscBinaryRead()`, `PetscBinarySynchronizedWrite()`,
613db781477SPatrick Sanan           `PetscBinarySynchronizedSeek()`
614e5c89e4eSSatish Balay @*/
615d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscBinarySynchronizedRead(MPI_Comm comm, int fd, void *data, PetscInt num, PetscInt *count, PetscDataType type)
616d71ae5a4SJacob Faibussowitsch {
6178b8bf82cSBarry Smith   PetscMPIInt  rank, size;
618e5c89e4eSSatish Balay   MPI_Datatype mtype;
6199860990eSLisandro Dalcin   PetscInt     ibuf[2] = {0, 0};
62005acbc63SBarry Smith   char        *fname   = NULL;
6219860990eSLisandro Dalcin   void        *fptr    = NULL;
622e5c89e4eSSatish Balay 
623e5c89e4eSSatish Balay   PetscFunctionBegin;
6242d53ad75SBarry Smith   if (type == PETSC_FUNCTION) {
6259860990eSLisandro Dalcin     num   = 64;
6262d53ad75SBarry Smith     type  = PETSC_CHAR;
6279860990eSLisandro Dalcin     fname = (char *)malloc(num * sizeof(char));
6289860990eSLisandro Dalcin     fptr  = data;
6299860990eSLisandro Dalcin     data  = (void *)fname;
63028b400f6SJacob Faibussowitsch     PetscCheck(fname, PETSC_COMM_SELF, PETSC_ERR_MEM, "Cannot allocate space for function name");
6312d53ad75SBarry Smith   }
6322d53ad75SBarry Smith 
6339566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
6349566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
635ad540459SPierre Jolivet   if (rank == 0) ibuf[0] = PetscBinaryRead(fd, data, num, count ? &ibuf[1] : NULL, type);
6369566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Bcast(ibuf, 2, MPIU_INT, 0, comm));
6379566063dSJacob Faibussowitsch   PetscCall((PetscErrorCode)ibuf[0]);
6388b8bf82cSBarry Smith 
6398b8bf82cSBarry 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 */
6408b8bf82cSBarry Smith   if (size > 1) {
6419566063dSJacob Faibussowitsch     PetscCall(PetscDataTypeToMPIDataType(type, &mtype));
6429566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Bcast(data, count ? ibuf[1] : num, 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 
660*cc4c1da9SBarry 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 
701*cc4c1da9SBarry Smith   No Fortran Support
702*cc4c1da9SBarry 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