Neko-TOP
A portable framework for high-order spectral element flow toplogy optimization.
Loading...
Searching...
No Matches
design_hdf5_io.f90
1
38
40submodule(design) design_hdf5_io
41 use hdf5
42 use mpi_f08, only: mpi_scan, mpi_info_null, mpi_integer8, mpi_max, mpi_min, &
43 mpi_in_place
44 use math, only: abscmp
45 use device, only: device_to_host, host_to_device
46 use comm, only: pe_rank, pe_size
47 use num_types, only: sp, dp
48 use scratch_registry, only: neko_scratch_registry
49 use hdf5_session, only: hdf5_session_init, hdf5_session_finalize
50
51contains
52
58 module subroutine design_save_checkpoint_hdf5(this, filename, overwrite)
59 class(design_t), intent(in) :: this
60 character(len=*), intent(in) :: filename
61 logical, intent(in), optional :: overwrite
62 type(vector_t), pointer :: temp_vec
63 integer :: temp_index
64
65 integer(hid_t) :: fapl_id, xf_id, file_id, dset_id, filespace, memspace, &
66 attr_id, grp_id, str_type, design_grp_id
67 integer(hid_t) :: H5T_NEKO_REAL
68 integer(hsize_t), dimension(1) :: ddim, dcount, doffset
69 integer :: ierr, info, drank
70 logical :: file_exists, design_exists, overwrite_flag
71 integer :: n_accum, n_array(pe_size)
72
73 overwrite_flag = .false.
74 if (present(overwrite)) overwrite_flag = overwrite
75
76 ! Gather the per-rank n values
77 n_array = -1
78 n_array(pe_rank + 1) = this%n
79 call mpi_allreduce(mpi_in_place, n_array, pe_size, mpi_integer, mpi_max, &
80 neko_comm, ierr)
81
82 ! ------------------------------------------------------------------------ !
83 ! Prepare the HDF5 file, settings for MPIO access and groups
84
85 call hdf5_session_init()
86 call h5pcreate_f(h5p_file_access_f, fapl_id, ierr)
87 info = mpi_info_null%mpi_val
88 call h5pset_fapl_mpio_f(fapl_id, neko_comm%mpi_val, info, ierr)
89
90 ! Handle overwriting if the file exists
91 file_exists = .false.
92 inquire(file=trim(filename), exist=file_exists)
93 if (.not. file_exists) then
94 call h5fcreate_f(trim(filename), h5f_acc_trunc_f, file_id, ierr, &
95 access_prp = fapl_id)
96
97 ! Create the Design/checkpoint group
98 call h5gcreate_f(file_id, "Design", design_grp_id, ierr)
99 call h5gcreate_f(design_grp_id, "checkpoint", grp_id, ierr)
100
101 else
102 call h5fopen_f(trim(filename), h5f_acc_rdwr_f, file_id, ierr, fapl_id)
103
104 ! Check for existing Design group
105 design_exists = .false.
106 call h5lexists_f(file_id, '/Design', design_exists, ierr)
107
108 if (.not. design_exists) then
109 ! Create the Design/checkpoint group
110 call h5gcreate_f(file_id, "Design", design_grp_id, ierr)
111 call h5gcreate_f(design_grp_id, "checkpoint", grp_id, ierr)
112 else
113 ! Open the existing "Design" group
114 call h5gopen_f(file_id, 'Design', design_grp_id, ierr)
115 call h5lexists_f(design_grp_id, 'checkpoint', design_exists, ierr)
116
117 if (design_exists .and. overwrite_flag) then
118 call h5gunlink_f(design_grp_id, "checkpoint", ierr)
119 call h5gcreate_f(design_grp_id, "checkpoint", grp_id, ierr)
120 else
121 call neko_error('design: HDF5 file "' // trim(filename) // '" ' &
122 // 'already contains Design group; ' &
123 // 'use overwrite option to replace')
124 end if
125 end if
126 end if
127 call h5gclose_f(design_grp_id, ierr)
128
129 ! Assign the correct HDF5 data type based on the neko real kind
130 select case (rp)
131 case (dp)
132 h5t_neko_real = h5t_native_double
133 case (sp)
134 h5t_neko_real = h5t_native_real
135 case default
136 call neko_error('design: unsupported real kind for HDF5')
137 end select
138
139 ! ------------------------------------------------------------------------ !
140 ! Write basic Parameters attributes
141
142 ! Integer-valued attributes
143 ddim = 1
144 call h5screate_f(h5s_scalar_f, filespace, ierr)
145
146 call h5acreate_f(grp_id, 'n_global', h5t_native_integer, filespace, &
147 attr_id, ierr, h5p_default_f, h5p_default_f)
148 call h5awrite_f(attr_id, h5t_native_integer, this%n_global, ddim, ierr)
149 call h5aclose_f(attr_id, ierr)
150
151 ! String-valued attributes
152
153 ! Create the string type
154 call h5tcopy_f(h5t_fortran_s1, str_type, ierr)
155 call h5tset_strpad_f(str_type, h5t_str_spacepad_f, ierr)
156
157 ddim(1) = len_trim(this%name)
158 call h5tset_size_f(str_type, ddim(1), ierr)
159 call h5acreate_f(grp_id, 'name', str_type, filespace, attr_id, &
160 ierr, h5p_default_f, h5p_default_f)
161 call h5awrite_f(attr_id, str_type, this%name, ddim, ierr)
162 call h5aclose_f(attr_id, ierr)
163
164 ! Close the string type
165 call h5tclose_f(str_type, ierr)
166
167 ! Close the scalar filespace
168 call h5sclose_f(filespace, ierr)
169
170 ! Array-valued attributes
171 drank = 1
172 ddim = pe_size
173 call h5screate_simple_f(drank, ddim, filespace, ierr)
174
175 call h5acreate_f(grp_id, 'n', h5t_native_integer, filespace, attr_id, ierr)
176 call h5awrite_f(attr_id, h5t_native_integer, n_array, ddim, ierr)
177 call h5aclose_f(attr_id, ierr)
178
179 call h5sclose_f(filespace, ierr)
180
181 ! ------------------------------------------------------------------------ !
182 ! Write per-rank datasets
183
184 ! Define the sizes and offsets
185 call mpi_scan(this%n, n_accum, 1, mpi_integer, mpi_sum, neko_comm, ierr)
186
187 drank = 1
188 dcount(1) = this%n
189 doffset(1) = n_accum - this%n
190 ddim(1) = this%n_global
191
192 ! Create a file and memory space
193 call h5screate_simple_f(drank, ddim, filespace, ierr)
194 call h5screate_simple_f(drank, dcount, memspace, ierr)
195
196 ! Dataset transfer property list: collective
197 call h5pcreate_f(h5p_dataset_xfer_f, xf_id, ierr)
198 call h5pset_dxpl_mpio_f(xf_id, h5fd_mpio_collective_f, ierr)
199
200 ! Select hyperslab in the file space
201 call h5sselect_hyperslab_f(filespace, h5s_select_set_f, doffset, dcount, &
202 ierr)
203
204 call neko_scratch_registry%request(temp_vec, temp_index, this%n, .true.)
205 call this%get_values(temp_vec)
206 call temp_vec%copy_from(device_to_host, sync = .true.)
207
208 ! Write values
209 call h5dcreate_f(grp_id, 'values', h5t_neko_real, &
210 filespace, dset_id, ierr)
211 call h5dwrite_f(dset_id, h5t_neko_real, temp_vec%x, ddim, ierr, &
212 file_space_id = filespace, mem_space_id = memspace, xfer_prp = xf_id)
213 call h5dclose_f(dset_id, ierr)
214
215 call neko_scratch_registry%relinquish(temp_index)
216 nullify(temp_vec)
217
218 ! Close the spaces used
219 call h5sclose_f(filespace, ierr)
220 call h5sclose_f(memspace, ierr)
221 call h5pclose_f(xf_id, ierr)
222
223 ! ------------------------------------------------------------------------ !
224 ! Close the group and file
225
226 call h5gclose_f(grp_id, ierr)
227 call h5fclose_f(file_id, ierr)
228 call h5pclose_f(fapl_id, ierr)
229
230 call hdf5_session_finalize()
231
232 end subroutine design_save_checkpoint_hdf5
233
237 module subroutine design_load_checkpoint_hdf5(this, filename)
238 class(design_t), intent(inout) :: this
239 character(len=*), intent(in) :: filename
240
241 type(vector_t), pointer :: temp_vec
242 integer :: temp_index
243
244 character(len=64) :: name
245 integer(hid_t) :: fapl_id, file_id, dset_id, &
246 attr_id, grp_id, str_type, filespace, memspace, xf_id
247 integer(hid_t) :: H5T_NEKO_REAL
248 integer(hsize_t), dimension(1) :: ddim, dcount, doffset
249 integer :: ierr, info, mpi_comm
250 integer :: n, n_global, n_accum, n_array(pe_size)
251
252 character(len=*), parameter :: h5_group = '/Design/checkpoint'
253
254 ! Initialize reader values
255 n = -1
256 n_global = -1
257 name = ''
258
259 ! MPI interfaces
260 info = mpi_info_null%mpi_val
261 mpi_comm = neko_comm%mpi_val
262
263 ! Open file and prepare reading
264 call hdf5_session_init()
265 call h5pcreate_f(h5p_file_access_f, fapl_id, ierr)
266 call h5pset_fapl_mpio_f(fapl_id, mpi_comm, info, ierr)
267 call h5fopen_f(trim(filename), h5f_acc_rdonly_f, file_id, ierr, &
268 access_prp = fapl_id)
269 call h5gopen_f(file_id, h5_group, grp_id, ierr)
270
271 if (ierr .ne. 0) then
272 call neko_error('design: unable to open HDF5 file "' // &
273 trim(filename) // '" or group "' // trim(h5_group) // '".')
274 end if
275
276 ! Assign the correct HDF5 data type based on the neko real kind
277 select case (rp)
278 case (dp)
279 h5t_neko_real = h5t_native_double
280 case (sp)
281 h5t_neko_real = h5t_native_real
282 case default
283 call neko_error('design: unsupported real kind for HDF5')
284 end select
285
286 ! ------------------------------------------------------------------------ !
287 ! Read basic Parameters attributes
288
289 ! Read scalar attributes
290 ddim(1) = 1
291 call h5aopen_f(grp_id, 'n_global', attr_id, ierr)
292 call h5aread_f(attr_id, h5t_native_integer, n_global, ddim, ierr)
293 call h5aclose_f(attr_id, ierr)
294
295 ! Read strings
296 call h5aopen_f(grp_id, 'name', attr_id, ierr)
297 call h5aget_type_f(attr_id, str_type, ierr)
298 call h5aread_f(attr_id, str_type, name, ddim, ierr)
299 call h5tclose_f(str_type, ierr)
300 call h5aclose_f(attr_id, ierr)
301
302 ! Read array attribute n
303 ddim(1) = pe_size
304 n_array = -1
305
306 call h5aopen_f(grp_id, 'n', attr_id, ierr)
307 call h5aread_f(attr_id, h5t_native_integer, n_array, ddim, ierr)
308 call h5aclose_f(attr_id, ierr)
309
310 ! ------------------------------------------------------------------------ !
311 ! Ensure the Design object is allocated with the same configuration as the file
312
313 if (n_array(pe_rank + 1) .ne. this%n) then
314 call neko_error('design: mismatch in n during HDF5 read')
315 end if
316 if (n_global .ne. this%n_global) then
317 call neko_error('design: mismatch in n_global during HDF5 read')
318 end if
319 if (trim(name) .ne. trim(this%name)) then
320 call neko_error('design: mismatch in name during HDF5 read' // &
321 ' (file: ' // trim(name) // ', object: ' // trim(this%name) // ')')
322 end if
323
324 ! ------------------------------------------------------------------------ !
325 ! Read per-rank datasets
326
327 ddim(1) = this%n
328
329 ! Define the sizes and offsets (each pe_rank reads its local n from the global array)
330 call mpi_scan(this%n, n_accum, 1, mpi_integer, mpi_sum, neko_comm, ierr)
331
332 dcount(1) = this%n
333 doffset(1) = n_accum - this%n
334 ddim(1) = this%n_global
335
336 ! Create file and memory space (pe_rank = 1 for 1D arrays)
337 call h5screate_simple_f(1, ddim, filespace, ierr)
338 call h5screate_simple_f(1, dcount, memspace, ierr)
339
340 ! Dataset transfer property list: MPI collective I/O
341 call h5pcreate_f(h5p_dataset_xfer_f, xf_id, ierr)
342 call h5pset_dxpl_mpio_f(xf_id, h5fd_mpio_collective_f, ierr)
343
344 ! Select hyperslab in the file space for this pe_rank
345 call h5sselect_hyperslab_f(filespace, h5s_select_set_f, doffset, dcount, &
346 ierr)
347
348 ! Read values
349 call neko_scratch_registry%request(temp_vec, temp_index, this%n, .false.)
350 call h5dopen_f(grp_id, 'values', dset_id, ierr)
351 call h5dread_f(dset_id, h5t_neko_real, temp_vec%x, dcount, ierr, &
352 file_space_id = filespace, mem_space_id = memspace, xfer_prp = xf_id)
353 call h5dclose_f(dset_id, ierr)
354
355 call temp_vec%copy_from(host_to_device, sync = .true.)
356 call this%update_design(temp_vec)
357 call neko_scratch_registry%relinquish(temp_index)
358 nullify(temp_vec)
359
360 ! Close transfer property list and dataspaces
361 call h5pclose_f(xf_id, ierr)
362 call h5sclose_f(memspace, ierr)
363 call h5sclose_f(filespace, ierr)
364
365 ! ------------------------------------------------------------------------ !
366 ! Close the group and file
367
368 call h5gclose_f(grp_id, ierr)
369 call h5fclose_f(file_id, ierr)
370 call h5pclose_f(fapl_id, ierr)
371
372 call hdf5_session_finalize()
373
374 end subroutine design_load_checkpoint_hdf5
375
376end submodule design_hdf5_io
Implements the design_t.
Definition design.f90:36