Actual source code: sysio.c
petsc-3.7.7 2017-09-25
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 PetscScalar
106: The complex case is dealt with with an array of PetscReal, 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 = NULL;
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: m = 64;
240: type = PETSC_CHAR;
241: fname = (char*) malloc(m*sizeof(char));
242: if (!fname) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Cannot allocate space for function name");
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,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 (type == PETSC_FUNCTION) {
298: #if defined(PETSC_SERIALIZE_FUNCTIONS)
299: PetscDLSym(NULL,fname,(void**)p);
300: #else
301: *(void**)p = NULL;
302: #endif
303: free(fname);
304: }
305: return(0);
306: }
307: /* --------------------------------------------------------- */
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: type = 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 && 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_DOUBLE) m *= sizeof(double);
413: else if (wtype == PETSC_FLOAT) m *= sizeof(float);
414: else if (wtype == PETSC_SHORT) m *= sizeof(short);
415: else if (wtype == PETSC_CHAR) m *= sizeof(char);
416: else if (wtype == PETSC_ENUM) m *= sizeof(PetscEnum);
417: else if (wtype == PETSC_BOOL) m *= sizeof(PetscBool);
418: else if (wtype == PETSC_BIT_LOGICAL) m = PetscBTLength(m)*sizeof(char);
419: else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown type");
421: #if !defined(PETSC_WORDS_BIGENDIAN)
422: PetscByteSwap(ptmp,wtype,n);
423: #endif
425: while (m) {
426: wsize = (m < maxblock) ? m : maxblock;
427: err = write(fd,pp,wsize);
428: if (err < 0 && errno == EINTR) continue;
429: 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);
430: m -= wsize;
431: pp += wsize;
432: }
434: #if !defined(PETSC_WORDS_BIGENDIAN)
435: if (!istemp) {
436: PetscByteSwap(ptmp,wtype,n);
437: }
438: #endif
439: if (type == PETSC_FUNCTION) {
440: free(fname);
441: }
442: #if defined(PETSC_USE_REAL___FLOAT128)
443: if (type == PETSC_SCALAR && writedouble) {
444: PetscFree(ppp);
445: }
446: #endif
447: return(0);
448: }
452: /*@C
453: PetscBinaryOpen - Opens a PETSc binary file.
455: Not Collective
457: Input Parameters:
458: + name - filename
459: - type - type of binary file, one of FILE_MODE_READ, FILE_MODE_APPEND, FILE_MODE_WRITE
461: Output Parameter:
462: . fd - the file
464: Level: advanced
466: Concepts: files^opening binary
467: Concepts: binary files^opening
469: Notes: 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: }
502: /*@
503: PetscBinaryClose - Closes a PETSc binary file.
505: Not Collective
507: Output Parameter:
508: . fd - the file
510: Level: advanced
512: .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
513: PetscBinarySynchronizedSeek()
514: @*/
515: PetscErrorCode PetscBinaryClose(int fd)
516: {
518: close(fd);
519: return(0);
520: }
525: /*@
526: PetscBinarySeek - Moves the file pointer on a PETSc binary file.
528: Not Collective
530: Input Parameters:
531: + fd - the file
532: . off - number of bytes to move. Use PETSC_BINARY_INT_SIZE, PETSC_BINARY_SCALAR_SIZE,
533: etc. in your calculation rather than sizeof() to compute byte lengths.
534: - whence - if PETSC_BINARY_SEEK_SET then off is an absolute location in the file
535: if PETSC_BINARY_SEEK_CUR then off is an offset from the current location
536: if PETSC_BINARY_SEEK_END then off is an offset from the end of file
538: Output Parameter:
539: . offset - new offset in file
541: Level: developer
543: Notes:
544: Integers are stored on the file as 32 long, regardless of whether
545: they are stored in the machine as 32 or 64, this means the same
546: binary file may be read on any machine. Hence you CANNOT use sizeof()
547: to determine the offset or location.
549: Concepts: files^binary seeking
550: Concepts: binary files^seeking
552: .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
553: PetscBinarySynchronizedSeek()
554: @*/
555: PetscErrorCode PetscBinarySeek(int fd,off_t off,PetscBinarySeekType whence,off_t *offset)
556: {
557: int iwhence = 0;
560: if (whence == PETSC_BINARY_SEEK_SET) iwhence = SEEK_SET;
561: else if (whence == PETSC_BINARY_SEEK_CUR) iwhence = SEEK_CUR;
562: else if (whence == PETSC_BINARY_SEEK_END) iwhence = SEEK_END;
563: else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown seek location");
564: #if defined(PETSC_HAVE_LSEEK)
565: *offset = lseek(fd,off,iwhence);
566: #elif defined(PETSC_HAVE__LSEEK)
567: *offset = _lseek(fd,(long)off,iwhence);
568: #else
569: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS,"System does not have a way of seeking on a file");
570: #endif
571: return(0);
572: }
576: /*@C
577: PetscBinarySynchronizedRead - Reads from a binary file.
579: Collective on MPI_Comm
581: Input Parameters:
582: + comm - the MPI communicator
583: . fd - the file
584: . n - the number of items to read
585: - type - the type of items to read (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)
587: Output Parameters:
588: . p - the buffer
590: Level: developer
592: Notes:
593: Does a PetscBinaryRead() followed by an MPI_Bcast()
595: PetscBinarySynchronizedRead() uses byte swapping to work on all machines.
596: Integers are stored on the file as 32 long, regardless of whether
597: they are stored in the machine as 32 or 64, this means the same
598: binary file may be read on any machine.
600: Concepts: files^synchronized reading of binary files
601: Concepts: binary files^reading, synchronized
603: .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscBinaryRead(), PetscBinarySynchronizedWrite(),
604: PetscBinarySynchronizedSeek()
605: @*/
606: PetscErrorCode PetscBinarySynchronizedRead(MPI_Comm comm,int fd,void *p,PetscInt n,PetscDataType type)
607: {
609: PetscMPIInt rank;
610: MPI_Datatype mtype;
611: char *fname = NULL;
612: void *ptmp = NULL;
615: if (type == PETSC_FUNCTION) {
616: n = 64;
617: type = PETSC_CHAR;
618: ptmp = p;
619: fname = (char*)malloc(n*sizeof(char));
620: if (!fname) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Cannot allocate space for function name");
621: p = (void*)fname;
622: }
624: MPI_Comm_rank(comm,&rank);
625: if (!rank) {
626: PetscBinaryRead(fd,p,n,type);
627: }
628: PetscDataTypeToMPIDataType(type,&mtype);
629: MPI_Bcast(p,n,mtype,0,comm);
631: if (type == PETSC_FUNCTION) {
632: #if defined(PETSC_SERIALIZE_FUNCTIONS)
633: PetscDLLibrarySym(PETSC_COMM_SELF,&PetscDLLibrariesLoaded,NULL,fname,(void**)ptmp);
634: #else
635: *(void**)ptmp = NULL;
636: #endif
637: free(fname);
638: }
639: return(0);
640: }
644: /*@C
645: PetscBinarySynchronizedWrite - writes to a binary file.
647: Collective on MPI_Comm
649: Input Parameters:
650: + comm - the MPI communicator
651: . fd - the file
652: . n - the number of items to write
653: . p - the buffer
654: . istemp - the buffer may be changed
655: - type - the type of items to write (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)
657: Level: developer
659: Notes:
660: Process 0 does a PetscBinaryWrite()
662: PetscBinarySynchronizedWrite() uses byte swapping to work on all machines.
663: Integers are stored on the file as 32 long, regardless of whether
664: they are stored in the machine as 32 or 64, this means the same
665: binary file may be read on any machine.
667: Notes: because byte-swapping may be done on the values in data it cannot be declared const
669: WARNING: This is NOT like PetscSynchronizedFPrintf()! This routine ignores calls on all but process 0,
670: while PetscSynchronizedFPrintf() has all processes print their strings in order.
672: Concepts: files^synchronized writing of binary files
673: Concepts: binary files^reading, synchronized
675: .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscBinaryRead(), PetscBinarySynchronizedRead(),
676: PetscBinarySynchronizedSeek()
677: @*/
678: PetscErrorCode PetscBinarySynchronizedWrite(MPI_Comm comm,int fd,void *p,PetscInt n,PetscDataType type,PetscBool istemp)
679: {
681: PetscMPIInt rank;
684: MPI_Comm_rank(comm,&rank);
685: if (!rank) {
686: PetscBinaryWrite(fd,p,n,type,istemp);
687: }
688: return(0);
689: }
693: /*@C
694: PetscBinarySynchronizedSeek - Moves the file pointer on a PETSc binary file.
697: Input Parameters:
698: + fd - the file
699: . whence - if PETSC_BINARY_SEEK_SET then size is an absolute location in the file
700: if PETSC_BINARY_SEEK_CUR then size is offset from current location
701: if PETSC_BINARY_SEEK_END then size is offset from end of file
702: - off - number of bytes to move. Use PETSC_BINARY_INT_SIZE, PETSC_BINARY_SCALAR_SIZE,
703: etc. in your calculation rather than sizeof() to compute byte lengths.
705: Output Parameter:
706: . offset - new offset in file
708: Level: developer
710: Notes:
711: Integers are stored on the file as 32 long, regardless of whether
712: they are stored in the machine as 32 or 64, this means the same
713: binary file may be read on any machine. Hence you CANNOT use sizeof()
714: to determine the offset or location.
716: Concepts: binary files^seeking
717: Concepts: files^seeking in binary
719: .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
720: PetscBinarySynchronizedSeek()
721: @*/
722: PetscErrorCode PetscBinarySynchronizedSeek(MPI_Comm comm,int fd,off_t off,PetscBinarySeekType whence,off_t *offset)
723: {
725: PetscMPIInt rank;
728: MPI_Comm_rank(comm,&rank);
729: if (!rank) {
730: PetscBinarySeek(fd,off,whence,offset);
731: }
732: return(0);
733: }
735: #if defined(PETSC_HAVE_MPIIO)
736: #if !defined(PETSC_WORDS_BIGENDIAN)
738: #if defined(PETSC_USE_PETSC_MPI_EXTERNAL32)
739: /*
740: MPICH does not provide the external32 representation for MPI_File_set_view() so we need to provide the functions.
741: These are set into MPI in PetscInitialize() via MPI_Register_datarep()
743: Note I use PetscMPIInt for the MPI error codes since that is what MPI uses (instead of the standard PetscErrorCode)
745: The next three routines are not used because MPICH does not support their use
747: */
748: PETSC_EXTERN PetscMPIInt PetscDataRep_extent_fn(MPI_Datatype datatype,MPI_Aint *file_extent,void *extra_state)
749: {
750: MPI_Aint ub;
751: PetscMPIInt ierr;
753: MPI_Type_get_extent(datatype,&ub,file_extent);
754: return ierr;
755: }
757: PETSC_EXTERN PetscMPIInt PetscDataRep_read_conv_fn(void *userbuf, MPI_Datatype datatype,PetscMPIInt count,void *filebuf, MPI_Offset position,void *extra_state)
758: {
759: PetscDataType pdtype;
760: PetscMPIInt ierr;
761: size_t dsize;
763: PetscMPIDataTypeToPetscDataType(datatype,&pdtype);
764: PetscDataTypeGetSize(pdtype,&dsize);
766: /* offset is given in units of MPI_Datatype */
767: userbuf = ((char*)userbuf) + dsize*position;
769: PetscMemcpy(userbuf,filebuf,count*dsize);
770: PetscByteSwap(userbuf,pdtype,count);
771: return ierr;
772: }
774: PetscMPIInt PetscDataRep_write_conv_fn(void *userbuf, MPI_Datatype datatype,PetscMPIInt count,void *filebuf, MPI_Offset position,void *extra_state)
775: {
776: PetscDataType pdtype;
777: PetscMPIInt ierr;
778: size_t dsize;
780: PetscMPIDataTypeToPetscDataType(datatype,&pdtype);
781: PetscDataTypeGetSize(pdtype,&dsize);
783: /* offset is given in units of MPI_Datatype */
784: userbuf = ((char*)userbuf) + dsize*position;
786: PetscMemcpy(filebuf,userbuf,count*dsize);
787: PetscByteSwap(filebuf,pdtype,count);
788: return ierr;
789: }
790: #endif
794: PetscErrorCode MPIU_File_write_all(MPI_File fd,void *data,PetscMPIInt cnt,MPI_Datatype dtype,MPI_Status *status)
795: {
797: PetscDataType pdtype;
800: PetscMPIDataTypeToPetscDataType(dtype,&pdtype);
801: PetscByteSwap(data,pdtype,cnt);
802: MPI_File_write_all(fd,data,cnt,dtype,status);
803: PetscByteSwap(data,pdtype,cnt);
804: return(0);
805: }
809: PetscErrorCode MPIU_File_read_all(MPI_File fd,void *data,PetscMPIInt cnt,MPI_Datatype dtype,MPI_Status *status)
810: {
812: PetscDataType pdtype;
815: PetscMPIDataTypeToPetscDataType(dtype,&pdtype);
816: MPI_File_read_all(fd,data,cnt,dtype,status);
817: PetscByteSwap(data,pdtype,cnt);
818: return(0);
819: }
820: #endif
821: #endif