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