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