Actual source code: ihdf5v.c
1: #include <petsc/private/viewerhdf5impl.h>
3: static PetscErrorCode PetscViewerHDF5Traverse_Inner_Internal(hid_t h5, const char name[], PetscBool createGroup, PetscBool *exists_)
4: {
5: htri_t exists;
6: hid_t group;
8: PetscFunctionBegin;
9: PetscCallHDF5Return(exists, H5Lexists, (h5, name, H5P_DEFAULT));
10: if (exists) PetscCallHDF5Return(exists, H5Oexists_by_name, (h5, name, H5P_DEFAULT));
11: if (!exists && createGroup) {
12: PetscCallHDF5Return(group, H5Gcreate2, (h5, name, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT));
13: PetscCallHDF5(H5Gclose, (group));
14: exists = PETSC_TRUE;
15: }
16: *exists_ = (PetscBool)exists;
17: PetscFunctionReturn(PETSC_SUCCESS);
18: }
20: static PetscErrorCode PetscViewerHDF5Traverse_Internal(PetscViewer viewer, const char name[], PetscBool createGroup, PetscBool *has, H5O_type_t *otype)
21: {
22: const char rootGroupName[] = "/";
23: hid_t h5;
24: PetscBool exists = PETSC_FALSE;
25: PetscInt i;
26: int n;
27: char **hierarchy;
28: char buf[PETSC_MAX_PATH_LEN] = "";
30: PetscFunctionBegin;
32: if (name) PetscAssertPointer(name, 2);
33: else name = rootGroupName;
34: if (has) {
35: PetscAssertPointer(has, 4);
36: *has = PETSC_FALSE;
37: }
38: if (otype) {
39: PetscAssertPointer(otype, 5);
40: *otype = H5O_TYPE_UNKNOWN;
41: }
42: PetscCall(PetscViewerHDF5GetFileId(viewer, &h5));
44: /*
45: Unfortunately, H5Oexists_by_name() fails if any object in hierarchy is missing.
46: Hence, each of them needs to be tested separately:
47: 1) whether it's a valid link
48: 2) whether this link resolves to an object
49: See H5Oexists_by_name() documentation.
50: */
51: PetscCall(PetscStrToArray(name, '/', &n, &hierarchy));
52: if (!n) {
53: /* Assume group "/" always exists in accordance with HDF5 >= 1.10.0. See H5Lexists() documentation. */
54: if (has) *has = PETSC_TRUE;
55: if (otype) *otype = H5O_TYPE_GROUP;
56: PetscCall(PetscStrToArrayDestroy(n, hierarchy));
57: PetscFunctionReturn(PETSC_SUCCESS);
58: }
59: for (i = 0; i < n; i++) {
60: PetscCall(PetscStrlcat(buf, "/", sizeof(buf)));
61: PetscCall(PetscStrlcat(buf, hierarchy[i], sizeof(buf)));
62: PetscCall(PetscViewerHDF5Traverse_Inner_Internal(h5, buf, createGroup, &exists));
63: if (!exists) break;
64: }
65: PetscCall(PetscStrToArrayDestroy(n, hierarchy));
67: /* If the object exists, get its type */
68: if (exists && otype) {
69: H5O_info_t info;
71: /* We could use H5Iget_type() here but that would require opening the object. This way we only need its name. */
72: PetscCallHDF5(H5Oget_info_by_name, (h5, name, &info, H5P_DEFAULT));
73: *otype = info.type;
74: }
75: if (has) *has = exists;
76: PetscFunctionReturn(PETSC_SUCCESS);
77: }
79: static PetscErrorCode PetscViewerHDF5GetGroup_Internal(PetscViewer viewer, const char *name[])
80: {
81: PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)viewer->data;
83: PetscFunctionBegin;
85: PetscAssertPointer(name, 2);
86: if (hdf5->groups) *name = hdf5->groups->name;
87: else *name = NULL;
88: PetscFunctionReturn(PETSC_SUCCESS);
89: }
91: static PetscErrorCode PetscViewerHDF5HasAttribute_Internal(PetscViewer viewer, const char parent[], const char name[], PetscBool *has)
92: {
93: hid_t h5;
94: htri_t hhas;
96: PetscFunctionBegin;
97: PetscCall(PetscViewerHDF5GetFileId(viewer, &h5));
98: PetscCallHDF5Return(hhas, H5Aexists_by_name, (h5, parent, name, H5P_DEFAULT));
99: *has = hhas ? PETSC_TRUE : PETSC_FALSE;
100: PetscFunctionReturn(PETSC_SUCCESS);
101: }
103: static PetscErrorCode PetscViewerHDF5GetGroup_HDF5(PetscViewer viewer, const char path[], const char *abspath[])
104: {
105: size_t len;
106: PetscBool relative = PETSC_FALSE;
107: const char *group;
108: char buf[PETSC_MAX_PATH_LEN] = "";
110: PetscFunctionBegin;
111: PetscCall(PetscViewerHDF5GetGroup_Internal(viewer, &group));
112: PetscCall(PetscStrlen(path, &len));
113: relative = (PetscBool)(!len || path[0] != '/');
114: if (relative) {
115: PetscCall(PetscStrncpy(buf, group, sizeof(buf)));
116: if (!group || len) PetscCall(PetscStrlcat(buf, "/", sizeof(buf)));
117: PetscCall(PetscStrlcat(buf, path, sizeof(buf)));
118: PetscCall(PetscStrallocpy(buf, (char **)abspath));
119: } else {
120: PetscCall(PetscStrallocpy(path, (char **)abspath));
121: }
122: PetscFunctionReturn(PETSC_SUCCESS);
123: }
125: static PetscErrorCode PetscViewerSetFromOptions_HDF5(PetscViewer v, PetscOptionItems PetscOptionsObject)
126: {
127: PetscBool flg = PETSC_FALSE, set;
128: PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)v->data;
130: PetscFunctionBegin;
131: PetscOptionsHeadBegin(PetscOptionsObject, "HDF5 PetscViewer Options");
132: PetscCall(PetscOptionsBool("-viewer_hdf5_base_dimension2", "1d Vectors get 2 dimensions in HDF5", "PetscViewerHDF5SetBaseDimension2", hdf5->basedimension2, &hdf5->basedimension2, NULL));
133: PetscCall(PetscOptionsBool("-viewer_hdf5_sp_output", "Force data to be written in single precision", "PetscViewerHDF5SetSPOutput", hdf5->spoutput, &hdf5->spoutput, NULL));
134: PetscCall(PetscOptionsBool("-viewer_hdf5_collective", "Enable collective transfer mode", "PetscViewerHDF5SetCollective", flg, &flg, &set));
135: if (set) PetscCall(PetscViewerHDF5SetCollective(v, flg));
136: flg = PETSC_FALSE;
137: PetscCall(PetscOptionsBool("-viewer_hdf5_default_timestepping", "Set default timestepping state", "PetscViewerHDF5SetDefaultTimestepping", flg, &flg, &set));
138: if (set) PetscCall(PetscViewerHDF5SetDefaultTimestepping(v, flg));
139: PetscCall(PetscOptionsBool("-viewer_hdf5_compress", "Enable compression", "PetscViewerHDF5SetCompress", hdf5->compress, &hdf5->compress, NULL));
140: PetscOptionsHeadEnd();
141: PetscFunctionReturn(PETSC_SUCCESS);
142: }
144: static PetscErrorCode PetscViewerView_HDF5(PetscViewer v, PetscViewer viewer)
145: {
146: PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)v->data;
147: PetscBool flg;
149: PetscFunctionBegin;
150: if (hdf5->filename) PetscCall(PetscViewerASCIIPrintf(viewer, "Filename: %s\n", hdf5->filename));
151: PetscCall(PetscViewerASCIIPrintf(viewer, "Vectors with blocksize 1 saved as 2D datasets: %s\n", PetscBools[hdf5->basedimension2]));
152: PetscCall(PetscViewerASCIIPrintf(viewer, "Enforce single precision storage: %s\n", PetscBools[hdf5->spoutput]));
153: PetscCall(PetscViewerHDF5GetCollective(v, &flg));
154: PetscCall(PetscViewerASCIIPrintf(viewer, "MPI-IO transfer mode: %s\n", flg ? "collective" : "independent"));
155: PetscCall(PetscViewerASCIIPrintf(viewer, "Default timestepping: %s\n", PetscBools[hdf5->defTimestepping]));
156: PetscCall(PetscViewerASCIIPrintf(viewer, "Compression: %s\n", PetscBools[hdf5->compress]));
157: PetscFunctionReturn(PETSC_SUCCESS);
158: }
160: static PetscErrorCode PetscViewerFileClose_HDF5(PetscViewer viewer)
161: {
162: PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)viewer->data;
164: PetscFunctionBegin;
165: PetscCall(PetscFree(hdf5->filename));
166: if (hdf5->file_id) PetscCallHDF5(H5Fclose, (hdf5->file_id));
167: PetscFunctionReturn(PETSC_SUCCESS);
168: }
170: static PetscErrorCode PetscViewerFlush_HDF5(PetscViewer viewer)
171: {
172: PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)viewer->data;
174: PetscFunctionBegin;
175: if (hdf5->file_id) PetscCallHDF5(H5Fflush, (hdf5->file_id, H5F_SCOPE_LOCAL));
176: PetscFunctionReturn(PETSC_SUCCESS);
177: }
179: static PetscErrorCode PetscViewerDestroy_HDF5(PetscViewer viewer)
180: {
181: PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)viewer->data;
183: PetscFunctionBegin;
184: PetscCallHDF5(H5Pclose, (hdf5->dxpl_id));
185: PetscCall(PetscViewerFileClose_HDF5(viewer));
186: while (hdf5->groups) {
187: PetscViewerHDF5GroupList *tmp = hdf5->groups->next;
189: PetscCall(PetscFree(hdf5->groups->name));
190: PetscCall(PetscFree(hdf5->groups));
191: hdf5->groups = tmp;
192: }
193: PetscCall(PetscFree(hdf5));
194: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetName_C", NULL));
195: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetName_C", NULL));
196: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetMode_C", NULL));
197: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetMode_C", NULL));
198: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerHDF5SetBaseDimension2_C", NULL));
199: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerHDF5GetBaseDimension2_C", NULL));
200: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerHDF5SetSPOutput_C", NULL));
201: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerHDF5SetCollective_C", NULL));
202: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerHDF5GetCollective_C", NULL));
203: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerHDF5GetDefaultTimestepping_C", NULL));
204: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerHDF5SetDefaultTimestepping_C", NULL));
205: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerHDF5SetCompress_C", NULL));
206: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerHDF5GetCompress_C", NULL));
207: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerHDF5WriteGroup_C", NULL));
208: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerHDF5PushGroup_C", NULL));
209: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerHDF5PopGroup_C", NULL));
210: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerHDF5GetGroup_C", NULL));
211: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerHDF5PushTimestepping_C", NULL));
212: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerHDF5PopTimestepping_C", NULL));
213: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerHDF5IsTimestepping_C", NULL));
214: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerHDF5IncrementTimestep_C", NULL));
215: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerHDF5SetTimestep_C", NULL));
216: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerHDF5GetTimestep_C", NULL));
217: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerHDF5WriteAttribute_C", NULL));
218: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerHDF5ReadAttribute_C", NULL));
219: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerHDF5HasGroup_C", NULL));
220: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerHDF5HasDataset_C", NULL));
221: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerHDF5HasAttribute_C", NULL));
222: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerHDF5GetSPOutput_C", NULL));
223: PetscFunctionReturn(PETSC_SUCCESS);
224: }
226: static PetscErrorCode PetscViewerFileSetMode_HDF5(PetscViewer viewer, PetscFileMode type)
227: {
228: PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)viewer->data;
230: PetscFunctionBegin;
231: hdf5->btype = type;
232: PetscFunctionReturn(PETSC_SUCCESS);
233: }
235: static PetscErrorCode PetscViewerFileGetMode_HDF5(PetscViewer viewer, PetscFileMode *type)
236: {
237: PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)viewer->data;
239: PetscFunctionBegin;
240: *type = hdf5->btype;
241: PetscFunctionReturn(PETSC_SUCCESS);
242: }
244: static PetscErrorCode PetscViewerHDF5SetBaseDimension2_HDF5(PetscViewer viewer, PetscBool flg)
245: {
246: PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)viewer->data;
248: PetscFunctionBegin;
249: hdf5->basedimension2 = flg;
250: PetscFunctionReturn(PETSC_SUCCESS);
251: }
253: static PetscErrorCode PetscViewerHDF5GetBaseDimension2_HDF5(PetscViewer viewer, PetscBool *flg)
254: {
255: PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)viewer->data;
257: PetscFunctionBegin;
258: *flg = hdf5->basedimension2;
259: PetscFunctionReturn(PETSC_SUCCESS);
260: }
262: static PetscErrorCode PetscViewerHDF5SetSPOutput_HDF5(PetscViewer viewer, PetscBool flg)
263: {
264: PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)viewer->data;
266: PetscFunctionBegin;
267: hdf5->spoutput = flg;
268: PetscFunctionReturn(PETSC_SUCCESS);
269: }
271: static PetscErrorCode PetscViewerHDF5GetSPOutput_HDF5(PetscViewer viewer, PetscBool *flg)
272: {
273: PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)viewer->data;
275: PetscFunctionBegin;
276: *flg = hdf5->spoutput;
277: PetscFunctionReturn(PETSC_SUCCESS);
278: }
280: static PetscErrorCode PetscViewerHDF5SetCollective_HDF5(PetscViewer viewer, PetscBool flg)
281: {
282: PetscFunctionBegin;
283: /* H5FD_MPIO_COLLECTIVE is wrong in hdf5 1.10.2, and is the same as H5FD_MPIO_INDEPENDENT in earlier versions
284: - see e.g. https://gitlab.cosma.dur.ac.uk/swift/swiftsim/issues/431 */
285: #if H5_VERSION_GE(1, 10, 3) && defined(H5_HAVE_PARALLEL)
286: {
287: PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)viewer->data;
288: PetscCallHDF5(H5Pset_dxpl_mpio, (hdf5->dxpl_id, flg ? H5FD_MPIO_COLLECTIVE : H5FD_MPIO_INDEPENDENT));
289: }
290: #else
291: if (flg) PetscCall(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"));
292: #endif
293: PetscFunctionReturn(PETSC_SUCCESS);
294: }
296: static PetscErrorCode PetscViewerHDF5GetCollective_HDF5(PetscViewer viewer, PetscBool *flg)
297: {
298: #if defined(H5_HAVE_PARALLEL)
299: PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)viewer->data;
300: H5FD_mpio_xfer_t mode;
301: #endif
303: PetscFunctionBegin;
304: #if !defined(H5_HAVE_PARALLEL)
305: *flg = PETSC_FALSE;
306: #else
307: PetscCallHDF5(H5Pget_dxpl_mpio, (hdf5->dxpl_id, &mode));
308: *flg = (mode == H5FD_MPIO_COLLECTIVE) ? PETSC_TRUE : PETSC_FALSE;
309: #endif
310: PetscFunctionReturn(PETSC_SUCCESS);
311: }
313: static PetscErrorCode PetscViewerFileSetName_HDF5(PetscViewer viewer, const char name[])
314: {
315: PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)viewer->data;
316: hid_t plist_id;
318: PetscFunctionBegin;
319: if (hdf5->file_id) PetscCallHDF5(H5Fclose, (hdf5->file_id));
320: if (hdf5->filename) PetscCall(PetscFree(hdf5->filename));
321: PetscCall(PetscStrallocpy(name, &hdf5->filename));
322: /* Set up file access property list with parallel I/O access */
323: PetscCallHDF5Return(plist_id, H5Pcreate, (H5P_FILE_ACCESS));
324: #if defined(H5_HAVE_PARALLEL)
325: PetscCallHDF5(H5Pset_fapl_mpio, (plist_id, PetscObjectComm((PetscObject)viewer), MPI_INFO_NULL));
326: #endif
327: /* Create or open the file collectively */
328: switch (hdf5->btype) {
329: case FILE_MODE_READ:
330: if (PetscDefined(USE_DEBUG)) {
331: PetscMPIInt rank;
332: PetscBool flg;
334: PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
335: if (rank == 0) {
336: PetscCall(PetscTestFile(hdf5->filename, 'r', &flg));
337: PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "File %s requested for reading does not exist", hdf5->filename);
338: }
339: PetscCallMPI(MPI_Barrier(PetscObjectComm((PetscObject)viewer)));
340: }
341: PetscCallHDF5Return(hdf5->file_id, H5Fopen, (name, H5F_ACC_RDONLY, plist_id));
342: break;
343: case FILE_MODE_APPEND:
344: case FILE_MODE_UPDATE: {
345: PetscBool flg;
346: PetscCall(PetscTestFile(hdf5->filename, 'r', &flg));
347: if (flg) PetscCallHDF5Return(hdf5->file_id, H5Fopen, (name, H5F_ACC_RDWR, plist_id));
348: else PetscCallHDF5Return(hdf5->file_id, H5Fcreate, (name, H5F_ACC_EXCL, H5P_DEFAULT, plist_id));
349: break;
350: }
351: case FILE_MODE_WRITE:
352: PetscCallHDF5Return(hdf5->file_id, H5Fcreate, (name, H5F_ACC_TRUNC, H5P_DEFAULT, plist_id));
353: break;
354: case FILE_MODE_UNDEFINED:
355: SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_ORDER, "Must call PetscViewerFileSetMode() before PetscViewerFileSetName()");
356: default:
357: SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Unsupported file mode %s", PetscFileModes[hdf5->btype]);
358: }
359: PetscCheck(hdf5->file_id >= 0, PETSC_COMM_SELF, PETSC_ERR_LIB, "H5Fcreate failed for %s", name);
360: PetscCallHDF5(H5Pclose, (plist_id));
361: PetscCall(PetscViewerHDF5ResetAttachedDMPlexStorageVersion(viewer));
362: PetscFunctionReturn(PETSC_SUCCESS);
363: }
365: static PetscErrorCode PetscViewerFileGetName_HDF5(PetscViewer viewer, const char **name)
366: {
367: PetscViewer_HDF5 *vhdf5 = (PetscViewer_HDF5 *)viewer->data;
369: PetscFunctionBegin;
370: *name = vhdf5->filename;
371: PetscFunctionReturn(PETSC_SUCCESS);
372: }
374: static PetscErrorCode PetscViewerSetUp_HDF5(PETSC_UNUSED PetscViewer viewer)
375: {
376: PetscFunctionBegin;
377: PetscFunctionReturn(PETSC_SUCCESS);
378: }
380: static PetscErrorCode PetscViewerHDF5SetDefaultTimestepping_HDF5(PetscViewer viewer, PetscBool flg)
381: {
382: PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)viewer->data;
384: PetscFunctionBegin;
385: hdf5->defTimestepping = flg;
386: PetscFunctionReturn(PETSC_SUCCESS);
387: }
389: static PetscErrorCode PetscViewerHDF5GetDefaultTimestepping_HDF5(PetscViewer viewer, PetscBool *flg)
390: {
391: PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)viewer->data;
393: PetscFunctionBegin;
394: *flg = hdf5->defTimestepping;
395: PetscFunctionReturn(PETSC_SUCCESS);
396: }
398: static PetscErrorCode PetscViewerHDF5SetCompress_HDF5(PetscViewer viewer, PetscBool flg)
399: {
400: PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)viewer->data;
402: PetscFunctionBegin;
403: hdf5->compress = flg;
404: PetscFunctionReturn(PETSC_SUCCESS);
405: }
407: static PetscErrorCode PetscViewerHDF5GetCompress_HDF5(PetscViewer viewer, PetscBool *flg)
408: {
409: PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)viewer->data;
411: PetscFunctionBegin;
412: *flg = hdf5->compress;
413: PetscFunctionReturn(PETSC_SUCCESS);
414: }
416: /*@C
417: PetscViewerHDF5GetFileId - Retrieve the file id, this file ID then can be used in direct HDF5 calls
419: Not Collective
421: Input Parameter:
422: . viewer - the `PetscViewer`
424: Output Parameter:
425: . file_id - The file id
427: Level: intermediate
429: .seealso: [](sec_viewers), `PETSCVIEWERHDF5`, `PetscViewerHDF5Open()`
430: @*/
431: PetscErrorCode PetscViewerHDF5GetFileId(PetscViewer viewer, hid_t *file_id)
432: {
433: PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)viewer->data;
435: PetscFunctionBegin;
437: if (file_id) *file_id = hdf5->file_id;
438: PetscFunctionReturn(PETSC_SUCCESS);
439: }
441: static PetscErrorCode PetscViewerHDF5PushGroup_HDF5(PetscViewer viewer, const char name[])
442: {
443: PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)viewer->data;
444: PetscViewerHDF5GroupList *groupNode;
445: size_t i, len;
446: char buf[PETSC_MAX_PATH_LEN];
447: const char *gname;
449: PetscFunctionBegin;
450: PetscCall(PetscStrlen(name, &len));
451: gname = NULL;
452: if (len) {
453: if (len == 1 && name[0] == '.') {
454: /* use current name */
455: gname = (hdf5->groups && hdf5->groups->name) ? hdf5->groups->name : NULL;
456: } else if (name[0] == '/') {
457: /* absolute */
458: for (i = 1; i < len; i++) {
459: if (name[i] != '/') {
460: gname = name;
461: break;
462: }
463: }
464: } else {
465: /* relative */
466: const char *parent = (hdf5->groups && hdf5->groups->name) ? hdf5->groups->name : "";
467: PetscCall(PetscSNPrintf(buf, sizeof(buf), "%s/%s", parent, name));
468: gname = buf;
469: }
470: }
471: PetscCall(PetscNew(&groupNode));
472: PetscCall(PetscStrallocpy(gname, (char **)&groupNode->name));
473: groupNode->next = hdf5->groups;
474: hdf5->groups = groupNode;
475: PetscFunctionReturn(PETSC_SUCCESS);
476: }
478: static PetscErrorCode PetscViewerHDF5PopGroup_HDF5(PetscViewer viewer)
479: {
480: PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)viewer->data;
481: PetscViewerHDF5GroupList *groupNode;
483: PetscFunctionBegin;
484: PetscCheck(hdf5->groups, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "HDF5 group stack is empty, cannot pop");
485: groupNode = hdf5->groups;
486: hdf5->groups = hdf5->groups->next;
487: PetscCall(PetscFree(groupNode->name));
488: PetscCall(PetscFree(groupNode));
489: PetscFunctionReturn(PETSC_SUCCESS);
490: }
492: /*@C
493: PetscViewerHDF5OpenGroup - Open the HDF5 group with the name (full path) returned by `PetscViewerHDF5GetGroup()`,
494: and return this group's ID and file ID.
495: If `PetscViewerHDF5GetGroup()` yields NULL, then group ID is file ID.
497: Not Collective
499: Input Parameters:
500: + viewer - the `PetscViewer` of type `PETSCVIEWERHDF5`
501: - path - (Optional) The path relative to the pushed group
503: Output Parameters:
504: + fileId - The HDF5 file ID
505: - groupId - The HDF5 group ID
507: Level: intermediate
509: Note:
510: If path starts with '/', it is taken as an absolute path overriding currently pushed group, else path is relative to the current pushed group.
511: `NULL` or empty path means the current pushed group.
513: If the viewer is writable, the group is created if it doesn't exist yet.
515: .seealso: [](sec_viewers), `PETSCVIEWERHDF5`, `PetscViewerHDF5Open()`, `PetscViewerHDF5PushGroup()`, `PetscViewerHDF5PopGroup()`, `PetscViewerHDF5GetGroup()`, `PetscViewerHDF5WriteGroup()`
516: @*/
517: PetscErrorCode PetscViewerHDF5OpenGroup(PetscViewer viewer, const char path[], hid_t *fileId, hid_t *groupId)
518: {
519: hid_t file_id;
520: H5O_type_t type;
521: const char *fileName = NULL;
522: const char *groupName = NULL;
523: PetscBool writable, has;
525: PetscFunctionBegin;
527: if (path) PetscAssertPointer(path, 2);
528: PetscAssertPointer(fileId, 3);
529: PetscAssertPointer(groupId, 4);
530: PetscCall(PetscViewerWritable(viewer, &writable));
531: PetscCall(PetscViewerHDF5GetFileId(viewer, &file_id));
532: PetscCall(PetscViewerFileGetName(viewer, &fileName));
533: PetscCall(PetscViewerHDF5GetGroup(viewer, path, &groupName));
534: PetscCall(PetscViewerHDF5Traverse_Internal(viewer, groupName, writable, &has, &type));
535: if (!has) {
536: PetscCheck(writable, PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Group %s does not exist and file %s is not open for writing", groupName, fileName);
537: SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_LIB, "HDF5 failed to create group %s although file %s is open for writing", groupName, fileName);
538: }
539: PetscCheck(type == H5O_TYPE_GROUP, PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Path %s in file %s resolves to something which is not a group", groupName, fileName);
540: PetscCallHDF5Return(*groupId, H5Gopen2, (file_id, groupName, H5P_DEFAULT));
541: PetscCall(PetscFree(groupName));
542: *fileId = file_id;
543: PetscFunctionReturn(PETSC_SUCCESS);
544: }
546: static PetscErrorCode PetscViewerHDF5WriteGroup_HDF5(PetscViewer viewer, const char path[])
547: {
548: hid_t fileId, groupId;
550: PetscFunctionBegin;
551: PetscCall(PetscViewerHDF5OpenGroup(viewer, path, &fileId, &groupId)); // make sure group is actually created
552: PetscCallHDF5(H5Gclose, (groupId));
553: PetscFunctionReturn(PETSC_SUCCESS);
554: }
556: static PetscErrorCode PetscViewerHDF5PushTimestepping_HDF5(PetscViewer viewer)
557: {
558: PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)viewer->data;
560: PetscFunctionBegin;
561: PetscCheck(!hdf5->timestepping, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Timestepping is already pushed");
562: hdf5->timestepping = PETSC_TRUE;
563: if (hdf5->timestep < 0) hdf5->timestep = 0;
564: PetscFunctionReturn(PETSC_SUCCESS);
565: }
567: static PetscErrorCode PetscViewerHDF5PopTimestepping_HDF5(PetscViewer viewer)
568: {
569: PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)viewer->data;
571: PetscFunctionBegin;
572: PetscCheck(hdf5->timestepping, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Timestepping has not been pushed yet. Call PetscViewerHDF5PushTimestepping() first");
573: hdf5->timestepping = PETSC_FALSE;
574: PetscFunctionReturn(PETSC_SUCCESS);
575: }
577: static PetscErrorCode PetscViewerHDF5IsTimestepping_HDF5(PetscViewer viewer, PetscBool *flg)
578: {
579: PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)viewer->data;
581: PetscFunctionBegin;
582: *flg = hdf5->timestepping;
583: PetscFunctionReturn(PETSC_SUCCESS);
584: }
586: static PetscErrorCode PetscViewerHDF5IncrementTimestep_HDF5(PetscViewer viewer)
587: {
588: PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)viewer->data;
590: PetscFunctionBegin;
591: PetscCheck(hdf5->timestepping, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Timestepping has not been pushed yet. Call PetscViewerHDF5PushTimestepping() first");
592: ++hdf5->timestep;
593: PetscFunctionReturn(PETSC_SUCCESS);
594: }
596: static PetscErrorCode PetscViewerHDF5SetTimestep_HDF5(PetscViewer viewer, PetscInt timestep)
597: {
598: PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)viewer->data;
600: PetscFunctionBegin;
601: PetscCheck(timestep >= 0, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Timestep %" PetscInt_FMT " is negative", timestep);
602: PetscCheck(hdf5->timestepping, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Timestepping has not been pushed yet. Call PetscViewerHDF5PushTimestepping() first");
603: hdf5->timestep = timestep;
604: PetscFunctionReturn(PETSC_SUCCESS);
605: }
607: static PetscErrorCode PetscViewerHDF5GetTimestep_HDF5(PetscViewer viewer, PetscInt *timestep)
608: {
609: PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)viewer->data;
611: PetscFunctionBegin;
612: PetscCheck(hdf5->timestepping, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Timestepping has not been pushed yet. Call PetscViewerHDF5PushTimestepping() first");
613: *timestep = hdf5->timestep;
614: PetscFunctionReturn(PETSC_SUCCESS);
615: }
617: /*@C
618: PetscDataTypeToHDF5DataType - Converts the PETSc name of a datatype to its HDF5 name.
620: Not Collective
622: Input Parameter:
623: . ptype - the PETSc datatype name (for example `PETSC_DOUBLE`)
625: Output Parameter:
626: . htype - the HDF5 datatype
628: Level: advanced
630: .seealso: [](sec_viewers), `PetscDataType`, `PetscHDF5DataTypeToPetscDataType()`
631: @*/
632: PetscErrorCode PetscDataTypeToHDF5DataType(PetscDataType ptype, hid_t *htype)
633: {
634: PetscFunctionBegin;
635: if (ptype == PETSC_INT) *htype = PetscDefined(USE_64BIT_INDICES) ? H5T_NATIVE_LLONG : H5T_NATIVE_INT;
636: else if (ptype == PETSC_DOUBLE) *htype = H5T_NATIVE_DOUBLE;
637: else if (ptype == PETSC_LONG) *htype = H5T_NATIVE_LONG;
638: else if (ptype == PETSC_SHORT) *htype = H5T_NATIVE_SHORT;
639: else if (ptype == PETSC_ENUM) *htype = H5T_NATIVE_INT;
640: else if (ptype == PETSC_BOOL) *htype = H5T_NATIVE_HBOOL;
641: else if (ptype == PETSC_FLOAT) *htype = H5T_NATIVE_FLOAT;
642: else if (ptype == PETSC_CHAR) *htype = H5T_NATIVE_CHAR;
643: else if (ptype == PETSC_BIT_LOGICAL) *htype = H5T_NATIVE_UCHAR;
644: else if (ptype == PETSC_STRING) *htype = H5Tcopy(H5T_C_S1);
645: else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Unsupported PETSc datatype");
646: PetscFunctionReturn(PETSC_SUCCESS);
647: }
649: /*@C
650: PetscHDF5DataTypeToPetscDataType - Finds the PETSc name of a datatype from its HDF5 name
652: Not Collective
654: Input Parameter:
655: . htype - the HDF5 datatype (for example `H5T_NATIVE_DOUBLE`, ...)
657: Output Parameter:
658: . ptype - the PETSc datatype name (for example `PETSC_DOUBLE`)
660: Level: advanced
662: .seealso: [](sec_viewers), `PetscDataType`
663: @*/
664: PetscErrorCode PetscHDF5DataTypeToPetscDataType(hid_t htype, PetscDataType *ptype)
665: {
666: PetscFunctionBegin;
667: if (htype == H5T_NATIVE_INT) *ptype = PetscDefined(USE_64BIT_INDICES) ? PETSC_LONG : PETSC_INT;
668: #if defined(PETSC_USE_64BIT_INDICES)
669: else if (htype == H5T_NATIVE_LLONG) *ptype = PETSC_INT;
670: #endif
671: else if (htype == H5T_NATIVE_DOUBLE) *ptype = PETSC_DOUBLE;
672: else if (htype == H5T_NATIVE_LONG) *ptype = PETSC_LONG;
673: else if (htype == H5T_NATIVE_SHORT) *ptype = PETSC_SHORT;
674: else if (htype == H5T_NATIVE_HBOOL) *ptype = PETSC_BOOL;
675: else if (htype == H5T_NATIVE_FLOAT) *ptype = PETSC_FLOAT;
676: else if (htype == H5T_NATIVE_CHAR) *ptype = PETSC_CHAR;
677: else if (htype == H5T_NATIVE_UCHAR) *ptype = PETSC_CHAR;
678: else if (htype == H5T_C_S1) *ptype = PETSC_STRING;
679: else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Unsupported HDF5 datatype");
680: PetscFunctionReturn(PETSC_SUCCESS);
681: }
683: static PetscErrorCode PetscViewerHDF5WriteAttribute_HDF5(PetscViewer viewer, const char parent[], const char name[], PetscDataType datatype, const void *value)
684: {
685: const char *parentAbsPath;
686: hid_t h5, dataspace, obj, attribute, dtype;
687: PetscBool has;
689: PetscFunctionBegin;
690: PetscCall(PetscViewerHDF5GetGroup(viewer, parent, &parentAbsPath));
691: PetscCall(PetscViewerHDF5Traverse_Internal(viewer, parentAbsPath, PETSC_TRUE, NULL, NULL));
692: PetscCall(PetscViewerHDF5HasAttribute_Internal(viewer, parentAbsPath, name, &has));
693: PetscCall(PetscDataTypeToHDF5DataType(datatype, &dtype));
694: if (datatype == PETSC_STRING) {
695: size_t len;
696: PetscCall(PetscStrlen((const char *)value, &len));
697: PetscCallHDF5(H5Tset_size, (dtype, len + 1));
698: }
699: PetscCall(PetscViewerHDF5GetFileId(viewer, &h5));
700: PetscCallHDF5Return(dataspace, H5Screate, (H5S_SCALAR));
701: PetscCallHDF5Return(obj, H5Oopen, (h5, parentAbsPath, H5P_DEFAULT));
702: if (has) {
703: PetscCallHDF5Return(attribute, H5Aopen_name, (obj, name));
704: } else {
705: PetscCallHDF5Return(attribute, H5Acreate2, (obj, name, dtype, dataspace, H5P_DEFAULT, H5P_DEFAULT));
706: }
707: PetscCallHDF5(H5Awrite, (attribute, dtype, value));
708: if (datatype == PETSC_STRING) PetscCallHDF5(H5Tclose, (dtype));
709: PetscCallHDF5(H5Aclose, (attribute));
710: PetscCallHDF5(H5Oclose, (obj));
711: PetscCallHDF5(H5Sclose, (dataspace));
712: PetscCall(PetscFree(parentAbsPath));
713: PetscFunctionReturn(PETSC_SUCCESS);
714: }
716: static PetscErrorCode PetscViewerHDF5ReadAttribute_HDF5(PetscViewer viewer, const char parent[], const char name[], PetscDataType datatype, const void *defaultValue, void *value)
717: {
718: const char *parentAbsPath;
719: hid_t h5, obj, attribute, dtype;
720: PetscBool has;
722: PetscFunctionBegin;
723: PetscCall(PetscDataTypeToHDF5DataType(datatype, &dtype));
724: PetscCall(PetscViewerHDF5GetGroup(viewer, parent, &parentAbsPath));
725: PetscCall(PetscViewerHDF5Traverse_Internal(viewer, parentAbsPath, PETSC_FALSE, &has, NULL));
726: if (has) PetscCall(PetscViewerHDF5HasAttribute_Internal(viewer, parentAbsPath, name, &has));
727: if (!has) {
728: if (defaultValue) {
729: if (defaultValue != value) {
730: if (datatype == PETSC_STRING) {
731: PetscCall(PetscStrallocpy(*(char **)defaultValue, (char **)value));
732: } else {
733: size_t len;
734: PetscCallHDF5ReturnNoCheck(len, H5Tget_size, (dtype));
735: PetscCall(PetscMemcpy(value, defaultValue, len));
736: }
737: }
738: PetscCall(PetscFree(parentAbsPath));
739: PetscFunctionReturn(PETSC_SUCCESS);
740: } else SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Attribute %s/%s does not exist and default value not provided", parentAbsPath, name);
741: }
742: PetscCall(PetscViewerHDF5GetFileId(viewer, &h5));
743: PetscCallHDF5Return(obj, H5Oopen, (h5, parentAbsPath, H5P_DEFAULT));
744: PetscCallHDF5Return(attribute, H5Aopen_name, (obj, name));
745: if (datatype == PETSC_STRING) {
746: size_t len;
747: hid_t atype;
748: PetscCallHDF5Return(atype, H5Aget_type, (attribute));
749: PetscCallHDF5ReturnNoCheck(len, H5Tget_size, (atype));
750: PetscCall(PetscMalloc((len + 1) * sizeof(char), value));
751: PetscCallHDF5(H5Tset_size, (dtype, len + 1));
752: PetscCallHDF5(H5Aread, (attribute, dtype, *(char **)value));
753: } else {
754: PetscCallHDF5(H5Aread, (attribute, dtype, value));
755: }
756: PetscCallHDF5(H5Aclose, (attribute));
757: /* H5Oclose can be used to close groups, datasets, or committed datatypes */
758: PetscCallHDF5(H5Oclose, (obj));
759: PetscCall(PetscFree(parentAbsPath));
760: PetscFunctionReturn(PETSC_SUCCESS);
761: }
763: static PetscErrorCode PetscViewerHDF5HasGroup_HDF5(PetscViewer viewer, const char path[], PetscBool *has)
764: {
765: H5O_type_t type;
766: const char *abspath;
768: PetscFunctionBegin;
769: PetscCall(PetscViewerHDF5GetGroup(viewer, path, &abspath));
770: PetscCall(PetscViewerHDF5Traverse_Internal(viewer, abspath, PETSC_FALSE, NULL, &type));
771: *has = (PetscBool)(type == H5O_TYPE_GROUP);
772: PetscCall(PetscFree(abspath));
773: PetscFunctionReturn(PETSC_SUCCESS);
774: }
776: static PetscErrorCode PetscViewerHDF5HasDataset_HDF5(PetscViewer viewer, const char path[], PetscBool *has)
777: {
778: H5O_type_t type;
779: const char *abspath;
781: PetscFunctionBegin;
782: PetscCall(PetscViewerHDF5GetGroup(viewer, path, &abspath));
783: PetscCall(PetscViewerHDF5Traverse_Internal(viewer, abspath, PETSC_FALSE, NULL, &type));
784: *has = (PetscBool)(type == H5O_TYPE_DATASET);
785: PetscCall(PetscFree(abspath));
786: PetscFunctionReturn(PETSC_SUCCESS);
787: }
789: static PetscErrorCode PetscViewerHDF5HasAttribute_HDF5(PetscViewer viewer, const char parent[], const char name[], PetscBool *has)
790: {
791: const char *parentAbsPath;
793: PetscFunctionBegin;
794: PetscCall(PetscViewerHDF5GetGroup(viewer, parent, &parentAbsPath));
795: PetscCall(PetscViewerHDF5Traverse_Internal(viewer, parentAbsPath, PETSC_FALSE, has, NULL));
796: if (*has) PetscCall(PetscViewerHDF5HasAttribute_Internal(viewer, parentAbsPath, name, has));
797: PetscCall(PetscFree(parentAbsPath));
798: PetscFunctionReturn(PETSC_SUCCESS);
799: }
801: /*MC
802: PETSCVIEWERHDF5 - A viewer that writes to an HDF5 file
804: Level: beginner
806: .seealso: [](sec_viewers), `PetscViewerHDF5Open()`, `PetscViewerStringSPrintf()`, `PetscViewerSocketOpen()`, `PetscViewerDrawOpen()`, `PETSCVIEWERSOCKET`,
807: `PetscViewerCreate()`, `PetscViewerASCIIOpen()`, `PetscViewerBinaryOpen()`, `PETSCVIEWERBINARY`, `PETSCVIEWERDRAW`, `PETSCVIEWERSTRING`,
808: `PetscViewerMatlabOpen()`, `VecView()`, `DMView()`, `PetscViewerMatlabPutArray()`, `PETSCVIEWERASCII`, `PETSCVIEWERMATLAB`,
809: `PetscViewerFileSetName()`, `PetscViewerFileSetMode()`, `PetscViewerFormat`, `PetscViewerType`, `PetscViewerSetType()`
810: M*/
812: PETSC_EXTERN PetscErrorCode PetscViewerCreate_HDF5(PetscViewer v)
813: {
814: PetscViewer_HDF5 *hdf5;
816: PetscFunctionBegin;
817: #if !defined(H5_HAVE_PARALLEL)
818: {
819: PetscMPIInt size;
820: PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)v), &size));
821: PetscCheck(size <= 1, PetscObjectComm((PetscObject)v), PETSC_ERR_SUP, "Cannot use parallel HDF5 viewer since the given HDF5 does not support parallel I/O (H5_HAVE_PARALLEL is unset)");
822: }
823: #endif
825: PetscCall(PetscNew(&hdf5));
827: v->data = (void *)hdf5;
828: v->ops->destroy = PetscViewerDestroy_HDF5;
829: v->ops->setfromoptions = PetscViewerSetFromOptions_HDF5;
830: v->ops->setup = PetscViewerSetUp_HDF5;
831: v->ops->view = PetscViewerView_HDF5;
832: v->ops->flush = PetscViewerFlush_HDF5;
833: hdf5->btype = FILE_MODE_UNDEFINED;
834: hdf5->filename = NULL;
835: hdf5->timestep = -1;
836: hdf5->groups = NULL;
838: PetscCallHDF5Return(hdf5->dxpl_id, H5Pcreate, (H5P_DATASET_XFER));
840: PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerFileSetName_C", PetscViewerFileSetName_HDF5));
841: PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerFileGetName_C", PetscViewerFileGetName_HDF5));
842: PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerFileSetMode_C", PetscViewerFileSetMode_HDF5));
843: PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerFileGetMode_C", PetscViewerFileGetMode_HDF5));
844: PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerHDF5SetBaseDimension2_C", PetscViewerHDF5SetBaseDimension2_HDF5));
845: PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerHDF5GetBaseDimension2_C", PetscViewerHDF5GetBaseDimension2_HDF5));
846: PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerHDF5SetSPOutput_C", PetscViewerHDF5SetSPOutput_HDF5));
847: PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerHDF5SetCollective_C", PetscViewerHDF5SetCollective_HDF5));
848: PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerHDF5GetCollective_C", PetscViewerHDF5GetCollective_HDF5));
849: PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerHDF5GetDefaultTimestepping_C", PetscViewerHDF5GetDefaultTimestepping_HDF5));
850: PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerHDF5SetDefaultTimestepping_C", PetscViewerHDF5SetDefaultTimestepping_HDF5));
851: PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerHDF5GetCompress_C", PetscViewerHDF5GetCompress_HDF5));
852: PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerHDF5SetCompress_C", PetscViewerHDF5SetCompress_HDF5));
853: PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerHDF5WriteGroup_C", PetscViewerHDF5WriteGroup_HDF5));
854: PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerHDF5PushGroup_C", PetscViewerHDF5PushGroup_HDF5));
855: PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerHDF5PopGroup_C", PetscViewerHDF5PopGroup_HDF5));
856: PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerHDF5GetGroup_C", PetscViewerHDF5GetGroup_HDF5));
857: PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerHDF5PushTimestepping_C", PetscViewerHDF5PushTimestepping_HDF5));
858: PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerHDF5PopTimestepping_C", PetscViewerHDF5PopTimestepping_HDF5));
859: PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerHDF5IsTimestepping_C", PetscViewerHDF5IsTimestepping_HDF5));
860: PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerHDF5IncrementTimestep_C", PetscViewerHDF5IncrementTimestep_HDF5));
861: PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerHDF5SetTimestep_C", PetscViewerHDF5SetTimestep_HDF5));
862: PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerHDF5GetTimestep_C", PetscViewerHDF5GetTimestep_HDF5));
863: PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerHDF5WriteAttribute_C", PetscViewerHDF5WriteAttribute_HDF5));
864: PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerHDF5ReadAttribute_C", PetscViewerHDF5ReadAttribute_HDF5));
865: PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerHDF5HasGroup_C", PetscViewerHDF5HasGroup_HDF5));
866: PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerHDF5HasDataset_C", PetscViewerHDF5HasDataset_HDF5));
867: PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerHDF5HasAttribute_C", PetscViewerHDF5HasAttribute_HDF5));
868: PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerHDF5GetSPOutput_C", PetscViewerHDF5GetSPOutput_HDF5));
869: PetscFunctionReturn(PETSC_SUCCESS);
870: }