xref: /petsc/src/sys/classes/viewer/impls/hdf5/hdf5v.c (revision 009bbdc485cd9ad46be9940d3549e2dde9cdc322)
1 #include <petsc-private/viewerimpl.h>    /*I   "petscsys.h"   I*/
2 #include <hdf5.h>
3 
4 typedef struct GroupList {
5   const char       *name;
6   struct GroupList *next;
7 } GroupList;
8 
9 typedef struct {
10   char         *filename;
11   PetscFileMode btype;
12   hid_t         file_id;
13   PetscInt      timestep;
14   GroupList    *groups;
15 } PetscViewer_HDF5;
16 
17 #undef __FUNCT__
18 #define __FUNCT__ "PetscViewerFileClose_HDF5"
19 static PetscErrorCode PetscViewerFileClose_HDF5(PetscViewer viewer)
20 {
21   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*)viewer->data;
22   PetscErrorCode ierr;
23 
24   PetscFunctionBegin;
25   ierr = PetscFree(hdf5->filename);CHKERRQ(ierr);
26   if (hdf5->file_id) {
27     H5Fclose(hdf5->file_id);
28   }
29   PetscFunctionReturn(0);
30 }
31 
32 #undef __FUNCT__
33 #define __FUNCT__ "PetscViewerDestroy_HDF5"
34 PetscErrorCode PetscViewerDestroy_HDF5(PetscViewer viewer)
35 {
36  PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *) viewer->data;
37  PetscErrorCode    ierr;
38 
39  PetscFunctionBegin;
40  ierr = PetscViewerFileClose_HDF5(viewer);CHKERRQ(ierr);
41  if (hdf5->groups) {
42    while (hdf5->groups) {
43      GroupList *tmp = hdf5->groups->next;
44 
45      ierr = PetscFree(hdf5->groups->name);CHKERRQ(ierr);
46      ierr = PetscFree(hdf5->groups);CHKERRQ(ierr);
47      hdf5->groups = tmp;
48    }
49  }
50  ierr = PetscFree(hdf5);CHKERRQ(ierr);
51  PetscFunctionReturn(0);
52 }
53 
54 EXTERN_C_BEGIN
55 #undef __FUNCT__
56 #define __FUNCT__ "PetscViewerFileSetMode_HDF5"
57 PetscErrorCode  PetscViewerFileSetMode_HDF5(PetscViewer viewer, PetscFileMode type)
58 {
59   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *) viewer->data;
60 
61   PetscFunctionBegin;
62   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
63   hdf5->btype = type;
64   PetscFunctionReturn(0);
65 }
66 EXTERN_C_END
67 
68 EXTERN_C_BEGIN
69 #undef __FUNCT__
70 #define __FUNCT__ "PetscViewerFileSetName_HDF5"
71 PetscErrorCode  PetscViewerFileSetName_HDF5(PetscViewer viewer, const char name[])
72 {
73   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *) viewer->data;
74 #if defined(PETSC_HAVE_H5PSET_FAPL_MPIO)
75   MPI_Info          info = MPI_INFO_NULL;
76 #endif
77   hid_t             plist_id;
78   herr_t            herr;
79   PetscErrorCode    ierr;
80 
81   PetscFunctionBegin;
82   ierr = PetscStrallocpy(name, &hdf5->filename);CHKERRQ(ierr);
83   /* Set up file access property list with parallel I/O access */
84   plist_id = H5Pcreate(H5P_FILE_ACCESS);
85 #if defined(PETSC_HAVE_H5PSET_FAPL_MPIO)
86   herr = H5Pset_fapl_mpio(plist_id, ((PetscObject)viewer)->comm, info);CHKERRQ(herr);
87 #endif
88   /* Create or open the file collectively */
89   switch (hdf5->btype) {
90     case FILE_MODE_READ:
91       hdf5->file_id = H5Fopen(name, H5F_ACC_RDONLY, plist_id);
92       break;
93     case FILE_MODE_APPEND:
94       hdf5->file_id = H5Fopen(name, H5F_ACC_RDWR, plist_id);
95       break;
96     case FILE_MODE_WRITE:
97       hdf5->file_id = H5Fcreate(name, H5F_ACC_TRUNC, H5P_DEFAULT, plist_id);
98       break;
99     default:
100       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER, "Must call PetscViewerFileSetMode() before PetscViewerFileSetName()");
101   }
102   if (hdf5->file_id < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB, "H5Fcreate failed for %s", name);
103   viewer->format = PETSC_VIEWER_NOFORMAT;
104   H5Pclose(plist_id);
105   PetscFunctionReturn(0);
106 }
107 EXTERN_C_END
108 
109 EXTERN_C_BEGIN
110 #undef __FUNCT__
111 #define __FUNCT__ "PetscViewerCreate_HDF5"
112 PetscErrorCode  PetscViewerCreate_HDF5(PetscViewer v)
113 {
114   PetscViewer_HDF5 *hdf5;
115   PetscErrorCode    ierr;
116 
117   PetscFunctionBegin;
118   ierr = PetscNewLog(v, PetscViewer_HDF5, &hdf5);CHKERRQ(ierr);
119 
120   v->data         = (void *) hdf5;
121   v->ops->destroy = PetscViewerDestroy_HDF5;
122   v->ops->flush   = 0;
123   v->iformat      = 0;
124   hdf5->btype     = (PetscFileMode) -1;
125   hdf5->filename  = 0;
126   hdf5->timestep  = -1;
127   hdf5->groups    = PETSC_NULL;
128 
129   ierr = PetscObjectComposeFunctionDynamic((PetscObject)v,"PetscViewerFileSetName_C","PetscViewerFileSetName_HDF5",
130                                            PetscViewerFileSetName_HDF5);CHKERRQ(ierr);
131   ierr = PetscObjectComposeFunctionDynamic((PetscObject)v,"PetscViewerFileSetMode_C","PetscViewerFileSetMode_HDF5",
132                                            PetscViewerFileSetMode_HDF5);CHKERRQ(ierr);
133   PetscFunctionReturn(0);
134 }
135 EXTERN_C_END
136 
137 #undef __FUNCT__
138 #define __FUNCT__ "PetscViewerHDF5Open"
139 /*@C
140    PetscViewerHDF5Open - Opens a file for HDF5 input/output.
141 
142    Collective on MPI_Comm
143 
144    Input Parameters:
145 +  comm - MPI communicator
146 .  name - name of file
147 -  type - type of file
148 $    FILE_MODE_WRITE - create new file for binary output
149 $    FILE_MODE_READ - open existing file for binary input
150 $    FILE_MODE_APPEND - open existing file for binary output
151 
152    Output Parameter:
153 .  hdf5v - PetscViewer for HDF5 input/output to use with the specified file
154 
155    Level: beginner
156 
157    Note:
158    This PetscViewer should be destroyed with PetscViewerDestroy().
159 
160    Concepts: HDF5 files
161    Concepts: PetscViewerHDF5^creating
162 
163 .seealso: PetscViewerASCIIOpen(), PetscViewerSetFormat(), PetscViewerDestroy(),
164           VecView(), MatView(), VecLoad(), MatLoad(),
165           PetscFileMode, PetscViewer
166 @*/
167 PetscErrorCode  PetscViewerHDF5Open(MPI_Comm comm, const char name[], PetscFileMode type, PetscViewer *hdf5v)
168 {
169   PetscErrorCode ierr;
170 
171   PetscFunctionBegin;
172   ierr = PetscViewerCreate(comm, hdf5v);CHKERRQ(ierr);
173   ierr = PetscViewerSetType(*hdf5v, PETSCVIEWERHDF5);CHKERRQ(ierr);
174   ierr = PetscViewerFileSetMode(*hdf5v, type);CHKERRQ(ierr);
175   ierr = PetscViewerFileSetName(*hdf5v, name);CHKERRQ(ierr);
176   PetscFunctionReturn(0);
177 }
178 
179 #undef __FUNCT__
180 #define __FUNCT__ "PetscViewerHDF5GetFileId"
181 /*@C
182   PetscViewerHDF5GetFileId - Retrieve the file id, this file ID then can be used in direct HDF5 calls
183 
184   Not collective
185 
186   Input Parameter:
187 . viewer - the PetscViewer
188 
189   Output Parameter:
190 . file_id - The file id
191 
192   Level: intermediate
193 
194 .seealso: PetscViewerHDF5Open()
195 @*/
196 PetscErrorCode  PetscViewerHDF5GetFileId(PetscViewer viewer, hid_t *file_id)
197 {
198   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *) viewer->data;
199 
200   PetscFunctionBegin;
201   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
202   if (file_id) *file_id = hdf5->file_id;
203   PetscFunctionReturn(0);
204 }
205 
206 #undef __FUNCT__
207 #define __FUNCT__ "PetscViewerHDF5PushGroup"
208 /*@C
209   PetscViewerHDF5PushGroup - Set the current HDF5 group for output
210 
211   Not collective
212 
213   Input Parameters:
214 + viewer - the PetscViewer
215 - name - The group name
216 
217   Level: intermediate
218 
219 .seealso: PetscViewerHDF5Open(),PetscViewerHDF5PopGroup(),PetscViewerHDF5GetGroup()
220 @*/
221 PetscErrorCode  PetscViewerHDF5PushGroup(PetscViewer viewer, const char *name)
222 {
223   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *) viewer->data;
224   GroupList        *groupNode;
225   PetscErrorCode    ierr;
226 
227   PetscFunctionBegin;
228   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
229   PetscValidCharPointer(name,2);
230   ierr = PetscMalloc(sizeof(GroupList), &groupNode);CHKERRQ(ierr);
231   ierr = PetscStrallocpy(name, (char **) &groupNode->name);CHKERRQ(ierr);
232   groupNode->next = hdf5->groups;
233   hdf5->groups    = groupNode;
234   PetscFunctionReturn(0);
235 }
236 
237 #undef __FUNCT__
238 #define __FUNCT__ "PetscViewerHDF5PopGroup"
239 /*@C
240   PetscViewerHDF5PopGroup - Return the current HDF5 group for output to the previous value
241 
242   Not collective
243 
244   Input Parameter:
245 . viewer - the PetscViewer
246 
247   Level: intermediate
248 
249 .seealso: PetscViewerHDF5Open(),PetscViewerHDF5PushGroup(),PetscViewerHDF5GetGroup()
250 @*/
251 PetscErrorCode  PetscViewerHDF5PopGroup(PetscViewer viewer)
252 {
253   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *) viewer->data;
254   GroupList        *groupNode;
255   PetscErrorCode    ierr;
256 
257   PetscFunctionBegin;
258   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
259   if (!hdf5->groups) SETERRQ(((PetscObject) viewer)->comm, PETSC_ERR_ARG_WRONGSTATE, "HDF5 group stack is empty, cannot pop");
260   groupNode    = hdf5->groups;
261   hdf5->groups = hdf5->groups->next;
262   ierr = PetscFree(groupNode->name);CHKERRQ(ierr);
263   ierr = PetscFree(groupNode);CHKERRQ(ierr);
264   PetscFunctionReturn(0);
265 }
266 
267 #undef __FUNCT__
268 #define __FUNCT__ "PetscViewerHDF5GetGroup"
269 /*@C
270   PetscViewerHDF5GetGroup - Get the current HDF5 group for output. If none has been assigned, returns PETSC_NULL.
271 
272   Not collective
273 
274   Input Parameter:
275 . viewer - the PetscViewer
276 
277   Output Parameter:
278 . name - The group name
279 
280   Level: intermediate
281 
282 .seealso: PetscViewerHDF5Open(),PetscViewerHDF5PushGroup(),PetscViewerHDF5PopGroup()
283 @*/
284 PetscErrorCode  PetscViewerHDF5GetGroup(PetscViewer viewer, const char **name)
285 {
286   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *) viewer->data;
287 
288   PetscFunctionBegin;
289   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
290   PetscValidCharPointer(name,2);
291   if (hdf5->groups) {
292     *name = hdf5->groups->name;
293   } else {
294     *name = PETSC_NULL;
295   }
296   PetscFunctionReturn(0);
297 }
298 
299 #undef __FUNCT__
300 #define __FUNCT__ "PetscViewerHDF5IncrementTimestep"
301 /*@C
302   PetscViewerHDF5IncrementTimestep - Increments the current timestep for the HDF5 output. Fields are stacked in time.
303 
304   Not collective
305 
306   Input Parameter:
307 . viewer - the PetscViewer
308 
309   Level: intermediate
310 
311 .seealso: PetscViewerHDF5Open(), PetscViewerHDF5SetTimestep(), PetscViewerHDF5GetTimestep()
312 @*/
313 PetscErrorCode PetscViewerHDF5IncrementTimestep(PetscViewer viewer)
314 {
315   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *) viewer->data;
316 
317   PetscFunctionBegin;
318   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
319   ++hdf5->timestep;
320   PetscFunctionReturn(0);
321 }
322 
323 #undef __FUNCT__
324 #define __FUNCT__ "PetscViewerHDF5SetTimestep"
325 /*@C
326   PetscViewerHDF5SetTimestep - Set the current timestep for the HDF5 output. Fields are stacked in time. A timestep
327   of -1 disables blocking with timesteps.
328 
329   Not collective
330 
331   Input Parameters:
332 + viewer - the PetscViewer
333 - timestep - The timestep number
334 
335   Level: intermediate
336 
337 .seealso: PetscViewerHDF5Open(), PetscViewerHDF5IncrementTimestep(), PetscViewerHDF5GetTimestep()
338 @*/
339 PetscErrorCode  PetscViewerHDF5SetTimestep(PetscViewer viewer, PetscInt timestep)
340 {
341   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *) viewer->data;
342 
343   PetscFunctionBegin;
344   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
345   hdf5->timestep = timestep;
346   PetscFunctionReturn(0);
347 }
348 
349 #undef __FUNCT__
350 #define __FUNCT__ "PetscViewerHDF5GetTimestep"
351 /*@C
352   PetscViewerHDF5GetTimestep - Get the current timestep for the HDF5 output. Fields are stacked in time.
353 
354   Not collective
355 
356   Input Parameter:
357 . viewer - the PetscViewer
358 
359   Output Parameter:
360 . timestep - The timestep number
361 
362   Level: intermediate
363 
364 .seealso: PetscViewerHDF5Open(), PetscViewerHDF5IncrementTimestep(), PetscViewerHDF5SetTimestep()
365 @*/
366 PetscErrorCode  PetscViewerHDF5GetTimestep(PetscViewer viewer, PetscInt *timestep)
367 {
368   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *) viewer->data;
369 
370   PetscFunctionBegin;
371   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
372   PetscValidPointer(timestep,2);
373   *timestep = hdf5->timestep;
374   PetscFunctionReturn(0);
375 }
376 
377 #if defined(oldhdf4stuff)
378 #undef __FUNCT__
379 #define __FUNCT__ "PetscViewerHDF5WriteSDS"
380 PetscErrorCode  PetscViewerHDF5WriteSDS(PetscViewer viewer, float *xf, int d, int *dims,int bs)
381 {
382  int                   i;
383  PetscViewer_HDF5      *vhdf5 = (PetscViewer_HDF5*)viewer->data;
384  int32                 sds_id,zero32[3],dims32[3];
385 
386  PetscFunctionBegin;
387  for (i = 0; i < d; i++) {
388    zero32[i] = 0;
389    dims32[i] = dims[i];
390  }
391  sds_id = SDcreate(vhdf5->sd_id, "Vec", DFNT_FLOAT32, d, dims32);
392  if (sds_id < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"SDcreate failed");
393  SDwritedata(sds_id, zero32, 0, dims32, xf);
394  SDendaccess(sds_id);
395  PetscFunctionReturn(0);
396 }
397 
398 #endif
399