Actual source code: sysio.c
petsc-3.4.5 2014-06-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: /* --------------------------------------------------------- */
22: /*
23: PetscByteSwapEnum - Swap bytes in a PETSc Enum
25: */
26: PetscErrorCode PetscByteSwapEnum(PetscEnum *buff,PetscInt n)
27: {
28: PetscInt i,j;
29: PetscEnum tmp = ENUM_DUMMY;
30: char *ptr1,*ptr2 = (char*)&tmp;
33: for (j=0; j<n; j++) {
34: ptr1 = (char*)(buff + j);
35: for (i=0; i<(PetscInt)sizeof(PetscEnum); i++) ptr2[i] = ptr1[sizeof(PetscEnum)-1-i];
36: for (i=0; i<(PetscInt)sizeof(PetscEnum); i++) ptr1[i] = ptr2[i];
37: }
38: return(0);
39: }
43: /*
44: PetscByteSwapBool - Swap bytes in a PETSc Bool
46: */
47: PetscErrorCode PetscByteSwapBool(PetscBool *buff,PetscInt n)
48: {
49: PetscInt i,j;
50: PetscBool tmp = PETSC_FALSE;
51: char *ptr1,*ptr2 = (char*)&tmp;
54: for (j=0; j<n; j++) {
55: ptr1 = (char*)(buff + j);
56: for (i=0; i<(PetscInt)sizeof(PetscBool); i++) ptr2[i] = ptr1[sizeof(PetscBool)-1-i];
57: for (i=0; i<(PetscInt)sizeof(PetscBool); i++) ptr1[i] = ptr2[i];
58: }
59: return(0);
60: }
64: /*
65: PetscByteSwapInt - Swap bytes in a PETSc integer (which may be 32 or 64 bits)
67: */
68: PetscErrorCode PetscByteSwapInt(PetscInt *buff,PetscInt n)
69: {
70: PetscInt i,j,tmp = 0;
71: char *ptr1,*ptr2 = (char*)&tmp;
74: for (j=0; j<n; j++) {
75: ptr1 = (char*)(buff + j);
76: for (i=0; i<(PetscInt)sizeof(PetscInt); i++) ptr2[i] = ptr1[sizeof(PetscInt)-1-i];
77: for (i=0; i<(PetscInt)sizeof(PetscInt); i++) ptr1[i] = ptr2[i];
78: }
79: return(0);
80: }
81: /* --------------------------------------------------------- */
84: /*
85: PetscByteSwapShort - Swap bytes in a short
86: */
87: PetscErrorCode PetscByteSwapShort(short *buff,PetscInt n)
88: {
89: PetscInt i,j;
90: short tmp;
91: char *ptr1,*ptr2 = (char*)&tmp;
94: for (j=0; j<n; j++) {
95: ptr1 = (char*)(buff + j);
96: for (i=0; i<(PetscInt) sizeof(short); i++) ptr2[i] = ptr1[sizeof(short)-1-i];
97: for (i=0; i<(PetscInt) sizeof(short); i++) ptr1[i] = ptr2[i];
98: }
99: return(0);
100: }
101: /* --------------------------------------------------------- */
104: /*
105: PetscByteSwapScalar - Swap bytes in a double
106: Complex is dealt with as if array of double twice as long.
107: */
108: PetscErrorCode PetscByteSwapScalar(PetscScalar *buff,PetscInt n)
109: {
110: PetscInt i,j;
111: PetscReal tmp,*buff1 = (PetscReal*)buff;
112: char *ptr1,*ptr2 = (char*)&tmp;
115: #if defined(PETSC_USE_COMPLEX)
116: n *= 2;
117: #endif
118: for (j=0; j<n; j++) {
119: ptr1 = (char*)(buff1 + j);
120: for (i=0; i<(PetscInt) sizeof(PetscReal); i++) ptr2[i] = ptr1[sizeof(PetscReal)-1-i];
121: for (i=0; i<(PetscInt) sizeof(PetscReal); i++) ptr1[i] = ptr2[i];
122: }
123: return(0);
124: }
125: /* --------------------------------------------------------- */
128: /*
129: PetscByteSwapDouble - Swap bytes in a double
130: */
131: PetscErrorCode PetscByteSwapDouble(double *buff,PetscInt n)
132: {
133: PetscInt i,j;
134: double tmp,*buff1 = (double*)buff;
135: char *ptr1,*ptr2 = (char*)&tmp;
138: for (j=0; j<n; j++) {
139: ptr1 = (char*)(buff1 + j);
140: for (i=0; i<(PetscInt) sizeof(double); i++) ptr2[i] = ptr1[sizeof(double)-1-i];
141: for (i=0; i<(PetscInt) sizeof(double); i++) ptr1[i] = ptr2[i];
142: }
143: return(0);
144: }
148: /*
149: PetscByteSwapFloat - Swap bytes in a float
150: */
151: PetscErrorCode PetscByteSwapFloat(float *buff,PetscInt n)
152: {
153: PetscInt i,j;
154: float tmp,*buff1 = (float*)buff;
155: char *ptr1,*ptr2 = (char*)&tmp;
158: for (j=0; j<n; j++) {
159: ptr1 = (char*)(buff1 + j);
160: for (i=0; i<(PetscInt) sizeof(float); i++) ptr2[i] = ptr1[sizeof(float)-1-i];
161: for (i=0; i<(PetscInt) sizeof(float); i++) ptr1[i] = ptr2[i];
162: }
163: return(0);
164: }
168: PetscErrorCode PetscByteSwap(void *data,PetscDataType pdtype,PetscInt count)
169: {
173: if (pdtype == PETSC_INT) {PetscByteSwapInt((PetscInt*)data,count);}
174: else if (pdtype == PETSC_ENUM) {PetscByteSwapEnum((PetscEnum*)data,count);}
175: else if (pdtype == PETSC_BOOL) {PetscByteSwapBool((PetscBool*)data,count);}
176: else if (pdtype == PETSC_SCALAR) {PetscByteSwapScalar((PetscScalar*)data,count);}
177: else if (pdtype == PETSC_DOUBLE) {PetscByteSwapDouble((double*)data,count);}
178: else if (pdtype == PETSC_FLOAT) {PetscByteSwapFloat((float*)data,count);}
179: else if (pdtype == PETSC_SHORT) {PetscByteSwapShort((short*)data,count);}
180: return(0);
181: }
183: /* --------------------------------------------------------- */
186: /*@
187: PetscBinaryRead - Reads from a binary file.
189: Not Collective
191: Input Parameters:
192: + fd - the file
193: . n - the number of items to read
194: - type - the type of items to read (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)
196: Output Parameters:
197: . p - the buffer
201: Level: developer
203: Notes:
204: PetscBinaryRead() uses byte swapping to work on all machines; the files
205: are written to file ALWAYS using big-endian ordering. On small-endian machines the numbers
206: are converted to the small-endian format when they are read in from the file.
207: When PETSc is ./configure with --with-64bit-indices the integers are written to the
208: file as 64 bit integers, this means they can only be read back in when the option --with-64bit-indices
209: is used.
211: Concepts: files^reading binary
212: Concepts: binary files^reading
214: .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscViewerBinaryGetDescriptor(), PetscBinarySynchronizedWrite(),
215: PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek()
216: @*/
217: PetscErrorCode PetscBinaryRead(int fd,void *p,PetscInt n,PetscDataType type)
218: {
219: int wsize,err;
220: size_t m = (size_t) n,maxblock = 65536;
221: char *pp = (char*)p;
222: #if defined(PETSC_USE_REAL___FLOAT128)
223: double *ppp;
224: #endif
225: #if !defined(PETSC_WORDS_BIGENDIAN) || defined(PETSC_USE_REAL___FLOAT128)
226: PetscErrorCode ierr;
227: #endif
228: #if !defined(PETSC_WORDS_BIGENDIAN)
229: void *ptmp = p;
230: #endif
231: char fname[64];
232: PetscBool functionload = PETSC_FALSE;
235: if (n < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Trying to write a negative amount of data %D",n);
236: if (!n) return(0);
238: if (type == PETSC_FUNCTION) {
239: functionload = PETSC_TRUE;
240: m = 64;
241: type = PETSC_CHAR;
242: pp = (char*)fname;
243: #if !defined(PETSC_WORDS_BIGENDIAN)
244: ptmp = (void*)fname;
245: #endif
246: }
248: if (type == PETSC_INT) m *= sizeof(PetscInt);
249: else if (type == PETSC_SCALAR) m *= sizeof(PetscScalar);
250: else if (type == PETSC_DOUBLE) m *= sizeof(double);
251: else if (type == PETSC_FLOAT) m *= sizeof(float);
252: else if (type == PETSC_SHORT) m *= sizeof(short);
253: else if (type == PETSC_CHAR) m *= sizeof(char);
254: else if (type == PETSC_ENUM) m *= sizeof(PetscEnum);
255: else if (type == PETSC_BOOL) m *= sizeof(PetscBool);
256: else if (type == PETSC_BIT_LOGICAL) m = PetscBTLength(m)*sizeof(char);
257: else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown type");
259: #if defined(PETSC_USE_REAL___FLOAT128)
260: /* If using __float128 precision we still read in doubles from file */
261: if (type == PETSC_SCALAR) {
262: m = m/2;
263: PetscMalloc(n*sizeof(double),&ppp);
264: pp = (char*)ppp;
265: }
266: #endif
268: while (m) {
269: wsize = (m < maxblock) ? m : maxblock;
270: err = read(fd,pp,wsize);
271: if (err < 0 && errno == EINTR) continue;
272: if (!err && wsize > 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_READ,"Read past end of file");
273: if (err < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_READ,"Error reading from file, errno %d",errno);
274: m -= err;
275: pp += err;
276: }
278: #if defined(PETSC_USE_REAL___FLOAT128)
279: if (type == PETSC_SCALAR) {
280: PetscScalar *pv = (PetscScalar*) p;
281: PetscInt i;
282: #if !defined(PETSC_WORDS_BIGENDIAN)
283: PetscByteSwapDouble(ppp,n);
284: #endif
285: for (i=0; i<n; i++) pv[i] = ppp[i];
286: PetscFree(ppp);
287: return(0);
288: }
289: #endif
291: #if !defined(PETSC_WORDS_BIGENDIAN)
292: PetscByteSwap(ptmp,type,n);
293: #endif
295: if (functionload) {
296: #if defined(PETSC_SERIALIZE_FUNCTIONS)
297: PetscDLSym(NULL,fname,(void**)p);
298: #else
299: *(void**)p = NULL;
300: #endif
301: }
302: return(0);
303: }
304: /* --------------------------------------------------------- */
307: /*@
308: PetscBinaryWrite - Writes to a binary file.
310: Not Collective
312: Input Parameters:
313: + fd - the file
314: . p - the buffer
315: . n - the number of items to write
316: . type - the type of items to read (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)
317: - istemp - PETSC_FALSE if buffer data should be preserved, PETSC_TRUE otherwise.
319: Level: advanced
321: Notes:
322: PetscBinaryWrite() uses byte swapping to work on all machines; the files
323: are written using big-endian ordering to the file. On small-endian machines the numbers
324: are converted to the big-endian format when they are written to disk.
325: When PETSc is ./configure with --with-64bit-indices the integers are written to the
326: file as 64 bit integers, this means they can only be read back in when the option --with-64bit-indices
327: is used.
329: The Buffer p should be read-write buffer, and not static data.
330: This way, byte-swapping is done in-place, and then the buffer is
331: written to the file.
333: This routine restores the original contents of the buffer, after
334: it is written to the file. This is done by byte-swapping in-place
335: the second time. If the flag istemp is set to PETSC_TRUE, the second
336: byte-swapping operation is not done, thus saving some computation,
337: but the buffer is left corrupted.
339: Because byte-swapping may be done on the values in data it cannot be declared const
341: Concepts: files^writing binary
342: Concepts: binary files^writing
344: .seealso: PetscBinaryRead(), PetscBinaryOpen(), PetscBinaryClose(), PetscViewerBinaryGetDescriptor(), PetscBinarySynchronizedWrite(),
345: PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek()
346: @*/
347: PetscErrorCode PetscBinaryWrite(int fd,void *p,PetscInt n,PetscDataType type,PetscBool istemp)
348: {
349: char *pp = (char*)p;
350: int err,wsize;
351: size_t m = (size_t)n,maxblock=65536;
353: #if !defined(PETSC_WORDS_BIGENDIAN)
354: void *ptmp = p;
355: #endif
356: char fname[64];
359: if (n < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Trying to write a negative amount of data %D",n);
360: if (!n) return(0);
362: if (type == PETSC_FUNCTION) {
363: #if defined(PETSC_SERIALIZE_FUNCTIONS)
364: const char *fnametmp;
366: if (n > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Can only binary view a single function at a time");
367: PetscFPTFind(p,&fnametmp);
368: PetscStrncpy(fname,fnametmp,64);
369: #else
370: PetscStrncpy(fname,"",64);
371: #endif
372: m = 64;
373: type = PETSC_CHAR;
374: pp = (char*)fname;
375: #if !defined(PETSC_WORDS_BIGENDIAN)
376: ptmp = (void*)fname;
377: #endif
378: }
380: if (type == PETSC_INT) m *= sizeof(PetscInt);
381: else if (type == PETSC_SCALAR) m *= sizeof(PetscScalar);
382: else if (type == PETSC_DOUBLE) m *= sizeof(double);
383: else if (type == PETSC_FLOAT) m *= sizeof(float);
384: else if (type == PETSC_SHORT) m *= sizeof(short);
385: else if (type == PETSC_CHAR) m *= sizeof(char);
386: else if (type == PETSC_ENUM) m *= sizeof(PetscEnum);
387: else if (type == PETSC_BOOL) m *= sizeof(PetscBool);
388: else if (type == PETSC_BIT_LOGICAL) m = PetscBTLength(m)*sizeof(char);
389: else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown type");
391: #if !defined(PETSC_WORDS_BIGENDIAN)
392: PetscByteSwap(ptmp,type,n);
393: #endif
395: while (m) {
396: wsize = (m < maxblock) ? m : maxblock;
397: err = write(fd,pp,wsize);
398: if (err < 0 && errno == EINTR) continue;
399: if (err != wsize) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_WRITE,"Error writing to file.");
400: m -= wsize;
401: pp += wsize;
402: }
404: #if !defined(PETSC_WORDS_BIGENDIAN)
405: if (!istemp) {
406: PetscByteSwap(ptmp,type,n);
407: }
408: #endif
409: return(0);
410: }
414: /*@C
415: PetscBinaryOpen - Opens a PETSc binary file.
417: Not Collective
419: Input Parameters:
420: + name - filename
421: - type - type of binary file, one of FILE_MODE_READ, FILE_MODE_APPEND, FILE_MODE_WRITE
423: Output Parameter:
424: . fd - the file
426: Level: advanced
428: Concepts: files^opening binary
429: Concepts: binary files^opening
431: Notes: Files access with PetscBinaryRead() and PetscBinaryWrite() are ALWAYS written in
432: big-endian format. This means the file can be accessed using PetscBinaryOpen() and
433: PetscBinaryRead() and PetscBinaryWrite() on any machine.
435: .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscFileMode, PetscViewerFileSetMode(), PetscViewerBinaryGetDescriptor(),
436: PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek()
438: @*/
439: PetscErrorCode PetscBinaryOpen(const char name[],PetscFileMode mode,int *fd)
440: {
442: #if defined(PETSC_HAVE_O_BINARY)
443: if (mode == FILE_MODE_WRITE) {
444: 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);
445: } else if (mode == FILE_MODE_READ) {
446: 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);
447: } else if (mode == FILE_MODE_APPEND) {
448: 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);
449: #else
450: if (mode == FILE_MODE_WRITE) {
451: if ((*fd = creat(name,0666)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot create file for writing: %s",name);
452: } else if (mode == FILE_MODE_READ) {
453: if ((*fd = open(name,O_RDONLY,0)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file for reading: %s",name);
454: }
455: else if (mode == FILE_MODE_APPEND) {
456: if ((*fd = open(name,O_WRONLY,0)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file for writing: %s",name);
457: #endif
458: } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown file mode");
459: return(0);
460: }
464: /*@
465: PetscBinaryClose - Closes a PETSc binary file.
467: Not Collective
469: Output Parameter:
470: . fd - the file
472: Level: advanced
474: .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
475: PetscBinarySynchronizedSeek()
476: @*/
477: PetscErrorCode PetscBinaryClose(int fd)
478: {
480: close(fd);
481: return(0);
482: }
487: /*@
488: PetscBinarySeek - Moves the file pointer on a PETSc binary file.
490: Not Collective
492: Input Parameters:
493: + fd - the file
494: . off - number of bytes to move. Use PETSC_BINARY_INT_SIZE, PETSC_BINARY_SCALAR_SIZE,
495: etc. in your calculation rather than sizeof() to compute byte lengths.
496: - whence - if PETSC_BINARY_SEEK_SET then off is an absolute location in the file
497: if PETSC_BINARY_SEEK_CUR then off is an offset from the current location
498: if PETSC_BINARY_SEEK_END then off is an offset from the end of file
500: Output Parameter:
501: . offset - new offset in file
503: Level: developer
505: Notes:
506: Integers are stored on the file as 32 long, regardless of whether
507: they are stored in the machine as 32 or 64, this means the same
508: binary file may be read on any machine. Hence you CANNOT use sizeof()
509: to determine the offset or location.
511: Concepts: files^binary seeking
512: Concepts: binary files^seeking
514: .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
515: PetscBinarySynchronizedSeek()
516: @*/
517: PetscErrorCode PetscBinarySeek(int fd,off_t off,PetscBinarySeekType whence,off_t *offset)
518: {
519: int iwhence = 0;
522: if (whence == PETSC_BINARY_SEEK_SET) iwhence = SEEK_SET;
523: else if (whence == PETSC_BINARY_SEEK_CUR) iwhence = SEEK_CUR;
524: else if (whence == PETSC_BINARY_SEEK_END) iwhence = SEEK_END;
525: else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown seek location");
526: #if defined(PETSC_HAVE_LSEEK)
527: *offset = lseek(fd,off,iwhence);
528: #elif defined(PETSC_HAVE__LSEEK)
529: *offset = _lseek(fd,(long)off,iwhence);
530: #else
531: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS,"System does not have a way of seeking on a file");
532: #endif
533: return(0);
534: }
538: /*@C
539: PetscBinarySynchronizedRead - Reads from a binary file.
541: Collective on MPI_Comm
543: Input Parameters:
544: + comm - the MPI communicator
545: . fd - the file
546: . n - the number of items to read
547: - type - the type of items to read (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)
549: Output Parameters:
550: . p - the buffer
552: Options Database Key:
553: . -binary_longints - indicates the file was generated on a Cray vector
554: machine (not the T3E/D) and the ints are stored as 64 bit
555: quantities, otherwise they are stored as 32 bit
557: Level: developer
559: Notes:
560: Does a PetscBinaryRead() followed by an MPI_Bcast()
562: PetscBinarySynchronizedRead() uses byte swapping to work on all machines.
563: Integers are stored on the file as 32 long, regardless of whether
564: they are stored in the machine as 32 or 64, this means the same
565: binary file may be read on any machine.
567: Concepts: files^synchronized reading of binary files
568: Concepts: binary files^reading, synchronized
570: .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscBinaryRead(), PetscBinarySynchronizedWrite(),
571: PetscBinarySynchronizedSeek()
572: @*/
573: PetscErrorCode PetscBinarySynchronizedRead(MPI_Comm comm,int fd,void *p,PetscInt n,PetscDataType type)
574: {
576: PetscMPIInt rank;
577: MPI_Datatype mtype;
578: char *fname;
579: PetscBool functionload = PETSC_FALSE;
580: void *ptmp = NULL;
583: if (type == PETSC_FUNCTION) {
584: functionload = PETSC_TRUE;
585: n = 64;
586: type = PETSC_CHAR;
587: ptmp = p;
588: /* warning memory leak */
589: fname = (char*)malloc(64*sizeof(char));
590: p = (void*)fname;
591: }
593: MPI_Comm_rank(comm,&rank);
594: if (!rank) {
595: PetscBinaryRead(fd,p,n,type);
596: }
597: PetscDataTypeToMPIDataType(type,&mtype);
598: MPI_Bcast(p,n,mtype,0,comm);
600: if (functionload) {
601: #if defined(PETSC_SERIALIZE_FUNCTIONS)
602: PetscDLLibrarySym(PETSC_COMM_SELF,&PetscDLLibrariesLoaded,NULL,fname,(void**)ptmp);
603: #else
604: *(void**)ptmp = NULL;
605: #endif
606: }
607: return(0);
608: }
612: /*@C
613: PetscBinarySynchronizedWrite - writes to a binary file.
615: Collective on MPI_Comm
617: Input Parameters:
618: + comm - the MPI communicator
619: . fd - the file
620: . n - the number of items to write
621: . p - the buffer
622: . istemp - the buffer may be changed
623: - type - the type of items to write (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)
625: Level: developer
627: Notes:
628: Process 0 does a PetscBinaryWrite()
630: PetscBinarySynchronizedWrite() uses byte swapping to work on all machines.
631: Integers are stored on the file as 32 long, regardless of whether
632: they are stored in the machine as 32 or 64, this means the same
633: binary file may be read on any machine.
635: Notes: because byte-swapping may be done on the values in data it cannot be declared const
637: WARNING: This is NOT like PetscSynchronizedFPrintf()! This routine ignores calls on all but process 0,
638: while PetscSynchronizedFPrintf() has all processes print their strings in order.
640: Concepts: files^synchronized writing of binary files
641: Concepts: binary files^reading, synchronized
643: .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscBinaryRead(), PetscBinarySynchronizedRead(),
644: PetscBinarySynchronizedSeek()
645: @*/
646: PetscErrorCode PetscBinarySynchronizedWrite(MPI_Comm comm,int fd,void *p,PetscInt n,PetscDataType type,PetscBool istemp)
647: {
649: PetscMPIInt rank;
652: MPI_Comm_rank(comm,&rank);
653: if (!rank) {
654: PetscBinaryWrite(fd,p,n,type,istemp);
655: }
656: return(0);
657: }
661: /*@C
662: PetscBinarySynchronizedSeek - Moves the file pointer on a PETSc binary file.
665: Input Parameters:
666: + fd - the file
667: . whence - if PETSC_BINARY_SEEK_SET then size is an absolute location in the file
668: if PETSC_BINARY_SEEK_CUR then size is offset from current location
669: if PETSC_BINARY_SEEK_END then size is offset from end of file
670: - off - number of bytes to move. Use PETSC_BINARY_INT_SIZE, PETSC_BINARY_SCALAR_SIZE,
671: etc. in your calculation rather than sizeof() to compute byte lengths.
673: Output Parameter:
674: . offset - new offset in file
676: Level: developer
678: Notes:
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. Hence you CANNOT use sizeof()
682: to determine the offset or location.
684: Concepts: binary files^seeking
685: Concepts: files^seeking in binary
687: .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
688: PetscBinarySynchronizedSeek()
689: @*/
690: PetscErrorCode PetscBinarySynchronizedSeek(MPI_Comm comm,int fd,off_t off,PetscBinarySeekType whence,off_t *offset)
691: {
693: PetscMPIInt rank;
696: MPI_Comm_rank(comm,&rank);
697: if (!rank) {
698: PetscBinarySeek(fd,off,whence,offset);
699: }
700: return(0);
701: }
703: #if defined(PETSC_HAVE_MPIIO)
704: #if !defined(PETSC_WORDS_BIGENDIAN)
706: #if defined(PETSC_USE_PETSC_MPI_EXTERNAL32)
707: /*
708: MPICH does not provide the external32 representation for MPI_File_set_view() so we need to provide the functions.
709: These are set into MPI in PetscInitialize() via MPI_Register_datarep()
711: Note I use PetscMPIInt for the MPI error codes since that is what MPI uses (instead of the standard PetscErrorCode)
713: The next three routines are not used because MPICH does not support their use
715: */
716: PETSC_EXTERN PetscMPIInt PetscDataRep_extent_fn(MPI_Datatype datatype,MPI_Aint *file_extent,void *extra_state)
717: {
718: MPI_Aint ub;
719: PetscMPIInt ierr;
721: MPI_Type_get_extent(datatype,&ub,file_extent);
722: return ierr;
723: }
725: PETSC_EXTERN PetscMPIInt PetscDataRep_read_conv_fn(void *userbuf, MPI_Datatype datatype,PetscMPIInt count,void *filebuf, MPI_Offset position,void *extra_state)
726: {
727: PetscDataType pdtype;
728: PetscMPIInt ierr;
729: size_t dsize;
731: PetscMPIDataTypeToPetscDataType(datatype,&pdtype);
732: PetscDataTypeGetSize(pdtype,&dsize);
734: /* offset is given in units of MPI_Datatype */
735: userbuf = ((char*)userbuf) + dsize*position;
737: PetscMemcpy(userbuf,filebuf,count*dsize);
738: PetscByteSwap(userbuf,pdtype,count);
739: return ierr;
740: }
742: PetscMPIInt PetscDataRep_write_conv_fn(void *userbuf, MPI_Datatype datatype,PetscMPIInt count,void *filebuf, MPI_Offset position,void *extra_state)
743: {
744: PetscDataType pdtype;
745: PetscMPIInt ierr;
746: size_t dsize;
748: PetscMPIDataTypeToPetscDataType(datatype,&pdtype);
749: PetscDataTypeGetSize(pdtype,&dsize);
751: /* offset is given in units of MPI_Datatype */
752: userbuf = ((char*)userbuf) + dsize*position;
754: PetscMemcpy(filebuf,userbuf,count*dsize);
755: PetscByteSwap(filebuf,pdtype,count);
756: return ierr;
757: }
758: #endif
762: PetscErrorCode MPIU_File_write_all(MPI_File fd,void *data,PetscMPIInt cnt,MPI_Datatype dtype,MPI_Status *status)
763: {
765: PetscDataType pdtype;
768: PetscMPIDataTypeToPetscDataType(dtype,&pdtype);
769: PetscByteSwap(data,pdtype,cnt);
770: MPI_File_write_all(fd,data,cnt,dtype,status);
771: PetscByteSwap(data,pdtype,cnt);
772: return(0);
773: }
777: PetscErrorCode MPIU_File_read_all(MPI_File fd,void *data,PetscMPIInt cnt,MPI_Datatype dtype,MPI_Status *status)
778: {
780: PetscDataType pdtype;
783: PetscMPIDataTypeToPetscDataType(dtype,&pdtype);
784: MPI_File_read_all(fd,data,cnt,dtype,status);
785: PetscByteSwap(data,pdtype,cnt);
786: return(0);
787: }
788: #endif
789: #endif