1 2 /* 3 This file contains simple binary read/write routines. 4 */ 5 6 #include <petscsys.h> 7 #include <petscbt.h> 8 #include <errno.h> 9 #include <fcntl.h> 10 #if defined(PETSC_HAVE_UNISTD_H) 11 #include <unistd.h> 12 #endif 13 #if defined(PETSC_HAVE_IO_H) 14 #include <io.h> 15 #endif 16 #if !defined(PETSC_HAVE_O_BINARY) 17 #define O_BINARY 0 18 #endif 19 20 const char *const PetscFileModes[] = {"READ","WRITE","APPEND","UPDATE","APPEND_UPDATE","PetscFileMode","PETSC_FILE_",NULL}; 21 22 /* --------------------------------------------------------- */ 23 /* 24 PetscByteSwapEnum - Swap bytes in a PETSc Enum 25 26 */ 27 PetscErrorCode PetscByteSwapEnum(PetscEnum *buff,PetscInt n) 28 { 29 PetscInt i,j; 30 PetscEnum tmp = ENUM_DUMMY; 31 char *ptr1,*ptr2 = (char*)&tmp; 32 33 PetscFunctionBegin; 34 for (j=0; j<n; j++) { 35 ptr1 = (char*)(buff + j); 36 for (i=0; i<(PetscInt)sizeof(PetscEnum); i++) ptr2[i] = ptr1[sizeof(PetscEnum)-1-i]; 37 for (i=0; i<(PetscInt)sizeof(PetscEnum); i++) ptr1[i] = ptr2[i]; 38 } 39 PetscFunctionReturn(0); 40 } 41 42 /* 43 PetscByteSwapBool - Swap bytes in a PETSc Bool 44 45 */ 46 PetscErrorCode PetscByteSwapBool(PetscBool *buff,PetscInt n) 47 { 48 PetscInt i,j; 49 PetscBool tmp = PETSC_FALSE; 50 char *ptr1,*ptr2 = (char*)&tmp; 51 52 PetscFunctionBegin; 53 for (j=0; j<n; j++) { 54 ptr1 = (char*)(buff + j); 55 for (i=0; i<(PetscInt)sizeof(PetscBool); i++) ptr2[i] = ptr1[sizeof(PetscBool)-1-i]; 56 for (i=0; i<(PetscInt)sizeof(PetscBool); i++) ptr1[i] = ptr2[i]; 57 } 58 PetscFunctionReturn(0); 59 } 60 61 /* 62 PetscByteSwapInt - Swap bytes in a PETSc integer (which may be 32 or 64 bits) 63 64 */ 65 PetscErrorCode PetscByteSwapInt(PetscInt *buff,PetscInt n) 66 { 67 PetscInt i,j,tmp = 0; 68 char *ptr1,*ptr2 = (char*)&tmp; 69 70 PetscFunctionBegin; 71 for (j=0; j<n; j++) { 72 ptr1 = (char*)(buff + j); 73 for (i=0; i<(PetscInt)sizeof(PetscInt); i++) ptr2[i] = ptr1[sizeof(PetscInt)-1-i]; 74 for (i=0; i<(PetscInt)sizeof(PetscInt); i++) ptr1[i] = ptr2[i]; 75 } 76 PetscFunctionReturn(0); 77 } 78 79 /* 80 PetscByteSwapInt64 - Swap bytes in a PETSc integer (64 bits) 81 82 */ 83 PetscErrorCode PetscByteSwapInt64(PetscInt64 *buff,PetscInt n) 84 { 85 PetscInt i,j; 86 PetscInt64 tmp = 0; 87 char *ptr1,*ptr2 = (char*)&tmp; 88 89 PetscFunctionBegin; 90 for (j=0; j<n; j++) { 91 ptr1 = (char*)(buff + j); 92 for (i=0; i<(PetscInt)sizeof(PetscInt64); i++) ptr2[i] = ptr1[sizeof(PetscInt64)-1-i]; 93 for (i=0; i<(PetscInt)sizeof(PetscInt64); i++) ptr1[i] = ptr2[i]; 94 } 95 PetscFunctionReturn(0); 96 } 97 98 /* --------------------------------------------------------- */ 99 /* 100 PetscByteSwapShort - Swap bytes in a short 101 */ 102 PetscErrorCode PetscByteSwapShort(short *buff,PetscInt n) 103 { 104 PetscInt i,j; 105 short tmp; 106 char *ptr1,*ptr2 = (char*)&tmp; 107 108 PetscFunctionBegin; 109 for (j=0; j<n; j++) { 110 ptr1 = (char*)(buff + j); 111 for (i=0; i<(PetscInt) sizeof(short); i++) ptr2[i] = ptr1[sizeof(short)-1-i]; 112 for (i=0; i<(PetscInt) sizeof(short); i++) ptr1[i] = ptr2[i]; 113 } 114 PetscFunctionReturn(0); 115 } 116 /* 117 PetscByteSwapLong - Swap bytes in a long 118 */ 119 PetscErrorCode PetscByteSwapLong(long *buff,PetscInt n) 120 { 121 PetscInt i,j; 122 long tmp; 123 char *ptr1,*ptr2 = (char*)&tmp; 124 125 PetscFunctionBegin; 126 for (j=0; j<n; j++) { 127 ptr1 = (char*)(buff + j); 128 for (i=0; i<(PetscInt) sizeof(long); i++) ptr2[i] = ptr1[sizeof(long)-1-i]; 129 for (i=0; i<(PetscInt) sizeof(long); i++) ptr1[i] = ptr2[i]; 130 } 131 PetscFunctionReturn(0); 132 } 133 /* --------------------------------------------------------- */ 134 /* 135 PetscByteSwapReal - Swap bytes in a PetscReal 136 */ 137 PetscErrorCode PetscByteSwapReal(PetscReal *buff,PetscInt n) 138 { 139 PetscInt i,j; 140 PetscReal tmp,*buff1 = (PetscReal*)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(PetscReal); i++) ptr2[i] = ptr1[sizeof(PetscReal)-1-i]; 147 for (i=0; i<(PetscInt) sizeof(PetscReal); i++) ptr1[i] = ptr2[i]; 148 } 149 PetscFunctionReturn(0); 150 } 151 /* --------------------------------------------------------- */ 152 /* 153 PetscByteSwapScalar - Swap bytes in a PetscScalar 154 The complex case is dealt with with an array of PetscReal, twice as long. 155 */ 156 PetscErrorCode PetscByteSwapScalar(PetscScalar *buff,PetscInt n) 157 { 158 PetscInt i,j; 159 PetscReal tmp,*buff1 = (PetscReal*)buff; 160 char *ptr1,*ptr2 = (char*)&tmp; 161 162 PetscFunctionBegin; 163 #if defined(PETSC_USE_COMPLEX) 164 n *= 2; 165 #endif 166 for (j=0; j<n; j++) { 167 ptr1 = (char*)(buff1 + j); 168 for (i=0; i<(PetscInt) sizeof(PetscReal); i++) ptr2[i] = ptr1[sizeof(PetscReal)-1-i]; 169 for (i=0; i<(PetscInt) sizeof(PetscReal); i++) ptr1[i] = ptr2[i]; 170 } 171 PetscFunctionReturn(0); 172 } 173 /* --------------------------------------------------------- */ 174 /* 175 PetscByteSwapDouble - Swap bytes in a double 176 */ 177 PetscErrorCode PetscByteSwapDouble(double *buff,PetscInt n) 178 { 179 PetscInt i,j; 180 double tmp,*buff1 = (double*)buff; 181 char *ptr1,*ptr2 = (char*)&tmp; 182 183 PetscFunctionBegin; 184 for (j=0; j<n; j++) { 185 ptr1 = (char*)(buff1 + j); 186 for (i=0; i<(PetscInt) sizeof(double); i++) ptr2[i] = ptr1[sizeof(double)-1-i]; 187 for (i=0; i<(PetscInt) sizeof(double); i++) ptr1[i] = ptr2[i]; 188 } 189 PetscFunctionReturn(0); 190 } 191 192 /* 193 PetscByteSwapFloat - Swap bytes in a float 194 */ 195 PetscErrorCode PetscByteSwapFloat(float *buff,PetscInt n) 196 { 197 PetscInt i,j; 198 float tmp,*buff1 = (float*)buff; 199 char *ptr1,*ptr2 = (char*)&tmp; 200 201 PetscFunctionBegin; 202 for (j=0; j<n; j++) { 203 ptr1 = (char*)(buff1 + j); 204 for (i=0; i<(PetscInt) sizeof(float); i++) ptr2[i] = ptr1[sizeof(float)-1-i]; 205 for (i=0; i<(PetscInt) sizeof(float); i++) ptr1[i] = ptr2[i]; 206 } 207 PetscFunctionReturn(0); 208 } 209 210 PetscErrorCode PetscByteSwap(void *data,PetscDataType pdtype,PetscInt count) 211 { 212 PetscErrorCode ierr; 213 214 PetscFunctionBegin; 215 if (pdtype == PETSC_INT) {ierr = PetscByteSwapInt((PetscInt*)data,count);CHKERRQ(ierr);} 216 else if (pdtype == PETSC_ENUM) {ierr = PetscByteSwapEnum((PetscEnum*)data,count);CHKERRQ(ierr);} 217 else if (pdtype == PETSC_BOOL) {ierr = PetscByteSwapBool((PetscBool*)data,count);CHKERRQ(ierr);} 218 else if (pdtype == PETSC_SCALAR) {ierr = PetscByteSwapScalar((PetscScalar*)data,count);CHKERRQ(ierr);} 219 else if (pdtype == PETSC_REAL) {ierr = PetscByteSwapReal((PetscReal*)data,count);CHKERRQ(ierr);} 220 else if (pdtype == PETSC_COMPLEX){ierr = PetscByteSwapReal((PetscReal*)data,2*count);CHKERRQ(ierr);} 221 else if (pdtype == PETSC_INT64) {ierr = PetscByteSwapInt64((PetscInt64*)data,count);CHKERRQ(ierr);} 222 else if (pdtype == PETSC_DOUBLE) {ierr = PetscByteSwapDouble((double*)data,count);CHKERRQ(ierr);} 223 else if (pdtype == PETSC_FLOAT) {ierr = PetscByteSwapFloat((float*)data,count);CHKERRQ(ierr);} 224 else if (pdtype == PETSC_SHORT) {ierr = PetscByteSwapShort((short*)data,count);CHKERRQ(ierr);} 225 else if (pdtype == PETSC_LONG) {ierr = PetscByteSwapLong((long*)data,count);CHKERRQ(ierr);} 226 PetscFunctionReturn(0); 227 } 228 229 /*@C 230 PetscBinaryRead - Reads from a binary file. 231 232 Not Collective 233 234 Input Parameters: 235 + fd - the file descriptor 236 . num - the maximum number of items to read 237 - type - the type of items to read (PETSC_INT, PETSC_REAL, PETSC_SCALAR, etc.) 238 239 Output Parameters: 240 + data - the buffer 241 - count - the number of items read, optional 242 243 Level: developer 244 245 Notes: 246 If count is not provided and the number of items read is less than 247 the maximum number of items to read, then this routine errors. 248 249 PetscBinaryRead() uses byte swapping to work on all machines; the files 250 are written to file ALWAYS using big-endian ordering. On little-endian machines the numbers 251 are converted to the little-endian format when they are read in from the file. 252 When PETSc is ./configure with --with-64-bit-indices the integers are written to the 253 file as 64 bit integers, this means they can only be read back in when the option --with-64-bit-indices 254 is used. 255 256 .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscViewerBinaryGetDescriptor(), PetscBinarySynchronizedWrite(), 257 PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek() 258 @*/ 259 PetscErrorCode PetscBinaryRead(int fd,void *data,PetscInt num,PetscInt *count,PetscDataType type) 260 { 261 size_t typesize, m = (size_t) num, n = 0, maxblock = 65536; 262 char *p = (char*)data; 263 #if defined(PETSC_USE_REAL___FLOAT128) 264 PetscBool readdouble = PETSC_FALSE; 265 double *pdouble; 266 #endif 267 void *ptmp = data; 268 char *fname = NULL; 269 PetscErrorCode ierr; 270 271 PetscFunctionBegin; 272 if (count) *count = 0; 273 if (num < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Trying to read a negative amount of data %" PetscInt_FMT,num); 274 if (!num) PetscFunctionReturn(0); 275 276 if (type == PETSC_FUNCTION) { 277 m = 64; 278 type = PETSC_CHAR; 279 fname = (char*)malloc(m*sizeof(char)); 280 p = (char*)fname; 281 ptmp = (void*)fname; 282 if (!fname) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Cannot allocate space for function name"); 283 } 284 if (type == PETSC_BIT_LOGICAL) m = PetscBTLength(m); 285 286 ierr = PetscDataTypeGetSize(type,&typesize);CHKERRQ(ierr); 287 288 #if defined(PETSC_USE_REAL___FLOAT128) 289 ierr = PetscOptionsGetBool(NULL,NULL,"-binary_read_double",&readdouble,NULL);CHKERRQ(ierr); 290 /* If using __float128 precision we still read in doubles from file */ 291 if ((type == PETSC_REAL || type == PETSC_COMPLEX) && readdouble) { 292 PetscInt cnt = num * ((type == PETSC_REAL) ? 1 : 2); 293 ierr = PetscMalloc1(cnt,&pdouble);CHKERRQ(ierr); 294 p = (char*)pdouble; 295 typesize /= 2; 296 } 297 #endif 298 299 m *= typesize; 300 301 while (m) { 302 size_t len = (m < maxblock) ? m : maxblock; 303 int ret = (int)read(fd,p,len); 304 if (ret < 0 && errno == EINTR) continue; 305 if (!ret && len > 0) break; /* Proxy for EOF */ 306 if (ret < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_READ,"Error reading from file, errno %d",errno); 307 m -= ret; 308 p += ret; 309 n += ret; 310 } 311 if (m && !count) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_READ,"Read past end of file"); 312 313 num = (PetscInt)(n/typesize); /* Should we require `n % typesize == 0` ? */ 314 if (count) *count = num; /* TODO: This is most likely wrong for PETSC_BIT_LOGICAL */ 315 316 #if defined(PETSC_USE_REAL___FLOAT128) 317 if ((type == PETSC_REAL || type == PETSC_COMPLEX) && readdouble) { 318 PetscInt i, cnt = num * ((type == PETSC_REAL) ? 1 : 2); 319 PetscReal *preal = (PetscReal*)data; 320 if (!PetscBinaryBigEndian()) {ierr = PetscByteSwapDouble(pdouble,cnt);CHKERRQ(ierr);} 321 for (i=0; i<cnt; i++) preal[i] = pdouble[i]; 322 ierr = PetscFree(pdouble);CHKERRQ(ierr); 323 PetscFunctionReturn(0); 324 } 325 #endif 326 327 if (!PetscBinaryBigEndian()) {ierr = PetscByteSwap(ptmp,type,num);CHKERRQ(ierr);} 328 329 if (type == PETSC_FUNCTION) { 330 #if defined(PETSC_SERIALIZE_FUNCTIONS) 331 ierr = PetscDLSym(NULL,fname,(void**)data);CHKERRQ(ierr); 332 #else 333 *(void**)data = NULL; 334 #endif 335 free(fname); 336 } 337 PetscFunctionReturn(0); 338 } 339 340 /*@C 341 PetscBinaryWrite - Writes to a binary file. 342 343 Not Collective 344 345 Input Parameters: 346 + fd - the file 347 . p - the buffer 348 . n - the number of items to write 349 - type - the type of items to read (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR) 350 351 Level: advanced 352 353 Notes: 354 PetscBinaryWrite() uses byte swapping to work on all machines; the files 355 are written using big-endian ordering to the file. On little-endian machines the numbers 356 are converted to the big-endian format when they are written to disk. 357 When PETSc is ./configure with --with-64-bit-indices the integers are written to the 358 file as 64 bit integers, this means they can only be read back in when the option --with-64-bit-indices 359 is used. 360 361 If running with __float128 precision the output is in __float128 unless one uses the -binary_write_double option 362 363 The Buffer p should be read-write buffer, and not static data. 364 This way, byte-swapping is done in-place, and then the buffer is 365 written to the file. 366 367 This routine restores the original contents of the buffer, after 368 it is written to the file. This is done by byte-swapping in-place 369 the second time. 370 371 Because byte-swapping may be done on the values in data it cannot be declared const 372 373 .seealso: PetscBinaryRead(), PetscBinaryOpen(), PetscBinaryClose(), PetscViewerBinaryGetDescriptor(), PetscBinarySynchronizedWrite(), 374 PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek() 375 @*/ 376 PetscErrorCode PetscBinaryWrite(int fd,const void *p,PetscInt n,PetscDataType type) 377 { 378 const char *pp = (char*)p; 379 int err,wsize; 380 size_t m = (size_t)n,maxblock=65536; 381 PetscErrorCode ierr; 382 const void *ptmp = p; 383 char *fname = NULL; 384 #if defined(PETSC_USE_REAL___FLOAT128) 385 PetscBool writedouble = PETSC_FALSE; 386 double *ppp; 387 PetscReal *pv; 388 PetscInt i; 389 #endif 390 PetscDataType wtype = type; 391 392 PetscFunctionBegin; 393 if (n < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Trying to write a negative amount of data %" PetscInt_FMT,n); 394 if (!n) PetscFunctionReturn(0); 395 396 if (type == PETSC_FUNCTION) { 397 #if defined(PETSC_SERIALIZE_FUNCTIONS) 398 const char *fnametmp; 399 #endif 400 m = 64; 401 fname = (char*)malloc(m*sizeof(char)); 402 if (!fname) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Cannot allocate space for function name"); 403 #if defined(PETSC_SERIALIZE_FUNCTIONS) 404 if (n > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Can only binary view a single function at a time"); 405 ierr = PetscFPTFind(*(void**)p,&fnametmp);CHKERRQ(ierr); 406 ierr = PetscStrncpy(fname,fnametmp,m);CHKERRQ(ierr); 407 #else 408 ierr = PetscStrncpy(fname,"",m);CHKERRQ(ierr); 409 #endif 410 wtype = PETSC_CHAR; 411 pp = (char*)fname; 412 ptmp = (void*)fname; 413 } 414 415 #if defined(PETSC_USE_REAL___FLOAT128) 416 ierr = PetscOptionsGetBool(NULL,NULL,"-binary_write_double",&writedouble,NULL);CHKERRQ(ierr); 417 /* If using __float128 precision we still write in doubles to file */ 418 if ((type == PETSC_SCALAR || type == PETSC_REAL || type == PETSC_COMPLEX) && writedouble) { 419 wtype = PETSC_DOUBLE; 420 ierr = PetscMalloc1(n,&ppp);CHKERRQ(ierr); 421 pv = (PetscReal*)pp; 422 for (i=0; i<n; i++) { 423 ppp[i] = (double) pv[i]; 424 } 425 pp = (char*)ppp; 426 ptmp = (char*)ppp; 427 } 428 #endif 429 430 if (wtype == PETSC_INT) m *= sizeof(PetscInt); 431 else if (wtype == PETSC_SCALAR) m *= sizeof(PetscScalar); 432 #if defined(PETSC_HAVE_COMPLEX) 433 else if (wtype == PETSC_COMPLEX) m *= sizeof(PetscComplex); 434 #endif 435 else if (wtype == PETSC_REAL) m *= sizeof(PetscReal); 436 else if (wtype == PETSC_DOUBLE) m *= sizeof(double); 437 else if (wtype == PETSC_FLOAT) m *= sizeof(float); 438 else if (wtype == PETSC_SHORT) m *= sizeof(short); 439 else if (wtype == PETSC_LONG) m *= sizeof(long); 440 else if (wtype == PETSC_CHAR) m *= sizeof(char); 441 else if (wtype == PETSC_ENUM) m *= sizeof(PetscEnum); 442 else if (wtype == PETSC_BOOL) m *= sizeof(PetscBool); 443 else if (wtype == PETSC_INT64) m *= sizeof(PetscInt64); 444 else if (wtype == PETSC_BIT_LOGICAL) m = PetscBTLength(m)*sizeof(char); 445 else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown type"); 446 447 if (!PetscBinaryBigEndian()) {ierr = PetscByteSwap((void*)ptmp,wtype,n);CHKERRQ(ierr);} 448 449 while (m) { 450 wsize = (m < maxblock) ? m : maxblock; 451 err = write(fd,pp,wsize); 452 if (err < 0 && errno == EINTR) continue; 453 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); 454 m -= wsize; 455 pp += wsize; 456 } 457 458 if (!PetscBinaryBigEndian()) {ierr = PetscByteSwap((void*)ptmp,wtype,n);CHKERRQ(ierr);} 459 460 if (type == PETSC_FUNCTION) { 461 free(fname); 462 } 463 #if defined(PETSC_USE_REAL___FLOAT128) 464 if ((type == PETSC_SCALAR || type == PETSC_REAL || type == PETSC_COMPLEX) && writedouble) { 465 ierr = PetscFree(ppp);CHKERRQ(ierr); 466 } 467 #endif 468 PetscFunctionReturn(0); 469 } 470 471 /*@C 472 PetscBinaryOpen - Opens a PETSc binary file. 473 474 Not Collective 475 476 Input Parameters: 477 + name - filename 478 - mode - open mode of binary file, one of FILE_MODE_READ, FILE_MODE_WRITE, FILE_MODE_APPEND 479 480 Output Parameter: 481 . fd - the file 482 483 Level: advanced 484 485 Notes: 486 Files access with PetscBinaryRead() and PetscBinaryWrite() are ALWAYS written in 487 big-endian format. This means the file can be accessed using PetscBinaryOpen() and 488 PetscBinaryRead() and PetscBinaryWrite() on any machine. 489 490 .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscFileMode, PetscViewerFileSetMode(), PetscViewerBinaryGetDescriptor(), 491 PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek() 492 493 @*/ 494 PetscErrorCode PetscBinaryOpen(const char name[],PetscFileMode mode,int *fd) 495 { 496 PetscFunctionBegin; 497 switch (mode) { 498 case FILE_MODE_READ: *fd = open(name,O_BINARY|O_RDONLY,0); break; 499 case FILE_MODE_WRITE: *fd = open(name,O_BINARY|O_WRONLY|O_CREAT|O_TRUNC,0666); break; 500 case FILE_MODE_APPEND: *fd = open(name,O_BINARY|O_WRONLY|O_APPEND,0); break; 501 default: SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unsupported file mode %s",PetscFileModes[mode]); 502 } 503 if (*fd == -1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file %s for %s",name,PetscFileModes[mode]); 504 PetscFunctionReturn(0); 505 } 506 507 /*@ 508 PetscBinaryClose - Closes a PETSc binary file. 509 510 Not Collective 511 512 Output Parameter: 513 . fd - the file 514 515 Level: advanced 516 517 .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(), 518 PetscBinarySynchronizedSeek() 519 @*/ 520 PetscErrorCode PetscBinaryClose(int fd) 521 { 522 PetscFunctionBegin; 523 if (close(fd)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"close() failed on file descriptor"); 524 PetscFunctionReturn(0); 525 } 526 527 /*@C 528 PetscBinarySeek - Moves the file pointer on a PETSc binary file. 529 530 Not Collective 531 532 Input Parameters: 533 + fd - the file 534 . off - number of bytes to move. Use PETSC_BINARY_INT_SIZE, PETSC_BINARY_SCALAR_SIZE, 535 etc. in your calculation rather than sizeof() to compute byte lengths. 536 - whence - if PETSC_BINARY_SEEK_SET then off is an absolute location in the file 537 if PETSC_BINARY_SEEK_CUR then off is an offset from the current location 538 if PETSC_BINARY_SEEK_END then off is an offset from the end of file 539 540 Output Parameter: 541 . offset - new offset in file 542 543 Level: developer 544 545 Notes: 546 Integers are stored on the file as 32 long, regardless of whether 547 they are stored in the machine as 32 or 64, this means the same 548 binary file may be read on any machine. Hence you CANNOT use sizeof() 549 to determine the offset or location. 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 /*@C 574 PetscBinarySynchronizedRead - Reads from a binary file. 575 576 Collective 577 578 Input Parameters: 579 + comm - the MPI communicator 580 . fd - the file descriptor 581 . num - the maximum number of items to read 582 - type - the type of items to read (PETSC_INT, PETSC_REAL, PETSC_SCALAR, etc.) 583 584 Output Parameters: 585 + data - the buffer 586 - count - the number of items read, optional 587 588 Level: developer 589 590 Notes: 591 Does a PetscBinaryRead() followed by an MPI_Bcast() 592 593 If count is not provided and the number of items read is less than 594 the maximum number of items to read, then this routine errors. 595 596 PetscBinarySynchronizedRead() uses byte swapping to work on all machines. 597 Integers are stored on the file as 32 long, regardless of whether 598 they are stored in the machine as 32 or 64, this means the same 599 binary file may be read on any machine. 600 601 .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscBinaryRead(), PetscBinarySynchronizedWrite(), 602 PetscBinarySynchronizedSeek() 603 @*/ 604 PetscErrorCode PetscBinarySynchronizedRead(MPI_Comm comm,int fd,void *data,PetscInt num,PetscInt *count,PetscDataType type) 605 { 606 PetscErrorCode ierr; 607 PetscMPIInt rank,size; 608 MPI_Datatype mtype; 609 PetscInt ibuf[2] = {0, 0}; 610 char *fname = NULL; 611 void *fptr = NULL; 612 613 PetscFunctionBegin; 614 if (type == PETSC_FUNCTION) { 615 num = 64; 616 type = PETSC_CHAR; 617 fname = (char*)malloc(num*sizeof(char)); 618 fptr = data; 619 data = (void*)fname; 620 if (!fname) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Cannot allocate space for function name"); 621 } 622 623 ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr); 624 ierr = MPI_Comm_size(comm,&size);CHKERRMPI(ierr); 625 if (rank == 0) { 626 ibuf[0] = PetscBinaryRead(fd,data,num,count?&ibuf[1]:NULL,type); 627 } 628 ierr = MPI_Bcast(ibuf,2,MPIU_INT,0,comm);CHKERRMPI(ierr); 629 ierr = (PetscErrorCode)ibuf[0];CHKERRQ(ierr); 630 631 /* skip MPI call on potentially huge amounts of data when running with one process; this allows the amount of data to basically unlimited in that case */ 632 if (size > 1) { 633 ierr = PetscDataTypeToMPIDataType(type,&mtype);CHKERRQ(ierr); 634 ierr = MPI_Bcast(data,count?ibuf[1]:num,mtype,0,comm);CHKERRMPI(ierr); 635 } 636 if (count) *count = ibuf[1]; 637 638 if (type == PETSC_FUNCTION) { 639 #if defined(PETSC_SERIALIZE_FUNCTIONS) 640 ierr = PetscDLLibrarySym(PETSC_COMM_SELF,&PetscDLLibrariesLoaded,NULL,fname,(void**)fptr);CHKERRQ(ierr); 641 #else 642 *(void**)fptr = NULL; 643 #endif 644 free(fname); 645 } 646 PetscFunctionReturn(0); 647 } 648 649 /*@C 650 PetscBinarySynchronizedWrite - writes to a binary file. 651 652 Collective 653 654 Input Parameters: 655 + comm - the MPI communicator 656 . fd - the file 657 . n - the number of items to write 658 . p - the buffer 659 - type - the type of items to write (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR) 660 661 Level: developer 662 663 Notes: 664 Process 0 does a PetscBinaryWrite() 665 666 PetscBinarySynchronizedWrite() uses byte swapping to work on all machines. 667 Integers are stored on the file as 32 long, regardless of whether 668 they are stored in the machine as 32 or 64, this means the same 669 binary file may be read on any machine. 670 671 Notes: 672 because byte-swapping may be done on the values in data it cannot be declared const 673 674 WARNING: This is NOT like PetscSynchronizedFPrintf()! This routine ignores calls on all but process 0, 675 while PetscSynchronizedFPrintf() has all processes print their strings in order. 676 677 .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscBinaryRead(), PetscBinarySynchronizedRead(), 678 PetscBinarySynchronizedSeek() 679 @*/ 680 PetscErrorCode PetscBinarySynchronizedWrite(MPI_Comm comm,int fd,const void *p,PetscInt n,PetscDataType type) 681 { 682 PetscErrorCode ierr; 683 PetscMPIInt rank; 684 685 PetscFunctionBegin; 686 ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr); 687 if (rank == 0) { 688 ierr = PetscBinaryWrite(fd,p,n,type);CHKERRQ(ierr); 689 } 690 PetscFunctionReturn(0); 691 } 692 693 /*@C 694 PetscBinarySynchronizedSeek - Moves the file pointer on a PETSc binary file. 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 .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(), 716 PetscBinarySynchronizedSeek() 717 @*/ 718 PetscErrorCode PetscBinarySynchronizedSeek(MPI_Comm comm,int fd,off_t off,PetscBinarySeekType whence,off_t *offset) 719 { 720 PetscErrorCode ierr; 721 PetscMPIInt rank; 722 723 PetscFunctionBegin; 724 ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr); 725 if (rank == 0) { 726 ierr = PetscBinarySeek(fd,off,whence,offset);CHKERRQ(ierr); 727 } 728 PetscFunctionReturn(0); 729 } 730 731 #if defined(PETSC_HAVE_MPIIO) 732 733 #if defined(PETSC_USE_PETSC_MPI_EXTERNAL32) 734 /* 735 MPICH does not provide the external32 representation for MPI_File_set_view() so we need to provide the functions. 736 These are set into MPI in PetscInitialize() via MPI_Register_datarep() 737 738 Note I use PetscMPIInt for the MPI error codes since that is what MPI uses (instead of the standard PetscErrorCode) 739 740 The next three routines are not used because MPICH does not support their use 741 742 */ 743 PETSC_EXTERN PetscMPIInt PetscDataRep_extent_fn(MPI_Datatype datatype,MPI_Aint *file_extent,void *extra_state) 744 { 745 MPI_Aint ub; 746 PetscMPIInt ierr; 747 748 ierr = MPI_Type_get_extent(datatype,&ub,file_extent); 749 return ierr; 750 } 751 752 PETSC_EXTERN PetscMPIInt PetscDataRep_read_conv_fn(void *userbuf, MPI_Datatype datatype,PetscMPIInt count,void *filebuf, MPI_Offset position,void *extra_state) 753 { 754 PetscDataType pdtype; 755 PetscMPIInt ierr; 756 size_t dsize; 757 758 ierr = PetscMPIDataTypeToPetscDataType(datatype,&pdtype);CHKERRQ(ierr); 759 ierr = PetscDataTypeGetSize(pdtype,&dsize);CHKERRQ(ierr); 760 761 /* offset is given in units of MPI_Datatype */ 762 userbuf = ((char*)userbuf) + dsize*position; 763 764 ierr = PetscMemcpy(userbuf,filebuf,count*dsize);CHKERRQ(ierr); 765 if (!PetscBinaryBigEndian()) {ierr = PetscByteSwap(userbuf,pdtype,count);CHKERRQ(ierr);} 766 return ierr; 767 } 768 769 PetscMPIInt PetscDataRep_write_conv_fn(void *userbuf, MPI_Datatype datatype,PetscMPIInt count,void *filebuf, MPI_Offset position,void *extra_state) 770 { 771 PetscDataType pdtype; 772 PetscMPIInt ierr; 773 size_t dsize; 774 775 ierr = PetscMPIDataTypeToPetscDataType(datatype,&pdtype);CHKERRQ(ierr); 776 ierr = PetscDataTypeGetSize(pdtype,&dsize);CHKERRQ(ierr); 777 778 /* offset is given in units of MPI_Datatype */ 779 userbuf = ((char*)userbuf) + dsize*position; 780 781 ierr = PetscMemcpy(filebuf,userbuf,count*dsize);CHKERRQ(ierr); 782 if (!PetscBinaryBigEndian()) {ierr = PetscByteSwap(filebuf,pdtype,count);CHKERRQ(ierr);} 783 return ierr; 784 } 785 #endif 786 787 PetscErrorCode MPIU_File_write_all(MPI_File fd,void *data,PetscMPIInt cnt,MPI_Datatype dtype,MPI_Status *status) 788 { 789 PetscDataType pdtype; 790 PetscErrorCode ierr; 791 792 PetscFunctionBegin; 793 ierr = PetscMPIDataTypeToPetscDataType(dtype,&pdtype);CHKERRQ(ierr); 794 if (!PetscBinaryBigEndian()) {ierr = PetscByteSwap(data,pdtype,cnt);CHKERRQ(ierr);} 795 ierr = MPI_File_write_all(fd,data,cnt,dtype,status);CHKERRMPI(ierr); 796 if (!PetscBinaryBigEndian()) {ierr = PetscByteSwap(data,pdtype,cnt);CHKERRQ(ierr);} 797 PetscFunctionReturn(0); 798 } 799 800 PetscErrorCode MPIU_File_read_all(MPI_File fd,void *data,PetscMPIInt cnt,MPI_Datatype dtype,MPI_Status *status) 801 { 802 PetscDataType pdtype; 803 PetscErrorCode ierr; 804 805 PetscFunctionBegin; 806 ierr = PetscMPIDataTypeToPetscDataType(dtype,&pdtype);CHKERRQ(ierr); 807 ierr = MPI_File_read_all(fd,data,cnt,dtype,status);CHKERRMPI(ierr); 808 if (!PetscBinaryBigEndian()) {ierr = PetscByteSwap(data,pdtype,cnt);CHKERRQ(ierr);} 809 PetscFunctionReturn(0); 810 } 811 812 PetscErrorCode MPIU_File_write_at(MPI_File fd,MPI_Offset off,void *data,PetscMPIInt cnt,MPI_Datatype dtype,MPI_Status *status) 813 { 814 PetscDataType pdtype; 815 PetscErrorCode ierr; 816 817 PetscFunctionBegin; 818 ierr = PetscMPIDataTypeToPetscDataType(dtype,&pdtype);CHKERRQ(ierr); 819 if (!PetscBinaryBigEndian()) {ierr = PetscByteSwap(data,pdtype,cnt);CHKERRQ(ierr);} 820 ierr = MPI_File_write_at(fd,off,data,cnt,dtype,status);CHKERRMPI(ierr); 821 if (!PetscBinaryBigEndian()) {ierr = PetscByteSwap(data,pdtype,cnt);CHKERRQ(ierr);} 822 PetscFunctionReturn(0); 823 } 824 825 PetscErrorCode MPIU_File_read_at(MPI_File fd,MPI_Offset off,void *data,PetscMPIInt cnt,MPI_Datatype dtype,MPI_Status *status) 826 { 827 PetscDataType pdtype; 828 PetscErrorCode ierr; 829 830 PetscFunctionBegin; 831 ierr = PetscMPIDataTypeToPetscDataType(dtype,&pdtype);CHKERRQ(ierr); 832 ierr = MPI_File_read_at(fd,off,data,cnt,dtype,status);CHKERRMPI(ierr); 833 if (!PetscBinaryBigEndian()) {ierr = PetscByteSwap(data,pdtype,cnt);CHKERRQ(ierr);} 834 PetscFunctionReturn(0); 835 } 836 837 PetscErrorCode MPIU_File_write_at_all(MPI_File fd,MPI_Offset off,void *data,PetscMPIInt cnt,MPI_Datatype dtype,MPI_Status *status) 838 { 839 PetscDataType pdtype; 840 PetscErrorCode ierr; 841 842 PetscFunctionBegin; 843 ierr = PetscMPIDataTypeToPetscDataType(dtype,&pdtype);CHKERRQ(ierr); 844 if (!PetscBinaryBigEndian()) {ierr = PetscByteSwap(data,pdtype,cnt);CHKERRQ(ierr);} 845 ierr = MPI_File_write_at_all(fd,off,data,cnt,dtype,status);CHKERRMPI(ierr); 846 if (!PetscBinaryBigEndian()) {ierr = PetscByteSwap(data,pdtype,cnt);CHKERRQ(ierr);} 847 PetscFunctionReturn(0); 848 } 849 850 PetscErrorCode MPIU_File_read_at_all(MPI_File fd,MPI_Offset off,void *data,PetscMPIInt cnt,MPI_Datatype dtype,MPI_Status *status) 851 { 852 PetscDataType pdtype; 853 PetscErrorCode ierr; 854 855 PetscFunctionBegin; 856 ierr = PetscMPIDataTypeToPetscDataType(dtype,&pdtype);CHKERRQ(ierr); 857 ierr = MPI_File_read_at_all(fd,off,data,cnt,dtype,status);CHKERRMPI(ierr); 858 if (!PetscBinaryBigEndian()) {ierr = PetscByteSwap(data,pdtype,cnt);CHKERRQ(ierr);} 859 PetscFunctionReturn(0); 860 } 861 862 #endif 863