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