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