Skip to content

Commit 3809d39

Browse files
committed
unify: add %create() and stride= indexing
1 parent 04b49f6 commit 3809d39

File tree

7 files changed

+330
-35
lines changed

7 files changed

+330
-35
lines changed

src/interface.f90

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ module h5mpi
3939
procedure, public :: open => h5open
4040
procedure, public :: close => h5close
4141
procedure, public :: write_group
42-
procedure, public :: create => hdf_create
42+
procedure, public :: create => hdf_create_user
4343
procedure, public :: flush => hdf_flush
4444
procedure, public :: filesize => hdf_filesize
4545
procedure, public :: ndim => hdf_get_ndim
@@ -102,6 +102,18 @@ module h5mpi
102102
public :: H5T_INTEGER_F, H5T_FLOAT_F, H5T_STRING_F
103103

104104
interface !< write.f90
105+
106+
module subroutine hdf_create_user(self, dname, dtype, dset_dims, mem_dims, chunk_size, compact, charlen)
107+
class(hdf5_file), intent(in) :: self
108+
character(*), intent(in) :: dname
109+
integer(HID_T), intent(in) :: dtype
110+
integer, dimension(:), intent(in) :: dset_dims
111+
integer, dimension(:), intent(in), optional :: mem_dims
112+
integer, intent(in), dimension(:), optional :: chunk_size !< (:) instead of size(dims) due to intel fortran quirk
113+
logical, intent(in), optional :: compact
114+
integer, intent(in), optional :: charlen
115+
end subroutine
116+
105117
module subroutine hdf_create(self, dname, dtype, mem_dims, dset_dims, &
106118
filespace_id, memspace, dset_id, dtype_id, &
107119
istart, iend, stride, chunk_size, compact, charlen)

src/utils.f90

Lines changed: 33 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -39,16 +39,17 @@
3939

4040
module procedure h5open
4141

42-
character(len=2) :: laction
42+
character(:), allocatable :: laction
4343
integer :: ier
4444
integer(HID_T) :: fapl !< file access property list
45+
integer :: file_mode
4546

4647
if(self%is_open()) then
4748
write(stderr,*) 'h5fortran:open: file handle already open: '//self%filename
4849
return
4950
endif
5051

51-
laction = 'rw'
52+
laction = 'r'
5253
if (present(action)) laction = action
5354

5455
self%filename = filename
@@ -103,34 +104,41 @@
103104

104105
if(self%use_mpi) then
105106
!! collective: setup for MPI access
106-
call h5pcreate_f(H5P_FILE_ACCESS_F, fapl, ier)
107+
call H5Pcreate_f(H5P_FILE_ACCESS_F, fapl, ier)
107108
if(ier /= 0) error stop "ERROR:h5fortran:open:h5pcreate could not collective open property for " // filename
108-
call h5pset_fapl_mpio_f(fapl, mpi_h5comm, mpi_h5info, ier)
109+
call H5Pset_fapl_mpio_f(fapl, mpi_h5comm, mpi_h5info, ier)
109110
if(ier /= 0) error stop "ERROR:h5fortran:open:h5pset_fapl_mpio could not collective open file for " // filename
110111
else
111112
fapl = H5P_DEFAULT_F
112113
endif
113114

114115
select case(laction)
115116
case('r')
116-
if(.not. is_hdf5(filename)) error stop "ERROR:h5fortran:open: file does not exist: "//filename
117-
call h5fopen_f(filename, H5F_ACC_RDONLY_F, self%file_id, ier, access_prp=fapl)
117+
file_mode = H5F_ACC_RDONLY_F
118118
case('r+')
119-
if(.not. is_hdf5(filename)) error stop "ERROR:h5fortran:open: file does not exist: "//filename
120-
call h5fopen_f(filename, H5F_ACC_RDWR_F, self%file_id, ier, access_prp=fapl)
119+
file_mode = H5F_ACC_RDWR_F
121120
case('rw', 'a')
122121
if(is_hdf5(filename)) then
123-
call h5fopen_f(filename, H5F_ACC_RDWR_F, self%file_id, ier, access_prp=fapl)
122+
file_mode = H5F_ACC_RDWR_F
124123
else
125-
call h5fcreate_f(filename, H5F_ACC_TRUNC_F, self%file_id, ier, access_prp=fapl)
124+
file_mode = H5F_ACC_TRUNC_F
126125
endif
127126
case ('w')
128-
call h5fcreate_f(filename, H5F_ACC_TRUNC_F, self%file_id, ier, access_prp=fapl)
127+
file_mode = H5F_ACC_TRUNC_F
129128
case default
130129
error stop 'ERROR:h5fortran:open Unsupported action ' // laction // ' for ' // filename
131130
end select
132131

