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