xref: /petsc/src/sys/classes/viewer/impls/hdf5/hdf5v.c (revision 972064b65a4dc64f53e590d2cefc17fe4e1ae983)
1 #include <petsc/private/viewerimpl.h>    /*I   "petscsys.h"   I*/
2 #include <petscviewerhdf5.h>    /*I   "petscviewerhdf5.h"   I*/
3 #if (H5_VERS_MAJOR * 10000 + H5_VERS_MINOR * 100 + H5_VERS_RELEASE < 10800)
4 #error "PETSc needs HDF5 version >= 1.8.0"
5 #endif
6 
7 static PetscErrorCode PetscViewerHDF5Traverse_Internal(PetscViewer, const char[], PetscBool, PetscBool*, H5O_type_t*);
8 static PetscErrorCode PetscViewerHDF5HasAttribute_Internal(PetscViewer, const char[], const char[], PetscBool*);
9 
10 typedef struct GroupList {
11   const char       *name;
12   struct GroupList *next;
13 } GroupList;
14 
15 typedef struct {
16   char          *filename;
17   PetscFileMode btype;
18   hid_t         file_id;
19   PetscInt      timestep;
20   GroupList     *groups;
21   PetscBool     basedimension2;  /* save vectors and DMDA vectors with a dimension of at least 2 even if the bs/dof is 1 */
22   PetscBool     spoutput;  /* write data in single precision even if PETSc is compiled with double precision PetscReal */
23   char          *mataij_iname;
24   char          *mataij_jname;
25   char          *mataij_aname;
26   char          *mataij_cname;
27   PetscBool     mataij_names_set;
28 } PetscViewer_HDF5;
29 
30 struct _n_HDF5ReadCtx {
31   hid_t file, group, dataset, dataspace, plist;
32   PetscInt timestep;
33   PetscBool complexVal, dim2, horizontal;
34 };
35 typedef struct _n_HDF5ReadCtx* HDF5ReadCtx;
36 
37 static PetscErrorCode PetscViewerHDF5GetAbsolutePath_Internal(PetscViewer viewer, const char objname[], char **fullpath)
38 {
39   const char *group;
40   char buf[PETSC_MAX_PATH_LEN]="";
41   PetscErrorCode ierr;
42 
43   PetscFunctionBegin;
44   ierr = PetscViewerHDF5GetGroup(viewer, &group);CHKERRQ(ierr);
45   ierr = PetscStrcat(buf, group);CHKERRQ(ierr);
46   ierr = PetscStrcat(buf, "/");CHKERRQ(ierr);
47   ierr = PetscStrcat(buf, objname);CHKERRQ(ierr);
48   ierr = PetscStrallocpy(buf, fullpath);CHKERRQ(ierr);
49   PetscFunctionReturn(0);
50 }
51 
52 static PetscErrorCode PetscViewerHDF5CheckNamedObject_Internal(PetscViewer viewer, PetscObject obj)
53 {
54   PetscBool has;
55   const char *group;
56   PetscErrorCode ierr;
57 
58   PetscFunctionBegin;
59   if (!obj->name) SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONG, "Object must be named");
60   ierr = PetscViewerHDF5HasObject(viewer, obj, &has);CHKERRQ(ierr);
61   if (!has) {
62     ierr = PetscViewerHDF5GetGroup(viewer, &group);CHKERRQ(ierr);
63     SETERRQ2(PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Object (dataset) %s not stored in group %s", obj->name, group);
64   }
65   PetscFunctionReturn(0);
66 }
67 
68 static PetscErrorCode PetscViewerSetFromOptions_HDF5(PetscOptionItems *PetscOptionsObject,PetscViewer v)
69 {
70   PetscErrorCode   ierr;
71   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*)v->data;
72 
73   PetscFunctionBegin;
74   ierr = PetscOptionsHead(PetscOptionsObject,"HDF5 PetscViewer Options");CHKERRQ(ierr);
75   ierr = PetscOptionsBool("-viewer_hdf5_base_dimension2","1d Vectors get 2 dimensions in HDF5","PetscViewerHDF5SetBaseDimension2",hdf5->basedimension2,&hdf5->basedimension2,NULL);CHKERRQ(ierr);
76   ierr = PetscOptionsBool("-viewer_hdf5_sp_output","Force data to be written in single precision","PetscViewerHDF5SetSPOutput",hdf5->spoutput,&hdf5->spoutput,NULL);CHKERRQ(ierr);
77   ierr = PetscOptionsTail();CHKERRQ(ierr);
78   PetscFunctionReturn(0);
79 }
80 
81 static PetscErrorCode PetscViewerFileClose_HDF5(PetscViewer viewer)
82 {
83   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*)viewer->data;
84   PetscErrorCode   ierr;
85 
86   PetscFunctionBegin;
87   ierr = PetscFree(hdf5->filename);CHKERRQ(ierr);
88   if (hdf5->file_id) PetscStackCallHDF5(H5Fclose,(hdf5->file_id));
89   PetscFunctionReturn(0);
90 }
91 
92 PetscErrorCode PetscViewerDestroy_HDF5(PetscViewer viewer)
93 {
94   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;
95   PetscErrorCode   ierr;
96 
97   PetscFunctionBegin;
98   ierr = PetscViewerFileClose_HDF5(viewer);CHKERRQ(ierr);
99   while (hdf5->groups) {
100     GroupList *tmp = hdf5->groups->next;
101 
102     ierr         = PetscFree(hdf5->groups->name);CHKERRQ(ierr);
103     ierr         = PetscFree(hdf5->groups);CHKERRQ(ierr);
104     hdf5->groups = tmp;
105   }
106   ierr = PetscFree(hdf5->mataij_iname);CHKERRQ(ierr);
107   ierr = PetscFree(hdf5->mataij_jname);CHKERRQ(ierr);
108   ierr = PetscFree(hdf5->mataij_aname);CHKERRQ(ierr);
109   ierr = PetscFree(hdf5->mataij_cname);CHKERRQ(ierr);
110   ierr = PetscFree(hdf5);CHKERRQ(ierr);
111   ierr = PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerFileSetName_C",NULL);CHKERRQ(ierr);
112   ierr = PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerFileGetName_C",NULL);CHKERRQ(ierr);
113   ierr = PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerFileSetMode_C",NULL);CHKERRQ(ierr);
114   ierr = PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerHDF5SetBaseDimension2_C",NULL);CHKERRQ(ierr);
115   ierr = PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerHDF5SetSPOutput_C",NULL);CHKERRQ(ierr);
116   ierr = PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerHDF5SetAIJNames_C",NULL);CHKERRQ(ierr);
117   ierr = PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerHDF5GetAIJNames_C",NULL);CHKERRQ(ierr);
118   PetscFunctionReturn(0);
119 }
120 
121 PetscErrorCode  PetscViewerFileSetMode_HDF5(PetscViewer viewer, PetscFileMode type)
122 {
123   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;
124 
125   PetscFunctionBegin;
126   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
127   hdf5->btype = type;
128   PetscFunctionReturn(0);
129 }
130 
131 PetscErrorCode  PetscViewerHDF5SetBaseDimension2_HDF5(PetscViewer viewer, PetscBool flg)
132 {
133   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;
134 
135   PetscFunctionBegin;
136   hdf5->basedimension2 = flg;
137   PetscFunctionReturn(0);
138 }
139 
140 /*@
141      PetscViewerHDF5SetBaseDimension2 - Vectors of 1 dimension (i.e. bs/dof is 1) will be saved in the HDF5 file with a
142        dimension of 2.
143 
144     Logically Collective on PetscViewer
145 
146   Input Parameters:
147 +  viewer - the PetscViewer; if it is not hdf5 then this command is ignored
148 -  flg - if PETSC_TRUE the vector will always have at least a dimension of 2 even if that first dimension is of size 1
149 
150   Options Database:
151 .  -viewer_hdf5_base_dimension2 - turns on (true) or off (false) using a dimension of 2 in the HDF5 file even if the bs/dof of the vector is 1
152 
153 
154   Notes:
155     Setting this option allegedly makes code that reads the HDF5 in easier since they do not have a "special case" of a bs/dof
156          of one when the dimension is lower. Others think the option is crazy.
157 
158   Level: intermediate
159 
160 .seealso: PetscViewerFileSetMode(), PetscViewerCreate(), PetscViewerSetType(), PetscViewerBinaryOpen()
161 
162 @*/
163 PetscErrorCode PetscViewerHDF5SetBaseDimension2(PetscViewer viewer,PetscBool flg)
164 {
165   PetscErrorCode ierr;
166 
167   PetscFunctionBegin;
168   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
169   ierr = PetscTryMethod(viewer,"PetscViewerHDF5SetBaseDimension2_C",(PetscViewer,PetscBool),(viewer,flg));CHKERRQ(ierr);
170   PetscFunctionReturn(0);
171 }
172 
173 /*@
174      PetscViewerHDF5GetBaseDimension2 - Vectors of 1 dimension (i.e. bs/dof is 1) will be saved in the HDF5 file with a
175        dimension of 2.
176 
177     Logically Collective on PetscViewer
178 
179   Input Parameter:
180 .  viewer - the PetscViewer, must be of type HDF5
181 
182   Output Parameter:
183 .  flg - if PETSC_TRUE the vector will always have at least a dimension of 2 even if that first dimension is of size 1
184 
185   Notes:
186     Setting this option allegedly makes code that reads the HDF5 in easier since they do not have a "special case" of a bs/dof
187          of one when the dimension is lower. Others think the option is crazy.
188 
189   Level: intermediate
190 
191 .seealso: PetscViewerFileSetMode(), PetscViewerCreate(), PetscViewerSetType(), PetscViewerBinaryOpen()
192 
193 @*/
194 PetscErrorCode PetscViewerHDF5GetBaseDimension2(PetscViewer viewer,PetscBool *flg)
195 {
196   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;
197 
198   PetscFunctionBegin;
199   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
200   *flg = hdf5->basedimension2;
201   PetscFunctionReturn(0);
202 }
203 
204 PetscErrorCode  PetscViewerHDF5SetSPOutput_HDF5(PetscViewer viewer, PetscBool flg)
205 {
206   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;
207 
208   PetscFunctionBegin;
209   hdf5->spoutput = flg;
210   PetscFunctionReturn(0);
211 }
212 
213 /*@
214      PetscViewerHDF5SetSPOutput - Data is written to disk in single precision even if PETSc is
215        compiled with double precision PetscReal.
216 
217     Logically Collective on PetscViewer
218 
219   Input Parameters:
220 +  viewer - the PetscViewer; if it is not hdf5 then this command is ignored
221 -  flg - if PETSC_TRUE the data will be written to disk with single precision
222 
223   Options Database:
224 .  -viewer_hdf5_sp_output - turns on (true) or off (false) output in single precision
225 
226 
227   Notes:
228     Setting this option does not make any difference if PETSc is compiled with single precision
229          in the first place. It does not affect reading datasets (HDF5 handle this internally).
230 
231   Level: intermediate
232 
233 .seealso: PetscViewerFileSetMode(), PetscViewerCreate(), PetscViewerSetType(), PetscViewerBinaryOpen(),
234           PetscReal
235 
236 @*/
237 PetscErrorCode PetscViewerHDF5SetSPOutput(PetscViewer viewer,PetscBool flg)
238 {
239   PetscErrorCode ierr;
240 
241   PetscFunctionBegin;
242   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
243   ierr = PetscTryMethod(viewer,"PetscViewerHDF5SetSPOutput_C",(PetscViewer,PetscBool),(viewer,flg));CHKERRQ(ierr);
244   PetscFunctionReturn(0);
245 }
246 
247 /*@
248      PetscViewerHDF5GetSPOutput - Data is written to disk in single precision even if PETSc is
249        compiled with double precision PetscReal.
250 
251     Logically Collective on PetscViewer
252 
253   Input Parameter:
254 .  viewer - the PetscViewer, must be of type HDF5
255 
256   Output Parameter:
257 .  flg - if PETSC_TRUE the data will be written to disk with single precision
258 
259   Notes:
260     Setting this option does not make any difference if PETSc is compiled with single precision
261          in the first place. It does not affect reading datasets (HDF5 handle this internally).
262 
263   Level: intermediate
264 
265 .seealso: PetscViewerFileSetMode(), PetscViewerCreate(), PetscViewerSetType(), PetscViewerBinaryOpen(),
266           PetscReal
267 
268 @*/
269 PetscErrorCode PetscViewerHDF5GetSPOutput(PetscViewer viewer,PetscBool *flg)
270 {
271   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;
272 
273   PetscFunctionBegin;
274   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
275   *flg = hdf5->spoutput;
276   PetscFunctionReturn(0);
277 }
278 
279 PetscErrorCode  PetscViewerFileSetName_HDF5(PetscViewer viewer, const char name[])
280 {
281   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;
282 #if defined(PETSC_HAVE_H5PSET_FAPL_MPIO)
283   MPI_Info          info = MPI_INFO_NULL;
284 #endif
285   hid_t             plist_id;
286   PetscErrorCode    ierr;
287 
288   PetscFunctionBegin;
289   if (hdf5->file_id) PetscStackCallHDF5(H5Fclose,(hdf5->file_id));
290   if (hdf5->filename) {ierr = PetscFree(hdf5->filename);CHKERRQ(ierr);}
291   ierr = PetscStrallocpy(name, &hdf5->filename);CHKERRQ(ierr);
292   /* Set up file access property list with parallel I/O access */
293   PetscStackCallHDF5Return(plist_id,H5Pcreate,(H5P_FILE_ACCESS));
294 #if defined(PETSC_HAVE_H5PSET_FAPL_MPIO)
295   PetscStackCallHDF5(H5Pset_fapl_mpio,(plist_id, PetscObjectComm((PetscObject)viewer), info));
296 #endif
297   /* Create or open the file collectively */
298   switch (hdf5->btype) {
299   case FILE_MODE_READ:
300     PetscStackCallHDF5Return(hdf5->file_id,H5Fopen,(name, H5F_ACC_RDONLY, plist_id));
301     break;
302   case FILE_MODE_APPEND:
303     PetscStackCallHDF5Return(hdf5->file_id,H5Fopen,(name, H5F_ACC_RDWR, plist_id));
304     break;
305   case FILE_MODE_WRITE:
306     PetscStackCallHDF5Return(hdf5->file_id,H5Fcreate,(name, H5F_ACC_TRUNC, H5P_DEFAULT, plist_id));
307     break;
308   default:
309     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER, "Must call PetscViewerFileSetMode() before PetscViewerFileSetName()");
310   }
311   if (hdf5->file_id < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB, "H5Fcreate failed for %s", name);
312   PetscStackCallHDF5(H5Pclose,(plist_id));
313   PetscFunctionReturn(0);
314 }
315 
316 static PetscErrorCode PetscViewerFileGetName_HDF5(PetscViewer viewer,const char **name)
317 {
318   PetscViewer_HDF5 *vhdf5 = (PetscViewer_HDF5*)viewer->data;
319 
320   PetscFunctionBegin;
321   *name = vhdf5->filename;
322   PetscFunctionReturn(0);
323 }
324 
325 PetscErrorCode  PetscViewerHDF5SetAIJNames_HDF5(PetscViewer viewer, const char iname[], const char jname[], const char aname[], const char cname[])
326 {
327   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;
328   PetscErrorCode ierr;
329 
330   PetscFunctionBegin;
331   ierr = PetscFree(hdf5->mataij_iname);CHKERRQ(ierr);
332   ierr = PetscFree(hdf5->mataij_jname);CHKERRQ(ierr);
333   ierr = PetscFree(hdf5->mataij_aname);CHKERRQ(ierr);
334   ierr = PetscFree(hdf5->mataij_cname);CHKERRQ(ierr);
335   ierr = PetscStrallocpy(iname,&hdf5->mataij_iname);CHKERRQ(ierr);
336   ierr = PetscStrallocpy(jname,&hdf5->mataij_jname);CHKERRQ(ierr);
337   ierr = PetscStrallocpy(aname,&hdf5->mataij_aname);CHKERRQ(ierr);
338   ierr = PetscStrallocpy(cname,&hdf5->mataij_cname);CHKERRQ(ierr);
339   hdf5->mataij_names_set = PETSC_TRUE;
340   PetscFunctionReturn(0);
341 }
342 
343 /*@C
344   PetscViewerHDF5SetAIJNames - Set the names of the datasets representing the three AIJ (CRS) arrays and the name of the attribute storing the number of columns within the HDF5 file.
345 
346   Collective on PetscViewer
347 
348   Input Parameters:
349 +  viewer - the PetscViewer; either ASCII or binary
350 .  iname - name of dataset i representing row pointers; that is i[0] = 0, i[row] = i[row-1] + number of elements in that row of the matrix
351 .  jname - name of dataset j representing column indices
352 .  aname - name of dataset a representing matrix values
353 -  cname - name of attribute stoting column count
354 
355   Level: advanced
356 
357   Notes:
358   Current defaults are (iname, jname, aname, cname) = ("i", "j", "a", "ncols").
359   For PetscViewerFormat PETSC_VIEWER_HDF5_MAT they are ("jc", "ir", "data", "MATLAB_sparse") so that MAT files can be loaded.
360 
361 .seealso: MatLoad(), PetscViewerCreate(), PetscViewerSetType(), PETSCVIEWERHDF5, PetscViewerHDF5GetAIJNames()
362 @*/
363 PetscErrorCode  PetscViewerHDF5SetAIJNames(PetscViewer viewer, const char iname[], const char jname[], const char aname[], const char cname[])
364 {
365   PetscErrorCode ierr;
366 
367   PetscFunctionBegin;
368   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
369   PetscValidCharPointer(iname,2);
370   PetscValidCharPointer(jname,3);
371   PetscValidCharPointer(aname,4);
372   PetscValidCharPointer(cname,5);
373   ierr = PetscTryMethod(viewer,"PetscViewerHDF5SetAIJNames_C",(PetscViewer,const char[],const char[],const char[],const char[]),(viewer,iname,jname,aname,cname));CHKERRQ(ierr);
374   PetscFunctionReturn(0);
375 }
376 
377 PetscErrorCode  PetscViewerHDF5GetAIJNames_HDF5(PetscViewer viewer, const char *iname[], const char *jname[], const char *aname[], const char *cname[])
378 {
379   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;
380 
381   PetscFunctionBegin;
382   *iname = hdf5->mataij_iname;
383   *jname = hdf5->mataij_jname;
384   *aname = hdf5->mataij_aname;
385   *cname = hdf5->mataij_cname;
386   PetscFunctionReturn(0);
387 }
388 
389 /*@C
390   PetscViewerHDF5GetAIJNames - Get the names of the datasets representing the three AIJ (CRS) arrays and the name of the attribute storing the number of columns within the HDF5 file.
391 
392   Collective on PetscViewer
393 
394   Input Parameters:
395 .  viewer - the PetscViewer; either ASCII or binary
396 
397   Output Parameters:
398 +  iname - name of dataset i representing row pointers; that is i[0] = 0, i[row] = i[row-1] + number of elements in that row of the matrix
399 .  jname - name of dataset j representing column indices
400 .  aname - name of dataset a representing matrix values
401 -  cname - name of attribute stoting column count
402 
403   Level: advanced
404 
405   Notes:
406   Current defaults are (iname, jname, aname, cname) = ("i", "j", "a", "ncols").
407   For PetscViewerFormat PETSC_VIEWER_HDF5_MAT they are ("jc", "ir", "data", "MATLAB_sparse") so that MAT files can be loaded.
408 
409 .seealso: MatLoad(), PetscViewerCreate(), PetscViewerSetType(), PETSCVIEWERHDF5, PetscViewerHDF5SetAIJNames()
410 @*/
411 PetscErrorCode  PetscViewerHDF5GetAIJNames(PetscViewer viewer, const char *iname[], const char *jname[], const char *aname[], const char *cname[])
412 {
413   PetscErrorCode ierr;
414 
415   PetscFunctionBegin;
416   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
417   PetscValidPointer(iname,2);
418   PetscValidPointer(jname,3);
419   PetscValidPointer(aname,4);
420   PetscValidPointer(cname,5);
421   ierr = PetscUseMethod(viewer,"PetscViewerHDF5GetAIJNames_C",(PetscViewer,const char*[],const char*[],const char*[],const char*[]),(viewer,iname,jname,aname,cname));CHKERRQ(ierr);
422   PetscFunctionReturn(0);
423 }
424 
425 static PetscErrorCode PetscViewerSetUp_HDF5(PetscViewer viewer)
426 {
427   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;
428   PetscErrorCode   ierr;
429 
430   PetscFunctionBegin;
431   if (!hdf5->mataij_names_set) {
432     if (viewer->format == PETSC_VIEWER_HDF5_MAT) {
433       ierr = PetscViewerHDF5SetAIJNames_HDF5(viewer,"jc","ir","data","MATLAB_sparse");CHKERRQ(ierr);
434     } else {
435       ierr = PetscViewerHDF5SetAIJNames_HDF5(viewer,"i","j","a","ncols");CHKERRQ(ierr);
436     }
437   }
438   PetscFunctionReturn(0);
439 }
440 
441 /*MC
442    PETSCVIEWERHDF5 - A viewer that writes to an HDF5 file
443 
444 
445 .seealso:  PetscViewerHDF5Open(), PetscViewerStringSPrintf(), PetscViewerSocketOpen(), PetscViewerDrawOpen(), PETSCVIEWERSOCKET,
446            PetscViewerCreate(), PetscViewerASCIIOpen(), PetscViewerBinaryOpen(), PETSCVIEWERBINARY, PETSCVIEWERDRAW, PETSCVIEWERSTRING,
447            PetscViewerMatlabOpen(), VecView(), DMView(), PetscViewerMatlabPutArray(), PETSCVIEWERASCII, PETSCVIEWERMATLAB,
448            PetscViewerFileSetName(), PetscViewerFileSetMode(), PetscViewerFormat, PetscViewerType, PetscViewerSetType()
449 
450   Level: beginner
451 M*/
452 
453 PETSC_EXTERN PetscErrorCode PetscViewerCreate_HDF5(PetscViewer v)
454 {
455   PetscViewer_HDF5 *hdf5;
456   PetscErrorCode   ierr;
457 
458   PetscFunctionBegin;
459   ierr = PetscNewLog(v,&hdf5);CHKERRQ(ierr);
460 
461   v->data                = (void*) hdf5;
462   v->ops->destroy        = PetscViewerDestroy_HDF5;
463   v->ops->setfromoptions = PetscViewerSetFromOptions_HDF5;
464   v->ops->setup          = PetscViewerSetUp_HDF5;
465   v->ops->flush          = 0;
466   hdf5->btype            = (PetscFileMode) -1;
467   hdf5->filename         = 0;
468   hdf5->timestep         = -1;
469   hdf5->groups           = NULL;
470 
471   hdf5->mataij_iname     = NULL;
472   hdf5->mataij_jname     = NULL;
473   hdf5->mataij_aname     = NULL;
474   hdf5->mataij_cname     = NULL;
475   hdf5->mataij_names_set = PETSC_FALSE;
476 
477   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileSetName_C",PetscViewerFileSetName_HDF5);CHKERRQ(ierr);
478   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileGetName_C",PetscViewerFileGetName_HDF5);CHKERRQ(ierr);
479   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileSetMode_C",PetscViewerFileSetMode_HDF5);CHKERRQ(ierr);
480   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerHDF5SetBaseDimension2_C",PetscViewerHDF5SetBaseDimension2_HDF5);CHKERRQ(ierr);
481   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerHDF5SetSPOutput_C",PetscViewerHDF5SetSPOutput_HDF5);CHKERRQ(ierr);
482   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerHDF5SetAIJNames_C",PetscViewerHDF5SetAIJNames_HDF5);CHKERRQ(ierr);
483   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerHDF5GetAIJNames_C",PetscViewerHDF5GetAIJNames_HDF5);CHKERRQ(ierr);
484   PetscFunctionReturn(0);
485 }
486 
487 /*@C
488    PetscViewerHDF5Open - Opens a file for HDF5 input/output.
489 
490    Collective on MPI_Comm
491 
492    Input Parameters:
493 +  comm - MPI communicator
494 .  name - name of file
495 -  type - type of file
496 $    FILE_MODE_WRITE - create new file for binary output
497 $    FILE_MODE_READ - open existing file for binary input
498 $    FILE_MODE_APPEND - open existing file for binary output
499 
500    Output Parameter:
501 .  hdf5v - PetscViewer for HDF5 input/output to use with the specified file
502 
503   Options Database:
504 .  -viewer_hdf5_base_dimension2 - turns on (true) or off (false) using a dimension of 2 in the HDF5 file even if the bs/dof of the vector is 1
505 .  -viewer_hdf5_sp_output - forces (if true) the viewer to write data in single precision independent on the precision of PetscReal
506 
507    Level: beginner
508 
509    Note:
510    This PetscViewer should be destroyed with PetscViewerDestroy().
511 
512    Concepts: HDF5 files
513    Concepts: PetscViewerHDF5^creating
514 
515 .seealso: PetscViewerASCIIOpen(), PetscViewerPushFormat(), PetscViewerDestroy(), PetscViewerHDF5SetBaseDimension2(),
516           PetscViewerHDF5SetSPOutput(), PetscViewerHDF5GetBaseDimension2(), VecView(), MatView(), VecLoad(),
517           MatLoad(), PetscFileMode, PetscViewer, PetscViewerSetType(), PetscViewerFileSetMode(), PetscViewerFileSetName()
518 @*/
519 PetscErrorCode  PetscViewerHDF5Open(MPI_Comm comm, const char name[], PetscFileMode type, PetscViewer *hdf5v)
520 {
521   PetscErrorCode ierr;
522 
523   PetscFunctionBegin;
524   ierr = PetscViewerCreate(comm, hdf5v);CHKERRQ(ierr);
525   ierr = PetscViewerSetType(*hdf5v, PETSCVIEWERHDF5);CHKERRQ(ierr);
526   ierr = PetscViewerFileSetMode(*hdf5v, type);CHKERRQ(ierr);
527   ierr = PetscViewerFileSetName(*hdf5v, name);CHKERRQ(ierr);
528   PetscFunctionReturn(0);
529 }
530 
531 /*@C
532   PetscViewerHDF5GetFileId - Retrieve the file id, this file ID then can be used in direct HDF5 calls
533 
534   Not collective
535 
536   Input Parameter:
537 . viewer - the PetscViewer
538 
539   Output Parameter:
540 . file_id - The file id
541 
542   Level: intermediate
543 
544 .seealso: PetscViewerHDF5Open()
545 @*/
546 PetscErrorCode  PetscViewerHDF5GetFileId(PetscViewer viewer, hid_t *file_id)
547 {
548   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;
549 
550   PetscFunctionBegin;
551   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
552   if (file_id) *file_id = hdf5->file_id;
553   PetscFunctionReturn(0);
554 }
555 
556 /*@C
557   PetscViewerHDF5PushGroup - Set the current HDF5 group for output
558 
559   Not collective
560 
561   Input Parameters:
562 + viewer - the PetscViewer
563 - name - The group name
564 
565   Level: intermediate
566 
567 .seealso: PetscViewerHDF5Open(),PetscViewerHDF5PopGroup(),PetscViewerHDF5GetGroup(),PetscViewerHDF5OpenGroup()
568 @*/
569 PetscErrorCode  PetscViewerHDF5PushGroup(PetscViewer viewer, const char *name)
570 {
571   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;
572   GroupList        *groupNode;
573   PetscErrorCode   ierr;
574 
575   PetscFunctionBegin;
576   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
577   PetscValidCharPointer(name,2);
578   ierr = PetscNew(&groupNode);CHKERRQ(ierr);
579   ierr = PetscStrallocpy(name, (char**) &groupNode->name);CHKERRQ(ierr);
580 
581   groupNode->next = hdf5->groups;
582   hdf5->groups    = groupNode;
583   PetscFunctionReturn(0);
584 }
585 
586 /*@
587   PetscViewerHDF5PopGroup - Return the current HDF5 group for output to the previous value
588 
589   Not collective
590 
591   Input Parameter:
592 . viewer - the PetscViewer
593 
594   Level: intermediate
595 
596 .seealso: PetscViewerHDF5Open(),PetscViewerHDF5PushGroup(),PetscViewerHDF5GetGroup(),PetscViewerHDF5OpenGroup()
597 @*/
598 PetscErrorCode  PetscViewerHDF5PopGroup(PetscViewer viewer)
599 {
600   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;
601   GroupList        *groupNode;
602   PetscErrorCode   ierr;
603 
604   PetscFunctionBegin;
605   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
606   if (!hdf5->groups) SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "HDF5 group stack is empty, cannot pop");
607   groupNode    = hdf5->groups;
608   hdf5->groups = hdf5->groups->next;
609   ierr         = PetscFree(groupNode->name);CHKERRQ(ierr);
610   ierr         = PetscFree(groupNode);CHKERRQ(ierr);
611   PetscFunctionReturn(0);
612 }
613 
614 /*@C
615   PetscViewerHDF5GetGroup - Get the current HDF5 group name (full path), set with PetscViewerHDF5PushGroup()/PetscViewerHDF5PopGroup().
616   If none has been assigned, returns NULL.
617 
618   Not collective
619 
620   Input Parameter:
621 . viewer - the PetscViewer
622 
623   Output Parameter:
624 . name - The group name
625 
626   Level: intermediate
627 
628 .seealso: PetscViewerHDF5Open(),PetscViewerHDF5PushGroup(),PetscViewerHDF5PopGroup(),PetscViewerHDF5OpenGroup()
629 @*/
630 PetscErrorCode  PetscViewerHDF5GetGroup(PetscViewer viewer, const char **name)
631 {
632   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *) viewer->data;
633 
634   PetscFunctionBegin;
635   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
636   PetscValidPointer(name,2);
637   if (hdf5->groups) *name = hdf5->groups->name;
638   else *name = NULL;
639   PetscFunctionReturn(0);
640 }
641 
642 /*@
643   PetscViewerHDF5OpenGroup - Open the HDF5 group with the name (full path) returned by PetscViewerHDF5GetGroup(),
644   and return this group's ID and file ID.
645   If PetscViewerHDF5GetGroup() yields NULL, then group ID is file ID.
646 
647   Not collective
648 
649   Input Parameter:
650 . viewer - the PetscViewer
651 
652   Output Parameter:
653 + fileId - The HDF5 file ID
654 - groupId - The HDF5 group ID
655 
656   Level: intermediate
657 
658 .seealso: PetscViewerHDF5Open(),PetscViewerHDF5PushGroup(),PetscViewerHDF5PopGroup(),PetscViewerHDF5GetGroup()
659 @*/
660 PetscErrorCode PetscViewerHDF5OpenGroup(PetscViewer viewer, hid_t *fileId, hid_t *groupId)
661 {
662   hid_t          file_id;
663   H5O_type_t     type;
664   const char     *groupName = NULL;
665   PetscErrorCode ierr;
666 
667   PetscFunctionBegin;
668   ierr = PetscViewerHDF5GetFileId(viewer, &file_id);CHKERRQ(ierr);
669   ierr = PetscViewerHDF5GetGroup(viewer, &groupName);CHKERRQ(ierr);
670   ierr = PetscViewerHDF5Traverse_Internal(viewer, groupName, PETSC_TRUE, NULL, &type);CHKERRQ(ierr);
671   if (type != H5O_TYPE_GROUP) SETERRQ1(PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Path %s resolves to something which is not a group", groupName);
672   PetscStackCallHDF5Return(*groupId,H5Gopen2,(file_id, groupName ? groupName : "/", H5P_DEFAULT));
673   *fileId  = file_id;
674   PetscFunctionReturn(0);
675 }
676 
677 /*@
678   PetscViewerHDF5IncrementTimestep - Increments the current timestep for the HDF5 output. Fields are stacked in time.
679 
680   Not collective
681 
682   Input Parameter:
683 . viewer - the PetscViewer
684 
685   Level: intermediate
686 
687 .seealso: PetscViewerHDF5Open(), PetscViewerHDF5SetTimestep(), PetscViewerHDF5GetTimestep()
688 @*/
689 PetscErrorCode PetscViewerHDF5IncrementTimestep(PetscViewer viewer)
690 {
691   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;
692 
693   PetscFunctionBegin;
694   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
695   ++hdf5->timestep;
696   PetscFunctionReturn(0);
697 }
698 
699 /*@
700   PetscViewerHDF5SetTimestep - Set the current timestep for the HDF5 output. Fields are stacked in time. A timestep
701   of -1 disables blocking with timesteps.
702 
703   Not collective
704 
705   Input Parameters:
706 + viewer - the PetscViewer
707 - timestep - The timestep number
708 
709   Level: intermediate
710 
711 .seealso: PetscViewerHDF5Open(), PetscViewerHDF5IncrementTimestep(), PetscViewerHDF5GetTimestep()
712 @*/
713 PetscErrorCode  PetscViewerHDF5SetTimestep(PetscViewer viewer, PetscInt timestep)
714 {
715   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;
716 
717   PetscFunctionBegin;
718   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
719   hdf5->timestep = timestep;
720   PetscFunctionReturn(0);
721 }
722 
723 /*@
724   PetscViewerHDF5GetTimestep - Get the current timestep for the HDF5 output. Fields are stacked in time.
725 
726   Not collective
727 
728   Input Parameter:
729 . viewer - the PetscViewer
730 
731   Output Parameter:
732 . timestep - The timestep number
733 
734   Level: intermediate
735 
736 .seealso: PetscViewerHDF5Open(), PetscViewerHDF5IncrementTimestep(), PetscViewerHDF5SetTimestep()
737 @*/
738 PetscErrorCode  PetscViewerHDF5GetTimestep(PetscViewer viewer, PetscInt *timestep)
739 {
740   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;
741 
742   PetscFunctionBegin;
743   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
744   PetscValidPointer(timestep,2);
745   *timestep = hdf5->timestep;
746   PetscFunctionReturn(0);
747 }
748 
749 /*@C
750   PetscDataTypeToHDF5DataType - Converts the PETSc name of a datatype to its HDF5 name.
751 
752   Not collective
753 
754   Input Parameter:
755 . ptype - the PETSc datatype name (for example PETSC_DOUBLE)
756 
757   Output Parameter:
758 . mtype - the MPI datatype (for example MPI_DOUBLE, ...)
759 
760   Level: advanced
761 
762 .seealso: PetscDataType, PetscHDF5DataTypeToPetscDataType()
763 @*/
764 PetscErrorCode PetscDataTypeToHDF5DataType(PetscDataType ptype, hid_t *htype)
765 {
766   PetscFunctionBegin;
767   if (ptype == PETSC_INT)
768 #if defined(PETSC_USE_64BIT_INDICES)
769                                        *htype = H5T_NATIVE_LLONG;
770 #else
771                                        *htype = H5T_NATIVE_INT;
772 #endif
773   else if (ptype == PETSC_DOUBLE)      *htype = H5T_NATIVE_DOUBLE;
774   else if (ptype == PETSC_LONG)        *htype = H5T_NATIVE_LONG;
775   else if (ptype == PETSC_SHORT)       *htype = H5T_NATIVE_SHORT;
776   else if (ptype == PETSC_ENUM)        *htype = H5T_NATIVE_DOUBLE;
777   else if (ptype == PETSC_BOOL)        *htype = H5T_NATIVE_INT;
778   else if (ptype == PETSC_FLOAT)       *htype = H5T_NATIVE_FLOAT;
779   else if (ptype == PETSC_CHAR)        *htype = H5T_NATIVE_CHAR;
780   else if (ptype == PETSC_BIT_LOGICAL) *htype = H5T_NATIVE_UCHAR;
781   else if (ptype == PETSC_STRING)      *htype = H5Tcopy(H5T_C_S1);
782   else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Unsupported PETSc datatype");
783   PetscFunctionReturn(0);
784 }
785 
786 /*@C
787   PetscHDF5DataTypeToPetscDataType - Finds the PETSc name of a datatype from its HDF5 name
788 
789   Not collective
790 
791   Input Parameter:
792 . htype - the HDF5 datatype (for example H5T_NATIVE_DOUBLE, ...)
793 
794   Output Parameter:
795 . ptype - the PETSc datatype name (for example PETSC_DOUBLE)
796 
797   Level: advanced
798 
799 .seealso: PetscDataType, PetscHDF5DataTypeToPetscDataType()
800 @*/
801 PetscErrorCode PetscHDF5DataTypeToPetscDataType(hid_t htype, PetscDataType *ptype)
802 {
803   PetscFunctionBegin;
804 #if defined(PETSC_USE_64BIT_INDICES)
805   if      (htype == H5T_NATIVE_INT)    *ptype = PETSC_LONG;
806   else if (htype == H5T_NATIVE_LLONG)  *ptype = PETSC_INT;
807 #else
808   if      (htype == H5T_NATIVE_INT)    *ptype = PETSC_INT;
809 #endif
810   else if (htype == H5T_NATIVE_DOUBLE) *ptype = PETSC_DOUBLE;
811   else if (htype == H5T_NATIVE_LONG)   *ptype = PETSC_LONG;
812   else if (htype == H5T_NATIVE_SHORT)  *ptype = PETSC_SHORT;
813   else if (htype == H5T_NATIVE_FLOAT)  *ptype = PETSC_FLOAT;
814   else if (htype == H5T_NATIVE_CHAR)   *ptype = PETSC_CHAR;
815   else if (htype == H5T_NATIVE_UCHAR)  *ptype = PETSC_CHAR;
816   else if (htype == H5T_C_S1)          *ptype = PETSC_STRING;
817   else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Unsupported HDF5 datatype");
818   PetscFunctionReturn(0);
819 }
820 
821 /*@C
822  PetscViewerHDF5WriteAttribute - Write an attribute
823 
824   Input Parameters:
825 + viewer - The HDF5 viewer
826 . dataset - The parent dataset name, relative to the current group. NULL means a group-wise attribute.
827 . name   - The attribute name
828 . datatype - The attribute type
829 - value    - The attribute value
830 
831   Level: advanced
832 
833 .seealso: PetscViewerHDF5Open(), PetscViewerHDF5WriteObjectAttribute(), PetscViewerHDF5ReadAttribute(), PetscViewerHDF5HasAttribute(), PetscViewerHDF5PushGroup(),PetscViewerHDF5PopGroup(),PetscViewerHDF5GetGroup()
834 @*/
835 PetscErrorCode PetscViewerHDF5WriteAttribute(PetscViewer viewer, const char dataset[], const char name[], PetscDataType datatype, const void *value)
836 {
837   char           *parent;
838   hid_t          h5, dataspace, obj, attribute, dtype;
839   PetscBool      has;
840   PetscErrorCode ierr;
841 
842   PetscFunctionBegin;
843   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
844   if (dataset) PetscValidCharPointer(dataset, 2);
845   PetscValidCharPointer(name, 3);
846   PetscValidPointer(value, 5);
847   ierr = PetscViewerHDF5GetAbsolutePath_Internal(viewer, dataset, &parent);CHKERRQ(ierr);
848   ierr = PetscViewerHDF5Traverse_Internal(viewer, parent, PETSC_TRUE, NULL, NULL);CHKERRQ(ierr);
849   ierr = PetscViewerHDF5HasAttribute_Internal(viewer, parent, name, &has);CHKERRQ(ierr);
850   ierr = PetscDataTypeToHDF5DataType(datatype, &dtype);CHKERRQ(ierr);
851   if (datatype == PETSC_STRING) {
852     size_t len;
853     ierr = PetscStrlen((const char *) value, &len);CHKERRQ(ierr);
854     PetscStackCallHDF5(H5Tset_size,(dtype, len+1));
855   }
856   ierr = PetscViewerHDF5GetFileId(viewer, &h5);CHKERRQ(ierr);
857   PetscStackCallHDF5Return(dataspace,H5Screate,(H5S_SCALAR));
858   PetscStackCallHDF5Return(obj,H5Oopen,(h5, parent, H5P_DEFAULT));
859   if (has) {
860     PetscStackCallHDF5Return(attribute,H5Aopen_name,(obj, name));
861   } else {
862     PetscStackCallHDF5Return(attribute,H5Acreate2,(obj, name, dtype, dataspace, H5P_DEFAULT, H5P_DEFAULT));
863   }
864   PetscStackCallHDF5(H5Awrite,(attribute, dtype, value));
865   if (datatype == PETSC_STRING) PetscStackCallHDF5(H5Tclose,(dtype));
866   PetscStackCallHDF5(H5Aclose,(attribute));
867   PetscStackCallHDF5(H5Oclose,(obj));
868   PetscStackCallHDF5(H5Sclose,(dataspace));
869   ierr = PetscFree(parent);CHKERRQ(ierr);
870   PetscFunctionReturn(0);
871 }
872 
873 /*@C
874  PetscViewerHDF5WriteObjectAttribute - Write an attribute to the dataset matching the given PetscObject by name
875 
876   Input Parameters:
877 + viewer   - The HDF5 viewer
878 . obj      - The object whose name is used to lookup the parent dataset, relative to the current group.
879 . name     - The attribute name
880 . datatype - The attribute type
881 - value    - The attribute value
882 
883   Notes:
884   This fails if current_group/object_name doesn't resolve to a dataset (the path doesn't exist or is not a dataset).
885   You might want to check first if it does using PetscViewerHDF5HasObject().
886 
887   Level: advanced
888 
889 .seealso: PetscViewerHDF5Open(), PetscViewerHDF5WriteAttribute(), PetscViewerHDF5ReadObjectAttribute(), PetscViewerHDF5HasObjectAttribute(), PetscViewerHDF5HasObject(), PetscViewerHDF5PushGroup(),PetscViewerHDF5PopGroup(),PetscViewerHDF5GetGroup()
890 @*/
891 PetscErrorCode PetscViewerHDF5WriteObjectAttribute(PetscViewer viewer, PetscObject obj, const char name[], PetscDataType datatype, const void *value)
892 {
893   PetscErrorCode ierr;
894 
895   PetscFunctionBegin;
896   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
897   PetscValidHeader(obj,2);
898   PetscValidCharPointer(name,3);
899   PetscValidPointer(value,5);
900   ierr = PetscViewerHDF5CheckNamedObject_Internal(viewer, obj);CHKERRQ(ierr);
901   ierr = PetscViewerHDF5WriteAttribute(viewer, obj->name, name, datatype, value);CHKERRQ(ierr);
902   PetscFunctionReturn(0);
903 }
904 
905 /*@C
906  PetscViewerHDF5ReadAttribute - Read an attribute
907 
908   Input Parameters:
909 + viewer - The HDF5 viewer
910 . dataset - The parent dataset name, relative to the current group. NULL means a group-wise attribute.
911 . name   - The attribute name
912 - datatype - The attribute type
913 
914   Output Parameter:
915 . value    - The attribute value
916 
917   Level: advanced
918 
919 .seealso: PetscViewerHDF5Open(), PetscViewerHDF5ReadObjectAttribute(), PetscViewerHDF5WriteAttribute(), PetscViewerHDF5HasAttribute(), PetscViewerHDF5HasObject(), PetscViewerHDF5PushGroup(),PetscViewerHDF5PopGroup(),PetscViewerHDF5GetGroup()
920 @*/
921 PetscErrorCode PetscViewerHDF5ReadAttribute(PetscViewer viewer, const char dataset[], const char name[], PetscDataType datatype, void *value)
922 {
923   char           *parent;
924   hid_t          h5, obj, attribute, atype, dtype;
925   PetscBool      has;
926   PetscErrorCode ierr;
927 
928   PetscFunctionBegin;
929   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
930   if (dataset) PetscValidCharPointer(dataset, 2);
931   PetscValidCharPointer(name, 3);
932   PetscValidPointer(value, 5);
933   ierr = PetscViewerHDF5GetAbsolutePath_Internal(viewer, dataset, &parent);CHKERRQ(ierr);
934   ierr = PetscViewerHDF5Traverse_Internal(viewer, parent, PETSC_FALSE, &has, NULL);CHKERRQ(ierr);
935   if (has) {ierr = PetscViewerHDF5HasAttribute_Internal(viewer, parent, name, &has);CHKERRQ(ierr);}
936   if (!has) SETERRQ2(PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Attribute %s/%s does not exist", parent, name);
937   ierr = PetscDataTypeToHDF5DataType(datatype, &dtype);CHKERRQ(ierr);
938   ierr = PetscViewerHDF5GetFileId(viewer, &h5);CHKERRQ(ierr);
939   PetscStackCallHDF5Return(obj,H5Oopen,(h5, parent, H5P_DEFAULT));
940   PetscStackCallHDF5Return(attribute,H5Aopen_name,(obj, name));
941   if (datatype == PETSC_STRING) {
942     size_t len;
943     PetscStackCallHDF5Return(atype,H5Aget_type,(attribute));
944     PetscStackCallHDF5Return(len,H5Tget_size,(atype));
945     PetscStackCallHDF5(H5Tclose,(atype));
946     ierr = PetscMalloc((len+1) * sizeof(char *), &value);CHKERRQ(ierr);
947   }
948   PetscStackCallHDF5(H5Aread,(attribute, dtype, value));
949   PetscStackCallHDF5(H5Aclose,(attribute));
950   /* H5Oclose can be used to close groups, datasets, or committed datatypes */
951   PetscStackCallHDF5(H5Oclose,(obj));
952   ierr = PetscFree(parent);CHKERRQ(ierr);
953   PetscFunctionReturn(0);
954 }
955 
956 /*@C
957  PetscViewerHDF5ReadObjectAttribute - Read an attribute from the dataset matching the given PetscObject by name
958 
959   Input Parameters:
960 + viewer   - The HDF5 viewer
961 . obj      - The object whose name is used to lookup the parent dataset, relative to the current group.
962 . name     - The attribute name
963 - datatype - The attribute type
964 
965   Output Parameter:
966 . value    - The attribute value
967 
968   Notes:
969   This fails if current_group/object_name doesn't resolve to a dataset (the path doesn't exist or is not a dataset).
970   You might want to check first if it does using PetscViewerHDF5HasObject().
971 
972   Level: advanced
973 
974 .seealso: PetscViewerHDF5Open(), PetscViewerHDF5ReadAttribute() PetscViewerHDF5WriteObjectAttribute(), PetscViewerHDF5HasObjectAttribute(), PetscViewerHDF5PushGroup(),PetscViewerHDF5PopGroup(),PetscViewerHDF5GetGroup()
975 @*/
976 PetscErrorCode PetscViewerHDF5ReadObjectAttribute(PetscViewer viewer, PetscObject obj, const char name[], PetscDataType datatype, void *value)
977 {
978   PetscErrorCode ierr;
979 
980   PetscFunctionBegin;
981   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
982   PetscValidHeader(obj,2);
983   PetscValidCharPointer(name,3);
984   PetscValidPointer(value, 5);
985   ierr = PetscViewerHDF5CheckNamedObject_Internal(viewer, obj);CHKERRQ(ierr);
986   ierr = PetscViewerHDF5ReadAttribute(viewer, obj->name, name, datatype, value);CHKERRQ(ierr);
987   PetscFunctionReturn(0);
988 }
989 
990 PETSC_STATIC_INLINE PetscErrorCode PetscViewerHDF5Traverse_Inner_Internal(hid_t h5, const char name[], PetscBool createGroup, PetscBool *exists_)
991 {
992   htri_t exists;
993   hid_t group;
994 
995   PetscFunctionBegin;
996   PetscStackCallHDF5Return(exists,H5Lexists,(h5, name, H5P_DEFAULT));
997   if (exists) PetscStackCallHDF5Return(exists,H5Oexists_by_name,(h5, name, H5P_DEFAULT));
998   if (!exists && createGroup) {
999     PetscStackCallHDF5Return(group,H5Gcreate2,(h5, name, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT));
1000     PetscStackCallHDF5(H5Gclose,(group));
1001     exists = PETSC_TRUE;
1002   }
1003   *exists_ = (PetscBool) exists;
1004   PetscFunctionReturn(0);
1005 }
1006 
1007 static PetscErrorCode PetscViewerHDF5Traverse_Internal(PetscViewer viewer, const char name[], PetscBool createGroup, PetscBool *has, H5O_type_t *otype)
1008 {
1009   const char     rootGroupName[] = "/";
1010   hid_t          h5;
1011   PetscBool      exists=PETSC_FALSE;
1012   PetscInt       i,n;
1013   char           **hierarchy;
1014   char           buf[PETSC_MAX_PATH_LEN]="";
1015   PetscErrorCode ierr;
1016 
1017   PetscFunctionBegin;
1018   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
1019   if (name) PetscValidCharPointer(name, 2);
1020   else name = rootGroupName;
1021   if (has) {
1022     PetscValidIntPointer(has, 3);
1023     *has = PETSC_FALSE;
1024   }
1025   if (otype) {
1026     PetscValidIntPointer(otype, 4);
1027     *otype = H5O_TYPE_UNKNOWN;
1028   }
1029   ierr = PetscViewerHDF5GetFileId(viewer, &h5);CHKERRQ(ierr);
1030 
1031   /*
1032      Unfortunately, H5Oexists_by_name() fails if any object in hierarchy is missing.
1033      Hence, each of them needs to be tested separately:
1034      1) whether it's a valid link
1035      2) whether this link resolves to an object
1036      See H5Oexists_by_name() documentation.
1037   */
1038   ierr = PetscStrToArray(name,'/',&n,&hierarchy);CHKERRQ(ierr);
1039   if (!n) {
1040     /*  Assume group "/" always exists in accordance with HDF5 >= 1.10.0. See H5Lexists() documentation. */
1041     if (has)   *has   = PETSC_TRUE;
1042     if (otype) *otype = H5O_TYPE_GROUP;
1043     ierr = PetscStrToArrayDestroy(n,hierarchy);CHKERRQ(ierr);
1044     PetscFunctionReturn(0);
1045   }
1046   for (i=0; i<n; i++) {
1047     ierr = PetscStrcat(buf,"/");CHKERRQ(ierr);
1048     ierr = PetscStrcat(buf,hierarchy[i]);CHKERRQ(ierr);
1049     ierr = PetscViewerHDF5Traverse_Inner_Internal(h5, buf, createGroup, &exists);CHKERRQ(ierr);
1050     if (!exists) break;
1051   }
1052   ierr = PetscStrToArrayDestroy(n,hierarchy);CHKERRQ(ierr);
1053 
1054   /* If the object exists, get its type */
1055   if (exists && otype) {
1056     H5O_info_t info;
1057 
1058     /* We could use H5Iget_type() here but that would require opening the object. This way we only need its name. */
1059     PetscStackCallHDF5(H5Oget_info_by_name,(h5, name, &info, H5P_DEFAULT));
1060     *otype = info.type;
1061   }
1062   if (has) *has = exists;
1063   PetscFunctionReturn(0);
1064 }
1065 
1066 /*@
1067  PetscViewerHDF5HasGroup - Check whether the current (pushed) group exists in the HDF5 file
1068 
1069   Input Parameters:
1070 . viewer - The HDF5 viewer
1071 
1072   Output Parameter:
1073 . has    - Flag for group existence
1074 
1075   Notes:
1076   If the path exists but is not a group, this returns PETSC_FALSE as well.
1077 
1078   Level: advanced
1079 
1080 .seealso: PetscViewerHDF5Open(), PetscViewerHDF5PushGroup(), PetscViewerHDF5PopGroup(), PetscViewerHDF5OpenGroup()
1081 @*/
1082 PetscErrorCode PetscViewerHDF5HasGroup(PetscViewer viewer, PetscBool *has)
1083 {
1084   H5O_type_t type;
1085   const char *name;
1086   PetscErrorCode ierr;
1087 
1088   PetscFunctionBegin;
1089   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
1090   PetscValidIntPointer(has,2);
1091   ierr = PetscViewerHDF5GetGroup(viewer, &name);CHKERRQ(ierr);
1092   ierr = PetscViewerHDF5Traverse_Internal(viewer, name, PETSC_FALSE, has, &type);CHKERRQ(ierr);
1093   *has = (type == H5O_TYPE_GROUP) ? PETSC_TRUE : PETSC_FALSE;
1094   PetscFunctionReturn(0);
1095 }
1096 
1097 /*@
1098  PetscViewerHDF5HasObject - Check whether a dataset with the same name as given object exists in the HDF5 file under current group
1099 
1100   Input Parameters:
1101 + viewer - The HDF5 viewer
1102 - obj    - The named object
1103 
1104   Output Parameter:
1105 . has    - Flag for dataset existence; PETSC_FALSE for unnamed object
1106 
1107   Notes:
1108   If the path exists but is not a dataset, this returns PETSC_FALSE as well.
1109 
1110   Level: advanced
1111 
1112 .seealso: PetscViewerHDF5Open(), PetscViewerHDF5HasAttribute(), PetscViewerHDF5PushGroup(),PetscViewerHDF5PopGroup(),PetscViewerHDF5GetGroup()
1113 @*/
1114 PetscErrorCode PetscViewerHDF5HasObject(PetscViewer viewer, PetscObject obj, PetscBool *has)
1115 {
1116   H5O_type_t type;
1117   char *path;
1118   PetscErrorCode ierr;
1119 
1120   PetscFunctionBegin;
1121   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
1122   PetscValidHeader(obj,2);
1123   PetscValidIntPointer(has,3);
1124   *has = PETSC_FALSE;
1125   if (!obj->name) PetscFunctionReturn(0);
1126   ierr = PetscViewerHDF5GetAbsolutePath_Internal(viewer, obj->name, &path);CHKERRQ(ierr);
1127   ierr = PetscViewerHDF5Traverse_Internal(viewer, path, PETSC_FALSE, has, &type);CHKERRQ(ierr);
1128   *has = (type == H5O_TYPE_DATASET) ? PETSC_TRUE : PETSC_FALSE;
1129   ierr = PetscFree(path);CHKERRQ(ierr);
1130   PetscFunctionReturn(0);
1131 }
1132 
1133 /*@C
1134  PetscViewerHDF5HasAttribute - Check whether an attribute exists
1135 
1136   Input Parameters:
1137 + viewer - The HDF5 viewer
1138 . dataset - The parent dataset name, relative to the current group. NULL means a group-wise attribute.
1139 - name   - The attribute name
1140 
1141   Output Parameter:
1142 . has    - Flag for attribute existence
1143 
1144   Level: advanced
1145 
1146 .seealso: PetscViewerHDF5Open(), PetscViewerHDF5HasObjectAttribute(), PetscViewerHDF5WriteAttribute(), PetscViewerHDF5ReadAttribute(), PetscViewerHDF5PushGroup(),PetscViewerHDF5PopGroup(),PetscViewerHDF5GetGroup()
1147 @*/
1148 PetscErrorCode PetscViewerHDF5HasAttribute(PetscViewer viewer, const char dataset[], const char name[], PetscBool *has)
1149 {
1150   char           *parent;
1151   PetscErrorCode ierr;
1152 
1153   PetscFunctionBegin;
1154   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
1155   if (dataset) PetscValidCharPointer(dataset,2);
1156   PetscValidCharPointer(name,3);
1157   PetscValidIntPointer(has,4);
1158   ierr = PetscViewerHDF5GetAbsolutePath_Internal(viewer, dataset, &parent);CHKERRQ(ierr);
1159   ierr = PetscViewerHDF5Traverse_Internal(viewer, parent, PETSC_FALSE, has, NULL);CHKERRQ(ierr);
1160   if (*has) {ierr = PetscViewerHDF5HasAttribute_Internal(viewer, parent, name, has);CHKERRQ(ierr);}
1161   ierr = PetscFree(parent);CHKERRQ(ierr);
1162   PetscFunctionReturn(0);
1163 }
1164 
1165 /*@C
1166  PetscViewerHDF5HasObjectAttribute - Check whether an attribute is attached to the dataset matching the given PetscObject by name
1167 
1168   Input Parameters:
1169 + viewer - The HDF5 viewer
1170 . obj    - The object whose name is used to lookup the parent dataset, relative to the current group.
1171 - name   - The attribute name
1172 
1173   Output Parameter:
1174 . has    - Flag for attribute existence
1175 
1176   Notes:
1177   This fails if current_group/object_name doesn't resolve to a dataset (the path doesn't exist or is not a dataset).
1178   You might want to check first if it does using PetscViewerHDF5HasObject().
1179 
1180   Level: advanced
1181 
1182 .seealso: PetscViewerHDF5Open(), PetscViewerHDF5HasAttribute(), PetscViewerHDF5WriteObjectAttribute(), PetscViewerHDF5ReadObjectAttribute(), PetscViewerHDF5HasObject(), PetscViewerHDF5PushGroup(),PetscViewerHDF5PopGroup(),PetscViewerHDF5GetGroup()
1183 @*/
1184 PetscErrorCode PetscViewerHDF5HasObjectAttribute(PetscViewer viewer, PetscObject obj, const char name[], PetscBool *has)
1185 {
1186   PetscErrorCode ierr;
1187 
1188   PetscFunctionBegin;
1189   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
1190   PetscValidHeader(obj,2);
1191   PetscValidCharPointer(name,3);
1192   PetscValidIntPointer(has,4);
1193   ierr = PetscViewerHDF5CheckNamedObject_Internal(viewer, obj);CHKERRQ(ierr);
1194   ierr = PetscViewerHDF5HasAttribute(viewer, obj->name, name, has);CHKERRQ(ierr);
1195   PetscFunctionReturn(0);
1196 }
1197 
1198 static PetscErrorCode PetscViewerHDF5HasAttribute_Internal(PetscViewer viewer, const char parent[], const char name[], PetscBool *has)
1199 {
1200   hid_t          h5;
1201   htri_t         hhas;
1202   PetscErrorCode ierr;
1203 
1204   PetscFunctionBegin;
1205   ierr = PetscViewerHDF5GetFileId(viewer, &h5);CHKERRQ(ierr);
1206   PetscStackCallHDF5Return(hhas,H5Aexists_by_name,(h5, parent, name, H5P_DEFAULT));
1207   *has = hhas ? PETSC_TRUE : PETSC_FALSE;
1208   PetscFunctionReturn(0);
1209 }
1210 
1211 static PetscErrorCode PetscViewerHDF5ReadInitialize_Private(PetscViewer viewer, const char name[], HDF5ReadCtx *ctx)
1212 {
1213   HDF5ReadCtx    h=NULL;
1214   PetscErrorCode ierr;
1215 
1216   PetscFunctionBegin;
1217   ierr = PetscNew(&h);CHKERRQ(ierr);
1218   ierr = PetscViewerHDF5OpenGroup(viewer, &h->file, &h->group);CHKERRQ(ierr);
1219   PetscStackCallHDF5Return(h->dataset,H5Dopen2,(h->group, name, H5P_DEFAULT));
1220   PetscStackCallHDF5Return(h->dataspace,H5Dget_space,(h->dataset));
1221   ierr = PetscViewerHDF5GetTimestep(viewer, &h->timestep);CHKERRQ(ierr);
1222   ierr = PetscViewerHDF5HasAttribute(viewer,name,"complex",&h->complexVal);CHKERRQ(ierr);
1223   if (h->complexVal) {ierr = PetscViewerHDF5ReadAttribute(viewer,name,"complex",PETSC_BOOL,&h->complexVal);CHKERRQ(ierr);}
1224   /* MATLAB stores column vectors horizontally */
1225   ierr = PetscViewerHDF5HasAttribute(viewer,name,"MATLAB_class",&h->horizontal);CHKERRQ(ierr);
1226   /* Create property list for collective dataset read */
1227   PetscStackCallHDF5Return(h->plist,H5Pcreate,(H5P_DATASET_XFER));
1228 #if defined(PETSC_HAVE_H5PSET_FAPL_MPIO)
1229   PetscStackCallHDF5(H5Pset_dxpl_mpio,(h->plist, H5FD_MPIO_COLLECTIVE));
1230 #endif
1231   /* To write dataset independently use H5Pset_dxpl_mpio(plist_id, H5FD_MPIO_INDEPENDENT) */
1232   *ctx = h;
1233   PetscFunctionReturn(0);
1234 }
1235 
1236 static PetscErrorCode PetscViewerHDF5ReadFinalize_Private(PetscViewer viewer, HDF5ReadCtx *ctx)
1237 {
1238   HDF5ReadCtx    h;
1239   PetscErrorCode ierr;
1240 
1241   PetscFunctionBegin;
1242   h = *ctx;
1243   PetscStackCallHDF5(H5Pclose,(h->plist));
1244   PetscStackCallHDF5(H5Gclose,(h->group));
1245   PetscStackCallHDF5(H5Sclose,(h->dataspace));
1246   PetscStackCallHDF5(H5Dclose,(h->dataset));
1247   ierr = PetscFree(*ctx);CHKERRQ(ierr);
1248   PetscFunctionReturn(0);
1249 }
1250 
1251 static PetscErrorCode PetscViewerHDF5ReadSizes_Private(PetscViewer viewer, HDF5ReadCtx ctx, PetscLayout *map_)
1252 {
1253   int            rdim, dim;
1254   hsize_t        dims[4];
1255   PetscInt       bsInd, lenInd, bs, len, N;
1256   PetscLayout    map;
1257   PetscErrorCode ierr;
1258 
1259   PetscFunctionBegin;
1260   if (!(*map_)) {
1261     ierr = PetscLayoutCreate(PetscObjectComm((PetscObject)viewer),map_);CHKERRQ(ierr);
1262   }
1263   map = *map_;
1264   /* calculate expected number of dimensions */
1265   dim = 0;
1266   if (ctx->timestep >= 0) ++dim;
1267   ++dim; /* length in blocks */
1268   if (ctx->complexVal) ++dim;
1269   /* get actual number of dimensions in dataset */
1270   PetscStackCallHDF5Return(rdim,H5Sget_simple_extent_dims,(ctx->dataspace, dims, NULL));
1271   /* calculate expected dimension indices */
1272   lenInd = 0;
1273   if (ctx->timestep >= 0) ++lenInd;
1274   bsInd = lenInd + 1;
1275   ctx->dim2 = PETSC_FALSE;
1276   if (rdim == dim) {
1277     bs = 1; /* support vectors stored as 1D array */
1278   } else if (rdim == dim+1) {
1279     bs = (PetscInt) dims[bsInd];
1280     if (bs == 1) ctx->dim2 = PETSC_TRUE; /* vector with blocksize of 1, still stored as 2D array */
1281   } else {
1282     SETERRQ2(PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Number of dimensions %d not %d as expected", rdim, dim);
1283   }
1284   len = dims[lenInd];
1285   if (ctx->horizontal) {
1286     if (len != 1) SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Cannot have horizontal array with number of rows > 1. In case of MATLAB MAT-file, vectors must be saved as column vectors.");
1287     len = bs;
1288     bs = 1;
1289   }
1290   N = (PetscInt) len*bs;
1291 
1292   /* Set Vec sizes,blocksize,and type if not already set */
1293   if (map->bs < 0) {
1294     ierr = PetscLayoutSetBlockSize(map, bs);CHKERRQ(ierr);
1295   } else if (map->bs != bs) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED, "Block size of array in file is %D, not %D as expected",bs,map->bs);
1296   if (map->N < 0) {
1297     ierr = PetscLayoutSetSize(map, N);CHKERRQ(ierr);
1298   } else if (map->N != N) SETERRQ2(PetscObjectComm((PetscObject)viewer),PETSC_ERR_FILE_UNEXPECTED, "Global size of array in file is %D, not %D as expected",N,map->N);
1299   PetscFunctionReturn(0);
1300 }
1301 
1302 static PetscErrorCode PetscViewerHDF5ReadSelectHyperslab_Private(PetscViewer viewer, HDF5ReadCtx ctx, PetscLayout map, hid_t *memspace)
1303 {
1304   hsize_t        count[4], offset[4];
1305   int            dim;
1306   PetscInt       bs, n, low;
1307   PetscErrorCode ierr;
1308 
1309   PetscFunctionBegin;
1310   /* Compute local size and ownership range */
1311   ierr = PetscLayoutSetUp(map);CHKERRQ(ierr);
1312   ierr = PetscLayoutGetBlockSize(map, &bs);CHKERRQ(ierr);
1313   ierr = PetscLayoutGetLocalSize(map, &n);CHKERRQ(ierr);
1314   ierr = PetscLayoutGetRange(map, &low, NULL);CHKERRQ(ierr);
1315 
1316   /* Each process defines a dataset and reads it from the hyperslab in the file */
1317   dim  = 0;
1318   if (ctx->timestep >= 0) {
1319     count[dim]  = 1;
1320     offset[dim] = ctx->timestep;
1321     ++dim;
1322   }
1323   if (ctx->horizontal) {
1324     count[dim]  = 1;
1325     offset[dim] = 0;
1326     ++dim;
1327   }
1328   {
1329     ierr = PetscHDF5IntCast(n/bs, &count[dim]);CHKERRQ(ierr);
1330     ierr = PetscHDF5IntCast(low/bs, &offset[dim]);CHKERRQ(ierr);
1331     ++dim;
1332   }
1333   if (bs > 1 || ctx->dim2) {
1334     if (PetscUnlikely(ctx->horizontal)) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "cannot have horizontal array with blocksize > 1");
1335     count[dim]  = bs;
1336     offset[dim] = 0;
1337     ++dim;
1338   }
1339   if (ctx->complexVal) {
1340     count[dim]  = 2;
1341     offset[dim] = 0;
1342     ++dim;
1343   }
1344   PetscStackCallHDF5Return(*memspace,H5Screate_simple,(dim, count, NULL));
1345   PetscStackCallHDF5(H5Sselect_hyperslab,(ctx->dataspace, H5S_SELECT_SET, offset, NULL, count, NULL));
1346   PetscFunctionReturn(0);
1347 }
1348 
1349 static PetscErrorCode PetscViewerHDF5ReadArray_Private(PetscViewer viewer, HDF5ReadCtx h, hid_t datatype, hid_t memspace, void *arr)
1350 {
1351   PetscFunctionBegin;
1352   PetscStackCallHDF5(H5Dread,(h->dataset, datatype, memspace, h->dataspace, h->plist, arr));
1353   PetscFunctionReturn(0);
1354 }
1355 
1356 PetscErrorCode PetscViewerHDF5Load(PetscViewer viewer, const char *name, PetscLayout map, hid_t datatype, void **newarr)
1357 {
1358   HDF5ReadCtx     h=NULL;
1359   hid_t           memspace=0;
1360   size_t          unitsize;
1361   void            *arr;
1362   PetscErrorCode  ierr;
1363 
1364   PetscFunctionBegin;
1365   ierr = PetscViewerHDF5ReadInitialize_Private(viewer, name, &h);CHKERRQ(ierr);
1366 #if defined(PETSC_USE_COMPLEX)
1367   if (!h->complexVal) {
1368     H5T_class_t clazz = H5Tget_class(datatype);
1369     if (clazz == H5T_FLOAT) SETERRQ(PetscObjectComm((PetscObject)viewer),PETSC_ERR_SUP,"File contains real numbers but PETSc is configured for complex. The conversion is not yet implemented. Configure with --with-scalar-type=real.");
1370   }
1371 #else
1372   if (h->complexVal) SETERRQ(PetscObjectComm((PetscObject)viewer),PETSC_ERR_SUP,"File contains complex numbers but PETSc not configured for them. Configure with --with-scalar-type=complex.");
1373 #endif
1374 
1375   ierr = PetscViewerHDF5ReadSizes_Private(viewer, h, &map);CHKERRQ(ierr);
1376   ierr = PetscLayoutSetUp(map);CHKERRQ(ierr);
1377   ierr = PetscViewerHDF5ReadSelectHyperslab_Private(viewer, h, map, &memspace);CHKERRQ(ierr);
1378 
1379   unitsize = H5Tget_size(datatype);
1380   if (h->complexVal) unitsize *= 2;
1381   if (unitsize <= 0 || unitsize > PetscMax(sizeof(PetscInt),sizeof(PetscScalar))) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Sanity check failed: HDF5 function H5Tget_size(datatype) returned suspicious value %D",unitsize);
1382   ierr = PetscMalloc(map->n*unitsize, &arr);CHKERRQ(ierr);
1383 
1384   ierr = PetscViewerHDF5ReadArray_Private(viewer, h, datatype, memspace, arr);CHKERRQ(ierr);
1385   PetscStackCallHDF5(H5Sclose,(memspace));
1386   ierr = PetscViewerHDF5ReadFinalize_Private(viewer, &h);CHKERRQ(ierr);
1387   *newarr = arr;
1388   PetscFunctionReturn(0);
1389 }
1390 
1391 /*@C
1392  PetscViewerHDF5ReadSizes - Read block size and global size of a vector (Vec or IS) stored in an HDF5 file.
1393 
1394   Input Parameters:
1395 + viewer - The HDF5 viewer
1396 - name   - The vector name
1397 
1398   Output Parameter:
1399 + bs     - block size
1400 - N      - global size
1401 
1402   Note:
1403   A vector is stored as an HDF5 dataspace with 1-4 dimensions in this order:
1404   1) # timesteps (optional), 2) # blocks, 3) # elements per block (optional), 4) real and imaginary part (only for complex).
1405 
1406   A vectors can be stored as a 2D dataspace even if its blocksize is 1; see PetscViewerHDF5SetBaseDimension2().
1407 
1408   Level: advanced
1409 
1410 .seealso: PetscViewerHDF5Open(), VecLoad(), ISLoad(), VecGetSize(), ISGetSize(), PetscViewerHDF5SetBaseDimension2()
1411 @*/
1412 PetscErrorCode PetscViewerHDF5ReadSizes(PetscViewer viewer, const char name[], PetscInt *bs, PetscInt *N)
1413 {
1414   HDF5ReadCtx    h=NULL;
1415   PetscLayout    map=NULL;
1416   PetscErrorCode ierr;
1417 
1418   PetscFunctionBegin;
1419   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
1420   ierr = PetscViewerHDF5ReadInitialize_Private(viewer, name, &h);CHKERRQ(ierr);
1421   ierr = PetscViewerHDF5ReadSizes_Private(viewer, h, &map);CHKERRQ(ierr);
1422   ierr = PetscViewerHDF5ReadFinalize_Private(viewer, &h);CHKERRQ(ierr);
1423   if (bs) *bs = map->bs;
1424   if (N) *N = map->N;
1425   ierr = PetscLayoutDestroy(&map);CHKERRQ(ierr);
1426   PetscFunctionReturn(0);
1427 }
1428 
1429 /*
1430   The variable Petsc_Viewer_HDF5_keyval is used to indicate an MPI attribute that
1431   is attached to a communicator, in this case the attribute is a PetscViewer.
1432 */
1433 PetscMPIInt Petsc_Viewer_HDF5_keyval = MPI_KEYVAL_INVALID;
1434 
1435 /*@C
1436   PETSC_VIEWER_HDF5_ - Creates an HDF5 PetscViewer shared by all processors in a communicator.
1437 
1438   Collective on MPI_Comm
1439 
1440   Input Parameter:
1441 . comm - the MPI communicator to share the HDF5 PetscViewer
1442 
1443   Level: intermediate
1444 
1445   Options Database Keys:
1446 . -viewer_hdf5_filename <name>
1447 
1448   Environmental variables:
1449 . PETSC_VIEWER_HDF5_FILENAME
1450 
1451   Notes:
1452   Unlike almost all other PETSc routines, PETSC_VIEWER_HDF5_ does not return
1453   an error code.  The HDF5 PetscViewer is usually used in the form
1454 $       XXXView(XXX object, PETSC_VIEWER_HDF5_(comm));
1455 
1456 .seealso: PetscViewerHDF5Open(), PetscViewerCreate(), PetscViewerDestroy()
1457 @*/
1458 PetscViewer PETSC_VIEWER_HDF5_(MPI_Comm comm)
1459 {
1460   PetscErrorCode ierr;
1461   PetscBool      flg;
1462   PetscViewer    viewer;
1463   char           fname[PETSC_MAX_PATH_LEN];
1464   MPI_Comm       ncomm;
1465 
1466   PetscFunctionBegin;
1467   ierr = PetscCommDuplicate(comm,&ncomm,NULL);if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
1468   if (Petsc_Viewer_HDF5_keyval == MPI_KEYVAL_INVALID) {
1469     ierr = MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN,MPI_COMM_NULL_DELETE_FN,&Petsc_Viewer_HDF5_keyval,0);
1470     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
1471   }
1472   ierr = MPI_Comm_get_attr(ncomm,Petsc_Viewer_HDF5_keyval,(void**)&viewer,(int*)&flg);
1473   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
1474   if (!flg) { /* PetscViewer not yet created */
1475     ierr = PetscOptionsGetenv(ncomm,"PETSC_VIEWER_HDF5_FILENAME",fname,PETSC_MAX_PATH_LEN,&flg);
1476     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
1477     if (!flg) {
1478       ierr = PetscStrcpy(fname,"output.h5");
1479       if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
1480     }
1481     ierr = PetscViewerHDF5Open(ncomm,fname,FILE_MODE_WRITE,&viewer);
1482     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
1483     ierr = PetscObjectRegisterDestroy((PetscObject)viewer);
1484     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
1485     ierr = MPI_Comm_set_attr(ncomm,Petsc_Viewer_HDF5_keyval,(void*)viewer);
1486     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
1487   }
1488   ierr = PetscCommDestroy(&ncomm);
1489   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
1490   PetscFunctionReturn(viewer);
1491 }
1492