Actual source code: sysio.c
petsc-3.7.3 2016-08-01
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 = 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_read_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
370: if (n < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Trying to write a negative amount of data %D",n);
371: if (!n) return(0);
373: if (type == PETSC_FUNCTION) {
374: #if defined(PETSC_SERIALIZE_FUNCTIONS)
375: const char *fnametmp;
376: #endif
377: m = 64;
378: fname = (char*)malloc(m*sizeof(char));
379: if (!fname) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Cannot allocate space for function name");
380: #if defined(PETSC_SERIALIZE_FUNCTIONS)
381: if (n > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Can only binary view a single function at a time");
382: PetscFPTFind(*(void**)p,&fnametmp);
383: PetscStrncpy(fname,fnametmp,m);
384: #else
385: PetscStrncpy(fname,"",m);
386: #endif
387: type = PETSC_CHAR;
388: pp = (char*)fname;
389: #if !defined(PETSC_WORDS_BIGENDIAN)
390: ptmp = (void*)fname;
391: #endif
392: }
394: #if defined(PETSC_USE_REAL___FLOAT128)
395: PetscOptionsGetBool(NULL,NULL,"-binary_write_double",&writedouble,NULL);
396: /* If using __float128 precision we still write in doubles to file */
397: if (type == PETSC_SCALAR && writedouble) {
398: m = m/2;
399: PetscMalloc1(n,&ppp);
400: pv = (PetscReal*)pp;
401: for (i=0; i<n; i++) {
402: ppp[i] = (double) pv[i];
403: }
404: pp = (char*)ppp;
405: ptmp = (char*)ppp;
406: }
407: #endif
409: if (type == PETSC_INT) m *= sizeof(PetscInt);
410: else if (type == PETSC_SCALAR) m *= sizeof(PetscScalar);
411: else if (type == PETSC_DOUBLE) m *= sizeof(double);
412: else if (type == PETSC_FLOAT) m *= sizeof(float);
413: else if (type == PETSC_SHORT) m *= sizeof(short);
414: else if (type == PETSC_CHAR) m *= sizeof(char);
415: else if (type == PETSC_ENUM) m *= sizeof(PetscEnum);
416: else if (type == PETSC_BOOL) m *= sizeof(PetscBool);
417: else if (type == PETSC_BIT_LOGICAL) m = PetscBTLength(m)*sizeof(char);
418: else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown type");
420: #if !defined(PETSC_WORDS_BIGENDIAN)
421: PetscByteSwap(ptmp,type,n);
422: #endif
424: while (m) {
425: wsize = (m < maxblock) ? m : maxblock;
426: err = write(fd,pp,wsize);
427: if (err < 0 && errno == EINTR) continue;
428: 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);
429: m -= wsize;
430: pp += wsize;
431: }
433: #if !defined(PETSC_WORDS_BIGENDIAN)
434: if (!istemp) {
435: PetscByteSwap(ptmp,type,n);
436: }
437: #endif
438: if (type == PETSC_FUNCTION) {
439: free(fname);
440: }
441: #if defined(PETSC_USE_REAL___FLOAT128)
442: if (type == PETSC_SCALAR && writedouble) {
443: PetscFree(ppp);
444: }
445: #endif
446: return(0);
447: }
451: /*@C
452: PetscBinaryOpen - Opens a PETSc binary file.
454: Not Collective
456: Input Parameters:
457: + name - filename
458: - type - type of binary file, one of FILE_MODE_READ, FILE_MODE_APPEND, FILE_MODE_WRITE
460: Output Parameter:
461: . fd - the file
463: Level: advanced
465: Concepts: files^opening binary
466: Concepts: binary files^opening
468: Notes: Files access with PetscBinaryRead() and PetscBinaryWrite() are ALWAYS written in
469: big-endian format. This means the file can be accessed using PetscBinaryOpen() and
470: PetscBinaryRead() and PetscBinaryWrite() on any machine.
472: .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscFileMode, PetscViewerFileSetMode(), PetscViewerBinaryGetDescriptor(),
473: PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek()
475: @*/
476: PetscErrorCode PetscBinaryOpen(const char name[],PetscFileMode mode,int *fd)
477: {
479: #if defined(PETSC_HAVE_O_BINARY)
480: if (mode == FILE_MODE_WRITE) {
481: if ((*fd = open(name,O_WRONLY|O_CREAT|O_TRUNC|O_BINARY,0666)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot create file for writing: %s",name);
482: } else if (mode == FILE_MODE_READ) {
483: if ((*fd = open(name,O_RDONLY|O_BINARY,0)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file for reading: %s",name);
484: } else if (mode == FILE_MODE_APPEND) {
485: if ((*fd = open(name,O_WRONLY|O_BINARY,0)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file for writing: %s",name);
486: #else
487: if (mode == FILE_MODE_WRITE) {
488: if ((*fd = creat(name,0666)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot create file for writing: %s",name);
489: } else if (mode == FILE_MODE_READ) {
490: if ((*fd = open(name,O_RDONLY,0)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file for reading: %s",name);
491: }
492: else if (mode == FILE_MODE_APPEND) {
493: if ((*fd = open(name,O_WRONLY,0)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file for writing: %s",name);
494: #endif
495: } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown file mode");
496: return(0);
497: }
501: /*@
502: PetscBinaryClose - Closes a PETSc binary file.
504: Not Collective
506: Output Parameter:
507: . fd - the file
509: Level: advanced
511: .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
512: PetscBinarySynchronizedSeek()
513: @*/
514: PetscErrorCode PetscBinaryClose(int fd)
515: {
517: close(fd);
518: return(0);
519: }
524: /*@
525: PetscBinarySeek - Moves the file pointer on a PETSc binary file.
527: Not Collective
529: Input Parameters:
530: + fd - the file
531: . off - number of bytes to move. Use PETSC_BINARY_INT_SIZE, PETSC_BINARY_SCALAR_SIZE,
532: etc. in your calculation rather than sizeof() to compute byte lengths.
533: - whence - if PETSC_BINARY_SEEK_SET then off is an absolute location in the file
534: if PETSC_BINARY_SEEK_CUR then off is an offset from the current location
535: if PETSC_BINARY_SEEK_END then off is an offset from the end of file
537: Output Parameter:
538: . offset - new offset in file
540: Level: developer
542: Notes:
543: Integers are stored on the file as 32 long, regardless of whether
544: they are stored in the machine as 32 or 64, this means the same
545: binary file may be read on any machine. Hence you CANNOT use sizeof()
546: to determine the offset or location.
548: Concepts: files^binary seeking
549: Concepts: binary files^seeking
551: .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
552: PetscBinarySynchronizedSeek()
553: @*/
554: PetscErrorCode PetscBinarySeek(int fd,off_t off,PetscBinarySeekType whence,off_t *offset)
555: {
556: int iwhence = 0;
559: if (whence == PETSC_BINARY_SEEK_SET) iwhence = SEEK_SET;
560: else if (whence == PETSC_BINARY_SEEK_CUR) iwhence = SEEK_CUR;
561: else if (whence == PETSC_BINARY_SEEK_END) iwhence = SEEK_END;
562: else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown seek location");
563: #if defined(PETSC_HAVE_LSEEK)
564: *offset = lseek(fd,off,iwhence);
565: #elif defined(PETSC_HAVE__LSEEK)
566: *offset = _lseek(fd,(long)off,iwhence);
567: #else
568: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS,"System does not have a way of seeking on a file");
569: #endif
570: return(0);
571: }
575: /*@C
576: PetscBinarySynchronizedRead - Reads from a binary file.
578: Collective on MPI_Comm
580: Input Parameters:
581: + comm - the MPI communicator
582: . fd - the file
583: . n - the number of items to read
584: - type - the type of items to read (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)
586: Output Parameters:
587: . p - the buffer
589: Level: developer
591: Notes:
592: Does a PetscBinaryRead() followed by an MPI_Bcast()
594: PetscBinarySynchronizedRead() uses byte swapping to work on all machines.
595: Integers are stored on the file as 32 long, regardless of whether
596: they are stored in the machine as 32 or 64, this means the same
597: binary file may be read on any machine.
599: Concepts: files^synchronized reading of binary files
600: Concepts: binary files^reading, synchronized
602: .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscBinaryRead(), PetscBinarySynchronizedWrite(),
603: PetscBinarySynchronizedSeek()
604: @*/
605: PetscErrorCode PetscBinarySynchronizedRead(MPI_Comm comm,int fd,void *p,PetscInt n,PetscDataType type)
606: {
608: PetscMPIInt rank;
609: MPI_Datatype mtype;
610: char *fname = NULL;
611: void *ptmp = NULL;
614: if (type == PETSC_FUNCTION) {
615: n = 64;
616: type = PETSC_CHAR;
617: ptmp = p;
618: fname = (char*)malloc(n*sizeof(char));
619: if (!fname) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Cannot allocate space for function name");
620: p = (void*)fname;
621: }
623: MPI_Comm_rank(comm,&rank);
624: if (!rank) {
625: PetscBinaryRead(fd,p,n,type);
626: }
627: PetscDataTypeToMPIDataType(type,&mtype);
628: MPI_Bcast(p,n,mtype,0,comm);
630: if (type == PETSC_FUNCTION) {
631: #if defined(PETSC_SERIALIZE_FUNCTIONS)
632: PetscDLLibrarySym(PETSC_COMM_SELF,&PetscDLLibrariesLoaded,NULL,fname,(void**)ptmp);
633: #else
634: *(void**)ptmp = NULL;
635: #endif
636: free(fname);
637: }
638: return(0);
639: }
643: /*@C
644: PetscBinarySynchronizedWrite - writes to a binary file.
646: Collective on MPI_Comm
648: Input Parameters:
649: + comm - the MPI communicator
650: . fd - the file
651: . n - the number of items to write
652: . p - the buffer
653: . istemp - the buffer may be changed
654: - type - the type of items to write (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)
656: Level: developer
658: Notes:
659: Process 0 does a PetscBinaryWrite()
661: PetscBinarySynchronizedWrite() uses byte swapping to work on all machines.
662: Integers are stored on the file as 32 long, regardless of whether
663: they are stored in the machine as 32 or 64, this means the same
664: binary file may be read on any machine.
666: Notes: because byte-swapping may be done on the values in data it cannot be declared const
668: WARNING: This is NOT like PetscSynchronizedFPrintf()! This routine ignores calls on all but process 0,
669: while PetscSynchronizedFPrintf() has all processes print their strings in order.
671: Concepts: files^synchronized writing of binary files
672: Concepts: binary files^reading, synchronized
674: .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscBinaryRead(), PetscBinarySynchronizedRead(),
675: PetscBinarySynchronizedSeek()
676: @*/
677: PetscErrorCode PetscBinarySynchronizedWrite(MPI_Comm comm,int fd,void *p,PetscInt n,PetscDataType type,PetscBool istemp)
678: {
680: PetscMPIInt rank;
683: MPI_Comm_rank(comm,&rank);
684: if (!rank) {
685: PetscBinaryWrite(fd,p,n,type,istemp);
686: }
687: return(0);
688: }
692: /*@C
693: PetscBinarySynchronizedSeek - Moves the file pointer on a PETSc binary file.
696: Input Parameters:
697: + fd - the file
698: . whence - if PETSC_BINARY_SEEK_SET then size is an absolute location in the file
699: if PETSC_BINARY_SEEK_CUR then size is offset from current location
700: if PETSC_BINARY_SEEK_END then size is offset from end of file
701: - off - number of bytes to move. Use PETSC_BINARY_INT_SIZE, PETSC_BINARY_SCALAR_SIZE,
702: etc. in your calculation rather than sizeof() to compute byte lengths.
704: Output Parameter:
705: . offset - new offset in file
707: Level: developer
709: Notes:
710: Integers are stored on the file as 32 long, regardless of whether
711: they are stored in the machine as 32 or 64, this means the same
712: binary file may be read on any machine. Hence you CANNOT use sizeof()
713: to determine the offset or location.
715: Concepts: binary files^seeking
716: Concepts: files^seeking in binary
718: .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
719: PetscBinarySynchronizedSeek()
720: @*/
721: PetscErrorCode PetscBinarySynchronizedSeek(MPI_Comm comm,int fd,off_t off,PetscBinarySeekType whence,off_t *offset)
722: {
724: PetscMPIInt rank;
727: MPI_Comm_rank(comm,&rank);
728: if (!rank) {
729: PetscBinarySeek(fd,off,whence,offset);
730: }
731: return(0);
732: }
734: #if defined(PETSC_HAVE_MPIIO)
735: #if !defined(PETSC_WORDS_BIGENDIAN)
737: #if defined(PETSC_USE_PETSC_MPI_EXTERNAL32)
738: /*
739: MPICH does not provide the external32 representation for MPI_File_set_view() so we need to provide the functions.
740: These are set into MPI in PetscInitialize() via MPI_Register_datarep()
742: Note I use PetscMPIInt for the MPI error codes since that is what MPI uses (instead of the standard PetscErrorCode)
744: The next three routines are not used because MPICH does not support their use
746: */
747: PETSC_EXTERN PetscMPIInt PetscDataRep_extent_fn(MPI_Datatype datatype,MPI_Aint *file_extent,void *extra_state)
748: {
749: MPI_Aint ub;
750: PetscMPIInt ierr;
752: MPI_Type_get_extent(datatype,&ub,file_extent);
753: return ierr;
754: }
756: PETSC_EXTERN PetscMPIInt PetscDataRep_read_conv_fn(void *userbuf, MPI_Datatype datatype,PetscMPIInt count,void *filebuf, MPI_Offset position,void *extra_state)
757: {
758: PetscDataType pdtype;
759: PetscMPIInt ierr;
760: size_t dsize;
762: PetscMPIDataTypeToPetscDataType(datatype,&pdtype);
763: PetscDataTypeGetSize(pdtype,&dsize);
765: /* offset is given in units of MPI_Datatype */
766: userbuf = ((char*)userbuf) + dsize*position;
768: PetscMemcpy(userbuf,filebuf,count*dsize);
769: PetscByteSwap(userbuf,pdtype,count);
770: return ierr;
771: }
773: PetscMPIInt PetscDataRep_write_conv_fn(void *userbuf, MPI_Datatype datatype,PetscMPIInt count,void *filebuf, MPI_Offset position,void *extra_state)
774: {
775: PetscDataType pdtype;
776: PetscMPIInt ierr;
777: size_t dsize;
779: PetscMPIDataTypeToPetscDataType(datatype,&pdtype);
780: PetscDataTypeGetSize(pdtype,&dsize);
782: /* offset is given in units of MPI_Datatype */
783: userbuf = ((char*)userbuf) + dsize*position;
785: PetscMemcpy(filebuf,userbuf,count*dsize);
786: PetscByteSwap(filebuf,pdtype,count);
787: return ierr;
788: }
789: #endif
793: PetscErrorCode MPIU_File_write_all(MPI_File fd,void *data,PetscMPIInt cnt,MPI_Datatype dtype,MPI_Status *status)
794: {
796: PetscDataType pdtype;
799: PetscMPIDataTypeToPetscDataType(dtype,&pdtype);
800: PetscByteSwap(data,pdtype,cnt);
801: MPI_File_write_all(fd,data,cnt,dtype,status);
802: PetscByteSwap(data,pdtype,cnt);
803: return(0);
804: }
808: PetscErrorCode MPIU_File_read_all(MPI_File fd,void *data,PetscMPIInt cnt,MPI_Datatype dtype,MPI_Status *status)
809: {
811: PetscDataType pdtype;
814: PetscMPIDataTypeToPetscDataType(dtype,&pdtype);
815: MPI_File_read_all(fd,data,cnt,dtype,status);
816: PetscByteSwap(data,pdtype,cnt);
817: return(0);
818: }
819: #endif
820: #endif