Skip to content

Commit 99862f0

Browse files
committed
unify: add %create(fill_value=)
1 parent 362c777 commit 99862f0

File tree

4 files changed

+104
-5
lines changed

4 files changed

+104
-5
lines changed

src/interface.f90

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ module h5mpi
103103

104104
interface !< write.f90
105105

106-
module subroutine hdf_create_user(self, dname, dtype, dset_dims, mem_dims, chunk_size, compact, charlen)
106+
module subroutine hdf_create_user(self, dname, dtype, dset_dims, mem_dims, chunk_size, compact, charlen, fill_value)
107107
class(hdf5_file), intent(in) :: self
108108
character(*), intent(in) :: dname
109109
integer(HID_T), intent(in) :: dtype
@@ -112,11 +112,12 @@ module subroutine hdf_create_user(self, dname, dtype, dset_dims, mem_dims, chunk
112112
integer, intent(in), dimension(:), optional :: chunk_size !< (:) instead of size(dims) due to intel fortran quirk
113113
logical, intent(in), optional :: compact
114114
integer, intent(in), optional :: charlen
115+
class(*), intent(in), optional :: fill_value
115116
end subroutine
116117

117118
module subroutine hdf_create(self, dname, dtype, mem_dims, dset_dims, &
118119
filespace_id, memspace, dset_id, dtype_id, &
119-
istart, iend, stride, chunk_size, compact, charlen)
120+
istart, iend, stride, chunk_size, compact, charlen, fill_value)
120121

121122
class(hdf5_file), intent(in) :: self
122123
character(*), intent(in) :: dname
@@ -127,6 +128,7 @@ module subroutine hdf_create(self, dname, dtype, mem_dims, dset_dims, &
127128
integer, intent(in), dimension(:), optional :: chunk_size, istart, iend, stride
128129
logical, intent(in), optional :: compact
129130
integer, intent(in), optional :: charlen !< length of character scalar
131+
class(*), intent(in), optional :: fill_value
130132
end subroutine
131133

132134
module subroutine write_group(self, group_path)

src/write.f90

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
h5fflush_f, &
55
h5screate_f, h5sclose_f, h5screate_simple_f, &
66
h5dcreate_f, h5dopen_f, h5dclose_f, h5dget_space_f, &
7-
h5pset_chunk_f, h5pset_layout_f, h5pset_deflate_f, h5pset_shuffle_f, h5pset_fletcher32_f, h5pcreate_f, h5pclose_f, &
7+
h5pset_chunk_f, h5pset_layout_f, h5pset_deflate_f, h5pset_shuffle_f, h5pset_fletcher32_f, &
8+
h5pcreate_f, h5pclose_f, h5pset_fill_value_f, &
89
H5P_DATASET_CREATE_F, &
910
h5gopen_f, h5gcreate_f, h5gclose_f, &
1011
H5Lcreate_soft_f, h5lexists_f, &
@@ -38,7 +39,7 @@
3839

3940
call hdf_create(self, dname, dtype, mem_dims=mdims, dset_dims=ddims, &
4041
filespace_id=file_space_id, memspace=mem_space_id, dset_id=dset_id, dtype_id=dtype_id, compact=compact, &
41-
charlen=charlen)
42+
charlen=charlen, fill_value=fill_value)
4243

4344
call h5dclose_f(dset_id, ierr)
4445
if(ierr /= 0) error stop "ERROR:h5fortran:write:create_user: closing dataset: " // dname // " in " // self%filename
@@ -146,6 +147,29 @@
146147
type_id = dtype
147148
endif
148149

150+
!> fill value
151+
if(present(fill_value)) then
152+
if(dcpl == H5P_DEFAULT_F) then
153+
call h5pcreate_f(H5P_DATASET_CREATE_F, dcpl, ierr)
154+
if (ierr /= 0) error stop "ERROR:h5fortran:set_fill:h5pcreate: " // self%filename
155+
endif
156+
157+
select type (fill_value)
158+
!! type_id MUST equal the fill_value type or "transfer()" like bit pattern unexpected data will result
159+
type is (real(real32))
160+
call h5pset_fill_value_f(dcpl, H5T_NATIVE_REAL, fill_value, ierr)
161+
type is (real(real64))
162+
call h5pset_fill_value_f(dcpl, H5T_NATIVE_DOUBLE, fill_value, ierr)
163+
type is (integer(int32))
164+
call h5pset_fill_value_f(dcpl, H5T_NATIVE_INTEGER, fill_value, ierr)
165+
!! int64 is NOT available for h5pset_fill_value_f
166+
type is (character(*))
167+
call h5pset_fill_value_f(dcpl, type_id, fill_value, ierr)
168+
class default
169+
error stop "ERROR:h5fortran:create: unknown fill value type"
170+
end select
171+
endif
172+
149173
!> create dataset
150174
call h5dcreate_f(self%file_id, dname, type_id=type_id, space_id=filespace_id, dset_id=dset_id, hdferr=ierr, dcpl_id=dcpl)
151175
if (ierr /= 0) error stop "ERROR:h5fortran:hdf_create:h5dcreate: " // dname // " in " // self%filename

