xref: /petsc/src/sys/classes/viewer/impls/hdf5/hdf5v.c (revision 77717648de277ae4789506d75523d5b3eb440c8c)
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 
6*77717648SVaclav Hapla /*@C
7*77717648SVaclav Hapla   PetscViewerHDF5GetGroup - Get the current HDF5 group name (full path), set with `PetscViewerHDF5PushGroup()`/`PetscViewerHDF5PopGroup()`.
8*77717648SVaclav Hapla 
9*77717648SVaclav Hapla   Not collective
10*77717648SVaclav Hapla 
11*77717648SVaclav Hapla   Input Parameters:
12*77717648SVaclav Hapla + viewer - the `PetscViewer` of type `PETSCVIEWERHDF5`
13*77717648SVaclav Hapla - path - (Optional) The path relative to the pushed group
14*77717648SVaclav Hapla 
15*77717648SVaclav Hapla   Output Parameter:
16*77717648SVaclav Hapla . abspath - The absolute HDF5 path (group)
17*77717648SVaclav Hapla 
18*77717648SVaclav Hapla   Level: intermediate
19*77717648SVaclav Hapla 
20*77717648SVaclav Hapla   Notes:
21*77717648SVaclav 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.
22*77717648SVaclav Hapla   So NULL or empty path means the current pushed group.
23*77717648SVaclav Hapla 
24*77717648SVaclav Hapla   The output abspath is newly allocated so needs to be freed.
25*77717648SVaclav Hapla 
26*77717648SVaclav Hapla .seealso: `PETSCVIEWERHDF5`, `PetscViewerHDF5Open()`, `PetscViewerHDF5PushGroup()`, `PetscViewerHDF5PopGroup()`, `PetscViewerHDF5OpenGroup()`
27*77717648SVaclav Hapla @*/
28*77717648SVaclav Hapla PetscErrorCode PetscViewerHDF5GetGroup(PetscViewer viewer, const char path[], char *abspath[]) {
29*77717648SVaclav 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;
35*77717648SVaclav Hapla   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
36*77717648SVaclav Hapla   if (path) PetscValidCharPointer(path, 2);
37*77717648SVaclav Hapla   PetscValidPointer(abspath, 3);
38*77717648SVaclav Hapla   PetscCall(PetscViewerHDF5GetGroup_Internal(viewer, &group));
39*77717648SVaclav Hapla   PetscCall(PetscStrlen(path, &len));
40*77717648SVaclav Hapla   relative = (PetscBool)(!len || path[0] != '/');
414302210dSVaclav Hapla   if (relative) {
429566063dSJacob Faibussowitsch     PetscCall(PetscStrcpy(buf, group));
43*77717648SVaclav 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) {
58*77717648SVaclav Hapla     char *group;
59*77717648SVaclav Hapla     PetscCall(PetscViewerHDF5GetGroup(viewer, NULL, &group));
60*77717648SVaclav 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 
719*77717648SVaclav 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 
7308c557b5aSVaclav Hapla /*@
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 
737874270d9SVaclav Hapla   Input Parameter:
738811af0c4SBarry Smith . viewer - the `PetscViewer` of type `PETSCVIEWERHDF5`
739874270d9SVaclav Hapla 
740d8d19677SJose E. Roman   Output Parameters:
741874270d9SVaclav Hapla + fileId - The HDF5 file ID
742874270d9SVaclav Hapla - groupId - The HDF5 group ID
743874270d9SVaclav Hapla 
744811af0c4SBarry Smith   Note:
745e74616beSVaclav Hapla   If the viewer is writable, the group is created if it doesn't exist yet.
746e74616beSVaclav Hapla 
747874270d9SVaclav Hapla   Level: intermediate
748874270d9SVaclav Hapla 
749811af0c4SBarry Smith .seealso: `PETSCVIEWERHDF5`, `PetscViewerHDF5Open()`, `PetscViewerHDF5PushGroup()`, `PetscViewerHDF5PopGroup()`, `PetscViewerHDF5GetGroup()`
750874270d9SVaclav Hapla @*/
7519371c9d4SSatish Balay PetscErrorCode PetscViewerHDF5OpenGroup(PetscViewer viewer, hid_t *fileId, hid_t *groupId) {
75290e03537SVaclav Hapla   hid_t       file_id;
75390e03537SVaclav Hapla   H5O_type_t  type;
75476d59af2SVaclav Hapla   const char *groupName = NULL, *fileName = NULL;
75576d59af2SVaclav Hapla   PetscBool   writable, has;
75654dbf706SVaclav Hapla 
75754dbf706SVaclav Hapla   PetscFunctionBegin;
7589566063dSJacob Faibussowitsch   PetscCall(PetscViewerWritable(viewer, &writable));
7599566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5GetFileId(viewer, &file_id));
7609566063dSJacob Faibussowitsch   PetscCall(PetscViewerFileGetName(viewer, &fileName));
761*77717648SVaclav Hapla   PetscCall(PetscViewerHDF5GetGroup_Internal(viewer, &groupName));
7629566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5Traverse_Internal(viewer, groupName, writable, &has, &type));
76376d59af2SVaclav Hapla   if (!has) {
7645f80ce2aSJacob 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);
765f7d195e4SLawrence Mitchell     SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_LIB, "HDF5 failed to create group %s although file %s is open for writing", groupName, fileName);
76676d59af2SVaclav Hapla   }
7675f80ce2aSJacob 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);
768792fecdfSBarry Smith   PetscCallHDF5Return(*groupId, H5Gopen2, (file_id, groupName ? groupName : "/", H5P_DEFAULT));
76954dbf706SVaclav Hapla   *fileId = file_id;
77054dbf706SVaclav Hapla   PetscFunctionReturn(0);
77154dbf706SVaclav Hapla }
77254dbf706SVaclav Hapla 
7733ef9c667SSatish Balay /*@
774d7dd068bSVaclav Hapla   PetscViewerHDF5PushTimestepping - Activate timestepping mode for subsequent HDF5 reading and writing.
7755c6c1daeSBarry Smith 
7765c6c1daeSBarry Smith   Not collective
7775c6c1daeSBarry Smith 
7785c6c1daeSBarry Smith   Input Parameter:
779811af0c4SBarry Smith . viewer - the `PetscViewer` of type `PETSCVIEWERHDF5`
7805c6c1daeSBarry Smith 
7815c6c1daeSBarry Smith   Level: intermediate
7825c6c1daeSBarry Smith 
783d7dd068bSVaclav Hapla   Notes:
784811af0c4SBarry Smith   On first `PetscViewerHDF5PushTimestepping()`, the initial time step is set to 0.
785811af0c4SBarry Smith   Next timesteps can then be set using `PetscViewerHDF5IncrementTimestep()` or `PetscViewerHDF5SetTimestep()`.
786811af0c4SBarry 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()`].
787811af0c4SBarry Smith   Use `PetscViewerHDF5PopTimestepping()` to deactivate timestepping mode; calling it by the end of the program is NOT mandatory.
788811af0c4SBarry Smith   Current timestep is remembered between `PetscViewerHDF5PopTimestepping()` and the next `PetscViewerHDF5PushTimestepping()`.
789d7dd068bSVaclav Hapla 
790d7dd068bSVaclav Hapla   If a dataset was stored with timestepping, it can be loaded only in the timestepping mode again.
791d7dd068bSVaclav Hapla   Loading a timestepped dataset with timestepping disabled, or vice-versa results in an error.
792d7dd068bSVaclav Hapla 
793811af0c4SBarry Smith   Developer note:
794d7dd068bSVaclav Hapla   Timestepped HDF5 dataset has an extra dimension and attribute "timestepping" set to true.
795d7dd068bSVaclav Hapla 
796811af0c4SBarry Smith .seealso: `PETSCVIEWERHDF5`, `PetscViewerHDF5Open()`, `PetscViewerHDF5PopTimestepping()`, `PetscViewerHDF5IsTimestepping()`, `PetscViewerHDF5SetTimestep()`, `PetscViewerHDF5IncrementTimestep()`, `PetscViewerHDF5GetTimestep()`
797d7dd068bSVaclav Hapla @*/
7989371c9d4SSatish Balay PetscErrorCode PetscViewerHDF5PushTimestepping(PetscViewer viewer) {
799d7dd068bSVaclav Hapla   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)viewer->data;
800d7dd068bSVaclav Hapla 
801d7dd068bSVaclav Hapla   PetscFunctionBegin;
802d7dd068bSVaclav Hapla   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
8035f80ce2aSJacob Faibussowitsch   PetscCheck(!hdf5->timestepping, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Timestepping is already pushed");
804d7dd068bSVaclav Hapla   hdf5->timestepping = PETSC_TRUE;
805d7dd068bSVaclav Hapla   if (hdf5->timestep < 0) hdf5->timestep = 0;
806d7dd068bSVaclav Hapla   PetscFunctionReturn(0);
807d7dd068bSVaclav Hapla }
808d7dd068bSVaclav Hapla 
809d7dd068bSVaclav Hapla /*@
810d7dd068bSVaclav Hapla   PetscViewerHDF5PopTimestepping - Deactivate timestepping mode for subsequent HDF5 reading and writing.
811d7dd068bSVaclav Hapla 
812d7dd068bSVaclav Hapla   Not collective
813d7dd068bSVaclav Hapla 
814d7dd068bSVaclav Hapla   Input Parameter:
815811af0c4SBarry Smith . viewer - the `PetscViewer` of type `PETSCVIEWERHDF5`
816d7dd068bSVaclav Hapla 
817d7dd068bSVaclav Hapla   Level: intermediate
818d7dd068bSVaclav Hapla 
819811af0c4SBarry Smith   Note:
820811af0c4SBarry Smith   See `PetscViewerHDF5PushTimestepping()` for details.
821d7dd068bSVaclav Hapla 
822811af0c4SBarry Smith .seealso: `PETSCVIEWERHDF5`, `PetscViewerHDF5Open()`, `PetscViewerHDF5PushTimestepping()`, `PetscViewerHDF5IsTimestepping()`, `PetscViewerHDF5SetTimestep()`, `PetscViewerHDF5IncrementTimestep()`, `PetscViewerHDF5GetTimestep()`
823d7dd068bSVaclav Hapla @*/
8249371c9d4SSatish Balay PetscErrorCode PetscViewerHDF5PopTimestepping(PetscViewer viewer) {
825d7dd068bSVaclav Hapla   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)viewer->data;
826d7dd068bSVaclav Hapla 
827d7dd068bSVaclav Hapla   PetscFunctionBegin;
828d7dd068bSVaclav Hapla   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
8295f80ce2aSJacob Faibussowitsch   PetscCheck(hdf5->timestepping, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Timestepping has not been pushed yet. Call PetscViewerHDF5PushTimestepping() first");
830d7dd068bSVaclav Hapla   hdf5->timestepping = PETSC_FALSE;
831d7dd068bSVaclav Hapla   PetscFunctionReturn(0);
832d7dd068bSVaclav Hapla }
833d7dd068bSVaclav Hapla 
834d7dd068bSVaclav Hapla /*@
835d7dd068bSVaclav Hapla   PetscViewerHDF5IsTimestepping - Ask the viewer whether it is in timestepping mode currently.
836d7dd068bSVaclav Hapla 
837d7dd068bSVaclav Hapla   Not collective
838d7dd068bSVaclav Hapla 
839d7dd068bSVaclav Hapla   Input Parameter:
840811af0c4SBarry Smith . viewer - the `PetscViewer` of type `PETSCVIEWERHDF5`
841d7dd068bSVaclav Hapla 
842d7dd068bSVaclav Hapla   Output Parameter:
843d7dd068bSVaclav Hapla . flg - is timestepping active?
844d7dd068bSVaclav Hapla 
845d7dd068bSVaclav Hapla   Level: intermediate
846d7dd068bSVaclav Hapla 
847811af0c4SBarry Smith   Note:
848811af0c4SBarry Smith   See `PetscViewerHDF5PushTimestepping()` for details.
849d7dd068bSVaclav Hapla 
850811af0c4SBarry Smith .seealso: `PETSCVIEWERHDF5`, `PetscViewerHDF5Open()`, `PetscViewerHDF5PushTimestepping()`, `PetscViewerHDF5PopTimestepping()`, `PetscViewerHDF5SetTimestep()`, `PetscViewerHDF5IncrementTimestep()`, `PetscViewerHDF5GetTimestep()`
851d7dd068bSVaclav Hapla @*/
8529371c9d4SSatish Balay PetscErrorCode PetscViewerHDF5IsTimestepping(PetscViewer viewer, PetscBool *flg) {
853d7dd068bSVaclav Hapla   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)viewer->data;
854d7dd068bSVaclav Hapla 
855d7dd068bSVaclav Hapla   PetscFunctionBegin;
856d7dd068bSVaclav Hapla   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
857d7dd068bSVaclav Hapla   *flg = hdf5->timestepping;
858d7dd068bSVaclav Hapla   PetscFunctionReturn(0);
859d7dd068bSVaclav Hapla }
860d7dd068bSVaclav Hapla 
861d7dd068bSVaclav Hapla /*@
862d7dd068bSVaclav Hapla   PetscViewerHDF5IncrementTimestep - Increments current timestep for the HDF5 output. Fields are stacked in time.
863d7dd068bSVaclav Hapla 
864d7dd068bSVaclav Hapla   Not collective
865d7dd068bSVaclav Hapla 
866d7dd068bSVaclav Hapla   Input Parameter:
867811af0c4SBarry Smith . viewer - the `PetscViewer` of type `PETSCVIEWERHDF5`
868d7dd068bSVaclav Hapla 
869d7dd068bSVaclav Hapla   Level: intermediate
870d7dd068bSVaclav Hapla 
871811af0c4SBarry Smith   Note:
872811af0c4SBarry Smith   This can be called only if the viewer is in timestepping mode. See `PetscViewerHDF5PushTimestepping()` for details.
873d7dd068bSVaclav Hapla 
874811af0c4SBarry Smith .seealso: `PETSCVIEWERHDF5`, `PetscViewerHDF5Open()`, `PetscViewerHDF5PushTimestepping()`, `PetscViewerHDF5SetTimestep()`, `PetscViewerHDF5GetTimestep()`
8755c6c1daeSBarry Smith @*/
8769371c9d4SSatish Balay PetscErrorCode PetscViewerHDF5IncrementTimestep(PetscViewer viewer) {
8775c6c1daeSBarry Smith   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)viewer->data;
8785c6c1daeSBarry Smith 
8795c6c1daeSBarry Smith   PetscFunctionBegin;
8805c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
8815f80ce2aSJacob Faibussowitsch   PetscCheck(hdf5->timestepping, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Timestepping has not been pushed yet. Call PetscViewerHDF5PushTimestepping() first");
8825c6c1daeSBarry Smith   ++hdf5->timestep;
8835c6c1daeSBarry Smith   PetscFunctionReturn(0);
8845c6c1daeSBarry Smith }
8855c6c1daeSBarry Smith 
8863ef9c667SSatish Balay /*@
887d7dd068bSVaclav Hapla   PetscViewerHDF5SetTimestep - Set the current timestep for the HDF5 output. Fields are stacked in time.
8885c6c1daeSBarry Smith 
889d7dd068bSVaclav Hapla   Logically collective
8905c6c1daeSBarry Smith 
8915c6c1daeSBarry Smith   Input Parameters:
892811af0c4SBarry Smith + viewer - the `PetscViewer` of type `PETSCVIEWERHDF5`
893d7dd068bSVaclav Hapla - timestep - The timestep
8945c6c1daeSBarry Smith 
8955c6c1daeSBarry Smith   Level: intermediate
8965c6c1daeSBarry Smith 
897811af0c4SBarry Smith   Note:
898811af0c4SBarry Smith   This can be called only if the viewer is in timestepping mode. See `PetscViewerHDF5PushTimestepping()` for details.
899d7dd068bSVaclav Hapla 
900811af0c4SBarry Smith .seealso: `PETSCVIEWERHDF5`, `PetscViewerHDF5Open()`, `PetscViewerHDF5PushTimestepping()`, `PetscViewerHDF5IncrementTimestep()`, `PetscViewerHDF5GetTimestep()`
9015c6c1daeSBarry Smith @*/
9029371c9d4SSatish Balay PetscErrorCode PetscViewerHDF5SetTimestep(PetscViewer viewer, PetscInt timestep) {
9035c6c1daeSBarry Smith   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)viewer->data;
9045c6c1daeSBarry Smith 
9055c6c1daeSBarry Smith   PetscFunctionBegin;
9065c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
907d7dd068bSVaclav Hapla   PetscValidLogicalCollectiveInt(viewer, timestep, 2);
9085f80ce2aSJacob Faibussowitsch   PetscCheck(timestep >= 0, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Timestep %" PetscInt_FMT " is negative", timestep);
9095f80ce2aSJacob Faibussowitsch   PetscCheck(hdf5->timestepping, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Timestepping has not been pushed yet. Call PetscViewerHDF5PushTimestepping() first");
9105c6c1daeSBarry Smith   hdf5->timestep = timestep;
9115c6c1daeSBarry Smith   PetscFunctionReturn(0);
9125c6c1daeSBarry Smith }
9135c6c1daeSBarry Smith 
9143ef9c667SSatish Balay /*@
9155c6c1daeSBarry Smith   PetscViewerHDF5GetTimestep - Get the current timestep for the HDF5 output. Fields are stacked in time.
9165c6c1daeSBarry Smith 
9175c6c1daeSBarry Smith   Not collective
9185c6c1daeSBarry Smith 
9195c6c1daeSBarry Smith   Input Parameter:
920811af0c4SBarry Smith . viewer - the `PetscViewer` of type `PETSCVIEWERHDF5`
9215c6c1daeSBarry Smith 
9225c6c1daeSBarry Smith   Output Parameter:
923d7dd068bSVaclav Hapla . timestep - The timestep
9245c6c1daeSBarry Smith 
9255c6c1daeSBarry Smith   Level: intermediate
9265c6c1daeSBarry Smith 
927811af0c4SBarry Smith   Note:
928811af0c4SBarry Smith   This can be called only if the viewer is in the timestepping mode. See `PetscViewerHDF5PushTimestepping()` for details.
929d7dd068bSVaclav Hapla 
930811af0c4SBarry Smith .seealso: `PETSCVIEWERHDF5`, `PetscViewerHDF5Open()`, `PetscViewerHDF5PushTimestepping()`, `PetscViewerHDF5IncrementTimestep()`, `PetscViewerHDF5SetTimestep()`
9315c6c1daeSBarry Smith @*/
9329371c9d4SSatish Balay PetscErrorCode PetscViewerHDF5GetTimestep(PetscViewer viewer, PetscInt *timestep) {
9335c6c1daeSBarry Smith   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)viewer->data;
9345c6c1daeSBarry Smith 
9355c6c1daeSBarry Smith   PetscFunctionBegin;
9365c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
937d7dd068bSVaclav Hapla   PetscValidIntPointer(timestep, 2);
9385f80ce2aSJacob Faibussowitsch   PetscCheck(hdf5->timestepping, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Timestepping has not been pushed yet. Call PetscViewerHDF5PushTimestepping() first");
9395c6c1daeSBarry Smith   *timestep = hdf5->timestep;
9405c6c1daeSBarry Smith   PetscFunctionReturn(0);
9415c6c1daeSBarry Smith }
9425c6c1daeSBarry Smith 
94336bce6e8SMatthew G. Knepley /*@C
94436bce6e8SMatthew G. Knepley   PetscDataTypeToHDF5DataType - Converts the PETSc name of a datatype to its HDF5 name.
94536bce6e8SMatthew G. Knepley 
94636bce6e8SMatthew G. Knepley   Not collective
94736bce6e8SMatthew G. Knepley 
94836bce6e8SMatthew G. Knepley   Input Parameter:
949811af0c4SBarry Smith . ptype - the PETSc datatype name (for example `PETSC_DOUBLE`)
95036bce6e8SMatthew G. Knepley 
95136bce6e8SMatthew G. Knepley   Output Parameter:
952811af0c4SBarry Smith . mtype - the HDF5  datatype
95336bce6e8SMatthew G. Knepley 
95436bce6e8SMatthew G. Knepley   Level: advanced
95536bce6e8SMatthew G. Knepley 
956db781477SPatrick Sanan .seealso: `PetscDataType`, `PetscHDF5DataTypeToPetscDataType()`
95736bce6e8SMatthew G. Knepley @*/
9589371c9d4SSatish Balay PetscErrorCode PetscDataTypeToHDF5DataType(PetscDataType ptype, hid_t *htype) {
95936bce6e8SMatthew G. Knepley   PetscFunctionBegin;
96036bce6e8SMatthew G. Knepley   if (ptype == PETSC_INT)
96136bce6e8SMatthew G. Knepley #if defined(PETSC_USE_64BIT_INDICES)
96236bce6e8SMatthew G. Knepley     *htype = H5T_NATIVE_LLONG;
96336bce6e8SMatthew G. Knepley #else
96436bce6e8SMatthew G. Knepley     *htype = H5T_NATIVE_INT;
96536bce6e8SMatthew G. Knepley #endif
96636bce6e8SMatthew G. Knepley   else if (ptype == PETSC_DOUBLE) *htype = H5T_NATIVE_DOUBLE;
96736bce6e8SMatthew G. Knepley   else if (ptype == PETSC_LONG) *htype = H5T_NATIVE_LONG;
96836bce6e8SMatthew G. Knepley   else if (ptype == PETSC_SHORT) *htype = H5T_NATIVE_SHORT;
969c9450970SBarry Smith   else if (ptype == PETSC_ENUM) *htype = H5T_NATIVE_INT;
970de3ba262SVaclav Hapla   else if (ptype == PETSC_BOOL) *htype = H5T_NATIVE_INT;
97136bce6e8SMatthew G. Knepley   else if (ptype == PETSC_FLOAT) *htype = H5T_NATIVE_FLOAT;
97236bce6e8SMatthew G. Knepley   else if (ptype == PETSC_CHAR) *htype = H5T_NATIVE_CHAR;
97336bce6e8SMatthew G. Knepley   else if (ptype == PETSC_BIT_LOGICAL) *htype = H5T_NATIVE_UCHAR;
9747e97c476SMatthew G. Knepley   else if (ptype == PETSC_STRING) *htype = H5Tcopy(H5T_C_S1);
97536bce6e8SMatthew G. Knepley   else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Unsupported PETSc datatype");
97636bce6e8SMatthew G. Knepley   PetscFunctionReturn(0);
97736bce6e8SMatthew G. Knepley }
97836bce6e8SMatthew G. Knepley 
97936bce6e8SMatthew G. Knepley /*@C
98036bce6e8SMatthew G. Knepley   PetscHDF5DataTypeToPetscDataType - Finds the PETSc name of a datatype from its HDF5 name
98136bce6e8SMatthew G. Knepley 
98236bce6e8SMatthew G. Knepley   Not collective
98336bce6e8SMatthew G. Knepley 
98436bce6e8SMatthew G. Knepley   Input Parameter:
985811af0c4SBarry Smith . htype - the HDF5 datatype (for example `H5T_NATIVE_DOUBLE`, ...)
98636bce6e8SMatthew G. Knepley 
98736bce6e8SMatthew G. Knepley   Output Parameter:
988811af0c4SBarry Smith . ptype - the PETSc datatype name (for example `PETSC_DOUBLE`)
98936bce6e8SMatthew G. Knepley 
99036bce6e8SMatthew G. Knepley   Level: advanced
99136bce6e8SMatthew G. Knepley 
992db781477SPatrick Sanan .seealso: `PetscDataType`, `PetscHDF5DataTypeToPetscDataType()`
99336bce6e8SMatthew G. Knepley @*/
9949371c9d4SSatish Balay PetscErrorCode PetscHDF5DataTypeToPetscDataType(hid_t htype, PetscDataType *ptype) {
99536bce6e8SMatthew G. Knepley   PetscFunctionBegin;
99636bce6e8SMatthew G. Knepley #if defined(PETSC_USE_64BIT_INDICES)
99736bce6e8SMatthew G. Knepley   if (htype == H5T_NATIVE_INT) *ptype = PETSC_LONG;
99836bce6e8SMatthew G. Knepley   else if (htype == H5T_NATIVE_LLONG) *ptype = PETSC_INT;
99936bce6e8SMatthew G. Knepley #else
100036bce6e8SMatthew G. Knepley   if (htype == H5T_NATIVE_INT) *ptype = PETSC_INT;
100136bce6e8SMatthew G. Knepley #endif
100236bce6e8SMatthew G. Knepley   else if (htype == H5T_NATIVE_DOUBLE) *ptype = PETSC_DOUBLE;
100336bce6e8SMatthew G. Knepley   else if (htype == H5T_NATIVE_LONG) *ptype = PETSC_LONG;
100436bce6e8SMatthew G. Knepley   else if (htype == H5T_NATIVE_SHORT) *ptype = PETSC_SHORT;
100536bce6e8SMatthew G. Knepley   else if (htype == H5T_NATIVE_FLOAT) *ptype = PETSC_FLOAT;
100636bce6e8SMatthew G. Knepley   else if (htype == H5T_NATIVE_CHAR) *ptype = PETSC_CHAR;
100736bce6e8SMatthew G. Knepley   else if (htype == H5T_NATIVE_UCHAR) *ptype = PETSC_CHAR;
10087e97c476SMatthew G. Knepley   else if (htype == H5T_C_S1) *ptype = PETSC_STRING;
100936bce6e8SMatthew G. Knepley   else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Unsupported HDF5 datatype");
101036bce6e8SMatthew G. Knepley   PetscFunctionReturn(0);
101136bce6e8SMatthew G. Knepley }
101236bce6e8SMatthew G. Knepley 
1013df863907SAlex Fikl /*@C
1014b8ee85a1SVaclav Hapla  PetscViewerHDF5WriteAttribute - Write an attribute
101536bce6e8SMatthew G. Knepley 
1016343a20b2SVaclav Hapla   Collective
1017343a20b2SVaclav Hapla 
101836bce6e8SMatthew G. Knepley   Input Parameters:
1019811af0c4SBarry Smith + viewer - The `PETSCVIEWERHDF5` viewer
10204302210dSVaclav Hapla . parent - The parent dataset/group name
102136bce6e8SMatthew G. Knepley . name   - The attribute name
102236bce6e8SMatthew G. Knepley . datatype - The attribute type
102336bce6e8SMatthew G. Knepley - value    - The attribute value
102436bce6e8SMatthew G. Knepley 
102536bce6e8SMatthew G. Knepley   Level: advanced
102636bce6e8SMatthew G. Knepley 
1027811af0c4SBarry Smith   Note:
1028343a20b2SVaclav 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.
10294302210dSVaclav Hapla 
1030811af0c4SBarry Smith .seealso: `PETSCVIEWERHDF5`, `PetscViewerHDF5Open()`, `PetscViewerHDF5WriteObjectAttribute()`, `PetscViewerHDF5ReadAttribute()`, `PetscViewerHDF5HasAttribute()`,
1031811af0c4SBarry Smith           `PetscViewerHDF5PushGroup()`, `PetscViewerHDF5PopGroup()`, `PetscViewerHDF5GetGroup()`
103236bce6e8SMatthew G. Knepley @*/
10339371c9d4SSatish Balay PetscErrorCode PetscViewerHDF5WriteAttribute(PetscViewer viewer, const char parent[], const char name[], PetscDataType datatype, const void *value) {
10344302210dSVaclav Hapla   char     *parentAbsPath;
103560568592SMatthew G. Knepley   hid_t     h5, dataspace, obj, attribute, dtype;
1036080f144cSVaclav Hapla   PetscBool has;
103736bce6e8SMatthew G. Knepley 
103836bce6e8SMatthew G. Knepley   PetscFunctionBegin;
10395cdeb108SMatthew G. Knepley   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
10404302210dSVaclav Hapla   if (parent) PetscValidCharPointer(parent, 2);
1041c57a1a9aSVaclav Hapla   PetscValidCharPointer(name, 3);
10424302210dSVaclav Hapla   PetscValidLogicalCollectiveEnum(viewer, datatype, 4);
1043b7e81f0fSVaclav Hapla   PetscValidPointer(value, 5);
1044*77717648SVaclav Hapla   PetscCall(PetscViewerHDF5GetGroup(viewer, parent, &parentAbsPath));
10459566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5Traverse_Internal(viewer, parentAbsPath, PETSC_TRUE, NULL, NULL));
10469566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5HasAttribute_Internal(viewer, parentAbsPath, name, &has));
10479566063dSJacob Faibussowitsch   PetscCall(PetscDataTypeToHDF5DataType(datatype, &dtype));
10487e97c476SMatthew G. Knepley   if (datatype == PETSC_STRING) {
10497e97c476SMatthew G. Knepley     size_t len;
10509566063dSJacob Faibussowitsch     PetscCall(PetscStrlen((const char *)value, &len));
1051792fecdfSBarry Smith     PetscCallHDF5(H5Tset_size, (dtype, len + 1));
10527e97c476SMatthew G. Knepley   }
10539566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5GetFileId(viewer, &h5));
1054792fecdfSBarry Smith   PetscCallHDF5Return(dataspace, H5Screate, (H5S_SCALAR));
1055792fecdfSBarry Smith   PetscCallHDF5Return(obj, H5Oopen, (h5, parentAbsPath, H5P_DEFAULT));
1056080f144cSVaclav Hapla   if (has) {
1057792fecdfSBarry Smith     PetscCallHDF5Return(attribute, H5Aopen_name, (obj, name));
1058080f144cSVaclav Hapla   } else {
1059792fecdfSBarry Smith     PetscCallHDF5Return(attribute, H5Acreate2, (obj, name, dtype, dataspace, H5P_DEFAULT, H5P_DEFAULT));
1060080f144cSVaclav Hapla   }
1061792fecdfSBarry Smith   PetscCallHDF5(H5Awrite, (attribute, dtype, value));
1062792fecdfSBarry Smith   if (datatype == PETSC_STRING) PetscCallHDF5(H5Tclose, (dtype));
1063792fecdfSBarry Smith   PetscCallHDF5(H5Aclose, (attribute));
1064792fecdfSBarry Smith   PetscCallHDF5(H5Oclose, (obj));
1065792fecdfSBarry Smith   PetscCallHDF5(H5Sclose, (dataspace));
10669566063dSJacob Faibussowitsch   PetscCall(PetscFree(parentAbsPath));
106736bce6e8SMatthew G. Knepley   PetscFunctionReturn(0);
106836bce6e8SMatthew G. Knepley }
106936bce6e8SMatthew G. Knepley 
1070df863907SAlex Fikl /*@C
1071811af0c4SBarry Smith  PetscViewerHDF5WriteObjectAttribute - Write an attribute to the dataset matching the given `PetscObject` by name
1072577e0e04SVaclav Hapla 
1073343a20b2SVaclav Hapla   Collective
1074343a20b2SVaclav Hapla 
1075577e0e04SVaclav Hapla   Input Parameters:
1076811af0c4SBarry Smith + viewer   - The `PETSCVIEWERHDF5` viewer
1077577e0e04SVaclav Hapla . obj      - The object whose name is used to lookup the parent dataset, relative to the current group.
1078577e0e04SVaclav Hapla . name     - The attribute name
1079577e0e04SVaclav Hapla . datatype - The attribute type
1080577e0e04SVaclav Hapla - value    - The attribute value
1081577e0e04SVaclav Hapla 
1082811af0c4SBarry Smith   Note:
1083343a20b2SVaclav 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).
1084811af0c4SBarry Smith   You might want to check first if it does using `PetscViewerHDF5HasObject()`.
1085577e0e04SVaclav Hapla 
1086577e0e04SVaclav Hapla   Level: advanced
1087577e0e04SVaclav Hapla 
1088811af0c4SBarry Smith .seealso: `PETSCVIEWERHDF5`, `PetscViewerHDF5Open()`, `PetscViewerHDF5WriteAttribute()`, `PetscViewerHDF5ReadObjectAttribute()`, `PetscViewerHDF5HasObjectAttribute()`,
1089811af0c4SBarry Smith           `PetscViewerHDF5HasObject()`, `PetscViewerHDF5PushGroup()`, `PetscViewerHDF5PopGroup()`, `PetscViewerHDF5GetGroup()`
1090577e0e04SVaclav Hapla @*/
10919371c9d4SSatish Balay PetscErrorCode PetscViewerHDF5WriteObjectAttribute(PetscViewer viewer, PetscObject obj, const char name[], PetscDataType datatype, const void *value) {
1092577e0e04SVaclav Hapla   PetscFunctionBegin;
1093577e0e04SVaclav Hapla   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
1094577e0e04SVaclav Hapla   PetscValidHeader(obj, 2);
1095577e0e04SVaclav Hapla   PetscValidCharPointer(name, 3);
1096b7e81f0fSVaclav Hapla   PetscValidPointer(value, 5);
10979566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5CheckNamedObject_Internal(viewer, obj));
10989566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5WriteAttribute(viewer, obj->name, name, datatype, value));
1099577e0e04SVaclav Hapla   PetscFunctionReturn(0);
1100577e0e04SVaclav Hapla }
1101577e0e04SVaclav Hapla 
1102577e0e04SVaclav Hapla /*@C
1103b8ee85a1SVaclav Hapla  PetscViewerHDF5ReadAttribute - Read an attribute
1104ad0c61feSMatthew G. Knepley 
1105343a20b2SVaclav Hapla   Collective
1106343a20b2SVaclav Hapla 
1107ad0c61feSMatthew G. Knepley   Input Parameters:
1108811af0c4SBarry Smith + viewer - The `PETSCVIEWERHDF5` viewer
11094302210dSVaclav Hapla . parent - The parent dataset/group name
1110ad0c61feSMatthew G. Knepley . name   - The attribute name
1111a2d6be1bSVaclav Hapla . datatype - The attribute type
1112a2d6be1bSVaclav Hapla - defaultValue - The pointer to the default value
1113ad0c61feSMatthew G. Knepley 
1114ad0c61feSMatthew G. Knepley   Output Parameter:
1115a2d6be1bSVaclav Hapla . value    - The pointer to the read HDF5 attribute value
1116ad0c61feSMatthew G. Knepley 
1117a2d6be1bSVaclav Hapla   Notes:
1118a2d6be1bSVaclav Hapla   If defaultValue is NULL and the attribute is not found, an error occurs.
1119a2d6be1bSVaclav Hapla   If defaultValue is not NULL and the attribute is not found, defaultValue is copied to value.
1120a2d6be1bSVaclav Hapla   The pointers defaultValue and value can be the same; for instance
1121811af0c4SBarry Smith $  flg = `PETSC_FALSE`;
1122811af0c4SBarry Smith $  PetscCall(`PetscViewerHDF5ReadAttribute`(viewer,name,"attr",PETSC_BOOL,&flg,&flg));
1123a2d6be1bSVaclav Hapla   is valid, but make sure the default value is initialized.
1124a2d6be1bSVaclav Hapla 
1125811af0c4SBarry Smith   If the datatype is `PETSC_STRING`, the output string is newly allocated so one must `PetscFree()` it when no longer needed.
1126708d4cb3SBarry Smith 
1127343a20b2SVaclav 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.
1128ad0c61feSMatthew G. Knepley 
1129343a20b2SVaclav Hapla   Level: advanced
11304302210dSVaclav Hapla 
1131811af0c4SBarry Smith .seealso: `PETSCVIEWERHDF5`, `PetscViewerHDF5Open()`, `PetscViewerHDF5ReadObjectAttribute()`, `PetscViewerHDF5WriteAttribute()`, `PetscViewerHDF5HasAttribute()`, `PetscViewerHDF5HasObject()`, `PetscViewerHDF5PushGroup()`, `PetscViewerHDF5PopGroup()`, `PetscViewerHDF5GetGroup()`
1132ad0c61feSMatthew G. Knepley @*/
11339371c9d4SSatish Balay PetscErrorCode PetscViewerHDF5ReadAttribute(PetscViewer viewer, const char parent[], const char name[], PetscDataType datatype, const void *defaultValue, void *value) {
11344302210dSVaclav Hapla   char     *parentAbsPath;
1135a2d6be1bSVaclav Hapla   hid_t     h5, obj, attribute, dtype;
1136969748fdSVaclav Hapla   PetscBool has;
1137ad0c61feSMatthew G. Knepley 
1138ad0c61feSMatthew G. Knepley   PetscFunctionBegin;
11395cdeb108SMatthew G. Knepley   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
11404302210dSVaclav Hapla   if (parent) PetscValidCharPointer(parent, 2);
1141c57a1a9aSVaclav Hapla   PetscValidCharPointer(name, 3);
1142a2d6be1bSVaclav Hapla   if (defaultValue) PetscValidPointer(defaultValue, 5);
1143a2d6be1bSVaclav Hapla   PetscValidPointer(value, 6);
11449566063dSJacob Faibussowitsch   PetscCall(PetscDataTypeToHDF5DataType(datatype, &dtype));
1145*77717648SVaclav Hapla   PetscCall(PetscViewerHDF5GetGroup(viewer, parent, &parentAbsPath));
11469566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5Traverse_Internal(viewer, parentAbsPath, PETSC_FALSE, &has, NULL));
11479566063dSJacob Faibussowitsch   if (has) PetscCall(PetscViewerHDF5HasAttribute_Internal(viewer, parentAbsPath, name, &has));
1148a2d6be1bSVaclav Hapla   if (!has) {
1149a2d6be1bSVaclav Hapla     if (defaultValue) {
1150a2d6be1bSVaclav Hapla       if (defaultValue != value) {
1151a2d6be1bSVaclav Hapla         if (datatype == PETSC_STRING) {
11529566063dSJacob Faibussowitsch           PetscCall(PetscStrallocpy(*(char **)defaultValue, (char **)value));
1153a2d6be1bSVaclav Hapla         } else {
1154a2d6be1bSVaclav Hapla           size_t len;
1155792fecdfSBarry Smith           PetscCallHDF5ReturnNoCheck(len, H5Tget_size, (dtype));
11569566063dSJacob Faibussowitsch           PetscCall(PetscMemcpy(value, defaultValue, len));
1157a2d6be1bSVaclav Hapla         }
1158a2d6be1bSVaclav Hapla       }
11599566063dSJacob Faibussowitsch       PetscCall(PetscFree(parentAbsPath));
1160a2d6be1bSVaclav Hapla       PetscFunctionReturn(0);
116198921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Attribute %s/%s does not exist and default value not provided", parentAbsPath, name);
1162a2d6be1bSVaclav Hapla   }
11639566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5GetFileId(viewer, &h5));
1164792fecdfSBarry Smith   PetscCallHDF5Return(obj, H5Oopen, (h5, parentAbsPath, H5P_DEFAULT));
1165792fecdfSBarry Smith   PetscCallHDF5Return(attribute, H5Aopen_name, (obj, name));
1166f0b58479SMatthew G. Knepley   if (datatype == PETSC_STRING) {
1167f0b58479SMatthew G. Knepley     size_t len;
1168a2d6be1bSVaclav Hapla     hid_t  atype;
1169792fecdfSBarry Smith     PetscCallHDF5Return(atype, H5Aget_type, (attribute));
1170792fecdfSBarry Smith     PetscCallHDF5ReturnNoCheck(len, H5Tget_size, (atype));
11719566063dSJacob Faibussowitsch     PetscCall(PetscMalloc((len + 1) * sizeof(char), value));
1172792fecdfSBarry Smith     PetscCallHDF5(H5Tset_size, (dtype, len + 1));
1173792fecdfSBarry Smith     PetscCallHDF5(H5Aread, (attribute, dtype, *(char **)value));
1174708d4cb3SBarry Smith   } else {
1175792fecdfSBarry Smith     PetscCallHDF5(H5Aread, (attribute, dtype, value));
1176708d4cb3SBarry Smith   }
1177792fecdfSBarry Smith   PetscCallHDF5(H5Aclose, (attribute));
1178e90c5075SMarek Pecha   /* H5Oclose can be used to close groups, datasets, or committed datatypes */
1179792fecdfSBarry Smith   PetscCallHDF5(H5Oclose, (obj));
11809566063dSJacob Faibussowitsch   PetscCall(PetscFree(parentAbsPath));
1181ad0c61feSMatthew G. Knepley   PetscFunctionReturn(0);
1182ad0c61feSMatthew G. Knepley }
1183ad0c61feSMatthew G. Knepley 
1184577e0e04SVaclav Hapla /*@C
1185811af0c4SBarry Smith  PetscViewerHDF5ReadObjectAttribute - Read an attribute from the dataset matching the given `PetscObject` by name
1186577e0e04SVaclav Hapla 
1187343a20b2SVaclav Hapla   Collective
1188343a20b2SVaclav Hapla 
1189577e0e04SVaclav Hapla   Input Parameters:
1190811af0c4SBarry Smith + viewer   - The `PETSCVIEWERHDF5` viewer
1191577e0e04SVaclav Hapla . obj      - The object whose name is used to lookup the parent dataset, relative to the current group.
1192577e0e04SVaclav Hapla . name     - The attribute name
1193577e0e04SVaclav Hapla - datatype - The attribute type
1194577e0e04SVaclav Hapla 
1195577e0e04SVaclav Hapla   Output Parameter:
1196577e0e04SVaclav Hapla . value    - The attribute value
1197577e0e04SVaclav Hapla 
1198811af0c4SBarry Smith   Note:
1199577e0e04SVaclav Hapla   This fails if current_group/object_name doesn't resolve to a dataset (the path doesn't exist or is not a dataset).
1200811af0c4SBarry Smith   You might want to check first if it does using `PetscViewerHDF5HasObject()`.
1201577e0e04SVaclav Hapla 
1202577e0e04SVaclav Hapla   Level: advanced
1203577e0e04SVaclav Hapla 
1204811af0c4SBarry Smith .seealso: `PETSCVIEWERHDF5`, `PetscViewerHDF5Open()`, `PetscViewerHDF5ReadAttribute()` `PetscViewerHDF5WriteObjectAttribute()`, `PetscViewerHDF5HasObjectAttribute()`, `PetscViewerHDF5PushGroup()`, `PetscViewerHDF5PopGroup()`, `PetscViewerHDF5GetGroup()`
1205577e0e04SVaclav Hapla @*/
12069371c9d4SSatish Balay PetscErrorCode PetscViewerHDF5ReadObjectAttribute(PetscViewer viewer, PetscObject obj, const char name[], PetscDataType datatype, void *defaultValue, void *value) {
1207577e0e04SVaclav Hapla   PetscFunctionBegin;
1208577e0e04SVaclav Hapla   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
1209577e0e04SVaclav Hapla   PetscValidHeader(obj, 2);
1210577e0e04SVaclav Hapla   PetscValidCharPointer(name, 3);
1211064a246eSJacob Faibussowitsch   PetscValidPointer(value, 6);
12129566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5CheckNamedObject_Internal(viewer, obj));
12139566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5ReadAttribute(viewer, obj->name, name, datatype, defaultValue, value));
1214577e0e04SVaclav Hapla   PetscFunctionReturn(0);
1215577e0e04SVaclav Hapla }
1216577e0e04SVaclav Hapla 
12179371c9d4SSatish Balay static inline PetscErrorCode PetscViewerHDF5Traverse_Inner_Internal(hid_t h5, const char name[], PetscBool createGroup, PetscBool *exists_) {
1218a75c3fd4SVaclav Hapla   htri_t exists;
1219a75c3fd4SVaclav Hapla   hid_t  group;
1220a75c3fd4SVaclav Hapla 
1221a75c3fd4SVaclav Hapla   PetscFunctionBegin;
1222792fecdfSBarry Smith   PetscCallHDF5Return(exists, H5Lexists, (h5, name, H5P_DEFAULT));
1223792fecdfSBarry Smith   if (exists) PetscCallHDF5Return(exists, H5Oexists_by_name, (h5, name, H5P_DEFAULT));
1224a75c3fd4SVaclav Hapla   if (!exists && createGroup) {
1225792fecdfSBarry Smith     PetscCallHDF5Return(group, H5Gcreate2, (h5, name, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT));
1226792fecdfSBarry Smith     PetscCallHDF5(H5Gclose, (group));
1227a75c3fd4SVaclav Hapla     exists = PETSC_TRUE;
1228a75c3fd4SVaclav Hapla   }
1229a75c3fd4SVaclav Hapla   *exists_ = (PetscBool)exists;
1230a75c3fd4SVaclav Hapla   PetscFunctionReturn(0);
1231a75c3fd4SVaclav Hapla }
1232a75c3fd4SVaclav Hapla 
12339371c9d4SSatish Balay static PetscErrorCode PetscViewerHDF5Traverse_Internal(PetscViewer viewer, const char name[], PetscBool createGroup, PetscBool *has, H5O_type_t *otype) {
123490e03537SVaclav Hapla   const char rootGroupName[] = "/";
12355cdeb108SMatthew G. Knepley   hid_t      h5;
1236e5bf9ebcSVaclav Hapla   PetscBool  exists = PETSC_FALSE;
123715b861d2SVaclav Hapla   PetscInt   i;
123815b861d2SVaclav Hapla   int        n;
123985688ae2SVaclav Hapla   char     **hierarchy;
124085688ae2SVaclav Hapla   char       buf[PETSC_MAX_PATH_LEN] = "";
12415cdeb108SMatthew G. Knepley 
12425cdeb108SMatthew G. Knepley   PetscFunctionBegin;
12435cdeb108SMatthew G. Knepley   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
124490e03537SVaclav Hapla   if (name) PetscValidCharPointer(name, 2);
124590e03537SVaclav Hapla   else name = rootGroupName;
1246ccd66a83SVaclav Hapla   if (has) {
1247064a246eSJacob Faibussowitsch     PetscValidBoolPointer(has, 4);
12485cdeb108SMatthew G. Knepley     *has = PETSC_FALSE;
1249ccd66a83SVaclav Hapla   }
1250ccd66a83SVaclav Hapla   if (otype) {
1251064a246eSJacob Faibussowitsch     PetscValidIntPointer(otype, 5);
125256cc0592SVaclav Hapla     *otype = H5O_TYPE_UNKNOWN;
1253ccd66a83SVaclav Hapla   }
12549566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5GetFileId(viewer, &h5));
125585688ae2SVaclav Hapla 
125685688ae2SVaclav Hapla   /*
125785688ae2SVaclav Hapla      Unfortunately, H5Oexists_by_name() fails if any object in hierarchy is missing.
125885688ae2SVaclav Hapla      Hence, each of them needs to be tested separately:
125985688ae2SVaclav Hapla      1) whether it's a valid link
126085688ae2SVaclav Hapla      2) whether this link resolves to an object
126185688ae2SVaclav Hapla      See H5Oexists_by_name() documentation.
126285688ae2SVaclav Hapla   */
12639566063dSJacob Faibussowitsch   PetscCall(PetscStrToArray(name, '/', &n, &hierarchy));
126485688ae2SVaclav Hapla   if (!n) {
126585688ae2SVaclav Hapla     /*  Assume group "/" always exists in accordance with HDF5 >= 1.10.0. See H5Lexists() documentation. */
1266ccd66a83SVaclav Hapla     if (has) *has = PETSC_TRUE;
1267ccd66a83SVaclav Hapla     if (otype) *otype = H5O_TYPE_GROUP;
12689566063dSJacob Faibussowitsch     PetscCall(PetscStrToArrayDestroy(n, hierarchy));
126985688ae2SVaclav Hapla     PetscFunctionReturn(0);
127085688ae2SVaclav Hapla   }
127185688ae2SVaclav Hapla   for (i = 0; i < n; i++) {
12729566063dSJacob Faibussowitsch     PetscCall(PetscStrcat(buf, "/"));
12739566063dSJacob Faibussowitsch     PetscCall(PetscStrcat(buf, hierarchy[i]));
12749566063dSJacob Faibussowitsch     PetscCall(PetscViewerHDF5Traverse_Inner_Internal(h5, buf, createGroup, &exists));
1275a75c3fd4SVaclav Hapla     if (!exists) break;
127685688ae2SVaclav Hapla   }
12779566063dSJacob Faibussowitsch   PetscCall(PetscStrToArrayDestroy(n, hierarchy));
127885688ae2SVaclav Hapla 
127985688ae2SVaclav Hapla   /* If the object exists, get its type */
1280ccd66a83SVaclav Hapla   if (exists && otype) {
12815cdeb108SMatthew G. Knepley     H5O_info_t info;
12825cdeb108SMatthew G. Knepley 
128376276748SVaclav Hapla     /* We could use H5Iget_type() here but that would require opening the object. This way we only need its name. */
1284792fecdfSBarry Smith     PetscCallHDF5(H5Oget_info_by_name, (h5, name, &info, H5P_DEFAULT));
128556cc0592SVaclav Hapla     *otype = info.type;
12865cdeb108SMatthew G. Knepley   }
1287ccd66a83SVaclav Hapla   if (has) *has = exists;
12885cdeb108SMatthew G. Knepley   PetscFunctionReturn(0);
12895cdeb108SMatthew G. Knepley }
12905cdeb108SMatthew G. Knepley 
12914302210dSVaclav Hapla /*@C
12920a9f38efSVaclav Hapla  PetscViewerHDF5HasGroup - Check whether the current (pushed) group exists in the HDF5 file
12930a9f38efSVaclav Hapla 
1294343a20b2SVaclav Hapla   Collective
1295343a20b2SVaclav Hapla 
12960a9f38efSVaclav Hapla   Input Parameters:
1297811af0c4SBarry Smith + viewer - The `PETSCVIEWERHDF5` viewer
1298*77717648SVaclav Hapla - path - The path relative to the pushed group, or NULL
12990a9f38efSVaclav Hapla 
13000a9f38efSVaclav Hapla   Output Parameter:
13010a9f38efSVaclav Hapla . has - Flag for group existence
13020a9f38efSVaclav Hapla 
13030a9f38efSVaclav Hapla   Level: advanced
13040a9f38efSVaclav Hapla 
13054302210dSVaclav Hapla   Notes:
1306785c443eSVaclav 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.
1307785c443eSVaclav Hapla   So NULL or empty path means the current pushed group.
13084302210dSVaclav Hapla 
1309811af0c4SBarry Smith   If path exists but is not a group, `PETSC_FALSE` is returned.
1310811af0c4SBarry Smith 
1311811af0c4SBarry Smith .seealso: `PETSCVIEWERHDF5`, `PetscViewerHDF5HasAttribute()`, `PetscViewerHDF5HasDataset()`, `PetscViewerHDF5PushGroup()`, `PetscViewerHDF5PopGroup()`, `PetscViewerHDF5GetGroup()`, `PetscViewerHDF5OpenGroup()`
13120a9f38efSVaclav Hapla @*/
13139371c9d4SSatish Balay PetscErrorCode PetscViewerHDF5HasGroup(PetscViewer viewer, const char path[], PetscBool *has) {
13140a9f38efSVaclav Hapla   H5O_type_t type;
13154302210dSVaclav Hapla   char      *abspath;
13160a9f38efSVaclav Hapla 
13170a9f38efSVaclav Hapla   PetscFunctionBegin;
13180a9f38efSVaclav Hapla   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
13194302210dSVaclav Hapla   if (path) PetscValidCharPointer(path, 2);
13204302210dSVaclav Hapla   PetscValidBoolPointer(has, 3);
1321*77717648SVaclav Hapla   PetscCall(PetscViewerHDF5GetGroup(viewer, path, &abspath));
13229566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5Traverse_Internal(viewer, abspath, PETSC_FALSE, NULL, &type));
13234302210dSVaclav Hapla   *has = (PetscBool)(type == H5O_TYPE_GROUP);
13249566063dSJacob Faibussowitsch   PetscCall(PetscFree(abspath));
13250a9f38efSVaclav Hapla   PetscFunctionReturn(0);
13260a9f38efSVaclav Hapla }
13270a9f38efSVaclav Hapla 
132889e0ef10SVaclav Hapla /*@C
132989e0ef10SVaclav Hapla  PetscViewerHDF5HasDataset - Check whether a given dataset exists in the HDF5 file
133089e0ef10SVaclav Hapla 
1331343a20b2SVaclav Hapla   Collective
1332343a20b2SVaclav Hapla 
133389e0ef10SVaclav Hapla   Input Parameters:
1334811af0c4SBarry Smith + viewer - The `PETSCVIEWERHDF5` viewer
133589e0ef10SVaclav Hapla - path - The dataset path
133689e0ef10SVaclav Hapla 
133789e0ef10SVaclav Hapla   Output Parameter:
133889e0ef10SVaclav Hapla . has - Flag whether dataset exists
133989e0ef10SVaclav Hapla 
134089e0ef10SVaclav Hapla   Level: advanced
134189e0ef10SVaclav Hapla 
134289e0ef10SVaclav Hapla   Notes:
1343343a20b2SVaclav 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.
134489e0ef10SVaclav Hapla 
1345811af0c4SBarry Smith   If path is NULL or empty, has is set to `PETSC_FALSE`.
1346811af0c4SBarry Smith 
1347811af0c4SBarry Smith   If path exists but is not a dataset, has is set to `PETSC_FALSE` as well.
1348811af0c4SBarry Smith 
1349811af0c4SBarry Smith .seealso: `PETSCVIEWERHDF5`, `PetscViewerHDF5HasObject()`, `PetscViewerHDF5HasAttribute()`, `PetscViewerHDF5HasGroup()`, `PetscViewerHDF5PushGroup()`, `PetscViewerHDF5PopGroup()`, `PetscViewerHDF5GetGroup()`
135089e0ef10SVaclav Hapla @*/
13519371c9d4SSatish Balay PetscErrorCode PetscViewerHDF5HasDataset(PetscViewer viewer, const char path[], PetscBool *has) {
135289e0ef10SVaclav Hapla   H5O_type_t type;
135389e0ef10SVaclav Hapla   char      *abspath;
135489e0ef10SVaclav Hapla 
135589e0ef10SVaclav Hapla   PetscFunctionBegin;
135689e0ef10SVaclav Hapla   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
135789e0ef10SVaclav Hapla   if (path) PetscValidCharPointer(path, 2);
135889e0ef10SVaclav Hapla   PetscValidBoolPointer(has, 3);
1359*77717648SVaclav Hapla   PetscCall(PetscViewerHDF5GetGroup(viewer, path, &abspath));
13609566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5Traverse_Internal(viewer, abspath, PETSC_FALSE, NULL, &type));
136189e0ef10SVaclav Hapla   *has = (PetscBool)(type == H5O_TYPE_DATASET);
13629566063dSJacob Faibussowitsch   PetscCall(PetscFree(abspath));
136389e0ef10SVaclav Hapla   PetscFunctionReturn(0);
136489e0ef10SVaclav Hapla }
136589e0ef10SVaclav Hapla 
13660a9f38efSVaclav Hapla /*@
1367e3f143f7SVaclav Hapla  PetscViewerHDF5HasObject - Check whether a dataset with the same name as given object exists in the HDF5 file under current group
1368ecce1506SVaclav Hapla 
1369343a20b2SVaclav Hapla   Collective
1370343a20b2SVaclav Hapla 
1371ecce1506SVaclav Hapla   Input Parameters:
1372811af0c4SBarry Smith + viewer - The `PETSCVIEWERHDF5` viewer
1373ecce1506SVaclav Hapla - obj    - The named object
1374ecce1506SVaclav Hapla 
1375ecce1506SVaclav Hapla   Output Parameter:
137689e0ef10SVaclav Hapla . has    - Flag for dataset existence
1377ecce1506SVaclav Hapla 
1378e3f143f7SVaclav Hapla   Notes:
137989e0ef10SVaclav Hapla   If the object is unnamed, an error occurs.
1380811af0c4SBarry Smith 
1381811af0c4SBarry Smith   If the path current_group/object_name exists but is not a dataset, has is set to `PETSC_FALSE` as well.
1382e3f143f7SVaclav Hapla 
1383ecce1506SVaclav Hapla   Level: advanced
1384ecce1506SVaclav Hapla 
1385811af0c4SBarry Smith .seealso: `PETSCVIEWERHDF5`, `PetscViewerHDF5Open()`, `PetscViewerHDF5HasDataset()`, `PetscViewerHDF5HasAttribute()`, `PetscViewerHDF5PushGroup()`, `PetscViewerHDF5PopGroup()`, `PetscViewerHDF5GetGroup()`
1386ecce1506SVaclav Hapla @*/
13879371c9d4SSatish Balay PetscErrorCode PetscViewerHDF5HasObject(PetscViewer viewer, PetscObject obj, PetscBool *has) {
138889e0ef10SVaclav Hapla   size_t len;
1389ecce1506SVaclav Hapla 
1390ecce1506SVaclav Hapla   PetscFunctionBegin;
1391c57a1a9aSVaclav Hapla   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
1392c57a1a9aSVaclav Hapla   PetscValidHeader(obj, 2);
13934302210dSVaclav Hapla   PetscValidBoolPointer(has, 3);
13949566063dSJacob Faibussowitsch   PetscCall(PetscStrlen(obj->name, &len));
13955f80ce2aSJacob Faibussowitsch   PetscCheck(len, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONG, "Object must be named");
13969566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5HasDataset(viewer, obj->name, has));
1397ecce1506SVaclav Hapla   PetscFunctionReturn(0);
1398ecce1506SVaclav Hapla }
1399ecce1506SVaclav Hapla 
1400df863907SAlex Fikl /*@C
1401ece83b6cSVaclav Hapla  PetscViewerHDF5HasAttribute - Check whether an attribute exists
1402e7bdbf8eSMatthew G. Knepley 
1403343a20b2SVaclav Hapla   Collective
1404343a20b2SVaclav Hapla 
1405e7bdbf8eSMatthew G. Knepley   Input Parameters:
1406811af0c4SBarry Smith + viewer - The `PETSCVIEWERHDF5` viewer
14074302210dSVaclav Hapla . parent - The parent dataset/group name
1408e7bdbf8eSMatthew G. Knepley - name   - The attribute name
1409e7bdbf8eSMatthew G. Knepley 
1410e7bdbf8eSMatthew G. Knepley   Output Parameter:
1411e7bdbf8eSMatthew G. Knepley . has    - Flag for attribute existence
1412e7bdbf8eSMatthew G. Knepley 
1413e7bdbf8eSMatthew G. Knepley   Level: advanced
1414e7bdbf8eSMatthew G. Knepley 
1415811af0c4SBarry Smith   Note:
1416343a20b2SVaclav 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.
14174302210dSVaclav Hapla 
1418811af0c4SBarry Smith .seealso: `PETSCVIEWERHDF5`, `PetscViewerHDF5Open()`, `PetscViewerHDF5HasObjectAttribute()`, `PetscViewerHDF5WriteAttribute()`, `PetscViewerHDF5ReadAttribute()`, `PetscViewerHDF5PushGroup()`, `PetscViewerHDF5PopGroup()`, `PetscViewerHDF5GetGroup()`
1419e7bdbf8eSMatthew G. Knepley @*/
14209371c9d4SSatish Balay PetscErrorCode PetscViewerHDF5HasAttribute(PetscViewer viewer, const char parent[], const char name[], PetscBool *has) {
14214302210dSVaclav Hapla   char *parentAbsPath;
1422e7bdbf8eSMatthew G. Knepley 
1423e7bdbf8eSMatthew G. Knepley   PetscFunctionBegin;
14245cdeb108SMatthew G. Knepley   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
14254302210dSVaclav Hapla   if (parent) PetscValidCharPointer(parent, 2);
1426c57a1a9aSVaclav Hapla   PetscValidCharPointer(name, 3);
14274302210dSVaclav Hapla   PetscValidBoolPointer(has, 4);
1428*77717648SVaclav Hapla   PetscCall(PetscViewerHDF5GetGroup(viewer, parent, &parentAbsPath));
14299566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5Traverse_Internal(viewer, parentAbsPath, PETSC_FALSE, has, NULL));
14309566063dSJacob Faibussowitsch   if (*has) PetscCall(PetscViewerHDF5HasAttribute_Internal(viewer, parentAbsPath, name, has));
14319566063dSJacob Faibussowitsch   PetscCall(PetscFree(parentAbsPath));
143206db490cSVaclav Hapla   PetscFunctionReturn(0);
143306db490cSVaclav Hapla }
143406db490cSVaclav Hapla 
1435577e0e04SVaclav Hapla /*@C
1436811af0c4SBarry Smith  PetscViewerHDF5HasObjectAttribute - Check whether an attribute is attached to the dataset matching the given `PetscObject` by name
1437577e0e04SVaclav Hapla 
1438343a20b2SVaclav Hapla   Collective
1439343a20b2SVaclav Hapla 
1440577e0e04SVaclav Hapla   Input Parameters:
1441811af0c4SBarry Smith + viewer - The `PETSCVIEWERHDF5` viewer
1442577e0e04SVaclav Hapla . obj    - The object whose name is used to lookup the parent dataset, relative to the current group.
1443577e0e04SVaclav Hapla - name   - The attribute name
1444577e0e04SVaclav Hapla 
1445577e0e04SVaclav Hapla   Output Parameter:
1446577e0e04SVaclav Hapla . has    - Flag for attribute existence
1447577e0e04SVaclav Hapla 
1448811af0c4SBarry Smith   Note:
1449577e0e04SVaclav Hapla   This fails if current_group/object_name doesn't resolve to a dataset (the path doesn't exist or is not a dataset).
1450811af0c4SBarry Smith   You might want to check first if it does using `PetscViewerHDF5HasObject()`.
1451577e0e04SVaclav Hapla 
1452577e0e04SVaclav Hapla   Level: advanced
1453577e0e04SVaclav Hapla 
1454811af0c4SBarry Smith .seealso: `PETSCVIEWERHDF5`, `PetscViewerHDF5Open()`, `PetscViewerHDF5HasAttribute()`, `PetscViewerHDF5WriteObjectAttribute()`, `PetscViewerHDF5ReadObjectAttribute()`, `PetscViewerHDF5HasObject()`, `PetscViewerHDF5PushGroup()`, `PetscViewerHDF5PopGroup()`, `PetscViewerHDF5GetGroup()`
1455577e0e04SVaclav Hapla @*/
14569371c9d4SSatish Balay PetscErrorCode PetscViewerHDF5HasObjectAttribute(PetscViewer viewer, PetscObject obj, const char name[], PetscBool *has) {
1457577e0e04SVaclav Hapla   PetscFunctionBegin;
1458577e0e04SVaclav Hapla   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
1459577e0e04SVaclav Hapla   PetscValidHeader(obj, 2);
1460577e0e04SVaclav Hapla   PetscValidCharPointer(name, 3);
14614302210dSVaclav Hapla   PetscValidBoolPointer(has, 4);
14629566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5CheckNamedObject_Internal(viewer, obj));
14639566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5HasAttribute(viewer, obj->name, name, has));
1464577e0e04SVaclav Hapla   PetscFunctionReturn(0);
1465577e0e04SVaclav Hapla }
1466577e0e04SVaclav Hapla 
14679371c9d4SSatish Balay static PetscErrorCode PetscViewerHDF5HasAttribute_Internal(PetscViewer viewer, const char parent[], const char name[], PetscBool *has) {
146806db490cSVaclav Hapla   hid_t  h5;
146906db490cSVaclav Hapla   htri_t hhas;
147006db490cSVaclav Hapla 
147106db490cSVaclav Hapla   PetscFunctionBegin;
14729566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5GetFileId(viewer, &h5));
1473792fecdfSBarry Smith   PetscCallHDF5Return(hhas, H5Aexists_by_name, (h5, parent, name, H5P_DEFAULT));
14745cdeb108SMatthew G. Knepley   *has = hhas ? PETSC_TRUE : PETSC_FALSE;
1475e7bdbf8eSMatthew G. Knepley   PetscFunctionReturn(0);
1476e7bdbf8eSMatthew G. Knepley }
1477e7bdbf8eSMatthew G. Knepley 
1478a75e6a4aSMatthew G. Knepley /*
1479a75e6a4aSMatthew G. Knepley   The variable Petsc_Viewer_HDF5_keyval is used to indicate an MPI attribute that
1480a75e6a4aSMatthew G. Knepley   is attached to a communicator, in this case the attribute is a PetscViewer.
1481a75e6a4aSMatthew G. Knepley */
1482d4c7638eSBarry Smith PetscMPIInt Petsc_Viewer_HDF5_keyval = MPI_KEYVAL_INVALID;
1483a75e6a4aSMatthew G. Knepley 
1484a75e6a4aSMatthew G. Knepley /*@C
1485811af0c4SBarry Smith   PETSC_VIEWER_HDF5_ - Creates an `PETSCVIEWERHDF5` `PetscViewer` shared by all processors in a communicator.
1486a75e6a4aSMatthew G. Knepley 
1487d083f849SBarry Smith   Collective
1488a75e6a4aSMatthew G. Knepley 
1489a75e6a4aSMatthew G. Knepley   Input Parameter:
1490811af0c4SBarry Smith . comm - the MPI communicator to share the HDF5 `PetscViewer`
1491a75e6a4aSMatthew G. Knepley 
1492a75e6a4aSMatthew G. Knepley   Level: intermediate
1493a75e6a4aSMatthew G. Knepley 
1494811af0c4SBarry Smith   Options Database Key:
149510699b91SBarry Smith . -viewer_hdf5_filename <name> - name of the HDF5 file
1496a75e6a4aSMatthew G. Knepley 
1497811af0c4SBarry Smith   Environmental variable:
1498811af0c4SBarry Smith . `PETSC_VIEWER_HDF5_FILENAME` - name of the HDF5 file
1499a75e6a4aSMatthew G. Knepley 
1500811af0c4SBarry Smith   Note:
1501811af0c4SBarry Smith   Unlike almost all other PETSc routines, `PETSC_VIEWER_HDF5_()` does not return
1502811af0c4SBarry Smith   an error code.  The HDF5 `PetscViewer` is usually used in the form
1503a75e6a4aSMatthew G. Knepley $       XXXView(XXX object, PETSC_VIEWER_HDF5_(comm));
1504a75e6a4aSMatthew G. Knepley 
1505811af0c4SBarry Smith .seealso: `PETSCVIEWERHDF5`, `PetscViewerHDF5Open()`, `PetscViewerCreate()`, `PetscViewerDestroy()`
1506a75e6a4aSMatthew G. Knepley @*/
15079371c9d4SSatish Balay PetscViewer PETSC_VIEWER_HDF5_(MPI_Comm comm) {
1508a75e6a4aSMatthew G. Knepley   PetscErrorCode ierr;
1509a75e6a4aSMatthew G. Knepley   PetscBool      flg;
1510a75e6a4aSMatthew G. Knepley   PetscViewer    viewer;
1511a75e6a4aSMatthew G. Knepley   char           fname[PETSC_MAX_PATH_LEN];
1512a75e6a4aSMatthew G. Knepley   MPI_Comm       ncomm;
1513a75e6a4aSMatthew G. Knepley 
1514a75e6a4aSMatthew G. Knepley   PetscFunctionBegin;
15159371c9d4SSatish Balay   ierr = PetscCommDuplicate(comm, &ncomm, NULL);
15169371c9d4SSatish Balay   if (ierr) {
15179371c9d4SSatish Balay     PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_HDF5_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
15189371c9d4SSatish Balay     PetscFunctionReturn(NULL);
15199371c9d4SSatish Balay   }
1520a75e6a4aSMatthew G. Knepley   if (Petsc_Viewer_HDF5_keyval == MPI_KEYVAL_INVALID) {
1521908793a3SLisandro Dalcin     ierr = MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, MPI_COMM_NULL_DELETE_FN, &Petsc_Viewer_HDF5_keyval, 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   }
152747435625SJed Brown   ierr = MPI_Comm_get_attr(ncomm, Petsc_Viewer_HDF5_keyval, (void **)&viewer, (int *)&flg);
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   if (!flg) { /* PetscViewer not yet created */
1533a75e6a4aSMatthew G. Knepley     ierr = PetscOptionsGetenv(ncomm, "PETSC_VIEWER_HDF5_FILENAME", fname, PETSC_MAX_PATH_LEN, &flg);
15349371c9d4SSatish Balay     if (ierr) {
15359371c9d4SSatish Balay       PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_HDF5_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " ");
15369371c9d4SSatish Balay       PetscFunctionReturn(NULL);
15379371c9d4SSatish Balay     }
1538a75e6a4aSMatthew G. Knepley     if (!flg) {
1539a75e6a4aSMatthew G. Knepley       ierr = PetscStrcpy(fname, "output.h5");
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     }
1545a75e6a4aSMatthew G. Knepley     ierr = PetscViewerHDF5Open(ncomm, fname, FILE_MODE_WRITE, &viewer);
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     ierr = PetscObjectRegisterDestroy((PetscObject)viewer);
15519371c9d4SSatish Balay     if (ierr) {
15529371c9d4SSatish Balay       PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_HDF5_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " ");
15539371c9d4SSatish Balay       PetscFunctionReturn(NULL);
15549371c9d4SSatish Balay     }
155547435625SJed Brown     ierr = MPI_Comm_set_attr(ncomm, Petsc_Viewer_HDF5_keyval, (void *)viewer);
15569371c9d4SSatish Balay     if (ierr) {
15579371c9d4SSatish Balay       PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_HDF5_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
15589371c9d4SSatish Balay       PetscFunctionReturn(NULL);
15599371c9d4SSatish Balay     }
1560a75e6a4aSMatthew G. Knepley   }
1561a75e6a4aSMatthew G. Knepley   ierr = PetscCommDestroy(&ncomm);
15629371c9d4SSatish Balay   if (ierr) {
15639371c9d4SSatish Balay     PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_HDF5_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " ");
15649371c9d4SSatish Balay     PetscFunctionReturn(NULL);
15659371c9d4SSatish Balay   }
1566a75e6a4aSMatthew G. Knepley   PetscFunctionReturn(viewer);
1567a75e6a4aSMatthew G. Knepley }
1568