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