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