xref: /petsc/src/sys/fileio/sysio.c (revision 372de11faf72df2eb4bae739d3ac5de9574185ef)
1e5c89e4eSSatish Balay 
2e5c89e4eSSatish Balay /*
3e5c89e4eSSatish Balay    This file contains simple binary read/write routines.
4e5c89e4eSSatish Balay  */
5e5c89e4eSSatish Balay 
6c6db04a5SJed Brown #include <petscsys.h>
7cc843e7aSLisandro Dalcin #include <petscbt.h>
8e5c89e4eSSatish Balay #include <errno.h>
9e5c89e4eSSatish Balay #include <fcntl.h>
10e5c89e4eSSatish Balay #if defined(PETSC_HAVE_UNISTD_H)
11e5c89e4eSSatish Balay   #include <unistd.h>
12e5c89e4eSSatish Balay #endif
13e5c89e4eSSatish Balay #if defined(PETSC_HAVE_IO_H)
14e5c89e4eSSatish Balay   #include <io.h>
15e5c89e4eSSatish Balay #endif
16cc843e7aSLisandro Dalcin #if !defined(PETSC_HAVE_O_BINARY)
17cc843e7aSLisandro Dalcin   #define O_BINARY 0
18cc843e7aSLisandro Dalcin #endif
19e5c89e4eSSatish Balay 
2002c9f0b5SLisandro Dalcin const char *const PetscFileModes[] = {"READ", "WRITE", "APPEND", "UPDATE", "APPEND_UPDATE", "PetscFileMode", "PETSC_FILE_", NULL};
21d6a4318aSJed Brown 
22e5c89e4eSSatish Balay /*
236de02169SBarry Smith   PetscByteSwapEnum - Swap bytes in a  PETSc Enum
24e5c89e4eSSatish Balay 
25e5c89e4eSSatish Balay */
26d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscByteSwapEnum(PetscEnum *buff, PetscInt n)
27d71ae5a4SJacob Faibussowitsch {
286de02169SBarry Smith   PetscInt  i, j;
290b20345dSBarry Smith   PetscEnum tmp = ENUM_DUMMY;
30e0890e22SSatish Balay   char     *ptr1, *ptr2 = (char *)&tmp;
31e5c89e4eSSatish Balay 
32e5c89e4eSSatish Balay   PetscFunctionBegin;
33e5c89e4eSSatish Balay   for (j = 0; j < n; j++) {
34e5c89e4eSSatish Balay     ptr1 = (char *)(buff + j);
35a297a907SKarl Rupp     for (i = 0; i < (PetscInt)sizeof(PetscEnum); i++) ptr2[i] = ptr1[sizeof(PetscEnum) - 1 - i];
36a297a907SKarl Rupp     for (i = 0; i < (PetscInt)sizeof(PetscEnum); i++) ptr1[i] = ptr2[i];
37e5c89e4eSSatish Balay   }
383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
39e5c89e4eSSatish Balay }
406de02169SBarry Smith 
416de02169SBarry Smith /*
42acfcf0e5SJed Brown   PetscByteSwapBool - Swap bytes in a  PETSc Bool
436de02169SBarry Smith 
446de02169SBarry Smith */
45d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscByteSwapBool(PetscBool *buff, PetscInt n)
46d71ae5a4SJacob Faibussowitsch {
476de02169SBarry Smith   PetscInt  i, j;
48ace3abfcSBarry Smith   PetscBool tmp = PETSC_FALSE;
49e0890e22SSatish Balay   char     *ptr1, *ptr2 = (char *)&tmp;
506de02169SBarry Smith 
516de02169SBarry Smith   PetscFunctionBegin;
526de02169SBarry Smith   for (j = 0; j < n; j++) {
536de02169SBarry Smith     ptr1 = (char *)(buff + j);
54a297a907SKarl Rupp     for (i = 0; i < (PetscInt)sizeof(PetscBool); i++) ptr2[i] = ptr1[sizeof(PetscBool) - 1 - i];
55a297a907SKarl Rupp     for (i = 0; i < (PetscInt)sizeof(PetscBool); i++) ptr1[i] = ptr2[i];
566de02169SBarry Smith   }
573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
586de02169SBarry Smith }
596de02169SBarry Smith 
60bd1d2e58SBarry Smith /*
617de69702SBarry Smith   PetscByteSwapInt - Swap bytes in a  PETSc integer (which may be 32 or 64-bits)
62bd1d2e58SBarry Smith 
63bd1d2e58SBarry Smith */
64d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscByteSwapInt(PetscInt *buff, PetscInt n)
65d71ae5a4SJacob Faibussowitsch {
66bd1d2e58SBarry Smith   PetscInt i, j, tmp = 0;
67e0890e22SSatish Balay   char    *ptr1, *ptr2 = (char *)&tmp;
68bd1d2e58SBarry Smith 
69bd1d2e58SBarry Smith   PetscFunctionBegin;
70bd1d2e58SBarry Smith   for (j = 0; j < n; j++) {
71bd1d2e58SBarry Smith     ptr1 = (char *)(buff + j);
72a297a907SKarl Rupp     for (i = 0; i < (PetscInt)sizeof(PetscInt); i++) ptr2[i] = ptr1[sizeof(PetscInt) - 1 - i];
73a297a907SKarl Rupp     for (i = 0; i < (PetscInt)sizeof(PetscInt); i++) ptr1[i] = ptr2[i];
74bd1d2e58SBarry Smith   }
753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
76bd1d2e58SBarry Smith }
779e3e4c22SLisandro Dalcin 
789e3e4c22SLisandro Dalcin /*
797de69702SBarry Smith   PetscByteSwapInt64 - Swap bytes in a  PETSc integer (64-bits)
809e3e4c22SLisandro Dalcin 
819e3e4c22SLisandro Dalcin */
82d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscByteSwapInt64(PetscInt64 *buff, PetscInt n)
83d71ae5a4SJacob Faibussowitsch {
849e3e4c22SLisandro Dalcin   PetscInt   i, j;
859e3e4c22SLisandro Dalcin   PetscInt64 tmp = 0;
869e3e4c22SLisandro Dalcin   char      *ptr1, *ptr2 = (char *)&tmp;
879e3e4c22SLisandro Dalcin 
889e3e4c22SLisandro Dalcin   PetscFunctionBegin;
899e3e4c22SLisandro Dalcin   for (j = 0; j < n; j++) {
909e3e4c22SLisandro Dalcin     ptr1 = (char *)(buff + j);
919e3e4c22SLisandro Dalcin     for (i = 0; i < (PetscInt)sizeof(PetscInt64); i++) ptr2[i] = ptr1[sizeof(PetscInt64) - 1 - i];
929e3e4c22SLisandro Dalcin     for (i = 0; i < (PetscInt)sizeof(PetscInt64); i++) ptr1[i] = ptr2[i];
939e3e4c22SLisandro Dalcin   }
943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
959e3e4c22SLisandro Dalcin }
969e3e4c22SLisandro Dalcin 
97e5c89e4eSSatish Balay /*
983321ca25SJames Wright   PetscByteSwapInt32 - Swap bytes in a  PETSc integer (32-bits)
993321ca25SJames Wright 
1003321ca25SJames Wright */
1013321ca25SJames Wright PetscErrorCode PetscByteSwapInt32(PetscInt32 *buff, PetscInt n)
1023321ca25SJames Wright {
1033321ca25SJames Wright   PetscInt   i, j;
1043321ca25SJames Wright   PetscInt32 tmp = 0;
1053321ca25SJames Wright   char      *ptr1, *ptr2 = (char *)&tmp;
1063321ca25SJames Wright 
1073321ca25SJames Wright   PetscFunctionBegin;
1083321ca25SJames Wright   for (j = 0; j < n; j++) {
1093321ca25SJames Wright     ptr1 = (char *)(buff + j);
1103321ca25SJames Wright     for (i = 0; i < (PetscInt)sizeof(PetscInt32); i++) ptr2[i] = ptr1[sizeof(PetscInt32) - 1 - i];
1113321ca25SJames Wright     for (i = 0; i < (PetscInt)sizeof(PetscInt32); i++) ptr1[i] = ptr2[i];
1123321ca25SJames Wright   }
1133321ca25SJames Wright   PetscFunctionReturn(PETSC_SUCCESS);
1143321ca25SJames Wright }
1153321ca25SJames Wright 
1163321ca25SJames Wright /*
117e5c89e4eSSatish Balay   PetscByteSwapShort - Swap bytes in a short
118e5c89e4eSSatish Balay */
119d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscByteSwapShort(short *buff, PetscInt n)
120d71ae5a4SJacob Faibussowitsch {
121e5c89e4eSSatish Balay   PetscInt i, j;
122e5c89e4eSSatish Balay   short    tmp;
123e5c89e4eSSatish Balay   char    *ptr1, *ptr2 = (char *)&tmp;
124e5c89e4eSSatish Balay 
125e5c89e4eSSatish Balay   PetscFunctionBegin;
126e5c89e4eSSatish Balay   for (j = 0; j < n; j++) {
127e5c89e4eSSatish Balay     ptr1 = (char *)(buff + j);
128a297a907SKarl Rupp     for (i = 0; i < (PetscInt)sizeof(short); i++) ptr2[i] = ptr1[sizeof(short) - 1 - i];
129a297a907SKarl Rupp     for (i = 0; i < (PetscInt)sizeof(short); i++) ptr1[i] = ptr2[i];
130e5c89e4eSSatish Balay   }
1313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
132e5c89e4eSSatish Balay }
133972064b6SLisandro Dalcin /*
134972064b6SLisandro Dalcin   PetscByteSwapLong - Swap bytes in a long
135972064b6SLisandro Dalcin */
136d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscByteSwapLong(long *buff, PetscInt n)
137d71ae5a4SJacob Faibussowitsch {
138972064b6SLisandro Dalcin   PetscInt i, j;
139972064b6SLisandro Dalcin   long     tmp;
140972064b6SLisandro Dalcin   char    *ptr1, *ptr2 = (char *)&tmp;
141972064b6SLisandro Dalcin 
142972064b6SLisandro Dalcin   PetscFunctionBegin;
143972064b6SLisandro Dalcin   for (j = 0; j < n; j++) {
144972064b6SLisandro Dalcin     ptr1 = (char *)(buff + j);
145972064b6SLisandro Dalcin     for (i = 0; i < (PetscInt)sizeof(long); i++) ptr2[i] = ptr1[sizeof(long) - 1 - i];
146972064b6SLisandro Dalcin     for (i = 0; i < (PetscInt)sizeof(long); i++) ptr1[i] = ptr2[i];
147972064b6SLisandro Dalcin   }
1483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
149972064b6SLisandro Dalcin }
15021532e8aSBarry Smith 
151e5c89e4eSSatish Balay /*
1524caf0332SSatish Balay   PetscByteSwapReal - Swap bytes in a PetscReal
1534caf0332SSatish Balay */
154d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscByteSwapReal(PetscReal *buff, PetscInt n)
155d71ae5a4SJacob Faibussowitsch {
1564caf0332SSatish Balay   PetscInt  i, j;
1574caf0332SSatish Balay   PetscReal tmp, *buff1 = (PetscReal *)buff;
1584caf0332SSatish Balay   char     *ptr1, *ptr2 = (char *)&tmp;
1594caf0332SSatish Balay 
1604caf0332SSatish Balay   PetscFunctionBegin;
1614caf0332SSatish Balay   for (j = 0; j < n; j++) {
1624caf0332SSatish Balay     ptr1 = (char *)(buff1 + j);
1634caf0332SSatish Balay     for (i = 0; i < (PetscInt)sizeof(PetscReal); i++) ptr2[i] = ptr1[sizeof(PetscReal) - 1 - i];
1644caf0332SSatish Balay     for (i = 0; i < (PetscInt)sizeof(PetscReal); i++) ptr1[i] = ptr2[i];
1654caf0332SSatish Balay   }
1663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1674caf0332SSatish Balay }
16821532e8aSBarry Smith 
1694caf0332SSatish Balay /*
17041f502e3SPatrick Sanan   PetscByteSwapScalar - Swap bytes in a PetscScalar
17141f502e3SPatrick Sanan   The complex case is dealt with with an array of PetscReal, twice as long.
172e5c89e4eSSatish Balay */
173d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscByteSwapScalar(PetscScalar *buff, PetscInt n)
174d71ae5a4SJacob Faibussowitsch {
175e5c89e4eSSatish Balay   PetscInt  i, j;
176e5c89e4eSSatish Balay   PetscReal tmp, *buff1 = (PetscReal *)buff;
177e5c89e4eSSatish Balay   char     *ptr1, *ptr2 = (char *)&tmp;
178e5c89e4eSSatish Balay 
179e5c89e4eSSatish Balay   PetscFunctionBegin;
180e5c89e4eSSatish Balay #if defined(PETSC_USE_COMPLEX)
181e5c89e4eSSatish Balay   n *= 2;
182e5c89e4eSSatish Balay #endif
183e5c89e4eSSatish Balay   for (j = 0; j < n; j++) {
184e5c89e4eSSatish Balay     ptr1 = (char *)(buff1 + j);
185a297a907SKarl Rupp     for (i = 0; i < (PetscInt)sizeof(PetscReal); i++) ptr2[i] = ptr1[sizeof(PetscReal) - 1 - i];
186a297a907SKarl Rupp     for (i = 0; i < (PetscInt)sizeof(PetscReal); i++) ptr1[i] = ptr2[i];
187e5c89e4eSSatish Balay   }
1883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
189e5c89e4eSSatish Balay }
19021532e8aSBarry Smith 
191e5c89e4eSSatish Balay /*
192e5c89e4eSSatish Balay   PetscByteSwapDouble - Swap bytes in a double
193e5c89e4eSSatish Balay */
194d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscByteSwapDouble(double *buff, PetscInt n)
195d71ae5a4SJacob Faibussowitsch {
196e5c89e4eSSatish Balay   PetscInt i, j;
197e5c89e4eSSatish Balay   double   tmp, *buff1 = (double *)buff;
198e5c89e4eSSatish Balay   char    *ptr1, *ptr2 = (char *)&tmp;
199e5c89e4eSSatish Balay 
200e5c89e4eSSatish Balay   PetscFunctionBegin;
201e5c89e4eSSatish Balay   for (j = 0; j < n; j++) {
202e5c89e4eSSatish Balay     ptr1 = (char *)(buff1 + j);
203a297a907SKarl Rupp     for (i = 0; i < (PetscInt)sizeof(double); i++) ptr2[i] = ptr1[sizeof(double) - 1 - i];
204a297a907SKarl Rupp     for (i = 0; i < (PetscInt)sizeof(double); i++) ptr1[i] = ptr2[i];
205e5c89e4eSSatish Balay   }
2063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
207e5c89e4eSSatish Balay }
208e39fd77fSBarry Smith 
209e95bf02fSSatish Balay /*
210e95bf02fSSatish Balay   PetscByteSwapFloat - Swap bytes in a float
211e95bf02fSSatish Balay */
212d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscByteSwapFloat(float *buff, PetscInt n)
213d71ae5a4SJacob Faibussowitsch {
214e95bf02fSSatish Balay   PetscInt i, j;
215e95bf02fSSatish Balay   float    tmp, *buff1 = (float *)buff;
216e95bf02fSSatish Balay   char    *ptr1, *ptr2 = (char *)&tmp;
217e95bf02fSSatish Balay 
218e95bf02fSSatish Balay   PetscFunctionBegin;
219e95bf02fSSatish Balay   for (j = 0; j < n; j++) {
220e95bf02fSSatish Balay     ptr1 = (char *)(buff1 + j);
221a297a907SKarl Rupp     for (i = 0; i < (PetscInt)sizeof(float); i++) ptr2[i] = ptr1[sizeof(float) - 1 - i];
222a297a907SKarl Rupp     for (i = 0; i < (PetscInt)sizeof(float); i++) ptr1[i] = ptr2[i];
223e95bf02fSSatish Balay   }
2243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
225e95bf02fSSatish Balay }
226e95bf02fSSatish Balay 
227d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscByteSwap(void *data, PetscDataType pdtype, PetscInt count)
228d71ae5a4SJacob Faibussowitsch {
229e39fd77fSBarry Smith   PetscFunctionBegin;
2309566063dSJacob Faibussowitsch   if (pdtype == PETSC_INT) PetscCall(PetscByteSwapInt((PetscInt *)data, count));
2319566063dSJacob Faibussowitsch   else if (pdtype == PETSC_ENUM) PetscCall(PetscByteSwapEnum((PetscEnum *)data, count));
2329566063dSJacob Faibussowitsch   else if (pdtype == PETSC_BOOL) PetscCall(PetscByteSwapBool((PetscBool *)data, count));
2339566063dSJacob Faibussowitsch   else if (pdtype == PETSC_SCALAR) PetscCall(PetscByteSwapScalar((PetscScalar *)data, count));
2349566063dSJacob Faibussowitsch   else if (pdtype == PETSC_REAL) PetscCall(PetscByteSwapReal((PetscReal *)data, count));
2359566063dSJacob Faibussowitsch   else if (pdtype == PETSC_COMPLEX) PetscCall(PetscByteSwapReal((PetscReal *)data, 2 * count));
2369566063dSJacob Faibussowitsch   else if (pdtype == PETSC_INT64) PetscCall(PetscByteSwapInt64((PetscInt64 *)data, count));
2373321ca25SJames Wright   else if (pdtype == PETSC_INT32) PetscCall(PetscByteSwapInt32((PetscInt32 *)data, count));
2389566063dSJacob Faibussowitsch   else if (pdtype == PETSC_DOUBLE) PetscCall(PetscByteSwapDouble((double *)data, count));
2399566063dSJacob Faibussowitsch   else if (pdtype == PETSC_FLOAT) PetscCall(PetscByteSwapFloat((float *)data, count));
2409566063dSJacob Faibussowitsch   else if (pdtype == PETSC_SHORT) PetscCall(PetscByteSwapShort((short *)data, count));
2419566063dSJacob Faibussowitsch   else if (pdtype == PETSC_LONG) PetscCall(PetscByteSwapLong((long *)data, count));
242*372de11fSJed Brown   else if (pdtype == PETSC_CHAR) PetscFunctionReturn(PETSC_SUCCESS);
2433321ca25SJames Wright   else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Unknown type: %d", pdtype);
2443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
245e39fd77fSBarry Smith }
246e39fd77fSBarry Smith 
2479860990eSLisandro Dalcin /*@C
248e5c89e4eSSatish Balay    PetscBinaryRead - Reads from a binary file.
249e5c89e4eSSatish Balay 
250e5c89e4eSSatish Balay    Not Collective
251e5c89e4eSSatish Balay 
252e5c89e4eSSatish Balay    Input Parameters:
2539860990eSLisandro Dalcin +  fd - the file descriptor
2549860990eSLisandro Dalcin .  num  - the maximum number of items to read
255811af0c4SBarry Smith -  type - the type of items to read (`PETSC_INT`, `PETSC_REAL`, `PETSC_SCALAR`, etc.)
256e5c89e4eSSatish Balay 
257e5c89e4eSSatish Balay    Output Parameters:
25821532e8aSBarry Smith +  data - the buffer, this is an array of the type that matches the value in `type`
2599860990eSLisandro Dalcin -  count - the number of items read, optional
260e5c89e4eSSatish Balay 
261e5c89e4eSSatish Balay    Level: developer
262e5c89e4eSSatish Balay 
263e5c89e4eSSatish Balay    Notes:
26421532e8aSBarry Smith    If `count` is not provided and the number of items read is less than
2659860990eSLisandro Dalcin    the maximum number of items to read, then this routine errors.
2669860990eSLisandro Dalcin 
267811af0c4SBarry Smith    `PetscBinaryRead()` uses byte swapping to work on all machines; the files
26821532e8aSBarry Smith    are written ALWAYS using big-endian ordering. On little-endian machines the numbers
269f253e43cSLisandro Dalcin    are converted to the little-endian format when they are read in from the file.
27021532e8aSBarry Smith    When PETSc is ./configure with `--with-64-bit-indices` the integers are written to the
2717de69702SBarry Smith    file as 64-bit integers, this means they can only be read back in when the option `--with-64-bit-indices`
27254f21887SBarry Smith    is used.
273e5c89e4eSSatish Balay 
274db781477SPatrick Sanan .seealso: `PetscBinaryWrite()`, `PetscBinaryOpen()`, `PetscBinaryClose()`, `PetscViewerBinaryGetDescriptor()`, `PetscBinarySynchronizedWrite()`,
275db781477SPatrick Sanan           `PetscBinarySynchronizedRead()`, `PetscBinarySynchronizedSeek()`
276e5c89e4eSSatish Balay @*/
277d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscBinaryRead(int fd, void *data, PetscInt num, PetscInt *count, PetscDataType type)
278d71ae5a4SJacob Faibussowitsch {
2799860990eSLisandro Dalcin   size_t typesize, m = (size_t)num, n = 0, maxblock = 65536;
2809860990eSLisandro Dalcin   char  *p = (char *)data;
2817a881295SBarry Smith #if defined(PETSC_USE_REAL___FLOAT128)
282cba51d77SBarry Smith   PetscBool readdouble = PETSC_FALSE;
2839860990eSLisandro Dalcin   double   *pdouble;
2847a881295SBarry Smith #endif
2859860990eSLisandro Dalcin   void *ptmp  = data;
28605acbc63SBarry Smith   char *fname = NULL;
287e5c89e4eSSatish Balay 
288e5c89e4eSSatish Balay   PetscFunctionBegin;
2899860990eSLisandro Dalcin   if (count) *count = 0;
29008401ef6SPierre Jolivet   PetscCheck(num >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to read a negative amount of data %" PetscInt_FMT, num);
2913ba16761SJacob Faibussowitsch   if (!num) PetscFunctionReturn(PETSC_SUCCESS);
292e5c89e4eSSatish Balay 
2932d53ad75SBarry Smith   if (type == PETSC_FUNCTION) {
2942d53ad75SBarry Smith     m     = 64;
2952d53ad75SBarry Smith     type  = PETSC_CHAR;
29605acbc63SBarry Smith     fname = (char *)malloc(m * sizeof(char));
2979860990eSLisandro Dalcin     p     = (char *)fname;
2982d53ad75SBarry Smith     ptmp  = (void *)fname;
29928b400f6SJacob Faibussowitsch     PetscCheck(fname, PETSC_COMM_SELF, PETSC_ERR_MEM, "Cannot allocate space for function name");
3002d53ad75SBarry Smith   }
3019860990eSLisandro Dalcin   if (type == PETSC_BIT_LOGICAL) m = PetscBTLength(m);
3022d53ad75SBarry Smith 
3039566063dSJacob Faibussowitsch   PetscCall(PetscDataTypeGetSize(type, &typesize));
304e5c89e4eSSatish Balay 
3057a881295SBarry Smith #if defined(PETSC_USE_REAL___FLOAT128)
3069566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(NULL, NULL, "-binary_read_double", &readdouble, NULL));
3077a881295SBarry Smith   /* If using __float128 precision we still read in doubles from file */
3089860990eSLisandro Dalcin   if ((type == PETSC_REAL || type == PETSC_COMPLEX) && readdouble) {
3099860990eSLisandro Dalcin     PetscInt cnt = num * ((type == PETSC_REAL) ? 1 : 2);
3109566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(cnt, &pdouble));
3119860990eSLisandro Dalcin     p = (char *)pdouble;
3129860990eSLisandro Dalcin     typesize /= 2;
3137a881295SBarry Smith   }
3147a881295SBarry Smith #endif
3157a881295SBarry Smith 
3169860990eSLisandro Dalcin   m *= typesize;
3179860990eSLisandro Dalcin 
318e5c89e4eSSatish Balay   while (m) {
3199860990eSLisandro Dalcin     size_t len = (m < maxblock) ? m : maxblock;
3209860990eSLisandro Dalcin     int    ret = (int)read(fd, p, len);
3219860990eSLisandro Dalcin     if (ret < 0 && errno == EINTR) continue;
3229860990eSLisandro Dalcin     if (!ret && len > 0) break; /* Proxy for EOF */
323bf31d2d3SBarry Smith     PetscCheck(ret >= 0, PETSC_COMM_SELF, PETSC_ERR_FILE_READ, "Error reading from file due to \"%s\"", strerror(errno));
324ff9f933bSBarry Smith     m -= (size_t)ret;
3259860990eSLisandro Dalcin     p += ret;
326ff9f933bSBarry Smith     n += (size_t)ret;
327e5c89e4eSSatish Balay   }
32808401ef6SPierre Jolivet   PetscCheck(!m || count, PETSC_COMM_SELF, PETSC_ERR_FILE_READ, "Read past end of file");
3299860990eSLisandro Dalcin 
3309860990eSLisandro Dalcin   num = (PetscInt)(n / typesize); /* Should we require `n % typesize == 0` ? */
3319860990eSLisandro Dalcin   if (count) *count = num;        /* TODO: This is most likely wrong for PETSC_BIT_LOGICAL */
3327a881295SBarry Smith 
3337a881295SBarry Smith #if defined(PETSC_USE_REAL___FLOAT128)
3349860990eSLisandro Dalcin   if ((type == PETSC_REAL || type == PETSC_COMPLEX) && readdouble) {
3359860990eSLisandro Dalcin     PetscInt   i, cnt = num * ((type == PETSC_REAL) ? 1 : 2);
3369860990eSLisandro Dalcin     PetscReal *preal = (PetscReal *)data;
3379566063dSJacob Faibussowitsch     if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwapDouble(pdouble, cnt));
3389860990eSLisandro Dalcin     for (i = 0; i < cnt; i++) preal[i] = pdouble[i];
3399566063dSJacob Faibussowitsch     PetscCall(PetscFree(pdouble));
3403ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
3417a881295SBarry Smith   }
3427a881295SBarry Smith #endif
3437a881295SBarry Smith 
3449566063dSJacob Faibussowitsch   if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(ptmp, type, num));
345e5c89e4eSSatish Balay 
34605acbc63SBarry Smith   if (type == PETSC_FUNCTION) {
3472d53ad75SBarry Smith #if defined(PETSC_SERIALIZE_FUNCTIONS)
3489566063dSJacob Faibussowitsch     PetscCall(PetscDLSym(NULL, fname, (void **)data));
3492d53ad75SBarry Smith #else
3509860990eSLisandro Dalcin     *(void **)data = NULL;
3512d53ad75SBarry Smith #endif
35205acbc63SBarry Smith     free(fname);
3532d53ad75SBarry Smith   }
3543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
355e5c89e4eSSatish Balay }
3569860990eSLisandro Dalcin 
357a9acdec7SBarry Smith /*@C
358e5c89e4eSSatish Balay    PetscBinaryWrite - Writes to a binary file.
359e5c89e4eSSatish Balay 
360e5c89e4eSSatish Balay    Not Collective
361e5c89e4eSSatish Balay 
362e5c89e4eSSatish Balay    Input Parameters:
363e5c89e4eSSatish Balay +  fd     - the file
36421532e8aSBarry Smith .  p      - the buffer, an array of the type that matches the value in `type`
365e5c89e4eSSatish Balay .  n      - the number of items to write
366811af0c4SBarry Smith -  type   - the type of items to read (`PETSC_INT`, `PETSC_REAL` or `PETSC_SCALAR`)
367e5c89e4eSSatish Balay 
368e5c89e4eSSatish Balay    Level: advanced
369e5c89e4eSSatish Balay 
370e5c89e4eSSatish Balay    Notes:
371811af0c4SBarry Smith    `PetscBinaryWrite()` uses byte swapping to work on all machines; the files
372f253e43cSLisandro Dalcin    are written using big-endian ordering to the file. On little-endian machines the numbers
373e5c89e4eSSatish Balay    are converted to the big-endian format when they are written to disk.
37421532e8aSBarry Smith    When PETSc is configured using `./configure with --with-64-bit-indices` the integers are written to the
3757de69702SBarry Smith    file as 64-bit integers, this means they can only be read back in when the option `--with-64-bit-indices`
37654f21887SBarry Smith    is used.
377e5c89e4eSSatish Balay 
37821532e8aSBarry Smith    If running with `__float128` precision the output of `PETSC_REAL` is in `__float128` unless one uses the `-binary_write_double` option
3790da86b62SBarry Smith 
380bfbbc7b7SBarry Smith    The buffer `p` should be read-write buffer, and not static data.
381e5c89e4eSSatish Balay    This way, byte-swapping is done in-place, and then the buffer is
382e5c89e4eSSatish Balay    written to the file.
383e5c89e4eSSatish Balay 
384e5c89e4eSSatish Balay    This routine restores the original contents of the buffer, after
385e5c89e4eSSatish Balay    it is written to the file. This is done by byte-swapping in-place
386f253e43cSLisandro Dalcin    the second time.
387e5c89e4eSSatish Balay 
388300a7f5bSBarry Smith    Because byte-swapping may be done on the values in data it cannot be declared const
389300a7f5bSBarry Smith 
390db781477SPatrick Sanan .seealso: `PetscBinaryRead()`, `PetscBinaryOpen()`, `PetscBinaryClose()`, `PetscViewerBinaryGetDescriptor()`, `PetscBinarySynchronizedWrite()`,
391db781477SPatrick Sanan           `PetscBinarySynchronizedRead()`, `PetscBinarySynchronizedSeek()`
392e5c89e4eSSatish Balay @*/
393d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscBinaryWrite(int fd, const void *p, PetscInt n, PetscDataType type)
394d71ae5a4SJacob Faibussowitsch {
395f253e43cSLisandro Dalcin   const char *pp = (char *)p;
396e5c89e4eSSatish Balay   int         err, wsize;
397e5c89e4eSSatish Balay   size_t      m = (size_t)n, maxblock = 65536;
398f253e43cSLisandro Dalcin   const void *ptmp  = p;
39905acbc63SBarry Smith   char       *fname = NULL;
4000da86b62SBarry Smith #if defined(PETSC_USE_REAL___FLOAT128)
401df40af56SBarry Smith   PetscBool  writedouble = PETSC_FALSE;
4020da86b62SBarry Smith   double    *ppp;
4030da86b62SBarry Smith   PetscReal *pv;
4040da86b62SBarry Smith   PetscInt   i;
4050da86b62SBarry Smith #endif
40641f502e3SPatrick Sanan   PetscDataType wtype = type;
407e5c89e4eSSatish Balay 
408e5c89e4eSSatish Balay   PetscFunctionBegin;
40908401ef6SPierre Jolivet   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to write a negative amount of data %" PetscInt_FMT, n);
4103ba16761SJacob Faibussowitsch   if (!n) PetscFunctionReturn(PETSC_SUCCESS);
411e5c89e4eSSatish Balay 
4122d53ad75SBarry Smith   if (type == PETSC_FUNCTION) {
4132d53ad75SBarry Smith #if defined(PETSC_SERIALIZE_FUNCTIONS)
4142d53ad75SBarry Smith     const char *fnametmp;
4152d53ad75SBarry Smith #endif
4162d53ad75SBarry Smith     m     = 64;
417e25ab156SSatish Balay     fname = (char *)malloc(m * sizeof(char));
41828b400f6SJacob Faibussowitsch     PetscCheck(fname, PETSC_COMM_SELF, PETSC_ERR_MEM, "Cannot allocate space for function name");
41905acbc63SBarry Smith #if defined(PETSC_SERIALIZE_FUNCTIONS)
42008401ef6SPierre Jolivet     PetscCheck(n <= 1, PETSC_COMM_SELF, PETSC_ERR_SUP, "Can only binary view a single function at a time");
4219566063dSJacob Faibussowitsch     PetscCall(PetscFPTFind(*(void **)p, &fnametmp));
4229566063dSJacob Faibussowitsch     PetscCall(PetscStrncpy(fname, fnametmp, m));
42305acbc63SBarry Smith #else
4249566063dSJacob Faibussowitsch     PetscCall(PetscStrncpy(fname, "", m));
42505acbc63SBarry Smith #endif
42601963f56SBarry Smith     wtype = PETSC_CHAR;
4272d53ad75SBarry Smith     pp    = (char *)fname;
4282d53ad75SBarry Smith     ptmp  = (void *)fname;
4292d53ad75SBarry Smith   }
4302d53ad75SBarry Smith 
4310da86b62SBarry Smith #if defined(PETSC_USE_REAL___FLOAT128)
4329566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(NULL, NULL, "-binary_write_double", &writedouble, NULL));
4330da86b62SBarry Smith   /* If using __float128 precision we still write in doubles to file */
434501ae109SJose E. Roman   if ((type == PETSC_SCALAR || type == PETSC_REAL || type == PETSC_COMPLEX) && writedouble) {
43541f502e3SPatrick Sanan     wtype = PETSC_DOUBLE;
4369566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(n, &ppp));
4370da86b62SBarry Smith     pv = (PetscReal *)pp;
438ad540459SPierre Jolivet     for (i = 0; i < n; i++) ppp[i] = (double)pv[i];
4390da86b62SBarry Smith     pp   = (char *)ppp;
4400da86b62SBarry Smith     ptmp = (char *)ppp;
4410da86b62SBarry Smith   }
4420da86b62SBarry Smith #endif
4430da86b62SBarry Smith 
44441f502e3SPatrick Sanan   if (wtype == PETSC_INT) m *= sizeof(PetscInt);
44541f502e3SPatrick Sanan   else if (wtype == PETSC_SCALAR) m *= sizeof(PetscScalar);
446501ae109SJose E. Roman #if defined(PETSC_HAVE_COMPLEX)
447501ae109SJose E. Roman   else if (wtype == PETSC_COMPLEX) m *= sizeof(PetscComplex);
448501ae109SJose E. Roman #endif
4494caf0332SSatish Balay   else if (wtype == PETSC_REAL) m *= sizeof(PetscReal);
45041f502e3SPatrick Sanan   else if (wtype == PETSC_DOUBLE) m *= sizeof(double);
45141f502e3SPatrick Sanan   else if (wtype == PETSC_FLOAT) m *= sizeof(float);
45241f502e3SPatrick Sanan   else if (wtype == PETSC_SHORT) m *= sizeof(short);
453972064b6SLisandro Dalcin   else if (wtype == PETSC_LONG) m *= sizeof(long);
45441f502e3SPatrick Sanan   else if (wtype == PETSC_CHAR) m *= sizeof(char);
45541f502e3SPatrick Sanan   else if (wtype == PETSC_ENUM) m *= sizeof(PetscEnum);
45641f502e3SPatrick Sanan   else if (wtype == PETSC_BOOL) m *= sizeof(PetscBool);
4579e3e4c22SLisandro Dalcin   else if (wtype == PETSC_INT64) m *= sizeof(PetscInt64);
4583321ca25SJames Wright   else if (wtype == PETSC_INT32) m *= sizeof(PetscInt32);
45941f502e3SPatrick Sanan   else if (wtype == PETSC_BIT_LOGICAL) m = PetscBTLength(m) * sizeof(char);
4603321ca25SJames Wright   else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Unknown type: %d", wtype);
461e5c89e4eSSatish Balay 
4629566063dSJacob Faibussowitsch   if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap((void *)ptmp, wtype, n));
463e5c89e4eSSatish Balay 
464e5c89e4eSSatish Balay   while (m) {
465e5c89e4eSSatish Balay     wsize = (m < maxblock) ? m : maxblock;
466e5c89e4eSSatish Balay     err   = write(fd, pp, wsize);
467e5c89e4eSSatish Balay     if (err < 0 && errno == EINTR) continue;
468bf31d2d3SBarry 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));
469e5c89e4eSSatish Balay     m -= wsize;
470e5c89e4eSSatish Balay     pp += wsize;
471e5c89e4eSSatish Balay   }
472e5c89e4eSSatish Balay 
4739566063dSJacob Faibussowitsch   if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap((void *)ptmp, wtype, n));
474f253e43cSLisandro Dalcin 
475ad540459SPierre Jolivet   if (type == PETSC_FUNCTION) free(fname);
4760da86b62SBarry Smith #if defined(PETSC_USE_REAL___FLOAT128)
47748a46eb9SPierre Jolivet   if ((type == PETSC_SCALAR || type == PETSC_REAL || type == PETSC_COMPLEX) && writedouble) PetscCall(PetscFree(ppp));
4780da86b62SBarry Smith #endif
4793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
480e5c89e4eSSatish Balay }
481e5c89e4eSSatish Balay 
482e5c89e4eSSatish Balay /*@C
483e5c89e4eSSatish Balay    PetscBinaryOpen - Opens a PETSc binary file.
484e5c89e4eSSatish Balay 
485e5c89e4eSSatish Balay    Not Collective
486e5c89e4eSSatish Balay 
487e5c89e4eSSatish Balay    Input Parameters:
488e5c89e4eSSatish Balay +  name - filename
489811af0c4SBarry Smith -  mode - open mode of binary file, one of `FILE_MODE_READ`, `FILE_MODE_WRITE`, `FILE_MODE_APPEND``
490e5c89e4eSSatish Balay 
491e5c89e4eSSatish Balay    Output Parameter:
492e5c89e4eSSatish Balay .  fd - the file
493e5c89e4eSSatish Balay 
494e5c89e4eSSatish Balay    Level: advanced
495e5c89e4eSSatish Balay 
496db781477SPatrick Sanan .seealso: `PetscBinaryRead()`, `PetscBinaryWrite()`, `PetscFileMode`, `PetscViewerFileSetMode()`, `PetscViewerBinaryGetDescriptor()`,
497db781477SPatrick Sanan           `PetscBinarySynchronizedWrite()`, `PetscBinarySynchronizedRead()`, `PetscBinarySynchronizedSeek()`
498e5c89e4eSSatish Balay @*/
499d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscBinaryOpen(const char name[], PetscFileMode mode, int *fd)
500d71ae5a4SJacob Faibussowitsch {
501e5c89e4eSSatish Balay   PetscFunctionBegin;
502cc843e7aSLisandro Dalcin   switch (mode) {
503d71ae5a4SJacob Faibussowitsch   case FILE_MODE_READ:
504d71ae5a4SJacob Faibussowitsch     *fd = open(name, O_BINARY | O_RDONLY, 0);
505d71ae5a4SJacob Faibussowitsch     break;
506d71ae5a4SJacob Faibussowitsch   case FILE_MODE_WRITE:
507d71ae5a4SJacob Faibussowitsch     *fd = open(name, O_BINARY | O_WRONLY | O_CREAT | O_TRUNC, 0666);
508d71ae5a4SJacob Faibussowitsch     break;
509d71ae5a4SJacob Faibussowitsch   case FILE_MODE_APPEND:
510d71ae5a4SJacob Faibussowitsch     *fd = open(name, O_BINARY | O_WRONLY | O_APPEND, 0);
511d71ae5a4SJacob Faibussowitsch     break;
512d71ae5a4SJacob Faibussowitsch   default:
513d71ae5a4SJacob Faibussowitsch     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Unsupported file mode %s", PetscFileModes[mode]);
514e5c89e4eSSatish Balay   }
515bf31d2d3SBarry 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));
5163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
517e5c89e4eSSatish Balay }
518e5c89e4eSSatish Balay 
519e30d2299SSatish Balay /*@
520e5c89e4eSSatish Balay    PetscBinaryClose - Closes a PETSc binary file.
521e5c89e4eSSatish Balay 
522e5c89e4eSSatish Balay    Not Collective
523e5c89e4eSSatish Balay 
524e5c89e4eSSatish Balay    Output Parameter:
525e5c89e4eSSatish Balay .  fd - the file
526e5c89e4eSSatish Balay 
527e5c89e4eSSatish Balay    Level: advanced
528e5c89e4eSSatish Balay 
529db781477SPatrick Sanan .seealso: `PetscBinaryRead()`, `PetscBinaryWrite()`, `PetscBinaryOpen()`, `PetscBinarySynchronizedWrite()`, `PetscBinarySynchronizedRead()`,
530db781477SPatrick Sanan           `PetscBinarySynchronizedSeek()`
531e5c89e4eSSatish Balay @*/
532d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscBinaryClose(int fd)
533d71ae5a4SJacob Faibussowitsch {
534e5c89e4eSSatish Balay   PetscFunctionBegin;
535cc73adaaSBarry Smith   PetscCheck(!close(fd), PETSC_COMM_SELF, PETSC_ERR_SYS, "close() failed on file descriptor");
5363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
537e5c89e4eSSatish Balay }
538e5c89e4eSSatish Balay 
539e8976759SBarry Smith /*@C
540e5c89e4eSSatish Balay    PetscBinarySeek - Moves the file pointer on a PETSc binary file.
541e5c89e4eSSatish Balay 
542e5c89e4eSSatish Balay    Not Collective
543e5c89e4eSSatish Balay 
544e5c89e4eSSatish Balay    Input Parameters:
545e5c89e4eSSatish Balay +  fd - the file
546811af0c4SBarry Smith .  off - number of bytes to move. Use `PETSC_BINARY_INT_SIZE`, `PETSC_BINARY_SCALAR_SIZE`,
54721532e8aSBarry Smith             etc. in your calculation rather than `sizeof()` to compute byte lengths.
54816a05f60SBarry Smith -  whence - see `PetscBinarySeekType` for possible values
549e5c89e4eSSatish Balay 
550e5c89e4eSSatish Balay    Output Parameter:
551e5c89e4eSSatish Balay .   offset - new offset in file
552e5c89e4eSSatish Balay 
553e5c89e4eSSatish Balay    Level: developer
554e5c89e4eSSatish Balay 
55516a05f60SBarry Smith .seealso: `PetscBinaryRead()`, `PetscBinarySeekType`, `PetscBinaryWrite()`, `PetscBinaryOpen()`, `PetscBinarySynchronizedWrite()`, `PetscBinarySynchronizedRead()`,
556db781477SPatrick Sanan           `PetscBinarySynchronizedSeek()`
557e5c89e4eSSatish Balay @*/
558d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscBinarySeek(int fd, off_t off, PetscBinarySeekType whence, off_t *offset)
559d71ae5a4SJacob Faibussowitsch {
560e5c89e4eSSatish Balay   int iwhence = 0;
561e5c89e4eSSatish Balay 
562e5c89e4eSSatish Balay   PetscFunctionBegin;
563a297a907SKarl Rupp   if (whence == PETSC_BINARY_SEEK_SET) iwhence = SEEK_SET;
564a297a907SKarl Rupp   else if (whence == PETSC_BINARY_SEEK_CUR) iwhence = SEEK_CUR;
565a297a907SKarl Rupp   else if (whence == PETSC_BINARY_SEEK_END) iwhence = SEEK_END;
566a297a907SKarl Rupp   else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Unknown seek location");
567e5c89e4eSSatish Balay #if defined(PETSC_HAVE_LSEEK)
568e5c89e4eSSatish Balay   *offset = lseek(fd, off, iwhence);
569e5c89e4eSSatish Balay #elif defined(PETSC_HAVE__LSEEK)
570e5c89e4eSSatish Balay   *offset = _lseek(fd, (long)off, iwhence);
571e5c89e4eSSatish Balay #else
572e32f2f54SBarry Smith   SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP_SYS, "System does not have a way of seeking on a file");
573e5c89e4eSSatish Balay #endif
5743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
575e5c89e4eSSatish Balay }
576e5c89e4eSSatish Balay 
577e5c89e4eSSatish Balay /*@C
57821532e8aSBarry Smith    PetscBinarySynchronizedRead - Reads from a binary file, all MPI processes get the same values
579e5c89e4eSSatish Balay 
580d083f849SBarry Smith    Collective
581e5c89e4eSSatish Balay 
582e5c89e4eSSatish Balay    Input Parameters:
583e5c89e4eSSatish Balay +  comm - the MPI communicator
5849860990eSLisandro Dalcin .  fd - the file descriptor
5859860990eSLisandro Dalcin .  num  - the maximum number of items to read
586811af0c4SBarry Smith -  type - the type of items to read (`PETSC_INT`, `PETSC_REAL`, `PETSC_SCALAR`, etc.)
587e5c89e4eSSatish Balay 
588e5c89e4eSSatish Balay    Output Parameters:
58921532e8aSBarry Smith +  data - the buffer, an array of the type that matches the value in `type`
5909860990eSLisandro Dalcin -  count - the number of items read, optional
591e5c89e4eSSatish Balay 
592e5c89e4eSSatish Balay    Level: developer
593e5c89e4eSSatish Balay 
594e5c89e4eSSatish Balay    Notes:
595811af0c4SBarry Smith    Does a `PetscBinaryRead()` followed by an `MPI_Bcast()`
596e5c89e4eSSatish Balay 
59721532e8aSBarry Smith    If `count` is not provided and the number of items read is less than
5989860990eSLisandro Dalcin    the maximum number of items to read, then this routine errors.
5999860990eSLisandro Dalcin 
600811af0c4SBarry Smith    `PetscBinarySynchronizedRead()` uses byte swapping to work on all machines.
60121532e8aSBarry Smith    The files  are written using big-endian ordering to the file. On little-endian machines the numbers
60221532e8aSBarry Smith    are converted to the big-endian format when they are written to disk.
60321532e8aSBarry Smith    When PETSc is configured using `./configure with --with-64-bit-indices` the integers are written to the
6047de69702SBarry Smith    file as 64-bit integers, this means they can only be read back in when the option `--with-64-bit-indices`
60521532e8aSBarry Smith    is used.
606e5c89e4eSSatish Balay 
607db781477SPatrick Sanan .seealso: `PetscBinaryWrite()`, `PetscBinaryOpen()`, `PetscBinaryClose()`, `PetscBinaryRead()`, `PetscBinarySynchronizedWrite()`,
608db781477SPatrick Sanan           `PetscBinarySynchronizedSeek()`
609e5c89e4eSSatish Balay @*/
610d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscBinarySynchronizedRead(MPI_Comm comm, int fd, void *data, PetscInt num, PetscInt *count, PetscDataType type)
611d71ae5a4SJacob Faibussowitsch {
6128b8bf82cSBarry Smith   PetscMPIInt  rank, size;
613e5c89e4eSSatish Balay   MPI_Datatype mtype;
6149860990eSLisandro Dalcin   PetscInt     ibuf[2] = {0, 0};
61505acbc63SBarry Smith   char        *fname   = NULL;
6169860990eSLisandro Dalcin   void        *fptr    = NULL;
617e5c89e4eSSatish Balay 
618e5c89e4eSSatish Balay   PetscFunctionBegin;
6192d53ad75SBarry Smith   if (type == PETSC_FUNCTION) {
6209860990eSLisandro Dalcin     num   = 64;
6212d53ad75SBarry Smith     type  = PETSC_CHAR;
6229860990eSLisandro Dalcin     fname = (char *)malloc(num * sizeof(char));
6239860990eSLisandro Dalcin     fptr  = data;
6249860990eSLisandro Dalcin     data  = (void *)fname;
62528b400f6SJacob Faibussowitsch     PetscCheck(fname, PETSC_COMM_SELF, PETSC_ERR_MEM, "Cannot allocate space for function name");
6262d53ad75SBarry Smith   }
6272d53ad75SBarry Smith 
6289566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
6299566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
630ad540459SPierre Jolivet   if (rank == 0) ibuf[0] = PetscBinaryRead(fd, data, num, count ? &ibuf[1] : NULL, type);
6319566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Bcast(ibuf, 2, MPIU_INT, 0, comm));
6329566063dSJacob Faibussowitsch   PetscCall((PetscErrorCode)ibuf[0]);
6338b8bf82cSBarry Smith 
6348b8bf82cSBarry 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 */
6358b8bf82cSBarry Smith   if (size > 1) {
6369566063dSJacob Faibussowitsch     PetscCall(PetscDataTypeToMPIDataType(type, &mtype));
6379566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Bcast(data, count ? ibuf[1] : num, mtype, 0, comm));
6388b8bf82cSBarry Smith   }
6399860990eSLisandro Dalcin   if (count) *count = ibuf[1];
6402d53ad75SBarry Smith 
641e366c363SBarry Smith   if (type == PETSC_FUNCTION) {
6422d53ad75SBarry Smith #if defined(PETSC_SERIALIZE_FUNCTIONS)
6439566063dSJacob Faibussowitsch     PetscCall(PetscDLLibrarySym(PETSC_COMM_SELF, &PetscDLLibrariesLoaded, NULL, fname, (void **)fptr));
6442d53ad75SBarry Smith #else
6459860990eSLisandro Dalcin     *(void **)fptr = NULL;
6462d53ad75SBarry Smith #endif
647e366c363SBarry Smith     free(fname);
6482d53ad75SBarry Smith   }
6493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
650e5c89e4eSSatish Balay }
651e5c89e4eSSatish Balay 
652e5c89e4eSSatish Balay /*@C
6531d280d73SBarry Smith    PetscBinarySynchronizedWrite - writes to a binary file.
654e5c89e4eSSatish Balay 
655d083f849SBarry Smith    Collective
656e5c89e4eSSatish Balay 
657e5c89e4eSSatish Balay    Input Parameters:
658e5c89e4eSSatish Balay +  comm - the MPI communicator
659e5c89e4eSSatish Balay .  fd - the file
660e5c89e4eSSatish Balay .  n  - the number of items to write
66121532e8aSBarry Smith .  p - the buffer, an array of the type that matches the value in `type`
662811af0c4SBarry Smith -  type - the type of items to write (`PETSC_INT`, `PETSC_REAL` or `PETSC_SCALAR`)
663e5c89e4eSSatish Balay 
664e5c89e4eSSatish Balay    Level: developer
665e5c89e4eSSatish Balay 
666e5c89e4eSSatish Balay    Notes:
66721532e8aSBarry Smith    MPI rank 0 does a `PetscBinaryWrite()` the values on other MPI processes are not used
668e5c89e4eSSatish Balay 
66921532e8aSBarry Smith    The files  are written using big-endian ordering to the file. On little-endian machines the numbers
67021532e8aSBarry Smith    are converted to the big-endian format when they are written to disk.
67121532e8aSBarry Smith    When PETSc is configured using `./configure with --with-64-bit-indices` the integers are written to the
6727de69702SBarry Smith    file as 64-bit integers, this means they can only be read back in when the option `--with-64-bit-indices`
67321532e8aSBarry Smith    is used.
674e5c89e4eSSatish Balay 
675811af0c4SBarry Smith    Because byte-swapping may be done on the values in data it cannot be declared const
676300a7f5bSBarry Smith 
677811af0c4SBarry Smith    WARNING:
678bfbbc7b7SBarry Smith    This is NOT like `PetscSynchronizedFPrintf()`! This routine ignores calls on all but MPI rank 0,
67921532e8aSBarry Smith    while `PetscSynchronizedFPrintf()` has all MPI processes print their strings in order.
6801d280d73SBarry Smith 
681db781477SPatrick Sanan .seealso: `PetscBinaryWrite()`, `PetscBinaryOpen()`, `PetscBinaryClose()`, `PetscBinaryRead()`, `PetscBinarySynchronizedRead()`,
682db781477SPatrick Sanan           `PetscBinarySynchronizedSeek()`
683e5c89e4eSSatish Balay @*/
684d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscBinarySynchronizedWrite(MPI_Comm comm, int fd, const void *p, PetscInt n, PetscDataType type)
685d71ae5a4SJacob Faibussowitsch {
686e5c89e4eSSatish Balay   PetscMPIInt rank;
687e5c89e4eSSatish Balay 
688e5c89e4eSSatish Balay   PetscFunctionBegin;
6899566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
69048a46eb9SPierre Jolivet   if (rank == 0) PetscCall(PetscBinaryWrite(fd, p, n, type));
6913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
692e5c89e4eSSatish Balay }
693e5c89e4eSSatish Balay 
694e5c89e4eSSatish Balay /*@C
6951d280d73SBarry Smith    PetscBinarySynchronizedSeek - Moves the file pointer on a PETSc binary file.
696e5c89e4eSSatish Balay 
697e5c89e4eSSatish Balay    Input Parameters:
698e5c89e4eSSatish Balay +  fd - the file
69916a05f60SBarry Smith .  whence -  see `PetscBinarySeekType` for possible values
700811af0c4SBarry Smith -  off    - number of bytes to move. Use `PETSC_BINARY_INT_SIZE`, `PETSC_BINARY_SCALAR_SIZE`,
701811af0c4SBarry Smith             etc. in your calculation rather than `sizeof()` to compute byte lengths.
702e5c89e4eSSatish Balay 
703e5c89e4eSSatish Balay    Output Parameter:
704e5c89e4eSSatish Balay .   offset - new offset in file
705e5c89e4eSSatish Balay 
706e5c89e4eSSatish Balay    Level: developer
707e5c89e4eSSatish Balay 
70816a05f60SBarry Smith .seealso: `PetscBinaryRead()`, `PetscBinarySeekType`, `PetscBinaryWrite()`, `PetscBinaryOpen()`, `PetscBinarySynchronizedWrite()`, `PetscBinarySynchronizedRead()`,
709db781477SPatrick Sanan           `PetscBinarySynchronizedSeek()`
710e5c89e4eSSatish Balay @*/
711d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscBinarySynchronizedSeek(MPI_Comm comm, int fd, off_t off, PetscBinarySeekType whence, off_t *offset)
712d71ae5a4SJacob Faibussowitsch {
713e5c89e4eSSatish Balay   PetscMPIInt rank;
714e5c89e4eSSatish Balay 
715e5c89e4eSSatish Balay   PetscFunctionBegin;
7169566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
71748a46eb9SPierre Jolivet   if (rank == 0) PetscCall(PetscBinarySeek(fd, off, whence, offset));
7183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
719e5c89e4eSSatish Balay }
720e5c89e4eSSatish Balay 
7210fc9d207SBarry Smith #if defined(PETSC_HAVE_MPIIO)
722e39fd77fSBarry Smith 
723951e3c8eSBarry Smith   #if defined(PETSC_USE_PETSC_MPI_EXTERNAL32)
724e39fd77fSBarry Smith /*
725e39fd77fSBarry Smith       MPICH does not provide the external32 representation for MPI_File_set_view() so we need to provide the functions.
726e39fd77fSBarry Smith     These are set into MPI in PetscInitialize() via MPI_Register_datarep()
727e39fd77fSBarry Smith 
728e39fd77fSBarry Smith     Note I use PetscMPIInt for the MPI error codes since that is what MPI uses (instead of the standard PetscErrorCode)
729e39fd77fSBarry Smith 
730951e3c8eSBarry Smith     The next three routines are not used because MPICH does not support their use
731e39fd77fSBarry Smith 
732e39fd77fSBarry Smith */
733d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscMPIInt PetscDataRep_extent_fn(MPI_Datatype datatype, MPI_Aint *file_extent, void *extra_state)
734d71ae5a4SJacob Faibussowitsch {
735e39fd77fSBarry Smith   MPI_Aint    ub;
736e39fd77fSBarry Smith   PetscMPIInt ierr;
737e39fd77fSBarry Smith 
738e39fd77fSBarry Smith   ierr = MPI_Type_get_extent(datatype, &ub, file_extent);
739e39fd77fSBarry Smith   return ierr;
740e39fd77fSBarry Smith }
741e39fd77fSBarry Smith 
742d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscMPIInt PetscDataRep_read_conv_fn(void *userbuf, MPI_Datatype datatype, PetscMPIInt count, void *filebuf, MPI_Offset position, void *extra_state)
743d71ae5a4SJacob Faibussowitsch {
744e39fd77fSBarry Smith   PetscDataType pdtype;
745e39fd77fSBarry Smith   PetscMPIInt   ierr;
746e39fd77fSBarry Smith   size_t        dsize;
747e39fd77fSBarry Smith 
7489566063dSJacob Faibussowitsch   PetscCall(PetscMPIDataTypeToPetscDataType(datatype, &pdtype));
7499566063dSJacob Faibussowitsch   PetscCall(PetscDataTypeGetSize(pdtype, &dsize));
750e39fd77fSBarry Smith 
751e39fd77fSBarry Smith   /* offset is given in units of MPI_Datatype */
752e39fd77fSBarry Smith   userbuf = ((char *)userbuf) + dsize * position;
753e39fd77fSBarry Smith 
7549566063dSJacob Faibussowitsch   PetscCall(PetscMemcpy(userbuf, filebuf, count * dsize));
7559566063dSJacob Faibussowitsch   if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(userbuf, pdtype, count));
756e39fd77fSBarry Smith   return ierr;
757e39fd77fSBarry Smith }
758e39fd77fSBarry Smith 
759d71ae5a4SJacob Faibussowitsch PetscMPIInt PetscDataRep_write_conv_fn(void *userbuf, MPI_Datatype datatype, PetscMPIInt count, void *filebuf, MPI_Offset position, void *extra_state)
760d71ae5a4SJacob Faibussowitsch {
761e39fd77fSBarry Smith   PetscDataType pdtype;
762e39fd77fSBarry Smith   PetscMPIInt   ierr;
763e39fd77fSBarry Smith   size_t        dsize;
764e39fd77fSBarry Smith 
7659566063dSJacob Faibussowitsch   PetscCall(PetscMPIDataTypeToPetscDataType(datatype, &pdtype));
7669566063dSJacob Faibussowitsch   PetscCall(PetscDataTypeGetSize(pdtype, &dsize));
767e39fd77fSBarry Smith 
768e39fd77fSBarry Smith   /* offset is given in units of MPI_Datatype */
769e39fd77fSBarry Smith   userbuf = ((char *)userbuf) + dsize * position;
770e39fd77fSBarry Smith 
7719566063dSJacob Faibussowitsch   PetscCall(PetscMemcpy(filebuf, userbuf, count * dsize));
7729566063dSJacob Faibussowitsch   if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(filebuf, pdtype, count));
773e39fd77fSBarry Smith   return ierr;
774e39fd77fSBarry Smith }
775951e3c8eSBarry Smith   #endif
776e39fd77fSBarry Smith 
777d71ae5a4SJacob Faibussowitsch PetscErrorCode MPIU_File_write_all(MPI_File fd, void *data, PetscMPIInt cnt, MPI_Datatype dtype, MPI_Status *status)
778d71ae5a4SJacob Faibussowitsch {
779e39fd77fSBarry Smith   PetscDataType pdtype;
78030815ce0SLisandro Dalcin 
781e39fd77fSBarry Smith   PetscFunctionBegin;
7829566063dSJacob Faibussowitsch   PetscCall(PetscMPIDataTypeToPetscDataType(dtype, &pdtype));
7839566063dSJacob Faibussowitsch   if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(data, pdtype, cnt));
7849566063dSJacob Faibussowitsch   PetscCallMPI(MPI_File_write_all(fd, data, cnt, dtype, status));
7859566063dSJacob Faibussowitsch   if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(data, pdtype, cnt));
7863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
787e39fd77fSBarry Smith }
788e39fd77fSBarry Smith 
789d71ae5a4SJacob Faibussowitsch PetscErrorCode MPIU_File_read_all(MPI_File fd, void *data, PetscMPIInt cnt, MPI_Datatype dtype, MPI_Status *status)
790d71ae5a4SJacob Faibussowitsch {
791e39fd77fSBarry Smith   PetscDataType pdtype;
792e39fd77fSBarry Smith 
793e39fd77fSBarry Smith   PetscFunctionBegin;
7949566063dSJacob Faibussowitsch   PetscCall(PetscMPIDataTypeToPetscDataType(dtype, &pdtype));
7959566063dSJacob Faibussowitsch   PetscCallMPI(MPI_File_read_all(fd, data, cnt, dtype, status));
7969566063dSJacob Faibussowitsch   if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(data, pdtype, cnt));
7973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
798e39fd77fSBarry Smith }
79930815ce0SLisandro Dalcin 
800d71ae5a4SJacob Faibussowitsch PetscErrorCode MPIU_File_write_at(MPI_File fd, MPI_Offset off, void *data, PetscMPIInt cnt, MPI_Datatype dtype, MPI_Status *status)
801d71ae5a4SJacob Faibussowitsch {
802c4e82887SLisandro Dalcin   PetscDataType pdtype;
803c4e82887SLisandro Dalcin 
804c4e82887SLisandro Dalcin   PetscFunctionBegin;
8059566063dSJacob Faibussowitsch   PetscCall(PetscMPIDataTypeToPetscDataType(dtype, &pdtype));
8069566063dSJacob Faibussowitsch   if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(data, pdtype, cnt));
8079566063dSJacob Faibussowitsch   PetscCallMPI(MPI_File_write_at(fd, off, data, cnt, dtype, status));
8089566063dSJacob Faibussowitsch   if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(data, pdtype, cnt));
8093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
810c4e82887SLisandro Dalcin }
811c4e82887SLisandro Dalcin 
812d71ae5a4SJacob Faibussowitsch PetscErrorCode MPIU_File_read_at(MPI_File fd, MPI_Offset off, void *data, PetscMPIInt cnt, MPI_Datatype dtype, MPI_Status *status)
813d71ae5a4SJacob Faibussowitsch {
814c4e82887SLisandro Dalcin   PetscDataType pdtype;
815c4e82887SLisandro Dalcin 
816c4e82887SLisandro Dalcin   PetscFunctionBegin;
8179566063dSJacob Faibussowitsch   PetscCall(PetscMPIDataTypeToPetscDataType(dtype, &pdtype));
8189566063dSJacob Faibussowitsch   PetscCallMPI(MPI_File_read_at(fd, off, data, cnt, dtype, status));
8199566063dSJacob Faibussowitsch   if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(data, pdtype, cnt));
8203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
821c4e82887SLisandro Dalcin }
822c4e82887SLisandro Dalcin 
823d71ae5a4SJacob Faibussowitsch PetscErrorCode MPIU_File_write_at_all(MPI_File fd, MPI_Offset off, void *data, PetscMPIInt cnt, MPI_Datatype dtype, MPI_Status *status)
824d71ae5a4SJacob Faibussowitsch {
825c4e82887SLisandro Dalcin   PetscDataType pdtype;
826c4e82887SLisandro Dalcin 
827c4e82887SLisandro Dalcin   PetscFunctionBegin;
8289566063dSJacob Faibussowitsch   PetscCall(PetscMPIDataTypeToPetscDataType(dtype, &pdtype));
8299566063dSJacob Faibussowitsch   if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(data, pdtype, cnt));
8309566063dSJacob Faibussowitsch   PetscCallMPI(MPI_File_write_at_all(fd, off, data, cnt, dtype, status));
8319566063dSJacob Faibussowitsch   if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(data, pdtype, cnt));
8323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
833c4e82887SLisandro Dalcin }
834c4e82887SLisandro Dalcin 
835d71ae5a4SJacob Faibussowitsch PetscErrorCode MPIU_File_read_at_all(MPI_File fd, MPI_Offset off, void *data, PetscMPIInt cnt, MPI_Datatype dtype, MPI_Status *status)
836d71ae5a4SJacob Faibussowitsch {
837c4e82887SLisandro Dalcin   PetscDataType pdtype;
838c4e82887SLisandro Dalcin 
839c4e82887SLisandro Dalcin   PetscFunctionBegin;
8409566063dSJacob Faibussowitsch   PetscCall(PetscMPIDataTypeToPetscDataType(dtype, &pdtype));
8419566063dSJacob Faibussowitsch   PetscCallMPI(MPI_File_read_at_all(fd, off, data, cnt, dtype, status));
8429566063dSJacob Faibussowitsch   if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(data, pdtype, cnt));
8433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
844c4e82887SLisandro Dalcin }
845c4e82887SLisandro Dalcin 
846951e3c8eSBarry Smith #endif
847