Actual source code: sysio.c
petsc-3.6.1 2015-08-06
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,"-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: The Buffer p should be read-write buffer, and not static data.
333: This way, byte-swapping is done in-place, and then the buffer is
334: written to the file.
336: This routine restores the original contents of the buffer, after
337: it is written to the file. This is done by byte-swapping in-place
338: the second time. If the flag istemp is set to PETSC_TRUE, the second
339: byte-swapping operation is not done, thus saving some computation,
340: but the buffer is left corrupted.
342: Because byte-swapping may be done on the values in data it cannot be declared const
344: Concepts: files^writing binary
345: Concepts: binary files^writing
347: .seealso: PetscBinaryRead(), PetscBinaryOpen(), PetscBinaryClose(), PetscViewerBinaryGetDescriptor(), PetscBinarySynchronizedWrite(),
348: PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek()
349: @*/
350: PetscErrorCode PetscBinaryWrite(int fd,void *p,PetscInt n,PetscDataType type,PetscBool istemp)
351: {
352: char *pp = (char*)p;
353: int err,wsize;
354: size_t m = (size_t)n,maxblock=65536;
356: #if !defined(PETSC_WORDS_BIGENDIAN)
357: void *ptmp = p;
358: #endif
359: char *fname = NULL;
362: if (n < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Trying to write a negative amount of data %D",n);
363: if (!n) return(0);
365: if (type == PETSC_FUNCTION) {
366: #if defined(PETSC_SERIALIZE_FUNCTIONS)
367: const char *fnametmp;
368: #endif
369: m = 64;
370: fname = (char*)malloc(m*sizeof(char));
371: if (!fname) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Cannot allocate space for function name");
372: #if defined(PETSC_SERIALIZE_FUNCTIONS)
373: if (n > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Can only binary view a single function at a time");
374: PetscFPTFind(*(void**)p,&fnametmp);
375: PetscStrncpy(fname,fnametmp,m);
376: #else
377: PetscStrncpy(fname,"",m);
378: #endif
379: type = PETSC_CHAR;
380: pp = (char*)fname;
381: #if !defined(PETSC_WORDS_BIGENDIAN)
382: ptmp = (void*)fname;
383: #endif
384: }
386: if (type == PETSC_INT) m *= sizeof(PetscInt);
387: else if (type == PETSC_SCALAR) m *= sizeof(PetscScalar);
388: else if (type == PETSC_DOUBLE) m *= sizeof(double);
389: else if (type == PETSC_FLOAT) m *= sizeof(float);
390: else if (type == PETSC_SHORT) m *= sizeof(short);
391: else if (type == PETSC_CHAR) m *= sizeof(char);
392: else if (type == PETSC_ENUM) m *= sizeof(PetscEnum);
393: else if (type == PETSC_BOOL) m *= sizeof(PetscBool);
394: else if (type == PETSC_BIT_LOGICAL) m = PetscBTLength(m)*sizeof(char);
395: else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown type");
397: #if !defined(PETSC_WORDS_BIGENDIAN)
398: PetscByteSwap(ptmp,type,n);
399: #endif
401: while (m) {
402: wsize = (m < maxblock) ? m : maxblock;
403: err = write(fd,pp,wsize);
404: if (err < 0 && errno == EINTR) continue;
405: 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);
406: m -= wsize;
407: pp += wsize;
408: }
410: #if !defined(PETSC_WORDS_BIGENDIAN)
411: if (!istemp) {
412: PetscByteSwap(ptmp,type,n);
413: }
414: #endif
415: if (type == PETSC_FUNCTION) {
416: free(fname);
417: }
418: return(0);
419: }
423: /*@C
424: PetscBinaryOpen - Opens a PETSc binary file.
426: Not Collective
428: Input Parameters:
429: + name - filename
430: - type - type of binary file, one of FILE_MODE_READ, FILE_MODE_APPEND, FILE_MODE_WRITE
432: Output Parameter:
433: . fd - the file
435: Level: advanced
437: Concepts: files^opening binary
438: Concepts: binary files^opening
440: Notes: Files access with PetscBinaryRead() and PetscBinaryWrite() are ALWAYS written in
441: big-endian format. This means the file can be accessed using PetscBinaryOpen() and
442: PetscBinaryRead() and PetscBinaryWrite() on any machine.
444: .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscFileMode, PetscViewerFileSetMode(), PetscViewerBinaryGetDescriptor(),
445: PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek()
447: @*/
448: PetscErrorCode PetscBinaryOpen(const char name[],PetscFileMode mode,int *fd)
449: {
451: #if defined(PETSC_HAVE_O_BINARY)
452: if (mode == FILE_MODE_WRITE) {
453: 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);
454: } else if (mode == FILE_MODE_READ) {
455: 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);
456: } else if (mode == FILE_MODE_APPEND) {
457: 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);
458: #else
459: if (mode == FILE_MODE_WRITE) {
460: if ((*fd = creat(name,0666)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot create file for writing: %s",name);
461: } else if (mode == FILE_MODE_READ) {
462: if ((*fd = open(name,O_RDONLY,0)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file for reading: %s",name);
463: }
464: else if (mode == FILE_MODE_APPEND) {
465: if ((*fd = open(name,O_WRONLY,0)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file for writing: %s",name);
466: #endif
467: } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown file mode");
468: return(0);
469: }
473: /*@
474: PetscBinaryClose - Closes a PETSc binary file.
476: Not Collective
478: Output Parameter:
479: . fd - the file
481: Level: advanced
483: .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
484: PetscBinarySynchronizedSeek()
485: @*/
486: PetscErrorCode PetscBinaryClose(int fd)
487: {
489: close(fd);
490: return(0);
491: }
496: /*@
497: PetscBinarySeek - Moves the file pointer on a PETSc binary file.
499: Not Collective
501: Input Parameters:
502: + fd - the file
503: . off - number of bytes to move. Use PETSC_BINARY_INT_SIZE, PETSC_BINARY_SCALAR_SIZE,
504: etc. in your calculation rather than sizeof() to compute byte lengths.
505: - whence - if PETSC_BINARY_SEEK_SET then off is an absolute location in the file
506: if PETSC_BINARY_SEEK_CUR then off is an offset from the current location
507: if PETSC_BINARY_SEEK_END then off is an offset from the end of file
509: Output Parameter:
510: . offset - new offset in file
512: Level: developer
514: Notes:
515: Integers are stored on the file as 32 long, regardless of whether
516: they are stored in the machine as 32 or 64, this means the same
517: binary file may be read on any machine. Hence you CANNOT use sizeof()
518: to determine the offset or location.
520: Concepts: files^binary seeking
521: Concepts: binary files^seeking
523: .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
524: PetscBinarySynchronizedSeek()
525: @*/
526: PetscErrorCode PetscBinarySeek(int fd,off_t off,PetscBinarySeekType whence,off_t *offset)
527: {
528: int iwhence = 0;
531: if (whence == PETSC_BINARY_SEEK_SET) iwhence = SEEK_SET;
532: else if (whence == PETSC_BINARY_SEEK_CUR) iwhence = SEEK_CUR;
533: else if (whence == PETSC_BINARY_SEEK_END) iwhence = SEEK_END;
534: else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown seek location");
535: #if defined(PETSC_HAVE_LSEEK)
536: *offset = lseek(fd,off,iwhence);
537: #elif defined(PETSC_HAVE__LSEEK)
538: *offset = _lseek(fd,(long)off,iwhence);
539: #else
540: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS,"System does not have a way of seeking on a file");
541: #endif
542: return(0);
543: }
547: /*@C
548: PetscBinarySynchronizedRead - Reads from a binary file.
550: Collective on MPI_Comm
552: Input Parameters:
553: + comm - the MPI communicator
554: . fd - the file
555: . n - the number of items to read
556: - type - the type of items to read (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)
558: Output Parameters:
559: . p - the buffer
561: Options Database Key:
562: . -binary_longints - indicates the file was generated on a Cray vector
563: machine (not the T3E/D) and the ints are stored as 64 bit
564: quantities, otherwise they are stored as 32 bit
566: Level: developer
568: Notes:
569: Does a PetscBinaryRead() followed by an MPI_Bcast()
571: PetscBinarySynchronizedRead() uses byte swapping to work on all machines.
572: Integers are stored on the file as 32 long, regardless of whether
573: they are stored in the machine as 32 or 64, this means the same
574: binary file may be read on any machine.
576: Concepts: files^synchronized reading of binary files
577: Concepts: binary files^reading, synchronized
579: .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscBinaryRead(), PetscBinarySynchronizedWrite(),
580: PetscBinarySynchronizedSeek()
581: @*/
582: PetscErrorCode PetscBinarySynchronizedRead(MPI_Comm comm,int fd,void *p,PetscInt n,PetscDataType type)
583: {
585: PetscMPIInt rank;
586: MPI_Datatype mtype;
587: char *fname = NULL;
588: void *ptmp = NULL;
591: if (type == PETSC_FUNCTION) {
592: n = 64;
593: type = PETSC_CHAR;
594: ptmp = p;
595: fname = (char*)malloc(n*sizeof(char));
596: if (!fname) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Cannot allocate space for function name");
597: p = (void*)fname;
598: }
600: MPI_Comm_rank(comm,&rank);
601: if (!rank) {
602: PetscBinaryRead(fd,p,n,type);
603: }
604: PetscDataTypeToMPIDataType(type,&mtype);
605: MPI_Bcast(p,n,mtype,0,comm);
607: if (type == PETSC_FUNCTION) {
608: #if defined(PETSC_SERIALIZE_FUNCTIONS)
609: PetscDLLibrarySym(PETSC_COMM_SELF,&PetscDLLibrariesLoaded,NULL,fname,(void**)ptmp);
610: #else
611: *(void**)ptmp = NULL;
612: #endif
613: free(fname);
614: }
615: return(0);
616: }
620: /*@C
621: PetscBinarySynchronizedWrite - writes to a binary file.
623: Collective on MPI_Comm
625: Input Parameters:
626: + comm - the MPI communicator
627: . fd - the file
628: . n - the number of items to write
629: . p - the buffer
630: . istemp - the buffer may be changed
631: - type - the type of items to write (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)
633: Level: developer
635: Notes:
636: Process 0 does a PetscBinaryWrite()
638: PetscBinarySynchronizedWrite() uses byte swapping to work on all machines.
639: Integers are stored on the file as 32 long, regardless of whether
640: they are stored in the machine as 32 or 64, this means the same
641: binary file may be read on any machine.
643: Notes: because byte-swapping may be done on the values in data it cannot be declared const
645: WARNING: This is NOT like PetscSynchronizedFPrintf()! This routine ignores calls on all but process 0,
646: while PetscSynchronizedFPrintf() has all processes print their strings in order.
648: Concepts: files^synchronized writing of binary files
649: Concepts: binary files^reading, synchronized
651: .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscBinaryRead(), PetscBinarySynchronizedRead(),
652: PetscBinarySynchronizedSeek()
653: @*/
654: PetscErrorCode PetscBinarySynchronizedWrite(MPI_Comm comm,int fd,void *p,PetscInt n,PetscDataType type,PetscBool istemp)
655: {
657: PetscMPIInt rank;
660: MPI_Comm_rank(comm,&rank);
661: if (!rank) {
662: PetscBinaryWrite(fd,p,n,type,istemp);
663: }
664: return(0);
665: }
669: /*@C
670: PetscBinarySynchronizedSeek - Moves the file pointer on a PETSc binary file.
673: Input Parameters:
674: + fd - the file
675: . whence - if PETSC_BINARY_SEEK_SET then size is an absolute location in the file
676: if PETSC_BINARY_SEEK_CUR then size is offset from current location
677: if PETSC_BINARY_SEEK_END then size is offset from end of file
678: - off - number of bytes to move. Use PETSC_BINARY_INT_SIZE, PETSC_BINARY_SCALAR_SIZE,
679: etc. in your calculation rather than sizeof() to compute byte lengths.
681: Output Parameter:
682: . offset - new offset in file
684: Level: developer
686: Notes:
687: Integers are stored on the file as 32 long, regardless of whether
688: they are stored in the machine as 32 or 64, this means the same
689: binary file may be read on any machine. Hence you CANNOT use sizeof()
690: to determine the offset or location.
692: Concepts: binary files^seeking
693: Concepts: files^seeking in binary
695: .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
696: PetscBinarySynchronizedSeek()
697: @*/
698: PetscErrorCode PetscBinarySynchronizedSeek(MPI_Comm comm,int fd,off_t off,PetscBinarySeekType whence,off_t *offset)
699: {
701: PetscMPIInt rank;
704: MPI_Comm_rank(comm,&rank);
705: if (!rank) {
706: PetscBinarySeek(fd,off,whence,offset);
707: }
708: return(0);
709: }
711: #if defined(PETSC_HAVE_MPIIO)
712: #if !defined(PETSC_WORDS_BIGENDIAN)
714: #if defined(PETSC_USE_PETSC_MPI_EXTERNAL32)
715: /*
716: MPICH does not provide the external32 representation for MPI_File_set_view() so we need to provide the functions.
717: These are set into MPI in PetscInitialize() via MPI_Register_datarep()
719: Note I use PetscMPIInt for the MPI error codes since that is what MPI uses (instead of the standard PetscErrorCode)
721: The next three routines are not used because MPICH does not support their use
723: */
724: PETSC_EXTERN PetscMPIInt PetscDataRep_extent_fn(MPI_Datatype datatype,MPI_Aint *file_extent,void *extra_state)
725: {
726: MPI_Aint ub;
727: PetscMPIInt ierr;
729: MPI_Type_get_extent(datatype,&ub,file_extent);
730: return ierr;
731: }
733: PETSC_EXTERN PetscMPIInt PetscDataRep_read_conv_fn(void *userbuf, MPI_Datatype datatype,PetscMPIInt count,void *filebuf, MPI_Offset position,void *extra_state)
734: {
735: PetscDataType pdtype;
736: PetscMPIInt ierr;
737: size_t dsize;
739: PetscMPIDataTypeToPetscDataType(datatype,&pdtype);
740: PetscDataTypeGetSize(pdtype,&dsize);
742: /* offset is given in units of MPI_Datatype */
743: userbuf = ((char*)userbuf) + dsize*position;
745: PetscMemcpy(userbuf,filebuf,count*dsize);
746: PetscByteSwap(userbuf,pdtype,count);
747: return ierr;
748: }
750: PetscMPIInt PetscDataRep_write_conv_fn(void *userbuf, MPI_Datatype datatype,PetscMPIInt count,void *filebuf, MPI_Offset position,void *extra_state)
751: {
752: PetscDataType pdtype;
753: PetscMPIInt ierr;
754: size_t dsize;
756: PetscMPIDataTypeToPetscDataType(datatype,&pdtype);
757: PetscDataTypeGetSize(pdtype,&dsize);
759: /* offset is given in units of MPI_Datatype */
760: userbuf = ((char*)userbuf) + dsize*position;
762: PetscMemcpy(filebuf,userbuf,count*dsize);
763: PetscByteSwap(filebuf,pdtype,count);
764: return ierr;
765: }
766: #endif
770: PetscErrorCode MPIU_File_write_all(MPI_File fd,void *data,PetscMPIInt cnt,MPI_Datatype dtype,MPI_Status *status)
771: {
773: PetscDataType pdtype;
776: PetscMPIDataTypeToPetscDataType(dtype,&pdtype);
777: PetscByteSwap(data,pdtype,cnt);
778: MPI_File_write_all(fd,data,cnt,dtype,status);
779: PetscByteSwap(data,pdtype,cnt);
780: return(0);
781: }
785: PetscErrorCode MPIU_File_read_all(MPI_File fd,void *data,PetscMPIInt cnt,MPI_Datatype dtype,MPI_Status *status)
786: {
788: PetscDataType pdtype;
791: PetscMPIDataTypeToPetscDataType(dtype,&pdtype);
792: MPI_File_read_all(fd,data,cnt,dtype,status);
793: PetscByteSwap(data,pdtype,cnt);
794: return(0);
795: }
796: #endif
797: #endif