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