1 #include <petsc/private/viewerimpl.h>
2 #include <petsc/private/viewerhdf5impl.h>
3 #include <petscviewerhdf5.h> /*I "petscviewerhdf5.h" I*/
4
5 static PetscErrorCode PetscViewerHDF5Traverse_Internal(PetscViewer, const char[], PetscBool, PetscBool*, H5O_type_t*);
6 static PetscErrorCode PetscViewerHDF5HasAttribute_Internal(PetscViewer, const char[], const char[], PetscBool*);
7
PetscViewerHDF5GetAbsolutePath_Internal(PetscViewer viewer,const char objname[],char ** fullpath)8 static PetscErrorCode PetscViewerHDF5GetAbsolutePath_Internal(PetscViewer viewer, const char objname[], char **fullpath)
9 {
10 const char *group;
11 char buf[PETSC_MAX_PATH_LEN]="";
12 PetscErrorCode ierr;
13
14 PetscFunctionBegin;
15 ierr = PetscViewerHDF5GetGroup(viewer, &group);CHKERRQ(ierr);
16 ierr = PetscStrcat(buf, group);CHKERRQ(ierr);
17 ierr = PetscStrcat(buf, "/");CHKERRQ(ierr);
18 ierr = PetscStrcat(buf, objname);CHKERRQ(ierr);
19 ierr = PetscStrallocpy(buf, fullpath);CHKERRQ(ierr);
20 PetscFunctionReturn(0);
21 }
22
PetscViewerHDF5CheckNamedObject_Internal(PetscViewer viewer,PetscObject obj)23 static PetscErrorCode PetscViewerHDF5CheckNamedObject_Internal(PetscViewer viewer, PetscObject obj)
24 {
25 PetscBool has;
26 const char *group;
27 PetscErrorCode ierr;
28
29 PetscFunctionBegin;
30 if (!obj->name) SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONG, "Object must be named");
31 ierr = PetscViewerHDF5HasObject(viewer, obj, &has);CHKERRQ(ierr);
32 if (!has) {
33 ierr = PetscViewerHDF5GetGroup(viewer, &group);CHKERRQ(ierr);
34 SETERRQ2(PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Object (dataset) %s not stored in group %s", obj->name, group);
35 }
36 PetscFunctionReturn(0);
37 }
38
PetscViewerSetFromOptions_HDF5(PetscOptionItems * PetscOptionsObject,PetscViewer v)39 static PetscErrorCode PetscViewerSetFromOptions_HDF5(PetscOptionItems *PetscOptionsObject,PetscViewer v)
40 {
41 PetscErrorCode ierr;
42 PetscBool flg = PETSC_FALSE, set;
43 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*)v->data;
44
45 PetscFunctionBegin;
46 ierr = PetscOptionsHead(PetscOptionsObject,"HDF5 PetscViewer Options");CHKERRQ(ierr);
47 ierr = PetscOptionsBool("-viewer_hdf5_base_dimension2","1d Vectors get 2 dimensions in HDF5","PetscViewerHDF5SetBaseDimension2",hdf5->basedimension2,&hdf5->basedimension2,NULL);CHKERRQ(ierr);
48 ierr = PetscOptionsBool("-viewer_hdf5_sp_output","Force data to be written in single precision","PetscViewerHDF5SetSPOutput",hdf5->spoutput,&hdf5->spoutput,NULL);CHKERRQ(ierr);
49 ierr = PetscOptionsBool("-viewer_hdf5_collective","Enable collective transfer mode","PetscViewerHDF5SetCollective",flg,&flg,&set);CHKERRQ(ierr);
50 if (set) {ierr = PetscViewerHDF5SetCollective(v,flg);CHKERRQ(ierr);}
51 ierr = PetscOptionsTail();CHKERRQ(ierr);
52 PetscFunctionReturn(0);
53 }
54
PetscViewerView_HDF5(PetscViewer v,PetscViewer viewer)55 static PetscErrorCode PetscViewerView_HDF5(PetscViewer v,PetscViewer viewer)
56 {
57 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*)v->data;
58 PetscBool flg;
59 PetscErrorCode ierr;
60
61 PetscFunctionBegin;
62 if (hdf5->filename) {
63 ierr = PetscViewerASCIIPrintf(viewer,"Filename: %s\n",hdf5->filename);CHKERRQ(ierr);
64 }
65 ierr = PetscViewerASCIIPrintf(viewer,"Vectors with blocksize 1 saved as 2D datasets: %s\n",PetscBools[hdf5->basedimension2]);CHKERRQ(ierr);
66 ierr = PetscViewerASCIIPrintf(viewer,"Enforce single precision storage: %s\n",PetscBools[hdf5->spoutput]);CHKERRQ(ierr);
67 ierr = PetscViewerHDF5GetCollective(v,&flg);CHKERRQ(ierr);
68 ierr = PetscViewerASCIIPrintf(viewer,"MPI-IO transfer mode: %s\n",flg ? "collective" : "independent");CHKERRQ(ierr);
69 PetscFunctionReturn(0);
70 }
71
PetscViewerFileClose_HDF5(PetscViewer viewer)72 static PetscErrorCode PetscViewerFileClose_HDF5(PetscViewer viewer)
73 {
74 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*)viewer->data;
75 PetscErrorCode ierr;
76
77 PetscFunctionBegin;
78 ierr = PetscFree(hdf5->filename);CHKERRQ(ierr);
79 if (hdf5->file_id) PetscStackCallHDF5(H5Fclose,(hdf5->file_id));
80 PetscFunctionReturn(0);
81 }
82
PetscViewerDestroy_HDF5(PetscViewer viewer)83 static PetscErrorCode PetscViewerDestroy_HDF5(PetscViewer viewer)
84 {
85 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;
86 PetscErrorCode ierr;
87
88 PetscFunctionBegin;
89 PetscStackCallHDF5(H5Pclose,(hdf5->dxpl_id));
90 ierr = PetscViewerFileClose_HDF5(viewer);CHKERRQ(ierr);
91 while (hdf5->groups) {
92 PetscViewerHDF5GroupList *tmp = hdf5->groups->next;
93
94 ierr = PetscFree(hdf5->groups->name);CHKERRQ(ierr);
95 ierr = PetscFree(hdf5->groups);CHKERRQ(ierr);
96 hdf5->groups = tmp;
97 }
98 ierr = PetscFree(hdf5);CHKERRQ(ierr);
99 ierr = PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerFileSetName_C",NULL);CHKERRQ(ierr);
100 ierr = PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerFileGetName_C",NULL);CHKERRQ(ierr);
101 ierr = PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerFileSetMode_C",NULL);CHKERRQ(ierr);
102 ierr = PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerHDF5SetBaseDimension2_C",NULL);CHKERRQ(ierr);
103 ierr = PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerHDF5SetSPOutput_C",NULL);CHKERRQ(ierr);
104 PetscFunctionReturn(0);
105 }
106
PetscViewerFileSetMode_HDF5(PetscViewer viewer,PetscFileMode type)107 static PetscErrorCode PetscViewerFileSetMode_HDF5(PetscViewer viewer, PetscFileMode type)
108 {
109 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;
110
111 PetscFunctionBegin;
112 hdf5->btype = type;
113 PetscFunctionReturn(0);
114 }
115
PetscViewerFileGetMode_HDF5(PetscViewer viewer,PetscFileMode * type)116 static PetscErrorCode PetscViewerFileGetMode_HDF5(PetscViewer viewer, PetscFileMode *type)
117 {
118 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;
119
120 PetscFunctionBegin;
121 *type = hdf5->btype;
122 PetscFunctionReturn(0);
123 }
124
PetscViewerHDF5SetBaseDimension2_HDF5(PetscViewer viewer,PetscBool flg)125 static PetscErrorCode PetscViewerHDF5SetBaseDimension2_HDF5(PetscViewer viewer, PetscBool flg)
126 {
127 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;
128
129 PetscFunctionBegin;
130 hdf5->basedimension2 = flg;
131 PetscFunctionReturn(0);
132 }
133
134 /*@
135 PetscViewerHDF5SetBaseDimension2 - Vectors of 1 dimension (i.e. bs/dof is 1) will be saved in the HDF5 file with a
136 dimension of 2.
137
138 Logically Collective on PetscViewer
139
140 Input Parameters:
141 + viewer - the PetscViewer; if it is not hdf5 then this command is ignored
142 - flg - if PETSC_TRUE the vector will always have at least a dimension of 2 even if that first dimension is of size 1
143
144 Options Database:
145 . -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
146
147
148 Notes:
149 Setting this option allegedly makes code that reads the HDF5 in easier since they do not have a "special case" of a bs/dof
150 of one when the dimension is lower. Others think the option is crazy.
151
152 Level: intermediate
153
154 .seealso: PetscViewerFileSetMode(), PetscViewerCreate(), PetscViewerSetType(), PetscViewerBinaryOpen()
155
156 @*/
PetscViewerHDF5SetBaseDimension2(PetscViewer viewer,PetscBool flg)157 PetscErrorCode PetscViewerHDF5SetBaseDimension2(PetscViewer viewer,PetscBool flg)
158 {
159 PetscErrorCode ierr;
160
161 PetscFunctionBegin;
162 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
163 ierr = PetscTryMethod(viewer,"PetscViewerHDF5SetBaseDimension2_C",(PetscViewer,PetscBool),(viewer,flg));CHKERRQ(ierr);
164 PetscFunctionReturn(0);
165 }
166
167 /*@
168 PetscViewerHDF5GetBaseDimension2 - Vectors of 1 dimension (i.e. bs/dof is 1) will be saved in the HDF5 file with a
169 dimension of 2.
170
171 Logically Collective on PetscViewer
172
173 Input Parameter:
174 . viewer - the PetscViewer, must be of type HDF5
175
176 Output Parameter:
177 . flg - if PETSC_TRUE the vector will always have at least a dimension of 2 even if that first dimension is of size 1
178
179 Notes:
180 Setting this option allegedly makes code that reads the HDF5 in easier since they do not have a "special case" of a bs/dof
181 of one when the dimension is lower. Others think the option is crazy.
182
183 Level: intermediate
184
185 .seealso: PetscViewerFileSetMode(), PetscViewerCreate(), PetscViewerSetType(), PetscViewerBinaryOpen()
186
187 @*/
PetscViewerHDF5GetBaseDimension2(PetscViewer viewer,PetscBool * flg)188 PetscErrorCode PetscViewerHDF5GetBaseDimension2(PetscViewer viewer,PetscBool *flg)
189 {
190 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;
191
192 PetscFunctionBegin;
193 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
194 *flg = hdf5->basedimension2;
195 PetscFunctionReturn(0);
196 }
197
PetscViewerHDF5SetSPOutput_HDF5(PetscViewer viewer,PetscBool flg)198 static PetscErrorCode PetscViewerHDF5SetSPOutput_HDF5(PetscViewer viewer, PetscBool flg)
199 {
200 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;
201
202 PetscFunctionBegin;
203 hdf5->spoutput = flg;
204 PetscFunctionReturn(0);
205 }
206
207 /*@
208 PetscViewerHDF5SetSPOutput - Data is written to disk in single precision even if PETSc is
209 compiled with double precision PetscReal.
210
211 Logically Collective on PetscViewer
212
213 Input Parameters:
214 + viewer - the PetscViewer; if it is not hdf5 then this command is ignored
215 - flg - if PETSC_TRUE the data will be written to disk with single precision
216
217 Options Database:
218 . -viewer_hdf5_sp_output - turns on (true) or off (false) output in single precision
219
220
221 Notes:
222 Setting this option does not make any difference if PETSc is compiled with single precision
223 in the first place. It does not affect reading datasets (HDF5 handle this internally).
224
225 Level: intermediate
226
227 .seealso: PetscViewerFileSetMode(), PetscViewerCreate(), PetscViewerSetType(), PetscViewerBinaryOpen(),
228 PetscReal
229
230 @*/
PetscViewerHDF5SetSPOutput(PetscViewer viewer,PetscBool flg)231 PetscErrorCode PetscViewerHDF5SetSPOutput(PetscViewer viewer,PetscBool flg)
232 {
233 PetscErrorCode ierr;
234
235 PetscFunctionBegin;
236 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
237 ierr = PetscTryMethod(viewer,"PetscViewerHDF5SetSPOutput_C",(PetscViewer,PetscBool),(viewer,flg));CHKERRQ(ierr);
238 PetscFunctionReturn(0);
239 }
240
241 /*@
242 PetscViewerHDF5GetSPOutput - Data is written to disk in single precision even if PETSc is
243 compiled with double precision PetscReal.
244
245 Logically Collective on PetscViewer
246
247 Input Parameter:
248 . viewer - the PetscViewer, must be of type HDF5
249
250 Output Parameter:
251 . flg - if PETSC_TRUE the data will be written to disk with single precision
252
253 Notes:
254 Setting this option does not make any difference if PETSc is compiled with single precision
255 in the first place. It does not affect reading datasets (HDF5 handle this internally).
256
257 Level: intermediate
258
259 .seealso: PetscViewerFileSetMode(), PetscViewerCreate(), PetscViewerSetType(), PetscViewerBinaryOpen(),
260 PetscReal
261
262 @*/
PetscViewerHDF5GetSPOutput(PetscViewer viewer,PetscBool * flg)263 PetscErrorCode PetscViewerHDF5GetSPOutput(PetscViewer viewer,PetscBool *flg)
264 {
265 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;
266
267 PetscFunctionBegin;
268 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
269 *flg = hdf5->spoutput;
270 PetscFunctionReturn(0);
271 }
272
PetscViewerHDF5SetCollective_HDF5(PetscViewer viewer,PetscBool flg)273 static PetscErrorCode PetscViewerHDF5SetCollective_HDF5(PetscViewer viewer, PetscBool flg)
274 {
275 PetscFunctionBegin;
276 /* H5FD_MPIO_COLLECTIVE is wrong in hdf5 1.10.2, and is the same as H5FD_MPIO_INDEPENDENT in earlier versions
277 - see e.g. https://gitlab.cosma.dur.ac.uk/swift/swiftsim/issues/431 */
278 #if H5_VERSION_GE(1,10,3) && defined(H5_HAVE_PARALLEL)
279 {
280 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;
281 PetscStackCallHDF5(H5Pset_dxpl_mpio,(hdf5->dxpl_id, flg ? H5FD_MPIO_COLLECTIVE : H5FD_MPIO_INDEPENDENT));
282 }
283 #else
284 if (flg) {
285 PetscErrorCode ierr;
286 ierr = PetscPrintf(PetscObjectComm((PetscObject)viewer), "Warning: PetscViewerHDF5SetCollective(viewer,PETSC_TRUE) is ignored for HDF5 versions prior to 1.10.3 or if built without MPI support\n");CHKERRQ(ierr);
287 }
288 #endif
289 PetscFunctionReturn(0);
290 }
291
292 /*@
293 PetscViewerHDF5SetCollective - Use collective MPI-IO transfer mode for HDF5 reads and writes.
294
295 Logically Collective; flg must contain common value
296
297 Input Parameters:
298 + viewer - the PetscViewer; if it is not hdf5 then this command is ignored
299 - flg - PETSC_TRUE for collective mode; PETSC_FALSE for independent mode (default)
300
301 Options Database:
302 . -viewer_hdf5_collective - turns on (true) or off (false) collective transfers
303
304 Notes:
305 Collective mode gives the MPI-IO layer underneath HDF5 a chance to do some additional collective optimizations and hence can perform better.
306 However, this works correctly only since HDF5 1.10.3 and if HDF5 is installed for MPI; hence, we ignore this setting for older versions.
307
308 Developer notes:
309 In the HDF5 layer, PETSC_TRUE / PETSC_FALSE means H5Pset_dxpl_mpio() is called with H5FD_MPIO_COLLECTIVE / H5FD_MPIO_INDEPENDENT, respectively.
310 This in turn means use of MPI_File_{read,write}_all / MPI_File_{read,write} in the MPI-IO layer, respectively.
311 See HDF5 documentation and MPI-IO documentation for details.
312
313 Level: intermediate
314
315 .seealso: PetscViewerHDF5GetCollective(), PetscViewerCreate(), PetscViewerSetType(), PetscViewerHDF5Open()
316
317 @*/
PetscViewerHDF5SetCollective(PetscViewer viewer,PetscBool flg)318 PetscErrorCode PetscViewerHDF5SetCollective(PetscViewer viewer,PetscBool flg)
319 {
320 PetscErrorCode ierr;
321
322 PetscFunctionBegin;
323 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
324 PetscValidLogicalCollectiveBool(viewer,flg,2);
325 ierr = PetscTryMethod(viewer,"PetscViewerHDF5SetCollective_C",(PetscViewer,PetscBool),(viewer,flg));CHKERRQ(ierr);
326 PetscFunctionReturn(0);
327 }
328
PetscViewerHDF5GetCollective_HDF5(PetscViewer viewer,PetscBool * flg)329 static PetscErrorCode PetscViewerHDF5GetCollective_HDF5(PetscViewer viewer, PetscBool *flg)
330 {
331 #if defined(H5_HAVE_PARALLEL)
332 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;
333 H5FD_mpio_xfer_t mode;
334 #endif
335
336 PetscFunctionBegin;
337 #if !defined(H5_HAVE_PARALLEL)
338 *flg = PETSC_FALSE;
339 #else
340 PetscStackCallHDF5(H5Pget_dxpl_mpio,(hdf5->dxpl_id, &mode));
341 *flg = (mode == H5FD_MPIO_COLLECTIVE) ? PETSC_TRUE : PETSC_FALSE;
342 #endif
343 PetscFunctionReturn(0);
344 }
345
346 /*@
347 PetscViewerHDF5GetCollective - Return flag whether collective MPI-IO transfer mode is used for HDF5 reads and writes.
348
349 Not Collective
350
351 Input Parameters:
352 . viewer - the HDF5 PetscViewer
353
354 Output Parameters:
355 . flg - the flag
356
357 Level: intermediate
358
359 Notes:
360 This setting works correctly only since HDF5 1.10.3 and if HDF5 was installed for MPI. For older versions, PETSC_FALSE will be always returned.
361 For more details, see PetscViewerHDF5SetCollective().
362
363 .seealso: PetscViewerHDF5SetCollective(), PetscViewerCreate(), PetscViewerSetType(), PetscViewerHDF5Open()
364
365 @*/
PetscViewerHDF5GetCollective(PetscViewer viewer,PetscBool * flg)366 PetscErrorCode PetscViewerHDF5GetCollective(PetscViewer viewer,PetscBool *flg)
367 {
368 PetscErrorCode ierr;
369
370 PetscFunctionBegin;
371 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
372 PetscValidBoolPointer(flg,2);
373
374 ierr = PetscUseMethod(viewer,"PetscViewerHDF5GetCollective_C",(PetscViewer,PetscBool*),(viewer,flg));CHKERRQ(ierr);
375 PetscFunctionReturn(0);
376 }
377
PetscViewerFileSetName_HDF5(PetscViewer viewer,const char name[])378 static PetscErrorCode PetscViewerFileSetName_HDF5(PetscViewer viewer, const char name[])
379 {
380 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;
381 hid_t plist_id;
382 PetscErrorCode ierr;
383
384 PetscFunctionBegin;
385 if (hdf5->file_id) PetscStackCallHDF5(H5Fclose,(hdf5->file_id));
386 if (hdf5->filename) {ierr = PetscFree(hdf5->filename);CHKERRQ(ierr);}
387 ierr = PetscStrallocpy(name, &hdf5->filename);CHKERRQ(ierr);
388 /* Set up file access property list with parallel I/O access */
389 PetscStackCallHDF5Return(plist_id,H5Pcreate,(H5P_FILE_ACCESS));
390 #if defined(H5_HAVE_PARALLEL)
391 PetscStackCallHDF5(H5Pset_fapl_mpio,(plist_id, PetscObjectComm((PetscObject)viewer), MPI_INFO_NULL));
392 #endif
393 /* Create or open the file collectively */
394 switch (hdf5->btype) {
395 case FILE_MODE_READ:
396 PetscStackCallHDF5Return(hdf5->file_id,H5Fopen,(name, H5F_ACC_RDONLY, plist_id));
397 break;
398 case FILE_MODE_APPEND:
399 PetscStackCallHDF5Return(hdf5->file_id,H5Fopen,(name, H5F_ACC_RDWR, plist_id));
400 break;
401 case FILE_MODE_WRITE:
402 PetscStackCallHDF5Return(hdf5->file_id,H5Fcreate,(name, H5F_ACC_TRUNC, H5P_DEFAULT, plist_id));
403 break;
404 default:
405 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER, "Must call PetscViewerFileSetMode() before PetscViewerFileSetName()");
406 }
407 if (hdf5->file_id < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB, "H5Fcreate failed for %s", name);
408 PetscStackCallHDF5(H5Pclose,(plist_id));
409 PetscFunctionReturn(0);
410 }
411
PetscViewerFileGetName_HDF5(PetscViewer viewer,const char ** name)412 static PetscErrorCode PetscViewerFileGetName_HDF5(PetscViewer viewer,const char **name)
413 {
414 PetscViewer_HDF5 *vhdf5 = (PetscViewer_HDF5*)viewer->data;
415
416 PetscFunctionBegin;
417 *name = vhdf5->filename;
418 PetscFunctionReturn(0);
419 }
420
PetscViewerSetUp_HDF5(PetscViewer viewer)421 static PetscErrorCode PetscViewerSetUp_HDF5(PetscViewer viewer)
422 {
423 /*
424 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;
425 PetscErrorCode ierr;
426 */
427
428 PetscFunctionBegin;
429 PetscFunctionReturn(0);
430 }
431
432 /*MC
433 PETSCVIEWERHDF5 - A viewer that writes to an HDF5 file
434
435
436 .seealso: PetscViewerHDF5Open(), PetscViewerStringSPrintf(), PetscViewerSocketOpen(), PetscViewerDrawOpen(), PETSCVIEWERSOCKET,
437 PetscViewerCreate(), PetscViewerASCIIOpen(), PetscViewerBinaryOpen(), PETSCVIEWERBINARY, PETSCVIEWERDRAW, PETSCVIEWERSTRING,
438 PetscViewerMatlabOpen(), VecView(), DMView(), PetscViewerMatlabPutArray(), PETSCVIEWERASCII, PETSCVIEWERMATLAB,
439 PetscViewerFileSetName(), PetscViewerFileSetMode(), PetscViewerFormat, PetscViewerType, PetscViewerSetType()
440
441 Level: beginner
442 M*/
443
PetscViewerCreate_HDF5(PetscViewer v)444 PETSC_EXTERN PetscErrorCode PetscViewerCreate_HDF5(PetscViewer v)
445 {
446 PetscViewer_HDF5 *hdf5;
447 PetscErrorCode ierr;
448
449 PetscFunctionBegin;
450 ierr = PetscNewLog(v,&hdf5);CHKERRQ(ierr);
451
452 v->data = (void*) hdf5;
453 v->ops->destroy = PetscViewerDestroy_HDF5;
454 v->ops->setfromoptions = PetscViewerSetFromOptions_HDF5;
455 v->ops->setup = PetscViewerSetUp_HDF5;
456 v->ops->view = PetscViewerView_HDF5;
457 v->ops->flush = NULL;
458 hdf5->btype = (PetscFileMode) -1;
459 hdf5->filename = NULL;
460 hdf5->timestep = -1;
461 hdf5->groups = NULL;
462
463 PetscStackCallHDF5Return(hdf5->dxpl_id,H5Pcreate,(H5P_DATASET_XFER));
464
465 ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileSetName_C",PetscViewerFileSetName_HDF5);CHKERRQ(ierr);
466 ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileGetName_C",PetscViewerFileGetName_HDF5);CHKERRQ(ierr);
467 ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileSetMode_C",PetscViewerFileSetMode_HDF5);CHKERRQ(ierr);
468 ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileGetMode_C",PetscViewerFileGetMode_HDF5);CHKERRQ(ierr);
469 ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerHDF5SetBaseDimension2_C",PetscViewerHDF5SetBaseDimension2_HDF5);CHKERRQ(ierr);
470 ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerHDF5SetSPOutput_C",PetscViewerHDF5SetSPOutput_HDF5);CHKERRQ(ierr);
471 ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerHDF5SetCollective_C",PetscViewerHDF5SetCollective_HDF5);CHKERRQ(ierr);
472 ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerHDF5GetCollective_C",PetscViewerHDF5GetCollective_HDF5);CHKERRQ(ierr);
473 PetscFunctionReturn(0);
474 }
475
476 /*@C
477 PetscViewerHDF5Open - Opens a file for HDF5 input/output.
478
479 Collective
480
481 Input Parameters:
482 + comm - MPI communicator
483 . name - name of file
484 - type - type of file
485 $ FILE_MODE_WRITE - create new file for binary output
486 $ FILE_MODE_READ - open existing file for binary input
487 $ FILE_MODE_APPEND - open existing file for binary output
488
489 Output Parameter:
490 . hdf5v - PetscViewer for HDF5 input/output to use with the specified file
491
492 Options Database:
493 + -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
494 - -viewer_hdf5_sp_output - forces (if true) the viewer to write data in single precision independent on the precision of PetscReal
495
496 Level: beginner
497
498 Note:
499 This PetscViewer should be destroyed with PetscViewerDestroy().
500
501
502 .seealso: PetscViewerASCIIOpen(), PetscViewerPushFormat(), PetscViewerDestroy(), PetscViewerHDF5SetBaseDimension2(),
503 PetscViewerHDF5SetSPOutput(), PetscViewerHDF5GetBaseDimension2(), VecView(), MatView(), VecLoad(),
504 MatLoad(), PetscFileMode, PetscViewer, PetscViewerSetType(), PetscViewerFileSetMode(), PetscViewerFileSetName()
505 @*/
PetscViewerHDF5Open(MPI_Comm comm,const char name[],PetscFileMode type,PetscViewer * hdf5v)506 PetscErrorCode PetscViewerHDF5Open(MPI_Comm comm, const char name[], PetscFileMode type, PetscViewer *hdf5v)
507 {
508 PetscErrorCode ierr;
509
510 PetscFunctionBegin;
511 ierr = PetscViewerCreate(comm, hdf5v);CHKERRQ(ierr);
512 ierr = PetscViewerSetType(*hdf5v, PETSCVIEWERHDF5);CHKERRQ(ierr);
513 ierr = PetscViewerFileSetMode(*hdf5v, type);CHKERRQ(ierr);
514 ierr = PetscViewerFileSetName(*hdf5v, name);CHKERRQ(ierr);
515 ierr = PetscViewerSetFromOptions(*hdf5v);CHKERRQ(ierr);
516 PetscFunctionReturn(0);
517 }
518
519 /*@C
520 PetscViewerHDF5GetFileId - Retrieve the file id, this file ID then can be used in direct HDF5 calls
521
522 Not collective
523
524 Input Parameter:
525 . viewer - the PetscViewer
526
527 Output Parameter:
528 . file_id - The file id
529
530 Level: intermediate
531
532 .seealso: PetscViewerHDF5Open()
533 @*/
PetscViewerHDF5GetFileId(PetscViewer viewer,hid_t * file_id)534 PetscErrorCode PetscViewerHDF5GetFileId(PetscViewer viewer, hid_t *file_id)
535 {
536 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;
537
538 PetscFunctionBegin;
539 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
540 if (file_id) *file_id = hdf5->file_id;
541 PetscFunctionReturn(0);
542 }
543
544 /*@C
545 PetscViewerHDF5PushGroup - Set the current HDF5 group for output
546
547 Not collective
548
549 Input Parameters:
550 + viewer - the PetscViewer
551 - name - The group name
552
553 Level: intermediate
554
555 Note: The group name being NULL, empty string, or a sequence of all slashes (e.g. "///") is always internally stored as NULL and interpreted as "/".
556
557 .seealso: PetscViewerHDF5Open(),PetscViewerHDF5PopGroup(),PetscViewerHDF5GetGroup(),PetscViewerHDF5OpenGroup()
558 @*/
PetscViewerHDF5PushGroup(PetscViewer viewer,const char name[])559 PetscErrorCode PetscViewerHDF5PushGroup(PetscViewer viewer, const char name[])
560 {
561 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;
562 PetscViewerHDF5GroupList *groupNode;
563 PetscErrorCode ierr;
564
565 PetscFunctionBegin;
566 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
567 if (name) PetscValidCharPointer(name,2);
568 if (name && name[0]) {
569 size_t i,len;
570 ierr = PetscStrlen(name, &len);CHKERRQ(ierr);
571 for (i=0; i<len; i++) if (name[i] != '/') break;
572 if (i == len) name = NULL;
573 } else name = NULL;
574 ierr = PetscNew(&groupNode);CHKERRQ(ierr);
575 ierr = PetscStrallocpy(name, (char**) &groupNode->name);CHKERRQ(ierr);
576 groupNode->next = hdf5->groups;
577 hdf5->groups = groupNode;
578 PetscFunctionReturn(0);
579 }
580
581 /*@
582 PetscViewerHDF5PopGroup - Return the current HDF5 group for output to the previous value
583
584 Not collective
585
586 Input Parameter:
587 . viewer - the PetscViewer
588
589 Level: intermediate
590
591 .seealso: PetscViewerHDF5Open(),PetscViewerHDF5PushGroup(),PetscViewerHDF5GetGroup(),PetscViewerHDF5OpenGroup()
592 @*/
PetscViewerHDF5PopGroup(PetscViewer viewer)593 PetscErrorCode PetscViewerHDF5PopGroup(PetscViewer viewer)
594 {
595 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;
596 PetscViewerHDF5GroupList *groupNode;
597 PetscErrorCode ierr;
598
599 PetscFunctionBegin;
600 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
601 if (!hdf5->groups) SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "HDF5 group stack is empty, cannot pop");
602 groupNode = hdf5->groups;
603 hdf5->groups = hdf5->groups->next;
604 ierr = PetscFree(groupNode->name);CHKERRQ(ierr);
605 ierr = PetscFree(groupNode);CHKERRQ(ierr);
606 PetscFunctionReturn(0);
607 }
608
609 /*@C
610 PetscViewerHDF5GetGroup - Get the current HDF5 group name (full path), set with PetscViewerHDF5PushGroup()/PetscViewerHDF5PopGroup().
611 If none has been assigned, returns NULL.
612
613 Not collective
614
615 Input Parameter:
616 . viewer - the PetscViewer
617
618 Output Parameter:
619 . name - The group name
620
621 Level: intermediate
622
623 .seealso: PetscViewerHDF5Open(),PetscViewerHDF5PushGroup(),PetscViewerHDF5PopGroup(),PetscViewerHDF5OpenGroup()
624 @*/
PetscViewerHDF5GetGroup(PetscViewer viewer,const char * name[])625 PetscErrorCode PetscViewerHDF5GetGroup(PetscViewer viewer, const char *name[])
626 {
627 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *) viewer->data;
628
629 PetscFunctionBegin;
630 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
631 PetscValidPointer(name,2);
632 if (hdf5->groups) *name = hdf5->groups->name;
633 else *name = NULL;
634 PetscFunctionReturn(0);
635 }
636
637 /*@
638 PetscViewerHDF5OpenGroup - Open the HDF5 group with the name (full path) returned by PetscViewerHDF5GetGroup(),
639 and return this group's ID and file ID.
640 If PetscViewerHDF5GetGroup() yields NULL, then group ID is file ID.
641
642 Not collective
643
644 Input Parameter:
645 . viewer - the PetscViewer
646
647 Output Parameter:
648 + fileId - The HDF5 file ID
649 - groupId - The HDF5 group ID
650
651 Notes:
652 If the viewer is writable, the group is created if it doesn't exist yet.
653
654 Level: intermediate
655
656 .seealso: PetscViewerHDF5Open(),PetscViewerHDF5PushGroup(),PetscViewerHDF5PopGroup(),PetscViewerHDF5GetGroup()
657 @*/
PetscViewerHDF5OpenGroup(PetscViewer viewer,hid_t * fileId,hid_t * groupId)658 PetscErrorCode PetscViewerHDF5OpenGroup(PetscViewer viewer, hid_t *fileId, hid_t *groupId)
659 {
660 hid_t file_id;
661 H5O_type_t type;
662 const char *groupName = NULL;
663 PetscBool create;
664 PetscErrorCode ierr;
665
666 PetscFunctionBegin;
667 ierr = PetscViewerWritable(viewer, &create);CHKERRQ(ierr);
668 ierr = PetscViewerHDF5GetFileId(viewer, &file_id);CHKERRQ(ierr);
669 ierr = PetscViewerHDF5GetGroup(viewer, &groupName);CHKERRQ(ierr);
670 ierr = PetscViewerHDF5Traverse_Internal(viewer, groupName, create, 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 @*/
PetscViewerHDF5IncrementTimestep(PetscViewer viewer)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 @*/
PetscViewerHDF5SetTimestep(PetscViewer viewer,PetscInt timestep)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 @*/
PetscViewerHDF5GetTimestep(PetscViewer viewer,PetscInt * timestep)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 @*/
PetscDataTypeToHDF5DataType(PetscDataType ptype,hid_t * htype)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_INT;
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 @*/
PetscHDF5DataTypeToPetscDataType(hid_t htype,PetscDataType * ptype)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 @*/
PetscViewerHDF5WriteAttribute(PetscViewer viewer,const char dataset[],const char name[],PetscDataType datatype,const void * value)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 @*/
PetscViewerHDF5WriteObjectAttribute(PetscViewer viewer,PetscObject obj,const char name[],PetscDataType datatype,const void * value)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 Notes: If the datatype is PETSC_STRING one must PetscFree() the obtained value when it is no longer needed.
918
919 Level: advanced
920
921 .seealso: PetscViewerHDF5Open(), PetscViewerHDF5ReadObjectAttribute(), PetscViewerHDF5WriteAttribute(), PetscViewerHDF5HasAttribute(), PetscViewerHDF5HasObject(), PetscViewerHDF5PushGroup(),PetscViewerHDF5PopGroup(),PetscViewerHDF5GetGroup()
922 @*/
PetscViewerHDF5ReadAttribute(PetscViewer viewer,const char dataset[],const char name[],PetscDataType datatype,void * value)923 PetscErrorCode PetscViewerHDF5ReadAttribute(PetscViewer viewer, const char dataset[], const char name[], PetscDataType datatype, void *value)
924 {
925 char *parent;
926 hid_t h5, obj, attribute, atype, dtype;
927 PetscBool has;
928 PetscErrorCode ierr;
929
930 PetscFunctionBegin;
931 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
932 if (dataset) PetscValidCharPointer(dataset, 2);
933 PetscValidCharPointer(name, 3);
934 PetscValidPointer(value, 5);
935 ierr = PetscViewerHDF5GetAbsolutePath_Internal(viewer, dataset, &parent);CHKERRQ(ierr);
936 ierr = PetscViewerHDF5Traverse_Internal(viewer, parent, PETSC_FALSE, &has, NULL);CHKERRQ(ierr);
937 if (has) {ierr = PetscViewerHDF5HasAttribute_Internal(viewer, parent, name, &has);CHKERRQ(ierr);}
938 if (!has) SETERRQ2(PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Attribute %s/%s does not exist", parent, name);
939 ierr = PetscDataTypeToHDF5DataType(datatype, &dtype);CHKERRQ(ierr);
940 ierr = PetscViewerHDF5GetFileId(viewer, &h5);CHKERRQ(ierr);
941 PetscStackCallHDF5Return(obj,H5Oopen,(h5, parent, H5P_DEFAULT));
942 PetscStackCallHDF5Return(attribute,H5Aopen_name,(obj, name));
943 if (datatype == PETSC_STRING) {
944 size_t len;
945 PetscStackCallHDF5Return(atype,H5Aget_type,(attribute));
946 PetscStackCall("H5Tget_size",len = H5Tget_size(atype));
947 ierr = PetscMalloc((len+1) * sizeof(char), value);CHKERRQ(ierr);
948 PetscStackCallHDF5(H5Tset_size,(dtype, len+1));
949 PetscStackCallHDF5(H5Aread,(attribute, dtype, *(char**)value));
950 } else {
951 PetscStackCallHDF5(H5Aread,(attribute, dtype, value));
952 }
953 PetscStackCallHDF5(H5Aclose,(attribute));
954 /* H5Oclose can be used to close groups, datasets, or committed datatypes */
955 PetscStackCallHDF5(H5Oclose,(obj));
956 ierr = PetscFree(parent);CHKERRQ(ierr);
957 PetscFunctionReturn(0);
958 }
959
960 /*@C
961 PetscViewerHDF5ReadObjectAttribute - Read an attribute from the dataset matching the given PetscObject by name
962
963 Input Parameters:
964 + viewer - The HDF5 viewer
965 . obj - The object whose name is used to lookup the parent dataset, relative to the current group.
966 . name - The attribute name
967 - datatype - The attribute type
968
969 Output Parameter:
970 . value - The attribute value
971
972 Notes:
973 This fails if current_group/object_name doesn't resolve to a dataset (the path doesn't exist or is not a dataset).
974 You might want to check first if it does using PetscViewerHDF5HasObject().
975
976 Level: advanced
977
978 .seealso: PetscViewerHDF5Open(), PetscViewerHDF5ReadAttribute() PetscViewerHDF5WriteObjectAttribute(), PetscViewerHDF5HasObjectAttribute(), PetscViewerHDF5PushGroup(),PetscViewerHDF5PopGroup(),PetscViewerHDF5GetGroup()
979 @*/
PetscViewerHDF5ReadObjectAttribute(PetscViewer viewer,PetscObject obj,const char name[],PetscDataType datatype,void * value)980 PetscErrorCode PetscViewerHDF5ReadObjectAttribute(PetscViewer viewer, PetscObject obj, const char name[], PetscDataType datatype, void *value)
981 {
982 PetscErrorCode ierr;
983
984 PetscFunctionBegin;
985 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
986 PetscValidHeader(obj,2);
987 PetscValidCharPointer(name,3);
988 PetscValidPointer(value, 5);
989 ierr = PetscViewerHDF5CheckNamedObject_Internal(viewer, obj);CHKERRQ(ierr);
990 ierr = PetscViewerHDF5ReadAttribute(viewer, obj->name, name, datatype, value);CHKERRQ(ierr);
991 PetscFunctionReturn(0);
992 }
993
PetscViewerHDF5Traverse_Inner_Internal(hid_t h5,const char name[],PetscBool createGroup,PetscBool * exists_)994 PETSC_STATIC_INLINE PetscErrorCode PetscViewerHDF5Traverse_Inner_Internal(hid_t h5, const char name[], PetscBool createGroup, PetscBool *exists_)
995 {
996 htri_t exists;
997 hid_t group;
998
999 PetscFunctionBegin;
1000 PetscStackCallHDF5Return(exists,H5Lexists,(h5, name, H5P_DEFAULT));
1001 if (exists) PetscStackCallHDF5Return(exists,H5Oexists_by_name,(h5, name, H5P_DEFAULT));
1002 if (!exists && createGroup) {
1003 PetscStackCallHDF5Return(group,H5Gcreate2,(h5, name, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT));
1004 PetscStackCallHDF5(H5Gclose,(group));
1005 exists = PETSC_TRUE;
1006 }
1007 *exists_ = (PetscBool) exists;
1008 PetscFunctionReturn(0);
1009 }
1010
PetscViewerHDF5Traverse_Internal(PetscViewer viewer,const char name[],PetscBool createGroup,PetscBool * has,H5O_type_t * otype)1011 static PetscErrorCode PetscViewerHDF5Traverse_Internal(PetscViewer viewer, const char name[], PetscBool createGroup, PetscBool *has, H5O_type_t *otype)
1012 {
1013 const char rootGroupName[] = "/";
1014 hid_t h5;
1015 PetscBool exists=PETSC_FALSE;
1016 PetscInt i;
1017 int n;
1018 char **hierarchy;
1019 char buf[PETSC_MAX_PATH_LEN]="";
1020 PetscErrorCode ierr;
1021
1022 PetscFunctionBegin;
1023 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
1024 if (name) PetscValidCharPointer(name, 2);
1025 else name = rootGroupName;
1026 if (has) {
1027 PetscValidIntPointer(has, 3);
1028 *has = PETSC_FALSE;
1029 }
1030 if (otype) {
1031 PetscValidIntPointer(otype, 4);
1032 *otype = H5O_TYPE_UNKNOWN;
1033 }
1034 ierr = PetscViewerHDF5GetFileId(viewer, &h5);CHKERRQ(ierr);
1035
1036 /*
1037 Unfortunately, H5Oexists_by_name() fails if any object in hierarchy is missing.
1038 Hence, each of them needs to be tested separately:
1039 1) whether it's a valid link
1040 2) whether this link resolves to an object
1041 See H5Oexists_by_name() documentation.
1042 */
1043 ierr = PetscStrToArray(name,'/',&n,&hierarchy);CHKERRQ(ierr);
1044 if (!n) {
1045 /* Assume group "/" always exists in accordance with HDF5 >= 1.10.0. See H5Lexists() documentation. */
1046 if (has) *has = PETSC_TRUE;
1047 if (otype) *otype = H5O_TYPE_GROUP;
1048 ierr = PetscStrToArrayDestroy(n,hierarchy);CHKERRQ(ierr);
1049 PetscFunctionReturn(0);
1050 }
1051 for (i=0; i<n; i++) {
1052 ierr = PetscStrcat(buf,"/");CHKERRQ(ierr);
1053 ierr = PetscStrcat(buf,hierarchy[i]);CHKERRQ(ierr);
1054 ierr = PetscViewerHDF5Traverse_Inner_Internal(h5, buf, createGroup, &exists);CHKERRQ(ierr);
1055 if (!exists) break;
1056 }
1057 ierr = PetscStrToArrayDestroy(n,hierarchy);CHKERRQ(ierr);
1058
1059 /* If the object exists, get its type */
1060 if (exists && otype) {
1061 H5O_info_t info;
1062
1063 /* We could use H5Iget_type() here but that would require opening the object. This way we only need its name. */
1064 PetscStackCallHDF5(H5Oget_info_by_name,(h5, name, &info, H5P_DEFAULT));
1065 *otype = info.type;
1066 }
1067 if (has) *has = exists;
1068 PetscFunctionReturn(0);
1069 }
1070
1071 /*@
1072 PetscViewerHDF5HasGroup - Check whether the current (pushed) group exists in the HDF5 file
1073
1074 Input Parameters:
1075 . viewer - The HDF5 viewer
1076
1077 Output Parameter:
1078 . has - Flag for group existence
1079
1080 Notes:
1081 If the path exists but is not a group, this returns PETSC_FALSE as well.
1082
1083 Level: advanced
1084
1085 .seealso: PetscViewerHDF5Open(), PetscViewerHDF5PushGroup(), PetscViewerHDF5PopGroup(), PetscViewerHDF5OpenGroup()
1086 @*/
PetscViewerHDF5HasGroup(PetscViewer viewer,PetscBool * has)1087 PetscErrorCode PetscViewerHDF5HasGroup(PetscViewer viewer, PetscBool *has)
1088 {
1089 H5O_type_t type;
1090 const char *name;
1091 PetscErrorCode ierr;
1092
1093 PetscFunctionBegin;
1094 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
1095 PetscValidIntPointer(has,2);
1096 ierr = PetscViewerHDF5GetGroup(viewer, &name);CHKERRQ(ierr);
1097 ierr = PetscViewerHDF5Traverse_Internal(viewer, name, PETSC_FALSE, has, &type);CHKERRQ(ierr);
1098 *has = (type == H5O_TYPE_GROUP) ? PETSC_TRUE : PETSC_FALSE;
1099 PetscFunctionReturn(0);
1100 }
1101
1102 /*@
1103 PetscViewerHDF5HasObject - Check whether a dataset with the same name as given object exists in the HDF5 file under current group
1104
1105 Input Parameters:
1106 + viewer - The HDF5 viewer
1107 - obj - The named object
1108
1109 Output Parameter:
1110 . has - Flag for dataset existence; PETSC_FALSE for unnamed object
1111
1112 Notes:
1113 If the path exists but is not a dataset, this returns PETSC_FALSE as well.
1114
1115 Level: advanced
1116
1117 .seealso: PetscViewerHDF5Open(), PetscViewerHDF5HasAttribute(), PetscViewerHDF5PushGroup(),PetscViewerHDF5PopGroup(),PetscViewerHDF5GetGroup()
1118 @*/
PetscViewerHDF5HasObject(PetscViewer viewer,PetscObject obj,PetscBool * has)1119 PetscErrorCode PetscViewerHDF5HasObject(PetscViewer viewer, PetscObject obj, PetscBool *has)
1120 {
1121 H5O_type_t type;
1122 char *path;
1123 PetscErrorCode ierr;
1124
1125 PetscFunctionBegin;
1126 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
1127 PetscValidHeader(obj,2);
1128 PetscValidIntPointer(has,3);
1129 *has = PETSC_FALSE;
1130 if (!obj->name) PetscFunctionReturn(0);
1131 ierr = PetscViewerHDF5GetAbsolutePath_Internal(viewer, obj->name, &path);CHKERRQ(ierr);
1132 ierr = PetscViewerHDF5Traverse_Internal(viewer, path, PETSC_FALSE, has, &type);CHKERRQ(ierr);
1133 *has = (type == H5O_TYPE_DATASET) ? PETSC_TRUE : PETSC_FALSE;
1134 ierr = PetscFree(path);CHKERRQ(ierr);
1135 PetscFunctionReturn(0);
1136 }
1137
1138 /*@C
1139 PetscViewerHDF5HasAttribute - Check whether an attribute exists
1140
1141 Input Parameters:
1142 + viewer - The HDF5 viewer
1143 . dataset - The parent dataset name, relative to the current group. NULL means a group-wise attribute.
1144 - name - The attribute name
1145
1146 Output Parameter:
1147 . has - Flag for attribute existence
1148
1149 Level: advanced
1150
1151 .seealso: PetscViewerHDF5Open(), PetscViewerHDF5HasObjectAttribute(), PetscViewerHDF5WriteAttribute(), PetscViewerHDF5ReadAttribute(), PetscViewerHDF5PushGroup(),PetscViewerHDF5PopGroup(),PetscViewerHDF5GetGroup()
1152 @*/
PetscViewerHDF5HasAttribute(PetscViewer viewer,const char dataset[],const char name[],PetscBool * has)1153 PetscErrorCode PetscViewerHDF5HasAttribute(PetscViewer viewer, const char dataset[], const char name[], PetscBool *has)
1154 {
1155 char *parent;
1156 PetscErrorCode ierr;
1157
1158 PetscFunctionBegin;
1159 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
1160 if (dataset) PetscValidCharPointer(dataset,2);
1161 PetscValidCharPointer(name,3);
1162 PetscValidIntPointer(has,4);
1163 ierr = PetscViewerHDF5GetAbsolutePath_Internal(viewer, dataset, &parent);CHKERRQ(ierr);
1164 ierr = PetscViewerHDF5Traverse_Internal(viewer, parent, PETSC_FALSE, has, NULL);CHKERRQ(ierr);
1165 if (*has) {ierr = PetscViewerHDF5HasAttribute_Internal(viewer, parent, name, has);CHKERRQ(ierr);}
1166 ierr = PetscFree(parent);CHKERRQ(ierr);
1167 PetscFunctionReturn(0);
1168 }
1169
1170 /*@C
1171 PetscViewerHDF5HasObjectAttribute - Check whether an attribute is attached to the dataset matching the given PetscObject by name
1172
1173 Input Parameters:
1174 + viewer - The HDF5 viewer
1175 . obj - The object whose name is used to lookup the parent dataset, relative to the current group.
1176 - name - The attribute name
1177
1178 Output Parameter:
1179 . has - Flag for attribute existence
1180
1181 Notes:
1182 This fails if current_group/object_name doesn't resolve to a dataset (the path doesn't exist or is not a dataset).
1183 You might want to check first if it does using PetscViewerHDF5HasObject().
1184
1185 Level: advanced
1186
1187 .seealso: PetscViewerHDF5Open(), PetscViewerHDF5HasAttribute(), PetscViewerHDF5WriteObjectAttribute(), PetscViewerHDF5ReadObjectAttribute(), PetscViewerHDF5HasObject(), PetscViewerHDF5PushGroup(),PetscViewerHDF5PopGroup(),PetscViewerHDF5GetGroup()
1188 @*/
PetscViewerHDF5HasObjectAttribute(PetscViewer viewer,PetscObject obj,const char name[],PetscBool * has)1189 PetscErrorCode PetscViewerHDF5HasObjectAttribute(PetscViewer viewer, PetscObject obj, const char name[], PetscBool *has)
1190 {
1191 PetscErrorCode ierr;
1192
1193 PetscFunctionBegin;
1194 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
1195 PetscValidHeader(obj,2);
1196 PetscValidCharPointer(name,3);
1197 PetscValidIntPointer(has,4);
1198 ierr = PetscViewerHDF5CheckNamedObject_Internal(viewer, obj);CHKERRQ(ierr);
1199 ierr = PetscViewerHDF5HasAttribute(viewer, obj->name, name, has);CHKERRQ(ierr);
1200 PetscFunctionReturn(0);
1201 }
1202
PetscViewerHDF5HasAttribute_Internal(PetscViewer viewer,const char parent[],const char name[],PetscBool * has)1203 static PetscErrorCode PetscViewerHDF5HasAttribute_Internal(PetscViewer viewer, const char parent[], const char name[], PetscBool *has)
1204 {
1205 hid_t h5;
1206 htri_t hhas;
1207 PetscErrorCode ierr;
1208
1209 PetscFunctionBegin;
1210 ierr = PetscViewerHDF5GetFileId(viewer, &h5);CHKERRQ(ierr);
1211 PetscStackCallHDF5Return(hhas,H5Aexists_by_name,(h5, parent, name, H5P_DEFAULT));
1212 *has = hhas ? PETSC_TRUE : PETSC_FALSE;
1213 PetscFunctionReturn(0);
1214 }
1215
1216 /*
1217 The variable Petsc_Viewer_HDF5_keyval is used to indicate an MPI attribute that
1218 is attached to a communicator, in this case the attribute is a PetscViewer.
1219 */
1220 PetscMPIInt Petsc_Viewer_HDF5_keyval = MPI_KEYVAL_INVALID;
1221
1222 /*@C
1223 PETSC_VIEWER_HDF5_ - Creates an HDF5 PetscViewer shared by all processors in a communicator.
1224
1225 Collective
1226
1227 Input Parameter:
1228 . comm - the MPI communicator to share the HDF5 PetscViewer
1229
1230 Level: intermediate
1231
1232 Options Database Keys:
1233 . -viewer_hdf5_filename <name>
1234
1235 Environmental variables:
1236 . PETSC_VIEWER_HDF5_FILENAME
1237
1238 Notes:
1239 Unlike almost all other PETSc routines, PETSC_VIEWER_HDF5_ does not return
1240 an error code. The HDF5 PetscViewer is usually used in the form
1241 $ XXXView(XXX object, PETSC_VIEWER_HDF5_(comm));
1242
1243 .seealso: PetscViewerHDF5Open(), PetscViewerCreate(), PetscViewerDestroy()
1244 @*/
PETSC_VIEWER_HDF5_(MPI_Comm comm)1245 PetscViewer PETSC_VIEWER_HDF5_(MPI_Comm comm)
1246 {
1247 PetscErrorCode ierr;
1248 PetscBool flg;
1249 PetscViewer viewer;
1250 char fname[PETSC_MAX_PATH_LEN];
1251 MPI_Comm ncomm;
1252
1253 PetscFunctionBegin;
1254 ierr = PetscCommDuplicate(comm,&ncomm,NULL);if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);}
1255 if (Petsc_Viewer_HDF5_keyval == MPI_KEYVAL_INVALID) {
1256 ierr = MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN,MPI_COMM_NULL_DELETE_FN,&Petsc_Viewer_HDF5_keyval,NULL);
1257 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);}
1258 }
1259 ierr = MPI_Comm_get_attr(ncomm,Petsc_Viewer_HDF5_keyval,(void**)&viewer,(int*)&flg);
1260 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);}
1261 if (!flg) { /* PetscViewer not yet created */
1262 ierr = PetscOptionsGetenv(ncomm,"PETSC_VIEWER_HDF5_FILENAME",fname,PETSC_MAX_PATH_LEN,&flg);
1263 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);}
1264 if (!flg) {
1265 ierr = PetscStrcpy(fname,"output.h5");
1266 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);}
1267 }
1268 ierr = PetscViewerHDF5Open(ncomm,fname,FILE_MODE_WRITE,&viewer);
1269 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);}
1270 ierr = PetscObjectRegisterDestroy((PetscObject)viewer);
1271 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);}
1272 ierr = MPI_Comm_set_attr(ncomm,Petsc_Viewer_HDF5_keyval,(void*)viewer);
1273 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);}
1274 }
1275 ierr = PetscCommDestroy(&ncomm);
1276 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);}
1277 PetscFunctionReturn(viewer);
1278 }
1279