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