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: }