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