Actual source code: sysio.c
petsc-3.8.4 2018-03-24
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: }
75: /* --------------------------------------------------------- */
76: /*
77: PetscByteSwapShort - Swap bytes in a short
78: */
79: PetscErrorCode PetscByteSwapShort(short *buff,PetscInt n)
80: {
81: PetscInt i,j;
82: short tmp;
83: char *ptr1,*ptr2 = (char*)&tmp;
86: for (j=0; j<n; j++) {
87: ptr1 = (char*)(buff + j);
88: for (i=0; i<(PetscInt) sizeof(short); i++) ptr2[i] = ptr1[sizeof(short)-1-i];
89: for (i=0; i<(PetscInt) sizeof(short); i++) ptr1[i] = ptr2[i];
90: }
91: return(0);
92: }
93: /* --------------------------------------------------------- */
94: /*
95: PetscByteSwapReal - Swap bytes in a PetscReal
96: */
97: PetscErrorCode PetscByteSwapReal(PetscReal *buff,PetscInt n)
98: {
99: PetscInt i,j;
100: PetscReal tmp,*buff1 = (PetscReal*)buff;
101: char *ptr1,*ptr2 = (char*)&tmp;
104: for (j=0; j<n; j++) {
105: ptr1 = (char*)(buff1 + j);
106: for (i=0; i<(PetscInt) sizeof(PetscReal); i++) ptr2[i] = ptr1[sizeof(PetscReal)-1-i];
107: for (i=0; i<(PetscInt) sizeof(PetscReal); i++) ptr1[i] = ptr2[i];
108: }
109: return(0);
110: }
111: /* --------------------------------------------------------- */
112: /*
113: PetscByteSwapScalar - Swap bytes in a PetscScalar
114: The complex case is dealt with with an array of PetscReal, twice as long.
115: */
116: PetscErrorCode PetscByteSwapScalar(PetscScalar *buff,PetscInt n)
117: {
118: PetscInt i,j;
119: PetscReal tmp,*buff1 = (PetscReal*)buff;
120: char *ptr1,*ptr2 = (char*)&tmp;
123: #if defined(PETSC_USE_COMPLEX)
124: n *= 2;
125: #endif
126: for (j=0; j<n; j++) {
127: ptr1 = (char*)(buff1 + j);
128: for (i=0; i<(PetscInt) sizeof(PetscReal); i++) ptr2[i] = ptr1[sizeof(PetscReal)-1-i];
129: for (i=0; i<(PetscInt) sizeof(PetscReal); i++) ptr1[i] = ptr2[i];
130: }
131: return(0);
132: }
133: /* --------------------------------------------------------- */
134: /*
135: PetscByteSwapDouble - Swap bytes in a double
136: */
137: PetscErrorCode PetscByteSwapDouble(double *buff,PetscInt n)
138: {
139: PetscInt i,j;
140: double tmp,*buff1 = (double*)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(double); i++) ptr2[i] = ptr1[sizeof(double)-1-i];
147: for (i=0; i<(PetscInt) sizeof(double); i++) ptr1[i] = ptr2[i];
148: }
149: return(0);
150: }
152: /*
153: PetscByteSwapFloat - Swap bytes in a float
154: */
155: PetscErrorCode PetscByteSwapFloat(float *buff,PetscInt n)
156: {
157: PetscInt i,j;
158: float tmp,*buff1 = (float*)buff;
159: char *ptr1,*ptr2 = (char*)&tmp;
162: for (j=0; j<n; j++) {
163: ptr1 = (char*)(buff1 + j);
164: for (i=0; i<(PetscInt) sizeof(float); i++) ptr2[i] = ptr1[sizeof(float)-1-i];
165: for (i=0; i<(PetscInt) sizeof(float); i++) ptr1[i] = ptr2[i];
166: }
167: return(0);
168: }
170: PetscErrorCode PetscByteSwap(void *data,PetscDataType pdtype,PetscInt count)
171: {
175: if (pdtype == PETSC_INT) {PetscByteSwapInt((PetscInt*)data,count);}
176: else if (pdtype == PETSC_ENUM) {PetscByteSwapEnum((PetscEnum*)data,count);}
177: else if (pdtype == PETSC_BOOL) {PetscByteSwapBool((PetscBool*)data,count);}
178: else if (pdtype == PETSC_SCALAR) {PetscByteSwapScalar((PetscScalar*)data,count);}
179: else if (pdtype == PETSC_REAL) {PetscByteSwapReal((PetscReal*)data,count);}
180: else if (pdtype == PETSC_DOUBLE) {PetscByteSwapDouble((double*)data,count);}
181: else if (pdtype == PETSC_FLOAT) {PetscByteSwapFloat((float*)data,count);}
182: else if (pdtype == PETSC_SHORT) {PetscByteSwapShort((short*)data,count);}
183: return(0);
184: }
186: /* --------------------------------------------------------- */
187: /*@
188: PetscBinaryRead - Reads from a binary file.
190: Not Collective
192: Input Parameters:
193: + fd - the file
194: . n - the number of items to read
195: - type - the type of items to read (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)
197: Output Parameters:
198: . p - the buffer
202: Level: developer
204: Notes:
205: PetscBinaryRead() uses byte swapping to work on all machines; the files
206: are written to file ALWAYS using big-endian ordering. On small-endian machines the numbers
207: are converted to the small-endian format when they are read in from the file.
208: When PETSc is ./configure with --with-64bit-indices the integers are written to the
209: file as 64 bit integers, this means they can only be read back in when the option --with-64bit-indices
210: is used.
212: Concepts: files^reading binary
213: Concepts: binary files^reading
215: .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscViewerBinaryGetDescriptor(), PetscBinarySynchronizedWrite(),
216: PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek()
217: @*/
218: PetscErrorCode PetscBinaryRead(int fd,void *p,PetscInt n,PetscDataType type)
219: {
220: int wsize,err;
221: size_t m = (size_t) n,maxblock = 65536;
222: char *pp = (char*)p;
223: #if defined(PETSC_USE_REAL___FLOAT128)
224: PetscBool readdouble = PETSC_FALSE;
225: double *ppp;
226: #endif
227: #if !defined(PETSC_WORDS_BIGENDIAN) || defined(PETSC_USE_REAL___FLOAT128)
228: PetscErrorCode ierr;
229: #endif
230: #if !defined(PETSC_WORDS_BIGENDIAN)
231: void *ptmp = p;
232: #endif
233: char *fname = NULL;
236: if (n < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Trying to write a negative amount of data %D",n);
237: if (!n) return(0);
239: if (type == PETSC_FUNCTION) {
240: m = 64;
241: type = PETSC_CHAR;
242: fname = (char*) malloc(m*sizeof(char));
243: if (!fname) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Cannot allocate space for function name");
244: pp = (char*)fname;
245: #if !defined(PETSC_WORDS_BIGENDIAN)
246: ptmp = (void*)fname;
247: #endif
248: }
250: if (type == PETSC_INT) m *= sizeof(PetscInt);
251: else if (type == PETSC_SCALAR) m *= sizeof(PetscScalar);
252: else if (type == PETSC_REAL) m *= sizeof(PetscReal);
253: else if (type == PETSC_DOUBLE) m *= sizeof(double);
254: else if (type == PETSC_FLOAT) m *= sizeof(float);
255: else if (type == PETSC_SHORT) m *= sizeof(short);
256: else if (type == PETSC_CHAR) m *= sizeof(char);
257: else if (type == PETSC_ENUM) m *= sizeof(PetscEnum);
258: else if (type == PETSC_BOOL) m *= sizeof(PetscBool);
259: else if (type == PETSC_BIT_LOGICAL) m = PetscBTLength(m)*sizeof(char);
260: else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown type");
262: #if defined(PETSC_USE_REAL___FLOAT128)
263: PetscOptionsGetBool(NULL,NULL,"-binary_read_double",&readdouble,NULL);
264: /* If using __float128 precision we still read in doubles from file */
265: if ((type == PETSC_SCALAR || type == PETSC_REAL) && readdouble) {
266: m = m/2;
267: PetscMalloc1(n,&ppp);
268: pp = (char*)ppp;
269: }
270: #endif
272: while (m) {
273: wsize = (m < maxblock) ? m : maxblock;
274: err = read(fd,pp,wsize);
275: if (err < 0 && errno == EINTR) continue;
276: if (!err && wsize > 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_READ,"Read past end of file");
277: if (err < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_READ,"Error reading from file, errno %d",errno);
278: m -= err;
279: pp += err;
280: }
282: #if defined(PETSC_USE_REAL___FLOAT128)
283: if ((type == PETSC_SCALAR || type == PETSC_REAL) && readdouble) {
284: PetscScalar *pv = (PetscScalar*) p;
285: PetscInt i;
286: #if !defined(PETSC_WORDS_BIGENDIAN)
287: PetscByteSwapDouble(ppp,n);
288: #endif
289: for (i=0; i<n; i++) pv[i] = ppp[i];
290: PetscFree(ppp);
291: return(0);
292: }
293: #endif
295: #if !defined(PETSC_WORDS_BIGENDIAN)
296: PetscByteSwap(ptmp,type,n);
297: #endif
299: if (type == PETSC_FUNCTION) {
300: #if defined(PETSC_SERIALIZE_FUNCTIONS)
301: PetscDLSym(NULL,fname,(void**)p);
302: #else
303: *(void**)p = NULL;
304: #endif
305: free(fname);
306: }
307: return(0);
308: }
309: /* --------------------------------------------------------- */
310: /*@
311: PetscBinaryWrite - Writes to a binary file.
313: Not Collective
315: Input Parameters:
316: + fd - the file
317: . p - the buffer
318: . n - the number of items to write
319: . type - the type of items to read (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)
320: - istemp - PETSC_FALSE if buffer data should be preserved, PETSC_TRUE otherwise.
322: Level: advanced
324: Notes:
325: PetscBinaryWrite() uses byte swapping to work on all machines; the files
326: are written using big-endian ordering to the file. On small-endian machines the numbers
327: are converted to the big-endian format when they are written to disk.
328: When PETSc is ./configure with --with-64bit-indices the integers are written to the
329: file as 64 bit integers, this means they can only be read back in when the option --with-64bit-indices
330: is used.
332: If running with __float128 precision the output is in __float128 unless one uses the -binary_write_double option
334: The Buffer p should be read-write buffer, and not static data.
335: This way, byte-swapping is done in-place, and then the buffer is
336: written to the file.
338: This routine restores the original contents of the buffer, after
339: it is written to the file. This is done by byte-swapping in-place
340: the second time. If the flag istemp is set to PETSC_TRUE, the second
341: byte-swapping operation is not done, thus saving some computation,
342: but the buffer is left corrupted.
344: Because byte-swapping may be done on the values in data it cannot be declared const
346: Concepts: files^writing binary
347: Concepts: binary files^writing
349: .seealso: PetscBinaryRead(), PetscBinaryOpen(), PetscBinaryClose(), PetscViewerBinaryGetDescriptor(), PetscBinarySynchronizedWrite(),
350: PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek()
351: @*/
352: PetscErrorCode PetscBinaryWrite(int fd,void *p,PetscInt n,PetscDataType type,PetscBool istemp)
353: {
354: char *pp = (char*)p;
355: int err,wsize;
356: size_t m = (size_t)n,maxblock=65536;
358: #if !defined(PETSC_WORDS_BIGENDIAN)
359: void *ptmp = p;
360: #endif
361: char *fname = NULL;
362: #if defined(PETSC_USE_REAL___FLOAT128)
363: PetscBool writedouble = PETSC_FALSE;
364: double *ppp;
365: PetscReal *pv;
366: PetscInt i;
367: #endif
368: PetscDataType wtype = type;
371: if (n < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Trying to write a negative amount of data %D",n);
372: if (!n) return(0);
374: if (type == PETSC_FUNCTION) {
375: #if defined(PETSC_SERIALIZE_FUNCTIONS)
376: const char *fnametmp;
377: #endif
378: m = 64;
379: fname = (char*)malloc(m*sizeof(char));
380: if (!fname) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Cannot allocate space for function name");
381: #if defined(PETSC_SERIALIZE_FUNCTIONS)
382: if (n > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Can only binary view a single function at a time");
383: PetscFPTFind(*(void**)p,&fnametmp);
384: PetscStrncpy(fname,fnametmp,m);
385: #else
386: PetscStrncpy(fname,"",m);
387: #endif
388: wtype = PETSC_CHAR;
389: pp = (char*)fname;
390: #if !defined(PETSC_WORDS_BIGENDIAN)
391: ptmp = (void*)fname;
392: #endif
393: }
395: #if defined(PETSC_USE_REAL___FLOAT128)
396: PetscOptionsGetBool(NULL,NULL,"-binary_write_double",&writedouble,NULL);
397: /* If using __float128 precision we still write in doubles to file */
398: if ((type == PETSC_SCALAR || type == PETSC_REAL) && writedouble) {
399: wtype = PETSC_DOUBLE;
400: PetscMalloc1(n,&ppp);
401: pv = (PetscReal*)pp;
402: for (i=0; i<n; i++) {
403: ppp[i] = (double) pv[i];
404: }
405: pp = (char*)ppp;
406: ptmp = (char*)ppp;
407: }
408: #endif
410: if (wtype == PETSC_INT) m *= sizeof(PetscInt);
411: else if (wtype == PETSC_SCALAR) m *= sizeof(PetscScalar);
412: else if (wtype == PETSC_REAL) m *= sizeof(PetscReal);
413: else if (wtype == PETSC_DOUBLE) m *= sizeof(double);
414: else if (wtype == PETSC_FLOAT) m *= sizeof(float);
415: else if (wtype == PETSC_SHORT) m *= sizeof(short);
416: else if (wtype == PETSC_CHAR) m *= sizeof(char);
417: else if (wtype == PETSC_ENUM) m *= sizeof(PetscEnum);
418: else if (wtype == PETSC_BOOL) m *= sizeof(PetscBool);
419: else if (wtype == PETSC_BIT_LOGICAL) m = PetscBTLength(m)*sizeof(char);
420: else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown type");
422: #if !defined(PETSC_WORDS_BIGENDIAN)
423: PetscByteSwap(ptmp,wtype,n);
424: #endif
426: while (m) {
427: wsize = (m < maxblock) ? m : maxblock;
428: err = write(fd,pp,wsize);
429: if (err < 0 && errno == EINTR) continue;
430: 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);
431: m -= wsize;
432: pp += wsize;
433: }
435: #if !defined(PETSC_WORDS_BIGENDIAN)
436: if (!istemp) {
437: PetscByteSwap(ptmp,wtype,n);
438: }
439: #endif
440: if (type == PETSC_FUNCTION) {
441: free(fname);
442: }
443: #if defined(PETSC_USE_REAL___FLOAT128)
444: if ((type == PETSC_SCALAR || type == PETSC_REAL) && writedouble) {
445: PetscFree(ppp);
446: }
447: #endif
448: return(0);
449: }
451: /*@C
452: PetscBinaryOpen - Opens a PETSc binary file.
454: Not Collective
456: Input Parameters:
457: + name - filename
458: - type - type of binary file, one of FILE_MODE_READ, FILE_MODE_APPEND, FILE_MODE_WRITE
460: Output Parameter:
461: . fd - the file
463: Level: advanced
465: Concepts: files^opening binary
466: Concepts: binary files^opening
468: Notes: Files access with PetscBinaryRead() and PetscBinaryWrite() are ALWAYS written in
469: big-endian format. This means the file can be accessed using PetscBinaryOpen() and
470: PetscBinaryRead() and PetscBinaryWrite() on any machine.
472: .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscFileMode, PetscViewerFileSetMode(), PetscViewerBinaryGetDescriptor(),
473: PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek()
475: @*/
476: PetscErrorCode PetscBinaryOpen(const char name[],PetscFileMode mode,int *fd)
477: {
479: #if defined(PETSC_HAVE_O_BINARY)
480: if (mode == FILE_MODE_WRITE) {
481: 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);
482: } else if (mode == FILE_MODE_READ) {
483: 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);
484: } else if (mode == FILE_MODE_APPEND) {
485: 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);
486: #else
487: if (mode == FILE_MODE_WRITE) {
488: if ((*fd = creat(name,0666)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot create file for writing: %s",name);
489: } else if (mode == FILE_MODE_READ) {
490: if ((*fd = open(name,O_RDONLY,0)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file for reading: %s",name);
491: }
492: else if (mode == FILE_MODE_APPEND) {
493: if ((*fd = open(name,O_WRONLY,0)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file for writing: %s",name);
494: #endif
495: } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown file mode");
496: return(0);
497: }
499: /*@
500: PetscBinaryClose - Closes a PETSc binary file.
502: Not Collective
504: Output Parameter:
505: . fd - the file
507: Level: advanced
509: .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
510: PetscBinarySynchronizedSeek()
511: @*/
512: PetscErrorCode PetscBinaryClose(int fd)
513: {
515: close(fd);
516: return(0);
517: }
520: /*@C
521: PetscBinarySeek - Moves the file pointer on a PETSc binary file.
523: Not Collective
525: Input Parameters:
526: + fd - the file
527: . off - number of bytes to move. Use PETSC_BINARY_INT_SIZE, PETSC_BINARY_SCALAR_SIZE,
528: etc. in your calculation rather than sizeof() to compute byte lengths.
529: - whence - if PETSC_BINARY_SEEK_SET then off is an absolute location in the file
530: if PETSC_BINARY_SEEK_CUR then off is an offset from the current location
531: if PETSC_BINARY_SEEK_END then off is an offset from the end of file
533: Output Parameter:
534: . offset - new offset in file
536: Level: developer
538: Notes:
539: Integers are stored on the file as 32 long, regardless of whether
540: they are stored in the machine as 32 or 64, this means the same
541: binary file may be read on any machine. Hence you CANNOT use sizeof()
542: to determine the offset or location.
544: Concepts: files^binary seeking
545: Concepts: binary files^seeking
547: .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
548: PetscBinarySynchronizedSeek()
549: @*/
550: PetscErrorCode PetscBinarySeek(int fd,off_t off,PetscBinarySeekType whence,off_t *offset)
551: {
552: int iwhence = 0;
555: if (whence == PETSC_BINARY_SEEK_SET) iwhence = SEEK_SET;
556: else if (whence == PETSC_BINARY_SEEK_CUR) iwhence = SEEK_CUR;
557: else if (whence == PETSC_BINARY_SEEK_END) iwhence = SEEK_END;
558: else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown seek location");
559: #if defined(PETSC_HAVE_LSEEK)
560: *offset = lseek(fd,off,iwhence);
561: #elif defined(PETSC_HAVE__LSEEK)
562: *offset = _lseek(fd,(long)off,iwhence);
563: #else
564: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS,"System does not have a way of seeking on a file");
565: #endif
566: return(0);
567: }
569: /*@C
570: PetscBinarySynchronizedRead - Reads from a binary file.
572: Collective on MPI_Comm
574: Input Parameters:
575: + comm - the MPI communicator
576: . fd - the file
577: . n - the number of items to read
578: - type - the type of items to read (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)
580: Output Parameters:
581: . p - the buffer
583: Level: developer
585: Notes:
586: Does a PetscBinaryRead() followed by an MPI_Bcast()
588: PetscBinarySynchronizedRead() uses byte swapping to work on all machines.
589: Integers are stored on the file as 32 long, regardless of whether
590: they are stored in the machine as 32 or 64, this means the same
591: binary file may be read on any machine.
593: Concepts: files^synchronized reading of binary files
594: Concepts: binary files^reading, synchronized
596: .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscBinaryRead(), PetscBinarySynchronizedWrite(),
597: PetscBinarySynchronizedSeek()
598: @*/
599: PetscErrorCode PetscBinarySynchronizedRead(MPI_Comm comm,int fd,void *p,PetscInt n,PetscDataType type)
600: {
601: PetscErrorCode ierr,ierrp=0;
602: PetscMPIInt rank;
603: MPI_Datatype mtype;
604: char *fname = NULL;
605: void *ptmp = NULL;
608: if (type == PETSC_FUNCTION) {
609: n = 64;
610: type = PETSC_CHAR;
611: ptmp = p;
612: fname = (char*)malloc(n*sizeof(char));
613: if (!fname) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Cannot allocate space for function name");
614: p = (void*)fname;
615: }
617: MPI_Comm_rank(comm,&rank);
618: if (!rank) {
619: ierrp = PetscBinaryRead(fd,p,n,type);
620: }
621: MPI_Bcast(&ierrp,1,MPI_INT,0,comm);
622: CHKERRQ(ierrp);
623: PetscDataTypeToMPIDataType(type,&mtype);
624: MPI_Bcast(p,n,mtype,0,comm);
626: if (type == PETSC_FUNCTION) {
627: #if defined(PETSC_SERIALIZE_FUNCTIONS)
628: PetscDLLibrarySym(PETSC_COMM_SELF,&PetscDLLibrariesLoaded,NULL,fname,(void**)ptmp);
629: #else
630: *(void**)ptmp = NULL;
631: #endif
632: free(fname);
633: }
634: return(0);
635: }
637: /*@C
638: PetscBinarySynchronizedWrite - writes to a binary file.
640: Collective on MPI_Comm
642: Input Parameters:
643: + comm - the MPI communicator
644: . fd - the file
645: . n - the number of items to write
646: . p - the buffer
647: . istemp - the buffer may be changed
648: - type - the type of items to write (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)
650: Level: developer
652: Notes:
653: Process 0 does a PetscBinaryWrite()
655: PetscBinarySynchronizedWrite() uses byte swapping to work on all machines.
656: Integers are stored on the file as 32 long, regardless of whether
657: they are stored in the machine as 32 or 64, this means the same
658: binary file may be read on any machine.
660: Notes: because byte-swapping may be done on the values in data it cannot be declared const
662: WARNING: This is NOT like PetscSynchronizedFPrintf()! This routine ignores calls on all but process 0,
663: while PetscSynchronizedFPrintf() has all processes print their strings in order.
665: Concepts: files^synchronized writing of binary files
666: Concepts: binary files^reading, synchronized
668: .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscBinaryRead(), PetscBinarySynchronizedRead(),
669: PetscBinarySynchronizedSeek()
670: @*/
671: PetscErrorCode PetscBinarySynchronizedWrite(MPI_Comm comm,int fd,void *p,PetscInt n,PetscDataType type,PetscBool istemp)
672: {
674: PetscMPIInt rank;
677: MPI_Comm_rank(comm,&rank);
678: if (!rank) {
679: PetscBinaryWrite(fd,p,n,type,istemp);
680: }
681: return(0);
682: }
684: /*@C
685: PetscBinarySynchronizedSeek - Moves the file pointer on a PETSc binary file.
688: Input Parameters:
689: + fd - the file
690: . whence - if PETSC_BINARY_SEEK_SET then size is an absolute location in the file
691: if PETSC_BINARY_SEEK_CUR then size is offset from current location
692: if PETSC_BINARY_SEEK_END then size is offset from end of file
693: - off - number of bytes to move. Use PETSC_BINARY_INT_SIZE, PETSC_BINARY_SCALAR_SIZE,
694: etc. in your calculation rather than sizeof() to compute byte lengths.
696: Output Parameter:
697: . offset - new offset in file
699: Level: developer
701: Notes:
702: Integers are stored on the file as 32 long, regardless of whether
703: they are stored in the machine as 32 or 64, this means the same
704: binary file may be read on any machine. Hence you CANNOT use sizeof()
705: to determine the offset or location.
707: Concepts: binary files^seeking
708: Concepts: files^seeking in binary
710: .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
711: PetscBinarySynchronizedSeek()
712: @*/
713: PetscErrorCode PetscBinarySynchronizedSeek(MPI_Comm comm,int fd,off_t off,PetscBinarySeekType whence,off_t *offset)
714: {
716: PetscMPIInt rank;
719: MPI_Comm_rank(comm,&rank);
720: if (!rank) {
721: PetscBinarySeek(fd,off,whence,offset);
722: }
723: return(0);
724: }
726: #if defined(PETSC_HAVE_MPIIO)
727: #if !defined(PETSC_WORDS_BIGENDIAN)
729: #if defined(PETSC_USE_PETSC_MPI_EXTERNAL32)
730: /*
731: MPICH does not provide the external32 representation for MPI_File_set_view() so we need to provide the functions.
732: These are set into MPI in PetscInitialize() via MPI_Register_datarep()
734: Note I use PetscMPIInt for the MPI error codes since that is what MPI uses (instead of the standard PetscErrorCode)
736: The next three routines are not used because MPICH does not support their use
738: */
739: PETSC_EXTERN PetscMPIInt PetscDataRep_extent_fn(MPI_Datatype datatype,MPI_Aint *file_extent,void *extra_state)
740: {
741: MPI_Aint ub;
742: PetscMPIInt ierr;
744: MPI_Type_get_extent(datatype,&ub,file_extent);
745: return ierr;
746: }
748: PETSC_EXTERN PetscMPIInt PetscDataRep_read_conv_fn(void *userbuf, MPI_Datatype datatype,PetscMPIInt count,void *filebuf, MPI_Offset position,void *extra_state)
749: {
750: PetscDataType pdtype;
751: PetscMPIInt ierr;
752: size_t dsize;
754: PetscMPIDataTypeToPetscDataType(datatype,&pdtype);
755: PetscDataTypeGetSize(pdtype,&dsize);
757: /* offset is given in units of MPI_Datatype */
758: userbuf = ((char*)userbuf) + dsize*position;
760: PetscMemcpy(userbuf,filebuf,count*dsize);
761: PetscByteSwap(userbuf,pdtype,count);
762: return ierr;
763: }
765: PetscMPIInt PetscDataRep_write_conv_fn(void *userbuf, MPI_Datatype datatype,PetscMPIInt count,void *filebuf, MPI_Offset position,void *extra_state)
766: {
767: PetscDataType pdtype;
768: PetscMPIInt ierr;
769: size_t dsize;
771: PetscMPIDataTypeToPetscDataType(datatype,&pdtype);
772: PetscDataTypeGetSize(pdtype,&dsize);
774: /* offset is given in units of MPI_Datatype */
775: userbuf = ((char*)userbuf) + dsize*position;
777: PetscMemcpy(filebuf,userbuf,count*dsize);
778: PetscByteSwap(filebuf,pdtype,count);
779: return ierr;
780: }
781: #endif
783: PetscErrorCode MPIU_File_write_all(MPI_File fd,void *data,PetscMPIInt cnt,MPI_Datatype dtype,MPI_Status *status)
784: {
786: PetscDataType pdtype;
789: PetscMPIDataTypeToPetscDataType(dtype,&pdtype);
790: PetscByteSwap(data,pdtype,cnt);
791: MPI_File_write_all(fd,data,cnt,dtype,status);
792: PetscByteSwap(data,pdtype,cnt);
793: return(0);
794: }
796: PetscErrorCode MPIU_File_read_all(MPI_File fd,void *data,PetscMPIInt cnt,MPI_Datatype dtype,MPI_Status *status)
797: {
799: PetscDataType pdtype;
802: PetscMPIDataTypeToPetscDataType(dtype,&pdtype);
803: MPI_File_read_all(fd,data,cnt,dtype,status);
804: PetscByteSwap(data,pdtype,cnt);
805: return(0);
806: }
807: #endif
808: #endif