test/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ target_link_libraries(test_write PRIVATE h5mpi::h5mpi)
5050

5151
add_test(NAME write COMMAND test_write)
5252

53-
set(test_names array attributes cast destructor exist groups layout shape
53+
set(test_names array attributes cast destructor exist fill groups layout shape
5454
string string_read
5555
)
5656

test/test_fill.f90

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
program fill
2+
3+
use, intrinsic:: ieee_arithmetic, only : ieee_value, ieee_quiet_nan, ieee_is_finite
4+
5+
use h5mpi, only : hdf5_file
6+
use hdf5, only : HSIZE_T, H5T_NATIVE_REAL, H5T_NATIVE_DOUBLE, H5T_NATIVE_INTEGER, H5T_NATIVE_CHARACTER
7+
use mpi, only : mpi_init, MPI_COMM_WORLD, mpi_comm_rank
8+
9+
implicit none (type, external)
10+
11+
external :: mpi_finalize
12+
13+
type(hdf5_file) :: h5
14+
15+
character(*), parameter :: fn = "test_fill.h5"
16+
17+
real :: NaN, r(3)
18+
integer :: i(2), ierr, mpi_id
19+
character(10) :: c, fill_value
20+
21+
call mpi_init(ierr)
22+
if (ierr /= 0) error stop "mpi_init"
23+
24+
call mpi_comm_rank(MPI_COMM_WORLD, mpi_id, ierr)
25+
if (ierr /= 0) error stop "mpi_comm_rank"
26+
27+
NaN = ieee_value(0., ieee_quiet_nan)
28+
29+
call h5%open(fn, action="w", mpi=.true.)
30+
31+
call h5%create("/r32", H5T_NATIVE_REAL, dset_dims=[3], fill_value=NaN)
32+
call h5%create("/r64", H5T_NATIVE_DOUBLE, dset_dims=[3], fill_value=NaN)
33+
call h5%create("/i32", H5T_NATIVE_INTEGER, dset_dims=[2], fill_value=-1)
34+
35+
!> Note that character fill value must have same length as dataset, hence we use a character(10)
36+
fill_value = "NaN"
37+
call h5%create("/char", H5T_NATIVE_CHARACTER, dset_dims=[1], fill_value=fill_value, charlen=10)
38+
fill_value = ""
39+
call h5%create("/char_blank", H5T_NATIVE_CHARACTER, dset_dims=[1], fill_value=fill_value, charlen=10)
40+
fill_value = " "
41+
call h5%create("/char_space", H5T_NATIVE_CHARACTER, dset_dims=[1], fill_value=fill_value, charlen=10)
42+
43+
call h5%close()
44+
45+
46+
call h5%open(fn, action="r", mpi=.true.)
47+
48+
call h5%read("/r32", r)
49+
if(any(ieee_is_finite(r))) error stop "real32: expected all NaN"
50+
51+
call h5%read("/r64", r)
52+
if(any(ieee_is_finite(r))) error stop "real64: expected all NaN"
53+
54+
call h5%read("/i32", i)
55+
if(any(i /= -1)) error stop "int32: expected all -1"
56+
57+
call h5%read("/char", c)
58+
if(c /= "NaN") error stop "char: expected 'NaN', got: " // c
59+
60+
call h5%read("/char_blank", c)
61+
if(c /= "") error stop "char: expected '', got: " // c
62+
63+
call h5%read("/char_space", c)
64+
if(c /= " ") error stop "char: expected ' ', got: " // c
65+
66+
call h5%close()
67+
68+
if(mpi_id == 0) print *, "OK: fill value"
69+
70+
call mpi_finalize(ierr)
71+
if (ierr /= 0) error stop "mpi_finalize"
72+
73+
end program

0 commit comments

Comments
 (0)