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