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