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