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