xref: /petsc/src/sys/fileio/sysio.c (revision 7de69702b957b5de648b60762d01f4e5276d32ac)
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 /*
61*7de69702SBarry 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 /*
79*7de69702SBarry 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 /*
98e5c89e4eSSatish Balay   PetscByteSwapShort - Swap bytes in a short
99e5c89e4eSSatish Balay */
100d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscByteSwapShort(short *buff, PetscInt n)
101d71ae5a4SJacob Faibussowitsch {
102e5c89e4eSSatish Balay   PetscInt i, j;
103e5c89e4eSSatish Balay   short    tmp;
104e5c89e4eSSatish Balay   char    *ptr1, *ptr2 = (char *)&tmp;
105e5c89e4eSSatish Balay 
106e5c89e4eSSatish Balay   PetscFunctionBegin;
107e5c89e4eSSatish Balay   for (j = 0; j < n; j++) {
108e5c89e4eSSatish Balay     ptr1 = (char *)(buff + j);
109a297a907SKarl Rupp     for (i = 0; i < (PetscInt)sizeof(short); i++) ptr2[i] = ptr1[sizeof(short) - 1 - i];
110a297a907SKarl Rupp     for (i = 0; i < (PetscInt)sizeof(short); i++) ptr1[i] = ptr2[i];
111e5c89e4eSSatish Balay   }
1123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
113e5c89e4eSSatish Balay }
114972064b6SLisandro Dalcin /*
115972064b6SLisandro Dalcin   PetscByteSwapLong - Swap bytes in a long
116972064b6SLisandro Dalcin */
117d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscByteSwapLong(long *buff, PetscInt n)
118d71ae5a4SJacob Faibussowitsch {
119972064b6SLisandro Dalcin   PetscInt i, j;
120972064b6SLisandro Dalcin   long     tmp;
121972064b6SLisandro Dalcin   char    *ptr1, *ptr2 = (char *)&tmp;
122972064b6SLisandro Dalcin 
123972064b6SLisandro Dalcin   PetscFunctionBegin;
124972064b6SLisandro Dalcin   for (j = 0; j < n; j++) {
125972064b6SLisandro Dalcin     ptr1 = (char *)(buff + j);
126972064b6SLisandro Dalcin     for (i = 0; i < (PetscInt)sizeof(long); i++) ptr2[i] = ptr1[sizeof(long) - 1 - i];
127972064b6SLisandro Dalcin     for (i = 0; i < (PetscInt)sizeof(long); i++) ptr1[i] = ptr2[i];
128972064b6SLisandro Dalcin   }
1293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
130972064b6SLisandro Dalcin }
13121532e8aSBarry Smith 
132e5c89e4eSSatish Balay /*
1334caf0332SSatish Balay   PetscByteSwapReal - Swap bytes in a PetscReal
1344caf0332SSatish Balay */
135d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscByteSwapReal(PetscReal *buff, PetscInt n)
136d71ae5a4SJacob Faibussowitsch {
1374caf0332SSatish Balay   PetscInt  i, j;
1384caf0332SSatish Balay   PetscReal tmp, *buff1 = (PetscReal *)buff;
1394caf0332SSatish Balay   char     *ptr1, *ptr2 = (char *)&tmp;
1404caf0332SSatish Balay 
1414caf0332SSatish Balay   PetscFunctionBegin;
1424caf0332SSatish Balay   for (j = 0; j < n; j++) {
1434caf0332SSatish Balay     ptr1 = (char *)(buff1 + j);
1444caf0332SSatish Balay     for (i = 0; i < (PetscInt)sizeof(PetscReal); i++) ptr2[i] = ptr1[sizeof(PetscReal) - 1 - i];
1454caf0332SSatish Balay     for (i = 0; i < (PetscInt)sizeof(PetscReal); i++) ptr1[i] = ptr2[i];
1464caf0332SSatish Balay   }
1473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1484caf0332SSatish Balay }
14921532e8aSBarry Smith 
1504caf0332SSatish Balay /*
15141f502e3SPatrick Sanan   PetscByteSwapScalar - Swap bytes in a PetscScalar
15241f502e3SPatrick Sanan   The complex case is dealt with with an array of PetscReal, twice as long.
153e5c89e4eSSatish Balay */
154d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscByteSwapScalar(PetscScalar *buff, PetscInt n)
155d71ae5a4SJacob Faibussowitsch {
156e5c89e4eSSatish Balay   PetscInt  i, j;
157e5c89e4eSSatish Balay   PetscReal tmp, *buff1 = (PetscReal *)buff;
158e5c89e4eSSatish Balay   char     *ptr1, *ptr2 = (char *)&tmp;
159e5c89e4eSSatish Balay 
160e5c89e4eSSatish Balay   PetscFunctionBegin;
161e5c89e4eSSatish Balay #if defined(PETSC_USE_COMPLEX)
162e5c89e4eSSatish Balay   n *= 2;
163e5c89e4eSSatish Balay #endif
164e5c89e4eSSatish Balay   for (j = 0; j < n; j++) {
165e5c89e4eSSatish Balay     ptr1 = (char *)(buff1 + j);
166a297a907SKarl Rupp     for (i = 0; i < (PetscInt)sizeof(PetscReal); i++) ptr2[i] = ptr1[sizeof(PetscReal) - 1 - i];
167a297a907SKarl Rupp     for (i = 0; i < (PetscInt)sizeof(PetscReal); i++) ptr1[i] = ptr2[i];
168e5c89e4eSSatish Balay   }
1693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
170e5c89e4eSSatish Balay }
17121532e8aSBarry Smith 
172e5c89e4eSSatish Balay /*
173e5c89e4eSSatish Balay   PetscByteSwapDouble - Swap bytes in a double
174e5c89e4eSSatish Balay */
175d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscByteSwapDouble(double *buff, PetscInt n)
176d71ae5a4SJacob Faibussowitsch {
177e5c89e4eSSatish Balay   PetscInt i, j;
178e5c89e4eSSatish Balay   double   tmp, *buff1 = (double *)buff;
179e5c89e4eSSatish Balay   char    *ptr1, *ptr2 = (char *)&tmp;
180e5c89e4eSSatish Balay 
181e5c89e4eSSatish Balay   PetscFunctionBegin;
182e5c89e4eSSatish Balay   for (j = 0; j < n; j++) {
183e5c89e4eSSatish Balay     ptr1 = (char *)(buff1 + j);
184a297a907SKarl Rupp     for (i = 0; i < (PetscInt)sizeof(double); i++) ptr2[i] = ptr1[sizeof(double) - 1 - i];
185a297a907SKarl Rupp     for (i = 0; i < (PetscInt)sizeof(double); i++) ptr1[i] = ptr2[i];
186e5c89e4eSSatish Balay   }
1873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
188e5c89e4eSSatish Balay }
189e39fd77fSBarry Smith 
190e95bf02fSSatish Balay /*
191e95bf02fSSatish Balay   PetscByteSwapFloat - Swap bytes in a float
192e95bf02fSSatish Balay */
193d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscByteSwapFloat(float *buff, PetscInt n)
194d71ae5a4SJacob Faibussowitsch {
195e95bf02fSSatish Balay   PetscInt i, j;
196e95bf02fSSatish Balay   float    tmp, *buff1 = (float *)buff;
197e95bf02fSSatish Balay   char    *ptr1, *ptr2 = (char *)&tmp;
198e95bf02fSSatish Balay 
199e95bf02fSSatish Balay   PetscFunctionBegin;
200e95bf02fSSatish Balay   for (j = 0; j < n; j++) {
201e95bf02fSSatish Balay     ptr1 = (char *)(buff1 + j);
202a297a907SKarl Rupp     for (i = 0; i < (PetscInt)sizeof(float); i++) ptr2[i] = ptr1[sizeof(float) - 1 - i];
203a297a907SKarl Rupp     for (i = 0; i < (PetscInt)sizeof(float); i++) ptr1[i] = ptr2[i];
204e95bf02fSSatish Balay   }
2053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
206e95bf02fSSatish Balay }
207e95bf02fSSatish Balay 
208d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscByteSwap(void *data, PetscDataType pdtype, PetscInt count)
209d71ae5a4SJacob Faibussowitsch {
210e39fd77fSBarry Smith   PetscFunctionBegin;
2119566063dSJacob Faibussowitsch   if (pdtype == PETSC_INT) PetscCall(PetscByteSwapInt((PetscInt *)data, count));
2129566063dSJacob Faibussowitsch   else if (pdtype == PETSC_ENUM) PetscCall(PetscByteSwapEnum((PetscEnum *)data, count));
2139566063dSJacob Faibussowitsch   else if (pdtype == PETSC_BOOL) PetscCall(PetscByteSwapBool((PetscBool *)data, count));
2149566063dSJacob Faibussowitsch   else if (pdtype == PETSC_SCALAR) PetscCall(PetscByteSwapScalar((PetscScalar *)data, count));
2159566063dSJacob Faibussowitsch   else if (pdtype == PETSC_REAL) PetscCall(PetscByteSwapReal((PetscReal *)data, count));
2169566063dSJacob Faibussowitsch   else if (pdtype == PETSC_COMPLEX) PetscCall(PetscByteSwapReal((PetscReal *)data, 2 * count));
2179566063dSJacob Faibussowitsch   else if (pdtype == PETSC_INT64) PetscCall(PetscByteSwapInt64((PetscInt64 *)data, count));
2189566063dSJacob Faibussowitsch   else if (pdtype == PETSC_DOUBLE) PetscCall(PetscByteSwapDouble((double *)data, count));
2199566063dSJacob Faibussowitsch   else if (pdtype == PETSC_FLOAT) PetscCall(PetscByteSwapFloat((float *)data, count));
2209566063dSJacob Faibussowitsch   else if (pdtype == PETSC_SHORT) PetscCall(PetscByteSwapShort((short *)data, count));
2219566063dSJacob Faibussowitsch   else if (pdtype == PETSC_LONG) PetscCall(PetscByteSwapLong((long *)data, count));
2223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
223e39fd77fSBarry Smith }
224e39fd77fSBarry Smith 
2259860990eSLisandro Dalcin /*@C
226e5c89e4eSSatish Balay    PetscBinaryRead - Reads from a binary file.
227e5c89e4eSSatish Balay 
228e5c89e4eSSatish Balay    Not Collective
229e5c89e4eSSatish Balay 
230e5c89e4eSSatish Balay    Input Parameters:
2319860990eSLisandro Dalcin +  fd - the file descriptor
2329860990eSLisandro Dalcin .  num  - the maximum number of items to read
233811af0c4SBarry Smith -  type - the type of items to read (`PETSC_INT`, `PETSC_REAL`, `PETSC_SCALAR`, etc.)
234e5c89e4eSSatish Balay 
235e5c89e4eSSatish Balay    Output Parameters:
23621532e8aSBarry Smith +  data - the buffer, this is an array of the type that matches the value in `type`
2379860990eSLisandro Dalcin -  count - the number of items read, optional
238e5c89e4eSSatish Balay 
239e5c89e4eSSatish Balay    Level: developer
240e5c89e4eSSatish Balay 
241e5c89e4eSSatish Balay    Notes:
24221532e8aSBarry Smith    If `count` is not provided and the number of items read is less than
2439860990eSLisandro Dalcin    the maximum number of items to read, then this routine errors.
2449860990eSLisandro Dalcin 
245811af0c4SBarry Smith    `PetscBinaryRead()` uses byte swapping to work on all machines; the files
24621532e8aSBarry Smith    are written ALWAYS using big-endian ordering. On little-endian machines the numbers
247f253e43cSLisandro Dalcin    are converted to the little-endian format when they are read in from the file.
24821532e8aSBarry Smith    When PETSc is ./configure with `--with-64-bit-indices` the integers are written to the
249*7de69702SBarry Smith    file as 64-bit integers, this means they can only be read back in when the option `--with-64-bit-indices`
25054f21887SBarry Smith    is used.
251e5c89e4eSSatish Balay 
252db781477SPatrick Sanan .seealso: `PetscBinaryWrite()`, `PetscBinaryOpen()`, `PetscBinaryClose()`, `PetscViewerBinaryGetDescriptor()`, `PetscBinarySynchronizedWrite()`,
253db781477SPatrick Sanan           `PetscBinarySynchronizedRead()`, `PetscBinarySynchronizedSeek()`
254e5c89e4eSSatish Balay @*/
255d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscBinaryRead(int fd, void *data, PetscInt num, PetscInt *count, PetscDataType type)
256d71ae5a4SJacob Faibussowitsch {
2579860990eSLisandro Dalcin   size_t typesize, m = (size_t)num, n = 0, maxblock = 65536;
2589860990eSLisandro Dalcin   char  *p = (char *)data;
2597a881295SBarry Smith #if defined(PETSC_USE_REAL___FLOAT128)
260cba51d77SBarry Smith   PetscBool readdouble = PETSC_FALSE;
2619860990eSLisandro Dalcin   double   *pdouble;
2627a881295SBarry Smith #endif
2639860990eSLisandro Dalcin   void *ptmp  = data;
26405acbc63SBarry Smith   char *fname = NULL;
265e5c89e4eSSatish Balay 
266e5c89e4eSSatish Balay   PetscFunctionBegin;
2679860990eSLisandro Dalcin   if (count) *count = 0;
26808401ef6SPierre Jolivet   PetscCheck(num >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to read a negative amount of data %" PetscInt_FMT, num);
2693ba16761SJacob Faibussowitsch   if (!num) PetscFunctionReturn(PETSC_SUCCESS);
270e5c89e4eSSatish Balay 
2712d53ad75SBarry Smith   if (type == PETSC_FUNCTION) {
2722d53ad75SBarry Smith     m     = 64;
2732d53ad75SBarry Smith     type  = PETSC_CHAR;
27405acbc63SBarry Smith     fname = (char *)malloc(m * sizeof(char));
2759860990eSLisandro Dalcin     p     = (char *)fname;
2762d53ad75SBarry Smith     ptmp  = (void *)fname;
27728b400f6SJacob Faibussowitsch     PetscCheck(fname, PETSC_COMM_SELF, PETSC_ERR_MEM, "Cannot allocate space for function name");
2782d53ad75SBarry Smith   }
2799860990eSLisandro Dalcin   if (type == PETSC_BIT_LOGICAL) m = PetscBTLength(m);
2802d53ad75SBarry Smith 
2819566063dSJacob Faibussowitsch   PetscCall(PetscDataTypeGetSize(type, &typesize));
282e5c89e4eSSatish Balay 
2837a881295SBarry Smith #if defined(PETSC_USE_REAL___FLOAT128)
2849566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(NULL, NULL, "-binary_read_double", &readdouble, NULL));
2857a881295SBarry Smith   /* If using __float128 precision we still read in doubles from file */
2869860990eSLisandro Dalcin   if ((type == PETSC_REAL || type == PETSC_COMPLEX) && readdouble) {
2879860990eSLisandro Dalcin     PetscInt cnt = num * ((type == PETSC_REAL) ? 1 : 2);
2889566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(cnt, &pdouble));
2899860990eSLisandro Dalcin     p = (char *)pdouble;
2909860990eSLisandro Dalcin     typesize /= 2;
2917a881295SBarry Smith   }
2927a881295SBarry Smith #endif
2937a881295SBarry Smith 
2949860990eSLisandro Dalcin   m *= typesize;
2959860990eSLisandro Dalcin 
296e5c89e4eSSatish Balay   while (m) {
2979860990eSLisandro Dalcin     size_t len = (m < maxblock) ? m : maxblock;
2989860990eSLisandro Dalcin     int    ret = (int)read(fd, p, len);
2999860990eSLisandro Dalcin     if (ret < 0 && errno == EINTR) continue;
3009860990eSLisandro Dalcin     if (!ret && len > 0) break; /* Proxy for EOF */
30108401ef6SPierre Jolivet     PetscCheck(ret >= 0, PETSC_COMM_SELF, PETSC_ERR_FILE_READ, "Error reading from file, errno %d", errno);
302ff9f933bSBarry Smith     m -= (size_t)ret;
3039860990eSLisandro Dalcin     p += ret;
304ff9f933bSBarry Smith     n += (size_t)ret;
305e5c89e4eSSatish Balay   }
30608401ef6SPierre Jolivet   PetscCheck(!m || count, PETSC_COMM_SELF, PETSC_ERR_FILE_READ, "Read past end of file");
3079860990eSLisandro Dalcin 
3089860990eSLisandro Dalcin   num = (PetscInt)(n / typesize); /* Should we require `n % typesize == 0` ? */
3099860990eSLisandro Dalcin   if (count) *count = num;        /* TODO: This is most likely wrong for PETSC_BIT_LOGICAL */
3107a881295SBarry Smith 
3117a881295SBarry Smith #if defined(PETSC_USE_REAL___FLOAT128)
3129860990eSLisandro Dalcin   if ((type == PETSC_REAL || type == PETSC_COMPLEX) && readdouble) {
3139860990eSLisandro Dalcin     PetscInt   i, cnt = num * ((type == PETSC_REAL) ? 1 : 2);
3149860990eSLisandro Dalcin     PetscReal *preal = (PetscReal *)data;
3159566063dSJacob Faibussowitsch     if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwapDouble(pdouble, cnt));
3169860990eSLisandro Dalcin     for (i = 0; i < cnt; i++) preal[i] = pdouble[i];
3179566063dSJacob Faibussowitsch     PetscCall(PetscFree(pdouble));
3183ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
3197a881295SBarry Smith   }
3207a881295SBarry Smith #endif
3217a881295SBarry Smith 
3229566063dSJacob Faibussowitsch   if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(ptmp, type, num));
323e5c89e4eSSatish Balay 
32405acbc63SBarry Smith   if (type == PETSC_FUNCTION) {
3252d53ad75SBarry Smith #if defined(PETSC_SERIALIZE_FUNCTIONS)
3269566063dSJacob Faibussowitsch     PetscCall(PetscDLSym(NULL, fname, (void **)data));
3272d53ad75SBarry Smith #else
3289860990eSLisandro Dalcin     *(void **)data = NULL;
3292d53ad75SBarry Smith #endif
33005acbc63SBarry Smith     free(fname);
3312d53ad75SBarry Smith   }
3323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
333e5c89e4eSSatish Balay }
3349860990eSLisandro Dalcin 
335a9acdec7SBarry Smith /*@C
336e5c89e4eSSatish Balay    PetscBinaryWrite - Writes to a binary file.
337e5c89e4eSSatish Balay 
338e5c89e4eSSatish Balay    Not Collective
339e5c89e4eSSatish Balay 
340e5c89e4eSSatish Balay    Input Parameters:
341e5c89e4eSSatish Balay +  fd     - the file
34221532e8aSBarry Smith .  p      - the buffer, an array of the type that matches the value in `type`
343e5c89e4eSSatish Balay .  n      - the number of items to write
344811af0c4SBarry Smith -  type   - the type of items to read (`PETSC_INT`, `PETSC_REAL` or `PETSC_SCALAR`)
345e5c89e4eSSatish Balay 
346e5c89e4eSSatish Balay    Level: advanced
347e5c89e4eSSatish Balay 
348e5c89e4eSSatish Balay    Notes:
349811af0c4SBarry Smith    `PetscBinaryWrite()` uses byte swapping to work on all machines; the files
350f253e43cSLisandro Dalcin    are written using big-endian ordering to the file. On little-endian machines the numbers
351e5c89e4eSSatish Balay    are converted to the big-endian format when they are written to disk.
35221532e8aSBarry Smith    When PETSc is configured using `./configure with --with-64-bit-indices` the integers are written to the
353*7de69702SBarry Smith    file as 64-bit integers, this means they can only be read back in when the option `--with-64-bit-indices`
35454f21887SBarry Smith    is used.
355e5c89e4eSSatish Balay 
35621532e8aSBarry Smith    If running with `__float128` precision the output of `PETSC_REAL` is in `__float128` unless one uses the `-binary_write_double` option
3570da86b62SBarry Smith 
358bfbbc7b7SBarry Smith    The buffer `p` should be read-write buffer, and not static data.
359e5c89e4eSSatish Balay    This way, byte-swapping is done in-place, and then the buffer is
360e5c89e4eSSatish Balay    written to the file.
361e5c89e4eSSatish Balay 
362e5c89e4eSSatish Balay    This routine restores the original contents of the buffer, after
363e5c89e4eSSatish Balay    it is written to the file. This is done by byte-swapping in-place
364f253e43cSLisandro Dalcin    the second time.
365e5c89e4eSSatish Balay 
366300a7f5bSBarry Smith    Because byte-swapping may be done on the values in data it cannot be declared const
367300a7f5bSBarry Smith 
368db781477SPatrick Sanan .seealso: `PetscBinaryRead()`, `PetscBinaryOpen()`, `PetscBinaryClose()`, `PetscViewerBinaryGetDescriptor()`, `PetscBinarySynchronizedWrite()`,
369db781477SPatrick Sanan           `PetscBinarySynchronizedRead()`, `PetscBinarySynchronizedSeek()`
370e5c89e4eSSatish Balay @*/
371d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscBinaryWrite(int fd, const void *p, PetscInt n, PetscDataType type)
372d71ae5a4SJacob Faibussowitsch {
373f253e43cSLisandro Dalcin   const char *pp = (char *)p;
374e5c89e4eSSatish Balay   int         err, wsize;
375e5c89e4eSSatish Balay   size_t      m = (size_t)n, maxblock = 65536;
376f253e43cSLisandro Dalcin   const void *ptmp  = p;
37705acbc63SBarry Smith   char       *fname = NULL;
3780da86b62SBarry Smith #if defined(PETSC_USE_REAL___FLOAT128)
379df40af56SBarry Smith   PetscBool  writedouble = PETSC_FALSE;
3800da86b62SBarry Smith   double    *ppp;
3810da86b62SBarry Smith   PetscReal *pv;
3820da86b62SBarry Smith   PetscInt   i;
3830da86b62SBarry Smith #endif
38441f502e3SPatrick Sanan   PetscDataType wtype = type;
385e5c89e4eSSatish Balay 
386e5c89e4eSSatish Balay   PetscFunctionBegin;
38708401ef6SPierre Jolivet   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to write a negative amount of data %" PetscInt_FMT, n);
3883ba16761SJacob Faibussowitsch   if (!n) PetscFunctionReturn(PETSC_SUCCESS);
389e5c89e4eSSatish Balay 
3902d53ad75SBarry Smith   if (type == PETSC_FUNCTION) {
3912d53ad75SBarry Smith #if defined(PETSC_SERIALIZE_FUNCTIONS)
3922d53ad75SBarry Smith     const char *fnametmp;
3932d53ad75SBarry Smith #endif
3942d53ad75SBarry Smith     m     = 64;
395e25ab156SSatish Balay     fname = (char *)malloc(m * sizeof(char));
39628b400f6SJacob Faibussowitsch     PetscCheck(fname, PETSC_COMM_SELF, PETSC_ERR_MEM, "Cannot allocate space for function name");
39705acbc63SBarry Smith #if defined(PETSC_SERIALIZE_FUNCTIONS)
39808401ef6SPierre Jolivet     PetscCheck(n <= 1, PETSC_COMM_SELF, PETSC_ERR_SUP, "Can only binary view a single function at a time");
3999566063dSJacob Faibussowitsch     PetscCall(PetscFPTFind(*(void **)p, &fnametmp));
4009566063dSJacob Faibussowitsch     PetscCall(PetscStrncpy(fname, fnametmp, m));
40105acbc63SBarry Smith #else
4029566063dSJacob Faibussowitsch     PetscCall(PetscStrncpy(fname, "", m));
40305acbc63SBarry Smith #endif
40401963f56SBarry Smith     wtype = PETSC_CHAR;
4052d53ad75SBarry Smith     pp    = (char *)fname;
4062d53ad75SBarry Smith     ptmp  = (void *)fname;
4072d53ad75SBarry Smith   }
4082d53ad75SBarry Smith 
4090da86b62SBarry Smith #if defined(PETSC_USE_REAL___FLOAT128)
4109566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(NULL, NULL, "-binary_write_double", &writedouble, NULL));
4110da86b62SBarry Smith   /* If using __float128 precision we still write in doubles to file */
412501ae109SJose E. Roman   if ((type == PETSC_SCALAR || type == PETSC_REAL || type == PETSC_COMPLEX) && writedouble) {
41341f502e3SPatrick Sanan     wtype = PETSC_DOUBLE;
4149566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(n, &ppp));
4150da86b62SBarry Smith     pv = (PetscReal *)pp;
416ad540459SPierre Jolivet     for (i = 0; i < n; i++) ppp[i] = (double)pv[i];
4170da86b62SBarry Smith     pp   = (char *)ppp;
4180da86b62SBarry Smith     ptmp = (char *)ppp;
4190da86b62SBarry Smith   }
4200da86b62SBarry Smith #endif
4210da86b62SBarry Smith 
42241f502e3SPatrick Sanan   if (wtype == PETSC_INT) m *= sizeof(PetscInt);
42341f502e3SPatrick Sanan   else if (wtype == PETSC_SCALAR) m *= sizeof(PetscScalar);
424501ae109SJose E. Roman #if defined(PETSC_HAVE_COMPLEX)
425501ae109SJose E. Roman   else if (wtype == PETSC_COMPLEX) m *= sizeof(PetscComplex);
426501ae109SJose E. Roman #endif
4274caf0332SSatish Balay   else if (wtype == PETSC_REAL) m *= sizeof(PetscReal);
42841f502e3SPatrick Sanan   else if (wtype == PETSC_DOUBLE) m *= sizeof(double);
42941f502e3SPatrick Sanan   else if (wtype == PETSC_FLOAT) m *= sizeof(float);
43041f502e3SPatrick Sanan   else if (wtype == PETSC_SHORT) m *= sizeof(short);
431972064b6SLisandro Dalcin   else if (wtype == PETSC_LONG) m *= sizeof(long);
43241f502e3SPatrick Sanan   else if (wtype == PETSC_CHAR) m *= sizeof(char);
43341f502e3SPatrick Sanan   else if (wtype == PETSC_ENUM) m *= sizeof(PetscEnum);
43441f502e3SPatrick Sanan   else if (wtype == PETSC_BOOL) m *= sizeof(PetscBool);
4359e3e4c22SLisandro Dalcin   else if (wtype == PETSC_INT64) m *= sizeof(PetscInt64);
43641f502e3SPatrick Sanan   else if (wtype == PETSC_BIT_LOGICAL) m = PetscBTLength(m) * sizeof(char);
437e32f2f54SBarry Smith   else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Unknown type");
438e5c89e4eSSatish Balay 
4399566063dSJacob Faibussowitsch   if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap((void *)ptmp, wtype, n));
440e5c89e4eSSatish Balay 
441e5c89e4eSSatish Balay   while (m) {
442e5c89e4eSSatish Balay     wsize = (m < maxblock) ? m : maxblock;
443e5c89e4eSSatish Balay     err   = write(fd, pp, wsize);
444e5c89e4eSSatish Balay     if (err < 0 && errno == EINTR) continue;
44508401ef6SPierre Jolivet     PetscCheck(err == wsize, PETSC_COMM_SELF, PETSC_ERR_FILE_WRITE, "Error writing to file total size %d err %d wsize %d", (int)n, (int)err, (int)wsize);
446e5c89e4eSSatish Balay     m -= wsize;
447e5c89e4eSSatish Balay     pp += wsize;
448e5c89e4eSSatish Balay   }
449e5c89e4eSSatish Balay 
4509566063dSJacob Faibussowitsch   if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap((void *)ptmp, wtype, n));
451f253e43cSLisandro Dalcin 
452ad540459SPierre Jolivet   if (type == PETSC_FUNCTION) free(fname);
4530da86b62SBarry Smith #if defined(PETSC_USE_REAL___FLOAT128)
45448a46eb9SPierre Jolivet   if ((type == PETSC_SCALAR || type == PETSC_REAL || type == PETSC_COMPLEX) && writedouble) PetscCall(PetscFree(ppp));
4550da86b62SBarry Smith #endif
4563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
457e5c89e4eSSatish Balay }
458e5c89e4eSSatish Balay 
459e5c89e4eSSatish Balay /*@C
460e5c89e4eSSatish Balay    PetscBinaryOpen - Opens a PETSc binary file.
461e5c89e4eSSatish Balay 
462e5c89e4eSSatish Balay    Not Collective
463e5c89e4eSSatish Balay 
464e5c89e4eSSatish Balay    Input Parameters:
465e5c89e4eSSatish Balay +  name - filename
466811af0c4SBarry Smith -  mode - open mode of binary file, one of `FILE_MODE_READ`, `FILE_MODE_WRITE`, `FILE_MODE_APPEND``
467e5c89e4eSSatish Balay 
468e5c89e4eSSatish Balay    Output Parameter:
469e5c89e4eSSatish Balay .  fd - the file
470e5c89e4eSSatish Balay 
471e5c89e4eSSatish Balay    Level: advanced
472e5c89e4eSSatish Balay 
473db781477SPatrick Sanan .seealso: `PetscBinaryRead()`, `PetscBinaryWrite()`, `PetscFileMode`, `PetscViewerFileSetMode()`, `PetscViewerBinaryGetDescriptor()`,
474db781477SPatrick Sanan           `PetscBinarySynchronizedWrite()`, `PetscBinarySynchronizedRead()`, `PetscBinarySynchronizedSeek()`
475e5c89e4eSSatish Balay @*/
476d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscBinaryOpen(const char name[], PetscFileMode mode, int *fd)
477d71ae5a4SJacob Faibussowitsch {
478e5c89e4eSSatish Balay   PetscFunctionBegin;
479cc843e7aSLisandro Dalcin   switch (mode) {
480d71ae5a4SJacob Faibussowitsch   case FILE_MODE_READ:
481d71ae5a4SJacob Faibussowitsch     *fd = open(name, O_BINARY | O_RDONLY, 0);
482d71ae5a4SJacob Faibussowitsch     break;
483d71ae5a4SJacob Faibussowitsch   case FILE_MODE_WRITE:
484d71ae5a4SJacob Faibussowitsch     *fd = open(name, O_BINARY | O_WRONLY | O_CREAT | O_TRUNC, 0666);
485d71ae5a4SJacob Faibussowitsch     break;
486d71ae5a4SJacob Faibussowitsch   case FILE_MODE_APPEND:
487d71ae5a4SJacob Faibussowitsch     *fd = open(name, O_BINARY | O_WRONLY | O_APPEND, 0);
488d71ae5a4SJacob Faibussowitsch     break;
489d71ae5a4SJacob Faibussowitsch   default:
490d71ae5a4SJacob Faibussowitsch     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Unsupported file mode %s", PetscFileModes[mode]);
491e5c89e4eSSatish Balay   }
49208401ef6SPierre Jolivet   PetscCheck(*fd != -1, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Cannot open file %s for %s", name, PetscFileModes[mode]);
4933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
494e5c89e4eSSatish Balay }
495e5c89e4eSSatish Balay 
496e30d2299SSatish Balay /*@
497e5c89e4eSSatish Balay    PetscBinaryClose - Closes a PETSc binary file.
498e5c89e4eSSatish Balay 
499e5c89e4eSSatish Balay    Not Collective
500e5c89e4eSSatish Balay 
501e5c89e4eSSatish Balay    Output Parameter:
502e5c89e4eSSatish Balay .  fd - the file
503e5c89e4eSSatish Balay 
504e5c89e4eSSatish Balay    Level: advanced
505e5c89e4eSSatish Balay 
506db781477SPatrick Sanan .seealso: `PetscBinaryRead()`, `PetscBinaryWrite()`, `PetscBinaryOpen()`, `PetscBinarySynchronizedWrite()`, `PetscBinarySynchronizedRead()`,
507db781477SPatrick Sanan           `PetscBinarySynchronizedSeek()`
508e5c89e4eSSatish Balay @*/
509d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscBinaryClose(int fd)
510d71ae5a4SJacob Faibussowitsch {
511e5c89e4eSSatish Balay   PetscFunctionBegin;
512cc73adaaSBarry Smith   PetscCheck(!close(fd), PETSC_COMM_SELF, PETSC_ERR_SYS, "close() failed on file descriptor");
5133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
514e5c89e4eSSatish Balay }
515e5c89e4eSSatish Balay 
516e8976759SBarry Smith /*@C
517e5c89e4eSSatish Balay    PetscBinarySeek - Moves the file pointer on a PETSc binary file.
518e5c89e4eSSatish Balay 
519e5c89e4eSSatish Balay    Not Collective
520e5c89e4eSSatish Balay 
521e5c89e4eSSatish Balay    Input Parameters:
522e5c89e4eSSatish Balay +  fd - the file
523811af0c4SBarry Smith .  off - number of bytes to move. Use `PETSC_BINARY_INT_SIZE`, `PETSC_BINARY_SCALAR_SIZE`,
52421532e8aSBarry Smith             etc. in your calculation rather than `sizeof()` to compute byte lengths.
52516a05f60SBarry Smith -  whence - see `PetscBinarySeekType` for possible values
526e5c89e4eSSatish Balay 
527e5c89e4eSSatish Balay    Output Parameter:
528e5c89e4eSSatish Balay .   offset - new offset in file
529e5c89e4eSSatish Balay 
530e5c89e4eSSatish Balay    Level: developer
531e5c89e4eSSatish Balay 
53216a05f60SBarry Smith .seealso: `PetscBinaryRead()`, `PetscBinarySeekType`, `PetscBinaryWrite()`, `PetscBinaryOpen()`, `PetscBinarySynchronizedWrite()`, `PetscBinarySynchronizedRead()`,
533db781477SPatrick Sanan           `PetscBinarySynchronizedSeek()`
534e5c89e4eSSatish Balay @*/
535d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscBinarySeek(int fd, off_t off, PetscBinarySeekType whence, off_t *offset)
536d71ae5a4SJacob Faibussowitsch {
537e5c89e4eSSatish Balay   int iwhence = 0;
538e5c89e4eSSatish Balay 
539e5c89e4eSSatish Balay   PetscFunctionBegin;
540a297a907SKarl Rupp   if (whence == PETSC_BINARY_SEEK_SET) iwhence = SEEK_SET;
541a297a907SKarl Rupp   else if (whence == PETSC_BINARY_SEEK_CUR) iwhence = SEEK_CUR;
542a297a907SKarl Rupp   else if (whence == PETSC_BINARY_SEEK_END) iwhence = SEEK_END;
543a297a907SKarl Rupp   else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Unknown seek location");
544e5c89e4eSSatish Balay #if defined(PETSC_HAVE_LSEEK)
545e5c89e4eSSatish Balay   *offset = lseek(fd, off, iwhence);
546e5c89e4eSSatish Balay #elif defined(PETSC_HAVE__LSEEK)
547e5c89e4eSSatish Balay   *offset = _lseek(fd, (long)off, iwhence);
548e5c89e4eSSatish Balay #else
549e32f2f54SBarry Smith   SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP_SYS, "System does not have a way of seeking on a file");
550e5c89e4eSSatish Balay #endif
5513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
552e5c89e4eSSatish Balay }
553e5c89e4eSSatish Balay 
554e5c89e4eSSatish Balay /*@C
55521532e8aSBarry Smith    PetscBinarySynchronizedRead - Reads from a binary file, all MPI processes get the same values
556e5c89e4eSSatish Balay 
557d083f849SBarry Smith    Collective
558e5c89e4eSSatish Balay 
559e5c89e4eSSatish Balay    Input Parameters:
560e5c89e4eSSatish Balay +  comm - the MPI communicator
5619860990eSLisandro Dalcin .  fd - the file descriptor
5629860990eSLisandro Dalcin .  num  - the maximum number of items to read
563811af0c4SBarry Smith -  type - the type of items to read (`PETSC_INT`, `PETSC_REAL`, `PETSC_SCALAR`, etc.)
564e5c89e4eSSatish Balay 
565e5c89e4eSSatish Balay    Output Parameters:
56621532e8aSBarry Smith +  data - the buffer, an array of the type that matches the value in `type`
5679860990eSLisandro Dalcin -  count - the number of items read, optional
568e5c89e4eSSatish Balay 
569e5c89e4eSSatish Balay    Level: developer
570e5c89e4eSSatish Balay 
571e5c89e4eSSatish Balay    Notes:
572811af0c4SBarry Smith    Does a `PetscBinaryRead()` followed by an `MPI_Bcast()`
573e5c89e4eSSatish Balay 
57421532e8aSBarry Smith    If `count` is not provided and the number of items read is less than
5759860990eSLisandro Dalcin    the maximum number of items to read, then this routine errors.
5769860990eSLisandro Dalcin 
577811af0c4SBarry Smith    `PetscBinarySynchronizedRead()` uses byte swapping to work on all machines.
57821532e8aSBarry Smith    The files  are written using big-endian ordering to the file. On little-endian machines the numbers
57921532e8aSBarry Smith    are converted to the big-endian format when they are written to disk.
58021532e8aSBarry Smith    When PETSc is configured using `./configure with --with-64-bit-indices` the integers are written to the
581*7de69702SBarry Smith    file as 64-bit integers, this means they can only be read back in when the option `--with-64-bit-indices`
58221532e8aSBarry Smith    is used.
583e5c89e4eSSatish Balay 
584db781477SPatrick Sanan .seealso: `PetscBinaryWrite()`, `PetscBinaryOpen()`, `PetscBinaryClose()`, `PetscBinaryRead()`, `PetscBinarySynchronizedWrite()`,
585db781477SPatrick Sanan           `PetscBinarySynchronizedSeek()`
586e5c89e4eSSatish Balay @*/
587d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscBinarySynchronizedRead(MPI_Comm comm, int fd, void *data, PetscInt num, PetscInt *count, PetscDataType type)
588d71ae5a4SJacob Faibussowitsch {
5898b8bf82cSBarry Smith   PetscMPIInt  rank, size;
590e5c89e4eSSatish Balay   MPI_Datatype mtype;
5919860990eSLisandro Dalcin   PetscInt     ibuf[2] = {0, 0};
59205acbc63SBarry Smith   char        *fname   = NULL;
5939860990eSLisandro Dalcin   void        *fptr    = NULL;
594e5c89e4eSSatish Balay 
595e5c89e4eSSatish Balay   PetscFunctionBegin;
5962d53ad75SBarry Smith   if (type == PETSC_FUNCTION) {
5979860990eSLisandro Dalcin     num   = 64;
5982d53ad75SBarry Smith     type  = PETSC_CHAR;
5999860990eSLisandro Dalcin     fname = (char *)malloc(num * sizeof(char));
6009860990eSLisandro Dalcin     fptr  = data;
6019860990eSLisandro Dalcin     data  = (void *)fname;
60228b400f6SJacob Faibussowitsch     PetscCheck(fname, PETSC_COMM_SELF, PETSC_ERR_MEM, "Cannot allocate space for function name");
6032d53ad75SBarry Smith   }
6042d53ad75SBarry Smith 
6059566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
6069566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
607ad540459SPierre Jolivet   if (rank == 0) ibuf[0] = PetscBinaryRead(fd, data, num, count ? &ibuf[1] : NULL, type);
6089566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Bcast(ibuf, 2, MPIU_INT, 0, comm));
6099566063dSJacob Faibussowitsch   PetscCall((PetscErrorCode)ibuf[0]);
6108b8bf82cSBarry Smith 
6118b8bf82cSBarry 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 */
6128b8bf82cSBarry Smith   if (size > 1) {
6139566063dSJacob Faibussowitsch     PetscCall(PetscDataTypeToMPIDataType(type, &mtype));
6149566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Bcast(data, count ? ibuf[1] : num, mtype, 0, comm));
6158b8bf82cSBarry Smith   }
6169860990eSLisandro Dalcin   if (count) *count = ibuf[1];
6172d53ad75SBarry Smith 
618e366c363SBarry Smith   if (type == PETSC_FUNCTION) {
6192d53ad75SBarry Smith #if defined(PETSC_SERIALIZE_FUNCTIONS)
6209566063dSJacob Faibussowitsch     PetscCall(PetscDLLibrarySym(PETSC_COMM_SELF, &PetscDLLibrariesLoaded, NULL, fname, (void **)fptr));
6212d53ad75SBarry Smith #else
6229860990eSLisandro Dalcin     *(void **)fptr = NULL;
6232d53ad75SBarry Smith #endif
624e366c363SBarry Smith     free(fname);
6252d53ad75SBarry Smith   }
6263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
627e5c89e4eSSatish Balay }
628e5c89e4eSSatish Balay 
629e5c89e4eSSatish Balay /*@C
6301d280d73SBarry Smith    PetscBinarySynchronizedWrite - writes to a binary file.
631e5c89e4eSSatish Balay 
632d083f849SBarry Smith    Collective
633e5c89e4eSSatish Balay 
634e5c89e4eSSatish Balay    Input Parameters:
635e5c89e4eSSatish Balay +  comm - the MPI communicator
636e5c89e4eSSatish Balay .  fd - the file
637e5c89e4eSSatish Balay .  n  - the number of items to write
63821532e8aSBarry Smith .  p - the buffer, an array of the type that matches the value in `type`
639811af0c4SBarry Smith -  type - the type of items to write (`PETSC_INT`, `PETSC_REAL` or `PETSC_SCALAR`)
640e5c89e4eSSatish Balay 
641e5c89e4eSSatish Balay    Level: developer
642e5c89e4eSSatish Balay 
643e5c89e4eSSatish Balay    Notes:
64421532e8aSBarry Smith    MPI rank 0 does a `PetscBinaryWrite()` the values on other MPI processes are not used
645e5c89e4eSSatish Balay 
64621532e8aSBarry Smith    The files  are written using big-endian ordering to the file. On little-endian machines the numbers
64721532e8aSBarry Smith    are converted to the big-endian format when they are written to disk.
64821532e8aSBarry Smith    When PETSc is configured using `./configure with --with-64-bit-indices` the integers are written to the
649*7de69702SBarry Smith    file as 64-bit integers, this means they can only be read back in when the option `--with-64-bit-indices`
65021532e8aSBarry Smith    is used.
651e5c89e4eSSatish Balay 
652811af0c4SBarry Smith    Because byte-swapping may be done on the values in data it cannot be declared const
653300a7f5bSBarry Smith 
654811af0c4SBarry Smith    WARNING:
655bfbbc7b7SBarry Smith    This is NOT like `PetscSynchronizedFPrintf()`! This routine ignores calls on all but MPI rank 0,
65621532e8aSBarry Smith    while `PetscSynchronizedFPrintf()` has all MPI processes print their strings in order.
6571d280d73SBarry Smith 
658db781477SPatrick Sanan .seealso: `PetscBinaryWrite()`, `PetscBinaryOpen()`, `PetscBinaryClose()`, `PetscBinaryRead()`, `PetscBinarySynchronizedRead()`,
659db781477SPatrick Sanan           `PetscBinarySynchronizedSeek()`
660e5c89e4eSSatish Balay @*/
661d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscBinarySynchronizedWrite(MPI_Comm comm, int fd, const void *p, PetscInt n, PetscDataType type)
662d71ae5a4SJacob Faibussowitsch {
663e5c89e4eSSatish Balay   PetscMPIInt rank;
664e5c89e4eSSatish Balay 
665e5c89e4eSSatish Balay   PetscFunctionBegin;
6669566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
66748a46eb9SPierre Jolivet   if (rank == 0) PetscCall(PetscBinaryWrite(fd, p, n, type));
6683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
669e5c89e4eSSatish Balay }
670e5c89e4eSSatish Balay 
671e5c89e4eSSatish Balay /*@C
6721d280d73SBarry Smith    PetscBinarySynchronizedSeek - Moves the file pointer on a PETSc binary file.
673e5c89e4eSSatish Balay 
674e5c89e4eSSatish Balay    Input Parameters:
675e5c89e4eSSatish Balay +  fd - the file
67616a05f60SBarry Smith .  whence -  see `PetscBinarySeekType` for possible values
677811af0c4SBarry Smith -  off    - number of bytes to move. Use `PETSC_BINARY_INT_SIZE`, `PETSC_BINARY_SCALAR_SIZE`,
678811af0c4SBarry Smith             etc. in your calculation rather than `sizeof()` to compute byte lengths.
679e5c89e4eSSatish Balay 
680e5c89e4eSSatish Balay    Output Parameter:
681e5c89e4eSSatish Balay .   offset - new offset in file
682e5c89e4eSSatish Balay 
683e5c89e4eSSatish Balay    Level: developer
684e5c89e4eSSatish Balay 
68516a05f60SBarry Smith .seealso: `PetscBinaryRead()`, `PetscBinarySeekType`, `PetscBinaryWrite()`, `PetscBinaryOpen()`, `PetscBinarySynchronizedWrite()`, `PetscBinarySynchronizedRead()`,
686db781477SPatrick Sanan           `PetscBinarySynchronizedSeek()`
687e5c89e4eSSatish Balay @*/
688d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscBinarySynchronizedSeek(MPI_Comm comm, int fd, off_t off, PetscBinarySeekType whence, off_t *offset)
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(PetscBinarySeek(fd, off, whence, offset));
6953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
696e5c89e4eSSatish Balay }
697e5c89e4eSSatish Balay 
6980fc9d207SBarry Smith #if defined(PETSC_HAVE_MPIIO)
699e39fd77fSBarry Smith 
700951e3c8eSBarry Smith   #if defined(PETSC_USE_PETSC_MPI_EXTERNAL32)
701e39fd77fSBarry Smith /*
702e39fd77fSBarry Smith       MPICH does not provide the external32 representation for MPI_File_set_view() so we need to provide the functions.
703e39fd77fSBarry Smith     These are set into MPI in PetscInitialize() via MPI_Register_datarep()
704e39fd77fSBarry Smith 
705e39fd77fSBarry Smith     Note I use PetscMPIInt for the MPI error codes since that is what MPI uses (instead of the standard PetscErrorCode)
706e39fd77fSBarry Smith 
707951e3c8eSBarry Smith     The next three routines are not used because MPICH does not support their use
708e39fd77fSBarry Smith 
709e39fd77fSBarry Smith */
710d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscMPIInt PetscDataRep_extent_fn(MPI_Datatype datatype, MPI_Aint *file_extent, void *extra_state)
711d71ae5a4SJacob Faibussowitsch {
712e39fd77fSBarry Smith   MPI_Aint    ub;
713e39fd77fSBarry Smith   PetscMPIInt ierr;
714e39fd77fSBarry Smith 
715e39fd77fSBarry Smith   ierr = MPI_Type_get_extent(datatype, &ub, file_extent);
716e39fd77fSBarry Smith   return ierr;
717e39fd77fSBarry Smith }
718e39fd77fSBarry Smith 
719d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscMPIInt PetscDataRep_read_conv_fn(void *userbuf, MPI_Datatype datatype, PetscMPIInt count, void *filebuf, MPI_Offset position, void *extra_state)
720d71ae5a4SJacob Faibussowitsch {
721e39fd77fSBarry Smith   PetscDataType pdtype;
722e39fd77fSBarry Smith   PetscMPIInt   ierr;
723e39fd77fSBarry Smith   size_t        dsize;
724e39fd77fSBarry Smith 
7259566063dSJacob Faibussowitsch   PetscCall(PetscMPIDataTypeToPetscDataType(datatype, &pdtype));
7269566063dSJacob Faibussowitsch   PetscCall(PetscDataTypeGetSize(pdtype, &dsize));
727e39fd77fSBarry Smith 
728e39fd77fSBarry Smith   /* offset is given in units of MPI_Datatype */
729e39fd77fSBarry Smith   userbuf = ((char *)userbuf) + dsize * position;
730e39fd77fSBarry Smith 
7319566063dSJacob Faibussowitsch   PetscCall(PetscMemcpy(userbuf, filebuf, count * dsize));
7329566063dSJacob Faibussowitsch   if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(userbuf, pdtype, count));
733e39fd77fSBarry Smith   return ierr;
734e39fd77fSBarry Smith }
735e39fd77fSBarry Smith 
736d71ae5a4SJacob Faibussowitsch PetscMPIInt PetscDataRep_write_conv_fn(void *userbuf, MPI_Datatype datatype, PetscMPIInt count, void *filebuf, MPI_Offset position, void *extra_state)
737d71ae5a4SJacob Faibussowitsch {
738e39fd77fSBarry Smith   PetscDataType pdtype;
739e39fd77fSBarry Smith   PetscMPIInt   ierr;
740e39fd77fSBarry Smith   size_t        dsize;
741e39fd77fSBarry Smith 
7429566063dSJacob Faibussowitsch   PetscCall(PetscMPIDataTypeToPetscDataType(datatype, &pdtype));
7439566063dSJacob Faibussowitsch   PetscCall(PetscDataTypeGetSize(pdtype, &dsize));
744e39fd77fSBarry Smith 
745e39fd77fSBarry Smith   /* offset is given in units of MPI_Datatype */
746e39fd77fSBarry Smith   userbuf = ((char *)userbuf) + dsize * position;
747e39fd77fSBarry Smith 
7489566063dSJacob Faibussowitsch   PetscCall(PetscMemcpy(filebuf, userbuf, count * dsize));
7499566063dSJacob Faibussowitsch   if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(filebuf, pdtype, count));
750e39fd77fSBarry Smith   return ierr;
751e39fd77fSBarry Smith }
752951e3c8eSBarry Smith   #endif
753e39fd77fSBarry Smith 
754d71ae5a4SJacob Faibussowitsch PetscErrorCode MPIU_File_write_all(MPI_File fd, void *data, PetscMPIInt cnt, MPI_Datatype dtype, MPI_Status *status)
755d71ae5a4SJacob Faibussowitsch {
756e39fd77fSBarry Smith   PetscDataType pdtype;
75730815ce0SLisandro Dalcin 
758e39fd77fSBarry Smith   PetscFunctionBegin;
7599566063dSJacob Faibussowitsch   PetscCall(PetscMPIDataTypeToPetscDataType(dtype, &pdtype));
7609566063dSJacob Faibussowitsch   if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(data, pdtype, cnt));
7619566063dSJacob Faibussowitsch   PetscCallMPI(MPI_File_write_all(fd, data, cnt, dtype, status));
7629566063dSJacob Faibussowitsch   if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(data, pdtype, cnt));
7633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
764e39fd77fSBarry Smith }
765e39fd77fSBarry Smith 
766d71ae5a4SJacob Faibussowitsch PetscErrorCode MPIU_File_read_all(MPI_File fd, void *data, PetscMPIInt cnt, MPI_Datatype dtype, MPI_Status *status)
767d71ae5a4SJacob Faibussowitsch {
768e39fd77fSBarry Smith   PetscDataType pdtype;
769e39fd77fSBarry Smith 
770e39fd77fSBarry Smith   PetscFunctionBegin;
7719566063dSJacob Faibussowitsch   PetscCall(PetscMPIDataTypeToPetscDataType(dtype, &pdtype));
7729566063dSJacob Faibussowitsch   PetscCallMPI(MPI_File_read_all(fd, data, cnt, dtype, status));
7739566063dSJacob Faibussowitsch   if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(data, pdtype, cnt));
7743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
775e39fd77fSBarry Smith }
77630815ce0SLisandro Dalcin 
777d71ae5a4SJacob Faibussowitsch PetscErrorCode MPIU_File_write_at(MPI_File fd, MPI_Offset off, void *data, PetscMPIInt cnt, MPI_Datatype dtype, MPI_Status *status)
778d71ae5a4SJacob Faibussowitsch {
779c4e82887SLisandro Dalcin   PetscDataType pdtype;
780c4e82887SLisandro Dalcin 
781c4e82887SLisandro Dalcin   PetscFunctionBegin;
7829566063dSJacob Faibussowitsch   PetscCall(PetscMPIDataTypeToPetscDataType(dtype, &pdtype));
7839566063dSJacob Faibussowitsch   if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(data, pdtype, cnt));
7849566063dSJacob Faibussowitsch   PetscCallMPI(MPI_File_write_at(fd, off, data, cnt, dtype, status));
7859566063dSJacob Faibussowitsch   if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(data, pdtype, cnt));
7863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
787c4e82887SLisandro Dalcin }
788c4e82887SLisandro Dalcin 
789d71ae5a4SJacob Faibussowitsch PetscErrorCode MPIU_File_read_at(MPI_File fd, MPI_Offset off, void *data, PetscMPIInt cnt, MPI_Datatype dtype, MPI_Status *status)
790d71ae5a4SJacob Faibussowitsch {
791c4e82887SLisandro Dalcin   PetscDataType pdtype;
792c4e82887SLisandro Dalcin 
793c4e82887SLisandro Dalcin   PetscFunctionBegin;
7949566063dSJacob Faibussowitsch   PetscCall(PetscMPIDataTypeToPetscDataType(dtype, &pdtype));
7959566063dSJacob Faibussowitsch   PetscCallMPI(MPI_File_read_at(fd, off, data, cnt, dtype, status));
7969566063dSJacob Faibussowitsch   if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(data, pdtype, cnt));
7973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
798c4e82887SLisandro Dalcin }
799c4e82887SLisandro Dalcin 
800d71ae5a4SJacob Faibussowitsch PetscErrorCode MPIU_File_write_at_all(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_all(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_all(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_all(fd, off, data, cnt, dtype, status));
8199566063dSJacob Faibussowitsch   if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(data, pdtype, cnt));
8203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
821c4e82887SLisandro Dalcin }
822c4e82887SLisandro Dalcin 
823951e3c8eSBarry Smith #endif
824