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