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