Actual source code: sysio.c
petsc-3.5.4 2015-05-23
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: PetscBool readdouble = PETSC_FALSE;
224: double *ppp;
225: #endif
226: #if !defined(PETSC_WORDS_BIGENDIAN) || defined(PETSC_USE_REAL___FLOAT128)
227: PetscErrorCode ierr;
228: #endif
229: #if !defined(PETSC_WORDS_BIGENDIAN)
230: void *ptmp = p;
231: #endif
232: char fname[64];
233: PetscBool functionload = PETSC_FALSE;
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: functionload = PETSC_TRUE;
241: m = 64;
242: type = PETSC_CHAR;
243: pp = (char*)fname;
244: #if !defined(PETSC_WORDS_BIGENDIAN)
245: ptmp = (void*)fname;
246: #endif
247: }
249: if (type == PETSC_INT) m *= sizeof(PetscInt);
250: else if (type == PETSC_SCALAR) m *= sizeof(PetscScalar);
251: else if (type == PETSC_DOUBLE) m *= sizeof(double);
252: else if (type == PETSC_FLOAT) m *= sizeof(float);
253: else if (type == PETSC_SHORT) m *= sizeof(short);
254: else if (type == PETSC_CHAR) m *= sizeof(char);
255: else if (type == PETSC_ENUM) m *= sizeof(PetscEnum);
256: else if (type == PETSC_BOOL) m *= sizeof(PetscBool);
257: else if (type == PETSC_BIT_LOGICAL) m = PetscBTLength(m)*sizeof(char);
258: else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown type");
260: #if defined(PETSC_USE_REAL___FLOAT128)
261: PetscOptionsGetBool(NULL,"-binary_read_double",&readdouble,NULL);
262: /* If using __float128 precision we still read in doubles from file */
263: if (type == PETSC_SCALAR && readdouble) {
264: m = m/2;
265: PetscMalloc1(n,&ppp);
266: pp = (char*)ppp;
267: }
268: #endif
270: while (m) {
271: wsize = (m < maxblock) ? m : maxblock;
272: err = read(fd,pp,wsize);
273: if (err < 0 && errno == EINTR) continue;
274: if (!err && wsize > 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_READ,"Read past end of file");
275: if (err < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_READ,"Error reading from file, errno %d",errno);
276: m -= err;
277: pp += err;
278: }
280: #if defined(PETSC_USE_REAL___FLOAT128)
281: if (type == PETSC_SCALAR && readdouble) {
282: PetscScalar *pv = (PetscScalar*) p;
283: PetscInt i;
284: #if !defined(PETSC_WORDS_BIGENDIAN)
285: PetscByteSwapDouble(ppp,n);
286: #endif
287: for (i=0; i<n; i++) pv[i] = ppp[i];
288: PetscFree(ppp);
289: return(0);
290: }
291: #endif
293: #if !defined(PETSC_WORDS_BIGENDIAN)
294: PetscByteSwap(ptmp,type,n);
295: #endif
297: if (functionload) {
298: #if defined(PETSC_SERIALIZE_FUNCTIONS)
299: PetscDLSym(NULL,fname,(void**)p);
300: #else
301: *(void**)p = NULL;
302: #endif
303: }
304: return(0);
305: }
306: /* --------------------------------------------------------- */
309: /*@
310: PetscBinaryWrite - Writes to a binary file.
312: Not Collective
314: Input Parameters:
315: + fd - the file
316: . p - the buffer
317: . n - the number of items to write
318: . type - the type of items to read (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)
319: - istemp - PETSC_FALSE if buffer data should be preserved, PETSC_TRUE otherwise.
321: Level: advanced
323: Notes:
324: PetscBinaryWrite() uses byte swapping to work on all machines; the files
325: are written using big-endian ordering to the file. On small-endian machines the numbers
326: are converted to the big-endian format when they are written to disk.
327: When PETSc is ./configure with --with-64bit-indices the integers are written to the
328: file as 64 bit integers, this means they can only be read back in when the option --with-64bit-indices
329: is used.
331: The Buffer p should be read-write buffer, and not static data.
332: This way, byte-swapping is done in-place, and then the buffer is
333: written to the file.
335: This routine restores the original contents of the buffer, after
336: it is written to the file. This is done by byte-swapping in-place
337: the second time. If the flag istemp is set to PETSC_TRUE, the second
338: byte-swapping operation is not done, thus saving some computation,
339: but the buffer is left corrupted.
341: Because byte-swapping may be done on the values in data it cannot be declared const
343: Concepts: files^writing binary
344: Concepts: binary files^writing
346: .seealso: PetscBinaryRead(), PetscBinaryOpen(), PetscBinaryClose(), PetscViewerBinaryGetDescriptor(), PetscBinarySynchronizedWrite(),
347: PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek()
348: @*/
349: PetscErrorCode PetscBinaryWrite(int fd,void *p,PetscInt n,PetscDataType type,PetscBool istemp)
350: {
351: char *pp = (char*)p;
352: int err,wsize;
353: size_t m = (size_t)n,maxblock=65536;
355: #if !defined(PETSC_WORDS_BIGENDIAN)
356: void *ptmp = p;
357: #endif
358: char fname[64];
361: if (n < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Trying to write a negative amount of data %D",n);
362: if (!n) return(0);
364: if (type == PETSC_FUNCTION) {
365: #if defined(PETSC_SERIALIZE_FUNCTIONS)
366: const char *fnametmp;
368: if (n > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Can only binary view a single function at a time");
369: PetscFPTFind(*(void**)p,&fnametmp);
370: PetscStrncpy(fname,fnametmp,64);
371: #else
372: PetscStrncpy(fname,"",64);
373: #endif
374: m = 64;
375: type = PETSC_CHAR;
376: pp = (char*)fname;
377: #if !defined(PETSC_WORDS_BIGENDIAN)
378: ptmp = (void*)fname;
379: #endif
380: }
382: if (type == PETSC_INT) m *= sizeof(PetscInt);
383: else if (type == PETSC_SCALAR) m *= sizeof(PetscScalar);
384: else if (type == PETSC_DOUBLE) m *= sizeof(double);
385: else if (type == PETSC_FLOAT) m *= sizeof(float);
386: else if (type == PETSC_SHORT) m *= sizeof(short);
387: else if (type == PETSC_CHAR) m *= sizeof(char);
388: else if (type == PETSC_ENUM) m *= sizeof(PetscEnum);
389: else if (type == PETSC_BOOL) m *= sizeof(PetscBool);
390: else if (type == PETSC_BIT_LOGICAL) m = PetscBTLength(m)*sizeof(char);
391: else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown type");
393: #if !defined(PETSC_WORDS_BIGENDIAN)
394: PetscByteSwap(ptmp,type,n);
395: #endif
397: while (m) {
398: wsize = (m < maxblock) ? m : maxblock;
399: err = write(fd,pp,wsize);
400: if (err < 0 && errno == EINTR) continue;
401: 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);
402: m -= wsize;
403: pp += wsize;
404: }
406: #if !defined(PETSC_WORDS_BIGENDIAN)
407: if (!istemp) {
408: PetscByteSwap(ptmp,type,n);
409: }
410: #endif
411: return(0);
412: }
416: /*@C
417: PetscBinaryOpen - Opens a PETSc binary file.
419: Not Collective
421: Input Parameters:
422: + name - filename
423: - type - type of binary file, one of FILE_MODE_READ, FILE_MODE_APPEND, FILE_MODE_WRITE
425: Output Parameter:
426: . fd - the file
428: Level: advanced
430: Concepts: files^opening binary
431: Concepts: binary files^opening
433: Notes: Files access with PetscBinaryRead() and PetscBinaryWrite() are ALWAYS written in
434: big-endian format. This means the file can be accessed using PetscBinaryOpen() and
435: PetscBinaryRead() and PetscBinaryWrite() on any machine.
437: .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscFileMode, PetscViewerFileSetMode(), PetscViewerBinaryGetDescriptor(),
438: PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek()
440: @*/
441: PetscErrorCode PetscBinaryOpen(const char name[],PetscFileMode mode,int *fd)
442: {
444: #if defined(PETSC_HAVE_O_BINARY)
445: if (mode == FILE_MODE_WRITE) {
446: 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);
447: } else if (mode == FILE_MODE_READ) {
448: 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);
449: } else if (mode == FILE_MODE_APPEND) {
450: 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);
451: #else
452: if (mode == FILE_MODE_WRITE) {
453: if ((*fd = creat(name,0666)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot create file for writing: %s",name);
454: } else if (mode == FILE_MODE_READ) {
455: if ((*fd = open(name,O_RDONLY,0)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file for reading: %s",name);
456: }
457: else if (mode == FILE_MODE_APPEND) {
458: if ((*fd = open(name,O_WRONLY,0)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file for writing: %s",name);
459: #endif
460: } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown file mode");
461: return(0);
462: }
466: /*@
467: PetscBinaryClose - Closes a PETSc binary file.
469: Not Collective
471: Output Parameter:
472: . fd - the file
474: Level: advanced
476: .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
477: PetscBinarySynchronizedSeek()
478: @*/
479: PetscErrorCode PetscBinaryClose(int fd)
480: {
482: close(fd);
483: return(0);
484: }
489: /*@
490: PetscBinarySeek - Moves the file pointer on a PETSc binary file.
492: Not Collective
494: Input Parameters:
495: + fd - the file
496: . off - number of bytes to move. Use PETSC_BINARY_INT_SIZE, PETSC_BINARY_SCALAR_SIZE,
497: etc. in your calculation rather than sizeof() to compute byte lengths.
498: - whence - if PETSC_BINARY_SEEK_SET then off is an absolute location in the file
499: if PETSC_BINARY_SEEK_CUR then off is an offset from the current location
500: if PETSC_BINARY_SEEK_END then off is an offset from the end of file
502: Output Parameter:
503: . offset - new offset in file
505: Level: developer
507: Notes:
508: Integers are stored on the file as 32 long, regardless of whether
509: they are stored in the machine as 32 or 64, this means the same
510: binary file may be read on any machine. Hence you CANNOT use sizeof()
511: to determine the offset or location.
513: Concepts: files^binary seeking
514: Concepts: binary files^seeking
516: .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
517: PetscBinarySynchronizedSeek()
518: @*/
519: PetscErrorCode PetscBinarySeek(int fd,off_t off,PetscBinarySeekType whence,off_t *offset)
520: {
521: int iwhence = 0;
524: if (whence == PETSC_BINARY_SEEK_SET) iwhence = SEEK_SET;
525: else if (whence == PETSC_BINARY_SEEK_CUR) iwhence = SEEK_CUR;
526: else if (whence == PETSC_BINARY_SEEK_END) iwhence = SEEK_END;
527: else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown seek location");
528: #if defined(PETSC_HAVE_LSEEK)
529: *offset = lseek(fd,off,iwhence);
530: #elif defined(PETSC_HAVE__LSEEK)
531: *offset = _lseek(fd,(long)off,iwhence);
532: #else
533: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS,"System does not have a way of seeking on a file");
534: #endif
535: return(0);
536: }
540: /*@C
541: PetscBinarySynchronizedRead - Reads from a binary file.
543: Collective on MPI_Comm
545: Input Parameters:
546: + comm - the MPI communicator
547: . fd - the file
548: . n - the number of items to read
549: - type - the type of items to read (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)
551: Output Parameters:
552: . p - the buffer
554: Options Database Key:
555: . -binary_longints - indicates the file was generated on a Cray vector
556: machine (not the T3E/D) and the ints are stored as 64 bit
557: quantities, otherwise they are stored as 32 bit
559: Level: developer
561: Notes:
562: Does a PetscBinaryRead() followed by an MPI_Bcast()
564: PetscBinarySynchronizedRead() uses byte swapping to work on all machines.
565: Integers are stored on the file as 32 long, regardless of whether
566: they are stored in the machine as 32 or 64, this means the same
567: binary file may be read on any machine.
569: Concepts: files^synchronized reading of binary files
570: Concepts: binary files^reading, synchronized
572: .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscBinaryRead(), PetscBinarySynchronizedWrite(),
573: PetscBinarySynchronizedSeek()
574: @*/
575: PetscErrorCode PetscBinarySynchronizedRead(MPI_Comm comm,int fd,void *p,PetscInt n,PetscDataType type)
576: {
578: PetscMPIInt rank;
579: MPI_Datatype mtype;
580: char *fname;
581: PetscBool functionload = PETSC_FALSE;
582: void *ptmp = NULL;
585: if (type == PETSC_FUNCTION) {
586: functionload = PETSC_TRUE;
587: n = 64;
588: type = PETSC_CHAR;
589: ptmp = p;
590: /* warning memory leak */
591: fname = (char*)malloc(64*sizeof(char));
592: p = (void*)fname;
593: }
595: MPI_Comm_rank(comm,&rank);
596: if (!rank) {
597: PetscBinaryRead(fd,p,n,type);
598: }
599: PetscDataTypeToMPIDataType(type,&mtype);
600: MPI_Bcast(p,n,mtype,0,comm);
602: if (functionload) {
603: #if defined(PETSC_SERIALIZE_FUNCTIONS)
604: PetscDLLibrarySym(PETSC_COMM_SELF,&PetscDLLibrariesLoaded,NULL,fname,(void**)ptmp);
605: #else
606: *(void**)ptmp = NULL;
607: #endif
608: }
609: return(0);
610: }
614: /*@C
615: PetscBinarySynchronizedWrite - writes to a binary file.
617: Collective on MPI_Comm
619: Input Parameters:
620: + comm - the MPI communicator
621: . fd - the file
622: . n - the number of items to write
623: . p - the buffer
624: . istemp - the buffer may be changed
625: - type - the type of items to write (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)
627: Level: developer
629: Notes:
630: Process 0 does a PetscBinaryWrite()
632: PetscBinarySynchronizedWrite() 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: Notes: because byte-swapping may be done on the values in data it cannot be declared const
639: WARNING: This is NOT like PetscSynchronizedFPrintf()! This routine ignores calls on all but process 0,
640: while PetscSynchronizedFPrintf() has all processes print their strings in order.
642: Concepts: files^synchronized writing of binary files
643: Concepts: binary files^reading, synchronized
645: .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscBinaryRead(), PetscBinarySynchronizedRead(),
646: PetscBinarySynchronizedSeek()
647: @*/
648: PetscErrorCode PetscBinarySynchronizedWrite(MPI_Comm comm,int fd,void *p,PetscInt n,PetscDataType type,PetscBool istemp)
649: {
651: PetscMPIInt rank;
654: MPI_Comm_rank(comm,&rank);
655: if (!rank) {
656: PetscBinaryWrite(fd,p,n,type,istemp);
657: }
658: return(0);
659: }
663: /*@C
664: PetscBinarySynchronizedSeek - Moves the file pointer on a PETSc binary file.
667: Input Parameters:
668: + fd - the file
669: . whence - if PETSC_BINARY_SEEK_SET then size is an absolute location in the file
670: if PETSC_BINARY_SEEK_CUR then size is offset from current location
671: if PETSC_BINARY_SEEK_END then size is offset from end of file
672: - off - number of bytes to move. Use PETSC_BINARY_INT_SIZE, PETSC_BINARY_SCALAR_SIZE,
673: etc. in your calculation rather than sizeof() to compute byte lengths.
675: Output Parameter:
676: . offset - new offset in file
678: Level: developer
680: Notes:
681: Integers are stored on the file as 32 long, regardless of whether
682: they are stored in the machine as 32 or 64, this means the same
683: binary file may be read on any machine. Hence you CANNOT use sizeof()
684: to determine the offset or location.
686: Concepts: binary files^seeking
687: Concepts: files^seeking in binary
689: .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
690: PetscBinarySynchronizedSeek()
691: @*/
692: PetscErrorCode PetscBinarySynchronizedSeek(MPI_Comm comm,int fd,off_t off,PetscBinarySeekType whence,off_t *offset)
693: {
695: PetscMPIInt rank;
698: MPI_Comm_rank(comm,&rank);
699: if (!rank) {
700: PetscBinarySeek(fd,off,whence,offset);
701: }
702: return(0);
703: }
705: #if defined(PETSC_HAVE_MPIIO)
706: #if !defined(PETSC_WORDS_BIGENDIAN)
708: #if defined(PETSC_USE_PETSC_MPI_EXTERNAL32)
709: /*
710: MPICH does not provide the external32 representation for MPI_File_set_view() so we need to provide the functions.
711: These are set into MPI in PetscInitialize() via MPI_Register_datarep()
713: Note I use PetscMPIInt for the MPI error codes since that is what MPI uses (instead of the standard PetscErrorCode)
715: The next three routines are not used because MPICH does not support their use
717: */
718: PETSC_EXTERN PetscMPIInt PetscDataRep_extent_fn(MPI_Datatype datatype,MPI_Aint *file_extent,void *extra_state)
719: {
720: MPI_Aint ub;
721: PetscMPIInt ierr;
723: MPI_Type_get_extent(datatype,&ub,file_extent);
724: return ierr;
725: }
727: PETSC_EXTERN PetscMPIInt PetscDataRep_read_conv_fn(void *userbuf, MPI_Datatype datatype,PetscMPIInt count,void *filebuf, MPI_Offset position,void *extra_state)
728: {
729: PetscDataType pdtype;
730: PetscMPIInt ierr;
731: size_t dsize;
733: PetscMPIDataTypeToPetscDataType(datatype,&pdtype);
734: PetscDataTypeGetSize(pdtype,&dsize);
736: /* offset is given in units of MPI_Datatype */
737: userbuf = ((char*)userbuf) + dsize*position;
739: PetscMemcpy(userbuf,filebuf,count*dsize);
740: PetscByteSwap(userbuf,pdtype,count);
741: return ierr;
742: }
744: PetscMPIInt PetscDataRep_write_conv_fn(void *userbuf, MPI_Datatype datatype,PetscMPIInt count,void *filebuf, MPI_Offset position,void *extra_state)
745: {
746: PetscDataType pdtype;
747: PetscMPIInt ierr;
748: size_t dsize;
750: PetscMPIDataTypeToPetscDataType(datatype,&pdtype);
751: PetscDataTypeGetSize(pdtype,&dsize);
753: /* offset is given in units of MPI_Datatype */
754: userbuf = ((char*)userbuf) + dsize*position;
756: PetscMemcpy(filebuf,userbuf,count*dsize);
757: PetscByteSwap(filebuf,pdtype,count);
758: return ierr;
759: }
760: #endif
764: PetscErrorCode MPIU_File_write_all(MPI_File fd,void *data,PetscMPIInt cnt,MPI_Datatype dtype,MPI_Status *status)
765: {
767: PetscDataType pdtype;
770: PetscMPIDataTypeToPetscDataType(dtype,&pdtype);
771: PetscByteSwap(data,pdtype,cnt);
772: MPI_File_write_all(fd,data,cnt,dtype,status);
773: PetscByteSwap(data,pdtype,cnt);
774: return(0);
775: }
779: PetscErrorCode MPIU_File_read_all(MPI_File fd,void *data,PetscMPIInt cnt,MPI_Datatype dtype,MPI_Status *status)
780: {
782: PetscDataType pdtype;
785: PetscMPIDataTypeToPetscDataType(dtype,&pdtype);
786: MPI_File_read_all(fd,data,cnt,dtype,status);
787: PetscByteSwap(data,pdtype,cnt);
788: return(0);
789: }
790: #endif
791: #endif