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