ALF dev.
A QMC Code for fermionic models
Loading...
Searching...
No Matches
alf_hdf5_mod.F90
1! Copyright (C) 2020-2021 The ALF project
2!
3! The ALF project is free software: you can redistribute it and/or modify
4! it under the terms of the GNU General Public License as published by
5! the Free Software Foundation, either version 3 of the License, or
6! (at your option) any later version.
7!
8! The ALF project is distributed in the hope that it will be useful,
9! but WITHOUT ANY WARRANTY; without even the implied warranty of
10! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11! GNU General Public License for more details.
12!
13! You should have received a copy of the GNU General Public License
14! along with Foobar. If not, see http://www.gnu.org/licenses/.
15!
16! Under Section 7 of GPL version 3 we require you to fulfill the following additional terms:
17!
18! - It is our hope that this program makes a contribution to the scientific community. Being
19! part of that community we feel that it is reasonable to require you to give an attribution
20! back to the original authors if you have benefitted from this program.
21! Guidelines for a proper citation can be found on the project's homepage
22! http://alf.physik.uni-wuerzburg.de .
23!
24! - We require the preservation of the above copyright notice and this license in all original files.
25!
26! - We prohibit the misrepresentation of the origin of the original source files. To obtain
27! the original source files please visit the homepage http://alf.physik.uni-wuerzburg.de .
28!
29! - If you make substantial changes to the program we require you to either consider contributing
30! to the ALF project or to mark your material in a reasonable way as different from the original version.
31
32
33#if defined(HDF5)
34 Module alf_hdf5
35!--------------------------------------------------------------------
36!> @author
37!> ALF-project
38!
39!> @brief
40!> Helper subroutines for using ALF with HDF5.
41!
42!--------------------------------------------------------------------
43 use runtime_error_mod
44 use iso_fortran_env, only: output_unit, error_unit
45 USE iso_c_binding
46
47 Use hdf5
48 use h5lt
49
50 Use lattices_v3
51
52 implicit none
53 private
54 public :: write_attribute, read_attribute, test_attribute, &
55 init_dset, append_dat, write_latt, write_comment
56
57 interface write_attribute
58 MODULE PROCEDURE write_attribute_double, write_attribute_int, write_attribute_string, write_attribute_logical
59 end interface write_attribute
60 interface read_attribute
61 MODULE PROCEDURE read_attribute_double, read_attribute_int, read_attribute_string, read_attribute_logical
62 end interface read_attribute
63 interface test_attribute
64 MODULE PROCEDURE test_attribute_double, test_attribute_int, test_attribute_string, test_attribute_logical
65 end interface test_attribute
66
67 contains
68
69 Subroutine init_dset(file_id, dsetname, dims, is_complex, chunklen)
70!--------------------------------------------------------------------
71!> @author
72!> ALF-project
73!
74!> @brief
75!> This subroutine creates a new dataset in an opened HDF5 file for the
76!> purpsose of filling it with Monte-Carlo bins.
77!
78!> @param [IN] file_id INTEGER(HID_T)
79!> \verbatim
80!> Idendifier of the opened HDF5 file
81!> \endverbatim
82!> @param [IN] dsetname Character(len=64)
83!> \verbatim
84!> Name of the new dataset
85!> \endverbatim
86!> @param [IN] dims(:) INTEGER(HSIZE_T)
87!> \verbatim
88!> Shape of one bin. Whith size(dims) = size(bin)+1 and dims(size(dims)) = 0
89!> \endverbatim
90!> @param [IN] is_complex logical
91!> \verbatim
92!> True if values to be stored can be complex.
93!> \endverbatim
94!> @param [IN] chunklen INTEGER(HSIZE_T), optional
95!> \verbatim
96!> Size of data chunks in number of bins, default = 1
97!> \endverbatim
98!-------------------------------------------------------------------
99 Implicit none
100
101 INTEGER(HID_T), intent(in) :: file_id
102 Character (len=64), intent(in) :: dsetname
103 INTEGER(HSIZE_T), intent(in) :: dims(:)
104 logical, intent(in) :: is_complex
105 INTEGER(HSIZE_T), intent(in), optional :: chunklen
106
107 INTEGER :: rank, hdferr
108 INTEGER(HSIZE_T), allocatable :: dimsc(:), maxdims(:)
109 INTEGER(HID_T) :: dset_id, dataspace, crp_list
110
111 !CALL h5open_f(hdferr)
112
113 !Define size of dataset and of chunks
114 rank = size(dims)
115 allocate( dimsc(rank), maxdims(rank) )
116 dimsc = dims
117 dimsc(rank) = 1
118 if ( present(chunklen) ) dimsc(rank) = chunklen
119 maxdims = dims
120 maxdims(rank) = h5s_unlimited_f
121
122 !Check for dims(rank) = 0
123 if (dims(rank) /= 0) then
124 write(error_unit,*) 'Error in init_dset: dims(rank) /= 0'
125 Call terminate_on_error(error_generic,__file__,__line__)
126 endif
127
128 !Create Dataspace
129 CALL h5screate_simple_f(rank, dims, dataspace, hdferr, maxdims)
130
131 !Modify dataset creation properties, i.e. enable chunking
132 CALL h5pcreate_f(h5p_dataset_create_f, crp_list, hdferr)
133 CALL h5pset_chunk_f(crp_list, rank, dimsc, hdferr)
134#ifdef HDF5_ZLIB
135 ! Set ZLIB / DEFLATE Compression using compression level HDF5_ZLIB
136 CALL h5pset_deflate_f(crp_list, hdf5_zlib, hdferr)
137#endif
138
139 !Create a dataset using cparms creation properties.
140 CALL h5dcreate_f(file_id, dsetname, h5t_native_double, dataspace, &
141 dset_id, hdferr, crp_list )
142
143 CALL write_attribute_logical(dset_id, '.', 'is_complex', is_complex, hdferr)
144
145 !Close objects
146 CALL h5sclose_f(dataspace, hdferr)
147 CALL h5pclose_f(crp_list, hdferr)
148 CALL h5dclose_f(dset_id, hdferr)
149 deallocate( dimsc, maxdims )
150
151 end Subroutine init_dset
152
153!--------------------------------------------------------------------
154
155 Subroutine append_dat(file_id, dsetname, dat_ptr, Nbins_in)
156!--------------------------------------------------------------------
157!> @author
158!> ALF-project
159!
160!> @brief
161!> This subroutine appends one bin to an existing dataset of an opened HDF5 file.
162!
163!> @param [IN] file_id INTEGER(HID_T)
164!> \verbatim
165!> Idendifier of the opened HDF5 file
166!> \endverbatim
167!> @param [IN] dsetname Character(len=64)
168!> \verbatim
169!> Name of the dataset
170!> \endverbatim
171!> @param [IN] data_ptr TYPE(C_PTR)
172!> \verbatim
173!> C-pointer to the first element of the data to write.
174!> data should be all double precision.
175!> The length of the data is assumed from the existing dataset.
176!> \endverbatim
177!> @param [IN] Nbins_in Integer, optional
178!> \verbatim
179!> Number of bins to be written, default = 1
180!> \endverbatim
181!-------------------------------------------------------------------
182 Implicit none
183
184 INTEGER(HID_T), intent(in) :: file_id
185 Character (len=64), intent(in) :: dsetname
186 TYPE(C_PTR), intent(in) :: dat_ptr
187 INTEGER, optional, intent(in) :: Nbins_in
188
189 INTEGER :: rank, hdferr, i, Nbins
190 INTEGER(HSIZE_T) :: mem_dims(1)
191 INTEGER(HSIZE_T), allocatable :: dims(:), maxdims(:), offset(:), count(:)
192 INTEGER(HID_T) :: dset_id, dataspace, memspace
193
194 !CALL h5open_f(hdferr)
195 if( present(nbins_in) ) then
196 nbins = nbins_in
197 else
198 nbins = 1
199 endif
200
201 !Open the dataset.
202 CALL h5dopen_f(file_id, dsetname, dset_id, hdferr)
203
204 !Get dataset's dataspace handle.
205 CALL h5dget_space_f(dset_id, dataspace, hdferr)
206
207 !Get dataspace's rank.
208 CALL h5sget_simple_extent_ndims_f(dataspace, rank, hdferr)
209 allocate( dims(rank), maxdims(rank), offset(rank), count(rank) )
210
211 !Get dataspace's dimensions.
212 CALL h5sget_simple_extent_dims_f(dataspace, dims, maxdims, hdferr)
213
214 !Extent dataset and define hyperslab to write on
215 offset(:) = 0
216 offset(rank) = dims(rank)
217 count(:) = dims(:)
218 count(rank) = nbins
219 dims(rank) = dims(rank)+nbins
220 CALL h5dset_extent_f(dset_id, dims, hdferr)
221 CALL h5sclose_f(dataspace, hdferr)
222 CALL h5dget_space_f(dset_id, dataspace, hdferr)
223 CALL h5sselect_hyperslab_f(dataspace, h5s_select_set_f, offset, count, hdferr)
224
225 !Define memory space of data
226 mem_dims = nbins
227 do i=1, rank-1
228 mem_dims = mem_dims*dims(i)
229 enddo
230 CALL h5screate_simple_f (1, mem_dims, memspace, hdferr)
231
232 !Write data
233 CALL h5dwrite_f(dset_id, h5t_native_double, dat_ptr, hdferr, &
234 mem_space_id = memspace, file_space_id = dataspace)
235
236 !Close objects
237 CALL h5sclose_f(memspace, hdferr)
238 CALL h5sclose_f(dataspace, hdferr)
239 CALL h5dclose_f(dset_id, hdferr)
240
241 deallocate( dims, maxdims, offset, count )
242
243 end Subroutine append_dat
244
245!--------------------------------------------------------------------
246
247 Subroutine write_latt(obj_id, Latt, Latt_Unit)
248!--------------------------------------------------------------------
249!> @author
250!> ALF-project
251!
252!> @brief
253!> This subroutine writes the lattice in an opened HDF5 object.
254!
255!> @param [IN] obj_id INTEGER(HID_T)
256!> \verbatim
257!> Idendifier of the opened HDF5 object
258!> \endverbatim
259!> @param [IN] Latt Type(Lattice)
260!> \verbatim
261!> The Bravais lattice
262!> \endverbatim
263!> @param [IN] Latt_unit Type(Unit_cell)
264!> \verbatim
265!> The unit cell
266!> \endverbatim
267!-------------------------------------------------------------------
268 Implicit none
269 INTEGER(HID_T), intent(in) :: obj_id
270 Type (Lattice), intent(in) :: Latt
271 Type (Unit_cell), intent(in) :: Latt_unit
272
273 Character (len=64) :: group_name, dset_name, attr_name
274 INTEGER(HID_T) :: group_id
275 LOGICAL :: link_exists
276 INTEGER :: ierr, no
277 INTEGER(HSIZE_T) :: size_dat
278 Real (Kind=kind(0.d0)), allocatable :: temp(:)
279
280 group_name = "lattice"
281 CALL h5lexists_f(obj_id, group_name, link_exists, ierr)
282 if ( link_exists ) return
283 call h5gcreate_f(obj_id, group_name, group_id, ierr)
284
285 size_dat = size(latt%L1_p)
286 dset_name = "."
287 attr_name = "a1"
288 call h5ltset_attribute_double_f(group_id, dset_name, attr_name, latt%a1_p, size_dat, ierr )
289 attr_name = "a2"
290 call h5ltset_attribute_double_f(group_id, dset_name, attr_name, latt%a2_p, size_dat, ierr )
291 attr_name = "L1"
292 call h5ltset_attribute_double_f(group_id, dset_name, attr_name, latt%L1_p, size_dat, ierr )
293 attr_name = "L2"
294 call h5ltset_attribute_double_f(group_id, dset_name, attr_name, latt%L2_p, size_dat, ierr )
295
296 attr_name = "N_coord"
297 call write_attribute(group_id, '.', attr_name, latt_unit%N_coord, ierr)
298 attr_name = "Norb"
299 call write_attribute(group_id, '.', attr_name, latt_unit%Norb, ierr)
300 attr_name = "Ndim"
301 call write_attribute(group_id, '.', attr_name, size(latt_unit%Orb_pos_p, 2), ierr)
302
303 size_dat = size(latt_unit%Orb_pos_p, 2)
304 allocate(temp(size_dat))
305 do no = 1, latt_unit%Norb
306 temp(:) = latt_unit%Orb_pos_p(no,:)
307 write(attr_name, '("Orbital", I0)') no
308 call h5ltset_attribute_double_f(group_id, dset_name, attr_name, temp, size_dat, ierr )
309 enddo
310 deallocate(temp)
311
312 call h5gclose_f(group_id, ierr)
313
314 end Subroutine write_latt
315
316!--------------------------------------------------------------------
317
318!--------------------------------------------------------------------
319
320 Subroutine write_attribute_double(loc_id, obj_name, attr_name, attr_value, ierr)
321!--------------------------------------------------------------------
322!> @author
323!> ALF-project
324!
325!> @brief
326!> Write a double as attribute to an HDF5 object.
327!
328!> @param [IN] loc_id INTEGER(HID_T)
329!> \verbatim
330!> Idendifier of opened HDF5 object
331!> \endverbatim
332!> @param [IN] obj_name CHARACTER(LEN=*)
333!> \verbatim
334!> Name of object to be written to in relation to loc_id
335!> \endverbatim
336!> @param [IN] attr_name CHARACTER(LEN=*)
337!> \verbatim
338!> Name of attribute
339!> \endverbatim
340!> @param [IN] attr_value double
341!> \verbatim
342!> Value of attribute
343!> \endverbatim
344!> @param [OUT] ierr integer
345!> \verbatim
346!> Error code
347!> \endverbatim
348!-------------------------------------------------------------------
349 Implicit none
350 INTEGER(HID_T), INTENT(IN) :: loc_id
351 CHARACTER(LEN=*), INTENT(IN) :: obj_name
352 CHARACTER(LEN=*), INTENT(IN) :: attr_name
353 real(Kind=kind(0.d0)), INTENT(IN) :: attr_value
354 INTEGER, INTENT(OUT) :: ierr
355
356 INTEGER(HID_T) :: space_id, attr_id
357 INTEGER(HSIZE_T), parameter :: dims(1) = 1
358
359 CALL h5screate_f (h5s_scalar_f, space_id, ierr)
360 call h5acreate_by_name_f(loc_id, obj_name, attr_name, h5t_native_double, &
361 space_id, attr_id, ierr)
362 call h5awrite_f (attr_id, h5t_native_double, attr_value, dims, ierr)
363 call h5aclose_f (attr_id, ierr)
364 call h5sclose_f (space_id, ierr)
365 end Subroutine write_attribute_double
366
367!--------------------------------------------------------------------
368
369 Subroutine write_attribute_int(loc_id, obj_name, attr_name, attr_value, ierr)
370!--------------------------------------------------------------------
371!> @author
372!> ALF-project
373!
374!> @brief
375!> Write an integer as attribute to an HDF5 object.
376!
377!> @param [IN] loc_id INTEGER(HID_T)
378!> \verbatim
379!> Idendifier of opened HDF5 object
380!> \endverbatim
381!> @param [IN] obj_name CHARACTER(LEN=*)
382!> \verbatim
383!> Name of object to be written to in relation to loc_id
384!> \endverbatim
385!> @param [IN] attr_name CHARACTER(LEN=*)
386!> \verbatim
387!> Name of attribute
388!> \endverbatim
389!> @param [IN] attr_value integer
390!> \verbatim
391!> Value of attribute
392!> \endverbatim
393!> @param [OUT] ierr integer
394!> \verbatim
395!> Error code
396!> \endverbatim
397!-------------------------------------------------------------------
398 Implicit none
399 INTEGER(HID_T), INTENT(IN) :: loc_id
400 CHARACTER(LEN=*), INTENT(IN) :: obj_name
401 CHARACTER(LEN=*), INTENT(IN) :: attr_name
402 INTEGER, INTENT(IN) :: attr_value
403 INTEGER, INTENT(OUT) :: ierr
404
405 INTEGER(HID_T) :: space_id, attr_id
406 INTEGER(HSIZE_T), parameter :: dims(1) = 1
407
408 CALL h5screate_f (h5s_scalar_f, space_id, ierr)
409 call h5acreate_by_name_f(loc_id, obj_name, attr_name, h5t_native_integer, &
410 space_id, attr_id, ierr)
411 call h5awrite_f (attr_id, h5t_native_integer, attr_value, dims, ierr)
412 call h5aclose_f (attr_id, ierr)
413 call h5sclose_f (space_id, ierr)
414 end Subroutine write_attribute_int
415
416!--------------------------------------------------------------------
417
418 Subroutine write_attribute_string(loc_id, obj_name, attr_name, attr_value, ierr)
419!--------------------------------------------------------------------
420!> @author
421!> ALF-project
422!
423!> @brief
424!> Write a string as attribute to an HDF5 object.
425!
426!> @param [IN] loc_id INTEGER(HID_T)
427!> \verbatim
428!> Idendifier of opened HDF5 object
429!> \endverbatim
430!> @param [IN] obj_name CHARACTER(LEN=*)
431!> \verbatim
432!> Name of object to be written to in relation to loc_id
433!> \endverbatim
434!> @param [IN] attr_name CHARACTER(LEN=*)
435!> \verbatim
436!> Name of attribute
437!> \endverbatim
438!> @param [IN] attr_value CHARACTER(LEN=*)
439!> \verbatim
440!> Value of attribute
441!> \endverbatim
442!> @param [OUT] ierr integer
443!> \verbatim
444!> Error code
445!> \endverbatim
446!-------------------------------------------------------------------
447 Implicit none
448 INTEGER(HID_T), INTENT(IN) :: loc_id
449 CHARACTER(LEN=*), INTENT(IN) :: obj_name
450 CHARACTER(LEN=*), INTENT(IN) :: attr_name
451 CHARACTER(LEN=*), INTENT(IN) :: attr_value
452 INTEGER, INTENT(OUT) :: ierr
453
454 call h5ltset_attribute_string_f(loc_id, obj_name, attr_name, &
455 attr_value, ierr)
456 end Subroutine write_attribute_string
457
458!--------------------------------------------------------------------
459
460 Subroutine write_attribute_logical(loc_id, obj_name, attr_name, attr_value, ierr)
461!--------------------------------------------------------------------
462!> @author
463!> ALF-project
464!
465!> @brief
466!> Write a boolean as attribute to an HDF5 object (stored as integer).
467!
468!> @param [IN] loc_id INTEGER(HID_T)
469!> \verbatim
470!> Idendifier of opened HDF5 object
471!> \endverbatim
472!> @param [IN] obj_name CHARACTER(LEN=*)
473!> \verbatim
474!> Name of object to be written to in relation to loc_id
475!> \endverbatim
476!> @param [IN] attr_name CHARACTER(LEN=*)
477!> \verbatim
478!> Name of attribute
479!> \endverbatim
480!> @param [IN] attr_value logical
481!> \verbatim
482!> Value of attribute
483!> \endverbatim
484!> @param [OUT] ierr integer
485!> \verbatim
486!> Error code
487!> \endverbatim
488!-------------------------------------------------------------------
489 Implicit none
490 INTEGER(HID_T), INTENT(IN) :: loc_id
491 CHARACTER(LEN=*), INTENT(IN) :: obj_name
492 CHARACTER(LEN=*), INTENT(IN) :: attr_name
493 LOGICAL, INTENT(IN) :: attr_value
494 INTEGER, INTENT(OUT) :: ierr
495
496 INTEGER :: attr_value2
497 INTEGER(HID_T) :: space_id, attr_id
498 INTEGER(HSIZE_T), parameter :: dims(1) = 1
499
500 attr_value2 = 0
501 if ( attr_value ) attr_value2 = 1
502
503 CALL h5screate_f (h5s_scalar_f, space_id, ierr)
504 call h5acreate_by_name_f(loc_id, obj_name, attr_name, h5t_native_integer, &
505 space_id, attr_id, ierr)
506 call h5awrite_f (attr_id, h5t_native_integer, attr_value2, dims, ierr)
507 call h5aclose_f (attr_id, ierr)
508 call h5sclose_f (space_id, ierr)
509 end Subroutine write_attribute_logical
510
511!--------------------------------------------------------------------
512
513 Subroutine read_attribute_double(loc_id, obj_name, attr_name, attr_value, ierr)
514!--------------------------------------------------------------------
515!> @author
516!> ALF-project
517!
518!> @brief
519!> Read a double from attribute of HDF5 object.
520!
521!> @param [IN] loc_id INTEGER(HID_T)
522!> \verbatim
523!> Idendifier of opened HDF5 object
524!> \endverbatim
525!> @param [IN] obj_name CHARACTER(LEN=*)
526!> \verbatim
527!> Name of object to be read from in relation to loc_id
528!> \endverbatim
529!> @param [IN] attr_name CHARACTER(LEN=*)
530!> \verbatim
531!> Name of attribute
532!> \endverbatim
533!> @param [OUT] attr_value double
534!> \verbatim
535!> Value of attribute
536!> \endverbatim
537!> @param [OUT] ierr integer
538!> \verbatim
539!> Error code
540!> \endverbatim
541!-------------------------------------------------------------------
542 Implicit none
543 INTEGER(HID_T), INTENT(IN) :: loc_id
544 CHARACTER(LEN=*), INTENT(IN) :: obj_name
545 CHARACTER(LEN=*), INTENT(IN) :: attr_name
546 real(Kind=kind(0.d0)), INTENT(OUT) :: attr_value
547 INTEGER, INTENT(OUT) :: ierr
548
549 INTEGER(HID_T) :: attr_id
550 INTEGER(HSIZE_T), parameter :: dims(1) = 1
551
552 call h5aopen_by_name_f(loc_id, obj_name, attr_name, attr_id, ierr)
553 call h5aread_f (attr_id, h5t_native_double, attr_value, dims, ierr)
554 call h5aclose_f (attr_id, ierr)
555 end Subroutine read_attribute_double
556
557!--------------------------------------------------------------------
558
559 Subroutine read_attribute_int(loc_id, obj_name, attr_name, attr_value, ierr)
560!--------------------------------------------------------------------
561!> @author
562!> ALF-project
563!
564!> @brief
565!> Read an integer from attribute of HDF5 object.
566!
567!> @param [IN] loc_id INTEGER(HID_T)
568!> \verbatim
569!> Idendifier of opened HDF5 object
570!> \endverbatim
571!> @param [IN] obj_name CHARACTER(LEN=*)
572!> \verbatim
573!> Name of object to be read from in relation to loc_id
574!> \endverbatim
575!> @param [IN] attr_name CHARACTER(LEN=*)
576!> \verbatim
577!> Name of attribute
578!> \endverbatim
579!> @param [OUT] attr_value integer
580!> \verbatim
581!> Value of attribute
582!> \endverbatim
583!> @param [OUT] ierr integer
584!> \verbatim
585!> Error code
586!> \endverbatim
587!-------------------------------------------------------------------
588 Implicit none
589 INTEGER(HID_T), INTENT(IN) :: loc_id
590 CHARACTER(LEN=*), INTENT(IN) :: obj_name
591 CHARACTER(LEN=*), INTENT(IN) :: attr_name
592 INTEGER, INTENT(OUT) :: attr_value
593 INTEGER, INTENT(OUT) :: ierr
594
595 INTEGER(HID_T) :: attr_id
596 INTEGER(HSIZE_T), parameter :: dims(1) = 1
597
598 call h5aopen_by_name_f(loc_id, obj_name, attr_name, attr_id, ierr)
599 call h5aread_f (attr_id, h5t_native_integer, attr_value, dims, ierr)
600 call h5aclose_f (attr_id, ierr)
601 end Subroutine read_attribute_int
602
603!--------------------------------------------------------------------
604
605 Subroutine read_attribute_string(loc_id, obj_name, attr_name, attr_value, ierr)
606!--------------------------------------------------------------------
607!> @author
608!> ALF-project
609!
610!> @brief
611!> Read a string from attribute of HDF5 object.
612!
613!> @param [IN] loc_id INTEGER(HID_T)
614!> \verbatim
615!> Idendifier of opened HDF5 object
616!> \endverbatim
617!> @param [IN] obj_name CHARACTER(LEN=*)
618!> \verbatim
619!> Name of object to be read from in relation to loc_id
620!> \endverbatim
621!> @param [IN] attr_name CHARACTER(LEN=*)
622!> \verbatim
623!> Name of attribute
624!> \endverbatim
625!> @param [OUT] attr_value CHARACTER(LEN=*)
626!> \verbatim
627!> Value of attribute
628!> \endverbatim
629!> @param [OUT] ierr integer
630!> \verbatim
631!> Error code
632!> \endverbatim
633!-------------------------------------------------------------------
634 Implicit none
635 INTEGER(HID_T), INTENT(IN) :: loc_id
636 CHARACTER(LEN=*), INTENT(IN) :: obj_name
637 CHARACTER(LEN=*), INTENT(IN) :: attr_name
638 CHARACTER(LEN=*), INTENT(OUT) :: attr_value
639 INTEGER, INTENT(OUT) :: ierr
640
641 call h5ltget_attribute_string_f(loc_id, obj_name, attr_name, &
642 attr_value, ierr)
643 end Subroutine read_attribute_string
644
645!--------------------------------------------------------------------
646
647 Subroutine read_attribute_logical(loc_id, obj_name, attr_name, attr_value, ierr)
648!--------------------------------------------------------------------
649!> @author
650!> ALF-project
651!
652!> @brief
653!> Read a boolean from attribute of HDF5 object (stored as integer).
654!
655!> @param [IN] loc_id INTEGER(HID_T)
656!> \verbatim
657!> Idendifier of opened HDF5 object
658!> \endverbatim
659!> @param [IN] obj_name CHARACTER(LEN=*)
660!> \verbatim
661!> Name of object to be read from in relation to loc_id
662!> \endverbatim
663!> @param [IN] attr_name CHARACTER(LEN=*)
664!> \verbatim
665!> Name of attribute
666!> \endverbatim
667!> @param [OUT] attr_value logical
668!> \verbatim
669!> Value of attribute
670!> \endverbatim
671!> @param [OUT] ierr integer
672!> \verbatim
673!> Error code
674!> \endverbatim
675!-------------------------------------------------------------------
676 Implicit none
677 INTEGER(HID_T), INTENT(IN) :: loc_id
678 CHARACTER(LEN=*), INTENT(IN) :: obj_name
679 CHARACTER(LEN=*), INTENT(IN) :: attr_name
680 LOGICAL, INTENT(OUT) :: attr_value
681 INTEGER, INTENT(OUT) :: ierr
682
683 INTEGER :: attr_value2
684 INTEGER(HID_T) :: attr_id
685 INTEGER(HSIZE_T), parameter :: dims(1) = 1
686
687 call h5aopen_by_name_f(loc_id, obj_name, attr_name, attr_id, ierr)
688 call h5aread_f (attr_id, h5t_native_integer, attr_value2, dims, ierr)
689 call h5aclose_f (attr_id, ierr)
690
691 if ( attr_value2 == 0 ) then
692 attr_value = .false.
693 elseif ( attr_value2 == 1 ) then
694 attr_value = .true.
695 else
696 write(error_unit,*) "Error in read_attribute_logical: attr_value2 is neither 0 or 1, but", attr_value2
697 Call terminate_on_error(error_generic,__file__,__line__)
698 endif
699 end Subroutine read_attribute_logical
700
701!--------------------------------------------------------------------
702
703 Subroutine test_attribute_double(loc_id, obj_name, attr_name, attr_value, ierr)
704!--------------------------------------------------------------------
705!> @author
706!> ALF-project
707!
708!> @brief
709!> Test whether supplied double is identical to attribute stored in HDF5 file.
710!> If not, triggers error stop.
711!
712!> @param [IN] loc_id INTEGER(HID_T)
713!> \verbatim
714!> Idendifier of opened HDF5 object
715!> \endverbatim
716!> @param [IN] obj_name CHARACTER(LEN=*)
717!> \verbatim
718!> Name of object attribute is attached to in relation to loc_id
719!> \endverbatim
720!> @param [IN] attr_name CHARACTER(LEN=*)
721!> \verbatim
722!> Name of attribute
723!> \endverbatim
724!> @param [IN] attr_value double
725!> \verbatim
726!> Value of supplied attribute
727!> \endverbatim
728!> @param [OUT] ierr integer
729!> \verbatim
730!> Error code
731!> \endverbatim
732!-------------------------------------------------------------------
733 Implicit none
734 INTEGER(HID_T), INTENT(IN) :: loc_id
735 CHARACTER(LEN=*), INTENT(IN) :: obj_name
736 CHARACTER(LEN=*), INTENT(IN) :: attr_name
737 real(Kind=kind(0.d0)), INTENT(IN) :: attr_value
738 INTEGER, INTENT(OUT) :: ierr
739
740 LOGICAL :: attr_exists
741 real(Kind=kind(0.d0)), parameter :: zero = 10d-8
742 real(Kind=kind(0.d0)) :: test_double, diff
743
744 call h5aexists_by_name_f(loc_id, obj_name, attr_name, attr_exists, ierr)
745
746 if ( .not. attr_exists ) then
747 call write_attribute_double(loc_id, obj_name, attr_name, attr_value, ierr)
748 else
749 call read_attribute_double(loc_id, obj_name, attr_name, test_double, ierr)
750 diff = abs(attr_value - test_double)
751 if (diff > zero) then
752 write(error_unit,'(A)') 'Error in test_attribute_double:'
753 write(error_unit,'(A)') ' Attribute name: "' // trim(attr_name) // '"'
754 write(error_unit,'(A, F0.6)') ' Supplied value: ' , attr_value
755 write(error_unit,'(A, F0.6)') ' Read value: ' , test_double
756 write(error_unit,'(A, F0.6)') ' Difference = ', diff
757 Call terminate_on_error(error_generic,__file__,__line__)
758 endif
759 endif
760 end Subroutine test_attribute_double
761
762!--------------------------------------------------------------------
763
764 Subroutine test_attribute_int(loc_id, obj_name, attr_name, attr_value, ierr)
765!--------------------------------------------------------------------
766!> @author
767!> ALF-project
768!
769!> @brief
770!> Test whether supplied integer is identical to attribute stored in HDF5 file.
771!> If not, triggers error stop.
772!
773!> @param [IN] loc_id INTEGER(HID_T)
774!> \verbatim
775!> Idendifier of opened HDF5 object
776!> \endverbatim
777!> @param [IN] obj_name CHARACTER(LEN=*)
778!> \verbatim
779!> Name of object attribute is attached to in relation to loc_id
780!> \endverbatim
781!> @param [IN] attr_name CHARACTER(LEN=*)
782!> \verbatim
783!> Name of attribute
784!> \endverbatim
785!> @param [IN] attr_value integer
786!> \verbatim
787!> Value of supplied attribute
788!> \endverbatim
789!> @param [OUT] ierr integer
790!> \verbatim
791!> Error code
792!> \endverbatim
793!-------------------------------------------------------------------
794 Implicit none
795 INTEGER(HID_T), INTENT(IN) :: loc_id
796 CHARACTER(LEN=*), INTENT(IN) :: obj_name
797 CHARACTER(LEN=*), INTENT(IN) :: attr_name
798 INTEGER, INTENT(IN) :: attr_value
799 INTEGER, INTENT(OUT) :: ierr
800
801 LOGICAL :: attr_exists
802 INTEGER :: test_int
803
804 call h5aexists_by_name_f(loc_id, obj_name, attr_name, attr_exists, ierr)
805
806 if ( .not. attr_exists ) then
807 call write_attribute_int(loc_id, obj_name, attr_name, attr_value, ierr)
808 else
809 call read_attribute_int(loc_id, obj_name, attr_name, test_int, ierr)
810 if (attr_value /= test_int) then
811 write(error_unit,'(A)') 'Error in test_attribute_int:'
812 write(error_unit,'(A)') ' Attribute name: "' // trim(attr_name) // '"'
813 write(error_unit,'(A, I0)') ' Supplied value: ' , attr_value
814 write(error_unit,'(A, I0)') ' Read value: ' , test_int
815 Call terminate_on_error(error_generic,__file__,__line__)
816 endif
817 endif
818 end Subroutine test_attribute_int
819
820!--------------------------------------------------------------------
821
822 Subroutine test_attribute_string(loc_id, obj_name, attr_name, attr_value, ierr)
823!--------------------------------------------------------------------
824!> @author
825!> ALF-project
826!
827!> @brief
828!> Test whether supplied string is identical to attribute stored in HDF5 file.
829!> If not, triggers error stop.
830!
831!> @param [IN] loc_id INTEGER(HID_T)
832!> \verbatim
833!> Idendifier of opened HDF5 object
834!> \endverbatim
835!> @param [IN] obj_name CHARACTER(LEN=*)
836!> \verbatim
837!> Name of object attribute is attached to in relation to loc_id
838!> \endverbatim
839!> @param [IN] attr_name CHARACTER(LEN=*)
840!> \verbatim
841!> Name of attribute
842!> \endverbatim
843!> @param [IN] attr_value CHARACTER(LEN=*)
844!> \verbatim
845!> Value of supplied attribute
846!> \endverbatim
847!> @param [OUT] ierr integer
848!> \verbatim
849!> Error code
850!> \endverbatim
851!-------------------------------------------------------------------
852 Implicit none
853 INTEGER(HID_T), INTENT(IN) :: loc_id
854 CHARACTER(LEN=*), INTENT(IN) :: obj_name
855 CHARACTER(LEN=*), INTENT(IN) :: attr_name
856 CHARACTER(LEN=*), INTENT(IN) :: attr_value
857 INTEGER, INTENT(OUT) :: ierr
858
859 LOGICAL :: attr_exists
860 CHARACTER(LEN=64) :: test_string
861
862 call h5aexists_by_name_f(loc_id, obj_name, attr_name, attr_exists, ierr)
863
864 if ( .not. attr_exists ) then
865 call write_attribute_string(loc_id, obj_name, attr_name, attr_value, ierr)
866 else
867 call read_attribute_string(loc_id, obj_name, attr_name, test_string, ierr)
868 if (trim(attr_value) /= trim(test_string)) then
869 write(error_unit,*) 'Error in test_attribute_string:'
870 write(error_unit,*) ' Attribute name: "' // trim(attr_name) // '"'
871 write(error_unit,*) ' Supplied value: "' // trim(attr_value) // '"'
872 write(error_unit,*) ' Read value: "' // trim(test_string) // '"'
873 Call terminate_on_error(error_generic,__file__,__line__)
874 endif
875 endif
876 end Subroutine test_attribute_string
877
878!--------------------------------------------------------------------
879
880 Subroutine test_attribute_logical(loc_id, obj_name, attr_name, attr_value, ierr)
881!--------------------------------------------------------------------
882!> @author
883!> ALF-project
884!
885!> @brief
886!> Test whether supplied boolean is identical to attribute stored in HDF5 file.
887!> If not, triggers error stop.
888!
889!> @param [IN] loc_id INTEGER(HID_T)
890!> \verbatim
891!> Idendifier of opened HDF5 object
892!> \endverbatim
893!> @param [IN] obj_name CHARACTER(LEN=*)
894!> \verbatim
895!> Name of object attribute is attached to in relation to loc_id
896!> \endverbatim
897!> @param [IN] attr_name CHARACTER(LEN=*)
898!> \verbatim
899!> Name of attribute
900!> \endverbatim
901!> @param [IN] attr_value logical
902!> \verbatim
903!> Value of supplied attribute
904!> \endverbatim
905!> @param [OUT] ierr integer
906!> \verbatim
907!> Error code
908!> \endverbatim
909!-------------------------------------------------------------------
910 Implicit none
911 INTEGER(HID_T), INTENT(IN) :: loc_id
912 CHARACTER(LEN=*), INTENT(IN) :: obj_name
913 CHARACTER(LEN=*), INTENT(IN) :: attr_name
914 LOGICAL, INTENT(IN) :: attr_value
915 INTEGER, INTENT(OUT) :: ierr
916
917 LOGICAL :: attr_exists
918 LOGICAL :: test_bool
919
920 call h5aexists_by_name_f(loc_id, obj_name, attr_name, attr_exists, ierr)
921
922 if ( .not. attr_exists ) then
923 call write_attribute_logical(loc_id, obj_name, attr_name, attr_value, ierr)
924 else
925 call read_attribute_logical(loc_id, obj_name, attr_name, test_bool, ierr)
926 if (attr_value .neqv. test_bool) then
927 write(error_unit,'(A)') 'Error in test_attribute_logical:'
928 write(error_unit,'(A, A, A)') ' Attribute name: "' // trim(attr_name) // '"'
929 write(error_unit,'(A,L1)') ' Supplied value: ', attr_value
930 write(error_unit,'(A,L1)') ' Read value: ', test_bool
931 Call terminate_on_error(error_generic,__file__,__line__)
932 endif
933 endif
934 end Subroutine test_attribute_logical
935
936
937
938 Subroutine write_comment(loc_id, obj_name, attr_name, comment, ierr)
939!--------------------------------------------------------------------
940!> @author
941!> ALF-project
942!
943!> @brief
944!> Write a comment (array of strings, each 64 characters in length)
945!> as attribute to an HDF5 object.
946!
947!> @param [IN] loc_id INTEGER(HID_T)
948!> \verbatim
949!> Idendifier of opened HDF5 object
950!> \endverbatim
951!> @param [IN] obj_name CHARACTER(LEN=*)
952!> \verbatim
953!> Name of object to be written to in relation to loc_id
954!> \endverbatim
955!> @param [IN] attr_name CHARACTER(LEN=*)
956!> \verbatim
957!> Name of attribute
958!> \endverbatim
959!> @param [IN] comment(:) CHARACTER(LEN=64)
960!> \verbatim
961!> Value of attribute
962!> \endverbatim
963!> @param [OUT] ierr integer
964!> \verbatim
965!> Error code
966!> \endverbatim
967!-------------------------------------------------------------------
968
969 IMPLICIT NONE
970 INTEGER(HID_T), INTENT(IN) :: loc_id
971 CHARACTER(LEN=*), INTENT(IN) :: obj_name
972 CHARACTER(LEN=*), INTENT(IN) :: attr_name
973 CHARACTER(len=64), INTENT(IN) :: comment(:)
974 INTEGER, INTENT(OUT) :: ierr
975
976 INTEGER(HID_T) :: attr_id ! Attribute identifier
977 INTEGER(HID_T) :: space_id ! Attribute Dataspace identifier
978 INTEGER(HID_T) :: type_id ! Attribute datatype identifier
979 INTEGER :: rank = 1 ! Attribure rank
980 INTEGER(HSIZE_T) :: dims(1) ! Attribute dimensions
981 INTEGER(SIZE_T) :: attrlen = 64 ! Length of the attribute string
982
983 ! Create scalar data space for the attribute.
984 dims(1) = size(comment)
985 CALL h5screate_simple_f(rank, dims, space_id, ierr)
986
987 ! Create datatype for the attribute.
988 CALL h5tcopy_f(h5t_native_character, type_id, ierr)
989 CALL h5tset_size_f(type_id, attrlen, ierr)
990
991 ! Create dataset attribute.
992 call h5acreate_by_name_f(loc_id, obj_name, attr_name, type_id, &
993 space_id, attr_id, ierr)
994
995 ! Write the attribute data.
996 CALL h5awrite_f(attr_id, type_id, comment, dims, ierr)
997
998 ! Close the attribute, datatype and data space.
999 CALL h5aclose_f(attr_id, ierr)
1000 CALL h5tclose_f(type_id, ierr)
1001 CALL h5sclose_f(space_id, ierr)
1002
1003 end Subroutine write_comment
1004
1005 end Module alf_hdf5
1006#endif