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