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