xref: /petsc/src/sys/classes/viewer/impls/binary/binv.c (revision d22fd6bccd970bc725775d38b4562d3998096202)
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(). 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(), PetscViewerBinarySkipInfo().
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_filename <name>
676 .    -viewer_binary_skip_info
677 .    -viewer_binary_skip_options
678 .    -viewer_binary_skip_header
679 -    -viewer_binary_mpiio
680 
681    Level: beginner
682 
683    Note:
684    This PetscViewer should be destroyed with PetscViewerDestroy().
685 
686     For reading files, the filename may begin with ftp:// or http:// and/or
687     end with .gz; in this case file is brought over and uncompressed.
688 
689     For creating files, if the file name ends with .gz it is automatically
690     compressed when closed.
691 
692     For writing files it only opens the file on processor 0 in the communicator.
693     For readable files it opens the file on all nodes that have the file. If
694     node 0 does not have the file it generates an error even if other nodes
695     do have the file.
696 
697    Concepts: binary files
698    Concepts: PetscViewerBinary^creating
699    Concepts: gzip
700    Concepts: accessing remote file
701    Concepts: remote file
702 
703 .seealso: PetscViewerASCIIOpen(), PetscViewerSetFormat(), PetscViewerDestroy(),
704           VecView(), MatView(), VecLoad(), MatLoad(), PetscViewerBinaryGetDescriptor(),
705           PetscViewerBinaryGetInfoPointer(), PetscFileMode, PetscViewer, PetscViewerBinaryRead()
706 @*/
707 PetscErrorCode  PetscViewerBinaryOpen(MPI_Comm comm,const char name[],PetscFileMode type,PetscViewer *binv)
708 {
709   PetscErrorCode ierr;
710 
711   PetscFunctionBegin;
712   ierr = PetscViewerCreate(comm,binv);CHKERRQ(ierr);
713   ierr = PetscViewerSetType(*binv,PETSCVIEWERBINARY);CHKERRQ(ierr);
714   ierr = PetscViewerFileSetMode(*binv,type);CHKERRQ(ierr);
715   ierr = PetscViewerFileSetName(*binv,name);CHKERRQ(ierr);
716   ierr = PetscViewerSetFromOptions(*binv);CHKERRQ(ierr);
717   PetscFunctionReturn(0);
718 }
719 
720 #if defined(PETSC_HAVE_MPIIO)
721 #undef __FUNCT__
722 #define __FUNCT__ "PetscViewerBinaryWriteReadMPIIO"
723 static PetscErrorCode PetscViewerBinaryWriteReadMPIIO(PetscViewer viewer,void *data,PetscInt count,PetscDataType dtype,PetscBool write)
724 {
725   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
726   PetscErrorCode     ierr;
727   MPI_Datatype       mdtype;
728   PetscMPIInt        cnt;
729   MPI_Status         status;
730   MPI_Aint           ul,dsize;
731 
732   PetscFunctionBegin;
733   ierr = PetscMPIIntCast(count,&cnt);CHKERRQ(ierr);
734   ierr = PetscDataTypeToMPIDataType(dtype,&mdtype);CHKERRQ(ierr);
735   ierr = MPI_File_set_view(vbinary->mfdes,vbinary->moff,mdtype,mdtype,(char*)"native",MPI_INFO_NULL);CHKERRQ(ierr);
736   if (write) {
737     ierr = MPIU_File_write_all(vbinary->mfdes,data,cnt,mdtype,&status);CHKERRQ(ierr);
738   } else {
739     ierr = MPIU_File_read_all(vbinary->mfdes,data,cnt,mdtype,&status);CHKERRQ(ierr);
740   }
741   ierr = MPI_Type_get_extent(mdtype,&ul,&dsize);CHKERRQ(ierr);
742 
743   vbinary->moff += dsize*cnt;
744   PetscFunctionReturn(0);
745 }
746 #endif
747 
748 #undef __FUNCT__
749 #define __FUNCT__ "PetscViewerBinaryRead"
750 /*@C
751    PetscViewerBinaryRead - Reads from a binary file, all processors get the same result
752 
753    Collective on MPI_Comm
754 
755    Input Parameters:
756 +  viewer - the binary viewer
757 .  data - location of the data to be written
758 .  count - number of items of data to read
759 -  dtype - type of data to read
760 
761    Level: beginner
762 
763    Concepts: binary files
764 
765 .seealso: PetscViewerASCIIOpen(), PetscViewerSetFormat(), PetscViewerDestroy(),
766           VecView(), MatView(), VecLoad(), MatLoad(), PetscViewerBinaryGetDescriptor(),
767           PetscViewerBinaryGetInfoPointer(), PetscFileMode, PetscViewer, PetscBinaryViewerRead()
768 @*/
769 PetscErrorCode  PetscViewerBinaryRead(PetscViewer viewer,void *data,PetscInt count,PetscDataType dtype)
770 {
771   PetscErrorCode     ierr;
772   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
773 
774   ierr = PetscViewerSetUp_Binary(viewer);CHKERRQ(ierr);
775 #if defined(PETSC_HAVE_MPIIO)
776   if (vbinary->MPIIO) {
777     ierr = PetscViewerBinaryWriteReadMPIIO(viewer,data,count,dtype,PETSC_FALSE);CHKERRQ(ierr);
778   } else {
779 #endif
780     ierr = PetscBinarySynchronizedRead(PetscObjectComm((PetscObject)viewer),vbinary->fdes,data,count,dtype);CHKERRQ(ierr);
781 #if defined(PETSC_HAVE_MPIIO)
782   }
783 #endif
784   PetscFunctionReturn(0);
785 }
786 
787 
788 #undef __FUNCT__
789 #define __FUNCT__ "PetscViewerBinaryWrite"
790 /*@C
791    PetscViewerBinaryWrite - writes to a binary file, only from the first process
792 
793    Collective on MPI_Comm
794 
795    Input Parameters:
796 +  viewer - the binary viewer
797 .  data - location of data
798 .  count - number of items of data to write
799 .  dtype - type of data to write
800 -  istemp - data may be overwritten
801 
802    Level: beginner
803 
804    Notes: because byte-swapping may be done on the values in data it cannot be declared const
805 
806    Concepts: binary files
807 
808 .seealso: PetscViewerASCIIOpen(), PetscViewerSetFormat(), PetscViewerDestroy(),
809           VecView(), MatView(), VecLoad(), MatLoad(), PetscViewerBinaryGetDescriptor(), PetscDataType
810           PetscViewerBinaryGetInfoPointer(), PetscFileMode, PetscViewer, PetscBinaryViewerRead()
811 @*/
812 PetscErrorCode  PetscViewerBinaryWrite(PetscViewer viewer,void *data,PetscInt count,PetscDataType dtype,PetscBool istemp)
813 {
814   PetscErrorCode     ierr;
815   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
816 
817   PetscFunctionBegin;
818   ierr = PetscViewerSetUp_Binary(viewer);CHKERRQ(ierr);
819 #if defined(PETSC_HAVE_MPIIO)
820   if (vbinary->MPIIO) {
821     ierr = PetscViewerBinaryWriteReadMPIIO(viewer,data,count,dtype,PETSC_TRUE);CHKERRQ(ierr);
822   } else {
823 #endif
824     ierr = PetscBinarySynchronizedWrite(PetscObjectComm((PetscObject)viewer),vbinary->fdes,data,count,dtype,istemp);CHKERRQ(ierr);
825 #if defined(PETSC_HAVE_MPIIO)
826   }
827 #endif
828   PetscFunctionReturn(0);
829 }
830 
831 #undef __FUNCT__
832 #define __FUNCT__ "PetscViewerBinaryWriteStringArray"
833 /*@C
834    PetscViewerBinaryWriteStringArray - writes to a binary file, only from the first process an array of strings
835 
836    Collective on MPI_Comm
837 
838    Input Parameters:
839 +  viewer - the binary viewer
840 -  data - location of the array of strings
841 
842 
843    Level: intermediate
844 
845    Concepts: binary files
846 
847     Notes: array of strings is null terminated
848 
849 .seealso: PetscViewerASCIIOpen(), PetscViewerSetFormat(), PetscViewerDestroy(),
850           VecView(), MatView(), VecLoad(), MatLoad(), PetscViewerBinaryGetDescriptor(),
851           PetscViewerBinaryGetInfoPointer(), PetscFileMode, PetscViewer, PetscBinaryViewerRead()
852 @*/
853 PetscErrorCode  PetscViewerBinaryWriteStringArray(PetscViewer viewer,char **data)
854 {
855   PetscErrorCode ierr;
856   PetscInt       i,n = 0,*sizes;
857 
858   ierr = PetscViewerSetUp_Binary(viewer);CHKERRQ(ierr);
859   /* count number of strings */
860   while (data[n++]) ;
861   n--;
862   ierr     = PetscMalloc1(n+1,&sizes);CHKERRQ(ierr);
863   sizes[0] = n;
864   for (i=0; i<n; i++) {
865     size_t tmp;
866     ierr       = PetscStrlen(data[i],&tmp);CHKERRQ(ierr);
867     sizes[i+1] = tmp + 1;   /* size includes space for the null terminator */
868   }
869   ierr = PetscViewerBinaryWrite(viewer,sizes,n+1,PETSC_INT,PETSC_FALSE);CHKERRQ(ierr);
870   for (i=0; i<n; i++) {
871     ierr = PetscViewerBinaryWrite(viewer,data[i],sizes[i+1],PETSC_CHAR,PETSC_FALSE);CHKERRQ(ierr);
872   }
873   ierr = PetscFree(sizes);CHKERRQ(ierr);
874   PetscFunctionReturn(0);
875 }
876 
877 #undef __FUNCT__
878 #define __FUNCT__ "PetscViewerBinaryReadStringArray"
879 /*@C
880    PetscViewerBinaryReadStringArray - reads a binary file an array of strings
881 
882    Collective on MPI_Comm
883 
884    Input Parameter:
885 .  viewer - the binary viewer
886 
887    Output Parameter:
888 .  data - location of the array of strings
889 
890    Level: intermediate
891 
892    Concepts: binary files
893 
894     Notes: array of strings is null terminated
895 
896 .seealso: PetscViewerASCIIOpen(), PetscViewerSetFormat(), PetscViewerDestroy(),
897           VecView(), MatView(), VecLoad(), MatLoad(), PetscViewerBinaryGetDescriptor(),
898           PetscViewerBinaryGetInfoPointer(), PetscFileMode, PetscViewer, PetscBinaryViewerRead()
899 @*/
900 PetscErrorCode  PetscViewerBinaryReadStringArray(PetscViewer viewer,char ***data)
901 {
902   PetscErrorCode ierr;
903   PetscInt       i,n,*sizes,N = 0;
904 
905   ierr = PetscViewerSetUp_Binary(viewer);CHKERRQ(ierr);
906   /* count number of strings */
907   ierr = PetscViewerBinaryRead(viewer,&n,1,PETSC_INT);CHKERRQ(ierr);
908   ierr = PetscMalloc1(n,&sizes);CHKERRQ(ierr);
909   ierr = PetscViewerBinaryRead(viewer,sizes,n,PETSC_INT);CHKERRQ(ierr);
910   for (i=0; i<n; i++) N += sizes[i];
911   ierr = PetscMalloc((n+1)*sizeof(char*) + N*sizeof(char),data);CHKERRQ(ierr);
912   (*data)[0] = (char*)((*data) + n + 1);
913   for (i=1; i<n; i++) (*data)[i] = (*data)[i-1] + sizes[i-1];
914   ierr = PetscViewerBinaryRead(viewer,(*data)[0],N,PETSC_CHAR);CHKERRQ(ierr);
915 
916   (*data)[n] = 0;
917 
918   ierr = PetscFree(sizes);CHKERRQ(ierr);
919   PetscFunctionReturn(0);
920 }
921 
922 #undef __FUNCT__
923 #define __FUNCT__ "PetscViewerFileGetName_Binary"
924 PetscErrorCode PetscViewerFileGetName_Binary(PetscViewer viewer,const char **name)
925 {
926   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
927 
928   PetscFunctionBegin;
929   *name = vbinary->filename;
930   PetscFunctionReturn(0);
931 }
932 
933 #undef __FUNCT__
934 #define __FUNCT__ "PetscViewerFileGetMode"
935 /*@C
936      PetscViewerFileGetMode - Gets the type of file to be open
937 
938     Not Collective
939 
940   Input Parameter:
941 .  viewer - the PetscViewer; must be a binary, MATLAB, hdf, or netcdf PetscViewer
942 
943   Output Parameter:
944 .  type - type of file
945 $    FILE_MODE_WRITE - create new file for binary output
946 $    FILE_MODE_READ - open existing file for binary input
947 $    FILE_MODE_APPEND - open existing file for binary output
948 
949   Level: advanced
950 
951 .seealso: PetscViewerFileSetMode(), PetscViewerCreate(), PetscViewerSetType(), PetscViewerBinaryOpen()
952 
953 @*/
954 PetscErrorCode  PetscViewerFileGetMode(PetscViewer viewer,PetscFileMode *type)
955 {
956   PetscErrorCode ierr;
957 
958   PetscFunctionBegin;
959   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
960   PetscValidPointer(type,2);
961   ierr = PetscUseMethod(viewer,"PetscViewerFileGetMode_C",(PetscViewer,PetscFileMode*),(viewer,type));CHKERRQ(ierr);
962   PetscFunctionReturn(0);
963 }
964 
965 #undef __FUNCT__
966 #define __FUNCT__ "PetscViewerBinarySetMPIIO"
967 /*@
968      PetscViewerBinarySetMPIIO - Sets a binary viewer to use MPI IO for reading/writing. Must be called
969         before PetscViewerFileSetName()
970 
971     Logically Collective on PetscViewer
972 
973   Input Parameters:
974 .  viewer - the PetscViewer; must be a binary
975 
976     Options Database:
977     -viewer_binary_mpiio : Flag for using MPI-IO
978 
979   Level: advanced
980 
981 .seealso: PetscViewerFileSetMode(), PetscViewerCreate(), PetscViewerSetType(), PetscViewerBinaryOpen()
982 
983 @*/
984 PetscErrorCode  PetscViewerBinarySetMPIIO(PetscViewer viewer)
985 {
986   PetscErrorCode ierr;
987 
988   PetscFunctionBegin;
989   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
990   ierr = PetscTryMethod(viewer,"PetscViewerBinarySetMPIIO_C",(PetscViewer),(viewer));CHKERRQ(ierr);
991   PetscFunctionReturn(0);
992 }
993 
994 
995 #undef __FUNCT__
996 #define __FUNCT__ "PetscViewerFileSetMode"
997 /*@C
998      PetscViewerFileSetMode - Sets the type of file to be open
999 
1000     Logically Collective on PetscViewer
1001 
1002   Input Parameters:
1003 +  viewer - the PetscViewer; must be a binary, Matlab, hdf, or netcdf PetscViewer
1004 -  type - type of file
1005 $    FILE_MODE_WRITE - create new file for binary output
1006 $    FILE_MODE_READ - open existing file for binary input
1007 $    FILE_MODE_APPEND - open existing file for binary output
1008 
1009   Level: advanced
1010 
1011 .seealso: PetscViewerFileSetMode(), PetscViewerCreate(), PetscViewerSetType(), PetscViewerBinaryOpen()
1012 
1013 @*/
1014 PetscErrorCode  PetscViewerFileSetMode(PetscViewer viewer,PetscFileMode type)
1015 {
1016   PetscErrorCode ierr;
1017 
1018   PetscFunctionBegin;
1019   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
1020   PetscValidLogicalCollectiveEnum(viewer,type,2);
1021   ierr = PetscTryMethod(viewer,"PetscViewerFileSetMode_C",(PetscViewer,PetscFileMode),(viewer,type));CHKERRQ(ierr);
1022   PetscFunctionReturn(0);
1023 }
1024 
1025 #undef __FUNCT__
1026 #define __FUNCT__ "PetscViewerFileGetMode_Binary"
1027 PetscErrorCode PetscViewerFileGetMode_Binary(PetscViewer viewer,PetscFileMode *type)
1028 {
1029   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
1030 
1031   PetscFunctionBegin;
1032   *type = vbinary->btype;
1033   PetscFunctionReturn(0);
1034 }
1035 
1036 #undef __FUNCT__
1037 #define __FUNCT__ "PetscViewerFileSetMode_Binary"
1038 PetscErrorCode PetscViewerFileSetMode_Binary(PetscViewer viewer,PetscFileMode type)
1039 {
1040   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
1041 
1042   PetscFunctionBegin;
1043   vbinary->btype = type;
1044   PetscFunctionReturn(0);
1045 }
1046 
1047 #undef __FUNCT__
1048 #define __FUNCT__ "PetscViewerFileSetName_Binary"
1049 PetscErrorCode PetscViewerFileSetName_Binary(PetscViewer viewer,const char name[])
1050 {
1051   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
1052   PetscErrorCode     ierr;
1053 
1054   PetscFunctionBegin;
1055   if (vbinary->filename) { ierr = PetscFree(vbinary->filename);CHKERRQ(ierr); }
1056   ierr = PetscStrallocpy(name,&vbinary->filename);CHKERRQ(ierr);
1057   PetscFunctionReturn(0);
1058 }
1059 /*
1060         Actually opens the file
1061 */
1062 #undef __FUNCT__
1063 #define __FUNCT__ "PetscViewerFileSetUp_Binary"
1064 static PetscErrorCode PetscViewerFileSetUp_Binary(PetscViewer viewer)
1065 {
1066   PetscMPIInt        rank;
1067   PetscErrorCode     ierr;
1068   size_t             len;
1069   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
1070   const char         *fname;
1071   char               bname[PETSC_MAX_PATH_LEN],*gz;
1072   PetscBool          found;
1073   PetscFileMode      type = vbinary->btype;
1074 
1075   PetscFunctionBegin;
1076   if (type == (PetscFileMode) -1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call PetscViewerFileSetMode()");
1077   if (!vbinary->filename) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call PetscViewerFileSetName()");
1078   ierr = PetscViewerFileClose_Binary(viewer);CHKERRQ(ierr);
1079 
1080   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)viewer),&rank);CHKERRQ(ierr);
1081 
1082   /* if ends in .gz strip that off and note user wants file compressed */
1083   vbinary->storecompressed = PETSC_FALSE;
1084   if (!rank && type == FILE_MODE_WRITE) {
1085     /* remove .gz if it ends library name */
1086     ierr = PetscStrstr(vbinary->filename,".gz",&gz);CHKERRQ(ierr);
1087     if (gz) {
1088       ierr = PetscStrlen(gz,&len);CHKERRQ(ierr);
1089       if (len == 3) {
1090         *gz = 0;
1091         vbinary->storecompressed = PETSC_TRUE;
1092       }
1093     }
1094   }
1095 
1096   /* only first processor opens file if writeable */
1097   if (!rank || type == FILE_MODE_READ) {
1098 
1099     if (type == FILE_MODE_READ) {
1100       /* possibly get the file from remote site or compressed file */
1101       ierr  = PetscFileRetrieve(PetscObjectComm((PetscObject)viewer),vbinary->filename,bname,PETSC_MAX_PATH_LEN,&found);CHKERRQ(ierr);
1102       fname = bname;
1103       if (!rank && !found) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot locate file: %s on node zero",vbinary->filename);
1104       else if (!found) {
1105         ierr  = PetscInfo(viewer,"Nonzero processor did not locate readonly file\n");CHKERRQ(ierr);
1106         fname = 0;
1107       }
1108     } else fname = vbinary->filename;
1109 
1110 #if defined(PETSC_HAVE_O_BINARY)
1111     if (type == FILE_MODE_WRITE) {
1112       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);
1113     } else if (type == FILE_MODE_READ && fname) {
1114       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);
1115     } else if (type == FILE_MODE_APPEND) {
1116       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);
1117     } else if (fname) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown file type");
1118 #else
1119     if (type == FILE_MODE_WRITE) {
1120       if ((vbinary->fdes = creat(fname,0666)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot create file %s for writing",fname);
1121     } else if (type == FILE_MODE_READ && fname) {
1122       if ((vbinary->fdes = open(fname,O_RDONLY,0)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file %s for reading",fname);
1123     } else if (type == FILE_MODE_APPEND) {
1124       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);
1125     } else if (fname) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown file type");
1126 #endif
1127   } else vbinary->fdes = -1;
1128 
1129   /*
1130       try to open info file: all processors open this file if read only
1131   */
1132   if (!vbinary->skipinfo && (!rank || type == FILE_MODE_READ)) {
1133     char infoname[PETSC_MAX_PATH_LEN],iname[PETSC_MAX_PATH_LEN];
1134 
1135     ierr = PetscStrcpy(infoname,vbinary->filename);CHKERRQ(ierr);
1136     /* remove .gz if it ends library name */
1137     ierr = PetscStrstr(infoname,".gz",&gz);CHKERRQ(ierr);
1138     if (gz) {
1139       ierr = PetscStrlen(gz,&len);CHKERRQ(ierr);
1140       if (len == 3) *gz = 0;
1141     }
1142 
1143     ierr = PetscStrcat(infoname,".info");CHKERRQ(ierr);
1144     ierr = PetscFixFilename(infoname,iname);CHKERRQ(ierr);
1145     if (type == FILE_MODE_READ) {
1146       ierr = PetscFileRetrieve(PetscObjectComm((PetscObject)viewer),iname,infoname,PETSC_MAX_PATH_LEN,&found);CHKERRQ(ierr);
1147       ierr = PetscOptionsInsertFile(PetscObjectComm((PetscObject)viewer),infoname,PETSC_FALSE);CHKERRQ(ierr);
1148     } else {
1149       vbinary->fdes_info = fopen(infoname,"w");
1150       if (!vbinary->fdes_info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open .info file %s for writing",infoname);
1151     }
1152   }
1153 #if defined(PETSC_USE_LOG)
1154   PetscLogObjectState((PetscObject)viewer,"File: %s",vbinary->filename);
1155 #endif
1156   PetscFunctionReturn(0);
1157 }
1158 
1159 #if defined(PETSC_HAVE_MPIIO)
1160 #undef __FUNCT__
1161 #define __FUNCT__ "PetscViewerFileSetUp_BinaryMPIIO"
1162 static PetscErrorCode PetscViewerFileSetUp_BinaryMPIIO(PetscViewer viewer)
1163 {
1164   PetscMPIInt        rank;
1165   PetscErrorCode     ierr;
1166   size_t             len;
1167   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
1168   char               *gz;
1169   PetscBool          found;
1170   PetscFileMode      type = vbinary->btype;
1171 
1172   PetscFunctionBegin;
1173   if (type == (PetscFileMode) -1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call PetscViewerFileSetMode()");
1174   if (!vbinary->filename) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call PetscViewerFileSetName()");
1175   ierr = PetscViewerFileClose_BinaryMPIIO(viewer);CHKERRQ(ierr);
1176 
1177   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)viewer),&rank);CHKERRQ(ierr);
1178 
1179   vbinary->storecompressed = PETSC_FALSE;
1180 
1181   /* only first processor opens file if writeable */
1182   if (type == FILE_MODE_READ) {
1183     MPI_File_open(PetscObjectComm((PetscObject)viewer),vbinary->filename,MPI_MODE_RDONLY,MPI_INFO_NULL,&vbinary->mfdes);CHKERRQ(ierr);
1184   } else if (type == FILE_MODE_WRITE) {
1185     MPI_File_open(PetscObjectComm((PetscObject)viewer),vbinary->filename,MPI_MODE_WRONLY | MPI_MODE_CREATE,MPI_INFO_NULL,&vbinary->mfdes);CHKERRQ(ierr);
1186   }
1187 
1188   /*
1189       try to open info file: all processors open this file if read only
1190 
1191       Below is identical code to the code for Binary above, should be put in seperate routine
1192   */
1193   if (!vbinary->skipinfo && (!rank || type == FILE_MODE_READ)) {
1194     char infoname[PETSC_MAX_PATH_LEN],iname[PETSC_MAX_PATH_LEN];
1195 
1196     ierr = PetscStrcpy(infoname,vbinary->filename);CHKERRQ(ierr);
1197     /* remove .gz if it ends library name */
1198     ierr = PetscStrstr(infoname,".gz",&gz);CHKERRQ(ierr);
1199     if (gz) {
1200       ierr = PetscStrlen(gz,&len);CHKERRQ(ierr);
1201       if (len == 3) *gz = 0;
1202     }
1203 
1204     ierr = PetscStrcat(infoname,".info");CHKERRQ(ierr);
1205     ierr = PetscFixFilename(infoname,iname);CHKERRQ(ierr);
1206     if (type == FILE_MODE_READ) {
1207       ierr = PetscFileRetrieve(PetscObjectComm((PetscObject)viewer),iname,infoname,PETSC_MAX_PATH_LEN,&found);CHKERRQ(ierr);
1208       ierr = PetscOptionsInsertFile(PetscObjectComm((PetscObject)viewer),infoname,PETSC_FALSE);CHKERRQ(ierr);
1209     } else {
1210       vbinary->fdes_info = fopen(infoname,"w");
1211       if (!vbinary->fdes_info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open .info file %s for writing",infoname);
1212     }
1213   }
1214 #if defined(PETSC_USE_LOG)
1215   PetscLogObjectState((PetscObject)viewer,"File: %s",vbinary->filename);
1216 #endif
1217   PetscFunctionReturn(0);
1218 }
1219 
1220 #undef __FUNCT__
1221 #define __FUNCT__ "PetscViewerBinarySetMPIIO_Binary"
1222 PetscErrorCode PetscViewerBinarySetMPIIO_Binary(PetscViewer viewer)
1223 {
1224   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
1225   PetscFunctionBegin;
1226   vbinary->MPIIO       = PETSC_TRUE;
1227   PetscFunctionReturn(0);
1228 }
1229 #endif
1230 
1231 #undef __FUNCT__
1232 #define __FUNCT__ "PetscViewerView_Binary"
1233 PetscErrorCode  PetscViewerView_Binary(PetscViewer v,PetscViewer viewer)
1234 {
1235   PetscErrorCode     ierr;
1236   PetscViewer_Binary *binary = (PetscViewer_Binary*)v->data;
1237 
1238   PetscFunctionBegin;
1239   if (binary->filename) {
1240     ierr = PetscViewerASCIIPrintf(viewer,"Filename: %s\n",binary->filename);CHKERRQ(ierr);
1241   }
1242   PetscFunctionReturn(0);
1243 }
1244 
1245 #undef __FUNCT__
1246 #define __FUNCT__ "PetscViewerSetUp_Binary"
1247 static PetscErrorCode PetscViewerSetUp_Binary(PetscViewer v)
1248 {
1249   PetscErrorCode     ierr;
1250   PetscViewer_Binary *binary = (PetscViewer_Binary*)v->data;
1251 
1252   PetscFunctionBegin;
1253   if (binary->setupcalled) { PetscFunctionReturn(0); }
1254   if (!binary->setfromoptionscalled) { ierr = PetscViewerSetFromOptions(v);CHKERRQ(ierr); }
1255 
1256 #if defined(PETSC_HAVE_MPIIO)
1257   if (binary->MPIIO) {
1258     ierr = PetscViewerFileSetUp_BinaryMPIIO(v);CHKERRQ(ierr);
1259   } else {
1260 #endif
1261     ierr = PetscViewerFileSetUp_Binary(v);CHKERRQ(ierr);
1262 #if defined(PETSC_HAVE_MPIIO)
1263   }
1264 #endif
1265   binary->setupcalled = PETSC_TRUE;
1266 
1267   PetscFunctionReturn(0);
1268 }
1269 
1270 #undef __FUNCT__
1271 #define __FUNCT__ "PetscViewerSetFromOptions_Binary"
1272 static PetscErrorCode PetscViewerSetFromOptions_Binary(PetscOptions *PetscOptionsObject,PetscViewer v)
1273 {
1274   PetscErrorCode     ierr;
1275   PetscViewer_Binary *binary = (PetscViewer_Binary*)v->data;
1276   char               defaultname[PETSC_MAX_PATH_LEN];
1277   PetscBool          flg;
1278 #if defined(PETSC_HAVE_MPIIO)
1279   PetscBool          useMPIIO = PETSC_FALSE;
1280 #endif
1281 
1282   PetscFunctionBegin;
1283   ierr = PetscOptionsHead(PetscOptionsObject,"Binary PetscViewer Options");CHKERRQ(ierr);
1284   ierr = PetscSNPrintf(defaultname,PETSC_MAX_PATH_LEN-1,"binaryoutput");CHKERRQ(ierr);
1285   ierr = PetscOptionsString("-viewer_binary_filename","Specify filename","PetscViewerFileSetName",defaultname,defaultname,PETSC_MAX_PATH_LEN-1,&flg);CHKERRQ(ierr);
1286   if (flg) { ierr = PetscViewerFileSetName_Binary(v,defaultname);CHKERRQ(ierr); }
1287   ierr = PetscOptionsBool("-viewer_binary_skip_info","Skip writing/reading .info file","PetscViewerBinarySkipInfo",PETSC_FALSE,&binary->skipinfo,&flg);CHKERRQ(ierr);
1288   ierr = PetscOptionsBool("-viewer_binary_skip_options","Skip parsing vec load options","PetscViewerBinarySetSkipOptions",PETSC_TRUE,&binary->skipoptions,&flg);CHKERRQ(ierr);
1289   ierr = PetscOptionsBool("-viewer_binary_skip_header","Skip writing/reading header information","PetscViewerBinarySetSkipHeader",PETSC_FALSE,&binary->skipheader,&flg);CHKERRQ(ierr);
1290 #if defined(PETSC_HAVE_MPIIO)
1291   ierr = PetscOptionsBool("-viewer_binary_mpiio","Use MPI-IO functionality to write/read binary file","PetscViewerBinarySetMPIIO",PETSC_FALSE,&useMPIIO,&flg);CHKERRQ(ierr);
1292   if (useMPIIO) {
1293     ierr = PetscViewerBinarySetMPIIO(v);CHKERRQ(ierr);
1294   }
1295 #endif
1296   ierr = PetscOptionsTail();CHKERRQ(ierr);
1297   binary->setfromoptionscalled = PETSC_FALSE;
1298   PetscFunctionReturn(0);
1299 }
1300 
1301 #undef __FUNCT__
1302 #define __FUNCT__ "PetscViewerCreate_Binary"
1303 PETSC_EXTERN PetscErrorCode PetscViewerCreate_Binary(PetscViewer v)
1304 {
1305   PetscErrorCode     ierr;
1306   PetscViewer_Binary *vbinary;
1307 
1308   PetscFunctionBegin;
1309   ierr                     = PetscNewLog(v,&vbinary);CHKERRQ(ierr);
1310   v->data                  = (void*)vbinary;
1311   v->ops->setfromoptions   = PetscViewerSetFromOptions_Binary;
1312   v->ops->destroy          = PetscViewerDestroy_Binary;
1313   v->ops->view             = PetscViewerView_Binary;
1314   v->ops->flush            = 0;
1315   vbinary->fdes_info       = 0;
1316   vbinary->fdes            = 0;
1317   vbinary->skipinfo        = PETSC_FALSE;
1318   vbinary->skipoptions     = PETSC_TRUE;
1319   vbinary->skipheader      = PETSC_FALSE;
1320   vbinary->setupcalled     = PETSC_FALSE;
1321   vbinary->setfromoptionscalled = PETSC_FALSE;
1322   v->ops->getsingleton     = PetscViewerGetSingleton_Binary;
1323   v->ops->restoresingleton = PetscViewerRestoreSingleton_Binary;
1324   v->ops->read             = PetscViewerBinaryRead;
1325   vbinary->btype           = (PetscFileMode) -1;
1326   vbinary->storecompressed = PETSC_FALSE;
1327   vbinary->filename        = 0;
1328   vbinary->flowcontrol     = 256; /* seems a good number for Cray XT-5 */
1329 
1330   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetFlowControl_C",PetscViewerBinaryGetFlowControl_Binary);CHKERRQ(ierr);
1331   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetFlowControl_C",PetscViewerBinarySetFlowControl_Binary);CHKERRQ(ierr);
1332   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetSkipHeader_C",PetscViewerBinarySetSkipHeader_Binary);CHKERRQ(ierr);
1333   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetSkipHeader_C",PetscViewerBinaryGetSkipHeader_Binary);CHKERRQ(ierr);
1334   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetInfoPointer_C",PetscViewerBinaryGetInfoPointer_Binary);CHKERRQ(ierr);
1335   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileSetName_C",PetscViewerFileSetName_Binary);CHKERRQ(ierr);
1336   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileSetMode_C",PetscViewerFileSetMode_Binary);CHKERRQ(ierr);
1337   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileGetMode_C",PetscViewerFileGetMode_Binary);CHKERRQ(ierr);
1338   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileGetName_C",PetscViewerFileGetName_Binary);CHKERRQ(ierr);
1339 #if defined(PETSC_HAVE_MPIIO)
1340   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetMPIIO_C",PetscViewerBinarySetMPIIO_Binary);CHKERRQ(ierr);
1341 #endif
1342   PetscFunctionReturn(0);
1343 }
1344 
1345 /* ---------------------------------------------------------------------*/
1346 /*
1347     The variable Petsc_Viewer_Binary_keyval is used to indicate an MPI attribute that
1348   is attached to a communicator, in this case the attribute is a PetscViewer.
1349 */
1350 static int Petsc_Viewer_Binary_keyval = MPI_KEYVAL_INVALID;
1351 
1352 #undef __FUNCT__
1353 #define __FUNCT__ "PETSC_VIEWER_BINARY_"
1354 /*@C
1355      PETSC_VIEWER_BINARY_ - Creates a binary PetscViewer shared by all processors
1356                      in a communicator.
1357 
1358      Collective on MPI_Comm
1359 
1360      Input Parameter:
1361 .    comm - the MPI communicator to share the binary PetscViewer
1362 
1363      Level: intermediate
1364 
1365    Options Database Keys:
1366 +    -viewer_binary_filename <name>
1367 .    -viewer_binary_skip_info
1368 .    -viewer_binary_skip_options
1369 .    -viewer_binary_skip_header
1370 -    -viewer_binary_mpiio
1371 
1372    Environmental variables:
1373 -   PETSC_VIEWER_BINARY_FILENAME
1374 
1375      Notes:
1376      Unlike almost all other PETSc routines, PETSC_VIEWER_BINARY_ does not return
1377      an error code.  The binary PetscViewer is usually used in the form
1378 $       XXXView(XXX object,PETSC_VIEWER_BINARY_(comm));
1379 
1380 .seealso: PETSC_VIEWER_BINARY_WORLD, PETSC_VIEWER_BINARY_SELF, PetscViewerBinaryOpen(), PetscViewerCreate(),
1381           PetscViewerDestroy()
1382 @*/
1383 PetscViewer  PETSC_VIEWER_BINARY_(MPI_Comm comm)
1384 {
1385   PetscErrorCode ierr;
1386   PetscBool      flg;
1387   PetscViewer    viewer;
1388   char           fname[PETSC_MAX_PATH_LEN];
1389   MPI_Comm       ncomm;
1390 
1391   PetscFunctionBegin;
1392   ierr = PetscCommDuplicate(comm,&ncomm,NULL);if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
1393   if (Petsc_Viewer_Binary_keyval == MPI_KEYVAL_INVALID) {
1394     ierr = MPI_Keyval_create(MPI_NULL_COPY_FN,MPI_NULL_DELETE_FN,&Petsc_Viewer_Binary_keyval,0);
1395     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
1396   }
1397   ierr = MPI_Attr_get(ncomm,Petsc_Viewer_Binary_keyval,(void**)&viewer,(int*)&flg);
1398   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
1399   if (!flg) { /* PetscViewer not yet created */
1400     ierr = PetscOptionsGetenv(ncomm,"PETSC_VIEWER_BINARY_FILENAME",fname,PETSC_MAX_PATH_LEN,&flg);
1401     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
1402     if (!flg) {
1403       ierr = PetscStrcpy(fname,"binaryoutput");
1404       if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
1405     }
1406     ierr = PetscViewerBinaryOpen(ncomm,fname,FILE_MODE_WRITE,&viewer);
1407     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
1408     ierr = PetscObjectRegisterDestroy((PetscObject)viewer);
1409     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
1410     ierr = MPI_Attr_put(ncomm,Petsc_Viewer_Binary_keyval,(void*)viewer);
1411     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
1412   }
1413   ierr = PetscCommDestroy(&ncomm);
1414   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
1415   PetscFunctionReturn(viewer);
1416 }
1417