Actual source code: sysio.c
petsc-3.12.5 2020-03-29
2: /*
3: This file contains simple binary read/write routines.
4: */
6: #include <petscsys.h>
7: #include <errno.h>
8: #include <fcntl.h>
9: #if defined(PETSC_HAVE_UNISTD_H)
10: #include <unistd.h>
11: #endif
12: #if defined(PETSC_HAVE_IO_H)
13: #include <io.h>
14: #endif
15: #include <petscbt.h>
17: const char *const PetscFileModes[] = {"READ","WRITE","APPEND","UPDATE","APPEND_UPDATE","PetscFileMode","PETSC_FILE_",0};
19: /* --------------------------------------------------------- */
20: /*
21: PetscByteSwapEnum - Swap bytes in a PETSc Enum
23: */
24: PetscErrorCode PetscByteSwapEnum(PetscEnum *buff,PetscInt n)
25: {
26: PetscInt i,j;
27: PetscEnum tmp = ENUM_DUMMY;
28: char *ptr1,*ptr2 = (char*)&tmp;
31: for (j=0; j<n; j++) {
32: ptr1 = (char*)(buff + j);
33: for (i=0; i<(PetscInt)sizeof(PetscEnum); i++) ptr2[i] = ptr1[sizeof(PetscEnum)-1-i];
34: for (i=0; i<(PetscInt)sizeof(PetscEnum); i++) ptr1[i] = ptr2[i];
35: }
36: return(0);
37: }
39: /*
40: PetscByteSwapBool - Swap bytes in a PETSc Bool
42: */
43: PetscErrorCode PetscByteSwapBool(PetscBool *buff,PetscInt n)
44: {
45: PetscInt i,j;
46: PetscBool tmp = PETSC_FALSE;
47: char *ptr1,*ptr2 = (char*)&tmp;
50: for (j=0; j<n; j++) {
51: ptr1 = (char*)(buff + j);
52: for (i=0; i<(PetscInt)sizeof(PetscBool); i++) ptr2[i] = ptr1[sizeof(PetscBool)-1-i];
53: for (i=0; i<(PetscInt)sizeof(PetscBool); i++) ptr1[i] = ptr2[i];
54: }
55: return(0);
56: }
58: /*
59: PetscByteSwapInt - Swap bytes in a PETSc integer (which may be 32 or 64 bits)
61: */
62: PetscErrorCode PetscByteSwapInt(PetscInt *buff,PetscInt n)
63: {
64: PetscInt i,j,tmp = 0;
65: char *ptr1,*ptr2 = (char*)&tmp;
68: for (j=0; j<n; j++) {
69: ptr1 = (char*)(buff + j);
70: for (i=0; i<(PetscInt)sizeof(PetscInt); i++) ptr2[i] = ptr1[sizeof(PetscInt)-1-i];
71: for (i=0; i<(PetscInt)sizeof(PetscInt); i++) ptr1[i] = ptr2[i];
72: }
73: return(0);
74: }
76: /*
77: PetscByteSwapInt64 - Swap bytes in a PETSc integer (64 bits)
79: */
80: PetscErrorCode PetscByteSwapInt64(PetscInt64 *buff,PetscInt n)
81: {
82: PetscInt i,j;
83: PetscInt64 tmp = 0;
84: char *ptr1,*ptr2 = (char*)&tmp;
87: for (j=0; j<n; j++) {
88: ptr1 = (char*)(buff + j);
89: for (i=0; i<(PetscInt)sizeof(PetscInt64); i++) ptr2[i] = ptr1[sizeof(PetscInt64)-1-i];
90: for (i=0; i<(PetscInt)sizeof(PetscInt64); i++) ptr1[i] = ptr2[i];
91: }
92: return(0);
93: }
95: /* --------------------------------------------------------- */
96: /*
97: PetscByteSwapShort - Swap bytes in a short
98: */
99: PetscErrorCode PetscByteSwapShort(short *buff,PetscInt n)
100: {
101: PetscInt i,j;
102: short tmp;
103: char *ptr1,*ptr2 = (char*)&tmp;
106: for (j=0; j<n; j++) {
107: ptr1 = (char*)(buff + j);
108: for (i=0; i<(PetscInt) sizeof(short); i++) ptr2[i] = ptr1[sizeof(short)-1-i];
109: for (i=0; i<(PetscInt) sizeof(short); i++) ptr1[i] = ptr2[i];
110: }
111: return(0);
112: }
113: /*
114: PetscByteSwapLong - Swap bytes in a long
115: */
116: PetscErrorCode PetscByteSwapLong(long *buff,PetscInt n)
117: {
118: PetscInt i,j;
119: long tmp;
120: char *ptr1,*ptr2 = (char*)&tmp;
123: for (j=0; j<n; j++) {
124: ptr1 = (char*)(buff + j);
125: for (i=0; i<(PetscInt) sizeof(long); i++) ptr2[i] = ptr1[sizeof(long)-1-i];
126: for (i=0; i<(PetscInt) sizeof(long); i++) ptr1[i] = ptr2[i];
127: }
128: return(0);
129: }
130: /* --------------------------------------------------------- */
131: /*
132: PetscByteSwapReal - Swap bytes in a PetscReal
133: */
134: PetscErrorCode PetscByteSwapReal(PetscReal *buff,PetscInt n)
135: {
136: PetscInt i,j;
137: PetscReal tmp,*buff1 = (PetscReal*)buff;
138: char *ptr1,*ptr2 = (char*)&tmp;
141: for (j=0; j<n; j++) {
142: ptr1 = (char*)(buff1 + j);
143: for (i=0; i<(PetscInt) sizeof(PetscReal); i++) ptr2[i] = ptr1[sizeof(PetscReal)-1-i];
144: for (i=0; i<(PetscInt) sizeof(PetscReal); i++) ptr1[i] = ptr2[i];
145: }
146: return(0);
147: }
148: /* --------------------------------------------------------- */
149: /*
150: PetscByteSwapScalar - Swap bytes in a PetscScalar
151: The complex case is dealt with with an array of PetscReal, twice as long.
152: */
153: PetscErrorCode PetscByteSwapScalar(PetscScalar *buff,PetscInt n)
154: {
155: PetscInt i,j;
156: PetscReal tmp,*buff1 = (PetscReal*)buff;
157: char *ptr1,*ptr2 = (char*)&tmp;
160: #if defined(PETSC_USE_COMPLEX)
161: n *= 2;
162: #endif
163: for (j=0; j<n; j++) {
164: ptr1 = (char*)(buff1 + j);
165: for (i=0; i<(PetscInt) sizeof(PetscReal); i++) ptr2[i] = ptr1[sizeof(PetscReal)-1-i];
166: for (i=0; i<(PetscInt) sizeof(PetscReal); i++) ptr1[i] = ptr2[i];
167: }
168: return(0);
169: }
170: /* --------------------------------------------------------- */
171: /*
172: PetscByteSwapDouble - Swap bytes in a double
173: */
174: PetscErrorCode PetscByteSwapDouble(double *buff,PetscInt n)
175: {
176: PetscInt i,j;
177: double tmp,*buff1 = (double*)buff;
178: char *ptr1,*ptr2 = (char*)&tmp;
181: for (j=0; j<n; j++) {
182: ptr1 = (char*)(buff1 + j);
183: for (i=0; i<(PetscInt) sizeof(double); i++) ptr2[i] = ptr1[sizeof(double)-1-i];
184: for (i=0; i<(PetscInt) sizeof(double); i++) ptr1[i] = ptr2[i];
185: }
186: return(0);
187: }
189: /*
190: PetscByteSwapFloat - Swap bytes in a float
191: */
192: PetscErrorCode PetscByteSwapFloat(float *buff,PetscInt n)
193: {
194: PetscInt i,j;
195: float tmp,*buff1 = (float*)buff;
196: char *ptr1,*ptr2 = (char*)&tmp;
199: for (j=0; j<n; j++) {
200: ptr1 = (char*)(buff1 + j);
201: for (i=0; i<(PetscInt) sizeof(float); i++) ptr2[i] = ptr1[sizeof(float)-1-i];
202: for (i=0; i<(PetscInt) sizeof(float); i++) ptr1[i] = ptr2[i];
203: }
204: return(0);
205: }
207: PetscErrorCode PetscByteSwap(void *data,PetscDataType pdtype,PetscInt count)
208: {
212: if (pdtype == PETSC_INT) {PetscByteSwapInt((PetscInt*)data,count);}
213: else if (pdtype == PETSC_ENUM) {PetscByteSwapEnum((PetscEnum*)data,count);}
214: else if (pdtype == PETSC_BOOL) {PetscByteSwapBool((PetscBool*)data,count);}
215: else if (pdtype == PETSC_SCALAR) {PetscByteSwapScalar((PetscScalar*)data,count);}
216: else if (pdtype == PETSC_REAL) {PetscByteSwapReal((PetscReal*)data,count);}
217: else if (pdtype == PETSC_COMPLEX){PetscByteSwapReal((PetscReal*)data,2*count);}
218: else if (pdtype == PETSC_INT64) {PetscByteSwapInt64((PetscInt64*)data,count);}
219: else if (pdtype == PETSC_DOUBLE) {PetscByteSwapDouble((double*)data,count);}
220: else if (pdtype == PETSC_FLOAT) {PetscByteSwapFloat((float*)data,count);}
221: else if (pdtype == PETSC_SHORT) {PetscByteSwapShort((short*)data,count);}
222: else if (pdtype == PETSC_LONG) {PetscByteSwapLong((long*)data,count);}
223: return(0);
224: }
226: /*@C
227: PetscBinaryRead - Reads from a binary file.
229: Not Collective
231: Input Parameters:
232: + fd - the file descriptor
233: . num - the maximum number of items to read
234: - type - the type of items to read (PETSC_INT, PETSC_REAL, PETSC_SCALAR, etc.)
236: Output Parameters:
237: + data - the buffer
238: - count - the number of items read, optional
242: Level: developer
244: Notes:
245: If count is not provided and the number of items read is less than
246: the maximum number of items to read, then this routine errors.
248: PetscBinaryRead() uses byte swapping to work on all machines; the files
249: are written to file ALWAYS using big-endian ordering. On small-endian machines the numbers
250: are converted to the small-endian format when they are read in from the file.
251: When PETSc is ./configure with --with-64bit-indices the integers are written to the
252: file as 64 bit integers, this means they can only be read back in when the option --with-64bit-indices
253: 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)
350: - istemp - PETSC_FALSE if buffer data should be preserved, PETSC_TRUE otherwise.
352: Level: advanced
354: Notes:
355: PetscBinaryWrite() uses byte swapping to work on all machines; the files
356: are written using big-endian ordering to the file. On small-endian machines the numbers
357: are converted to the big-endian format when they are written to disk.
358: When PETSc is ./configure with --with-64bit-indices the integers are written to the
359: file as 64 bit integers, this means they can only be read back in when the option --with-64bit-indices
360: is used.
362: If running with __float128 precision the output is in __float128 unless one uses the -binary_write_double option
364: The Buffer p should be read-write buffer, and not static data.
365: This way, byte-swapping is done in-place, and then the buffer is
366: written to the file.
368: This routine restores the original contents of the buffer, after
369: it is written to the file. This is done by byte-swapping in-place
370: the second time. If the flag istemp is set to PETSC_TRUE, the second
371: byte-swapping operation is not done, thus saving some computation,
372: but the buffer is left corrupted.
374: Because byte-swapping may be done on the values in data it cannot be declared const
377: .seealso: PetscBinaryRead(), PetscBinaryOpen(), PetscBinaryClose(), PetscViewerBinaryGetDescriptor(), PetscBinarySynchronizedWrite(),
378: PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek()
379: @*/
380: PetscErrorCode PetscBinaryWrite(int fd,void *p,PetscInt n,PetscDataType type,PetscBool istemp)
381: {
382: char *pp = (char*)p;
383: int err,wsize;
384: size_t m = (size_t)n,maxblock=65536;
386: void *ptmp = p;
387: char *fname = NULL;
388: #if defined(PETSC_USE_REAL___FLOAT128)
389: PetscBool writedouble = PETSC_FALSE;
390: double *ppp;
391: PetscReal *pv;
392: PetscInt i;
393: #endif
394: PetscDataType wtype = type;
397: if (n < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Trying to write a negative amount of data %D",n);
398: if (!n) return(0);
400: if (type == PETSC_FUNCTION) {
401: #if defined(PETSC_SERIALIZE_FUNCTIONS)
402: const char *fnametmp;
403: #endif
404: m = 64;
405: fname = (char*)malloc(m*sizeof(char));
406: if (!fname) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Cannot allocate space for function name");
407: #if defined(PETSC_SERIALIZE_FUNCTIONS)
408: if (n > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Can only binary view a single function at a time");
409: PetscFPTFind(*(void**)p,&fnametmp);
410: PetscStrncpy(fname,fnametmp,m);
411: #else
412: PetscStrncpy(fname,"",m);
413: #endif
414: wtype = PETSC_CHAR;
415: pp = (char*)fname;
416: ptmp = (void*)fname;
417: }
419: #if defined(PETSC_USE_REAL___FLOAT128)
420: PetscOptionsGetBool(NULL,NULL,"-binary_write_double",&writedouble,NULL);
421: /* If using __float128 precision we still write in doubles to file */
422: if ((type == PETSC_SCALAR || type == PETSC_REAL) && writedouble) {
423: wtype = PETSC_DOUBLE;
424: PetscMalloc1(n,&ppp);
425: pv = (PetscReal*)pp;
426: for (i=0; i<n; i++) {
427: ppp[i] = (double) pv[i];
428: }
429: pp = (char*)ppp;
430: ptmp = (char*)ppp;
431: }
432: #endif
434: if (wtype == PETSC_INT) m *= sizeof(PetscInt);
435: else if (wtype == PETSC_SCALAR) m *= sizeof(PetscScalar);
436: else if (wtype == PETSC_REAL) m *= sizeof(PetscReal);
437: else if (wtype == PETSC_DOUBLE) m *= sizeof(double);
438: else if (wtype == PETSC_FLOAT) m *= sizeof(float);
439: else if (wtype == PETSC_SHORT) m *= sizeof(short);
440: else if (wtype == PETSC_LONG) m *= sizeof(long);
441: else if (wtype == PETSC_CHAR) m *= sizeof(char);
442: else if (wtype == PETSC_ENUM) m *= sizeof(PetscEnum);
443: else if (wtype == PETSC_BOOL) m *= sizeof(PetscBool);
444: else if (wtype == PETSC_INT64) m *= sizeof(PetscInt64);
445: else if (wtype == PETSC_BIT_LOGICAL) m = PetscBTLength(m)*sizeof(char);
446: else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown type");
448: if (!PetscBinaryBigEndian()) {PetscByteSwap(ptmp,wtype,n);}
450: while (m) {
451: wsize = (m < maxblock) ? m : maxblock;
452: err = write(fd,pp,wsize);
453: if (err < 0 && errno == EINTR) continue;
454: 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);
455: m -= wsize;
456: pp += wsize;
457: }
459: if (!istemp) {
460: if (!PetscBinaryBigEndian()) {PetscByteSwap(ptmp,wtype,n);}
461: }
462: if (type == PETSC_FUNCTION) {
463: free(fname);
464: }
465: #if defined(PETSC_USE_REAL___FLOAT128)
466: if ((type == PETSC_SCALAR || type == PETSC_REAL) && writedouble) {
467: PetscFree(ppp);
468: }
469: #endif
470: return(0);
471: }
473: /*@C
474: PetscBinaryOpen - Opens a PETSc binary file.
476: Not Collective
478: Input Parameters:
479: + name - filename
480: - type - type of binary file, one of FILE_MODE_READ, FILE_MODE_APPEND, FILE_MODE_WRITE
482: Output Parameter:
483: . fd - the file
485: Level: advanced
488: Notes:
489: Files access with PetscBinaryRead() and PetscBinaryWrite() are ALWAYS written in
490: big-endian format. This means the file can be accessed using PetscBinaryOpen() and
491: PetscBinaryRead() and PetscBinaryWrite() on any machine.
493: .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscFileMode, PetscViewerFileSetMode(), PetscViewerBinaryGetDescriptor(),
494: PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek()
496: @*/
497: PetscErrorCode PetscBinaryOpen(const char name[],PetscFileMode mode,int *fd)
498: {
500: #if defined(PETSC_HAVE_O_BINARY)
501: if (mode == FILE_MODE_WRITE) {
502: if ((*fd = open(name,O_WRONLY|O_CREAT|O_TRUNC|O_BINARY,0666)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot create file for writing: %s",name);
503: } else if (mode == FILE_MODE_READ) {
504: if ((*fd = open(name,O_RDONLY|O_BINARY,0)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file for reading: %s",name);
505: } else if (mode == FILE_MODE_APPEND) {
506: if ((*fd = open(name,O_WRONLY|O_BINARY,0)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file for writing: %s",name);
507: #else
508: if (mode == FILE_MODE_WRITE) {
509: if ((*fd = creat(name,0666)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot create file for writing: %s",name);
510: } else if (mode == FILE_MODE_READ) {
511: if ((*fd = open(name,O_RDONLY,0)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file for reading: %s",name);
512: }
513: else if (mode == FILE_MODE_APPEND) {
514: if ((*fd = open(name,O_WRONLY,0)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file for writing: %s",name);
515: #endif
516: } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown file mode");
517: return(0);
518: }
520: /*@
521: PetscBinaryClose - Closes a PETSc binary file.
523: Not Collective
525: Output Parameter:
526: . fd - the file
528: Level: advanced
530: .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
531: PetscBinarySynchronizedSeek()
532: @*/
533: PetscErrorCode PetscBinaryClose(int fd)
534: {
536: close(fd);
537: return(0);
538: }
541: /*@C
542: PetscBinarySeek - Moves the file pointer on a PETSc binary file.
544: Not Collective
546: Input Parameters:
547: + fd - the file
548: . off - number of bytes to move. Use PETSC_BINARY_INT_SIZE, PETSC_BINARY_SCALAR_SIZE,
549: etc. in your calculation rather than sizeof() to compute byte lengths.
550: - whence - if PETSC_BINARY_SEEK_SET then off is an absolute location in the file
551: if PETSC_BINARY_SEEK_CUR then off is an offset from the current location
552: if PETSC_BINARY_SEEK_END then off is an offset from the end of file
554: Output Parameter:
555: . offset - new offset in file
557: Level: developer
559: Notes:
560: Integers are stored on the file as 32 long, regardless of whether
561: they are stored in the machine as 32 or 64, this means the same
562: binary file may be read on any machine. Hence you CANNOT use sizeof()
563: to determine the offset or location.
566: .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
567: PetscBinarySynchronizedSeek()
568: @*/
569: PetscErrorCode PetscBinarySeek(int fd,off_t off,PetscBinarySeekType whence,off_t *offset)
570: {
571: int iwhence = 0;
574: if (whence == PETSC_BINARY_SEEK_SET) iwhence = SEEK_SET;
575: else if (whence == PETSC_BINARY_SEEK_CUR) iwhence = SEEK_CUR;
576: else if (whence == PETSC_BINARY_SEEK_END) iwhence = SEEK_END;
577: else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown seek location");
578: #if defined(PETSC_HAVE_LSEEK)
579: *offset = lseek(fd,off,iwhence);
580: #elif defined(PETSC_HAVE__LSEEK)
581: *offset = _lseek(fd,(long)off,iwhence);
582: #else
583: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS,"System does not have a way of seeking on a file");
584: #endif
585: return(0);
586: }
588: /*@C
589: PetscBinarySynchronizedRead - Reads from a binary file.
591: Collective
593: Input Parameters:
594: + comm - the MPI communicator
595: . fd - the file descriptor
596: . num - the maximum number of items to read
597: - type - the type of items to read (PETSC_INT, PETSC_REAL, PETSC_SCALAR, etc.)
599: Output Parameters:
600: + data - the buffer
601: - count - the number of items read, optional
603: Level: developer
605: Notes:
606: Does a PetscBinaryRead() followed by an MPI_Bcast()
608: If count is not provided and the number of items read is less than
609: the maximum number of items to read, then this routine errors.
611: PetscBinarySynchronizedRead() uses byte swapping to work on all machines.
612: Integers are stored on the file as 32 long, regardless of whether
613: they are stored in the machine as 32 or 64, this means the same
614: binary file may be read on any machine.
617: .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscBinaryRead(), PetscBinarySynchronizedWrite(),
618: PetscBinarySynchronizedSeek()
619: @*/
620: PetscErrorCode PetscBinarySynchronizedRead(MPI_Comm comm,int fd,void *data,PetscInt num,PetscInt *count,PetscDataType type)
621: {
623: PetscMPIInt rank;
624: MPI_Datatype mtype;
625: PetscInt ibuf[2] = {0, 0};
626: char *fname = NULL;
627: void *fptr = NULL;
630: if (type == PETSC_FUNCTION) {
631: num = 64;
632: type = PETSC_CHAR;
633: fname = (char*)malloc(num*sizeof(char));
634: fptr = data;
635: data = (void*)fname;
636: if (!fname) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Cannot allocate space for function name");
637: }
639: MPI_Comm_rank(comm,&rank);
640: if (!rank) {
641: ibuf[0] = PetscBinaryRead(fd,data,num,count?&ibuf[1]:NULL,type);
642: }
643: MPI_Bcast(ibuf,2,MPIU_INT,0,comm);
644: (PetscErrorCode)ibuf[0];
645: PetscDataTypeToMPIDataType(type,&mtype);
646: MPI_Bcast(data,count?ibuf[1]:num,mtype,0,comm);
647: if (count) *count = ibuf[1];
649: if (type == PETSC_FUNCTION) {
650: #if defined(PETSC_SERIALIZE_FUNCTIONS)
651: PetscDLLibrarySym(PETSC_COMM_SELF,&PetscDLLibrariesLoaded,NULL,fname,(void**)fptr);
652: #else
653: *(void**)fptr = NULL;
654: #endif
655: free(fname);
656: }
657: return(0);
658: }
660: /*@C
661: PetscBinarySynchronizedWrite - writes to a binary file.
663: Collective
665: Input Parameters:
666: + comm - the MPI communicator
667: . fd - the file
668: . n - the number of items to write
669: . p - the buffer
670: . istemp - the buffer may be changed
671: - type - the type of items to write (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)
673: Level: developer
675: Notes:
676: Process 0 does a PetscBinaryWrite()
678: PetscBinarySynchronizedWrite() uses byte swapping to work on all machines.
679: Integers are stored on the file as 32 long, regardless of whether
680: they are stored in the machine as 32 or 64, this means the same
681: binary file may be read on any machine.
683: Notes:
684: because byte-swapping may be done on the values in data it cannot be declared const
686: WARNING: This is NOT like PetscSynchronizedFPrintf()! This routine ignores calls on all but process 0,
687: while PetscSynchronizedFPrintf() has all processes print their strings in order.
690: .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscBinaryRead(), PetscBinarySynchronizedRead(),
691: PetscBinarySynchronizedSeek()
692: @*/
693: PetscErrorCode PetscBinarySynchronizedWrite(MPI_Comm comm,int fd,void *p,PetscInt n,PetscDataType type,PetscBool istemp)
694: {
696: PetscMPIInt rank;
699: MPI_Comm_rank(comm,&rank);
700: if (!rank) {
701: PetscBinaryWrite(fd,p,n,type,istemp);
702: }
703: return(0);
704: }
706: /*@C
707: PetscBinarySynchronizedSeek - Moves the file pointer on a PETSc binary file.
710: Input Parameters:
711: + fd - the file
712: . whence - if PETSC_BINARY_SEEK_SET then size is an absolute location in the file
713: if PETSC_BINARY_SEEK_CUR then size is offset from current location
714: if PETSC_BINARY_SEEK_END then size is offset from end of file
715: - off - number of bytes to move. Use PETSC_BINARY_INT_SIZE, PETSC_BINARY_SCALAR_SIZE,
716: etc. in your calculation rather than sizeof() to compute byte lengths.
718: Output Parameter:
719: . offset - new offset in file
721: Level: developer
723: Notes:
724: Integers are stored on the file as 32 long, regardless of whether
725: they are stored in the machine as 32 or 64, this means the same
726: binary file may be read on any machine. Hence you CANNOT use sizeof()
727: to determine the offset or location.
730: .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
731: PetscBinarySynchronizedSeek()
732: @*/
733: PetscErrorCode PetscBinarySynchronizedSeek(MPI_Comm comm,int fd,off_t off,PetscBinarySeekType whence,off_t *offset)
734: {
736: PetscMPIInt rank;
739: MPI_Comm_rank(comm,&rank);
740: if (!rank) {
741: PetscBinarySeek(fd,off,whence,offset);
742: }
743: return(0);
744: }
746: #if defined(PETSC_HAVE_MPIIO)
748: #if defined(PETSC_USE_PETSC_MPI_EXTERNAL32)
749: /*
750: MPICH does not provide the external32 representation for MPI_File_set_view() so we need to provide the functions.
751: These are set into MPI in PetscInitialize() via MPI_Register_datarep()
753: Note I use PetscMPIInt for the MPI error codes since that is what MPI uses (instead of the standard PetscErrorCode)
755: The next three routines are not used because MPICH does not support their use
757: */
758: PETSC_EXTERN PetscMPIInt PetscDataRep_extent_fn(MPI_Datatype datatype,MPI_Aint *file_extent,void *extra_state)
759: {
760: MPI_Aint ub;
761: PetscMPIInt ierr;
763: MPI_Type_get_extent(datatype,&ub,file_extent);
764: return ierr;
765: }
767: PETSC_EXTERN PetscMPIInt PetscDataRep_read_conv_fn(void *userbuf, MPI_Datatype datatype,PetscMPIInt count,void *filebuf, MPI_Offset position,void *extra_state)
768: {
769: PetscDataType pdtype;
770: PetscMPIInt ierr;
771: size_t dsize;
773: PetscMPIDataTypeToPetscDataType(datatype,&pdtype);
774: PetscDataTypeGetSize(pdtype,&dsize);
776: /* offset is given in units of MPI_Datatype */
777: userbuf = ((char*)userbuf) + dsize*position;
779: PetscMemcpy(userbuf,filebuf,count*dsize);
780: if (!PetscBinaryBigEndian()) {PetscByteSwap(userbuf,pdtype,count);}
781: return ierr;
782: }
784: PetscMPIInt PetscDataRep_write_conv_fn(void *userbuf, MPI_Datatype datatype,PetscMPIInt count,void *filebuf, MPI_Offset position,void *extra_state)
785: {
786: PetscDataType pdtype;
787: PetscMPIInt ierr;
788: size_t dsize;
790: PetscMPIDataTypeToPetscDataType(datatype,&pdtype);
791: PetscDataTypeGetSize(pdtype,&dsize);
793: /* offset is given in units of MPI_Datatype */
794: userbuf = ((char*)userbuf) + dsize*position;
796: PetscMemcpy(filebuf,userbuf,count*dsize);
797: if (!PetscBinaryBigEndian()) {PetscByteSwap(filebuf,pdtype,count);}
798: return ierr;
799: }
800: #endif
802: PetscErrorCode MPIU_File_write_all(MPI_File fd,void *data,PetscMPIInt cnt,MPI_Datatype dtype,MPI_Status *status)
803: {
804: PetscDataType pdtype;
809: PetscMPIDataTypeToPetscDataType(dtype,&pdtype);
810: if (!PetscBinaryBigEndian()) {PetscByteSwap(data,pdtype,cnt);}
811: MPI_File_write_all(fd,data,cnt,dtype,status);
812: if (!PetscBinaryBigEndian()) {PetscByteSwap(data,pdtype,cnt);}
813: return(0);
814: }
816: PetscErrorCode MPIU_File_read_all(MPI_File fd,void *data,PetscMPIInt cnt,MPI_Datatype dtype,MPI_Status *status)
817: {
818: PetscDataType pdtype;
822: PetscMPIDataTypeToPetscDataType(dtype,&pdtype);
823: MPI_File_read_all(fd,data,cnt,dtype,status);
824: if (!PetscBinaryBigEndian()) {PetscByteSwap(data,pdtype,cnt);}
825: return(0);
826: }
828: #endif