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