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