xref: /petsc/src/sys/classes/viewer/impls/hdf5/hdf5v.c (revision 3014b61aa36a362266ae4eadf9b334e8b11a5815)
16b9fdc0aSVaclav Hapla #include <petsc/private/viewerhdf5impl.h> /*I "petscviewerhdf5.h" I*/
25c6c1daeSBarry Smith 
3bb286ee1SVaclav Hapla static PetscErrorCode PetscViewerHDF5Traverse_Internal(PetscViewer, const char[], PetscBool, PetscBool *, H5O_type_t *);
406db490cSVaclav Hapla static PetscErrorCode PetscViewerHDF5HasAttribute_Internal(PetscViewer, const char[], const char[], PetscBool *);
506db490cSVaclav Hapla 
677717648SVaclav Hapla /*@C
777717648SVaclav Hapla   PetscViewerHDF5GetGroup - Get the current HDF5 group name (full path), set with `PetscViewerHDF5PushGroup()`/`PetscViewerHDF5PopGroup()`.
877717648SVaclav Hapla 
977717648SVaclav Hapla   Not collective
1077717648SVaclav Hapla 
1177717648SVaclav Hapla   Input Parameters:
1277717648SVaclav Hapla + viewer - the `PetscViewer` of type `PETSCVIEWERHDF5`
1377717648SVaclav Hapla - path - (Optional) The path relative to the pushed group
1477717648SVaclav Hapla 
1577717648SVaclav Hapla   Output Parameter:
1677717648SVaclav Hapla . abspath - The absolute HDF5 path (group)
1777717648SVaclav Hapla 
1877717648SVaclav Hapla   Level: intermediate
1977717648SVaclav Hapla 
2077717648SVaclav Hapla   Notes:
2177717648SVaclav Hapla   If path starts with '/', it is taken as an absolute path overriding currently pushed group, else path is relative to the current pushed group.
2277717648SVaclav Hapla   So NULL or empty path means the current pushed group.
2377717648SVaclav Hapla 
2477717648SVaclav Hapla   The output abspath is newly allocated so needs to be freed.
2577717648SVaclav Hapla 
2677717648SVaclav Hapla .seealso: `PETSCVIEWERHDF5`, `PetscViewerHDF5Open()`, `PetscViewerHDF5PushGroup()`, `PetscViewerHDF5PopGroup()`, `PetscViewerHDF5OpenGroup()`
2777717648SVaclav Hapla @*/
2877717648SVaclav Hapla PetscErrorCode PetscViewerHDF5GetGroup(PetscViewer viewer, const char path[], char *abspath[]) {
2977717648SVaclav Hapla   size_t      len;
304302210dSVaclav Hapla   PetscBool   relative = PETSC_FALSE;
316c132bc1SVaclav Hapla   const char *group;
326c132bc1SVaclav Hapla   char        buf[PETSC_MAX_PATH_LEN] = "";
336c132bc1SVaclav Hapla 
346c132bc1SVaclav Hapla   PetscFunctionBegin;
3577717648SVaclav Hapla   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
3677717648SVaclav Hapla   if (path) PetscValidCharPointer(path, 2);
3777717648SVaclav Hapla   PetscValidPointer(abspath, 3);
3877717648SVaclav Hapla   PetscCall(PetscViewerHDF5GetGroup_Internal(viewer, &group));
3977717648SVaclav Hapla   PetscCall(PetscStrlen(path, &len));
4077717648SVaclav Hapla   relative = (PetscBool)(!len || path[0] != '/');
414302210dSVaclav Hapla   if (relative) {
429566063dSJacob Faibussowitsch     PetscCall(PetscStrcpy(buf, group));
4377717648SVaclav Hapla     if (!group || len) PetscCall(PetscStrcat(buf, "/"));
449566063dSJacob Faibussowitsch     PetscCall(PetscStrcat(buf, path));
459566063dSJacob Faibussowitsch     PetscCall(PetscStrallocpy(buf, abspath));
464302210dSVaclav Hapla   } else {
479566063dSJacob Faibussowitsch     PetscCall(PetscStrallocpy(path, abspath));
484302210dSVaclav Hapla   }
496c132bc1SVaclav Hapla   PetscFunctionReturn(0);
506c132bc1SVaclav Hapla }
516c132bc1SVaclav Hapla 
529371c9d4SSatish Balay static PetscErrorCode PetscViewerHDF5CheckNamedObject_Internal(PetscViewer viewer, PetscObject obj) {
53577e0e04SVaclav Hapla   PetscBool has;
54577e0e04SVaclav Hapla 
55577e0e04SVaclav Hapla   PetscFunctionBegin;
569566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5HasObject(viewer, obj, &has));
57577e0e04SVaclav Hapla   if (!has) {
5877717648SVaclav Hapla     char *group;
5977717648SVaclav Hapla     PetscCall(PetscViewerHDF5GetGroup(viewer, NULL, &group));
6077717648SVaclav Hapla     SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Object (dataset) \"%s\" not stored in group %s", obj->name, group);
61577e0e04SVaclav Hapla   }
62577e0e04SVaclav Hapla   PetscFunctionReturn(0);
63577e0e04SVaclav Hapla }
64577e0e04SVaclav Hapla 
659371c9d4SSatish Balay static PetscErrorCode PetscViewerSetFromOptions_HDF5(PetscViewer v, PetscOptionItems *PetscOptionsObject) {
66ee8b9732SVaclav Hapla   PetscBool         flg  = PETSC_FALSE, set;
6782ea9b62SBarry Smith   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)v->data;
6882ea9b62SBarry Smith 
6982ea9b62SBarry Smith   PetscFunctionBegin;
70d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HDF5 PetscViewer Options");
719566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-viewer_hdf5_base_dimension2", "1d Vectors get 2 dimensions in HDF5", "PetscViewerHDF5SetBaseDimension2", hdf5->basedimension2, &hdf5->basedimension2, NULL));
729566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-viewer_hdf5_sp_output", "Force data to be written in single precision", "PetscViewerHDF5SetSPOutput", hdf5->spoutput, &hdf5->spoutput, NULL));
739566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-viewer_hdf5_collective", "Enable collective transfer mode", "PetscViewerHDF5SetCollective", flg, &flg, &set));
749566063dSJacob Faibussowitsch   if (set) PetscCall(PetscViewerHDF5SetCollective(v, flg));
7519a20e4cSMatthew G. Knepley   flg = PETSC_FALSE;
769566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-viewer_hdf5_default_timestepping", "Set default timestepping state", "PetscViewerHDF5SetDefaultTimestepping", flg, &flg, &set));
779566063dSJacob Faibussowitsch   if (set) PetscCall(PetscViewerHDF5SetDefaultTimestepping(v, flg));
78d0609cedSBarry Smith   PetscOptionsHeadEnd();
7982ea9b62SBarry Smith   PetscFunctionReturn(0);
8082ea9b62SBarry Smith }
8182ea9b62SBarry Smith 
829371c9d4SSatish Balay static PetscErrorCode PetscViewerView_HDF5(PetscViewer v, PetscViewer viewer) {
831b793a25SVaclav Hapla   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)v->data;
8403fa8834SVaclav Hapla   PetscBool         flg;
851b793a25SVaclav Hapla 
861b793a25SVaclav Hapla   PetscFunctionBegin;
8748a46eb9SPierre Jolivet   if (hdf5->filename) PetscCall(PetscViewerASCIIPrintf(viewer, "Filename: %s\n", hdf5->filename));
889566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "Vectors with blocksize 1 saved as 2D datasets: %s\n", PetscBools[hdf5->basedimension2]));
899566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "Enforce single precision storage: %s\n", PetscBools[hdf5->spoutput]));
909566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5GetCollective(v, &flg));
919566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "MPI-IO transfer mode: %s\n", flg ? "collective" : "independent"));
929566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "Default timestepping: %s\n", PetscBools[hdf5->defTimestepping]));
931b793a25SVaclav Hapla   PetscFunctionReturn(0);
941b793a25SVaclav Hapla }
951b793a25SVaclav Hapla 
969371c9d4SSatish Balay static PetscErrorCode PetscViewerFileClose_HDF5(PetscViewer viewer) {
975c6c1daeSBarry Smith   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)viewer->data;
985c6c1daeSBarry Smith 
995c6c1daeSBarry Smith   PetscFunctionBegin;
1009566063dSJacob Faibussowitsch   PetscCall(PetscFree(hdf5->filename));
101792fecdfSBarry Smith   if (hdf5->file_id) PetscCallHDF5(H5Fclose, (hdf5->file_id));
1025c6c1daeSBarry Smith   PetscFunctionReturn(0);
1035c6c1daeSBarry Smith }
1045c6c1daeSBarry Smith 
1059371c9d4SSatish Balay static PetscErrorCode PetscViewerFlush_HDF5(PetscViewer viewer) {
1066226335aSVaclav Hapla   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)viewer->data;
1076226335aSVaclav Hapla 
1086226335aSVaclav Hapla   PetscFunctionBegin;
109792fecdfSBarry Smith   if (hdf5->file_id) PetscCallHDF5(H5Fflush, (hdf5->file_id, H5F_SCOPE_LOCAL));
1106226335aSVaclav Hapla   PetscFunctionReturn(0);
1116226335aSVaclav Hapla }
1126226335aSVaclav Hapla 
1139371c9d4SSatish Balay static PetscErrorCode PetscViewerDestroy_HDF5(PetscViewer viewer) {
1145c6c1daeSBarry Smith   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)viewer->data;
1155c6c1daeSBarry Smith 
1165c6c1daeSBarry Smith   PetscFunctionBegin;
117792fecdfSBarry Smith   PetscCallHDF5(H5Pclose, (hdf5->dxpl_id));
1189566063dSJacob Faibussowitsch   PetscCall(PetscViewerFileClose_HDF5(viewer));
1195c6c1daeSBarry Smith   while (hdf5->groups) {
1207d964842SVaclav Hapla     PetscViewerHDF5GroupList *tmp = hdf5->groups->next;
1215c6c1daeSBarry Smith 
1229566063dSJacob Faibussowitsch     PetscCall(PetscFree(hdf5->groups->name));
1239566063dSJacob Faibussowitsch     PetscCall(PetscFree(hdf5->groups));
1245c6c1daeSBarry Smith     hdf5->groups = tmp;
1255c6c1daeSBarry Smith   }
1269566063dSJacob Faibussowitsch   PetscCall(PetscFree(hdf5));
1279566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetName_C", NULL));
1289566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetName_C", NULL));
1299566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetMode_C", NULL));
1302e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetMode_C", NULL));
1319566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerHDF5SetBaseDimension2_C", NULL));
1329566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerHDF5SetSPOutput_C", NULL));
1332e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerHDF5SetCollective_C", NULL));
1342e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerHDF5GetCollective_C", NULL));
1359566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerHDF5GetDefaultTimestepping_C", NULL));
1369566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerHDF5SetDefaultTimestepping_C", NULL));
1375c6c1daeSBarry Smith   PetscFunctionReturn(0);
1385c6c1daeSBarry Smith }
1395c6c1daeSBarry Smith 
1409371c9d4SSatish Balay static PetscErrorCode PetscViewerFileSetMode_HDF5(PetscViewer viewer, PetscFileMode type) {
1415c6c1daeSBarry Smith   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)viewer->data;
1425c6c1daeSBarry Smith 
1435c6c1daeSBarry Smith   PetscFunctionBegin;
1445c6c1daeSBarry Smith   hdf5->btype = type;
1455c6c1daeSBarry Smith   PetscFunctionReturn(0);
1465c6c1daeSBarry Smith }
1475c6c1daeSBarry Smith 
1489371c9d4SSatish Balay static PetscErrorCode PetscViewerFileGetMode_HDF5(PetscViewer viewer, PetscFileMode *type) {
1490b62783dSVaclav Hapla   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)viewer->data;
1500b62783dSVaclav Hapla 
1510b62783dSVaclav Hapla   PetscFunctionBegin;
1520b62783dSVaclav Hapla   *type = hdf5->btype;
1530b62783dSVaclav Hapla   PetscFunctionReturn(0);
1540b62783dSVaclav Hapla }
1550b62783dSVaclav Hapla 
1569371c9d4SSatish Balay static PetscErrorCode PetscViewerHDF5SetBaseDimension2_HDF5(PetscViewer viewer, PetscBool flg) {
15782ea9b62SBarry Smith   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)viewer->data;
15882ea9b62SBarry Smith 
15982ea9b62SBarry Smith   PetscFunctionBegin;
16082ea9b62SBarry Smith   hdf5->basedimension2 = flg;
16182ea9b62SBarry Smith   PetscFunctionReturn(0);
16282ea9b62SBarry Smith }
16382ea9b62SBarry Smith 
164df863907SAlex Fikl /*@
16582ea9b62SBarry Smith      PetscViewerHDF5SetBaseDimension2 - Vectors of 1 dimension (i.e. bs/dof is 1) will be saved in the HDF5 file with a
16682ea9b62SBarry Smith        dimension of 2.
16782ea9b62SBarry Smith 
168811af0c4SBarry Smith     Logically Collective on viewer
16982ea9b62SBarry Smith 
17082ea9b62SBarry Smith   Input Parameters:
171811af0c4SBarry Smith +  viewer - the `PetscViewer`; if it is a `PETSCVIEWERHDF5` then this command is ignored
172811af0c4SBarry Smith -  flg - if `PETSC_TRUE` the vector will always have at least a dimension of 2 even if that first dimension is of size 1
17382ea9b62SBarry Smith 
174811af0c4SBarry Smith   Options Database Key:
17582ea9b62SBarry Smith .  -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
17682ea9b62SBarry Smith 
177811af0c4SBarry Smith   Note:
17895452b02SPatrick Sanan   Setting this option allegedly makes code that reads the HDF5 in easier since they do not have a "special case" of a bs/dof
17982ea9b62SBarry Smith   of one when the dimension is lower. Others think the option is crazy.
18082ea9b62SBarry Smith 
18182ea9b62SBarry Smith   Level: intermediate
18282ea9b62SBarry Smith 
183811af0c4SBarry Smith .seealso: `PETSCVIEWERHDF5`, PetscViewerFileSetMode()`, `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerBinaryOpen()`
18482ea9b62SBarry Smith @*/
1859371c9d4SSatish Balay PetscErrorCode PetscViewerHDF5SetBaseDimension2(PetscViewer viewer, PetscBool flg) {
18682ea9b62SBarry Smith   PetscFunctionBegin;
18782ea9b62SBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
188cac4c232SBarry Smith   PetscTryMethod(viewer, "PetscViewerHDF5SetBaseDimension2_C", (PetscViewer, PetscBool), (viewer, flg));
18982ea9b62SBarry Smith   PetscFunctionReturn(0);
19082ea9b62SBarry Smith }
19182ea9b62SBarry Smith 
192df863907SAlex Fikl /*@
19382ea9b62SBarry Smith      PetscViewerHDF5GetBaseDimension2 - Vectors of 1 dimension (i.e. bs/dof is 1) will be saved in the HDF5 file with a
19482ea9b62SBarry Smith        dimension of 2.
19582ea9b62SBarry Smith 
196811af0c4SBarry Smith     Logically Collective on viewer
19782ea9b62SBarry Smith 
19882ea9b62SBarry Smith   Input Parameter:
199811af0c4SBarry Smith .  viewer - the `PetscViewer`, must be `PETSCVIEWERHDF5`
20082ea9b62SBarry Smith 
20182ea9b62SBarry Smith   Output Parameter:
202811af0c4SBarry Smith .  flg - if `PETSC_TRUE` the vector will always have at least a dimension of 2 even if that first dimension is of size 1
20382ea9b62SBarry Smith 
204811af0c4SBarry Smith   Note:
20595452b02SPatrick Sanan   Setting this option allegedly makes code that reads the HDF5 in easier since they do not have a "special case" of a bs/dof
20682ea9b62SBarry Smith   of one when the dimension is lower. Others think the option is crazy.
20782ea9b62SBarry Smith 
20882ea9b62SBarry Smith   Level: intermediate
20982ea9b62SBarry Smith 
210811af0c4SBarry Smith .seealso: `PETSCVIEWERHDF5`, `PetscViewerFileSetMode()`, `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerBinaryOpen()`
21182ea9b62SBarry Smith @*/
2129371c9d4SSatish Balay PetscErrorCode PetscViewerHDF5GetBaseDimension2(PetscViewer viewer, PetscBool *flg) {
21382ea9b62SBarry Smith   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)viewer->data;
21482ea9b62SBarry Smith 
21582ea9b62SBarry Smith   PetscFunctionBegin;
21682ea9b62SBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
21782ea9b62SBarry Smith   *flg = hdf5->basedimension2;
21882ea9b62SBarry Smith   PetscFunctionReturn(0);
21982ea9b62SBarry Smith }
22082ea9b62SBarry Smith 
2219371c9d4SSatish Balay static PetscErrorCode PetscViewerHDF5SetSPOutput_HDF5(PetscViewer viewer, PetscBool flg) {
2229a0502c6SHåkon Strandenes   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)viewer->data;
2239a0502c6SHåkon Strandenes 
2249a0502c6SHåkon Strandenes   PetscFunctionBegin;
2259a0502c6SHåkon Strandenes   hdf5->spoutput = flg;
2269a0502c6SHåkon Strandenes   PetscFunctionReturn(0);
2279a0502c6SHåkon Strandenes }
2289a0502c6SHåkon Strandenes 
229df863907SAlex Fikl /*@
2309a0502c6SHåkon Strandenes      PetscViewerHDF5SetSPOutput - Data is written to disk in single precision even if PETSc is
231811af0c4SBarry Smith        compiled with double precision `PetscReal`.
2329a0502c6SHåkon Strandenes 
233811af0c4SBarry Smith     Logically Collective on viewer
2349a0502c6SHåkon Strandenes 
2359a0502c6SHåkon Strandenes   Input Parameters:
236811af0c4SBarry Smith +  viewer - the PetscViewer; if it is a `PETSCVIEWERHDF5` then this command is ignored
237811af0c4SBarry Smith -  flg - if `PETSC_TRUE` the data will be written to disk with single precision
2389a0502c6SHåkon Strandenes 
239811af0c4SBarry Smith   Options Database Key:
2409a0502c6SHåkon Strandenes .  -viewer_hdf5_sp_output - turns on (true) or off (false) output in single precision
2419a0502c6SHåkon Strandenes 
242811af0c4SBarry Smith   Note:
24395452b02SPatrick Sanan     Setting this option does not make any difference if PETSc is compiled with single precision
2449a0502c6SHåkon Strandenes          in the first place. It does not affect reading datasets (HDF5 handle this internally).
2459a0502c6SHåkon Strandenes 
2469a0502c6SHåkon Strandenes   Level: intermediate
2479a0502c6SHåkon Strandenes 
248811af0c4SBarry Smith .seealso: `PETSCVIEWERHDF5`, `PetscViewerFileSetMode()`, `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerBinaryOpen()`,
249811af0c4SBarry Smith           `PetscReal`, `PetscViewerHDF5GetSPOutput()`
2509a0502c6SHåkon Strandenes @*/
2519371c9d4SSatish Balay PetscErrorCode PetscViewerHDF5SetSPOutput(PetscViewer viewer, PetscBool flg) {
2529a0502c6SHåkon Strandenes   PetscFunctionBegin;
2539a0502c6SHåkon Strandenes   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
254cac4c232SBarry Smith   PetscTryMethod(viewer, "PetscViewerHDF5SetSPOutput_C", (PetscViewer, PetscBool), (viewer, flg));
2559a0502c6SHåkon Strandenes   PetscFunctionReturn(0);
2569a0502c6SHåkon Strandenes }
2579a0502c6SHåkon Strandenes 
258df863907SAlex Fikl /*@
2599a0502c6SHåkon Strandenes      PetscViewerHDF5GetSPOutput - Data is written to disk in single precision even if PETSc is
260811af0c4SBarry Smith        compiled with double precision `PetscReal`.
2619a0502c6SHåkon Strandenes 
262811af0c4SBarry Smith     Logically Collective on viewer
2639a0502c6SHåkon Strandenes 
2649a0502c6SHåkon Strandenes   Input Parameter:
265811af0c4SBarry Smith .  viewer - the PetscViewer, must be of type `PETSCVIEWERHDF5`
2669a0502c6SHåkon Strandenes 
2679a0502c6SHåkon Strandenes   Output Parameter:
268811af0c4SBarry Smith .  flg - if `PETSC_TRUE` the data will be written to disk with single precision
2699a0502c6SHåkon Strandenes 
2709a0502c6SHåkon Strandenes   Level: intermediate
2719a0502c6SHåkon Strandenes 
272db781477SPatrick Sanan .seealso: `PetscViewerFileSetMode()`, `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerBinaryOpen()`,
273811af0c4SBarry Smith           `PetscReal`, `PetscViewerHDF5SetSPOutput()`
2749a0502c6SHåkon Strandenes @*/
2759371c9d4SSatish Balay PetscErrorCode PetscViewerHDF5GetSPOutput(PetscViewer viewer, PetscBool *flg) {
2769a0502c6SHåkon Strandenes   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)viewer->data;
2779a0502c6SHåkon Strandenes 
2789a0502c6SHåkon Strandenes   PetscFunctionBegin;
2799a0502c6SHåkon Strandenes   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
2809a0502c6SHåkon Strandenes   *flg = hdf5->spoutput;
2819a0502c6SHåkon Strandenes   PetscFunctionReturn(0);
2829a0502c6SHåkon Strandenes }
2839a0502c6SHåkon Strandenes 
2849371c9d4SSatish Balay static PetscErrorCode PetscViewerHDF5SetCollective_HDF5(PetscViewer viewer, PetscBool flg) {
285ee8b9732SVaclav Hapla   PetscFunctionBegin;
286ee8b9732SVaclav Hapla   /* H5FD_MPIO_COLLECTIVE is wrong in hdf5 1.10.2, and is the same as H5FD_MPIO_INDEPENDENT in earlier versions
287ee8b9732SVaclav Hapla      - see e.g. https://gitlab.cosma.dur.ac.uk/swift/swiftsim/issues/431 */
288c796909eSBarry Smith #if H5_VERSION_GE(1, 10, 3) && defined(H5_HAVE_PARALLEL)
289ee8b9732SVaclav Hapla   {
290ee8b9732SVaclav Hapla     PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)viewer->data;
291792fecdfSBarry Smith     PetscCallHDF5(H5Pset_dxpl_mpio, (hdf5->dxpl_id, flg ? H5FD_MPIO_COLLECTIVE : H5FD_MPIO_INDEPENDENT));
292ee8b9732SVaclav Hapla   }
293ee8b9732SVaclav Hapla #else
2949566063dSJacob Faibussowitsch   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"));
295ee8b9732SVaclav Hapla #endif
296ee8b9732SVaclav Hapla   PetscFunctionReturn(0);
297ee8b9732SVaclav Hapla }
298ee8b9732SVaclav Hapla 
299ee8b9732SVaclav Hapla /*@
300ee8b9732SVaclav Hapla   PetscViewerHDF5SetCollective - Use collective MPI-IO transfer mode for HDF5 reads and writes.
301ee8b9732SVaclav Hapla 
302ee8b9732SVaclav Hapla   Logically Collective; flg must contain common value
303ee8b9732SVaclav Hapla 
304ee8b9732SVaclav Hapla   Input Parameters:
305811af0c4SBarry Smith + viewer - the `PetscViewer`; if it is not `PETSCVIEWERHDF5` then this command is ignored
306811af0c4SBarry Smith - flg - `PETSC_TRUE` for collective mode; `PETSC_FALSE` for independent mode (default)
307ee8b9732SVaclav Hapla 
308811af0c4SBarry Smith   Options Database Key:
309ee8b9732SVaclav Hapla . -viewer_hdf5_collective - turns on (true) or off (false) collective transfers
310ee8b9732SVaclav Hapla 
311811af0c4SBarry Smith   Note:
312ee8b9732SVaclav Hapla   Collective mode gives the MPI-IO layer underneath HDF5 a chance to do some additional collective optimizations and hence can perform better.
31353effed7SBarry Smith   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.
314ee8b9732SVaclav Hapla 
315811af0c4SBarry Smith   Developer Note:
316811af0c4SBarry Smith   In the HDF5 layer, `PETSC_TRUE` / `PETSC_FALSE` means `H5Pset_dxpl_mpio()` is called with `H5FD_MPIO_COLLECTIVE` / `H5FD_MPIO_INDEPENDENT`, respectively.
317ee8b9732SVaclav Hapla   This in turn means use of MPI_File_{read,write}_all /  MPI_File_{read,write} in the MPI-IO layer, respectively.
318ee8b9732SVaclav Hapla   See HDF5 documentation and MPI-IO documentation for details.
319ee8b9732SVaclav Hapla 
320ee8b9732SVaclav Hapla   Level: intermediate
321ee8b9732SVaclav Hapla 
322811af0c4SBarry Smith .seealso: `PETSCVIEWERHDF5`, `PetscViewerHDF5GetCollective()`, `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerHDF5Open()`
323ee8b9732SVaclav Hapla @*/
3249371c9d4SSatish Balay PetscErrorCode PetscViewerHDF5SetCollective(PetscViewer viewer, PetscBool flg) {
325ee8b9732SVaclav Hapla   PetscFunctionBegin;
326ee8b9732SVaclav Hapla   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
327ee8b9732SVaclav Hapla   PetscValidLogicalCollectiveBool(viewer, flg, 2);
328cac4c232SBarry Smith   PetscTryMethod(viewer, "PetscViewerHDF5SetCollective_C", (PetscViewer, PetscBool), (viewer, flg));
329ee8b9732SVaclav Hapla   PetscFunctionReturn(0);
330ee8b9732SVaclav Hapla }
331ee8b9732SVaclav Hapla 
3329371c9d4SSatish Balay static PetscErrorCode PetscViewerHDF5GetCollective_HDF5(PetscViewer viewer, PetscBool *flg) {
333c796909eSBarry Smith #if defined(H5_HAVE_PARALLEL)
334ee8b9732SVaclav Hapla   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)viewer->data;
335ee8b9732SVaclav Hapla   H5FD_mpio_xfer_t  mode;
336c796909eSBarry Smith #endif
337ee8b9732SVaclav Hapla 
338ee8b9732SVaclav Hapla   PetscFunctionBegin;
339c796909eSBarry Smith #if !defined(H5_HAVE_PARALLEL)
340c796909eSBarry Smith   *flg = PETSC_FALSE;
341c796909eSBarry Smith #else
342792fecdfSBarry Smith   PetscCallHDF5(H5Pget_dxpl_mpio, (hdf5->dxpl_id, &mode));
343ee8b9732SVaclav Hapla   *flg = (mode == H5FD_MPIO_COLLECTIVE) ? PETSC_TRUE : PETSC_FALSE;
344c796909eSBarry Smith #endif
345ee8b9732SVaclav Hapla   PetscFunctionReturn(0);
346ee8b9732SVaclav Hapla }
347ee8b9732SVaclav Hapla 
348ee8b9732SVaclav Hapla /*@
349ee8b9732SVaclav Hapla   PetscViewerHDF5GetCollective - Return flag whether collective MPI-IO transfer mode is used for HDF5 reads and writes.
350ee8b9732SVaclav Hapla 
351ee8b9732SVaclav Hapla   Not Collective
352ee8b9732SVaclav Hapla 
353ee8b9732SVaclav Hapla   Input Parameters:
354811af0c4SBarry Smith . viewer - the `PETSCVIEWERHDF5` `PetscViewer`
355ee8b9732SVaclav Hapla 
356ee8b9732SVaclav Hapla   Output Parameters:
357ee8b9732SVaclav Hapla . flg - the flag
358ee8b9732SVaclav Hapla 
359ee8b9732SVaclav Hapla   Level: intermediate
360ee8b9732SVaclav Hapla 
361811af0c4SBarry Smith   Note:
362811af0c4SBarry Smith   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.
363811af0c4SBarry Smith   For more details, see `PetscViewerHDF5SetCollective()`.
364ee8b9732SVaclav Hapla 
365811af0c4SBarry Smith .seealso: `PETSCVIEWERHDF5`, `PetscViewerHDF5SetCollective()`, `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerHDF5Open()`
366ee8b9732SVaclav Hapla @*/
3679371c9d4SSatish Balay PetscErrorCode PetscViewerHDF5GetCollective(PetscViewer viewer, PetscBool *flg) {
368ee8b9732SVaclav Hapla   PetscFunctionBegin;
369ee8b9732SVaclav Hapla   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
370534a8f05SLisandro Dalcin   PetscValidBoolPointer(flg, 2);
371ee8b9732SVaclav Hapla 
372cac4c232SBarry Smith   PetscUseMethod(viewer, "PetscViewerHDF5GetCollective_C", (PetscViewer, PetscBool *), (viewer, flg));
373ee8b9732SVaclav Hapla   PetscFunctionReturn(0);
374ee8b9732SVaclav Hapla }
375ee8b9732SVaclav Hapla 
3769371c9d4SSatish Balay static PetscErrorCode PetscViewerFileSetName_HDF5(PetscViewer viewer, const char name[]) {
3775c6c1daeSBarry Smith   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)viewer->data;
3785c6c1daeSBarry Smith   hid_t             plist_id;
3795c6c1daeSBarry Smith 
3805c6c1daeSBarry Smith   PetscFunctionBegin;
381792fecdfSBarry Smith   if (hdf5->file_id) PetscCallHDF5(H5Fclose, (hdf5->file_id));
3829566063dSJacob Faibussowitsch   if (hdf5->filename) PetscCall(PetscFree(hdf5->filename));
3839566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(name, &hdf5->filename));
3845c6c1daeSBarry Smith   /* Set up file access property list with parallel I/O access */
385792fecdfSBarry Smith   PetscCallHDF5Return(plist_id, H5Pcreate, (H5P_FILE_ACCESS));
386c796909eSBarry Smith #if defined(H5_HAVE_PARALLEL)
387792fecdfSBarry Smith   PetscCallHDF5(H5Pset_fapl_mpio, (plist_id, PetscObjectComm((PetscObject)viewer), MPI_INFO_NULL));
388c796909eSBarry Smith #endif
3895c6c1daeSBarry Smith   /* Create or open the file collectively */
3905c6c1daeSBarry Smith   switch (hdf5->btype) {
3915c6c1daeSBarry Smith   case FILE_MODE_READ:
3928a2871f6SBarry Smith     if (PetscDefined(USE_DEBUG)) {
3938a2871f6SBarry Smith       PetscMPIInt rank;
3948a2871f6SBarry Smith       PetscBool   flg;
3958a2871f6SBarry Smith 
3969566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
3978a2871f6SBarry Smith       if (rank == 0) {
3989566063dSJacob Faibussowitsch         PetscCall(PetscTestFile(hdf5->filename, 'r', &flg));
3995f80ce2aSJacob Faibussowitsch         PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "File %s requested for reading does not exist", hdf5->filename);
4008a2871f6SBarry Smith       }
4019566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Barrier(PetscObjectComm((PetscObject)viewer)));
4028a2871f6SBarry Smith     }
403792fecdfSBarry Smith     PetscCallHDF5Return(hdf5->file_id, H5Fopen, (name, H5F_ACC_RDONLY, plist_id));
4045c6c1daeSBarry Smith     break;
4055c6c1daeSBarry Smith   case FILE_MODE_APPEND:
4069371c9d4SSatish Balay   case FILE_MODE_UPDATE: {
4077e4fd573SVaclav Hapla     PetscBool flg;
4089566063dSJacob Faibussowitsch     PetscCall(PetscTestFile(hdf5->filename, 'r', &flg));
409792fecdfSBarry Smith     if (flg) PetscCallHDF5Return(hdf5->file_id, H5Fopen, (name, H5F_ACC_RDWR, plist_id));
410792fecdfSBarry Smith     else PetscCallHDF5Return(hdf5->file_id, H5Fcreate, (name, H5F_ACC_EXCL, H5P_DEFAULT, plist_id));
4115c6c1daeSBarry Smith     break;
4127e4fd573SVaclav Hapla   }
4139371c9d4SSatish Balay   case FILE_MODE_WRITE: PetscCallHDF5Return(hdf5->file_id, H5Fcreate, (name, H5F_ACC_TRUNC, H5P_DEFAULT, plist_id)); break;
4149371c9d4SSatish Balay   case FILE_MODE_UNDEFINED: SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_ORDER, "Must call PetscViewerFileSetMode() before PetscViewerFileSetName()");
4159371c9d4SSatish Balay   default: SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Unsupported file mode %s", PetscFileModes[hdf5->btype]);
4165c6c1daeSBarry Smith   }
4175f80ce2aSJacob Faibussowitsch   PetscCheck(hdf5->file_id >= 0, PETSC_COMM_SELF, PETSC_ERR_LIB, "H5Fcreate failed for %s", name);
418792fecdfSBarry Smith   PetscCallHDF5(H5Pclose, (plist_id));
4195c6c1daeSBarry Smith   PetscFunctionReturn(0);
4205c6c1daeSBarry Smith }
4215c6c1daeSBarry Smith 
4229371c9d4SSatish Balay static PetscErrorCode PetscViewerFileGetName_HDF5(PetscViewer viewer, const char **name) {
423d1232d7fSToby Isaac   PetscViewer_HDF5 *vhdf5 = (PetscViewer_HDF5 *)viewer->data;
424d1232d7fSToby Isaac 
425d1232d7fSToby Isaac   PetscFunctionBegin;
426d1232d7fSToby Isaac   *name = vhdf5->filename;
427d1232d7fSToby Isaac   PetscFunctionReturn(0);
428d1232d7fSToby Isaac }
429d1232d7fSToby Isaac 
4309371c9d4SSatish Balay static PetscErrorCode PetscViewerSetUp_HDF5(PetscViewer viewer) {
4315dc64a97SVaclav Hapla   /*
432b723ab35SVaclav Hapla   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;
4335dc64a97SVaclav Hapla   */
434b723ab35SVaclav Hapla 
435b723ab35SVaclav Hapla   PetscFunctionBegin;
436b723ab35SVaclav Hapla   PetscFunctionReturn(0);
437b723ab35SVaclav Hapla }
438b723ab35SVaclav Hapla 
4399371c9d4SSatish Balay static PetscErrorCode PetscViewerHDF5SetDefaultTimestepping_HDF5(PetscViewer viewer, PetscBool flg) {
44019a20e4cSMatthew G. Knepley   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)viewer->data;
44119a20e4cSMatthew G. Knepley 
44219a20e4cSMatthew G. Knepley   PetscFunctionBegin;
44319a20e4cSMatthew G. Knepley   hdf5->defTimestepping = flg;
44419a20e4cSMatthew G. Knepley   PetscFunctionReturn(0);
44519a20e4cSMatthew G. Knepley }
44619a20e4cSMatthew G. Knepley 
4479371c9d4SSatish Balay static PetscErrorCode PetscViewerHDF5GetDefaultTimestepping_HDF5(PetscViewer viewer, PetscBool *flg) {
44819a20e4cSMatthew G. Knepley   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)viewer->data;
44919a20e4cSMatthew G. Knepley 
45019a20e4cSMatthew G. Knepley   PetscFunctionBegin;
45119a20e4cSMatthew G. Knepley   *flg = hdf5->defTimestepping;
45219a20e4cSMatthew G. Knepley   PetscFunctionReturn(0);
45319a20e4cSMatthew G. Knepley }
45419a20e4cSMatthew G. Knepley 
45519a20e4cSMatthew G. Knepley /*@
45619a20e4cSMatthew G. Knepley   PetscViewerHDF5SetDefaultTimestepping - Set the flag for default timestepping
45719a20e4cSMatthew G. Knepley 
458811af0c4SBarry Smith   Logically Collective on viewer
45919a20e4cSMatthew G. Knepley 
46019a20e4cSMatthew G. Knepley   Input Parameters:
461811af0c4SBarry Smith + viewer - the `PetscViewer`; if it is not `PETSCVIEWERHDF5` then this command is ignored
462811af0c4SBarry Smith - flg    - if `PETSC_TRUE` we will assume that timestepping is on
46319a20e4cSMatthew G. Knepley 
464811af0c4SBarry Smith   Options Database Key:
46519a20e4cSMatthew G. Knepley . -viewer_hdf5_default_timestepping - turns on (true) or off (false) default timestepping
46619a20e4cSMatthew G. Knepley 
467811af0c4SBarry Smith   Note:
46819a20e4cSMatthew G. Knepley   If the timestepping attribute is not found for an object, then the default timestepping is used
46919a20e4cSMatthew G. Knepley 
47019a20e4cSMatthew G. Knepley   Level: intermediate
47119a20e4cSMatthew G. Knepley 
472811af0c4SBarry Smith .seealso: `PETSCVIEWERHDF5`, `PetscViewerHDF5GetDefaultTimestepping()`, `PetscViewerHDF5PushTimestepping()`, `PetscViewerHDF5GetTimestep()`
47319a20e4cSMatthew G. Knepley @*/
4749371c9d4SSatish Balay PetscErrorCode PetscViewerHDF5SetDefaultTimestepping(PetscViewer viewer, PetscBool flg) {
47519a20e4cSMatthew G. Knepley   PetscFunctionBegin;
47619a20e4cSMatthew G. Knepley   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
477cac4c232SBarry Smith   PetscTryMethod(viewer, "PetscViewerHDF5SetDefaultTimestepping_C", (PetscViewer, PetscBool), (viewer, flg));
47819a20e4cSMatthew G. Knepley   PetscFunctionReturn(0);
47919a20e4cSMatthew G. Knepley }
48019a20e4cSMatthew G. Knepley 
48119a20e4cSMatthew G. Knepley /*@
48219a20e4cSMatthew G. Knepley   PetscViewerHDF5GetDefaultTimestepping - Get the flag for default timestepping
48319a20e4cSMatthew G. Knepley 
48419a20e4cSMatthew G. Knepley   Not collective
48519a20e4cSMatthew G. Knepley 
48619a20e4cSMatthew G. Knepley   Input Parameter:
487811af0c4SBarry Smith . viewer - the `PetscViewer` of type `PETSCVIEWERHDF5`
48819a20e4cSMatthew G. Knepley 
48919a20e4cSMatthew G. Knepley   Output Parameter:
490811af0c4SBarry Smith . flg    - if `PETSC_TRUE` we will assume that timestepping is on
49119a20e4cSMatthew G. Knepley 
49219a20e4cSMatthew G. Knepley   Level: intermediate
49319a20e4cSMatthew G. Knepley 
494811af0c4SBarry Smith .seealso: `PETSCVIEWERHDF5`, `PetscViewerHDF5SetDefaultTimestepping()`, `PetscViewerHDF5PushTimestepping()`, `PetscViewerHDF5GetTimestep()`
49519a20e4cSMatthew G. Knepley @*/
4969371c9d4SSatish Balay PetscErrorCode PetscViewerHDF5GetDefaultTimestepping(PetscViewer viewer, PetscBool *flg) {
49719a20e4cSMatthew G. Knepley   PetscFunctionBegin;
49819a20e4cSMatthew G. Knepley   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
499cac4c232SBarry Smith   PetscUseMethod(viewer, "PetscViewerHDF5GetDefaultTimestepping_C", (PetscViewer, PetscBool *), (viewer, flg));
50019a20e4cSMatthew G. Knepley   PetscFunctionReturn(0);
50119a20e4cSMatthew G. Knepley }
50219a20e4cSMatthew G. Knepley 
5038556b5ebSBarry Smith /*MC
5048556b5ebSBarry Smith    PETSCVIEWERHDF5 - A viewer that writes to an HDF5 file
5058556b5ebSBarry Smith 
506811af0c4SBarry Smith   Level: beginner
507811af0c4SBarry Smith 
508db781477SPatrick Sanan .seealso: `PetscViewerHDF5Open()`, `PetscViewerStringSPrintf()`, `PetscViewerSocketOpen()`, `PetscViewerDrawOpen()`, `PETSCVIEWERSOCKET`,
509db781477SPatrick Sanan           `PetscViewerCreate()`, `PetscViewerASCIIOpen()`, `PetscViewerBinaryOpen()`, `PETSCVIEWERBINARY`, `PETSCVIEWERDRAW`, `PETSCVIEWERSTRING`,
510db781477SPatrick Sanan           `PetscViewerMatlabOpen()`, `VecView()`, `DMView()`, `PetscViewerMatlabPutArray()`, `PETSCVIEWERASCII`, `PETSCVIEWERMATLAB`,
511db781477SPatrick Sanan           `PetscViewerFileSetName()`, `PetscViewerFileSetMode()`, `PetscViewerFormat`, `PetscViewerType`, `PetscViewerSetType()`
5128556b5ebSBarry Smith M*/
513d1232d7fSToby Isaac 
5149371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode PetscViewerCreate_HDF5(PetscViewer v) {
5155c6c1daeSBarry Smith   PetscViewer_HDF5 *hdf5;
5165c6c1daeSBarry Smith 
5175c6c1daeSBarry Smith   PetscFunctionBegin;
51899335c34SVaclav Hapla #if !defined(H5_HAVE_PARALLEL)
51999335c34SVaclav Hapla   {
52099335c34SVaclav Hapla     PetscMPIInt size;
5219566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)v), &size));
5225f80ce2aSJacob Faibussowitsch     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)");
52399335c34SVaclav Hapla   }
52499335c34SVaclav Hapla #endif
52599335c34SVaclav Hapla 
5269566063dSJacob Faibussowitsch   PetscCall(PetscNewLog(v, &hdf5));
5275c6c1daeSBarry Smith 
5285c6c1daeSBarry Smith   v->data                = (void *)hdf5;
5295c6c1daeSBarry Smith   v->ops->destroy        = PetscViewerDestroy_HDF5;
53082ea9b62SBarry Smith   v->ops->setfromoptions = PetscViewerSetFromOptions_HDF5;
531b723ab35SVaclav Hapla   v->ops->setup          = PetscViewerSetUp_HDF5;
5321b793a25SVaclav Hapla   v->ops->view           = PetscViewerView_HDF5;
5336226335aSVaclav Hapla   v->ops->flush          = PetscViewerFlush_HDF5;
5347e4fd573SVaclav Hapla   hdf5->btype            = FILE_MODE_UNDEFINED;
535908793a3SLisandro Dalcin   hdf5->filename         = NULL;
5365c6c1daeSBarry Smith   hdf5->timestep         = -1;
5370298fd71SBarry Smith   hdf5->groups           = NULL;
5385c6c1daeSBarry Smith 
539792fecdfSBarry Smith   PetscCallHDF5Return(hdf5->dxpl_id, H5Pcreate, (H5P_DATASET_XFER));
5409c5072fbSVaclav Hapla 
5419566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerFileSetName_C", PetscViewerFileSetName_HDF5));
5429566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerFileGetName_C", PetscViewerFileGetName_HDF5));
5439566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerFileSetMode_C", PetscViewerFileSetMode_HDF5));
5449566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerFileGetMode_C", PetscViewerFileGetMode_HDF5));
5459566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerHDF5SetBaseDimension2_C", PetscViewerHDF5SetBaseDimension2_HDF5));
5469566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerHDF5SetSPOutput_C", PetscViewerHDF5SetSPOutput_HDF5));
5479566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerHDF5SetCollective_C", PetscViewerHDF5SetCollective_HDF5));
5489566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerHDF5GetCollective_C", PetscViewerHDF5GetCollective_HDF5));
5499566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerHDF5GetDefaultTimestepping_C", PetscViewerHDF5GetDefaultTimestepping_HDF5));
5509566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerHDF5SetDefaultTimestepping_C", PetscViewerHDF5SetDefaultTimestepping_HDF5));
5515c6c1daeSBarry Smith   PetscFunctionReturn(0);
5525c6c1daeSBarry Smith }
5535c6c1daeSBarry Smith 
5545c6c1daeSBarry Smith /*@C
555811af0c4SBarry Smith    PetscViewerHDF5Open - Opens a file for HDF5 input/output as a `PETSCVIEWERHDF5` `PetscViewer`
5565c6c1daeSBarry Smith 
557d083f849SBarry Smith    Collective
5585c6c1daeSBarry Smith 
5595c6c1daeSBarry Smith    Input Parameters:
5605c6c1daeSBarry Smith +  comm - MPI communicator
5615c6c1daeSBarry Smith .  name - name of file
5625c6c1daeSBarry Smith -  type - type of file
5635c6c1daeSBarry Smith 
5645c6c1daeSBarry Smith    Output Parameter:
565811af0c4SBarry Smith .  hdf5v - `PetscViewer` for HDF5 input/output to use with the specified file
5665c6c1daeSBarry Smith 
567811af0c4SBarry Smith   Options Database Keys:
568a2b725a8SWilliam Gropp +  -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
569a2b725a8SWilliam Gropp -  -viewer_hdf5_sp_output - forces (if true) the viewer to write data in single precision independent on the precision of PetscReal
57082ea9b62SBarry Smith 
5715c6c1daeSBarry Smith    Level: beginner
5725c6c1daeSBarry Smith 
5737e4fd573SVaclav Hapla    Notes:
5747e4fd573SVaclav Hapla    Reading is always available, regardless of the mode. Available modes are
575811af0c4SBarry Smith .vb
576811af0c4SBarry Smith   FILE_MODE_READ - open existing HDF5 file for read only access, fail if file does not exist [H5Fopen() with H5F_ACC_RDONLY]
577811af0c4SBarry Smith   FILE_MODE_WRITE - if file exists, fully overwrite it, else create new HDF5 file [H5FcreateH5Fcreate() with H5F_ACC_TRUNC]
578811af0c4SBarry Smith   FILE_MODE_APPEND - if file exists, keep existing contents [H5Fopen() with H5F_ACC_RDWR], else create new HDF5 file [H5FcreateH5Fcreate() with H5F_ACC_EXCL]
579811af0c4SBarry Smith   FILE_MODE_UPDATE - same as FILE_MODE_APPEND
580811af0c4SBarry Smith .ve
5817e4fd573SVaclav Hapla 
582811af0c4SBarry Smith    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.
5837e4fd573SVaclav Hapla 
5845c6c1daeSBarry Smith    This PetscViewer should be destroyed with PetscViewerDestroy().
5855c6c1daeSBarry Smith 
586811af0c4SBarry Smith .seealso: `PETSCVIEWERHDF5`, `PetscViewerASCIIOpen()`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`, `PetscViewerHDF5SetBaseDimension2()`,
587db781477SPatrick Sanan           `PetscViewerHDF5SetSPOutput()`, `PetscViewerHDF5GetBaseDimension2()`, `VecView()`, `MatView()`, `VecLoad()`,
588db781477SPatrick Sanan           `MatLoad()`, `PetscFileMode`, `PetscViewer`, `PetscViewerSetType()`, `PetscViewerFileSetMode()`, `PetscViewerFileSetName()`
5895c6c1daeSBarry Smith @*/
5909371c9d4SSatish Balay PetscErrorCode PetscViewerHDF5Open(MPI_Comm comm, const char name[], PetscFileMode type, PetscViewer *hdf5v) {
5915c6c1daeSBarry Smith   PetscFunctionBegin;
5929566063dSJacob Faibussowitsch   PetscCall(PetscViewerCreate(comm, hdf5v));
5939566063dSJacob Faibussowitsch   PetscCall(PetscViewerSetType(*hdf5v, PETSCVIEWERHDF5));
5949566063dSJacob Faibussowitsch   PetscCall(PetscViewerFileSetMode(*hdf5v, type));
5959566063dSJacob Faibussowitsch   PetscCall(PetscViewerFileSetName(*hdf5v, name));
5969566063dSJacob Faibussowitsch   PetscCall(PetscViewerSetFromOptions(*hdf5v));
5975c6c1daeSBarry Smith   PetscFunctionReturn(0);
5985c6c1daeSBarry Smith }
5995c6c1daeSBarry Smith 
6005c6c1daeSBarry Smith /*@C
6015c6c1daeSBarry Smith   PetscViewerHDF5GetFileId - Retrieve the file id, this file ID then can be used in direct HDF5 calls
6025c6c1daeSBarry Smith 
6035c6c1daeSBarry Smith   Not collective
6045c6c1daeSBarry Smith 
6055c6c1daeSBarry Smith   Input Parameter:
606811af0c4SBarry Smith . viewer - the `PetscViewer`
6075c6c1daeSBarry Smith 
6085c6c1daeSBarry Smith   Output Parameter:
6095c6c1daeSBarry Smith . file_id - The file id
6105c6c1daeSBarry Smith 
6115c6c1daeSBarry Smith   Level: intermediate
6125c6c1daeSBarry Smith 
613811af0c4SBarry Smith .seealso: `PETSCVIEWERHDF5`, `PetscViewerHDF5Open()`
6145c6c1daeSBarry Smith @*/
6159371c9d4SSatish Balay PetscErrorCode PetscViewerHDF5GetFileId(PetscViewer viewer, hid_t *file_id) {
6165c6c1daeSBarry Smith   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)viewer->data;
6175c6c1daeSBarry Smith 
6185c6c1daeSBarry Smith   PetscFunctionBegin;
6195c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
6205c6c1daeSBarry Smith   if (file_id) *file_id = hdf5->file_id;
6215c6c1daeSBarry Smith   PetscFunctionReturn(0);
6225c6c1daeSBarry Smith }
6235c6c1daeSBarry Smith 
6245c6c1daeSBarry Smith /*@C
6255c6c1daeSBarry Smith   PetscViewerHDF5PushGroup - Set the current HDF5 group for output
6265c6c1daeSBarry Smith 
6275c6c1daeSBarry Smith   Not collective
6285c6c1daeSBarry Smith 
6295c6c1daeSBarry Smith   Input Parameters:
630811af0c4SBarry Smith + viewer - the `PetscViewer` of type `PETSCVIEWERHDF5`
6315c6c1daeSBarry Smith - name - The group name
6325c6c1daeSBarry Smith 
6335c6c1daeSBarry Smith   Level: intermediate
6345c6c1daeSBarry Smith 
6352e361344SVaclav Hapla   Notes:
6362e361344SVaclav Hapla   This is designed to mnemonically resemble the Unix cd command.
637811af0c4SBarry Smith .vb
638811af0c4SBarry Smith   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.
639811af0c4SBarry Smith   NULL, empty string, or any sequence of all slashes (e.g. "///") is interpreted as the root group "/".
640811af0c4SBarry Smith   "." means the current group is pushed again.
641811af0c4SBarry Smith .ve
6422e361344SVaclav Hapla 
6432e361344SVaclav Hapla   Example:
6442e361344SVaclav Hapla   Suppose the current group is "/a".
6452e361344SVaclav Hapla   + If name is NULL, empty string, or a sequence of all slashes (e.g. "///"), then the new group will be "/".
6462e361344SVaclav Hapla   . If name is ".", then the new group will be "/a".
6472e361344SVaclav Hapla   . If name is "b", then the new group will be "/a/b".
6482e361344SVaclav Hapla   - If name is "/b", then the new group will be "/b".
6492e361344SVaclav Hapla 
650811af0c4SBarry Smith   Developer Note:
6512e361344SVaclav Hapla   The root group "/" is internally stored as NULL.
652820fc2d1SVaclav Hapla 
653811af0c4SBarry Smith .seealso: `PETSCVIEWERHDF5`, `PetscViewerHDF5Open()`, `PetscViewerHDF5PopGroup()`, `PetscViewerHDF5GetGroup()`, `PetscViewerHDF5OpenGroup()`
6545c6c1daeSBarry Smith @*/
6559371c9d4SSatish Balay PetscErrorCode PetscViewerHDF5PushGroup(PetscViewer viewer, const char name[]) {
6565c6c1daeSBarry Smith   PetscViewer_HDF5         *hdf5 = (PetscViewer_HDF5 *)viewer->data;
6577d964842SVaclav Hapla   PetscViewerHDF5GroupList *groupNode;
6582e361344SVaclav Hapla   size_t                    i, len;
6592e361344SVaclav Hapla   char                      buf[PETSC_MAX_PATH_LEN];
6602e361344SVaclav Hapla   const char               *gname;
6615c6c1daeSBarry Smith 
6625c6c1daeSBarry Smith   PetscFunctionBegin;
6635c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
664820fc2d1SVaclav Hapla   if (name) PetscValidCharPointer(name, 2);
6659566063dSJacob Faibussowitsch   PetscCall(PetscStrlen(name, &len));
6662e361344SVaclav Hapla   gname = NULL;
6672e361344SVaclav Hapla   if (len) {
6682e361344SVaclav Hapla     if (len == 1 && name[0] == '.') {
6692e361344SVaclav Hapla       /* use current name */
6702e361344SVaclav Hapla       gname = (hdf5->groups && hdf5->groups->name) ? hdf5->groups->name : NULL;
6712e361344SVaclav Hapla     } else if (name[0] == '/') {
6722e361344SVaclav Hapla       /* absolute */
6732e361344SVaclav Hapla       for (i = 1; i < len; i++) {
6742e361344SVaclav Hapla         if (name[i] != '/') {
6752e361344SVaclav Hapla           gname = name;
6762e361344SVaclav Hapla           break;
6772e361344SVaclav Hapla         }
6782e361344SVaclav Hapla       }
6792e361344SVaclav Hapla     } else {
6802e361344SVaclav Hapla       /* relative */
6812e361344SVaclav Hapla       const char *parent = (hdf5->groups && hdf5->groups->name) ? hdf5->groups->name : "";
6829566063dSJacob Faibussowitsch       PetscCall(PetscSNPrintf(buf, sizeof(buf), "%s/%s", parent, name));
6832e361344SVaclav Hapla       gname = buf;
6842e361344SVaclav Hapla     }
6852e361344SVaclav Hapla   }
6869566063dSJacob Faibussowitsch   PetscCall(PetscNew(&groupNode));
6879566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(gname, (char **)&groupNode->name));
6885c6c1daeSBarry Smith   groupNode->next = hdf5->groups;
6895c6c1daeSBarry Smith   hdf5->groups    = groupNode;
6905c6c1daeSBarry Smith   PetscFunctionReturn(0);
6915c6c1daeSBarry Smith }
6925c6c1daeSBarry Smith 
6933ef9c667SSatish Balay /*@
6945c6c1daeSBarry Smith   PetscViewerHDF5PopGroup - Return the current HDF5 group for output to the previous value
6955c6c1daeSBarry Smith 
6965c6c1daeSBarry Smith   Not collective
6975c6c1daeSBarry Smith 
6985c6c1daeSBarry Smith   Input Parameter:
699811af0c4SBarry Smith . viewer - the `PetscViewer` of type `PETSCVIEWERHDF5`
7005c6c1daeSBarry Smith 
7015c6c1daeSBarry Smith   Level: intermediate
7025c6c1daeSBarry Smith 
703811af0c4SBarry Smith .seealso: `PETSCVIEWERHDF5`, `PetscViewerHDF5Open()`, `PetscViewerHDF5PushGroup()`, `PetscViewerHDF5GetGroup()`, `PetscViewerHDF5OpenGroup()`
7045c6c1daeSBarry Smith @*/
7059371c9d4SSatish Balay PetscErrorCode PetscViewerHDF5PopGroup(PetscViewer viewer) {
7065c6c1daeSBarry Smith   PetscViewer_HDF5         *hdf5 = (PetscViewer_HDF5 *)viewer->data;
7077d964842SVaclav Hapla   PetscViewerHDF5GroupList *groupNode;
7085c6c1daeSBarry Smith 
7095c6c1daeSBarry Smith   PetscFunctionBegin;
7105c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
7115f80ce2aSJacob Faibussowitsch   PetscCheck(hdf5->groups, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "HDF5 group stack is empty, cannot pop");
7125c6c1daeSBarry Smith   groupNode    = hdf5->groups;
7135c6c1daeSBarry Smith   hdf5->groups = hdf5->groups->next;
7149566063dSJacob Faibussowitsch   PetscCall(PetscFree(groupNode->name));
7159566063dSJacob Faibussowitsch   PetscCall(PetscFree(groupNode));
7165c6c1daeSBarry Smith   PetscFunctionReturn(0);
7175c6c1daeSBarry Smith }
7185c6c1daeSBarry Smith 
71977717648SVaclav Hapla PetscErrorCode PetscViewerHDF5GetGroup_Internal(PetscViewer viewer, const char *name[]) {
7205c6c1daeSBarry Smith   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)viewer->data;
7215c6c1daeSBarry Smith 
7225c6c1daeSBarry Smith   PetscFunctionBegin;
7235c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
724c959eef4SJed Brown   PetscValidPointer(name, 2);
725a297a907SKarl Rupp   if (hdf5->groups) *name = hdf5->groups->name;
7260298fd71SBarry Smith   else *name = NULL;
7275c6c1daeSBarry Smith   PetscFunctionReturn(0);
7285c6c1daeSBarry Smith }
7295c6c1daeSBarry Smith 
730*3014b61aSVaclav Hapla /*@C
731811af0c4SBarry Smith   PetscViewerHDF5OpenGroup - Open the HDF5 group with the name (full path) returned by `PetscViewerHDF5GetGroup()`,
732874270d9SVaclav Hapla   and return this group's ID and file ID.
733811af0c4SBarry Smith   If `PetscViewerHDF5GetGroup()` yields NULL, then group ID is file ID.
734874270d9SVaclav Hapla 
735874270d9SVaclav Hapla   Not collective
736874270d9SVaclav Hapla 
737*3014b61aSVaclav Hapla   Input Parameters:
738*3014b61aSVaclav Hapla + viewer - the `PetscViewer` of type `PETSCVIEWERHDF5`
739*3014b61aSVaclav Hapla - path - (Optional) The path relative to the pushed group
740874270d9SVaclav Hapla 
741d8d19677SJose E. Roman   Output Parameters:
742874270d9SVaclav Hapla + fileId - The HDF5 file ID
743874270d9SVaclav Hapla - groupId - The HDF5 group ID
744874270d9SVaclav Hapla 
745811af0c4SBarry Smith   Note:
746*3014b61aSVaclav Hapla   If path starts with '/', it is taken as an absolute path overriding currently pushed group, else path is relative to the current pushed group.
747*3014b61aSVaclav Hapla   So NULL or empty path means the current pushed group.
748*3014b61aSVaclav Hapla 
749e74616beSVaclav Hapla   If the viewer is writable, the group is created if it doesn't exist yet.
750e74616beSVaclav Hapla 
751874270d9SVaclav Hapla   Level: intermediate
752874270d9SVaclav Hapla 
753811af0c4SBarry Smith .seealso: `PETSCVIEWERHDF5`, `PetscViewerHDF5Open()`, `PetscViewerHDF5PushGroup()`, `PetscViewerHDF5PopGroup()`, `PetscViewerHDF5GetGroup()`
754874270d9SVaclav Hapla @*/
755*3014b61aSVaclav Hapla PetscErrorCode PetscViewerHDF5OpenGroup(PetscViewer viewer, const char path[], hid_t *fileId, hid_t *groupId) {
75690e03537SVaclav Hapla   hid_t       file_id;
75790e03537SVaclav Hapla   H5O_type_t  type;
758*3014b61aSVaclav Hapla   const char *fileName  = NULL;
759*3014b61aSVaclav Hapla   char       *groupName = NULL;
76076d59af2SVaclav Hapla   PetscBool   writable, has;
76154dbf706SVaclav Hapla 
76254dbf706SVaclav Hapla   PetscFunctionBegin;
7639566063dSJacob Faibussowitsch   PetscCall(PetscViewerWritable(viewer, &writable));
7649566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5GetFileId(viewer, &file_id));
7659566063dSJacob Faibussowitsch   PetscCall(PetscViewerFileGetName(viewer, &fileName));
766*3014b61aSVaclav Hapla   PetscCall(PetscViewerHDF5GetGroup(viewer, path, &groupName));
7679566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5Traverse_Internal(viewer, groupName, writable, &has, &type));
76876d59af2SVaclav Hapla   if (!has) {
7695f80ce2aSJacob Faibussowitsch     PetscCheck(writable, PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Group %s does not exist and file %s is not open for writing", groupName, fileName);
770f7d195e4SLawrence Mitchell     SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_LIB, "HDF5 failed to create group %s although file %s is open for writing", groupName, fileName);
77176d59af2SVaclav Hapla   }
7725f80ce2aSJacob Faibussowitsch   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);
773*3014b61aSVaclav Hapla   PetscCallHDF5Return(*groupId, H5Gopen2, (file_id, groupName, H5P_DEFAULT));
774*3014b61aSVaclav Hapla   PetscCall(PetscFree(groupName));
77554dbf706SVaclav Hapla   *fileId = file_id;
77654dbf706SVaclav Hapla   PetscFunctionReturn(0);
77754dbf706SVaclav Hapla }
77854dbf706SVaclav Hapla 
7793ef9c667SSatish Balay /*@
780d7dd068bSVaclav Hapla   PetscViewerHDF5PushTimestepping - Activate timestepping mode for subsequent HDF5 reading and writing.
7815c6c1daeSBarry Smith 
7825c6c1daeSBarry Smith   Not collective
7835c6c1daeSBarry Smith 
7845c6c1daeSBarry Smith   Input Parameter:
785811af0c4SBarry Smith . viewer - the `PetscViewer` of type `PETSCVIEWERHDF5`
7865c6c1daeSBarry Smith 
7875c6c1daeSBarry Smith   Level: intermediate
7885c6c1daeSBarry Smith 
789d7dd068bSVaclav Hapla   Notes:
790811af0c4SBarry Smith   On first `PetscViewerHDF5PushTimestepping()`, the initial time step is set to 0.
791811af0c4SBarry Smith   Next timesteps can then be set using `PetscViewerHDF5IncrementTimestep()` or `PetscViewerHDF5SetTimestep()`.
792811af0c4SBarry Smith   Current timestep value determines which timestep is read from or written to any dataset on the next HDF5 I/O operation [e.g. `VecView()`].
793811af0c4SBarry Smith   Use `PetscViewerHDF5PopTimestepping()` to deactivate timestepping mode; calling it by the end of the program is NOT mandatory.
794811af0c4SBarry Smith   Current timestep is remembered between `PetscViewerHDF5PopTimestepping()` and the next `PetscViewerHDF5PushTimestepping()`.
795d7dd068bSVaclav Hapla 
796d7dd068bSVaclav Hapla   If a dataset was stored with timestepping, it can be loaded only in the timestepping mode again.
797d7dd068bSVaclav Hapla   Loading a timestepped dataset with timestepping disabled, or vice-versa results in an error.
798d7dd068bSVaclav Hapla 
799811af0c4SBarry Smith   Developer note:
800d7dd068bSVaclav Hapla   Timestepped HDF5 dataset has an extra dimension and attribute "timestepping" set to true.
801d7dd068bSVaclav Hapla 
802811af0c4SBarry Smith .seealso: `PETSCVIEWERHDF5`, `PetscViewerHDF5Open()`, `PetscViewerHDF5PopTimestepping()`, `PetscViewerHDF5IsTimestepping()`, `PetscViewerHDF5SetTimestep()`, `PetscViewerHDF5IncrementTimestep()`, `PetscViewerHDF5GetTimestep()`
803d7dd068bSVaclav Hapla @*/
8049371c9d4SSatish Balay PetscErrorCode PetscViewerHDF5PushTimestepping(PetscViewer viewer) {
805d7dd068bSVaclav Hapla   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)viewer->data;
806d7dd068bSVaclav Hapla 
807d7dd068bSVaclav Hapla   PetscFunctionBegin;
808d7dd068bSVaclav Hapla   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
8095f80ce2aSJacob Faibussowitsch   PetscCheck(!hdf5->timestepping, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Timestepping is already pushed");
810d7dd068bSVaclav Hapla   hdf5->timestepping = PETSC_TRUE;
811d7dd068bSVaclav Hapla   if (hdf5->timestep < 0) hdf5->timestep = 0;
812d7dd068bSVaclav Hapla   PetscFunctionReturn(0);
813d7dd068bSVaclav Hapla }
814d7dd068bSVaclav Hapla 
815d7dd068bSVaclav Hapla /*@
816d7dd068bSVaclav Hapla   PetscViewerHDF5PopTimestepping - Deactivate timestepping mode for subsequent HDF5 reading and writing.
817d7dd068bSVaclav Hapla 
818d7dd068bSVaclav Hapla   Not collective
819d7dd068bSVaclav Hapla 
820d7dd068bSVaclav Hapla   Input Parameter:
821811af0c4SBarry Smith . viewer - the `PetscViewer` of type `PETSCVIEWERHDF5`
822d7dd068bSVaclav Hapla 
823d7dd068bSVaclav Hapla   Level: intermediate
824d7dd068bSVaclav Hapla 
825811af0c4SBarry Smith   Note:
826811af0c4SBarry Smith   See `PetscViewerHDF5PushTimestepping()` for details.
827d7dd068bSVaclav Hapla 
828811af0c4SBarry Smith .seealso: `PETSCVIEWERHDF5`, `PetscViewerHDF5Open()`, `PetscViewerHDF5PushTimestepping()`, `PetscViewerHDF5IsTimestepping()`, `PetscViewerHDF5SetTimestep()`, `PetscViewerHDF5IncrementTimestep()`, `PetscViewerHDF5GetTimestep()`
829d7dd068bSVaclav Hapla @*/
8309371c9d4SSatish Balay PetscErrorCode PetscViewerHDF5PopTimestepping(PetscViewer viewer) {
831d7dd068bSVaclav Hapla   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)viewer->data;
832d7dd068bSVaclav Hapla 
833d7dd068bSVaclav Hapla   PetscFunctionBegin;
834d7dd068bSVaclav Hapla   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
8355f80ce2aSJacob Faibussowitsch   PetscCheck(hdf5->timestepping, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Timestepping has not been pushed yet. Call PetscViewerHDF5PushTimestepping() first");
836d7dd068bSVaclav Hapla   hdf5->timestepping = PETSC_FALSE;
837d7dd068bSVaclav Hapla   PetscFunctionReturn(0);
838d7dd068bSVaclav Hapla }
839d7dd068bSVaclav Hapla 
840d7dd068bSVaclav Hapla /*@
841d7dd068bSVaclav Hapla   PetscViewerHDF5IsTimestepping - Ask the viewer whether it is in timestepping mode currently.
842d7dd068bSVaclav Hapla 
843d7dd068bSVaclav Hapla   Not collective
844d7dd068bSVaclav Hapla 
845d7dd068bSVaclav Hapla   Input Parameter:
846811af0c4SBarry Smith . viewer - the `PetscViewer` of type `PETSCVIEWERHDF5`
847d7dd068bSVaclav Hapla 
848d7dd068bSVaclav Hapla   Output Parameter:
849d7dd068bSVaclav Hapla . flg - is timestepping active?
850d7dd068bSVaclav Hapla 
851d7dd068bSVaclav Hapla   Level: intermediate
852d7dd068bSVaclav Hapla 
853811af0c4SBarry Smith   Note:
854811af0c4SBarry Smith   See `PetscViewerHDF5PushTimestepping()` for details.
855d7dd068bSVaclav Hapla 
856811af0c4SBarry Smith .seealso: `PETSCVIEWERHDF5`, `PetscViewerHDF5Open()`, `PetscViewerHDF5PushTimestepping()`, `PetscViewerHDF5PopTimestepping()`, `PetscViewerHDF5SetTimestep()`, `PetscViewerHDF5IncrementTimestep()`, `PetscViewerHDF5GetTimestep()`
857d7dd068bSVaclav Hapla @*/
8589371c9d4SSatish Balay PetscErrorCode PetscViewerHDF5IsTimestepping(PetscViewer viewer, PetscBool *flg) {
859d7dd068bSVaclav Hapla   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)viewer->data;
860d7dd068bSVaclav Hapla 
861d7dd068bSVaclav Hapla   PetscFunctionBegin;
862d7dd068bSVaclav Hapla   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
863d7dd068bSVaclav Hapla   *flg = hdf5->timestepping;
864d7dd068bSVaclav Hapla   PetscFunctionReturn(0);
865d7dd068bSVaclav Hapla }
866d7dd068bSVaclav Hapla 
867d7dd068bSVaclav Hapla /*@
868d7dd068bSVaclav Hapla   PetscViewerHDF5IncrementTimestep - Increments current timestep for the HDF5 output. Fields are stacked in time.
869d7dd068bSVaclav Hapla 
870d7dd068bSVaclav Hapla   Not collective
871d7dd068bSVaclav Hapla 
872d7dd068bSVaclav Hapla   Input Parameter:
873811af0c4SBarry Smith . viewer - the `PetscViewer` of type `PETSCVIEWERHDF5`
874d7dd068bSVaclav Hapla 
875d7dd068bSVaclav Hapla   Level: intermediate
876d7dd068bSVaclav Hapla 
877811af0c4SBarry Smith   Note:
878811af0c4SBarry Smith   This can be called only if the viewer is in timestepping mode. See `PetscViewerHDF5PushTimestepping()` for details.
879d7dd068bSVaclav Hapla 
880811af0c4SBarry Smith .seealso: `PETSCVIEWERHDF5`, `PetscViewerHDF5Open()`, `PetscViewerHDF5PushTimestepping()`, `PetscViewerHDF5SetTimestep()`, `PetscViewerHDF5GetTimestep()`
8815c6c1daeSBarry Smith @*/
8829371c9d4SSatish Balay PetscErrorCode PetscViewerHDF5IncrementTimestep(PetscViewer viewer) {
8835c6c1daeSBarry Smith   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)viewer->data;
8845c6c1daeSBarry Smith 
8855c6c1daeSBarry Smith   PetscFunctionBegin;
8865c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
8875f80ce2aSJacob Faibussowitsch   PetscCheck(hdf5->timestepping, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Timestepping has not been pushed yet. Call PetscViewerHDF5PushTimestepping() first");
8885c6c1daeSBarry Smith   ++hdf5->timestep;
8895c6c1daeSBarry Smith   PetscFunctionReturn(0);
8905c6c1daeSBarry Smith }
8915c6c1daeSBarry Smith 
8923ef9c667SSatish Balay /*@
893d7dd068bSVaclav Hapla   PetscViewerHDF5SetTimestep - Set the current timestep for the HDF5 output. Fields are stacked in time.
8945c6c1daeSBarry Smith 
895d7dd068bSVaclav Hapla   Logically collective
8965c6c1daeSBarry Smith 
8975c6c1daeSBarry Smith   Input Parameters:
898811af0c4SBarry Smith + viewer - the `PetscViewer` of type `PETSCVIEWERHDF5`
899d7dd068bSVaclav Hapla - timestep - The timestep
9005c6c1daeSBarry Smith 
9015c6c1daeSBarry Smith   Level: intermediate
9025c6c1daeSBarry Smith 
903811af0c4SBarry Smith   Note:
904811af0c4SBarry Smith   This can be called only if the viewer is in timestepping mode. See `PetscViewerHDF5PushTimestepping()` for details.
905d7dd068bSVaclav Hapla 
906811af0c4SBarry Smith .seealso: `PETSCVIEWERHDF5`, `PetscViewerHDF5Open()`, `PetscViewerHDF5PushTimestepping()`, `PetscViewerHDF5IncrementTimestep()`, `PetscViewerHDF5GetTimestep()`
9075c6c1daeSBarry Smith @*/
9089371c9d4SSatish Balay PetscErrorCode PetscViewerHDF5SetTimestep(PetscViewer viewer, PetscInt timestep) {
9095c6c1daeSBarry Smith   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)viewer->data;
9105c6c1daeSBarry Smith 
9115c6c1daeSBarry Smith   PetscFunctionBegin;
9125c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
913d7dd068bSVaclav Hapla   PetscValidLogicalCollectiveInt(viewer, timestep, 2);
9145f80ce2aSJacob Faibussowitsch   PetscCheck(timestep >= 0, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Timestep %" PetscInt_FMT " is negative", timestep);
9155f80ce2aSJacob Faibussowitsch   PetscCheck(hdf5->timestepping, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Timestepping has not been pushed yet. Call PetscViewerHDF5PushTimestepping() first");
9165c6c1daeSBarry Smith   hdf5->timestep = timestep;
9175c6c1daeSBarry Smith   PetscFunctionReturn(0);
9185c6c1daeSBarry Smith }
9195c6c1daeSBarry Smith 
9203ef9c667SSatish Balay /*@
9215c6c1daeSBarry Smith   PetscViewerHDF5GetTimestep - Get the current timestep for the HDF5 output. Fields are stacked in time.
9225c6c1daeSBarry Smith 
9235c6c1daeSBarry Smith   Not collective
9245c6c1daeSBarry Smith 
9255c6c1daeSBarry Smith   Input Parameter:
926811af0c4SBarry Smith . viewer - the `PetscViewer` of type `PETSCVIEWERHDF5`
9275c6c1daeSBarry Smith 
9285c6c1daeSBarry Smith   Output Parameter:
929d7dd068bSVaclav Hapla . timestep - The timestep
9305c6c1daeSBarry Smith 
9315c6c1daeSBarry Smith   Level: intermediate
9325c6c1daeSBarry Smith 
933811af0c4SBarry Smith   Note:
934811af0c4SBarry Smith   This can be called only if the viewer is in the timestepping mode. See `PetscViewerHDF5PushTimestepping()` for details.
935d7dd068bSVaclav Hapla 
936811af0c4SBarry Smith .seealso: `PETSCVIEWERHDF5`, `PetscViewerHDF5Open()`, `PetscViewerHDF5PushTimestepping()`, `PetscViewerHDF5IncrementTimestep()`, `PetscViewerHDF5SetTimestep()`
9375c6c1daeSBarry Smith @*/
9389371c9d4SSatish Balay PetscErrorCode PetscViewerHDF5GetTimestep(PetscViewer viewer, PetscInt *timestep) {
9395c6c1daeSBarry Smith   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)viewer->data;
9405c6c1daeSBarry Smith 
9415c6c1daeSBarry Smith   PetscFunctionBegin;
9425c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
943d7dd068bSVaclav Hapla   PetscValidIntPointer(timestep, 2);
9445f80ce2aSJacob Faibussowitsch   PetscCheck(hdf5->timestepping, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Timestepping has not been pushed yet. Call PetscViewerHDF5PushTimestepping() first");
9455c6c1daeSBarry Smith   *timestep = hdf5->timestep;
9465c6c1daeSBarry Smith   PetscFunctionReturn(0);
9475c6c1daeSBarry Smith }
9485c6c1daeSBarry Smith 
94936bce6e8SMatthew G. Knepley /*@C
95036bce6e8SMatthew G. Knepley   PetscDataTypeToHDF5DataType - Converts the PETSc name of a datatype to its HDF5 name.
95136bce6e8SMatthew G. Knepley 
95236bce6e8SMatthew G. Knepley   Not collective
95336bce6e8SMatthew G. Knepley 
95436bce6e8SMatthew G. Knepley   Input Parameter:
955811af0c4SBarry Smith . ptype - the PETSc datatype name (for example `PETSC_DOUBLE`)
95636bce6e8SMatthew G. Knepley 
95736bce6e8SMatthew G. Knepley   Output Parameter:
958811af0c4SBarry Smith . mtype - the HDF5  datatype
95936bce6e8SMatthew G. Knepley 
96036bce6e8SMatthew G. Knepley   Level: advanced
96136bce6e8SMatthew G. Knepley 
962db781477SPatrick Sanan .seealso: `PetscDataType`, `PetscHDF5DataTypeToPetscDataType()`
96336bce6e8SMatthew G. Knepley @*/
9649371c9d4SSatish Balay PetscErrorCode PetscDataTypeToHDF5DataType(PetscDataType ptype, hid_t *htype) {
96536bce6e8SMatthew G. Knepley   PetscFunctionBegin;
96636bce6e8SMatthew G. Knepley   if (ptype == PETSC_INT)
96736bce6e8SMatthew G. Knepley #if defined(PETSC_USE_64BIT_INDICES)
96836bce6e8SMatthew G. Knepley     *htype = H5T_NATIVE_LLONG;
96936bce6e8SMatthew G. Knepley #else
97036bce6e8SMatthew G. Knepley     *htype = H5T_NATIVE_INT;
97136bce6e8SMatthew G. Knepley #endif
97236bce6e8SMatthew G. Knepley   else if (ptype == PETSC_DOUBLE) *htype = H5T_NATIVE_DOUBLE;
97336bce6e8SMatthew G. Knepley   else if (ptype == PETSC_LONG) *htype = H5T_NATIVE_LONG;
97436bce6e8SMatthew G. Knepley   else if (ptype == PETSC_SHORT) *htype = H5T_NATIVE_SHORT;
975c9450970SBarry Smith   else if (ptype == PETSC_ENUM) *htype = H5T_NATIVE_INT;
976de3ba262SVaclav Hapla   else if (ptype == PETSC_BOOL) *htype = H5T_NATIVE_INT;
97736bce6e8SMatthew G. Knepley   else if (ptype == PETSC_FLOAT) *htype = H5T_NATIVE_FLOAT;
97836bce6e8SMatthew G. Knepley   else if (ptype == PETSC_CHAR) *htype = H5T_NATIVE_CHAR;
97936bce6e8SMatthew G. Knepley   else if (ptype == PETSC_BIT_LOGICAL) *htype = H5T_NATIVE_UCHAR;
9807e97c476SMatthew G. Knepley   else if (ptype == PETSC_STRING) *htype = H5Tcopy(H5T_C_S1);
98136bce6e8SMatthew G. Knepley   else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Unsupported PETSc datatype");
98236bce6e8SMatthew G. Knepley   PetscFunctionReturn(0);
98336bce6e8SMatthew G. Knepley }
98436bce6e8SMatthew G. Knepley 
98536bce6e8SMatthew G. Knepley /*@C
98636bce6e8SMatthew G. Knepley   PetscHDF5DataTypeToPetscDataType - Finds the PETSc name of a datatype from its HDF5 name
98736bce6e8SMatthew G. Knepley 
98836bce6e8SMatthew G. Knepley   Not collective
98936bce6e8SMatthew G. Knepley 
99036bce6e8SMatthew G. Knepley   Input Parameter:
991811af0c4SBarry Smith . htype - the HDF5 datatype (for example `H5T_NATIVE_DOUBLE`, ...)
99236bce6e8SMatthew G. Knepley 
99336bce6e8SMatthew G. Knepley   Output Parameter:
994811af0c4SBarry Smith . ptype - the PETSc datatype name (for example `PETSC_DOUBLE`)
99536bce6e8SMatthew G. Knepley 
99636bce6e8SMatthew G. Knepley   Level: advanced
99736bce6e8SMatthew G. Knepley 
998db781477SPatrick Sanan .seealso: `PetscDataType`, `PetscHDF5DataTypeToPetscDataType()`
99936bce6e8SMatthew G. Knepley @*/
10009371c9d4SSatish Balay PetscErrorCode PetscHDF5DataTypeToPetscDataType(hid_t htype, PetscDataType *ptype) {
100136bce6e8SMatthew G. Knepley   PetscFunctionBegin;
100236bce6e8SMatthew G. Knepley #if defined(PETSC_USE_64BIT_INDICES)
100336bce6e8SMatthew G. Knepley   if (htype == H5T_NATIVE_INT) *ptype = PETSC_LONG;
100436bce6e8SMatthew G. Knepley   else if (htype == H5T_NATIVE_LLONG) *ptype = PETSC_INT;
100536bce6e8SMatthew G. Knepley #else
100636bce6e8SMatthew G. Knepley   if (htype == H5T_NATIVE_INT) *ptype = PETSC_INT;
100736bce6e8SMatthew G. Knepley #endif
100836bce6e8SMatthew G. Knepley   else if (htype == H5T_NATIVE_DOUBLE) *ptype = PETSC_DOUBLE;
100936bce6e8SMatthew G. Knepley   else if (htype == H5T_NATIVE_LONG) *ptype = PETSC_LONG;
101036bce6e8SMatthew G. Knepley   else if (htype == H5T_NATIVE_SHORT) *ptype = PETSC_SHORT;
101136bce6e8SMatthew G. Knepley   else if (htype == H5T_NATIVE_FLOAT) *ptype = PETSC_FLOAT;
101236bce6e8SMatthew G. Knepley   else if (htype == H5T_NATIVE_CHAR) *ptype = PETSC_CHAR;
101336bce6e8SMatthew G. Knepley   else if (htype == H5T_NATIVE_UCHAR) *ptype = PETSC_CHAR;
10147e97c476SMatthew G. Knepley   else if (htype == H5T_C_S1) *ptype = PETSC_STRING;
101536bce6e8SMatthew G. Knepley   else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Unsupported HDF5 datatype");
101636bce6e8SMatthew G. Knepley   PetscFunctionReturn(0);
101736bce6e8SMatthew G. Knepley }
101836bce6e8SMatthew G. Knepley 
1019df863907SAlex Fikl /*@C
1020b8ee85a1SVaclav Hapla  PetscViewerHDF5WriteAttribute - Write an attribute
102136bce6e8SMatthew G. Knepley 
1022343a20b2SVaclav Hapla   Collective
1023343a20b2SVaclav Hapla 
102436bce6e8SMatthew G. Knepley   Input Parameters:
1025811af0c4SBarry Smith + viewer - The `PETSCVIEWERHDF5` viewer
10264302210dSVaclav Hapla . parent - The parent dataset/group name
102736bce6e8SMatthew G. Knepley . name   - The attribute name
102836bce6e8SMatthew G. Knepley . datatype - The attribute type
102936bce6e8SMatthew G. Knepley - value    - The attribute value
103036bce6e8SMatthew G. Knepley 
103136bce6e8SMatthew G. Knepley   Level: advanced
103236bce6e8SMatthew G. Knepley 
1033811af0c4SBarry Smith   Note:
1034343a20b2SVaclav Hapla   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.
10354302210dSVaclav Hapla 
1036811af0c4SBarry Smith .seealso: `PETSCVIEWERHDF5`, `PetscViewerHDF5Open()`, `PetscViewerHDF5WriteObjectAttribute()`, `PetscViewerHDF5ReadAttribute()`, `PetscViewerHDF5HasAttribute()`,
1037811af0c4SBarry Smith           `PetscViewerHDF5PushGroup()`, `PetscViewerHDF5PopGroup()`, `PetscViewerHDF5GetGroup()`
103836bce6e8SMatthew G. Knepley @*/
10399371c9d4SSatish Balay PetscErrorCode PetscViewerHDF5WriteAttribute(PetscViewer viewer, const char parent[], const char name[], PetscDataType datatype, const void *value) {
10404302210dSVaclav Hapla   char     *parentAbsPath;
104160568592SMatthew G. Knepley   hid_t     h5, dataspace, obj, attribute, dtype;
1042080f144cSVaclav Hapla   PetscBool has;
104336bce6e8SMatthew G. Knepley 
104436bce6e8SMatthew G. Knepley   PetscFunctionBegin;
10455cdeb108SMatthew G. Knepley   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
10464302210dSVaclav Hapla   if (parent) PetscValidCharPointer(parent, 2);
1047c57a1a9aSVaclav Hapla   PetscValidCharPointer(name, 3);
10484302210dSVaclav Hapla   PetscValidLogicalCollectiveEnum(viewer, datatype, 4);
1049b7e81f0fSVaclav Hapla   PetscValidPointer(value, 5);
105077717648SVaclav Hapla   PetscCall(PetscViewerHDF5GetGroup(viewer, parent, &parentAbsPath));
10519566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5Traverse_Internal(viewer, parentAbsPath, PETSC_TRUE, NULL, NULL));
10529566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5HasAttribute_Internal(viewer, parentAbsPath, name, &has));
10539566063dSJacob Faibussowitsch   PetscCall(PetscDataTypeToHDF5DataType(datatype, &dtype));
10547e97c476SMatthew G. Knepley   if (datatype == PETSC_STRING) {
10557e97c476SMatthew G. Knepley     size_t len;
10569566063dSJacob Faibussowitsch     PetscCall(PetscStrlen((const char *)value, &len));
1057792fecdfSBarry Smith     PetscCallHDF5(H5Tset_size, (dtype, len + 1));
10587e97c476SMatthew G. Knepley   }
10599566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5GetFileId(viewer, &h5));
1060792fecdfSBarry Smith   PetscCallHDF5Return(dataspace, H5Screate, (H5S_SCALAR));
1061792fecdfSBarry Smith   PetscCallHDF5Return(obj, H5Oopen, (h5, parentAbsPath, H5P_DEFAULT));
1062080f144cSVaclav Hapla   if (has) {
1063792fecdfSBarry Smith     PetscCallHDF5Return(attribute, H5Aopen_name, (obj, name));
1064080f144cSVaclav Hapla   } else {
1065792fecdfSBarry Smith     PetscCallHDF5Return(attribute, H5Acreate2, (obj, name, dtype, dataspace, H5P_DEFAULT, H5P_DEFAULT));
1066080f144cSVaclav Hapla   }
1067792fecdfSBarry Smith   PetscCallHDF5(H5Awrite, (attribute, dtype, value));
1068792fecdfSBarry Smith   if (datatype == PETSC_STRING) PetscCallHDF5(H5Tclose, (dtype));
1069792fecdfSBarry Smith   PetscCallHDF5(H5Aclose, (attribute));
1070792fecdfSBarry Smith   PetscCallHDF5(H5Oclose, (obj));
1071792fecdfSBarry Smith   PetscCallHDF5(H5Sclose, (dataspace));
10729566063dSJacob Faibussowitsch   PetscCall(PetscFree(parentAbsPath));
107336bce6e8SMatthew G. Knepley   PetscFunctionReturn(0);
107436bce6e8SMatthew G. Knepley }
107536bce6e8SMatthew G. Knepley 
1076df863907SAlex Fikl /*@C
1077811af0c4SBarry Smith  PetscViewerHDF5WriteObjectAttribute - Write an attribute to the dataset matching the given `PetscObject` by name
1078577e0e04SVaclav Hapla 
1079343a20b2SVaclav Hapla   Collective
1080343a20b2SVaclav Hapla 
1081577e0e04SVaclav Hapla   Input Parameters:
1082811af0c4SBarry Smith + viewer   - The `PETSCVIEWERHDF5` viewer
1083577e0e04SVaclav Hapla . obj      - The object whose name is used to lookup the parent dataset, relative to the current group.
1084577e0e04SVaclav Hapla . name     - The attribute name
1085577e0e04SVaclav Hapla . datatype - The attribute type
1086577e0e04SVaclav Hapla - value    - The attribute value
1087577e0e04SVaclav Hapla 
1088811af0c4SBarry Smith   Note:
1089343a20b2SVaclav Hapla   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).
1090811af0c4SBarry Smith   You might want to check first if it does using `PetscViewerHDF5HasObject()`.
1091577e0e04SVaclav Hapla 
1092577e0e04SVaclav Hapla   Level: advanced
1093577e0e04SVaclav Hapla 
1094811af0c4SBarry Smith .seealso: `PETSCVIEWERHDF5`, `PetscViewerHDF5Open()`, `PetscViewerHDF5WriteAttribute()`, `PetscViewerHDF5ReadObjectAttribute()`, `PetscViewerHDF5HasObjectAttribute()`,
1095811af0c4SBarry Smith           `PetscViewerHDF5HasObject()`, `PetscViewerHDF5PushGroup()`, `PetscViewerHDF5PopGroup()`, `PetscViewerHDF5GetGroup()`
1096577e0e04SVaclav Hapla @*/
10979371c9d4SSatish Balay PetscErrorCode PetscViewerHDF5WriteObjectAttribute(PetscViewer viewer, PetscObject obj, const char name[], PetscDataType datatype, const void *value) {
1098577e0e04SVaclav Hapla   PetscFunctionBegin;
1099577e0e04SVaclav Hapla   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
1100577e0e04SVaclav Hapla   PetscValidHeader(obj, 2);
1101577e0e04SVaclav Hapla   PetscValidCharPointer(name, 3);
1102b7e81f0fSVaclav Hapla   PetscValidPointer(value, 5);
11039566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5CheckNamedObject_Internal(viewer, obj));
11049566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5WriteAttribute(viewer, obj->name, name, datatype, value));
1105577e0e04SVaclav Hapla   PetscFunctionReturn(0);
1106577e0e04SVaclav Hapla }
1107577e0e04SVaclav Hapla 
1108577e0e04SVaclav Hapla /*@C
1109b8ee85a1SVaclav Hapla  PetscViewerHDF5ReadAttribute - Read an attribute
1110ad0c61feSMatthew G. Knepley 
1111343a20b2SVaclav Hapla   Collective
1112343a20b2SVaclav Hapla 
1113ad0c61feSMatthew G. Knepley   Input Parameters:
1114811af0c4SBarry Smith + viewer - The `PETSCVIEWERHDF5` viewer
11154302210dSVaclav Hapla . parent - The parent dataset/group name
1116ad0c61feSMatthew G. Knepley . name   - The attribute name
1117a2d6be1bSVaclav Hapla . datatype - The attribute type
1118a2d6be1bSVaclav Hapla - defaultValue - The pointer to the default value
1119ad0c61feSMatthew G. Knepley 
1120ad0c61feSMatthew G. Knepley   Output Parameter:
1121a2d6be1bSVaclav Hapla . value    - The pointer to the read HDF5 attribute value
1122ad0c61feSMatthew G. Knepley 
1123a2d6be1bSVaclav Hapla   Notes:
1124a2d6be1bSVaclav Hapla   If defaultValue is NULL and the attribute is not found, an error occurs.
1125a2d6be1bSVaclav Hapla   If defaultValue is not NULL and the attribute is not found, defaultValue is copied to value.
1126a2d6be1bSVaclav Hapla   The pointers defaultValue and value can be the same; for instance
1127811af0c4SBarry Smith $  flg = `PETSC_FALSE`;
1128811af0c4SBarry Smith $  PetscCall(`PetscViewerHDF5ReadAttribute`(viewer,name,"attr",PETSC_BOOL,&flg,&flg));
1129a2d6be1bSVaclav Hapla   is valid, but make sure the default value is initialized.
1130a2d6be1bSVaclav Hapla 
1131811af0c4SBarry Smith   If the datatype is `PETSC_STRING`, the output string is newly allocated so one must `PetscFree()` it when no longer needed.
1132708d4cb3SBarry Smith 
1133343a20b2SVaclav Hapla   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.
1134ad0c61feSMatthew G. Knepley 
1135343a20b2SVaclav Hapla   Level: advanced
11364302210dSVaclav Hapla 
1137811af0c4SBarry Smith .seealso: `PETSCVIEWERHDF5`, `PetscViewerHDF5Open()`, `PetscViewerHDF5ReadObjectAttribute()`, `PetscViewerHDF5WriteAttribute()`, `PetscViewerHDF5HasAttribute()`, `PetscViewerHDF5HasObject()`, `PetscViewerHDF5PushGroup()`, `PetscViewerHDF5PopGroup()`, `PetscViewerHDF5GetGroup()`
1138ad0c61feSMatthew G. Knepley @*/
11399371c9d4SSatish Balay PetscErrorCode PetscViewerHDF5ReadAttribute(PetscViewer viewer, const char parent[], const char name[], PetscDataType datatype, const void *defaultValue, void *value) {
11404302210dSVaclav Hapla   char     *parentAbsPath;
1141a2d6be1bSVaclav Hapla   hid_t     h5, obj, attribute, dtype;
1142969748fdSVaclav Hapla   PetscBool has;
1143ad0c61feSMatthew G. Knepley 
1144ad0c61feSMatthew G. Knepley   PetscFunctionBegin;
11455cdeb108SMatthew G. Knepley   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
11464302210dSVaclav Hapla   if (parent) PetscValidCharPointer(parent, 2);
1147c57a1a9aSVaclav Hapla   PetscValidCharPointer(name, 3);
1148a2d6be1bSVaclav Hapla   if (defaultValue) PetscValidPointer(defaultValue, 5);
1149a2d6be1bSVaclav Hapla   PetscValidPointer(value, 6);
11509566063dSJacob Faibussowitsch   PetscCall(PetscDataTypeToHDF5DataType(datatype, &dtype));
115177717648SVaclav Hapla   PetscCall(PetscViewerHDF5GetGroup(viewer, parent, &parentAbsPath));
11529566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5Traverse_Internal(viewer, parentAbsPath, PETSC_FALSE, &has, NULL));
11539566063dSJacob Faibussowitsch   if (has) PetscCall(PetscViewerHDF5HasAttribute_Internal(viewer, parentAbsPath, name, &has));
1154a2d6be1bSVaclav Hapla   if (!has) {
1155a2d6be1bSVaclav Hapla     if (defaultValue) {
1156a2d6be1bSVaclav Hapla       if (defaultValue != value) {
1157a2d6be1bSVaclav Hapla         if (datatype == PETSC_STRING) {
11589566063dSJacob Faibussowitsch           PetscCall(PetscStrallocpy(*(char **)defaultValue, (char **)value));
1159a2d6be1bSVaclav Hapla         } else {
1160a2d6be1bSVaclav Hapla           size_t len;
1161792fecdfSBarry Smith           PetscCallHDF5ReturnNoCheck(len, H5Tget_size, (dtype));
11629566063dSJacob Faibussowitsch           PetscCall(PetscMemcpy(value, defaultValue, len));
1163a2d6be1bSVaclav Hapla         }
1164a2d6be1bSVaclav Hapla       }
11659566063dSJacob Faibussowitsch       PetscCall(PetscFree(parentAbsPath));
1166a2d6be1bSVaclav Hapla       PetscFunctionReturn(0);
116798921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Attribute %s/%s does not exist and default value not provided", parentAbsPath, name);
1168a2d6be1bSVaclav Hapla   }
11699566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5GetFileId(viewer, &h5));
1170792fecdfSBarry Smith   PetscCallHDF5Return(obj, H5Oopen, (h5, parentAbsPath, H5P_DEFAULT));
1171792fecdfSBarry Smith   PetscCallHDF5Return(attribute, H5Aopen_name, (obj, name));
1172f0b58479SMatthew G. Knepley   if (datatype == PETSC_STRING) {
1173f0b58479SMatthew G. Knepley     size_t len;
1174a2d6be1bSVaclav Hapla     hid_t  atype;
1175792fecdfSBarry Smith     PetscCallHDF5Return(atype, H5Aget_type, (attribute));
1176792fecdfSBarry Smith     PetscCallHDF5ReturnNoCheck(len, H5Tget_size, (atype));
11779566063dSJacob Faibussowitsch     PetscCall(PetscMalloc((len + 1) * sizeof(char), value));
1178792fecdfSBarry Smith     PetscCallHDF5(H5Tset_size, (dtype, len + 1));
1179792fecdfSBarry Smith     PetscCallHDF5(H5Aread, (attribute, dtype, *(char **)value));
1180708d4cb3SBarry Smith   } else {
1181792fecdfSBarry Smith     PetscCallHDF5(H5Aread, (attribute, dtype, value));
1182708d4cb3SBarry Smith   }
1183792fecdfSBarry Smith   PetscCallHDF5(H5Aclose, (attribute));
1184e90c5075SMarek Pecha   /* H5Oclose can be used to close groups, datasets, or committed datatypes */
1185792fecdfSBarry Smith   PetscCallHDF5(H5Oclose, (obj));
11869566063dSJacob Faibussowitsch   PetscCall(PetscFree(parentAbsPath));
1187ad0c61feSMatthew G. Knepley   PetscFunctionReturn(0);
1188ad0c61feSMatthew G. Knepley }
1189ad0c61feSMatthew G. Knepley 
1190577e0e04SVaclav Hapla /*@C
1191811af0c4SBarry Smith  PetscViewerHDF5ReadObjectAttribute - Read an attribute from the dataset matching the given `PetscObject` by name
1192577e0e04SVaclav Hapla 
1193343a20b2SVaclav Hapla   Collective
1194343a20b2SVaclav Hapla 
1195577e0e04SVaclav Hapla   Input Parameters:
1196811af0c4SBarry Smith + viewer   - The `PETSCVIEWERHDF5` viewer
1197577e0e04SVaclav Hapla . obj      - The object whose name is used to lookup the parent dataset, relative to the current group.
1198577e0e04SVaclav Hapla . name     - The attribute name
1199577e0e04SVaclav Hapla - datatype - The attribute type
1200577e0e04SVaclav Hapla 
1201577e0e04SVaclav Hapla   Output Parameter:
1202577e0e04SVaclav Hapla . value    - The attribute value
1203577e0e04SVaclav Hapla 
1204811af0c4SBarry Smith   Note:
1205577e0e04SVaclav Hapla   This fails if current_group/object_name doesn't resolve to a dataset (the path doesn't exist or is not a dataset).
1206811af0c4SBarry Smith   You might want to check first if it does using `PetscViewerHDF5HasObject()`.
1207577e0e04SVaclav Hapla 
1208577e0e04SVaclav Hapla   Level: advanced
1209577e0e04SVaclav Hapla 
1210811af0c4SBarry Smith .seealso: `PETSCVIEWERHDF5`, `PetscViewerHDF5Open()`, `PetscViewerHDF5ReadAttribute()` `PetscViewerHDF5WriteObjectAttribute()`, `PetscViewerHDF5HasObjectAttribute()`, `PetscViewerHDF5PushGroup()`, `PetscViewerHDF5PopGroup()`, `PetscViewerHDF5GetGroup()`
1211577e0e04SVaclav Hapla @*/
12129371c9d4SSatish Balay PetscErrorCode PetscViewerHDF5ReadObjectAttribute(PetscViewer viewer, PetscObject obj, const char name[], PetscDataType datatype, void *defaultValue, void *value) {
1213577e0e04SVaclav Hapla   PetscFunctionBegin;
1214577e0e04SVaclav Hapla   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
1215577e0e04SVaclav Hapla   PetscValidHeader(obj, 2);
1216577e0e04SVaclav Hapla   PetscValidCharPointer(name, 3);
1217064a246eSJacob Faibussowitsch   PetscValidPointer(value, 6);
12189566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5CheckNamedObject_Internal(viewer, obj));
12199566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5ReadAttribute(viewer, obj->name, name, datatype, defaultValue, value));
1220577e0e04SVaclav Hapla   PetscFunctionReturn(0);
1221577e0e04SVaclav Hapla }
1222577e0e04SVaclav Hapla 
12239371c9d4SSatish Balay static inline PetscErrorCode PetscViewerHDF5Traverse_Inner_Internal(hid_t h5, const char name[], PetscBool createGroup, PetscBool *exists_) {
1224a75c3fd4SVaclav Hapla   htri_t exists;
1225a75c3fd4SVaclav Hapla   hid_t  group;
1226a75c3fd4SVaclav Hapla 
1227a75c3fd4SVaclav Hapla   PetscFunctionBegin;
1228792fecdfSBarry Smith   PetscCallHDF5Return(exists, H5Lexists, (h5, name, H5P_DEFAULT));
1229792fecdfSBarry Smith   if (exists) PetscCallHDF5Return(exists, H5Oexists_by_name, (h5, name, H5P_DEFAULT));
1230a75c3fd4SVaclav Hapla   if (!exists && createGroup) {
1231792fecdfSBarry Smith     PetscCallHDF5Return(group, H5Gcreate2, (h5, name, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT));
1232792fecdfSBarry Smith     PetscCallHDF5(H5Gclose, (group));
1233a75c3fd4SVaclav Hapla     exists = PETSC_TRUE;
1234a75c3fd4SVaclav Hapla   }
1235a75c3fd4SVaclav Hapla   *exists_ = (PetscBool)exists;
1236a75c3fd4SVaclav Hapla   PetscFunctionReturn(0);
1237a75c3fd4SVaclav Hapla }
1238a75c3fd4SVaclav Hapla 
12399371c9d4SSatish Balay static PetscErrorCode PetscViewerHDF5Traverse_Internal(PetscViewer viewer, const char name[], PetscBool createGroup, PetscBool *has, H5O_type_t *otype) {
124090e03537SVaclav Hapla   const char rootGroupName[] = "/";
12415cdeb108SMatthew G. Knepley   hid_t      h5;
1242e5bf9ebcSVaclav Hapla   PetscBool  exists = PETSC_FALSE;
124315b861d2SVaclav Hapla   PetscInt   i;
124415b861d2SVaclav Hapla   int        n;
124585688ae2SVaclav Hapla   char     **hierarchy;
124685688ae2SVaclav Hapla   char       buf[PETSC_MAX_PATH_LEN] = "";
12475cdeb108SMatthew G. Knepley 
12485cdeb108SMatthew G. Knepley   PetscFunctionBegin;
12495cdeb108SMatthew G. Knepley   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
125090e03537SVaclav Hapla   if (name) PetscValidCharPointer(name, 2);
125190e03537SVaclav Hapla   else name = rootGroupName;
1252ccd66a83SVaclav Hapla   if (has) {
1253064a246eSJacob Faibussowitsch     PetscValidBoolPointer(has, 4);
12545cdeb108SMatthew G. Knepley     *has = PETSC_FALSE;
1255ccd66a83SVaclav Hapla   }
1256ccd66a83SVaclav Hapla   if (otype) {
1257064a246eSJacob Faibussowitsch     PetscValidIntPointer(otype, 5);
125856cc0592SVaclav Hapla     *otype = H5O_TYPE_UNKNOWN;
1259ccd66a83SVaclav Hapla   }
12609566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5GetFileId(viewer, &h5));
126185688ae2SVaclav Hapla 
126285688ae2SVaclav Hapla   /*
126385688ae2SVaclav Hapla      Unfortunately, H5Oexists_by_name() fails if any object in hierarchy is missing.
126485688ae2SVaclav Hapla      Hence, each of them needs to be tested separately:
126585688ae2SVaclav Hapla      1) whether it's a valid link
126685688ae2SVaclav Hapla      2) whether this link resolves to an object
126785688ae2SVaclav Hapla      See H5Oexists_by_name() documentation.
126885688ae2SVaclav Hapla   */
12699566063dSJacob Faibussowitsch   PetscCall(PetscStrToArray(name, '/', &n, &hierarchy));
127085688ae2SVaclav Hapla   if (!n) {
127185688ae2SVaclav Hapla     /*  Assume group "/" always exists in accordance with HDF5 >= 1.10.0. See H5Lexists() documentation. */
1272ccd66a83SVaclav Hapla     if (has) *has = PETSC_TRUE;
1273ccd66a83SVaclav Hapla     if (otype) *otype = H5O_TYPE_GROUP;
12749566063dSJacob Faibussowitsch     PetscCall(PetscStrToArrayDestroy(n, hierarchy));
127585688ae2SVaclav Hapla     PetscFunctionReturn(0);
127685688ae2SVaclav Hapla   }
127785688ae2SVaclav Hapla   for (i = 0; i < n; i++) {
12789566063dSJacob Faibussowitsch     PetscCall(PetscStrcat(buf, "/"));
12799566063dSJacob Faibussowitsch     PetscCall(PetscStrcat(buf, hierarchy[i]));
12809566063dSJacob Faibussowitsch     PetscCall(PetscViewerHDF5Traverse_Inner_Internal(h5, buf, createGroup, &exists));
1281a75c3fd4SVaclav Hapla     if (!exists) break;
128285688ae2SVaclav Hapla   }
12839566063dSJacob Faibussowitsch   PetscCall(PetscStrToArrayDestroy(n, hierarchy));
128485688ae2SVaclav Hapla 
128585688ae2SVaclav Hapla   /* If the object exists, get its type */
1286ccd66a83SVaclav Hapla   if (exists && otype) {
12875cdeb108SMatthew G. Knepley     H5O_info_t info;
12885cdeb108SMatthew G. Knepley 
128976276748SVaclav Hapla     /* We could use H5Iget_type() here but that would require opening the object. This way we only need its name. */
1290792fecdfSBarry Smith     PetscCallHDF5(H5Oget_info_by_name, (h5, name, &info, H5P_DEFAULT));
129156cc0592SVaclav Hapla     *otype = info.type;
12925cdeb108SMatthew G. Knepley   }
1293ccd66a83SVaclav Hapla   if (has) *has = exists;
12945cdeb108SMatthew G. Knepley   PetscFunctionReturn(0);
12955cdeb108SMatthew G. Knepley }
12965cdeb108SMatthew G. Knepley 
12974302210dSVaclav Hapla /*@C
12980a9f38efSVaclav Hapla  PetscViewerHDF5HasGroup - Check whether the current (pushed) group exists in the HDF5 file
12990a9f38efSVaclav Hapla 
1300343a20b2SVaclav Hapla   Collective
1301343a20b2SVaclav Hapla 
13020a9f38efSVaclav Hapla   Input Parameters:
1303811af0c4SBarry Smith + viewer - The `PETSCVIEWERHDF5` viewer
130477717648SVaclav Hapla - path - The path relative to the pushed group, or NULL
13050a9f38efSVaclav Hapla 
13060a9f38efSVaclav Hapla   Output Parameter:
13070a9f38efSVaclav Hapla . has - Flag for group existence
13080a9f38efSVaclav Hapla 
13090a9f38efSVaclav Hapla   Level: advanced
13100a9f38efSVaclav Hapla 
13114302210dSVaclav Hapla   Notes:
1312785c443eSVaclav Hapla   If path starts with '/', it is taken as an absolute path overriding currently pushed group, else path is relative to the current pushed group.
1313785c443eSVaclav Hapla   So NULL or empty path means the current pushed group.
13144302210dSVaclav Hapla 
1315811af0c4SBarry Smith   If path exists but is not a group, `PETSC_FALSE` is returned.
1316811af0c4SBarry Smith 
1317811af0c4SBarry Smith .seealso: `PETSCVIEWERHDF5`, `PetscViewerHDF5HasAttribute()`, `PetscViewerHDF5HasDataset()`, `PetscViewerHDF5PushGroup()`, `PetscViewerHDF5PopGroup()`, `PetscViewerHDF5GetGroup()`, `PetscViewerHDF5OpenGroup()`
13180a9f38efSVaclav Hapla @*/
13199371c9d4SSatish Balay PetscErrorCode PetscViewerHDF5HasGroup(PetscViewer viewer, const char path[], PetscBool *has) {
13200a9f38efSVaclav Hapla   H5O_type_t type;
13214302210dSVaclav Hapla   char      *abspath;
13220a9f38efSVaclav Hapla 
13230a9f38efSVaclav Hapla   PetscFunctionBegin;
13240a9f38efSVaclav Hapla   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
13254302210dSVaclav Hapla   if (path) PetscValidCharPointer(path, 2);
13264302210dSVaclav Hapla   PetscValidBoolPointer(has, 3);
132777717648SVaclav Hapla   PetscCall(PetscViewerHDF5GetGroup(viewer, path, &abspath));
13289566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5Traverse_Internal(viewer, abspath, PETSC_FALSE, NULL, &type));
13294302210dSVaclav Hapla   *has = (PetscBool)(type == H5O_TYPE_GROUP);
13309566063dSJacob Faibussowitsch   PetscCall(PetscFree(abspath));
13310a9f38efSVaclav Hapla   PetscFunctionReturn(0);
13320a9f38efSVaclav Hapla }
13330a9f38efSVaclav Hapla 
133489e0ef10SVaclav Hapla /*@C
133589e0ef10SVaclav Hapla  PetscViewerHDF5HasDataset - Check whether a given dataset exists in the HDF5 file
133689e0ef10SVaclav Hapla 
1337343a20b2SVaclav Hapla   Collective
1338343a20b2SVaclav Hapla 
133989e0ef10SVaclav Hapla   Input Parameters:
1340811af0c4SBarry Smith + viewer - The `PETSCVIEWERHDF5` viewer
134189e0ef10SVaclav Hapla - path - The dataset path
134289e0ef10SVaclav Hapla 
134389e0ef10SVaclav Hapla   Output Parameter:
134489e0ef10SVaclav Hapla . has - Flag whether dataset exists
134589e0ef10SVaclav Hapla 
134689e0ef10SVaclav Hapla   Level: advanced
134789e0ef10SVaclav Hapla 
134889e0ef10SVaclav Hapla   Notes:
1349343a20b2SVaclav Hapla   If path starts with '/', it is taken as an absolute path overriding currently pushed group, else path is relative to the current pushed group.
135089e0ef10SVaclav Hapla 
1351811af0c4SBarry Smith   If path is NULL or empty, has is set to `PETSC_FALSE`.
1352811af0c4SBarry Smith 
1353811af0c4SBarry Smith   If path exists but is not a dataset, has is set to `PETSC_FALSE` as well.
1354811af0c4SBarry Smith 
1355811af0c4SBarry Smith .seealso: `PETSCVIEWERHDF5`, `PetscViewerHDF5HasObject()`, `PetscViewerHDF5HasAttribute()`, `PetscViewerHDF5HasGroup()`, `PetscViewerHDF5PushGroup()`, `PetscViewerHDF5PopGroup()`, `PetscViewerHDF5GetGroup()`
135689e0ef10SVaclav Hapla @*/
13579371c9d4SSatish Balay PetscErrorCode PetscViewerHDF5HasDataset(PetscViewer viewer, const char path[], PetscBool *has) {
135889e0ef10SVaclav Hapla   H5O_type_t type;
135989e0ef10SVaclav Hapla   char      *abspath;
136089e0ef10SVaclav Hapla 
136189e0ef10SVaclav Hapla   PetscFunctionBegin;
136289e0ef10SVaclav Hapla   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
136389e0ef10SVaclav Hapla   if (path) PetscValidCharPointer(path, 2);
136489e0ef10SVaclav Hapla   PetscValidBoolPointer(has, 3);
136577717648SVaclav Hapla   PetscCall(PetscViewerHDF5GetGroup(viewer, path, &abspath));
13669566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5Traverse_Internal(viewer, abspath, PETSC_FALSE, NULL, &type));
136789e0ef10SVaclav Hapla   *has = (PetscBool)(type == H5O_TYPE_DATASET);
13689566063dSJacob Faibussowitsch   PetscCall(PetscFree(abspath));
136989e0ef10SVaclav Hapla   PetscFunctionReturn(0);
137089e0ef10SVaclav Hapla }
137189e0ef10SVaclav Hapla 
13720a9f38efSVaclav Hapla /*@
1373e3f143f7SVaclav Hapla  PetscViewerHDF5HasObject - Check whether a dataset with the same name as given object exists in the HDF5 file under current group
1374ecce1506SVaclav Hapla 
1375343a20b2SVaclav Hapla   Collective
1376343a20b2SVaclav Hapla 
1377ecce1506SVaclav Hapla   Input Parameters:
1378811af0c4SBarry Smith + viewer - The `PETSCVIEWERHDF5` viewer
1379ecce1506SVaclav Hapla - obj    - The named object
1380ecce1506SVaclav Hapla 
1381ecce1506SVaclav Hapla   Output Parameter:
138289e0ef10SVaclav Hapla . has    - Flag for dataset existence
1383ecce1506SVaclav Hapla 
1384e3f143f7SVaclav Hapla   Notes:
138589e0ef10SVaclav Hapla   If the object is unnamed, an error occurs.
1386811af0c4SBarry Smith 
1387811af0c4SBarry Smith   If the path current_group/object_name exists but is not a dataset, has is set to `PETSC_FALSE` as well.
1388e3f143f7SVaclav Hapla 
1389ecce1506SVaclav Hapla   Level: advanced
1390ecce1506SVaclav Hapla 
1391811af0c4SBarry Smith .seealso: `PETSCVIEWERHDF5`, `PetscViewerHDF5Open()`, `PetscViewerHDF5HasDataset()`, `PetscViewerHDF5HasAttribute()`, `PetscViewerHDF5PushGroup()`, `PetscViewerHDF5PopGroup()`, `PetscViewerHDF5GetGroup()`
1392ecce1506SVaclav Hapla @*/
13939371c9d4SSatish Balay PetscErrorCode PetscViewerHDF5HasObject(PetscViewer viewer, PetscObject obj, PetscBool *has) {
139489e0ef10SVaclav Hapla   size_t len;
1395ecce1506SVaclav Hapla 
1396ecce1506SVaclav Hapla   PetscFunctionBegin;
1397c57a1a9aSVaclav Hapla   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
1398c57a1a9aSVaclav Hapla   PetscValidHeader(obj, 2);
13994302210dSVaclav Hapla   PetscValidBoolPointer(has, 3);
14009566063dSJacob Faibussowitsch   PetscCall(PetscStrlen(obj->name, &len));
14015f80ce2aSJacob Faibussowitsch   PetscCheck(len, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONG, "Object must be named");
14029566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5HasDataset(viewer, obj->name, has));
1403ecce1506SVaclav Hapla   PetscFunctionReturn(0);
1404ecce1506SVaclav Hapla }
1405ecce1506SVaclav Hapla 
1406df863907SAlex Fikl /*@C
1407ece83b6cSVaclav Hapla  PetscViewerHDF5HasAttribute - Check whether an attribute exists
1408e7bdbf8eSMatthew G. Knepley 
1409343a20b2SVaclav Hapla   Collective
1410343a20b2SVaclav Hapla 
1411e7bdbf8eSMatthew G. Knepley   Input Parameters:
1412811af0c4SBarry Smith + viewer - The `PETSCVIEWERHDF5` viewer
14134302210dSVaclav Hapla . parent - The parent dataset/group name
1414e7bdbf8eSMatthew G. Knepley - name   - The attribute name
1415e7bdbf8eSMatthew G. Knepley 
1416e7bdbf8eSMatthew G. Knepley   Output Parameter:
1417e7bdbf8eSMatthew G. Knepley . has    - Flag for attribute existence
1418e7bdbf8eSMatthew G. Knepley 
1419e7bdbf8eSMatthew G. Knepley   Level: advanced
1420e7bdbf8eSMatthew G. Knepley 
1421811af0c4SBarry Smith   Note:
1422343a20b2SVaclav Hapla   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.
14234302210dSVaclav Hapla 
1424811af0c4SBarry Smith .seealso: `PETSCVIEWERHDF5`, `PetscViewerHDF5Open()`, `PetscViewerHDF5HasObjectAttribute()`, `PetscViewerHDF5WriteAttribute()`, `PetscViewerHDF5ReadAttribute()`, `PetscViewerHDF5PushGroup()`, `PetscViewerHDF5PopGroup()`, `PetscViewerHDF5GetGroup()`
1425e7bdbf8eSMatthew G. Knepley @*/
14269371c9d4SSatish Balay PetscErrorCode PetscViewerHDF5HasAttribute(PetscViewer viewer, const char parent[], const char name[], PetscBool *has) {
14274302210dSVaclav Hapla   char *parentAbsPath;
1428e7bdbf8eSMatthew G. Knepley 
1429e7bdbf8eSMatthew G. Knepley   PetscFunctionBegin;
14305cdeb108SMatthew G. Knepley   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
14314302210dSVaclav Hapla   if (parent) PetscValidCharPointer(parent, 2);
1432c57a1a9aSVaclav Hapla   PetscValidCharPointer(name, 3);
14334302210dSVaclav Hapla   PetscValidBoolPointer(has, 4);
143477717648SVaclav Hapla   PetscCall(PetscViewerHDF5GetGroup(viewer, parent, &parentAbsPath));
14359566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5Traverse_Internal(viewer, parentAbsPath, PETSC_FALSE, has, NULL));
14369566063dSJacob Faibussowitsch   if (*has) PetscCall(PetscViewerHDF5HasAttribute_Internal(viewer, parentAbsPath, name, has));
14379566063dSJacob Faibussowitsch   PetscCall(PetscFree(parentAbsPath));
143806db490cSVaclav Hapla   PetscFunctionReturn(0);
143906db490cSVaclav Hapla }
144006db490cSVaclav Hapla 
1441577e0e04SVaclav Hapla /*@C
1442811af0c4SBarry Smith  PetscViewerHDF5HasObjectAttribute - Check whether an attribute is attached to the dataset matching the given `PetscObject` by name
1443577e0e04SVaclav Hapla 
1444343a20b2SVaclav Hapla   Collective
1445343a20b2SVaclav Hapla 
1446577e0e04SVaclav Hapla   Input Parameters:
1447811af0c4SBarry Smith + viewer - The `PETSCVIEWERHDF5` viewer
1448577e0e04SVaclav Hapla . obj    - The object whose name is used to lookup the parent dataset, relative to the current group.
1449577e0e04SVaclav Hapla - name   - The attribute name
1450577e0e04SVaclav Hapla 
1451577e0e04SVaclav Hapla   Output Parameter:
1452577e0e04SVaclav Hapla . has    - Flag for attribute existence
1453577e0e04SVaclav Hapla 
1454811af0c4SBarry Smith   Note:
1455577e0e04SVaclav Hapla   This fails if current_group/object_name doesn't resolve to a dataset (the path doesn't exist or is not a dataset).
1456811af0c4SBarry Smith   You might want to check first if it does using `PetscViewerHDF5HasObject()`.
1457577e0e04SVaclav Hapla 
1458577e0e04SVaclav Hapla   Level: advanced
1459577e0e04SVaclav Hapla 
1460811af0c4SBarry Smith .seealso: `PETSCVIEWERHDF5`, `PetscViewerHDF5Open()`, `PetscViewerHDF5HasAttribute()`, `PetscViewerHDF5WriteObjectAttribute()`, `PetscViewerHDF5ReadObjectAttribute()`, `PetscViewerHDF5HasObject()`, `PetscViewerHDF5PushGroup()`, `PetscViewerHDF5PopGroup()`, `PetscViewerHDF5GetGroup()`
1461577e0e04SVaclav Hapla @*/
14629371c9d4SSatish Balay PetscErrorCode PetscViewerHDF5HasObjectAttribute(PetscViewer viewer, PetscObject obj, const char name[], PetscBool *has) {
1463577e0e04SVaclav Hapla   PetscFunctionBegin;
1464577e0e04SVaclav Hapla   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
1465577e0e04SVaclav Hapla   PetscValidHeader(obj, 2);
1466577e0e04SVaclav Hapla   PetscValidCharPointer(name, 3);
14674302210dSVaclav Hapla   PetscValidBoolPointer(has, 4);
14689566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5CheckNamedObject_Internal(viewer, obj));
14699566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5HasAttribute(viewer, obj->name, name, has));
1470577e0e04SVaclav Hapla   PetscFunctionReturn(0);
1471577e0e04SVaclav Hapla }
1472577e0e04SVaclav Hapla 
14739371c9d4SSatish Balay static PetscErrorCode PetscViewerHDF5HasAttribute_Internal(PetscViewer viewer, const char parent[], const char name[], PetscBool *has) {
147406db490cSVaclav Hapla   hid_t  h5;
147506db490cSVaclav Hapla   htri_t hhas;
147606db490cSVaclav Hapla 
147706db490cSVaclav Hapla   PetscFunctionBegin;
14789566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5GetFileId(viewer, &h5));
1479792fecdfSBarry Smith   PetscCallHDF5Return(hhas, H5Aexists_by_name, (h5, parent, name, H5P_DEFAULT));
14805cdeb108SMatthew G. Knepley   *has = hhas ? PETSC_TRUE : PETSC_FALSE;
1481e7bdbf8eSMatthew G. Knepley   PetscFunctionReturn(0);
1482e7bdbf8eSMatthew G. Knepley }
1483e7bdbf8eSMatthew G. Knepley 
1484a75e6a4aSMatthew G. Knepley /*
1485a75e6a4aSMatthew G. Knepley   The variable Petsc_Viewer_HDF5_keyval is used to indicate an MPI attribute that
1486a75e6a4aSMatthew G. Knepley   is attached to a communicator, in this case the attribute is a PetscViewer.
1487a75e6a4aSMatthew G. Knepley */
1488d4c7638eSBarry Smith PetscMPIInt Petsc_Viewer_HDF5_keyval = MPI_KEYVAL_INVALID;
1489a75e6a4aSMatthew G. Knepley 
1490a75e6a4aSMatthew G. Knepley /*@C
1491811af0c4SBarry Smith   PETSC_VIEWER_HDF5_ - Creates an `PETSCVIEWERHDF5` `PetscViewer` shared by all processors in a communicator.
1492a75e6a4aSMatthew G. Knepley 
1493d083f849SBarry Smith   Collective
1494a75e6a4aSMatthew G. Knepley 
1495a75e6a4aSMatthew G. Knepley   Input Parameter:
1496811af0c4SBarry Smith . comm - the MPI communicator to share the HDF5 `PetscViewer`
1497a75e6a4aSMatthew G. Knepley 
1498a75e6a4aSMatthew G. Knepley   Level: intermediate
1499a75e6a4aSMatthew G. Knepley 
1500811af0c4SBarry Smith   Options Database Key:
150110699b91SBarry Smith . -viewer_hdf5_filename <name> - name of the HDF5 file
1502a75e6a4aSMatthew G. Knepley 
1503811af0c4SBarry Smith   Environmental variable:
1504811af0c4SBarry Smith . `PETSC_VIEWER_HDF5_FILENAME` - name of the HDF5 file
1505a75e6a4aSMatthew G. Knepley 
1506811af0c4SBarry Smith   Note:
1507811af0c4SBarry Smith   Unlike almost all other PETSc routines, `PETSC_VIEWER_HDF5_()` does not return
1508811af0c4SBarry Smith   an error code.  The HDF5 `PetscViewer` is usually used in the form
1509a75e6a4aSMatthew G. Knepley $       XXXView(XXX object, PETSC_VIEWER_HDF5_(comm));
1510a75e6a4aSMatthew G. Knepley 
1511811af0c4SBarry Smith .seealso: `PETSCVIEWERHDF5`, `PetscViewerHDF5Open()`, `PetscViewerCreate()`, `PetscViewerDestroy()`
1512a75e6a4aSMatthew G. Knepley @*/
15139371c9d4SSatish Balay PetscViewer PETSC_VIEWER_HDF5_(MPI_Comm comm) {
1514a75e6a4aSMatthew G. Knepley   PetscErrorCode ierr;
1515a75e6a4aSMatthew G. Knepley   PetscBool      flg;
1516a75e6a4aSMatthew G. Knepley   PetscViewer    viewer;
1517a75e6a4aSMatthew G. Knepley   char           fname[PETSC_MAX_PATH_LEN];
1518a75e6a4aSMatthew G. Knepley   MPI_Comm       ncomm;
1519a75e6a4aSMatthew G. Knepley 
1520a75e6a4aSMatthew G. Knepley   PetscFunctionBegin;
15219371c9d4SSatish Balay   ierr = PetscCommDuplicate(comm, &ncomm, NULL);
15229371c9d4SSatish Balay   if (ierr) {
15239371c9d4SSatish Balay     PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_HDF5_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
15249371c9d4SSatish Balay     PetscFunctionReturn(NULL);
15259371c9d4SSatish Balay   }
1526a75e6a4aSMatthew G. Knepley   if (Petsc_Viewer_HDF5_keyval == MPI_KEYVAL_INVALID) {
1527908793a3SLisandro Dalcin     ierr = MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, MPI_COMM_NULL_DELETE_FN, &Petsc_Viewer_HDF5_keyval, NULL);
15289371c9d4SSatish Balay     if (ierr) {
15299371c9d4SSatish Balay       PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_HDF5_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
15309371c9d4SSatish Balay       PetscFunctionReturn(NULL);
15319371c9d4SSatish Balay     }
1532a75e6a4aSMatthew G. Knepley   }
153347435625SJed Brown   ierr = MPI_Comm_get_attr(ncomm, Petsc_Viewer_HDF5_keyval, (void **)&viewer, (int *)&flg);
15349371c9d4SSatish Balay   if (ierr) {
15359371c9d4SSatish Balay     PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_HDF5_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
15369371c9d4SSatish Balay     PetscFunctionReturn(NULL);
15379371c9d4SSatish Balay   }
1538a75e6a4aSMatthew G. Knepley   if (!flg) { /* PetscViewer not yet created */
1539a75e6a4aSMatthew G. Knepley     ierr = PetscOptionsGetenv(ncomm, "PETSC_VIEWER_HDF5_FILENAME", fname, PETSC_MAX_PATH_LEN, &flg);
15409371c9d4SSatish Balay     if (ierr) {
15419371c9d4SSatish Balay       PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_HDF5_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " ");
15429371c9d4SSatish Balay       PetscFunctionReturn(NULL);
15439371c9d4SSatish Balay     }
1544a75e6a4aSMatthew G. Knepley     if (!flg) {
1545a75e6a4aSMatthew G. Knepley       ierr = PetscStrcpy(fname, "output.h5");
15469371c9d4SSatish Balay       if (ierr) {
15479371c9d4SSatish Balay         PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_HDF5_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " ");
15489371c9d4SSatish Balay         PetscFunctionReturn(NULL);
15499371c9d4SSatish Balay       }
1550a75e6a4aSMatthew G. Knepley     }
1551a75e6a4aSMatthew G. Knepley     ierr = PetscViewerHDF5Open(ncomm, fname, FILE_MODE_WRITE, &viewer);
15529371c9d4SSatish Balay     if (ierr) {
15539371c9d4SSatish Balay       PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_HDF5_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " ");
15549371c9d4SSatish Balay       PetscFunctionReturn(NULL);
15559371c9d4SSatish Balay     }
1556a75e6a4aSMatthew G. Knepley     ierr = PetscObjectRegisterDestroy((PetscObject)viewer);
15579371c9d4SSatish Balay     if (ierr) {
15589371c9d4SSatish Balay       PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_HDF5_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " ");
15599371c9d4SSatish Balay       PetscFunctionReturn(NULL);
15609371c9d4SSatish Balay     }
156147435625SJed Brown     ierr = MPI_Comm_set_attr(ncomm, Petsc_Viewer_HDF5_keyval, (void *)viewer);
15629371c9d4SSatish Balay     if (ierr) {
15639371c9d4SSatish Balay       PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_HDF5_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
15649371c9d4SSatish Balay       PetscFunctionReturn(NULL);
15659371c9d4SSatish Balay     }
1566a75e6a4aSMatthew G. Knepley   }
1567a75e6a4aSMatthew G. Knepley   ierr = PetscCommDestroy(&ncomm);
15689371c9d4SSatish Balay   if (ierr) {
15699371c9d4SSatish Balay     PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_HDF5_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " ");
15709371c9d4SSatish Balay     PetscFunctionReturn(NULL);
15719371c9d4SSatish Balay   }
1572a75e6a4aSMatthew G. Knepley   PetscFunctionReturn(viewer);
1573a75e6a4aSMatthew G. Knepley }
1574