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