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