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