Actual source code: sysio.c
petsc-3.13.6 2020-09-29
2: /*
3: This file contains simple binary read/write routines.
4: */
6: #include <petscsys.h>
7: #include <petscbt.h>
8: #include <errno.h>
9: #include <fcntl.h>
10: #if defined(PETSC_HAVE_UNISTD_H)
11: #include <unistd.h>
12: #endif
13: #if defined(PETSC_HAVE_IO_H)
14: #include <io.h>
15: #endif
16: #if !defined(PETSC_HAVE_O_BINARY)
17: #define O_BINARY 0
18: #endif
20: const char *const PetscFileModes[] = {"READ","WRITE","APPEND","UPDATE","APPEND_UPDATE","PetscFileMode","PETSC_FILE_",NULL};
22: /* --------------------------------------------------------- */
23: /*
24: PetscByteSwapEnum - Swap bytes in a PETSc Enum
26: */
27: PetscErrorCode PetscByteSwapEnum(PetscEnum *buff,PetscInt n)
28: {
29: PetscInt i,j;
30: PetscEnum tmp = ENUM_DUMMY;
31: char *ptr1,*ptr2 = (char*)&tmp;
34: for (j=0; j<n; j++) {
35: ptr1 = (char*)(buff + j);
36: for (i=0; i<(PetscInt)sizeof(PetscEnum); i++) ptr2[i] = ptr1[sizeof(PetscEnum)-1-i];
37: for (i=0; i<(PetscInt)sizeof(PetscEnum); i++) ptr1[i] = ptr2[i];
38: }
39: return(0);
40: }
42: /*
43: PetscByteSwapBool - Swap bytes in a PETSc Bool
45: */
46: PetscErrorCode PetscByteSwapBool(PetscBool *buff,PetscInt n)
47: {
48: PetscInt i,j;
49: PetscBool tmp = PETSC_FALSE;
50: char *ptr1,*ptr2 = (char*)&tmp;
53: for (j=0; j<n; j++) {
54: ptr1 = (char*)(buff + j);
55: for (i=0; i<(PetscInt)sizeof(PetscBool); i++) ptr2[i] = ptr1[sizeof(PetscBool)-1-i];
56: for (i=0; i<(PetscInt)sizeof(PetscBool); i++) ptr1[i] = ptr2[i];
57: }
58: return(0);
59: }
61: /*
62: PetscByteSwapInt - Swap bytes in a PETSc integer (which may be 32 or 64 bits)
64: */
65: PetscErrorCode PetscByteSwapInt(PetscInt *buff,PetscInt n)
66: {
67: PetscInt i,j,tmp = 0;
68: char *ptr1,*ptr2 = (char*)&tmp;
71: for (j=0; j<n; j++) {
72: ptr1 = (char*)(buff + j);
73: for (i=0; i<(PetscInt)sizeof(PetscInt); i++) ptr2[i] = ptr1[sizeof(PetscInt)-1-i];
74: for (i=0; i<(PetscInt)sizeof(PetscInt); i++) ptr1[i] = ptr2[i];
75: }
76: return(0);
77: }
79: /*
80: PetscByteSwapInt64 - Swap bytes in a PETSc integer (64 bits)
82: */
83: PetscErrorCode PetscByteSwapInt64(PetscInt64 *buff,PetscInt n)
84: {
85: PetscInt i,j;
86: PetscInt64 tmp = 0;
87: char *ptr1,*ptr2 = (char*)&tmp;
90: for (j=0; j<n; j++) {
91: ptr1 = (char*)(buff + j);
92: for (i=0; i<(PetscInt)sizeof(PetscInt64); i++) ptr2[i] = ptr1[sizeof(PetscInt64)-1-i];
93: for (i=0; i<(PetscInt)sizeof(PetscInt64); i++) ptr1[i] = ptr2[i];
94: }
95: return(0);
96: }
98: /* --------------------------------------------------------- */
99: /*
100: PetscByteSwapShort - Swap bytes in a short
101: */
102: PetscErrorCode PetscByteSwapShort(short *buff,PetscInt n)
103: {
104: PetscInt i,j;
105: short tmp;
106: char *ptr1,*ptr2 = (char*)&tmp;
109: for (j=0; j<n; j++) {
110: ptr1 = (char*)(buff + j);
111: for (i=0; i<(PetscInt) sizeof(short); i++) ptr2[i] = ptr1[sizeof(short)-1-i];
112: for (i=0; i<(PetscInt) sizeof(short); i++) ptr1[i] = ptr2[i];
113: }
114: return(0);
115: }
116: /*
117: PetscByteSwapLong - Swap bytes in a long
118: */
119: PetscErrorCode PetscByteSwapLong(long *buff,PetscInt n)
120: {
121: PetscInt i,j;
122: long tmp;
123: char *ptr1,*ptr2 = (char*)&tmp;
126: for (j=0; j<n; j++) {
127: ptr1 = (char*)(buff + j);
128: for (i=0; i<(PetscInt) sizeof(long); i++) ptr2[i] = ptr1[sizeof(long)-1-i];
129: for (i=0; i<(PetscInt) sizeof(long); i++) ptr1[i] = ptr2[i];
130: }
131: return(0);
132: }
133: /* --------------------------------------------------------- */
134: /*
135: PetscByteSwapReal - Swap bytes in a PetscReal
136: */
137: PetscErrorCode PetscByteSwapReal(PetscReal *buff,PetscInt n)
138: {
139: PetscInt i,j;
140: PetscReal tmp,*buff1 = (PetscReal*)buff;
141: char *ptr1,*ptr2 = (char*)&tmp;
144: for (j=0; j<n; j++) {
145: ptr1 = (char*)(buff1 + j);
146: for (i=0; i<(PetscInt) sizeof(PetscReal); i++) ptr2[i] = ptr1[sizeof(PetscReal)-1-i];
147: for (i=0; i<(PetscInt) sizeof(PetscReal); i++) ptr1[i] = ptr2[i];
148: }
149: return(0);
150: }
151: /* --------------------------------------------------------- */
152: /*
153: PetscByteSwapScalar - Swap bytes in a PetscScalar
154: The complex case is dealt with with an array of PetscReal, twice as long.
155: */
156: PetscErrorCode PetscByteSwapScalar(PetscScalar *buff,PetscInt n)
157: {
158: PetscInt i,j;
159: PetscReal tmp,*buff1 = (PetscReal*)buff;
160: char *ptr1,*ptr2 = (char*)&tmp;
163: #if defined(PETSC_USE_COMPLEX)
164: n *= 2;
165: #endif
166: for (j=0; j<n; j++) {
167: ptr1 = (char*)(buff1 + j);
168: for (i=0; i<(PetscInt) sizeof(PetscReal); i++) ptr2[i] = ptr1[sizeof(PetscReal)-1-i];
169: for (i=0; i<(PetscInt) sizeof(PetscReal); i++) ptr1[i] = ptr2[i];
170: }
171: return(0);
172: }
173: /* --------------------------------------------------------- */
174: /*
175: PetscByteSwapDouble - Swap bytes in a double
176: */
177: PetscErrorCode PetscByteSwapDouble(double *buff,PetscInt n)
178: {
179: PetscInt i,j;
180: double tmp,*buff1 = (double*)buff;
181: char *ptr1,*ptr2 = (char*)&tmp;
184: for (j=0; j<n; j++) {
185: ptr1 = (char*)(buff1 + j);
186: for (i=0; i<(PetscInt) sizeof(double); i++) ptr2[i] = ptr1[sizeof(double)-1-i];
187: for (i=0; i<(PetscInt) sizeof(double); i++) ptr1[i] = ptr2[i];
188: }
189: return(0);
190: }
192: /*
193: PetscByteSwapFloat - Swap bytes in a float
194: */
195: PetscErrorCode PetscByteSwapFloat(float *buff,PetscInt n)
196: {
197: PetscInt i,j;
198: float tmp,*buff1 = (float*)buff;
199: char *ptr1,*ptr2 = (char*)&tmp;
202: for (j=0; j<n; j++) {
203: ptr1 = (char*)(buff1 + j);
204: for (i=0; i<(PetscInt) sizeof(float); i++) ptr2[i] = ptr1[sizeof(float)-1-i];
205: for (i=0; i<(PetscInt) sizeof(float); i++) ptr1[i] = ptr2[i];
206: }
207: return(0);
208: }
210: PetscErrorCode PetscByteSwap(void *data,PetscDataType pdtype,PetscInt count)
211: {
215: if (pdtype == PETSC_INT) {PetscByteSwapInt((PetscInt*)data,count);}
216: else if (pdtype == PETSC_ENUM) {PetscByteSwapEnum((PetscEnum*)data,count);}
217: else if (pdtype == PETSC_BOOL) {PetscByteSwapBool((PetscBool*)data,count);}
218: else if (pdtype == PETSC_SCALAR) {PetscByteSwapScalar((PetscScalar*)data,count);}
219: else if (pdtype == PETSC_REAL) {PetscByteSwapReal((PetscReal*)data,count);}
220: else if (pdtype == PETSC_COMPLEX){PetscByteSwapReal((PetscReal*)data,2*count);}
221: else if (pdtype == PETSC_INT64) {PetscByteSwapInt64((PetscInt64*)data,count);}
222: else if (pdtype == PETSC_DOUBLE) {PetscByteSwapDouble((double*)data,count);}
223: else if (pdtype == PETSC_FLOAT) {PetscByteSwapFloat((float*)data,count);}
224: else if (pdtype == PETSC_SHORT) {PetscByteSwapShort((short*)data,count);}
225: else if (pdtype == PETSC_LONG) {PetscByteSwapLong((long*)data,count);}
226: return(0);
227: }
229: /*@C
230: PetscBinaryRead - Reads from a binary file.
232: Not Collective
234: Input Parameters:
235: + fd - the file descriptor
236: . num - the maximum number of items to read
237: - type - the type of items to read (PETSC_INT, PETSC_REAL, PETSC_SCALAR, etc.)
239: Output Parameters:
240: + data - the buffer
241: - count - the number of items read, optional
243: Level: developer
245: Notes:
246: If count is not provided and the number of items read is less than
247: the maximum number of items to read, then this routine errors.
249: PetscBinaryRead() uses byte swapping to work on all machines; the files
250: are written to file ALWAYS using big-endian ordering. On little-endian machines the numbers
251: are converted to the little-endian format when they are read in from the file.
252: When PETSc is ./configure with --with-64-bit-indices the integers are written to the
253: file as 64 bit integers, this means they can only be read back in when the option --with-64-bit-indices
254: is used.
256: .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscViewerBinaryGetDescriptor(), PetscBinarySynchronizedWrite(),
257: PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek()
258: @*/
259: PetscErrorCode PetscBinaryRead(int fd,void *data,PetscInt num,PetscInt *count,PetscDataType type)
260: {
261: size_t typesize, m = (size_t) num, n = 0, maxblock = 65536;
262: char *p = (char*)data;
263: #if defined(PETSC_USE_REAL___FLOAT128)
264: PetscBool readdouble = PETSC_FALSE;
265: double *pdouble;
266: #endif
267: void *ptmp = data;
268: char *fname = NULL;
269: PetscErrorCode ierr;
272: if (count) *count = 0;
273: if (num < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Trying to read a negative amount of data %D",num);
274: if (!num) return(0);
276: if (type == PETSC_FUNCTION) {
277: m = 64;
278: type = PETSC_CHAR;
279: fname = (char*)malloc(m*sizeof(char));
280: p = (char*)fname;
281: ptmp = (void*)fname;
282: if (!fname) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Cannot allocate space for function name");
283: }
284: if (type == PETSC_BIT_LOGICAL) m = PetscBTLength(m);
286: PetscDataTypeGetSize(type,&typesize);
288: #if defined(PETSC_USE_REAL___FLOAT128)
289: PetscOptionsGetBool(NULL,NULL,"-binary_read_double",&readdouble,NULL);
290: /* If using __float128 precision we still read in doubles from file */
291: if ((type == PETSC_REAL || type == PETSC_COMPLEX) && readdouble) {
292: PetscInt cnt = num * ((type == PETSC_REAL) ? 1 : 2);
293: PetscMalloc1(cnt,&pdouble);
294: p = (char*)pdouble;
295: typesize /= 2;
296: }
297: #endif
299: m *= typesize;
301: while (m) {
302: size_t len = (m < maxblock) ? m : maxblock;
303: int ret = (int)read(fd,p,len);
304: if (ret < 0 && errno == EINTR) continue;
305: if (!ret && len > 0) break; /* Proxy for EOF */
306: if (ret < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_READ,"Error reading from file, errno %d",errno);
307: m -= ret;
308: p += ret;
309: n += ret;
310: }
311: if (m && !count) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_READ,"Read past end of file");
313: num = (PetscInt)(n/typesize); /* Should we require `n % typesize == 0` ? */
314: if (count) *count = num; /* TODO: This is most likely wrong for PETSC_BIT_LOGICAL */
316: #if defined(PETSC_USE_REAL___FLOAT128)
317: if ((type == PETSC_REAL || type == PETSC_COMPLEX) && readdouble) {
318: PetscInt i, cnt = num * ((type == PETSC_REAL) ? 1 : 2);
319: PetscReal *preal = (PetscReal*)data;
320: if (!PetscBinaryBigEndian()) {PetscByteSwapDouble(pdouble,cnt);}
321: for (i=0; i<cnt; i++) preal[i] = pdouble[i];
322: PetscFree(pdouble);
323: return(0);
324: }
325: #endif
327: if (!PetscBinaryBigEndian()) {PetscByteSwap(ptmp,type,num);}
329: if (type == PETSC_FUNCTION) {
330: #if defined(PETSC_SERIALIZE_FUNCTIONS)
331: PetscDLSym(NULL,fname,(void**)data);
332: #else
333: *(void**)data = NULL;
334: #endif
335: free(fname);
336: }
337: return(0);
338: }
340: /*@C
341: PetscBinaryWrite - Writes to a binary file.
343: Not Collective
345: Input Parameters:
346: + fd - the file
347: . p - the buffer
348: . n - the number of items to write
349: - type - the type of items to read (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)
351: Level: advanced
353: Notes:
354: PetscBinaryWrite() uses byte swapping to work on all machines; the files
355: are written using big-endian ordering to the file. On little-endian machines the numbers
356: are converted to the big-endian format when they are written to disk.
357: When PETSc is ./configure with --with-64-bit-indices the integers are written to the
358: file as 64 bit integers, this means they can only be read back in when the option --with-64-bit-indices
359: is used.
361: If running with __float128 precision the output is in __float128 unless one uses the -binary_write_double option
363: The Buffer p should be read-write buffer, and not static data.
364: This way, byte-swapping is done in-place, and then the buffer is
365: written to the file.
367: This routine restores the original contents of the buffer, after
368: it is written to the file. This is done by byte-swapping in-place
369: the second time.
371: Because byte-swapping may be done on the values in data it cannot be declared const
374: .seealso: PetscBinaryRead(), PetscBinaryOpen(), PetscBinaryClose(), PetscViewerBinaryGetDescriptor(), PetscBinarySynchronizedWrite(),
375: PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek()
376: @*/
377: PetscErrorCode PetscBinaryWrite(int fd,const void *p,PetscInt n,PetscDataType type)
378: {
379: const char *pp = (char*)p;
380: int err,wsize;
381: size_t m = (size_t)n,maxblock=65536;
383: const void *ptmp = p;
384: char *fname = NULL;
385: #if defined(PETSC_USE_REAL___FLOAT128)
386: PetscBool writedouble = PETSC_FALSE;
387: double *ppp;
388: PetscReal *pv;
389: PetscInt i;
390: #endif
391: PetscDataType wtype = type;
394: if (n < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Trying to write a negative amount of data %D",n);
395: if (!n) return(0);
397: if (type == PETSC_FUNCTION) {
398: #if defined(PETSC_SERIALIZE_FUNCTIONS)
399: const char *fnametmp;
400: #endif
401: m = 64;
402: fname = (char*)malloc(m*sizeof(char));
403: if (!fname) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Cannot allocate space for function name");
404: #if defined(PETSC_SERIALIZE_FUNCTIONS)
405: if (n > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Can only binary view a single function at a time");
406: PetscFPTFind(*(void**)p,&fnametmp);
407: PetscStrncpy(fname,fnametmp,m);
408: #else
409: PetscStrncpy(fname,"",m);
410: #endif
411: wtype = PETSC_CHAR;
412: pp = (char*)fname;
413: ptmp = (void*)fname;
414: }
416: #if defined(PETSC_USE_REAL___FLOAT128)
417: PetscOptionsGetBool(NULL,NULL,"-binary_write_double",&writedouble,NULL);
418: /* If using __float128 precision we still write in doubles to file */
419: if ((type == PETSC_SCALAR || type == PETSC_REAL) && writedouble) {
420: wtype = PETSC_DOUBLE;
421: PetscMalloc1(n,&ppp);
422: pv = (PetscReal*)pp;
423: for (i=0; i<n; i++) {
424: ppp[i] = (double) pv[i];
425: }
426: pp = (char*)ppp;
427: ptmp = (char*)ppp;
428: }
429: #endif
431: if (wtype == PETSC_INT) m *= sizeof(PetscInt);
432: else if (wtype == PETSC_SCALAR) m *= sizeof(PetscScalar);
433: else if (wtype == PETSC_REAL) m *= sizeof(PetscReal);
434: else if (wtype == PETSC_DOUBLE) m *= sizeof(double);
435: else if (wtype == PETSC_FLOAT) m *= sizeof(float);
436: else if (wtype == PETSC_SHORT) m *= sizeof(short);
437: else if (wtype == PETSC_LONG) m *= sizeof(long);
438: else if (wtype == PETSC_CHAR) m *= sizeof(char);
439: else if (wtype == PETSC_ENUM) m *= sizeof(PetscEnum);
440: else if (wtype == PETSC_BOOL) m *= sizeof(PetscBool);
441: else if (wtype == PETSC_INT64) m *= sizeof(PetscInt64);
442: else if (wtype == PETSC_BIT_LOGICAL) m = PetscBTLength(m)*sizeof(char);
443: else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown type");
445: if (!PetscBinaryBigEndian()) {PetscByteSwap((void*)ptmp,wtype,n);}
447: while (m) {
448: wsize = (m < maxblock) ? m : maxblock;
449: err = write(fd,pp,wsize);
450: if (err < 0 && errno == EINTR) continue;
451: if (err != wsize) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_FILE_WRITE,"Error writing to file total size %d err %d wsize %d",(int)n,(int)err,(int)wsize);
452: m -= wsize;
453: pp += wsize;
454: }
456: if (!PetscBinaryBigEndian()) {PetscByteSwap((void*)ptmp,wtype,n);}
458: if (type == PETSC_FUNCTION) {
459: free(fname);
460: }
461: #if defined(PETSC_USE_REAL___FLOAT128)
462: if ((type == PETSC_SCALAR || type == PETSC_REAL) && writedouble) {
463: PetscFree(ppp);
464: }
465: #endif
466: return(0);
467: }
469: /*@C
470: PetscBinaryOpen - Opens a PETSc binary file.
472: Not Collective
474: Input Parameters:
475: + name - filename
476: - mode - open mode of binary file, one of FILE_MODE_READ, FILE_MODE_WRITE, FILE_MODE_APPEND
478: Output Parameter:
479: . fd - the file
481: Level: advanced
484: Notes:
485: Files access with PetscBinaryRead() and PetscBinaryWrite() are ALWAYS written in
486: big-endian format. This means the file can be accessed using PetscBinaryOpen() and
487: PetscBinaryRead() and PetscBinaryWrite() on any machine.
489: .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscFileMode, PetscViewerFileSetMode(), PetscViewerBinaryGetDescriptor(),
490: PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek()
492: @*/
493: PetscErrorCode PetscBinaryOpen(const char name[],PetscFileMode mode,int *fd)
494: {
496: switch (mode) {
497: case FILE_MODE_READ: *fd = open(name,O_BINARY|O_RDONLY,0); break;
498: case FILE_MODE_WRITE: *fd = open(name,O_BINARY|O_WRONLY|O_CREAT|O_TRUNC,0666); break;
499: case FILE_MODE_APPEND: *fd = open(name,O_BINARY|O_WRONLY|O_APPEND,0); break;
500: default: SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unsupported file mode %s",PetscFileModes[mode]);
501: }
502: if (*fd == -1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file %s for %s: %s",name,PetscFileModes[mode]);
503: return(0);
504: }
506: /*@
507: PetscBinaryClose - Closes a PETSc binary file.
509: Not Collective
511: Output Parameter:
512: . fd - the file
514: Level: advanced
516: .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
517: PetscBinarySynchronizedSeek()
518: @*/
519: PetscErrorCode PetscBinaryClose(int fd)
520: {
522: if (close(fd)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"close() failed on file descriptor");
523: return(0);
524: }
527: /*@C
528: PetscBinarySeek - Moves the file pointer on a PETSc binary file.
530: Not Collective
532: Input Parameters:
533: + fd - the file
534: . off - number of bytes to move. Use PETSC_BINARY_INT_SIZE, PETSC_BINARY_SCALAR_SIZE,
535: etc. in your calculation rather than sizeof() to compute byte lengths.
536: - whence - if PETSC_BINARY_SEEK_SET then off is an absolute location in the file
537: if PETSC_BINARY_SEEK_CUR then off is an offset from the current location
538: if PETSC_BINARY_SEEK_END then off is an offset from the end of file
540: Output Parameter:
541: . offset - new offset in file
543: Level: developer
545: Notes:
546: Integers are stored on the file as 32 long, regardless of whether
547: they are stored in the machine as 32 or 64, this means the same
548: binary file may be read on any machine. Hence you CANNOT use sizeof()
549: to determine the offset or location.
552: .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
553: PetscBinarySynchronizedSeek()
554: @*/
555: PetscErrorCode PetscBinarySeek(int fd,off_t off,PetscBinarySeekType whence,off_t *offset)
556: {
557: int iwhence = 0;
560: if (whence == PETSC_BINARY_SEEK_SET) iwhence = SEEK_SET;
561: else if (whence == PETSC_BINARY_SEEK_CUR) iwhence = SEEK_CUR;
562: else if (whence == PETSC_BINARY_SEEK_END) iwhence = SEEK_END;
563: else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown seek location");
564: #if defined(PETSC_HAVE_LSEEK)
565: *offset = lseek(fd,off,iwhence);
566: #elif defined(PETSC_HAVE__LSEEK)
567: *offset = _lseek(fd,(long)off,iwhence);
568: #else
569: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS,"System does not have a way of seeking on a file");
570: #endif
571: return(0);
572: }
574: /*@C
575: PetscBinarySynchronizedRead - Reads from a binary file.
577: Collective
579: Input Parameters:
580: + comm - the MPI communicator
581: . fd - the file descriptor
582: . num - the maximum number of items to read
583: - type - the type of items to read (PETSC_INT, PETSC_REAL, PETSC_SCALAR, etc.)
585: Output Parameters:
586: + data - the buffer
587: - count - the number of items read, optional
589: Level: developer
591: Notes:
592: Does a PetscBinaryRead() followed by an MPI_Bcast()
594: If count is not provided and the number of items read is less than
595: the maximum number of items to read, then this routine errors.
597: PetscBinarySynchronizedRead() uses byte swapping to work on all machines.
598: Integers are stored on the file as 32 long, regardless of whether
599: they are stored in the machine as 32 or 64, this means the same
600: binary file may be read on any machine.
603: .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscBinaryRead(), PetscBinarySynchronizedWrite(),
604: PetscBinarySynchronizedSeek()
605: @*/
606: PetscErrorCode PetscBinarySynchronizedRead(MPI_Comm comm,int fd,void *data,PetscInt num,PetscInt *count,PetscDataType type)
607: {
609: PetscMPIInt rank;
610: MPI_Datatype mtype;
611: PetscInt ibuf[2] = {0, 0};
612: char *fname = NULL;
613: void *fptr = NULL;
616: if (type == PETSC_FUNCTION) {
617: num = 64;
618: type = PETSC_CHAR;
619: fname = (char*)malloc(num*sizeof(char));
620: fptr = data;
621: data = (void*)fname;
622: if (!fname) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Cannot allocate space for function name");
623: }
625: MPI_Comm_rank(comm,&rank);
626: if (!rank) {
627: ibuf[0] = PetscBinaryRead(fd,data,num,count?&ibuf[1]:NULL,type);
628: }
629: MPI_Bcast(ibuf,2,MPIU_INT,0,comm);
630: (PetscErrorCode)ibuf[0];
631: PetscDataTypeToMPIDataType(type,&mtype);
632: MPI_Bcast(data,count?ibuf[1]:num,mtype,0,comm);
633: if (count) *count = ibuf[1];
635: if (type == PETSC_FUNCTION) {
636: #if defined(PETSC_SERIALIZE_FUNCTIONS)
637: PetscDLLibrarySym(PETSC_COMM_SELF,&PetscDLLibrariesLoaded,NULL,fname,(void**)fptr);
638: #else
639: *(void**)fptr = NULL;
640: #endif
641: free(fname);
642: }
643: return(0);
644: }
646: /*@C
647: PetscBinarySynchronizedWrite - writes to a binary file.
649: Collective
651: Input Parameters:
652: + comm - the MPI communicator
653: . fd - the file
654: . n - the number of items to write
655: . p - the buffer
656: - type - the type of items to write (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)
658: Level: developer
660: Notes:
661: Process 0 does a PetscBinaryWrite()
663: PetscBinarySynchronizedWrite() uses byte swapping to work on all machines.
664: Integers are stored on the file as 32 long, regardless of whether
665: they are stored in the machine as 32 or 64, this means the same
666: binary file may be read on any machine.
668: Notes:
669: because byte-swapping may be done on the values in data it cannot be declared const
671: WARNING: This is NOT like PetscSynchronizedFPrintf()! This routine ignores calls on all but process 0,
672: while PetscSynchronizedFPrintf() has all processes print their strings in order.
675: .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscBinaryRead(), PetscBinarySynchronizedRead(),
676: PetscBinarySynchronizedSeek()
677: @*/
678: PetscErrorCode PetscBinarySynchronizedWrite(MPI_Comm comm,int fd,const void *p,PetscInt n,PetscDataType type)
679: {
681: PetscMPIInt rank;
684: MPI_Comm_rank(comm,&rank);
685: if (!rank) {
686: PetscBinaryWrite(fd,p,n,type);
687: }
688: return(0);
689: }
691: /*@C
692: PetscBinarySynchronizedSeek - Moves the file pointer on a PETSc binary file.
695: Input Parameters:
696: + fd - the file
697: . whence - if PETSC_BINARY_SEEK_SET then size is an absolute location in the file
698: if PETSC_BINARY_SEEK_CUR then size is offset from current location
699: if PETSC_BINARY_SEEK_END then size is offset from end of file
700: - off - number of bytes to move. Use PETSC_BINARY_INT_SIZE, PETSC_BINARY_SCALAR_SIZE,
701: etc. in your calculation rather than sizeof() to compute byte lengths.
703: Output Parameter:
704: . offset - new offset in file
706: Level: developer
708: Notes:
709: Integers are stored on the file as 32 long, regardless of whether
710: they are stored in the machine as 32 or 64, this means the same
711: binary file may be read on any machine. Hence you CANNOT use sizeof()
712: to determine the offset or location.
715: .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
716: PetscBinarySynchronizedSeek()
717: @*/
718: PetscErrorCode PetscBinarySynchronizedSeek(MPI_Comm comm,int fd,off_t off,PetscBinarySeekType whence,off_t *offset)
719: {
721: PetscMPIInt rank;
724: MPI_Comm_rank(comm,&rank);
725: if (!rank) {
726: PetscBinarySeek(fd,off,whence,offset);
727: }
728: return(0);
729: }
731: #if defined(PETSC_HAVE_MPIIO)
733: #if defined(PETSC_USE_PETSC_MPI_EXTERNAL32)
734: /*
735: MPICH does not provide the external32 representation for MPI_File_set_view() so we need to provide the functions.
736: These are set into MPI in PetscInitialize() via MPI_Register_datarep()
738: Note I use PetscMPIInt for the MPI error codes since that is what MPI uses (instead of the standard PetscErrorCode)
740: The next three routines are not used because MPICH does not support their use
742: */
743: PETSC_EXTERN PetscMPIInt PetscDataRep_extent_fn(MPI_Datatype datatype,MPI_Aint *file_extent,void *extra_state)
744: {
745: MPI_Aint ub;
746: PetscMPIInt ierr;
748: MPI_Type_get_extent(datatype,&ub,file_extent);
749: return ierr;
750: }
752: PETSC_EXTERN PetscMPIInt PetscDataRep_read_conv_fn(void *userbuf, MPI_Datatype datatype,PetscMPIInt count,void *filebuf, MPI_Offset position,void *extra_state)
753: {
754: PetscDataType pdtype;
755: PetscMPIInt ierr;
756: size_t dsize;
758: PetscMPIDataTypeToPetscDataType(datatype,&pdtype);
759: PetscDataTypeGetSize(pdtype,&dsize);
761: /* offset is given in units of MPI_Datatype */
762: userbuf = ((char*)userbuf) + dsize*position;
764: PetscMemcpy(userbuf,filebuf,count*dsize);
765: if (!PetscBinaryBigEndian()) {PetscByteSwap(userbuf,pdtype,count);}
766: return ierr;
767: }
769: PetscMPIInt PetscDataRep_write_conv_fn(void *userbuf, MPI_Datatype datatype,PetscMPIInt count,void *filebuf, MPI_Offset position,void *extra_state)
770: {
771: PetscDataType pdtype;
772: PetscMPIInt ierr;
773: size_t dsize;
775: PetscMPIDataTypeToPetscDataType(datatype,&pdtype);
776: PetscDataTypeGetSize(pdtype,&dsize);
778: /* offset is given in units of MPI_Datatype */
779: userbuf = ((char*)userbuf) + dsize*position;
781: PetscMemcpy(filebuf,userbuf,count*dsize);
782: if (!PetscBinaryBigEndian()) {PetscByteSwap(filebuf,pdtype,count);}
783: return ierr;
784: }
785: #endif
787: PetscErrorCode MPIU_File_write_all(MPI_File fd,void *data,PetscMPIInt cnt,MPI_Datatype dtype,MPI_Status *status)
788: {
789: PetscDataType pdtype;
794: PetscMPIDataTypeToPetscDataType(dtype,&pdtype);
795: if (!PetscBinaryBigEndian()) {PetscByteSwap(data,pdtype,cnt);}
796: MPI_File_write_all(fd,data,cnt,dtype,status);
797: if (!PetscBinaryBigEndian()) {PetscByteSwap(data,pdtype,cnt);}
798: return(0);
799: }
801: PetscErrorCode MPIU_File_read_all(MPI_File fd,void *data,PetscMPIInt cnt,MPI_Datatype dtype,MPI_Status *status)
802: {
803: PetscDataType pdtype;
807: PetscMPIDataTypeToPetscDataType(dtype,&pdtype);
808: MPI_File_read_all(fd,data,cnt,dtype,status);
809: if (!PetscBinaryBigEndian()) {PetscByteSwap(data,pdtype,cnt);}
810: return(0);
811: }
813: PetscErrorCode MPIU_File_write_at(MPI_File fd,MPI_Offset off,void *data,PetscMPIInt cnt,MPI_Datatype dtype,MPI_Status *status)
814: {
815: PetscDataType pdtype;
820: PetscMPIDataTypeToPetscDataType(dtype,&pdtype);
821: if (!PetscBinaryBigEndian()) {PetscByteSwap(data,pdtype,cnt);}
822: MPI_File_write_at(fd,off,data,cnt,dtype,status);
823: if (!PetscBinaryBigEndian()) {PetscByteSwap(data,pdtype,cnt);}
824: return(0);
825: }
827: PetscErrorCode MPIU_File_read_at(MPI_File fd,MPI_Offset off,void *data,PetscMPIInt cnt,MPI_Datatype dtype,MPI_Status *status)
828: {
829: PetscDataType pdtype;
833: PetscMPIDataTypeToPetscDataType(dtype,&pdtype);
834: MPI_File_read_at(fd,off,data,cnt,dtype,status);
835: if (!PetscBinaryBigEndian()) {PetscByteSwap(data,pdtype,cnt);}
836: return(0);
837: }
839: PetscErrorCode MPIU_File_write_at_all(MPI_File fd,MPI_Offset off,void *data,PetscMPIInt cnt,MPI_Datatype dtype,MPI_Status *status)
840: {
841: PetscDataType pdtype;
846: PetscMPIDataTypeToPetscDataType(dtype,&pdtype);
847: if (!PetscBinaryBigEndian()) {PetscByteSwap(data,pdtype,cnt);}
848: MPI_File_write_at_all(fd,off,data,cnt,dtype,status);
849: if (!PetscBinaryBigEndian()) {PetscByteSwap(data,pdtype,cnt);}
850: return(0);
851: }
853: PetscErrorCode MPIU_File_read_at_all(MPI_File fd,MPI_Offset off,void *data,PetscMPIInt cnt,MPI_Datatype dtype,MPI_Status *status)
854: {
855: PetscDataType pdtype;
859: PetscMPIDataTypeToPetscDataType(dtype,&pdtype);
860: MPI_File_read_at_all(fd,off,data,cnt,dtype,status);
861: if (!PetscBinaryBigEndian()) {PetscByteSwap(data,pdtype,cnt);}
862: return(0);
863: }
865: #endif