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