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