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