xref: /petsc/src/sys/fileio/sysio.c (revision be37439ebbbdb2f81c3420c175a94aa72e59929c)
1c6db04a5SJed Brown #include <petscsys.h>
2cc843e7aSLisandro Dalcin #include <petscbt.h>
3e5c89e4eSSatish Balay #include <errno.h>
4e5c89e4eSSatish Balay #include <fcntl.h>
5e5c89e4eSSatish Balay #if defined(PETSC_HAVE_UNISTD_H)
6e5c89e4eSSatish Balay   #include <unistd.h>
7e5c89e4eSSatish Balay #endif
8e5c89e4eSSatish Balay #if defined(PETSC_HAVE_IO_H)
9e5c89e4eSSatish Balay   #include <io.h>
10e5c89e4eSSatish Balay #endif
11cc843e7aSLisandro Dalcin #if !defined(PETSC_HAVE_O_BINARY)
12cc843e7aSLisandro Dalcin   #define O_BINARY 0
13cc843e7aSLisandro Dalcin #endif
14e5c89e4eSSatish Balay 
1502c9f0b5SLisandro Dalcin const char *const PetscFileModes[] = {"READ", "WRITE", "APPEND", "UPDATE", "APPEND_UPDATE", "PetscFileMode", "PETSC_FILE_", NULL};
16d6a4318aSJed Brown 
17e5c89e4eSSatish Balay /*
186de02169SBarry Smith   PetscByteSwapEnum - Swap bytes in a  PETSc Enum
19e5c89e4eSSatish Balay 
20e5c89e4eSSatish Balay */
PetscByteSwapEnum(PetscEnum * buff,PetscCount n)216497c311SBarry Smith static PetscErrorCode PetscByteSwapEnum(PetscEnum *buff, PetscCount n)
22d71ae5a4SJacob Faibussowitsch {
236497c311SBarry Smith   PetscCount i, j;
240b20345dSBarry Smith   PetscEnum  tmp = ENUM_DUMMY;
25e0890e22SSatish Balay   char      *ptr1, *ptr2 = (char *)&tmp;
26e5c89e4eSSatish Balay 
27e5c89e4eSSatish Balay   PetscFunctionBegin;
28e5c89e4eSSatish Balay   for (j = 0; j < n; j++) {
29e5c89e4eSSatish Balay     ptr1 = (char *)(buff + j);
306497c311SBarry Smith     for (i = 0; i < (PetscCount)sizeof(PetscEnum); i++) ptr2[i] = ptr1[sizeof(PetscEnum) - 1 - i];
316497c311SBarry Smith     for (i = 0; i < (PetscCount)sizeof(PetscEnum); i++) ptr1[i] = ptr2[i];
32e5c89e4eSSatish Balay   }
333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
34e5c89e4eSSatish Balay }
356de02169SBarry Smith 
366de02169SBarry Smith /*
37acfcf0e5SJed Brown   PetscByteSwapBool - Swap bytes in a  PETSc Bool
386de02169SBarry Smith 
396de02169SBarry Smith */
PetscByteSwapBool(PetscBool * buff,PetscCount n)406497c311SBarry Smith static PetscErrorCode PetscByteSwapBool(PetscBool *buff, PetscCount n)
41d71ae5a4SJacob Faibussowitsch {
426497c311SBarry Smith   PetscCount i, j;
43ace3abfcSBarry Smith   PetscBool  tmp = PETSC_FALSE;
44e0890e22SSatish Balay   char      *ptr1, *ptr2 = (char *)&tmp;
456de02169SBarry Smith 
466de02169SBarry Smith   PetscFunctionBegin;
476de02169SBarry Smith   for (j = 0; j < n; j++) {
486de02169SBarry Smith     ptr1 = (char *)(buff + j);
496497c311SBarry Smith     for (i = 0; i < (PetscCount)sizeof(PetscBool); i++) ptr2[i] = ptr1[sizeof(PetscBool) - 1 - i];
506497c311SBarry Smith     for (i = 0; i < (PetscCount)sizeof(PetscBool); i++) ptr1[i] = ptr2[i];
516de02169SBarry Smith   }
523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
536de02169SBarry Smith }
546de02169SBarry Smith 
55bd1d2e58SBarry Smith /*
567de69702SBarry Smith   PetscByteSwapInt - Swap bytes in a  PETSc integer (which may be 32 or 64-bits)
57bd1d2e58SBarry Smith 
58bd1d2e58SBarry Smith */
PetscByteSwapInt(PetscInt * buff,PetscCount n)596497c311SBarry Smith static PetscErrorCode PetscByteSwapInt(PetscInt *buff, PetscCount n)
60d71ae5a4SJacob Faibussowitsch {
616497c311SBarry Smith   PetscCount i, j;
626497c311SBarry Smith   PetscInt   tmp = 0;
63e0890e22SSatish Balay   char      *ptr1, *ptr2 = (char *)&tmp;
64bd1d2e58SBarry Smith 
65bd1d2e58SBarry Smith   PetscFunctionBegin;
66bd1d2e58SBarry Smith   for (j = 0; j < n; j++) {
67bd1d2e58SBarry Smith     ptr1 = (char *)(buff + j);
686497c311SBarry Smith     for (i = 0; i < (PetscCount)sizeof(PetscInt); i++) ptr2[i] = ptr1[sizeof(PetscInt) - 1 - i];
696497c311SBarry Smith     for (i = 0; i < (PetscCount)sizeof(PetscInt); i++) ptr1[i] = ptr2[i];
70bd1d2e58SBarry Smith   }
713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
72bd1d2e58SBarry Smith }
739e3e4c22SLisandro Dalcin 
749e3e4c22SLisandro Dalcin /*
757de69702SBarry Smith   PetscByteSwapInt64 - Swap bytes in a  PETSc integer (64-bits)
769e3e4c22SLisandro Dalcin 
779e3e4c22SLisandro Dalcin */
PetscByteSwapInt64(PetscInt64 * buff,PetscCount n)786497c311SBarry Smith static PetscErrorCode PetscByteSwapInt64(PetscInt64 *buff, PetscCount n)
79d71ae5a4SJacob Faibussowitsch {
806497c311SBarry Smith   PetscCount i, j;
819e3e4c22SLisandro Dalcin   PetscInt64 tmp = 0;
829e3e4c22SLisandro Dalcin   char      *ptr1, *ptr2 = (char *)&tmp;
839e3e4c22SLisandro Dalcin 
849e3e4c22SLisandro Dalcin   PetscFunctionBegin;
859e3e4c22SLisandro Dalcin   for (j = 0; j < n; j++) {
869e3e4c22SLisandro Dalcin     ptr1 = (char *)(buff + j);
876497c311SBarry Smith     for (i = 0; i < (PetscCount)sizeof(PetscInt64); i++) ptr2[i] = ptr1[sizeof(PetscInt64) - 1 - i];
886497c311SBarry Smith     for (i = 0; i < (PetscCount)sizeof(PetscInt64); i++) ptr1[i] = ptr2[i];
899e3e4c22SLisandro Dalcin   }
903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
919e3e4c22SLisandro Dalcin }
929e3e4c22SLisandro Dalcin 
93e5c89e4eSSatish Balay /*
943321ca25SJames Wright   PetscByteSwapInt32 - Swap bytes in a  PETSc integer (32-bits)
953321ca25SJames Wright 
963321ca25SJames Wright */
PetscByteSwapInt32(PetscInt32 * buff,PetscCount n)976497c311SBarry Smith static PetscErrorCode PetscByteSwapInt32(PetscInt32 *buff, PetscCount n)
983321ca25SJames Wright {
996497c311SBarry Smith   PetscCount i, j;
1003321ca25SJames Wright   PetscInt32 tmp = 0;
1013321ca25SJames Wright   char      *ptr1, *ptr2 = (char *)&tmp;
1023321ca25SJames Wright 
1033321ca25SJames Wright   PetscFunctionBegin;
1043321ca25SJames Wright   for (j = 0; j < n; j++) {
1053321ca25SJames Wright     ptr1 = (char *)(buff + j);
1066497c311SBarry Smith     for (i = 0; i < (PetscCount)sizeof(PetscInt32); i++) ptr2[i] = ptr1[sizeof(PetscInt32) - 1 - i];
1076497c311SBarry Smith     for (i = 0; i < (PetscCount)sizeof(PetscInt32); i++) ptr1[i] = ptr2[i];
1083321ca25SJames Wright   }
1093321ca25SJames Wright   PetscFunctionReturn(PETSC_SUCCESS);
1103321ca25SJames Wright }
1113321ca25SJames Wright 
1123321ca25SJames Wright /*
113e5c89e4eSSatish Balay   PetscByteSwapShort - Swap bytes in a short
114e5c89e4eSSatish Balay */
PetscByteSwapShort(short * buff,PetscCount n)1156497c311SBarry Smith static PetscErrorCode PetscByteSwapShort(short *buff, PetscCount n)
116d71ae5a4SJacob Faibussowitsch {
1176497c311SBarry Smith   PetscCount i, j;
118e5c89e4eSSatish Balay   short      tmp;
119e5c89e4eSSatish Balay   char      *ptr1, *ptr2 = (char *)&tmp;
120e5c89e4eSSatish Balay 
121e5c89e4eSSatish Balay   PetscFunctionBegin;
122e5c89e4eSSatish Balay   for (j = 0; j < n; j++) {
123e5c89e4eSSatish Balay     ptr1 = (char *)(buff + j);
1246497c311SBarry Smith     for (i = 0; i < (PetscCount)sizeof(short); i++) ptr2[i] = ptr1[sizeof(short) - 1 - i];
1256497c311SBarry Smith     for (i = 0; i < (PetscCount)sizeof(short); i++) ptr1[i] = ptr2[i];
126e5c89e4eSSatish Balay   }
1273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
128e5c89e4eSSatish Balay }
129972064b6SLisandro Dalcin /*
130972064b6SLisandro Dalcin   PetscByteSwapLong - Swap bytes in a long
131972064b6SLisandro Dalcin */
PetscByteSwapLong(long * buff,PetscCount n)1326497c311SBarry Smith static PetscErrorCode PetscByteSwapLong(long *buff, PetscCount n)
133d71ae5a4SJacob Faibussowitsch {
1346497c311SBarry Smith   PetscCount i, j;
135972064b6SLisandro Dalcin   long       tmp;
136972064b6SLisandro Dalcin   char      *ptr1, *ptr2 = (char *)&tmp;
137972064b6SLisandro Dalcin 
138972064b6SLisandro Dalcin   PetscFunctionBegin;
139972064b6SLisandro Dalcin   for (j = 0; j < n; j++) {
140972064b6SLisandro Dalcin     ptr1 = (char *)(buff + j);
1416497c311SBarry Smith     for (i = 0; i < (PetscCount)sizeof(long); i++) ptr2[i] = ptr1[sizeof(long) - 1 - i];
1426497c311SBarry Smith     for (i = 0; i < (PetscCount)sizeof(long); i++) ptr1[i] = ptr2[i];
143972064b6SLisandro Dalcin   }
1443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
145972064b6SLisandro Dalcin }
14621532e8aSBarry Smith 
147e5c89e4eSSatish Balay /*
1484caf0332SSatish Balay   PetscByteSwapReal - Swap bytes in a PetscReal
1494caf0332SSatish Balay */
PetscByteSwapReal(PetscReal * buff,PetscCount n)1506497c311SBarry Smith static PetscErrorCode PetscByteSwapReal(PetscReal *buff, PetscCount n)
151d71ae5a4SJacob Faibussowitsch {
1526497c311SBarry Smith   PetscCount i, j;
153*835f2295SStefano Zampini   PetscReal  tmp, *buff1 = buff;
1544caf0332SSatish Balay   char      *ptr1, *ptr2 = (char *)&tmp;
1554caf0332SSatish Balay 
1564caf0332SSatish Balay   PetscFunctionBegin;
1574caf0332SSatish Balay   for (j = 0; j < n; j++) {
1584caf0332SSatish Balay     ptr1 = (char *)(buff1 + j);
1596497c311SBarry Smith     for (i = 0; i < (PetscCount)sizeof(PetscReal); i++) ptr2[i] = ptr1[sizeof(PetscReal) - 1 - i];
1606497c311SBarry Smith     for (i = 0; i < (PetscCount)sizeof(PetscReal); i++) ptr1[i] = ptr2[i];
1614caf0332SSatish Balay   }
1623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1634caf0332SSatish Balay }
16421532e8aSBarry Smith 
1654caf0332SSatish Balay /*
16641f502e3SPatrick Sanan   PetscByteSwapScalar - Swap bytes in a PetscScalar
16715229ffcSPierre Jolivet   The complex case is dealt with an array of PetscReal, twice as long.
168e5c89e4eSSatish Balay */
PetscByteSwapScalar(PetscScalar * buff,PetscCount n)1696497c311SBarry Smith static PetscErrorCode PetscByteSwapScalar(PetscScalar *buff, PetscCount n)
170d71ae5a4SJacob Faibussowitsch {
1716497c311SBarry Smith   PetscCount i, j;
172*835f2295SStefano Zampini #if defined(PETSC_USE_COMPLEX)
173e5c89e4eSSatish Balay   PetscReal tmp, *buff1 = (PetscReal *)buff;
174*835f2295SStefano Zampini #else
175*835f2295SStefano Zampini   PetscReal tmp, *buff1 = buff;
176*835f2295SStefano Zampini #endif
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);
1856497c311SBarry Smith     for (i = 0; i < (PetscCount)sizeof(PetscReal); i++) ptr2[i] = ptr1[sizeof(PetscReal) - 1 - i];
1866497c311SBarry Smith     for (i = 0; i < (PetscCount)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 */
PetscByteSwapDouble(double * buff,PetscCount n)1946497c311SBarry Smith static PetscErrorCode PetscByteSwapDouble(double *buff, PetscCount n)
195d71ae5a4SJacob Faibussowitsch {
1966497c311SBarry Smith   PetscCount i, j;
197*835f2295SStefano Zampini   double     tmp, *buff1 = 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);
2036497c311SBarry Smith     for (i = 0; i < (PetscCount)sizeof(double); i++) ptr2[i] = ptr1[sizeof(double) - 1 - i];
2046497c311SBarry Smith     for (i = 0; i < (PetscCount)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 */
PetscByteSwapFloat(float * buff,PetscCount n)2126497c311SBarry Smith static PetscErrorCode PetscByteSwapFloat(float *buff, PetscCount n)
213d71ae5a4SJacob Faibussowitsch {
2146497c311SBarry Smith   PetscCount i, j;
215*835f2295SStefano Zampini   float      tmp, *buff1 = 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);
2216497c311SBarry Smith     for (i = 0; i < (PetscCount)sizeof(float); i++) ptr2[i] = ptr1[sizeof(float) - 1 - i];
2226497c311SBarry Smith     for (i = 0; i < (PetscCount)sizeof(float); i++) ptr1[i] = ptr2[i];
223e95bf02fSSatish Balay   }
2243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
225e95bf02fSSatish Balay }
226e95bf02fSSatish Balay 
PetscByteSwap(void * data,PetscDataType pdtype,PetscCount count)2276497c311SBarry Smith PetscErrorCode PetscByteSwap(void *data, PetscDataType pdtype, PetscCount 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));
2376497c311SBarry Smith   else if (pdtype == PETSC_COUNT) PetscCall(PetscByteSwapInt64((PetscInt64 *)data, count));
2383321ca25SJames Wright   else if (pdtype == PETSC_INT32) PetscCall(PetscByteSwapInt32((PetscInt32 *)data, count));
2399566063dSJacob Faibussowitsch   else if (pdtype == PETSC_DOUBLE) PetscCall(PetscByteSwapDouble((double *)data, count));
2409566063dSJacob Faibussowitsch   else if (pdtype == PETSC_FLOAT) PetscCall(PetscByteSwapFloat((float *)data, count));
2419566063dSJacob Faibussowitsch   else if (pdtype == PETSC_SHORT) PetscCall(PetscByteSwapShort((short *)data, count));
2429566063dSJacob Faibussowitsch   else if (pdtype == PETSC_LONG) PetscCall(PetscByteSwapLong((long *)data, count));
243372de11fSJed Brown   else if (pdtype == PETSC_CHAR) PetscFunctionReturn(PETSC_SUCCESS);
2443321ca25SJames Wright   else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Unknown type: %d", pdtype);
2453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
246e39fd77fSBarry Smith }
247e39fd77fSBarry Smith 
2489860990eSLisandro Dalcin /*@C
249e5c89e4eSSatish Balay   PetscBinaryRead - Reads from a binary file.
250e5c89e4eSSatish Balay 
251e5c89e4eSSatish Balay   Not Collective
252e5c89e4eSSatish Balay 
253e5c89e4eSSatish Balay   Input Parameters:
2549860990eSLisandro Dalcin + fd   - the file descriptor
2559860990eSLisandro Dalcin . num  - the maximum number of items to read
256811af0c4SBarry Smith - type - the type of items to read (`PETSC_INT`, `PETSC_REAL`, `PETSC_SCALAR`, etc.)
257e5c89e4eSSatish Balay 
258e5c89e4eSSatish Balay   Output Parameters:
25921532e8aSBarry Smith + data  - the buffer, this is an array of the type that matches the value in `type`
2609860990eSLisandro Dalcin - count - the number of items read, optional
261e5c89e4eSSatish Balay 
262e5c89e4eSSatish Balay   Level: developer
263e5c89e4eSSatish Balay 
264e5c89e4eSSatish Balay   Notes:
26521532e8aSBarry Smith   If `count` is not provided and the number of items read is less than
2669860990eSLisandro Dalcin   the maximum number of items to read, then this routine errors.
2679860990eSLisandro Dalcin 
268811af0c4SBarry Smith   `PetscBinaryRead()` uses byte swapping to work on all machines; the files
26921532e8aSBarry Smith   are written ALWAYS using big-endian ordering. On little-endian machines the numbers
270f253e43cSLisandro Dalcin   are converted to the little-endian format when they are read in from the file.
27121532e8aSBarry Smith   When PETSc is ./configure with `--with-64-bit-indices` the integers are written to the
2727de69702SBarry Smith   file as 64-bit integers, this means they can only be read back in when the option `--with-64-bit-indices`
27354f21887SBarry Smith   is used.
274e5c89e4eSSatish Balay 
275cc4c1da9SBarry Smith   Fortran Note:
276cc4c1da9SBarry Smith   There are different functions for each datatype, for example `PetscBinaryReadInt()`
277cc4c1da9SBarry Smith 
278db781477SPatrick Sanan .seealso: `PetscBinaryWrite()`, `PetscBinaryOpen()`, `PetscBinaryClose()`, `PetscViewerBinaryGetDescriptor()`, `PetscBinarySynchronizedWrite()`,
279db781477SPatrick Sanan           `PetscBinarySynchronizedRead()`, `PetscBinarySynchronizedSeek()`
280e5c89e4eSSatish Balay @*/
PetscBinaryRead(int fd,void * data,PetscCount num,PetscInt * count,PetscDataType type)2816497c311SBarry Smith PetscErrorCode PetscBinaryRead(int fd, void *data, PetscCount num, PetscInt *count, PetscDataType type)
282d71ae5a4SJacob Faibussowitsch {
2839860990eSLisandro Dalcin   size_t typesize, m = (size_t)num, n = 0, maxblock = 65536;
2849860990eSLisandro Dalcin   char  *p = (char *)data;
2857a881295SBarry Smith #if defined(PETSC_USE_REAL___FLOAT128)
286cba51d77SBarry Smith   PetscBool readdouble = PETSC_FALSE;
2879860990eSLisandro Dalcin   double   *pdouble;
2887a881295SBarry Smith #endif
2899860990eSLisandro Dalcin   void *ptmp  = data;
29005acbc63SBarry Smith   char *fname = NULL;
291e5c89e4eSSatish Balay 
292e5c89e4eSSatish Balay   PetscFunctionBegin;
2939860990eSLisandro Dalcin   if (count) *count = 0;
2946497c311SBarry Smith   PetscCheck(num >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to read a negative amount of data %" PetscCount_FMT, num);
2953ba16761SJacob Faibussowitsch   if (!num) PetscFunctionReturn(PETSC_SUCCESS);
296e5c89e4eSSatish Balay 
2972d53ad75SBarry Smith   if (type == PETSC_FUNCTION) {
2982d53ad75SBarry Smith     m     = 64;
2992d53ad75SBarry Smith     type  = PETSC_CHAR;
30005acbc63SBarry Smith     fname = (char *)malloc(m * sizeof(char));
301*835f2295SStefano Zampini     p     = fname;
3022d53ad75SBarry Smith     ptmp  = (void *)fname;
30328b400f6SJacob Faibussowitsch     PetscCheck(fname, PETSC_COMM_SELF, PETSC_ERR_MEM, "Cannot allocate space for function name");
3042d53ad75SBarry Smith   }
3056497c311SBarry Smith   if (type == PETSC_BIT_LOGICAL) m = PetscBTLength(num);
3062d53ad75SBarry Smith 
3079566063dSJacob Faibussowitsch   PetscCall(PetscDataTypeGetSize(type, &typesize));
308e5c89e4eSSatish Balay 
3097a881295SBarry Smith #if defined(PETSC_USE_REAL___FLOAT128)
3109566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(NULL, NULL, "-binary_read_double", &readdouble, NULL));
3117a881295SBarry Smith   /* If using __float128 precision we still read in doubles from file */
3129860990eSLisandro Dalcin   if ((type == PETSC_REAL || type == PETSC_COMPLEX) && readdouble) {
3139860990eSLisandro Dalcin     PetscInt cnt = num * ((type == PETSC_REAL) ? 1 : 2);
3149566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(cnt, &pdouble));
3159860990eSLisandro Dalcin     p = (char *)pdouble;
3169860990eSLisandro Dalcin     typesize /= 2;
3177a881295SBarry Smith   }
3187a881295SBarry Smith #endif
3197a881295SBarry Smith 
3209860990eSLisandro Dalcin   m *= typesize;
3219860990eSLisandro Dalcin 
322e5c89e4eSSatish Balay   while (m) {
3239860990eSLisandro Dalcin     size_t len = (m < maxblock) ? m : maxblock;
3249860990eSLisandro Dalcin     int    ret = (int)read(fd, p, len);
3259860990eSLisandro Dalcin     if (ret < 0 && errno == EINTR) continue;
3269860990eSLisandro Dalcin     if (!ret && len > 0) break; /* Proxy for EOF */
327bf31d2d3SBarry Smith     PetscCheck(ret >= 0, PETSC_COMM_SELF, PETSC_ERR_FILE_READ, "Error reading from file due to \"%s\"", strerror(errno));
328ff9f933bSBarry Smith     m -= (size_t)ret;
3299860990eSLisandro Dalcin     p += ret;
330ff9f933bSBarry Smith     n += (size_t)ret;
331e5c89e4eSSatish Balay   }
33208401ef6SPierre Jolivet   PetscCheck(!m || count, PETSC_COMM_SELF, PETSC_ERR_FILE_READ, "Read past end of file");
3339860990eSLisandro Dalcin 
3346497c311SBarry Smith   num = n / typesize;                             /* Should we require `n % typesize == 0` ? */
3356497c311SBarry Smith   if (count) PetscCall(PetscIntCast(num, count)); /* TODO: This is most likely wrong for PETSC_BIT_LOGICAL */
3367a881295SBarry Smith 
3377a881295SBarry Smith #if defined(PETSC_USE_REAL___FLOAT128)
3389860990eSLisandro Dalcin   if ((type == PETSC_REAL || type == PETSC_COMPLEX) && readdouble) {
3399860990eSLisandro Dalcin     PetscInt   i, cnt = num * ((type == PETSC_REAL) ? 1 : 2);
3409860990eSLisandro Dalcin     PetscReal *preal = (PetscReal *)data;
3419566063dSJacob Faibussowitsch     if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwapDouble(pdouble, cnt));
3429860990eSLisandro Dalcin     for (i = 0; i < cnt; i++) preal[i] = pdouble[i];
3439566063dSJacob Faibussowitsch     PetscCall(PetscFree(pdouble));
3443ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
3457a881295SBarry Smith   }
3467a881295SBarry Smith #endif
3477a881295SBarry Smith 
3489566063dSJacob Faibussowitsch   if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(ptmp, type, num));
349e5c89e4eSSatish Balay 
35005acbc63SBarry Smith   if (type == PETSC_FUNCTION) {
3512d53ad75SBarry Smith #if defined(PETSC_SERIALIZE_FUNCTIONS)
3529566063dSJacob Faibussowitsch     PetscCall(PetscDLSym(NULL, fname, (void **)data));
3532d53ad75SBarry Smith #else
3549860990eSLisandro Dalcin     *(void **)data = NULL;
3552d53ad75SBarry Smith #endif
35605acbc63SBarry Smith     free(fname);
3572d53ad75SBarry Smith   }
3583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
359e5c89e4eSSatish Balay }
3609860990eSLisandro Dalcin 
361a9acdec7SBarry Smith /*@C
362e5c89e4eSSatish Balay   PetscBinaryWrite - Writes to a binary file.
363e5c89e4eSSatish Balay 
364e5c89e4eSSatish Balay   Not Collective
365e5c89e4eSSatish Balay 
366e5c89e4eSSatish Balay   Input Parameters:
367e5c89e4eSSatish Balay + fd   - the file
36821532e8aSBarry Smith . p    - the buffer, an array of the type that matches the value in `type`
369e5c89e4eSSatish Balay . n    - the number of items to write
370811af0c4SBarry Smith - type - the type of items to read (`PETSC_INT`, `PETSC_REAL` or `PETSC_SCALAR`)
371e5c89e4eSSatish Balay 
372e5c89e4eSSatish Balay   Level: advanced
373e5c89e4eSSatish Balay 
374e5c89e4eSSatish Balay   Notes:
375811af0c4SBarry Smith   `PetscBinaryWrite()` uses byte swapping to work on all machines; the files
376f253e43cSLisandro Dalcin   are written using big-endian ordering to the file. On little-endian machines the numbers
377e5c89e4eSSatish Balay   are converted to the big-endian format when they are written to disk.
37821532e8aSBarry Smith   When PETSc is configured using `./configure with --with-64-bit-indices` the integers are written to the
3797de69702SBarry Smith   file as 64-bit integers, this means they can only be read back in when the option `--with-64-bit-indices`
38054f21887SBarry Smith   is used.
381e5c89e4eSSatish Balay 
38221532e8aSBarry Smith   If running with `__float128` precision the output of `PETSC_REAL` is in `__float128` unless one uses the `-binary_write_double` option
3830da86b62SBarry Smith 
384bfbbc7b7SBarry Smith   The buffer `p` should be read-write buffer, and not static data.
385e5c89e4eSSatish Balay   This way, byte-swapping is done in-place, and then the buffer is
386e5c89e4eSSatish Balay   written to the file.
387e5c89e4eSSatish Balay 
388e5c89e4eSSatish Balay   This routine restores the original contents of the buffer, after
389e5c89e4eSSatish Balay   it is written to the file. This is done by byte-swapping in-place
390f253e43cSLisandro Dalcin   the second time.
391e5c89e4eSSatish Balay 
392300a7f5bSBarry Smith   Because byte-swapping may be done on the values in data it cannot be declared const
393300a7f5bSBarry Smith 
394cc4c1da9SBarry Smith   Fortran Note:
395cc4c1da9SBarry Smith   There are different functions for each datatype, for example `PetscBinaryWriteInt()`
396cc4c1da9SBarry Smith 
397db781477SPatrick Sanan .seealso: `PetscBinaryRead()`, `PetscBinaryOpen()`, `PetscBinaryClose()`, `PetscViewerBinaryGetDescriptor()`, `PetscBinarySynchronizedWrite()`,
398db781477SPatrick Sanan           `PetscBinarySynchronizedRead()`, `PetscBinarySynchronizedSeek()`
399e5c89e4eSSatish Balay @*/
PetscBinaryWrite(int fd,const void * p,PetscCount n,PetscDataType type)4006497c311SBarry Smith PetscErrorCode PetscBinaryWrite(int fd, const void *p, PetscCount n, PetscDataType type)
401d71ae5a4SJacob Faibussowitsch {
402f253e43cSLisandro Dalcin   const char  *pp = (char *)p;
4036497c311SBarry Smith   size_t       err, m = (size_t)n, wsize;
4046497c311SBarry Smith   const size_t maxblock = 65536;
405f253e43cSLisandro Dalcin   const void  *ptmp     = p;
40605acbc63SBarry Smith   char        *fname    = NULL;
4070da86b62SBarry Smith #if defined(PETSC_USE_REAL___FLOAT128)
408df40af56SBarry Smith   PetscBool  writedouble = PETSC_FALSE;
4090da86b62SBarry Smith   double    *ppp;
4100da86b62SBarry Smith   PetscReal *pv;
4110da86b62SBarry Smith #endif
41241f502e3SPatrick Sanan   PetscDataType wtype = type;
413e5c89e4eSSatish Balay 
414e5c89e4eSSatish Balay   PetscFunctionBegin;
4156497c311SBarry Smith   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to write a negative amount of data %" PetscCount_FMT, n);
4163ba16761SJacob Faibussowitsch   if (!n) PetscFunctionReturn(PETSC_SUCCESS);
417e5c89e4eSSatish Balay 
4182d53ad75SBarry Smith   if (type == PETSC_FUNCTION) {
4192d53ad75SBarry Smith #if defined(PETSC_SERIALIZE_FUNCTIONS)
4202d53ad75SBarry Smith     const char *fnametmp;
4212d53ad75SBarry Smith #endif
4222d53ad75SBarry Smith     m     = 64;
423e25ab156SSatish Balay     fname = (char *)malloc(m * sizeof(char));
42428b400f6SJacob Faibussowitsch     PetscCheck(fname, PETSC_COMM_SELF, PETSC_ERR_MEM, "Cannot allocate space for function name");
42505acbc63SBarry Smith #if defined(PETSC_SERIALIZE_FUNCTIONS)
42608401ef6SPierre Jolivet     PetscCheck(n <= 1, PETSC_COMM_SELF, PETSC_ERR_SUP, "Can only binary view a single function at a time");
4279566063dSJacob Faibussowitsch     PetscCall(PetscFPTFind(*(void **)p, &fnametmp));
4289566063dSJacob Faibussowitsch     PetscCall(PetscStrncpy(fname, fnametmp, m));
42905acbc63SBarry Smith #else
4309566063dSJacob Faibussowitsch     PetscCall(PetscStrncpy(fname, "", m));
43105acbc63SBarry Smith #endif
43201963f56SBarry Smith     wtype = PETSC_CHAR;
433*835f2295SStefano Zampini     pp    = fname;
4342d53ad75SBarry Smith     ptmp  = (void *)fname;
4352d53ad75SBarry Smith   }
4362d53ad75SBarry Smith 
4370da86b62SBarry Smith #if defined(PETSC_USE_REAL___FLOAT128)
4389566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(NULL, NULL, "-binary_write_double", &writedouble, NULL));
4390da86b62SBarry Smith   /* If using __float128 precision we still write in doubles to file */
440501ae109SJose E. Roman   if ((type == PETSC_SCALAR || type == PETSC_REAL || type == PETSC_COMPLEX) && writedouble) {
44141f502e3SPatrick Sanan     wtype = PETSC_DOUBLE;
4429566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(n, &ppp));
4430da86b62SBarry Smith     pv = (PetscReal *)pp;
4446497c311SBarry Smith     for (PetscCount i = 0; i < n; i++) ppp[i] = (double)pv[i];
4450da86b62SBarry Smith     pp   = (char *)ppp;
4460da86b62SBarry Smith     ptmp = (char *)ppp;
4470da86b62SBarry Smith   }
4480da86b62SBarry Smith #endif
4490da86b62SBarry Smith 
45041f502e3SPatrick Sanan   if (wtype == PETSC_INT) m *= sizeof(PetscInt);
45141f502e3SPatrick Sanan   else if (wtype == PETSC_SCALAR) m *= sizeof(PetscScalar);
452501ae109SJose E. Roman #if defined(PETSC_HAVE_COMPLEX)
453501ae109SJose E. Roman   else if (wtype == PETSC_COMPLEX) m *= sizeof(PetscComplex);
454501ae109SJose E. Roman #endif
4554caf0332SSatish Balay   else if (wtype == PETSC_REAL) m *= sizeof(PetscReal);
45641f502e3SPatrick Sanan   else if (wtype == PETSC_DOUBLE) m *= sizeof(double);
45741f502e3SPatrick Sanan   else if (wtype == PETSC_FLOAT) m *= sizeof(float);
45841f502e3SPatrick Sanan   else if (wtype == PETSC_SHORT) m *= sizeof(short);
459972064b6SLisandro Dalcin   else if (wtype == PETSC_LONG) m *= sizeof(long);
46041f502e3SPatrick Sanan   else if (wtype == PETSC_CHAR) m *= sizeof(char);
46141f502e3SPatrick Sanan   else if (wtype == PETSC_ENUM) m *= sizeof(PetscEnum);
46241f502e3SPatrick Sanan   else if (wtype == PETSC_BOOL) m *= sizeof(PetscBool);
4639e3e4c22SLisandro Dalcin   else if (wtype == PETSC_INT64) m *= sizeof(PetscInt64);
4643321ca25SJames Wright   else if (wtype == PETSC_INT32) m *= sizeof(PetscInt32);
46541f502e3SPatrick Sanan   else if (wtype == PETSC_BIT_LOGICAL) m = PetscBTLength(m) * sizeof(char);
4663321ca25SJames Wright   else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Unknown type: %d", wtype);
467e5c89e4eSSatish Balay 
4689566063dSJacob Faibussowitsch   if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap((void *)ptmp, wtype, n));
469e5c89e4eSSatish Balay 
470e5c89e4eSSatish Balay   while (m) {
471e5c89e4eSSatish Balay     wsize = (m < maxblock) ? m : maxblock;
4726497c311SBarry Smith     err   = (size_t)write(fd, pp, wsize);
4735607bdc5SPierre Jolivet     if (errno == EINTR) continue;
474bf31d2d3SBarry 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));
475e5c89e4eSSatish Balay     m -= wsize;
476e5c89e4eSSatish Balay     pp += wsize;
477e5c89e4eSSatish Balay   }
478e5c89e4eSSatish Balay 
4799566063dSJacob Faibussowitsch   if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap((void *)ptmp, wtype, n));
480f253e43cSLisandro Dalcin 
481ad540459SPierre Jolivet   if (type == PETSC_FUNCTION) free(fname);
4820da86b62SBarry Smith #if defined(PETSC_USE_REAL___FLOAT128)
48348a46eb9SPierre Jolivet   if ((type == PETSC_SCALAR || type == PETSC_REAL || type == PETSC_COMPLEX) && writedouble) PetscCall(PetscFree(ppp));
4840da86b62SBarry Smith #endif
4853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
486e5c89e4eSSatish Balay }
487e5c89e4eSSatish Balay 
488cc4c1da9SBarry Smith /*@
489e5c89e4eSSatish Balay   PetscBinaryOpen - Opens a PETSc binary file.
490e5c89e4eSSatish Balay 
491e5c89e4eSSatish Balay   Not Collective
492e5c89e4eSSatish Balay 
493e5c89e4eSSatish Balay   Input Parameters:
494e5c89e4eSSatish Balay + name - filename
495fe8e7dddSPierre Jolivet - mode - open mode of binary file, one of `FILE_MODE_READ`, `FILE_MODE_WRITE`, `FILE_MODE_APPEND`
496e5c89e4eSSatish Balay 
497e5c89e4eSSatish Balay   Output Parameter:
498e5c89e4eSSatish Balay . fd - the file
499e5c89e4eSSatish Balay 
500e5c89e4eSSatish Balay   Level: advanced
501e5c89e4eSSatish Balay 
502db781477SPatrick Sanan .seealso: `PetscBinaryRead()`, `PetscBinaryWrite()`, `PetscFileMode`, `PetscViewerFileSetMode()`, `PetscViewerBinaryGetDescriptor()`,
503db781477SPatrick Sanan           `PetscBinarySynchronizedWrite()`, `PetscBinarySynchronizedRead()`, `PetscBinarySynchronizedSeek()`
504e5c89e4eSSatish Balay @*/
PetscBinaryOpen(const char name[],PetscFileMode mode,int * fd)505d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscBinaryOpen(const char name[], PetscFileMode mode, int *fd)
506d71ae5a4SJacob Faibussowitsch {
507e5c89e4eSSatish Balay   PetscFunctionBegin;
508cc843e7aSLisandro Dalcin   switch (mode) {
509d71ae5a4SJacob Faibussowitsch   case FILE_MODE_READ:
510d71ae5a4SJacob Faibussowitsch     *fd = open(name, O_BINARY | O_RDONLY, 0);
511d71ae5a4SJacob Faibussowitsch     break;
512d71ae5a4SJacob Faibussowitsch   case FILE_MODE_WRITE:
513d71ae5a4SJacob Faibussowitsch     *fd = open(name, O_BINARY | O_WRONLY | O_CREAT | O_TRUNC, 0666);
514d71ae5a4SJacob Faibussowitsch     break;
515d71ae5a4SJacob Faibussowitsch   case FILE_MODE_APPEND:
516d71ae5a4SJacob Faibussowitsch     *fd = open(name, O_BINARY | O_WRONLY | O_APPEND, 0);
517d71ae5a4SJacob Faibussowitsch     break;
518d71ae5a4SJacob Faibussowitsch   default:
519d71ae5a4SJacob Faibussowitsch     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Unsupported file mode %s", PetscFileModes[mode]);
520e5c89e4eSSatish Balay   }
521bf31d2d3SBarry 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));
5223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
523e5c89e4eSSatish Balay }
524e5c89e4eSSatish Balay 
525e30d2299SSatish Balay /*@
526e5c89e4eSSatish Balay   PetscBinaryClose - Closes a PETSc binary file.
527e5c89e4eSSatish Balay 
528e5c89e4eSSatish Balay   Not Collective
529e5c89e4eSSatish Balay 
530e5c89e4eSSatish Balay   Output Parameter:
531e5c89e4eSSatish Balay . fd - the file
532e5c89e4eSSatish Balay 
533e5c89e4eSSatish Balay   Level: advanced
534e5c89e4eSSatish Balay 
535db781477SPatrick Sanan .seealso: `PetscBinaryRead()`, `PetscBinaryWrite()`, `PetscBinaryOpen()`, `PetscBinarySynchronizedWrite()`, `PetscBinarySynchronizedRead()`,
536db781477SPatrick Sanan           `PetscBinarySynchronizedSeek()`
537e5c89e4eSSatish Balay @*/
PetscBinaryClose(int fd)538d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscBinaryClose(int fd)
539d71ae5a4SJacob Faibussowitsch {
540e5c89e4eSSatish Balay   PetscFunctionBegin;
541cc73adaaSBarry Smith   PetscCheck(!close(fd), PETSC_COMM_SELF, PETSC_ERR_SYS, "close() failed on file descriptor");
5423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
543e5c89e4eSSatish Balay }
544e5c89e4eSSatish Balay 
545e8976759SBarry Smith /*@C
546e5c89e4eSSatish Balay   PetscBinarySeek - Moves the file pointer on a PETSc binary file.
547e5c89e4eSSatish Balay 
548cc4c1da9SBarry Smith   Not Collective, No Fortran Support
549e5c89e4eSSatish Balay 
550e5c89e4eSSatish Balay   Input Parameters:
551e5c89e4eSSatish Balay + fd     - the file
552811af0c4SBarry Smith . off    - number of bytes to move. Use `PETSC_BINARY_INT_SIZE`, `PETSC_BINARY_SCALAR_SIZE`,
55321532e8aSBarry Smith            etc. in your calculation rather than `sizeof()` to compute byte lengths.
55416a05f60SBarry Smith - whence - see `PetscBinarySeekType` for possible values
555e5c89e4eSSatish Balay 
556e5c89e4eSSatish Balay   Output Parameter:
557e5c89e4eSSatish Balay . offset - new offset in file
558e5c89e4eSSatish Balay 
559e5c89e4eSSatish Balay   Level: developer
560e5c89e4eSSatish Balay 
56116a05f60SBarry Smith .seealso: `PetscBinaryRead()`, `PetscBinarySeekType`, `PetscBinaryWrite()`, `PetscBinaryOpen()`, `PetscBinarySynchronizedWrite()`, `PetscBinarySynchronizedRead()`,
562db781477SPatrick Sanan           `PetscBinarySynchronizedSeek()`
563e5c89e4eSSatish Balay @*/
PetscBinarySeek(int fd,off_t off,PetscBinarySeekType whence,off_t * offset)564d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscBinarySeek(int fd, off_t off, PetscBinarySeekType whence, off_t *offset)
565d71ae5a4SJacob Faibussowitsch {
566e5c89e4eSSatish Balay   int iwhence = 0;
567e5c89e4eSSatish Balay 
568e5c89e4eSSatish Balay   PetscFunctionBegin;
569a297a907SKarl Rupp   if (whence == PETSC_BINARY_SEEK_SET) iwhence = SEEK_SET;
570a297a907SKarl Rupp   else if (whence == PETSC_BINARY_SEEK_CUR) iwhence = SEEK_CUR;
571a297a907SKarl Rupp   else if (whence == PETSC_BINARY_SEEK_END) iwhence = SEEK_END;
572a297a907SKarl Rupp   else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Unknown seek location");
573e5c89e4eSSatish Balay #if defined(PETSC_HAVE_LSEEK)
574e5c89e4eSSatish Balay   *offset = lseek(fd, off, iwhence);
575e5c89e4eSSatish Balay #elif defined(PETSC_HAVE__LSEEK)
576e5c89e4eSSatish Balay   *offset = _lseek(fd, (long)off, iwhence);
577e5c89e4eSSatish Balay #else
578e32f2f54SBarry Smith   SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP_SYS, "System does not have a way of seeking on a file");
579e5c89e4eSSatish Balay #endif
5803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
581e5c89e4eSSatish Balay }
582e5c89e4eSSatish Balay 
583e5c89e4eSSatish Balay /*@C
58421532e8aSBarry Smith   PetscBinarySynchronizedRead - Reads from a binary file, all MPI processes get the same values
585e5c89e4eSSatish Balay 
586cc4c1da9SBarry Smith   Collective, No Fortran Support
587e5c89e4eSSatish Balay 
588e5c89e4eSSatish Balay   Input Parameters:
589e5c89e4eSSatish Balay + comm - the MPI communicator
5909860990eSLisandro Dalcin . fd   - the file descriptor
5919860990eSLisandro Dalcin . num  - the maximum number of items to read
592811af0c4SBarry Smith - type - the type of items to read (`PETSC_INT`, `PETSC_REAL`, `PETSC_SCALAR`, etc.)
593e5c89e4eSSatish Balay 
594e5c89e4eSSatish Balay   Output Parameters:
59521532e8aSBarry Smith + data  - the buffer, an array of the type that matches the value in `type`
5969860990eSLisandro Dalcin - count - the number of items read, optional
597e5c89e4eSSatish Balay 
598e5c89e4eSSatish Balay   Level: developer
599e5c89e4eSSatish Balay 
600e5c89e4eSSatish Balay   Notes:
601811af0c4SBarry Smith   Does a `PetscBinaryRead()` followed by an `MPI_Bcast()`
602e5c89e4eSSatish Balay 
60321532e8aSBarry Smith   If `count` is not provided and the number of items read is less than
6049860990eSLisandro Dalcin   the maximum number of items to read, then this routine errors.
6059860990eSLisandro Dalcin 
606811af0c4SBarry Smith   `PetscBinarySynchronizedRead()` uses byte swapping to work on all machines.
60721532e8aSBarry Smith   The files  are written using big-endian ordering to the file. On little-endian machines the numbers
60821532e8aSBarry Smith   are converted to the big-endian format when they are written to disk.
60921532e8aSBarry Smith   When PETSc is configured using `./configure with --with-64-bit-indices` the integers are written to the
6107de69702SBarry Smith   file as 64-bit integers, this means they can only be read back in when the option `--with-64-bit-indices`
61121532e8aSBarry Smith   is used.
612e5c89e4eSSatish Balay 
613db781477SPatrick Sanan .seealso: `PetscBinaryWrite()`, `PetscBinaryOpen()`, `PetscBinaryClose()`, `PetscBinaryRead()`, `PetscBinarySynchronizedWrite()`,
614db781477SPatrick Sanan           `PetscBinarySynchronizedSeek()`
615e5c89e4eSSatish Balay @*/
PetscBinarySynchronizedRead(MPI_Comm comm,int fd,void * data,PetscInt num,PetscInt * count,PetscDataType type)616d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscBinarySynchronizedRead(MPI_Comm comm, int fd, void *data, PetscInt num, PetscInt *count, PetscDataType type)
617d71ae5a4SJacob Faibussowitsch {
6188b8bf82cSBarry Smith   PetscMPIInt  rank, size;
619e5c89e4eSSatish Balay   MPI_Datatype mtype;
6209860990eSLisandro Dalcin   PetscInt     ibuf[2] = {0, 0};
62105acbc63SBarry Smith   char        *fname   = NULL;
6229860990eSLisandro Dalcin   void        *fptr    = NULL;
623e5c89e4eSSatish Balay 
624e5c89e4eSSatish Balay   PetscFunctionBegin;
6252d53ad75SBarry Smith   if (type == PETSC_FUNCTION) {
6269860990eSLisandro Dalcin     num   = 64;
6272d53ad75SBarry Smith     type  = PETSC_CHAR;
6289860990eSLisandro Dalcin     fname = (char *)malloc(num * sizeof(char));
6299860990eSLisandro Dalcin     fptr  = data;
6309860990eSLisandro Dalcin     data  = (void *)fname;
63128b400f6SJacob Faibussowitsch     PetscCheck(fname, PETSC_COMM_SELF, PETSC_ERR_MEM, "Cannot allocate space for function name");
6322d53ad75SBarry Smith   }
6332d53ad75SBarry Smith 
6349566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
6359566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
63680bff17dSBarry Smith   if (rank == 0) ibuf[0] = (PetscInt)PetscBinaryRead(fd, data, num, count ? &ibuf[1] : NULL, type);
6379566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Bcast(ibuf, 2, MPIU_INT, 0, comm));
6389566063dSJacob Faibussowitsch   PetscCall((PetscErrorCode)ibuf[0]);
6398b8bf82cSBarry Smith 
6408b8bf82cSBarry 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 */
6418b8bf82cSBarry Smith   if (size > 1) {
6426497c311SBarry Smith     PetscMPIInt cnt;
6436497c311SBarry Smith 
6446497c311SBarry Smith     PetscCall(PetscMPIIntCast(count ? ibuf[1] : num, &cnt));
6459566063dSJacob Faibussowitsch     PetscCall(PetscDataTypeToMPIDataType(type, &mtype));
6466497c311SBarry Smith     PetscCallMPI(MPI_Bcast(data, cnt, mtype, 0, comm));
6478b8bf82cSBarry Smith   }
6489860990eSLisandro Dalcin   if (count) *count = ibuf[1];
6492d53ad75SBarry Smith 
650e366c363SBarry Smith   if (type == PETSC_FUNCTION) {
6512d53ad75SBarry Smith #if defined(PETSC_SERIALIZE_FUNCTIONS)
6529566063dSJacob Faibussowitsch     PetscCall(PetscDLLibrarySym(PETSC_COMM_SELF, &PetscDLLibrariesLoaded, NULL, fname, (void **)fptr));
6532d53ad75SBarry Smith #else
6549860990eSLisandro Dalcin     *(void **)fptr = NULL;
6552d53ad75SBarry Smith #endif
656e366c363SBarry Smith     free(fname);
6572d53ad75SBarry Smith   }
6583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
659e5c89e4eSSatish Balay }
660e5c89e4eSSatish Balay 
661e5c89e4eSSatish Balay /*@C
6621d280d73SBarry Smith   PetscBinarySynchronizedWrite - writes to a binary file.
663e5c89e4eSSatish Balay 
664cc4c1da9SBarry Smith   Collective, No Fortran Support
665e5c89e4eSSatish Balay 
666e5c89e4eSSatish Balay   Input Parameters:
667e5c89e4eSSatish Balay + comm - the MPI communicator
668e5c89e4eSSatish Balay . fd   - the file
669e5c89e4eSSatish Balay . n    - the number of items to write
67021532e8aSBarry Smith . p    - the buffer, an array of the type that matches the value in `type`
671811af0c4SBarry Smith - type - the type of items to write (`PETSC_INT`, `PETSC_REAL` or `PETSC_SCALAR`)
672e5c89e4eSSatish Balay 
673e5c89e4eSSatish Balay   Level: developer
674e5c89e4eSSatish Balay 
675e5c89e4eSSatish Balay   Notes:
67621532e8aSBarry Smith   MPI rank 0 does a `PetscBinaryWrite()` the values on other MPI processes are not used
677e5c89e4eSSatish Balay 
67821532e8aSBarry Smith   The files  are written using big-endian ordering to the file. On little-endian machines the numbers
67921532e8aSBarry Smith   are converted to the big-endian format when they are written to disk.
68021532e8aSBarry Smith   When PETSc is configured using `./configure with --with-64-bit-indices` the integers are written to the
6817de69702SBarry Smith   file as 64-bit integers, this means they can only be read back in when the option `--with-64-bit-indices`
68221532e8aSBarry Smith   is used.
683e5c89e4eSSatish Balay 
684811af0c4SBarry Smith   Because byte-swapping may be done on the values in data it cannot be declared const
685300a7f5bSBarry Smith 
686bfbbc7b7SBarry Smith   This is NOT like `PetscSynchronizedFPrintf()`! This routine ignores calls on all but MPI rank 0,
68721532e8aSBarry Smith   while `PetscSynchronizedFPrintf()` has all MPI processes print their strings in order.
6881d280d73SBarry Smith 
689db781477SPatrick Sanan .seealso: `PetscBinaryWrite()`, `PetscBinaryOpen()`, `PetscBinaryClose()`, `PetscBinaryRead()`, `PetscBinarySynchronizedRead()`,
690db781477SPatrick Sanan           `PetscBinarySynchronizedSeek()`
691e5c89e4eSSatish Balay @*/
PetscBinarySynchronizedWrite(MPI_Comm comm,int fd,const void * p,PetscInt n,PetscDataType type)692d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscBinarySynchronizedWrite(MPI_Comm comm, int fd, const void *p, PetscInt n, PetscDataType type)
693d71ae5a4SJacob Faibussowitsch {
694e5c89e4eSSatish Balay   PetscMPIInt rank;
695e5c89e4eSSatish Balay 
696e5c89e4eSSatish Balay   PetscFunctionBegin;
6979566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
69848a46eb9SPierre Jolivet   if (rank == 0) PetscCall(PetscBinaryWrite(fd, p, n, type));
6993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
700e5c89e4eSSatish Balay }
701e5c89e4eSSatish Balay 
702e5c89e4eSSatish Balay /*@C
7031d280d73SBarry Smith   PetscBinarySynchronizedSeek - Moves the file pointer on a PETSc binary file.
704e5c89e4eSSatish Balay 
705cc4c1da9SBarry Smith   No Fortran Support
706cc4c1da9SBarry Smith 
707e5c89e4eSSatish Balay   Input Parameters:
70810450e9eSJacob Faibussowitsch + comm   - the communicator to read with
70910450e9eSJacob Faibussowitsch . fd     - the file
71016a05f60SBarry Smith . whence - see `PetscBinarySeekType` for possible values
711811af0c4SBarry Smith - off    - number of bytes to move. Use `PETSC_BINARY_INT_SIZE`, `PETSC_BINARY_SCALAR_SIZE`,
712811af0c4SBarry Smith             etc. in your calculation rather than `sizeof()` to compute byte lengths.
713e5c89e4eSSatish Balay 
714e5c89e4eSSatish Balay   Output Parameter:
715e5c89e4eSSatish Balay . offset - new offset in file
716e5c89e4eSSatish Balay 
717e5c89e4eSSatish Balay   Level: developer
718e5c89e4eSSatish Balay 
71916a05f60SBarry Smith .seealso: `PetscBinaryRead()`, `PetscBinarySeekType`, `PetscBinaryWrite()`, `PetscBinaryOpen()`, `PetscBinarySynchronizedWrite()`, `PetscBinarySynchronizedRead()`,
72042747ad1SJacob Faibussowitsch 
721e5c89e4eSSatish Balay @*/
PetscBinarySynchronizedSeek(MPI_Comm comm,int fd,off_t off,PetscBinarySeekType whence,off_t * offset)722d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscBinarySynchronizedSeek(MPI_Comm comm, int fd, off_t off, PetscBinarySeekType whence, off_t *offset)
723d71ae5a4SJacob Faibussowitsch {
724e5c89e4eSSatish Balay   PetscMPIInt rank;
725e5c89e4eSSatish Balay 
726e5c89e4eSSatish Balay   PetscFunctionBegin;
7279566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
72848a46eb9SPierre Jolivet   if (rank == 0) PetscCall(PetscBinarySeek(fd, off, whence, offset));
7293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
730e5c89e4eSSatish Balay }
731e5c89e4eSSatish Balay 
7320fc9d207SBarry Smith #if defined(PETSC_HAVE_MPIIO)
733e39fd77fSBarry Smith 
734951e3c8eSBarry Smith   #if defined(PETSC_USE_PETSC_MPI_EXTERNAL32)
735e39fd77fSBarry Smith /*
736e39fd77fSBarry Smith       MPICH does not provide the external32 representation for MPI_File_set_view() so we need to provide the functions.
737e39fd77fSBarry Smith     These are set into MPI in PetscInitialize() via MPI_Register_datarep()
738e39fd77fSBarry Smith 
739e39fd77fSBarry Smith     Note I use PetscMPIInt for the MPI error codes since that is what MPI uses (instead of the standard PetscErrorCode)
740e39fd77fSBarry Smith 
741951e3c8eSBarry Smith     The next three routines are not used because MPICH does not support their use
742e39fd77fSBarry Smith 
743e39fd77fSBarry Smith */
PetscDataRep_extent_fn(MPI_Datatype datatype,MPI_Aint * file_extent,void * extra_state)744d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscMPIInt PetscDataRep_extent_fn(MPI_Datatype datatype, MPI_Aint *file_extent, void *extra_state)
745d71ae5a4SJacob Faibussowitsch {
746e39fd77fSBarry Smith   MPI_Aint    ub;
747e39fd77fSBarry Smith   PetscMPIInt ierr;
748e39fd77fSBarry Smith 
749e39fd77fSBarry Smith   ierr = MPI_Type_get_extent(datatype, &ub, file_extent);
750e39fd77fSBarry Smith   return ierr;
751e39fd77fSBarry Smith }
752e39fd77fSBarry Smith 
PetscDataRep_read_conv_fn(void * userbuf,MPI_Datatype datatype,PetscMPIInt count,void * filebuf,MPI_Offset position,void * extra_state)753d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscMPIInt PetscDataRep_read_conv_fn(void *userbuf, MPI_Datatype datatype, PetscMPIInt count, void *filebuf, MPI_Offset position, void *extra_state)
754d71ae5a4SJacob Faibussowitsch {
755e39fd77fSBarry Smith   PetscDataType pdtype;
756e39fd77fSBarry Smith   PetscMPIInt   ierr;
757e39fd77fSBarry Smith   size_t        dsize;
758e39fd77fSBarry Smith 
7599566063dSJacob Faibussowitsch   PetscCall(PetscMPIDataTypeToPetscDataType(datatype, &pdtype));
7609566063dSJacob Faibussowitsch   PetscCall(PetscDataTypeGetSize(pdtype, &dsize));
761e39fd77fSBarry Smith 
762e39fd77fSBarry Smith   /* offset is given in units of MPI_Datatype */
763e39fd77fSBarry Smith   userbuf = ((char *)userbuf) + dsize * position;
764e39fd77fSBarry Smith 
7659566063dSJacob Faibussowitsch   PetscCall(PetscMemcpy(userbuf, filebuf, count * dsize));
7669566063dSJacob Faibussowitsch   if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(userbuf, pdtype, count));
767e39fd77fSBarry Smith   return ierr;
768e39fd77fSBarry Smith }
769e39fd77fSBarry Smith 
PetscDataRep_write_conv_fn(void * userbuf,MPI_Datatype datatype,PetscMPIInt count,void * filebuf,MPI_Offset position,void * extra_state)770d71ae5a4SJacob Faibussowitsch PetscMPIInt PetscDataRep_write_conv_fn(void *userbuf, MPI_Datatype datatype, PetscMPIInt count, void *filebuf, MPI_Offset position, void *extra_state)
771d71ae5a4SJacob Faibussowitsch {
772e39fd77fSBarry Smith   PetscDataType pdtype;
773e39fd77fSBarry Smith   PetscMPIInt   ierr;
774e39fd77fSBarry Smith   size_t        dsize;
775e39fd77fSBarry Smith 
7769566063dSJacob Faibussowitsch   PetscCall(PetscMPIDataTypeToPetscDataType(datatype, &pdtype));
7779566063dSJacob Faibussowitsch   PetscCall(PetscDataTypeGetSize(pdtype, &dsize));
778e39fd77fSBarry Smith 
779e39fd77fSBarry Smith   /* offset is given in units of MPI_Datatype */
780e39fd77fSBarry Smith   userbuf = ((char *)userbuf) + dsize * position;
781e39fd77fSBarry Smith 
7829566063dSJacob Faibussowitsch   PetscCall(PetscMemcpy(filebuf, userbuf, count * dsize));
7839566063dSJacob Faibussowitsch   if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(filebuf, pdtype, count));
784e39fd77fSBarry Smith   return ierr;
785e39fd77fSBarry Smith }
786951e3c8eSBarry Smith   #endif
787e39fd77fSBarry Smith 
MPIU_File_write_all(MPI_File fd,void * data,PetscMPIInt cnt,MPI_Datatype dtype,MPI_Status * status)788d71ae5a4SJacob Faibussowitsch PetscErrorCode MPIU_File_write_all(MPI_File fd, void *data, PetscMPIInt cnt, MPI_Datatype dtype, MPI_Status *status)
789d71ae5a4SJacob Faibussowitsch {
790e39fd77fSBarry Smith   PetscDataType pdtype;
79130815ce0SLisandro Dalcin 
792e39fd77fSBarry Smith   PetscFunctionBegin;
7939566063dSJacob Faibussowitsch   PetscCall(PetscMPIDataTypeToPetscDataType(dtype, &pdtype));
7949566063dSJacob Faibussowitsch   if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(data, pdtype, cnt));
7959566063dSJacob Faibussowitsch   PetscCallMPI(MPI_File_write_all(fd, data, cnt, dtype, status));
7969566063dSJacob Faibussowitsch   if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(data, pdtype, cnt));
7973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
798e39fd77fSBarry Smith }
799e39fd77fSBarry Smith 
MPIU_File_read_all(MPI_File fd,void * data,PetscMPIInt cnt,MPI_Datatype dtype,MPI_Status * status)800d71ae5a4SJacob Faibussowitsch PetscErrorCode MPIU_File_read_all(MPI_File fd, void *data, PetscMPIInt cnt, MPI_Datatype dtype, MPI_Status *status)
801d71ae5a4SJacob Faibussowitsch {
802e39fd77fSBarry Smith   PetscDataType pdtype;
803e39fd77fSBarry Smith 
804e39fd77fSBarry Smith   PetscFunctionBegin;
8059566063dSJacob Faibussowitsch   PetscCall(PetscMPIDataTypeToPetscDataType(dtype, &pdtype));
8069566063dSJacob Faibussowitsch   PetscCallMPI(MPI_File_read_all(fd, data, cnt, dtype, status));
8079566063dSJacob Faibussowitsch   if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(data, pdtype, cnt));
8083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
809e39fd77fSBarry Smith }
81030815ce0SLisandro Dalcin 
MPIU_File_write_at(MPI_File fd,MPI_Offset off,void * data,PetscMPIInt cnt,MPI_Datatype dtype,MPI_Status * status)811d71ae5a4SJacob Faibussowitsch PetscErrorCode MPIU_File_write_at(MPI_File fd, MPI_Offset off, void *data, PetscMPIInt cnt, MPI_Datatype dtype, MPI_Status *status)
812d71ae5a4SJacob Faibussowitsch {
813c4e82887SLisandro Dalcin   PetscDataType pdtype;
814c4e82887SLisandro Dalcin 
815c4e82887SLisandro Dalcin   PetscFunctionBegin;
8169566063dSJacob Faibussowitsch   PetscCall(PetscMPIDataTypeToPetscDataType(dtype, &pdtype));
8179566063dSJacob Faibussowitsch   if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(data, pdtype, cnt));
8189566063dSJacob Faibussowitsch   PetscCallMPI(MPI_File_write_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 
MPIU_File_read_at(MPI_File fd,MPI_Offset off,void * data,PetscMPIInt cnt,MPI_Datatype dtype,MPI_Status * status)823d71ae5a4SJacob Faibussowitsch PetscErrorCode MPIU_File_read_at(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   PetscCallMPI(MPI_File_read_at(fd, off, data, cnt, dtype, status));
8309566063dSJacob Faibussowitsch   if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(data, pdtype, cnt));
8313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
832c4e82887SLisandro Dalcin }
833c4e82887SLisandro Dalcin 
MPIU_File_write_at_all(MPI_File fd,MPI_Offset off,void * data,PetscMPIInt cnt,MPI_Datatype dtype,MPI_Status * status)834d71ae5a4SJacob Faibussowitsch PetscErrorCode MPIU_File_write_at_all(MPI_File fd, MPI_Offset off, void *data, PetscMPIInt cnt, MPI_Datatype dtype, MPI_Status *status)
835d71ae5a4SJacob Faibussowitsch {
836c4e82887SLisandro Dalcin   PetscDataType pdtype;
837c4e82887SLisandro Dalcin 
838c4e82887SLisandro Dalcin   PetscFunctionBegin;
8399566063dSJacob Faibussowitsch   PetscCall(PetscMPIDataTypeToPetscDataType(dtype, &pdtype));
8409566063dSJacob Faibussowitsch   if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(data, pdtype, cnt));
8419566063dSJacob Faibussowitsch   PetscCallMPI(MPI_File_write_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 
MPIU_File_read_at_all(MPI_File fd,MPI_Offset off,void * data,PetscMPIInt cnt,MPI_Datatype dtype,MPI_Status * status)846d71ae5a4SJacob Faibussowitsch PetscErrorCode MPIU_File_read_at_all(MPI_File fd, MPI_Offset off, void *data, PetscMPIInt cnt, MPI_Datatype dtype, MPI_Status *status)
847d71ae5a4SJacob Faibussowitsch {
848c4e82887SLisandro Dalcin   PetscDataType pdtype;
849c4e82887SLisandro Dalcin 
850c4e82887SLisandro Dalcin   PetscFunctionBegin;
8519566063dSJacob Faibussowitsch   PetscCall(PetscMPIDataTypeToPetscDataType(dtype, &pdtype));
8529566063dSJacob Faibussowitsch   PetscCallMPI(MPI_File_read_at_all(fd, off, data, cnt, dtype, status));
8539566063dSJacob Faibussowitsch   if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(data, pdtype, cnt));
8543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
855c4e82887SLisandro Dalcin }
856c4e82887SLisandro Dalcin 
857951e3c8eSBarry Smith #endif
858