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