133-
if (ier /= 0) error stop "ERROR:h5fortran:open: HDF5 file open failed: "//filename
132+
if (file_mode == H5F_ACC_RDONLY_F .or. file_mode == H5F_ACC_RDWR_F) then
133+
if(.not. is_hdf5(filename)) error stop "ERROR:h5fortran:open: not an HDF5 file: "//filename
134+
call H5Fopen_f(filename, file_mode, self%file_id, ier, access_prp=fapl)
135+
if (ier /= 0) error stop "ERROR:h5fortran:open:H5Fopen: " // filename
136+
elseif(file_mode == H5F_ACC_TRUNC_F) then
137+
call H5Fcreate_f(filename, file_mode, self%file_id, ier, access_prp=fapl)
138+
if (ier /= 0) error stop "ERROR:h5fortran:open:H5Fcreate: " // filename
139+
else
140+
error stop "ERROR:h5fortran:open: Unsupported file mode: " // filename
141+
endif
134142

135143
if(fapl /= H5P_DEFAULT_F) then
136144
call h5pclose_f(fapl, ier)
@@ -302,27 +310,30 @@
302310

303311
!> check that all necessary filters to access dataset are available on the system.
304312
call h5dget_create_plist_f(dset_id, dcpl, ierr)
305-
if (ierr/=0) error stop "h5fortran:mpi_hyperslab:h5dget_create_plist: " // dset_name
313+
if (ierr/=0) error stop "ERROR:h5fortran:mpi_hyperslab:h5dget_create_plist: " // dset_name
306314

307315
call h5pall_filters_avail_f(dcpl, filters_OK, ierr)
308-
if (ierr/=0) error stop "h5fortran:mpi_hyperslab:h5pall_filters_avail: " // dset_name
316+
if (ierr/=0) error stop "ERROR:h5fortran:mpi_hyperslab:h5pall_filters_avail: " // dset_name
309317
if (.not. filters_OK) then
310318
error stop "h5fortran: filter(s) missing necessary for dataset " // dset_name // " in parallel with MPI. This is " // &
311319
"typically caused by missing DEFLATE compression with HDF5-MPI."
312320
endif
313321

314322
call h5pclose_f(dcpl, ierr)
315-
if(ierr/=0) error stop "h5fortran:mpi_hyperslab:h5pclose: " // dset_name
323+
if(ierr/=0) error stop "ERROR:h5fortran:mpi_hyperslab:h5pclose: " // dset_name
324+
325+
istride = 1
326+
if(present(stride)) istride = int(stride, HSIZE_T)
316327

317328
if(filespace == H5S_ALL_F) then
318329
!> create dataspace
319330
call h5screate_simple_f(rank=size(dset_dims), dims=dset_dims, space_id=filespace, hdferr=ierr)
320-
if (ierr/=0) error stop "h5fortran:mpi_hyperslab:h5screate_simple:filespace " // dset_name
331+
if (ierr/=0) error stop "ERROR:h5fortran:mpi_hyperslab:h5screate_simple:filespace " // dset_name
321332
endif
322333

323334
!> Select hyperslab in the file.
324335
call h5dget_space_f(dset_id, filespace, ierr)
325-
if (ierr/=0) error stop "h5fortran:mpi_hyperslab:h5dget_space: " // dset_name
336+
if (ierr/=0) error stop "ERROR:h5fortran:mpi_hyperslab:h5dget_space: " // dset_name
326337

327338

328339
! blk(1) = 1
@@ -332,9 +343,6 @@
332343
i0 = istart - 1
333344
c_mem_dims = iend - i0
334345

