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