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 331 PetscFunctionReturn(0); 332 } 333 /* --------------------------------------------------------- */ 334 #undef __FUNCT__ 335 #define __FUNCT__ "PetscBinaryWrite" 336 /*@ 337 PetscBinaryWrite - Writes to a binary file. 338 339 Not Collective 340 341 Input Parameters: 342 + fd - the file 343 . p - the buffer 344 . n - the number of items to write 345 . type - the type of items to read (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR) 346 - istemp - PETSC_FALSE if buffer data should be preserved, PETSC_TRUE otherwise. 347 348 Level: advanced 349 350 Notes: 351 PetscBinaryWrite() uses byte swapping to work on all machines; the files 352 are written using big-endian ordering to the file. On small-endian machines the numbers 353 are converted to the big-endian format when they are written to disk. 354 When PETSc is ./configure with --with-64bit-indices the integers are written to the 355 file as 64 bit integers, this means they can only be read back in when the option --with-64bit-indices 356 is used. 357 358 The Buffer p should be read-write buffer, and not static data. 359 This way, byte-swapping is done in-place, and then the buffer is 360 written to the file. 361 362 This routine restores the original contents of the buffer, after 363 it is written to the file. This is done by byte-swapping in-place 364 the second time. If the flag istemp is set to PETSC_TRUE, the second 365 byte-swapping operation is not done, thus saving some computation, 366 but the buffer is left corrupted. 367 368 Because byte-swapping may be done on the values in data it cannot be declared const 369 370 Concepts: files^writing binary 371 Concepts: binary files^writing 372 373 .seealso: PetscBinaryRead(), PetscBinaryOpen(), PetscBinaryClose(), PetscViewerBinaryGetDescriptor(), PetscBinarySynchronizedWrite(), 374 PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek() 375 @*/ 376 PetscErrorCode PetscBinaryWrite(int fd,void *p,PetscInt n,PetscDataType type,PetscBool istemp) 377 { 378 char *pp = (char*)p; 379 int err,wsize; 380 size_t m = (size_t)n,maxblock=65536; 381 PetscErrorCode ierr; 382 #if !defined(PETSC_WORDS_BIGENDIAN) 383 void *ptmp = p; 384 #endif 385 char fname[64]; 386 387 PetscFunctionBegin; 388 if (n < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Trying to write a negative amount of data %D",n); 389 if (!n) PetscFunctionReturn(0); 390 391 if (type == PETSC_FUNCTION) { 392 #if defined(PETSC_SERIALIZE_FUNCTIONS) 393 const char *fnametmp; 394 395 if (n > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Can only binary view a single function at a time"); 396 ierr = PetscFPTFind(p,&fnametmp);CHKERRQ(ierr); 397 ierr = PetscStrncpy(fname,fnametmp,64);CHKERRQ(ierr); 398 #else 399 ierr = PetscStrncpy(fname,"",64);CHKERRQ(ierr); 400 #endif 401 m = 64; 402 type = PETSC_CHAR; 403 pp = (char*)fname; 404 #if !defined(PETSC_WORDS_BIGENDIAN) 405 ptmp = (void*)fname; 406 #endif 407 } 408 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"); 419 420 #if !defined(PETSC_WORDS_BIGENDIAN) 421 ierr = PetscByteSwap(ptmp,type,n);CHKERRQ(ierr); 422 #endif 423 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) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_WRITE,"Error writing to file."); 429 m -= wsize; 430 pp += wsize; 431 } 432 433 #if !defined(PETSC_WORDS_BIGENDIAN) 434 if (!istemp) { 435 ierr = PetscByteSwap(ptmp,type,n);CHKERRQ(ierr); 436 } 437 #endif 438 PetscFunctionReturn(0); 439 } 440 441 #undef __FUNCT__ 442 #define __FUNCT__ "PetscBinaryOpen" 443 /*@C 444 PetscBinaryOpen - Opens a PETSc binary file. 445 446 Not Collective 447 448 Input Parameters: 449 + name - filename 450 - type - type of binary file, one of FILE_MODE_READ, FILE_MODE_APPEND, FILE_MODE_WRITE 451 452 Output Parameter: 453 . fd - the file 454 455 Level: advanced 456 457 Concepts: files^opening binary 458 Concepts: binary files^opening 459 460 Notes: Files access with PetscBinaryRead() and PetscBinaryWrite() are ALWAYS written in 461 big-endian format. This means the file can be accessed using PetscBinaryOpen() and 462 PetscBinaryRead() and PetscBinaryWrite() on any machine. 463 464 .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscFileMode, PetscViewerFileSetMode(), PetscViewerBinaryGetDescriptor(), 465 PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek() 466 467 @*/ 468 PetscErrorCode PetscBinaryOpen(const char name[],PetscFileMode mode,int *fd) 469 { 470 PetscFunctionBegin; 471 #if defined(PETSC_HAVE_O_BINARY) 472 if (mode == FILE_MODE_WRITE) { 473 if ((*fd = open(name,O_WRONLY|O_CREAT|O_TRUNC|O_BINARY,0666)) == -1) { 474 SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot create file for writing: %s",name); 475 } 476 } else if (mode == FILE_MODE_READ) { 477 if ((*fd = open(name,O_RDONLY|O_BINARY,0)) == -1) { 478 SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file for reading: %s",name); 479 } 480 } else if (mode == FILE_MODE_APPEND) { 481 if ((*fd = open(name,O_WRONLY|O_BINARY,0)) == -1) { 482 SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file for writing: %s",name); 483 } 484 #else 485 if (mode == FILE_MODE_WRITE) { 486 if ((*fd = creat(name,0666)) == -1) { 487 SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot create file for writing: %s",name); 488 } 489 } else if (mode == FILE_MODE_READ) { 490 if ((*fd = open(name,O_RDONLY,0)) == -1) { 491 SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file for reading: %s",name); 492 } 493 } 494 else if (mode == FILE_MODE_APPEND) { 495 if ((*fd = open(name,O_WRONLY,0)) == -1) { 496 SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file for writing: %s",name); 497 } 498 #endif 499 } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown file mode"); 500 PetscFunctionReturn(0); 501 } 502 503 #undef __FUNCT__ 504 #define __FUNCT__ "PetscBinaryClose" 505 /*@ 506 PetscBinaryClose - Closes a PETSc binary file. 507 508 Not Collective 509 510 Output Parameter: 511 . fd - the file 512 513 Level: advanced 514 515 .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(), 516 PetscBinarySynchronizedSeek() 517 @*/ 518 PetscErrorCode PetscBinaryClose(int fd) 519 { 520 PetscFunctionBegin; 521 close(fd); 522 PetscFunctionReturn(0); 523 } 524 525 526 #undef __FUNCT__ 527 #define __FUNCT__ "PetscBinarySeek" 528 /*@ 529 PetscBinarySeek - Moves the file pointer on a PETSc binary file. 530 531 Not Collective 532 533 Input Parameters: 534 + fd - the file 535 . off - number of bytes to move. Use PETSC_BINARY_INT_SIZE, PETSC_BINARY_SCALAR_SIZE, 536 etc. in your calculation rather than sizeof() to compute byte lengths. 537 - whence - if PETSC_BINARY_SEEK_SET then off is an absolute location in the file 538 if PETSC_BINARY_SEEK_CUR then off is an offset from the current location 539 if PETSC_BINARY_SEEK_END then off is an offset from the end of file 540 541 Output Parameter: 542 . offset - new offset in file 543 544 Level: developer 545 546 Notes: 547 Integers are stored on the file as 32 long, regardless of whether 548 they are stored in the machine as 32 or 64, this means the same 549 binary file may be read on any machine. Hence you CANNOT use sizeof() 550 to determine the offset or location. 551 552 Concepts: files^binary seeking 553 Concepts: binary files^seeking 554 555 .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(), 556 PetscBinarySynchronizedSeek() 557 @*/ 558 PetscErrorCode PetscBinarySeek(int fd,off_t off,PetscBinarySeekType whence,off_t *offset) 559 { 560 int iwhence = 0; 561 562 PetscFunctionBegin; 563 if (whence == PETSC_BINARY_SEEK_SET) { 564 iwhence = SEEK_SET; 565 } else if (whence == PETSC_BINARY_SEEK_CUR) { 566 iwhence = SEEK_CUR; 567 } else if (whence == PETSC_BINARY_SEEK_END) { 568 iwhence = SEEK_END; 569 } else { 570 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown seek location"); 571 } 572 #if defined(PETSC_HAVE_LSEEK) 573 *offset = lseek(fd,off,iwhence); 574 #elif defined(PETSC_HAVE__LSEEK) 575 *offset = _lseek(fd,(long)off,iwhence); 576 #else 577 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS,"System does not have a way of seeking on a file"); 578 #endif 579 PetscFunctionReturn(0); 580 } 581 582 #undef __FUNCT__ 583 #define __FUNCT__ "PetscBinarySynchronizedRead" 584 /*@C 585 PetscBinarySynchronizedRead - Reads from a binary file. 586 587 Collective on MPI_Comm 588 589 Input Parameters: 590 + comm - the MPI communicator 591 . fd - the file 592 . n - the number of items to read 593 - type - the type of items to read (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR) 594 595 Output Parameters: 596 . p - the buffer 597 598 Options Database Key: 599 . -binary_longints - indicates the file was generated on a Cray vector 600 machine (not the T3E/D) and the ints are stored as 64 bit 601 quantities, otherwise they are stored as 32 bit 602 603 Level: developer 604 605 Notes: 606 Does a PetscBinaryRead() followed by an MPI_Bcast() 607 608 PetscBinarySynchronizedRead() uses byte swapping to work on all machines. 609 Integers are stored on the file as 32 long, regardless of whether 610 they are stored in the machine as 32 or 64, this means the same 611 binary file may be read on any machine. 612 613 Concepts: files^synchronized reading of binary files 614 Concepts: binary files^reading, synchronized 615 616 .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscBinaryRead(), PetscBinarySynchronizedWrite(), 617 PetscBinarySynchronizedSeek() 618 @*/ 619 PetscErrorCode PetscBinarySynchronizedRead(MPI_Comm comm,int fd,void *p,PetscInt n,PetscDataType type) 620 { 621 PetscErrorCode ierr; 622 PetscMPIInt rank; 623 MPI_Datatype mtype; 624 char *fname; 625 PetscBool functionload = PETSC_FALSE; 626 void *ptmp; 627 628 PetscFunctionBegin; 629 if (type == PETSC_FUNCTION) { 630 functionload = PETSC_TRUE; 631 n = 64; 632 type = PETSC_CHAR; 633 ptmp = p; 634 /* warning memory leak */ 635 fname = (char*)malloc(64*sizeof(char)); 636 p = (void*)fname; 637 } 638 639 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 640 if (!rank) { 641 ierr = PetscBinaryRead(fd,p,n,type);CHKERRQ(ierr); 642 } 643 ierr = PetscDataTypeToMPIDataType(type,&mtype);CHKERRQ(ierr); 644 ierr = MPI_Bcast(p,n,mtype,0,comm);CHKERRQ(ierr); 645 646 if (functionload) { 647 #if defined(PETSC_SERIALIZE_FUNCTIONS) 648 ierr = PetscDLLibrarySym(PETSC_COMM_SELF,&PetscDLLibrariesLoaded,PETSC_NULL,fname,(void**)ptmp);CHKERRQ(ierr); 649 #else 650 *(void**)ptmp = PETSC_NULL; 651 #endif 652 } 653 PetscFunctionReturn(0); 654 } 655 656 #undef __FUNCT__ 657 #define __FUNCT__ "PetscBinarySynchronizedWrite" 658 /*@C 659 PetscBinarySynchronizedWrite - writes to a binary file. 660 661 Collective on MPI_Comm 662 663 Input Parameters: 664 + comm - the MPI communicator 665 . fd - the file 666 . n - the number of items to write 667 . p - the buffer 668 . istemp - the buffer may be changed 669 - type - the type of items to write (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR) 670 671 Level: developer 672 673 Notes: 674 Process 0 does a PetscBinaryWrite() 675 676 PetscBinarySynchronizedWrite() uses byte swapping to work on all machines. 677 Integers are stored on the file as 32 long, regardless of whether 678 they are stored in the machine as 32 or 64, this means the same 679 binary file may be read on any machine. 680 681 Notes: because byte-swapping may be done on the values in data it cannot be declared const 682 683 WARNING: This is NOT like PetscSynchronizedFPrintf()! This routine ignores calls on all but process 0, 684 while PetscSynchronizedFPrintf() has all processes print their strings in order. 685 686 Concepts: files^synchronized writing of binary files 687 Concepts: binary files^reading, synchronized 688 689 .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscBinaryRead(), PetscBinarySynchronizedRead(), 690 PetscBinarySynchronizedSeek() 691 @*/ 692 PetscErrorCode PetscBinarySynchronizedWrite(MPI_Comm comm,int fd,void *p,PetscInt n,PetscDataType type,PetscBool istemp) 693 { 694 PetscErrorCode ierr; 695 PetscMPIInt rank; 696 697 PetscFunctionBegin; 698 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 699 if (!rank) { 700 ierr = PetscBinaryWrite(fd,p,n,type,istemp);CHKERRQ(ierr); 701 } 702 PetscFunctionReturn(0); 703 } 704 705 #undef __FUNCT__ 706 #define __FUNCT__ "PetscBinarySynchronizedSeek" 707 /*@C 708 PetscBinarySynchronizedSeek - Moves the file pointer on a PETSc binary file. 709 710 711 Input Parameters: 712 + fd - the file 713 . whence - if PETSC_BINARY_SEEK_SET then size is an absolute location in the file 714 if PETSC_BINARY_SEEK_CUR then size is offset from current location 715 if PETSC_BINARY_SEEK_END then size is offset from end of file 716 - off - number of bytes to move. Use PETSC_BINARY_INT_SIZE, PETSC_BINARY_SCALAR_SIZE, 717 etc. in your calculation rather than sizeof() to compute byte lengths. 718 719 Output Parameter: 720 . offset - new offset in file 721 722 Level: developer 723 724 Notes: 725 Integers are stored on the file as 32 long, regardless of whether 726 they are stored in the machine as 32 or 64, this means the same 727 binary file may be read on any machine. Hence you CANNOT use sizeof() 728 to determine the offset or location. 729 730 Concepts: binary files^seeking 731 Concepts: files^seeking in binary 732 733 .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(), 734 PetscBinarySynchronizedSeek() 735 @*/ 736 PetscErrorCode PetscBinarySynchronizedSeek(MPI_Comm comm,int fd,off_t off,PetscBinarySeekType whence,off_t *offset) 737 { 738 PetscErrorCode ierr; 739 PetscMPIInt rank; 740 741 PetscFunctionBegin; 742 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 743 if (!rank) { 744 ierr = PetscBinarySeek(fd,off,whence,offset);CHKERRQ(ierr); 745 } 746 PetscFunctionReturn(0); 747 } 748 749 #if defined(PETSC_HAVE_MPIIO) 750 #if !defined(PETSC_WORDS_BIGENDIAN) 751 752 #if defined(PETSC_USE_PETSC_MPI_EXTERNAL32) 753 EXTERN_C_BEGIN 754 /* 755 MPICH does not provide the external32 representation for MPI_File_set_view() so we need to provide the functions. 756 These are set into MPI in PetscInitialize() via MPI_Register_datarep() 757 758 Note I use PetscMPIInt for the MPI error codes since that is what MPI uses (instead of the standard PetscErrorCode) 759 760 The next three routines are not used because MPICH does not support their use 761 762 */ 763 PetscMPIInt PetscDataRep_extent_fn(MPI_Datatype datatype,MPI_Aint *file_extent,void *extra_state) 764 { 765 MPI_Aint ub; 766 PetscMPIInt ierr; 767 768 ierr = MPI_Type_get_extent(datatype,&ub,file_extent); 769 return ierr; 770 } 771 772 PetscMPIInt PetscDataRep_read_conv_fn(void *userbuf, MPI_Datatype datatype,PetscMPIInt count,void *filebuf, MPI_Offset position,void *extra_state) 773 { 774 PetscDataType pdtype; 775 PetscMPIInt ierr; 776 size_t dsize; 777 778 ierr = PetscMPIDataTypeToPetscDataType(datatype,&pdtype);CHKERRQ(ierr); 779 ierr = PetscDataTypeGetSize(pdtype,&dsize);CHKERRQ(ierr); 780 781 /* offset is given in units of MPI_Datatype */ 782 userbuf = ((char *)userbuf) + dsize*position; 783 784 ierr = PetscMemcpy(userbuf,filebuf,count*dsize);CHKERRQ(ierr); 785 ierr = PetscByteSwap(userbuf,pdtype,count);CHKERRQ(ierr); 786 return ierr; 787 } 788 789 PetscMPIInt PetscDataRep_write_conv_fn(void *userbuf, MPI_Datatype datatype,PetscMPIInt count,void *filebuf, MPI_Offset position,void *extra_state) 790 { 791 PetscDataType pdtype; 792 PetscMPIInt ierr; 793 size_t dsize; 794 795 ierr = PetscMPIDataTypeToPetscDataType(datatype,&pdtype);CHKERRQ(ierr); 796 ierr = PetscDataTypeGetSize(pdtype,&dsize);CHKERRQ(ierr); 797 798 /* offset is given in units of MPI_Datatype */ 799 userbuf = ((char *)userbuf) + dsize*position; 800 801 ierr = PetscMemcpy(filebuf,userbuf,count*dsize);CHKERRQ(ierr); 802 ierr = PetscByteSwap(filebuf,pdtype,count);CHKERRQ(ierr); 803 return ierr; 804 } 805 EXTERN_C_END 806 #endif 807 808 #undef __FUNCT__ 809 #define __FUNCT__ "MPIU_File_write_all" 810 PetscErrorCode MPIU_File_write_all(MPI_File fd,void *data,PetscMPIInt cnt,MPI_Datatype dtype,MPI_Status *status) 811 { 812 PetscErrorCode ierr; 813 PetscDataType pdtype; 814 815 PetscFunctionBegin; 816 ierr = PetscMPIDataTypeToPetscDataType(dtype,&pdtype);CHKERRQ(ierr); 817 ierr = PetscByteSwap(data,pdtype,cnt);CHKERRQ(ierr); 818 ierr = MPI_File_write_all(fd,data,cnt,dtype,status);CHKERRQ(ierr); 819 ierr = PetscByteSwap(data,pdtype,cnt);CHKERRQ(ierr); 820 PetscFunctionReturn(0); 821 } 822 823 #undef __FUNCT__ 824 #define __FUNCT__ "MPIU_File_read_all" 825 PetscErrorCode MPIU_File_read_all(MPI_File fd,void *data,PetscMPIInt cnt,MPI_Datatype dtype,MPI_Status *status) 826 { 827 PetscErrorCode ierr; 828 PetscDataType pdtype; 829 830 PetscFunctionBegin; 831 ierr = PetscMPIDataTypeToPetscDataType(dtype,&pdtype);CHKERRQ(ierr); 832 ierr = MPI_File_read_all(fd,data,cnt,dtype,status);CHKERRQ(ierr); 833 ierr = PetscByteSwap(data,pdtype,cnt);CHKERRQ(ierr); 834 PetscFunctionReturn(0); 835 } 836 #endif 837 #endif 838