Actual source code: hdf5v.c
1: #include <petsc/private/viewerhdf5impl.h>
3: static PetscErrorCode PetscViewerHDF5Traverse_Internal(PetscViewer, const char[], PetscBool, PetscBool*, H5O_type_t*);
4: static PetscErrorCode PetscViewerHDF5HasAttribute_Internal(PetscViewer, const char[], const char[], PetscBool*);
6: static PetscErrorCode PetscViewerHDF5GetAbsolutePath_Internal(PetscViewer viewer, const char path[], char *abspath[])
7: {
8: PetscBool relative = PETSC_FALSE;
9: const char *group;
10: char buf[PETSC_MAX_PATH_LEN] = "";
12: PetscViewerHDF5GetGroup(viewer, &group);
13: PetscViewerHDF5PathIsRelative(path, PETSC_TRUE, &relative);
14: if (relative) {
15: PetscStrcpy(buf, group);
16: PetscStrcat(buf, "/");
17: PetscStrcat(buf, path);
18: PetscStrallocpy(buf, abspath);
19: } else {
20: PetscStrallocpy(path, abspath);
21: }
22: return 0;
23: }
25: static PetscErrorCode PetscViewerHDF5CheckNamedObject_Internal(PetscViewer viewer, PetscObject obj)
26: {
27: PetscBool has;
29: PetscViewerHDF5HasObject(viewer, obj, &has);
30: if (!has) {
31: const char *group;
32: PetscViewerHDF5GetGroup(viewer, &group);
33: SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Object (dataset) \"%s\" not stored in group %s", obj->name, group ? group : "/");
34: }
35: return 0;
36: }
38: static PetscErrorCode PetscViewerSetFromOptions_HDF5(PetscOptionItems *PetscOptionsObject,PetscViewer v)
39: {
40: PetscBool flg = PETSC_FALSE, set;
41: PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*)v->data;
43: PetscOptionsHead(PetscOptionsObject,"HDF5 PetscViewer Options");
44: PetscOptionsBool("-viewer_hdf5_base_dimension2","1d Vectors get 2 dimensions in HDF5","PetscViewerHDF5SetBaseDimension2",hdf5->basedimension2,&hdf5->basedimension2,NULL);
45: PetscOptionsBool("-viewer_hdf5_sp_output","Force data to be written in single precision","PetscViewerHDF5SetSPOutput",hdf5->spoutput,&hdf5->spoutput,NULL);
46: PetscOptionsBool("-viewer_hdf5_collective","Enable collective transfer mode","PetscViewerHDF5SetCollective",flg,&flg,&set);
47: if (set) PetscViewerHDF5SetCollective(v,flg);
48: flg = PETSC_FALSE;
49: PetscOptionsBool("-viewer_hdf5_default_timestepping","Set default timestepping state","PetscViewerHDF5SetDefaultTimestepping",flg,&flg,&set);
50: if (set) PetscViewerHDF5SetDefaultTimestepping(v,flg);
51: PetscOptionsTail();
52: return 0;
53: }
55: static PetscErrorCode PetscViewerView_HDF5(PetscViewer v,PetscViewer viewer)
56: {
57: PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*)v->data;
58: PetscBool flg;
60: if (hdf5->filename) {
61: PetscViewerASCIIPrintf(viewer,"Filename: %s\n",hdf5->filename);
62: }
63: PetscViewerASCIIPrintf(viewer,"Vectors with blocksize 1 saved as 2D datasets: %s\n",PetscBools[hdf5->basedimension2]);
64: PetscViewerASCIIPrintf(viewer,"Enforce single precision storage: %s\n",PetscBools[hdf5->spoutput]);
65: PetscViewerHDF5GetCollective(v,&flg);
66: PetscViewerASCIIPrintf(viewer,"MPI-IO transfer mode: %s\n",flg ? "collective" : "independent");
67: PetscViewerASCIIPrintf(viewer,"Default timestepping: %s\n",PetscBools[hdf5->defTimestepping]);
68: return 0;
69: }
71: static PetscErrorCode PetscViewerFileClose_HDF5(PetscViewer viewer)
72: {
73: PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*)viewer->data;
75: PetscFree(hdf5->filename);
76: if (hdf5->file_id) PetscStackCallHDF5(H5Fclose,(hdf5->file_id));
77: return 0;
78: }
80: static PetscErrorCode PetscViewerFlush_HDF5(PetscViewer viewer)
81: {
82: PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*)viewer->data;
84: if (hdf5->file_id) PetscStackCallHDF5(H5Fflush,(hdf5->file_id, H5F_SCOPE_LOCAL));
85: return 0;
86: }
88: static PetscErrorCode PetscViewerDestroy_HDF5(PetscViewer viewer)
89: {
90: PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;
92: PetscStackCallHDF5(H5Pclose,(hdf5->dxpl_id));
93: PetscViewerFileClose_HDF5(viewer);
94: while (hdf5->groups) {
95: PetscViewerHDF5GroupList *tmp = hdf5->groups->next;
97: PetscFree(hdf5->groups->name);
98: PetscFree(hdf5->groups);
99: hdf5->groups = tmp;
100: }
101: PetscFree(hdf5);
102: PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerFileSetName_C",NULL);
103: PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerFileGetName_C",NULL);
104: PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerFileSetMode_C",NULL);
105: PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerHDF5SetBaseDimension2_C",NULL);
106: PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerHDF5SetSPOutput_C",NULL);
107: PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerHDF5GetDefaultTimestepping_C",NULL);
108: PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerHDF5SetDefaultTimestepping_C",NULL);
109: return 0;
110: }
112: static PetscErrorCode PetscViewerFileSetMode_HDF5(PetscViewer viewer, PetscFileMode type)
113: {
114: PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;
116: hdf5->btype = type;
117: return 0;
118: }
120: static PetscErrorCode PetscViewerFileGetMode_HDF5(PetscViewer viewer, PetscFileMode *type)
121: {
122: PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;
124: *type = hdf5->btype;
125: return 0;
126: }
128: static PetscErrorCode PetscViewerHDF5SetBaseDimension2_HDF5(PetscViewer viewer, PetscBool flg)
129: {
130: PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;
132: hdf5->basedimension2 = flg;
133: return 0;
134: }
136: /*@
137: PetscViewerHDF5SetBaseDimension2 - Vectors of 1 dimension (i.e. bs/dof is 1) will be saved in the HDF5 file with a
138: dimension of 2.
140: Logically Collective on PetscViewer
142: Input Parameters:
143: + viewer - the PetscViewer; if it is not hdf5 then this command is ignored
144: - flg - if PETSC_TRUE the vector will always have at least a dimension of 2 even if that first dimension is of size 1
146: Options Database:
147: . -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
149: Notes:
150: Setting this option allegedly makes code that reads the HDF5 in easier since they do not have a "special case" of a bs/dof
151: of one when the dimension is lower. Others think the option is crazy.
153: Level: intermediate
155: .seealso: PetscViewerFileSetMode(), PetscViewerCreate(), PetscViewerSetType(), PetscViewerBinaryOpen()
157: @*/
158: PetscErrorCode PetscViewerHDF5SetBaseDimension2(PetscViewer viewer,PetscBool flg)
159: {
161: PetscTryMethod(viewer,"PetscViewerHDF5SetBaseDimension2_C",(PetscViewer,PetscBool),(viewer,flg));
162: return 0;
163: }
165: /*@
166: PetscViewerHDF5GetBaseDimension2 - Vectors of 1 dimension (i.e. bs/dof is 1) will be saved in the HDF5 file with a
167: dimension of 2.
169: Logically Collective on PetscViewer
171: Input Parameter:
172: . viewer - the PetscViewer, must be of type HDF5
174: Output Parameter:
175: . flg - if PETSC_TRUE the vector will always have at least a dimension of 2 even if that first dimension is of size 1
177: Notes:
178: Setting this option allegedly makes code that reads the HDF5 in easier since they do not have a "special case" of a bs/dof
179: of one when the dimension is lower. Others think the option is crazy.
181: Level: intermediate
183: .seealso: PetscViewerFileSetMode(), PetscViewerCreate(), PetscViewerSetType(), PetscViewerBinaryOpen()
185: @*/
186: PetscErrorCode PetscViewerHDF5GetBaseDimension2(PetscViewer viewer,PetscBool *flg)
187: {
188: PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;
191: *flg = hdf5->basedimension2;
192: return 0;
193: }
195: static PetscErrorCode PetscViewerHDF5SetSPOutput_HDF5(PetscViewer viewer, PetscBool flg)
196: {
197: PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;
199: hdf5->spoutput = flg;
200: return 0;
201: }
203: /*@
204: PetscViewerHDF5SetSPOutput - Data is written to disk in single precision even if PETSc is
205: compiled with double precision PetscReal.
207: Logically Collective on PetscViewer
209: Input Parameters:
210: + viewer - the PetscViewer; if it is not hdf5 then this command is ignored
211: - flg - if PETSC_TRUE the data will be written to disk with single precision
213: Options Database:
214: . -viewer_hdf5_sp_output - turns on (true) or off (false) output in single precision
216: Notes:
217: Setting this option does not make any difference if PETSc is compiled with single precision
218: in the first place. It does not affect reading datasets (HDF5 handle this internally).
220: Level: intermediate
222: .seealso: PetscViewerFileSetMode(), PetscViewerCreate(), PetscViewerSetType(), PetscViewerBinaryOpen(),
223: PetscReal
225: @*/
226: PetscErrorCode PetscViewerHDF5SetSPOutput(PetscViewer viewer,PetscBool flg)
227: {
229: PetscTryMethod(viewer,"PetscViewerHDF5SetSPOutput_C",(PetscViewer,PetscBool),(viewer,flg));
230: return 0;
231: }
233: /*@
234: PetscViewerHDF5GetSPOutput - Data is written to disk in single precision even if PETSc is
235: compiled with double precision PetscReal.
237: Logically Collective on PetscViewer
239: Input Parameter:
240: . viewer - the PetscViewer, must be of type HDF5
242: Output Parameter:
243: . flg - if PETSC_TRUE the data will be written to disk with single precision
245: Notes:
246: Setting this option does not make any difference if PETSc is compiled with single precision
247: in the first place. It does not affect reading datasets (HDF5 handle this internally).
249: Level: intermediate
251: .seealso: PetscViewerFileSetMode(), PetscViewerCreate(), PetscViewerSetType(), PetscViewerBinaryOpen(),
252: PetscReal
254: @*/
255: PetscErrorCode PetscViewerHDF5GetSPOutput(PetscViewer viewer,PetscBool *flg)
256: {
257: PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;
260: *flg = hdf5->spoutput;
261: return 0;
262: }
264: static PetscErrorCode PetscViewerHDF5SetCollective_HDF5(PetscViewer viewer, PetscBool flg)
265: {
266: /* H5FD_MPIO_COLLECTIVE is wrong in hdf5 1.10.2, and is the same as H5FD_MPIO_INDEPENDENT in earlier versions
267: - see e.g. https://gitlab.cosma.dur.ac.uk/swift/swiftsim/issues/431 */
268: #if H5_VERSION_GE(1,10,3) && defined(H5_HAVE_PARALLEL)
269: {
270: PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;
271: PetscStackCallHDF5(H5Pset_dxpl_mpio,(hdf5->dxpl_id, flg ? H5FD_MPIO_COLLECTIVE : H5FD_MPIO_INDEPENDENT));
272: }
273: #else
274: if (flg) 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");
275: #endif
276: return 0;
277: }
279: /*@
280: PetscViewerHDF5SetCollective - Use collective MPI-IO transfer mode for HDF5 reads and writes.
282: Logically Collective; flg must contain common value
284: Input Parameters:
285: + viewer - the PetscViewer; if it is not hdf5 then this command is ignored
286: - flg - PETSC_TRUE for collective mode; PETSC_FALSE for independent mode (default)
288: Options Database:
289: . -viewer_hdf5_collective - turns on (true) or off (false) collective transfers
291: Notes:
292: Collective mode gives the MPI-IO layer underneath HDF5 a chance to do some additional collective optimizations and hence can perform better.
293: 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.
295: Developer notes:
296: In the HDF5 layer, PETSC_TRUE / PETSC_FALSE means H5Pset_dxpl_mpio() is called with H5FD_MPIO_COLLECTIVE / H5FD_MPIO_INDEPENDENT, respectively.
297: This in turn means use of MPI_File_{read,write}_all / MPI_File_{read,write} in the MPI-IO layer, respectively.
298: See HDF5 documentation and MPI-IO documentation for details.
300: Level: intermediate
302: .seealso: PetscViewerHDF5GetCollective(), PetscViewerCreate(), PetscViewerSetType(), PetscViewerHDF5Open()
304: @*/
305: PetscErrorCode PetscViewerHDF5SetCollective(PetscViewer viewer,PetscBool flg)
306: {
309: PetscTryMethod(viewer,"PetscViewerHDF5SetCollective_C",(PetscViewer,PetscBool),(viewer,flg));
310: return 0;
311: }
313: static PetscErrorCode PetscViewerHDF5GetCollective_HDF5(PetscViewer viewer, PetscBool *flg)
314: {
315: #if defined(H5_HAVE_PARALLEL)
316: PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;
317: H5FD_mpio_xfer_t mode;
318: #endif
320: #if !defined(H5_HAVE_PARALLEL)
321: *flg = PETSC_FALSE;
322: #else
323: PetscStackCallHDF5(H5Pget_dxpl_mpio,(hdf5->dxpl_id, &mode));
324: *flg = (mode == H5FD_MPIO_COLLECTIVE) ? PETSC_TRUE : PETSC_FALSE;
325: #endif
326: return 0;
327: }
329: /*@
330: PetscViewerHDF5GetCollective - Return flag whether collective MPI-IO transfer mode is used for HDF5 reads and writes.
332: Not Collective
334: Input Parameters:
335: . viewer - the HDF5 PetscViewer
337: Output Parameters:
338: . flg - the flag
340: Level: intermediate
342: Notes:
343: 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.
344: For more details, see PetscViewerHDF5SetCollective().
346: .seealso: PetscViewerHDF5SetCollective(), PetscViewerCreate(), PetscViewerSetType(), PetscViewerHDF5Open()
348: @*/
349: PetscErrorCode PetscViewerHDF5GetCollective(PetscViewer viewer,PetscBool *flg)
350: {
354: PetscUseMethod(viewer,"PetscViewerHDF5GetCollective_C",(PetscViewer,PetscBool*),(viewer,flg));
355: return 0;
356: }
358: static PetscErrorCode PetscViewerFileSetName_HDF5(PetscViewer viewer, const char name[])
359: {
360: PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;
361: hid_t plist_id;
363: if (hdf5->file_id) PetscStackCallHDF5(H5Fclose,(hdf5->file_id));
364: if (hdf5->filename) PetscFree(hdf5->filename);
365: PetscStrallocpy(name, &hdf5->filename);
366: /* Set up file access property list with parallel I/O access */
367: PetscStackCallHDF5Return(plist_id,H5Pcreate,(H5P_FILE_ACCESS));
368: #if defined(H5_HAVE_PARALLEL)
369: PetscStackCallHDF5(H5Pset_fapl_mpio,(plist_id, PetscObjectComm((PetscObject)viewer), MPI_INFO_NULL));
370: #endif
371: /* Create or open the file collectively */
372: switch (hdf5->btype) {
373: case FILE_MODE_READ:
374: if (PetscDefined(USE_DEBUG)) {
375: PetscMPIInt rank;
376: PetscBool flg;
378: MPI_Comm_rank(PetscObjectComm((PetscObject)viewer),&rank);
379: if (rank == 0) {
380: PetscTestFile(hdf5->filename, 'r', &flg);
382: }
383: MPI_Barrier(PetscObjectComm((PetscObject)viewer));
384: }
385: PetscStackCallHDF5Return(hdf5->file_id,H5Fopen,(name, H5F_ACC_RDONLY, plist_id));
386: break;
387: case FILE_MODE_APPEND:
388: case FILE_MODE_UPDATE:
389: {
390: PetscBool flg;
391: PetscTestFile(hdf5->filename, 'r', &flg);
392: if (flg) PetscStackCallHDF5Return(hdf5->file_id,H5Fopen,(name, H5F_ACC_RDWR, plist_id));
393: else PetscStackCallHDF5Return(hdf5->file_id,H5Fcreate,(name, H5F_ACC_EXCL, H5P_DEFAULT, plist_id));
394: break;
395: }
396: case FILE_MODE_WRITE:
397: PetscStackCallHDF5Return(hdf5->file_id,H5Fcreate,(name, H5F_ACC_TRUNC, H5P_DEFAULT, plist_id));
398: break;
399: case FILE_MODE_UNDEFINED:
400: SETERRQ(PetscObjectComm((PetscObject)viewer),PETSC_ERR_ORDER, "Must call PetscViewerFileSetMode() before PetscViewerFileSetName()");
401: default:
402: SETERRQ(PetscObjectComm((PetscObject)viewer),PETSC_ERR_SUP, "Unsupported file mode %s",PetscFileModes[hdf5->btype]);
403: }
405: PetscStackCallHDF5(H5Pclose,(plist_id));
406: return 0;
407: }
409: static PetscErrorCode PetscViewerFileGetName_HDF5(PetscViewer viewer,const char **name)
410: {
411: PetscViewer_HDF5 *vhdf5 = (PetscViewer_HDF5*)viewer->data;
413: *name = vhdf5->filename;
414: return 0;
415: }
417: static PetscErrorCode PetscViewerSetUp_HDF5(PetscViewer viewer)
418: {
419: /*
420: PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;
421: */
423: return 0;
424: }
426: static PetscErrorCode PetscViewerHDF5SetDefaultTimestepping_HDF5(PetscViewer viewer, PetscBool flg)
427: {
428: PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;
430: hdf5->defTimestepping = flg;
431: return 0;
432: }
434: static PetscErrorCode PetscViewerHDF5GetDefaultTimestepping_HDF5(PetscViewer viewer, PetscBool *flg)
435: {
436: PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;
438: *flg = hdf5->defTimestepping;
439: return 0;
440: }
442: /*@
443: PetscViewerHDF5SetDefaultTimestepping - Set the flag for default timestepping
445: Logically Collective on PetscViewer
447: Input Parameters:
448: + viewer - the PetscViewer; if it is not hdf5 then this command is ignored
449: - flg - if PETSC_TRUE we will assume that timestepping is on
451: Options Database:
452: . -viewer_hdf5_default_timestepping - turns on (true) or off (false) default timestepping
454: Notes:
455: If the timestepping attribute is not found for an object, then the default timestepping is used
457: Level: intermediate
459: .seealso: PetscViewerHDF5GetDefaultTimestepping(), PetscViewerHDF5PushTimestepping(), PetscViewerHDF5GetTimestep()
460: @*/
461: PetscErrorCode PetscViewerHDF5SetDefaultTimestepping(PetscViewer viewer, PetscBool flg)
462: {
464: PetscTryMethod(viewer, "PetscViewerHDF5SetDefaultTimestepping_C", (PetscViewer,PetscBool), (viewer,flg));
465: return 0;
466: }
468: /*@
469: PetscViewerHDF5GetDefaultTimestepping - Get the flag for default timestepping
471: Not collective
473: Input Parameter:
474: . viewer - the PetscViewer
476: Output Parameter:
477: . flg - if PETSC_TRUE we will assume that timestepping is on
479: Notes:
480: If the timestepping attribute is not found for an object, then the default timestepping is used
482: Level: intermediate
484: .seealso: PetscViewerHDF5SetDefaultTimestepping(), PetscViewerHDF5PushTimestepping(), PetscViewerHDF5GetTimestep()
485: @*/
486: PetscErrorCode PetscViewerHDF5GetDefaultTimestepping(PetscViewer viewer, PetscBool *flg)
487: {
489: PetscUseMethod(viewer, "PetscViewerHDF5GetDefaultTimestepping_C", (PetscViewer,PetscBool*), (viewer,flg));
490: return 0;
491: }
493: /*MC
494: PETSCVIEWERHDF5 - A viewer that writes to an HDF5 file
496: .seealso: PetscViewerHDF5Open(), PetscViewerStringSPrintf(), PetscViewerSocketOpen(), PetscViewerDrawOpen(), PETSCVIEWERSOCKET,
497: PetscViewerCreate(), PetscViewerASCIIOpen(), PetscViewerBinaryOpen(), PETSCVIEWERBINARY, PETSCVIEWERDRAW, PETSCVIEWERSTRING,
498: PetscViewerMatlabOpen(), VecView(), DMView(), PetscViewerMatlabPutArray(), PETSCVIEWERASCII, PETSCVIEWERMATLAB,
499: PetscViewerFileSetName(), PetscViewerFileSetMode(), PetscViewerFormat, PetscViewerType, PetscViewerSetType()
501: Level: beginner
502: M*/
504: PETSC_EXTERN PetscErrorCode PetscViewerCreate_HDF5(PetscViewer v)
505: {
506: PetscViewer_HDF5 *hdf5;
508: #if !defined(H5_HAVE_PARALLEL)
509: {
510: PetscMPIInt size;
511: MPI_Comm_size(PetscObjectComm((PetscObject)v), &size);
513: }
514: #endif
516: PetscNewLog(v,&hdf5);
518: v->data = (void*) hdf5;
519: v->ops->destroy = PetscViewerDestroy_HDF5;
520: v->ops->setfromoptions = PetscViewerSetFromOptions_HDF5;
521: v->ops->setup = PetscViewerSetUp_HDF5;
522: v->ops->view = PetscViewerView_HDF5;
523: v->ops->flush = PetscViewerFlush_HDF5;
524: hdf5->btype = FILE_MODE_UNDEFINED;
525: hdf5->filename = NULL;
526: hdf5->timestep = -1;
527: hdf5->groups = NULL;
529: PetscStackCallHDF5Return(hdf5->dxpl_id,H5Pcreate,(H5P_DATASET_XFER));
531: PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileSetName_C",PetscViewerFileSetName_HDF5);
532: PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileGetName_C",PetscViewerFileGetName_HDF5);
533: PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileSetMode_C",PetscViewerFileSetMode_HDF5);
534: PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileGetMode_C",PetscViewerFileGetMode_HDF5);
535: PetscObjectComposeFunction((PetscObject)v,"PetscViewerHDF5SetBaseDimension2_C",PetscViewerHDF5SetBaseDimension2_HDF5);
536: PetscObjectComposeFunction((PetscObject)v,"PetscViewerHDF5SetSPOutput_C",PetscViewerHDF5SetSPOutput_HDF5);
537: PetscObjectComposeFunction((PetscObject)v,"PetscViewerHDF5SetCollective_C",PetscViewerHDF5SetCollective_HDF5);
538: PetscObjectComposeFunction((PetscObject)v,"PetscViewerHDF5GetCollective_C",PetscViewerHDF5GetCollective_HDF5);
539: PetscObjectComposeFunction((PetscObject)v,"PetscViewerHDF5GetDefaultTimestepping_C",PetscViewerHDF5GetDefaultTimestepping_HDF5);
540: PetscObjectComposeFunction((PetscObject)v,"PetscViewerHDF5SetDefaultTimestepping_C",PetscViewerHDF5SetDefaultTimestepping_HDF5);
541: return 0;
542: }
544: /*@C
545: PetscViewerHDF5Open - Opens a file for HDF5 input/output.
547: Collective
549: Input Parameters:
550: + comm - MPI communicator
551: . name - name of file
552: - type - type of file
554: Output Parameter:
555: . hdf5v - PetscViewer for HDF5 input/output to use with the specified file
557: Options Database:
558: + -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
559: - -viewer_hdf5_sp_output - forces (if true) the viewer to write data in single precision independent on the precision of PetscReal
561: Level: beginner
563: Notes:
564: Reading is always available, regardless of the mode. Available modes are
565: + FILE_MODE_READ - open existing HDF5 file for read only access, fail if file does not exist [H5Fopen() with H5F_ACC_RDONLY]
566: . FILE_MODE_WRITE - if file exists, fully overwrite it, else create new HDF5 file [H5FcreateH5Fcreate() with H5F_ACC_TRUNC]
567: . FILE_MODE_APPEND - if file exists, keep existing contents [H5Fopen() with H5F_ACC_RDWR], else create new HDF5 file [H5FcreateH5Fcreate() with H5F_ACC_EXCL]
568: - FILE_MODE_UPDATE - same as FILE_MODE_APPEND
570: In case of FILE_MODE_APPEND / FILE_MODE_UPDATE, any stored object (dataset, attribute) can be selectively ovewritten if the same fully qualified name (/group/path/to/object) is specified.
572: This PetscViewer should be destroyed with PetscViewerDestroy().
574: .seealso: PetscViewerASCIIOpen(), PetscViewerPushFormat(), PetscViewerDestroy(), PetscViewerHDF5SetBaseDimension2(),
575: PetscViewerHDF5SetSPOutput(), PetscViewerHDF5GetBaseDimension2(), VecView(), MatView(), VecLoad(),
576: MatLoad(), PetscFileMode, PetscViewer, PetscViewerSetType(), PetscViewerFileSetMode(), PetscViewerFileSetName()
577: @*/
578: PetscErrorCode PetscViewerHDF5Open(MPI_Comm comm, const char name[], PetscFileMode type, PetscViewer *hdf5v)
579: {
580: PetscViewerCreate(comm, hdf5v);
581: PetscViewerSetType(*hdf5v, PETSCVIEWERHDF5);
582: PetscViewerFileSetMode(*hdf5v, type);
583: PetscViewerFileSetName(*hdf5v, name);
584: PetscViewerSetFromOptions(*hdf5v);
585: return 0;
586: }
588: /*@C
589: PetscViewerHDF5GetFileId - Retrieve the file id, this file ID then can be used in direct HDF5 calls
591: Not collective
593: Input Parameter:
594: . viewer - the PetscViewer
596: Output Parameter:
597: . file_id - The file id
599: Level: intermediate
601: .seealso: PetscViewerHDF5Open()
602: @*/
603: PetscErrorCode PetscViewerHDF5GetFileId(PetscViewer viewer, hid_t *file_id)
604: {
605: PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;
608: if (file_id) *file_id = hdf5->file_id;
609: return 0;
610: }
612: /*@C
613: PetscViewerHDF5PushGroup - Set the current HDF5 group for output
615: Not collective
617: Input Parameters:
618: + viewer - the PetscViewer
619: - name - The group name
621: Level: intermediate
623: Notes:
624: This is designed to mnemonically resemble the Unix cd command.
625: + If name begins with '/', it is interpreted as an absolute path fully replacing current group, otherwise it is taken as relative to the current group.
626: . NULL, empty string, or any sequence of all slashes (e.g. "///") is interpreted as the root group "/".
627: - "." means the current group is pushed again.
629: Example:
630: Suppose the current group is "/a".
631: + If name is NULL, empty string, or a sequence of all slashes (e.g. "///"), then the new group will be "/".
632: . If name is ".", then the new group will be "/a".
633: . If name is "b", then the new group will be "/a/b".
634: - If name is "/b", then the new group will be "/b".
636: Developer Notes:
637: The root group "/" is internally stored as NULL.
639: .seealso: PetscViewerHDF5Open(),PetscViewerHDF5PopGroup(),PetscViewerHDF5GetGroup(),PetscViewerHDF5OpenGroup()
640: @*/
641: PetscErrorCode PetscViewerHDF5PushGroup(PetscViewer viewer, const char name[])
642: {
643: PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;
644: PetscViewerHDF5GroupList *groupNode;
645: size_t i,len;
646: char buf[PETSC_MAX_PATH_LEN];
647: const char *gname;
651: PetscStrlen(name, &len);
652: gname = NULL;
653: if (len) {
654: if (len == 1 && name[0] == '.') {
655: /* use current name */
656: gname = (hdf5->groups && hdf5->groups->name) ? hdf5->groups->name : NULL;
657: } else if (name[0] == '/') {
658: /* absolute */
659: for (i=1; i<len; i++) {
660: if (name[i] != '/') {
661: gname = name;
662: break;
663: }
664: }
665: } else {
666: /* relative */
667: const char *parent = (hdf5->groups && hdf5->groups->name) ? hdf5->groups->name : "";
668: PetscSNPrintf(buf, sizeof(buf), "%s/%s", parent, name);
669: gname = buf;
670: }
671: }
672: PetscNew(&groupNode);
673: PetscStrallocpy(gname, (char**) &groupNode->name);
674: groupNode->next = hdf5->groups;
675: hdf5->groups = groupNode;
676: return 0;
677: }
679: /*@
680: PetscViewerHDF5PopGroup - Return the current HDF5 group for output to the previous value
682: Not collective
684: Input Parameter:
685: . viewer - the PetscViewer
687: Level: intermediate
689: .seealso: PetscViewerHDF5Open(),PetscViewerHDF5PushGroup(),PetscViewerHDF5GetGroup(),PetscViewerHDF5OpenGroup()
690: @*/
691: PetscErrorCode PetscViewerHDF5PopGroup(PetscViewer viewer)
692: {
693: PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;
694: PetscViewerHDF5GroupList *groupNode;
698: groupNode = hdf5->groups;
699: hdf5->groups = hdf5->groups->next;
700: PetscFree(groupNode->name);
701: PetscFree(groupNode);
702: return 0;
703: }
705: /*@C
706: PetscViewerHDF5GetGroup - Get the current HDF5 group name (full path), set with PetscViewerHDF5PushGroup()/PetscViewerHDF5PopGroup().
707: If none has been assigned, returns NULL.
709: Not collective
711: Input Parameter:
712: . viewer - the PetscViewer
714: Output Parameter:
715: . name - The group name
717: Level: intermediate
719: .seealso: PetscViewerHDF5Open(),PetscViewerHDF5PushGroup(),PetscViewerHDF5PopGroup(),PetscViewerHDF5OpenGroup()
720: @*/
721: PetscErrorCode PetscViewerHDF5GetGroup(PetscViewer viewer, const char *name[])
722: {
723: PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *) viewer->data;
727: if (hdf5->groups) *name = hdf5->groups->name;
728: else *name = NULL;
729: return 0;
730: }
732: /*@
733: PetscViewerHDF5OpenGroup - Open the HDF5 group with the name (full path) returned by PetscViewerHDF5GetGroup(),
734: and return this group's ID and file ID.
735: If PetscViewerHDF5GetGroup() yields NULL, then group ID is file ID.
737: Not collective
739: Input Parameter:
740: . viewer - the PetscViewer
742: Output Parameters:
743: + fileId - The HDF5 file ID
744: - groupId - The HDF5 group ID
746: Notes:
747: If the viewer is writable, the group is created if it doesn't exist yet.
749: Level: intermediate
751: .seealso: PetscViewerHDF5Open(),PetscViewerHDF5PushGroup(),PetscViewerHDF5PopGroup(),PetscViewerHDF5GetGroup()
752: @*/
753: PetscErrorCode PetscViewerHDF5OpenGroup(PetscViewer viewer, hid_t *fileId, hid_t *groupId)
754: {
755: hid_t file_id;
756: H5O_type_t type;
757: const char *groupName = NULL, *fileName = NULL;
758: PetscBool writable, has;
760: PetscViewerWritable(viewer, &writable);
761: PetscViewerHDF5GetFileId(viewer, &file_id);
762: PetscViewerFileGetName(viewer, &fileName);
763: PetscViewerHDF5GetGroup(viewer, &groupName);
764: PetscViewerHDF5Traverse_Internal(viewer, groupName, writable, &has, &type);
765: if (!has) {
767: else SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_LIB, "HDF5 failed to create group %s although file %s is open for writing", groupName, fileName);
768: }
770: PetscStackCallHDF5Return(*groupId,H5Gopen2,(file_id, groupName ? groupName : "/", H5P_DEFAULT));
771: *fileId = file_id;
772: return 0;
773: }
775: /*@
776: PetscViewerHDF5PushTimestepping - Activate timestepping mode for subsequent HDF5 reading and writing.
778: Not collective
780: Input Parameter:
781: . viewer - the PetscViewer
783: Level: intermediate
785: Notes:
786: On first PetscViewerHDF5PushTimestepping(), the initial time step is set to 0.
787: Next timesteps can then be set using PetscViewerHDF5IncrementTimestep() or PetscViewerHDF5SetTimestep().
788: Current timestep value determines which timestep is read from or written to any dataset on the next HDF5 I/O operation [e.g. VecView()].
789: Use PetscViewerHDF5PopTimestepping() to deactivate timestepping mode; calling it by the end of the program is NOT mandatory.
790: Current timestep is remembered between PetscViewerHDF5PopTimestepping() and the next PetscViewerHDF5PushTimestepping().
792: If a dataset was stored with timestepping, it can be loaded only in the timestepping mode again.
793: Loading a timestepped dataset with timestepping disabled, or vice-versa results in an error.
795: Developer notes:
796: Timestepped HDF5 dataset has an extra dimension and attribute "timestepping" set to true.
798: .seealso: PetscViewerHDF5Open(), PetscViewerHDF5PopTimestepping(), PetscViewerHDF5IsTimestepping(), PetscViewerHDF5SetTimestep(), PetscViewerHDF5IncrementTimestep(), PetscViewerHDF5GetTimestep()
799: @*/
800: PetscErrorCode PetscViewerHDF5PushTimestepping(PetscViewer viewer)
801: {
802: PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;
806: hdf5->timestepping = PETSC_TRUE;
807: if (hdf5->timestep < 0) hdf5->timestep = 0;
808: return 0;
809: }
811: /*@
812: PetscViewerHDF5PopTimestepping - Deactivate timestepping mode for subsequent HDF5 reading and writing.
814: Not collective
816: Input Parameter:
817: . viewer - the PetscViewer
819: Level: intermediate
821: Notes:
822: See PetscViewerHDF5PushTimestepping() for details.
824: .seealso: PetscViewerHDF5Open(), PetscViewerHDF5PushTimestepping(), PetscViewerHDF5IsTimestepping(), PetscViewerHDF5SetTimestep(), PetscViewerHDF5IncrementTimestep(), PetscViewerHDF5GetTimestep()
825: @*/
826: PetscErrorCode PetscViewerHDF5PopTimestepping(PetscViewer viewer)
827: {
828: PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;
832: hdf5->timestepping = PETSC_FALSE;
833: return 0;
834: }
836: /*@
837: PetscViewerHDF5IsTimestepping - Ask the viewer whether it is in timestepping mode currently.
839: Not collective
841: Input Parameter:
842: . viewer - the PetscViewer
844: Output Parameter:
845: . flg - is timestepping active?
847: Level: intermediate
849: Notes:
850: See PetscViewerHDF5PushTimestepping() for details.
852: .seealso: PetscViewerHDF5Open(), PetscViewerHDF5PushTimestepping(), PetscViewerHDF5PopTimestepping(), PetscViewerHDF5SetTimestep(), PetscViewerHDF5IncrementTimestep(), PetscViewerHDF5GetTimestep()
853: @*/
854: PetscErrorCode PetscViewerHDF5IsTimestepping(PetscViewer viewer, PetscBool *flg)
855: {
856: PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;
859: *flg = hdf5->timestepping;
860: return 0;
861: }
863: /*@
864: PetscViewerHDF5IncrementTimestep - Increments current timestep for the HDF5 output. Fields are stacked in time.
866: Not collective
868: Input Parameter:
869: . viewer - the PetscViewer
871: Level: intermediate
873: Notes:
874: This can be called only if the viewer is in timestepping mode. See PetscViewerHDF5PushTimestepping() for details.
876: .seealso: PetscViewerHDF5Open(), PetscViewerHDF5PushTimestepping(), PetscViewerHDF5SetTimestep(), PetscViewerHDF5GetTimestep()
877: @*/
878: PetscErrorCode PetscViewerHDF5IncrementTimestep(PetscViewer viewer)
879: {
880: PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;
884: ++hdf5->timestep;
885: return 0;
886: }
888: /*@
889: PetscViewerHDF5SetTimestep - Set the current timestep for the HDF5 output. Fields are stacked in time.
891: Logically collective
893: Input Parameters:
894: + viewer - the PetscViewer
895: - timestep - The timestep
897: Level: intermediate
899: Notes:
900: This can be called only if the viewer is in timestepping mode. See PetscViewerHDF5PushTimestepping() for details.
902: .seealso: PetscViewerHDF5Open(), PetscViewerHDF5PushTimestepping(), PetscViewerHDF5IncrementTimestep(), PetscViewerHDF5GetTimestep()
903: @*/
904: PetscErrorCode PetscViewerHDF5SetTimestep(PetscViewer viewer, PetscInt timestep)
905: {
906: PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;
912: hdf5->timestep = timestep;
913: return 0;
914: }
916: /*@
917: PetscViewerHDF5GetTimestep - Get the current timestep for the HDF5 output. Fields are stacked in time.
919: Not collective
921: Input Parameter:
922: . viewer - the PetscViewer
924: Output Parameter:
925: . timestep - The timestep
927: Level: intermediate
929: Notes:
930: This can be called only if the viewer is in the timestepping mode. See PetscViewerHDF5PushTimestepping() for details.
932: .seealso: PetscViewerHDF5Open(), PetscViewerHDF5PushTimestepping(), PetscViewerHDF5IncrementTimestep(), PetscViewerHDF5SetTimestep()
933: @*/
934: PetscErrorCode PetscViewerHDF5GetTimestep(PetscViewer viewer, PetscInt *timestep)
935: {
936: PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;
941: *timestep = hdf5->timestep;
942: return 0;
943: }
945: /*@C
946: PetscDataTypeToHDF5DataType - Converts the PETSc name of a datatype to its HDF5 name.
948: Not collective
950: Input Parameter:
951: . ptype - the PETSc datatype name (for example PETSC_DOUBLE)
953: Output Parameter:
954: . mtype - the MPI datatype (for example MPI_DOUBLE, ...)
956: Level: advanced
958: .seealso: PetscDataType, PetscHDF5DataTypeToPetscDataType()
959: @*/
960: PetscErrorCode PetscDataTypeToHDF5DataType(PetscDataType ptype, hid_t *htype)
961: {
962: if (ptype == PETSC_INT)
963: #if defined(PETSC_USE_64BIT_INDICES)
964: *htype = H5T_NATIVE_LLONG;
965: #else
966: *htype = H5T_NATIVE_INT;
967: #endif
968: else if (ptype == PETSC_DOUBLE) *htype = H5T_NATIVE_DOUBLE;
969: else if (ptype == PETSC_LONG) *htype = H5T_NATIVE_LONG;
970: else if (ptype == PETSC_SHORT) *htype = H5T_NATIVE_SHORT;
971: else if (ptype == PETSC_ENUM) *htype = H5T_NATIVE_INT;
972: else if (ptype == PETSC_BOOL) *htype = H5T_NATIVE_INT;
973: else if (ptype == PETSC_FLOAT) *htype = H5T_NATIVE_FLOAT;
974: else if (ptype == PETSC_CHAR) *htype = H5T_NATIVE_CHAR;
975: else if (ptype == PETSC_BIT_LOGICAL) *htype = H5T_NATIVE_UCHAR;
976: else if (ptype == PETSC_STRING) *htype = H5Tcopy(H5T_C_S1);
977: else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Unsupported PETSc datatype");
978: return 0;
979: }
981: /*@C
982: PetscHDF5DataTypeToPetscDataType - Finds the PETSc name of a datatype from its HDF5 name
984: Not collective
986: Input Parameter:
987: . htype - the HDF5 datatype (for example H5T_NATIVE_DOUBLE, ...)
989: Output Parameter:
990: . ptype - the PETSc datatype name (for example PETSC_DOUBLE)
992: Level: advanced
994: .seealso: PetscDataType, PetscHDF5DataTypeToPetscDataType()
995: @*/
996: PetscErrorCode PetscHDF5DataTypeToPetscDataType(hid_t htype, PetscDataType *ptype)
997: {
998: #if defined(PETSC_USE_64BIT_INDICES)
999: if (htype == H5T_NATIVE_INT) *ptype = PETSC_LONG;
1000: else if (htype == H5T_NATIVE_LLONG) *ptype = PETSC_INT;
1001: #else
1002: if (htype == H5T_NATIVE_INT) *ptype = PETSC_INT;
1003: #endif
1004: else if (htype == H5T_NATIVE_DOUBLE) *ptype = PETSC_DOUBLE;
1005: else if (htype == H5T_NATIVE_LONG) *ptype = PETSC_LONG;
1006: else if (htype == H5T_NATIVE_SHORT) *ptype = PETSC_SHORT;
1007: else if (htype == H5T_NATIVE_FLOAT) *ptype = PETSC_FLOAT;
1008: else if (htype == H5T_NATIVE_CHAR) *ptype = PETSC_CHAR;
1009: else if (htype == H5T_NATIVE_UCHAR) *ptype = PETSC_CHAR;
1010: else if (htype == H5T_C_S1) *ptype = PETSC_STRING;
1011: else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Unsupported HDF5 datatype");
1012: return 0;
1013: }
1015: /*@C
1016: PetscViewerHDF5WriteAttribute - Write an attribute
1018: Collective
1020: Input Parameters:
1021: + viewer - The HDF5 viewer
1022: . parent - The parent dataset/group name
1023: . name - The attribute name
1024: . datatype - The attribute type
1025: - value - The attribute value
1027: Level: advanced
1029: Notes:
1030: If parent starts with '/', it is taken as an absolute path overriding currently pushed group, else parent is relative to the current pushed group. NULL means the current pushed group.
1032: .seealso: PetscViewerHDF5Open(), PetscViewerHDF5WriteObjectAttribute(), PetscViewerHDF5ReadAttribute(), PetscViewerHDF5HasAttribute(), PetscViewerHDF5PushGroup(),PetscViewerHDF5PopGroup(),PetscViewerHDF5GetGroup()
1033: @*/
1034: PetscErrorCode PetscViewerHDF5WriteAttribute(PetscViewer viewer, const char parent[], const char name[], PetscDataType datatype, const void *value)
1035: {
1036: char *parentAbsPath;
1037: hid_t h5, dataspace, obj, attribute, dtype;
1038: PetscBool has;
1045: PetscViewerHDF5GetAbsolutePath_Internal(viewer, parent, &parentAbsPath);
1046: PetscViewerHDF5Traverse_Internal(viewer, parentAbsPath, PETSC_TRUE, NULL, NULL);
1047: PetscViewerHDF5HasAttribute_Internal(viewer, parentAbsPath, name, &has);
1048: PetscDataTypeToHDF5DataType(datatype, &dtype);
1049: if (datatype == PETSC_STRING) {
1050: size_t len;
1051: PetscStrlen((const char *) value, &len);
1052: PetscStackCallHDF5(H5Tset_size,(dtype, len+1));
1053: }
1054: PetscViewerHDF5GetFileId(viewer, &h5);
1055: PetscStackCallHDF5Return(dataspace,H5Screate,(H5S_SCALAR));
1056: PetscStackCallHDF5Return(obj,H5Oopen,(h5, parentAbsPath, H5P_DEFAULT));
1057: if (has) {
1058: PetscStackCallHDF5Return(attribute,H5Aopen_name,(obj, name));
1059: } else {
1060: PetscStackCallHDF5Return(attribute,H5Acreate2,(obj, name, dtype, dataspace, H5P_DEFAULT, H5P_DEFAULT));
1061: }
1062: PetscStackCallHDF5(H5Awrite,(attribute, dtype, value));
1063: if (datatype == PETSC_STRING) PetscStackCallHDF5(H5Tclose,(dtype));
1064: PetscStackCallHDF5(H5Aclose,(attribute));
1065: PetscStackCallHDF5(H5Oclose,(obj));
1066: PetscStackCallHDF5(H5Sclose,(dataspace));
1067: PetscFree(parentAbsPath);
1068: return 0;
1069: }
1071: /*@C
1072: PetscViewerHDF5WriteObjectAttribute - Write an attribute to the dataset matching the given PetscObject by name
1074: Collective
1076: Input Parameters:
1077: + viewer - The HDF5 viewer
1078: . obj - The object whose name is used to lookup the parent dataset, relative to the current group.
1079: . name - The attribute name
1080: . datatype - The attribute type
1081: - value - The attribute value
1083: Notes:
1084: This fails if the path current_group/object_name doesn't resolve to a dataset (the path doesn't exist or is not a dataset).
1085: You might want to check first if it does using PetscViewerHDF5HasObject().
1087: Level: advanced
1089: .seealso: PetscViewerHDF5Open(), PetscViewerHDF5WriteAttribute(), PetscViewerHDF5ReadObjectAttribute(), PetscViewerHDF5HasObjectAttribute(), PetscViewerHDF5HasObject(), PetscViewerHDF5PushGroup(),PetscViewerHDF5PopGroup(),PetscViewerHDF5GetGroup()
1090: @*/
1091: PetscErrorCode PetscViewerHDF5WriteObjectAttribute(PetscViewer viewer, PetscObject obj, const char name[], PetscDataType datatype, const void *value)
1092: {
1097: PetscViewerHDF5CheckNamedObject_Internal(viewer, obj);
1098: PetscViewerHDF5WriteAttribute(viewer, obj->name, name, datatype, value);
1099: return 0;
1100: }
1102: /*@C
1103: PetscViewerHDF5ReadAttribute - Read an attribute
1105: Collective
1107: Input Parameters:
1108: + viewer - The HDF5 viewer
1109: . parent - The parent dataset/group name
1110: . name - The attribute name
1111: . datatype - The attribute type
1112: - defaultValue - The pointer to the default value
1114: Output Parameter:
1115: . value - The pointer to the read HDF5 attribute value
1117: Notes:
1118: If defaultValue is NULL and the attribute is not found, an error occurs.
1119: If defaultValue is not NULL and the attribute is not found, defaultValue is copied to value.
1120: The pointers defaultValue and value can be the same; for instance
1121: $ flg = PETSC_FALSE;
1122: $ PetscViewerHDF5ReadAttribute(viewer,name,"attr",PETSC_BOOL,&flg,&flg);
1123: is valid, but make sure the default value is initialized.
1125: If the datatype is PETSC_STRING, the output string is newly allocated so one must PetscFree() it when no longer needed.
1127: If parent starts with '/', it is taken as an absolute path overriding currently pushed group, else parent is relative to the current pushed group. NULL means the current pushed group.
1129: Level: advanced
1131: .seealso: PetscViewerHDF5Open(), PetscViewerHDF5ReadObjectAttribute(), PetscViewerHDF5WriteAttribute(), PetscViewerHDF5HasAttribute(), PetscViewerHDF5HasObject(), PetscViewerHDF5PushGroup(),PetscViewerHDF5PopGroup(),PetscViewerHDF5GetGroup()
1132: @*/
1133: PetscErrorCode PetscViewerHDF5ReadAttribute(PetscViewer viewer, const char parent[], const char name[], PetscDataType datatype, const void *defaultValue, void *value)
1134: {
1135: char *parentAbsPath;
1136: hid_t h5, obj, attribute, dtype;
1137: PetscBool has;
1144: PetscDataTypeToHDF5DataType(datatype, &dtype);
1145: PetscViewerHDF5GetAbsolutePath_Internal(viewer, parent, &parentAbsPath);
1146: PetscViewerHDF5Traverse_Internal(viewer, parentAbsPath, PETSC_FALSE, &has, NULL);
1147: if (has) PetscViewerHDF5HasAttribute_Internal(viewer, parentAbsPath, name, &has);
1148: if (!has) {
1149: if (defaultValue) {
1150: if (defaultValue != value) {
1151: if (datatype == PETSC_STRING) {
1152: PetscStrallocpy(*(char**)defaultValue, (char**)value);
1153: } else {
1154: size_t len;
1155: PetscStackCallHDF5ReturnNoCheck(len,H5Tget_size,(dtype));
1156: PetscMemcpy(value, defaultValue, len);
1157: }
1158: }
1159: PetscFree(parentAbsPath);
1160: return 0;
1161: } else SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Attribute %s/%s does not exist and default value not provided", parentAbsPath, name);
1162: }
1163: PetscViewerHDF5GetFileId(viewer, &h5);
1164: PetscStackCallHDF5Return(obj,H5Oopen,(h5, parentAbsPath, H5P_DEFAULT));
1165: PetscStackCallHDF5Return(attribute,H5Aopen_name,(obj, name));
1166: if (datatype == PETSC_STRING) {
1167: size_t len;
1168: hid_t atype;
1169: PetscStackCallHDF5Return(atype,H5Aget_type,(attribute));
1170: PetscStackCallHDF5ReturnNoCheck(len,H5Tget_size,(atype));
1171: PetscMalloc((len+1) * sizeof(char), value);
1172: PetscStackCallHDF5(H5Tset_size,(dtype, len+1));
1173: PetscStackCallHDF5(H5Aread,(attribute, dtype, *(char**)value));
1174: } else {
1175: PetscStackCallHDF5(H5Aread,(attribute, dtype, value));
1176: }
1177: PetscStackCallHDF5(H5Aclose,(attribute));
1178: /* H5Oclose can be used to close groups, datasets, or committed datatypes */
1179: PetscStackCallHDF5(H5Oclose,(obj));
1180: PetscFree(parentAbsPath);
1181: return 0;
1182: }
1184: /*@C
1185: PetscViewerHDF5ReadObjectAttribute - Read an attribute from the dataset matching the given PetscObject by name
1187: Collective
1189: Input Parameters:
1190: + viewer - The HDF5 viewer
1191: . obj - The object whose name is used to lookup the parent dataset, relative to the current group.
1192: . name - The attribute name
1193: - datatype - The attribute type
1195: Output Parameter:
1196: . value - The attribute value
1198: Notes:
1199: This fails if current_group/object_name doesn't resolve to a dataset (the path doesn't exist or is not a dataset).
1200: You might want to check first if it does using PetscViewerHDF5HasObject().
1202: Level: advanced
1204: .seealso: PetscViewerHDF5Open(), PetscViewerHDF5ReadAttribute() PetscViewerHDF5WriteObjectAttribute(), PetscViewerHDF5HasObjectAttribute(), PetscViewerHDF5PushGroup(),PetscViewerHDF5PopGroup(),PetscViewerHDF5GetGroup()
1205: @*/
1206: PetscErrorCode PetscViewerHDF5ReadObjectAttribute(PetscViewer viewer, PetscObject obj, const char name[], PetscDataType datatype, void *defaultValue, void *value)
1207: {
1212: PetscViewerHDF5CheckNamedObject_Internal(viewer, obj);
1213: PetscViewerHDF5ReadAttribute(viewer, obj->name, name, datatype, defaultValue, value);
1214: return 0;
1215: }
1217: static inline PetscErrorCode PetscViewerHDF5Traverse_Inner_Internal(hid_t h5, const char name[], PetscBool createGroup, PetscBool *exists_)
1218: {
1219: htri_t exists;
1220: hid_t group;
1222: PetscStackCallHDF5Return(exists,H5Lexists,(h5, name, H5P_DEFAULT));
1223: if (exists) PetscStackCallHDF5Return(exists,H5Oexists_by_name,(h5, name, H5P_DEFAULT));
1224: if (!exists && createGroup) {
1225: PetscStackCallHDF5Return(group,H5Gcreate2,(h5, name, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT));
1226: PetscStackCallHDF5(H5Gclose,(group));
1227: exists = PETSC_TRUE;
1228: }
1229: *exists_ = (PetscBool) exists;
1230: return 0;
1231: }
1233: static PetscErrorCode PetscViewerHDF5Traverse_Internal(PetscViewer viewer, const char name[], PetscBool createGroup, PetscBool *has, H5O_type_t *otype)
1234: {
1235: const char rootGroupName[] = "/";
1236: hid_t h5;
1237: PetscBool exists=PETSC_FALSE;
1238: PetscInt i;
1239: int n;
1240: char **hierarchy;
1241: char buf[PETSC_MAX_PATH_LEN]="";
1245: else name = rootGroupName;
1246: if (has) {
1248: *has = PETSC_FALSE;
1249: }
1250: if (otype) {
1252: *otype = H5O_TYPE_UNKNOWN;
1253: }
1254: PetscViewerHDF5GetFileId(viewer, &h5);
1256: /*
1257: Unfortunately, H5Oexists_by_name() fails if any object in hierarchy is missing.
1258: Hence, each of them needs to be tested separately:
1259: 1) whether it's a valid link
1260: 2) whether this link resolves to an object
1261: See H5Oexists_by_name() documentation.
1262: */
1263: PetscStrToArray(name,'/',&n,&hierarchy);
1264: if (!n) {
1265: /* Assume group "/" always exists in accordance with HDF5 >= 1.10.0. See H5Lexists() documentation. */
1266: if (has) *has = PETSC_TRUE;
1267: if (otype) *otype = H5O_TYPE_GROUP;
1268: PetscStrToArrayDestroy(n,hierarchy);
1269: return 0;
1270: }
1271: for (i=0; i<n; i++) {
1272: PetscStrcat(buf,"/");
1273: PetscStrcat(buf,hierarchy[i]);
1274: PetscViewerHDF5Traverse_Inner_Internal(h5, buf, createGroup, &exists);
1275: if (!exists) break;
1276: }
1277: PetscStrToArrayDestroy(n,hierarchy);
1279: /* If the object exists, get its type */
1280: if (exists && otype) {
1281: H5O_info_t info;
1283: /* We could use H5Iget_type() here but that would require opening the object. This way we only need its name. */
1284: PetscStackCallHDF5(H5Oget_info_by_name,(h5, name, &info, H5P_DEFAULT));
1285: *otype = info.type;
1286: }
1287: if (has) *has = exists;
1288: return 0;
1289: }
1291: /*@C
1292: PetscViewerHDF5HasGroup - Check whether the current (pushed) group exists in the HDF5 file
1294: Collective
1296: Input Parameters:
1297: + viewer - The HDF5 viewer
1298: - path - The group path
1300: Output Parameter:
1301: . has - Flag for group existence
1303: Level: advanced
1305: Notes:
1306: If path starts with '/', it is taken as an absolute path overriding currently pushed group, else path is relative to the current pushed group.
1307: So NULL or empty path means the current pushed group.
1308: If path exists but is not a group, PETSC_FALSE is returned.
1310: .seealso: PetscViewerHDF5HasAttribute(), PetscViewerHDF5HasDataset(), PetscViewerHDF5PushGroup(), PetscViewerHDF5PopGroup(), PetscViewerHDF5GetGroup(), PetscViewerHDF5OpenGroup()
1311: @*/
1312: PetscErrorCode PetscViewerHDF5HasGroup(PetscViewer viewer, const char path[], PetscBool *has)
1313: {
1314: H5O_type_t type;
1315: char *abspath;
1320: PetscViewerHDF5GetAbsolutePath_Internal(viewer, path, &abspath);
1321: PetscViewerHDF5Traverse_Internal(viewer, abspath, PETSC_FALSE, NULL, &type);
1322: *has = (PetscBool)(type == H5O_TYPE_GROUP);
1323: PetscFree(abspath);
1324: return 0;
1325: }
1327: /*@C
1328: PetscViewerHDF5HasDataset - Check whether a given dataset exists in the HDF5 file
1330: Collective
1332: Input Parameters:
1333: + viewer - The HDF5 viewer
1334: - path - The dataset path
1336: Output Parameter:
1337: . has - Flag whether dataset exists
1339: Level: advanced
1341: Notes:
1342: If path starts with '/', it is taken as an absolute path overriding currently pushed group, else path is relative to the current pushed group.
1343: If path is NULL or empty, has is set to PETSC_FALSE.
1344: If path exists but is not a dataset, has is set to PETSC_FALSE as well.
1346: .seealso: PetscViewerHDF5HasObject(), PetscViewerHDF5HasAttribute(), PetscViewerHDF5HasGroup(), PetscViewerHDF5PushGroup(), PetscViewerHDF5PopGroup(), PetscViewerHDF5GetGroup()
1347: @*/
1348: PetscErrorCode PetscViewerHDF5HasDataset(PetscViewer viewer, const char path[], PetscBool *has)
1349: {
1350: H5O_type_t type;
1351: char *abspath;
1356: PetscViewerHDF5GetAbsolutePath_Internal(viewer, path, &abspath);
1357: PetscViewerHDF5Traverse_Internal(viewer, abspath, PETSC_FALSE, NULL, &type);
1358: *has = (PetscBool)(type == H5O_TYPE_DATASET);
1359: PetscFree(abspath);
1360: return 0;
1361: }
1363: /*@
1364: PetscViewerHDF5HasObject - Check whether a dataset with the same name as given object exists in the HDF5 file under current group
1366: Collective
1368: Input Parameters:
1369: + viewer - The HDF5 viewer
1370: - obj - The named object
1372: Output Parameter:
1373: . has - Flag for dataset existence
1375: Notes:
1376: If the object is unnamed, an error occurs.
1377: If the path current_group/object_name exists but is not a dataset, has is set to PETSC_FALSE as well.
1379: Level: advanced
1381: .seealso: PetscViewerHDF5Open(), PetscViewerHDF5HasDataset(), PetscViewerHDF5HasAttribute(), PetscViewerHDF5PushGroup(), PetscViewerHDF5PopGroup(), PetscViewerHDF5GetGroup()
1382: @*/
1383: PetscErrorCode PetscViewerHDF5HasObject(PetscViewer viewer, PetscObject obj, PetscBool *has)
1384: {
1385: size_t len;
1390: PetscStrlen(obj->name, &len);
1392: PetscViewerHDF5HasDataset(viewer, obj->name, has);
1393: return 0;
1394: }
1396: /*@C
1397: PetscViewerHDF5HasAttribute - Check whether an attribute exists
1399: Collective
1401: Input Parameters:
1402: + viewer - The HDF5 viewer
1403: . parent - The parent dataset/group name
1404: - name - The attribute name
1406: Output Parameter:
1407: . has - Flag for attribute existence
1409: Level: advanced
1411: Notes:
1412: If parent starts with '/', it is taken as an absolute path overriding currently pushed group, else parent is relative to the current pushed group. NULL means the current pushed group.
1414: .seealso: PetscViewerHDF5Open(), PetscViewerHDF5HasObjectAttribute(), PetscViewerHDF5WriteAttribute(), PetscViewerHDF5ReadAttribute(), PetscViewerHDF5PushGroup(),PetscViewerHDF5PopGroup(),PetscViewerHDF5GetGroup()
1415: @*/
1416: PetscErrorCode PetscViewerHDF5HasAttribute(PetscViewer viewer, const char parent[], const char name[], PetscBool *has)
1417: {
1418: char *parentAbsPath;
1424: PetscViewerHDF5GetAbsolutePath_Internal(viewer, parent, &parentAbsPath);
1425: PetscViewerHDF5Traverse_Internal(viewer, parentAbsPath, PETSC_FALSE, has, NULL);
1426: if (*has) PetscViewerHDF5HasAttribute_Internal(viewer, parentAbsPath, name, has);
1427: PetscFree(parentAbsPath);
1428: return 0;
1429: }
1431: /*@C
1432: PetscViewerHDF5HasObjectAttribute - Check whether an attribute is attached to the dataset matching the given PetscObject by name
1434: Collective
1436: Input Parameters:
1437: + viewer - The HDF5 viewer
1438: . obj - The object whose name is used to lookup the parent dataset, relative to the current group.
1439: - name - The attribute name
1441: Output Parameter:
1442: . has - Flag for attribute existence
1444: Notes:
1445: This fails if current_group/object_name doesn't resolve to a dataset (the path doesn't exist or is not a dataset).
1446: You might want to check first if it does using PetscViewerHDF5HasObject().
1448: Level: advanced
1450: .seealso: PetscViewerHDF5Open(), PetscViewerHDF5HasAttribute(), PetscViewerHDF5WriteObjectAttribute(), PetscViewerHDF5ReadObjectAttribute(), PetscViewerHDF5HasObject(), PetscViewerHDF5PushGroup(),PetscViewerHDF5PopGroup(),PetscViewerHDF5GetGroup()
1451: @*/
1452: PetscErrorCode PetscViewerHDF5HasObjectAttribute(PetscViewer viewer, PetscObject obj, const char name[], PetscBool *has)
1453: {
1458: PetscViewerHDF5CheckNamedObject_Internal(viewer, obj);
1459: PetscViewerHDF5HasAttribute(viewer, obj->name, name, has);
1460: return 0;
1461: }
1463: static PetscErrorCode PetscViewerHDF5HasAttribute_Internal(PetscViewer viewer, const char parent[], const char name[], PetscBool *has)
1464: {
1465: hid_t h5;
1466: htri_t hhas;
1468: PetscViewerHDF5GetFileId(viewer, &h5);
1469: PetscStackCallHDF5Return(hhas,H5Aexists_by_name,(h5, parent, name, H5P_DEFAULT));
1470: *has = hhas ? PETSC_TRUE : PETSC_FALSE;
1471: return 0;
1472: }
1474: /*
1475: The variable Petsc_Viewer_HDF5_keyval is used to indicate an MPI attribute that
1476: is attached to a communicator, in this case the attribute is a PetscViewer.
1477: */
1478: PetscMPIInt Petsc_Viewer_HDF5_keyval = MPI_KEYVAL_INVALID;
1480: /*@C
1481: PETSC_VIEWER_HDF5_ - Creates an HDF5 PetscViewer shared by all processors in a communicator.
1483: Collective
1485: Input Parameter:
1486: . comm - the MPI communicator to share the HDF5 PetscViewer
1488: Level: intermediate
1490: Options Database Keys:
1491: . -viewer_hdf5_filename <name> - name of the HDF5 file
1493: Environmental variables:
1494: . PETSC_VIEWER_HDF5_FILENAME - name of the HDF5 file
1496: Notes:
1497: Unlike almost all other PETSc routines, PETSC_VIEWER_HDF5_ does not return
1498: an error code. The HDF5 PetscViewer is usually used in the form
1499: $ XXXView(XXX object, PETSC_VIEWER_HDF5_(comm));
1501: .seealso: PetscViewerHDF5Open(), PetscViewerCreate(), PetscViewerDestroy()
1502: @*/
1503: PetscViewer PETSC_VIEWER_HDF5_(MPI_Comm comm)
1504: {
1506: PetscBool flg;
1507: PetscViewer viewer;
1508: char fname[PETSC_MAX_PATH_LEN];
1509: MPI_Comm ncomm;
1511: PetscCommDuplicate(comm,&ncomm,NULL);if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return NULL;}
1512: if (Petsc_Viewer_HDF5_keyval == MPI_KEYVAL_INVALID) {
1513: MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN,MPI_COMM_NULL_DELETE_FN,&Petsc_Viewer_HDF5_keyval,NULL);
1514: if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return NULL;}
1515: }
1516: MPI_Comm_get_attr(ncomm,Petsc_Viewer_HDF5_keyval,(void**)&viewer,(int*)&flg);
1517: if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return NULL;}
1518: if (!flg) { /* PetscViewer not yet created */
1519: PetscOptionsGetenv(ncomm,"PETSC_VIEWER_HDF5_FILENAME",fname,PETSC_MAX_PATH_LEN,&flg);
1520: if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_REPEAT," ");return NULL;}
1521: if (!flg) {
1522: PetscStrcpy(fname,"output.h5");
1523: if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_REPEAT," ");return NULL;}
1524: }
1525: PetscViewerHDF5Open(ncomm,fname,FILE_MODE_WRITE,&viewer);
1526: if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_REPEAT," ");return NULL;}
1527: PetscObjectRegisterDestroy((PetscObject)viewer);
1528: if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_REPEAT," ");return NULL;}
1529: MPI_Comm_set_attr(ncomm,Petsc_Viewer_HDF5_keyval,(void*)viewer);
1530: if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return NULL;}
1531: }
1532: PetscCommDestroy(&ncomm);
1533: if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_REPEAT," ");return NULL;}
1534: return viewer;
1535: }