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