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