1 2 /* 3 This file contains simple binary read/write routines. 4 */ 5 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> 16 17 const char *const PetscFileModes[] = {"READ","WRITE","APPEND","UPDATE","APPEND_UPDATE","PetscFileMode","PETSC_FILE_",0}; 18 19 /* --------------------------------------------------------- */ 20 /* 21 PetscByteSwapEnum - Swap bytes in a PETSc Enum 22 23 */ 24 PetscErrorCode PetscByteSwapEnum(PetscEnum *buff,PetscInt n) 25 { 26 PetscInt i,j; 27 PetscEnum tmp = ENUM_DUMMY; 28 char *ptr1,*ptr2 = (char*)&tmp; 29 30 PetscFunctionBegin; 31 for (j=0; j<n; j++) { 32 ptr1 = (char*)(buff + j); 33 for (i=0; i<(PetscInt)sizeof(PetscEnum); i++) ptr2[i] = ptr1[sizeof(PetscEnum)-1-i]; 34 for (i=0; i<(PetscInt)sizeof(PetscEnum); i++) ptr1[i] = ptr2[i]; 35 } 36 PetscFunctionReturn(0); 37 } 38 39 /* 40 PetscByteSwapBool - Swap bytes in a PETSc Bool 41 42 */ 43 PetscErrorCode PetscByteSwapBool(PetscBool *buff,PetscInt n) 44 { 45 PetscInt i,j; 46 PetscBool tmp = PETSC_FALSE; 47 char *ptr1,*ptr2 = (char*)&tmp; 48 49 PetscFunctionBegin; 50 for (j=0; j<n; j++) { 51 ptr1 = (char*)(buff + j); 52 for (i=0; i<(PetscInt)sizeof(PetscBool); i++) ptr2[i] = ptr1[sizeof(PetscBool)-1-i]; 53 for (i=0; i<(PetscInt)sizeof(PetscBool); i++) ptr1[i] = ptr2[i]; 54 } 55 PetscFunctionReturn(0); 56 } 57 58 /* 59 PetscByteSwapInt - Swap bytes in a PETSc integer (which may be 32 or 64 bits) 60 61 */ 62 PetscErrorCode PetscByteSwapInt(PetscInt *buff,PetscInt n) 63 { 64 PetscInt i,j,tmp = 0; 65 char *ptr1,*ptr2 = (char*)&tmp; 66 67 PetscFunctionBegin; 68 for (j=0; j<n; j++) { 69 ptr1 = (char*)(buff + j); 70 for (i=0; i<(PetscInt)sizeof(PetscInt); i++) ptr2[i] = ptr1[sizeof(PetscInt)-1-i]; 71 for (i=0; i<(PetscInt)sizeof(PetscInt); i++) ptr1[i] = ptr2[i]; 72 } 73 PetscFunctionReturn(0); 74 } 75 /* --------------------------------------------------------- */ 76 /* 77 PetscByteSwapShort - Swap bytes in a short 78 */ 79 PetscErrorCode PetscByteSwapShort(short *buff,PetscInt n) 80 { 81 PetscInt i,j; 82 short tmp; 83 char *ptr1,*ptr2 = (char*)&tmp; 84 85 PetscFunctionBegin; 86 for (j=0; j<n; j++) { 87 ptr1 = (char*)(buff + j); 88 for (i=0; i<(PetscInt) sizeof(short); i++) ptr2[i] = ptr1[sizeof(short)-1-i]; 89 for (i=0; i<(PetscInt) sizeof(short); i++) ptr1[i] = ptr2[i]; 90 } 91 PetscFunctionReturn(0); 92 } 93 /* --------------------------------------------------------- */ 94 /* 95 PetscByteSwapScalar - Swap bytes in a PetscScalar 96 The complex case is dealt with with an array of PetscReal, twice as long. 97 */ 98 PetscErrorCode PetscByteSwapScalar(PetscScalar *buff,PetscInt n) 99 { 100 PetscInt i,j; 101 PetscReal tmp,*buff1 = (PetscReal*)buff; 102 char *ptr1,*ptr2 = (char*)&tmp; 103 104 PetscFunctionBegin; 105 #if defined(PETSC_USE_COMPLEX) 106 n *= 2; 107 #endif 108 for (j=0; j<n; j++) { 109 ptr1 = (char*)(buff1 + j); 110 for (i=0; i<(PetscInt) sizeof(PetscReal); i++) ptr2[i] = ptr1[sizeof(PetscReal)-1-i]; 111 for (i=0; i<(PetscInt) sizeof(PetscReal); i++) ptr1[i] = ptr2[i]; 112 } 113 PetscFunctionReturn(0); 114 } 115 /* --------------------------------------------------------- */ 116 /* 117 PetscByteSwapDouble - Swap bytes in a double 118 */ 119 PetscErrorCode PetscByteSwapDouble(double *buff,PetscInt n) 120 { 121 PetscInt i,j; 122 double tmp,*buff1 = (double*)buff; 123 char *ptr1,*ptr2 = (char*)&tmp; 124 125 PetscFunctionBegin; 126 for (j=0; j<n; j++) { 127 ptr1 = (char*)(buff1 + j); 128 for (i=0; i<(PetscInt) sizeof(double); i++) ptr2[i] = ptr1[sizeof(double)-1-i]; 129 for (i=0; i<(PetscInt) sizeof(double); i++) ptr1[i] = ptr2[i]; 130 } 131 PetscFunctionReturn(0); 132 } 133 134 /* 135 PetscByteSwapFloat - Swap bytes in a float 136 */ 137 PetscErrorCode PetscByteSwapFloat(float *buff,PetscInt n) 138 { 139 PetscInt i,j; 140 float tmp,*buff1 = (float*)buff; 141 char *ptr1,*ptr2 = (char*)&tmp; 142 143 PetscFunctionBegin; 144 for (j=0; j<n; j++) { 145 ptr1 = (char*)(buff1 + j); 146 for (i=0; i<(PetscInt) sizeof(float); i++) ptr2[i] = ptr1[sizeof(float)-1-i]; 147 for (i=0; i<(PetscInt) sizeof(float); i++) ptr1[i] = ptr2[i]; 148 } 149 PetscFunctionReturn(0); 150 } 151 152 PetscErrorCode PetscByteSwap(void *data,PetscDataType pdtype,PetscInt count) 153 { 154 PetscErrorCode ierr; 155 156 PetscFunctionBegin; 157 if (pdtype == PETSC_INT) {ierr = PetscByteSwapInt((PetscInt*)data,count);CHKERRQ(ierr);} 158 else if (pdtype == PETSC_ENUM) {ierr = PetscByteSwapEnum((PetscEnum*)data,count);CHKERRQ(ierr);} 159 else if (pdtype == PETSC_BOOL) {ierr = PetscByteSwapBool((PetscBool*)data,count);CHKERRQ(ierr);} 160 else if (pdtype == PETSC_SCALAR) {ierr = PetscByteSwapScalar((PetscScalar*)data,count);CHKERRQ(ierr);} 161 else if (pdtype == PETSC_DOUBLE) {ierr = PetscByteSwapDouble((double*)data,count);CHKERRQ(ierr);} 162 else if (pdtype == PETSC_FLOAT) {ierr = PetscByteSwapFloat((float*)data,count);CHKERRQ(ierr);} 163 else if (pdtype == PETSC_SHORT) {ierr = PetscByteSwapShort((short*)data,count);CHKERRQ(ierr);} 164 PetscFunctionReturn(0); 165 } 166 167 /* --------------------------------------------------------- */ 168 /*@ 169 PetscBinaryRead - Reads from a binary file. 170 171 Not Collective 172 173 Input Parameters: 174 + fd - the file 175 . n - the number of items to read 176 - type - the type of items to read (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR) 177 178 Output Parameters: 179 . p - the buffer 180 181 182 183 Level: developer 184 185 Notes: 186 PetscBinaryRead() uses byte swapping to work on all machines; the files 187 are written to file ALWAYS using big-endian ordering. On small-endian machines the numbers 188 are converted to the small-endian format when they are read in from the file. 189 When PETSc is ./configure with --with-64bit-indices the integers are written to the 190 file as 64 bit integers, this means they can only be read back in when the option --with-64bit-indices 191 is used. 192 193 Concepts: files^reading binary 194 Concepts: binary files^reading 195 196 .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscViewerBinaryGetDescriptor(), PetscBinarySynchronizedWrite(), 197 PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek() 198 @*/ 199 PetscErrorCode PetscBinaryRead(int fd,void *p,PetscInt n,PetscDataType type) 200 { 201 int wsize,err; 202 size_t m = (size_t) n,maxblock = 65536; 203 char *pp = (char*)p; 204 #if defined(PETSC_USE_REAL___FLOAT128) 205 PetscBool readdouble = PETSC_FALSE; 206 double *ppp; 207 #endif 208 #if !defined(PETSC_WORDS_BIGENDIAN) || defined(PETSC_USE_REAL___FLOAT128) 209 PetscErrorCode ierr; 210 #endif 211 #if !defined(PETSC_WORDS_BIGENDIAN) 212 void *ptmp = p; 213 #endif 214 char *fname = NULL; 215 216 PetscFunctionBegin; 217 if (n < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Trying to write a negative amount of data %D",n); 218 if (!n) PetscFunctionReturn(0); 219 220 if (type == PETSC_FUNCTION) { 221 m = 64; 222 type = PETSC_CHAR; 223 fname = (char*) malloc(m*sizeof(char)); 224 if (!fname) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Cannot allocate space for function name"); 225 pp = (char*)fname; 226 #if !defined(PETSC_WORDS_BIGENDIAN) 227 ptmp = (void*)fname; 228 #endif 229 } 230 231 if (type == PETSC_INT) m *= sizeof(PetscInt); 232 else if (type == PETSC_SCALAR) m *= sizeof(PetscScalar); 233 else if (type == PETSC_DOUBLE) m *= sizeof(double); 234 else if (type == PETSC_FLOAT) m *= sizeof(float); 235 else if (type == PETSC_SHORT) m *= sizeof(short); 236 else if (type == PETSC_CHAR) m *= sizeof(char); 237 else if (type == PETSC_ENUM) m *= sizeof(PetscEnum); 238 else if (type == PETSC_BOOL) m *= sizeof(PetscBool); 239 else if (type == PETSC_BIT_LOGICAL) m = PetscBTLength(m)*sizeof(char); 240 else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown type"); 241 242 #if defined(PETSC_USE_REAL___FLOAT128) 243 ierr = PetscOptionsGetBool(NULL,NULL,"-binary_read_double",&readdouble,NULL);CHKERRQ(ierr); 244 /* If using __float128 precision we still read in doubles from file */ 245 if (type == PETSC_SCALAR && readdouble) { 246 m = m/2; 247 ierr = PetscMalloc1(n,&ppp);CHKERRQ(ierr); 248 pp = (char*)ppp; 249 } 250 #endif 251 252 while (m) { 253 wsize = (m < maxblock) ? m : maxblock; 254 err = read(fd,pp,wsize); 255 if (err < 0 && errno == EINTR) continue; 256 if (!err && wsize > 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_READ,"Read past end of file"); 257 if (err < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_READ,"Error reading from file, errno %d",errno); 258 m -= err; 259 pp += err; 260 } 261 262 #if defined(PETSC_USE_REAL___FLOAT128) 263 if (type == PETSC_SCALAR && readdouble) { 264 PetscScalar *pv = (PetscScalar*) p; 265 PetscInt i; 266 #if !defined(PETSC_WORDS_BIGENDIAN) 267 ierr = PetscByteSwapDouble(ppp,n);CHKERRQ(ierr); 268 #endif 269 for (i=0; i<n; i++) pv[i] = ppp[i]; 270 ierr = PetscFree(ppp);CHKERRQ(ierr); 271 PetscFunctionReturn(0); 272 } 273 #endif 274 275 #if !defined(PETSC_WORDS_BIGENDIAN) 276 ierr = PetscByteSwap(ptmp,type,n);CHKERRQ(ierr); 277 #endif 278 279 if (type == PETSC_FUNCTION) { 280 #if defined(PETSC_SERIALIZE_FUNCTIONS) 281 ierr = PetscDLSym(NULL,fname,(void**)p);CHKERRQ(ierr); 282 #else 283 *(void**)p = NULL; 284 #endif 285 free(fname); 286 } 287 PetscFunctionReturn(0); 288 } 289 /* --------------------------------------------------------- */ 290 /*@ 291 PetscBinaryWrite - Writes to a binary file. 292 293 Not Collective 294 295 Input Parameters: 296 + fd - the file 297 . p - the buffer 298 . n - the number of items to write 299 . type - the type of items to read (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR) 300 - istemp - PETSC_FALSE if buffer data should be preserved, PETSC_TRUE otherwise. 301 302 Level: advanced 303 304 Notes: 305 PetscBinaryWrite() uses byte swapping to work on all machines; the files 306 are written using big-endian ordering to the file. On small-endian machines the numbers 307 are converted to the big-endian format when they are written to disk. 308 When PETSc is ./configure with --with-64bit-indices the integers are written to the 309 file as 64 bit integers, this means they can only be read back in when the option --with-64bit-indices 310 is used. 311 312 If running with __float128 precision the output is in __float128 unless one uses the -binary_write_double option 313 314 The Buffer p should be read-write buffer, and not static data. 315 This way, byte-swapping is done in-place, and then the buffer is 316 written to the file. 317 318 This routine restores the original contents of the buffer, after 319 it is written to the file. This is done by byte-swapping in-place 320 the second time. If the flag istemp is set to PETSC_TRUE, the second 321 byte-swapping operation is not done, thus saving some computation, 322 but the buffer is left corrupted. 323 324 Because byte-swapping may be done on the values in data it cannot be declared const 325 326 Concepts: files^writing binary 327 Concepts: binary files^writing 328 329 .seealso: PetscBinaryRead(), PetscBinaryOpen(), PetscBinaryClose(), PetscViewerBinaryGetDescriptor(), PetscBinarySynchronizedWrite(), 330 PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek() 331 @*/ 332 PetscErrorCode PetscBinaryWrite(int fd,void *p,PetscInt n,PetscDataType type,PetscBool istemp) 333 { 334 char *pp = (char*)p; 335 int err,wsize; 336 size_t m = (size_t)n,maxblock=65536; 337 PetscErrorCode ierr; 338 #if !defined(PETSC_WORDS_BIGENDIAN) 339 void *ptmp = p; 340 #endif 341 char *fname = NULL; 342 #if defined(PETSC_USE_REAL___FLOAT128) 343 PetscBool writedouble = PETSC_FALSE; 344 double *ppp; 345 PetscReal *pv; 346 PetscInt i; 347 #endif 348 PetscDataType wtype = type; 349 350 PetscFunctionBegin; 351 if (n < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Trying to write a negative amount of data %D",n); 352 if (!n) PetscFunctionReturn(0); 353 354 if (type == PETSC_FUNCTION) { 355 #if defined(PETSC_SERIALIZE_FUNCTIONS) 356 const char *fnametmp; 357 #endif 358 m = 64; 359 fname = (char*)malloc(m*sizeof(char)); 360 if (!fname) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Cannot allocate space for function name"); 361 #if defined(PETSC_SERIALIZE_FUNCTIONS) 362 if (n > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Can only binary view a single function at a time"); 363 ierr = PetscFPTFind(*(void**)p,&fnametmp);CHKERRQ(ierr); 364 ierr = PetscStrncpy(fname,fnametmp,m);CHKERRQ(ierr); 365 #else 366 ierr = PetscStrncpy(fname,"",m);CHKERRQ(ierr); 367 #endif 368 type = PETSC_CHAR; 369 pp = (char*)fname; 370 #if !defined(PETSC_WORDS_BIGENDIAN) 371 ptmp = (void*)fname; 372 #endif 373 } 374 375 #if defined(PETSC_USE_REAL___FLOAT128) 376 ierr = PetscOptionsGetBool(NULL,NULL,"-binary_write_double",&writedouble,NULL);CHKERRQ(ierr); 377 /* If using __float128 precision we still write in doubles to file */ 378 if (type == PETSC_SCALAR && writedouble) { 379 wtype = PETSC_DOUBLE; 380 ierr = PetscMalloc1(n,&ppp);CHKERRQ(ierr); 381 pv = (PetscReal*)pp; 382 for (i=0; i<n; i++) { 383 ppp[i] = (double) pv[i]; 384 } 385 pp = (char*)ppp; 386 ptmp = (char*)ppp; 387 } 388 #endif 389 390 if (wtype == PETSC_INT) m *= sizeof(PetscInt); 391 else if (wtype == PETSC_SCALAR) m *= sizeof(PetscScalar); 392 else if (wtype == PETSC_DOUBLE) m *= sizeof(double); 393 else if (wtype == PETSC_FLOAT) m *= sizeof(float); 394 else if (wtype == PETSC_SHORT) m *= sizeof(short); 395 else if (wtype == PETSC_CHAR) m *= sizeof(char); 396 else if (wtype == PETSC_ENUM) m *= sizeof(PetscEnum); 397 else if (wtype == PETSC_BOOL) m *= sizeof(PetscBool); 398 else if (wtype == PETSC_BIT_LOGICAL) m = PetscBTLength(m)*sizeof(char); 399 else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown type"); 400 401 #if !defined(PETSC_WORDS_BIGENDIAN) 402 ierr = PetscByteSwap(ptmp,wtype,n);CHKERRQ(ierr); 403 #endif 404 405 while (m) { 406 wsize = (m < maxblock) ? m : maxblock; 407 err = write(fd,pp,wsize); 408 if (err < 0 && errno == EINTR) continue; 409 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); 410 m -= wsize; 411 pp += wsize; 412 } 413 414 #if !defined(PETSC_WORDS_BIGENDIAN) 415 if (!istemp) { 416 ierr = PetscByteSwap(ptmp,wtype,n);CHKERRQ(ierr); 417 } 418 #endif 419 if (type == PETSC_FUNCTION) { 420 free(fname); 421 } 422 #if defined(PETSC_USE_REAL___FLOAT128) 423 if (type == PETSC_SCALAR && writedouble) { 424 ierr = PetscFree(ppp);CHKERRQ(ierr); 425 } 426 #endif 427 PetscFunctionReturn(0); 428 } 429 430 /*@C 431 PetscBinaryOpen - Opens a PETSc binary file. 432 433 Not Collective 434 435 Input Parameters: 436 + name - filename 437 - type - type of binary file, one of FILE_MODE_READ, FILE_MODE_APPEND, FILE_MODE_WRITE 438 439 Output Parameter: 440 . fd - the file 441 442 Level: advanced 443 444 Concepts: files^opening binary 445 Concepts: binary files^opening 446 447 Notes: Files access with PetscBinaryRead() and PetscBinaryWrite() are ALWAYS written in 448 big-endian format. This means the file can be accessed using PetscBinaryOpen() and 449 PetscBinaryRead() and PetscBinaryWrite() on any machine. 450 451 .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscFileMode, PetscViewerFileSetMode(), PetscViewerBinaryGetDescriptor(), 452 PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek() 453 454 @*/ 455 PetscErrorCode PetscBinaryOpen(const char name[],PetscFileMode mode,int *fd) 456 { 457 PetscFunctionBegin; 458 #if defined(PETSC_HAVE_O_BINARY) 459 if (mode == FILE_MODE_WRITE) { 460 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); 461 } else if (mode == FILE_MODE_READ) { 462 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); 463 } else if (mode == FILE_MODE_APPEND) { 464 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); 465 #else 466 if (mode == FILE_MODE_WRITE) { 467 if ((*fd = creat(name,0666)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot create file for writing: %s",name); 468 } else if (mode == FILE_MODE_READ) { 469 if ((*fd = open(name,O_RDONLY,0)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file for reading: %s",name); 470 } 471 else if (mode == FILE_MODE_APPEND) { 472 if ((*fd = open(name,O_WRONLY,0)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file for writing: %s",name); 473 #endif 474 } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown file mode"); 475 PetscFunctionReturn(0); 476 } 477 478 /*@ 479 PetscBinaryClose - Closes a PETSc binary file. 480 481 Not Collective 482 483 Output Parameter: 484 . fd - the file 485 486 Level: advanced 487 488 .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(), 489 PetscBinarySynchronizedSeek() 490 @*/ 491 PetscErrorCode PetscBinaryClose(int fd) 492 { 493 PetscFunctionBegin; 494 close(fd); 495 PetscFunctionReturn(0); 496 } 497 498 499 /*@C 500 PetscBinarySeek - Moves the file pointer on a PETSc binary file. 501 502 Not Collective 503 504 Input Parameters: 505 + fd - the file 506 . off - number of bytes to move. Use PETSC_BINARY_INT_SIZE, PETSC_BINARY_SCALAR_SIZE, 507 etc. in your calculation rather than sizeof() to compute byte lengths. 508 - whence - if PETSC_BINARY_SEEK_SET then off is an absolute location in the file 509 if PETSC_BINARY_SEEK_CUR then off is an offset from the current location 510 if PETSC_BINARY_SEEK_END then off is an offset from the end of file 511 512 Output Parameter: 513 . offset - new offset in file 514 515 Level: developer 516 517 Notes: 518 Integers are stored on the file as 32 long, regardless of whether 519 they are stored in the machine as 32 or 64, this means the same 520 binary file may be read on any machine. Hence you CANNOT use sizeof() 521 to determine the offset or location. 522 523 Concepts: files^binary seeking 524 Concepts: binary files^seeking 525 526 .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(), 527 PetscBinarySynchronizedSeek() 528 @*/ 529 PetscErrorCode PetscBinarySeek(int fd,off_t off,PetscBinarySeekType whence,off_t *offset) 530 { 531 int iwhence = 0; 532 533 PetscFunctionBegin; 534 if (whence == PETSC_BINARY_SEEK_SET) iwhence = SEEK_SET; 535 else if (whence == PETSC_BINARY_SEEK_CUR) iwhence = SEEK_CUR; 536 else if (whence == PETSC_BINARY_SEEK_END) iwhence = SEEK_END; 537 else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown seek location"); 538 #if defined(PETSC_HAVE_LSEEK) 539 *offset = lseek(fd,off,iwhence); 540 #elif defined(PETSC_HAVE__LSEEK) 541 *offset = _lseek(fd,(long)off,iwhence); 542 #else 543 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS,"System does not have a way of seeking on a file"); 544 #endif 545 PetscFunctionReturn(0); 546 } 547 548 /*@C 549 PetscBinarySynchronizedRead - Reads from a binary file. 550 551 Collective on MPI_Comm 552 553 Input Parameters: 554 + comm - the MPI communicator 555 . fd - the file 556 . n - the number of items to read 557 - type - the type of items to read (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR) 558 559 Output Parameters: 560 . p - the buffer 561 562 Level: developer 563 564 Notes: 565 Does a PetscBinaryRead() followed by an MPI_Bcast() 566 567 PetscBinarySynchronizedRead() uses byte swapping to work on all machines. 568 Integers are stored on the file as 32 long, regardless of whether 569 they are stored in the machine as 32 or 64, this means the same 570 binary file may be read on any machine. 571 572 Concepts: files^synchronized reading of binary files 573 Concepts: binary files^reading, synchronized 574 575 .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscBinaryRead(), PetscBinarySynchronizedWrite(), 576 PetscBinarySynchronizedSeek() 577 @*/ 578 PetscErrorCode PetscBinarySynchronizedRead(MPI_Comm comm,int fd,void *p,PetscInt n,PetscDataType type) 579 { 580 PetscErrorCode ierr; 581 PetscMPIInt rank; 582 MPI_Datatype mtype; 583 char *fname = NULL; 584 void *ptmp = NULL; 585 586 PetscFunctionBegin; 587 if (type == PETSC_FUNCTION) { 588 n = 64; 589 type = PETSC_CHAR; 590 ptmp = p; 591 fname = (char*)malloc(n*sizeof(char)); 592 if (!fname) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Cannot allocate space for function name"); 593 p = (void*)fname; 594 } 595 596 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 597 if (!rank) { 598 ierr = PetscBinaryRead(fd,p,n,type);CHKERRQ(ierr); 599 } 600 ierr = PetscDataTypeToMPIDataType(type,&mtype);CHKERRQ(ierr); 601 ierr = MPI_Bcast(p,n,mtype,0,comm);CHKERRQ(ierr); 602 603 if (type == PETSC_FUNCTION) { 604 #if defined(PETSC_SERIALIZE_FUNCTIONS) 605 ierr = PetscDLLibrarySym(PETSC_COMM_SELF,&PetscDLLibrariesLoaded,NULL,fname,(void**)ptmp);CHKERRQ(ierr); 606 #else 607 *(void**)ptmp = NULL; 608 #endif 609 free(fname); 610 } 611 PetscFunctionReturn(0); 612 } 613 614 /*@C 615 PetscBinarySynchronizedWrite - writes to a binary file. 616 617 Collective on MPI_Comm 618 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) 626 627 Level: developer 628 629 Notes: 630 Process 0 does a PetscBinaryWrite() 631 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. 636 637 Notes: because byte-swapping may be done on the values in data it cannot be declared const 638 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. 641 642 Concepts: files^synchronized writing of binary files 643 Concepts: binary files^reading, synchronized 644 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 { 650 PetscErrorCode ierr; 651 PetscMPIInt rank; 652 653 PetscFunctionBegin; 654 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 655 if (!rank) { 656 ierr = PetscBinaryWrite(fd,p,n,type,istemp);CHKERRQ(ierr); 657 } 658 PetscFunctionReturn(0); 659 } 660 661 /*@C 662 PetscBinarySynchronizedSeek - Moves the file pointer on a PETSc binary file. 663 664 665 Input Parameters: 666 + fd - the file 667 . whence - if PETSC_BINARY_SEEK_SET then size is an absolute location in the file 668 if PETSC_BINARY_SEEK_CUR then size is offset from current location 669 if PETSC_BINARY_SEEK_END then size is offset from end of file 670 - off - number of bytes to move. Use PETSC_BINARY_INT_SIZE, PETSC_BINARY_SCALAR_SIZE, 671 etc. in your calculation rather than sizeof() to compute byte lengths. 672 673 Output Parameter: 674 . offset - new offset in file 675 676 Level: developer 677 678 Notes: 679 Integers are stored on the file as 32 long, regardless of whether 680 they are stored in the machine as 32 or 64, this means the same 681 binary file may be read on any machine. Hence you CANNOT use sizeof() 682 to determine the offset or location. 683 684 Concepts: binary files^seeking 685 Concepts: files^seeking in binary 686 687 .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(), 688 PetscBinarySynchronizedSeek() 689 @*/ 690 PetscErrorCode PetscBinarySynchronizedSeek(MPI_Comm comm,int fd,off_t off,PetscBinarySeekType whence,off_t *offset) 691 { 692 PetscErrorCode ierr; 693 PetscMPIInt rank; 694 695 PetscFunctionBegin; 696 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 697 if (!rank) { 698 ierr = PetscBinarySeek(fd,off,whence,offset);CHKERRQ(ierr); 699 } 700 PetscFunctionReturn(0); 701 } 702 703 #if defined(PETSC_HAVE_MPIIO) 704 #if !defined(PETSC_WORDS_BIGENDIAN) 705 706 #if defined(PETSC_USE_PETSC_MPI_EXTERNAL32) 707 /* 708 MPICH does not provide the external32 representation for MPI_File_set_view() so we need to provide the functions. 709 These are set into MPI in PetscInitialize() via MPI_Register_datarep() 710 711 Note I use PetscMPIInt for the MPI error codes since that is what MPI uses (instead of the standard PetscErrorCode) 712 713 The next three routines are not used because MPICH does not support their use 714 715 */ 716 PETSC_EXTERN PetscMPIInt PetscDataRep_extent_fn(MPI_Datatype datatype,MPI_Aint *file_extent,void *extra_state) 717 { 718 MPI_Aint ub; 719 PetscMPIInt ierr; 720 721 ierr = MPI_Type_get_extent(datatype,&ub,file_extent); 722 return ierr; 723 } 724 725 PETSC_EXTERN PetscMPIInt PetscDataRep_read_conv_fn(void *userbuf, MPI_Datatype datatype,PetscMPIInt count,void *filebuf, MPI_Offset position,void *extra_state) 726 { 727 PetscDataType pdtype; 728 PetscMPIInt ierr; 729 size_t dsize; 730 731 ierr = PetscMPIDataTypeToPetscDataType(datatype,&pdtype);CHKERRQ(ierr); 732 ierr = PetscDataTypeGetSize(pdtype,&dsize);CHKERRQ(ierr); 733 734 /* offset is given in units of MPI_Datatype */ 735 userbuf = ((char*)userbuf) + dsize*position; 736 737 ierr = PetscMemcpy(userbuf,filebuf,count*dsize);CHKERRQ(ierr); 738 ierr = PetscByteSwap(userbuf,pdtype,count);CHKERRQ(ierr); 739 return ierr; 740 } 741 742 PetscMPIInt PetscDataRep_write_conv_fn(void *userbuf, MPI_Datatype datatype,PetscMPIInt count,void *filebuf, MPI_Offset position,void *extra_state) 743 { 744 PetscDataType pdtype; 745 PetscMPIInt ierr; 746 size_t dsize; 747 748 ierr = PetscMPIDataTypeToPetscDataType(datatype,&pdtype);CHKERRQ(ierr); 749 ierr = PetscDataTypeGetSize(pdtype,&dsize);CHKERRQ(ierr); 750 751 /* offset is given in units of MPI_Datatype */ 752 userbuf = ((char*)userbuf) + dsize*position; 753 754 ierr = PetscMemcpy(filebuf,userbuf,count*dsize);CHKERRQ(ierr); 755 ierr = PetscByteSwap(filebuf,pdtype,count);CHKERRQ(ierr); 756 return ierr; 757 } 758 #endif 759 760 PetscErrorCode MPIU_File_write_all(MPI_File fd,void *data,PetscMPIInt cnt,MPI_Datatype dtype,MPI_Status *status) 761 { 762 PetscErrorCode ierr; 763 PetscDataType pdtype; 764 765 PetscFunctionBegin; 766 ierr = PetscMPIDataTypeToPetscDataType(dtype,&pdtype);CHKERRQ(ierr); 767 ierr = PetscByteSwap(data,pdtype,cnt);CHKERRQ(ierr); 768 ierr = MPI_File_write_all(fd,data,cnt,dtype,status);CHKERRQ(ierr); 769 ierr = PetscByteSwap(data,pdtype,cnt);CHKERRQ(ierr); 770 PetscFunctionReturn(0); 771 } 772 773 PetscErrorCode MPIU_File_read_all(MPI_File fd,void *data,PetscMPIInt cnt,MPI_Datatype dtype,MPI_Status *status) 774 { 775 PetscErrorCode ierr; 776 PetscDataType pdtype; 777 778 PetscFunctionBegin; 779 ierr = PetscMPIDataTypeToPetscDataType(dtype,&pdtype);CHKERRQ(ierr); 780 ierr = MPI_File_read_all(fd,data,cnt,dtype,status);CHKERRQ(ierr); 781 ierr = PetscByteSwap(data,pdtype,cnt);CHKERRQ(ierr); 782 PetscFunctionReturn(0); 783 } 784 #endif 785 #endif 786