Actual source code: sysio.c
petsc-3.10.5 2019-03-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: }
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:
469: Files access with PetscBinaryRead() and PetscBinaryWrite() are ALWAYS written in
470: big-endian format. This means the file can be accessed using PetscBinaryOpen() and
471: PetscBinaryRead() and PetscBinaryWrite() on any machine.
473: .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscFileMode, PetscViewerFileSetMode(), PetscViewerBinaryGetDescriptor(),
474: PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek()
476: @*/
477: PetscErrorCode PetscBinaryOpen(const char name[],PetscFileMode mode,int *fd)
478: {
480: #if defined(PETSC_HAVE_O_BINARY)
481: if (mode == FILE_MODE_WRITE) {
482: 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);
483: } else if (mode == FILE_MODE_READ) {
484: 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);
485: } else if (mode == FILE_MODE_APPEND) {
486: 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);
487: #else
488: if (mode == FILE_MODE_WRITE) {
489: if ((*fd = creat(name,0666)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot create file for writing: %s",name);
490: } else if (mode == FILE_MODE_READ) {
491: if ((*fd = open(name,O_RDONLY,0)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file for reading: %s",name);
492: }
493: else if (mode == FILE_MODE_APPEND) {
494: if ((*fd = open(name,O_WRONLY,0)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file for writing: %s",name);
495: #endif
496: } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown file mode");
497: return(0);
498: }
500: /*@
501: PetscBinaryClose - Closes a PETSc binary file.
503: Not Collective
505: Output Parameter:
506: . fd - the file
508: Level: advanced
510: .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
511: PetscBinarySynchronizedSeek()
512: @*/
513: PetscErrorCode PetscBinaryClose(int fd)
514: {
516: close(fd);
517: return(0);
518: }
521: /*@C
522: PetscBinarySeek - Moves the file pointer on a PETSc binary file.
524: Not Collective
526: Input Parameters:
527: + fd - the file
528: . off - number of bytes to move. Use PETSC_BINARY_INT_SIZE, PETSC_BINARY_SCALAR_SIZE,
529: etc. in your calculation rather than sizeof() to compute byte lengths.
530: - whence - if PETSC_BINARY_SEEK_SET then off is an absolute location in the file
531: if PETSC_BINARY_SEEK_CUR then off is an offset from the current location
532: if PETSC_BINARY_SEEK_END then off is an offset from the end of file
534: Output Parameter:
535: . offset - new offset in file
537: Level: developer
539: Notes:
540: Integers are stored on the file as 32 long, regardless of whether
541: they are stored in the machine as 32 or 64, this means the same
542: binary file may be read on any machine. Hence you CANNOT use sizeof()
543: to determine the offset or location.
545: Concepts: files^binary seeking
546: Concepts: binary files^seeking
548: .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
549: PetscBinarySynchronizedSeek()
550: @*/
551: PetscErrorCode PetscBinarySeek(int fd,off_t off,PetscBinarySeekType whence,off_t *offset)
552: {
553: int iwhence = 0;
556: if (whence == PETSC_BINARY_SEEK_SET) iwhence = SEEK_SET;
557: else if (whence == PETSC_BINARY_SEEK_CUR) iwhence = SEEK_CUR;
558: else if (whence == PETSC_BINARY_SEEK_END) iwhence = SEEK_END;
559: else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown seek location");
560: #if defined(PETSC_HAVE_LSEEK)
561: *offset = lseek(fd,off,iwhence);
562: #elif defined(PETSC_HAVE__LSEEK)
563: *offset = _lseek(fd,(long)off,iwhence);
564: #else
565: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS,"System does not have a way of seeking on a file");
566: #endif
567: return(0);
568: }
570: /*@C
571: PetscBinarySynchronizedRead - Reads from a binary file.
573: Collective on MPI_Comm
575: Input Parameters:
576: + comm - the MPI communicator
577: . fd - the file
578: . n - the number of items to read
579: - type - the type of items to read (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)
581: Output Parameters:
582: . p - the buffer
584: Level: developer
586: Notes:
587: Does a PetscBinaryRead() followed by an MPI_Bcast()
589: PetscBinarySynchronizedRead() uses byte swapping to work on all machines.
590: Integers are stored on the file as 32 long, regardless of whether
591: they are stored in the machine as 32 or 64, this means the same
592: binary file may be read on any machine.
594: Concepts: files^synchronized reading of binary files
595: Concepts: binary files^reading, synchronized
597: .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscBinaryRead(), PetscBinarySynchronizedWrite(),
598: PetscBinarySynchronizedSeek()
599: @*/
600: PetscErrorCode PetscBinarySynchronizedRead(MPI_Comm comm,int fd,void *p,PetscInt n,PetscDataType type)
601: {
602: PetscErrorCode ierr,ierrp=0;
603: PetscMPIInt rank;
604: MPI_Datatype mtype;
605: char *fname = NULL;
606: void *ptmp = NULL;
609: if (type == PETSC_FUNCTION) {
610: n = 64;
611: type = PETSC_CHAR;
612: ptmp = p;
613: fname = (char*)malloc(n*sizeof(char));
614: if (!fname) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Cannot allocate space for function name");
615: p = (void*)fname;
616: }
618: MPI_Comm_rank(comm,&rank);
619: if (!rank) {
620: ierrp = PetscBinaryRead(fd,p,n,type);
621: }
622: MPI_Bcast(&ierrp,1,MPI_INT,0,comm);
623: CHKERRQ(ierrp);
624: PetscDataTypeToMPIDataType(type,&mtype);
625: MPI_Bcast(p,n,mtype,0,comm);
627: if (type == PETSC_FUNCTION) {
628: #if defined(PETSC_SERIALIZE_FUNCTIONS)
629: PetscDLLibrarySym(PETSC_COMM_SELF,&PetscDLLibrariesLoaded,NULL,fname,(void**)ptmp);
630: #else
631: *(void**)ptmp = NULL;
632: #endif
633: free(fname);
634: }
635: return(0);
636: }
638: /*@C
639: PetscBinarySynchronizedWrite - writes to a binary file.
641: Collective on MPI_Comm
643: Input Parameters:
644: + comm - the MPI communicator
645: . fd - the file
646: . n - the number of items to write
647: . p - the buffer
648: . istemp - the buffer may be changed
649: - type - the type of items to write (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)
651: Level: developer
653: Notes:
654: Process 0 does a PetscBinaryWrite()
656: PetscBinarySynchronizedWrite() uses byte swapping to work on all machines.
657: Integers are stored on the file as 32 long, regardless of whether
658: they are stored in the machine as 32 or 64, this means the same
659: binary file may be read on any machine.
661: Notes:
662: because byte-swapping may be done on the values in data it cannot be declared const
664: WARNING: This is NOT like PetscSynchronizedFPrintf()! This routine ignores calls on all but process 0,
665: while PetscSynchronizedFPrintf() has all processes print their strings in order.
667: Concepts: files^synchronized writing of binary files
668: Concepts: binary files^reading, synchronized
670: .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscBinaryRead(), PetscBinarySynchronizedRead(),
671: PetscBinarySynchronizedSeek()
672: @*/
673: PetscErrorCode PetscBinarySynchronizedWrite(MPI_Comm comm,int fd,void *p,PetscInt n,PetscDataType type,PetscBool istemp)
674: {
676: PetscMPIInt rank;
679: MPI_Comm_rank(comm,&rank);
680: if (!rank) {
681: PetscBinaryWrite(fd,p,n,type,istemp);
682: }
683: return(0);
684: }
686: /*@C
687: PetscBinarySynchronizedSeek - Moves the file pointer on a PETSc binary file.
690: Input Parameters:
691: + fd - the file
692: . whence - if PETSC_BINARY_SEEK_SET then size is an absolute location in the file
693: if PETSC_BINARY_SEEK_CUR then size is offset from current location
694: if PETSC_BINARY_SEEK_END then size is offset from end of file
695: - off - number of bytes to move. Use PETSC_BINARY_INT_SIZE, PETSC_BINARY_SCALAR_SIZE,
696: etc. in your calculation rather than sizeof() to compute byte lengths.
698: Output Parameter:
699: . offset - new offset in file
701: Level: developer
703: Notes:
704: Integers are stored on the file as 32 long, regardless of whether
705: they are stored in the machine as 32 or 64, this means the same
706: binary file may be read on any machine. Hence you CANNOT use sizeof()
707: to determine the offset or location.
709: Concepts: binary files^seeking
710: Concepts: files^seeking in binary
712: .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
713: PetscBinarySynchronizedSeek()
714: @*/
715: PetscErrorCode PetscBinarySynchronizedSeek(MPI_Comm comm,int fd,off_t off,PetscBinarySeekType whence,off_t *offset)
716: {
718: PetscMPIInt rank;
721: MPI_Comm_rank(comm,&rank);
722: if (!rank) {
723: PetscBinarySeek(fd,off,whence,offset);
724: }
725: return(0);
726: }
728: #if defined(PETSC_HAVE_MPIIO)
729: #if !defined(PETSC_WORDS_BIGENDIAN)
731: #if defined(PETSC_USE_PETSC_MPI_EXTERNAL32)
732: /*
733: MPICH does not provide the external32 representation for MPI_File_set_view() so we need to provide the functions.
734: These are set into MPI in PetscInitialize() via MPI_Register_datarep()
736: Note I use PetscMPIInt for the MPI error codes since that is what MPI uses (instead of the standard PetscErrorCode)
738: The next three routines are not used because MPICH does not support their use
740: */
741: PETSC_EXTERN PetscMPIInt PetscDataRep_extent_fn(MPI_Datatype datatype,MPI_Aint *file_extent,void *extra_state)
742: {
743: MPI_Aint ub;
744: PetscMPIInt ierr;
746: MPI_Type_get_extent(datatype,&ub,file_extent);
747: return ierr;
748: }
750: PETSC_EXTERN PetscMPIInt PetscDataRep_read_conv_fn(void *userbuf, MPI_Datatype datatype,PetscMPIInt count,void *filebuf, MPI_Offset position,void *extra_state)
751: {
752: PetscDataType pdtype;
753: PetscMPIInt ierr;
754: size_t dsize;
756: PetscMPIDataTypeToPetscDataType(datatype,&pdtype);
757: PetscDataTypeGetSize(pdtype,&dsize);
759: /* offset is given in units of MPI_Datatype */
760: userbuf = ((char*)userbuf) + dsize*position;
762: PetscMemcpy(userbuf,filebuf,count*dsize);
763: PetscByteSwap(userbuf,pdtype,count);
764: return ierr;
765: }
767: PetscMPIInt PetscDataRep_write_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(filebuf,userbuf,count*dsize);
780: PetscByteSwap(filebuf,pdtype,count);
781: return ierr;
782: }
783: #endif
785: PetscErrorCode MPIU_File_write_all(MPI_File fd,void *data,PetscMPIInt cnt,MPI_Datatype dtype,MPI_Status *status)
786: {
788: PetscDataType pdtype;
791: PetscMPIDataTypeToPetscDataType(dtype,&pdtype);
792: PetscByteSwap(data,pdtype,cnt);
793: MPI_File_write_all(fd,data,cnt,dtype,status);
794: PetscByteSwap(data,pdtype,cnt);
795: return(0);
796: }
798: PetscErrorCode MPIU_File_read_all(MPI_File fd,void *data,PetscMPIInt cnt,MPI_Datatype dtype,MPI_Status *status)
799: {
801: PetscDataType pdtype;
804: PetscMPIDataTypeToPetscDataType(dtype,&pdtype);
805: MPI_File_read_all(fd,data,cnt,dtype,status);
806: PetscByteSwap(data,pdtype,cnt);
807: return(0);
808: }
809: #endif
810: #endif