Neko 1.99.9
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-2026, 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, i8
37 use checkpoint, only : chkp_t
42 use mesh, only : mesh_t
43 use field, only : field_t, field_ptr_t
44 use field_list, only : field_list_t
46 use dofmap, only : dofmap_t
47 use space, only : neko_space_t => space_t, gll
50 use vector, only : vector_t
51 use matrix, only : matrix_t
52 use datadist, only : linear_dist_t
54 use math, only : rzero
56 use mpi_f08, only : mpi_info_null, mpi_allreduce, mpi_allgather, &
57 mpi_in_place, mpi_integer, mpi_sum, mpi_max, mpi_comm_size, mpi_exscan, &
58 mpi_barrier, mpi_integer8, mpi_scan, mpi_bcast, &
59 mpi_double_precision
61#ifdef HAVE_HDF5
62 use hdf5
63#endif
64 implicit none
65 private
66
68 type, public, extends(generic_file_t) :: hdf5_file_t
69
70 ! HDF5 members
71#ifdef HAVE_HDF5
72 integer(hid_t) :: file_id = -1_hid_t
73 integer(hid_t) :: active_group_id = -1_hid_t
74 integer(hid_t) :: plist_id = -1_hid_t
75#endif
76 character(len=1) :: mode
77 integer :: precision = -1
78 integer :: offset = 0
79 integer :: count = 0
80
81 contains
82 ! General methods for reading/writing HDF5 files
84 procedure :: read => hdf5_file_read
86 procedure :: write => hdf5_file_write
87 procedure :: get_next_output_fname => hdf5_file_get_next_output_fname
88 procedure :: set_overwrite => hdf5_file_set_overwrite
89 ! Granular methods for dealing with HDF5 files
90 procedure :: open => hdf5_file_open
91 procedure :: close => hdf5_file_close
92 procedure :: set_active_group => hdf5_file_set_group
93 procedure :: set_precision => hdf5_file_set_precision
94 procedure, pass(this) :: write_vector => hdf5_file_write_vector
95 procedure, pass(this) :: write_matrix => hdf5_file_write_matrix
96 procedure, pass(this) :: write_field => hdf5_file_write_field
97 procedure, pass(this) :: write_int_attribute => &
99 procedure, pass(this) :: write_rp_attribute => hdf5_file_write_rp_attribute
100 procedure, pass(this) :: read_vector => hdf5_file_read_vector
101 procedure, pass(this) :: read_matrix => hdf5_file_read_matrix
102 procedure, pass(this) :: read_int_attribute => hdf5_file_read_int_attribute
103 procedure, pass(this) :: read_rp_attribute => hdf5_file_read_rp_attribute
104 procedure :: write_dataset => hdf5_file_write_dataset
105 procedure :: read_dataset => hdf5_file_read_dataset
106 procedure :: write_attribute => hdf5_file_write_attribute
107 procedure :: read_attribute => hdf5_file_read_attribute
108 end type hdf5_file_t
109
117 type(mesh_t), pointer :: msh => null()
119 type(neko_space_t) :: xh
121 logical :: mesh2mesh = .false.
123 type(dofmap_t) :: src_dof
125 type(global_interpolation_t) :: global_interp
126 contains
128 procedure, pass(this) :: free => hdf5_checkpoint_layout_free
130
131contains
132
134 function hdf5_file_get_next_output_fname(this) result(fname)
135 class(hdf5_file_t), intent(in) :: this
136 character(len=1024) :: fname
137 character(len=5) :: id_str
138 integer :: counter, suffix_pos
139
140 if (this%overwrite) then
141 fname = this%get_fname()
142 else
143 counter = this%get_counter()
144 if (counter .eq. -1) then
145 counter = this%get_start_counter()
146 else
147 counter = counter + 1
148 end if
149
150 fname = this%get_base_fname()
151 suffix_pos = filename_suffix_pos(fname)
152 write(id_str, '(i5.5)') counter
153 fname = trim(fname(1:suffix_pos-1)) // id_str // fname(suffix_pos:)
154 end if
155
157
159 subroutine hdf5_file_set_overwrite(this, overwrite)
160 class(hdf5_file_t), intent(inout) :: this
161 logical, intent(in) :: overwrite
162 this%overwrite = overwrite
163 end subroutine hdf5_file_set_overwrite
164
166 function file_get_fname(this) result(base_fname)
167 class(hdf5_file_t), intent(in) :: this
168 character(len=1024) :: base_fname
169 character(len=1024) :: fname
170 character(len=1024) :: path, name, suffix
171
172 fname = trim(this%get_base_fname())
173 call filename_split(fname, path, name, suffix)
174
175 ! Append a counter
176 !write(base_fname, '(A,A,"_",I0,A)') &
177 ! trim(path), trim(name), this%get_start_counter(), trim(suffix)
178
179 ! Do not append anything
180 base_fname = trim(fname)
181
182 end function file_get_fname
183
185 subroutine hdf5_file_set_precision(this, precision)
186 class(hdf5_file_t), intent(inout) :: this
187 integer, intent(in) :: precision
188 this%precision = precision
189 end subroutine hdf5_file_set_precision
190
194 class(hdf5_checkpoint_layout_t), intent(inout) :: this
195
196 if (this%mesh2mesh) then
197 call this%global_interp%free()
198 call this%src_dof%free()
199 end if
200 call this%Xh%free()
201 nullify(this%msh)
202 this%mesh2mesh = .false.
203
204 end subroutine hdf5_checkpoint_layout_free
205
206
207#ifdef HAVE_HDF5
208
209 ! ===============
210 ! General methods
211 ! ===============
212
216 subroutine hdf5_file_write(this, data, t)
217 class(hdf5_file_t), intent(inout) :: this
218 class(*), target, intent(in) :: data
219 real(kind=dp), intent(in), optional :: t
220 type(mesh_t), pointer :: msh
221 type(dofmap_t), pointer :: dof
222 type(field_ptr_t), allocatable :: fp(:)
223 type(field_series_ptr_t), allocatable :: fsp(:)
224 real(kind=dp), pointer :: dtlag(:)
225 real(kind=dp), pointer :: tlag(:)
226 integer :: ierr, info, drank, i, j
227 integer(hid_t) :: plist_id, fapl_id
228 integer(hid_t) :: file_id, dset_id, grp_id, attr_id
229 integer(hid_t) :: filespace, dspace_id, memspace
230 integer(hid_t) :: H5T_NEKO_REAL
231 integer(hsize_t), dimension(1) :: ddim, dcount, doffset
232 integer :: suffix_pos
233 character(len=5) :: id_str
234 character(len=1024) :: fname
235 logical :: checkpoint_data
236
237 call hdf5_file_determine_data(data, msh, dof, fp, fsp, dtlag, tlag)
238 checkpoint_data = .false.
239 select type (data)
240 type is (chkp_t)
241 checkpoint_data = .true.
242 end select
243
244 if (.not. this%overwrite) call this%increment_counter()
245 fname = trim(this%get_fname())
246
247 call hdf5_session_init()
248
249 call hdf5_file_determine_real(h5t_neko_real)
250
251 ! The file-access and dataset-transfer property lists are distinct
252 ! objects; reusing one identifier for both would leak the first, and
253 ! HDF5 then refuses to close the library at the end of the session.
254 call h5pcreate_f(h5p_file_access_f, fapl_id, ierr)
255 info = mpi_info_null%mpi_val
256 call h5pset_fapl_mpio_f(fapl_id, neko_comm%mpi_val, info, ierr)
257
258 call h5fcreate_f(fname, h5f_acc_trunc_f, &
259 file_id, ierr, access_prp = fapl_id)
260 call h5pclose_f(fapl_id, ierr)
261
262 call h5pcreate_f(h5p_dataset_xfer_f, plist_id, ierr)
263 call h5pset_dxpl_mpio_f(plist_id, h5fd_mpio_collective_f, ierr)
264
265 call h5screate_f(h5s_scalar_f, filespace, ierr)
266 ddim = 1
267
268 if (present(t)) then
269 call h5acreate_f(file_id, "Time", h5t_native_double, filespace, attr_id, &
270 ierr, h5p_default_f, h5p_default_f)
271 call h5awrite_f(attr_id, h5t_native_double, t, ddim, ierr)
272 call h5aclose_f(attr_id, ierr)
273 end if
274
275 if (associated(dof)) then
276 call h5acreate_f(file_id, "Lx", h5t_native_integer, filespace, attr_id, &
277 ierr, h5p_default_f, h5p_default_f)
278 call h5awrite_f(attr_id, h5t_native_integer, dof%Xh%lx, ddim, ierr)
279 call h5aclose_f(attr_id, ierr)
280 end if
281
282 if (associated(msh)) then
283 call h5gcreate_f(file_id, "Mesh", grp_id, ierr, &
284 lcpl_id = h5p_default_f, gcpl_id = h5p_default_f, &
285 gapl_id = h5p_default_f)
286
287 call h5acreate_f(grp_id, "Elements", h5t_native_integer, filespace, &
288 attr_id, ierr, h5p_default_f, h5p_default_f)
289 call h5awrite_f(attr_id, h5t_native_integer, msh%glb_nelv, ddim, ierr)
290 call h5aclose_f(attr_id, ierr)
291
292 call h5acreate_f(grp_id, "Dimension", h5t_native_integer, filespace, &
293 attr_id, ierr, h5p_default_f, h5p_default_f)
294 call h5awrite_f(attr_id, h5t_native_integer, msh%gdim, ddim, ierr)
295 call h5aclose_f(attr_id, ierr)
296
297 call h5gclose_f(grp_id, ierr)
298 end if
299
300
301 call h5sclose_f(filespace, ierr)
302
303 !
304 ! Write restart group (tlag, dtlag)
305 !
306 if (associated(tlag) .and. associated(dtlag)) then
307 call h5gcreate_f(file_id, "Restart", grp_id, ierr, &
308 lcpl_id = h5p_default_f, gcpl_id = h5p_default_f, &
309 gapl_id = h5p_default_f)
310
311 drank = 1
312 ddim = size(tlag)
313 doffset(1) = 0
314 if (pe_rank .eq. 0) then
315 dcount = size(tlag)
316 else
317 dcount = 0
318 end if
319
320 call h5screate_simple_f(drank, ddim, filespace, ierr)
321
322 call h5dcreate_f(grp_id, 'tlag', h5t_native_double, &
323 filespace, dset_id, ierr)
324 call h5dget_space_f(dset_id, dspace_id, ierr)
325 call h5sselect_hyperslab_f (dspace_id, h5s_select_set_f, &
326 doffset, dcount, ierr)
327 call h5dwrite_f(dset_id, h5t_native_double, tlag, &
328 ddim, ierr, xfer_prp = plist_id)
329 call h5sclose_f(dspace_id, ierr)
330 call h5dclose_f(dset_id, ierr)
331
332 call h5dcreate_f(grp_id, 'dtlag', h5t_native_double, &
333 filespace, dset_id, ierr)
334 call h5dget_space_f(dset_id, dspace_id, ierr)
335 call h5sselect_hyperslab_f (dspace_id, h5s_select_set_f, &
336 doffset, dcount, ierr)
337 call h5dwrite_f(dset_id, h5t_native_double, dtlag, &
338 ddim, ierr, xfer_prp = plist_id)
339 call h5sclose_f(dspace_id, ierr)
340 call h5dclose_f(dset_id, ierr)
341
342 call h5sclose_f(filespace, ierr)
343 call h5gclose_f(grp_id, ierr)
344
345 end if
346
347
348 !
349 ! Write fields group
350 !
351 if (checkpoint_data) then
352 select type (data)
353 type is (chkp_t)
354 call hdf5_checkpoint_write_payloads( &
355 file_id, plist_id, h5t_neko_real, data)
356 end select
357 if (allocated(fp)) deallocate(fp)
358 if (allocated(fsp)) deallocate(fsp)
359 else if (allocated(fp) .or. allocated(fsp)) then
360 call h5gcreate_f(file_id, "Fields", grp_id, ierr, &
361 lcpl_id = h5p_default_f, gcpl_id = h5p_default_f, &
362 gapl_id = h5p_default_f)
363
364 ! `lxyz` rather than `lx**3`: they agree in 3D, but a 2D case has
365 ! `lz = 1`, and the reader derives its offsets the same way.
366 dcount(1) = int(dof%size(), 8)
367 doffset(1) = int(msh%offset_el, 8) * int(dof%Xh%lxyz, 8)
368 ddim = int(dof%size(), 8)
369 drank = 1
370 call mpi_allreduce(mpi_in_place, ddim(1), 1, &
371 mpi_integer8, mpi_sum, neko_comm, ierr)
372
373 call h5screate_simple_f(drank, ddim, filespace, ierr)
374 call h5screate_simple_f(drank, dcount, memspace, ierr)
375
376
377 if (allocated(fp)) then
378 do i = 1, size(fp)
379 call h5dcreate_f(grp_id, fp(i)%ptr%name, h5t_neko_real, &
380 filespace, dset_id, ierr)
381 call h5dget_space_f(dset_id, dspace_id, ierr)
382 call h5sselect_hyperslab_f(dspace_id, h5s_select_set_f, &
383 doffset, dcount, ierr)
384 call h5dwrite_f(dset_id, h5t_neko_real, &
385 fp(i)%ptr%x(1,1,1,1), &
386 ddim, ierr, file_space_id = dspace_id, &
387 mem_space_id = memspace, xfer_prp = plist_id)
388 call h5sclose_f(dspace_id, ierr)
389 call h5dclose_f(dset_id, ierr)
390 end do
391 deallocate(fp)
392 end if
393
394 if (allocated(fsp)) then
395 do i = 1, size(fsp)
396 do j = 1, fsp(i)%ptr%size()
397 call h5dcreate_f(grp_id, fsp(i)%ptr%lf(j)%name, &
398 h5t_neko_real, filespace, dset_id, ierr)
399 call h5dget_space_f(dset_id, dspace_id, ierr)
400 call h5sselect_hyperslab_f(dspace_id, h5s_select_set_f, &
401 doffset, dcount, ierr)
402 call h5dwrite_f(dset_id, h5t_neko_real, &
403 fsp(i)%ptr%lf(j)%x(1,1,1,1), &
404 ddim, ierr, file_space_id = dspace_id, &
405 mem_space_id = memspace, xfer_prp = plist_id)
406 call h5sclose_f(dspace_id, ierr)
407 call h5dclose_f(dset_id, ierr)
408 end do
409 end do
410 deallocate(fsp)
411 end if
412
413 call h5gclose_f(grp_id, ierr)
414 call h5sclose_f(filespace, ierr)
415 call h5sclose_f(memspace, ierr)
416 end if
417
418 call h5pclose_f(plist_id, ierr)
419 call h5fclose_f(file_id, ierr)
421
422 end subroutine hdf5_file_write
423
426 subroutine hdf5_file_read(this, data)
427 class(hdf5_file_t) :: this
428 class(*), target, intent(inout) :: data
429 integer(hid_t) :: plist_id, fapl_id
430 integer(hid_t) :: file_id, dset_id, grp_id, attr_id
431 integer(hid_t) :: filespace, memspace
432 integer(hid_t) :: H5T_NEKO_REAL
433 integer(hsize_t), dimension(1) :: ddim, dcount, doffset
434 integer :: i,j, ierr, info, glb_nelv, gdim, lx, drank
435 type(mesh_t), pointer :: msh
436 type(dofmap_t), pointer :: dof
437 type(field_ptr_t), allocatable :: fp(:)
438 type(field_series_ptr_t), allocatable :: fsp(:)
439 type(hdf5_checkpoint_layout_t), target :: layout
440 real(kind=dp), pointer :: dtlag(:)
441 real(kind=dp), pointer :: tlag(:)
442 real(kind=dp) :: t
443 character(len=1024) :: fname
444 ! Not LOG_SIZE: these messages are longer than 79 characters, and an
445 ! overflowing internal write is a runtime error, not a truncation.
446 character(len=256) :: err_msg
447 logical :: payloads_exist
448
449 fname = trim(this%get_fname())
450
451 call hdf5_session_init()
452
453 call hdf5_file_determine_data(data, msh, dof, fp, fsp, dtlag, tlag)
454 call hdf5_file_determine_real(h5t_neko_real)
455
456 ! As in the write path, keep the file-access and dataset-transfer
457 ! property lists in separate identifiers so neither is leaked.
458 call h5pcreate_f(h5p_file_access_f, fapl_id, ierr)
459 info = mpi_info_null%mpi_val
460 call h5pset_fapl_mpio_f(fapl_id, neko_comm%mpi_val, info, ierr)
461
462 call h5fopen_f(fname, h5f_acc_rdonly_f, &
463 file_id, ierr, access_prp = fapl_id)
464 call h5pclose_f(fapl_id, ierr)
465
466 call h5lexists_f(file_id, 'Payloads', payloads_exist, ierr)
467
468 call h5pcreate_f(h5p_dataset_xfer_f, plist_id, ierr)
469 call h5pset_dxpl_mpio_f(plist_id, h5fd_mpio_collective_f, ierr)
470
471 ddim = 1
472 call h5aopen_name_f(file_id, 'Time', attr_id, ierr)
473 call h5aread_f(attr_id, h5t_native_double, t, ddim, ierr)
474 call h5aclose_f(attr_id, ierr)
475
476 select type (data)
477 type is (chkp_t)
478 data%t = t
479 end select
480
481 call h5aopen_name_f(file_id, 'Lx', attr_id, ierr)
482 call h5aread_f(attr_id, h5t_native_integer, lx, ddim, ierr)
483 call h5aclose_f(attr_id, ierr)
484
485 call h5gopen_f(file_id, 'Mesh', grp_id, ierr, gapl_id = h5p_default_f)
486
487 call h5aopen_name_f(grp_id, 'Elements', attr_id, ierr)
488 call h5aread_f(attr_id, h5t_native_integer, glb_nelv, ddim, ierr)
489 call h5aclose_f(attr_id, ierr)
490
491 call h5aopen_name_f(grp_id, 'Dimension', attr_id, ierr)
492 call h5aread_f(attr_id, h5t_native_integer, gdim, ddim, ierr)
493 call h5aclose_f(attr_id, ierr)
494 call h5gclose_f(grp_id, ierr)
495
496 ! A mesh supplied through `case.restart_mesh_file` is the one the
497 ! checkpoint was written on, and the file's layout follows it.
498 layout%msh => msh
499 layout%mesh2mesh = .false.
500 select type (data)
501 type is (chkp_t)
502 if (allocated(data%previous_mesh%elements)) then
503 layout%msh => data%previous_mesh
504 layout%mesh2mesh = .true.
505 end if
506 end select
507
508 if (gdim .ne. layout%msh%gdim) then
509 write(err_msg, '(A,I0,A,I0,A)') 'HDF5 checkpoint is for a ', gdim, &
510 'D mesh but this case is ', layout%msh%gdim, 'D'
511 call neko_error(trim(err_msg))
512 end if
513
514 if (glb_nelv .ne. layout%msh%glb_nelv) then
515 write(err_msg, '(A,I0,A,I0,A)') 'HDF5 checkpoint has ', glb_nelv, &
516 ' elements but the mesh it is read on has ', &
517 layout%msh%glb_nelv, '; set case.restart_mesh_file to the ' // &
518 'mesh the checkpoint was written on'
519 call neko_error(trim(err_msg))
520 end if
521
522 if (gdim .eq. 3) then
523 call layout%Xh%init(gll, lx, lx, lx)
524 else
525 call layout%Xh%init(gll, lx, lx)
526 end if
527
528 select type (data)
529 type is (chkp_t)
530 if (gdim .eq. 3) then
531 call data%previous_Xh%init(gll, lx, lx, lx)
532 else
533 call data%previous_Xh%init(gll, lx, lx)
534 end if
535
536 if (layout%mesh2mesh) then
537 call layout%src_dof%init(layout%msh, layout%Xh)
538 call layout%global_interp%init(layout%src_dof, neko_comm, &
539 tol = data%mesh2mesh_tol)
540 call layout%global_interp%find_points(dof%x%x, dof%y%x, dof%z%x, &
541 dof%size())
542 end if
543 end select
544
545 if (associated(tlag) .and. associated(dtlag)) then
546 drank = 1
547 ddim = size(tlag)
548 doffset(1) = 0
549 if (pe_rank .eq. 0) then
550 dcount = size(tlag)
551 else
552 dcount = 0
553 end if
554
555 call h5gopen_f(file_id, 'Restart', grp_id, ierr, &
556 gapl_id = h5p_default_f)
557 call h5dopen_f(grp_id, 'tlag', dset_id, ierr)
558 call h5dget_space_f(dset_id, filespace, ierr)
559 call h5sselect_hyperslab_f (filespace, h5s_select_set_f, &
560 doffset, dcount, ierr)
561 call h5dread_f(dset_id, h5t_native_double, tlag, ddim, ierr, &
562 xfer_prp = plist_id)
563 call h5dclose_f(dset_id, ierr)
564 call h5sclose_f(filespace, ierr)
565
566 call h5dopen_f(grp_id, 'dtlag', dset_id, ierr)
567 call h5dget_space_f(dset_id, filespace, ierr)
568 call h5sselect_hyperslab_f (filespace, h5s_select_set_f, &
569 doffset, dcount, ierr)
570 call h5dread_f(dset_id, h5t_native_double, dtlag, ddim, ierr, &
571 xfer_prp = plist_id)
572 call h5dclose_f(dset_id, ierr)
573 call h5sclose_f(filespace, ierr)
574
575 call h5gclose_f(grp_id, ierr)
576 end if
577
578 if (payloads_exist) then
579 select type (data)
580 type is (chkp_t)
581 call hdf5_checkpoint_read_payloads( &
582 file_id, plist_id, h5t_neko_real, data, layout)
583 class default
584 call neko_error( &
585 "HDF5 payload checkpoints require a checkpoint object")
586 end select
587 if (allocated(fp)) deallocate(fp)
588 if (allocated(fsp)) deallocate(fsp)
589 else if (allocated(fp) .or. allocated(fsp)) then
590 call h5gopen_f(file_id, 'Fields', grp_id, ierr, gapl_id = h5p_default_f)
591
592 if (allocated(fp)) then
593 do i = 1, size(fp)
594 call hdf5_checkpoint_read_field(grp_id, plist_id, &
595 h5t_neko_real, fp(i)%ptr, layout)
596 end do
597 end if
598
599 if (allocated(fsp)) then
600 do i = 1, size(fsp)
601 do j = 1, fsp(i)%ptr%size()
602 call hdf5_checkpoint_read_field(grp_id, plist_id, &
603 h5t_neko_real, fsp(i)%ptr%lf(j), layout)
604 end do
605 end do
606 end if
607 call h5gclose_f(grp_id, ierr)
608 end if
609
610 call h5pclose_f(plist_id, ierr)
611 call h5fclose_f(file_id, ierr)
612
613 call layout%free()
614
616
617 end subroutine hdf5_file_read
618
624 subroutine hdf5_checkpoint_write_payloads(file_id, plist_id, &
625 h5_neko_real, chkp)
626 integer(hid_t), intent(in) :: file_id, plist_id, h5_neko_real
627 type(chkp_t), intent(in) :: chkp
628 integer(hid_t) :: payloads_id, payload_id
629 integer :: i, j, k, ierr
630
631 call h5gcreate_f(file_id, "Payloads", payloads_id, ierr)
632
633 do i = 1, chkp%payload_count()
634 call hdf5_checkpoint_open_group(payloads_id, &
635 chkp%payloads(i)%ptr%name, .true., payload_id)
636
637 do j = 1, chkp%payloads(i)%ptr%field_count()
638 call hdf5_checkpoint_write_field(payload_id, plist_id, &
639 h5_neko_real, chkp%payloads(i)%ptr%fields(j)%ptr)
640 end do
641
642 do j = 1, chkp%payloads(i)%ptr%series_count()
643 do k = 1, chkp%payloads(i)%ptr%series(j)%ptr%size()
644 call hdf5_checkpoint_write_field(payload_id, plist_id, &
645 h5_neko_real, &
646 chkp%payloads(i)%ptr%series(j)%ptr%lf(k))
647 end do
648 end do
649
650 do j = 1, chkp%payloads(i)%ptr%mesh_array_count()
651 call hdf5_checkpoint_write_mesh_array(payload_id, plist_id, &
652 h5_neko_real, chkp%payloads(i)%ptr%mesh_arrays(j)%ptr)
653 end do
654
655 do j = 1, chkp%payloads(i)%ptr%array_count()
656 call hdf5_checkpoint_write_array(payload_id, plist_id, &
657 h5_neko_real, chkp%payloads(i)%ptr%arrays(j)%ptr)
658 end do
659
660 call h5gclose_f(payload_id, ierr)
661 end do
662
663 call h5gclose_f(payloads_id, ierr)
664
665 end subroutine hdf5_checkpoint_write_payloads
666
673 subroutine hdf5_checkpoint_read_payloads(file_id, plist_id, &
674 h5_neko_real, chkp, layout)
675 integer(hid_t), intent(in) :: file_id, plist_id, h5_neko_real
676 type(chkp_t), intent(inout) :: chkp
677 type(hdf5_checkpoint_layout_t), target, intent(inout) :: layout
678 integer(hid_t) :: payloads_id, payload_id
679 integer :: i, j, k, ierr
680
681 call h5gopen_f(file_id, "Payloads", payloads_id, ierr)
682
683 do i = 1, chkp%payload_count()
684 call hdf5_checkpoint_open_group(payloads_id, &
685 chkp%payloads(i)%ptr%name, .false., payload_id)
686
687 do j = 1, chkp%payloads(i)%ptr%field_count()
688 call hdf5_checkpoint_read_field(payload_id, plist_id, &
689 h5_neko_real, chkp%payloads(i)%ptr%fields(j)%ptr, &
690 layout)
691 end do
692
693 do j = 1, chkp%payloads(i)%ptr%series_count()
694 do k = 1, chkp%payloads(i)%ptr%series(j)%ptr%size()
695 call hdf5_checkpoint_read_field(payload_id, plist_id, &
696 h5_neko_real, &
697 chkp%payloads(i)%ptr%series(j)%ptr%lf(k), layout)
698 end do
699 end do
700
701 do j = 1, chkp%payloads(i)%ptr%mesh_array_count()
702 call hdf5_checkpoint_read_mesh_array(payload_id, plist_id, &
703 h5_neko_real, chkp%payloads(i)%ptr%mesh_arrays(j)%ptr, &
704 layout)
705 end do
706
707 do j = 1, chkp%payloads(i)%ptr%array_count()
708 call hdf5_checkpoint_read_array(payload_id, plist_id, &
709 h5_neko_real, chkp%payloads(i)%ptr%arrays(j)%ptr)
710 end do
711
712 call h5gclose_f(payload_id, ierr)
713 end do
714
715 call h5gclose_f(payloads_id, ierr)
716
717 end subroutine hdf5_checkpoint_read_payloads
718
724 subroutine hdf5_checkpoint_open_group(root_id, path, create, group_id)
725 integer(hid_t), intent(in) :: root_id
726 character(len=*), intent(in) :: path
727 logical, intent(in) :: create
728 integer(hid_t), intent(out) :: group_id
729 integer(hid_t) :: current_id, next_id
730 integer :: first, last, slash, path_len, ierr
731 logical :: group_exists
732 character(len=:), allocatable :: group_name
733
734 current_id = root_id
735 first = 1
736 path_len = len_trim(path)
737
738 do
739 slash = index(path(first:path_len), "/")
740 if (slash .eq. 0) then
741 last = path_len
742 else
743 last = first + slash - 2
744 end if
745
746 group_name = path(first:last)
747 call h5lexists_f(current_id, group_name, group_exists, ierr)
748 if (group_exists) then
749 call h5gopen_f(current_id, group_name, next_id, ierr)
750 else if (create) then
751 call h5gcreate_f(current_id, group_name, next_id, ierr)
752 else
753 call neko_error("Checkpoint payload group '" // trim(path) // &
754 "' is missing")
755 end if
756
757 if (current_id .ne. root_id) call h5gclose_f(current_id, ierr)
758 current_id = next_id
759
760 if (slash .eq. 0) exit
761 first = last + 2
762 end do
763
764 group_id = current_id
765
766 end subroutine hdf5_checkpoint_open_group
767
773 subroutine hdf5_checkpoint_write_field(group_id, plist_id, &
774 h5_neko_real, fld)
775 integer(hid_t), intent(in) :: group_id, plist_id, h5_neko_real
776 type(field_t), intent(in) :: fld
777 integer(hid_t) :: dset_id, filespace, memspace
778 integer(hsize_t), dimension(1) :: ddim, dcount, doffset
779 integer :: ierr
780
781 dcount(1) = int(fld%dof%size(), 8)
782 doffset(1) = int(fld%msh%offset_el, 8) * int(fld%Xh%lxyz, 8)
783 ddim = dcount
784 call mpi_allreduce(mpi_in_place, ddim(1), 1, &
785 mpi_integer8, mpi_sum, neko_comm, ierr)
786
787 call h5screate_simple_f(1, ddim, filespace, ierr)
788 call h5screate_simple_f(1, dcount, memspace, ierr)
789 call h5sselect_hyperslab_f(filespace, h5s_select_set_f, &
790 doffset, dcount, ierr)
791 call h5dcreate_f(group_id, trim(fld%name), h5_neko_real, &
792 filespace, dset_id, ierr)
793 call h5dwrite_f(dset_id, h5_neko_real, fld%x(1,1,1,1), &
794 dcount, ierr, file_space_id = filespace, mem_space_id = memspace, &
795 xfer_prp = plist_id)
796
797 call h5dclose_f(dset_id, ierr)
798 call h5sclose_f(filespace, ierr)
799 call h5sclose_f(memspace, ierr)
800
801 end subroutine hdf5_checkpoint_write_field
802
809 subroutine hdf5_checkpoint_read_field(group_id, plist_id, &
810 h5_neko_real, fld, layout)
811 integer(hid_t), intent(in) :: group_id, plist_id, h5_neko_real
812 type(field_t), intent(inout) :: fld
813 type(hdf5_checkpoint_layout_t), target, intent(inout) :: layout
814 integer(hid_t) :: dset_id, filespace, memspace
815 integer(hsize_t), dimension(1) :: dcount, doffset
816 real(kind=rp), allocatable :: checkpoint_data(:)
817 type(interpolator_t) :: space_interp
818 integer :: ierr
819 logical :: dataset_exists
820
821 call h5lexists_f(group_id, trim(fld%name), dataset_exists, ierr)
822 if (.not. dataset_exists) then
823 call neko_error("Checkpoint field '" // trim(fld%name) // &
824 "' is missing")
825 end if
826
827 call h5dopen_f(group_id, trim(fld%name), dset_id, ierr)
828 call h5dget_space_f(dset_id, filespace, ierr)
829
830 ! The hyperslab follows the file's own layout, which coincides with
831 ! the running case's only when neither the mesh nor the order changed.
832 dcount(1) = int(layout%msh%nelv, hsize_t) * int(layout%Xh%lxyz, hsize_t)
833 doffset(1) = int(layout%msh%offset_el, hsize_t) * &
834 int(layout%Xh%lxyz, hsize_t)
835 call h5screate_simple_f(1, dcount, memspace, ierr)
836 call h5sselect_hyperslab_f(filespace, h5s_select_set_f, &
837 doffset, dcount, ierr)
838
839 if (layout%mesh2mesh) then
840 allocate(checkpoint_data(int(dcount(1))))
841 call h5dread_f(dset_id, h5_neko_real, checkpoint_data, dcount, ierr, &
842 file_space_id = filespace, mem_space_id = memspace, &
843 xfer_prp = plist_id)
844 call rzero(fld%x, fld%dof%size())
845 call layout%global_interp%evaluate(fld%x, checkpoint_data, .true.)
846 deallocate(checkpoint_data)
847 else if (layout%Xh%lxyz .ne. fld%Xh%lxyz) then
848 allocate(checkpoint_data(int(dcount(1))))
849 call h5dread_f(dset_id, h5_neko_real, checkpoint_data, dcount, ierr, &
850 file_space_id = filespace, mem_space_id = memspace, &
851 xfer_prp = plist_id)
852 call space_interp%init(fld%Xh, layout%Xh)
853 call space_interp%map_host(fld%x, checkpoint_data, fld%msh%nelv, &
854 fld%Xh)
855 call space_interp%free()
856 deallocate(checkpoint_data)
857 else
858 call h5dread_f(dset_id, h5_neko_real, fld%x(1,1,1,1), &
859 dcount, ierr, file_space_id = filespace, &
860 mem_space_id = memspace, xfer_prp = plist_id)
861 end if
862
863 call h5dclose_f(dset_id, ierr)
864 call h5sclose_f(filespace, ierr)
865 call h5sclose_f(memspace, ierr)
866
867 end subroutine hdf5_checkpoint_read_field
868
874 subroutine hdf5_checkpoint_write_mesh_array(group_id, plist_id, &
875 h5_neko_real, array)
876 integer(hid_t), intent(in) :: group_id, plist_id, h5_neko_real
877 type(checkpoint_mesh_array_t), intent(in) :: array
878 integer(hid_t) :: dset_id, filespace, memspace, attr_id, attr_space
879 integer(hsize_t), dimension(1) :: ddim, dcount, doffset, attr_dims
880 integer :: nodal_shape(3)
881 integer :: ierr
882
883 dcount(1) = int(size(array%x), hsize_t)
884 doffset(1) = int(array%msh%offset_el, hsize_t) * &
885 int(array%Xh%lxyz, hsize_t)
886 ddim(1) = int(array%msh%glb_nelv, hsize_t) * &
887 int(array%Xh%lxyz, hsize_t)
888
889 call h5screate_simple_f(1, ddim, filespace, ierr)
890 call h5screate_simple_f(1, dcount, memspace, ierr)
891 call h5sselect_hyperslab_f(filespace, h5s_select_set_f, &
892 doffset, dcount, ierr)
893 call h5dcreate_f(group_id, trim(array%name), h5_neko_real, &
894 filespace, dset_id, ierr)
895
896 nodal_shape = [array%Xh%lx, array%Xh%ly, array%Xh%lz]
897 attr_dims(1) = size(nodal_shape)
898 call h5screate_simple_f(1, attr_dims, attr_space, ierr)
899 call h5acreate_f(dset_id, "NodalShape", h5t_native_integer, &
900 attr_space, attr_id, ierr)
901 call h5awrite_f(attr_id, h5t_native_integer, nodal_shape, &
902 attr_dims, ierr)
903 call h5aclose_f(attr_id, ierr)
904 call h5sclose_f(attr_space, ierr)
905
906 call h5dwrite_f(dset_id, h5_neko_real, array%x, dcount, ierr, &
907 file_space_id = filespace, mem_space_id = memspace, &
908 xfer_prp = plist_id)
909
910 call h5dclose_f(dset_id, ierr)
911 call h5sclose_f(filespace, ierr)
912 call h5sclose_f(memspace, ierr)
913
914 end subroutine hdf5_checkpoint_write_mesh_array
915
922 subroutine hdf5_checkpoint_read_mesh_array(group_id, plist_id, &
923 h5_neko_real, array, layout)
924 integer(hid_t), intent(in) :: group_id, plist_id, h5_neko_real
925 type(checkpoint_mesh_array_t), intent(inout) :: array
926 type(hdf5_checkpoint_layout_t), target, intent(inout) :: layout
927 integer(hid_t) :: dset_id, filespace, memspace, attr_id, attr_space
928 integer(hsize_t), dimension(1) :: dcount, doffset
929 integer(hsize_t), dimension(1) :: dataset_dims, dataset_maxdims
930 integer(hsize_t), dimension(1) :: attr_dims, attr_maxdims
931 integer :: stored_shape(3)
932 real(kind=rp), allocatable :: stored_data(:)
933 type(neko_space_t), target :: stored_xh
934 type(interpolator_t) :: space_interp
935 integer :: ierr
936 logical :: dataset_exists, shape_exists
937
938 ! Mesh arrays hold ALE state (mesh coordinates, lagged mass matrices),
939 ! which has no meaning on a different mesh. Same check and message as
940 ! chkp_file.
941 if (layout%mesh2mesh) then
942 call neko_error('ALE does not yet support mesh2mesh ' // &
943 'interpolation for restart!')
944 end if
945
946 call h5lexists_f(group_id, trim(array%name), dataset_exists, ierr)
947 if (.not. dataset_exists) then
948 call neko_error("Checkpoint mesh array '" // trim(array%name) // &
949 "' is missing")
950 end if
951
952 call h5dopen_f(group_id, trim(array%name), dset_id, ierr)
953 call h5dget_space_f(dset_id, filespace, ierr)
954 call h5sget_simple_extent_dims_f(filespace, dataset_dims, &
955 dataset_maxdims, ierr)
956
957 stored_shape = [layout%Xh%lx, layout%Xh%ly, layout%Xh%lz]
958 call h5aexists_f(dset_id, "NodalShape", shape_exists, ierr)
959 if (shape_exists) then
960 call h5aopen_f(dset_id, "NodalShape", attr_id, ierr)
961 else
962 ! Compatibility with development checkpoints using generic blocks.
963 call h5aexists_f(dset_id, "BlockShape", shape_exists, ierr)
964 if (shape_exists) then
965 call h5aopen_f(dset_id, "BlockShape", attr_id, ierr)
966 end if
967 end if
968 if (shape_exists) then
969 call h5aget_space_f(attr_id, attr_space, ierr)
970 call h5sget_simple_extent_dims_f(attr_space, attr_dims, &
971 attr_maxdims, ierr)
972 if (attr_dims(1) .ne. 3) then
973 call neko_error("Checkpoint mesh-array nodal shape must have " // &
974 "three dimensions")
975 end if
976 call h5aread_f(attr_id, h5t_native_integer, stored_shape, &
977 attr_dims, ierr)
978 call h5sclose_f(attr_space, ierr)
979 call h5aclose_f(attr_id, ierr)
980 end if
981
982 if (any(stored_shape .le. 0)) then
983 call neko_error("Checkpoint mesh-array nodal shape must be positive")
984 end if
985 if (array%msh%gdim .eq. 3) then
986 call stored_xh%init(gll, stored_shape(1), stored_shape(2), &
987 stored_shape(3))
988 else
989 if (stored_shape(3) .ne. 1) then
990 call neko_error("Two-dimensional checkpoint mesh arrays must " // &
991 "have one nodal plane")
992 end if
993 call stored_xh%init(gll, stored_shape(1), stored_shape(2))
994 end if
995
996 if (int(dataset_dims(1), i8) .ne. &
997 int(layout%msh%glb_nelv, i8) * int(stored_xh%lxyz, i8)) then
998 call neko_error("Checkpoint mesh array '" // trim(array%name) // &
999 "' does not match the current mesh")
1000 end if
1001
1002 dcount(1) = int(layout%msh%nelv, hsize_t) * &
1003 int(stored_xh%lxyz, hsize_t)
1004 doffset(1) = int(layout%msh%offset_el, hsize_t) * &
1005 int(stored_xh%lxyz, hsize_t)
1006 call h5screate_simple_f(1, dcount, memspace, ierr)
1007 call h5sselect_hyperslab_f(filespace, h5s_select_set_f, &
1008 doffset, dcount, ierr)
1009
1010 if (stored_xh%lxyz .eq. array%Xh%lxyz) then
1011 call h5dread_f(dset_id, h5_neko_real, array%x, dcount, ierr, &
1012 file_space_id = filespace, mem_space_id = memspace, &
1013 xfer_prp = plist_id)
1014 else
1015 allocate(stored_data(int(dcount(1))))
1016 call h5dread_f(dset_id, h5_neko_real, stored_data, dcount, ierr, &
1017 file_space_id = filespace, mem_space_id = memspace, &
1018 xfer_prp = plist_id)
1019 call space_interp%init(array%Xh, stored_xh)
1020 call space_interp%map_host(array%x, stored_data, array%msh%nelv, &
1021 array%Xh)
1022 call space_interp%free()
1023 deallocate(stored_data)
1024 end if
1025
1026 call stored_xh%free()
1027 call h5dclose_f(dset_id, ierr)
1028 call h5sclose_f(filespace, ierr)
1029 call h5sclose_f(memspace, ierr)
1030
1031 end subroutine hdf5_checkpoint_read_mesh_array
1032
1038 subroutine hdf5_checkpoint_write_array(group_id, plist_id, &
1039 h5_neko_real, array)
1040 integer(hid_t), intent(in) :: group_id, plist_id, h5_neko_real
1041 type(checkpoint_array_t), intent(in) :: array
1042 integer(hid_t) :: dset_id, filespace, memspace, h5_type
1043 integer(hsize_t), dimension(1) :: ddim, dcount, doffset
1044 integer :: ierr
1045 logical :: stored_dp
1046
1047 ! Arrays registered through `add_array_dp` keep double precision in the
1048 ! file whatever `rp` is, so that the time history survives a restart into
1049 ! a build of the other precision.
1050 stored_dp = associated(array%x_dp)
1051 if (stored_dp) then
1052 h5_type = h5t_native_double
1053 dcount(1) = int(size(array%x_dp), hsize_t)
1054 else
1055 h5_type = h5_neko_real
1056 dcount(1) = int(size(array%x), hsize_t)
1057 end if
1058 ddim(1) = int(array%global_count, hsize_t)
1059 doffset(1) = int(array%offset, hsize_t)
1060
1061 call h5screate_simple_f(1, ddim, filespace, ierr)
1062 call h5screate_simple_f(1, dcount, memspace, ierr)
1063 call h5dcreate_f(group_id, trim(array%name), h5_type, &
1064 filespace, dset_id, ierr)
1065
1066 if (array%replicated .and. pe_rank .ne. 0) then
1067 call h5sselect_none_f(filespace, ierr)
1068 call h5sselect_none_f(memspace, ierr)
1069 else
1070 call h5sselect_hyperslab_f(filespace, h5s_select_set_f, &
1071 doffset, dcount, ierr)
1072 end if
1073
1074 if (stored_dp) then
1075 call h5dwrite_f(dset_id, h5_type, array%x_dp, dcount, ierr, &
1076 file_space_id = filespace, mem_space_id = memspace, &
1077 xfer_prp = plist_id)
1078 else
1079 call h5dwrite_f(dset_id, h5_type, array%x, dcount, ierr, &
1080 file_space_id = filespace, mem_space_id = memspace, &
1081 xfer_prp = plist_id)
1082 end if
1083
1084 call h5dclose_f(dset_id, ierr)
1085 call h5sclose_f(filespace, ierr)
1086 call h5sclose_f(memspace, ierr)
1087
1088 end subroutine hdf5_checkpoint_write_array
1089
1095 subroutine hdf5_checkpoint_read_array(group_id, plist_id, &
1096 h5_neko_real, array)
1097 integer(hid_t), intent(in) :: group_id, plist_id, h5_neko_real
1098 type(checkpoint_array_t), intent(inout) :: array
1099 integer(hid_t) :: dset_id, filespace, memspace, h5_type
1100 integer(hsize_t), dimension(1) :: dcount, doffset
1101 integer(hsize_t), dimension(1) :: dataset_dims, dataset_maxdims
1102 integer :: ierr
1103 logical :: dataset_exists, stored_dp
1104
1105 call h5lexists_f(group_id, trim(array%name), dataset_exists, ierr)
1106 if (.not. dataset_exists) then
1107 call neko_error("Checkpoint array '" // trim(array%name) // &
1108 "' is missing")
1109 end if
1110
1111 call h5dopen_f(group_id, trim(array%name), dset_id, ierr)
1112 call h5dget_space_f(dset_id, filespace, ierr)
1113 call h5sget_simple_extent_dims_f(filespace, dataset_dims, &
1114 dataset_maxdims, ierr)
1115
1116 if (int(dataset_dims(1), i8) .ne. array%global_count) then
1117 call neko_error("Checkpoint array '" // trim(array%name) // &
1118 "' has an incompatible global extent")
1119 end if
1120
1121 stored_dp = associated(array%x_dp)
1122 if (stored_dp) then
1123 h5_type = h5t_native_double
1124 dcount(1) = int(size(array%x_dp), hsize_t)
1125 else
1126 h5_type = h5_neko_real
1127 dcount(1) = int(size(array%x), hsize_t)
1128 end if
1129 doffset(1) = int(array%offset, hsize_t)
1130 call h5screate_simple_f(1, dcount, memspace, ierr)
1131
1132 if (array%replicated .and. pe_rank .ne. 0) then
1133 call h5sselect_none_f(filespace, ierr)
1134 call h5sselect_none_f(memspace, ierr)
1135 else
1136 call h5sselect_hyperslab_f(filespace, h5s_select_set_f, &
1137 doffset, dcount, ierr)
1138 end if
1139 if (stored_dp) then
1140 call h5dread_f(dset_id, h5_type, array%x_dp, dcount, ierr, &
1141 file_space_id = filespace, mem_space_id = memspace, &
1142 xfer_prp = plist_id)
1143 else
1144 call h5dread_f(dset_id, h5_type, array%x, dcount, ierr, &
1145 file_space_id = filespace, mem_space_id = memspace, &
1146 xfer_prp = plist_id)
1147 end if
1148
1149 call h5dclose_f(dset_id, ierr)
1150 call h5sclose_f(filespace, ierr)
1151 call h5sclose_f(memspace, ierr)
1152
1153 ! Only rank zero selected the dataset above, so the copy every rank holds
1154 ! has to come from there.
1155 if (array%replicated) then
1156 if (stored_dp) then
1157 call mpi_bcast(array%x_dp, size(array%x_dp), &
1158 mpi_double_precision, 0, neko_comm, ierr)
1159 else
1160 call mpi_bcast(array%x, size(array%x), mpi_real_precision, 0, &
1161 neko_comm, ierr)
1162 end if
1163 end if
1164
1165 end subroutine hdf5_checkpoint_read_array
1166
1175 subroutine hdf5_file_determine_data(data, msh, dof, fp, fsp, dtlag, tlag)
1176 class(*), target, intent(in) :: data
1177 type(mesh_t), pointer, intent(inout) :: msh
1178 type(dofmap_t), pointer, intent(inout) :: dof
1179 type(field_ptr_t), allocatable, intent(inout) :: fp(:)
1180 type(field_series_ptr_t), allocatable, intent(inout) :: fsp(:)
1181 real(kind=dp), pointer, intent(inout) :: dtlag(:)
1182 real(kind=dp), pointer, intent(inout) :: tlag(:)
1183 integer :: i, j, fp_size, fp_cur, fsp_size, fsp_cur
1184
1185 select type (data)
1186 type is (field_t)
1187 dof => data%dof
1188 msh => data%msh
1189 fp_size = 1
1190 allocate(fp(fp_size))
1191 fp(1)%ptr => data
1192
1193 nullify(dtlag)
1194 nullify(tlag)
1195
1196 type is (field_list_t)
1197
1198 if (data%size() .gt. 0) then
1199 allocate(fp(data%size()))
1200
1201 dof => data%dof(1)
1202 msh => data%msh(1)
1203
1204 do i = 1, data%size()
1205 fp(i)%ptr => data%items(i)%ptr
1206 end do
1207 else
1208 call neko_error('Empty field list')
1209 end if
1210
1211 nullify(dtlag)
1212 nullify(tlag)
1213
1214 type is (chkp_t)
1215 block
1216 type(checkpoint_payload_t), pointer :: fluid
1217 type(field_t), pointer :: u
1218
1219 fluid => data%get_payload("fluid")
1220 u => fluid%find_field("u")
1221 if (.not. associated(u) .or. &
1222 .not. associated(fluid%find_field("v")) .or. &
1223 .not. associated(fluid%find_field("w")) .or. &
1224 .not. associated(fluid%find_field("p"))) then
1225 call neko_error("Checkpoint not initialized")
1226 end if
1227 dof => u%dof
1228 msh => u%msh
1229
1230 fp_size = 0
1231 fsp_size = 0
1232 do i = 1, data%payload_count()
1233 fp_size = fp_size + data%payloads(i)%ptr%field_count()
1234 fsp_size = fsp_size + data%payloads(i)%ptr%series_count()
1235 end do
1236
1237 if (fp_size .gt. 0) allocate(fp(fp_size))
1238 if (fsp_size .gt. 0) allocate(fsp(fsp_size))
1239
1240 fp_cur = 1
1241 fsp_cur = 1
1242 do i = 1, data%payload_count()
1243 do j = 1, data%payloads(i)%ptr%field_count()
1244 fp(fp_cur)%ptr => data%payloads(i)%ptr%fields(j)%ptr
1245 fp_cur = fp_cur + 1
1246 end do
1247 do j = 1, data%payloads(i)%ptr%series_count()
1248 fsp(fsp_cur)%ptr => data%payloads(i)%ptr%series(j)%ptr
1249 fsp_cur = fsp_cur + 1
1250 end do
1251 end do
1252
1253 call data%get_time_history(tlag, dtlag)
1254 end block
1255
1256 class default
1257 call neko_log%error('Invalid data')
1258 end select
1259
1260 end subroutine hdf5_file_determine_data
1261
1265 subroutine hdf5_file_determine_real(H5T_NEKO_REAL)
1266 integer(hid_t), intent(inout) :: H5T_NEKO_REAL
1267 select case (rp)
1268 case (dp)
1269 h5t_neko_real = h5t_native_double
1270 case (sp)
1271 h5t_neko_real = h5t_native_real
1272 case default
1273 call neko_error("Unsupported real type")
1274 end select
1275 end subroutine hdf5_file_determine_real
1276
1277 ! ================
1278 ! Granular methods
1279 ! ================
1280
1282 subroutine hdf5_file_open(this, mode)
1283 class(hdf5_file_t), intent(inout) :: this
1284 character(len=1), intent(in) :: mode
1285 integer :: ierr, mpi_info, mpi_comm, i, n_fields, counter
1286 logical :: file_exists
1287 character(len=1024) :: fname
1288 character(len=LOG_SIZE) :: log_buf
1289
1290 ! Set the mode for the file
1291 this%mode = mode
1292
1293 ! Ensure precision is set and are valid.
1294 if (this%precision .gt. rp) then
1295 this%precision = rp
1296 call neko_warning('Requested precision is higher than working precision')
1297 else if (this%precision .eq. -1) then
1298 this%precision = rp
1299 end if
1300
1301 fname = trim(file_get_fname(this))
1302 counter = this%get_counter() - this%get_start_counter()
1303
1304 ! Set the configuration for MPI IO
1305 call hdf5_session_init()
1306
1307 mpi_info = mpi_info_null%mpi_val
1308 mpi_comm = neko_comm%mpi_val
1309 call h5pcreate_f(h5p_file_access_f, this%plist_id, ierr)
1310 call h5pset_fapl_mpio_f(this%plist_id, mpi_comm, mpi_info, ierr)
1311
1312 ! Open the file
1313 inquire(file = fname, exist = file_exists)
1314 if (file_exists) then
1315 call h5fopen_f(fname, h5f_acc_rdwr_f, this%file_id, ierr, &
1316 access_prp = this%plist_id)
1317 else
1318 call h5fcreate_f(fname, h5f_acc_trunc_f, &
1319 this%file_id, ierr, access_prp = this%plist_id)
1320 end if
1321
1322 ! Set the active group to the root of the file
1323 call this%set_active_group()
1324
1325 write (log_buf, *) "Opened HDF5 file: ", trim(fname), " with counter: ", &
1326 counter
1327 call neko_log%message(log_buf, lvl = neko_log_debug)
1328
1329 end subroutine hdf5_file_open
1330
1332 subroutine hdf5_file_close(this)
1333 class(hdf5_file_t), intent(inout) :: this
1334 integer :: ierr
1335
1336 if (this%active_group_id .ne. -1_hid_t .and. &
1337 this%active_group_id .ne. this%file_id) then
1338 call h5gclose_f(this%active_group_id, ierr)
1339 end if
1340 this%active_group_id = -1_hid_t
1341
1342 call h5pclose_f(this%plist_id, ierr)
1343 this%plist_id = -1_hid_t
1344 call h5fclose_f(this%file_id, ierr)
1345 this%file_id = -1_hid_t
1346 call hdf5_session_finalize()
1347
1348 call neko_log%message("Closed HDF5 file: " // trim(this%get_fname()), &
1349 lvl = neko_log_debug)
1350
1351 end subroutine hdf5_file_close
1352
1353
1357 subroutine hdf5_file_set_group(this, group_name_path)
1358 class(hdf5_file_t), intent(inout) :: this
1359 character(len=*), intent(in), optional :: group_name_path
1360 character(len=1000), allocatable :: group_name(:)
1361
1362 integer(hid_t) :: current_id, group_id
1363 integer :: ierr, i, j, num_groups, name_len, group_loc
1364 logical :: group_exists
1365
1366
1367 ! Close previous active group if one is open
1368 if (this%active_group_id .ne. -1_hid_t .and. this%active_group_id .ne. &
1369 this%file_id) then
1370 call h5gclose_f(this%active_group_id, ierr)
1371 end if
1372 this%active_group_id = -1_hid_t
1373
1374 ! Start from root location = file
1375 current_id = this%file_id
1376 ! Return the root directory if no group name is given
1377 if (.not. present(group_name_path)) then
1378 this%active_group_id = current_id
1379 return
1380 end if
1381
1382 ! Split the input string into group names using "/" as a delimiter
1383 name_len = len(trim(group_name_path))
1384 ! Count how many groups
1385 num_groups = 1 ! There is at least one group if this was passed
1386 do i = 1, name_len
1387 if (group_name_path .eq. "/") then
1388 num_groups = num_groups + 1
1389 end if
1390 end do
1391
1392 ! Allocate the group array and populate it
1393 allocate(group_name(num_groups))
1394 j = 1
1395 group_loc = 1
1396 do i = 1, name_len
1397 if (group_name_path .eq. "/") then
1398 group_name(group_loc) = group_name_path(j:i-1)
1399 group_loc = group_loc + 1
1400 j = i + 1
1401 end if
1402 end do
1403 if (j .ne. name_len) then
1404 group_name(group_loc) = group_name_path(j:name_len)
1405 end if
1406
1407 ! Iterate over the groups in the path
1408 do i = 1, num_groups
1409 call h5lexists_f(current_id, trim(group_name(i)), group_exists, ierr)
1410
1411 ! Only create groups if they dont exist and we are in write mode "w"
1412 if (group_exists) then
1413 call h5gopen_f(current_id, trim(group_name(i)), group_id, ierr)
1414 else
1415 if (this%mode == "r") then
1416 call neko_error("Group " // trim(group_name(i)) // &
1417 " does not exist in file " // trim(file_get_fname(this)))
1418 end if
1419 call h5gcreate_f(current_id, trim(group_name(i)), group_id, ierr)
1420 end if
1421
1422 ! Close previous location only if it was an opened group, not the file
1423 if (i > 1) then
1424 call h5gclose_f(current_id, ierr)
1425 end if
1426
1427 current_id = group_id
1428 end do
1429
1430 this%active_group_id = current_id
1431 end subroutine hdf5_file_set_group
1432
1433
1434 subroutine hdf5_file_write_dataset(this, data)
1435 class(hdf5_file_t), intent(inout) :: this
1436 class(*), intent(inout) :: data
1437
1438 select type (d => data)
1439 type is (vector_t)
1440 call this%write_vector(d)
1441 type is (matrix_t)
1442 call this%write_matrix(d)
1443 type is (field_t)
1444 call this%write_field(d)
1445 class default
1446 call neko_error("write_dataset not implemented for this data type")
1447 end select
1448 end subroutine hdf5_file_write_dataset
1449
1450 subroutine hdf5_file_read_dataset(this, data_name, data, strategy)
1451 class(hdf5_file_t), intent(inout) :: this
1452 character(len=*), intent(in) :: data_name
1453 class(*), intent(inout) :: data
1454 character(len=*), intent(in), optional :: strategy
1455
1456 select type (d => data)
1457 type is (vector_t)
1458 call this%read_vector(data_name, d, strategy)
1459 type is (matrix_t)
1460 call this%read_matrix(data_name, d, strategy)
1461 type is (field_t)
1462 call neko_error("Reading a field_t is not supported yet")
1463 class default
1464 call neko_error("read_dataset not implemented for this data type")
1465 end select
1466 end subroutine hdf5_file_read_dataset
1467
1468 subroutine hdf5_file_write_attribute(this, data_name, data)
1469 class(hdf5_file_t), intent(inout) :: this
1470 character(len=*), intent(in) :: data_name
1471 class(*), intent(inout) :: data
1472
1473 select type (d => data)
1474 type is (integer)
1475 call this%write_int_attribute(data_name, d)
1476 type is (real(kind=rp))
1477 call this%write_rp_attribute(data_name, d)
1478 class default
1479 call neko_error("write_attribute not implemented for this data type")
1480 end select
1481 end subroutine hdf5_file_write_attribute
1482
1483 subroutine hdf5_file_read_attribute(this, data_name, data, exist)
1484 class(hdf5_file_t), intent(inout) :: this
1485 character(len=*), intent(in) :: data_name
1486 class(*), intent(inout) :: data
1487 logical, intent(inout) :: exist
1488
1489 select type (d => data)
1490 type is (integer)
1491 call this%read_int_attribute(data_name, d, exist)
1492 type is (real(kind=rp))
1493 call this%read_rp_attribute(data_name, d, exist)
1494 class default
1495 call neko_error("read_attribute not implemented for this data type")
1496 end select
1497 end subroutine hdf5_file_read_attribute
1498
1499
1500 subroutine hdf5_file_write_vector(this, vec)
1501 class(hdf5_file_t), intent(inout) :: this
1502 type(vector_t), intent(inout) :: vec
1503 integer :: ierr, counts, offset, total_count, dset_rank, max_count
1504 integer(hsize_t) :: append_offset
1505 integer(hid_t) :: precision_hdf
1506 integer(hid_t) :: xf_id, filespace, dset_id, memspace, dcpl_id
1507 integer(hsize_t), dimension(1) :: dcount, doffset
1508 integer(hsize_t), dimension(1) :: ddims, ddims_max, chunkdims
1509 integer(hsize_t), dimension(1) :: tempddims, tempmaxddims
1510 logical :: dset_exists
1511 real(kind=sp), allocatable :: write_buffer_sp(:) ! Write buffer single
1512 real(kind=dp), allocatable :: write_buffer_dp(:) ! Write buffer double
1513
1514 ! ===============
1515 ! Get vector info
1516 ! ===============
1517 counts = vec%size()
1518 append_offset = 0_hsize_t
1519 offset = 0
1520 total_count = 0
1521 max_count = 0
1522 call mpi_scan(counts, offset, 1, mpi_integer, &
1523 mpi_sum, neko_comm, ierr)
1524 offset = offset - counts ! Not using exclusive scan
1525 call mpi_allreduce(counts, total_count, 1, mpi_integer, &
1526 mpi_sum, neko_comm, ierr)
1527 call mpi_allreduce(counts, max_count, 1, mpi_integer, &
1528 mpi_max, neko_comm, ierr)
1529
1530 ! ===============
1531 ! Configure MPIIO
1532 ! ===============
1533 call h5pcreate_f(h5p_dataset_xfer_f, xf_id, ierr)
1534 call h5pset_dxpl_mpio_f(xf_id, h5fd_mpio_collective_f, ierr)
1535 precision_hdf = h5kind_to_type(this%precision, h5_real_kind)
1536
1537 ! ===================
1538 ! Create the data set
1539 ! ===================
1540 dset_rank = 1 ! rank 1 array, i.e. a vector
1541 ddims = [int(total_count, hsize_t)] ! global size of the vector
1542
1543 ! Enable chunking to be able to append
1544 chunkdims = [max(int(max_count, hsize_t), 1_hsize_t)]
1545 ddims_max = [h5s_unlimited_f] ! allow unlimited size for appending
1546 call h5lexists_f(this%active_group_id, trim(vec%name), dset_exists, ierr)
1547 if (dset_exists) then
1548 if (this%overwrite) then
1549 ! retrieve the dset id for the existing data set
1550 call h5dopen_f(this%active_group_id, trim(vec%name), dset_id, ierr)
1551 else
1552 ! Retreive the existing data set
1553 call h5dopen_f(this%active_group_id, trim(vec%name), dset_id, ierr)
1554 ! Retrieve the current filespace (shape space)
1555 call h5dget_space_f(dset_id, filespace, ierr)
1556 ! Get the current shape
1557 call h5sget_simple_extent_dims_f(filespace, tempddims, tempmaxddims, &
1558 ierr)
1559 ! Clean up the opened file space
1560 call h5sclose_f(filespace, ierr)
1561 ! Overwrite the new full shape
1562 ddims(1) = ddims(1) + tempddims(1) ! New size
1563 append_offset = tempddims(1) ! current size which is the offset
1564 ! Extend the data set to the new shape
1565 call h5dset_extent_f(dset_id, ddims, ierr)
1566 end if
1567 else
1568 ! create file space of this shape
1569 call h5screate_simple_f(dset_rank, ddims, filespace, ierr, ddims_max)
1570 ! Create chunk property list (needed to be able to append)
1571 call h5pcreate_f(h5p_dataset_create_f, dcpl_id, ierr)
1572 call h5pset_chunk_f(dcpl_id, dset_rank, chunkdims, ierr)
1573 ! create the data set with the given shape
1574 call h5dcreate_f(this%active_group_id, trim(vec%name), precision_hdf, &
1575 filespace, dset_id, ierr, dcpl_id = dcpl_id)
1576 ! clean opened ids
1577 call h5sclose_f(filespace, ierr)
1578 call h5pclose_f(dcpl_id, ierr)
1579 end if
1580
1581 ! ===========================
1582 ! Set up writing the data set
1583 ! ===========================
1584 dcount = [int(counts, hsize_t)] ! local size of the vector
1585
1586 ! offset for this rank in the global vector
1587 doffset = [int(offset, hsize_t) + append_offset]
1588 ! Get the total file space (shape) of the data set
1589 call h5dget_space_f(dset_id, filespace, ierr)
1590 ! Get only the slice where my rank writes
1591 call h5sselect_hyperslab_f(filespace, h5s_select_set_f, doffset, dcount, &
1592 ierr)
1593 ! Create the corresponding memory space (buffer) for my local data
1594 call h5screate_simple_f(dset_rank, dcount, memspace, ierr)
1595
1596
1597 ! =======================
1598 ! Cast and write the data
1599 ! =======================
1600 if (this%precision == sp) then
1601 allocate(write_buffer_sp(vec%size()))
1602 if (vec%size() > 0) write_buffer_sp = real(vec%x, kind=sp)
1603 ! Write the data
1604 call h5dwrite_f(dset_id, precision_hdf, write_buffer_sp, dcount, ierr, &
1605 file_space_id = filespace, mem_space_id = memspace, &
1606 xfer_prp = xf_id)
1607 deallocate(write_buffer_sp)
1608 else if (this%precision == dp) then
1609 allocate(write_buffer_dp(vec%size()))
1610 if (vec%size() > 0) write_buffer_dp = real(vec%x, kind=dp)
1611 ! Write the data
1612 call h5dwrite_f(dset_id, precision_hdf, write_buffer_dp, dcount, ierr, &
1613 file_space_id = filespace, mem_space_id = memspace, &
1614 xfer_prp = xf_id)
1615 deallocate(write_buffer_dp)
1616 else
1617 call neko_error("Unsupported precision")
1618 end if
1619
1620 ! =======================
1621 ! Clean up
1622 ! =======================
1623 call h5pclose_f(xf_id, ierr)
1624 call h5sclose_f(memspace, ierr)
1625 call h5sclose_f(filespace, ierr)
1626 call h5dclose_f(dset_id, ierr)
1627
1628 end subroutine hdf5_file_write_vector
1629
1630 subroutine hdf5_file_write_matrix(this, mat)
1631 class(hdf5_file_t), intent(inout) :: this
1632 type(matrix_t), intent(inout) :: mat
1633 integer :: ierr, counts, offset, total_count, dset_rank, strides, max_count
1634 integer(hsize_t) :: append_offset
1635 integer(hid_t) :: precision_hdf
1636 integer(hid_t) :: xf_id, filespace, dset_id, memspace, dcpl_id
1637 integer(hsize_t), dimension(2) :: dcount, doffset
1638 integer(hsize_t), dimension(2) :: ddims, ddims_max, chunkdims
1639 integer(hsize_t), dimension(2) :: tempddims, tempmaxddims
1640 logical :: dset_exists
1641 real(kind=sp), allocatable :: write_buffer_sp(:,:) ! Write buffer single
1642 real(kind=dp), allocatable :: write_buffer_dp(:,:) ! Write buffer double
1643
1644 ! ===============
1645 ! Get Matrix info
1646 ! ===============
1647 strides = mat%get_nrows()
1648 counts = mat%get_ncols()
1649 append_offset = 0_hsize_t
1650 total_count = 0
1651 max_count = 0
1652 offset = 0
1653 call mpi_scan(counts, offset, 1, mpi_integer, &
1654 mpi_sum, neko_comm, ierr)
1655 offset = offset - counts ! Not using exclusive scan
1656 call mpi_allreduce(counts, total_count, 1, mpi_integer, &
1657 mpi_sum, neko_comm, ierr)
1658 call mpi_allreduce(counts, max_count, 1, mpi_integer, &
1659 mpi_max, neko_comm, ierr)
1660
1661 ! ===============
1662 ! Configure MPIIO
1663 ! ===============
1664 call h5pcreate_f(h5p_dataset_xfer_f, xf_id, ierr)
1665 call h5pset_dxpl_mpio_f(xf_id, h5fd_mpio_collective_f, ierr)
1666 precision_hdf = h5kind_to_type(this%precision, h5_real_kind)
1667
1668 ! ===================
1669 ! Create the data set
1670 ! ===================
1671 dset_rank = 2 ! rank 2 array, i.e. a matrix
1672 ! global size of the matrix
1673 ddims = [int(strides, hsize_t), int(total_count, hsize_t)]
1674 chunkdims = [int(strides, hsize_t), max(int(max_count, hsize_t), 1_hsize_t)]
1675 ddims_max = [int(strides, hsize_t), h5s_unlimited_f]
1676 call h5lexists_f(this%active_group_id, trim(mat%name), dset_exists, ierr)
1677 if (dset_exists) then
1678 if (this%overwrite) then
1679
1680 if (pe_rank .eq. 0) then
1681 call neko_warning("Dataset " // trim(mat%name) // &
1682 " already exists and wil be overwritten")
1683 end if
1684 ! retrieve the dset id for the existing data set
1685 call h5dopen_f(this%active_group_id, trim(mat%name), dset_id, ierr)
1686 else
1687 call h5dopen_f(this%active_group_id, trim(mat%name), dset_id, ierr)
1688 call h5dget_space_f(dset_id, filespace, ierr)
1689 call h5sget_simple_extent_dims_f(filespace, tempddims, tempmaxddims, &
1690 ierr)
1691 call h5sclose_f(filespace, ierr)
1692 ddims(2) = ddims(2) + tempddims(2)
1693 append_offset = tempddims(2)
1694 call h5dset_extent_f(dset_id, ddims, ierr)
1695 end if
1696 else
1697 ! create file space of this shape
1698 call h5screate_simple_f(dset_rank, ddims, filespace, ierr, ddims_max)
1699 call h5pcreate_f(h5p_dataset_create_f, dcpl_id, ierr)
1700 call h5pset_chunk_f(dcpl_id, dset_rank, chunkdims, ierr)
1701 ! create the data set with the given shape
1702 call h5dcreate_f(this%active_group_id, trim(mat%name), precision_hdf, &
1703 filespace, dset_id, ierr, dcpl_id = dcpl_id)
1704 call h5sclose_f(filespace, ierr)
1705 call h5pclose_f(dcpl_id, ierr)
1706 end if
1707
1708 ! ===========================
1709 ! Set up writing the data set
1710 ! ===========================
1711 ! local size of the matrix
1712 dcount = [int(strides, hsize_t), int(counts, hsize_t)]
1713 ! offset for this rank in the global matrix
1714 doffset = [0_hsize_t, int(offset, hsize_t) + append_offset]
1715 ! Get the total file space (shape) of the data set
1716 call h5dget_space_f(dset_id, filespace, ierr)
1717 ! Get only the slice where my rank writes
1718 call h5sselect_hyperslab_f(filespace, h5s_select_set_f, doffset, dcount, &
1719 ierr)
1720 ! Create the corresponding memory space (buffer) for my local data
1721 call h5screate_simple_f(dset_rank, dcount, memspace, ierr)
1722
1723 ! =======================
1724 ! Cast and write the data
1725 ! =======================
1726 if (this%precision == sp) then
1727 allocate(write_buffer_sp(mat%get_nrows(), mat%get_ncols()))
1728 if (mat%size() > 0) write_buffer_sp = real(mat%x, kind=sp)
1729 ! Write the data
1730 call h5dwrite_f(dset_id, precision_hdf, write_buffer_sp, dcount, ierr, &
1731 file_space_id = filespace, mem_space_id = memspace, &
1732 xfer_prp = xf_id)
1733 deallocate(write_buffer_sp)
1734 else if (this%precision == dp) then
1735 allocate(write_buffer_dp(mat%get_nrows(), mat%get_ncols()))
1736 if (mat%size() > 0) write_buffer_dp = real(mat%x, kind=dp)
1737 ! Write the data
1738 call h5dwrite_f(dset_id, precision_hdf, write_buffer_dp, dcount, ierr, &
1739 file_space_id = filespace, mem_space_id = memspace, &
1740 xfer_prp = xf_id)
1741 deallocate(write_buffer_dp)
1742 else
1743 call neko_error("Unsupported precision")
1744 end if
1745
1746 ! =======================
1747 ! Clean up
1748 ! =======================
1749 call h5pclose_f(xf_id, ierr)
1750 call h5sclose_f(memspace, ierr)
1751 call h5sclose_f(filespace, ierr)
1752 call h5dclose_f(dset_id, ierr)
1753
1754 end subroutine hdf5_file_write_matrix
1755
1756 subroutine hdf5_file_write_field(this, field)
1757 class(hdf5_file_t), intent(inout) :: this
1758 type(field_t), intent(inout) :: field
1759 integer :: ierr, counts, offset, total_count, dset_rank, max_count
1760 integer :: stride_ax_1, stride_ax_2, stride_ax_3
1761 integer(hsize_t) :: append_offset
1762 integer(hid_t) :: precision_hdf
1763 integer(hid_t) :: xf_id, filespace, dset_id, memspace, dcpl_id
1764 integer(hsize_t), dimension(4) :: dcount, doffset
1765 integer(hsize_t), dimension(4) :: ddims, ddims_max, chunkdims
1766 integer(hsize_t), dimension(4) :: tempddims, tempmaxddims
1767 logical :: dset_exists
1768 real(kind=sp), allocatable :: write_buffer_sp(:,:,:,:) ! Write buffer single
1769 real(kind=dp), allocatable :: write_buffer_dp(:,:,:,:) ! Write buffer double
1770
1771 ! ==============
1772 ! Get Field info
1773 ! ==============
1774 stride_ax_1 = field%Xh%lx
1775 stride_ax_2 = field%Xh%ly
1776 stride_ax_3 = field%Xh%lz
1777 counts = field%msh%nelv
1778 append_offset = 0_hsize_t
1779 total_count = field%msh%glb_nelv
1780 max_count = 0
1781 offset = field%msh%offset_el
1782 call mpi_allreduce(counts, max_count, 1, mpi_integer, &
1783 mpi_max, neko_comm, ierr)
1784
1785 ! ===============
1786 ! Configure MPIIO
1787 ! ===============
1788 call h5pcreate_f(h5p_dataset_xfer_f, xf_id, ierr)
1789 call h5pset_dxpl_mpio_f(xf_id, h5fd_mpio_collective_f, ierr)
1790 precision_hdf = h5kind_to_type(this%precision, h5_real_kind)
1791
1792 ! ===================
1793 ! Create the data set
1794 ! ===================
1795 dset_rank = 4 ! rank 4 array, i.e. a 4D tensor
1796 ddims = [int(stride_ax_1, hsize_t), &
1797 int(stride_ax_2, hsize_t), &
1798 int(stride_ax_3, hsize_t), &
1799 int(total_count, hsize_t)] ! global size of the tensor
1800 chunkdims = [int(stride_ax_1, hsize_t), &
1801 int(stride_ax_2, hsize_t), &
1802 int(stride_ax_3, hsize_t), &
1803 max(int(max_count, hsize_t), 1_hsize_t)]
1804 ddims_max = [int(stride_ax_1, hsize_t), &
1805 int(stride_ax_2, hsize_t), &
1806 int(stride_ax_3, hsize_t), &
1807 h5s_unlimited_f]
1808 call h5lexists_f(this%active_group_id, trim(field%name), dset_exists, ierr)
1809 if (dset_exists) then
1810 if (this%overwrite) then
1811 ! retrieve the dset id for the existing data set
1812 if (pe_rank .eq. 0) then
1813 call neko_warning("Overwriting dataset: " // trim(field%name))
1814 end if
1815 call h5dopen_f(this%active_group_id, trim(field%name), dset_id, ierr)
1816 else
1817 call h5dopen_f(this%active_group_id, trim(field%name), dset_id, ierr)
1818 call h5dget_space_f(dset_id, filespace, ierr)
1819 call h5sget_simple_extent_dims_f(filespace, tempddims, tempmaxddims, &
1820 ierr)
1821 call h5sclose_f(filespace, ierr)
1822 ddims(4) = ddims(4) + tempddims(4)
1823 append_offset = tempddims(4)
1824 call h5dset_extent_f(dset_id, ddims, ierr)
1825 end if
1826 else
1827 ! create file space of this shape
1828 call h5screate_simple_f(dset_rank, ddims, filespace, ierr, ddims_max)
1829 call h5pcreate_f(h5p_dataset_create_f, dcpl_id, ierr)
1830 call h5pset_chunk_f(dcpl_id, dset_rank, chunkdims, ierr)
1831 ! create the data set with the given shape
1832 call h5dcreate_f(this%active_group_id, trim(field%name), precision_hdf, &
1833 filespace, dset_id, ierr, dcpl_id = dcpl_id)
1834 call h5sclose_f(filespace, ierr)
1835 call h5pclose_f(dcpl_id, ierr)
1836 end if
1837
1838 ! ===========================
1839 ! Set up writing the data set
1840 ! ===========================
1841 dcount = [int(stride_ax_1, hsize_t), &
1842 int(stride_ax_2, hsize_t), &
1843 int(stride_ax_3, hsize_t), &
1844 int(counts, hsize_t)] ! local size of the tensor
1845 doffset = [0_hsize_t, 0_hsize_t, 0_hsize_t, &
1846 int(offset, hsize_t) + append_offset] ! offset in the global tensor
1847 ! Get the total file space (shape) of the data set
1848 call h5dget_space_f(dset_id, filespace, ierr)
1849 ! Get only the slice where my rank writes
1850 call h5sselect_hyperslab_f(filespace, h5s_select_set_f, doffset, dcount, &
1851 ierr)
1852 ! Create the corresponding memory space (buffer) for my local data
1853 call h5screate_simple_f(dset_rank, dcount, memspace, ierr)
1854
1855 ! =======================
1856 ! Cast and write the data
1857 ! =======================
1858 if (this%precision == sp) then
1859 allocate(write_buffer_sp(field%Xh%lx, field%Xh%ly, field%Xh%lz, &
1860 field%msh%nelv))
1861 if (field%msh%nelv > 0) write_buffer_sp = real(field%x, kind=sp)
1862 ! Write the data
1863 call h5dwrite_f(dset_id, precision_hdf, write_buffer_sp, dcount, ierr, &
1864 file_space_id = filespace, mem_space_id = memspace, &
1865 xfer_prp = xf_id)
1866 deallocate(write_buffer_sp)
1867 else if (this%precision == dp) then
1868 allocate(write_buffer_dp(field%Xh%lx, field%Xh%ly, field%Xh%lz, &
1869 field%msh%nelv))
1870 if (field%msh%nelv > 0) write_buffer_dp = real(field%x, kind=dp)
1871 ! Write the data
1872 call h5dwrite_f(dset_id, precision_hdf, write_buffer_dp, dcount, ierr, &
1873 file_space_id = filespace, mem_space_id = memspace, &
1874 xfer_prp = xf_id)
1875 deallocate(write_buffer_dp)
1876 else
1877 call neko_error("Unsupported precision")
1878 end if
1879
1880 ! =======================
1881 ! Clean up
1882 ! =======================
1883 call h5pclose_f(xf_id, ierr)
1884 call h5sclose_f(memspace, ierr)
1885 call h5sclose_f(filespace, ierr)
1886 call h5dclose_f(dset_id, ierr)
1887
1888 end subroutine hdf5_file_write_field
1889
1891 subroutine hdf5_file_read_vector(this, data_name, vec, strategy)
1892 class(hdf5_file_t) :: this
1893 character(len=*), intent(in) :: data_name
1894 type(vector_t), intent(inout) :: vec
1895 character(len=*), intent(in), optional :: strategy
1896 character(len=1000) :: strategy_
1897 integer :: ierr, counts, offset, total_count, dset_rank
1898 integer(hid_t) :: precision_hdf
1899 integer(hid_t) :: xf_id, filespace, dset_id, memspace
1900 integer(hsize_t), dimension(1) :: dcount, doffset
1901 integer(hsize_t), dimension(1) :: tempddims, tempmaxddims
1902 integer :: temprank
1903 logical :: dset_exists
1904 type(linear_dist_t) :: dist
1905
1906 ! Set up strategy
1907 if (present(strategy)) then
1908 if (trim(strategy) .eq. "linear" .or. &
1909 trim(strategy) .eq. "rank_0") then
1910 strategy_ = strategy
1911 else
1912 call neko_error("Unsupported strategy: " // trim(strategy))
1913 end if
1914 else
1915 strategy_ = "linear"
1916 end if
1917
1918 ! Free the input
1919 call vec%free()
1920
1921 ! ===============
1922 ! Configure MPIIO
1923 ! ===============
1924 call h5pcreate_f(h5p_dataset_xfer_f, xf_id, ierr)
1925 call h5pset_dxpl_mpio_f(xf_id, h5fd_mpio_collective_f, ierr)
1926 precision_hdf = h5kind_to_type(rp, h5_real_kind)
1927
1928 ! ===================
1929 ! Get the data set info
1930 ! ===================
1931 call h5lexists_f(this%active_group_id, trim(data_name), dset_exists, ierr)
1932 if (dset_exists) then
1933 ! Open the data set
1934 call h5dopen_f(this%active_group_id, trim(data_name), dset_id, ierr)
1935 ! Get the current rank of the dataset
1936 call h5dget_space_f(dset_id, filespace, ierr)
1937 call h5sget_simple_extent_ndims_f(filespace, temprank, ierr)
1938 if (temprank .ne. 1) then
1939 call neko_error("Dataset " // trim(data_name) // &
1940 " is not a rank 1 vector in file " // trim(file_get_fname(this)))
1941 end if
1942 ! Get the current shape and close the filespace
1943 call h5sget_simple_extent_dims_f(filespace, tempddims, tempmaxddims, &
1944 ierr)
1945 call h5sclose_f(filespace, ierr)
1946 else
1947 call neko_error("Dataset " // trim(data_name) // &
1948 " does not exist in current group " // trim(file_get_fname(this)))
1949 end if
1950
1951 ! =============================
1952 ! Perform the data distribution
1953 ! =============================
1954 total_count = int(tempddims(1))
1955 if (strategy_ .eq. "linear") then
1956 dist = linear_dist_t(total_count, pe_rank, pe_size, neko_comm)
1957 counts = dist%num_local()
1958 offset = 0
1959 else if (strategy_ .eq. "rank_0") then
1960 if (pe_rank .eq. 0) then
1961 counts = total_count
1962 else
1963 counts = 0
1964 end if
1965 offset = 0
1966 end if
1967 call mpi_exscan(counts, offset, 1, mpi_integer, &
1968 mpi_sum, neko_comm, ierr)
1969
1970 ! ===========================
1971 ! Set up reading the data set
1972 ! ===========================
1973 dset_rank = 1 ! rank 1 array, i.e. a vector
1974 dcount = [int(counts, hsize_t)] ! local size of the vector
1975 doffset = [int(offset, hsize_t)] ! offset for this rank in the global vector
1976 ! Get the total file space (shape) of the data set
1977 call h5dget_space_f(dset_id, filespace, ierr)
1978 ! Get only the slice where my rank reads
1979 call h5sselect_hyperslab_f(filespace, h5s_select_set_f, doffset, dcount, &
1980 ierr)
1981 ! Create the corresponding memory space (buffer) for my local data
1982 call h5screate_simple_f(dset_rank, dcount, memspace, ierr)
1983
1984 ! =============================
1985 ! Allocate data. HDF5 will cast
1986 ! =============================
1987 call vec%init(counts, trim(data_name)) ! this is rp
1988 call h5dread_f(dset_id, precision_hdf, vec%x, dcount, ierr, &
1989 file_space_id = filespace, mem_space_id = memspace, &
1990 xfer_prp = xf_id)
1991
1992 ! =======================
1993 ! Clean up
1994 ! =======================
1995 call h5pclose_f(xf_id, ierr)
1996 call h5sclose_f(memspace, ierr)
1997 call h5sclose_f(filespace, ierr)
1998 call h5dclose_f(dset_id, ierr)
1999
2000 end subroutine hdf5_file_read_vector
2001
2003 subroutine hdf5_file_read_matrix(this, data_name, mat, strategy)
2004 class(hdf5_file_t) :: this
2005 character(len=*), intent(in) :: data_name
2006 type(matrix_t), intent(inout) :: mat
2007 character(len=*), intent(in), optional :: strategy
2008 character(len=1000) :: strategy_
2009 integer :: ierr, counts, offset, total_count, dset_rank
2010 integer(hid_t) :: precision_hdf
2011 integer(hid_t) :: xf_id, filespace, dset_id, memspace
2012 integer(hsize_t), dimension(2) :: dcount, doffset
2013 integer(hsize_t), dimension(2) :: tempddims, tempmaxddims
2014 integer :: temprank
2015 logical :: dset_exists
2016 type(linear_dist_t) :: dist
2017
2018 ! Set up strategy
2019 if (present(strategy)) then
2020 if (trim(strategy) .eq. "linear" .or. &
2021 trim(strategy) .eq. "rank_0") then
2022 strategy_ = strategy
2023 else
2024 call neko_error("Unsupported strategy: " // trim(strategy))
2025 end if
2026 else
2027 strategy_ = "linear"
2028 end if
2029
2030 ! Free the input
2031 call mat%free()
2032
2033 ! ===============
2034 ! Configure MPIIO
2035 ! ===============
2036 call h5pcreate_f(h5p_dataset_xfer_f, xf_id, ierr)
2037 call h5pset_dxpl_mpio_f(xf_id, h5fd_mpio_collective_f, ierr)
2038 precision_hdf = h5kind_to_type(rp, h5_real_kind)
2039
2040 ! ===================
2041 ! Get the data set info
2042 ! ===================
2043 call h5lexists_f(this%active_group_id, trim(data_name), dset_exists, ierr)
2044 if (dset_exists) then
2045 ! Openr the data set
2046 call h5dopen_f(this%active_group_id, trim(data_name), dset_id, ierr)
2047 ! Get the current rank of the of the dataset
2048 call h5dget_space_f(dset_id, filespace, ierr)
2049 call h5sget_simple_extent_ndims_f(filespace, temprank, ierr)
2050 if (temprank .ne. 2) then
2051 call neko_error("Dataset " // trim(data_name) // &
2052 " is not a rank 2 matrix in file " // trim(file_get_fname(this)))
2053 end if
2054 ! Get the current shape and close the filespace
2055 call h5sget_simple_extent_dims_f(filespace, tempddims, tempmaxddims, &
2056 ierr)
2057 call h5sclose_f(filespace, ierr)
2058 else
2059 call neko_error("Dataset " // trim(data_name) &
2060 // " does not exist in current group " // &
2061 trim(file_get_fname(this)))
2062 end if
2063
2064 ! =============================
2065 ! Perform the data distribution
2066 ! =============================
2067 total_count = int(tempddims(2))
2068 if (strategy_ .eq. "linear") then
2069 dist = linear_dist_t(total_count, pe_rank, pe_size, neko_comm)
2070 counts = dist%num_local()
2071 offset = 0
2072 else if (strategy_ .eq. "rank_0") then
2073 if (pe_rank .eq. 0) then
2074 counts = total_count
2075 else
2076 counts = 0
2077 end if
2078 offset = 0
2079 end if
2080 call mpi_scan(counts, offset, 1, mpi_integer, &
2081 mpi_sum, neko_comm, ierr)
2082 offset = offset - counts ! Not using exclusive scan
2083
2084 ! ===========================
2085 ! Set up reading the data set
2086 ! ===========================
2087 dset_rank = 2 ! rank 2 array, i.e. a matrix
2088 dcount = [int(tempddims(1), hsize_t), int(counts, hsize_t)] ! local size
2089 doffset = [0_hsize_t, int(offset, hsize_t)] ! offset in the global matrix
2090 ! Get the total file space (shape) of the data set
2091 call h5dget_space_f(dset_id, filespace, ierr)
2092 ! Get only the slice where my rank reads
2093 call h5sselect_hyperslab_f(filespace, h5s_select_set_f, doffset, dcount, &
2094 ierr)
2095 ! Create the corresponding memory space (buffer) for my local data
2096 call h5screate_simple_f(dset_rank, dcount, memspace, ierr)
2097
2098 ! =============================
2099 ! Allocate data. HDF5 will cast
2100 ! =============================
2101 call mat%init(int(tempddims(1)), counts, trim(data_name)) ! this is rp
2102 call h5dread_f(dset_id, precision_hdf, mat%x, dcount, ierr, &
2103 file_space_id = filespace, mem_space_id = memspace, &
2104 xfer_prp = xf_id)
2105
2106 ! =======================
2107 ! Clean up
2108 ! =======================
2109 call h5pclose_f(xf_id, ierr)
2110 call h5sclose_f(memspace, ierr)
2111 call h5sclose_f(filespace, ierr)
2112 call h5dclose_f(dset_id, ierr)
2113
2114
2115 end subroutine hdf5_file_read_matrix
2116
2118 subroutine hdf5_file_write_int_attribute(this, attr_name, attr)
2119 class(hdf5_file_t), intent(inout) :: this
2120 character(len=*), intent(in) :: attr_name
2121 integer, intent(in) :: attr
2122 integer :: ierr
2123 integer(hid_t) :: filespace, attr_id
2124 integer(hsize_t), dimension(1) :: dcount
2125 logical :: attr_exists
2126
2127 ! ====================
2128 ! Create the attribute
2129 ! ====================
2130 dcount = [int(1, hsize_t)]
2131 call h5aexists_f(this%active_group_id, trim(attr_name), attr_exists, ierr)
2132 if (attr_exists) then
2133 ! retrieve the attr id for the existing attribute
2134 call h5aopen_f(this%active_group_id, trim(attr_name), attr_id, ierr)
2135 else
2136 ! create file space of this shape
2137 call h5screate_f(h5s_scalar_f, filespace, ierr)
2138 ! create the data set with the given shape
2139 call h5acreate_f(this%active_group_id, trim(attr_name), &
2140 h5t_native_integer, &
2141 filespace, attr_id, ierr, h5p_default_f, h5p_default_f)
2142 call h5sclose_f(filespace, ierr)
2143 end if
2144
2145 ! ===========================
2146 ! Set up writing the data set
2147 ! ===========================
2148 call h5awrite_f(attr_id, h5t_native_integer, attr, dcount, ierr)
2149
2150 ! =======================
2151 ! Clean up
2152 ! =======================
2153 call h5aclose_f(attr_id, ierr)
2154
2155 end subroutine hdf5_file_write_int_attribute
2156
2158 subroutine hdf5_file_write_rp_attribute(this, attr_name, attr)
2159 class(hdf5_file_t), intent(inout) :: this
2160 character(len=*), intent(in) :: attr_name
2161 real(kind=rp), intent(in) :: attr
2162 integer :: ierr
2163 integer(hid_t) :: precision_hdf
2164 integer(hid_t) :: filespace, attr_id
2165 integer(hsize_t), dimension(1) :: dcount
2166 logical :: attr_exists
2167
2168 ! Get the precision
2169 precision_hdf = h5kind_to_type(rp, h5_real_kind)
2170
2171 ! ====================
2172 ! Create the attribute
2173 ! ====================
2174 dcount = [int(1, hsize_t)]
2175 call h5aexists_f(this%active_group_id, trim(attr_name), attr_exists, ierr)
2176 if (attr_exists) then
2177 ! retrieve the attr id for the existing attribute
2178 call h5aopen_f(this%active_group_id, trim(attr_name), attr_id, ierr)
2179 else
2180 ! create file space of this shape
2181 call h5screate_f(h5s_scalar_f, filespace, ierr)
2182 ! create the data set with the given shape
2183 call h5acreate_f(this%active_group_id, trim(attr_name), precision_hdf, &
2184 filespace, attr_id, ierr, h5p_default_f, h5p_default_f)
2185 call h5sclose_f(filespace, ierr)
2186 end if
2187
2188 ! ===========================
2189 ! Set up writing the data set
2190 ! ===========================
2191 call h5awrite_f(attr_id, precision_hdf, attr, dcount, ierr)
2192
2193 ! =======================
2194 ! Clean up
2195 ! =======================
2196 call h5aclose_f(attr_id, ierr)
2197
2198 end subroutine hdf5_file_write_rp_attribute
2199
2201 subroutine hdf5_file_read_int_attribute(this, attr_name, attr, attr_exists)
2202 class(hdf5_file_t), intent(inout) :: this
2203 character(len=*), intent(in) :: attr_name
2204 integer, intent(inout) :: attr
2205 logical, intent(inout) :: attr_exists
2206 integer :: ierr
2207 integer(hid_t) :: filespace, attr_id
2208 integer(hsize_t), dimension(1) :: dcount
2209
2210 ! ====================
2211 ! Create the attribute
2212 ! ====================
2213 dcount = [int(1, hsize_t)]
2214 call h5aexists_f(this%active_group_id, trim(attr_name), attr_exists, ierr)
2215 if (attr_exists) then
2216 ! retrieve the attr id for the existing attribute
2217 call h5aopen_f(this%active_group_id, trim(attr_name), attr_id, ierr)
2218 else
2219 return
2220 end if
2221
2222 ! ===========================
2223 ! Set up writing the data set
2224 ! ===========================
2225 call h5aread_f(attr_id, h5t_native_integer, attr, dcount, ierr)
2226
2227 ! =======================
2228 ! Clean up
2229 ! =======================
2230 call h5aclose_f(attr_id, ierr)
2231
2232 end subroutine hdf5_file_read_int_attribute
2233
2235 subroutine hdf5_file_read_rp_attribute(this, attr_name, attr, attr_exists)
2236 class(hdf5_file_t), intent(inout) :: this
2237 character(len=*), intent(in) :: attr_name
2238 real(kind=rp), intent(inout) :: attr
2239 logical, intent(inout) :: attr_exists
2240 integer :: ierr
2241 integer(hid_t) :: precision_hdf
2242 integer(hid_t) :: filespace, attr_id
2243 integer(hsize_t), dimension(1) :: dcount
2244
2245 ! Get the precision
2246 precision_hdf = h5kind_to_type(rp, h5_real_kind)
2247
2248 ! ====================
2249 ! Create the attribute
2250 ! ====================
2251 dcount = [int(1, hsize_t)]
2252 call h5aexists_f(this%active_group_id, trim(attr_name), attr_exists, ierr)
2253 if (attr_exists) then
2254 ! retrieve the attr id for the existing attribute
2255 call h5aopen_f(this%active_group_id, trim(attr_name), attr_id, ierr)
2256 else
2257 return
2258 end if
2259
2260 ! ===========================
2261 ! Set up writing the data set
2262 ! ===========================
2263 call h5aread_f(attr_id, precision_hdf, attr, dcount, ierr)
2264
2265 ! =======================
2266 ! Clean up
2267 ! =======================
2268 call h5aclose_f(attr_id, ierr)
2269
2270 end subroutine hdf5_file_read_rp_attribute
2271
2272#else
2273
2275 subroutine hdf5_file_open(this, mode)
2276 class(hdf5_file_t), intent(inout) :: this
2277 character(len=1), intent(in) :: mode
2278 call neko_error('Neko needs to be built with HDF5 support')
2279 end subroutine hdf5_file_open
2280
2282 subroutine hdf5_file_close(this)
2283 class(hdf5_file_t), intent(inout) :: this
2284 call neko_error('Neko needs to be built with HDF5 support')
2285 end subroutine hdf5_file_close
2286
2288 subroutine hdf5_file_set_group(this, group_name_path)
2289 class(hdf5_file_t), intent(inout) :: this
2290 character(len=*), intent(in), optional :: group_name_path
2291 call neko_error('Neko needs to be built with HDF5 support')
2292 end subroutine hdf5_file_set_group
2293
2297 subroutine hdf5_file_write(this, data, t)
2298 class(hdf5_file_t), intent(inout) :: this
2299 class(*), target, intent(in) :: data
2300 real(kind=dp), intent(in), optional :: t
2301 call neko_error('Neko needs to be built with HDF5 support')
2302 end subroutine hdf5_file_write
2303
2306 subroutine hdf5_file_read(this, data)
2307 class(hdf5_file_t) :: this
2308 class(*), target, intent(inout) :: data
2309 call neko_error('Neko needs to be built with HDF5 support')
2310 end subroutine hdf5_file_read
2311
2312 subroutine hdf5_file_write_dataset(this, data)
2313 class(hdf5_file_t), intent(inout) :: this
2314 class(*), intent(inout) :: data
2315 call neko_error('Neko needs to be built with HDF5 support')
2316 end subroutine hdf5_file_write_dataset
2317
2318 subroutine hdf5_file_read_dataset(this, data_name, data, strategy)
2319 class(hdf5_file_t), intent(inout) :: this
2320 character(len=*), intent(in) :: data_name
2321 class(*), intent(inout) :: data
2322 character(len=*), intent(in), optional :: strategy
2323 call neko_error('Neko needs to be built with HDF5 support')
2324 end subroutine hdf5_file_read_dataset
2325
2326 subroutine hdf5_file_write_attribute(this, data_name, data)
2327 class(hdf5_file_t), intent(inout) :: this
2328 character(len=*), intent(in) :: data_name
2329 class(*), intent(inout) :: data
2330 call neko_error('Neko needs to be built with HDF5 support')
2331 end subroutine hdf5_file_write_attribute
2332
2333 subroutine hdf5_file_read_attribute(this, data_name, data, exist)
2334 class(hdf5_file_t), intent(inout) :: this
2335 character(len=*), intent(in) :: data_name
2336 class(*), intent(inout) :: data
2337 logical, intent(inout) :: exist
2338 call neko_error('Neko needs to be built with HDF5 support')
2339 end subroutine hdf5_file_read_attribute
2340
2341 subroutine hdf5_file_write_vector(this, vec)
2342 class(hdf5_file_t), intent(inout) :: this
2343 type(vector_t), intent(inout) :: vec
2344 call neko_error('Neko needs to be built with HDF5 support')
2345 end subroutine hdf5_file_write_vector
2346
2347 subroutine hdf5_file_write_matrix(this, mat)
2348 class(hdf5_file_t), intent(inout) :: this
2349 type(matrix_t), intent(inout) :: mat
2350 call neko_error('Neko needs to be built with HDF5 support')
2351 end subroutine hdf5_file_write_matrix
2352
2353 subroutine hdf5_file_write_field(this, fld)
2354 class(hdf5_file_t), intent(inout) :: this
2355 type(field_t), intent(inout) :: fld
2356 call neko_error('Neko needs to be built with HDF5 support')
2357 end subroutine hdf5_file_write_field
2358
2359 subroutine hdf5_file_read_vector(this, data_name, vec, strategy)
2360 class(hdf5_file_t) :: this
2361 character(len=*), intent(in) :: data_name
2362 type(vector_t), intent(inout) :: vec
2363 character(len=*), intent(in), optional :: strategy
2364 call neko_error('Neko needs to be built with HDF5 support')
2365 end subroutine hdf5_file_read_vector
2366
2367 subroutine hdf5_file_read_matrix(this, data_name, mat, strategy)
2368 class(hdf5_file_t) :: this
2369 character(len=*), intent(in) :: data_name
2370 type(matrix_t), intent(inout) :: mat
2371 character(len=*), intent(in), optional :: strategy
2372 call neko_error('Neko needs to be built with HDF5 support')
2373 end subroutine hdf5_file_read_matrix
2374
2375 subroutine hdf5_file_write_int_attribute(this, attr_name, attr)
2376 class(hdf5_file_t), intent(inout) :: this
2377 character(len=*), intent(in) :: attr_name
2378 integer, intent(in) :: attr
2379 call neko_error('Neko needs to be built with HDF5 support')
2380 end subroutine hdf5_file_write_int_attribute
2381
2382 subroutine hdf5_file_write_rp_attribute(this, attr_name, attr)
2383 class(hdf5_file_t), intent(inout) :: this
2384 character(len=*), intent(in) :: attr_name
2385 real(kind=rp), intent(in) :: attr
2386 call neko_error('Neko needs to be built with HDF5 support')
2387 end subroutine hdf5_file_write_rp_attribute
2388
2389 subroutine hdf5_file_read_int_attribute(this, attr_name, attr, attr_exists)
2390 class(hdf5_file_t), intent(inout) :: this
2391 character(len=*), intent(in) :: attr_name
2392 integer, intent(inout) :: attr
2393 logical, intent(inout) :: attr_exists
2394 call neko_error('Neko needs to be built with HDF5 support')
2395 end subroutine hdf5_file_read_int_attribute
2396
2397 subroutine hdf5_file_read_rp_attribute(this, attr_name, attr, attr_exists)
2398 class(hdf5_file_t), intent(inout) :: this
2399 character(len=*), intent(in) :: attr_name
2400 real(kind=rp), intent(inout) :: attr
2401 logical, intent(inout) :: attr_exists
2402 call neko_error('Neko needs to be built with HDF5 support')
2403 end subroutine hdf5_file_read_rp_attribute
2404
2405#endif
2406
2407end module hdf5_file
double real
Format-independent checkpoint payloads.
Defines format-independent checkpoint registration and restart state.
Definition comm.F90:1
type(mpi_datatype), public mpi_real_precision
MPI type for working precision of REAL types.
Definition comm.F90:54
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
Implements global_interpolation given a dofmap.
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_checkpoint_layout_free(this)
Release the interpolation state and the function space of a layout. The mesh is only referenced; it b...
subroutine hdf5_file_write_dataset(this, data)
subroutine hdf5_file_set_overwrite(this, overwrite)
Set the overwrite flag for HDF5 files.
HDF5 session management.
subroutine, public hdf5_session_init
Initialise the global HDF5 session HDF5 does not maintain a global reference count,...
subroutine, public hdf5_session_finalize
Finalize the global HDF5 session.
Routines to interpolate between different spaces.
Logging routines.
Definition log.f90:34
integer, parameter, public neko_log_debug
Debug.
Definition log.f90:56
type(log_t), public neko_log
Global log stream.
Definition log.f90:91
integer, parameter, public log_size
Definition log.f90:46
Definition math.f90:60
subroutine, public rzero(a, n)
Zero a real vector.
Definition math.f90:239
Defines a matrix.
Definition matrix.f90:34
Defines a mesh.
Definition mesh.f90:34
integer, parameter, public i8
Definition num_types.f90:7
integer, parameter, public dp
Definition num_types.f90:10
integer, parameter, public sp
Definition num_types.f90:8
integer, parameter, public rp
Global precision used in computations.
Definition num_types.f90:14
Defines a function space.
Definition space.f90:34
integer, parameter, public gll
Definition space.f90:50
Utilities.
Definition utils.f90:35
subroutine, public filename_split(fname, path, name, suffix)
Extract file name components.
Definition utils.f90:168
subroutine, public neko_warning(warning_msg)
Reports a warning to standard output.
Definition utils.f90:452
pure integer function, public filename_suffix_pos(fname)
Find position (in the string) of a filename's suffix.
Definition utils.f90:111
Defines a vector.
Definition vector.f90:34
Collection of live simulation data registered for checkpointing.
A named real array and its selection in a global checkpoint dataset.
A named nodal real array distributed over mesh elements.
A named collection of live fields to checkpoint together.
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.
Implements global interpolation for arbitrary points in the domain.
Where the data in a checkpoint file sits and how it maps onto the running case. Built once per read a...
Interface for HDF5 files.
Definition hdf5_file.F90:68
Interpolation between two space::space_t.
The function space for the SEM solution fields.
Definition space.f90:64
#define max(a, b)
Definition tensor.cu:40