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