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