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