335-
istride = 1
336-
if(present(stride)) istride = int(stride, HSIZE_T)
337-
338346
if(any(c_mem_dims /= mem_dims)) then
339347
write(stderr,*) "ERROR:h5fortran:mpi_hyperslab: memory size /= dataset size: check variable slice (index). " // &
340348
" Dset_dims:", dset_dims, "C Mem_dims", c_mem_dims
@@ -343,7 +351,7 @@
343351

344352
! print *, 'TRACE:mpi_hyperslab: ' // dset_name //': istart', i0, 'C mem_dims: ', c_mem_dims, 'mem_dims', mem_dims
345353

346-
if(any(c_mem_dims < 1)) error stop "h5mpi:hyperslab:non-positive hyperslab: " // dset_name
354+
if(any(c_mem_dims < 1)) error stop "ERROR:h5mpi:hyperslab:non-positive hyperslab: " // dset_name
347355

348356
call h5sselect_hyperslab_f(filespace, H5S_SELECT_SET_F, &
349357
start=i0, &
@@ -352,11 +360,11 @@
352360
hdferr=ierr)
353361
! block=blk !< would this help performance?
354362

355-
if (ierr/=0) error stop "g5fortran:mpi_hyperslab:h5sselect_hyperslab: " // dset_name
363+
if (ierr/=0) error stop "ERROR:h5fortran:mpi_hyperslab:h5sselect_hyperslab: " // dset_name
356364

357365
!> create memory dataspace
358366
call h5screate_simple_f(rank=size(c_mem_dims), dims=c_mem_dims, space_id=memspace, hdferr=ierr)
359-
if (ierr/=0) error stop "h5fortran:mpi_hyperslab:h5screate_simple:memspace " // dset_name
367+
if (ierr/=0) error stop "ERROR:h5fortran:mpi_hyperslab:h5screate_simple:memspace " // dset_name
360368

361369
end procedure mpi_hyperslab
362370

@@ -367,10 +375,10 @@
367375

368376
!! Create property list for collective dataset operations
369377
call h5pcreate_f(H5P_DATASET_XFER_F, xfer_id, ierr)
370-
if (ierr/=0) error stop "h5pcreate dataset xfer: " // dname
378+
if (ierr/=0) error stop "ERROR:h5fortran:h5pcreate dataset xfer: " // dname
371379

372380
call h5pset_dxpl_mpio_f(xfer_id, H5FD_MPIO_COLLECTIVE_F, ierr)
373-
if (ierr/=0) error stop "h5pset_dxpl_mpio collective: " // dname
381+
if (ierr/=0) error stop "ERROR:h5fortran:h5pset_dxpl_mpio collective: " // dname
374382

375383
! For independent dataset operations
376384
! call h5pset_dxpl_mpio_f(xfer_id, H5FD_MPIO_INDEPENDENT_F, ierr)

src/write.f90

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,40 @@
2121
contains
2222

2323

24+
module procedure hdf_create_user
25+
!! for user %create() method
26+
27+
integer(HID_T) :: file_space_id, mem_space_id, dset_id, dtype_id
28+
integer(HSIZE_T), dimension(size(dset_dims)) :: mdims, ddims
29+
integer :: ierr
30+
31+
ddims = int(dset_dims, HSIZE_T)
32+
33+
if(present(mem_dims)) then
34+
mdims = int(mem_dims, HSIZE_T)
35+
else
36+
mdims = ddims
37+
endif
38+
39+
call hdf_create(self, dname, dtype, mem_dims=mdims, dset_dims=ddims, &
40+
filespace_id=file_space_id, memspace=mem_space_id, dset_id=dset_id, dtype_id=dtype_id, compact=compact, &
41+
charlen=charlen)
42+
43+
call h5dclose_f(dset_id, ierr)
44+
if(ierr /= 0) error stop "ERROR:h5fortran:write:create_user: closing dataset: " // dname // " in " // self%filename
45+
46+
if(file_space_id /= H5S_ALL_F) call h5sclose_f(file_space_id, ierr)
47+
if(ierr /= 0) error stop "ERROR:h5fortran:write:create_user: closing file dataspace: " // dname // " in " // self%filename
48+
49+
if(mem_space_id /= H5S_ALL_F) call h5sclose_f(mem_space_id, ierr)
50+
if(ierr /= 0) error stop "ERROR:h5fortran:write:create_user: closing memory dataspace: " // dname // " in " // self%filename
51+
52+
if(dtype == H5T_NATIVE_CHARACTER) call h5tclose_f(dtype_id, ierr)
53+
if(ierr /= 0) error stop "ERROR:h5fortran:write:create_user: closing datatype: " // dname // " in " // self%filename
54+
55+
end procedure hdf_create_user
56+
57+
2458
module procedure hdf_create
2559

