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