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