1 #include <petsc/private/viewerimpl.h> /*I "petscviewer.h" I*/ 2 3 typedef struct { 4 int fdes; /* file descriptor, ignored if using MPI IO */ 5 #if defined(PETSC_HAVE_MPIIO) 6 PetscBool usempiio; 7 MPI_File mfdes; /* ignored unless using MPI IO */ 8 MPI_File mfsub; /* subviewer support */ 9 MPI_Offset moff; 10 #endif 11 char *filename; /* file name */ 12 PetscFileMode filemode; /* read/write/append mode */ 13 FILE *fdes_info; /* optional file containing info on binary file*/ 14 PetscBool storecompressed; /* gzip the write binary file when closing it*/ 15 char *ogzfilename; /* gzip can be run after the filename has been updated */ 16 PetscBool skipinfo; /* Don't create info file for writing; don't use for reading */ 17 PetscBool skipoptions; /* don't use PETSc options database when loading */ 18 PetscInt flowcontrol; /* allow only <flowcontrol> messages outstanding at a time while doing IO */ 19 PetscBool skipheader; /* don't write header, only raw data */ 20 PetscBool matlabheaderwritten; /* if format is PETSC_VIEWER_BINARY_MATLAB has the MATLAB .info header been written yet */ 21 PetscBool setfromoptionscalled; 22 } PetscViewer_Binary; 23 24 #if defined(PETSC_HAVE_MPIIO) 25 static PetscErrorCode PetscViewerBinarySyncMPIIO(PetscViewer viewer) 26 { 27 PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data; 28 29 PetscFunctionBegin; 30 if (vbinary->filemode == FILE_MODE_READ) PetscFunctionReturn(0); 31 if (vbinary->mfsub != MPI_FILE_NULL) { 32 PetscCallMPI(MPI_File_sync(vbinary->mfsub)); 33 } 34 if (vbinary->mfdes != MPI_FILE_NULL) { 35 PetscCallMPI(MPI_Barrier(PetscObjectComm((PetscObject)viewer))); 36 PetscCallMPI(MPI_File_sync(vbinary->mfdes)); 37 } 38 PetscFunctionReturn(0); 39 } 40 #endif 41 42 static PetscErrorCode PetscViewerGetSubViewer_Binary(PetscViewer viewer,MPI_Comm comm,PetscViewer *outviewer) 43 { 44 PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data; 45 PetscMPIInt rank; 46 47 PetscFunctionBegin; 48 PetscCall(PetscViewerSetUp(viewer)); 49 50 /* Return subviewer in process zero */ 51 PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer),&rank)); 52 if (rank == 0) { 53 PetscMPIInt flg; 54 55 PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF,comm,&flg)); 56 PetscCheck(flg == MPI_IDENT || flg == MPI_CONGRUENT,PETSC_COMM_SELF,PETSC_ERR_SUP,"PetscViewerGetSubViewer() for PETSCVIEWERBINARY requires a singleton MPI_Comm"); 57 PetscCall(PetscViewerCreate(comm,outviewer)); 58 PetscCall(PetscViewerSetType(*outviewer,PETSCVIEWERBINARY)); 59 PetscCall(PetscMemcpy((*outviewer)->data,vbinary,sizeof(PetscViewer_Binary))); 60 (*outviewer)->setupcalled = PETSC_TRUE; 61 } else { 62 *outviewer = NULL; 63 } 64 65 #if defined(PETSC_HAVE_MPIIO) 66 if (vbinary->usempiio && *outviewer) { 67 PetscViewer_Binary *obinary = (PetscViewer_Binary*)(*outviewer)->data; 68 /* Parent viewer opens a new MPI file handle on PETSC_COMM_SELF and keeps track of it for future reuse */ 69 if (vbinary->mfsub == MPI_FILE_NULL) { 70 int amode; 71 switch (vbinary->filemode) { 72 case FILE_MODE_READ: amode = MPI_MODE_RDONLY; break; 73 case FILE_MODE_WRITE: amode = MPI_MODE_WRONLY; break; 74 case FILE_MODE_APPEND: amode = MPI_MODE_WRONLY; break; 75 default: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unsupported file mode %s",PetscFileModes[vbinary->filemode]); 76 } 77 PetscCallMPI(MPI_File_open(PETSC_COMM_SELF,vbinary->filename,amode,MPI_INFO_NULL,&vbinary->mfsub)); 78 } 79 /* Subviewer gets the MPI file handle on PETSC_COMM_SELF */ 80 obinary->mfdes = vbinary->mfsub; 81 obinary->mfsub = MPI_FILE_NULL; 82 obinary->moff = vbinary->moff; 83 } 84 #endif 85 86 #if defined(PETSC_HAVE_MPIIO) 87 PetscCall(PetscViewerBinarySyncMPIIO(viewer)); 88 #endif 89 PetscFunctionReturn(0); 90 } 91 92 static PetscErrorCode PetscViewerRestoreSubViewer_Binary(PetscViewer viewer,MPI_Comm comm,PetscViewer *outviewer) 93 { 94 PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data; 95 PetscMPIInt rank; 96 #if defined(PETSC_HAVE_MPIIO) 97 MPI_Offset moff = 0; 98 #endif 99 100 PetscFunctionBegin; 101 PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer),&rank)); 102 PetscCheck(!rank || !*outviewer,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Subviewer not obtained from viewer"); 103 104 #if defined(PETSC_HAVE_MPIIO) 105 if (vbinary->usempiio && *outviewer) { 106 PetscViewer_Binary *obinary = (PetscViewer_Binary*)(*outviewer)->data; 107 PetscCheck(obinary->mfdes == vbinary->mfsub,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Subviewer not obtained from viewer"); 108 if (obinary->mfsub != MPI_FILE_NULL) PetscCallMPI(MPI_File_close(&obinary->mfsub)); 109 moff = obinary->moff; 110 } 111 #endif 112 113 if (*outviewer) { 114 PetscViewer_Binary *obinary = (PetscViewer_Binary*)(*outviewer)->data; 115 PetscCheck(obinary->fdes == vbinary->fdes,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Subviewer not obtained from viewer"); 116 PetscCall(PetscFree((*outviewer)->data)); 117 PetscCall(PetscHeaderDestroy(outviewer)); 118 } 119 120 #if defined(PETSC_HAVE_MPIIO) 121 if (vbinary->usempiio) { 122 PetscInt64 ioff = (PetscInt64)moff; /* We could use MPI_OFFSET datatype (requires MPI 2.2) */ 123 PetscCallMPI(MPI_Bcast(&ioff,1,MPIU_INT64,0,PetscObjectComm((PetscObject)viewer))); 124 vbinary->moff = (MPI_Offset)ioff; 125 } 126 #endif 127 128 #if defined(PETSC_HAVE_MPIIO) 129 PetscCall(PetscViewerBinarySyncMPIIO(viewer)); 130 #endif 131 PetscFunctionReturn(0); 132 } 133 134 #if defined(PETSC_HAVE_MPIIO) 135 /*@C 136 PetscViewerBinaryGetMPIIOOffset - Gets the current global offset that should be passed to `MPI_File_set_view()` or `MPI_File_{write|read}_at[_all]()` 137 138 Not Collective 139 140 Input Parameter: 141 . viewer - PetscViewer context, obtained from `PetscViewerBinaryOpen()` 142 143 Output Parameter: 144 . off - the current global offset 145 146 Level: advanced 147 148 Fortran Note: 149 This routine is not supported in Fortran. 150 151 Use `PetscViewerBinaryAddMPIIOOffset()` to increase this value after you have written a view. 152 153 .seealso: `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetInfoPointer()`, `PetscViewerBinaryGetUseMPIIO()`, `PetscViewerBinarySetUseMPIIO()`, `PetscViewerBinaryAddMPIIOOffset()` 154 @*/ 155 PetscErrorCode PetscViewerBinaryGetMPIIOOffset(PetscViewer viewer,MPI_Offset *off) 156 { 157 PetscViewer_Binary *vbinary; 158 159 PetscFunctionBegin; 160 PetscValidHeaderSpecificType(viewer,PETSC_VIEWER_CLASSID,1,PETSCVIEWERBINARY); 161 PetscValidPointer(off,2); 162 vbinary = (PetscViewer_Binary*)viewer->data; 163 *off = vbinary->moff; 164 PetscFunctionReturn(0); 165 } 166 167 /*@C 168 PetscViewerBinaryAddMPIIOOffset - Adds to the current global offset 169 170 Logically Collective 171 172 Input Parameters: 173 + viewer - PetscViewer context, obtained from PetscViewerBinaryOpen() 174 - off - the addition to the global offset 175 176 Level: advanced 177 178 Fortran Note: 179 This routine is not supported in Fortran. 180 181 Use `PetscViewerBinaryGetMPIIOOffset()` to get the value that you should pass to `MPI_File_set_view()` or `MPI_File_{write|read}_at[_all]()` 182 183 .seealso: `PetscViewerBinaryOpen(),PetscViewerBinaryGetInfoPointer()`, `PetscViewerBinaryGetUseMPIIO()`, `PetscViewerBinarySetUseMPIIO()`, `PetscViewerBinaryGetMPIIOOffset()` 184 @*/ 185 PetscErrorCode PetscViewerBinaryAddMPIIOOffset(PetscViewer viewer,MPI_Offset off) 186 { 187 PetscViewer_Binary *vbinary; 188 189 PetscFunctionBegin; 190 PetscValidHeaderSpecificType(viewer,PETSC_VIEWER_CLASSID,1,PETSCVIEWERBINARY); 191 PetscValidLogicalCollectiveInt(viewer,(PetscInt)off,2); 192 vbinary = (PetscViewer_Binary*)viewer->data; 193 vbinary->moff += off; 194 PetscFunctionReturn(0); 195 } 196 197 /*@C 198 PetscViewerBinaryGetMPIIODescriptor - Extracts the MPI IO file descriptor from a PetscViewer. 199 200 Not Collective 201 202 Input Parameter: 203 . viewer - PetscViewer context, obtained from PetscViewerBinaryOpen() 204 205 Output Parameter: 206 . fdes - file descriptor 207 208 Level: advanced 209 210 Fortran Note: 211 This routine is not supported in Fortran. 212 213 .seealso: `PetscViewerBinaryOpen(),PetscViewerBinaryGetInfoPointer()`, `PetscViewerBinaryGetUseMPIIO()`, `PetscViewerBinarySetUseMPIIO()`, `PetscViewerBinaryGetMPIIOOffset()` 214 @*/ 215 PetscErrorCode PetscViewerBinaryGetMPIIODescriptor(PetscViewer viewer,MPI_File *fdes) 216 { 217 PetscViewer_Binary *vbinary; 218 219 PetscFunctionBegin; 220 PetscValidHeaderSpecificType(viewer,PETSC_VIEWER_CLASSID,1,PETSCVIEWERBINARY); 221 PetscValidPointer(fdes,2); 222 PetscCall(PetscViewerSetUp(viewer)); 223 vbinary = (PetscViewer_Binary*)viewer->data; 224 *fdes = vbinary->mfdes; 225 PetscFunctionReturn(0); 226 } 227 #endif 228 229 /*@ 230 PetscViewerBinarySetUseMPIIO - Sets a binary viewer to use MPI-IO for reading/writing. Must be called 231 before PetscViewerFileSetName() 232 233 Logically Collective on PetscViewer 234 235 Input Parameters: 236 + viewer - the PetscViewer; must be a binary 237 - use - PETSC_TRUE means MPI-IO will be used 238 239 Options Database: 240 -viewer_binary_mpiio : Flag for using MPI-IO 241 242 Level: advanced 243 244 .seealso: `PetscViewerFileSetMode()`, `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerBinaryOpen()`, 245 `PetscViewerBinaryGetUseMPIIO()` 246 247 @*/ 248 PetscErrorCode PetscViewerBinarySetUseMPIIO(PetscViewer viewer,PetscBool use) 249 { 250 PetscFunctionBegin; 251 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 252 PetscValidLogicalCollectiveBool(viewer,use,2); 253 PetscTryMethod(viewer,"PetscViewerBinarySetUseMPIIO_C",(PetscViewer,PetscBool),(viewer,use)); 254 PetscFunctionReturn(0); 255 } 256 257 #if defined(PETSC_HAVE_MPIIO) 258 static PetscErrorCode PetscViewerBinarySetUseMPIIO_Binary(PetscViewer viewer,PetscBool use) 259 { 260 PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data; 261 PetscFunctionBegin; 262 PetscCheck(!viewer->setupcalled || vbinary->usempiio == use,PetscObjectComm((PetscObject)viewer),PETSC_ERR_ORDER,"Cannot change MPIIO to %s after setup",PetscBools[use]); 263 vbinary->usempiio = use; 264 PetscFunctionReturn(0); 265 } 266 #endif 267 268 /*@ 269 PetscViewerBinaryGetUseMPIIO - Returns PETSC_TRUE if the binary viewer uses MPI-IO. 270 271 Not Collective 272 273 Input Parameter: 274 . viewer - PetscViewer context, obtained from PetscViewerBinaryOpen() 275 276 Output Parameter: 277 . use - PETSC_TRUE if MPI-IO is being used 278 279 Options Database: 280 -viewer_binary_mpiio : Flag for using MPI-IO 281 282 Level: advanced 283 284 Note: 285 If MPI-IO is not available, this function will always return PETSC_FALSE 286 287 Fortran Note: 288 This routine is not supported in Fortran. 289 290 .seealso: `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetInfoPointer()`, `PetscViewerBinarySetUseMPIIO()`, `PetscViewerBinaryGetMPIIOOffset()` 291 @*/ 292 PetscErrorCode PetscViewerBinaryGetUseMPIIO(PetscViewer viewer,PetscBool *use) 293 { 294 PetscFunctionBegin; 295 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 296 PetscValidBoolPointer(use,2); 297 *use = PETSC_FALSE; 298 PetscTryMethod(viewer,"PetscViewerBinaryGetUseMPIIO_C",(PetscViewer,PetscBool*),(viewer,use)); 299 PetscFunctionReturn(0); 300 } 301 302 #if defined(PETSC_HAVE_MPIIO) 303 static PetscErrorCode PetscViewerBinaryGetUseMPIIO_Binary(PetscViewer viewer,PetscBool *use) 304 { 305 PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data; 306 307 PetscFunctionBegin; 308 *use = vbinary->usempiio; 309 PetscFunctionReturn(0); 310 } 311 #endif 312 313 /*@ 314 PetscViewerBinarySetFlowControl - Sets how many messages are allowed to outstanding at the same time during parallel IO reads/writes 315 316 Not Collective 317 318 Input Parameters: 319 + viewer - PetscViewer context, obtained from PetscViewerBinaryOpen() 320 - fc - the number of messages, defaults to 256 if this function was not called 321 322 Level: advanced 323 324 .seealso: `PetscViewerBinaryOpen(),PetscViewerBinaryGetInfoPointer()`, `PetscViewerBinaryGetFlowControl()` 325 326 @*/ 327 PetscErrorCode PetscViewerBinarySetFlowControl(PetscViewer viewer,PetscInt fc) 328 { 329 PetscFunctionBegin; 330 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 331 PetscValidLogicalCollectiveInt(viewer,fc,2); 332 PetscTryMethod(viewer,"PetscViewerBinarySetFlowControl_C",(PetscViewer,PetscInt),(viewer,fc)); 333 PetscFunctionReturn(0); 334 } 335 336 static PetscErrorCode PetscViewerBinarySetFlowControl_Binary(PetscViewer viewer,PetscInt fc) 337 { 338 PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data; 339 340 PetscFunctionBegin; 341 PetscCheck(fc > 1,PetscObjectComm((PetscObject)viewer),PETSC_ERR_ARG_OUTOFRANGE,"Flow control count must be greater than 1, %" PetscInt_FMT " was set",fc); 342 vbinary->flowcontrol = fc; 343 PetscFunctionReturn(0); 344 } 345 346 /*@ 347 PetscViewerBinaryGetFlowControl - Returns how many messages are allowed to outstanding at the same time during parallel IO reads/writes 348 349 Not Collective 350 351 Input Parameter: 352 . viewer - PetscViewer context, obtained from PetscViewerBinaryOpen() 353 354 Output Parameter: 355 . fc - the number of messages 356 357 Level: advanced 358 359 .seealso: `PetscViewerBinaryOpen(),PetscViewerBinaryGetInfoPointer()`, `PetscViewerBinarySetFlowControl()` 360 361 @*/ 362 PetscErrorCode PetscViewerBinaryGetFlowControl(PetscViewer viewer,PetscInt *fc) 363 { 364 PetscFunctionBegin; 365 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 366 PetscValidIntPointer(fc,2); 367 PetscUseMethod(viewer,"PetscViewerBinaryGetFlowControl_C",(PetscViewer,PetscInt*),(viewer,fc)); 368 PetscFunctionReturn(0); 369 } 370 371 static PetscErrorCode PetscViewerBinaryGetFlowControl_Binary(PetscViewer viewer,PetscInt *fc) 372 { 373 PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data; 374 375 PetscFunctionBegin; 376 *fc = vbinary->flowcontrol; 377 PetscFunctionReturn(0); 378 } 379 380 /*@C 381 PetscViewerBinaryGetDescriptor - Extracts the file descriptor from a PetscViewer. 382 383 Collective On PetscViewer 384 385 Input Parameter: 386 . viewer - PetscViewer context, obtained from PetscViewerBinaryOpen() 387 388 Output Parameter: 389 . fdes - file descriptor 390 391 Level: advanced 392 393 Notes: 394 For writable binary PetscViewers, the descriptor will only be valid for the 395 first processor in the communicator that shares the PetscViewer. For readable 396 files it will only be valid on nodes that have the file. If node 0 does not 397 have the file it generates an error even if another node does have the file. 398 399 Fortran Note: 400 This routine is not supported in Fortran. 401 402 Developer Notes: 403 This must be called on all processes because Dave May changed 404 the source code that this may be trigger a PetscViewerSetUp() call if it was not previously triggered. 405 406 .seealso: `PetscViewerBinaryOpen(),PetscViewerBinaryGetInfoPointer()` 407 @*/ 408 PetscErrorCode PetscViewerBinaryGetDescriptor(PetscViewer viewer,int *fdes) 409 { 410 PetscViewer_Binary *vbinary; 411 412 PetscFunctionBegin; 413 PetscValidHeaderSpecificType(viewer,PETSC_VIEWER_CLASSID,1,PETSCVIEWERBINARY); 414 PetscValidPointer(fdes,2); 415 PetscCall(PetscViewerSetUp(viewer)); 416 vbinary = (PetscViewer_Binary*)viewer->data; 417 *fdes = vbinary->fdes; 418 PetscFunctionReturn(0); 419 } 420 421 /*@ 422 PetscViewerBinarySkipInfo - Binary file will not have .info file created with it 423 424 Not Collective 425 426 Input Parameter: 427 . viewer - PetscViewer context, obtained from PetscViewerCreate() 428 429 Options Database Key: 430 . -viewer_binary_skip_info - true indicates do not generate .info file 431 432 Level: advanced 433 434 Notes: 435 This must be called after PetscViewerSetType(). If you use PetscViewerBinaryOpen() then 436 you can only skip the info file with the -viewer_binary_skip_info flag. To use the function you must open the 437 viewer with PetscViewerCreate(), PetscViewerSetType(), PetscViewerBinarySkipInfo(). 438 439 The .info contains meta information about the data in the binary file, for example the block size if it was 440 set for a vector or matrix. 441 442 .seealso: `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetDescriptor()`, `PetscViewerBinarySetSkipOptions()`, 443 `PetscViewerBinaryGetSkipOptions()`, `PetscViewerBinaryGetSkipInfo()` 444 @*/ 445 PetscErrorCode PetscViewerBinarySkipInfo(PetscViewer viewer) 446 { 447 PetscFunctionBegin; 448 PetscCall(PetscViewerBinarySetSkipInfo(viewer,PETSC_TRUE)); 449 PetscFunctionReturn(0); 450 } 451 452 /*@ 453 PetscViewerBinarySetSkipInfo - Binary file will not have .info file created with it 454 455 Not Collective 456 457 Input Parameters: 458 + viewer - PetscViewer context, obtained from PetscViewerCreate() 459 - skip - PETSC_TRUE implies the .info file will not be generated 460 461 Options Database Key: 462 . -viewer_binary_skip_info - true indicates do not generate .info file 463 464 Level: advanced 465 466 .seealso: `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetDescriptor()`, `PetscViewerBinarySetSkipOptions()`, 467 `PetscViewerBinaryGetSkipOptions()`, `PetscViewerBinaryGetSkipInfo()` 468 @*/ 469 PetscErrorCode PetscViewerBinarySetSkipInfo(PetscViewer viewer,PetscBool skip) 470 { 471 PetscFunctionBegin; 472 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 473 PetscValidLogicalCollectiveBool(viewer,skip,2); 474 PetscTryMethod(viewer,"PetscViewerBinarySetSkipInfo_C",(PetscViewer,PetscBool),(viewer,skip)); 475 PetscFunctionReturn(0); 476 } 477 478 static PetscErrorCode PetscViewerBinarySetSkipInfo_Binary(PetscViewer viewer,PetscBool skip) 479 { 480 PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data; 481 482 PetscFunctionBegin; 483 vbinary->skipinfo = skip; 484 PetscFunctionReturn(0); 485 } 486 487 /*@ 488 PetscViewerBinaryGetSkipInfo - check if viewer wrote a .info file 489 490 Not Collective 491 492 Input Parameter: 493 . viewer - PetscViewer context, obtained from PetscViewerBinaryOpen() 494 495 Output Parameter: 496 . skip - PETSC_TRUE implies the .info file was not generated 497 498 Level: advanced 499 500 Notes: 501 This must be called after PetscViewerSetType() 502 503 .seealso: `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetDescriptor()`, `PetscViewerBinarySkipInfo()`, 504 `PetscViewerBinarySetSkipOptions()`, `PetscViewerBinarySetSkipInfo()` 505 @*/ 506 PetscErrorCode PetscViewerBinaryGetSkipInfo(PetscViewer viewer,PetscBool *skip) 507 { 508 PetscFunctionBegin; 509 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 510 PetscValidBoolPointer(skip,2); 511 PetscUseMethod(viewer,"PetscViewerBinaryGetSkipInfo_C",(PetscViewer,PetscBool*),(viewer,skip)); 512 PetscFunctionReturn(0); 513 } 514 515 static PetscErrorCode PetscViewerBinaryGetSkipInfo_Binary(PetscViewer viewer,PetscBool *skip) 516 { 517 PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data; 518 519 PetscFunctionBegin; 520 *skip = vbinary->skipinfo; 521 PetscFunctionReturn(0); 522 } 523 524 /*@ 525 PetscViewerBinarySetSkipOptions - do not use the PETSc options database when loading objects 526 527 Not Collective 528 529 Input Parameters: 530 + viewer - PetscViewer context, obtained from PetscViewerBinaryOpen() 531 - skip - PETSC_TRUE means do not use the options from the options database 532 533 Options Database Key: 534 . -viewer_binary_skip_options - true means do not use the options from the options database 535 536 Level: advanced 537 538 Notes: 539 This must be called after PetscViewerSetType() 540 541 .seealso: `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetDescriptor()`, `PetscViewerBinarySkipInfo()`, 542 `PetscViewerBinaryGetSkipOptions()` 543 @*/ 544 PetscErrorCode PetscViewerBinarySetSkipOptions(PetscViewer viewer,PetscBool skip) 545 { 546 PetscFunctionBegin; 547 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 548 PetscValidLogicalCollectiveBool(viewer,skip,2); 549 PetscTryMethod(viewer,"PetscViewerBinarySetSkipOptions_C",(PetscViewer,PetscBool),(viewer,skip)); 550 PetscFunctionReturn(0); 551 } 552 553 static PetscErrorCode PetscViewerBinarySetSkipOptions_Binary(PetscViewer viewer,PetscBool skip) 554 { 555 PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data; 556 557 PetscFunctionBegin; 558 vbinary->skipoptions = skip; 559 PetscFunctionReturn(0); 560 } 561 562 /*@ 563 PetscViewerBinaryGetSkipOptions - checks if viewer uses the PETSc options database when loading objects 564 565 Not Collective 566 567 Input Parameter: 568 . viewer - PetscViewer context, obtained from PetscViewerBinaryOpen() 569 570 Output Parameter: 571 . skip - PETSC_TRUE means do not use 572 573 Level: advanced 574 575 Notes: 576 This must be called after PetscViewerSetType() 577 578 .seealso: `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetDescriptor()`, `PetscViewerBinarySkipInfo()`, 579 `PetscViewerBinarySetSkipOptions()` 580 @*/ 581 PetscErrorCode PetscViewerBinaryGetSkipOptions(PetscViewer viewer,PetscBool *skip) 582 { 583 PetscFunctionBegin; 584 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 585 PetscValidBoolPointer(skip,2); 586 PetscUseMethod(viewer,"PetscViewerBinaryGetSkipOptions_C",(PetscViewer,PetscBool*),(viewer,skip)); 587 PetscFunctionReturn(0); 588 } 589 590 static PetscErrorCode PetscViewerBinaryGetSkipOptions_Binary(PetscViewer viewer,PetscBool *skip) 591 { 592 PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data; 593 594 PetscFunctionBegin; 595 *skip = vbinary->skipoptions; 596 PetscFunctionReturn(0); 597 } 598 599 /*@ 600 PetscViewerBinarySetSkipHeader - do not write a header with size information on output, just raw data 601 602 Not Collective 603 604 Input Parameters: 605 + viewer - PetscViewer context, obtained from PetscViewerBinaryOpen() 606 - skip - PETSC_TRUE means do not write header 607 608 Options Database Key: 609 . -viewer_binary_skip_header - PETSC_TRUE means do not write header 610 611 Level: advanced 612 613 Notes: 614 This must be called after PetscViewerSetType() 615 616 Is ignored on anything but a binary viewer 617 618 .seealso: `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetDescriptor()`, `PetscViewerBinarySkipInfo()`, 619 `PetscViewerBinaryGetSkipHeader()` 620 @*/ 621 PetscErrorCode PetscViewerBinarySetSkipHeader(PetscViewer viewer,PetscBool skip) 622 { 623 PetscFunctionBegin; 624 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 625 PetscValidLogicalCollectiveBool(viewer,skip,2); 626 PetscTryMethod(viewer,"PetscViewerBinarySetSkipHeader_C",(PetscViewer,PetscBool),(viewer,skip)); 627 PetscFunctionReturn(0); 628 } 629 630 static PetscErrorCode PetscViewerBinarySetSkipHeader_Binary(PetscViewer viewer,PetscBool skip) 631 { 632 PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data; 633 634 PetscFunctionBegin; 635 vbinary->skipheader = skip; 636 PetscFunctionReturn(0); 637 } 638 639 /*@ 640 PetscViewerBinaryGetSkipHeader - checks whether to write a header with size information on output, or just raw data 641 642 Not Collective 643 644 Input Parameter: 645 . viewer - PetscViewer context, obtained from PetscViewerBinaryOpen() 646 647 Output Parameter: 648 . skip - PETSC_TRUE means do not write header 649 650 Level: advanced 651 652 Notes: 653 This must be called after PetscViewerSetType() 654 655 Returns false for PETSCSOCKETVIEWER, you cannot skip the header for it. 656 657 .seealso: `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetDescriptor()`, `PetscViewerBinarySkipInfo()`, 658 `PetscViewerBinarySetSkipHeader()` 659 @*/ 660 PetscErrorCode PetscViewerBinaryGetSkipHeader(PetscViewer viewer,PetscBool *skip) 661 { 662 PetscFunctionBegin; 663 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 664 PetscValidBoolPointer(skip,2); 665 PetscUseMethod(viewer,"PetscViewerBinaryGetSkipHeader_C",(PetscViewer,PetscBool*),(viewer,skip)); 666 PetscFunctionReturn(0); 667 } 668 669 static PetscErrorCode PetscViewerBinaryGetSkipHeader_Binary(PetscViewer viewer,PetscBool *skip) 670 { 671 PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data; 672 673 PetscFunctionBegin; 674 *skip = vbinary->skipheader; 675 PetscFunctionReturn(0); 676 } 677 678 /*@C 679 PetscViewerBinaryGetInfoPointer - Extracts the file pointer for the ASCII 680 info file associated with a binary file. 681 682 Not Collective 683 684 Input Parameter: 685 . viewer - PetscViewer context, obtained from PetscViewerBinaryOpen() 686 687 Output Parameter: 688 . file - file pointer Always returns NULL if not a binary viewer 689 690 Level: advanced 691 692 Notes: 693 For writable binary PetscViewers, the descriptor will only be valid for the 694 first processor in the communicator that shares the PetscViewer. 695 696 Fortran Note: 697 This routine is not supported in Fortran. 698 699 .seealso: `PetscViewerBinaryOpen(),PetscViewerBinaryGetDescriptor()` 700 @*/ 701 PetscErrorCode PetscViewerBinaryGetInfoPointer(PetscViewer viewer,FILE **file) 702 { 703 PetscFunctionBegin; 704 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 705 PetscValidPointer(file,2); 706 *file = NULL; 707 PetscTryMethod(viewer,"PetscViewerBinaryGetInfoPointer_C",(PetscViewer,FILE **),(viewer,file)); 708 PetscFunctionReturn(0); 709 } 710 711 static PetscErrorCode PetscViewerBinaryGetInfoPointer_Binary(PetscViewer viewer,FILE **file) 712 { 713 PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data; 714 715 PetscFunctionBegin; 716 PetscCall(PetscViewerSetUp(viewer)); 717 *file = vbinary->fdes_info; 718 if (viewer->format == PETSC_VIEWER_BINARY_MATLAB && !vbinary->matlabheaderwritten) { 719 if (vbinary->fdes_info) { 720 FILE *info = vbinary->fdes_info; 721 PetscCall(PetscFPrintf(PETSC_COMM_SELF,info,"#--- begin code written by PetscViewerBinary for MATLAB format ---#\n")); 722 PetscCall(PetscFPrintf(PETSC_COMM_SELF,info,"#$$ Set.filename = '%s';\n",vbinary->filename)); 723 PetscCall(PetscFPrintf(PETSC_COMM_SELF,info,"#$$ fd = PetscOpenFile(Set.filename);\n")); 724 PetscCall(PetscFPrintf(PETSC_COMM_SELF,info,"#--- end code written by PetscViewerBinary for MATLAB format ---#\n\n")); 725 } 726 vbinary->matlabheaderwritten = PETSC_TRUE; 727 } 728 PetscFunctionReturn(0); 729 } 730 731 #if defined(PETSC_HAVE_MPIIO) 732 static PetscErrorCode PetscViewerFileClose_BinaryMPIIO(PetscViewer v) 733 { 734 PetscViewer_Binary *vbinary = (PetscViewer_Binary*)v->data; 735 736 PetscFunctionBegin; 737 if (vbinary->mfdes != MPI_FILE_NULL) { 738 PetscCallMPI(MPI_File_close(&vbinary->mfdes)); 739 } 740 if (vbinary->mfsub != MPI_FILE_NULL) { 741 PetscCallMPI(MPI_File_close(&vbinary->mfsub)); 742 } 743 vbinary->moff = 0; 744 PetscFunctionReturn(0); 745 } 746 #endif 747 748 static PetscErrorCode PetscViewerFileClose_BinarySTDIO(PetscViewer v) 749 { 750 PetscViewer_Binary *vbinary = (PetscViewer_Binary*)v->data; 751 752 PetscFunctionBegin; 753 if (vbinary->fdes != -1) { 754 PetscCall(PetscBinaryClose(vbinary->fdes)); 755 vbinary->fdes = -1; 756 if (vbinary->storecompressed) { 757 char cmd[8+PETSC_MAX_PATH_LEN],out[64+PETSC_MAX_PATH_LEN] = ""; 758 const char *gzfilename = vbinary->ogzfilename ? vbinary->ogzfilename : vbinary->filename; 759 /* compress the file */ 760 PetscCall(PetscStrncpy(cmd,"gzip -f ",sizeof(cmd))); 761 PetscCall(PetscStrlcat(cmd,gzfilename,sizeof(cmd))); 762 #if defined(PETSC_HAVE_POPEN) 763 { 764 FILE *fp; 765 PetscCall(PetscPOpen(PETSC_COMM_SELF,NULL,cmd,"r",&fp)); 766 PetscCheck(!fgets(out,(int)(sizeof(out)-1),fp),PETSC_COMM_SELF,PETSC_ERR_LIB,"Error from command %s\n%s",cmd,out); 767 PetscCall(PetscPClose(PETSC_COMM_SELF,fp)); 768 } 769 #endif 770 } 771 } 772 PetscCall(PetscFree(vbinary->ogzfilename)); 773 PetscFunctionReturn(0); 774 } 775 776 static PetscErrorCode PetscViewerFileClose_BinaryInfo(PetscViewer v) 777 { 778 PetscViewer_Binary *vbinary = (PetscViewer_Binary*)v->data; 779 780 PetscFunctionBegin; 781 if (v->format == PETSC_VIEWER_BINARY_MATLAB && vbinary->matlabheaderwritten) { 782 if (vbinary->fdes_info) { 783 FILE *info = vbinary->fdes_info; 784 PetscCall(PetscFPrintf(PETSC_COMM_SELF,info,"#--- begin code written by PetscViewerBinary for MATLAB format ---#\n")); 785 PetscCall(PetscFPrintf(PETSC_COMM_SELF,info,"#$$ close(fd);\n")); 786 PetscCall(PetscFPrintf(PETSC_COMM_SELF,info,"#--- end code written by PetscViewerBinary for MATLAB format ---#\n\n")); 787 } 788 } 789 if (vbinary->fdes_info) { 790 FILE *info = vbinary->fdes_info; 791 vbinary->fdes_info = NULL; 792 PetscCheck(!fclose(info),PETSC_COMM_SELF,PETSC_ERR_SYS,"fclose() failed on file"); 793 } 794 PetscFunctionReturn(0); 795 } 796 797 static PetscErrorCode PetscViewerFileClose_Binary(PetscViewer v) 798 { 799 PetscFunctionBegin; 800 #if defined(PETSC_HAVE_MPIIO) 801 PetscCall(PetscViewerFileClose_BinaryMPIIO(v)); 802 #endif 803 PetscCall(PetscViewerFileClose_BinarySTDIO(v)); 804 PetscCall(PetscViewerFileClose_BinaryInfo(v)); 805 PetscFunctionReturn(0); 806 } 807 808 static PetscErrorCode PetscViewerDestroy_Binary(PetscViewer v) 809 { 810 PetscViewer_Binary *vbinary = (PetscViewer_Binary*)v->data; 811 812 PetscFunctionBegin; 813 PetscCall(PetscViewerFileClose_Binary(v)); 814 PetscCall(PetscFree(vbinary->filename)); 815 PetscCall(PetscFree(vbinary)); 816 817 PetscCall(PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetFlowControl_C",NULL)); 818 PetscCall(PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetFlowControl_C",NULL)); 819 PetscCall(PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetSkipHeader_C",NULL)); 820 PetscCall(PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetSkipHeader_C",NULL)); 821 PetscCall(PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetSkipOptions_C",NULL)); 822 PetscCall(PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetSkipOptions_C",NULL)); 823 PetscCall(PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetSkipInfo_C",NULL)); 824 PetscCall(PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetSkipInfo_C",NULL)); 825 PetscCall(PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetInfoPointer_C",NULL)); 826 PetscCall(PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileGetName_C",NULL)); 827 PetscCall(PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileSetName_C",NULL)); 828 PetscCall(PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileGetMode_C",NULL)); 829 PetscCall(PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileSetMode_C",NULL)); 830 #if defined(PETSC_HAVE_MPIIO) 831 PetscCall(PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetUseMPIIO_C",NULL)); 832 PetscCall(PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetUseMPIIO_C",NULL)); 833 #endif 834 PetscFunctionReturn(0); 835 } 836 837 /*@C 838 PetscViewerBinaryOpen - Opens a file for binary input/output. 839 840 Collective 841 842 Input Parameters: 843 + comm - MPI communicator 844 . name - name of file 845 - mode - open mode of file 846 $ FILE_MODE_WRITE - create new file for binary output 847 $ FILE_MODE_READ - open existing file for binary input 848 $ FILE_MODE_APPEND - open existing file for binary output 849 850 Output Parameter: 851 . viewer - PetscViewer for binary input/output to use with the specified file 852 853 Options Database Keys: 854 + -viewer_binary_filename <name> - 855 . -viewer_binary_skip_info - 856 . -viewer_binary_skip_options - 857 . -viewer_binary_skip_header - 858 - -viewer_binary_mpiio - 859 860 Level: beginner 861 862 Note: 863 This PetscViewer should be destroyed with PetscViewerDestroy(). 864 865 For reading files, the filename may begin with ftp:// or http:// and/or 866 end with .gz; in this case file is brought over and uncompressed. 867 868 For creating files, if the file name ends with .gz it is automatically 869 compressed when closed. 870 871 .seealso: `PetscViewerASCIIOpen()`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`, 872 `VecView()`, `MatView()`, `VecLoad()`, `MatLoad()`, `PetscViewerBinaryGetDescriptor()`, 873 `PetscViewerBinaryGetInfoPointer()`, `PetscFileMode`, `PetscViewer`, `PetscViewerBinaryRead()`, `PetscViewerBinarySetUseMPIIO()`, 874 `PetscViewerBinaryGetUseMPIIO()`, `PetscViewerBinaryGetMPIIOOffset()` 875 @*/ 876 PetscErrorCode PetscViewerBinaryOpen(MPI_Comm comm,const char name[],PetscFileMode mode,PetscViewer *viewer) 877 { 878 PetscFunctionBegin; 879 PetscCall(PetscViewerCreate(comm,viewer)); 880 PetscCall(PetscViewerSetType(*viewer,PETSCVIEWERBINARY)); 881 PetscCall(PetscViewerFileSetMode(*viewer,mode)); 882 PetscCall(PetscViewerFileSetName(*viewer,name)); 883 PetscCall(PetscViewerSetFromOptions(*viewer)); 884 PetscFunctionReturn(0); 885 } 886 887 #if defined(PETSC_HAVE_MPIIO) 888 static PetscErrorCode PetscViewerBinaryWriteReadMPIIO(PetscViewer viewer,void *data,PetscInt num,PetscInt *count,PetscDataType dtype,PetscBool write) 889 { 890 MPI_Comm comm = PetscObjectComm((PetscObject)viewer); 891 PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data; 892 MPI_File mfdes = vbinary->mfdes; 893 MPI_Datatype mdtype; 894 PetscMPIInt rank,cnt; 895 MPI_Status status; 896 MPI_Aint ul,dsize; 897 898 PetscFunctionBegin; 899 PetscCallMPI(MPI_Comm_rank(comm,&rank)); 900 PetscCall(PetscMPIIntCast(num,&cnt)); 901 PetscCall(PetscDataTypeToMPIDataType(dtype,&mdtype)); 902 if (write) { 903 if (rank == 0) { 904 PetscCall(MPIU_File_write_at(mfdes,vbinary->moff,data,cnt,mdtype,&status)); 905 } 906 } else { 907 if (rank == 0) { 908 PetscCall(MPIU_File_read_at(mfdes,vbinary->moff,data,cnt,mdtype,&status)); 909 if (cnt > 0) PetscCallMPI(MPI_Get_count(&status,mdtype,&cnt)); 910 } 911 PetscCallMPI(MPI_Bcast(&cnt,1,MPI_INT,0,comm)); 912 PetscCallMPI(MPI_Bcast(data,cnt,mdtype,0,comm)); 913 } 914 PetscCallMPI(MPI_Type_get_extent(mdtype,&ul,&dsize)); 915 vbinary->moff += dsize*cnt; 916 if (count) *count = cnt; 917 PetscFunctionReturn(0); 918 } 919 #endif 920 921 /*@C 922 PetscViewerBinaryRead - Reads from a binary file, all processors get the same result 923 924 Collective 925 926 Input Parameters: 927 + viewer - the binary viewer 928 . data - location of the data to be written 929 . num - number of items of data to read 930 - dtype - type of data to read 931 932 Output Parameters: 933 . count - number of items of data actually read, or NULL. 934 935 Level: beginner 936 937 .seealso: `PetscViewerASCIIOpen()`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`, 938 `VecView()`, `MatView()`, `VecLoad()`, `MatLoad()`, `PetscViewerBinaryGetDescriptor()`, 939 `PetscViewerBinaryGetInfoPointer()`, `PetscFileMode`, `PetscViewer`, `PetscViewerBinaryRead()` 940 @*/ 941 PetscErrorCode PetscViewerBinaryRead(PetscViewer viewer,void *data,PetscInt num,PetscInt *count,PetscDataType dtype) 942 { 943 PetscViewer_Binary *vbinary; 944 945 PetscFunctionBegin; 946 PetscValidHeaderSpecificType(viewer,PETSC_VIEWER_CLASSID,1,PETSCVIEWERBINARY); 947 PetscValidLogicalCollectiveInt(viewer,num,3); 948 PetscCall(PetscViewerSetUp(viewer)); 949 vbinary = (PetscViewer_Binary*)viewer->data; 950 #if defined(PETSC_HAVE_MPIIO) 951 if (vbinary->usempiio) { 952 PetscCall(PetscViewerBinaryWriteReadMPIIO(viewer,data,num,count,dtype,PETSC_FALSE)); 953 } else { 954 #endif 955 PetscCall(PetscBinarySynchronizedRead(PetscObjectComm((PetscObject)viewer),vbinary->fdes,data,num,count,dtype)); 956 #if defined(PETSC_HAVE_MPIIO) 957 } 958 #endif 959 PetscFunctionReturn(0); 960 } 961 962 /*@C 963 PetscViewerBinaryWrite - writes to a binary file, only from the first process 964 965 Collective 966 967 Input Parameters: 968 + viewer - the binary viewer 969 . data - location of data 970 . count - number of items of data to write 971 - dtype - type of data to write 972 973 Level: beginner 974 975 .seealso: `PetscViewerASCIIOpen()`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`, 976 `VecView()`, `MatView()`, `VecLoad()`, `MatLoad()`, `PetscViewerBinaryGetDescriptor()`, `PetscDataType` 977 `PetscViewerBinaryGetInfoPointer()`, `PetscFileMode`, `PetscViewer`, `PetscViewerBinaryRead()` 978 @*/ 979 PetscErrorCode PetscViewerBinaryWrite(PetscViewer viewer,const void *data,PetscInt count,PetscDataType dtype) 980 { 981 PetscViewer_Binary *vbinary; 982 983 PetscFunctionBegin; 984 PetscValidHeaderSpecificType(viewer,PETSC_VIEWER_CLASSID,1,PETSCVIEWERBINARY); 985 PetscValidLogicalCollectiveInt(viewer,count,3); 986 PetscCall(PetscViewerSetUp(viewer)); 987 vbinary = (PetscViewer_Binary*)viewer->data; 988 #if defined(PETSC_HAVE_MPIIO) 989 if (vbinary->usempiio) { 990 PetscCall(PetscViewerBinaryWriteReadMPIIO(viewer,(void*)data,count,NULL,dtype,PETSC_TRUE)); 991 } else { 992 #endif 993 PetscCall(PetscBinarySynchronizedWrite(PetscObjectComm((PetscObject)viewer),vbinary->fdes,data,count,dtype)); 994 #if defined(PETSC_HAVE_MPIIO) 995 } 996 #endif 997 PetscFunctionReturn(0); 998 } 999 1000 static PetscErrorCode PetscViewerBinaryWriteReadAll(PetscViewer viewer,PetscBool write,void *data,PetscInt count,PetscInt start,PetscInt total,PetscDataType dtype) 1001 { 1002 MPI_Comm comm = PetscObjectComm((PetscObject)viewer); 1003 PetscMPIInt size,rank; 1004 MPI_Datatype mdtype; 1005 PETSC_UNUSED MPI_Aint lb; 1006 MPI_Aint dsize; 1007 PetscBool useMPIIO; 1008 1009 PetscFunctionBegin; 1010 PetscValidHeaderSpecificType(viewer,PETSC_VIEWER_CLASSID,1,PETSCVIEWERBINARY); 1011 PetscValidLogicalCollectiveBool(viewer,((start>=0)||(start==PETSC_DETERMINE)),5); 1012 PetscValidLogicalCollectiveBool(viewer,((total>=0)||(total==PETSC_DETERMINE)),6); 1013 PetscValidLogicalCollectiveInt(viewer,total,6); 1014 PetscCall(PetscViewerSetUp(viewer)); 1015 1016 PetscCall(PetscDataTypeToMPIDataType(dtype,&mdtype)); 1017 PetscCallMPI(MPI_Type_get_extent(mdtype,&lb,&dsize)); 1018 PetscCallMPI(MPI_Comm_rank(comm,&rank)); 1019 PetscCallMPI(MPI_Comm_size(comm,&size)); 1020 1021 PetscCall(PetscViewerBinaryGetUseMPIIO(viewer,&useMPIIO)); 1022 #if defined(PETSC_HAVE_MPIIO) 1023 if (useMPIIO) { 1024 MPI_File mfdes; 1025 MPI_Offset off; 1026 PetscMPIInt cnt; 1027 1028 if (start == PETSC_DETERMINE) { 1029 PetscCallMPI(MPI_Scan(&count,&start,1,MPIU_INT,MPI_SUM,comm)); 1030 start -= count; 1031 } 1032 if (total == PETSC_DETERMINE) { 1033 total = start + count; 1034 PetscCallMPI(MPI_Bcast(&total,1,MPIU_INT,size-1,comm)); 1035 } 1036 PetscCall(PetscMPIIntCast(count,&cnt)); 1037 PetscCall(PetscViewerBinaryGetMPIIODescriptor(viewer,&mfdes)); 1038 PetscCall(PetscViewerBinaryGetMPIIOOffset(viewer,&off)); 1039 off += (MPI_Offset)(start*dsize); 1040 if (write) { 1041 PetscCall(MPIU_File_write_at_all(mfdes,off,data,cnt,mdtype,MPI_STATUS_IGNORE)); 1042 } else { 1043 PetscCall(MPIU_File_read_at_all(mfdes,off,data,cnt,mdtype,MPI_STATUS_IGNORE)); 1044 } 1045 off = (MPI_Offset)(total*dsize); 1046 PetscCall(PetscViewerBinaryAddMPIIOOffset(viewer,off)); 1047 PetscFunctionReturn(0); 1048 } 1049 #endif 1050 { 1051 int fdes; 1052 char *workbuf = NULL; 1053 PetscInt tcount = rank == 0 ? 0 : count,maxcount=0,message_count,flowcontrolcount; 1054 PetscMPIInt tag,cnt,maxcnt,scnt=0,rcnt=0,j; 1055 MPI_Status status; 1056 1057 PetscCall(PetscCommGetNewTag(comm,&tag)); 1058 PetscCallMPI(MPI_Reduce(&tcount,&maxcount,1,MPIU_INT,MPI_MAX,0,comm)); 1059 PetscCall(PetscMPIIntCast(maxcount,&maxcnt)); 1060 PetscCall(PetscMPIIntCast(count,&cnt)); 1061 1062 PetscCall(PetscViewerBinaryGetDescriptor(viewer,&fdes)); 1063 PetscCall(PetscViewerFlowControlStart(viewer,&message_count,&flowcontrolcount)); 1064 if (rank == 0) { 1065 PetscCall(PetscMalloc(maxcnt*dsize,&workbuf)); 1066 if (write) { 1067 PetscCall(PetscBinaryWrite(fdes,data,cnt,dtype)); 1068 } else { 1069 PetscCall(PetscBinaryRead(fdes,data,cnt,NULL,dtype)); 1070 } 1071 for (j=1; j<size; j++) { 1072 PetscCall(PetscViewerFlowControlStepMain(viewer,j,&message_count,flowcontrolcount)); 1073 if (write) { 1074 PetscCallMPI(MPI_Recv(workbuf,maxcnt,mdtype,j,tag,comm,&status)); 1075 PetscCallMPI(MPI_Get_count(&status,mdtype,&rcnt)); 1076 PetscCall(PetscBinaryWrite(fdes,workbuf,rcnt,dtype)); 1077 } else { 1078 PetscCallMPI(MPI_Recv(&scnt,1,MPI_INT,j,tag,comm,MPI_STATUS_IGNORE)); 1079 PetscCall(PetscBinaryRead(fdes,workbuf,scnt,NULL,dtype)); 1080 PetscCallMPI(MPI_Send(workbuf,scnt,mdtype,j,tag,comm)); 1081 } 1082 } 1083 PetscCall(PetscFree(workbuf)); 1084 PetscCall(PetscViewerFlowControlEndMain(viewer,&message_count)); 1085 } else { 1086 PetscCall(PetscViewerFlowControlStepWorker(viewer,rank,&message_count)); 1087 if (write) { 1088 PetscCallMPI(MPI_Send(data,cnt,mdtype,0,tag,comm)); 1089 } else { 1090 PetscCallMPI(MPI_Send(&cnt,1,MPI_INT,0,tag,comm)); 1091 PetscCallMPI(MPI_Recv(data,cnt,mdtype,0,tag,comm,MPI_STATUS_IGNORE)); 1092 } 1093 PetscCall(PetscViewerFlowControlEndWorker(viewer,&message_count)); 1094 } 1095 } 1096 PetscFunctionReturn(0); 1097 } 1098 1099 /*@C 1100 PetscViewerBinaryReadAll - reads from a binary file from all processes 1101 1102 Collective 1103 1104 Input Parameters: 1105 + viewer - the binary viewer 1106 . data - location of data 1107 . count - local number of items of data to read 1108 . start - local start, can be PETSC_DETERMINE 1109 . total - global number of items of data to read, can be PETSC_DETERMINE 1110 - dtype - type of data to read 1111 1112 Level: advanced 1113 1114 .seealso: `PetscViewerBinaryOpen()`, `PetscViewerBinarySetUseMPIIO()`, `PetscViewerBinaryRead()`, `PetscViewerBinaryWriteAll()` 1115 @*/ 1116 PetscErrorCode PetscViewerBinaryReadAll(PetscViewer viewer,void *data,PetscInt count,PetscInt start,PetscInt total,PetscDataType dtype) 1117 { 1118 PetscFunctionBegin; 1119 PetscCall(PetscViewerBinaryWriteReadAll(viewer,PETSC_FALSE,data,count,start,total,dtype)); 1120 PetscFunctionReturn(0); 1121 } 1122 1123 /*@C 1124 PetscViewerBinaryWriteAll - writes to a binary file from all processes 1125 1126 Collective 1127 1128 Input Parameters: 1129 + viewer - the binary viewer 1130 . data - location of data 1131 . count - local number of items of data to write 1132 . start - local start, can be PETSC_DETERMINE 1133 . total - global number of items of data to write, can be PETSC_DETERMINE 1134 - dtype - type of data to write 1135 1136 Level: advanced 1137 1138 .seealso: `PetscViewerBinaryOpen()`, `PetscViewerBinarySetUseMPIIO()`, `PetscViewerBinaryWriteAll()`, `PetscViewerBinaryReadAll()` 1139 @*/ 1140 PetscErrorCode PetscViewerBinaryWriteAll(PetscViewer viewer,const void *data,PetscInt count,PetscInt start,PetscInt total,PetscDataType dtype) 1141 { 1142 PetscFunctionBegin; 1143 PetscCall(PetscViewerBinaryWriteReadAll(viewer,PETSC_TRUE,(void*)data,count,start,total,dtype)); 1144 PetscFunctionReturn(0); 1145 } 1146 1147 /*@C 1148 PetscViewerBinaryWriteStringArray - writes to a binary file, only from the first process an array of strings 1149 1150 Collective 1151 1152 Input Parameters: 1153 + viewer - the binary viewer 1154 - data - location of the array of strings 1155 1156 Level: intermediate 1157 1158 Notes: 1159 array of strings is null terminated 1160 1161 .seealso: `PetscViewerASCIIOpen()`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`, 1162 `VecView()`, `MatView()`, `VecLoad()`, `MatLoad()`, `PetscViewerBinaryGetDescriptor()`, 1163 `PetscViewerBinaryGetInfoPointer()`, `PetscFileMode`, `PetscViewer`, `PetscViewerBinaryRead()` 1164 @*/ 1165 PetscErrorCode PetscViewerBinaryWriteStringArray(PetscViewer viewer,const char * const *data) 1166 { 1167 PetscInt i,n = 0,*sizes; 1168 size_t len; 1169 1170 PetscFunctionBegin; 1171 PetscCall(PetscViewerSetUp(viewer)); 1172 /* count number of strings */ 1173 while (data[n++]); 1174 n--; 1175 PetscCall(PetscMalloc1(n+1,&sizes)); 1176 sizes[0] = n; 1177 for (i=0; i<n; i++) { 1178 PetscCall(PetscStrlen(data[i],&len)); 1179 sizes[i+1] = (PetscInt)len + 1; /* size includes space for the null terminator */ 1180 } 1181 PetscCall(PetscViewerBinaryWrite(viewer,sizes,n+1,PETSC_INT)); 1182 for (i=0; i<n; i++) { 1183 PetscCall(PetscViewerBinaryWrite(viewer,(void*)data[i],sizes[i+1],PETSC_CHAR)); 1184 } 1185 PetscCall(PetscFree(sizes)); 1186 PetscFunctionReturn(0); 1187 } 1188 1189 /*@C 1190 PetscViewerBinaryReadStringArray - reads a binary file an array of strings 1191 1192 Collective 1193 1194 Input Parameter: 1195 . viewer - the binary viewer 1196 1197 Output Parameter: 1198 . data - location of the array of strings 1199 1200 Level: intermediate 1201 1202 Notes: 1203 array of strings is null terminated 1204 1205 .seealso: `PetscViewerASCIIOpen()`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`, 1206 `VecView()`, `MatView()`, `VecLoad()`, `MatLoad()`, `PetscViewerBinaryGetDescriptor()`, 1207 `PetscViewerBinaryGetInfoPointer()`, `PetscFileMode`, `PetscViewer`, `PetscViewerBinaryRead()` 1208 @*/ 1209 PetscErrorCode PetscViewerBinaryReadStringArray(PetscViewer viewer,char ***data) 1210 { 1211 PetscInt i,n,*sizes,N = 0; 1212 1213 PetscFunctionBegin; 1214 PetscCall(PetscViewerSetUp(viewer)); 1215 /* count number of strings */ 1216 PetscCall(PetscViewerBinaryRead(viewer,&n,1,NULL,PETSC_INT)); 1217 PetscCall(PetscMalloc1(n,&sizes)); 1218 PetscCall(PetscViewerBinaryRead(viewer,sizes,n,NULL,PETSC_INT)); 1219 for (i=0; i<n; i++) N += sizes[i]; 1220 PetscCall(PetscMalloc((n+1)*sizeof(char*) + N*sizeof(char),data)); 1221 (*data)[0] = (char*)((*data) + n + 1); 1222 for (i=1; i<n; i++) (*data)[i] = (*data)[i-1] + sizes[i-1]; 1223 PetscCall(PetscViewerBinaryRead(viewer,(*data)[0],N,NULL,PETSC_CHAR)); 1224 (*data)[n] = NULL; 1225 PetscCall(PetscFree(sizes)); 1226 PetscFunctionReturn(0); 1227 } 1228 1229 /*@C 1230 PetscViewerFileSetMode - Sets the open mode of file 1231 1232 Logically Collective on PetscViewer 1233 1234 Input Parameters: 1235 + viewer - the PetscViewer; must be a a PETSCVIEWERBINARY, PETSCVIEWERMATLAB, PETSCVIEWERHDF5, or PETSCVIEWERASCII PetscViewer 1236 - mode - open mode of file 1237 $ FILE_MODE_WRITE - create new file for output 1238 $ FILE_MODE_READ - open existing file for input 1239 $ FILE_MODE_APPEND - open existing file for output 1240 1241 Level: advanced 1242 1243 .seealso: `PetscViewerFileSetMode()`, `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerBinaryOpen()` 1244 1245 @*/ 1246 PetscErrorCode PetscViewerFileSetMode(PetscViewer viewer,PetscFileMode mode) 1247 { 1248 PetscFunctionBegin; 1249 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 1250 PetscValidLogicalCollectiveEnum(viewer,mode,2); 1251 PetscCheck(mode != FILE_MODE_UNDEFINED,PetscObjectComm((PetscObject)viewer),PETSC_ERR_SUP,"Cannot set FILE_MODE_UNDEFINED"); 1252 else PetscCheck(mode >= FILE_MODE_UNDEFINED && mode <= FILE_MODE_APPEND_UPDATE,PetscObjectComm((PetscObject)viewer),PETSC_ERR_ARG_OUTOFRANGE,"Invalid file mode %d",(int)mode); 1253 PetscTryMethod(viewer,"PetscViewerFileSetMode_C",(PetscViewer,PetscFileMode),(viewer,mode)); 1254 PetscFunctionReturn(0); 1255 } 1256 1257 static PetscErrorCode PetscViewerFileSetMode_Binary(PetscViewer viewer,PetscFileMode mode) 1258 { 1259 PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data; 1260 1261 PetscFunctionBegin; 1262 PetscCheck(!viewer->setupcalled || vbinary->filemode == mode,PetscObjectComm((PetscObject)viewer),PETSC_ERR_ORDER,"Cannot change mode to %s after setup",PetscFileModes[mode]); 1263 vbinary->filemode = mode; 1264 PetscFunctionReturn(0); 1265 } 1266 1267 /*@C 1268 PetscViewerFileGetMode - Gets the open mode of file 1269 1270 Not Collective 1271 1272 Input Parameter: 1273 . viewer - the PetscViewer; must be a PETSCVIEWERBINARY, PETSCVIEWERMATLAB, PETSCVIEWERHDF5, or PETSCVIEWERASCII PetscViewer 1274 1275 Output Parameter: 1276 . mode - open mode of file 1277 $ FILE_MODE_WRITE - create new file for binary output 1278 $ FILE_MODE_READ - open existing file for binary input 1279 $ FILE_MODE_APPEND - open existing file for binary output 1280 1281 Level: advanced 1282 1283 .seealso: `PetscViewerFileSetMode()`, `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerBinaryOpen()` 1284 1285 @*/ 1286 PetscErrorCode PetscViewerFileGetMode(PetscViewer viewer,PetscFileMode *mode) 1287 { 1288 PetscFunctionBegin; 1289 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 1290 PetscValidPointer(mode,2); 1291 PetscUseMethod(viewer,"PetscViewerFileGetMode_C",(PetscViewer,PetscFileMode*),(viewer,mode)); 1292 PetscFunctionReturn(0); 1293 } 1294 1295 static PetscErrorCode PetscViewerFileGetMode_Binary(PetscViewer viewer,PetscFileMode *mode) 1296 { 1297 PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data; 1298 1299 PetscFunctionBegin; 1300 *mode = vbinary->filemode; 1301 PetscFunctionReturn(0); 1302 } 1303 1304 static PetscErrorCode PetscViewerFileSetName_Binary(PetscViewer viewer,const char name[]) 1305 { 1306 PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data; 1307 1308 PetscFunctionBegin; 1309 if (viewer->setupcalled && vbinary->filename) { 1310 /* gzip can be run after the file with the previous filename has been closed */ 1311 PetscCall(PetscFree(vbinary->ogzfilename)); 1312 PetscCall(PetscStrallocpy(vbinary->filename,&vbinary->ogzfilename)); 1313 } 1314 PetscCall(PetscFree(vbinary->filename)); 1315 PetscCall(PetscStrallocpy(name,&vbinary->filename)); 1316 viewer->setupcalled = PETSC_FALSE; 1317 PetscFunctionReturn(0); 1318 } 1319 1320 static PetscErrorCode PetscViewerFileGetName_Binary(PetscViewer viewer,const char **name) 1321 { 1322 PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data; 1323 1324 PetscFunctionBegin; 1325 *name = vbinary->filename; 1326 PetscFunctionReturn(0); 1327 } 1328 1329 #if defined(PETSC_HAVE_MPIIO) 1330 static PetscErrorCode PetscViewerFileSetUp_BinaryMPIIO(PetscViewer viewer) 1331 { 1332 PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data; 1333 int amode; 1334 1335 PetscFunctionBegin; 1336 vbinary->storecompressed = PETSC_FALSE; 1337 1338 vbinary->moff = 0; 1339 switch (vbinary->filemode) { 1340 case FILE_MODE_READ: amode = MPI_MODE_RDONLY; break; 1341 case FILE_MODE_WRITE: amode = MPI_MODE_WRONLY | MPI_MODE_CREATE; break; 1342 case FILE_MODE_APPEND: amode = MPI_MODE_WRONLY | MPI_MODE_CREATE | MPI_MODE_APPEND; break; 1343 case FILE_MODE_UNDEFINED: SETERRQ(PetscObjectComm((PetscObject)viewer),PETSC_ERR_ORDER, "Must call PetscViewerFileSetMode() before PetscViewerSetUp()"); 1344 default: SETERRQ(PetscObjectComm((PetscObject)viewer),PETSC_ERR_SUP,"Unsupported file mode %s",PetscFileModes[vbinary->filemode]); 1345 } 1346 PetscCallMPI(MPI_File_open(PetscObjectComm((PetscObject)viewer),vbinary->filename,amode,MPI_INFO_NULL,&vbinary->mfdes)); 1347 /* 1348 The MPI standard does not have MPI_MODE_TRUNCATE. We emulate this behavior by setting the file size to zero. 1349 */ 1350 if (vbinary->filemode == FILE_MODE_WRITE) PetscCallMPI(MPI_File_set_size(vbinary->mfdes,0)); 1351 /* 1352 Initially, all processes view the file as a linear byte stream. Therefore, for files opened with MPI_MODE_APPEND, 1353 MPI_File_get_position[_shared](fh, &offset) returns the absolute byte position at the end of file. 1354 Otherwise, we would need to call MPI_File_get_byte_offset(fh, offset, &byte_offset) to convert 1355 the offset in etype units to an absolute byte position. 1356 */ 1357 if (vbinary->filemode == FILE_MODE_APPEND) PetscCallMPI(MPI_File_get_position(vbinary->mfdes,&vbinary->moff)); 1358 PetscFunctionReturn(0); 1359 } 1360 #endif 1361 1362 static PetscErrorCode PetscViewerFileSetUp_BinarySTDIO(PetscViewer viewer) 1363 { 1364 PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data; 1365 const char *fname; 1366 char bname[PETSC_MAX_PATH_LEN],*gz; 1367 PetscBool found; 1368 PetscMPIInt rank; 1369 1370 PetscFunctionBegin; 1371 PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer),&rank)); 1372 1373 /* if file name ends in .gz strip that off and note user wants file compressed */ 1374 vbinary->storecompressed = PETSC_FALSE; 1375 if (vbinary->filemode == FILE_MODE_WRITE) { 1376 PetscCall(PetscStrstr(vbinary->filename,".gz",&gz)); 1377 if (gz && gz[3] == 0) {*gz = 0; vbinary->storecompressed = PETSC_TRUE;} 1378 } 1379 #if !defined(PETSC_HAVE_POPEN) 1380 PetscCheck(!vbinary->storecompressed,PetscObjectComm((PetscObject)viewer),PETSC_ERR_SUP_SYS,"Cannot run gzip on this machine"); 1381 #endif 1382 1383 fname = vbinary->filename; 1384 if (vbinary->filemode == FILE_MODE_READ) { /* possibly get the file from remote site or compressed file */ 1385 PetscCall(PetscFileRetrieve(PetscObjectComm((PetscObject)viewer),fname,bname,PETSC_MAX_PATH_LEN,&found)); 1386 PetscCheck(found,PetscObjectComm((PetscObject)viewer),PETSC_ERR_FILE_OPEN,"Cannot locate file: %s",fname); 1387 fname = bname; 1388 } 1389 1390 vbinary->fdes = -1; 1391 if (rank == 0) { /* only first processor opens file*/ 1392 PetscFileMode mode = vbinary->filemode; 1393 if (mode == FILE_MODE_APPEND) { 1394 /* check if asked to append to a non-existing file */ 1395 PetscCall(PetscTestFile(fname,'\0',&found)); 1396 if (!found) mode = FILE_MODE_WRITE; 1397 } 1398 PetscCall(PetscBinaryOpen(fname,mode,&vbinary->fdes)); 1399 } 1400 PetscFunctionReturn(0); 1401 } 1402 1403 static PetscErrorCode PetscViewerFileSetUp_BinaryInfo(PetscViewer viewer) 1404 { 1405 PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data; 1406 PetscMPIInt rank; 1407 PetscBool found; 1408 1409 PetscFunctionBegin; 1410 vbinary->fdes_info = NULL; 1411 PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer),&rank)); 1412 if (!vbinary->skipinfo && (vbinary->filemode == FILE_MODE_READ || rank == 0)) { 1413 char infoname[PETSC_MAX_PATH_LEN],iname[PETSC_MAX_PATH_LEN],*gz; 1414 1415 PetscCall(PetscStrncpy(infoname,vbinary->filename,sizeof(infoname))); 1416 /* remove .gz if it ends file name */ 1417 PetscCall(PetscStrstr(infoname,".gz",&gz)); 1418 if (gz && gz[3] == 0) *gz = 0; 1419 1420 PetscCall(PetscStrlcat(infoname,".info",sizeof(infoname))); 1421 if (vbinary->filemode == FILE_MODE_READ) { 1422 PetscCall(PetscFixFilename(infoname,iname)); 1423 PetscCall(PetscFileRetrieve(PetscObjectComm((PetscObject)viewer),iname,infoname,PETSC_MAX_PATH_LEN,&found)); 1424 if (found) PetscCall(PetscOptionsInsertFile(PetscObjectComm((PetscObject)viewer),((PetscObject)viewer)->options,infoname,PETSC_FALSE)); 1425 } else if (rank == 0) { /* write or append */ 1426 const char *omode = (vbinary->filemode == FILE_MODE_APPEND) ? "a" : "w"; 1427 vbinary->fdes_info = fopen(infoname,omode); 1428 PetscCheck(vbinary->fdes_info,PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open .info file %s for writing",infoname); 1429 } 1430 } 1431 PetscFunctionReturn(0); 1432 } 1433 1434 static PetscErrorCode PetscViewerSetUp_Binary(PetscViewer viewer) 1435 { 1436 PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data; 1437 PetscBool usempiio; 1438 1439 PetscFunctionBegin; 1440 if (!vbinary->setfromoptionscalled) PetscCall(PetscViewerSetFromOptions(viewer)); 1441 PetscCheck(vbinary->filename,PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call PetscViewerFileSetName()"); 1442 PetscCheck(vbinary->filemode != (PetscFileMode)-1,PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call PetscViewerFileSetMode()"); 1443 PetscCall(PetscViewerFileClose_Binary(viewer)); 1444 1445 PetscCall(PetscViewerBinaryGetUseMPIIO(viewer,&usempiio)); 1446 if (usempiio) { 1447 #if defined(PETSC_HAVE_MPIIO) 1448 PetscCall(PetscViewerFileSetUp_BinaryMPIIO(viewer)); 1449 #endif 1450 } else { 1451 PetscCall(PetscViewerFileSetUp_BinarySTDIO(viewer)); 1452 } 1453 PetscCall(PetscViewerFileSetUp_BinaryInfo(viewer)); 1454 1455 PetscCall(PetscLogObjectState((PetscObject)viewer,"File: %s",vbinary->filename)); 1456 PetscFunctionReturn(0); 1457 } 1458 1459 static PetscErrorCode PetscViewerView_Binary(PetscViewer v,PetscViewer viewer) 1460 { 1461 PetscViewer_Binary *vbinary = (PetscViewer_Binary*)v->data; 1462 const char *fname = vbinary->filename ? vbinary->filename : "not yet set"; 1463 const char *fmode = vbinary->filemode != (PetscFileMode) -1 ? PetscFileModes[vbinary->filemode] : "not yet set"; 1464 PetscBool usempiio; 1465 1466 PetscFunctionBegin; 1467 PetscCall(PetscViewerBinaryGetUseMPIIO(v,&usempiio)); 1468 PetscCall(PetscViewerASCIIPrintf(viewer,"Filename: %s\n",fname)); 1469 PetscCall(PetscViewerASCIIPrintf(viewer,"Mode: %s (%s)\n",fmode,usempiio ? "mpiio" : "stdio")); 1470 PetscFunctionReturn(0); 1471 } 1472 1473 static PetscErrorCode PetscViewerSetFromOptions_Binary(PetscOptionItems *PetscOptionsObject,PetscViewer viewer) 1474 { 1475 PetscViewer_Binary *binary = (PetscViewer_Binary*)viewer->data; 1476 char defaultname[PETSC_MAX_PATH_LEN]; 1477 PetscBool flg; 1478 1479 PetscFunctionBegin; 1480 if (viewer->setupcalled) PetscFunctionReturn(0); 1481 PetscOptionsHeadBegin(PetscOptionsObject,"Binary PetscViewer Options"); 1482 PetscCall(PetscSNPrintf(defaultname,PETSC_MAX_PATH_LEN-1,"binaryoutput")); 1483 PetscCall(PetscOptionsString("-viewer_binary_filename","Specify filename","PetscViewerFileSetName",defaultname,defaultname,sizeof(defaultname),&flg)); 1484 if (flg) PetscCall(PetscViewerFileSetName_Binary(viewer,defaultname)); 1485 PetscCall(PetscOptionsBool("-viewer_binary_skip_info","Skip writing/reading .info file","PetscViewerBinarySetSkipInfo",binary->skipinfo,&binary->skipinfo,NULL)); 1486 PetscCall(PetscOptionsBool("-viewer_binary_skip_options","Skip parsing Vec/Mat load options","PetscViewerBinarySetSkipOptions",binary->skipoptions,&binary->skipoptions,NULL)); 1487 PetscCall(PetscOptionsBool("-viewer_binary_skip_header","Skip writing/reading header information","PetscViewerBinarySetSkipHeader",binary->skipheader,&binary->skipheader,NULL)); 1488 #if defined(PETSC_HAVE_MPIIO) 1489 PetscCall(PetscOptionsBool("-viewer_binary_mpiio","Use MPI-IO functionality to write/read binary file","PetscViewerBinarySetUseMPIIO",binary->usempiio,&binary->usempiio,NULL)); 1490 #else 1491 PetscCall(PetscOptionsBool("-viewer_binary_mpiio","Use MPI-IO functionality to write/read binary file (NOT AVAILABLE)","PetscViewerBinarySetUseMPIIO",PETSC_FALSE,NULL,NULL)); 1492 #endif 1493 PetscOptionsHeadEnd(); 1494 binary->setfromoptionscalled = PETSC_TRUE; 1495 PetscFunctionReturn(0); 1496 } 1497 1498 /*MC 1499 PETSCVIEWERBINARY - A viewer that saves to binary files 1500 1501 .seealso: `PetscViewerBinaryOpen()`, `PETSC_VIEWER_STDOUT_(),PETSC_VIEWER_STDOUT_SELF`, `PETSC_VIEWER_STDOUT_WORLD`, `PetscViewerCreate()`, `PetscViewerASCIIOpen()`, 1502 `PetscViewerMatlabOpen()`, `VecView()`, `DMView()`, `PetscViewerMatlabPutArray()`, `PETSCVIEWERASCII`, `PETSCVIEWERMATLAB`, `PETSCVIEWERDRAW`, 1503 `PetscViewerFileSetName()`, `PetscViewerFileSetMode()`, `PetscViewerFormat`, `PetscViewerType`, `PetscViewerSetType()`, 1504 `PetscViewerBinaryGetUseMPIIO()`, `PetscViewerBinarySetUseMPIIO()` 1505 1506 Level: beginner 1507 1508 M*/ 1509 1510 PETSC_EXTERN PetscErrorCode PetscViewerCreate_Binary(PetscViewer v) 1511 { 1512 PetscViewer_Binary *vbinary; 1513 1514 PetscFunctionBegin; 1515 PetscCall(PetscNewLog(v,&vbinary)); 1516 v->data = (void*)vbinary; 1517 1518 v->ops->setfromoptions = PetscViewerSetFromOptions_Binary; 1519 v->ops->destroy = PetscViewerDestroy_Binary; 1520 v->ops->view = PetscViewerView_Binary; 1521 v->ops->setup = PetscViewerSetUp_Binary; 1522 v->ops->flush = NULL; /* Should we support Flush() ? */ 1523 v->ops->getsubviewer = PetscViewerGetSubViewer_Binary; 1524 v->ops->restoresubviewer = PetscViewerRestoreSubViewer_Binary; 1525 v->ops->read = PetscViewerBinaryRead; 1526 1527 vbinary->fdes = -1; 1528 #if defined(PETSC_HAVE_MPIIO) 1529 vbinary->usempiio = PETSC_FALSE; 1530 vbinary->mfdes = MPI_FILE_NULL; 1531 vbinary->mfsub = MPI_FILE_NULL; 1532 #endif 1533 vbinary->filename = NULL; 1534 vbinary->filemode = FILE_MODE_UNDEFINED; 1535 vbinary->fdes_info = NULL; 1536 vbinary->skipinfo = PETSC_FALSE; 1537 vbinary->skipoptions = PETSC_TRUE; 1538 vbinary->skipheader = PETSC_FALSE; 1539 vbinary->storecompressed = PETSC_FALSE; 1540 vbinary->ogzfilename = NULL; 1541 vbinary->flowcontrol = 256; /* seems a good number for Cray XT-5 */ 1542 1543 vbinary->setfromoptionscalled = PETSC_FALSE; 1544 1545 PetscCall(PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetFlowControl_C",PetscViewerBinaryGetFlowControl_Binary)); 1546 PetscCall(PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetFlowControl_C",PetscViewerBinarySetFlowControl_Binary)); 1547 PetscCall(PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetSkipHeader_C",PetscViewerBinaryGetSkipHeader_Binary)); 1548 PetscCall(PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetSkipHeader_C",PetscViewerBinarySetSkipHeader_Binary)); 1549 PetscCall(PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetSkipOptions_C",PetscViewerBinaryGetSkipOptions_Binary)); 1550 PetscCall(PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetSkipOptions_C",PetscViewerBinarySetSkipOptions_Binary)); 1551 PetscCall(PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetSkipInfo_C",PetscViewerBinaryGetSkipInfo_Binary)); 1552 PetscCall(PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetSkipInfo_C",PetscViewerBinarySetSkipInfo_Binary)); 1553 PetscCall(PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetInfoPointer_C",PetscViewerBinaryGetInfoPointer_Binary)); 1554 PetscCall(PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileGetName_C",PetscViewerFileGetName_Binary)); 1555 PetscCall(PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileSetName_C",PetscViewerFileSetName_Binary)); 1556 PetscCall(PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileGetMode_C",PetscViewerFileGetMode_Binary)); 1557 PetscCall(PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileSetMode_C",PetscViewerFileSetMode_Binary)); 1558 #if defined(PETSC_HAVE_MPIIO) 1559 PetscCall(PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetUseMPIIO_C",PetscViewerBinaryGetUseMPIIO_Binary)); 1560 PetscCall(PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetUseMPIIO_C",PetscViewerBinarySetUseMPIIO_Binary)); 1561 #endif 1562 PetscFunctionReturn(0); 1563 } 1564 1565 /* ---------------------------------------------------------------------*/ 1566 /* 1567 The variable Petsc_Viewer_Binary_keyval is used to indicate an MPI attribute that 1568 is attached to a communicator, in this case the attribute is a PetscViewer. 1569 */ 1570 PetscMPIInt Petsc_Viewer_Binary_keyval = MPI_KEYVAL_INVALID; 1571 1572 /*@C 1573 PETSC_VIEWER_BINARY_ - Creates a binary PetscViewer shared by all processors 1574 in a communicator. 1575 1576 Collective 1577 1578 Input Parameter: 1579 . comm - the MPI communicator to share the binary PetscViewer 1580 1581 Level: intermediate 1582 1583 Options Database Keys: 1584 + -viewer_binary_filename <name> - filename in which to store the binary data, defaults to binaryoutput 1585 . -viewer_binary_skip_info - true means do not create .info file for this viewer 1586 . -viewer_binary_skip_options - true means do not use the options database for this viewer 1587 . -viewer_binary_skip_header - true means do not store the usual header information in the binary file 1588 - -viewer_binary_mpiio - true means use the file via MPI-IO, maybe faster for large files and many MPI ranks 1589 1590 Environmental variables: 1591 - PETSC_VIEWER_BINARY_FILENAME - filename in which to store the binary data, defaults to binaryoutput 1592 1593 Notes: 1594 Unlike almost all other PETSc routines, PETSC_VIEWER_BINARY_ does not return 1595 an error code. The binary PetscViewer is usually used in the form 1596 $ XXXView(XXX object,PETSC_VIEWER_BINARY_(comm)); 1597 1598 .seealso: `PETSC_VIEWER_BINARY_WORLD`, `PETSC_VIEWER_BINARY_SELF`, `PetscViewerBinaryOpen()`, `PetscViewerCreate()`, 1599 `PetscViewerDestroy()` 1600 @*/ 1601 PetscViewer PETSC_VIEWER_BINARY_(MPI_Comm comm) 1602 { 1603 PetscErrorCode ierr; 1604 PetscBool flg; 1605 PetscViewer viewer; 1606 char fname[PETSC_MAX_PATH_LEN]; 1607 MPI_Comm ncomm; 1608 1609 PetscFunctionBegin; 1610 ierr = PetscCommDuplicate(comm,&ncomm,NULL);if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);} 1611 if (Petsc_Viewer_Binary_keyval == MPI_KEYVAL_INVALID) { 1612 ierr = MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN,MPI_COMM_NULL_DELETE_FN,&Petsc_Viewer_Binary_keyval,NULL); 1613 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);} 1614 } 1615 ierr = MPI_Comm_get_attr(ncomm,Petsc_Viewer_Binary_keyval,(void**)&viewer,(int*)&flg); 1616 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);} 1617 if (!flg) { /* PetscViewer not yet created */ 1618 ierr = PetscOptionsGetenv(ncomm,"PETSC_VIEWER_BINARY_FILENAME",fname,PETSC_MAX_PATH_LEN,&flg); 1619 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_REPEAT," ");PetscFunctionReturn(NULL);} 1620 if (!flg) { 1621 ierr = PetscStrcpy(fname,"binaryoutput"); 1622 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_REPEAT," ");PetscFunctionReturn(NULL);} 1623 } 1624 ierr = PetscViewerBinaryOpen(ncomm,fname,FILE_MODE_WRITE,&viewer); 1625 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_REPEAT," ");PetscFunctionReturn(NULL);} 1626 ierr = PetscObjectRegisterDestroy((PetscObject)viewer); 1627 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_REPEAT," ");PetscFunctionReturn(NULL);} 1628 ierr = MPI_Comm_set_attr(ncomm,Petsc_Viewer_Binary_keyval,(void*)viewer); 1629 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);} 1630 } 1631 ierr = PetscCommDestroy(&ncomm); 1632 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_REPEAT," ");PetscFunctionReturn(NULL);} 1633 PetscFunctionReturn(viewer); 1634 } 1635