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