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