xref: /petsc/src/sys/classes/viewer/impls/hdf5/hdf5v.c (revision 10450e9e44b354a0a3da7bbd573407bdf051df10)
16b9fdc0aSVaclav Hapla #include <petsc/private/viewerhdf5impl.h> /*I "petscviewerhdf5.h" I*/
25c6c1daeSBarry Smith 
3bb286ee1SVaclav Hapla static PetscErrorCode PetscViewerHDF5Traverse_Internal(PetscViewer, const char[], PetscBool, PetscBool *, H5O_type_t *);
406db490cSVaclav Hapla static PetscErrorCode PetscViewerHDF5HasAttribute_Internal(PetscViewer, const char[], const char[], PetscBool *);
506db490cSVaclav Hapla 
677717648SVaclav Hapla /*@C
777717648SVaclav Hapla   PetscViewerHDF5GetGroup - Get the current HDF5 group name (full path), set with `PetscViewerHDF5PushGroup()`/`PetscViewerHDF5PopGroup()`.
877717648SVaclav Hapla 
920f4b53cSBarry Smith   Not Collective
1077717648SVaclav Hapla 
1177717648SVaclav Hapla   Input Parameters:
1277717648SVaclav Hapla + viewer - the `PetscViewer` of type `PETSCVIEWERHDF5`
1377717648SVaclav Hapla - path   - (Optional) The path relative to the pushed group
1477717648SVaclav Hapla 
1577717648SVaclav Hapla   Output Parameter:
1677717648SVaclav Hapla . abspath - The absolute HDF5 path (group)
1777717648SVaclav Hapla 
1877717648SVaclav Hapla   Level: intermediate
1977717648SVaclav Hapla 
2077717648SVaclav Hapla   Notes:
2177717648SVaclav Hapla   If path starts with '/', it is taken as an absolute path overriding currently pushed group, else path is relative to the current pushed group.
223f423023SBarry Smith   `NULL` or empty path means the current pushed group.
2377717648SVaclav Hapla 
2477717648SVaclav Hapla   The output abspath is newly allocated so needs to be freed.
2577717648SVaclav Hapla 
26d1f92df0SBarry Smith .seealso: [](sec_viewers), `PETSCVIEWERHDF5`, `PetscViewerHDF5Open()`, `PetscViewerHDF5PushGroup()`, `PetscViewerHDF5PopGroup()`, `PetscViewerHDF5OpenGroup()`, `PetscViewerHDF5WriteGroup()`
2777717648SVaclav Hapla @*/
28d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerHDF5GetGroup(PetscViewer viewer, const char path[], char *abspath[])
29d71ae5a4SJacob Faibussowitsch {
3077717648SVaclav Hapla   size_t      len;
314302210dSVaclav Hapla   PetscBool   relative = PETSC_FALSE;
326c132bc1SVaclav Hapla   const char *group;
336c132bc1SVaclav Hapla   char        buf[PETSC_MAX_PATH_LEN] = "";
346c132bc1SVaclav Hapla 
356c132bc1SVaclav Hapla   PetscFunctionBegin;
3677717648SVaclav Hapla   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
3777717648SVaclav Hapla   if (path) PetscValidCharPointer(path, 2);
3877717648SVaclav Hapla   PetscValidPointer(abspath, 3);
3977717648SVaclav Hapla   PetscCall(PetscViewerHDF5GetGroup_Internal(viewer, &group));
4077717648SVaclav Hapla   PetscCall(PetscStrlen(path, &len));
4177717648SVaclav Hapla   relative = (PetscBool)(!len || path[0] != '/');
424302210dSVaclav Hapla   if (relative) {
43c6a7a370SJeremy L Thompson     PetscCall(PetscStrncpy(buf, group, sizeof(buf)));
44c6a7a370SJeremy L Thompson     if (!group || len) PetscCall(PetscStrlcat(buf, "/", sizeof(buf)));
45c6a7a370SJeremy L Thompson     PetscCall(PetscStrlcat(buf, path, sizeof(buf)));
469566063dSJacob Faibussowitsch     PetscCall(PetscStrallocpy(buf, abspath));
474302210dSVaclav Hapla   } else {
489566063dSJacob Faibussowitsch     PetscCall(PetscStrallocpy(path, abspath));
494302210dSVaclav Hapla   }
503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
516c132bc1SVaclav Hapla }
526c132bc1SVaclav Hapla 
53d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscViewerHDF5CheckNamedObject_Internal(PetscViewer viewer, PetscObject obj)
54d71ae5a4SJacob Faibussowitsch {
55577e0e04SVaclav Hapla   PetscBool has;
56577e0e04SVaclav Hapla 
57577e0e04SVaclav Hapla   PetscFunctionBegin;
589566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5HasObject(viewer, obj, &has));
59577e0e04SVaclav Hapla   if (!has) {
6077717648SVaclav Hapla     char *group;
6177717648SVaclav Hapla     PetscCall(PetscViewerHDF5GetGroup(viewer, NULL, &group));
6277717648SVaclav Hapla     SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Object (dataset) \"%s\" not stored in group %s", obj->name, group);
63577e0e04SVaclav Hapla   }
643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
65577e0e04SVaclav Hapla }
66577e0e04SVaclav Hapla 
67d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscViewerSetFromOptions_HDF5(PetscViewer v, PetscOptionItems *PetscOptionsObject)
68d71ae5a4SJacob Faibussowitsch {
69ee8b9732SVaclav Hapla   PetscBool         flg  = PETSC_FALSE, set;
7082ea9b62SBarry Smith   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)v->data;
7182ea9b62SBarry Smith 
7282ea9b62SBarry Smith   PetscFunctionBegin;
73d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "HDF5 PetscViewer Options");
749566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-viewer_hdf5_base_dimension2", "1d Vectors get 2 dimensions in HDF5", "PetscViewerHDF5SetBaseDimension2", hdf5->basedimension2, &hdf5->basedimension2, NULL));
759566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-viewer_hdf5_sp_output", "Force data to be written in single precision", "PetscViewerHDF5SetSPOutput", hdf5->spoutput, &hdf5->spoutput, NULL));
769566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-viewer_hdf5_collective", "Enable collective transfer mode", "PetscViewerHDF5SetCollective", flg, &flg, &set));
779566063dSJacob Faibussowitsch   if (set) PetscCall(PetscViewerHDF5SetCollective(v, flg));
7819a20e4cSMatthew G. Knepley   flg = PETSC_FALSE;
799566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-viewer_hdf5_default_timestepping", "Set default timestepping state", "PetscViewerHDF5SetDefaultTimestepping", flg, &flg, &set));
809566063dSJacob Faibussowitsch   if (set) PetscCall(PetscViewerHDF5SetDefaultTimestepping(v, flg));
81d0609cedSBarry Smith   PetscOptionsHeadEnd();
823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8382ea9b62SBarry Smith }
8482ea9b62SBarry Smith 
85d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscViewerView_HDF5(PetscViewer v, PetscViewer viewer)
86d71ae5a4SJacob Faibussowitsch {
871b793a25SVaclav Hapla   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)v->data;
8803fa8834SVaclav Hapla   PetscBool         flg;
891b793a25SVaclav Hapla 
901b793a25SVaclav Hapla   PetscFunctionBegin;
9148a46eb9SPierre Jolivet   if (hdf5->filename) PetscCall(PetscViewerASCIIPrintf(viewer, "Filename: %s\n", hdf5->filename));
929566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "Vectors with blocksize 1 saved as 2D datasets: %s\n", PetscBools[hdf5->basedimension2]));
939566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "Enforce single precision storage: %s\n", PetscBools[hdf5->spoutput]));
949566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5GetCollective(v, &flg));
959566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "MPI-IO transfer mode: %s\n", flg ? "collective" : "independent"));
969566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "Default timestepping: %s\n", PetscBools[hdf5->defTimestepping]));
973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
981b793a25SVaclav Hapla }
991b793a25SVaclav Hapla 
100d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscViewerFileClose_HDF5(PetscViewer viewer)
101d71ae5a4SJacob Faibussowitsch {
1025c6c1daeSBarry Smith   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)viewer->data;
1035c6c1daeSBarry Smith 
1045c6c1daeSBarry Smith   PetscFunctionBegin;
1059566063dSJacob Faibussowitsch   PetscCall(PetscFree(hdf5->filename));
106792fecdfSBarry Smith   if (hdf5->file_id) PetscCallHDF5(H5Fclose, (hdf5->file_id));
1073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1085c6c1daeSBarry Smith }
1095c6c1daeSBarry Smith 
110d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscViewerFlush_HDF5(PetscViewer viewer)
111d71ae5a4SJacob Faibussowitsch {
1126226335aSVaclav Hapla   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)viewer->data;
1136226335aSVaclav Hapla 
1146226335aSVaclav Hapla   PetscFunctionBegin;
115792fecdfSBarry Smith   if (hdf5->file_id) PetscCallHDF5(H5Fflush, (hdf5->file_id, H5F_SCOPE_LOCAL));
1163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1176226335aSVaclav Hapla }
1186226335aSVaclav Hapla 
119d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscViewerDestroy_HDF5(PetscViewer viewer)
120d71ae5a4SJacob Faibussowitsch {
1215c6c1daeSBarry Smith   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)viewer->data;
1225c6c1daeSBarry Smith 
1235c6c1daeSBarry Smith   PetscFunctionBegin;
124792fecdfSBarry Smith   PetscCallHDF5(H5Pclose, (hdf5->dxpl_id));
1259566063dSJacob Faibussowitsch   PetscCall(PetscViewerFileClose_HDF5(viewer));
1265c6c1daeSBarry Smith   while (hdf5->groups) {
1277d964842SVaclav Hapla     PetscViewerHDF5GroupList *tmp = hdf5->groups->next;
1285c6c1daeSBarry Smith 
1299566063dSJacob Faibussowitsch     PetscCall(PetscFree(hdf5->groups->name));
1309566063dSJacob Faibussowitsch     PetscCall(PetscFree(hdf5->groups));
1315c6c1daeSBarry Smith     hdf5->groups = tmp;
1325c6c1daeSBarry Smith   }
1339566063dSJacob Faibussowitsch   PetscCall(PetscFree(hdf5));
1349566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetName_C", NULL));
1359566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetName_C", NULL));
1369566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetMode_C", NULL));
1372e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetMode_C", NULL));
1389566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerHDF5SetBaseDimension2_C", NULL));
1399566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerHDF5SetSPOutput_C", NULL));
1402e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerHDF5SetCollective_C", NULL));
1412e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerHDF5GetCollective_C", NULL));
1429566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerHDF5GetDefaultTimestepping_C", NULL));
1439566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerHDF5SetDefaultTimestepping_C", NULL));
1443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1455c6c1daeSBarry Smith }
1465c6c1daeSBarry Smith 
147d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscViewerFileSetMode_HDF5(PetscViewer viewer, PetscFileMode type)
148d71ae5a4SJacob Faibussowitsch {
1495c6c1daeSBarry Smith   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)viewer->data;
1505c6c1daeSBarry Smith 
1515c6c1daeSBarry Smith   PetscFunctionBegin;
1525c6c1daeSBarry Smith   hdf5->btype = type;
1533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1545c6c1daeSBarry Smith }
1555c6c1daeSBarry Smith 
156d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscViewerFileGetMode_HDF5(PetscViewer viewer, PetscFileMode *type)
157d71ae5a4SJacob Faibussowitsch {
1580b62783dSVaclav Hapla   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)viewer->data;
1590b62783dSVaclav Hapla 
1600b62783dSVaclav Hapla   PetscFunctionBegin;
1610b62783dSVaclav Hapla   *type = hdf5->btype;
1623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1630b62783dSVaclav Hapla }
1640b62783dSVaclav Hapla 
165d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscViewerHDF5SetBaseDimension2_HDF5(PetscViewer viewer, PetscBool flg)
166d71ae5a4SJacob Faibussowitsch {
16782ea9b62SBarry Smith   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)viewer->data;
16882ea9b62SBarry Smith 
16982ea9b62SBarry Smith   PetscFunctionBegin;
17082ea9b62SBarry Smith   hdf5->basedimension2 = flg;
1713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17282ea9b62SBarry Smith }
17382ea9b62SBarry Smith 
174df863907SAlex Fikl /*@
17582ea9b62SBarry Smith   PetscViewerHDF5SetBaseDimension2 - Vectors of 1 dimension (i.e. bs/dof is 1) will be saved in the HDF5 file with a
17682ea9b62SBarry Smith   dimension of 2.
17782ea9b62SBarry Smith 
178c3339decSBarry Smith   Logically Collective
17982ea9b62SBarry Smith 
18082ea9b62SBarry Smith   Input Parameters:
181811af0c4SBarry Smith + viewer - the `PetscViewer`; if it is a `PETSCVIEWERHDF5` then this command is ignored
182811af0c4SBarry 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
18382ea9b62SBarry Smith 
184811af0c4SBarry Smith   Options Database Key:
18582ea9b62SBarry 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
18682ea9b62SBarry Smith 
1873f423023SBarry Smith   Level: intermediate
1883f423023SBarry Smith 
189811af0c4SBarry Smith   Note:
19095452b02SPatrick 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
19182ea9b62SBarry Smith   of one when the dimension is lower. Others think the option is crazy.
19282ea9b62SBarry Smith 
193aec76313SJacob Faibussowitsch .seealso: [](sec_viewers), `PETSCVIEWERHDF5`, `PetscViewerFileSetMode()`, `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerBinaryOpen()`
19482ea9b62SBarry Smith @*/
195d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerHDF5SetBaseDimension2(PetscViewer viewer, PetscBool flg)
196d71ae5a4SJacob Faibussowitsch {
19782ea9b62SBarry Smith   PetscFunctionBegin;
19882ea9b62SBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
199cac4c232SBarry Smith   PetscTryMethod(viewer, "PetscViewerHDF5SetBaseDimension2_C", (PetscViewer, PetscBool), (viewer, flg));
2003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
20182ea9b62SBarry Smith }
20282ea9b62SBarry Smith 
203df863907SAlex Fikl /*@
20482ea9b62SBarry Smith   PetscViewerHDF5GetBaseDimension2 - Vectors of 1 dimension (i.e. bs/dof is 1) will be saved in the HDF5 file with a
20582ea9b62SBarry Smith   dimension of 2.
20682ea9b62SBarry Smith 
207c3339decSBarry Smith   Logically Collective
20882ea9b62SBarry Smith 
20982ea9b62SBarry Smith   Input Parameter:
210811af0c4SBarry Smith . viewer - the `PetscViewer`, must be `PETSCVIEWERHDF5`
21182ea9b62SBarry Smith 
21282ea9b62SBarry Smith   Output Parameter:
213811af0c4SBarry 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
21482ea9b62SBarry Smith 
2153f423023SBarry Smith   Level: intermediate
2163f423023SBarry Smith 
217811af0c4SBarry Smith   Note:
21895452b02SPatrick 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
21982ea9b62SBarry Smith   of one when the dimension is lower. Others think the option is crazy.
22082ea9b62SBarry Smith 
221d1f92df0SBarry Smith .seealso: [](sec_viewers), `PETSCVIEWERHDF5`, `PetscViewerFileSetMode()`, `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerBinaryOpen()`
22282ea9b62SBarry Smith @*/
223d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerHDF5GetBaseDimension2(PetscViewer viewer, PetscBool *flg)
224d71ae5a4SJacob Faibussowitsch {
22582ea9b62SBarry Smith   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)viewer->data;
22682ea9b62SBarry Smith 
22782ea9b62SBarry Smith   PetscFunctionBegin;
22882ea9b62SBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
22982ea9b62SBarry Smith   *flg = hdf5->basedimension2;
2303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23182ea9b62SBarry Smith }
23282ea9b62SBarry Smith 
233d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscViewerHDF5SetSPOutput_HDF5(PetscViewer viewer, PetscBool flg)
234d71ae5a4SJacob Faibussowitsch {
2359a0502c6SHåkon Strandenes   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)viewer->data;
2369a0502c6SHåkon Strandenes 
2379a0502c6SHåkon Strandenes   PetscFunctionBegin;
2389a0502c6SHåkon Strandenes   hdf5->spoutput = flg;
2393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2409a0502c6SHåkon Strandenes }
2419a0502c6SHåkon Strandenes 
242df863907SAlex Fikl /*@
2439a0502c6SHåkon Strandenes   PetscViewerHDF5SetSPOutput - Data is written to disk in single precision even if PETSc is
244811af0c4SBarry Smith   compiled with double precision `PetscReal`.
2459a0502c6SHåkon Strandenes 
246c3339decSBarry Smith   Logically Collective
2479a0502c6SHåkon Strandenes 
2489a0502c6SHåkon Strandenes   Input Parameters:
249811af0c4SBarry Smith + viewer - the PetscViewer; if it is a `PETSCVIEWERHDF5` then this command is ignored
250811af0c4SBarry Smith - flg    - if `PETSC_TRUE` the data will be written to disk with single precision
2519a0502c6SHåkon Strandenes 
252811af0c4SBarry Smith   Options Database Key:
2539a0502c6SHåkon Strandenes . -viewer_hdf5_sp_output - turns on (true) or off (false) output in single precision
2549a0502c6SHåkon Strandenes 
2553f423023SBarry Smith   Level: intermediate
2563f423023SBarry Smith 
257811af0c4SBarry Smith   Note:
25895452b02SPatrick Sanan   Setting this option does not make any difference if PETSc is compiled with single precision
2599a0502c6SHåkon Strandenes   in the first place. It does not affect reading datasets (HDF5 handle this internally).
2609a0502c6SHåkon Strandenes 
261d1f92df0SBarry Smith .seealso: [](sec_viewers), `PETSCVIEWERHDF5`, `PetscViewerFileSetMode()`, `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerBinaryOpen()`,
262811af0c4SBarry Smith           `PetscReal`, `PetscViewerHDF5GetSPOutput()`
2639a0502c6SHåkon Strandenes @*/
264d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerHDF5SetSPOutput(PetscViewer viewer, PetscBool flg)
265d71ae5a4SJacob Faibussowitsch {
2669a0502c6SHåkon Strandenes   PetscFunctionBegin;
2679a0502c6SHåkon Strandenes   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
268cac4c232SBarry Smith   PetscTryMethod(viewer, "PetscViewerHDF5SetSPOutput_C", (PetscViewer, PetscBool), (viewer, flg));
2693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2709a0502c6SHåkon Strandenes }
2719a0502c6SHåkon Strandenes 
272df863907SAlex Fikl /*@
2739a0502c6SHåkon Strandenes   PetscViewerHDF5GetSPOutput - Data is written to disk in single precision even if PETSc is
274811af0c4SBarry Smith   compiled with double precision `PetscReal`.
2759a0502c6SHåkon Strandenes 
276c3339decSBarry Smith   Logically Collective
2779a0502c6SHåkon Strandenes 
2789a0502c6SHåkon Strandenes   Input Parameter:
279811af0c4SBarry Smith . viewer - the PetscViewer, must be of type `PETSCVIEWERHDF5`
2809a0502c6SHåkon Strandenes 
2819a0502c6SHåkon Strandenes   Output Parameter:
282811af0c4SBarry Smith . flg - if `PETSC_TRUE` the data will be written to disk with single precision
2839a0502c6SHåkon Strandenes 
2849a0502c6SHåkon Strandenes   Level: intermediate
2859a0502c6SHåkon Strandenes 
286d1f92df0SBarry Smith .seealso: [](sec_viewers), `PetscViewerFileSetMode()`, `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerBinaryOpen()`,
287811af0c4SBarry Smith           `PetscReal`, `PetscViewerHDF5SetSPOutput()`
2889a0502c6SHåkon Strandenes @*/
289d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerHDF5GetSPOutput(PetscViewer viewer, PetscBool *flg)
290d71ae5a4SJacob Faibussowitsch {
2919a0502c6SHåkon Strandenes   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)viewer->data;
2929a0502c6SHåkon Strandenes 
2939a0502c6SHåkon Strandenes   PetscFunctionBegin;
2949a0502c6SHåkon Strandenes   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
2959a0502c6SHåkon Strandenes   *flg = hdf5->spoutput;
2963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2979a0502c6SHåkon Strandenes }
2989a0502c6SHåkon Strandenes 
299d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscViewerHDF5SetCollective_HDF5(PetscViewer viewer, PetscBool flg)
300d71ae5a4SJacob Faibussowitsch {
301ee8b9732SVaclav Hapla   PetscFunctionBegin;
302ee8b9732SVaclav Hapla   /* H5FD_MPIO_COLLECTIVE is wrong in hdf5 1.10.2, and is the same as H5FD_MPIO_INDEPENDENT in earlier versions
303ee8b9732SVaclav Hapla      - see e.g. https://gitlab.cosma.dur.ac.uk/swift/swiftsim/issues/431 */
304c796909eSBarry Smith #if H5_VERSION_GE(1, 10, 3) && defined(H5_HAVE_PARALLEL)
305ee8b9732SVaclav Hapla   {
306ee8b9732SVaclav Hapla     PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)viewer->data;
307792fecdfSBarry Smith     PetscCallHDF5(H5Pset_dxpl_mpio, (hdf5->dxpl_id, flg ? H5FD_MPIO_COLLECTIVE : H5FD_MPIO_INDEPENDENT));
308ee8b9732SVaclav Hapla   }
309ee8b9732SVaclav Hapla #else
3109566063dSJacob 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"));
311ee8b9732SVaclav Hapla #endif
3123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
313ee8b9732SVaclav Hapla }
314ee8b9732SVaclav Hapla 
315ee8b9732SVaclav Hapla /*@
316ee8b9732SVaclav Hapla   PetscViewerHDF5SetCollective - Use collective MPI-IO transfer mode for HDF5 reads and writes.
317ee8b9732SVaclav Hapla 
318ee8b9732SVaclav Hapla   Logically Collective; flg must contain common value
319ee8b9732SVaclav Hapla 
320ee8b9732SVaclav Hapla   Input Parameters:
321811af0c4SBarry Smith + viewer - the `PetscViewer`; if it is not `PETSCVIEWERHDF5` then this command is ignored
322811af0c4SBarry Smith - flg    - `PETSC_TRUE` for collective mode; `PETSC_FALSE` for independent mode (default)
323ee8b9732SVaclav Hapla 
324811af0c4SBarry Smith   Options Database Key:
325ee8b9732SVaclav Hapla . -viewer_hdf5_collective - turns on (true) or off (false) collective transfers
326ee8b9732SVaclav Hapla 
3273f423023SBarry Smith   Level: intermediate
3283f423023SBarry Smith 
329811af0c4SBarry Smith   Note:
330ee8b9732SVaclav Hapla   Collective mode gives the MPI-IO layer underneath HDF5 a chance to do some additional collective optimizations and hence can perform better.
33153effed7SBarry 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.
332ee8b9732SVaclav Hapla 
333aec76313SJacob Faibussowitsch   Developer Notes:
334811af0c4SBarry Smith   In the HDF5 layer, `PETSC_TRUE` / `PETSC_FALSE` means `H5Pset_dxpl_mpio()` is called with `H5FD_MPIO_COLLECTIVE` / `H5FD_MPIO_INDEPENDENT`, respectively.
335ee8b9732SVaclav Hapla   This in turn means use of MPI_File_{read,write}_all /  MPI_File_{read,write} in the MPI-IO layer, respectively.
336ee8b9732SVaclav Hapla   See HDF5 documentation and MPI-IO documentation for details.
337ee8b9732SVaclav Hapla 
338d1f92df0SBarry Smith .seealso: [](sec_viewers), `PETSCVIEWERHDF5`, `PetscViewerHDF5GetCollective()`, `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerHDF5Open()`
339ee8b9732SVaclav Hapla @*/
340d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerHDF5SetCollective(PetscViewer viewer, PetscBool flg)
341d71ae5a4SJacob Faibussowitsch {
342ee8b9732SVaclav Hapla   PetscFunctionBegin;
343ee8b9732SVaclav Hapla   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
344ee8b9732SVaclav Hapla   PetscValidLogicalCollectiveBool(viewer, flg, 2);
345cac4c232SBarry Smith   PetscTryMethod(viewer, "PetscViewerHDF5SetCollective_C", (PetscViewer, PetscBool), (viewer, flg));
3463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
347ee8b9732SVaclav Hapla }
348ee8b9732SVaclav Hapla 
349d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscViewerHDF5GetCollective_HDF5(PetscViewer viewer, PetscBool *flg)
350d71ae5a4SJacob Faibussowitsch {
351c796909eSBarry Smith #if defined(H5_HAVE_PARALLEL)
352ee8b9732SVaclav Hapla   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)viewer->data;
353ee8b9732SVaclav Hapla   H5FD_mpio_xfer_t  mode;
354c796909eSBarry Smith #endif
355ee8b9732SVaclav Hapla 
356ee8b9732SVaclav Hapla   PetscFunctionBegin;
357c796909eSBarry Smith #if !defined(H5_HAVE_PARALLEL)
358c796909eSBarry Smith   *flg = PETSC_FALSE;
359c796909eSBarry Smith #else
360792fecdfSBarry Smith   PetscCallHDF5(H5Pget_dxpl_mpio, (hdf5->dxpl_id, &mode));
361ee8b9732SVaclav Hapla   *flg = (mode == H5FD_MPIO_COLLECTIVE) ? PETSC_TRUE : PETSC_FALSE;
362c796909eSBarry Smith #endif
3633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
364ee8b9732SVaclav Hapla }
365ee8b9732SVaclav Hapla 
366ee8b9732SVaclav Hapla /*@
367ee8b9732SVaclav Hapla   PetscViewerHDF5GetCollective - Return flag whether collective MPI-IO transfer mode is used for HDF5 reads and writes.
368ee8b9732SVaclav Hapla 
369ee8b9732SVaclav Hapla   Not Collective
370ee8b9732SVaclav Hapla 
37120f4b53cSBarry Smith   Input Parameter:
372811af0c4SBarry Smith . viewer - the `PETSCVIEWERHDF5` `PetscViewer`
373ee8b9732SVaclav Hapla 
37420f4b53cSBarry Smith   Output Parameter:
375ee8b9732SVaclav Hapla . flg - the flag
376ee8b9732SVaclav Hapla 
377ee8b9732SVaclav Hapla   Level: intermediate
378ee8b9732SVaclav Hapla 
379811af0c4SBarry Smith   Note:
380811af0c4SBarry 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.
381811af0c4SBarry Smith   For more details, see `PetscViewerHDF5SetCollective()`.
382ee8b9732SVaclav Hapla 
383d1f92df0SBarry Smith .seealso: [](sec_viewers), `PETSCVIEWERHDF5`, `PetscViewerHDF5SetCollective()`, `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerHDF5Open()`
384ee8b9732SVaclav Hapla @*/
385d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerHDF5GetCollective(PetscViewer viewer, PetscBool *flg)
386d71ae5a4SJacob Faibussowitsch {
387ee8b9732SVaclav Hapla   PetscFunctionBegin;
388ee8b9732SVaclav Hapla   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
389534a8f05SLisandro Dalcin   PetscValidBoolPointer(flg, 2);
390ee8b9732SVaclav Hapla 
391cac4c232SBarry Smith   PetscUseMethod(viewer, "PetscViewerHDF5GetCollective_C", (PetscViewer, PetscBool *), (viewer, flg));
3923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
393ee8b9732SVaclav Hapla }
394ee8b9732SVaclav Hapla 
395d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscViewerFileSetName_HDF5(PetscViewer viewer, const char name[])
396d71ae5a4SJacob Faibussowitsch {
3975c6c1daeSBarry Smith   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)viewer->data;
3985c6c1daeSBarry Smith   hid_t             plist_id;
3995c6c1daeSBarry Smith 
4005c6c1daeSBarry Smith   PetscFunctionBegin;
401792fecdfSBarry Smith   if (hdf5->file_id) PetscCallHDF5(H5Fclose, (hdf5->file_id));
4029566063dSJacob Faibussowitsch   if (hdf5->filename) PetscCall(PetscFree(hdf5->filename));
4039566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(name, &hdf5->filename));
4045c6c1daeSBarry Smith   /* Set up file access property list with parallel I/O access */
405792fecdfSBarry Smith   PetscCallHDF5Return(plist_id, H5Pcreate, (H5P_FILE_ACCESS));
406c796909eSBarry Smith #if defined(H5_HAVE_PARALLEL)
407792fecdfSBarry Smith   PetscCallHDF5(H5Pset_fapl_mpio, (plist_id, PetscObjectComm((PetscObject)viewer), MPI_INFO_NULL));
408c796909eSBarry Smith #endif
4095c6c1daeSBarry Smith   /* Create or open the file collectively */
4105c6c1daeSBarry Smith   switch (hdf5->btype) {
4115c6c1daeSBarry Smith   case FILE_MODE_READ:
4128a2871f6SBarry Smith     if (PetscDefined(USE_DEBUG)) {
4138a2871f6SBarry Smith       PetscMPIInt rank;
4148a2871f6SBarry Smith       PetscBool   flg;
4158a2871f6SBarry Smith 
4169566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
4178a2871f6SBarry Smith       if (rank == 0) {
4189566063dSJacob Faibussowitsch         PetscCall(PetscTestFile(hdf5->filename, 'r', &flg));
4195f80ce2aSJacob Faibussowitsch         PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "File %s requested for reading does not exist", hdf5->filename);
4208a2871f6SBarry Smith       }
4219566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Barrier(PetscObjectComm((PetscObject)viewer)));
4228a2871f6SBarry Smith     }
423792fecdfSBarry Smith     PetscCallHDF5Return(hdf5->file_id, H5Fopen, (name, H5F_ACC_RDONLY, plist_id));
4245c6c1daeSBarry Smith     break;
4255c6c1daeSBarry Smith   case FILE_MODE_APPEND:
4269371c9d4SSatish Balay   case FILE_MODE_UPDATE: {
4277e4fd573SVaclav Hapla     PetscBool flg;
4289566063dSJacob Faibussowitsch     PetscCall(PetscTestFile(hdf5->filename, 'r', &flg));
429792fecdfSBarry Smith     if (flg) PetscCallHDF5Return(hdf5->file_id, H5Fopen, (name, H5F_ACC_RDWR, plist_id));
430792fecdfSBarry Smith     else PetscCallHDF5Return(hdf5->file_id, H5Fcreate, (name, H5F_ACC_EXCL, H5P_DEFAULT, plist_id));
4315c6c1daeSBarry Smith     break;
4327e4fd573SVaclav Hapla   }
433d71ae5a4SJacob Faibussowitsch   case FILE_MODE_WRITE:
434d71ae5a4SJacob Faibussowitsch     PetscCallHDF5Return(hdf5->file_id, H5Fcreate, (name, H5F_ACC_TRUNC, H5P_DEFAULT, plist_id));
435d71ae5a4SJacob Faibussowitsch     break;
436d71ae5a4SJacob Faibussowitsch   case FILE_MODE_UNDEFINED:
437d71ae5a4SJacob Faibussowitsch     SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_ORDER, "Must call PetscViewerFileSetMode() before PetscViewerFileSetName()");
438d71ae5a4SJacob Faibussowitsch   default:
439d71ae5a4SJacob Faibussowitsch     SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Unsupported file mode %s", PetscFileModes[hdf5->btype]);
4405c6c1daeSBarry Smith   }
4415f80ce2aSJacob Faibussowitsch   PetscCheck(hdf5->file_id >= 0, PETSC_COMM_SELF, PETSC_ERR_LIB, "H5Fcreate failed for %s", name);
442792fecdfSBarry Smith   PetscCallHDF5(H5Pclose, (plist_id));
443671abe24SVaclav Hapla   PetscCall(PetscViewerHDF5ResetAttachedDMPlexStorageVersion(viewer));
4443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4455c6c1daeSBarry Smith }
4465c6c1daeSBarry Smith 
447d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscViewerFileGetName_HDF5(PetscViewer viewer, const char **name)
448d71ae5a4SJacob Faibussowitsch {
449d1232d7fSToby Isaac   PetscViewer_HDF5 *vhdf5 = (PetscViewer_HDF5 *)viewer->data;
450d1232d7fSToby Isaac 
451d1232d7fSToby Isaac   PetscFunctionBegin;
452d1232d7fSToby Isaac   *name = vhdf5->filename;
4533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
454d1232d7fSToby Isaac }
455d1232d7fSToby Isaac 
456d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscViewerSetUp_HDF5(PetscViewer viewer)
457d71ae5a4SJacob Faibussowitsch {
4585dc64a97SVaclav Hapla   /*
459b723ab35SVaclav Hapla   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;
4605dc64a97SVaclav Hapla   */
461b723ab35SVaclav Hapla 
462b723ab35SVaclav Hapla   PetscFunctionBegin;
4633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
464b723ab35SVaclav Hapla }
465b723ab35SVaclav Hapla 
466d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscViewerHDF5SetDefaultTimestepping_HDF5(PetscViewer viewer, PetscBool flg)
467d71ae5a4SJacob Faibussowitsch {
46819a20e4cSMatthew G. Knepley   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)viewer->data;
46919a20e4cSMatthew G. Knepley 
47019a20e4cSMatthew G. Knepley   PetscFunctionBegin;
47119a20e4cSMatthew G. Knepley   hdf5->defTimestepping = flg;
4723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
47319a20e4cSMatthew G. Knepley }
47419a20e4cSMatthew G. Knepley 
475d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscViewerHDF5GetDefaultTimestepping_HDF5(PetscViewer viewer, PetscBool *flg)
476d71ae5a4SJacob Faibussowitsch {
47719a20e4cSMatthew G. Knepley   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)viewer->data;
47819a20e4cSMatthew G. Knepley 
47919a20e4cSMatthew G. Knepley   PetscFunctionBegin;
48019a20e4cSMatthew G. Knepley   *flg = hdf5->defTimestepping;
4813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
48219a20e4cSMatthew G. Knepley }
48319a20e4cSMatthew G. Knepley 
48419a20e4cSMatthew G. Knepley /*@
48519a20e4cSMatthew G. Knepley   PetscViewerHDF5SetDefaultTimestepping - Set the flag for default timestepping
48619a20e4cSMatthew G. Knepley 
487c3339decSBarry Smith   Logically Collective
48819a20e4cSMatthew G. Knepley 
48919a20e4cSMatthew G. Knepley   Input Parameters:
490811af0c4SBarry Smith + viewer - the `PetscViewer`; if it is not `PETSCVIEWERHDF5` then this command is ignored
491811af0c4SBarry Smith - flg    - if `PETSC_TRUE` we will assume that timestepping is on
49219a20e4cSMatthew G. Knepley 
493811af0c4SBarry Smith   Options Database Key:
49419a20e4cSMatthew G. Knepley . -viewer_hdf5_default_timestepping - turns on (true) or off (false) default timestepping
49519a20e4cSMatthew G. Knepley 
4963f423023SBarry Smith   Level: intermediate
4973f423023SBarry Smith 
498811af0c4SBarry Smith   Note:
49919a20e4cSMatthew G. Knepley   If the timestepping attribute is not found for an object, then the default timestepping is used
50019a20e4cSMatthew G. Knepley 
501d1f92df0SBarry Smith .seealso: [](sec_viewers), `PETSCVIEWERHDF5`, `PetscViewerHDF5GetDefaultTimestepping()`, `PetscViewerHDF5PushTimestepping()`, `PetscViewerHDF5GetTimestep()`
50219a20e4cSMatthew G. Knepley @*/
503d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerHDF5SetDefaultTimestepping(PetscViewer viewer, PetscBool flg)
504d71ae5a4SJacob Faibussowitsch {
50519a20e4cSMatthew G. Knepley   PetscFunctionBegin;
50619a20e4cSMatthew G. Knepley   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
507cac4c232SBarry Smith   PetscTryMethod(viewer, "PetscViewerHDF5SetDefaultTimestepping_C", (PetscViewer, PetscBool), (viewer, flg));
5083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
50919a20e4cSMatthew G. Knepley }
51019a20e4cSMatthew G. Knepley 
51119a20e4cSMatthew G. Knepley /*@
51219a20e4cSMatthew G. Knepley   PetscViewerHDF5GetDefaultTimestepping - Get the flag for default timestepping
51319a20e4cSMatthew G. Knepley 
51420f4b53cSBarry Smith   Not Collective
51519a20e4cSMatthew G. Knepley 
51619a20e4cSMatthew G. Knepley   Input Parameter:
517811af0c4SBarry Smith . viewer - the `PetscViewer` of type `PETSCVIEWERHDF5`
51819a20e4cSMatthew G. Knepley 
51919a20e4cSMatthew G. Knepley   Output Parameter:
520811af0c4SBarry Smith . flg - if `PETSC_TRUE` we will assume that timestepping is on
52119a20e4cSMatthew G. Knepley 
52219a20e4cSMatthew G. Knepley   Level: intermediate
52319a20e4cSMatthew G. Knepley 
524d1f92df0SBarry Smith .seealso: [](sec_viewers), `PETSCVIEWERHDF5`, `PetscViewerHDF5SetDefaultTimestepping()`, `PetscViewerHDF5PushTimestepping()`, `PetscViewerHDF5GetTimestep()`
52519a20e4cSMatthew G. Knepley @*/
526d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerHDF5GetDefaultTimestepping(PetscViewer viewer, PetscBool *flg)
527d71ae5a4SJacob Faibussowitsch {
52819a20e4cSMatthew G. Knepley   PetscFunctionBegin;
52919a20e4cSMatthew G. Knepley   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
530cac4c232SBarry Smith   PetscUseMethod(viewer, "PetscViewerHDF5GetDefaultTimestepping_C", (PetscViewer, PetscBool *), (viewer, flg));
5313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
53219a20e4cSMatthew G. Knepley }
53319a20e4cSMatthew G. Knepley 
5348556b5ebSBarry Smith /*MC
5358556b5ebSBarry Smith    PETSCVIEWERHDF5 - A viewer that writes to an HDF5 file
5368556b5ebSBarry Smith 
537811af0c4SBarry Smith   Level: beginner
538811af0c4SBarry Smith 
539d1f92df0SBarry Smith .seealso: [](sec_viewers), `PetscViewerHDF5Open()`, `PetscViewerStringSPrintf()`, `PetscViewerSocketOpen()`, `PetscViewerDrawOpen()`, `PETSCVIEWERSOCKET`,
540db781477SPatrick Sanan           `PetscViewerCreate()`, `PetscViewerASCIIOpen()`, `PetscViewerBinaryOpen()`, `PETSCVIEWERBINARY`, `PETSCVIEWERDRAW`, `PETSCVIEWERSTRING`,
541db781477SPatrick Sanan           `PetscViewerMatlabOpen()`, `VecView()`, `DMView()`, `PetscViewerMatlabPutArray()`, `PETSCVIEWERASCII`, `PETSCVIEWERMATLAB`,
542db781477SPatrick Sanan           `PetscViewerFileSetName()`, `PetscViewerFileSetMode()`, `PetscViewerFormat`, `PetscViewerType`, `PetscViewerSetType()`
5438556b5ebSBarry Smith M*/
544d1232d7fSToby Isaac 
545d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscViewerCreate_HDF5(PetscViewer v)
546d71ae5a4SJacob Faibussowitsch {
5475c6c1daeSBarry Smith   PetscViewer_HDF5 *hdf5;
5485c6c1daeSBarry Smith 
5495c6c1daeSBarry Smith   PetscFunctionBegin;
55099335c34SVaclav Hapla #if !defined(H5_HAVE_PARALLEL)
55199335c34SVaclav Hapla   {
55299335c34SVaclav Hapla     PetscMPIInt size;
5539566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)v), &size));
5545f80ce2aSJacob 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)");
55599335c34SVaclav Hapla   }
55699335c34SVaclav Hapla #endif
55799335c34SVaclav Hapla 
5584dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&hdf5));
5595c6c1daeSBarry Smith 
5605c6c1daeSBarry Smith   v->data                = (void *)hdf5;
5615c6c1daeSBarry Smith   v->ops->destroy        = PetscViewerDestroy_HDF5;
56282ea9b62SBarry Smith   v->ops->setfromoptions = PetscViewerSetFromOptions_HDF5;
563b723ab35SVaclav Hapla   v->ops->setup          = PetscViewerSetUp_HDF5;
5641b793a25SVaclav Hapla   v->ops->view           = PetscViewerView_HDF5;
5656226335aSVaclav Hapla   v->ops->flush          = PetscViewerFlush_HDF5;
5667e4fd573SVaclav Hapla   hdf5->btype            = FILE_MODE_UNDEFINED;
567908793a3SLisandro Dalcin   hdf5->filename         = NULL;
5685c6c1daeSBarry Smith   hdf5->timestep         = -1;
5690298fd71SBarry Smith   hdf5->groups           = NULL;
5705c6c1daeSBarry Smith 
571792fecdfSBarry Smith   PetscCallHDF5Return(hdf5->dxpl_id, H5Pcreate, (H5P_DATASET_XFER));
5729c5072fbSVaclav Hapla 
5739566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerFileSetName_C", PetscViewerFileSetName_HDF5));
5749566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerFileGetName_C", PetscViewerFileGetName_HDF5));
5759566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerFileSetMode_C", PetscViewerFileSetMode_HDF5));
5769566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerFileGetMode_C", PetscViewerFileGetMode_HDF5));
5779566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerHDF5SetBaseDimension2_C", PetscViewerHDF5SetBaseDimension2_HDF5));
5789566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerHDF5SetSPOutput_C", PetscViewerHDF5SetSPOutput_HDF5));
5799566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerHDF5SetCollective_C", PetscViewerHDF5SetCollective_HDF5));
5809566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerHDF5GetCollective_C", PetscViewerHDF5GetCollective_HDF5));
5819566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerHDF5GetDefaultTimestepping_C", PetscViewerHDF5GetDefaultTimestepping_HDF5));
5829566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerHDF5SetDefaultTimestepping_C", PetscViewerHDF5SetDefaultTimestepping_HDF5));
5833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5845c6c1daeSBarry Smith }
5855c6c1daeSBarry Smith 
5865c6c1daeSBarry Smith /*@C
587811af0c4SBarry Smith   PetscViewerHDF5Open - Opens a file for HDF5 input/output as a `PETSCVIEWERHDF5` `PetscViewer`
5885c6c1daeSBarry Smith 
589d083f849SBarry Smith   Collective
5905c6c1daeSBarry Smith 
5915c6c1daeSBarry Smith   Input Parameters:
5925c6c1daeSBarry Smith + comm - MPI communicator
5935c6c1daeSBarry Smith . name - name of file
5945c6c1daeSBarry Smith - type - type of file
5955c6c1daeSBarry Smith 
5965c6c1daeSBarry Smith   Output Parameter:
597811af0c4SBarry Smith . hdf5v - `PetscViewer` for HDF5 input/output to use with the specified file
5985c6c1daeSBarry Smith 
599811af0c4SBarry Smith   Options Database Keys:
600a2b725a8SWilliam 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
601a2b725a8SWilliam Gropp - -viewer_hdf5_sp_output       - forces (if true) the viewer to write data in single precision independent on the precision of PetscReal
60282ea9b62SBarry Smith 
6035c6c1daeSBarry Smith   Level: beginner
6045c6c1daeSBarry Smith 
6057e4fd573SVaclav Hapla   Notes:
6067e4fd573SVaclav Hapla   Reading is always available, regardless of the mode. Available modes are
607811af0c4SBarry Smith .vb
608811af0c4SBarry Smith   FILE_MODE_READ - open existing HDF5 file for read only access, fail if file does not exist [H5Fopen() with H5F_ACC_RDONLY]
609811af0c4SBarry Smith   FILE_MODE_WRITE - if file exists, fully overwrite it, else create new HDF5 file [H5FcreateH5Fcreate() with H5F_ACC_TRUNC]
610811af0c4SBarry 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]
611811af0c4SBarry Smith   FILE_MODE_UPDATE - same as FILE_MODE_APPEND
612811af0c4SBarry Smith .ve
6137e4fd573SVaclav Hapla 
614da81f932SPierre Jolivet   In case of `FILE_MODE_APPEND` / `FILE_MODE_UPDATE`, any stored object (dataset, attribute) can be selectively overwritten if the same fully qualified name (/group/path/to/object) is specified.
6157e4fd573SVaclav Hapla 
6165c6c1daeSBarry Smith   This PetscViewer should be destroyed with PetscViewerDestroy().
6175c6c1daeSBarry Smith 
618d1f92df0SBarry Smith .seealso: [](sec_viewers), `PETSCVIEWERHDF5`, `PetscViewerASCIIOpen()`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`, `PetscViewerHDF5SetBaseDimension2()`,
619db781477SPatrick Sanan           `PetscViewerHDF5SetSPOutput()`, `PetscViewerHDF5GetBaseDimension2()`, `VecView()`, `MatView()`, `VecLoad()`,
620db781477SPatrick Sanan           `MatLoad()`, `PetscFileMode`, `PetscViewer`, `PetscViewerSetType()`, `PetscViewerFileSetMode()`, `PetscViewerFileSetName()`
6215c6c1daeSBarry Smith @*/
622d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerHDF5Open(MPI_Comm comm, const char name[], PetscFileMode type, PetscViewer *hdf5v)
623d71ae5a4SJacob Faibussowitsch {
6245c6c1daeSBarry Smith   PetscFunctionBegin;
6259566063dSJacob Faibussowitsch   PetscCall(PetscViewerCreate(comm, hdf5v));
6269566063dSJacob Faibussowitsch   PetscCall(PetscViewerSetType(*hdf5v, PETSCVIEWERHDF5));
6279566063dSJacob Faibussowitsch   PetscCall(PetscViewerFileSetMode(*hdf5v, type));
6289566063dSJacob Faibussowitsch   PetscCall(PetscViewerFileSetName(*hdf5v, name));
6299566063dSJacob Faibussowitsch   PetscCall(PetscViewerSetFromOptions(*hdf5v));
6303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6315c6c1daeSBarry Smith }
6325c6c1daeSBarry Smith 
6335c6c1daeSBarry Smith /*@C
6345c6c1daeSBarry Smith   PetscViewerHDF5GetFileId - Retrieve the file id, this file ID then can be used in direct HDF5 calls
6355c6c1daeSBarry Smith 
63620f4b53cSBarry Smith   Not Collective
6375c6c1daeSBarry Smith 
6385c6c1daeSBarry Smith   Input Parameter:
639811af0c4SBarry Smith . viewer - the `PetscViewer`
6405c6c1daeSBarry Smith 
6415c6c1daeSBarry Smith   Output Parameter:
6425c6c1daeSBarry Smith . file_id - The file id
6435c6c1daeSBarry Smith 
6445c6c1daeSBarry Smith   Level: intermediate
6455c6c1daeSBarry Smith 
646d1f92df0SBarry Smith .seealso: [](sec_viewers), `PETSCVIEWERHDF5`, `PetscViewerHDF5Open()`
6475c6c1daeSBarry Smith @*/
648d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerHDF5GetFileId(PetscViewer viewer, hid_t *file_id)
649d71ae5a4SJacob Faibussowitsch {
6505c6c1daeSBarry Smith   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)viewer->data;
6515c6c1daeSBarry Smith 
6525c6c1daeSBarry Smith   PetscFunctionBegin;
6535c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
6545c6c1daeSBarry Smith   if (file_id) *file_id = hdf5->file_id;
6553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6565c6c1daeSBarry Smith }
6575c6c1daeSBarry Smith 
6585c6c1daeSBarry Smith /*@C
6595c6c1daeSBarry Smith   PetscViewerHDF5PushGroup - Set the current HDF5 group for output
6605c6c1daeSBarry Smith 
66120f4b53cSBarry Smith   Not Collective
6625c6c1daeSBarry Smith 
6635c6c1daeSBarry Smith   Input Parameters:
664811af0c4SBarry Smith + viewer - the `PetscViewer` of type `PETSCVIEWERHDF5`
6655c6c1daeSBarry Smith - name   - The group name
6665c6c1daeSBarry Smith 
6675c6c1daeSBarry Smith   Level: intermediate
6685c6c1daeSBarry Smith 
6692e361344SVaclav Hapla   Notes:
6702e361344SVaclav Hapla   This is designed to mnemonically resemble the Unix cd command.
671811af0c4SBarry Smith .vb
672811af0c4SBarry 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.
6733f423023SBarry Smith   `NULL`, empty string, or any sequence of all slashes (e.g. "///") is interpreted as the root group "/".
674811af0c4SBarry Smith   "." means the current group is pushed again.
675811af0c4SBarry Smith .ve
6762e361344SVaclav Hapla 
6772e361344SVaclav Hapla   Example:
6782e361344SVaclav Hapla   Suppose the current group is "/a".
6793f423023SBarry Smith .vb
6803f423023SBarry Smith   If name is `NULL`, empty string, or a sequence of all slashes (e.g. "///"), then the new group will be "/".
6813f423023SBarry Smith   If name is ".", then the new group will be "/a".
6823f423023SBarry Smith   If name is "b", then the new group will be "/a/b".
6833f423023SBarry Smith   If name is "/b", then the new group will be "/b".
6843f423023SBarry Smith .ve
6852e361344SVaclav Hapla 
686aec76313SJacob Faibussowitsch   Developer Notes:
6873f423023SBarry Smith   The root group "/" is internally stored as `NULL`.
688820fc2d1SVaclav Hapla 
689d1f92df0SBarry Smith .seealso: [](sec_viewers), `PETSCVIEWERHDF5`, `PetscViewerHDF5Open()`, `PetscViewerHDF5PopGroup()`, `PetscViewerHDF5GetGroup()`, `PetscViewerHDF5OpenGroup()`, `PetscViewerHDF5WriteGroup()`
6905c6c1daeSBarry Smith @*/
691d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerHDF5PushGroup(PetscViewer viewer, const char name[])
692d71ae5a4SJacob Faibussowitsch {
6935c6c1daeSBarry Smith   PetscViewer_HDF5         *hdf5 = (PetscViewer_HDF5 *)viewer->data;
6947d964842SVaclav Hapla   PetscViewerHDF5GroupList *groupNode;
6952e361344SVaclav Hapla   size_t                    i, len;
6962e361344SVaclav Hapla   char                      buf[PETSC_MAX_PATH_LEN];
6972e361344SVaclav Hapla   const char               *gname;
6985c6c1daeSBarry Smith 
6995c6c1daeSBarry Smith   PetscFunctionBegin;
7005c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
701820fc2d1SVaclav Hapla   if (name) PetscValidCharPointer(name, 2);
7029566063dSJacob Faibussowitsch   PetscCall(PetscStrlen(name, &len));
7032e361344SVaclav Hapla   gname = NULL;
7042e361344SVaclav Hapla   if (len) {
7052e361344SVaclav Hapla     if (len == 1 && name[0] == '.') {
7062e361344SVaclav Hapla       /* use current name */
7072e361344SVaclav Hapla       gname = (hdf5->groups && hdf5->groups->name) ? hdf5->groups->name : NULL;
7082e361344SVaclav Hapla     } else if (name[0] == '/') {
7092e361344SVaclav Hapla       /* absolute */
7102e361344SVaclav Hapla       for (i = 1; i < len; i++) {
7112e361344SVaclav Hapla         if (name[i] != '/') {
7122e361344SVaclav Hapla           gname = name;
7132e361344SVaclav Hapla           break;
7142e361344SVaclav Hapla         }
7152e361344SVaclav Hapla       }
7162e361344SVaclav Hapla     } else {
7172e361344SVaclav Hapla       /* relative */
7182e361344SVaclav Hapla       const char *parent = (hdf5->groups && hdf5->groups->name) ? hdf5->groups->name : "";
7199566063dSJacob Faibussowitsch       PetscCall(PetscSNPrintf(buf, sizeof(buf), "%s/%s", parent, name));
7202e361344SVaclav Hapla       gname = buf;
7212e361344SVaclav Hapla     }
7222e361344SVaclav Hapla   }
7239566063dSJacob Faibussowitsch   PetscCall(PetscNew(&groupNode));
7249566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(gname, (char **)&groupNode->name));
7255c6c1daeSBarry Smith   groupNode->next = hdf5->groups;
7265c6c1daeSBarry Smith   hdf5->groups    = groupNode;
7273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7285c6c1daeSBarry Smith }
7295c6c1daeSBarry Smith 
7303ef9c667SSatish Balay /*@
7315c6c1daeSBarry Smith   PetscViewerHDF5PopGroup - Return the current HDF5 group for output to the previous value
7325c6c1daeSBarry Smith 
73320f4b53cSBarry Smith   Not Collective
7345c6c1daeSBarry Smith 
7355c6c1daeSBarry Smith   Input Parameter:
736811af0c4SBarry Smith . viewer - the `PetscViewer` of type `PETSCVIEWERHDF5`
7375c6c1daeSBarry Smith 
7385c6c1daeSBarry Smith   Level: intermediate
7395c6c1daeSBarry Smith 
740d1f92df0SBarry Smith .seealso: [](sec_viewers), `PETSCVIEWERHDF5`, `PetscViewerHDF5Open()`, `PetscViewerHDF5PushGroup()`, `PetscViewerHDF5GetGroup()`, `PetscViewerHDF5OpenGroup()`, `PetscViewerHDF5WriteGroup()`
7415c6c1daeSBarry Smith @*/
742d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerHDF5PopGroup(PetscViewer viewer)
743d71ae5a4SJacob Faibussowitsch {
7445c6c1daeSBarry Smith   PetscViewer_HDF5         *hdf5 = (PetscViewer_HDF5 *)viewer->data;
7457d964842SVaclav Hapla   PetscViewerHDF5GroupList *groupNode;
7465c6c1daeSBarry Smith 
7475c6c1daeSBarry Smith   PetscFunctionBegin;
7485c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
7495f80ce2aSJacob Faibussowitsch   PetscCheck(hdf5->groups, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "HDF5 group stack is empty, cannot pop");
7505c6c1daeSBarry Smith   groupNode    = hdf5->groups;
7515c6c1daeSBarry Smith   hdf5->groups = hdf5->groups->next;
7529566063dSJacob Faibussowitsch   PetscCall(PetscFree(groupNode->name));
7539566063dSJacob Faibussowitsch   PetscCall(PetscFree(groupNode));
7543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7555c6c1daeSBarry Smith }
7565c6c1daeSBarry Smith 
757d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerHDF5GetGroup_Internal(PetscViewer viewer, const char *name[])
758d71ae5a4SJacob Faibussowitsch {
7595c6c1daeSBarry Smith   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)viewer->data;
7605c6c1daeSBarry Smith 
7615c6c1daeSBarry Smith   PetscFunctionBegin;
7625c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
763c959eef4SJed Brown   PetscValidPointer(name, 2);
764a297a907SKarl Rupp   if (hdf5->groups) *name = hdf5->groups->name;
7650298fd71SBarry Smith   else *name = NULL;
7663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7675c6c1daeSBarry Smith }
7685c6c1daeSBarry Smith 
7693014b61aSVaclav Hapla /*@C
770811af0c4SBarry Smith   PetscViewerHDF5OpenGroup - Open the HDF5 group with the name (full path) returned by `PetscViewerHDF5GetGroup()`,
771874270d9SVaclav Hapla   and return this group's ID and file ID.
772811af0c4SBarry Smith   If `PetscViewerHDF5GetGroup()` yields NULL, then group ID is file ID.
773874270d9SVaclav Hapla 
77420f4b53cSBarry Smith   Not Collective
775874270d9SVaclav Hapla 
7763014b61aSVaclav Hapla   Input Parameters:
7773014b61aSVaclav Hapla + viewer - the `PetscViewer` of type `PETSCVIEWERHDF5`
7783014b61aSVaclav Hapla - path   - (Optional) The path relative to the pushed group
779874270d9SVaclav Hapla 
780d8d19677SJose E. Roman   Output Parameters:
781874270d9SVaclav Hapla + fileId  - The HDF5 file ID
782874270d9SVaclav Hapla - groupId - The HDF5 group ID
783874270d9SVaclav Hapla 
7843f423023SBarry Smith   Level: intermediate
7853f423023SBarry Smith 
786811af0c4SBarry Smith   Note:
7873014b61aSVaclav 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.
7883f423023SBarry Smith   `NULL` or empty path means the current pushed group.
7893014b61aSVaclav Hapla 
790e74616beSVaclav Hapla   If the viewer is writable, the group is created if it doesn't exist yet.
791e74616beSVaclav Hapla 
792d1f92df0SBarry Smith .seealso: [](sec_viewers), `PETSCVIEWERHDF5`, `PetscViewerHDF5Open()`, `PetscViewerHDF5PushGroup()`, `PetscViewerHDF5PopGroup()`, `PetscViewerHDF5GetGroup()`, `PetscViewerHDF5WriteGroup()`
793874270d9SVaclav Hapla @*/
794d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerHDF5OpenGroup(PetscViewer viewer, const char path[], hid_t *fileId, hid_t *groupId)
795d71ae5a4SJacob Faibussowitsch {
79690e03537SVaclav Hapla   hid_t       file_id;
79790e03537SVaclav Hapla   H5O_type_t  type;
7983014b61aSVaclav Hapla   const char *fileName  = NULL;
7993014b61aSVaclav Hapla   char       *groupName = NULL;
80076d59af2SVaclav Hapla   PetscBool   writable, has;
80154dbf706SVaclav Hapla 
80254dbf706SVaclav Hapla   PetscFunctionBegin;
8039566063dSJacob Faibussowitsch   PetscCall(PetscViewerWritable(viewer, &writable));
8049566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5GetFileId(viewer, &file_id));
8059566063dSJacob Faibussowitsch   PetscCall(PetscViewerFileGetName(viewer, &fileName));
8063014b61aSVaclav Hapla   PetscCall(PetscViewerHDF5GetGroup(viewer, path, &groupName));
8079566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5Traverse_Internal(viewer, groupName, writable, &has, &type));
80876d59af2SVaclav Hapla   if (!has) {
8095f80ce2aSJacob 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);
810f7d195e4SLawrence Mitchell     SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_LIB, "HDF5 failed to create group %s although file %s is open for writing", groupName, fileName);
81176d59af2SVaclav Hapla   }
8125f80ce2aSJacob 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);
8133014b61aSVaclav Hapla   PetscCallHDF5Return(*groupId, H5Gopen2, (file_id, groupName, H5P_DEFAULT));
8143014b61aSVaclav Hapla   PetscCall(PetscFree(groupName));
81554dbf706SVaclav Hapla   *fileId = file_id;
8163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
81754dbf706SVaclav Hapla }
81854dbf706SVaclav Hapla 
81963cb69f5SVaclav Hapla /*@C
82063cb69f5SVaclav Hapla   PetscViewerHDF5WriteGroup - Ensure the HDF5 group exists in the HDF5 file
82163cb69f5SVaclav Hapla 
82220f4b53cSBarry Smith   Not Collective
82363cb69f5SVaclav Hapla 
82463cb69f5SVaclav Hapla   Input Parameters:
82563cb69f5SVaclav Hapla + viewer - the `PetscViewer` of type `PETSCVIEWERHDF5`
82663cb69f5SVaclav Hapla - path   - (Optional) The path relative to the pushed group
82763cb69f5SVaclav Hapla 
8283f423023SBarry Smith   Level: intermediate
8293f423023SBarry Smith 
83063cb69f5SVaclav Hapla   Note:
83163cb69f5SVaclav 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.
8323f423023SBarry Smith   `NULL` or empty path means the current pushed group.
83363cb69f5SVaclav Hapla 
83463cb69f5SVaclav Hapla   This will fail if the viewer is not writable.
83563cb69f5SVaclav Hapla 
836d1f92df0SBarry Smith .seealso: [](sec_viewers), `PETSCVIEWERHDF5`, `PetscViewerHDF5Open()`, `PetscViewerHDF5PushGroup()`, `PetscViewerHDF5PopGroup()`, `PetscViewerHDF5GetGroup()`, `PetscViewerHDF5OpenGroup()`
83763cb69f5SVaclav Hapla @*/
838d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerHDF5WriteGroup(PetscViewer viewer, const char path[])
839d71ae5a4SJacob Faibussowitsch {
84063cb69f5SVaclav Hapla   hid_t fileId, groupId;
84163cb69f5SVaclav Hapla 
84263cb69f5SVaclav Hapla   PetscFunctionBegin;
84363cb69f5SVaclav Hapla   PetscCall(PetscViewerHDF5OpenGroup(viewer, path, &fileId, &groupId)); // make sure group is actually created
84463cb69f5SVaclav Hapla   PetscCallHDF5(H5Gclose, (groupId));
8453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
84663cb69f5SVaclav Hapla }
84763cb69f5SVaclav Hapla 
8483ef9c667SSatish Balay /*@
849d7dd068bSVaclav Hapla   PetscViewerHDF5PushTimestepping - Activate timestepping mode for subsequent HDF5 reading and writing.
8505c6c1daeSBarry Smith 
85120f4b53cSBarry Smith   Not Collective
8525c6c1daeSBarry Smith 
8535c6c1daeSBarry Smith   Input Parameter:
854811af0c4SBarry Smith . viewer - the `PetscViewer` of type `PETSCVIEWERHDF5`
8555c6c1daeSBarry Smith 
8565c6c1daeSBarry Smith   Level: intermediate
8575c6c1daeSBarry Smith 
858d7dd068bSVaclav Hapla   Notes:
859811af0c4SBarry Smith   On first `PetscViewerHDF5PushTimestepping()`, the initial time step is set to 0.
860811af0c4SBarry Smith   Next timesteps can then be set using `PetscViewerHDF5IncrementTimestep()` or `PetscViewerHDF5SetTimestep()`.
861811af0c4SBarry 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()`].
862811af0c4SBarry Smith   Use `PetscViewerHDF5PopTimestepping()` to deactivate timestepping mode; calling it by the end of the program is NOT mandatory.
863811af0c4SBarry Smith   Current timestep is remembered between `PetscViewerHDF5PopTimestepping()` and the next `PetscViewerHDF5PushTimestepping()`.
864d7dd068bSVaclav Hapla 
865d7dd068bSVaclav Hapla   If a dataset was stored with timestepping, it can be loaded only in the timestepping mode again.
866d7dd068bSVaclav Hapla   Loading a timestepped dataset with timestepping disabled, or vice-versa results in an error.
867d7dd068bSVaclav Hapla 
868aec76313SJacob Faibussowitsch   Developer Notes:
869d7dd068bSVaclav Hapla   Timestepped HDF5 dataset has an extra dimension and attribute "timestepping" set to true.
870d7dd068bSVaclav Hapla 
871d1f92df0SBarry Smith .seealso: [](sec_viewers), `PETSCVIEWERHDF5`, `PetscViewerHDF5Open()`, `PetscViewerHDF5PopTimestepping()`, `PetscViewerHDF5IsTimestepping()`, `PetscViewerHDF5SetTimestep()`, `PetscViewerHDF5IncrementTimestep()`, `PetscViewerHDF5GetTimestep()`
872d7dd068bSVaclav Hapla @*/
873d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerHDF5PushTimestepping(PetscViewer viewer)
874d71ae5a4SJacob Faibussowitsch {
875d7dd068bSVaclav Hapla   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)viewer->data;
876d7dd068bSVaclav Hapla 
877d7dd068bSVaclav Hapla   PetscFunctionBegin;
878d7dd068bSVaclav Hapla   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
8795f80ce2aSJacob Faibussowitsch   PetscCheck(!hdf5->timestepping, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Timestepping is already pushed");
880d7dd068bSVaclav Hapla   hdf5->timestepping = PETSC_TRUE;
881d7dd068bSVaclav Hapla   if (hdf5->timestep < 0) hdf5->timestep = 0;
8823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
883d7dd068bSVaclav Hapla }
884d7dd068bSVaclav Hapla 
885d7dd068bSVaclav Hapla /*@
886d7dd068bSVaclav Hapla   PetscViewerHDF5PopTimestepping - Deactivate timestepping mode for subsequent HDF5 reading and writing.
887d7dd068bSVaclav Hapla 
88820f4b53cSBarry Smith   Not Collective
889d7dd068bSVaclav Hapla 
890d7dd068bSVaclav Hapla   Input Parameter:
891811af0c4SBarry Smith . viewer - the `PetscViewer` of type `PETSCVIEWERHDF5`
892d7dd068bSVaclav Hapla 
893d7dd068bSVaclav Hapla   Level: intermediate
894d7dd068bSVaclav Hapla 
895811af0c4SBarry Smith   Note:
896811af0c4SBarry Smith   See `PetscViewerHDF5PushTimestepping()` for details.
897d7dd068bSVaclav Hapla 
898d1f92df0SBarry Smith .seealso: [](sec_viewers), `PETSCVIEWERHDF5`, `PetscViewerHDF5Open()`, `PetscViewerHDF5PushTimestepping()`, `PetscViewerHDF5IsTimestepping()`, `PetscViewerHDF5SetTimestep()`, `PetscViewerHDF5IncrementTimestep()`, `PetscViewerHDF5GetTimestep()`
899d7dd068bSVaclav Hapla @*/
900d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerHDF5PopTimestepping(PetscViewer viewer)
901d71ae5a4SJacob Faibussowitsch {
902d7dd068bSVaclav Hapla   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)viewer->data;
903d7dd068bSVaclav Hapla 
904d7dd068bSVaclav Hapla   PetscFunctionBegin;
905d7dd068bSVaclav Hapla   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
9065f80ce2aSJacob Faibussowitsch   PetscCheck(hdf5->timestepping, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Timestepping has not been pushed yet. Call PetscViewerHDF5PushTimestepping() first");
907d7dd068bSVaclav Hapla   hdf5->timestepping = PETSC_FALSE;
9083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
909d7dd068bSVaclav Hapla }
910d7dd068bSVaclav Hapla 
911d7dd068bSVaclav Hapla /*@
912d7dd068bSVaclav Hapla   PetscViewerHDF5IsTimestepping - Ask the viewer whether it is in timestepping mode currently.
913d7dd068bSVaclav Hapla 
91420f4b53cSBarry Smith   Not Collective
915d7dd068bSVaclav Hapla 
916d7dd068bSVaclav Hapla   Input Parameter:
917811af0c4SBarry Smith . viewer - the `PetscViewer` of type `PETSCVIEWERHDF5`
918d7dd068bSVaclav Hapla 
919d7dd068bSVaclav Hapla   Output Parameter:
920d7dd068bSVaclav Hapla . flg - is timestepping active?
921d7dd068bSVaclav Hapla 
922d7dd068bSVaclav Hapla   Level: intermediate
923d7dd068bSVaclav Hapla 
924811af0c4SBarry Smith   Note:
925811af0c4SBarry Smith   See `PetscViewerHDF5PushTimestepping()` for details.
926d7dd068bSVaclav Hapla 
927d1f92df0SBarry Smith .seealso: [](sec_viewers), `PETSCVIEWERHDF5`, `PetscViewerHDF5Open()`, `PetscViewerHDF5PushTimestepping()`, `PetscViewerHDF5PopTimestepping()`, `PetscViewerHDF5SetTimestep()`, `PetscViewerHDF5IncrementTimestep()`, `PetscViewerHDF5GetTimestep()`
928d7dd068bSVaclav Hapla @*/
929d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerHDF5IsTimestepping(PetscViewer viewer, PetscBool *flg)
930d71ae5a4SJacob Faibussowitsch {
931d7dd068bSVaclav Hapla   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)viewer->data;
932d7dd068bSVaclav Hapla 
933d7dd068bSVaclav Hapla   PetscFunctionBegin;
934d7dd068bSVaclav Hapla   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
935d7dd068bSVaclav Hapla   *flg = hdf5->timestepping;
9363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
937d7dd068bSVaclav Hapla }
938d7dd068bSVaclav Hapla 
939d7dd068bSVaclav Hapla /*@
940d7dd068bSVaclav Hapla   PetscViewerHDF5IncrementTimestep - Increments current timestep for the HDF5 output. Fields are stacked in time.
941d7dd068bSVaclav Hapla 
94220f4b53cSBarry Smith   Not Collective
943d7dd068bSVaclav Hapla 
944d7dd068bSVaclav Hapla   Input Parameter:
945811af0c4SBarry Smith . viewer - the `PetscViewer` of type `PETSCVIEWERHDF5`
946d7dd068bSVaclav Hapla 
947d7dd068bSVaclav Hapla   Level: intermediate
948d7dd068bSVaclav Hapla 
949811af0c4SBarry Smith   Note:
950811af0c4SBarry Smith   This can be called only if the viewer is in timestepping mode. See `PetscViewerHDF5PushTimestepping()` for details.
951d7dd068bSVaclav Hapla 
952d1f92df0SBarry Smith .seealso: [](sec_viewers), `PETSCVIEWERHDF5`, `PetscViewerHDF5Open()`, `PetscViewerHDF5PushTimestepping()`, `PetscViewerHDF5SetTimestep()`, `PetscViewerHDF5GetTimestep()`
9535c6c1daeSBarry Smith @*/
954d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerHDF5IncrementTimestep(PetscViewer viewer)
955d71ae5a4SJacob Faibussowitsch {
9565c6c1daeSBarry Smith   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)viewer->data;
9575c6c1daeSBarry Smith 
9585c6c1daeSBarry Smith   PetscFunctionBegin;
9595c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
9605f80ce2aSJacob Faibussowitsch   PetscCheck(hdf5->timestepping, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Timestepping has not been pushed yet. Call PetscViewerHDF5PushTimestepping() first");
9615c6c1daeSBarry Smith   ++hdf5->timestep;
9623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9635c6c1daeSBarry Smith }
9645c6c1daeSBarry Smith 
9653ef9c667SSatish Balay /*@
966d7dd068bSVaclav Hapla   PetscViewerHDF5SetTimestep - Set the current timestep for the HDF5 output. Fields are stacked in time.
9675c6c1daeSBarry Smith 
96820f4b53cSBarry Smith   Logically Collective
9695c6c1daeSBarry Smith 
9705c6c1daeSBarry Smith   Input Parameters:
971811af0c4SBarry Smith + viewer   - the `PetscViewer` of type `PETSCVIEWERHDF5`
972d7dd068bSVaclav Hapla - timestep - The timestep
9735c6c1daeSBarry Smith 
9745c6c1daeSBarry Smith   Level: intermediate
9755c6c1daeSBarry Smith 
976811af0c4SBarry Smith   Note:
977811af0c4SBarry Smith   This can be called only if the viewer is in timestepping mode. See `PetscViewerHDF5PushTimestepping()` for details.
978d7dd068bSVaclav Hapla 
979d1f92df0SBarry Smith .seealso: [](sec_viewers), `PETSCVIEWERHDF5`, `PetscViewerHDF5Open()`, `PetscViewerHDF5PushTimestepping()`, `PetscViewerHDF5IncrementTimestep()`, `PetscViewerHDF5GetTimestep()`
9805c6c1daeSBarry Smith @*/
981d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerHDF5SetTimestep(PetscViewer viewer, PetscInt timestep)
982d71ae5a4SJacob Faibussowitsch {
9835c6c1daeSBarry Smith   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)viewer->data;
9845c6c1daeSBarry Smith 
9855c6c1daeSBarry Smith   PetscFunctionBegin;
9865c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
987d7dd068bSVaclav Hapla   PetscValidLogicalCollectiveInt(viewer, timestep, 2);
9885f80ce2aSJacob Faibussowitsch   PetscCheck(timestep >= 0, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Timestep %" PetscInt_FMT " is negative", timestep);
9895f80ce2aSJacob Faibussowitsch   PetscCheck(hdf5->timestepping, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Timestepping has not been pushed yet. Call PetscViewerHDF5PushTimestepping() first");
9905c6c1daeSBarry Smith   hdf5->timestep = timestep;
9913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9925c6c1daeSBarry Smith }
9935c6c1daeSBarry Smith 
9943ef9c667SSatish Balay /*@
9955c6c1daeSBarry Smith   PetscViewerHDF5GetTimestep - Get the current timestep for the HDF5 output. Fields are stacked in time.
9965c6c1daeSBarry Smith 
99720f4b53cSBarry Smith   Not Collective
9985c6c1daeSBarry Smith 
9995c6c1daeSBarry Smith   Input Parameter:
1000811af0c4SBarry Smith . viewer - the `PetscViewer` of type `PETSCVIEWERHDF5`
10015c6c1daeSBarry Smith 
10025c6c1daeSBarry Smith   Output Parameter:
1003d7dd068bSVaclav Hapla . timestep - The timestep
10045c6c1daeSBarry Smith 
10055c6c1daeSBarry Smith   Level: intermediate
10065c6c1daeSBarry Smith 
1007811af0c4SBarry Smith   Note:
1008811af0c4SBarry Smith   This can be called only if the viewer is in the timestepping mode. See `PetscViewerHDF5PushTimestepping()` for details.
1009d7dd068bSVaclav Hapla 
1010d1f92df0SBarry Smith .seealso: [](sec_viewers), `PETSCVIEWERHDF5`, `PetscViewerHDF5Open()`, `PetscViewerHDF5PushTimestepping()`, `PetscViewerHDF5IncrementTimestep()`, `PetscViewerHDF5SetTimestep()`
10115c6c1daeSBarry Smith @*/
1012d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerHDF5GetTimestep(PetscViewer viewer, PetscInt *timestep)
1013d71ae5a4SJacob Faibussowitsch {
10145c6c1daeSBarry Smith   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *)viewer->data;
10155c6c1daeSBarry Smith 
10165c6c1daeSBarry Smith   PetscFunctionBegin;
10175c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
1018d7dd068bSVaclav Hapla   PetscValidIntPointer(timestep, 2);
10195f80ce2aSJacob Faibussowitsch   PetscCheck(hdf5->timestepping, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Timestepping has not been pushed yet. Call PetscViewerHDF5PushTimestepping() first");
10205c6c1daeSBarry Smith   *timestep = hdf5->timestep;
10213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10225c6c1daeSBarry Smith }
10235c6c1daeSBarry Smith 
102436bce6e8SMatthew G. Knepley /*@C
102536bce6e8SMatthew G. Knepley   PetscDataTypeToHDF5DataType - Converts the PETSc name of a datatype to its HDF5 name.
102636bce6e8SMatthew G. Knepley 
102720f4b53cSBarry Smith   Not Collective
102836bce6e8SMatthew G. Knepley 
102936bce6e8SMatthew G. Knepley   Input Parameter:
1030811af0c4SBarry Smith . ptype - the PETSc datatype name (for example `PETSC_DOUBLE`)
103136bce6e8SMatthew G. Knepley 
103236bce6e8SMatthew G. Knepley   Output Parameter:
1033aec76313SJacob Faibussowitsch . htype - the HDF5  datatype
103436bce6e8SMatthew G. Knepley 
103536bce6e8SMatthew G. Knepley   Level: advanced
103636bce6e8SMatthew G. Knepley 
1037d1f92df0SBarry Smith .seealso: [](sec_viewers), `PetscDataType`, `PetscHDF5DataTypeToPetscDataType()`
103836bce6e8SMatthew G. Knepley @*/
1039d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDataTypeToHDF5DataType(PetscDataType ptype, hid_t *htype)
1040d71ae5a4SJacob Faibussowitsch {
104136bce6e8SMatthew G. Knepley   PetscFunctionBegin;
104236bce6e8SMatthew G. Knepley   if (ptype == PETSC_INT)
104336bce6e8SMatthew G. Knepley #if defined(PETSC_USE_64BIT_INDICES)
104436bce6e8SMatthew G. Knepley     *htype = H5T_NATIVE_LLONG;
104536bce6e8SMatthew G. Knepley #else
104636bce6e8SMatthew G. Knepley     *htype = H5T_NATIVE_INT;
104736bce6e8SMatthew G. Knepley #endif
104836bce6e8SMatthew G. Knepley   else if (ptype == PETSC_DOUBLE) *htype = H5T_NATIVE_DOUBLE;
104936bce6e8SMatthew G. Knepley   else if (ptype == PETSC_LONG) *htype = H5T_NATIVE_LONG;
105036bce6e8SMatthew G. Knepley   else if (ptype == PETSC_SHORT) *htype = H5T_NATIVE_SHORT;
1051c9450970SBarry Smith   else if (ptype == PETSC_ENUM) *htype = H5T_NATIVE_INT;
1052de3ba262SVaclav Hapla   else if (ptype == PETSC_BOOL) *htype = H5T_NATIVE_INT;
105336bce6e8SMatthew G. Knepley   else if (ptype == PETSC_FLOAT) *htype = H5T_NATIVE_FLOAT;
105436bce6e8SMatthew G. Knepley   else if (ptype == PETSC_CHAR) *htype = H5T_NATIVE_CHAR;
105536bce6e8SMatthew G. Knepley   else if (ptype == PETSC_BIT_LOGICAL) *htype = H5T_NATIVE_UCHAR;
10567e97c476SMatthew G. Knepley   else if (ptype == PETSC_STRING) *htype = H5Tcopy(H5T_C_S1);
105736bce6e8SMatthew G. Knepley   else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Unsupported PETSc datatype");
10583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
105936bce6e8SMatthew G. Knepley }
106036bce6e8SMatthew G. Knepley 
106136bce6e8SMatthew G. Knepley /*@C
106236bce6e8SMatthew G. Knepley   PetscHDF5DataTypeToPetscDataType - Finds the PETSc name of a datatype from its HDF5 name
106336bce6e8SMatthew G. Knepley 
106420f4b53cSBarry Smith   Not Collective
106536bce6e8SMatthew G. Knepley 
106636bce6e8SMatthew G. Knepley   Input Parameter:
1067811af0c4SBarry Smith . htype - the HDF5 datatype (for example `H5T_NATIVE_DOUBLE`, ...)
106836bce6e8SMatthew G. Knepley 
106936bce6e8SMatthew G. Knepley   Output Parameter:
1070811af0c4SBarry Smith . ptype - the PETSc datatype name (for example `PETSC_DOUBLE`)
107136bce6e8SMatthew G. Knepley 
107236bce6e8SMatthew G. Knepley   Level: advanced
107336bce6e8SMatthew G. Knepley 
1074d1f92df0SBarry Smith .seealso: [](sec_viewers), `PetscDataType`, `PetscHDF5DataTypeToPetscDataType()`
107536bce6e8SMatthew G. Knepley @*/
1076d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscHDF5DataTypeToPetscDataType(hid_t htype, PetscDataType *ptype)
1077d71ae5a4SJacob Faibussowitsch {
107836bce6e8SMatthew G. Knepley   PetscFunctionBegin;
107936bce6e8SMatthew G. Knepley #if defined(PETSC_USE_64BIT_INDICES)
108036bce6e8SMatthew G. Knepley   if (htype == H5T_NATIVE_INT) *ptype = PETSC_LONG;
108136bce6e8SMatthew G. Knepley   else if (htype == H5T_NATIVE_LLONG) *ptype = PETSC_INT;
108236bce6e8SMatthew G. Knepley #else
108336bce6e8SMatthew G. Knepley   if (htype == H5T_NATIVE_INT) *ptype = PETSC_INT;
108436bce6e8SMatthew G. Knepley #endif
108536bce6e8SMatthew G. Knepley   else if (htype == H5T_NATIVE_DOUBLE) *ptype = PETSC_DOUBLE;
108636bce6e8SMatthew G. Knepley   else if (htype == H5T_NATIVE_LONG) *ptype = PETSC_LONG;
108736bce6e8SMatthew G. Knepley   else if (htype == H5T_NATIVE_SHORT) *ptype = PETSC_SHORT;
108836bce6e8SMatthew G. Knepley   else if (htype == H5T_NATIVE_FLOAT) *ptype = PETSC_FLOAT;
108936bce6e8SMatthew G. Knepley   else if (htype == H5T_NATIVE_CHAR) *ptype = PETSC_CHAR;
109036bce6e8SMatthew G. Knepley   else if (htype == H5T_NATIVE_UCHAR) *ptype = PETSC_CHAR;
10917e97c476SMatthew G. Knepley   else if (htype == H5T_C_S1) *ptype = PETSC_STRING;
109236bce6e8SMatthew G. Knepley   else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Unsupported HDF5 datatype");
10933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
109436bce6e8SMatthew G. Knepley }
109536bce6e8SMatthew G. Knepley 
1096df863907SAlex Fikl /*@C
1097b8ee85a1SVaclav Hapla   PetscViewerHDF5WriteAttribute - Write an attribute
109836bce6e8SMatthew G. Knepley 
1099343a20b2SVaclav Hapla   Collective
1100343a20b2SVaclav Hapla 
110136bce6e8SMatthew G. Knepley   Input Parameters:
1102811af0c4SBarry Smith + viewer   - The `PETSCVIEWERHDF5` viewer
11034302210dSVaclav Hapla . parent   - The parent dataset/group name
110436bce6e8SMatthew G. Knepley . name     - The attribute name
110536bce6e8SMatthew G. Knepley . datatype - The attribute type
110636bce6e8SMatthew G. Knepley - value    - The attribute value
110736bce6e8SMatthew G. Knepley 
110836bce6e8SMatthew G. Knepley   Level: advanced
110936bce6e8SMatthew G. Knepley 
1110811af0c4SBarry Smith   Note:
1111343a20b2SVaclav 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.
11124302210dSVaclav Hapla 
1113d1f92df0SBarry Smith .seealso: [](sec_viewers), `PETSCVIEWERHDF5`, `PetscViewerHDF5Open()`, `PetscViewerHDF5WriteObjectAttribute()`, `PetscViewerHDF5ReadAttribute()`, `PetscViewerHDF5HasAttribute()`,
1114811af0c4SBarry Smith           `PetscViewerHDF5PushGroup()`, `PetscViewerHDF5PopGroup()`, `PetscViewerHDF5GetGroup()`
111536bce6e8SMatthew G. Knepley @*/
1116d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerHDF5WriteAttribute(PetscViewer viewer, const char parent[], const char name[], PetscDataType datatype, const void *value)
1117d71ae5a4SJacob Faibussowitsch {
11184302210dSVaclav Hapla   char     *parentAbsPath;
111960568592SMatthew G. Knepley   hid_t     h5, dataspace, obj, attribute, dtype;
1120080f144cSVaclav Hapla   PetscBool has;
112136bce6e8SMatthew G. Knepley 
112236bce6e8SMatthew G. Knepley   PetscFunctionBegin;
11235cdeb108SMatthew G. Knepley   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
11244302210dSVaclav Hapla   if (parent) PetscValidCharPointer(parent, 2);
1125c57a1a9aSVaclav Hapla   PetscValidCharPointer(name, 3);
11264302210dSVaclav Hapla   PetscValidLogicalCollectiveEnum(viewer, datatype, 4);
1127b7e81f0fSVaclav Hapla   PetscValidPointer(value, 5);
112877717648SVaclav Hapla   PetscCall(PetscViewerHDF5GetGroup(viewer, parent, &parentAbsPath));
11299566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5Traverse_Internal(viewer, parentAbsPath, PETSC_TRUE, NULL, NULL));
11309566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5HasAttribute_Internal(viewer, parentAbsPath, name, &has));
11319566063dSJacob Faibussowitsch   PetscCall(PetscDataTypeToHDF5DataType(datatype, &dtype));
11327e97c476SMatthew G. Knepley   if (datatype == PETSC_STRING) {
11337e97c476SMatthew G. Knepley     size_t len;
11349566063dSJacob Faibussowitsch     PetscCall(PetscStrlen((const char *)value, &len));
1135792fecdfSBarry Smith     PetscCallHDF5(H5Tset_size, (dtype, len + 1));
11367e97c476SMatthew G. Knepley   }
11379566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5GetFileId(viewer, &h5));
1138792fecdfSBarry Smith   PetscCallHDF5Return(dataspace, H5Screate, (H5S_SCALAR));
1139792fecdfSBarry Smith   PetscCallHDF5Return(obj, H5Oopen, (h5, parentAbsPath, H5P_DEFAULT));
1140080f144cSVaclav Hapla   if (has) {
1141792fecdfSBarry Smith     PetscCallHDF5Return(attribute, H5Aopen_name, (obj, name));
1142080f144cSVaclav Hapla   } else {
1143792fecdfSBarry Smith     PetscCallHDF5Return(attribute, H5Acreate2, (obj, name, dtype, dataspace, H5P_DEFAULT, H5P_DEFAULT));
1144080f144cSVaclav Hapla   }
1145792fecdfSBarry Smith   PetscCallHDF5(H5Awrite, (attribute, dtype, value));
1146792fecdfSBarry Smith   if (datatype == PETSC_STRING) PetscCallHDF5(H5Tclose, (dtype));
1147792fecdfSBarry Smith   PetscCallHDF5(H5Aclose, (attribute));
1148792fecdfSBarry Smith   PetscCallHDF5(H5Oclose, (obj));
1149792fecdfSBarry Smith   PetscCallHDF5(H5Sclose, (dataspace));
11509566063dSJacob Faibussowitsch   PetscCall(PetscFree(parentAbsPath));
11513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
115236bce6e8SMatthew G. Knepley }
115336bce6e8SMatthew G. Knepley 
1154df863907SAlex Fikl /*@C
1155811af0c4SBarry Smith   PetscViewerHDF5WriteObjectAttribute - Write an attribute to the dataset matching the given `PetscObject` by name
1156577e0e04SVaclav Hapla 
1157343a20b2SVaclav Hapla   Collective
1158343a20b2SVaclav Hapla 
1159577e0e04SVaclav Hapla   Input Parameters:
1160811af0c4SBarry Smith + viewer   - The `PETSCVIEWERHDF5` viewer
1161577e0e04SVaclav Hapla . obj      - The object whose name is used to lookup the parent dataset, relative to the current group.
1162577e0e04SVaclav Hapla . name     - The attribute name
1163577e0e04SVaclav Hapla . datatype - The attribute type
1164577e0e04SVaclav Hapla - value    - The attribute value
1165577e0e04SVaclav Hapla 
11663f423023SBarry Smith   Level: advanced
11673f423023SBarry Smith 
1168811af0c4SBarry Smith   Note:
1169343a20b2SVaclav 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).
1170811af0c4SBarry Smith   You might want to check first if it does using `PetscViewerHDF5HasObject()`.
1171577e0e04SVaclav Hapla 
1172d1f92df0SBarry Smith .seealso: [](sec_viewers), `PETSCVIEWERHDF5`, `PetscViewerHDF5Open()`, `PetscViewerHDF5WriteAttribute()`, `PetscViewerHDF5ReadObjectAttribute()`, `PetscViewerHDF5HasObjectAttribute()`,
1173811af0c4SBarry Smith           `PetscViewerHDF5HasObject()`, `PetscViewerHDF5PushGroup()`, `PetscViewerHDF5PopGroup()`, `PetscViewerHDF5GetGroup()`
1174577e0e04SVaclav Hapla @*/
1175d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerHDF5WriteObjectAttribute(PetscViewer viewer, PetscObject obj, const char name[], PetscDataType datatype, const void *value)
1176d71ae5a4SJacob Faibussowitsch {
1177577e0e04SVaclav Hapla   PetscFunctionBegin;
1178577e0e04SVaclav Hapla   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
1179577e0e04SVaclav Hapla   PetscValidHeader(obj, 2);
1180577e0e04SVaclav Hapla   PetscValidCharPointer(name, 3);
1181b7e81f0fSVaclav Hapla   PetscValidPointer(value, 5);
11829566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5CheckNamedObject_Internal(viewer, obj));
11839566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5WriteAttribute(viewer, obj->name, name, datatype, value));
11843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1185577e0e04SVaclav Hapla }
1186577e0e04SVaclav Hapla 
1187577e0e04SVaclav Hapla /*@C
1188b8ee85a1SVaclav Hapla   PetscViewerHDF5ReadAttribute - Read an attribute
1189ad0c61feSMatthew G. Knepley 
1190343a20b2SVaclav Hapla   Collective
1191343a20b2SVaclav Hapla 
1192ad0c61feSMatthew G. Knepley   Input Parameters:
1193811af0c4SBarry Smith + viewer       - The `PETSCVIEWERHDF5` viewer
11944302210dSVaclav Hapla . parent       - The parent dataset/group name
1195ad0c61feSMatthew G. Knepley . name         - The attribute name
1196a2d6be1bSVaclav Hapla . datatype     - The attribute type
1197a2d6be1bSVaclav Hapla - defaultValue - The pointer to the default value
1198ad0c61feSMatthew G. Knepley 
1199ad0c61feSMatthew G. Knepley   Output Parameter:
1200a2d6be1bSVaclav Hapla . value - The pointer to the read HDF5 attribute value
1201ad0c61feSMatthew G. Knepley 
12023f423023SBarry Smith   Level: advanced
12033f423023SBarry Smith 
1204a2d6be1bSVaclav Hapla   Notes:
12053f423023SBarry Smith   If defaultValue is `NULL` and the attribute is not found, an error occurs.
12063f423023SBarry Smith 
12073f423023SBarry Smith   If defaultValue is not `NULL` and the attribute is not found, `defaultValue` is copied to value.
12083f423023SBarry Smith 
12093f423023SBarry Smith   The pointers `defaultValue` and value can be the same; for instance
12103f423023SBarry Smith .vb
12113f423023SBarry Smith   flg = PETSC_FALSE;
12123f423023SBarry Smith   PetscCall(`PetscViewerHDF5ReadAttribute`(viewer,name,"attr",PETSC_BOOL,&flg,&flg));
12133f423023SBarry Smith .ve
1214a2d6be1bSVaclav Hapla   is valid, but make sure the default value is initialized.
1215a2d6be1bSVaclav Hapla 
1216811af0c4SBarry Smith   If the datatype is `PETSC_STRING`, the output string is newly allocated so one must `PetscFree()` it when no longer needed.
1217708d4cb3SBarry Smith 
12183f423023SBarry Smith   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.
12194302210dSVaclav Hapla 
1220d1f92df0SBarry Smith .seealso: [](sec_viewers), `PETSCVIEWERHDF5`, `PetscViewerHDF5Open()`, `PetscViewerHDF5ReadObjectAttribute()`, `PetscViewerHDF5WriteAttribute()`, `PetscViewerHDF5HasAttribute()`, `PetscViewerHDF5HasObject()`, `PetscViewerHDF5PushGroup()`, `PetscViewerHDF5PopGroup()`, `PetscViewerHDF5GetGroup()`
1221ad0c61feSMatthew G. Knepley @*/
1222d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerHDF5ReadAttribute(PetscViewer viewer, const char parent[], const char name[], PetscDataType datatype, const void *defaultValue, void *value)
1223d71ae5a4SJacob Faibussowitsch {
12244302210dSVaclav Hapla   char     *parentAbsPath;
1225a2d6be1bSVaclav Hapla   hid_t     h5, obj, attribute, dtype;
1226969748fdSVaclav Hapla   PetscBool has;
1227ad0c61feSMatthew G. Knepley 
1228ad0c61feSMatthew G. Knepley   PetscFunctionBegin;
12295cdeb108SMatthew G. Knepley   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
12304302210dSVaclav Hapla   if (parent) PetscValidCharPointer(parent, 2);
1231c57a1a9aSVaclav Hapla   PetscValidCharPointer(name, 3);
1232a2d6be1bSVaclav Hapla   if (defaultValue) PetscValidPointer(defaultValue, 5);
1233a2d6be1bSVaclav Hapla   PetscValidPointer(value, 6);
12349566063dSJacob Faibussowitsch   PetscCall(PetscDataTypeToHDF5DataType(datatype, &dtype));
123577717648SVaclav Hapla   PetscCall(PetscViewerHDF5GetGroup(viewer, parent, &parentAbsPath));
12369566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5Traverse_Internal(viewer, parentAbsPath, PETSC_FALSE, &has, NULL));
12379566063dSJacob Faibussowitsch   if (has) PetscCall(PetscViewerHDF5HasAttribute_Internal(viewer, parentAbsPath, name, &has));
1238a2d6be1bSVaclav Hapla   if (!has) {
1239a2d6be1bSVaclav Hapla     if (defaultValue) {
1240a2d6be1bSVaclav Hapla       if (defaultValue != value) {
1241a2d6be1bSVaclav Hapla         if (datatype == PETSC_STRING) {
12429566063dSJacob Faibussowitsch           PetscCall(PetscStrallocpy(*(char **)defaultValue, (char **)value));
1243a2d6be1bSVaclav Hapla         } else {
1244a2d6be1bSVaclav Hapla           size_t len;
1245792fecdfSBarry Smith           PetscCallHDF5ReturnNoCheck(len, H5Tget_size, (dtype));
12469566063dSJacob Faibussowitsch           PetscCall(PetscMemcpy(value, defaultValue, len));
1247a2d6be1bSVaclav Hapla         }
1248a2d6be1bSVaclav Hapla       }
12499566063dSJacob Faibussowitsch       PetscCall(PetscFree(parentAbsPath));
12503ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
125198921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Attribute %s/%s does not exist and default value not provided", parentAbsPath, name);
1252a2d6be1bSVaclav Hapla   }
12539566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5GetFileId(viewer, &h5));
1254792fecdfSBarry Smith   PetscCallHDF5Return(obj, H5Oopen, (h5, parentAbsPath, H5P_DEFAULT));
1255792fecdfSBarry Smith   PetscCallHDF5Return(attribute, H5Aopen_name, (obj, name));
1256f0b58479SMatthew G. Knepley   if (datatype == PETSC_STRING) {
1257f0b58479SMatthew G. Knepley     size_t len;
1258a2d6be1bSVaclav Hapla     hid_t  atype;
1259792fecdfSBarry Smith     PetscCallHDF5Return(atype, H5Aget_type, (attribute));
1260792fecdfSBarry Smith     PetscCallHDF5ReturnNoCheck(len, H5Tget_size, (atype));
12619566063dSJacob Faibussowitsch     PetscCall(PetscMalloc((len + 1) * sizeof(char), value));
1262792fecdfSBarry Smith     PetscCallHDF5(H5Tset_size, (dtype, len + 1));
1263792fecdfSBarry Smith     PetscCallHDF5(H5Aread, (attribute, dtype, *(char **)value));
1264708d4cb3SBarry Smith   } else {
1265792fecdfSBarry Smith     PetscCallHDF5(H5Aread, (attribute, dtype, value));
1266708d4cb3SBarry Smith   }
1267792fecdfSBarry Smith   PetscCallHDF5(H5Aclose, (attribute));
1268e90c5075SMarek Pecha   /* H5Oclose can be used to close groups, datasets, or committed datatypes */
1269792fecdfSBarry Smith   PetscCallHDF5(H5Oclose, (obj));
12709566063dSJacob Faibussowitsch   PetscCall(PetscFree(parentAbsPath));
12713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1272ad0c61feSMatthew G. Knepley }
1273ad0c61feSMatthew G. Knepley 
1274577e0e04SVaclav Hapla /*@C
1275811af0c4SBarry Smith   PetscViewerHDF5ReadObjectAttribute - Read an attribute from the dataset matching the given `PetscObject` by name
1276577e0e04SVaclav Hapla 
1277343a20b2SVaclav Hapla   Collective
1278343a20b2SVaclav Hapla 
1279577e0e04SVaclav Hapla   Input Parameters:
1280811af0c4SBarry Smith + viewer       - The `PETSCVIEWERHDF5` viewer
1281577e0e04SVaclav Hapla . obj          - The object whose name is used to lookup the parent dataset, relative to the current group.
1282577e0e04SVaclav Hapla . name         - The attribute name
1283*10450e9eSJacob Faibussowitsch . datatype     - The attribute type
1284*10450e9eSJacob Faibussowitsch - defaultValue - The default attribute value
1285577e0e04SVaclav Hapla 
1286577e0e04SVaclav Hapla   Output Parameter:
1287577e0e04SVaclav Hapla . value - The attribute value
1288577e0e04SVaclav Hapla 
12893f423023SBarry Smith   Level: advanced
12903f423023SBarry Smith 
1291811af0c4SBarry Smith   Note:
1292577e0e04SVaclav Hapla   This fails if current_group/object_name doesn't resolve to a dataset (the path doesn't exist or is not a dataset).
1293811af0c4SBarry Smith   You might want to check first if it does using `PetscViewerHDF5HasObject()`.
1294577e0e04SVaclav Hapla 
1295d1f92df0SBarry Smith .seealso: [](sec_viewers), `PETSCVIEWERHDF5`, `PetscViewerHDF5Open()`, `PetscViewerHDF5ReadAttribute()` `PetscViewerHDF5WriteObjectAttribute()`, `PetscViewerHDF5HasObjectAttribute()`, `PetscViewerHDF5PushGroup()`, `PetscViewerHDF5PopGroup()`, `PetscViewerHDF5GetGroup()`
1296577e0e04SVaclav Hapla @*/
1297d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerHDF5ReadObjectAttribute(PetscViewer viewer, PetscObject obj, const char name[], PetscDataType datatype, void *defaultValue, void *value)
1298d71ae5a4SJacob Faibussowitsch {
1299577e0e04SVaclav Hapla   PetscFunctionBegin;
1300577e0e04SVaclav Hapla   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
1301577e0e04SVaclav Hapla   PetscValidHeader(obj, 2);
1302577e0e04SVaclav Hapla   PetscValidCharPointer(name, 3);
1303064a246eSJacob Faibussowitsch   PetscValidPointer(value, 6);
13049566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5CheckNamedObject_Internal(viewer, obj));
13059566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5ReadAttribute(viewer, obj->name, name, datatype, defaultValue, value));
13063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1307577e0e04SVaclav Hapla }
1308577e0e04SVaclav Hapla 
1309d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode PetscViewerHDF5Traverse_Inner_Internal(hid_t h5, const char name[], PetscBool createGroup, PetscBool *exists_)
1310d71ae5a4SJacob Faibussowitsch {
1311a75c3fd4SVaclav Hapla   htri_t exists;
1312a75c3fd4SVaclav Hapla   hid_t  group;
1313a75c3fd4SVaclav Hapla 
1314a75c3fd4SVaclav Hapla   PetscFunctionBegin;
1315792fecdfSBarry Smith   PetscCallHDF5Return(exists, H5Lexists, (h5, name, H5P_DEFAULT));
1316792fecdfSBarry Smith   if (exists) PetscCallHDF5Return(exists, H5Oexists_by_name, (h5, name, H5P_DEFAULT));
1317a75c3fd4SVaclav Hapla   if (!exists && createGroup) {
1318792fecdfSBarry Smith     PetscCallHDF5Return(group, H5Gcreate2, (h5, name, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT));
1319792fecdfSBarry Smith     PetscCallHDF5(H5Gclose, (group));
1320a75c3fd4SVaclav Hapla     exists = PETSC_TRUE;
1321a75c3fd4SVaclav Hapla   }
1322a75c3fd4SVaclav Hapla   *exists_ = (PetscBool)exists;
13233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1324a75c3fd4SVaclav Hapla }
1325a75c3fd4SVaclav Hapla 
1326d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscViewerHDF5Traverse_Internal(PetscViewer viewer, const char name[], PetscBool createGroup, PetscBool *has, H5O_type_t *otype)
1327d71ae5a4SJacob Faibussowitsch {
132890e03537SVaclav Hapla   const char rootGroupName[] = "/";
13295cdeb108SMatthew G. Knepley   hid_t      h5;
1330e5bf9ebcSVaclav Hapla   PetscBool  exists = PETSC_FALSE;
133115b861d2SVaclav Hapla   PetscInt   i;
133215b861d2SVaclav Hapla   int        n;
133385688ae2SVaclav Hapla   char     **hierarchy;
133485688ae2SVaclav Hapla   char       buf[PETSC_MAX_PATH_LEN] = "";
13355cdeb108SMatthew G. Knepley 
13365cdeb108SMatthew G. Knepley   PetscFunctionBegin;
13375cdeb108SMatthew G. Knepley   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
133890e03537SVaclav Hapla   if (name) PetscValidCharPointer(name, 2);
133990e03537SVaclav Hapla   else name = rootGroupName;
1340ccd66a83SVaclav Hapla   if (has) {
1341064a246eSJacob Faibussowitsch     PetscValidBoolPointer(has, 4);
13425cdeb108SMatthew G. Knepley     *has = PETSC_FALSE;
1343ccd66a83SVaclav Hapla   }
1344ccd66a83SVaclav Hapla   if (otype) {
1345064a246eSJacob Faibussowitsch     PetscValidIntPointer(otype, 5);
134656cc0592SVaclav Hapla     *otype = H5O_TYPE_UNKNOWN;
1347ccd66a83SVaclav Hapla   }
13489566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5GetFileId(viewer, &h5));
134985688ae2SVaclav Hapla 
135085688ae2SVaclav Hapla   /*
135185688ae2SVaclav Hapla      Unfortunately, H5Oexists_by_name() fails if any object in hierarchy is missing.
135285688ae2SVaclav Hapla      Hence, each of them needs to be tested separately:
135385688ae2SVaclav Hapla      1) whether it's a valid link
135485688ae2SVaclav Hapla      2) whether this link resolves to an object
135585688ae2SVaclav Hapla      See H5Oexists_by_name() documentation.
135685688ae2SVaclav Hapla   */
13579566063dSJacob Faibussowitsch   PetscCall(PetscStrToArray(name, '/', &n, &hierarchy));
135885688ae2SVaclav Hapla   if (!n) {
135985688ae2SVaclav Hapla     /*  Assume group "/" always exists in accordance with HDF5 >= 1.10.0. See H5Lexists() documentation. */
1360ccd66a83SVaclav Hapla     if (has) *has = PETSC_TRUE;
1361ccd66a83SVaclav Hapla     if (otype) *otype = H5O_TYPE_GROUP;
13629566063dSJacob Faibussowitsch     PetscCall(PetscStrToArrayDestroy(n, hierarchy));
13633ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
136485688ae2SVaclav Hapla   }
136585688ae2SVaclav Hapla   for (i = 0; i < n; i++) {
1366c6a7a370SJeremy L Thompson     PetscCall(PetscStrlcat(buf, "/", sizeof(buf)));
1367c6a7a370SJeremy L Thompson     PetscCall(PetscStrlcat(buf, hierarchy[i], sizeof(buf)));
13689566063dSJacob Faibussowitsch     PetscCall(PetscViewerHDF5Traverse_Inner_Internal(h5, buf, createGroup, &exists));
1369a75c3fd4SVaclav Hapla     if (!exists) break;
137085688ae2SVaclav Hapla   }
13719566063dSJacob Faibussowitsch   PetscCall(PetscStrToArrayDestroy(n, hierarchy));
137285688ae2SVaclav Hapla 
137385688ae2SVaclav Hapla   /* If the object exists, get its type */
1374ccd66a83SVaclav Hapla   if (exists && otype) {
13755cdeb108SMatthew G. Knepley     H5O_info_t info;
13765cdeb108SMatthew G. Knepley 
137776276748SVaclav Hapla     /* We could use H5Iget_type() here but that would require opening the object. This way we only need its name. */
1378792fecdfSBarry Smith     PetscCallHDF5(H5Oget_info_by_name, (h5, name, &info, H5P_DEFAULT));
137956cc0592SVaclav Hapla     *otype = info.type;
13805cdeb108SMatthew G. Knepley   }
1381ccd66a83SVaclav Hapla   if (has) *has = exists;
13823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13835cdeb108SMatthew G. Knepley }
13845cdeb108SMatthew G. Knepley 
13854302210dSVaclav Hapla /*@C
13860a9f38efSVaclav Hapla   PetscViewerHDF5HasGroup - Check whether the current (pushed) group exists in the HDF5 file
13870a9f38efSVaclav Hapla 
1388343a20b2SVaclav Hapla   Collective
1389343a20b2SVaclav Hapla 
13900a9f38efSVaclav Hapla   Input Parameters:
1391811af0c4SBarry Smith + viewer - The `PETSCVIEWERHDF5` viewer
1392a0558868SVaclav Hapla - path   - (Optional) The path relative to the pushed group
13930a9f38efSVaclav Hapla 
13940a9f38efSVaclav Hapla   Output Parameter:
13950a9f38efSVaclav Hapla . has - Flag for group existence
13960a9f38efSVaclav Hapla 
13970a9f38efSVaclav Hapla   Level: advanced
13980a9f38efSVaclav Hapla 
13994302210dSVaclav Hapla   Notes:
1400785c443eSVaclav 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.
14013f423023SBarry Smith   `NULL` or empty path means the current pushed group.
14024302210dSVaclav Hapla 
1403811af0c4SBarry Smith   If path exists but is not a group, `PETSC_FALSE` is returned.
1404811af0c4SBarry Smith 
1405d1f92df0SBarry Smith .seealso: [](sec_viewers), `PETSCVIEWERHDF5`, `PetscViewerHDF5HasAttribute()`, `PetscViewerHDF5HasDataset()`, `PetscViewerHDF5PushGroup()`, `PetscViewerHDF5PopGroup()`, `PetscViewerHDF5GetGroup()`, `PetscViewerHDF5OpenGroup()`
14060a9f38efSVaclav Hapla @*/
1407d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerHDF5HasGroup(PetscViewer viewer, const char path[], PetscBool *has)
1408d71ae5a4SJacob Faibussowitsch {
14090a9f38efSVaclav Hapla   H5O_type_t type;
14104302210dSVaclav Hapla   char      *abspath;
14110a9f38efSVaclav Hapla 
14120a9f38efSVaclav Hapla   PetscFunctionBegin;
14130a9f38efSVaclav Hapla   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
14144302210dSVaclav Hapla   if (path) PetscValidCharPointer(path, 2);
14154302210dSVaclav Hapla   PetscValidBoolPointer(has, 3);
141677717648SVaclav Hapla   PetscCall(PetscViewerHDF5GetGroup(viewer, path, &abspath));
14179566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5Traverse_Internal(viewer, abspath, PETSC_FALSE, NULL, &type));
14184302210dSVaclav Hapla   *has = (PetscBool)(type == H5O_TYPE_GROUP);
14199566063dSJacob Faibussowitsch   PetscCall(PetscFree(abspath));
14203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
14210a9f38efSVaclav Hapla }
14220a9f38efSVaclav Hapla 
142389e0ef10SVaclav Hapla /*@C
142489e0ef10SVaclav Hapla   PetscViewerHDF5HasDataset - Check whether a given dataset exists in the HDF5 file
142589e0ef10SVaclav Hapla 
1426343a20b2SVaclav Hapla   Collective
1427343a20b2SVaclav Hapla 
142889e0ef10SVaclav Hapla   Input Parameters:
1429811af0c4SBarry Smith + viewer - The `PETSCVIEWERHDF5` viewer
143089e0ef10SVaclav Hapla - path   - The dataset path
143189e0ef10SVaclav Hapla 
143289e0ef10SVaclav Hapla   Output Parameter:
143389e0ef10SVaclav Hapla . has - Flag whether dataset exists
143489e0ef10SVaclav Hapla 
143589e0ef10SVaclav Hapla   Level: advanced
143689e0ef10SVaclav Hapla 
143789e0ef10SVaclav Hapla   Notes:
1438343a20b2SVaclav 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.
143989e0ef10SVaclav Hapla 
14403f423023SBarry Smith   If `path` is `NULL` or empty, has is set to `PETSC_FALSE`.
1441811af0c4SBarry Smith 
14423f423023SBarry Smith   If `path` exists but is not a dataset, has is set to `PETSC_FALSE` as well.
1443811af0c4SBarry Smith 
1444d1f92df0SBarry Smith .seealso: [](sec_viewers), `PETSCVIEWERHDF5`, `PetscViewerHDF5HasObject()`, `PetscViewerHDF5HasAttribute()`, `PetscViewerHDF5HasGroup()`, `PetscViewerHDF5PushGroup()`, `PetscViewerHDF5PopGroup()`, `PetscViewerHDF5GetGroup()`
144589e0ef10SVaclav Hapla @*/
1446d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerHDF5HasDataset(PetscViewer viewer, const char path[], PetscBool *has)
1447d71ae5a4SJacob Faibussowitsch {
144889e0ef10SVaclav Hapla   H5O_type_t type;
144989e0ef10SVaclav Hapla   char      *abspath;
145089e0ef10SVaclav Hapla 
145189e0ef10SVaclav Hapla   PetscFunctionBegin;
145289e0ef10SVaclav Hapla   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
145389e0ef10SVaclav Hapla   if (path) PetscValidCharPointer(path, 2);
145489e0ef10SVaclav Hapla   PetscValidBoolPointer(has, 3);
145577717648SVaclav Hapla   PetscCall(PetscViewerHDF5GetGroup(viewer, path, &abspath));
14569566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5Traverse_Internal(viewer, abspath, PETSC_FALSE, NULL, &type));
145789e0ef10SVaclav Hapla   *has = (PetscBool)(type == H5O_TYPE_DATASET);
14589566063dSJacob Faibussowitsch   PetscCall(PetscFree(abspath));
14593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
146089e0ef10SVaclav Hapla }
146189e0ef10SVaclav Hapla 
14620a9f38efSVaclav Hapla /*@
1463e3f143f7SVaclav Hapla   PetscViewerHDF5HasObject - Check whether a dataset with the same name as given object exists in the HDF5 file under current group
1464ecce1506SVaclav Hapla 
1465343a20b2SVaclav Hapla   Collective
1466343a20b2SVaclav Hapla 
1467ecce1506SVaclav Hapla   Input Parameters:
1468811af0c4SBarry Smith + viewer - The `PETSCVIEWERHDF5` viewer
1469ecce1506SVaclav Hapla - obj    - The named object
1470ecce1506SVaclav Hapla 
1471ecce1506SVaclav Hapla   Output Parameter:
147289e0ef10SVaclav Hapla . has - Flag for dataset existence
1473ecce1506SVaclav Hapla 
14743f423023SBarry Smith   Level: advanced
14753f423023SBarry Smith 
1476e3f143f7SVaclav Hapla   Notes:
147789e0ef10SVaclav Hapla   If the object is unnamed, an error occurs.
1478811af0c4SBarry Smith 
1479811af0c4SBarry Smith   If the path current_group/object_name exists but is not a dataset, has is set to `PETSC_FALSE` as well.
1480e3f143f7SVaclav Hapla 
1481d1f92df0SBarry Smith .seealso: [](sec_viewers), `PETSCVIEWERHDF5`, `PetscViewerHDF5Open()`, `PetscViewerHDF5HasDataset()`, `PetscViewerHDF5HasAttribute()`, `PetscViewerHDF5PushGroup()`, `PetscViewerHDF5PopGroup()`, `PetscViewerHDF5GetGroup()`
1482ecce1506SVaclav Hapla @*/
1483d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerHDF5HasObject(PetscViewer viewer, PetscObject obj, PetscBool *has)
1484d71ae5a4SJacob Faibussowitsch {
148589e0ef10SVaclav Hapla   size_t len;
1486ecce1506SVaclav Hapla 
1487ecce1506SVaclav Hapla   PetscFunctionBegin;
1488c57a1a9aSVaclav Hapla   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
1489c57a1a9aSVaclav Hapla   PetscValidHeader(obj, 2);
14904302210dSVaclav Hapla   PetscValidBoolPointer(has, 3);
14919566063dSJacob Faibussowitsch   PetscCall(PetscStrlen(obj->name, &len));
14925f80ce2aSJacob Faibussowitsch   PetscCheck(len, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONG, "Object must be named");
14939566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5HasDataset(viewer, obj->name, has));
14943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1495ecce1506SVaclav Hapla }
1496ecce1506SVaclav Hapla 
1497df863907SAlex Fikl /*@C
1498ece83b6cSVaclav Hapla   PetscViewerHDF5HasAttribute - Check whether an attribute exists
1499e7bdbf8eSMatthew G. Knepley 
1500343a20b2SVaclav Hapla   Collective
1501343a20b2SVaclav Hapla 
1502e7bdbf8eSMatthew G. Knepley   Input Parameters:
1503811af0c4SBarry Smith + viewer - The `PETSCVIEWERHDF5` viewer
15044302210dSVaclav Hapla . parent - The parent dataset/group name
1505e7bdbf8eSMatthew G. Knepley - name   - The attribute name
1506e7bdbf8eSMatthew G. Knepley 
1507e7bdbf8eSMatthew G. Knepley   Output Parameter:
1508e7bdbf8eSMatthew G. Knepley . has - Flag for attribute existence
1509e7bdbf8eSMatthew G. Knepley 
1510e7bdbf8eSMatthew G. Knepley   Level: advanced
1511e7bdbf8eSMatthew G. Knepley 
1512811af0c4SBarry Smith   Note:
15133f423023SBarry Smith   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.
15144302210dSVaclav Hapla 
1515d1f92df0SBarry Smith .seealso: [](sec_viewers), `PETSCVIEWERHDF5`, `PetscViewerHDF5Open()`, `PetscViewerHDF5HasObjectAttribute()`, `PetscViewerHDF5WriteAttribute()`, `PetscViewerHDF5ReadAttribute()`, `PetscViewerHDF5PushGroup()`, `PetscViewerHDF5PopGroup()`, `PetscViewerHDF5GetGroup()`
1516e7bdbf8eSMatthew G. Knepley @*/
1517d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerHDF5HasAttribute(PetscViewer viewer, const char parent[], const char name[], PetscBool *has)
1518d71ae5a4SJacob Faibussowitsch {
15194302210dSVaclav Hapla   char *parentAbsPath;
1520e7bdbf8eSMatthew G. Knepley 
1521e7bdbf8eSMatthew G. Knepley   PetscFunctionBegin;
15225cdeb108SMatthew G. Knepley   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
15234302210dSVaclav Hapla   if (parent) PetscValidCharPointer(parent, 2);
1524c57a1a9aSVaclav Hapla   PetscValidCharPointer(name, 3);
15254302210dSVaclav Hapla   PetscValidBoolPointer(has, 4);
152677717648SVaclav Hapla   PetscCall(PetscViewerHDF5GetGroup(viewer, parent, &parentAbsPath));
15279566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5Traverse_Internal(viewer, parentAbsPath, PETSC_FALSE, has, NULL));
15289566063dSJacob Faibussowitsch   if (*has) PetscCall(PetscViewerHDF5HasAttribute_Internal(viewer, parentAbsPath, name, has));
15299566063dSJacob Faibussowitsch   PetscCall(PetscFree(parentAbsPath));
15303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
153106db490cSVaclav Hapla }
153206db490cSVaclav Hapla 
1533577e0e04SVaclav Hapla /*@C
1534811af0c4SBarry Smith   PetscViewerHDF5HasObjectAttribute - Check whether an attribute is attached to the dataset matching the given `PetscObject` by name
1535577e0e04SVaclav Hapla 
1536343a20b2SVaclav Hapla   Collective
1537343a20b2SVaclav Hapla 
1538577e0e04SVaclav Hapla   Input Parameters:
1539811af0c4SBarry Smith + viewer - The `PETSCVIEWERHDF5` viewer
1540577e0e04SVaclav Hapla . obj    - The object whose name is used to lookup the parent dataset, relative to the current group.
1541577e0e04SVaclav Hapla - name   - The attribute name
1542577e0e04SVaclav Hapla 
1543577e0e04SVaclav Hapla   Output Parameter:
1544577e0e04SVaclav Hapla . has - Flag for attribute existence
1545577e0e04SVaclav Hapla 
15463f423023SBarry Smith   Level: advanced
15473f423023SBarry Smith 
1548811af0c4SBarry Smith   Note:
1549577e0e04SVaclav Hapla   This fails if current_group/object_name doesn't resolve to a dataset (the path doesn't exist or is not a dataset).
1550811af0c4SBarry Smith   You might want to check first if it does using `PetscViewerHDF5HasObject()`.
1551577e0e04SVaclav Hapla 
1552d1f92df0SBarry Smith .seealso: [](sec_viewers), `PETSCVIEWERHDF5`, `PetscViewerHDF5Open()`, `PetscViewerHDF5HasAttribute()`, `PetscViewerHDF5WriteObjectAttribute()`, `PetscViewerHDF5ReadObjectAttribute()`, `PetscViewerHDF5HasObject()`, `PetscViewerHDF5PushGroup()`, `PetscViewerHDF5PopGroup()`, `PetscViewerHDF5GetGroup()`
1553577e0e04SVaclav Hapla @*/
1554d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerHDF5HasObjectAttribute(PetscViewer viewer, PetscObject obj, const char name[], PetscBool *has)
1555d71ae5a4SJacob Faibussowitsch {
1556577e0e04SVaclav Hapla   PetscFunctionBegin;
1557577e0e04SVaclav Hapla   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
1558577e0e04SVaclav Hapla   PetscValidHeader(obj, 2);
1559577e0e04SVaclav Hapla   PetscValidCharPointer(name, 3);
15604302210dSVaclav Hapla   PetscValidBoolPointer(has, 4);
15619566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5CheckNamedObject_Internal(viewer, obj));
15629566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5HasAttribute(viewer, obj->name, name, has));
15633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1564577e0e04SVaclav Hapla }
1565577e0e04SVaclav Hapla 
1566d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscViewerHDF5HasAttribute_Internal(PetscViewer viewer, const char parent[], const char name[], PetscBool *has)
1567d71ae5a4SJacob Faibussowitsch {
156806db490cSVaclav Hapla   hid_t  h5;
156906db490cSVaclav Hapla   htri_t hhas;
157006db490cSVaclav Hapla 
157106db490cSVaclav Hapla   PetscFunctionBegin;
15729566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5GetFileId(viewer, &h5));
1573792fecdfSBarry Smith   PetscCallHDF5Return(hhas, H5Aexists_by_name, (h5, parent, name, H5P_DEFAULT));
15745cdeb108SMatthew G. Knepley   *has = hhas ? PETSC_TRUE : PETSC_FALSE;
15753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1576e7bdbf8eSMatthew G. Knepley }
1577e7bdbf8eSMatthew G. Knepley 
1578a75e6a4aSMatthew G. Knepley /*
1579a75e6a4aSMatthew G. Knepley   The variable Petsc_Viewer_HDF5_keyval is used to indicate an MPI attribute that
1580a75e6a4aSMatthew G. Knepley   is attached to a communicator, in this case the attribute is a PetscViewer.
1581a75e6a4aSMatthew G. Knepley */
1582d4c7638eSBarry Smith PetscMPIInt Petsc_Viewer_HDF5_keyval = MPI_KEYVAL_INVALID;
1583a75e6a4aSMatthew G. Knepley 
1584a75e6a4aSMatthew G. Knepley /*@C
1585811af0c4SBarry Smith   PETSC_VIEWER_HDF5_ - Creates an `PETSCVIEWERHDF5` `PetscViewer` shared by all processors in a communicator.
1586a75e6a4aSMatthew G. Knepley 
1587d083f849SBarry Smith   Collective
1588a75e6a4aSMatthew G. Knepley 
1589a75e6a4aSMatthew G. Knepley   Input Parameter:
15903f423023SBarry Smith . comm - the MPI communicator to share the `PETSCVIEWERHDF5` `PetscViewer`
1591a75e6a4aSMatthew G. Knepley 
1592811af0c4SBarry Smith   Options Database Key:
159310699b91SBarry Smith . -viewer_hdf5_filename <name> - name of the HDF5 file
1594a75e6a4aSMatthew G. Knepley 
1595811af0c4SBarry Smith   Environmental variable:
1596811af0c4SBarry Smith . `PETSC_VIEWER_HDF5_FILENAME` - name of the HDF5 file
1597a75e6a4aSMatthew G. Knepley 
159820f4b53cSBarry Smith   Level: intermediate
159920f4b53cSBarry Smith 
1600811af0c4SBarry Smith   Note:
1601811af0c4SBarry Smith   Unlike almost all other PETSc routines, `PETSC_VIEWER_HDF5_()` does not return
1602811af0c4SBarry Smith   an error code.  The HDF5 `PetscViewer` is usually used in the form
1603a75e6a4aSMatthew G. Knepley $       XXXView(XXX object, PETSC_VIEWER_HDF5_(comm));
1604a75e6a4aSMatthew G. Knepley 
1605d1f92df0SBarry Smith .seealso: [](sec_viewers), `PETSCVIEWERHDF5`, `PetscViewerHDF5Open()`, `PetscViewerCreate()`, `PetscViewerDestroy()`
1606a75e6a4aSMatthew G. Knepley @*/
1607d71ae5a4SJacob Faibussowitsch PetscViewer PETSC_VIEWER_HDF5_(MPI_Comm comm)
1608d71ae5a4SJacob Faibussowitsch {
1609a75e6a4aSMatthew G. Knepley   PetscErrorCode ierr;
16103ba16761SJacob Faibussowitsch   PetscMPIInt    mpi_ierr;
1611a75e6a4aSMatthew G. Knepley   PetscBool      flg;
1612a75e6a4aSMatthew G. Knepley   PetscViewer    viewer;
1613a75e6a4aSMatthew G. Knepley   char           fname[PETSC_MAX_PATH_LEN];
1614a75e6a4aSMatthew G. Knepley   MPI_Comm       ncomm;
1615a75e6a4aSMatthew G. Knepley 
1616a75e6a4aSMatthew G. Knepley   PetscFunctionBegin;
16179371c9d4SSatish Balay   ierr = PetscCommDuplicate(comm, &ncomm, NULL);
16189371c9d4SSatish Balay   if (ierr) {
16193ba16761SJacob Faibussowitsch     ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_HDF5_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
16209371c9d4SSatish Balay     PetscFunctionReturn(NULL);
16219371c9d4SSatish Balay   }
1622a75e6a4aSMatthew G. Knepley   if (Petsc_Viewer_HDF5_keyval == MPI_KEYVAL_INVALID) {
16233ba16761SJacob Faibussowitsch     mpi_ierr = MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, MPI_COMM_NULL_DELETE_FN, &Petsc_Viewer_HDF5_keyval, NULL);
16243ba16761SJacob Faibussowitsch     if (mpi_ierr) {
16253ba16761SJacob Faibussowitsch       ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_HDF5_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
16269371c9d4SSatish Balay       PetscFunctionReturn(NULL);
16279371c9d4SSatish Balay     }
1628a75e6a4aSMatthew G. Knepley   }
16293ba16761SJacob Faibussowitsch   mpi_ierr = MPI_Comm_get_attr(ncomm, Petsc_Viewer_HDF5_keyval, (void **)&viewer, (int *)&flg);
16303ba16761SJacob Faibussowitsch   if (mpi_ierr) {
16313ba16761SJacob Faibussowitsch     ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_HDF5_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
16329371c9d4SSatish Balay     PetscFunctionReturn(NULL);
16339371c9d4SSatish Balay   }
1634a75e6a4aSMatthew G. Knepley   if (!flg) { /* PetscViewer not yet created */
1635a75e6a4aSMatthew G. Knepley     ierr = PetscOptionsGetenv(ncomm, "PETSC_VIEWER_HDF5_FILENAME", fname, PETSC_MAX_PATH_LEN, &flg);
16369371c9d4SSatish Balay     if (ierr) {
16373ba16761SJacob Faibussowitsch       ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_HDF5_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " ");
16389371c9d4SSatish Balay       PetscFunctionReturn(NULL);
16399371c9d4SSatish Balay     }
1640a75e6a4aSMatthew G. Knepley     if (!flg) {
1641c6a7a370SJeremy L Thompson       ierr = PetscStrncpy(fname, "output.h5", sizeof(fname));
16429371c9d4SSatish Balay       if (ierr) {
16433ba16761SJacob Faibussowitsch         ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_HDF5_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " ");
16449371c9d4SSatish Balay         PetscFunctionReturn(NULL);
16459371c9d4SSatish Balay       }
1646a75e6a4aSMatthew G. Knepley     }
1647a75e6a4aSMatthew G. Knepley     ierr = PetscViewerHDF5Open(ncomm, fname, FILE_MODE_WRITE, &viewer);
16489371c9d4SSatish Balay     if (ierr) {
16493ba16761SJacob Faibussowitsch       ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_HDF5_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " ");
16509371c9d4SSatish Balay       PetscFunctionReturn(NULL);
16519371c9d4SSatish Balay     }
1652a75e6a4aSMatthew G. Knepley     ierr = PetscObjectRegisterDestroy((PetscObject)viewer);
16539371c9d4SSatish Balay     if (ierr) {
16543ba16761SJacob Faibussowitsch       ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_HDF5_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " ");
16559371c9d4SSatish Balay       PetscFunctionReturn(NULL);
16569371c9d4SSatish Balay     }
16573ba16761SJacob Faibussowitsch     mpi_ierr = MPI_Comm_set_attr(ncomm, Petsc_Viewer_HDF5_keyval, (void *)viewer);
16583ba16761SJacob Faibussowitsch     if (mpi_ierr) {
16593ba16761SJacob Faibussowitsch       ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_HDF5_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
16609371c9d4SSatish Balay       PetscFunctionReturn(NULL);
16619371c9d4SSatish Balay     }
1662a75e6a4aSMatthew G. Knepley   }
1663a75e6a4aSMatthew G. Knepley   ierr = PetscCommDestroy(&ncomm);
16649371c9d4SSatish Balay   if (ierr) {
16653ba16761SJacob Faibussowitsch     ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_HDF5_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " ");
16669371c9d4SSatish Balay     PetscFunctionReturn(NULL);
16679371c9d4SSatish Balay   }
1668a75e6a4aSMatthew G. Knepley   PetscFunctionReturn(viewer);
1669a75e6a4aSMatthew G. Knepley }
1670