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 /* 98*3321ca25SJames Wright PetscByteSwapInt32 - Swap bytes in a PETSc integer (32-bits) 99*3321ca25SJames Wright 100*3321ca25SJames Wright */ 101*3321ca25SJames Wright PetscErrorCode PetscByteSwapInt32(PetscInt32 *buff, PetscInt n) 102*3321ca25SJames Wright { 103*3321ca25SJames Wright PetscInt i, j; 104*3321ca25SJames Wright PetscInt32 tmp = 0; 105*3321ca25SJames Wright char *ptr1, *ptr2 = (char *)&tmp; 106*3321ca25SJames Wright 107*3321ca25SJames Wright PetscFunctionBegin; 108*3321ca25SJames Wright for (j = 0; j < n; j++) { 109*3321ca25SJames Wright ptr1 = (char *)(buff + j); 110*3321ca25SJames Wright for (i = 0; i < (PetscInt)sizeof(PetscInt32); i++) ptr2[i] = ptr1[sizeof(PetscInt32) - 1 - i]; 111*3321ca25SJames Wright for (i = 0; i < (PetscInt)sizeof(PetscInt32); i++) ptr1[i] = ptr2[i]; 112*3321ca25SJames Wright } 113*3321ca25SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 114*3321ca25SJames Wright } 115*3321ca25SJames Wright 116*3321ca25SJames 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)); 237*3321ca25SJames 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*3321ca25SJames Wright else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Unknown type: %d", pdtype); 2433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 244e39fd77fSBarry Smith } 245e39fd77fSBarry Smith 2469860990eSLisandro Dalcin /*@C 247e5c89e4eSSatish Balay PetscBinaryRead - Reads from a binary file. 248e5c89e4eSSatish Balay 249e5c89e4eSSatish Balay Not Collective 250e5c89e4eSSatish Balay 251e5c89e4eSSatish Balay Input Parameters: 2529860990eSLisandro Dalcin + fd - the file descriptor 2539860990eSLisandro Dalcin . num - the maximum number of items to read 254811af0c4SBarry Smith - type - the type of items to read (`PETSC_INT`, `PETSC_REAL`, `PETSC_SCALAR`, etc.) 255e5c89e4eSSatish Balay 256e5c89e4eSSatish Balay Output Parameters: 25721532e8aSBarry Smith + data - the buffer, this is an array of the type that matches the value in `type` 2589860990eSLisandro Dalcin - count - the number of items read, optional 259e5c89e4eSSatish Balay 260e5c89e4eSSatish Balay Level: developer 261e5c89e4eSSatish Balay 262e5c89e4eSSatish Balay Notes: 26321532e8aSBarry Smith If `count` is not provided and the number of items read is less than 2649860990eSLisandro Dalcin the maximum number of items to read, then this routine errors. 2659860990eSLisandro Dalcin 266811af0c4SBarry Smith `PetscBinaryRead()` uses byte swapping to work on all machines; the files 26721532e8aSBarry Smith are written ALWAYS using big-endian ordering. On little-endian machines the numbers 268f253e43cSLisandro Dalcin are converted to the little-endian format when they are read in from the file. 26921532e8aSBarry Smith When PETSc is ./configure with `--with-64-bit-indices` the integers are written to the 2707de69702SBarry Smith file as 64-bit integers, this means they can only be read back in when the option `--with-64-bit-indices` 27154f21887SBarry Smith is used. 272e5c89e4eSSatish Balay 273db781477SPatrick Sanan .seealso: `PetscBinaryWrite()`, `PetscBinaryOpen()`, `PetscBinaryClose()`, `PetscViewerBinaryGetDescriptor()`, `PetscBinarySynchronizedWrite()`, 274db781477SPatrick Sanan `PetscBinarySynchronizedRead()`, `PetscBinarySynchronizedSeek()` 275e5c89e4eSSatish Balay @*/ 276d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscBinaryRead(int fd, void *data, PetscInt num, PetscInt *count, PetscDataType type) 277d71ae5a4SJacob Faibussowitsch { 2789860990eSLisandro Dalcin size_t typesize, m = (size_t)num, n = 0, maxblock = 65536; 2799860990eSLisandro Dalcin char *p = (char *)data; 2807a881295SBarry Smith #if defined(PETSC_USE_REAL___FLOAT128) 281cba51d77SBarry Smith PetscBool readdouble = PETSC_FALSE; 2829860990eSLisandro Dalcin double *pdouble; 2837a881295SBarry Smith #endif 2849860990eSLisandro Dalcin void *ptmp = data; 28505acbc63SBarry Smith char *fname = NULL; 286e5c89e4eSSatish Balay 287e5c89e4eSSatish Balay PetscFunctionBegin; 2889860990eSLisandro Dalcin if (count) *count = 0; 28908401ef6SPierre Jolivet PetscCheck(num >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to read a negative amount of data %" PetscInt_FMT, num); 2903ba16761SJacob Faibussowitsch if (!num) PetscFunctionReturn(PETSC_SUCCESS); 291e5c89e4eSSatish Balay 2922d53ad75SBarry Smith if (type == PETSC_FUNCTION) { 2932d53ad75SBarry Smith m = 64; 2942d53ad75SBarry Smith type = PETSC_CHAR; 29505acbc63SBarry Smith fname = (char *)malloc(m * sizeof(char)); 2969860990eSLisandro Dalcin p = (char *)fname; 2972d53ad75SBarry Smith ptmp = (void *)fname; 29828b400f6SJacob Faibussowitsch PetscCheck(fname, PETSC_COMM_SELF, PETSC_ERR_MEM, "Cannot allocate space for function name"); 2992d53ad75SBarry Smith } 3009860990eSLisandro Dalcin if (type == PETSC_BIT_LOGICAL) m = PetscBTLength(m); 3012d53ad75SBarry Smith 3029566063dSJacob Faibussowitsch PetscCall(PetscDataTypeGetSize(type, &typesize)); 303e5c89e4eSSatish Balay 3047a881295SBarry Smith #if defined(PETSC_USE_REAL___FLOAT128) 3059566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-binary_read_double", &readdouble, NULL)); 3067a881295SBarry Smith /* If using __float128 precision we still read in doubles from file */ 3079860990eSLisandro Dalcin if ((type == PETSC_REAL || type == PETSC_COMPLEX) && readdouble) { 3089860990eSLisandro Dalcin PetscInt cnt = num * ((type == PETSC_REAL) ? 1 : 2); 3099566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cnt, &pdouble)); 3109860990eSLisandro Dalcin p = (char *)pdouble; 3119860990eSLisandro Dalcin typesize /= 2; 3127a881295SBarry Smith } 3137a881295SBarry Smith #endif 3147a881295SBarry Smith 3159860990eSLisandro Dalcin m *= typesize; 3169860990eSLisandro Dalcin 317e5c89e4eSSatish Balay while (m) { 3189860990eSLisandro Dalcin size_t len = (m < maxblock) ? m : maxblock; 3199860990eSLisandro Dalcin int ret = (int)read(fd, p, len); 3209860990eSLisandro Dalcin if (ret < 0 && errno == EINTR) continue; 3219860990eSLisandro Dalcin if (!ret && len > 0) break; /* Proxy for EOF */ 322bf31d2d3SBarry Smith PetscCheck(ret >= 0, PETSC_COMM_SELF, PETSC_ERR_FILE_READ, "Error reading from file due to \"%s\"", strerror(errno)); 323ff9f933bSBarry Smith m -= (size_t)ret; 3249860990eSLisandro Dalcin p += ret; 325ff9f933bSBarry Smith n += (size_t)ret; 326e5c89e4eSSatish Balay } 32708401ef6SPierre Jolivet PetscCheck(!m || count, PETSC_COMM_SELF, PETSC_ERR_FILE_READ, "Read past end of file"); 3289860990eSLisandro Dalcin 3299860990eSLisandro Dalcin num = (PetscInt)(n / typesize); /* Should we require `n % typesize == 0` ? */ 3309860990eSLisandro Dalcin if (count) *count = num; /* TODO: This is most likely wrong for PETSC_BIT_LOGICAL */ 3317a881295SBarry Smith 3327a881295SBarry Smith #if defined(PETSC_USE_REAL___FLOAT128) 3339860990eSLisandro Dalcin if ((type == PETSC_REAL || type == PETSC_COMPLEX) && readdouble) { 3349860990eSLisandro Dalcin PetscInt i, cnt = num * ((type == PETSC_REAL) ? 1 : 2); 3359860990eSLisandro Dalcin PetscReal *preal = (PetscReal *)data; 3369566063dSJacob Faibussowitsch if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwapDouble(pdouble, cnt)); 3379860990eSLisandro Dalcin for (i = 0; i < cnt; i++) preal[i] = pdouble[i]; 3389566063dSJacob Faibussowitsch PetscCall(PetscFree(pdouble)); 3393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3407a881295SBarry Smith } 3417a881295SBarry Smith #endif 3427a881295SBarry Smith 3439566063dSJacob Faibussowitsch if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(ptmp, type, num)); 344e5c89e4eSSatish Balay 34505acbc63SBarry Smith if (type == PETSC_FUNCTION) { 3462d53ad75SBarry Smith #if defined(PETSC_SERIALIZE_FUNCTIONS) 3479566063dSJacob Faibussowitsch PetscCall(PetscDLSym(NULL, fname, (void **)data)); 3482d53ad75SBarry Smith #else 3499860990eSLisandro Dalcin *(void **)data = NULL; 3502d53ad75SBarry Smith #endif 35105acbc63SBarry Smith free(fname); 3522d53ad75SBarry Smith } 3533ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 354e5c89e4eSSatish Balay } 3559860990eSLisandro Dalcin 356a9acdec7SBarry Smith /*@C 357e5c89e4eSSatish Balay PetscBinaryWrite - Writes to a binary file. 358e5c89e4eSSatish Balay 359e5c89e4eSSatish Balay Not Collective 360e5c89e4eSSatish Balay 361e5c89e4eSSatish Balay Input Parameters: 362e5c89e4eSSatish Balay + fd - the file 36321532e8aSBarry Smith . p - the buffer, an array of the type that matches the value in `type` 364e5c89e4eSSatish Balay . n - the number of items to write 365811af0c4SBarry Smith - type - the type of items to read (`PETSC_INT`, `PETSC_REAL` or `PETSC_SCALAR`) 366e5c89e4eSSatish Balay 367e5c89e4eSSatish Balay Level: advanced 368e5c89e4eSSatish Balay 369e5c89e4eSSatish Balay Notes: 370811af0c4SBarry Smith `PetscBinaryWrite()` uses byte swapping to work on all machines; the files 371f253e43cSLisandro Dalcin are written using big-endian ordering to the file. On little-endian machines the numbers 372e5c89e4eSSatish Balay are converted to the big-endian format when they are written to disk. 37321532e8aSBarry Smith When PETSc is configured using `./configure with --with-64-bit-indices` the integers are written to the 3747de69702SBarry Smith file as 64-bit integers, this means they can only be read back in when the option `--with-64-bit-indices` 37554f21887SBarry Smith is used. 376e5c89e4eSSatish Balay 37721532e8aSBarry Smith If running with `__float128` precision the output of `PETSC_REAL` is in `__float128` unless one uses the `-binary_write_double` option 3780da86b62SBarry Smith 379bfbbc7b7SBarry Smith The buffer `p` should be read-write buffer, and not static data. 380e5c89e4eSSatish Balay This way, byte-swapping is done in-place, and then the buffer is 381e5c89e4eSSatish Balay written to the file. 382e5c89e4eSSatish Balay 383e5c89e4eSSatish Balay This routine restores the original contents of the buffer, after 384e5c89e4eSSatish Balay it is written to the file. This is done by byte-swapping in-place 385f253e43cSLisandro Dalcin the second time. 386e5c89e4eSSatish Balay 387300a7f5bSBarry Smith Because byte-swapping may be done on the values in data it cannot be declared const 388300a7f5bSBarry Smith 389db781477SPatrick Sanan .seealso: `PetscBinaryRead()`, `PetscBinaryOpen()`, `PetscBinaryClose()`, `PetscViewerBinaryGetDescriptor()`, `PetscBinarySynchronizedWrite()`, 390db781477SPatrick Sanan `PetscBinarySynchronizedRead()`, `PetscBinarySynchronizedSeek()` 391e5c89e4eSSatish Balay @*/ 392d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscBinaryWrite(int fd, const void *p, PetscInt n, PetscDataType type) 393d71ae5a4SJacob Faibussowitsch { 394f253e43cSLisandro Dalcin const char *pp = (char *)p; 395e5c89e4eSSatish Balay int err, wsize; 396e5c89e4eSSatish Balay size_t m = (size_t)n, maxblock = 65536; 397f253e43cSLisandro Dalcin const void *ptmp = p; 39805acbc63SBarry Smith char *fname = NULL; 3990da86b62SBarry Smith #if defined(PETSC_USE_REAL___FLOAT128) 400df40af56SBarry Smith PetscBool writedouble = PETSC_FALSE; 4010da86b62SBarry Smith double *ppp; 4020da86b62SBarry Smith PetscReal *pv; 4030da86b62SBarry Smith PetscInt i; 4040da86b62SBarry Smith #endif 40541f502e3SPatrick Sanan PetscDataType wtype = type; 406e5c89e4eSSatish Balay 407e5c89e4eSSatish Balay PetscFunctionBegin; 40808401ef6SPierre Jolivet PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to write a negative amount of data %" PetscInt_FMT, n); 4093ba16761SJacob Faibussowitsch if (!n) PetscFunctionReturn(PETSC_SUCCESS); 410e5c89e4eSSatish Balay 4112d53ad75SBarry Smith if (type == PETSC_FUNCTION) { 4122d53ad75SBarry Smith #if defined(PETSC_SERIALIZE_FUNCTIONS) 4132d53ad75SBarry Smith const char *fnametmp; 4142d53ad75SBarry Smith #endif 4152d53ad75SBarry Smith m = 64; 416e25ab156SSatish Balay fname = (char *)malloc(m * sizeof(char)); 41728b400f6SJacob Faibussowitsch PetscCheck(fname, PETSC_COMM_SELF, PETSC_ERR_MEM, "Cannot allocate space for function name"); 41805acbc63SBarry Smith #if defined(PETSC_SERIALIZE_FUNCTIONS) 41908401ef6SPierre Jolivet PetscCheck(n <= 1, PETSC_COMM_SELF, PETSC_ERR_SUP, "Can only binary view a single function at a time"); 4209566063dSJacob Faibussowitsch PetscCall(PetscFPTFind(*(void **)p, &fnametmp)); 4219566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(fname, fnametmp, m)); 42205acbc63SBarry Smith #else 4239566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(fname, "", m)); 42405acbc63SBarry Smith #endif 42501963f56SBarry Smith wtype = PETSC_CHAR; 4262d53ad75SBarry Smith pp = (char *)fname; 4272d53ad75SBarry Smith ptmp = (void *)fname; 4282d53ad75SBarry Smith } 4292d53ad75SBarry Smith 4300da86b62SBarry Smith #if defined(PETSC_USE_REAL___FLOAT128) 4319566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-binary_write_double", &writedouble, NULL)); 4320da86b62SBarry Smith /* If using __float128 precision we still write in doubles to file */ 433501ae109SJose E. Roman if ((type == PETSC_SCALAR || type == PETSC_REAL || type == PETSC_COMPLEX) && writedouble) { 43441f502e3SPatrick Sanan wtype = PETSC_DOUBLE; 4359566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n, &ppp)); 4360da86b62SBarry Smith pv = (PetscReal *)pp; 437ad540459SPierre Jolivet for (i = 0; i < n; i++) ppp[i] = (double)pv[i]; 4380da86b62SBarry Smith pp = (char *)ppp; 4390da86b62SBarry Smith ptmp = (char *)ppp; 4400da86b62SBarry Smith } 4410da86b62SBarry Smith #endif 4420da86b62SBarry Smith 44341f502e3SPatrick Sanan if (wtype == PETSC_INT) m *= sizeof(PetscInt); 44441f502e3SPatrick Sanan else if (wtype == PETSC_SCALAR) m *= sizeof(PetscScalar); 445501ae109SJose E. Roman #if defined(PETSC_HAVE_COMPLEX) 446501ae109SJose E. Roman else if (wtype == PETSC_COMPLEX) m *= sizeof(PetscComplex); 447501ae109SJose E. Roman #endif 4484caf0332SSatish Balay else if (wtype == PETSC_REAL) m *= sizeof(PetscReal); 44941f502e3SPatrick Sanan else if (wtype == PETSC_DOUBLE) m *= sizeof(double); 45041f502e3SPatrick Sanan else if (wtype == PETSC_FLOAT) m *= sizeof(float); 45141f502e3SPatrick Sanan else if (wtype == PETSC_SHORT) m *= sizeof(short); 452972064b6SLisandro Dalcin else if (wtype == PETSC_LONG) m *= sizeof(long); 45341f502e3SPatrick Sanan else if (wtype == PETSC_CHAR) m *= sizeof(char); 45441f502e3SPatrick Sanan else if (wtype == PETSC_ENUM) m *= sizeof(PetscEnum); 45541f502e3SPatrick Sanan else if (wtype == PETSC_BOOL) m *= sizeof(PetscBool); 4569e3e4c22SLisandro Dalcin else if (wtype == PETSC_INT64) m *= sizeof(PetscInt64); 457*3321ca25SJames Wright else if (wtype == PETSC_INT32) m *= sizeof(PetscInt32); 45841f502e3SPatrick Sanan else if (wtype == PETSC_BIT_LOGICAL) m = PetscBTLength(m) * sizeof(char); 459*3321ca25SJames Wright else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Unknown type: %d", wtype); 460e5c89e4eSSatish Balay 4619566063dSJacob Faibussowitsch if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap((void *)ptmp, wtype, n)); 462e5c89e4eSSatish Balay 463e5c89e4eSSatish Balay while (m) { 464e5c89e4eSSatish Balay wsize = (m < maxblock) ? m : maxblock; 465e5c89e4eSSatish Balay err = write(fd, pp, wsize); 466e5c89e4eSSatish Balay if (err < 0 && errno == EINTR) continue; 467bf31d2d3SBarry 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)); 468e5c89e4eSSatish Balay m -= wsize; 469e5c89e4eSSatish Balay pp += wsize; 470e5c89e4eSSatish Balay } 471e5c89e4eSSatish Balay 4729566063dSJacob Faibussowitsch if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap((void *)ptmp, wtype, n)); 473f253e43cSLisandro Dalcin 474ad540459SPierre Jolivet if (type == PETSC_FUNCTION) free(fname); 4750da86b62SBarry Smith #if defined(PETSC_USE_REAL___FLOAT128) 47648a46eb9SPierre Jolivet if ((type == PETSC_SCALAR || type == PETSC_REAL || type == PETSC_COMPLEX) && writedouble) PetscCall(PetscFree(ppp)); 4770da86b62SBarry Smith #endif 4783ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 479e5c89e4eSSatish Balay } 480e5c89e4eSSatish Balay 481e5c89e4eSSatish Balay /*@C 482e5c89e4eSSatish Balay PetscBinaryOpen - Opens a PETSc binary file. 483e5c89e4eSSatish Balay 484e5c89e4eSSatish Balay Not Collective 485e5c89e4eSSatish Balay 486e5c89e4eSSatish Balay Input Parameters: 487e5c89e4eSSatish Balay + name - filename 488811af0c4SBarry Smith - mode - open mode of binary file, one of `FILE_MODE_READ`, `FILE_MODE_WRITE`, `FILE_MODE_APPEND`` 489e5c89e4eSSatish Balay 490e5c89e4eSSatish Balay Output Parameter: 491e5c89e4eSSatish Balay . fd - the file 492e5c89e4eSSatish Balay 493e5c89e4eSSatish Balay Level: advanced 494e5c89e4eSSatish Balay 495db781477SPatrick Sanan .seealso: `PetscBinaryRead()`, `PetscBinaryWrite()`, `PetscFileMode`, `PetscViewerFileSetMode()`, `PetscViewerBinaryGetDescriptor()`, 496db781477SPatrick Sanan `PetscBinarySynchronizedWrite()`, `PetscBinarySynchronizedRead()`, `PetscBinarySynchronizedSeek()` 497e5c89e4eSSatish Balay @*/ 498d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscBinaryOpen(const char name[], PetscFileMode mode, int *fd) 499d71ae5a4SJacob Faibussowitsch { 500e5c89e4eSSatish Balay PetscFunctionBegin; 501cc843e7aSLisandro Dalcin switch (mode) { 502d71ae5a4SJacob Faibussowitsch case FILE_MODE_READ: 503d71ae5a4SJacob Faibussowitsch *fd = open(name, O_BINARY | O_RDONLY, 0); 504d71ae5a4SJacob Faibussowitsch break; 505d71ae5a4SJacob Faibussowitsch case FILE_MODE_WRITE: 506d71ae5a4SJacob Faibussowitsch *fd = open(name, O_BINARY | O_WRONLY | O_CREAT | O_TRUNC, 0666); 507d71ae5a4SJacob Faibussowitsch break; 508d71ae5a4SJacob Faibussowitsch case FILE_MODE_APPEND: 509d71ae5a4SJacob Faibussowitsch *fd = open(name, O_BINARY | O_WRONLY | O_APPEND, 0); 510d71ae5a4SJacob Faibussowitsch break; 511d71ae5a4SJacob Faibussowitsch default: 512d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Unsupported file mode %s", PetscFileModes[mode]); 513e5c89e4eSSatish Balay } 514bf31d2d3SBarry 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)); 5153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 516e5c89e4eSSatish Balay } 517e5c89e4eSSatish Balay 518e30d2299SSatish Balay /*@ 519e5c89e4eSSatish Balay PetscBinaryClose - Closes a PETSc binary file. 520e5c89e4eSSatish Balay 521e5c89e4eSSatish Balay Not Collective 522e5c89e4eSSatish Balay 523e5c89e4eSSatish Balay Output Parameter: 524e5c89e4eSSatish Balay . fd - the file 525e5c89e4eSSatish Balay 526e5c89e4eSSatish Balay Level: advanced 527e5c89e4eSSatish Balay 528db781477SPatrick Sanan .seealso: `PetscBinaryRead()`, `PetscBinaryWrite()`, `PetscBinaryOpen()`, `PetscBinarySynchronizedWrite()`, `PetscBinarySynchronizedRead()`, 529db781477SPatrick Sanan `PetscBinarySynchronizedSeek()` 530e5c89e4eSSatish Balay @*/ 531d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscBinaryClose(int fd) 532d71ae5a4SJacob Faibussowitsch { 533e5c89e4eSSatish Balay PetscFunctionBegin; 534cc73adaaSBarry Smith PetscCheck(!close(fd), PETSC_COMM_SELF, PETSC_ERR_SYS, "close() failed on file descriptor"); 5353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 536e5c89e4eSSatish Balay } 537e5c89e4eSSatish Balay 538e8976759SBarry Smith /*@C 539e5c89e4eSSatish Balay PetscBinarySeek - Moves the file pointer on a PETSc binary file. 540e5c89e4eSSatish Balay 541e5c89e4eSSatish Balay Not Collective 542e5c89e4eSSatish Balay 543e5c89e4eSSatish Balay Input Parameters: 544e5c89e4eSSatish Balay + fd - the file 545811af0c4SBarry Smith . off - number of bytes to move. Use `PETSC_BINARY_INT_SIZE`, `PETSC_BINARY_SCALAR_SIZE`, 54621532e8aSBarry Smith etc. in your calculation rather than `sizeof()` to compute byte lengths. 54716a05f60SBarry Smith - whence - see `PetscBinarySeekType` for possible values 548e5c89e4eSSatish Balay 549e5c89e4eSSatish Balay Output Parameter: 550e5c89e4eSSatish Balay . offset - new offset in file 551e5c89e4eSSatish Balay 552e5c89e4eSSatish Balay Level: developer 553e5c89e4eSSatish Balay 55416a05f60SBarry Smith .seealso: `PetscBinaryRead()`, `PetscBinarySeekType`, `PetscBinaryWrite()`, `PetscBinaryOpen()`, `PetscBinarySynchronizedWrite()`, `PetscBinarySynchronizedRead()`, 555db781477SPatrick Sanan `PetscBinarySynchronizedSeek()` 556e5c89e4eSSatish Balay @*/ 557d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscBinarySeek(int fd, off_t off, PetscBinarySeekType whence, off_t *offset) 558d71ae5a4SJacob Faibussowitsch { 559e5c89e4eSSatish Balay int iwhence = 0; 560e5c89e4eSSatish Balay 561e5c89e4eSSatish Balay PetscFunctionBegin; 562a297a907SKarl Rupp if (whence == PETSC_BINARY_SEEK_SET) iwhence = SEEK_SET; 563a297a907SKarl Rupp else if (whence == PETSC_BINARY_SEEK_CUR) iwhence = SEEK_CUR; 564a297a907SKarl Rupp else if (whence == PETSC_BINARY_SEEK_END) iwhence = SEEK_END; 565a297a907SKarl Rupp else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Unknown seek location"); 566e5c89e4eSSatish Balay #if defined(PETSC_HAVE_LSEEK) 567e5c89e4eSSatish Balay *offset = lseek(fd, off, iwhence); 568e5c89e4eSSatish Balay #elif defined(PETSC_HAVE__LSEEK) 569e5c89e4eSSatish Balay *offset = _lseek(fd, (long)off, iwhence); 570e5c89e4eSSatish Balay #else 571e32f2f54SBarry Smith SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP_SYS, "System does not have a way of seeking on a file"); 572e5c89e4eSSatish Balay #endif 5733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 574e5c89e4eSSatish Balay } 575e5c89e4eSSatish Balay 576e5c89e4eSSatish Balay /*@C 57721532e8aSBarry Smith PetscBinarySynchronizedRead - Reads from a binary file, all MPI processes get the same values 578e5c89e4eSSatish Balay 579d083f849SBarry Smith Collective 580e5c89e4eSSatish Balay 581e5c89e4eSSatish Balay Input Parameters: 582e5c89e4eSSatish Balay + comm - the MPI communicator 5839860990eSLisandro Dalcin . fd - the file descriptor 5849860990eSLisandro Dalcin . num - the maximum number of items to read 585811af0c4SBarry Smith - type - the type of items to read (`PETSC_INT`, `PETSC_REAL`, `PETSC_SCALAR`, etc.) 586e5c89e4eSSatish Balay 587e5c89e4eSSatish Balay Output Parameters: 58821532e8aSBarry Smith + data - the buffer, an array of the type that matches the value in `type` 5899860990eSLisandro Dalcin - count - the number of items read, optional 590e5c89e4eSSatish Balay 591e5c89e4eSSatish Balay Level: developer 592e5c89e4eSSatish Balay 593e5c89e4eSSatish Balay Notes: 594811af0c4SBarry Smith Does a `PetscBinaryRead()` followed by an `MPI_Bcast()` 595e5c89e4eSSatish Balay 59621532e8aSBarry Smith If `count` is not provided and the number of items read is less than 5979860990eSLisandro Dalcin the maximum number of items to read, then this routine errors. 5989860990eSLisandro Dalcin 599811af0c4SBarry Smith `PetscBinarySynchronizedRead()` uses byte swapping to work on all machines. 60021532e8aSBarry Smith The files are written using big-endian ordering to the file. On little-endian machines the numbers 60121532e8aSBarry Smith are converted to the big-endian format when they are written to disk. 60221532e8aSBarry Smith When PETSc is configured using `./configure with --with-64-bit-indices` the integers are written to the 6037de69702SBarry Smith file as 64-bit integers, this means they can only be read back in when the option `--with-64-bit-indices` 60421532e8aSBarry Smith is used. 605e5c89e4eSSatish Balay 606db781477SPatrick Sanan .seealso: `PetscBinaryWrite()`, `PetscBinaryOpen()`, `PetscBinaryClose()`, `PetscBinaryRead()`, `PetscBinarySynchronizedWrite()`, 607db781477SPatrick Sanan `PetscBinarySynchronizedSeek()` 608e5c89e4eSSatish Balay @*/ 609d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscBinarySynchronizedRead(MPI_Comm comm, int fd, void *data, PetscInt num, PetscInt *count, PetscDataType type) 610d71ae5a4SJacob Faibussowitsch { 6118b8bf82cSBarry Smith PetscMPIInt rank, size; 612e5c89e4eSSatish Balay MPI_Datatype mtype; 6139860990eSLisandro Dalcin PetscInt ibuf[2] = {0, 0}; 61405acbc63SBarry Smith char *fname = NULL; 6159860990eSLisandro Dalcin void *fptr = NULL; 616e5c89e4eSSatish Balay 617e5c89e4eSSatish Balay PetscFunctionBegin; 6182d53ad75SBarry Smith if (type == PETSC_FUNCTION) { 6199860990eSLisandro Dalcin num = 64; 6202d53ad75SBarry Smith type = PETSC_CHAR; 6219860990eSLisandro Dalcin fname = (char *)malloc(num * sizeof(char)); 6229860990eSLisandro Dalcin fptr = data; 6239860990eSLisandro Dalcin data = (void *)fname; 62428b400f6SJacob Faibussowitsch PetscCheck(fname, PETSC_COMM_SELF, PETSC_ERR_MEM, "Cannot allocate space for function name"); 6252d53ad75SBarry Smith } 6262d53ad75SBarry Smith 6279566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 6289566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 629ad540459SPierre Jolivet if (rank == 0) ibuf[0] = PetscBinaryRead(fd, data, num, count ? &ibuf[1] : NULL, type); 6309566063dSJacob Faibussowitsch PetscCallMPI(MPI_Bcast(ibuf, 2, MPIU_INT, 0, comm)); 6319566063dSJacob Faibussowitsch PetscCall((PetscErrorCode)ibuf[0]); 6328b8bf82cSBarry Smith 6338b8bf82cSBarry 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 */ 6348b8bf82cSBarry Smith if (size > 1) { 6359566063dSJacob Faibussowitsch PetscCall(PetscDataTypeToMPIDataType(type, &mtype)); 6369566063dSJacob Faibussowitsch PetscCallMPI(MPI_Bcast(data, count ? ibuf[1] : num, mtype, 0, comm)); 6378b8bf82cSBarry Smith } 6389860990eSLisandro Dalcin if (count) *count = ibuf[1]; 6392d53ad75SBarry Smith 640e366c363SBarry Smith if (type == PETSC_FUNCTION) { 6412d53ad75SBarry Smith #if defined(PETSC_SERIALIZE_FUNCTIONS) 6429566063dSJacob Faibussowitsch PetscCall(PetscDLLibrarySym(PETSC_COMM_SELF, &PetscDLLibrariesLoaded, NULL, fname, (void **)fptr)); 6432d53ad75SBarry Smith #else 6449860990eSLisandro Dalcin *(void **)fptr = NULL; 6452d53ad75SBarry Smith #endif 646e366c363SBarry Smith free(fname); 6472d53ad75SBarry Smith } 6483ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 649e5c89e4eSSatish Balay } 650e5c89e4eSSatish Balay 651e5c89e4eSSatish Balay /*@C 6521d280d73SBarry Smith PetscBinarySynchronizedWrite - writes to a binary file. 653e5c89e4eSSatish Balay 654d083f849SBarry Smith Collective 655e5c89e4eSSatish Balay 656e5c89e4eSSatish Balay Input Parameters: 657e5c89e4eSSatish Balay + comm - the MPI communicator 658e5c89e4eSSatish Balay . fd - the file 659e5c89e4eSSatish Balay . n - the number of items to write 66021532e8aSBarry Smith . p - the buffer, an array of the type that matches the value in `type` 661811af0c4SBarry Smith - type - the type of items to write (`PETSC_INT`, `PETSC_REAL` or `PETSC_SCALAR`) 662e5c89e4eSSatish Balay 663e5c89e4eSSatish Balay Level: developer 664e5c89e4eSSatish Balay 665e5c89e4eSSatish Balay Notes: 66621532e8aSBarry Smith MPI rank 0 does a `PetscBinaryWrite()` the values on other MPI processes are not used 667e5c89e4eSSatish Balay 66821532e8aSBarry Smith The files are written using big-endian ordering to the file. On little-endian machines the numbers 66921532e8aSBarry Smith are converted to the big-endian format when they are written to disk. 67021532e8aSBarry Smith When PETSc is configured using `./configure with --with-64-bit-indices` the integers are written to the 6717de69702SBarry Smith file as 64-bit integers, this means they can only be read back in when the option `--with-64-bit-indices` 67221532e8aSBarry Smith is used. 673e5c89e4eSSatish Balay 674811af0c4SBarry Smith Because byte-swapping may be done on the values in data it cannot be declared const 675300a7f5bSBarry Smith 676811af0c4SBarry Smith WARNING: 677bfbbc7b7SBarry Smith This is NOT like `PetscSynchronizedFPrintf()`! This routine ignores calls on all but MPI rank 0, 67821532e8aSBarry Smith while `PetscSynchronizedFPrintf()` has all MPI processes print their strings in order. 6791d280d73SBarry Smith 680db781477SPatrick Sanan .seealso: `PetscBinaryWrite()`, `PetscBinaryOpen()`, `PetscBinaryClose()`, `PetscBinaryRead()`, `PetscBinarySynchronizedRead()`, 681db781477SPatrick Sanan `PetscBinarySynchronizedSeek()` 682e5c89e4eSSatish Balay @*/ 683d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscBinarySynchronizedWrite(MPI_Comm comm, int fd, const void *p, PetscInt n, PetscDataType type) 684d71ae5a4SJacob Faibussowitsch { 685e5c89e4eSSatish Balay PetscMPIInt rank; 686e5c89e4eSSatish Balay 687e5c89e4eSSatish Balay PetscFunctionBegin; 6889566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 68948a46eb9SPierre Jolivet if (rank == 0) PetscCall(PetscBinaryWrite(fd, p, n, type)); 6903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 691e5c89e4eSSatish Balay } 692e5c89e4eSSatish Balay 693e5c89e4eSSatish Balay /*@C 6941d280d73SBarry Smith PetscBinarySynchronizedSeek - Moves the file pointer on a PETSc binary file. 695e5c89e4eSSatish Balay 696e5c89e4eSSatish Balay Input Parameters: 697e5c89e4eSSatish Balay + fd - the file 69816a05f60SBarry Smith . whence - see `PetscBinarySeekType` for possible values 699811af0c4SBarry Smith - off - number of bytes to move. Use `PETSC_BINARY_INT_SIZE`, `PETSC_BINARY_SCALAR_SIZE`, 700811af0c4SBarry Smith etc. in your calculation rather than `sizeof()` to compute byte lengths. 701e5c89e4eSSatish Balay 702e5c89e4eSSatish Balay Output Parameter: 703e5c89e4eSSatish Balay . offset - new offset in file 704e5c89e4eSSatish Balay 705e5c89e4eSSatish Balay Level: developer 706e5c89e4eSSatish Balay 70716a05f60SBarry Smith .seealso: `PetscBinaryRead()`, `PetscBinarySeekType`, `PetscBinaryWrite()`, `PetscBinaryOpen()`, `PetscBinarySynchronizedWrite()`, `PetscBinarySynchronizedRead()`, 708db781477SPatrick Sanan `PetscBinarySynchronizedSeek()` 709e5c89e4eSSatish Balay @*/ 710d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscBinarySynchronizedSeek(MPI_Comm comm, int fd, off_t off, PetscBinarySeekType whence, off_t *offset) 711d71ae5a4SJacob Faibussowitsch { 712e5c89e4eSSatish Balay PetscMPIInt rank; 713e5c89e4eSSatish Balay 714e5c89e4eSSatish Balay PetscFunctionBegin; 7159566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 71648a46eb9SPierre Jolivet if (rank == 0) PetscCall(PetscBinarySeek(fd, off, whence, offset)); 7173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 718e5c89e4eSSatish Balay } 719e5c89e4eSSatish Balay 7200fc9d207SBarry Smith #if defined(PETSC_HAVE_MPIIO) 721e39fd77fSBarry Smith 722951e3c8eSBarry Smith #if defined(PETSC_USE_PETSC_MPI_EXTERNAL32) 723e39fd77fSBarry Smith /* 724e39fd77fSBarry Smith MPICH does not provide the external32 representation for MPI_File_set_view() so we need to provide the functions. 725e39fd77fSBarry Smith These are set into MPI in PetscInitialize() via MPI_Register_datarep() 726e39fd77fSBarry Smith 727e39fd77fSBarry Smith Note I use PetscMPIInt for the MPI error codes since that is what MPI uses (instead of the standard PetscErrorCode) 728e39fd77fSBarry Smith 729951e3c8eSBarry Smith The next three routines are not used because MPICH does not support their use 730e39fd77fSBarry Smith 731e39fd77fSBarry Smith */ 732d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscMPIInt PetscDataRep_extent_fn(MPI_Datatype datatype, MPI_Aint *file_extent, void *extra_state) 733d71ae5a4SJacob Faibussowitsch { 734e39fd77fSBarry Smith MPI_Aint ub; 735e39fd77fSBarry Smith PetscMPIInt ierr; 736e39fd77fSBarry Smith 737e39fd77fSBarry Smith ierr = MPI_Type_get_extent(datatype, &ub, file_extent); 738e39fd77fSBarry Smith return ierr; 739e39fd77fSBarry Smith } 740e39fd77fSBarry Smith 741d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscMPIInt PetscDataRep_read_conv_fn(void *userbuf, MPI_Datatype datatype, PetscMPIInt count, void *filebuf, MPI_Offset position, void *extra_state) 742d71ae5a4SJacob Faibussowitsch { 743e39fd77fSBarry Smith PetscDataType pdtype; 744e39fd77fSBarry Smith PetscMPIInt ierr; 745e39fd77fSBarry Smith size_t dsize; 746e39fd77fSBarry Smith 7479566063dSJacob Faibussowitsch PetscCall(PetscMPIDataTypeToPetscDataType(datatype, &pdtype)); 7489566063dSJacob Faibussowitsch PetscCall(PetscDataTypeGetSize(pdtype, &dsize)); 749e39fd77fSBarry Smith 750e39fd77fSBarry Smith /* offset is given in units of MPI_Datatype */ 751e39fd77fSBarry Smith userbuf = ((char *)userbuf) + dsize * position; 752e39fd77fSBarry Smith 7539566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(userbuf, filebuf, count * dsize)); 7549566063dSJacob Faibussowitsch if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(userbuf, pdtype, count)); 755e39fd77fSBarry Smith return ierr; 756e39fd77fSBarry Smith } 757e39fd77fSBarry Smith 758d71ae5a4SJacob Faibussowitsch PetscMPIInt PetscDataRep_write_conv_fn(void *userbuf, MPI_Datatype datatype, PetscMPIInt count, void *filebuf, MPI_Offset position, void *extra_state) 759d71ae5a4SJacob Faibussowitsch { 760e39fd77fSBarry Smith PetscDataType pdtype; 761e39fd77fSBarry Smith PetscMPIInt ierr; 762e39fd77fSBarry Smith size_t dsize; 763e39fd77fSBarry Smith 7649566063dSJacob Faibussowitsch PetscCall(PetscMPIDataTypeToPetscDataType(datatype, &pdtype)); 7659566063dSJacob Faibussowitsch PetscCall(PetscDataTypeGetSize(pdtype, &dsize)); 766e39fd77fSBarry Smith 767e39fd77fSBarry Smith /* offset is given in units of MPI_Datatype */ 768e39fd77fSBarry Smith userbuf = ((char *)userbuf) + dsize * position; 769e39fd77fSBarry Smith 7709566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(filebuf, userbuf, count * dsize)); 7719566063dSJacob Faibussowitsch if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(filebuf, pdtype, count)); 772e39fd77fSBarry Smith return ierr; 773e39fd77fSBarry Smith } 774951e3c8eSBarry Smith #endif 775e39fd77fSBarry Smith 776d71ae5a4SJacob Faibussowitsch PetscErrorCode MPIU_File_write_all(MPI_File fd, void *data, PetscMPIInt cnt, MPI_Datatype dtype, MPI_Status *status) 777d71ae5a4SJacob Faibussowitsch { 778e39fd77fSBarry Smith PetscDataType pdtype; 77930815ce0SLisandro Dalcin 780e39fd77fSBarry Smith PetscFunctionBegin; 7819566063dSJacob Faibussowitsch PetscCall(PetscMPIDataTypeToPetscDataType(dtype, &pdtype)); 7829566063dSJacob Faibussowitsch if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(data, pdtype, cnt)); 7839566063dSJacob Faibussowitsch PetscCallMPI(MPI_File_write_all(fd, data, cnt, dtype, status)); 7849566063dSJacob Faibussowitsch if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(data, pdtype, cnt)); 7853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 786e39fd77fSBarry Smith } 787e39fd77fSBarry Smith 788d71ae5a4SJacob Faibussowitsch PetscErrorCode MPIU_File_read_all(MPI_File fd, void *data, PetscMPIInt cnt, MPI_Datatype dtype, MPI_Status *status) 789d71ae5a4SJacob Faibussowitsch { 790e39fd77fSBarry Smith PetscDataType pdtype; 791e39fd77fSBarry Smith 792e39fd77fSBarry Smith PetscFunctionBegin; 7939566063dSJacob Faibussowitsch PetscCall(PetscMPIDataTypeToPetscDataType(dtype, &pdtype)); 7949566063dSJacob Faibussowitsch PetscCallMPI(MPI_File_read_all(fd, data, cnt, dtype, status)); 7959566063dSJacob Faibussowitsch if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(data, pdtype, cnt)); 7963ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 797e39fd77fSBarry Smith } 79830815ce0SLisandro Dalcin 799d71ae5a4SJacob Faibussowitsch PetscErrorCode MPIU_File_write_at(MPI_File fd, MPI_Offset off, void *data, PetscMPIInt cnt, MPI_Datatype dtype, MPI_Status *status) 800d71ae5a4SJacob Faibussowitsch { 801c4e82887SLisandro Dalcin PetscDataType pdtype; 802c4e82887SLisandro Dalcin 803c4e82887SLisandro Dalcin PetscFunctionBegin; 8049566063dSJacob Faibussowitsch PetscCall(PetscMPIDataTypeToPetscDataType(dtype, &pdtype)); 8059566063dSJacob Faibussowitsch if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(data, pdtype, cnt)); 8069566063dSJacob Faibussowitsch PetscCallMPI(MPI_File_write_at(fd, off, data, cnt, dtype, status)); 8079566063dSJacob Faibussowitsch if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(data, pdtype, cnt)); 8083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 809c4e82887SLisandro Dalcin } 810c4e82887SLisandro Dalcin 811d71ae5a4SJacob Faibussowitsch PetscErrorCode MPIU_File_read_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 PetscCallMPI(MPI_File_read_at(fd, off, data, cnt, dtype, status)); 8189566063dSJacob Faibussowitsch if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(data, pdtype, cnt)); 8193ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 820c4e82887SLisandro Dalcin } 821c4e82887SLisandro Dalcin 822d71ae5a4SJacob Faibussowitsch PetscErrorCode MPIU_File_write_at_all(MPI_File fd, MPI_Offset off, void *data, PetscMPIInt cnt, MPI_Datatype dtype, MPI_Status *status) 823d71ae5a4SJacob Faibussowitsch { 824c4e82887SLisandro Dalcin PetscDataType pdtype; 825c4e82887SLisandro Dalcin 826c4e82887SLisandro Dalcin PetscFunctionBegin; 8279566063dSJacob Faibussowitsch PetscCall(PetscMPIDataTypeToPetscDataType(dtype, &pdtype)); 8289566063dSJacob Faibussowitsch if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(data, pdtype, cnt)); 8299566063dSJacob Faibussowitsch PetscCallMPI(MPI_File_write_at_all(fd, off, data, cnt, dtype, status)); 8309566063dSJacob Faibussowitsch if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(data, pdtype, cnt)); 8313ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 832c4e82887SLisandro Dalcin } 833c4e82887SLisandro Dalcin 834d71ae5a4SJacob Faibussowitsch PetscErrorCode MPIU_File_read_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 PetscCallMPI(MPI_File_read_at_all(fd, off, data, cnt, dtype, status)); 8419566063dSJacob Faibussowitsch if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(data, pdtype, cnt)); 8423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 843c4e82887SLisandro Dalcin } 844c4e82887SLisandro Dalcin 845951e3c8eSBarry Smith #endif 846