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