Neko 1.1.0
A portable framework for high-order spectral element flow simulations
Loading...
Searching...
No Matches
hdf5_file.F90
Go to the documentation of this file.
1! Copyright (c) 2024-2025, The Neko Authors
2! All rights reserved.
3!
4! Redistribution and use in source and binary forms, with or without
5! modification, are permitted provided that the following conditions
6! are met:
7!
8! * Redistributions of source code must retain the above copyright
9! notice, this list of conditions and the following disclaimer.
10!
11! * Redistributions in binary form must reproduce the above
12! copyright notice, this list of conditions and the following
13! disclaimer in the documentation and/or other materials provided
14! with the distribution.
15!
16! * Neither the name of the authors nor the names of its
17! contributors may be used to endorse or promote products derived
18! from this software without specific prior written permission.
19!
20! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21! "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22! LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23! FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24! COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25! INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26! BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27! LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28! CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29! LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30! ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31! POSSIBILITY OF SUCH DAMAGE.
32!
35 use num_types, only : rp, dp, sp
37 use checkpoint, only : chkp_t
40 use mesh, only : mesh_t
41 use field, only : field_t, field_ptr_t
42 use field_list, only : field_list_t
44 use dofmap, only : dofmap_t
46 use vector, only : vector_t
47 use matrix, only : matrix_t
48 use datadist, only : linear_dist_t
49 use comm, only : pe_rank, pe_size, neko_comm
50 use mpi_f08, only : mpi_info_null, mpi_allreduce, mpi_allgather, &
51 mpi_in_place, mpi_integer, mpi_sum, mpi_max, mpi_comm_size, mpi_exscan, &
52 mpi_barrier, mpi_integer8, mpi_scan
53#ifdef HAVE_HDF5
54 use hdf5
55#endif
56 implicit none
57 private
58
60 type, public, extends(generic_file_t) :: hdf5_file_t
61
62 ! HDF5 members
63#ifdef HAVE_HDF5
64 integer(hid_t) :: file_id = -1_hid_t
65 integer(hid_t) :: active_group_id = -1_hid_t
66 integer(hid_t) :: plist_id = -1_hid_t
67#endif
68 character(len=1) :: mode
69 integer :: precision = -1
70 integer :: offset = 0
71 integer :: count = 0
72
73 contains
74 ! General methods for reading/writing HDF5 files
75 procedure :: read => hdf5_file_read
76 procedure :: write => hdf5_file_write
77 procedure :: set_overwrite => hdf5_file_set_overwrite
78 ! Granular methods for dealing with HDF5 files
79 procedure :: open => hdf5_file_open
80 procedure :: close => hdf5_file_close
81 procedure :: set_active_group => hdf5_file_set_group
82 procedure :: set_precision => hdf5_file_set_precision
83 procedure, pass(this) :: write_vector => hdf5_file_write_vector
84 procedure, pass(this) :: write_matrix => hdf5_file_write_matrix
85 procedure, pass(this) :: write_field => hdf5_file_write_field
86 procedure, pass(this) :: write_int_attribute => &
88 procedure, pass(this) :: write_rp_attribute => hdf5_file_write_rp_attribute
89 procedure, pass(this) :: read_vector => hdf5_file_read_vector
90 procedure, pass(this) :: read_matrix => hdf5_file_read_matrix
91 procedure, pass(this) :: read_int_attribute => hdf5_file_read_int_attribute
92 procedure, pass(this) :: read_rp_attribute => hdf5_file_read_rp_attribute
93 procedure :: write_dataset => hdf5_file_write_dataset
94 procedure :: read_dataset => hdf5_file_read_dataset
95 procedure :: write_attribute => hdf5_file_write_attribute
96 procedure :: read_attribute => hdf5_file_read_attribute
97 end type hdf5_file_t
98
99contains
100
102 subroutine hdf5_file_set_overwrite(this, overwrite)
103 class(hdf5_file_t), intent(inout) :: this
104 logical, intent(in) :: overwrite
105 this%overwrite = overwrite
106 end subroutine hdf5_file_set_overwrite
107
109 function file_get_fname(this) result(base_fname)
110 class(hdf5_file_t), intent(in) :: this
111 character(len=1024) :: base_fname
112 character(len=1024) :: fname
113 character(len=1024) :: path, name, suffix
114
115 fname = trim(this%get_base_fname())
116 call filename_split(fname, path, name, suffix)
117
118 ! Append a counter
119 !write(base_fname, '(A,A,"_",I0,A)') &
120 ! trim(path), trim(name), this%get_start_counter(), trim(suffix)
121
122 ! Do not append anything
123 base_fname = trim(fname)
124
125 end function file_get_fname
126
128 subroutine hdf5_file_set_precision(this, precision)
129 class(hdf5_file_t), intent(inout) :: this
130 integer, intent(in) :: precision
131 this%precision = precision
132 end subroutine hdf5_file_set_precision
133
134
135#ifdef HAVE_HDF5
136
137 ! ===============
138 ! General methods
139 ! ===============
140
142 subroutine hdf5_file_write(this, data, t)
143 class(hdf5_file_t), intent(inout) :: this
144 class(*), target, intent(in) :: data
145 real(kind=rp), intent(in), optional :: t
146 type(mesh_t), pointer :: msh
147 type(dofmap_t), pointer :: dof
148 type(field_ptr_t), allocatable :: fp(:)
149 type(field_series_ptr_t), allocatable :: fsp(:)
150 real(kind=rp), pointer :: dtlag(:)
151 real(kind=rp), pointer :: tlag(:)
152 integer :: ierr, info, drank, i, j
153 integer(hid_t) :: plist_id, file_id, dset_id, grp_id, attr_id
154 integer(hid_t) :: filespace, memspace
155 integer(hid_t) :: H5T_NEKO_REAL
156 integer(hsize_t), dimension(1) :: ddim, dcount, doffset
157 integer :: suffix_pos
158 character(len=5) :: id_str
159 character(len=1024) :: fname
160
161 call hdf5_file_determine_data(data, msh, dof, fp, fsp, dtlag, tlag)
162
163 if (.not. this%overwrite) call this%increment_counter()
164 fname = trim(this%get_fname())
165
166 call h5open_f(ierr)
167
168 call hdf5_file_determine_real(h5t_neko_real)
169
170 call h5pcreate_f(h5p_file_access_f, plist_id, ierr)
171 info = mpi_info_null%mpi_val
172 call h5pset_fapl_mpio_f(plist_id, neko_comm%mpi_val, info, ierr)
173
174 call h5fcreate_f(fname, h5f_acc_trunc_f, &
175 file_id, ierr, access_prp = plist_id)
176
177 call h5pcreate_f(h5p_dataset_xfer_f, plist_id, ierr)
178 call h5pset_dxpl_mpio_f(plist_id, h5fd_mpio_collective_f, ierr)
179
180 call h5screate_f(h5s_scalar_f, filespace, ierr)
181 ddim = 1
182
183 if (present(t)) then
184 call h5acreate_f(file_id, "Time", h5t_neko_real, filespace, attr_id, &
185 ierr, h5p_default_f, h5p_default_f)
186 call h5awrite_f(attr_id, h5t_neko_real, t, ddim, ierr)
187 call h5aclose_f(attr_id, ierr)
188 end if
189
190 if (associated(dof)) then
191 call h5acreate_f(file_id, "Lx", h5t_native_integer, filespace, attr_id, &
192 ierr, h5p_default_f, h5p_default_f)
193 call h5awrite_f(attr_id, h5t_native_integer, dof%Xh%lx, ddim, ierr)
194 call h5aclose_f(attr_id, ierr)
195 end if
196
197 if (associated(msh)) then
198 call h5gcreate_f(file_id, "Mesh", grp_id, ierr, &
199 lcpl_id = h5p_default_f, gcpl_id = h5p_default_f, &
200 gapl_id = h5p_default_f)
201
202 call h5acreate_f(grp_id, "Elements", h5t_native_integer, filespace, &
203 attr_id, ierr, h5p_default_f, h5p_default_f)
204 call h5awrite_f(attr_id, h5t_native_integer, msh%glb_nelv, ddim, ierr)
205 call h5aclose_f(attr_id, ierr)
206
207 call h5acreate_f(grp_id, "Dimension", h5t_native_integer, filespace, &
208 attr_id, ierr, h5p_default_f, h5p_default_f)
209 call h5awrite_f(attr_id, h5t_native_integer, msh%gdim, ddim, ierr)
210 call h5aclose_f(attr_id, ierr)
211
212 call h5gclose_f(grp_id, ierr)
213 end if
214
215
216 call h5sclose_f(filespace, ierr)
217
218 !
219 ! Write restart group (tlag, dtlag)
220 !
221 if (associated(tlag) .and. associated(dtlag)) then
222 call h5gcreate_f(file_id, "Restart", grp_id, ierr, &
223 lcpl_id = h5p_default_f, gcpl_id = h5p_default_f, &
224 gapl_id = h5p_default_f)
225
226 drank = 1
227 ddim = size(tlag)
228 doffset(1) = 0
229 if (pe_rank .eq. 0) then
230 dcount = size(tlag)
231 else
232 dcount = 0
233 end if
234
235 call h5screate_simple_f(drank, ddim, filespace, ierr)
236
237 call h5dcreate_f(grp_id, 'tlag', h5t_neko_real, &
238 filespace, dset_id, ierr)
239 call h5dget_space_f(dset_id, filespace, ierr)
240 call h5sselect_hyperslab_f (filespace, h5s_select_set_f, &
241 doffset, dcount, ierr)
242 call h5dwrite_f(dset_id, h5t_neko_real, tlag, &
243 ddim, ierr, xfer_prp = plist_id)
244 call h5dclose_f(dset_id, ierr)
245
246 call h5dcreate_f(grp_id, 'dtlag', h5t_neko_real, &
247 filespace, dset_id, ierr)
248 call h5dget_space_f(dset_id, filespace, ierr)
249 call h5sselect_hyperslab_f (filespace, h5s_select_set_f, &
250 doffset, dcount, ierr)
251 call h5dwrite_f(dset_id, h5t_neko_real, dtlag, &
252 ddim, ierr, xfer_prp = plist_id)
253 call h5dclose_f(dset_id, ierr)
254
255 call h5sclose_f(filespace, ierr)
256 call h5gclose_f(grp_id, ierr)
257
258 end if
259
260
261 !
262 ! Write fields group
263 !
264 if (allocated(fp) .or. allocated(fsp)) then
265 call h5gcreate_f(file_id, "Fields", grp_id, ierr, &
266 lcpl_id = h5p_default_f, gcpl_id = h5p_default_f, &
267 gapl_id = h5p_default_f)
268
269 dcount(1) = int(dof%size(), 8)
270 doffset(1) = int(msh%offset_el, 8) * int((dof%Xh%lx**3),8)
271 ddim = int(dof%size(), 8)
272 drank = 1
273 call mpi_allreduce(mpi_in_place, ddim(1), 1, &
274 mpi_integer8, mpi_sum, neko_comm, ierr)
275
276 call h5screate_simple_f(drank, ddim, filespace, ierr)
277 call h5screate_simple_f(drank, dcount, memspace, ierr)
278
279
280 if (allocated(fp)) then
281 do i = 1, size(fp)
282 call h5dcreate_f(grp_id, fp(i)%ptr%name, h5t_neko_real, &
283 filespace, dset_id, ierr)
284 call h5dget_space_f(dset_id, filespace, ierr)
285 call h5sselect_hyperslab_f(filespace, h5s_select_set_f, &
286 doffset, dcount, ierr)
287 call h5dwrite_f(dset_id, h5t_neko_real, &
288 fp(i)%ptr%x(1,1,1,1), &
289 ddim, ierr, file_space_id = filespace, &
290 mem_space_id = memspace, xfer_prp = plist_id)
291 call h5dclose_f(dset_id, ierr)
292 end do
293 deallocate(fp)
294 end if
295
296 if (allocated(fsp)) then
297 do i = 1, size(fsp)
298 do j = 1, fsp(i)%ptr%size()
299 call h5dcreate_f(grp_id, fsp(i)%ptr%lf(j)%name, &
300 h5t_neko_real, filespace, dset_id, ierr)
301 call h5dget_space_f(dset_id, filespace, ierr)
302 call h5sselect_hyperslab_f(filespace, h5s_select_set_f, &
303 doffset, dcount, ierr)
304 call h5dwrite_f(dset_id, h5t_neko_real, &
305 fsp(i)%ptr%lf(j)%x(1,1,1,1), &
306 ddim, ierr, file_space_id = filespace, &
307 mem_space_id = memspace, xfer_prp = plist_id)
308 call h5dclose_f(dset_id, ierr)
309 end do
310 end do
311 deallocate(fsp)
312 end if
313
314 call h5gclose_f(grp_id, ierr)
315 call h5sclose_f(filespace, ierr)
316 call h5sclose_f(memspace, ierr)
317 end if
318
319 call h5pclose_f(plist_id, ierr)
320 call h5fclose_f(file_id, ierr)
321 call h5close_f(ierr)
322
323 end subroutine hdf5_file_write
324
326 subroutine hdf5_file_read(this, data)
327 class(hdf5_file_t) :: this
328 class(*), target, intent(inout) :: data
329 integer(hid_t) :: plist_id, file_id, dset_id, grp_id, attr_id
330 integer(hid_t) :: filespace, memspace
331 integer(hid_t) :: H5T_NEKO_REAL
332 integer(hsize_t), dimension(1) :: ddim, dcount, doffset
333 integer :: i,j, ierr, info, glb_nelv, gdim, lx, drank
334 type(mesh_t), pointer :: msh
335 type(dofmap_t), pointer :: dof
336 type(field_ptr_t), allocatable :: fp(:)
337 type(field_series_ptr_t), allocatable :: fsp(:)
338 real(kind=rp), pointer :: dtlag(:)
339 real(kind=rp), pointer :: tlag(:)
340 real(kind=rp) :: t
341 character(len=1024) :: fname
342
343 fname = trim(this%get_fname())
344
345 call h5open_f(ierr)
346
347 call hdf5_file_determine_data(data, msh, dof, fp, fsp, dtlag, tlag)
348 call hdf5_file_determine_real(h5t_neko_real)
349
350 call h5pcreate_f(h5p_file_access_f, plist_id, ierr)
351 info = mpi_info_null%mpi_val
352 call h5pset_fapl_mpio_f(plist_id, neko_comm%mpi_val, info, ierr)
353
354 call h5fopen_f(fname, h5f_acc_rdonly_f, &
355 file_id, ierr, access_prp = plist_id)
356
357 call h5pcreate_f(h5p_dataset_xfer_f, plist_id, ierr)
358 call h5pset_dxpl_mpio_f(plist_id, h5fd_mpio_collective_f, ierr)
359
360 ddim = 1
361 call h5aopen_name_f(file_id, 'Time', attr_id, ierr)
362 call h5aread_f(attr_id, h5t_neko_real, t, ddim, ierr)
363 call h5aclose_f(attr_id, ierr)
364
365 select type (data)
366 type is (chkp_t)
367 data%t = t
368 end select
369
370 call h5aopen_name_f(file_id, 'Lx', attr_id, ierr)
371 call h5aread_f(attr_id, h5t_native_integer, lx, ddim, ierr)
372 call h5aclose_f(attr_id, ierr)
373
374 call h5gopen_f(file_id, 'Mesh', grp_id, ierr, gapl_id = h5p_default_f)
375
376 call h5aopen_name_f(grp_id, 'Elements', attr_id, ierr)
377 call h5aread_f(attr_id, h5t_native_integer, glb_nelv, ddim, ierr)
378 call h5aclose_f(attr_id, ierr)
379
380 call h5aopen_name_f(grp_id, 'Dimension', attr_id, ierr)
381 call h5aread_f(attr_id, h5t_native_integer, gdim, ddim, ierr)
382 call h5aclose_f(attr_id, ierr)
383 call h5gclose_f(grp_id, ierr)
384
385
386 if (associated(tlag) .and. associated(dtlag)) then
387 drank = 1
388 ddim = size(tlag)
389 doffset(1) = 0
390 if (pe_rank .eq. 0) then
391 dcount = size(tlag)
392 else
393 dcount = 0
394 end if
395
396 call h5gopen_f(file_id, 'Restart', grp_id, ierr, &
397 gapl_id = h5p_default_f)
398 call h5dopen_f(grp_id, 'tlag', dset_id, ierr)
399 call h5dget_space_f(dset_id, filespace, ierr)
400 call h5sselect_hyperslab_f (filespace, h5s_select_set_f, &
401 doffset, dcount, ierr)
402 call h5dread_f(dset_id, h5t_neko_real, tlag, ddim, ierr, &
403 xfer_prp = plist_id)
404 call h5dclose_f(dset_id, ierr)
405 call h5sclose_f(filespace, ierr)
406
407 call h5dopen_f(grp_id, 'dtlag', dset_id, ierr)
408 call h5dget_space_f(dset_id, filespace, ierr)
409 call h5sselect_hyperslab_f (filespace, h5s_select_set_f, &
410 doffset, dcount, ierr)
411 call h5dread_f(dset_id, h5t_neko_real, dtlag, ddim, ierr, &
412 xfer_prp = plist_id)
413 call h5dclose_f(dset_id, ierr)
414 call h5sclose_f(filespace, ierr)
415
416 call h5gclose_f(grp_id, ierr)
417 end if
418
419 if (allocated(fp) .or. allocated(fsp)) then
420 call h5gopen_f(file_id, 'Fields', grp_id, ierr, gapl_id = h5p_default_f)
421
422 dcount(1) = int(dof%size(), 8)
423 doffset(1) = int(msh%offset_el, 8) * int((dof%Xh%lx**3),8)
424 ddim = int(dof%size(), 8)
425 drank = 1
426
427 dcount(1) = int(dof%size(), 8)
428 doffset(1) = int(msh%offset_el, 8) * int((dof%Xh%lx**3),8)
429 ddim = int(dof%size(), 8)
430 drank = 1
431 call mpi_allreduce(mpi_in_place, ddim(1), 1, &
432 mpi_integer8, mpi_sum, neko_comm, ierr)
433
434 call h5screate_simple_f(drank, dcount, memspace, ierr)
435
436 if (allocated(fp)) then
437 do i = 1, size(fp)
438 call h5dopen_f(grp_id, fp(i)%ptr%name, dset_id, ierr)
439 call h5dget_space_f(dset_id, filespace, ierr)
440 call h5sselect_hyperslab_f (filespace, h5s_select_set_f, &
441 doffset, dcount, ierr)
442 call h5dread_f(dset_id, h5t_neko_real, &
443 fp(i)%ptr%x(1,1,1,1), &
444 ddim, ierr, file_space_id = filespace, &
445 mem_space_id = memspace, xfer_prp = plist_id)
446 call h5dclose_f(dset_id, ierr)
447 call h5sclose_f(filespace, ierr)
448 end do
449 end if
450
451 if (allocated(fsp)) then
452 do i = 1, size(fsp)
453 do j = 1, fsp(i)%ptr%size()
454 call h5dopen_f(grp_id, fsp(i)%ptr%lf(j)%name, dset_id, ierr)
455 call h5dget_space_f(dset_id, filespace, ierr)
456 call h5sselect_hyperslab_f (filespace, h5s_select_set_f, &
457 doffset, dcount, ierr)
458 call h5dread_f(dset_id, h5t_neko_real, &
459 fsp(i)%ptr%lf(j)%x(1,1,1,1), &
460 ddim, ierr, file_space_id = filespace, &
461 mem_space_id = memspace, xfer_prp = plist_id)
462 call h5dclose_f(dset_id, ierr)
463 call h5sclose_f(filespace, ierr)
464 end do
465 end do
466 end if
467 call h5sclose_f(memspace, ierr)
468 call h5gclose_f(grp_id, ierr)
469 end if
470
471 call h5pclose_f(plist_id, ierr)
472 call h5fclose_f(file_id, ierr)
473 call h5close_f(ierr)
474
475 end subroutine hdf5_file_read
476
477
478 subroutine hdf5_file_determine_data(data, msh, dof, fp, fsp, dtlag, tlag)
479 class(*), target, intent(in) :: data
480 type(mesh_t), pointer, intent(inout) :: msh
481 type(dofmap_t), pointer, intent(inout) :: dof
482 type(field_ptr_t), allocatable, intent(inout) :: fp(:)
483 type(field_series_ptr_t), allocatable, intent(inout) :: fsp(:)
484 real(kind=rp), pointer, intent(inout) :: dtlag(:)
485 real(kind=rp), pointer, intent(inout) :: tlag(:)
486 integer :: i, j, fp_size, fp_cur, fsp_size, fsp_cur, scalar_count, ab_count
487 character(len=32) :: scalar_name
488
489 select type (data)
490 type is (field_t)
491 dof => data%dof
492 msh => data%msh
493 fp_size = 1
494 allocate(fp(fp_size))
495 fp(1)%ptr => data
496
497 nullify(dtlag)
498 nullify(tlag)
499
500 type is (field_list_t)
501
502 if (data%size() .gt. 0) then
503 allocate(fp(data%size()))
504
505 dof => data%dof(1)
506 msh => data%msh(1)
507
508 do i = 1, data%size()
509 fp(i)%ptr => data%items(i)%ptr
510 end do
511 else
512 call neko_error('Empty field list')
513 end if
514
515 nullify(dtlag)
516 nullify(tlag)
517
518 type is (chkp_t)
519
520 if ( .not. associated(data%u) .or. &
521 .not. associated(data%v) .or. &
522 .not. associated(data%w) .or. &
523 .not. associated(data%p) ) then
524 call neko_error('Checkpoint not initialized')
525 end if
526
527 fp_size = 4
528
529 if (allocated(data%scalar_lags%items) .and. &
530 data%scalar_lags%size() > 0) then
531 scalar_count = data%scalar_lags%size()
532 else if (associated(data%s)) then
533 scalar_count = 1
534 else
535 scalar_count = 0
536 end if
537
538 if (scalar_count .gt. 1) then
539 fp_size = fp_size + scalar_count
540
541 ! Add abx1 and abx2 fields for each scalar
542 fp_size = fp_size + (scalar_count * 2)
543 else if (associated(data%s)) then
544 ! Single scalar support
545 fp_size = fp_size + 1
546 if (associated(data%abs1)) then
547 fp_size = fp_size + 2
548 end if
549 end if
550
551 if (associated(data%abx1)) then
552 fp_size = fp_size + 6
553 end if
554
555 allocate(fp(fp_size))
556
557 fsp_size = 0
558 if (associated(data%ulag)) then
559 fsp_size = fsp_size + 3
560 end if
561
562 if (scalar_count .gt. 1) then
563 if (allocated(data%scalar_lags%items)) then
564 fsp_size = fsp_size + data%scalar_lags%size()
565 end if
566 else if (associated(data%slag)) then
567 fsp_size = fsp_size + 1
568 end if
569
570 if (fsp_size .gt. 0) then
571 allocate(fsp(fsp_size))
572 fsp_cur = 1
573 end if
574
575 dof => data%u%dof
576 msh => data%u%msh
577
578 fp(1)%ptr => data%u
579 fp(2)%ptr => data%v
580 fp(3)%ptr => data%w
581 fp(4)%ptr => data%p
582
583 fp_cur = 5
584
585 if (scalar_count .gt. 1) then
586 block
587 type(field_series_t), pointer :: slag
588 do i = 1, scalar_count
589 slag => data%scalar_lags%get(i)
590 fp(fp_cur)%ptr => slag%f
591 fp_cur = fp_cur + 1
592 end do
593 end block
594
595 do i = 1, scalar_count
596 fp(fp_cur)%ptr => data%scalar_abx1(i)%ptr
597 fp_cur = fp_cur + 1
598 fp(fp_cur)%ptr => data%scalar_abx2(i)%ptr
599 fp_cur = fp_cur + 1
600 end do
601 else if (associated(data%s)) then
602 ! Single scalar support
603 fp(fp_cur)%ptr => data%s
604 fp_cur = fp_cur + 1
605
606 if (associated(data%abs1)) then
607 fp(fp_cur)%ptr => data%abs1
608 fp(fp_cur+1)%ptr => data%abs2
609 fp_cur = fp_cur + 2
610 end if
611 end if
612
613 if (associated(data%abx1)) then
614 fp(fp_cur)%ptr => data%abx1
615 fp(fp_cur+1)%ptr => data%abx2
616 fp(fp_cur+2)%ptr => data%aby1
617 fp(fp_cur+3)%ptr => data%aby2
618 fp(fp_cur+4)%ptr => data%abz1
619 fp(fp_cur+5)%ptr => data%abz2
620 fp_cur = fp_cur + 6
621 end if
622
623 if (associated(data%ulag)) then
624 fsp(fsp_cur)%ptr => data%ulag
625 fsp(fsp_cur+1)%ptr => data%vlag
626 fsp(fsp_cur+2)%ptr => data%wlag
627 fsp_cur = fsp_cur + 3
628 end if
629
630
631 if (scalar_count .gt. 1) then
632 if (allocated(data%scalar_lags%items)) then
633 do j = 1, data%scalar_lags%size()
634 fsp(fsp_cur)%ptr => data%scalar_lags%get(j)
635 fsp_cur = fsp_cur + 1
636 end do
637 end if
638 else if (associated(data%slag)) then
639 fsp(fsp_cur)%ptr => data%slag
640 fsp_cur = fsp_cur + 1
641 end if
642
643 if (associated(data%tlag)) then
644 tlag => data%tlag
645 dtlag => data%dtlag
646 end if
647
648 class default
649 call neko_log%error('Invalid data')
650 end select
651
652 end subroutine hdf5_file_determine_data
653
657 subroutine hdf5_file_determine_real(H5T_NEKO_REAL)
658 integer(hid_t), intent(inout) :: H5T_NEKO_REAL
659 select case (rp)
660 case (dp)
661 h5t_neko_real = h5t_native_double
662 case (sp)
663 h5t_neko_real = h5t_native_real
664 case default
665 call neko_error("Unsupported real type")
666 end select
667 end subroutine hdf5_file_determine_real
668
669 ! ================
670 ! Granular methods
671 ! ================
672
674 subroutine hdf5_file_open(this, mode)
675 class(hdf5_file_t), intent(inout) :: this
676 character(len=1), intent(in) :: mode
677 integer :: ierr, mpi_info, mpi_comm, i, n_fields, counter
678 logical :: file_exists
679 character(len=1024) :: fname
680 character(len=LOG_SIZE) :: log_buf
681
682 ! Set the mode for the file
683 this%mode = mode
684
685 ! Ensure precision is set and are valid.
686 if (this%precision .gt. rp) then
687 this%precision = rp
688 call neko_warning('Requested precision is higher than working precision')
689 else if (this%precision .eq. -1) then
690 this%precision = rp
691 end if
692
693 fname = trim(file_get_fname(this))
694 counter = this%get_counter() - this%get_start_counter()
695
696 ! Set the configuration for MPI IO
697 call h5open_f(ierr)
698
699 mpi_info = mpi_info_null%mpi_val
700 mpi_comm = neko_comm%mpi_val
701 call h5pcreate_f(h5p_file_access_f, this%plist_id, ierr)
702 call h5pset_fapl_mpio_f(this%plist_id, mpi_comm, mpi_info, ierr)
703
704 ! Open the file
705 inquire(file = fname, exist = file_exists)
706 if (file_exists) then
707 call h5fopen_f(fname, h5f_acc_rdwr_f, this%file_id, ierr, &
708 access_prp = this%plist_id)
709 else
710 call h5fcreate_f(fname, h5f_acc_trunc_f, &
711 this%file_id, ierr, access_prp = this%plist_id)
712 end if
713
714 ! Set the active group to the root of the file
715 call this%set_active_group()
716
717 write (log_buf, *) "Opened HDF5 file: ", trim(fname), " with counter: ", &
718 counter
719 call neko_log%message(log_buf, lvl = neko_log_debug)
720
721 end subroutine hdf5_file_open
722
724 subroutine hdf5_file_close(this)
725 class(hdf5_file_t), intent(inout) :: this
726 integer :: ierr
727
728 if (this%active_group_id .ne. -1_hid_t .and. &
729 this%active_group_id .ne. this%file_id) then
730 call h5gclose_f(this%active_group_id, ierr)
731 end if
732 this%active_group_id = -1_hid_t
733
734 call h5pclose_f(this%plist_id, ierr)
735 this%plist_id = -1_hid_t
736 call h5fclose_f(this%file_id, ierr)
737 this%file_id = -1_hid_t
738 call h5close_f(ierr)
739
740 call neko_log%message("Closed HDF5 file: " // trim(this%get_fname()), &
741 lvl = neko_log_debug)
742
743 end subroutine hdf5_file_close
744
745
749 subroutine hdf5_file_set_group(this, group_name_path)
750 class(hdf5_file_t), intent(inout) :: this
751 character(len=*), intent(in), optional :: group_name_path
752 character(len=1000), allocatable :: group_name(:)
753
754 integer(hid_t) :: current_id, group_id
755 integer :: ierr, i, j, num_groups, name_len, group_loc
756 logical :: group_exists
757
758
759 ! Close previous active group if one is open
760 if (this%active_group_id .ne. -1_hid_t .and. this%active_group_id .ne. &
761 this%file_id) then
762 call h5gclose_f(this%active_group_id, ierr)
763 end if
764 this%active_group_id = -1_hid_t
765
766 ! Start from root location = file
767 current_id = this%file_id
768 ! Return the root directory if no group name is given
769 if (.not. present(group_name_path)) then
770 this%active_group_id = current_id
771 return
772 end if
773
774 ! Split the input string into group names using "/" as a delimiter
775 name_len = len(trim(group_name_path))
776 ! Count how many groups
777 num_groups = 1 ! There is at least one group if this was passed
778 do i = 1, name_len
779 if (group_name_path .eq. "/") then
780 num_groups = num_groups + 1
781 end if
782 end do
783
784 ! Allocate the group array and populate it
785 allocate(group_name(num_groups))
786 j = 1
787 group_loc = 1
788 do i = 1, name_len
789 if (group_name_path .eq. "/") then
790 group_name(group_loc) = group_name_path(j:i-1)
791 group_loc = group_loc + 1
792 j = i + 1
793 end if
794 end do
795 if (j .ne. name_len) then
796 group_name(group_loc) = group_name_path(j:name_len)
797 end if
798
799 ! Iterate over the groups in the path
800 do i = 1, num_groups
801 call h5lexists_f(current_id, trim(group_name(i)), group_exists, ierr)
802
803 ! Only create groups if they dont exist and we are in write mode "w"
804 if (group_exists) then
805 call h5gopen_f(current_id, trim(group_name(i)), group_id, ierr)
806 else
807 if (this%mode == "r") then
808 call neko_error("Group " // trim(group_name(i)) // &
809 " does not exist in file " // trim(file_get_fname(this)))
810 end if
811 call h5gcreate_f(current_id, trim(group_name(i)), group_id, ierr)
812 end if
813
814 ! Close previous location only if it was an opened group, not the file
815 if (i > 1) then
816 call h5gclose_f(current_id, ierr)
817 end if
818
819 current_id = group_id
820 end do
821
822 this%active_group_id = current_id
823 end subroutine hdf5_file_set_group
824
825
826 subroutine hdf5_file_write_dataset(this, data)
827 class(hdf5_file_t), intent(inout) :: this
828 class(*), intent(inout) :: data
829
830 select type (d => data)
831 type is (vector_t)
832 call this%write_vector(d)
833 type is (matrix_t)
834 call this%write_matrix(d)
835 type is (field_t)
836 call this%write_field(d)
837 class default
838 call neko_error("write_dataset not implemented for this data type")
839 end select
840 end subroutine hdf5_file_write_dataset
841
842 subroutine hdf5_file_read_dataset(this, data_name, data, strategy)
843 class(hdf5_file_t), intent(inout) :: this
844 character(len=*), intent(in) :: data_name
845 class(*), intent(inout) :: data
846 character(len=*), intent(in), optional :: strategy
847
848 select type (d => data)
849 type is (vector_t)
850 call this%read_vector(data_name, d, strategy)
851 type is (matrix_t)
852 call this%read_matrix(data_name, d, strategy)
853 type is (field_t)
854 call neko_error("Reading a field_t is not supported yet")
855 class default
856 call neko_error("read_dataset not implemented for this data type")
857 end select
858 end subroutine hdf5_file_read_dataset
859
860 subroutine hdf5_file_write_attribute(this, data_name, data)
861 class(hdf5_file_t), intent(inout) :: this
862 character(len=*), intent(in) :: data_name
863 class(*), intent(inout) :: data
864
865 select type (d => data)
866 type is (integer)
867 call this%write_int_attribute(data_name, d)
868 type is (real(kind=rp))
869 call this%write_rp_attribute(data_name, d)
870 class default
871 call neko_error("write_attribute not implemented for this data type")
872 end select
873 end subroutine hdf5_file_write_attribute
874
875 subroutine hdf5_file_read_attribute(this, data_name, data, exist)
876 class(hdf5_file_t), intent(inout) :: this
877 character(len=*), intent(in) :: data_name
878 class(*), intent(inout) :: data
879 logical, intent(inout) :: exist
880
881 select type (d => data)
882 type is (integer)
883 call this%read_int_attribute(data_name, d, exist)
884 type is (real(kind=rp))
885 call this%read_rp_attribute(data_name, d, exist)
886 class default
887 call neko_error("read_attribute not implemented for this data type")
888 end select
889 end subroutine hdf5_file_read_attribute
890
891
892 subroutine hdf5_file_write_vector(this, vec)
893 class(hdf5_file_t), intent(inout) :: this
894 type(vector_t), intent(inout) :: vec
895 integer :: ierr, counts, offset, total_count, dset_rank, max_count
896 integer(hsize_t) :: append_offset
897 integer(hid_t) :: precision_hdf
898 integer(hid_t) :: xf_id, filespace, dset_id, memspace, dcpl_id
899 integer(hsize_t), dimension(1) :: dcount, doffset
900 integer(hsize_t), dimension(1) :: ddims, ddims_max, chunkdims
901 integer(hsize_t), dimension(1) :: tempddims, tempmaxddims
902 logical :: dset_exists
903 real(kind=sp), allocatable :: write_buffer_sp(:) ! Write buffer single
904 real(kind=dp), allocatable :: write_buffer_dp(:) ! Write buffer double
905
906 ! ===============
907 ! Get vector info
908 ! ===============
909 counts = vec%size()
910 append_offset = 0_hsize_t
911 offset = 0
912 total_count = 0
913 max_count = 0
914 call mpi_scan(counts, offset, 1, mpi_integer, &
915 mpi_sum, neko_comm, ierr)
916 offset = offset - counts ! Not using exclusive scan
917 call mpi_allreduce(counts, total_count, 1, mpi_integer, &
918 mpi_sum, neko_comm, ierr)
919 call mpi_allreduce(counts, max_count, 1, mpi_integer, &
920 mpi_max, neko_comm, ierr)
921
922 ! ===============
923 ! Configure MPIIO
924 ! ===============
925 call h5pcreate_f(h5p_dataset_xfer_f, xf_id, ierr)
926 call h5pset_dxpl_mpio_f(xf_id, h5fd_mpio_collective_f, ierr)
927 precision_hdf = h5kind_to_type(this%precision, h5_real_kind)
928
929 ! ===================
930 ! Create the data set
931 ! ===================
932 dset_rank = 1 ! rank 1 array, i.e. a vector
933 ddims = [int(total_count, hsize_t)] ! global size of the vector
934
935 ! Enable chunking to be able to append
936 chunkdims = [max(int(max_count, hsize_t), 1_hsize_t)]
937 ddims_max = [h5s_unlimited_f] ! allow unlimited size for appending
938 call h5lexists_f(this%active_group_id, trim(vec%name), dset_exists, ierr)
939 if (dset_exists) then
940 if (this%overwrite) then
941 ! retrieve the dset id for the existing data set
942 call h5dopen_f(this%active_group_id, trim(vec%name), dset_id, ierr)
943 else
944 ! Retreive the existing data set
945 call h5dopen_f(this%active_group_id, trim(vec%name), dset_id, ierr)
946 ! Retrieve the current filespace (shape space)
947 call h5dget_space_f(dset_id, filespace, ierr)
948 ! Get the current shape
949 call h5sget_simple_extent_dims_f(filespace, tempddims, tempmaxddims, &
950 ierr)
951 ! Clean up the opened file space
952 call h5sclose_f(filespace, ierr)
953 ! Overwrite the new full shape
954 ddims(1) = ddims(1) + tempddims(1) ! New size
955 append_offset = tempddims(1) ! current size which is the offset
956 ! Extend the data set to the new shape
957 call h5dset_extent_f(dset_id, ddims, ierr)
958 end if
959 else
960 ! create file space of this shape
961 call h5screate_simple_f(dset_rank, ddims, filespace, ierr, ddims_max)
962 ! Create chunk property list (needed to be able to append)
963 call h5pcreate_f(h5p_dataset_create_f, dcpl_id, ierr)
964 call h5pset_chunk_f(dcpl_id, dset_rank, chunkdims, ierr)
965 ! create the data set with the given shape
966 call h5dcreate_f(this%active_group_id, trim(vec%name), precision_hdf, &
967 filespace, dset_id, ierr, dcpl_id = dcpl_id)
968 ! clean opened ids
969 call h5sclose_f(filespace, ierr)
970 call h5pclose_f(dcpl_id, ierr)
971 end if
972
973 ! ===========================
974 ! Set up writing the data set
975 ! ===========================
976 dcount = [int(counts, hsize_t)] ! local size of the vector
977
978 ! offset for this rank in the global vector
979 doffset = [int(offset, hsize_t) + append_offset]
980 ! Get the total file space (shape) of the data set
981 call h5dget_space_f(dset_id, filespace, ierr)
982 ! Get only the slice where my rank writes
983 call h5sselect_hyperslab_f(filespace, h5s_select_set_f, doffset, dcount, &
984 ierr)
985 ! Create the corresponding memory space (buffer) for my local data
986 call h5screate_simple_f(dset_rank, dcount, memspace, ierr)
987
988
989 ! =======================
990 ! Cast and write the data
991 ! =======================
992 if (this%precision == sp) then
993 allocate(write_buffer_sp(vec%size()))
994 if (vec%size() > 0) write_buffer_sp = real(vec%x, kind=sp)
995 ! Write the data
996 call h5dwrite_f(dset_id, precision_hdf, write_buffer_sp, dcount, ierr, &
997 file_space_id = filespace, mem_space_id = memspace, &
998 xfer_prp = xf_id)
999 deallocate(write_buffer_sp)
1000 else if (this%precision == dp) then
1001 allocate(write_buffer_dp(vec%size()))
1002 if (vec%size() > 0) write_buffer_dp = real(vec%x, kind=dp)
1003 ! Write the data
1004 call h5dwrite_f(dset_id, precision_hdf, write_buffer_dp, dcount, ierr, &
1005 file_space_id = filespace, mem_space_id = memspace, &
1006 xfer_prp = xf_id)
1007 deallocate(write_buffer_dp)
1008 else
1009 call neko_error("Unsupported precision")
1010 end if
1011
1012 ! =======================
1013 ! Clean up
1014 ! =======================
1015 call h5pclose_f(xf_id, ierr)
1016 call h5sclose_f(memspace, ierr)
1017 call h5sclose_f(filespace, ierr)
1018 call h5dclose_f(dset_id, ierr)
1019
1020 end subroutine hdf5_file_write_vector
1021
1022 subroutine hdf5_file_write_matrix(this, mat)
1023 class(hdf5_file_t), intent(inout) :: this
1024 type(matrix_t), intent(inout) :: mat
1025 integer :: ierr, counts, offset, total_count, dset_rank, strides, max_count
1026 integer(hsize_t) :: append_offset
1027 integer(hid_t) :: precision_hdf
1028 integer(hid_t) :: xf_id, filespace, dset_id, memspace, dcpl_id
1029 integer(hsize_t), dimension(2) :: dcount, doffset
1030 integer(hsize_t), dimension(2) :: ddims, ddims_max, chunkdims
1031 integer(hsize_t), dimension(2) :: tempddims, tempmaxddims
1032 logical :: dset_exists
1033 real(kind=sp), allocatable :: write_buffer_sp(:,:) ! Write buffer single
1034 real(kind=dp), allocatable :: write_buffer_dp(:,:) ! Write buffer double
1035
1036 ! ===============
1037 ! Get Matrix info
1038 ! ===============
1039 strides = mat%get_nrows()
1040 counts = mat%get_ncols()
1041 append_offset = 0_hsize_t
1042 total_count = 0
1043 max_count = 0
1044 offset = 0
1045 call mpi_scan(counts, offset, 1, mpi_integer, &
1046 mpi_sum, neko_comm, ierr)
1047 offset = offset - counts ! Not using exclusive scan
1048 call mpi_allreduce(counts, total_count, 1, mpi_integer, &
1049 mpi_sum, neko_comm, ierr)
1050 call mpi_allreduce(counts, max_count, 1, mpi_integer, &
1051 mpi_max, neko_comm, ierr)
1052
1053 ! ===============
1054 ! Configure MPIIO
1055 ! ===============
1056 call h5pcreate_f(h5p_dataset_xfer_f, xf_id, ierr)
1057 call h5pset_dxpl_mpio_f(xf_id, h5fd_mpio_collective_f, ierr)
1058 precision_hdf = h5kind_to_type(this%precision, h5_real_kind)
1059
1060 ! ===================
1061 ! Create the data set
1062 ! ===================
1063 dset_rank = 2 ! rank 2 array, i.e. a matrix
1064 ! global size of the matrix
1065 ddims = [int(strides, hsize_t), int(total_count, hsize_t)]
1066 chunkdims = [int(strides, hsize_t), max(int(max_count, hsize_t), 1_hsize_t)]
1067 ddims_max = [int(strides, hsize_t), h5s_unlimited_f]
1068 call h5lexists_f(this%active_group_id, trim(mat%name), dset_exists, ierr)
1069 if (dset_exists) then
1070 if (this%overwrite) then
1071
1072 if (pe_rank .eq. 0) then
1073 call neko_warning("Dataset " // trim(mat%name) // &
1074 " already exists and wil be overwritten")
1075 end if
1076 ! retrieve the dset id for the existing data set
1077 call h5dopen_f(this%active_group_id, trim(mat%name), dset_id, ierr)
1078 else
1079 call h5dopen_f(this%active_group_id, trim(mat%name), dset_id, ierr)
1080 call h5dget_space_f(dset_id, filespace, ierr)
1081 call h5sget_simple_extent_dims_f(filespace, tempddims, tempmaxddims, &
1082 ierr)
1083 call h5sclose_f(filespace, ierr)
1084 ddims(2) = ddims(2) + tempddims(2)
1085 append_offset = tempddims(2)
1086 call h5dset_extent_f(dset_id, ddims, ierr)
1087 end if
1088 else
1089 ! create file space of this shape
1090 call h5screate_simple_f(dset_rank, ddims, filespace, ierr, ddims_max)
1091 call h5pcreate_f(h5p_dataset_create_f, dcpl_id, ierr)
1092 call h5pset_chunk_f(dcpl_id, dset_rank, chunkdims, ierr)
1093 ! create the data set with the given shape
1094 call h5dcreate_f(this%active_group_id, trim(mat%name), precision_hdf, &
1095 filespace, dset_id, ierr, dcpl_id = dcpl_id)
1096 call h5sclose_f(filespace, ierr)
1097 call h5pclose_f(dcpl_id, ierr)
1098 end if
1099
1100 ! ===========================
1101 ! Set up writing the data set
1102 ! ===========================
1103 ! local size of the matrix
1104 dcount = [int(strides, hsize_t), int(counts, hsize_t)]
1105 ! offset for this rank in the global matrix
1106 doffset = [0_hsize_t, int(offset, hsize_t) + append_offset]
1107 ! Get the total file space (shape) of the data set
1108 call h5dget_space_f(dset_id, filespace, ierr)
1109 ! Get only the slice where my rank writes
1110 call h5sselect_hyperslab_f(filespace, h5s_select_set_f, doffset, dcount, &
1111 ierr)
1112 ! Create the corresponding memory space (buffer) for my local data
1113 call h5screate_simple_f(dset_rank, dcount, memspace, ierr)
1114
1115 ! =======================
1116 ! Cast and write the data
1117 ! =======================
1118 if (this%precision == sp) then
1119 allocate(write_buffer_sp(mat%get_nrows(), mat%get_ncols()))
1120 if (mat%size() > 0) write_buffer_sp = real(mat%x, kind=sp)
1121 ! Write the data
1122 call h5dwrite_f(dset_id, precision_hdf, write_buffer_sp, dcount, ierr, &
1123 file_space_id = filespace, mem_space_id = memspace, &
1124 xfer_prp = xf_id)
1125 deallocate(write_buffer_sp)
1126 else if (this%precision == dp) then
1127 allocate(write_buffer_dp(mat%get_nrows(), mat%get_ncols()))
1128 if (mat%size() > 0) write_buffer_dp = real(mat%x, kind=dp)
1129 ! Write the data
1130 call h5dwrite_f(dset_id, precision_hdf, write_buffer_dp, dcount, ierr, &
1131 file_space_id = filespace, mem_space_id = memspace, &
1132 xfer_prp = xf_id)
1133 deallocate(write_buffer_dp)
1134 else
1135 call neko_error("Unsupported precision")
1136 end if
1137
1138 ! =======================
1139 ! Clean up
1140 ! =======================
1141 call h5pclose_f(xf_id, ierr)
1142 call h5sclose_f(memspace, ierr)
1143 call h5sclose_f(filespace, ierr)
1144 call h5dclose_f(dset_id, ierr)
1145
1146 end subroutine hdf5_file_write_matrix
1147
1148 subroutine hdf5_file_write_field(this, field)
1149 class(hdf5_file_t), intent(inout) :: this
1150 type(field_t), intent(inout) :: field
1151 integer :: ierr, counts, offset, total_count, dset_rank, max_count
1152 integer :: stride_ax_1, stride_ax_2, stride_ax_3
1153 integer(hsize_t) :: append_offset
1154 integer(hid_t) :: precision_hdf
1155 integer(hid_t) :: xf_id, filespace, dset_id, memspace, dcpl_id
1156 integer(hsize_t), dimension(4) :: dcount, doffset
1157 integer(hsize_t), dimension(4) :: ddims, ddims_max, chunkdims
1158 integer(hsize_t), dimension(4) :: tempddims, tempmaxddims
1159 logical :: dset_exists
1160 real(kind=sp), allocatable :: write_buffer_sp(:,:,:,:) ! Write buffer single
1161 real(kind=dp), allocatable :: write_buffer_dp(:,:,:,:) ! Write buffer double
1162
1163 ! ==============
1164 ! Get Field info
1165 ! ==============
1166 stride_ax_1 = field%Xh%lx
1167 stride_ax_2 = field%Xh%ly
1168 stride_ax_3 = field%Xh%lz
1169 counts = field%msh%nelv
1170 append_offset = 0_hsize_t
1171 total_count = field%msh%glb_nelv
1172 max_count = 0
1173 offset = field%msh%offset_el
1174 call mpi_allreduce(counts, max_count, 1, mpi_integer, &
1175 mpi_max, neko_comm, ierr)
1176
1177 ! ===============
1178 ! Configure MPIIO
1179 ! ===============
1180 call h5pcreate_f(h5p_dataset_xfer_f, xf_id, ierr)
1181 call h5pset_dxpl_mpio_f(xf_id, h5fd_mpio_collective_f, ierr)
1182 precision_hdf = h5kind_to_type(this%precision, h5_real_kind)
1183
1184 ! ===================
1185 ! Create the data set
1186 ! ===================
1187 dset_rank = 4 ! rank 4 array, i.e. a 4D tensor
1188 ddims = [int(stride_ax_1, hsize_t), &
1189 int(stride_ax_2, hsize_t), &
1190 int(stride_ax_3, hsize_t), &
1191 int(total_count, hsize_t)] ! global size of the tensor
1192 chunkdims = [int(stride_ax_1, hsize_t), &
1193 int(stride_ax_2, hsize_t), &
1194 int(stride_ax_3, hsize_t), &
1195 max(int(max_count, hsize_t), 1_hsize_t)]
1196 ddims_max = [int(stride_ax_1, hsize_t), &
1197 int(stride_ax_2, hsize_t), &
1198 int(stride_ax_3, hsize_t), &
1199 h5s_unlimited_f]
1200 call h5lexists_f(this%active_group_id, trim(field%name), dset_exists, ierr)
1201 if (dset_exists) then
1202 if (this%overwrite) then
1203 ! retrieve the dset id for the existing data set
1204 if (pe_rank .eq. 0) then
1205 call neko_warning("Overwriting dataset: " // trim(field%name))
1206 end if
1207 call h5dopen_f(this%active_group_id, trim(field%name), dset_id, ierr)
1208 else
1209 call h5dopen_f(this%active_group_id, trim(field%name), dset_id, ierr)
1210 call h5dget_space_f(dset_id, filespace, ierr)
1211 call h5sget_simple_extent_dims_f(filespace, tempddims, tempmaxddims, &
1212 ierr)
1213 call h5sclose_f(filespace, ierr)
1214 ddims(4) = ddims(4) + tempddims(4)
1215 append_offset = tempddims(4)
1216 call h5dset_extent_f(dset_id, ddims, ierr)
1217 end if
1218 else
1219 ! create file space of this shape
1220 call h5screate_simple_f(dset_rank, ddims, filespace, ierr, ddims_max)
1221 call h5pcreate_f(h5p_dataset_create_f, dcpl_id, ierr)
1222 call h5pset_chunk_f(dcpl_id, dset_rank, chunkdims, ierr)
1223 ! create the data set with the given shape
1224 call h5dcreate_f(this%active_group_id, trim(field%name), precision_hdf, &
1225 filespace, dset_id, ierr, dcpl_id = dcpl_id)
1226 call h5sclose_f(filespace, ierr)
1227 call h5pclose_f(dcpl_id, ierr)
1228 end if
1229
1230 ! ===========================
1231 ! Set up writing the data set
1232 ! ===========================
1233 dcount = [int(stride_ax_1, hsize_t), &
1234 int(stride_ax_2, hsize_t), &
1235 int(stride_ax_3, hsize_t), &
1236 int(counts, hsize_t)] ! local size of the tensor
1237 doffset = [0_hsize_t, 0_hsize_t, 0_hsize_t, &
1238 int(offset, hsize_t) + append_offset] ! offset in the global tensor
1239 ! Get the total file space (shape) of the data set
1240 call h5dget_space_f(dset_id, filespace, ierr)
1241 ! Get only the slice where my rank writes
1242 call h5sselect_hyperslab_f(filespace, h5s_select_set_f, doffset, dcount, &
1243 ierr)
1244 ! Create the corresponding memory space (buffer) for my local data
1245 call h5screate_simple_f(dset_rank, dcount, memspace, ierr)
1246
1247 ! =======================
1248 ! Cast and write the data
1249 ! =======================
1250 if (this%precision == sp) then
1251 allocate(write_buffer_sp(field%Xh%lx, field%Xh%ly, field%Xh%lz, &
1252 field%msh%nelv))
1253 if (field%msh%nelv > 0) write_buffer_sp = real(field%x, kind=sp)
1254 ! Write the data
1255 call h5dwrite_f(dset_id, precision_hdf, write_buffer_sp, dcount, ierr, &
1256 file_space_id = filespace, mem_space_id = memspace, &
1257 xfer_prp = xf_id)
1258 deallocate(write_buffer_sp)
1259 else if (this%precision == dp) then
1260 allocate(write_buffer_dp(field%Xh%lx, field%Xh%ly, field%Xh%lz, &
1261 field%msh%nelv))
1262 if (field%msh%nelv > 0) write_buffer_dp = real(field%x, kind=dp)
1263 ! Write the data
1264 call h5dwrite_f(dset_id, precision_hdf, write_buffer_dp, dcount, ierr, &
1265 file_space_id = filespace, mem_space_id = memspace, &
1266 xfer_prp = xf_id)
1267 deallocate(write_buffer_dp)
1268 else
1269 call neko_error("Unsupported precision")
1270 end if
1271
1272 ! =======================
1273 ! Clean up
1274 ! =======================
1275 call h5pclose_f(xf_id, ierr)
1276 call h5sclose_f(memspace, ierr)
1277 call h5sclose_f(filespace, ierr)
1278 call h5dclose_f(dset_id, ierr)
1279
1280 end subroutine hdf5_file_write_field
1281
1283 subroutine hdf5_file_read_vector(this, data_name, vec, strategy)
1284 class(hdf5_file_t) :: this
1285 character(len=*), intent(in) :: data_name
1286 type(vector_t), intent(inout) :: vec
1287 character(len=*), intent(in), optional :: strategy
1288 character(len=1000) :: strategy_
1289 integer :: ierr, counts, offset, total_count, dset_rank
1290 integer(hid_t) :: precision_hdf
1291 integer(hid_t) :: xf_id, filespace, dset_id, memspace
1292 integer(hsize_t), dimension(1) :: dcount, doffset
1293 integer(hsize_t), dimension(1) :: tempddims, tempmaxddims
1294 integer :: temprank
1295 logical :: dset_exists
1296 type(linear_dist_t) :: dist
1297
1298 ! Set up strategy
1299 if (present(strategy)) then
1300 if (trim(strategy) .eq. "linear" .or. &
1301 trim(strategy) .eq. "rank_0") then
1302 strategy_ = strategy
1303 else
1304 call neko_error("Unsupported strategy: " // trim(strategy))
1305 end if
1306 else
1307 strategy_ = "linear"
1308 end if
1309
1310 ! Free the input
1311 call vec%free()
1312
1313 ! ===============
1314 ! Configure MPIIO
1315 ! ===============
1316 call h5pcreate_f(h5p_dataset_xfer_f, xf_id, ierr)
1317 call h5pset_dxpl_mpio_f(xf_id, h5fd_mpio_collective_f, ierr)
1318 precision_hdf = h5kind_to_type(rp, h5_real_kind)
1319
1320 ! ===================
1321 ! Get the data set info
1322 ! ===================
1323 call h5lexists_f(this%active_group_id, trim(data_name), dset_exists, ierr)
1324 if (dset_exists) then
1325 ! Open the data set
1326 call h5dopen_f(this%active_group_id, trim(data_name), dset_id, ierr)
1327 ! Get the current rank of the dataset
1328 call h5dget_space_f(dset_id, filespace, ierr)
1329 call h5sget_simple_extent_ndims_f(filespace, temprank, ierr)
1330 if (temprank .ne. 1) then
1331 call neko_error("Dataset " // trim(data_name) // &
1332 " is not a rank 1 vector in file " // trim(file_get_fname(this)))
1333 end if
1334 ! Get the current shape and close the filespace
1335 call h5sget_simple_extent_dims_f(filespace, tempddims, tempmaxddims, &
1336 ierr)
1337 call h5sclose_f(filespace, ierr)
1338 else
1339 call neko_error("Dataset " // trim(data_name) // &
1340 " does not exist in current group " // trim(file_get_fname(this)))
1341 end if
1342
1343 ! =============================
1344 ! Perform the data distribution
1345 ! =============================
1346 total_count = int(tempddims(1))
1347 if (strategy_ .eq. "linear") then
1348 dist = linear_dist_t(total_count, pe_rank, pe_size, neko_comm)
1349 counts = dist%num_local()
1350 offset = 0
1351 else if (strategy_ .eq. "rank_0") then
1352 if (pe_rank .eq. 0) then
1353 counts = total_count
1354 else
1355 counts = 0
1356 end if
1357 offset = 0
1358 end if
1359 call mpi_exscan(counts, offset, 1, mpi_integer, &
1360 mpi_sum, neko_comm, ierr)
1361
1362 ! ===========================
1363 ! Set up reading the data set
1364 ! ===========================
1365 dset_rank = 1 ! rank 1 array, i.e. a vector
1366 dcount = [int(counts, hsize_t)] ! local size of the vector
1367 doffset = [int(offset, hsize_t)] ! offset for this rank in the global vector
1368 ! Get the total file space (shape) of the data set
1369 call h5dget_space_f(dset_id, filespace, ierr)
1370 ! Get only the slice where my rank reads
1371 call h5sselect_hyperslab_f(filespace, h5s_select_set_f, doffset, dcount, &
1372 ierr)
1373 ! Create the corresponding memory space (buffer) for my local data
1374 call h5screate_simple_f(dset_rank, dcount, memspace, ierr)
1375
1376 ! =============================
1377 ! Allocate data. HDF5 will cast
1378 ! =============================
1379 call vec%init(counts, trim(data_name)) ! this is rp
1380 call h5dread_f(dset_id, precision_hdf, vec%x, dcount, ierr, &
1381 file_space_id = filespace, mem_space_id = memspace, &
1382 xfer_prp = xf_id)
1383
1384 ! =======================
1385 ! Clean up
1386 ! =======================
1387 call h5pclose_f(xf_id, ierr)
1388 call h5sclose_f(memspace, ierr)
1389 call h5sclose_f(filespace, ierr)
1390 call h5dclose_f(dset_id, ierr)
1391
1392 end subroutine hdf5_file_read_vector
1393
1395 subroutine hdf5_file_read_matrix(this, data_name, mat, strategy)
1396 class(hdf5_file_t) :: this
1397 character(len=*), intent(in) :: data_name
1398 type(matrix_t), intent(inout) :: mat
1399 character(len=*), intent(in), optional :: strategy
1400 character(len=1000) :: strategy_
1401 integer :: ierr, counts, offset, total_count, dset_rank
1402 integer(hid_t) :: precision_hdf
1403 integer(hid_t) :: xf_id, filespace, dset_id, memspace
1404 integer(hsize_t), dimension(2) :: dcount, doffset
1405 integer(hsize_t), dimension(2) :: tempddims, tempmaxddims
1406 integer :: temprank
1407 logical :: dset_exists
1408 type(linear_dist_t) :: dist
1409
1410 ! Set up strategy
1411 if (present(strategy)) then
1412 if (trim(strategy) .eq. "linear" .or. &
1413 trim(strategy) .eq. "rank_0") then
1414 strategy_ = strategy
1415 else
1416 call neko_error("Unsupported strategy: " // trim(strategy))
1417 end if
1418 else
1419 strategy_ = "linear"
1420 end if
1421
1422 ! Free the input
1423 call mat%free()
1424
1425 ! ===============
1426 ! Configure MPIIO
1427 ! ===============
1428 call h5pcreate_f(h5p_dataset_xfer_f, xf_id, ierr)
1429 call h5pset_dxpl_mpio_f(xf_id, h5fd_mpio_collective_f, ierr)
1430 precision_hdf = h5kind_to_type(rp, h5_real_kind)
1431
1432 ! ===================
1433 ! Get the data set info
1434 ! ===================
1435 call h5lexists_f(this%active_group_id, trim(data_name), dset_exists, ierr)
1436 if (dset_exists) then
1437 ! Openr the data set
1438 call h5dopen_f(this%active_group_id, trim(data_name), dset_id, ierr)
1439 ! Get the current rank of the of the dataset
1440 call h5dget_space_f(dset_id, filespace, ierr)
1441 call h5sget_simple_extent_ndims_f(filespace, temprank, ierr)
1442 if (temprank .ne. 2) then
1443 call neko_error("Dataset " // trim(data_name) // &
1444 " is not a rank 2 matrix in file " // trim(file_get_fname(this)))
1445 end if
1446 ! Get the current shape and close the filespace
1447 call h5sget_simple_extent_dims_f(filespace, tempddims, tempmaxddims, &
1448 ierr)
1449 call h5sclose_f(filespace, ierr)
1450 else
1451 call neko_error("Dataset " // trim(data_name) &
1452 // " does not exist in current group " // &
1453 trim(file_get_fname(this)))
1454 end if
1455
1456 ! =============================
1457 ! Perform the data distribution
1458 ! =============================
1459 total_count = int(tempddims(2))
1460 if (strategy_ .eq. "linear") then
1461 dist = linear_dist_t(total_count, pe_rank, pe_size, neko_comm)
1462 counts = dist%num_local()
1463 offset = 0
1464 else if (strategy_ .eq. "rank_0") then
1465 if (pe_rank .eq. 0) then
1466 counts = total_count
1467 else
1468 counts = 0
1469 end if
1470 offset = 0
1471 end if
1472 call mpi_scan(counts, offset, 1, mpi_integer, &
1473 mpi_sum, neko_comm, ierr)
1474 offset = offset - counts ! Not using exclusive scan
1475
1476 ! ===========================
1477 ! Set up reading the data set
1478 ! ===========================
1479 dset_rank = 2 ! rank 2 array, i.e. a matrix
1480 dcount = [int(tempddims(1), hsize_t), int(counts, hsize_t)] ! local size
1481 doffset = [0_hsize_t, int(offset, hsize_t)] ! offset in the global matrix
1482 ! Get the total file space (shape) of the data set
1483 call h5dget_space_f(dset_id, filespace, ierr)
1484 ! Get only the slice where my rank reads
1485 call h5sselect_hyperslab_f(filespace, h5s_select_set_f, doffset, dcount, &
1486 ierr)
1487 ! Create the corresponding memory space (buffer) for my local data
1488 call h5screate_simple_f(dset_rank, dcount, memspace, ierr)
1489
1490 ! =============================
1491 ! Allocate data. HDF5 will cast
1492 ! =============================
1493 call mat%init(int(tempddims(1)), counts, trim(data_name)) ! this is rp
1494 call h5dread_f(dset_id, precision_hdf, mat%x, dcount, ierr, &
1495 file_space_id = filespace, mem_space_id = memspace, &
1496 xfer_prp = xf_id)
1497
1498 ! =======================
1499 ! Clean up
1500 ! =======================
1501 call h5pclose_f(xf_id, ierr)
1502 call h5sclose_f(memspace, ierr)
1503 call h5sclose_f(filespace, ierr)
1504 call h5dclose_f(dset_id, ierr)
1505
1506
1507 end subroutine hdf5_file_read_matrix
1508
1510 subroutine hdf5_file_write_int_attribute(this, attr_name, attr)
1511 class(hdf5_file_t), intent(inout) :: this
1512 character(len=*), intent(in) :: attr_name
1513 integer, intent(in) :: attr
1514 integer :: ierr
1515 integer(hid_t) :: filespace, attr_id
1516 integer(hsize_t), dimension(1) :: dcount
1517 logical :: attr_exists
1518
1519 ! ====================
1520 ! Create the attribute
1521 ! ====================
1522 dcount = [int(1, hsize_t)]
1523 call h5aexists_f(this%active_group_id, trim(attr_name), attr_exists, ierr)
1524 if (attr_exists) then
1525 ! retrieve the attr id for the existing attribute
1526 call h5aopen_f(this%active_group_id, trim(attr_name), attr_id, ierr)
1527 else
1528 ! create file space of this shape
1529 call h5screate_f(h5s_scalar_f, filespace, ierr)
1530 ! create the data set with the given shape
1531 call h5acreate_f(this%active_group_id, trim(attr_name), &
1532 h5t_native_integer, &
1533 filespace, attr_id, ierr, h5p_default_f, h5p_default_f)
1534 call h5sclose_f(filespace, ierr)
1535 end if
1536
1537 ! ===========================
1538 ! Set up writing the data set
1539 ! ===========================
1540 call h5awrite_f(attr_id, h5t_native_integer, attr, dcount, ierr)
1541
1542 ! =======================
1543 ! Clean up
1544 ! =======================
1545 call h5aclose_f(attr_id, ierr)
1546
1547 end subroutine hdf5_file_write_int_attribute
1548
1550 subroutine hdf5_file_write_rp_attribute(this, attr_name, attr)
1551 class(hdf5_file_t), intent(inout) :: this
1552 character(len=*), intent(in) :: attr_name
1553 real(kind=rp), intent(in) :: attr
1554 integer :: ierr
1555 integer(hid_t) :: precision_hdf
1556 integer(hid_t) :: filespace, attr_id
1557 integer(hsize_t), dimension(1) :: dcount
1558 logical :: attr_exists
1559
1560 ! Get the precision
1561 precision_hdf = h5kind_to_type(rp, h5_real_kind)
1562
1563 ! ====================
1564 ! Create the attribute
1565 ! ====================
1566 dcount = [int(1, hsize_t)]
1567 call h5aexists_f(this%active_group_id, trim(attr_name), attr_exists, ierr)
1568 if (attr_exists) then
1569 ! retrieve the attr id for the existing attribute
1570 call h5aopen_f(this%active_group_id, trim(attr_name), attr_id, ierr)
1571 else
1572 ! create file space of this shape
1573 call h5screate_f(h5s_scalar_f, filespace, ierr)
1574 ! create the data set with the given shape
1575 call h5acreate_f(this%active_group_id, trim(attr_name), precision_hdf, &
1576 filespace, attr_id, ierr, h5p_default_f, h5p_default_f)
1577 call h5sclose_f(filespace, ierr)
1578 end if
1579
1580 ! ===========================
1581 ! Set up writing the data set
1582 ! ===========================
1583 call h5awrite_f(attr_id, precision_hdf, attr, dcount, ierr)
1584
1585 ! =======================
1586 ! Clean up
1587 ! =======================
1588 call h5aclose_f(attr_id, ierr)
1589
1590 end subroutine hdf5_file_write_rp_attribute
1591
1593 subroutine hdf5_file_read_int_attribute(this, attr_name, attr, attr_exists)
1594 class(hdf5_file_t), intent(inout) :: this
1595 character(len=*), intent(in) :: attr_name
1596 integer, intent(inout) :: attr
1597 logical, intent(inout) :: attr_exists
1598 integer :: ierr
1599 integer(hid_t) :: filespace, attr_id
1600 integer(hsize_t), dimension(1) :: dcount
1601
1602 ! ====================
1603 ! Create the attribute
1604 ! ====================
1605 dcount = [int(1, hsize_t)]
1606 call h5aexists_f(this%active_group_id, trim(attr_name), attr_exists, ierr)
1607 if (attr_exists) then
1608 ! retrieve the attr id for the existing attribute
1609 call h5aopen_f(this%active_group_id, trim(attr_name), attr_id, ierr)
1610 else
1611 return
1612 end if
1613
1614 ! ===========================
1615 ! Set up writing the data set
1616 ! ===========================
1617 call h5aread_f(attr_id, h5t_native_integer, attr, dcount, ierr)
1618
1619 ! =======================
1620 ! Clean up
1621 ! =======================
1622 call h5aclose_f(attr_id, ierr)
1623
1624 end subroutine hdf5_file_read_int_attribute
1625
1627 subroutine hdf5_file_read_rp_attribute(this, attr_name, attr, attr_exists)
1628 class(hdf5_file_t), intent(inout) :: this
1629 character(len=*), intent(in) :: attr_name
1630 real(kind=rp), intent(inout) :: attr
1631 logical, intent(inout) :: attr_exists
1632 integer :: ierr
1633 integer(hid_t) :: precision_hdf
1634 integer(hid_t) :: filespace, attr_id
1635 integer(hsize_t), dimension(1) :: dcount
1636
1637 ! Get the precision
1638 precision_hdf = h5kind_to_type(rp, h5_real_kind)
1639
1640 ! ====================
1641 ! Create the attribute
1642 ! ====================
1643 dcount = [int(1, hsize_t)]
1644 call h5aexists_f(this%active_group_id, trim(attr_name), attr_exists, ierr)
1645 if (attr_exists) then
1646 ! retrieve the attr id for the existing attribute
1647 call h5aopen_f(this%active_group_id, trim(attr_name), attr_id, ierr)
1648 else
1649 return
1650 end if
1651
1652 ! ===========================
1653 ! Set up writing the data set
1654 ! ===========================
1655 call h5aread_f(attr_id, precision_hdf, attr, dcount, ierr)
1656
1657 ! =======================
1658 ! Clean up
1659 ! =======================
1660 call h5aclose_f(attr_id, ierr)
1661
1662 end subroutine hdf5_file_read_rp_attribute
1663
1664#else
1665
1667 subroutine hdf5_file_open(this, mode)
1668 class(hdf5_file_t), intent(inout) :: this
1669 character(len=1), intent(in) :: mode
1670 call neko_error('Neko needs to be built with HDF5 support')
1671 end subroutine hdf5_file_open
1672
1674 subroutine hdf5_file_close(this)
1675 class(hdf5_file_t), intent(inout) :: this
1676 call neko_error('Neko needs to be built with HDF5 support')
1677 end subroutine hdf5_file_close
1678
1680 subroutine hdf5_file_set_group(this, group_name_path)
1681 class(hdf5_file_t), intent(inout) :: this
1682 character(len=*), intent(in), optional :: group_name_path
1683 call neko_error('Neko needs to be built with HDF5 support')
1684 end subroutine hdf5_file_set_group
1685
1687 subroutine hdf5_file_write(this, data, t)
1688 class(hdf5_file_t), intent(inout) :: this
1689 class(*), target, intent(in) :: data
1690 real(kind=rp), intent(in), optional :: t
1691 call neko_error('Neko needs to be built with HDF5 support')
1692 end subroutine hdf5_file_write
1693
1695 subroutine hdf5_file_read(this, data)
1696 class(hdf5_file_t) :: this
1697 class(*), target, intent(inout) :: data
1698 call neko_error('Neko needs to be built with HDF5 support')
1699 end subroutine hdf5_file_read
1700
1701 subroutine hdf5_file_write_dataset(this, data)
1702 class(hdf5_file_t), intent(inout) :: this
1703 class(*), intent(inout) :: data
1704 call neko_error('Neko needs to be built with HDF5 support')
1705 end subroutine hdf5_file_write_dataset
1706
1707 subroutine hdf5_file_read_dataset(this, data_name, data, strategy)
1708 class(hdf5_file_t), intent(inout) :: this
1709 character(len=*), intent(in) :: data_name
1710 class(*), intent(inout) :: data
1711 character(len=*), intent(in), optional :: strategy
1712 call neko_error('Neko needs to be built with HDF5 support')
1713 end subroutine hdf5_file_read_dataset
1714
1715 subroutine hdf5_file_write_attribute(this, data_name, data)
1716 class(hdf5_file_t), intent(inout) :: this
1717 character(len=*), intent(in) :: data_name
1718 class(*), intent(inout) :: data
1719 call neko_error('Neko needs to be built with HDF5 support')
1720 end subroutine hdf5_file_write_attribute
1721
1722 subroutine hdf5_file_read_attribute(this, data_name, data, exist)
1723 class(hdf5_file_t), intent(inout) :: this
1724 character(len=*), intent(in) :: data_name
1725 class(*), intent(inout) :: data
1726 logical, intent(inout) :: exist
1727 call neko_error('Neko needs to be built with HDF5 support')
1728 end subroutine hdf5_file_read_attribute
1729
1730 subroutine hdf5_file_write_vector(this, vec)
1731 class(hdf5_file_t), intent(inout) :: this
1732 type(vector_t), intent(inout) :: vec
1733 call neko_error('Neko needs to be built with HDF5 support')
1734 end subroutine hdf5_file_write_vector
1735
1736 subroutine hdf5_file_write_matrix(this, mat)
1737 class(hdf5_file_t), intent(inout) :: this
1738 type(matrix_t), intent(inout) :: mat
1739 call neko_error('Neko needs to be built with HDF5 support')
1740 end subroutine hdf5_file_write_matrix
1741
1742 subroutine hdf5_file_write_field(this, fld)
1743 class(hdf5_file_t), intent(inout) :: this
1744 type(field_t), intent(inout) :: fld
1745 call neko_error('Neko needs to be built with HDF5 support')
1746 end subroutine hdf5_file_write_field
1747
1748 subroutine hdf5_file_read_vector(this, data_name, vec, strategy)
1749 class(hdf5_file_t) :: this
1750 character(len=*), intent(in) :: data_name
1751 type(vector_t), intent(inout) :: vec
1752 character(len=*), intent(in), optional :: strategy
1753 call neko_error('Neko needs to be built with HDF5 support')
1754 end subroutine hdf5_file_read_vector
1755
1756 subroutine hdf5_file_read_matrix(this, data_name, mat, strategy)
1757 class(hdf5_file_t) :: this
1758 character(len=*), intent(in) :: data_name
1759 type(matrix_t), intent(inout) :: mat
1760 character(len=*), intent(in), optional :: strategy
1761 call neko_error('Neko needs to be built with HDF5 support')
1762 end subroutine hdf5_file_read_matrix
1763
1764 subroutine hdf5_file_write_int_attribute(this, attr_name, attr)
1765 class(hdf5_file_t), intent(inout) :: this
1766 character(len=*), intent(in) :: attr_name
1767 integer, intent(in) :: attr
1768 call neko_error('Neko needs to be built with HDF5 support')
1769 end subroutine hdf5_file_write_int_attribute
1770
1771 subroutine hdf5_file_write_rp_attribute(this, attr_name, attr)
1772 class(hdf5_file_t), intent(inout) :: this
1773 character(len=*), intent(in) :: attr_name
1774 real(kind=rp), intent(in) :: attr
1775 call neko_error('Neko needs to be built with HDF5 support')
1776 end subroutine hdf5_file_write_rp_attribute
1777
1778 subroutine hdf5_file_read_int_attribute(this, attr_name, attr, attr_exists)
1779 class(hdf5_file_t), intent(inout) :: this
1780 character(len=*), intent(in) :: attr_name
1781 integer, intent(inout) :: attr
1782 logical, intent(inout) :: attr_exists
1783 call neko_error('Neko needs to be built with HDF5 support')
1784 end subroutine hdf5_file_read_int_attribute
1785
1786 subroutine hdf5_file_read_rp_attribute(this, attr_name, attr, attr_exists)
1787 class(hdf5_file_t), intent(inout) :: this
1788 character(len=*), intent(in) :: attr_name
1789 real(kind=rp), intent(inout) :: attr
1790 logical, intent(inout) :: attr_exists
1791 call neko_error('Neko needs to be built with HDF5 support')
1792 end subroutine hdf5_file_read_rp_attribute
1793
1794#endif
1795
1796end module hdf5_file
double real
Defines a checkpoint.
Definition comm.F90:1
integer, public pe_size
MPI size of communicator.
Definition comm.F90:62
integer, public pe_rank
MPI rank.
Definition comm.F90:59
type(mpi_comm), public neko_comm
MPI communicator.
Definition comm.F90:46
Defines practical data distributions.
Definition datadist.f90:34
Defines a mapping of the degrees of freedom.
Definition dofmap.f90:35
Contains the field_serties_t type.
Defines a field.
Definition field.f90:34
Module for file I/O operations.
Definition file.f90:34
HDF5 file format.
Definition hdf5_file.F90:34
subroutine hdf5_file_open(this, mode)
Open a HDF5 file in a given mode.
character(len=1024) function file_get_fname(this)
Return the file name with the start counter.
subroutine hdf5_file_write_field(this, fld)
subroutine hdf5_file_read(this, data)
Read data in HDF5 format.
subroutine hdf5_file_write(this, data, t)
Write data in HDF5 format.
subroutine hdf5_file_read_dataset(this, data_name, data, strategy)
subroutine hdf5_file_write_int_attribute(this, attr_name, attr)
subroutine hdf5_file_write_attribute(this, data_name, data)
subroutine hdf5_file_read_vector(this, data_name, vec, strategy)
subroutine hdf5_file_write_vector(this, vec)
subroutine hdf5_file_read_matrix(this, data_name, mat, strategy)
subroutine hdf5_file_read_int_attribute(this, attr_name, attr, attr_exists)
subroutine hdf5_file_write_rp_attribute(this, attr_name, attr)
subroutine hdf5_file_set_precision(this, precision)
Set the precision for the output (single or double)
subroutine hdf5_file_read_rp_attribute(this, attr_name, attr, attr_exists)
subroutine hdf5_file_read_attribute(this, data_name, data, exist)
subroutine hdf5_file_close(this)
Close the file.
subroutine hdf5_file_set_group(this, group_name_path)
Set the active group for HDF5 files.
subroutine hdf5_file_write_matrix(this, mat)
subroutine hdf5_file_write_dataset(this, data)
subroutine hdf5_file_set_overwrite(this, overwrite)
Set the overwrite flag for HDF5 files.
Logging routines.
Definition log.f90:34
integer, parameter, public neko_log_debug
Debug log level.
Definition log.f90:90
type(log_t), public neko_log
Global log stream.
Definition log.f90:80
integer, parameter, public log_size
Definition log.f90:46
Defines a matrix.
Definition matrix.f90:34
Defines a mesh.
Definition mesh.f90:34
integer, parameter, public dp
Definition num_types.f90:9
integer, parameter, public sp
Definition num_types.f90:8
integer, parameter, public rp
Global precision used in computations.
Definition num_types.f90:12
Utilities.
Definition utils.f90:35
subroutine, public filename_split(fname, path, name, suffix)
Extract file name components.
Definition utils.f90:131
subroutine, public neko_warning(warning_msg)
Reports a warning to standard output.
Definition utils.f90:398
pure integer function, public filename_suffix_pos(fname)
Find position (in the string) of a filename's suffix.
Definition utils.f90:74
Defines a vector.
Definition vector.f90:34
Load-balanced linear distribution .
Definition datadist.f90:50
field_ptr_t, To easily obtain a pointer to a field
Definition field.f90:83
field_list_t, To be able to group fields together
A wrapper for a pointer to a field_series_t.
Stores a series (sequence) of fields, logically connected to a base field, and arranged according to ...
A generic file handler.
Interface for HDF5 files.
Definition hdf5_file.F90:60
#define max(a, b)
Definition tensor.cu:40