Actual source code: sysio.c
petsc-3.11.4 2019-09-28
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_INT64) {PetscByteSwapInt64((PetscInt64*)data,count);}
218: else if (pdtype == PETSC_DOUBLE) {PetscByteSwapDouble((double*)data,count);}
219: else if (pdtype == PETSC_FLOAT) {PetscByteSwapFloat((float*)data,count);}
220: else if (pdtype == PETSC_SHORT) {PetscByteSwapShort((short*)data,count);}
221: else if (pdtype == PETSC_LONG) {PetscByteSwapLong((long*)data,count);}
222: return(0);
223: }
225: /* --------------------------------------------------------- */
226: /*@
227: PetscBinaryRead - Reads from a binary file.
229: Not Collective
231: Input Parameters:
232: + fd - the file
233: . n - the number of items to read
234: - type - the type of items to read (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)
236: Output Parameters:
237: . p - the buffer
241: Level: developer
243: Notes:
244: PetscBinaryRead() uses byte swapping to work on all machines; the files
245: are written to file ALWAYS using big-endian ordering. On small-endian machines the numbers
246: are converted to the small-endian format when they are read in from the file.
247: When PETSc is ./configure with --with-64bit-indices the integers are written to the
248: file as 64 bit integers, this means they can only be read back in when the option --with-64bit-indices
249: is used.
251: Concepts: files^reading binary
252: Concepts: binary files^reading
254: .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscViewerBinaryGetDescriptor(), PetscBinarySynchronizedWrite(),
255: PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek()
256: @*/
257: PetscErrorCode PetscBinaryRead(int fd,void *p,PetscInt n,PetscDataType type)
258: {
259: int wsize,err;
260: size_t m = (size_t) n,maxblock = 65536;
261: char *pp = (char*)p;
262: #if defined(PETSC_USE_REAL___FLOAT128)
263: PetscBool readdouble = PETSC_FALSE;
264: double *ppp;
265: #endif
266: #if !defined(PETSC_WORDS_BIGENDIAN) || defined(PETSC_USE_REAL___FLOAT128)
267: PetscErrorCode ierr;
268: #endif
269: #if !defined(PETSC_WORDS_BIGENDIAN)
270: void *ptmp = p;
271: #endif
272: char *fname = NULL;
275: if (n < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Trying to write a negative amount of data %D",n);
276: if (!n) return(0);
278: if (type == PETSC_FUNCTION) {
279: m = 64;
280: type = PETSC_CHAR;
281: fname = (char*) malloc(m*sizeof(char));
282: if (!fname) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Cannot allocate space for function name");
283: pp = (char*)fname;
284: #if !defined(PETSC_WORDS_BIGENDIAN)
285: ptmp = (void*)fname;
286: #endif
287: }
289: if (type == PETSC_INT) m *= sizeof(PetscInt);
290: else if (type == PETSC_SCALAR) m *= sizeof(PetscScalar);
291: else if (type == PETSC_REAL) m *= sizeof(PetscReal);
292: else if (type == PETSC_DOUBLE) m *= sizeof(double);
293: else if (type == PETSC_FLOAT) m *= sizeof(float);
294: else if (type == PETSC_SHORT) m *= sizeof(short);
295: else if (type == PETSC_LONG) m *= sizeof(long);
296: else if (type == PETSC_CHAR) m *= sizeof(char);
297: else if (type == PETSC_ENUM) m *= sizeof(PetscEnum);
298: else if (type == PETSC_BOOL) m *= sizeof(PetscBool);
299: else if (type == PETSC_INT64) m *= sizeof(PetscInt64);
300: else if (type == PETSC_BIT_LOGICAL) m = PetscBTLength(m)*sizeof(char);
301: else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown type");
303: #if defined(PETSC_USE_REAL___FLOAT128)
304: PetscOptionsGetBool(NULL,NULL,"-binary_read_double",&readdouble,NULL);
305: /* If using __float128 precision we still read in doubles from file */
306: if ((type == PETSC_SCALAR || type == PETSC_REAL) && readdouble) {
307: m = m/2;
308: PetscMalloc1(n,&ppp);
309: pp = (char*)ppp;
310: }
311: #endif
313: while (m) {
314: wsize = (m < maxblock) ? m : maxblock;
315: err = read(fd,pp,wsize);
316: if (err < 0 && errno == EINTR) continue;
317: if (!err && wsize > 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_READ,"Read past end of file");
318: if (err < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_READ,"Error reading from file, errno %d",errno);
319: m -= err;
320: pp += err;
321: }
323: #if defined(PETSC_USE_REAL___FLOAT128)
324: if ((type == PETSC_SCALAR || type == PETSC_REAL) && readdouble) {
325: PetscScalar *pv = (PetscScalar*) p;
326: PetscInt i;
327: #if !defined(PETSC_WORDS_BIGENDIAN)
328: PetscByteSwapDouble(ppp,n);
329: #endif
330: for (i=0; i<n; i++) pv[i] = ppp[i];
331: PetscFree(ppp);
332: return(0);
333: }
334: #endif
336: #if !defined(PETSC_WORDS_BIGENDIAN)
337: PetscByteSwap(ptmp,type,n);
338: #endif
340: if (type == PETSC_FUNCTION) {
341: #if defined(PETSC_SERIALIZE_FUNCTIONS)
342: PetscDLSym(NULL,fname,(void**)p);
343: #else
344: *(void**)p = NULL;
345: #endif
346: free(fname);
347: }
348: return(0);
349: }
350: /* --------------------------------------------------------- */
351: /*@
352: PetscBinaryWrite - Writes to a binary file.
354: Not Collective
356: Input Parameters:
357: + fd - the file
358: . p - the buffer
359: . n - the number of items to write
360: . type - the type of items to read (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)
361: - istemp - PETSC_FALSE if buffer data should be preserved, PETSC_TRUE otherwise.
363: Level: advanced
365: Notes:
366: PetscBinaryWrite() uses byte swapping to work on all machines; the files
367: are written using big-endian ordering to the file. On small-endian machines the numbers
368: are converted to the big-endian format when they are written to disk.
369: When PETSc is ./configure with --with-64bit-indices the integers are written to the
370: file as 64 bit integers, this means they can only be read back in when the option --with-64bit-indices
371: is used.
373: If running with __float128 precision the output is in __float128 unless one uses the -binary_write_double option
375: The Buffer p should be read-write buffer, and not static data.
376: This way, byte-swapping is done in-place, and then the buffer is
377: written to the file.
379: This routine restores the original contents of the buffer, after
380: it is written to the file. This is done by byte-swapping in-place
381: the second time. If the flag istemp is set to PETSC_TRUE, the second
382: byte-swapping operation is not done, thus saving some computation,
383: but the buffer is left corrupted.
385: Because byte-swapping may be done on the values in data it cannot be declared const
387: Concepts: files^writing binary
388: Concepts: binary files^writing
390: .seealso: PetscBinaryRead(), PetscBinaryOpen(), PetscBinaryClose(), PetscViewerBinaryGetDescriptor(), PetscBinarySynchronizedWrite(),
391: PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek()
392: @*/
393: PetscErrorCode PetscBinaryWrite(int fd,void *p,PetscInt n,PetscDataType type,PetscBool istemp)
394: {
395: char *pp = (char*)p;
396: int err,wsize;
397: size_t m = (size_t)n,maxblock=65536;
399: #if !defined(PETSC_WORDS_BIGENDIAN)
400: void *ptmp = p;
401: #endif
402: char *fname = NULL;
403: #if defined(PETSC_USE_REAL___FLOAT128)
404: PetscBool writedouble = PETSC_FALSE;
405: double *ppp;
406: PetscReal *pv;
407: PetscInt i;
408: #endif
409: PetscDataType wtype = type;
412: if (n < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Trying to write a negative amount of data %D",n);
413: if (!n) return(0);
415: if (type == PETSC_FUNCTION) {
416: #if defined(PETSC_SERIALIZE_FUNCTIONS)
417: const char *fnametmp;
418: #endif
419: m = 64;
420: fname = (char*)malloc(m*sizeof(char));
421: if (!fname) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Cannot allocate space for function name");
422: #if defined(PETSC_SERIALIZE_FUNCTIONS)
423: if (n > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Can only binary view a single function at a time");
424: PetscFPTFind(*(void**)p,&fnametmp);
425: PetscStrncpy(fname,fnametmp,m);
426: #else
427: PetscStrncpy(fname,"",m);
428: #endif
429: wtype = PETSC_CHAR;
430: pp = (char*)fname;
431: #if !defined(PETSC_WORDS_BIGENDIAN)
432: ptmp = (void*)fname;
433: #endif
434: }
436: #if defined(PETSC_USE_REAL___FLOAT128)
437: PetscOptionsGetBool(NULL,NULL,"-binary_write_double",&writedouble,NULL);
438: /* If using __float128 precision we still write in doubles to file */
439: if ((type == PETSC_SCALAR || type == PETSC_REAL) && writedouble) {
440: wtype = PETSC_DOUBLE;
441: PetscMalloc1(n,&ppp);
442: pv = (PetscReal*)pp;
443: for (i=0; i<n; i++) {
444: ppp[i] = (double) pv[i];
445: }
446: pp = (char*)ppp;
447: ptmp = (char*)ppp;
448: }
449: #endif
451: if (wtype == PETSC_INT) m *= sizeof(PetscInt);
452: else if (wtype == PETSC_SCALAR) m *= sizeof(PetscScalar);
453: else if (wtype == PETSC_REAL) m *= sizeof(PetscReal);
454: else if (wtype == PETSC_DOUBLE) m *= sizeof(double);
455: else if (wtype == PETSC_FLOAT) m *= sizeof(float);
456: else if (wtype == PETSC_SHORT) m *= sizeof(short);
457: else if (wtype == PETSC_LONG) m *= sizeof(long);
458: else if (wtype == PETSC_CHAR) m *= sizeof(char);
459: else if (wtype == PETSC_ENUM) m *= sizeof(PetscEnum);
460: else if (wtype == PETSC_BOOL) m *= sizeof(PetscBool);
461: else if (wtype == PETSC_INT64) m *= sizeof(PetscInt64);
462: else if (wtype == PETSC_BIT_LOGICAL) m = PetscBTLength(m)*sizeof(char);
463: else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown type");
465: #if !defined(PETSC_WORDS_BIGENDIAN)
466: PetscByteSwap(ptmp,wtype,n);
467: #endif
469: while (m) {
470: wsize = (m < maxblock) ? m : maxblock;
471: err = write(fd,pp,wsize);
472: if (err < 0 && errno == EINTR) continue;
473: 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);
474: m -= wsize;
475: pp += wsize;
476: }
478: #if !defined(PETSC_WORDS_BIGENDIAN)
479: if (!istemp) {
480: PetscByteSwap(ptmp,wtype,n);
481: }
482: #endif
483: if (type == PETSC_FUNCTION) {
484: free(fname);
485: }
486: #if defined(PETSC_USE_REAL___FLOAT128)
487: if ((type == PETSC_SCALAR || type == PETSC_REAL) && writedouble) {
488: PetscFree(ppp);
489: }
490: #endif
491: return(0);
492: }
494: /*@C
495: PetscBinaryOpen - Opens a PETSc binary file.
497: Not Collective
499: Input Parameters:
500: + name - filename
501: - type - type of binary file, one of FILE_MODE_READ, FILE_MODE_APPEND, FILE_MODE_WRITE
503: Output Parameter:
504: . fd - the file
506: Level: advanced
508: Concepts: files^opening binary
509: Concepts: binary files^opening
511: Notes:
512: Files access with PetscBinaryRead() and PetscBinaryWrite() are ALWAYS written in
513: big-endian format. This means the file can be accessed using PetscBinaryOpen() and
514: PetscBinaryRead() and PetscBinaryWrite() on any machine.
516: .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscFileMode, PetscViewerFileSetMode(), PetscViewerBinaryGetDescriptor(),
517: PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek()
519: @*/
520: PetscErrorCode PetscBinaryOpen(const char name[],PetscFileMode mode,int *fd)
521: {
523: #if defined(PETSC_HAVE_O_BINARY)
524: if (mode == FILE_MODE_WRITE) {
525: 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);
526: } else if (mode == FILE_MODE_READ) {
527: 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);
528: } else if (mode == FILE_MODE_APPEND) {
529: 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);
530: #else
531: if (mode == FILE_MODE_WRITE) {
532: if ((*fd = creat(name,0666)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot create file for writing: %s",name);
533: } else if (mode == FILE_MODE_READ) {
534: if ((*fd = open(name,O_RDONLY,0)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file for reading: %s",name);
535: }
536: else if (mode == FILE_MODE_APPEND) {
537: if ((*fd = open(name,O_WRONLY,0)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file for writing: %s",name);
538: #endif
539: } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown file mode");
540: return(0);
541: }
543: /*@
544: PetscBinaryClose - Closes a PETSc binary file.
546: Not Collective
548: Output Parameter:
549: . fd - the file
551: Level: advanced
553: .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
554: PetscBinarySynchronizedSeek()
555: @*/
556: PetscErrorCode PetscBinaryClose(int fd)
557: {
559: close(fd);
560: return(0);
561: }
564: /*@C
565: PetscBinarySeek - Moves the file pointer on a PETSc binary file.
567: Not Collective
569: Input Parameters:
570: + fd - the file
571: . off - number of bytes to move. Use PETSC_BINARY_INT_SIZE, PETSC_BINARY_SCALAR_SIZE,
572: etc. in your calculation rather than sizeof() to compute byte lengths.
573: - whence - if PETSC_BINARY_SEEK_SET then off is an absolute location in the file
574: if PETSC_BINARY_SEEK_CUR then off is an offset from the current location
575: if PETSC_BINARY_SEEK_END then off is an offset from the end of file
577: Output Parameter:
578: . offset - new offset in file
580: Level: developer
582: Notes:
583: Integers are stored on the file as 32 long, regardless of whether
584: they are stored in the machine as 32 or 64, this means the same
585: binary file may be read on any machine. Hence you CANNOT use sizeof()
586: to determine the offset or location.
588: Concepts: files^binary seeking
589: Concepts: binary files^seeking
591: .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
592: PetscBinarySynchronizedSeek()
593: @*/
594: PetscErrorCode PetscBinarySeek(int fd,off_t off,PetscBinarySeekType whence,off_t *offset)
595: {
596: int iwhence = 0;
599: if (whence == PETSC_BINARY_SEEK_SET) iwhence = SEEK_SET;
600: else if (whence == PETSC_BINARY_SEEK_CUR) iwhence = SEEK_CUR;
601: else if (whence == PETSC_BINARY_SEEK_END) iwhence = SEEK_END;
602: else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown seek location");
603: #if defined(PETSC_HAVE_LSEEK)
604: *offset = lseek(fd,off,iwhence);
605: #elif defined(PETSC_HAVE__LSEEK)
606: *offset = _lseek(fd,(long)off,iwhence);
607: #else
608: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS,"System does not have a way of seeking on a file");
609: #endif
610: return(0);
611: }
613: /*@C
614: PetscBinarySynchronizedRead - Reads from a binary file.
616: Collective on MPI_Comm
618: Input Parameters:
619: + comm - the MPI communicator
620: . fd - the file
621: . n - the number of items to read
622: - type - the type of items to read (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)
624: Output Parameters:
625: . p - the buffer
627: Level: developer
629: Notes:
630: Does a PetscBinaryRead() followed by an MPI_Bcast()
632: PetscBinarySynchronizedRead() uses byte swapping to work on all machines.
633: Integers are stored on the file as 32 long, regardless of whether
634: they are stored in the machine as 32 or 64, this means the same
635: binary file may be read on any machine.
637: Concepts: files^synchronized reading of binary files
638: Concepts: binary files^reading, synchronized
640: .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscBinaryRead(), PetscBinarySynchronizedWrite(),
641: PetscBinarySynchronizedSeek()
642: @*/
643: PetscErrorCode PetscBinarySynchronizedRead(MPI_Comm comm,int fd,void *p,PetscInt n,PetscDataType type)
644: {
645: PetscErrorCode ierr,ierrp=0;
646: PetscMPIInt rank;
647: MPI_Datatype mtype;
648: char *fname = NULL;
649: void *ptmp = NULL;
652: if (type == PETSC_FUNCTION) {
653: n = 64;
654: type = PETSC_CHAR;
655: ptmp = p;
656: fname = (char*)malloc(n*sizeof(char));
657: if (!fname) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Cannot allocate space for function name");
658: p = (void*)fname;
659: }
661: MPI_Comm_rank(comm,&rank);
662: if (!rank) {
663: ierrp = PetscBinaryRead(fd,p,n,type);
664: }
665: MPI_Bcast(&ierrp,1,MPI_INT,0,comm);
666: CHKERRQ(ierrp);
667: PetscDataTypeToMPIDataType(type,&mtype);
668: MPI_Bcast(p,n,mtype,0,comm);
670: if (type == PETSC_FUNCTION) {
671: #if defined(PETSC_SERIALIZE_FUNCTIONS)
672: PetscDLLibrarySym(PETSC_COMM_SELF,&PetscDLLibrariesLoaded,NULL,fname,(void**)ptmp);
673: #else
674: *(void**)ptmp = NULL;
675: #endif
676: free(fname);
677: }
678: return(0);
679: }
681: /*@C
682: PetscBinarySynchronizedWrite - writes to a binary file.
684: Collective on MPI_Comm
686: Input Parameters:
687: + comm - the MPI communicator
688: . fd - the file
689: . n - the number of items to write
690: . p - the buffer
691: . istemp - the buffer may be changed
692: - type - the type of items to write (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)
694: Level: developer
696: Notes:
697: Process 0 does a PetscBinaryWrite()
699: PetscBinarySynchronizedWrite() uses byte swapping to work on all machines.
700: Integers are stored on the file as 32 long, regardless of whether
701: they are stored in the machine as 32 or 64, this means the same
702: binary file may be read on any machine.
704: Notes:
705: because byte-swapping may be done on the values in data it cannot be declared const
707: WARNING: This is NOT like PetscSynchronizedFPrintf()! This routine ignores calls on all but process 0,
708: while PetscSynchronizedFPrintf() has all processes print their strings in order.
710: Concepts: files^synchronized writing of binary files
711: Concepts: binary files^reading, synchronized
713: .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscBinaryRead(), PetscBinarySynchronizedRead(),
714: PetscBinarySynchronizedSeek()
715: @*/
716: PetscErrorCode PetscBinarySynchronizedWrite(MPI_Comm comm,int fd,void *p,PetscInt n,PetscDataType type,PetscBool istemp)
717: {
719: PetscMPIInt rank;
722: MPI_Comm_rank(comm,&rank);
723: if (!rank) {
724: PetscBinaryWrite(fd,p,n,type,istemp);
725: }
726: return(0);
727: }
729: /*@C
730: PetscBinarySynchronizedSeek - Moves the file pointer on a PETSc binary file.
733: Input Parameters:
734: + fd - the file
735: . whence - if PETSC_BINARY_SEEK_SET then size is an absolute location in the file
736: if PETSC_BINARY_SEEK_CUR then size is offset from current location
737: if PETSC_BINARY_SEEK_END then size is offset from end of file
738: - off - number of bytes to move. Use PETSC_BINARY_INT_SIZE, PETSC_BINARY_SCALAR_SIZE,
739: etc. in your calculation rather than sizeof() to compute byte lengths.
741: Output Parameter:
742: . offset - new offset in file
744: Level: developer
746: Notes:
747: Integers are stored on the file as 32 long, regardless of whether
748: they are stored in the machine as 32 or 64, this means the same
749: binary file may be read on any machine. Hence you CANNOT use sizeof()
750: to determine the offset or location.
752: Concepts: binary files^seeking
753: Concepts: files^seeking in binary
755: .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
756: PetscBinarySynchronizedSeek()
757: @*/
758: PetscErrorCode PetscBinarySynchronizedSeek(MPI_Comm comm,int fd,off_t off,PetscBinarySeekType whence,off_t *offset)
759: {
761: PetscMPIInt rank;
764: MPI_Comm_rank(comm,&rank);
765: if (!rank) {
766: PetscBinarySeek(fd,off,whence,offset);
767: }
768: return(0);
769: }
771: #if defined(PETSC_HAVE_MPIIO)
772: #if !defined(PETSC_WORDS_BIGENDIAN)
774: #if defined(PETSC_USE_PETSC_MPI_EXTERNAL32)
775: /*
776: MPICH does not provide the external32 representation for MPI_File_set_view() so we need to provide the functions.
777: These are set into MPI in PetscInitialize() via MPI_Register_datarep()
779: Note I use PetscMPIInt for the MPI error codes since that is what MPI uses (instead of the standard PetscErrorCode)
781: The next three routines are not used because MPICH does not support their use
783: */
784: PETSC_EXTERN PetscMPIInt PetscDataRep_extent_fn(MPI_Datatype datatype,MPI_Aint *file_extent,void *extra_state)
785: {
786: MPI_Aint ub;
787: PetscMPIInt ierr;
789: MPI_Type_get_extent(datatype,&ub,file_extent);
790: return ierr;
791: }
793: PETSC_EXTERN PetscMPIInt PetscDataRep_read_conv_fn(void *userbuf, MPI_Datatype datatype,PetscMPIInt count,void *filebuf, MPI_Offset position,void *extra_state)
794: {
795: PetscDataType pdtype;
796: PetscMPIInt ierr;
797: size_t dsize;
799: PetscMPIDataTypeToPetscDataType(datatype,&pdtype);
800: PetscDataTypeGetSize(pdtype,&dsize);
802: /* offset is given in units of MPI_Datatype */
803: userbuf = ((char*)userbuf) + dsize*position;
805: PetscMemcpy(userbuf,filebuf,count*dsize);
806: PetscByteSwap(userbuf,pdtype,count);
807: return ierr;
808: }
810: PetscMPIInt PetscDataRep_write_conv_fn(void *userbuf, MPI_Datatype datatype,PetscMPIInt count,void *filebuf, MPI_Offset position,void *extra_state)
811: {
812: PetscDataType pdtype;
813: PetscMPIInt ierr;
814: size_t dsize;
816: PetscMPIDataTypeToPetscDataType(datatype,&pdtype);
817: PetscDataTypeGetSize(pdtype,&dsize);
819: /* offset is given in units of MPI_Datatype */
820: userbuf = ((char*)userbuf) + dsize*position;
822: PetscMemcpy(filebuf,userbuf,count*dsize);
823: PetscByteSwap(filebuf,pdtype,count);
824: return ierr;
825: }
826: #endif
828: PetscErrorCode MPIU_File_write_all(MPI_File fd,void *data,PetscMPIInt cnt,MPI_Datatype dtype,MPI_Status *status)
829: {
831: PetscDataType pdtype;
834: PetscMPIDataTypeToPetscDataType(dtype,&pdtype);
835: PetscByteSwap(data,pdtype,cnt);
836: MPI_File_write_all(fd,data,cnt,dtype,status);
837: PetscByteSwap(data,pdtype,cnt);
838: return(0);
839: }
841: PetscErrorCode MPIU_File_read_all(MPI_File fd,void *data,PetscMPIInt cnt,MPI_Datatype dtype,MPI_Status *status)
842: {
844: PetscDataType pdtype;
847: PetscMPIDataTypeToPetscDataType(dtype,&pdtype);
848: MPI_File_read_all(fd,data,cnt,dtype,status);
849: PetscByteSwap(data,pdtype,cnt);
850: return(0);
851: }
852: #endif
853: #endif