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