2660
logical :: exists
@@ -241,15 +275,15 @@ subroutine set_deflate(self, dims, dcpl, chunk_size)
241275
if (self%fletcher32) then
242276
!! fletcher32 filter adds a checksum to the data
243277
if (self%use_mpi .and. .not. self%parallel_compression) then
244-
write(stderr, '(a)') 'WARNING: h5fortran:set_deflate: fletcher32 parallel filter not supported ' // self%filename
278+
if(self%mpi_id == 0) write(stderr, '(a)') 'WARNING: h5fortran:set_deflate: fletcher32 parallel not supported ' // self%filename
245279
else
246280
call h5pset_fletcher32_f(dcpl, ierr)
247281
if (ierr /= 0) error stop "ERROR:h5fortran:set_deflate:h5pset_fletcher32: " // self%filename
248282
endif
249283
endif
250284

251285
if (self%use_mpi .and. .not. self%parallel_compression) then
252-
write(stderr, '(a)') 'WARNING: h5fortran:set_deflate: deflate parallel filter not supported ' // self%filename
286+
if(self%mpi_id == 0) write(stderr, '(a)') 'WARNING: h5fortran:set_deflate: deflate parallel not supported ' // self%filename
253287
return
254288
endif
255289

@@ -258,7 +292,7 @@ subroutine set_deflate(self, dims, dcpl, chunk_size)
258292
if(self%shuffle) then
259293
!! shuffle filter improves compression
260294
if (self%use_mpi .and. .not. self%parallel_compression) then
261-
write(stderr, '(a)') 'WARNING: h5fortran:set_deflate: shuffle parallel filter not supported ' // self%filename
295+
if(self%mpi_id == 0) write(stderr, '(a)') 'WARNING: h5fortran:set_deflate: shuffle parallel not supported ' // self%filename
262296
else
263297
call h5pset_shuffle_f(dcpl, ierr)
264298
if (ierr /= 0) error stop "ERROR:h5fortran:set_deflate:h5pset_shuffle: " // self%filename

src/writer.inc

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ mem_dims = shape(A, HSIZE_T)
99
if(present(dset_dims)) then
1010
dims_dset = dset_dims
1111
else
12+
if(present(istart) .or. present(iend)) then
13+
error stop "ERROR:h5fortran:write: dset_dims required if istart or iend are specified: " // dname // " in " // self%filename
14+
endif
1215
dims_dset = mem_dims
1316
endif
1417

@@ -36,10 +39,12 @@ filespace_id=file_space_id, memspace=mem_space_id, dset_id=dset_id, &
3639
istart=istart, iend=iend, stride=stride, chunk_size=chunk_size, compact=compact, &
3740
dtype_id=dtype_id, charlen=charlen)
3841

42+
if((self%use_mpi .and. present(dset_dims)) .or. (present(istart) .and. present(iend))) then
43+
call mpi_hyperslab(mem_dims, dims_dset, dset_id, file_space_id, mem_space_id, istart=istart, iend=iend, stride=stride)
44+
endif
45+
3946
if(self%use_mpi) then
40-
if(present(dset_dims)) then
41-
call mpi_hyperslab(mem_dims, dims_dset, dset_id, file_space_id, mem_space_id, istart=istart, iend=iend, stride=stride)
42-
elseif(self%mpi_id > 0) then
47+
if(.not. present(dset_dims) .and. self%mpi_id > 0) then
4348
call h5sselect_none_f(file_space_id, ier)
4449
if(ier /= 0) error stop "ERROR:h5fortran:writer:h5sselect_none: selecting no write failed for worker. " // dname
4550
!! for MPI collective scalar or whole array writes, only root worker can write.

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 attributes cast destructor exist groups layout shape
53+
set(test_names array attributes cast destructor exist groups layout shape
5454
string string_read
5555
)
5656

0 commit comments

Comments
 (0)