1 #include <petsc/private/viewerimpl.h>    /*I   "petscviewer.h"   I*/
2 
3 typedef struct  {
4   int           fdes;                 /* file descriptor, ignored if using MPI IO */
5 #if defined(PETSC_HAVE_MPIIO)
6   PetscBool     usempiio;
7   MPI_File      mfdes;                /* ignored unless using MPI IO */
8   MPI_File      mfsub;                /* subviewer support */
9   MPI_Offset    moff;
10 #endif
11   char          *filename;            /* file name */
12   PetscFileMode filemode;             /* read/write/append mode */
13   FILE          *fdes_info;           /* optional file containing info on binary file*/
14   PetscBool     storecompressed;      /* gzip the write binary file when closing it*/
15   char          *ogzfilename;         /* gzip can be run after the filename has been updated */
16   PetscBool     skipinfo;             /* Don't create info file for writing; don't use for reading */
17   PetscBool     skipoptions;          /* don't use PETSc options database when loading */
18   PetscInt      flowcontrol;          /* allow only <flowcontrol> messages outstanding at a time while doing IO */
19   PetscBool     skipheader;           /* don't write header, only raw data */
20   PetscBool     matlabheaderwritten;  /* if format is PETSC_VIEWER_BINARY_MATLAB has the MATLAB .info header been written yet */
21   PetscBool     setfromoptionscalled;
22 } PetscViewer_Binary;
23 
24 #if defined(PETSC_HAVE_MPIIO)
PetscViewerBinarySyncMPIIO(PetscViewer viewer)25 static PetscErrorCode PetscViewerBinarySyncMPIIO(PetscViewer viewer)
26 {
27   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
28   PetscErrorCode     ierr;
29 
30   PetscFunctionBegin;
31   if (vbinary->filemode == FILE_MODE_READ) PetscFunctionReturn(0);
32   if (vbinary->mfsub != MPI_FILE_NULL) {
33     ierr = MPI_File_sync(vbinary->mfsub);CHKERRQ(ierr);
34   }
35   if (vbinary->mfdes != MPI_FILE_NULL) {
36     ierr = MPI_Barrier(PetscObjectComm((PetscObject)viewer));CHKERRQ(ierr);
37     ierr = MPI_File_sync(vbinary->mfdes);CHKERRQ(ierr);
38   }
39   PetscFunctionReturn(0);
40 }
41 #endif
42 
PetscViewerGetSubViewer_Binary(PetscViewer viewer,MPI_Comm comm,PetscViewer * outviewer)43 static PetscErrorCode PetscViewerGetSubViewer_Binary(PetscViewer viewer,MPI_Comm comm,PetscViewer *outviewer)
44 {
45   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
46   PetscMPIInt        rank;
47   PetscErrorCode     ierr;
48 
49   PetscFunctionBegin;
50   ierr = PetscViewerSetUp(viewer);CHKERRQ(ierr);
51 
52   /* Return subviewer in process zero */
53   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)viewer),&rank);CHKERRQ(ierr);
54   if (!rank) {
55     PetscMPIInt flg;
56 
57     ierr = MPI_Comm_compare(PETSC_COMM_SELF,comm,&flg);CHKERRQ(ierr);
58     if (flg != MPI_IDENT && flg != MPI_CONGRUENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"PetscViewerGetSubViewer() for PETSCVIEWERBINARY requires a singleton MPI_Comm");
59     ierr = PetscViewerCreate(comm,outviewer);CHKERRQ(ierr);
60     ierr = PetscViewerSetType(*outviewer,PETSCVIEWERBINARY);CHKERRQ(ierr);
61     ierr = PetscMemcpy((*outviewer)->data,vbinary,sizeof(PetscViewer_Binary));CHKERRQ(ierr);
62     (*outviewer)->setupcalled = PETSC_TRUE;
63   } else {
64     *outviewer = NULL;
65   }
66 
67 #if defined(PETSC_HAVE_MPIIO)
68   if (vbinary->usempiio && *outviewer) {
69     PetscViewer_Binary *obinary = (PetscViewer_Binary*)(*outviewer)->data;
70     /* Parent viewer opens a new MPI file handle on PETSC_COMM_SELF and keeps track of it for future reuse */
71     if (vbinary->mfsub == MPI_FILE_NULL) {
72       int amode;
73       switch (vbinary->filemode) {
74       case FILE_MODE_READ:   amode = MPI_MODE_RDONLY; break;
75       case FILE_MODE_WRITE:  amode = MPI_MODE_WRONLY; break;
76       case FILE_MODE_APPEND: amode = MPI_MODE_WRONLY; break;
77       default: SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unsupported file mode %s",PetscFileModes[vbinary->filemode]);
78       }
79       ierr = MPI_File_open(PETSC_COMM_SELF,vbinary->filename,amode,MPI_INFO_NULL,&vbinary->mfsub);CHKERRQ(ierr);
80     }
81     /* Subviewer gets the MPI file handle on PETSC_COMM_SELF */
82     obinary->mfdes = vbinary->mfsub;
83     obinary->mfsub = MPI_FILE_NULL;
84     obinary->moff  = vbinary->moff;
85   }
86 #endif
87 
88 #if defined(PETSC_HAVE_MPIIO)
89   ierr = PetscViewerBinarySyncMPIIO(viewer);CHKERRQ(ierr);
90 #endif
91   PetscFunctionReturn(0);
92 }
93 
PetscViewerRestoreSubViewer_Binary(PetscViewer viewer,MPI_Comm comm,PetscViewer * outviewer)94 static PetscErrorCode PetscViewerRestoreSubViewer_Binary(PetscViewer viewer,MPI_Comm comm,PetscViewer *outviewer)
95 {
96   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
97   PetscMPIInt        rank;
98   PetscErrorCode     ierr;
99 #if defined(PETSC_HAVE_MPIIO)
100   MPI_Offset         moff = 0;
101 #endif
102 
103   PetscFunctionBegin;
104   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)viewer),&rank);CHKERRQ(ierr);
105   if (rank && *outviewer) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Subviewer not obtained from viewer");
106 
107 #if defined(PETSC_HAVE_MPIIO)
108   if (vbinary->usempiio && *outviewer) {
109     PetscViewer_Binary *obinary = (PetscViewer_Binary*)(*outviewer)->data;
110     if (obinary->mfdes != vbinary->mfsub) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Subviewer not obtained from viewer");
111     if (obinary->mfsub != MPI_FILE_NULL) {ierr = MPI_File_close(&obinary->mfsub);CHKERRQ(ierr);}
112     moff = obinary->moff;
113   }
114 #endif
115 
116   if (*outviewer) {
117     PetscViewer_Binary *obinary = (PetscViewer_Binary*)(*outviewer)->data;
118     if (obinary->fdes != vbinary->fdes) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Subviewer not obtained from viewer");
119     ierr = PetscFree((*outviewer)->data);CHKERRQ(ierr);
120     ierr = PetscHeaderDestroy(outviewer);CHKERRQ(ierr);
121   }
122 
123 #if defined(PETSC_HAVE_MPIIO)
124   if (vbinary->usempiio) {
125     PetscInt64 ioff = (PetscInt64)moff; /* We could use MPI_OFFSET datatype (requires MPI 2.2) */
126     ierr = MPI_Bcast(&ioff,1,MPIU_INT64,0,PetscObjectComm((PetscObject)viewer));CHKERRQ(ierr);
127     vbinary->moff = (MPI_Offset)ioff;
128   }
129 #endif
130 
131 #if defined(PETSC_HAVE_MPIIO)
132   ierr = PetscViewerBinarySyncMPIIO(viewer);CHKERRQ(ierr);
133 #endif
134   PetscFunctionReturn(0);
135 }
136 
137 #if defined(PETSC_HAVE_MPIIO)
138 /*@C
139     PetscViewerBinaryGetMPIIOOffset - Gets the current global offset that should be passed to MPI_File_set_view() or MPI_File_{write|read}_at[_all]()
140 
141     Not Collective
142 
143     Input Parameter:
144 .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()
145 
146     Output Parameter:
147 .   off - the current global offset
148 
149     Level: advanced
150 
151     Fortran Note:
152     This routine is not supported in Fortran.
153 
154     Use PetscViewerBinaryAddMPIIOOffset() to increase this value after you have written a view.
155 
156 
157 .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetInfoPointer(), PetscViewerBinaryGetUseMPIIO(), PetscViewerBinarySetUseMPIIO(), PetscViewerBinaryAddMPIIOOffset()
158 @*/
PetscViewerBinaryGetMPIIOOffset(PetscViewer viewer,MPI_Offset * off)159 PetscErrorCode PetscViewerBinaryGetMPIIOOffset(PetscViewer viewer,MPI_Offset *off)
160 {
161   PetscViewer_Binary *vbinary;
162 
163   PetscFunctionBegin;
164   PetscValidHeaderSpecificType(viewer,PETSC_VIEWER_CLASSID,1,PETSCVIEWERBINARY);
165   PetscValidPointer(off,2);
166   vbinary = (PetscViewer_Binary*)viewer->data;
167   *off = vbinary->moff;
168   PetscFunctionReturn(0);
169 }
170 
171 /*@C
172     PetscViewerBinaryAddMPIIOOffset - Adds to the current global offset
173 
174     Logically Collective
175 
176     Input Parameters:
177 +   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()
178 -   off - the addition to the global offset
179 
180     Level: advanced
181 
182     Fortran Note:
183     This routine is not supported in Fortran.
184 
185     Use PetscViewerBinaryGetMPIIOOffset() to get the value that you should pass to MPI_File_set_view() or MPI_File_{write|read}_at[_all]()
186 
187 
188 .seealso: PetscViewerBinaryOpen(),PetscViewerBinaryGetInfoPointer(), PetscViewerBinaryGetUseMPIIO(), PetscViewerBinarySetUseMPIIO(), PetscViewerBinaryGetMPIIOOffset()
189 @*/
PetscViewerBinaryAddMPIIOOffset(PetscViewer viewer,MPI_Offset off)190 PetscErrorCode PetscViewerBinaryAddMPIIOOffset(PetscViewer viewer,MPI_Offset off)
191 {
192   PetscViewer_Binary *vbinary;
193 
194   PetscFunctionBegin;
195   PetscValidHeaderSpecificType(viewer,PETSC_VIEWER_CLASSID,1,PETSCVIEWERBINARY);
196   PetscValidLogicalCollectiveInt(viewer,(PetscInt)off,2);
197   vbinary = (PetscViewer_Binary*)viewer->data;
198   vbinary->moff += off;
199   PetscFunctionReturn(0);
200 }
201 
202 /*@C
203     PetscViewerBinaryGetMPIIODescriptor - Extracts the MPI IO file descriptor from a PetscViewer.
204 
205     Not Collective
206 
207     Input Parameter:
208 .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()
209 
210     Output Parameter:
211 .   fdes - file descriptor
212 
213     Level: advanced
214 
215     Fortran Note:
216     This routine is not supported in Fortran.
217 
218 
219 .seealso: PetscViewerBinaryOpen(),PetscViewerBinaryGetInfoPointer(), PetscViewerBinaryGetUseMPIIO(), PetscViewerBinarySetUseMPIIO(), PetscViewerBinaryGetMPIIOOffset()
220 @*/
PetscViewerBinaryGetMPIIODescriptor(PetscViewer viewer,MPI_File * fdes)221 PetscErrorCode PetscViewerBinaryGetMPIIODescriptor(PetscViewer viewer,MPI_File *fdes)
222 {
223   PetscErrorCode     ierr;
224   PetscViewer_Binary *vbinary;
225 
226   PetscFunctionBegin;
227   PetscValidHeaderSpecificType(viewer,PETSC_VIEWER_CLASSID,1,PETSCVIEWERBINARY);
228   PetscValidPointer(fdes,2);
229   ierr = PetscViewerSetUp(viewer);CHKERRQ(ierr);
230   vbinary = (PetscViewer_Binary*)viewer->data;
231   *fdes = vbinary->mfdes;
232   PetscFunctionReturn(0);
233 }
234 #endif
235 
236 /*@
237     PetscViewerBinarySetUseMPIIO - Sets a binary viewer to use MPI-IO for reading/writing. Must be called
238         before PetscViewerFileSetName()
239 
240     Logically Collective on PetscViewer
241 
242     Input Parameters:
243 +   viewer - the PetscViewer; must be a binary
244 -   use - PETSC_TRUE means MPI-IO will be used
245 
246     Options Database:
247     -viewer_binary_mpiio : Flag for using MPI-IO
248 
249     Level: advanced
250 
251 .seealso: PetscViewerFileSetMode(), PetscViewerCreate(), PetscViewerSetType(), PetscViewerBinaryOpen(),
252           PetscViewerBinaryGetUseMPIIO()
253 
254 @*/
PetscViewerBinarySetUseMPIIO(PetscViewer viewer,PetscBool use)255 PetscErrorCode PetscViewerBinarySetUseMPIIO(PetscViewer viewer,PetscBool use)
256 {
257   PetscErrorCode ierr;
258 
259   PetscFunctionBegin;
260   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
261   PetscValidLogicalCollectiveBool(viewer,use,2);
262   ierr = PetscTryMethod(viewer,"PetscViewerBinarySetUseMPIIO_C",(PetscViewer,PetscBool),(viewer,use));CHKERRQ(ierr);
263   PetscFunctionReturn(0);
264 }
265 
266 #if defined(PETSC_HAVE_MPIIO)
PetscViewerBinarySetUseMPIIO_Binary(PetscViewer viewer,PetscBool use)267 static PetscErrorCode PetscViewerBinarySetUseMPIIO_Binary(PetscViewer viewer,PetscBool use)
268 {
269   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
270   PetscFunctionBegin;
271   if (viewer->setupcalled && vbinary->usempiio != use) SETERRQ1(PetscObjectComm((PetscObject)viewer),PETSC_ERR_ORDER,"Cannot change MPIIO to %s after setup",PetscBools[use]);
272   vbinary->usempiio = use;
273   PetscFunctionReturn(0);
274 }
275 #endif
276 
277 /*@
278     PetscViewerBinaryGetUseMPIIO - Returns PETSC_TRUE if the binary viewer uses MPI-IO.
279 
280     Not Collective
281 
282     Input Parameter:
283 .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()
284 
285     Output Parameter:
286 -   use - PETSC_TRUE if MPI-IO is being used
287 
288     Options Database:
289     -viewer_binary_mpiio : Flag for using MPI-IO
290 
291     Level: advanced
292 
293     Note:
294     If MPI-IO is not available, this function will always return PETSC_FALSE
295 
296     Fortran Note:
297     This routine is not supported in Fortran.
298 
299 
300 .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetInfoPointer(), PetscViewerBinarySetUseMPIIO(), PetscViewerBinaryGetMPIIOOffset()
301 @*/
PetscViewerBinaryGetUseMPIIO(PetscViewer viewer,PetscBool * use)302 PetscErrorCode PetscViewerBinaryGetUseMPIIO(PetscViewer viewer,PetscBool *use)
303 {
304   PetscErrorCode ierr;
305 
306   PetscFunctionBegin;
307   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
308   PetscValidBoolPointer(use,2);
309   *use = PETSC_FALSE;
310   ierr = PetscTryMethod(viewer,"PetscViewerBinaryGetUseMPIIO_C",(PetscViewer,PetscBool*),(viewer,use));CHKERRQ(ierr);
311   PetscFunctionReturn(0);
312 }
313 
314 #if defined(PETSC_HAVE_MPIIO)
PetscViewerBinaryGetUseMPIIO_Binary(PetscViewer viewer,PetscBool * use)315 static PetscErrorCode PetscViewerBinaryGetUseMPIIO_Binary(PetscViewer viewer,PetscBool  *use)
316 {
317   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
318 
319   PetscFunctionBegin;
320   *use = vbinary->usempiio;
321   PetscFunctionReturn(0);
322 }
323 #endif
324 
325 /*@
326     PetscViewerBinarySetFlowControl - Sets how many messages are allowed to outstanding at the same time during parallel IO reads/writes
327 
328     Not Collective
329 
330     Input Parameter:
331 +   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()
332 -   fc - the number of messages, defaults to 256 if this function was not called
333 
334     Level: advanced
335 
336 .seealso: PetscViewerBinaryOpen(),PetscViewerBinaryGetInfoPointer(), PetscViewerBinaryGetFlowControl()
337 
338 @*/
PetscViewerBinarySetFlowControl(PetscViewer viewer,PetscInt fc)339 PetscErrorCode  PetscViewerBinarySetFlowControl(PetscViewer viewer,PetscInt fc)
340 {
341   PetscErrorCode ierr;
342 
343   PetscFunctionBegin;
344   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
345   PetscValidLogicalCollectiveInt(viewer,fc,2);
346   ierr = PetscTryMethod(viewer,"PetscViewerBinarySetFlowControl_C",(PetscViewer,PetscInt),(viewer,fc));CHKERRQ(ierr);
347   PetscFunctionReturn(0);
348 }
349 
PetscViewerBinarySetFlowControl_Binary(PetscViewer viewer,PetscInt fc)350 static PetscErrorCode PetscViewerBinarySetFlowControl_Binary(PetscViewer viewer,PetscInt fc)
351 {
352   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
353 
354   PetscFunctionBegin;
355   if (fc <= 1) SETERRQ1(PetscObjectComm((PetscObject)viewer),PETSC_ERR_ARG_OUTOFRANGE,"Flow control count must be greater than 1, %D was set",fc);
356   vbinary->flowcontrol = fc;
357   PetscFunctionReturn(0);
358 }
359 
360 /*@
361     PetscViewerBinaryGetFlowControl - Returns how many messages are allowed to outstanding at the same time during parallel IO reads/writes
362 
363     Not Collective
364 
365     Input Parameter:
366 .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()
367 
368     Output Parameter:
369 .   fc - the number of messages
370 
371     Level: advanced
372 
373 .seealso: PetscViewerBinaryOpen(),PetscViewerBinaryGetInfoPointer(), PetscViewerBinarySetFlowControl()
374 
375 @*/
PetscViewerBinaryGetFlowControl(PetscViewer viewer,PetscInt * fc)376 PetscErrorCode PetscViewerBinaryGetFlowControl(PetscViewer viewer,PetscInt *fc)
377 {
378   PetscErrorCode ierr;
379 
380   PetscFunctionBegin;
381   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
382   PetscValidIntPointer(fc,2);
383   ierr = PetscUseMethod(viewer,"PetscViewerBinaryGetFlowControl_C",(PetscViewer,PetscInt*),(viewer,fc));CHKERRQ(ierr);
384   PetscFunctionReturn(0);
385 }
386 
PetscViewerBinaryGetFlowControl_Binary(PetscViewer viewer,PetscInt * fc)387 static PetscErrorCode  PetscViewerBinaryGetFlowControl_Binary(PetscViewer viewer,PetscInt *fc)
388 {
389   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
390 
391   PetscFunctionBegin;
392   *fc = vbinary->flowcontrol;
393   PetscFunctionReturn(0);
394 }
395 
396 /*@C
397     PetscViewerBinaryGetDescriptor - Extracts the file descriptor from a PetscViewer.
398 
399     Collective On PetscViewer
400 
401     Input Parameter:
402 .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()
403 
404     Output Parameter:
405 .   fdes - file descriptor
406 
407     Level: advanced
408 
409     Notes:
410       For writable binary PetscViewers, the descriptor will only be valid for the
411     first processor in the communicator that shares the PetscViewer. For readable
412     files it will only be valid on nodes that have the file. If node 0 does not
413     have the file it generates an error even if another node does have the file.
414 
415     Fortran Note:
416     This routine is not supported in Fortran.
417 
418     Developer Notes:
419     This must be called on all processes because Dave May changed
420     the source code that this may be trigger a PetscViewerSetUp() call if it was not previously triggered.
421 
422 
423 
424 .seealso: PetscViewerBinaryOpen(),PetscViewerBinaryGetInfoPointer()
425 @*/
PetscViewerBinaryGetDescriptor(PetscViewer viewer,int * fdes)426 PetscErrorCode PetscViewerBinaryGetDescriptor(PetscViewer viewer,int *fdes)
427 {
428   PetscErrorCode     ierr;
429   PetscViewer_Binary *vbinary;
430 
431   PetscFunctionBegin;
432   PetscValidHeaderSpecificType(viewer,PETSC_VIEWER_CLASSID,1,PETSCVIEWERBINARY);
433   PetscValidPointer(fdes,2);
434   ierr = PetscViewerSetUp(viewer);CHKERRQ(ierr);
435   vbinary = (PetscViewer_Binary*)viewer->data;
436   *fdes = vbinary->fdes;
437   PetscFunctionReturn(0);
438 }
439 
440 /*@
441     PetscViewerBinarySkipInfo - Binary file will not have .info file created with it
442 
443     Not Collective
444 
445     Input Parameter:
446 .   viewer - PetscViewer context, obtained from PetscViewerCreate()
447 
448     Options Database Key:
449 .   -viewer_binary_skip_info
450 
451     Level: advanced
452 
453     Notes:
454     This must be called after PetscViewerSetType(). If you use PetscViewerBinaryOpen() then
455     you can only skip the info file with the -viewer_binary_skip_info flag. To use the function you must open the
456     viewer with PetscViewerCreate(), PetscViewerSetType(), PetscViewerBinarySkipInfo().
457 
458     The .info contains meta information about the data in the binary file, for example the block size if it was
459     set for a vector or matrix.
460 
461 .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetDescriptor(), PetscViewerBinarySetSkipOptions(),
462           PetscViewerBinaryGetSkipOptions(), PetscViewerBinaryGetSkipInfo()
463 @*/
PetscViewerBinarySkipInfo(PetscViewer viewer)464 PetscErrorCode PetscViewerBinarySkipInfo(PetscViewer viewer)
465 {
466   PetscErrorCode ierr;
467 
468   PetscFunctionBegin;
469   ierr = PetscViewerBinarySetSkipInfo(viewer,PETSC_TRUE);CHKERRQ(ierr);
470   PetscFunctionReturn(0);
471 }
472 
473 /*@
474     PetscViewerBinarySetSkipInfo - Binary file will not have .info file created with it
475 
476     Not Collective
477 
478     Input Parameter:
479 +   viewer - PetscViewer context, obtained from PetscViewerCreate()
480 -   skip - PETSC_TRUE implies the .info file will not be generated
481 
482     Options Database Key:
483 .   -viewer_binary_skip_info
484 
485     Level: advanced
486 
487 .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetDescriptor(), PetscViewerBinarySetSkipOptions(),
488           PetscViewerBinaryGetSkipOptions(), PetscViewerBinaryGetSkipInfo()
489 @*/
PetscViewerBinarySetSkipInfo(PetscViewer viewer,PetscBool skip)490 PetscErrorCode PetscViewerBinarySetSkipInfo(PetscViewer viewer,PetscBool skip)
491 {
492   PetscErrorCode ierr;
493 
494   PetscFunctionBegin;
495   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
496   PetscValidLogicalCollectiveBool(viewer,skip,2);
497   ierr = PetscTryMethod(viewer,"PetscViewerBinarySetSkipInfo_C",(PetscViewer,PetscBool),(viewer,skip));CHKERRQ(ierr);
498   PetscFunctionReturn(0);
499 }
500 
PetscViewerBinarySetSkipInfo_Binary(PetscViewer viewer,PetscBool skip)501 static PetscErrorCode PetscViewerBinarySetSkipInfo_Binary(PetscViewer viewer,PetscBool skip)
502 {
503   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
504 
505   PetscFunctionBegin;
506   vbinary->skipinfo = skip;
507   PetscFunctionReturn(0);
508 }
509 
510 /*@
511     PetscViewerBinaryGetSkipInfo - check if viewer wrote a .info file
512 
513     Not Collective
514 
515     Input Parameter:
516 .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()
517 
518     Output Parameter:
519 .   skip - PETSC_TRUE implies the .info file was not generated
520 
521     Level: advanced
522 
523     Notes:
524     This must be called after PetscViewerSetType()
525 
526 .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetDescriptor(), PetscViewerBinarySkipInfo(),
527           PetscViewerBinarySetSkipOptions(), PetscViewerBinarySetSkipInfo()
528 @*/
PetscViewerBinaryGetSkipInfo(PetscViewer viewer,PetscBool * skip)529 PetscErrorCode PetscViewerBinaryGetSkipInfo(PetscViewer viewer,PetscBool *skip)
530 {
531   PetscErrorCode ierr;
532 
533   PetscFunctionBegin;
534   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
535   PetscValidBoolPointer(skip,2);
536   ierr = PetscUseMethod(viewer,"PetscViewerBinaryGetSkipInfo_C",(PetscViewer,PetscBool*),(viewer,skip));CHKERRQ(ierr);
537   PetscFunctionReturn(0);
538 }
539 
PetscViewerBinaryGetSkipInfo_Binary(PetscViewer viewer,PetscBool * skip)540 static PetscErrorCode PetscViewerBinaryGetSkipInfo_Binary(PetscViewer viewer,PetscBool *skip)
541 {
542   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
543 
544   PetscFunctionBegin;
545   *skip  = vbinary->skipinfo;
546   PetscFunctionReturn(0);
547 }
548 
549 /*@
550     PetscViewerBinarySetSkipOptions - do not use the PETSc options database when loading objects
551 
552     Not Collective
553 
554     Input Parameters:
555 +   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()
556 -   skip - PETSC_TRUE means do not use
557 
558     Options Database Key:
559 .   -viewer_binary_skip_options
560 
561     Level: advanced
562 
563     Notes:
564     This must be called after PetscViewerSetType()
565 
566 .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetDescriptor(), PetscViewerBinarySkipInfo(),
567           PetscViewerBinaryGetSkipOptions()
568 @*/
PetscViewerBinarySetSkipOptions(PetscViewer viewer,PetscBool skip)569 PetscErrorCode PetscViewerBinarySetSkipOptions(PetscViewer viewer,PetscBool skip)
570 {
571   PetscErrorCode ierr;
572 
573   PetscFunctionBegin;
574   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
575   PetscValidLogicalCollectiveBool(viewer,skip,2);
576   ierr = PetscTryMethod(viewer,"PetscViewerBinarySetSkipOptions_C",(PetscViewer,PetscBool),(viewer,skip));CHKERRQ(ierr);
577   PetscFunctionReturn(0);
578 }
579 
PetscViewerBinarySetSkipOptions_Binary(PetscViewer viewer,PetscBool skip)580 static PetscErrorCode PetscViewerBinarySetSkipOptions_Binary(PetscViewer viewer,PetscBool skip)
581 {
582   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
583 
584   PetscFunctionBegin;
585   vbinary->skipoptions = skip;
586   PetscFunctionReturn(0);
587 }
588 
589 /*@
590     PetscViewerBinaryGetSkipOptions - checks if viewer uses the PETSc options database when loading objects
591 
592     Not Collective
593 
594     Input Parameter:
595 .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()
596 
597     Output Parameter:
598 .   skip - PETSC_TRUE means do not use
599 
600     Level: advanced
601 
602     Notes:
603     This must be called after PetscViewerSetType()
604 
605 .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetDescriptor(), PetscViewerBinarySkipInfo(),
606           PetscViewerBinarySetSkipOptions()
607 @*/
PetscViewerBinaryGetSkipOptions(PetscViewer viewer,PetscBool * skip)608 PetscErrorCode PetscViewerBinaryGetSkipOptions(PetscViewer viewer,PetscBool *skip)
609 {
610   PetscErrorCode ierr;
611 
612   PetscFunctionBegin;
613   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
614   PetscValidBoolPointer(skip,2);
615   ierr = PetscUseMethod(viewer,"PetscViewerBinaryGetSkipOptions_C",(PetscViewer,PetscBool*),(viewer,skip));CHKERRQ(ierr);
616   PetscFunctionReturn(0);
617 }
618 
PetscViewerBinaryGetSkipOptions_Binary(PetscViewer viewer,PetscBool * skip)619 static PetscErrorCode PetscViewerBinaryGetSkipOptions_Binary(PetscViewer viewer,PetscBool *skip)
620 {
621   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
622 
623   PetscFunctionBegin;
624   *skip = vbinary->skipoptions;
625   PetscFunctionReturn(0);
626 }
627 
628 /*@
629     PetscViewerBinarySetSkipHeader - do not write a header with size information on output, just raw data
630 
631     Not Collective
632 
633     Input Parameters:
634 +   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()
635 -   skip - PETSC_TRUE means do not write header
636 
637     Options Database Key:
638 .   -viewer_binary_skip_header
639 
640     Level: advanced
641 
642     Notes:
643     This must be called after PetscViewerSetType()
644 
645            Can ONLY be called on a binary viewer
646 
647 .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetDescriptor(), PetscViewerBinarySkipInfo(),
648           PetscViewerBinaryGetSkipHeader()
649 @*/
PetscViewerBinarySetSkipHeader(PetscViewer viewer,PetscBool skip)650 PetscErrorCode PetscViewerBinarySetSkipHeader(PetscViewer viewer,PetscBool skip)
651 {
652   PetscErrorCode ierr;
653 
654   PetscFunctionBegin;
655   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
656   PetscValidLogicalCollectiveBool(viewer,skip,2);
657   ierr = PetscTryMethod(viewer,"PetscViewerBinarySetSkipHeader_C",(PetscViewer,PetscBool),(viewer,skip));CHKERRQ(ierr);
658   PetscFunctionReturn(0);
659 }
660 
PetscViewerBinarySetSkipHeader_Binary(PetscViewer viewer,PetscBool skip)661 static PetscErrorCode PetscViewerBinarySetSkipHeader_Binary(PetscViewer viewer,PetscBool skip)
662 {
663   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
664 
665   PetscFunctionBegin;
666   vbinary->skipheader = skip;
667   PetscFunctionReturn(0);
668 }
669 
670 /*@
671     PetscViewerBinaryGetSkipHeader - checks whether to write a header with size information on output, or just raw data
672 
673     Not Collective
674 
675     Input Parameter:
676 .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()
677 
678     Output Parameter:
679 .   skip - PETSC_TRUE means do not write header
680 
681     Level: advanced
682 
683     Notes:
684     This must be called after PetscViewerSetType()
685 
686             Returns false for PETSCSOCKETVIEWER, you cannot skip the header for it.
687 
688 .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetDescriptor(), PetscViewerBinarySkipInfo(),
689           PetscViewerBinarySetSkipHeader()
690 @*/
PetscViewerBinaryGetSkipHeader(PetscViewer viewer,PetscBool * skip)691 PetscErrorCode PetscViewerBinaryGetSkipHeader(PetscViewer viewer,PetscBool  *skip)
692 {
693   PetscErrorCode ierr;
694 
695   PetscFunctionBegin;
696   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
697   PetscValidBoolPointer(skip,2);
698   ierr = PetscUseMethod(viewer,"PetscViewerBinaryGetSkipHeader_C",(PetscViewer,PetscBool*),(viewer,skip));CHKERRQ(ierr);
699   PetscFunctionReturn(0);
700 }
701 
PetscViewerBinaryGetSkipHeader_Binary(PetscViewer viewer,PetscBool * skip)702 static PetscErrorCode PetscViewerBinaryGetSkipHeader_Binary(PetscViewer viewer,PetscBool  *skip)
703 {
704   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
705 
706   PetscFunctionBegin;
707   *skip = vbinary->skipheader;
708   PetscFunctionReturn(0);
709 }
710 
711 /*@C
712     PetscViewerBinaryGetInfoPointer - Extracts the file pointer for the ASCII
713           info file associated with a binary file.
714 
715     Not Collective
716 
717     Input Parameter:
718 .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()
719 
720     Output Parameter:
721 .   file - file pointer  Always returns NULL if not a binary viewer
722 
723     Level: advanced
724 
725     Notes:
726       For writable binary PetscViewers, the descriptor will only be valid for the
727     first processor in the communicator that shares the PetscViewer.
728 
729     Fortran Note:
730     This routine is not supported in Fortran.
731 
732 .seealso: PetscViewerBinaryOpen(),PetscViewerBinaryGetDescriptor()
733 @*/
PetscViewerBinaryGetInfoPointer(PetscViewer viewer,FILE ** file)734 PetscErrorCode PetscViewerBinaryGetInfoPointer(PetscViewer viewer,FILE **file)
735 {
736   PetscErrorCode ierr;
737 
738   PetscFunctionBegin;
739   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
740   PetscValidPointer(file,2);
741   *file = NULL;
742   ierr = PetscTryMethod(viewer,"PetscViewerBinaryGetInfoPointer_C",(PetscViewer,FILE **),(viewer,file));CHKERRQ(ierr);
743   PetscFunctionReturn(0);
744 }
745 
PetscViewerBinaryGetInfoPointer_Binary(PetscViewer viewer,FILE ** file)746 static PetscErrorCode PetscViewerBinaryGetInfoPointer_Binary(PetscViewer viewer,FILE **file)
747 {
748   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
749   PetscErrorCode     ierr;
750 
751   PetscFunctionBegin;
752   ierr = PetscViewerSetUp(viewer);CHKERRQ(ierr);
753   *file = vbinary->fdes_info;
754   if (viewer->format == PETSC_VIEWER_BINARY_MATLAB && !vbinary->matlabheaderwritten) {
755     if (vbinary->fdes_info) {
756       FILE *info = vbinary->fdes_info;
757       ierr = PetscFPrintf(PETSC_COMM_SELF,info,"#--- begin code written by PetscViewerBinary for MATLAB format ---#\n");CHKERRQ(ierr);
758       ierr = PetscFPrintf(PETSC_COMM_SELF,info,"#$$ Set.filename = '%s';\n",vbinary->filename);CHKERRQ(ierr);
759       ierr = PetscFPrintf(PETSC_COMM_SELF,info,"#$$ fd = PetscOpenFile(Set.filename);\n");CHKERRQ(ierr);
760       ierr = PetscFPrintf(PETSC_COMM_SELF,info,"#--- end code written by PetscViewerBinary for MATLAB format ---#\n\n");CHKERRQ(ierr);
761     }
762     vbinary->matlabheaderwritten = PETSC_TRUE;
763   }
764   PetscFunctionReturn(0);
765 }
766 
767 
768 #if defined(PETSC_HAVE_MPIIO)
PetscViewerFileClose_BinaryMPIIO(PetscViewer v)769 static PetscErrorCode PetscViewerFileClose_BinaryMPIIO(PetscViewer v)
770 {
771   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)v->data;
772   PetscErrorCode     ierr;
773 
774   PetscFunctionBegin;
775   if (vbinary->mfdes != MPI_FILE_NULL) {
776     ierr = MPI_File_close(&vbinary->mfdes);CHKERRQ(ierr);
777   }
778   if (vbinary->mfsub != MPI_FILE_NULL) {
779     ierr = MPI_File_close(&vbinary->mfsub);CHKERRQ(ierr);
780   }
781   vbinary->moff = 0;
782   PetscFunctionReturn(0);
783 }
784 #endif
785 
PetscViewerFileClose_BinarySTDIO(PetscViewer v)786 static PetscErrorCode PetscViewerFileClose_BinarySTDIO(PetscViewer v)
787 {
788   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)v->data;
789   PetscErrorCode     ierr;
790 
791   PetscFunctionBegin;
792   if (vbinary->fdes != -1) {
793     ierr = PetscBinaryClose(vbinary->fdes);CHKERRQ(ierr);
794     vbinary->fdes = -1;
795     if (vbinary->storecompressed) {
796       char cmd[8+PETSC_MAX_PATH_LEN],out[64+PETSC_MAX_PATH_LEN] = "";
797       const char *gzfilename = vbinary->ogzfilename ? vbinary->ogzfilename : vbinary->filename;
798       /* compress the file */
799       ierr = PetscStrncpy(cmd,"gzip -f ",sizeof(cmd));CHKERRQ(ierr);
800       ierr = PetscStrlcat(cmd,gzfilename,sizeof(cmd));CHKERRQ(ierr);
801 #if defined(PETSC_HAVE_POPEN)
802       {
803         FILE *fp;
804         ierr = PetscPOpen(PETSC_COMM_SELF,NULL,cmd,"r",&fp);CHKERRQ(ierr);
805         if (fgets(out,(int)(sizeof(out)-1),fp)) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error from command %s\n%s",cmd,out);
806         ierr = PetscPClose(PETSC_COMM_SELF,fp);CHKERRQ(ierr);
807       }
808 #endif
809     }
810   }
811   ierr = PetscFree(vbinary->ogzfilename);CHKERRQ(ierr);
812   PetscFunctionReturn(0);
813 }
814 
PetscViewerFileClose_BinaryInfo(PetscViewer v)815 static PetscErrorCode PetscViewerFileClose_BinaryInfo(PetscViewer v)
816 {
817   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)v->data;
818   PetscErrorCode     ierr;
819 
820   PetscFunctionBegin;
821   if (v->format == PETSC_VIEWER_BINARY_MATLAB && vbinary->matlabheaderwritten) {
822     if (vbinary->fdes_info) {
823       FILE *info = vbinary->fdes_info;
824       ierr = PetscFPrintf(PETSC_COMM_SELF,info,"#--- begin code written by PetscViewerBinary for MATLAB format ---#\n");CHKERRQ(ierr);
825       ierr = PetscFPrintf(PETSC_COMM_SELF,info,"#$$ close(fd);\n");CHKERRQ(ierr);
826       ierr = PetscFPrintf(PETSC_COMM_SELF,info,"#--- end code written by PetscViewerBinary for MATLAB format ---#\n\n");CHKERRQ(ierr);
827     }
828   }
829   if (vbinary->fdes_info) {
830     FILE *info = vbinary->fdes_info;
831     vbinary->fdes_info = NULL;
832     if (fclose(info)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fclose() failed on file");
833   }
834   PetscFunctionReturn(0);
835 }
836 
PetscViewerFileClose_Binary(PetscViewer v)837 static PetscErrorCode PetscViewerFileClose_Binary(PetscViewer v)
838 {
839   PetscErrorCode     ierr;
840 
841   PetscFunctionBegin;
842 #if defined(PETSC_HAVE_MPIIO)
843   ierr = PetscViewerFileClose_BinaryMPIIO(v);CHKERRQ(ierr);
844 #endif
845   ierr = PetscViewerFileClose_BinarySTDIO(v);CHKERRQ(ierr);
846   ierr = PetscViewerFileClose_BinaryInfo(v);CHKERRQ(ierr);
847   PetscFunctionReturn(0);
848 }
849 
PetscViewerDestroy_Binary(PetscViewer v)850 static PetscErrorCode PetscViewerDestroy_Binary(PetscViewer v)
851 {
852   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)v->data;
853   PetscErrorCode     ierr;
854 
855   PetscFunctionBegin;
856   ierr = PetscViewerFileClose_Binary(v);CHKERRQ(ierr);
857   ierr = PetscFree(vbinary->filename);CHKERRQ(ierr);
858   ierr = PetscFree(vbinary);CHKERRQ(ierr);
859 
860   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetFlowControl_C",NULL);CHKERRQ(ierr);
861   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetFlowControl_C",NULL);CHKERRQ(ierr);
862   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetSkipHeader_C",NULL);CHKERRQ(ierr);
863   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetSkipHeader_C",NULL);CHKERRQ(ierr);
864   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetSkipOptions_C",NULL);CHKERRQ(ierr);
865   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetSkipOptions_C",NULL);CHKERRQ(ierr);
866   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetSkipInfo_C",NULL);CHKERRQ(ierr);
867   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetSkipInfo_C",NULL);CHKERRQ(ierr);
868   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetInfoPointer_C",NULL);CHKERRQ(ierr);
869   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileGetName_C",NULL);CHKERRQ(ierr);
870   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileSetName_C",NULL);CHKERRQ(ierr);
871   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileGetMode_C",NULL);CHKERRQ(ierr);
872   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileSetMode_C",NULL);CHKERRQ(ierr);
873 #if defined(PETSC_HAVE_MPIIO)
874   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetUseMPIIO_C",NULL);CHKERRQ(ierr);
875   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetUseMPIIO_C",NULL);CHKERRQ(ierr);
876 #endif
877   PetscFunctionReturn(0);
878 }
879 
880 /*@C
881    PetscViewerBinaryOpen - Opens a file for binary input/output.
882 
883    Collective
884 
885    Input Parameters:
886 +  comm - MPI communicator
887 .  name - name of file
888 -  mode - open mode of file
889 $    FILE_MODE_WRITE - create new file for binary output
890 $    FILE_MODE_READ - open existing file for binary input
891 $    FILE_MODE_APPEND - open existing file for binary output
892 
893    Output Parameter:
894 .  viewer - PetscViewer for binary input/output to use with the specified file
895 
896     Options Database Keys:
897 +    -viewer_binary_filename <name> -
898 .    -viewer_binary_skip_info -
899 .    -viewer_binary_skip_options -
900 .    -viewer_binary_skip_header -
901 -    -viewer_binary_mpiio -
902 
903    Level: beginner
904 
905    Note:
906    This PetscViewer should be destroyed with PetscViewerDestroy().
907 
908     For reading files, the filename may begin with ftp:// or http:// and/or
909     end with .gz; in this case file is brought over and uncompressed.
910 
911     For creating files, if the file name ends with .gz it is automatically
912     compressed when closed.
913 
914 .seealso: PetscViewerASCIIOpen(), PetscViewerPushFormat(), PetscViewerDestroy(),
915           VecView(), MatView(), VecLoad(), MatLoad(), PetscViewerBinaryGetDescriptor(),
916           PetscViewerBinaryGetInfoPointer(), PetscFileMode, PetscViewer, PetscViewerBinaryRead(), PetscViewerBinarySetUseMPIIO(),
917           PetscViewerBinaryGetUseMPIIO(), PetscViewerBinaryGetMPIIOOffset()
918 @*/
PetscViewerBinaryOpen(MPI_Comm comm,const char name[],PetscFileMode mode,PetscViewer * viewer)919 PetscErrorCode PetscViewerBinaryOpen(MPI_Comm comm,const char name[],PetscFileMode mode,PetscViewer *viewer)
920 {
921   PetscErrorCode ierr;
922 
923   PetscFunctionBegin;
924   ierr = PetscViewerCreate(comm,viewer);CHKERRQ(ierr);
925   ierr = PetscViewerSetType(*viewer,PETSCVIEWERBINARY);CHKERRQ(ierr);
926   ierr = PetscViewerFileSetMode(*viewer,mode);CHKERRQ(ierr);
927   ierr = PetscViewerFileSetName(*viewer,name);CHKERRQ(ierr);
928   ierr = PetscViewerSetFromOptions(*viewer);CHKERRQ(ierr);
929   PetscFunctionReturn(0);
930 }
931 
932 #if defined(PETSC_HAVE_MPIIO)
PetscViewerBinaryWriteReadMPIIO(PetscViewer viewer,void * data,PetscInt num,PetscInt * count,PetscDataType dtype,PetscBool write)933 static PetscErrorCode PetscViewerBinaryWriteReadMPIIO(PetscViewer viewer,void *data,PetscInt num,PetscInt *count,PetscDataType dtype,PetscBool write)
934 {
935   MPI_Comm           comm = PetscObjectComm((PetscObject)viewer);
936   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
937   MPI_File           mfdes = vbinary->mfdes;
938   PetscErrorCode     ierr;
939   MPI_Datatype       mdtype;
940   PetscMPIInt        rank,cnt;
941   MPI_Status         status;
942   MPI_Aint           ul,dsize;
943 
944   PetscFunctionBegin;
945   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
946   ierr = PetscMPIIntCast(num,&cnt);CHKERRQ(ierr);
947   ierr = PetscDataTypeToMPIDataType(dtype,&mdtype);CHKERRQ(ierr);
948   if (write) {
949     if (!rank) {
950       ierr = MPIU_File_write_at(mfdes,vbinary->moff,data,cnt,mdtype,&status);CHKERRQ(ierr);
951     }
952   } else {
953     if (!rank) {
954       ierr = MPIU_File_read_at(mfdes,vbinary->moff,data,cnt,mdtype,&status);CHKERRQ(ierr);
955       if (cnt > 0) {ierr = MPI_Get_count(&status,mdtype,&cnt);CHKERRQ(ierr);}
956     }
957     ierr = MPI_Bcast(&cnt,1,MPI_INT,0,comm);CHKERRQ(ierr);
958     ierr = MPI_Bcast(data,cnt,mdtype,0,comm);CHKERRQ(ierr);
959   }
960   ierr = MPI_Type_get_extent(mdtype,&ul,&dsize);CHKERRQ(ierr);
961   vbinary->moff += dsize*cnt;
962   if (count) *count = cnt;
963   PetscFunctionReturn(0);
964 }
965 #endif
966 
967 /*@C
968    PetscViewerBinaryRead - Reads from a binary file, all processors get the same result
969 
970    Collective
971 
972    Input Parameters:
973 +  viewer - the binary viewer
974 .  data - location of the data to be written
975 .  num - number of items of data to read
976 -  dtype - type of data to read
977 
978    Output Parameters:
979 .  count - number of items of data actually read, or NULL.
980 
981    Level: beginner
982 
983 .seealso: PetscViewerASCIIOpen(), PetscViewerPushFormat(), PetscViewerDestroy(),
984           VecView(), MatView(), VecLoad(), MatLoad(), PetscViewerBinaryGetDescriptor(),
985           PetscViewerBinaryGetInfoPointer(), PetscFileMode, PetscViewer, PetscViewerBinaryRead()
986 @*/
PetscViewerBinaryRead(PetscViewer viewer,void * data,PetscInt num,PetscInt * count,PetscDataType dtype)987 PetscErrorCode PetscViewerBinaryRead(PetscViewer viewer,void *data,PetscInt num,PetscInt *count,PetscDataType dtype)
988 {
989   PetscErrorCode     ierr;
990   PetscViewer_Binary *vbinary;
991 
992   PetscFunctionBegin;
993   PetscValidHeaderSpecificType(viewer,PETSC_VIEWER_CLASSID,1,PETSCVIEWERBINARY);
994   PetscValidLogicalCollectiveInt(viewer,num,3);
995   ierr = PetscViewerSetUp(viewer);CHKERRQ(ierr);
996   vbinary = (PetscViewer_Binary*)viewer->data;
997 #if defined(PETSC_HAVE_MPIIO)
998   if (vbinary->usempiio) {
999     ierr = PetscViewerBinaryWriteReadMPIIO(viewer,data,num,count,dtype,PETSC_FALSE);CHKERRQ(ierr);
1000   } else {
1001 #endif
1002     ierr = PetscBinarySynchronizedRead(PetscObjectComm((PetscObject)viewer),vbinary->fdes,data,num,count,dtype);CHKERRQ(ierr);
1003 #if defined(PETSC_HAVE_MPIIO)
1004   }
1005 #endif
1006   PetscFunctionReturn(0);
1007 }
1008 
1009 /*@C
1010    PetscViewerBinaryWrite - writes to a binary file, only from the first process
1011 
1012    Collective
1013 
1014    Input Parameters:
1015 +  viewer - the binary viewer
1016 .  data - location of data
1017 .  count - number of items of data to write
1018 -  dtype - type of data to write
1019 
1020    Level: beginner
1021 
1022 .seealso: PetscViewerASCIIOpen(), PetscViewerPushFormat(), PetscViewerDestroy(),
1023           VecView(), MatView(), VecLoad(), MatLoad(), PetscViewerBinaryGetDescriptor(), PetscDataType
1024           PetscViewerBinaryGetInfoPointer(), PetscFileMode, PetscViewer, PetscViewerBinaryRead()
1025 @*/
PetscViewerBinaryWrite(PetscViewer viewer,const void * data,PetscInt count,PetscDataType dtype)1026 PetscErrorCode PetscViewerBinaryWrite(PetscViewer viewer,const void *data,PetscInt count,PetscDataType dtype)
1027 {
1028   PetscErrorCode     ierr;
1029   PetscViewer_Binary *vbinary;
1030 
1031   PetscFunctionBegin;
1032   PetscValidHeaderSpecificType(viewer,PETSC_VIEWER_CLASSID,1,PETSCVIEWERBINARY);
1033   PetscValidLogicalCollectiveInt(viewer,count,3);
1034   ierr = PetscViewerSetUp(viewer);CHKERRQ(ierr);
1035   vbinary = (PetscViewer_Binary*)viewer->data;
1036 #if defined(PETSC_HAVE_MPIIO)
1037   if (vbinary->usempiio) {
1038     ierr = PetscViewerBinaryWriteReadMPIIO(viewer,(void*)data,count,NULL,dtype,PETSC_TRUE);CHKERRQ(ierr);
1039   } else {
1040 #endif
1041     ierr = PetscBinarySynchronizedWrite(PetscObjectComm((PetscObject)viewer),vbinary->fdes,data,count,dtype);CHKERRQ(ierr);
1042 #if defined(PETSC_HAVE_MPIIO)
1043   }
1044 #endif
1045   PetscFunctionReturn(0);
1046 }
1047 
PetscViewerBinaryWriteReadAll(PetscViewer viewer,PetscBool write,void * data,PetscInt count,PetscInt start,PetscInt total,PetscDataType dtype)1048 static PetscErrorCode PetscViewerBinaryWriteReadAll(PetscViewer viewer,PetscBool write,void *data,PetscInt count,PetscInt start,PetscInt total,PetscDataType dtype)
1049 {
1050   MPI_Comm       comm = PetscObjectComm((PetscObject)viewer);
1051   PetscMPIInt    size,rank;
1052   MPI_Datatype   mdtype;
1053   MPI_Aint       lb,dsize;
1054   PetscBool      useMPIIO;
1055   PetscErrorCode ierr;
1056 
1057   PetscFunctionBegin;
1058   PetscValidHeaderSpecificType(viewer,PETSC_VIEWER_CLASSID,1,PETSCVIEWERBINARY);
1059   PetscValidLogicalCollectiveBool(viewer,((start>=0)||(start==PETSC_DETERMINE)),4);
1060   PetscValidLogicalCollectiveBool(viewer,((total>=0)||(total==PETSC_DETERMINE)),5);
1061   PetscValidLogicalCollectiveInt(viewer,total,5);
1062   ierr = PetscViewerSetUp(viewer);CHKERRQ(ierr);
1063 
1064   ierr = PetscDataTypeToMPIDataType(dtype,&mdtype);CHKERRQ(ierr);
1065   ierr = MPI_Type_get_extent(mdtype,&lb,&dsize);CHKERRQ(ierr);
1066   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
1067   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
1068 
1069   ierr = PetscViewerBinaryGetUseMPIIO(viewer,&useMPIIO);CHKERRQ(ierr);
1070 #if defined(PETSC_HAVE_MPIIO)
1071   if (useMPIIO) {
1072     MPI_File       mfdes;
1073     MPI_Offset     off;
1074     PetscMPIInt    cnt;
1075 
1076     if (start == PETSC_DETERMINE) {
1077       ierr = MPI_Scan(&count,&start,1,MPIU_INT,MPI_SUM,comm);CHKERRQ(ierr);
1078       start -= count;
1079     }
1080     if (total == PETSC_DETERMINE) {
1081       total = start + count;
1082       ierr = MPI_Bcast(&total,1,MPIU_INT,size-1,comm);CHKERRQ(ierr);
1083     }
1084     ierr = PetscMPIIntCast(count,&cnt);CHKERRQ(ierr);
1085     ierr = PetscViewerBinaryGetMPIIODescriptor(viewer,&mfdes);CHKERRQ(ierr);
1086     ierr = PetscViewerBinaryGetMPIIOOffset(viewer,&off);CHKERRQ(ierr);
1087     off += (MPI_Offset)(start*dsize);
1088     if (write) {
1089       ierr = MPIU_File_write_at_all(mfdes,off,data,cnt,mdtype,MPI_STATUS_IGNORE);CHKERRQ(ierr);
1090     } else {
1091       ierr = MPIU_File_read_at_all(mfdes,off,data,cnt,mdtype,MPI_STATUS_IGNORE);CHKERRQ(ierr);
1092     }
1093     off  = (MPI_Offset)(total*dsize);
1094     ierr = PetscViewerBinaryAddMPIIOOffset(viewer,off);CHKERRQ(ierr);
1095     PetscFunctionReturn(0);
1096   }
1097 #endif
1098   {
1099     int         fdes;
1100     char        *workbuf = NULL;
1101     PetscInt    maxcount=0,message_count,flowcontrolcount;
1102     PetscMPIInt tag,cnt,maxcnt,scnt=0,rcnt=0,j;
1103     MPI_Status  status;
1104 
1105     ierr = PetscCommGetNewTag(comm,&tag);CHKERRQ(ierr);
1106     ierr = MPI_Reduce(&count,&maxcount,1,MPIU_INT,MPI_MAX,0,comm);CHKERRQ(ierr);
1107     ierr = PetscMPIIntCast(maxcount,&maxcnt);CHKERRQ(ierr);
1108     ierr = PetscMPIIntCast(count,&cnt);CHKERRQ(ierr);
1109 
1110     ierr = PetscViewerBinaryGetDescriptor(viewer,&fdes);CHKERRQ(ierr);
1111     ierr = PetscViewerFlowControlStart(viewer,&message_count,&flowcontrolcount);CHKERRQ(ierr);
1112     if (!rank) {
1113       ierr = PetscMalloc(maxcnt*dsize,&workbuf);CHKERRQ(ierr);
1114       if (write) {
1115         ierr = PetscBinaryWrite(fdes,data,cnt,dtype);CHKERRQ(ierr);
1116       } else {
1117         ierr = PetscBinaryRead(fdes,data,cnt,NULL,dtype);CHKERRQ(ierr);
1118       }
1119       for (j=1; j<size; j++) {
1120         ierr = PetscViewerFlowControlStepMaster(viewer,j,&message_count,flowcontrolcount);CHKERRQ(ierr);
1121         if (write) {
1122           ierr = MPI_Recv(workbuf,maxcnt,mdtype,j,tag,comm,&status);CHKERRQ(ierr);
1123           ierr = MPI_Get_count(&status,mdtype,&rcnt);CHKERRQ(ierr);
1124           ierr = PetscBinaryWrite(fdes,workbuf,rcnt,dtype);CHKERRQ(ierr);
1125         } else {
1126           ierr = MPI_Recv(&scnt,1,MPI_INT,j,tag,comm,MPI_STATUS_IGNORE);CHKERRQ(ierr);
1127           ierr = PetscBinaryRead(fdes,workbuf,scnt,NULL,dtype);CHKERRQ(ierr);
1128           ierr = MPI_Send(workbuf,scnt,mdtype,j,tag,comm);CHKERRQ(ierr);
1129         }
1130       }
1131       ierr = PetscFree(workbuf);CHKERRQ(ierr);
1132       ierr = PetscViewerFlowControlEndMaster(viewer,&message_count);CHKERRQ(ierr);
1133     } else {
1134       ierr = PetscViewerFlowControlStepWorker(viewer,rank,&message_count);CHKERRQ(ierr);
1135       if (write) {
1136         ierr = MPI_Send(data,cnt,mdtype,0,tag,comm);CHKERRQ(ierr);
1137       } else {
1138         ierr = MPI_Send(&cnt,1,MPI_INT,0,tag,comm);CHKERRQ(ierr);
1139         ierr = MPI_Recv(data,cnt,mdtype,0,tag,comm,MPI_STATUS_IGNORE);CHKERRQ(ierr);
1140       }
1141       ierr = PetscViewerFlowControlEndWorker(viewer,&message_count);CHKERRQ(ierr);
1142     }
1143   }
1144   PetscFunctionReturn(0);
1145 }
1146 
1147 /*@C
1148    PetscViewerBinaryReadAll - reads from a binary file from all processes
1149 
1150    Collective
1151 
1152    Input Parameters:
1153 +  viewer - the binary viewer
1154 .  data - location of data
1155 .  count - local number of items of data to read
1156 .  start - local start, can be PETSC_DETERMINE
1157 .  total - global number of items of data to read, can be PETSC_DETERMINE
1158 -  dtype - type of data to read
1159 
1160    Level: advanced
1161 
1162 .seealso: PetscViewerBinaryOpen(), PetscViewerBinarySetUseMPIIO(), PetscViewerBinaryRead(), PetscViewerBinaryWriteAll()
1163 @*/
PetscViewerBinaryReadAll(PetscViewer viewer,void * data,PetscInt count,PetscInt start,PetscInt total,PetscDataType dtype)1164 PetscErrorCode PetscViewerBinaryReadAll(PetscViewer viewer,void *data,PetscInt count,PetscInt start,PetscInt total,PetscDataType dtype)
1165 {
1166   PetscErrorCode ierr;
1167   PetscFunctionBegin;
1168   ierr = PetscViewerBinaryWriteReadAll(viewer,PETSC_FALSE,data,count,start,total,dtype);CHKERRQ(ierr);
1169   PetscFunctionReturn(0);
1170 }
1171 
1172 /*@C
1173    PetscViewerBinaryWriteAll - writes to a binary file from all processes
1174 
1175    Collective
1176 
1177    Input Parameters:
1178 +  viewer - the binary viewer
1179 .  data - location of data
1180 .  count - local number of items of data to write
1181 .  start - local start, can be PETSC_DETERMINE
1182 .  total - global number of items of data to write, can be PETSC_DETERMINE
1183 -  dtype - type of data to write
1184 
1185    Level: advanced
1186 
1187 .seealso: PetscViewerBinaryOpen(), PetscViewerBinarySetUseMPIIO(), PetscViewerBinaryWriteAll(), PetscViewerBinaryReadAll()
1188 @*/
PetscViewerBinaryWriteAll(PetscViewer viewer,const void * data,PetscInt count,PetscInt start,PetscInt total,PetscDataType dtype)1189 PetscErrorCode PetscViewerBinaryWriteAll(PetscViewer viewer,const void *data,PetscInt count,PetscInt start,PetscInt total,PetscDataType dtype)
1190 {
1191   PetscErrorCode ierr;
1192   PetscFunctionBegin;
1193   ierr = PetscViewerBinaryWriteReadAll(viewer,PETSC_TRUE,(void*)data,count,start,total,dtype);CHKERRQ(ierr);
1194   PetscFunctionReturn(0);
1195 }
1196 
1197 /*@C
1198    PetscViewerBinaryWriteStringArray - writes to a binary file, only from the first process an array of strings
1199 
1200    Collective
1201 
1202    Input Parameters:
1203 +  viewer - the binary viewer
1204 -  data - location of the array of strings
1205 
1206 
1207    Level: intermediate
1208 
1209     Notes:
1210     array of strings is null terminated
1211 
1212 .seealso: PetscViewerASCIIOpen(), PetscViewerPushFormat(), PetscViewerDestroy(),
1213           VecView(), MatView(), VecLoad(), MatLoad(), PetscViewerBinaryGetDescriptor(),
1214           PetscViewerBinaryGetInfoPointer(), PetscFileMode, PetscViewer, PetscViewerBinaryRead()
1215 @*/
PetscViewerBinaryWriteStringArray(PetscViewer viewer,const char * const * data)1216 PetscErrorCode PetscViewerBinaryWriteStringArray(PetscViewer viewer,const char * const *data)
1217 {
1218   PetscErrorCode ierr;
1219   PetscInt       i,n = 0,*sizes;
1220   size_t         len;
1221 
1222   PetscFunctionBegin;
1223   ierr = PetscViewerSetUp(viewer);CHKERRQ(ierr);
1224   /* count number of strings */
1225   while (data[n++]);
1226   n--;
1227   ierr = PetscMalloc1(n+1,&sizes);CHKERRQ(ierr);
1228   sizes[0] = n;
1229   for (i=0; i<n; i++) {
1230     ierr = PetscStrlen(data[i],&len);CHKERRQ(ierr);
1231     sizes[i+1] = (PetscInt)len + 1; /* size includes space for the null terminator */
1232   }
1233   ierr = PetscViewerBinaryWrite(viewer,sizes,n+1,PETSC_INT);CHKERRQ(ierr);
1234   for (i=0; i<n; i++) {
1235     ierr = PetscViewerBinaryWrite(viewer,(void*)data[i],sizes[i+1],PETSC_CHAR);CHKERRQ(ierr);
1236   }
1237   ierr = PetscFree(sizes);CHKERRQ(ierr);
1238   PetscFunctionReturn(0);
1239 }
1240 
1241 /*@C
1242    PetscViewerBinaryReadStringArray - reads a binary file an array of strings
1243 
1244    Collective
1245 
1246    Input Parameter:
1247 .  viewer - the binary viewer
1248 
1249    Output Parameter:
1250 .  data - location of the array of strings
1251 
1252    Level: intermediate
1253 
1254     Notes:
1255     array of strings is null terminated
1256 
1257 .seealso: PetscViewerASCIIOpen(), PetscViewerPushFormat(), PetscViewerDestroy(),
1258           VecView(), MatView(), VecLoad(), MatLoad(), PetscViewerBinaryGetDescriptor(),
1259           PetscViewerBinaryGetInfoPointer(), PetscFileMode, PetscViewer, PetscViewerBinaryRead()
1260 @*/
PetscViewerBinaryReadStringArray(PetscViewer viewer,char *** data)1261 PetscErrorCode PetscViewerBinaryReadStringArray(PetscViewer viewer,char ***data)
1262 {
1263   PetscErrorCode ierr;
1264   PetscInt       i,n,*sizes,N = 0;
1265 
1266   PetscFunctionBegin;
1267   ierr = PetscViewerSetUp(viewer);CHKERRQ(ierr);
1268   /* count number of strings */
1269   ierr = PetscViewerBinaryRead(viewer,&n,1,NULL,PETSC_INT);CHKERRQ(ierr);
1270   ierr = PetscMalloc1(n,&sizes);CHKERRQ(ierr);
1271   ierr = PetscViewerBinaryRead(viewer,sizes,n,NULL,PETSC_INT);CHKERRQ(ierr);
1272   for (i=0; i<n; i++) N += sizes[i];
1273   ierr = PetscMalloc((n+1)*sizeof(char*) + N*sizeof(char),data);CHKERRQ(ierr);
1274   (*data)[0] = (char*)((*data) + n + 1);
1275   for (i=1; i<n; i++) (*data)[i] = (*data)[i-1] + sizes[i-1];
1276   ierr = PetscViewerBinaryRead(viewer,(*data)[0],N,NULL,PETSC_CHAR);CHKERRQ(ierr);
1277   (*data)[n] = NULL;
1278   ierr = PetscFree(sizes);CHKERRQ(ierr);
1279   PetscFunctionReturn(0);
1280 }
1281 
1282 /*@C
1283      PetscViewerFileSetMode - Sets the open mode of file
1284 
1285     Logically Collective on PetscViewer
1286 
1287   Input Parameters:
1288 +  viewer - the PetscViewer; must be a a PETSCVIEWERBINARY, PETSCVIEWERMATLAB, PETSCVIEWERHDF5, or PETSCVIEWERASCII  PetscViewer
1289 -  mode - open mode of file
1290 $    FILE_MODE_WRITE - create new file for output
1291 $    FILE_MODE_READ - open existing file for input
1292 $    FILE_MODE_APPEND - open existing file for output
1293 
1294   Level: advanced
1295 
1296 .seealso: PetscViewerFileSetMode(), PetscViewerCreate(), PetscViewerSetType(), PetscViewerBinaryOpen()
1297 
1298 @*/
PetscViewerFileSetMode(PetscViewer viewer,PetscFileMode mode)1299 PetscErrorCode PetscViewerFileSetMode(PetscViewer viewer,PetscFileMode mode)
1300 {
1301   PetscErrorCode ierr;
1302 
1303   PetscFunctionBegin;
1304   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
1305   PetscValidLogicalCollectiveEnum(viewer,mode,2);
1306   ierr = PetscTryMethod(viewer,"PetscViewerFileSetMode_C",(PetscViewer,PetscFileMode),(viewer,mode));CHKERRQ(ierr);
1307   PetscFunctionReturn(0);
1308 }
1309 
PetscViewerFileSetMode_Binary(PetscViewer viewer,PetscFileMode mode)1310 static PetscErrorCode PetscViewerFileSetMode_Binary(PetscViewer viewer,PetscFileMode mode)
1311 {
1312   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
1313 
1314   PetscFunctionBegin;
1315   if (viewer->setupcalled && vbinary->filemode != mode) SETERRQ1(PetscObjectComm((PetscObject)viewer),PETSC_ERR_ORDER,"Cannot change mode to %s after setup",PetscFileModes[mode]);
1316   vbinary->filemode = mode;
1317   PetscFunctionReturn(0);
1318 }
1319 
1320 /*@C
1321      PetscViewerFileGetMode - Gets the open mode of file
1322 
1323     Not Collective
1324 
1325   Input Parameter:
1326 .  viewer - the PetscViewer; must be a PETSCVIEWERBINARY, PETSCVIEWERMATLAB, PETSCVIEWERHDF5, or PETSCVIEWERASCII  PetscViewer
1327 
1328   Output Parameter:
1329 .  mode - open mode of file
1330 $    FILE_MODE_WRITE - create new file for binary output
1331 $    FILE_MODE_READ - open existing file for binary input
1332 $    FILE_MODE_APPEND - open existing file for binary output
1333 
1334   Level: advanced
1335 
1336 .seealso: PetscViewerFileSetMode(), PetscViewerCreate(), PetscViewerSetType(), PetscViewerBinaryOpen()
1337 
1338 @*/
PetscViewerFileGetMode(PetscViewer viewer,PetscFileMode * mode)1339 PetscErrorCode PetscViewerFileGetMode(PetscViewer viewer,PetscFileMode *mode)
1340 {
1341   PetscErrorCode ierr;
1342 
1343   PetscFunctionBegin;
1344   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
1345   PetscValidPointer(mode,2);
1346   ierr = PetscUseMethod(viewer,"PetscViewerFileGetMode_C",(PetscViewer,PetscFileMode*),(viewer,mode));CHKERRQ(ierr);
1347   PetscFunctionReturn(0);
1348 }
1349 
PetscViewerFileGetMode_Binary(PetscViewer viewer,PetscFileMode * mode)1350 static PetscErrorCode PetscViewerFileGetMode_Binary(PetscViewer viewer,PetscFileMode *mode)
1351 {
1352   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
1353 
1354   PetscFunctionBegin;
1355   *mode = vbinary->filemode;
1356   PetscFunctionReturn(0);
1357 }
1358 
PetscViewerFileSetName_Binary(PetscViewer viewer,const char name[])1359 static PetscErrorCode PetscViewerFileSetName_Binary(PetscViewer viewer,const char name[])
1360 {
1361   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
1362   PetscErrorCode     ierr;
1363 
1364   PetscFunctionBegin;
1365   if (viewer->setupcalled && vbinary->filename) {
1366     /* gzip can be run after the file with the previous filename has been closed */
1367     ierr = PetscFree(vbinary->ogzfilename);CHKERRQ(ierr);
1368     ierr = PetscStrallocpy(vbinary->filename,&vbinary->ogzfilename);CHKERRQ(ierr);
1369   }
1370   ierr = PetscFree(vbinary->filename);CHKERRQ(ierr);
1371   ierr = PetscStrallocpy(name,&vbinary->filename);CHKERRQ(ierr);
1372   viewer->setupcalled = PETSC_FALSE;
1373   PetscFunctionReturn(0);
1374 }
1375 
PetscViewerFileGetName_Binary(PetscViewer viewer,const char ** name)1376 static PetscErrorCode PetscViewerFileGetName_Binary(PetscViewer viewer,const char **name)
1377 {
1378   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
1379 
1380   PetscFunctionBegin;
1381   *name = vbinary->filename;
1382   PetscFunctionReturn(0);
1383 }
1384 
1385 #if defined(PETSC_HAVE_MPIIO)
PetscViewerFileSetUp_BinaryMPIIO(PetscViewer viewer)1386 static PetscErrorCode PetscViewerFileSetUp_BinaryMPIIO(PetscViewer viewer)
1387 {
1388   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
1389   int                amode;
1390   PetscErrorCode     ierr;
1391 
1392   PetscFunctionBegin;
1393   vbinary->storecompressed = PETSC_FALSE;
1394 
1395   vbinary->moff = 0;
1396   switch (vbinary->filemode) {
1397   case FILE_MODE_READ:   amode = MPI_MODE_RDONLY; break;
1398   case FILE_MODE_WRITE:  amode = MPI_MODE_WRONLY | MPI_MODE_CREATE; break;
1399   case FILE_MODE_APPEND: amode = MPI_MODE_WRONLY | MPI_MODE_CREATE | MPI_MODE_APPEND; break;
1400   default: SETERRQ1(PetscObjectComm((PetscObject)viewer),PETSC_ERR_SUP,"Unsupported file mode %s",PetscFileModes[vbinary->filemode]);
1401   }
1402   ierr = MPI_File_open(PetscObjectComm((PetscObject)viewer),vbinary->filename,amode,MPI_INFO_NULL,&vbinary->mfdes);CHKERRQ(ierr);
1403   /*
1404       The MPI standard does not have MPI_MODE_TRUNCATE. We emulate this behavior by setting the file size to zero.
1405   */
1406   if (vbinary->filemode == FILE_MODE_WRITE) {ierr = MPI_File_set_size(vbinary->mfdes,0);CHKERRQ(ierr);}
1407   /*
1408       Initially, all processes view the file as a linear byte stream. Therefore, for files opened with MPI_MODE_APPEND,
1409       MPI_File_get_position[_shared](fh, &offset) returns the absolute byte position at the end of file.
1410       Otherwise, we would need to call MPI_File_get_byte_offset(fh, offset, &byte_offset) to convert
1411       the offset in etype units to an absolute byte position.
1412    */
1413   if (vbinary->filemode == FILE_MODE_APPEND) {ierr = MPI_File_get_position(vbinary->mfdes,&vbinary->moff);CHKERRQ(ierr);}
1414   PetscFunctionReturn(0);
1415 }
1416 #endif
1417 
PetscViewerFileSetUp_BinarySTDIO(PetscViewer viewer)1418 static PetscErrorCode PetscViewerFileSetUp_BinarySTDIO(PetscViewer viewer)
1419 {
1420   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
1421   const char         *fname;
1422   char               bname[PETSC_MAX_PATH_LEN],*gz;
1423   PetscBool          found;
1424   PetscMPIInt        rank;
1425   PetscErrorCode     ierr;
1426 
1427   PetscFunctionBegin;
1428   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)viewer),&rank);CHKERRQ(ierr);
1429 
1430   /* if file name ends in .gz strip that off and note user wants file compressed */
1431   vbinary->storecompressed = PETSC_FALSE;
1432   if (vbinary->filemode == FILE_MODE_WRITE) {
1433     ierr = PetscStrstr(vbinary->filename,".gz",&gz);CHKERRQ(ierr);
1434     if (gz && gz[3] == 0) {*gz = 0; vbinary->storecompressed = PETSC_TRUE;}
1435   }
1436 #if !defined(PETSC_HAVE_POPEN)
1437   if (vbinary->storecompressed) SETERRQ(PetscObjectComm((PetscObject)viewer),PETSC_ERR_SUP_SYS,"Cannot run gzip on this machine");
1438 #endif
1439 
1440 
1441   fname = vbinary->filename;
1442   if (vbinary->filemode == FILE_MODE_READ) { /* possibly get the file from remote site or compressed file */
1443     ierr  = PetscFileRetrieve(PetscObjectComm((PetscObject)viewer),fname,bname,PETSC_MAX_PATH_LEN,&found);CHKERRQ(ierr);
1444     if (!found) SETERRQ1(PetscObjectComm((PetscObject)viewer),PETSC_ERR_FILE_OPEN,"Cannot locate file: %s",fname);
1445     fname = bname;
1446   }
1447 
1448   vbinary->fdes = -1;
1449   if (!rank) { /* only first processor opens file*/
1450     PetscFileMode mode = vbinary->filemode;
1451     if (mode == FILE_MODE_APPEND) {
1452       /* check if asked to append to a non-existing file */
1453       ierr = PetscTestFile(fname,'\0',&found);CHKERRQ(ierr);
1454       if (!found) mode = FILE_MODE_WRITE;
1455     }
1456     ierr = PetscBinaryOpen(fname,mode,&vbinary->fdes);CHKERRQ(ierr);
1457   }
1458   PetscFunctionReturn(0);
1459 }
1460 
PetscViewerFileSetUp_BinaryInfo(PetscViewer viewer)1461 static PetscErrorCode PetscViewerFileSetUp_BinaryInfo(PetscViewer viewer)
1462 {
1463   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
1464   PetscMPIInt        rank;
1465   PetscBool          found;
1466   PetscErrorCode     ierr;
1467 
1468   PetscFunctionBegin;
1469   vbinary->fdes_info = NULL;
1470   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)viewer),&rank);CHKERRQ(ierr);
1471   if (!vbinary->skipinfo && (vbinary->filemode == FILE_MODE_READ || !rank)) {
1472     char infoname[PETSC_MAX_PATH_LEN],iname[PETSC_MAX_PATH_LEN],*gz;
1473 
1474     ierr = PetscStrncpy(infoname,vbinary->filename,sizeof(infoname));CHKERRQ(ierr);
1475     /* remove .gz if it ends file name */
1476     ierr = PetscStrstr(infoname,".gz",&gz);CHKERRQ(ierr);
1477     if (gz && gz[3] == 0) *gz = 0;
1478 
1479     ierr = PetscStrlcat(infoname,".info",sizeof(infoname));CHKERRQ(ierr);
1480     if (vbinary->filemode == FILE_MODE_READ) {
1481       ierr = PetscFixFilename(infoname,iname);CHKERRQ(ierr);
1482       ierr = PetscFileRetrieve(PetscObjectComm((PetscObject)viewer),iname,infoname,PETSC_MAX_PATH_LEN,&found);CHKERRQ(ierr);
1483       if (found) {ierr = PetscOptionsInsertFile(PetscObjectComm((PetscObject)viewer),((PetscObject)viewer)->options,infoname,PETSC_FALSE);CHKERRQ(ierr);}
1484     } else if (!rank) { /* write or append */
1485       const char *omode = (vbinary->filemode == FILE_MODE_APPEND) ? "a" : "w";
1486       vbinary->fdes_info = fopen(infoname,omode);
1487       if (!vbinary->fdes_info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open .info file %s for writing",infoname);
1488     }
1489   }
1490   PetscFunctionReturn(0);
1491 }
1492 
PetscViewerSetUp_Binary(PetscViewer viewer)1493 static PetscErrorCode PetscViewerSetUp_Binary(PetscViewer viewer)
1494 {
1495   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
1496   PetscBool          usempiio;
1497   PetscErrorCode     ierr;
1498 
1499   PetscFunctionBegin;
1500   if (!vbinary->setfromoptionscalled) {ierr = PetscViewerSetFromOptions(viewer);CHKERRQ(ierr);}
1501   if (!vbinary->filename) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call PetscViewerFileSetName()");
1502   if (vbinary->filemode == (PetscFileMode)-1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call PetscViewerFileSetMode()");
1503   ierr = PetscViewerFileClose_Binary(viewer);CHKERRQ(ierr);
1504 
1505   ierr = PetscViewerBinaryGetUseMPIIO(viewer,&usempiio);CHKERRQ(ierr);
1506   if (usempiio) {
1507 #if defined(PETSC_HAVE_MPIIO)
1508     ierr = PetscViewerFileSetUp_BinaryMPIIO(viewer);CHKERRQ(ierr);
1509 #endif
1510   } else {
1511     ierr = PetscViewerFileSetUp_BinarySTDIO(viewer);CHKERRQ(ierr);
1512   }
1513   ierr = PetscViewerFileSetUp_BinaryInfo(viewer);CHKERRQ(ierr);
1514 
1515   ierr = PetscLogObjectState((PetscObject)viewer,"File: %s",vbinary->filename);CHKERRQ(ierr);
1516   PetscFunctionReturn(0);
1517 }
1518 
PetscViewerView_Binary(PetscViewer v,PetscViewer viewer)1519 static PetscErrorCode PetscViewerView_Binary(PetscViewer v,PetscViewer viewer)
1520 {
1521   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)v->data;
1522   const char         *fname = vbinary->filename ? vbinary->filename : "not yet set";
1523   const char         *fmode = vbinary->filemode != (PetscFileMode) -1 ? PetscFileModes[vbinary->filemode] : "not yet set";
1524   PetscBool          usempiio;
1525   PetscErrorCode     ierr;
1526 
1527   PetscFunctionBegin;
1528   ierr = PetscViewerBinaryGetUseMPIIO(v,&usempiio);CHKERRQ(ierr);
1529   ierr = PetscViewerASCIIPrintf(viewer,"Filename: %s\n",fname);CHKERRQ(ierr);
1530   ierr = PetscViewerASCIIPrintf(viewer,"Mode: %s (%s)\n",fmode,usempiio ? "mpiio" : "stdio");CHKERRQ(ierr);
1531   PetscFunctionReturn(0);
1532 }
1533 
PetscViewerSetFromOptions_Binary(PetscOptionItems * PetscOptionsObject,PetscViewer viewer)1534 static PetscErrorCode PetscViewerSetFromOptions_Binary(PetscOptionItems *PetscOptionsObject,PetscViewer viewer)
1535 {
1536   PetscViewer_Binary *binary = (PetscViewer_Binary*)viewer->data;
1537   char               defaultname[PETSC_MAX_PATH_LEN];
1538   PetscBool          flg;
1539   PetscErrorCode     ierr;
1540 
1541   PetscFunctionBegin;
1542   if (viewer->setupcalled) PetscFunctionReturn(0);
1543   ierr = PetscOptionsHead(PetscOptionsObject,"Binary PetscViewer Options");CHKERRQ(ierr);
1544   ierr = PetscSNPrintf(defaultname,PETSC_MAX_PATH_LEN-1,"binaryoutput");CHKERRQ(ierr);
1545   ierr = PetscOptionsString("-viewer_binary_filename","Specify filename","PetscViewerFileSetName",defaultname,defaultname,sizeof(defaultname),&flg);CHKERRQ(ierr);
1546   if (flg) { ierr = PetscViewerFileSetName_Binary(viewer,defaultname);CHKERRQ(ierr); }
1547   ierr = PetscOptionsBool("-viewer_binary_skip_info","Skip writing/reading .info file","PetscViewerBinarySetSkipInfo",binary->skipinfo,&binary->skipinfo,NULL);CHKERRQ(ierr);
1548   ierr = PetscOptionsBool("-viewer_binary_skip_options","Skip parsing Vec/Mat load options","PetscViewerBinarySetSkipOptions",binary->skipoptions,&binary->skipoptions,NULL);CHKERRQ(ierr);
1549   ierr = PetscOptionsBool("-viewer_binary_skip_header","Skip writing/reading header information","PetscViewerBinarySetSkipHeader",binary->skipheader,&binary->skipheader,NULL);CHKERRQ(ierr);
1550 #if defined(PETSC_HAVE_MPIIO)
1551   ierr = PetscOptionsBool("-viewer_binary_mpiio","Use MPI-IO functionality to write/read binary file","PetscViewerBinarySetUseMPIIO",binary->usempiio,&binary->usempiio,NULL);CHKERRQ(ierr);
1552 #else
1553   ierr = PetscOptionsBool("-viewer_binary_mpiio","Use MPI-IO functionality to write/read binary file (NOT AVAILABLE)","PetscViewerBinarySetUseMPIIO",PETSC_FALSE,NULL,NULL);CHKERRQ(ierr);
1554 #endif
1555   ierr = PetscOptionsTail();CHKERRQ(ierr);
1556   binary->setfromoptionscalled = PETSC_TRUE;
1557   PetscFunctionReturn(0);
1558 }
1559 
1560 /*MC
1561    PETSCVIEWERBINARY - A viewer that saves to binary files
1562 
1563 
1564 .seealso:  PetscViewerBinaryOpen(), PETSC_VIEWER_STDOUT_(),PETSC_VIEWER_STDOUT_SELF, PETSC_VIEWER_STDOUT_WORLD, PetscViewerCreate(), PetscViewerASCIIOpen(),
1565            PetscViewerMatlabOpen(), VecView(), DMView(), PetscViewerMatlabPutArray(), PETSCVIEWERASCII, PETSCVIEWERMATLAB, PETSCVIEWERDRAW,
1566            PetscViewerFileSetName(), PetscViewerFileSetMode(), PetscViewerFormat, PetscViewerType, PetscViewerSetType(),
1567            PetscViewerBinaryGetUseMPIIO(), PetscViewerBinarySetUseMPIIO()
1568 
1569   Level: beginner
1570 
1571 M*/
1572 
PetscViewerCreate_Binary(PetscViewer v)1573 PETSC_EXTERN PetscErrorCode PetscViewerCreate_Binary(PetscViewer v)
1574 {
1575   PetscErrorCode     ierr;
1576   PetscViewer_Binary *vbinary;
1577 
1578   PetscFunctionBegin;
1579   ierr    = PetscNewLog(v,&vbinary);CHKERRQ(ierr);
1580   v->data = (void*)vbinary;
1581 
1582   v->ops->setfromoptions   = PetscViewerSetFromOptions_Binary;
1583   v->ops->destroy          = PetscViewerDestroy_Binary;
1584   v->ops->view             = PetscViewerView_Binary;
1585   v->ops->setup            = PetscViewerSetUp_Binary;
1586   v->ops->flush            = NULL; /* Should we support Flush() ? */
1587   v->ops->getsubviewer     = PetscViewerGetSubViewer_Binary;
1588   v->ops->restoresubviewer = PetscViewerRestoreSubViewer_Binary;
1589   v->ops->read             = PetscViewerBinaryRead;
1590 
1591   vbinary->fdes            = -1;
1592 #if defined(PETSC_HAVE_MPIIO)
1593   vbinary->usempiio        = PETSC_FALSE;
1594   vbinary->mfdes           = MPI_FILE_NULL;
1595   vbinary->mfsub           = MPI_FILE_NULL;
1596 #endif
1597   vbinary->filename        = NULL;
1598   vbinary->filemode        = (PetscFileMode)-1;
1599   vbinary->fdes_info       = NULL;
1600   vbinary->skipinfo        = PETSC_FALSE;
1601   vbinary->skipoptions     = PETSC_TRUE;
1602   vbinary->skipheader      = PETSC_FALSE;
1603   vbinary->storecompressed = PETSC_FALSE;
1604   vbinary->ogzfilename     = NULL;
1605   vbinary->flowcontrol     = 256; /* seems a good number for Cray XT-5 */
1606 
1607   vbinary->setfromoptionscalled = PETSC_FALSE;
1608 
1609   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetFlowControl_C",PetscViewerBinaryGetFlowControl_Binary);CHKERRQ(ierr);
1610   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetFlowControl_C",PetscViewerBinarySetFlowControl_Binary);CHKERRQ(ierr);
1611   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetSkipHeader_C",PetscViewerBinaryGetSkipHeader_Binary);CHKERRQ(ierr);
1612   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetSkipHeader_C",PetscViewerBinarySetSkipHeader_Binary);CHKERRQ(ierr);
1613   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetSkipOptions_C",PetscViewerBinaryGetSkipOptions_Binary);CHKERRQ(ierr);
1614   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetSkipOptions_C",PetscViewerBinarySetSkipOptions_Binary);CHKERRQ(ierr);
1615   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetSkipInfo_C",PetscViewerBinaryGetSkipInfo_Binary);CHKERRQ(ierr);
1616   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetSkipInfo_C",PetscViewerBinarySetSkipInfo_Binary);CHKERRQ(ierr);
1617   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetInfoPointer_C",PetscViewerBinaryGetInfoPointer_Binary);CHKERRQ(ierr);
1618   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileGetName_C",PetscViewerFileGetName_Binary);CHKERRQ(ierr);
1619   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileSetName_C",PetscViewerFileSetName_Binary);CHKERRQ(ierr);
1620   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileGetMode_C",PetscViewerFileGetMode_Binary);CHKERRQ(ierr);
1621   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileSetMode_C",PetscViewerFileSetMode_Binary);CHKERRQ(ierr);
1622 #if defined(PETSC_HAVE_MPIIO)
1623   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetUseMPIIO_C",PetscViewerBinaryGetUseMPIIO_Binary);CHKERRQ(ierr);
1624   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetUseMPIIO_C",PetscViewerBinarySetUseMPIIO_Binary);CHKERRQ(ierr);
1625 #endif
1626   PetscFunctionReturn(0);
1627 }
1628 
1629 /* ---------------------------------------------------------------------*/
1630 /*
1631     The variable Petsc_Viewer_Binary_keyval is used to indicate an MPI attribute that
1632   is attached to a communicator, in this case the attribute is a PetscViewer.
1633 */
1634 PetscMPIInt Petsc_Viewer_Binary_keyval = MPI_KEYVAL_INVALID;
1635 
1636 /*@C
1637      PETSC_VIEWER_BINARY_ - Creates a binary PetscViewer shared by all processors
1638                      in a communicator.
1639 
1640      Collective
1641 
1642      Input Parameter:
1643 .    comm - the MPI communicator to share the binary PetscViewer
1644 
1645      Level: intermediate
1646 
1647    Options Database Keys:
1648 +    -viewer_binary_filename <name>
1649 .    -viewer_binary_skip_info
1650 .    -viewer_binary_skip_options
1651 .    -viewer_binary_skip_header
1652 -    -viewer_binary_mpiio
1653 
1654    Environmental variables:
1655 -   PETSC_VIEWER_BINARY_FILENAME
1656 
1657      Notes:
1658      Unlike almost all other PETSc routines, PETSC_VIEWER_BINARY_ does not return
1659      an error code.  The binary PetscViewer is usually used in the form
1660 $       XXXView(XXX object,PETSC_VIEWER_BINARY_(comm));
1661 
1662 .seealso: PETSC_VIEWER_BINARY_WORLD, PETSC_VIEWER_BINARY_SELF, PetscViewerBinaryOpen(), PetscViewerCreate(),
1663           PetscViewerDestroy()
1664 @*/
PETSC_VIEWER_BINARY_(MPI_Comm comm)1665 PetscViewer PETSC_VIEWER_BINARY_(MPI_Comm comm)
1666 {
1667   PetscErrorCode ierr;
1668   PetscBool      flg;
1669   PetscViewer    viewer;
1670   char           fname[PETSC_MAX_PATH_LEN];
1671   MPI_Comm       ncomm;
1672 
1673   PetscFunctionBegin;
1674   ierr = PetscCommDuplicate(comm,&ncomm,NULL);if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);}
1675   if (Petsc_Viewer_Binary_keyval == MPI_KEYVAL_INVALID) {
1676     ierr = MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN,MPI_COMM_NULL_DELETE_FN,&Petsc_Viewer_Binary_keyval,NULL);
1677     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);}
1678   }
1679   ierr = MPI_Comm_get_attr(ncomm,Petsc_Viewer_Binary_keyval,(void**)&viewer,(int*)&flg);
1680   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);}
1681   if (!flg) { /* PetscViewer not yet created */
1682     ierr = PetscOptionsGetenv(ncomm,"PETSC_VIEWER_BINARY_FILENAME",fname,PETSC_MAX_PATH_LEN,&flg);
1683     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);}
1684     if (!flg) {
1685       ierr = PetscStrcpy(fname,"binaryoutput");
1686       if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);}
1687     }
1688     ierr = PetscViewerBinaryOpen(ncomm,fname,FILE_MODE_WRITE,&viewer);
1689     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);}
1690     ierr = PetscObjectRegisterDestroy((PetscObject)viewer);
1691     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);}
1692     ierr = MPI_Comm_set_attr(ncomm,Petsc_Viewer_Binary_keyval,(void*)viewer);
1693     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);}
1694   }
1695   ierr = PetscCommDestroy(&ncomm);
1696   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);}
1697   PetscFunctionReturn(viewer);
1698 }
1699