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