Actual source code: sysio.c
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
373: .seealso: PetscBinaryRead(), PetscBinaryOpen(), PetscBinaryClose(), PetscViewerBinaryGetDescriptor(), PetscBinarySynchronizedWrite(),
374: PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek()
375: @*/
376: PetscErrorCode PetscBinaryWrite(int fd,const void *p,PetscInt n,PetscDataType type)
377: {
378: const char *pp = (char*)p;
379: int err,wsize;
380: size_t m = (size_t)n,maxblock=65536;
382: const void *ptmp = p;
383: char *fname = NULL;
384: #if defined(PETSC_USE_REAL___FLOAT128)
385: PetscBool writedouble = PETSC_FALSE;
386: double *ppp;
387: PetscReal *pv;
388: PetscInt i;
389: #endif
390: PetscDataType wtype = type;
393: if (n < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Trying to write a negative amount of data %D",n);
394: if (!n) return(0);
396: if (type == PETSC_FUNCTION) {
397: #if defined(PETSC_SERIALIZE_FUNCTIONS)
398: const char *fnametmp;
399: #endif
400: m = 64;
401: fname = (char*)malloc(m*sizeof(char));
402: if (!fname) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Cannot allocate space for function name");
403: #if defined(PETSC_SERIALIZE_FUNCTIONS)
404: if (n > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Can only binary view a single function at a time");
405: PetscFPTFind(*(void**)p,&fnametmp);
406: PetscStrncpy(fname,fnametmp,m);
407: #else
408: PetscStrncpy(fname,"",m);
409: #endif
410: wtype = PETSC_CHAR;
411: pp = (char*)fname;
412: ptmp = (void*)fname;
413: }
415: #if defined(PETSC_USE_REAL___FLOAT128)
416: PetscOptionsGetBool(NULL,NULL,"-binary_write_double",&writedouble,NULL);
417: /* If using __float128 precision we still write in doubles to file */
418: if ((type == PETSC_SCALAR || type == PETSC_REAL || type == PETSC_COMPLEX) && writedouble) {
419: wtype = PETSC_DOUBLE;
420: PetscMalloc1(n,&ppp);
421: pv = (PetscReal*)pp;
422: for (i=0; i<n; i++) {
423: ppp[i] = (double) pv[i];
424: }
425: pp = (char*)ppp;
426: ptmp = (char*)ppp;
427: }
428: #endif
430: if (wtype == PETSC_INT) m *= sizeof(PetscInt);
431: else if (wtype == PETSC_SCALAR) m *= sizeof(PetscScalar);
432: #if defined(PETSC_HAVE_COMPLEX)
433: else if (wtype == PETSC_COMPLEX) m *= sizeof(PetscComplex);
434: #endif
435: else if (wtype == PETSC_REAL) m *= sizeof(PetscReal);
436: else if (wtype == PETSC_DOUBLE) m *= sizeof(double);
437: else if (wtype == PETSC_FLOAT) m *= sizeof(float);
438: else if (wtype == PETSC_SHORT) m *= sizeof(short);
439: else if (wtype == PETSC_LONG) m *= sizeof(long);
440: else if (wtype == PETSC_CHAR) m *= sizeof(char);
441: else if (wtype == PETSC_ENUM) m *= sizeof(PetscEnum);
442: else if (wtype == PETSC_BOOL) m *= sizeof(PetscBool);
443: else if (wtype == PETSC_INT64) m *= sizeof(PetscInt64);
444: else if (wtype == PETSC_BIT_LOGICAL) m = PetscBTLength(m)*sizeof(char);
445: else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown type");
447: if (!PetscBinaryBigEndian()) {PetscByteSwap((void*)ptmp,wtype,n);}
449: while (m) {
450: wsize = (m < maxblock) ? m : maxblock;
451: err = write(fd,pp,wsize);
452: if (err < 0 && errno == EINTR) continue;
453: 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);
454: m -= wsize;
455: pp += wsize;
456: }
458: if (!PetscBinaryBigEndian()) {PetscByteSwap((void*)ptmp,wtype,n);}
460: if (type == PETSC_FUNCTION) {
461: free(fname);
462: }
463: #if defined(PETSC_USE_REAL___FLOAT128)
464: if ((type == PETSC_SCALAR || type == PETSC_REAL || type == PETSC_COMPLEX) && writedouble) {
465: PetscFree(ppp);
466: }
467: #endif
468: return(0);
469: }
471: /*@C
472: PetscBinaryOpen - Opens a PETSc binary file.
474: Not Collective
476: Input Parameters:
477: + name - filename
478: - mode - open mode of binary file, one of FILE_MODE_READ, FILE_MODE_WRITE, FILE_MODE_APPEND
480: Output Parameter:
481: . fd - the file
483: Level: advanced
485: Notes:
486: Files access with PetscBinaryRead() and PetscBinaryWrite() are ALWAYS written in
487: big-endian format. This means the file can be accessed using PetscBinaryOpen() and
488: PetscBinaryRead() and PetscBinaryWrite() on any machine.
490: .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscFileMode, PetscViewerFileSetMode(), PetscViewerBinaryGetDescriptor(),
491: PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek()
493: @*/
494: PetscErrorCode PetscBinaryOpen(const char name[],PetscFileMode mode,int *fd)
495: {
497: switch (mode) {
498: case FILE_MODE_READ: *fd = open(name,O_BINARY|O_RDONLY,0); break;
499: case FILE_MODE_WRITE: *fd = open(name,O_BINARY|O_WRONLY|O_CREAT|O_TRUNC,0666); break;
500: case FILE_MODE_APPEND: *fd = open(name,O_BINARY|O_WRONLY|O_APPEND,0); break;
501: default: SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unsupported file mode %s",PetscFileModes[mode]);
502: }
503: if (*fd == -1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file %s for %s: %s",name,PetscFileModes[mode]);
504: return(0);
505: }
507: /*@
508: PetscBinaryClose - Closes a PETSc binary file.
510: Not Collective
512: Output Parameter:
513: . fd - the file
515: Level: advanced
517: .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
518: PetscBinarySynchronizedSeek()
519: @*/
520: PetscErrorCode PetscBinaryClose(int fd)
521: {
523: if (close(fd)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"close() failed on file descriptor");
524: return(0);
525: }
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.
551: .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
552: PetscBinarySynchronizedSeek()
553: @*/
554: PetscErrorCode PetscBinarySeek(int fd,off_t off,PetscBinarySeekType whence,off_t *offset)
555: {
556: int iwhence = 0;
559: if (whence == PETSC_BINARY_SEEK_SET) iwhence = SEEK_SET;
560: else if (whence == PETSC_BINARY_SEEK_CUR) iwhence = SEEK_CUR;
561: else if (whence == PETSC_BINARY_SEEK_END) iwhence = SEEK_END;
562: else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown seek location");
563: #if defined(PETSC_HAVE_LSEEK)
564: *offset = lseek(fd,off,iwhence);
565: #elif defined(PETSC_HAVE__LSEEK)
566: *offset = _lseek(fd,(long)off,iwhence);
567: #else
568: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS,"System does not have a way of seeking on a file");
569: #endif
570: return(0);
571: }
573: /*@C
574: PetscBinarySynchronizedRead - Reads from a binary file.
576: Collective
578: Input Parameters:
579: + comm - the MPI communicator
580: . fd - the file descriptor
581: . num - the maximum number of items to read
582: - type - the type of items to read (PETSC_INT, PETSC_REAL, PETSC_SCALAR, etc.)
584: Output Parameters:
585: + data - the buffer
586: - count - the number of items read, optional
588: Level: developer
590: Notes:
591: Does a PetscBinaryRead() followed by an MPI_Bcast()
593: If count is not provided and the number of items read is less than
594: the maximum number of items to read, then this routine errors.
596: PetscBinarySynchronizedRead() uses byte swapping to work on all machines.
597: Integers are stored on the file as 32 long, regardless of whether
598: they are stored in the machine as 32 or 64, this means the same
599: binary file may be read on any machine.
601: .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscBinaryRead(), PetscBinarySynchronizedWrite(),
602: PetscBinarySynchronizedSeek()
603: @*/
604: PetscErrorCode PetscBinarySynchronizedRead(MPI_Comm comm,int fd,void *data,PetscInt num,PetscInt *count,PetscDataType type)
605: {
607: PetscMPIInt rank,size;
608: MPI_Datatype mtype;
609: PetscInt ibuf[2] = {0, 0};
610: char *fname = NULL;
611: void *fptr = NULL;
614: if (type == PETSC_FUNCTION) {
615: num = 64;
616: type = PETSC_CHAR;
617: fname = (char*)malloc(num*sizeof(char));
618: fptr = data;
619: data = (void*)fname;
620: if (!fname) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Cannot allocate space for function name");
621: }
623: MPI_Comm_rank(comm,&rank);
624: MPI_Comm_size(comm,&size);
625: if (rank == 0) {
626: ibuf[0] = PetscBinaryRead(fd,data,num,count?&ibuf[1]:NULL,type);
627: }
628: MPI_Bcast(ibuf,2,MPIU_INT,0,comm);
629: (PetscErrorCode)ibuf[0];
631: /* 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 */
632: if (size > 1) {
633: PetscDataTypeToMPIDataType(type,&mtype);
634: MPI_Bcast(data,count?ibuf[1]:num,mtype,0,comm);
635: }
636: if (count) *count = ibuf[1];
638: if (type == PETSC_FUNCTION) {
639: #if defined(PETSC_SERIALIZE_FUNCTIONS)
640: PetscDLLibrarySym(PETSC_COMM_SELF,&PetscDLLibrariesLoaded,NULL,fname,(void**)fptr);
641: #else
642: *(void**)fptr = NULL;
643: #endif
644: free(fname);
645: }
646: return(0);
647: }
649: /*@C
650: PetscBinarySynchronizedWrite - writes to a binary file.
652: Collective
654: Input Parameters:
655: + comm - the MPI communicator
656: . fd - the file
657: . n - the number of items to write
658: . p - the buffer
659: - type - the type of items to write (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)
661: Level: developer
663: Notes:
664: Process 0 does a PetscBinaryWrite()
666: PetscBinarySynchronizedWrite() uses byte swapping to work on all machines.
667: Integers are stored on the file as 32 long, regardless of whether
668: they are stored in the machine as 32 or 64, this means the same
669: binary file may be read on any machine.
671: Notes:
672: because byte-swapping may be done on the values in data it cannot be declared const
674: WARNING: This is NOT like PetscSynchronizedFPrintf()! This routine ignores calls on all but process 0,
675: while PetscSynchronizedFPrintf() has all processes print their strings in order.
677: .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscBinaryRead(), PetscBinarySynchronizedRead(),
678: PetscBinarySynchronizedSeek()
679: @*/
680: PetscErrorCode PetscBinarySynchronizedWrite(MPI_Comm comm,int fd,const void *p,PetscInt n,PetscDataType type)
681: {
683: PetscMPIInt rank;
686: MPI_Comm_rank(comm,&rank);
687: if (rank == 0) {
688: PetscBinaryWrite(fd,p,n,type);
689: }
690: return(0);
691: }
693: /*@C
694: PetscBinarySynchronizedSeek - Moves the file pointer on a PETSc binary file.
696: Input Parameters:
697: + fd - the file
698: . whence - if PETSC_BINARY_SEEK_SET then size is an absolute location in the file
699: if PETSC_BINARY_SEEK_CUR then size is offset from current location
700: if PETSC_BINARY_SEEK_END then size is offset from end of file
701: - off - number of bytes to move. Use PETSC_BINARY_INT_SIZE, PETSC_BINARY_SCALAR_SIZE,
702: etc. in your calculation rather than sizeof() to compute byte lengths.
704: Output Parameter:
705: . offset - new offset in file
707: Level: developer
709: Notes:
710: Integers are stored on the file as 32 long, regardless of whether
711: they are stored in the machine as 32 or 64, this means the same
712: binary file may be read on any machine. Hence you CANNOT use sizeof()
713: 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 == 0) {
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;
793: PetscMPIDataTypeToPetscDataType(dtype,&pdtype);
794: if (!PetscBinaryBigEndian()) {PetscByteSwap(data,pdtype,cnt);}
795: MPI_File_write_all(fd,data,cnt,dtype,status);
796: if (!PetscBinaryBigEndian()) {PetscByteSwap(data,pdtype,cnt);}
797: return(0);
798: }
800: PetscErrorCode MPIU_File_read_all(MPI_File fd,void *data,PetscMPIInt cnt,MPI_Datatype dtype,MPI_Status *status)
801: {
802: PetscDataType pdtype;
806: PetscMPIDataTypeToPetscDataType(dtype,&pdtype);
807: MPI_File_read_all(fd,data,cnt,dtype,status);
808: if (!PetscBinaryBigEndian()) {PetscByteSwap(data,pdtype,cnt);}
809: return(0);
810: }
812: PetscErrorCode MPIU_File_write_at(MPI_File fd,MPI_Offset off,void *data,PetscMPIInt cnt,MPI_Datatype dtype,MPI_Status *status)
813: {
814: PetscDataType pdtype;
818: PetscMPIDataTypeToPetscDataType(dtype,&pdtype);
819: if (!PetscBinaryBigEndian()) {PetscByteSwap(data,pdtype,cnt);}
820: MPI_File_write_at(fd,off,data,cnt,dtype,status);
821: if (!PetscBinaryBigEndian()) {PetscByteSwap(data,pdtype,cnt);}
822: return(0);
823: }
825: PetscErrorCode MPIU_File_read_at(MPI_File fd,MPI_Offset off,void *data,PetscMPIInt cnt,MPI_Datatype dtype,MPI_Status *status)
826: {
827: PetscDataType pdtype;
831: PetscMPIDataTypeToPetscDataType(dtype,&pdtype);
832: MPI_File_read_at(fd,off,data,cnt,dtype,status);
833: if (!PetscBinaryBigEndian()) {PetscByteSwap(data,pdtype,cnt);}
834: return(0);
835: }
837: PetscErrorCode MPIU_File_write_at_all(MPI_File fd,MPI_Offset off,void *data,PetscMPIInt cnt,MPI_Datatype dtype,MPI_Status *status)
838: {
839: PetscDataType pdtype;
843: PetscMPIDataTypeToPetscDataType(dtype,&pdtype);
844: if (!PetscBinaryBigEndian()) {PetscByteSwap(data,pdtype,cnt);}
845: MPI_File_write_at_all(fd,off,data,cnt,dtype,status);
846: if (!PetscBinaryBigEndian()) {PetscByteSwap(data,pdtype,cnt);}
847: return(0);
848: }
850: PetscErrorCode MPIU_File_read_at_all(MPI_File fd,MPI_Offset off,void *data,PetscMPIInt cnt,MPI_Datatype dtype,MPI_Status *status)
851: {
852: PetscDataType pdtype;
856: PetscMPIDataTypeToPetscDataType(dtype,&pdtype);
857: MPI_File_read_at_all(fd,off,data,cnt,dtype,status);
858: if (!PetscBinaryBigEndian()) {PetscByteSwap(data,pdtype,cnt);}
859: return(0);
860: }
862: #endif