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