PB3D [2.47]
Ideal linear high-n MHD stability in 3-D
Loading...
Searching...
No Matches
HDF5_ops.f90
Go to the documentation of this file.
1!------------------------------------------------------------------------------!
2!> Operations on HDF5 and XDMF variables
3!!
4!! \note
5!! Notes about XDMF:
6!! - Collections can be spatial or temporal. If a variable is to be evolved in
7!! time or if its domain is decomposed (e.g. the same physical variable is
8!! defined in multiple HDF5 variables), then the attribute name of this
9!! variable has to be the same for all the grids in the collection.
10!! - If no collection is used, but just multiple grids, the attribute can be
11!! different but does not have to be, as the different grid are distinguished
12!! by their different grid names, not by the attribute of the variables they
13!! contain.
14!! - The selection of hyperslabs is used, as described here:
15!! <http://davis.lbl.gov/Manuals/HDF5-1.8.7/UG/12_Dataspaces.html>
16!! - Chunking is used for partial I/O, as described here:
17!! <https://www.hdfgroup.org/HDF5/doc/Advanced/Chunking/> As no chunk cache is
18!! reused, the w0 setting should be 1. Furthermore, the number of slots is
19!! chosen to be equal to the number of chunks. And Finally, the chunk size is
20!! chosen to be the size of the previous dimensions, if it does not exceed 4GB
21!! - Individual writes or plots are done now using the standard I/O driver, as
22!! using MPI does not allow for more than 2GB. This is important for the
23!! HELENA version of PB3D where \c X_2 variables get larger than that.
24!! <https://www.hdfgroup.org/HDF5/doc/UG/OldHtmlSource/UG_frame08TheFile.html>
25!! - Have a look in Documentation/XDMF_HDF5.pdf for an example.
26!------------------------------------------------------------------------------!
28#include <PB3D_macros.h>
30 use messages
31 use str_utilities, only: i2str, r2str, r2strt
32 use hdf5_vars
33 use hdf5
34
35 implicit none
36 private
41#if ldebug
43#endif
44
45#if ldebug
46 ! global variables
47 logical :: debug_hdf5_ops = .false. !< set to true to debug general information \ldebug
48 logical :: debug_print_hdf5_arrs = .false. !< set to true to debug print_HDF5_arrs \ldebug
49#endif
50
51 ! interfaces
52
53 !> \public Resets an HDF5 XDMF item.
54 !!
55 !! \note individual version cannot make use of array version because then
56 !! the deallocation does not work properly.
58 !> \public
59 module procedure reset_hdf5_item_ind
60 !> \public
61 module procedure reset_hdf5_item_arr
62 end interface
63
64contains
65 !> Opens an HDF5 file and accompanying xmf file and returns the handles.
66 !!
67 !! Optionally, a description of the file can be provided.
68 !!
69 !! Also, the plot can be done for only one process, setting the variable
70 !! \c ind_plot.
71 !!
72 !! Furthermore, if the plot is a continuation, using \c cont_plot, the
73 !! previous plot is opened and \c sym_type is returned.
74 !!
75 !! \return ierr
76 integer function open_hdf5_file(file_info,file_name,sym_type,descr,&
77 &ind_plot,cont_plot) result(ierr)
78 use num_vars, only: rank
79 use mpi
80 use files_utilities, only: nextunit
82
83 character(*), parameter :: rout_name = 'open_HDF5_file'
84
85 ! input / output
86 type(hdf5_file_type), intent(inout) :: file_info !< info about HDF5 file
87 character(len=*), intent(in) :: file_name !< name of HDF5 file
88 integer, intent(inout), optional :: sym_type !< symmetry type
89 character(len=*), intent(in), optional :: descr !< description of file
90 logical, intent(in), optional :: ind_plot !< whether individual plot
91 logical, intent(in), optional :: cont_plot !< continued plot
92
93 ! local variables
94 character(len=max_str_ln) :: full_file_name ! full file name
95 character(len=max_str_ln) :: line ! line in file
96 character(len=max_str_ln) :: err_msg ! error message
97 integer(HID_T) :: hdf5_i ! file identifier
98 integer(HID_T) :: plist_id ! property list identifier
99 integer :: sym_type_loc ! local symmetry type
100 integer :: mpi_comm_loc ! MPI Communicator used
101 integer :: disable_rw ! MPI info to disable read and write
102 integer :: i_st(2) ! indices of sym_type in read string
103 integer :: id ! counter
104 logical :: ind_plot_loc ! local version of ind_plot
105 logical :: cont_plot_loc ! local version of cont_plot
106
107 ! initialize ierr
108 ierr = 0
109
110 ! set up local ind_plot
111 ind_plot_loc = .false.
112 if (present(ind_plot)) ind_plot_loc = ind_plot
113
114 ! set up local cont_plot
115 cont_plot_loc = .false.
116 if (present(cont_plot)) cont_plot_loc = cont_plot
117
118 ! set up MPI Communicator
119 if (ind_plot_loc) then
120 mpi_comm_loc = mpi_comm_self ! individual plot
121 else
122 mpi_comm_loc = mpi_comm_world ! default world communicator
123 end if
124
125 ! set up full file name
126 full_file_name = data_dir//'/'//trim(file_name)
127
128 ! initialize FORTRAN predefined datatypes
129 call h5open_f(ierr)
130 chckerr('Failed to initialize HDF5')
131
132#if lIB
133 ! disable file locking
134 call mpi_info_create(disable_rw,ierr)
135 chckerr('Failed to create MPI info')
136 call mpi_info_set(disable_rw,'romio_ds_read','disable',ierr)
137 chckerr('Failed to set MPI info')
138 call mpi_info_set(disable_rw,'romio_ds_write','disable',ierr)
139 chckerr('Failed to set MPI info')
140#else
141 disable_rw = mpi_info_null
142#endif
143
144 ! setup file access property list with parallel I/O access if needed
145 call h5pcreate_f(h5p_file_access_f,plist_id,ierr)
146 chckerr('Failed to create property list')
147 call h5pset_fapl_mpio_f(plist_id,mpi_comm_loc,disable_rw,ierr)
148 chckerr('Failed to set file access property')
149
150#if lIB
151 ! free file locking info
152 call mpi_info_free(disable_rw,ierr)
153 chckerr('Failed to free MPI info')
154#endif
155
156 ! create or open the file collectively.
157 if (cont_plot_loc) then
158 call h5fopen_f(trim(full_file_name)//'.h5',h5f_acc_rdwr_f,&
159 &hdf5_i,ierr,access_prp=plist_id)
160 chckerr('Failed to open file')
161 else
162 call h5fcreate_f(trim(full_file_name)//'.h5',h5f_acc_trunc_f,&
163 &hdf5_i,ierr,access_prp=plist_id)
164 err_msg = 'Failed to create file. Is '//trim(data_dir)//'/ present?'
165 chckerr(err_msg)
166 end if
167
168 ! close property list
169 call h5pclose_f(plist_id,ierr)
170 chckerr('Failed to close property list')
171
172 ! update file info, converting integers and setting name
173 file_info%HDF5_i = hdf5_i
174 file_info%name = file_name
175
176 ! XDMF operations: only master if parallel plot or current rank if
177 ! individual plot
178 if (ind_plot_loc .or. .not.ind_plot_loc.and.rank.eq.0) then
179 if (cont_plot_loc) then
180 ! open accompanying xmf file
181 open(nextunit(file_info%XDMF_i),status='old',action='read',&
182 &file=trim(full_file_name)//'.xmf',iostat=ierr)
183 chckerr('Failed to open xmf file')
184
185 ! read symmetry type in fourth line if requested
186 if (present(sym_type)) then
187 do id = 1,4
188 read(file_info%XDMF_i,'(A)',iostat=ierr) line
189 chckerr('Failed to read file')
190 end do
191 i_st(1) = index(line,'Value="')
192 if (i_st(1).eq.0) then
193 ierr = 1
194 chckerr('Can''t find symmetry type')
195 else
196 i_st(1) = i_st(1) + 7
197 end if
198 i_st(2) = index(line(i_st(1):),'"/>') + i_st(1)
199 if (i_st(2).eq.0) then
200 ierr = 1
201 chckerr('Can''t find symmetry type')
202 else
203 i_st(2) = i_st(2) - 2
204 end if
205 read(line(i_st(1):i_st(2)),*,iostat=ierr) sym_type_loc
206 chckerr('Can''t read symmetry type')
207 if (sym_type_loc.ne.sym_type) then
208 ierr = 1
209 err_msg = 'Symmetry type of continued plot does not &
210 &match previous plot'
211 chckerr(err_msg)
212 end if
213 end if
214 else
215 ! open accompanying xmf file
216 open(nextunit(file_info%XDMF_i),status='replace',&
217 &file=trim(full_file_name)//'.xmf',iostat=ierr)
218 chckerr('Failed to create xmf file')
219
220 ! write header if group master
221 write(unit=file_info%XDMF_i,fmt=xmf_fmt,iostat=ierr) &
222 &'<?xml version="1.0" ?>'
223 chckerr('Failed to write')
224 write(unit=file_info%XDMF_i,fmt=xmf_fmt,iostat=ierr) &
225 &'<!DOCTYPE Xdmf SYSTEM "Xdmf.dtd" []>'
226 chckerr('Failed to write')
227 write(unit=file_info%XDMF_i,fmt=xmf_fmt,iostat=ierr) &
228 &'<Xdmf Version="2.0">'
229 chckerr('Failed to write')
230 if (present(sym_type)) then
231 write(unit=file_info%XDMF_i,fmt=xmf_fmt,iostat=ierr) &
232 &'<Information Name="sym_type" &
233 &Value="'//trim(i2str(sym_type))//'"/>'
234 chckerr('Failed to write')
235 end if
236 write(unit=file_info%XDMF_i,fmt=xmf_fmt,iostat=ierr) &
237 &'<Domain>'
238 chckerr('Failed to write')
239 if (present(descr)) then
240 write(unit=file_info%XDMF_i,fmt=xmf_fmt,iostat=ierr) &
241 &'<Information Name="Description">'
242 chckerr('Failed to write')
243 write(unit=file_info%XDMF_i,fmt=xmf_fmt,iostat=ierr) &
244 &trim(descr)
245 chckerr('Failed to write')
246 write(unit=file_info%XDMF_i,fmt=xmf_fmt,iostat=ierr) &
247 &'</Information>'
248 chckerr('Failed to write')
249 end if
250 end if
251 end if
252
253 ! pass symmetry type to other processes if continued plot
254 if (cont_plot_loc .and. .not.ind_plot_loc .and. present(sym_type)) then
255 ierr = broadcast_var(sym_type)
256 chckerr('')
257 end if
258 end function open_hdf5_file
259
260 !> Closes an HDF5 file and writes the accompanying xmf file.
261 !!
262 !! \return ierr
263 integer function close_hdf5_file(file_info,ind_plot,cont_plot) result(ierr)
264 use num_vars, only: rank
265
266 character(*), parameter :: rout_name = 'close_HDF5_file'
267
268 ! input / output
269 type(hdf5_file_type), intent(inout) :: file_info !< info about HDF5 file
270 logical, intent(in), optional :: ind_plot !< whether individual plot
271 logical, intent(in), optional :: cont_plot !< continued plot
272
273 ! local variables
274 character(len=max_str_ln) :: err_msg ! error message
275 character(len=max_str_ln) :: full_file_name ! full file name
276 integer(HID_T) :: hdf5_i ! file identifier
277 logical :: ind_plot_loc ! local version of ind_plot
278 logical :: cont_plot_loc ! local version of cont_plot
279
280 ! initialize ierr
281 ierr = 0
282
283 ! set up local ind_plot
284 ind_plot_loc = .false.
285 if (present(ind_plot)) ind_plot_loc = ind_plot
286
287 ! set up local cont_plot
288 cont_plot_loc = .false.
289 if (present(cont_plot)) cont_plot_loc = cont_plot
290
291 ! set full file name and HDF5_i (converting integers)
292 full_file_name = data_dir//'/'//trim(file_info%name)
293 hdf5_i = file_info%HDF5_i
294
295 ! close the HDF5 file
296 call h5fclose_f(hdf5_i,ierr)
297 chckerr('failed to close HDF5 file')
298
299 ! close FORTRAN interfaces and HDF5 library.
300 call h5close_f(ierr)
301 err_msg = 'Failed to close FORTRAN HDF5 interface'
302 chckerr(err_msg)
303
304 ! only master if parallel plot or current rank if individual plot
305 if (ind_plot_loc .or. .not.ind_plot_loc.and.rank.eq.0) then
306 ! XDMF operations: only if not continued plot
307 if (.not.cont_plot_loc) then
308 ! close header
309 write(unit=file_info%XDMF_i,fmt=xmf_fmt,iostat=ierr) &
310 &'</Domain>'
311 chckerr('Failed to write')
312 write(unit=file_info%XDMF_i,fmt=xmf_fmt,iostat=ierr) &
313 &'</Xdmf>'
314 chckerr('Failed to write')
315 end if
316
317 ! close accompanying xmf file
318 close(file_info%XDMF_i,iostat=ierr)
319 chckerr('Failed to close xmf file')
320
321 ! user output
322 if (cont_plot_loc) then
323 call writo('Contributed to HDF5/XMF plot in output file "'//&
324 &trim(full_file_name)//'.xmf''')
325 else
326 call writo('Created HDF5/XMF plot in output file "'//&
327 &trim(full_file_name)//'.xmf''')
328 end if
329 end if
330 end function close_hdf5_file
331
332 !> Add an XDMF item to a HDF5 file.
333 !!
334 !! \note This should only be used with grids (or for topologies and
335 !! geometries that are used throughout)
336 !!
337 !! \return ierr
338 integer function add_hdf5_item(file_info,XDMF_item,reset,ind_plot) &
339 &result(ierr)
340 use num_vars, only: rank
341
342 character(*), parameter :: rout_name = 'add_HDF5_item'
343
344 ! input / output
345 type(hdf5_file_type), intent(inout) :: file_info !< info about HDF5 file
346 type(xml_str_type), intent(inout) :: xdmf_item !< XDMF item to add
347 logical, intent(in), optional :: reset !< if .true., XDMF_item is reset
348 logical, intent(in), optional :: ind_plot !< whether individual plot
349
350 ! local variables
351 integer :: id ! counter
352 integer :: item_len ! length of item
353 logical :: reset_loc ! local copy of reset
354 logical :: ind_plot_loc ! local version of ind_plot
355
356 ! initialize ierr
357 ierr = 0
358
359 ! set up local ind_plot
360 ind_plot_loc = .false.
361 if (present(ind_plot)) ind_plot_loc = ind_plot
362
363 ! only group master if parallel plot or current rank if individual plot
364 if (ind_plot_loc .or. .not.ind_plot_loc.and.rank.eq.0) then
365 ! set item_len
366 item_len = size(xdmf_item%xml_str)
367
368 ! set local reset
369 if (present(reset)) then
370 reset_loc = reset
371 else
372 reset_loc = .false.
373 end if
374
375 ! write the strings to the file
376 do id = 1,item_len
377 write(unit=file_info%XDMF_i,fmt=xmf_fmt,iostat=ierr) &
378 &trim(xdmf_item%xml_str(id))
379 chckerr('Failed to write HDF5 item')
380 end do
381
382 ! reset if requested
383 if (reset_loc) call reset_hdf5_item(xdmf_item,ind_plot_loc)
384 end if
385 end function add_hdf5_item
386
387 !> Prints an HDF5 data item.
388 !!
389 !! If this is a parallel data item, the group dimension and offset have to
390 !! be specified as well.
391 !!
392 !! \return ierr
393 integer function print_hdf5_3d_data_item(dataitem_id,file_info,var_name,&
394 &var,dim_tot,loc_dim,loc_offset,init_val,ind_plot,cont_plot) &
395 &result(ierr)
396
397 use num_vars, only: rank
398
399 character(*), parameter :: rout_name = 'print_HDF5_3D_data_item'
400
401 ! input / output
402 type(xml_str_type), intent(inout) :: dataitem_id !< ID of data item
403 type(hdf5_file_type), intent(in) :: file_info !< info about HDF5 file
404 character(len=*), intent(in) :: var_name !< name of variable
405 real(dp), intent(in) :: var(:,:,:) !< variable to write
406 integer, intent(in) :: dim_tot(3) !< total dimensions of variable
407 integer, intent(in), optional :: loc_dim(3) !< dimensions in this group
408 integer, intent(in), optional :: loc_offset(3) !< offset in this group
409 real(dp), intent(in), optional :: init_val !< initial fill value
410 logical, intent(in), optional :: ind_plot !< whether individual plot
411 logical, intent(in), optional :: cont_plot !< continued plot
412
413 ! local variables
414 integer :: id ! counter
415 integer :: loc_dim_loc(3) ! local copy of loc_dim
416 integer :: loc_offset_loc(3) ! local copy of loc_offset
417 integer(HSIZE_T) :: dimsf(3) ! total dataset dimensions
418 integer(HSIZE_T) :: dimsm(3) ! group dataset dimensions
419 integer(HID_T) :: filespace ! dataspace identifier in file
420 integer(HID_T) :: memspace ! Dataspace identifier in memory
421 integer(HID_T) :: plist_id ! property list identifier
422 integer(HID_T) :: dset_id ! dataset identifier
423 integer(HSIZE_T) :: mem_offset(3) ! offset in memory
424 integer(HSIZE_T) :: mem_block(3) ! block size in memory
425 integer(HSIZE_T) :: mem_stride(3) ! stride in memory
426 integer(HSIZE_T) :: mem_count(3) ! nr. of repetitions of block in memory
427 character(len=max_str_ln) :: dim_str ! string with dimensions
428 character(len=max_str_ln) :: err_msg ! error message
429 logical :: ind_plot_loc ! local version of ind_plot
430 logical :: cont_plot_loc ! local version of cont_plot
431 integer(HID_T) :: hdf5_kind_64 ! HDF5 type corresponding to dp
432#if ldebug
433 integer :: istat ! status
434#endif
435
436 ! initialize ierr
437 ierr = 0
438
439 ! set up local ind_plot
440 ind_plot_loc = .false.
441 if (present(ind_plot)) ind_plot_loc = ind_plot
442
443 ! set up local cont_plot
444 cont_plot_loc = .false.
445 if (present(cont_plot)) cont_plot_loc = cont_plot
446
447 ! set HDF5 type corresponding to dp
448 hdf5_kind_64 = h5kind_to_type(dp,h5_real_kind)
449
450 ! set the group dimensions and offset
451 ierr = check_for_parallel_3d(dim_tot,loc_dim_loc,loc_offset_loc,&
452 &loc_dim,loc_offset)
453 chckerr('')
454
455 ! create the data spaces for the dataset.
456 dimsf = dim_tot
457 dimsm = loc_dim_loc
458 call h5screate_simple_f(size(dimsf),dimsf,filespace,ierr)
459 chckerr('Failed to create file space')
460 call h5screate_simple_f(size(dimsm),dimsm,memspace,ierr)
461 chckerr('Failed to create memory space')
462
463 ! open or create data set
464 if (cont_plot_loc) then
465 ! open file data set
466 call h5dopen_f(file_info%HDF5_i,trim(var_name),dset_id,ierr)
467 chckerr('Failed to open file data set')
468
469 ! get file data space
470 call h5dget_space_f(dset_id,filespace,ierr)
471 chckerr('Failed to get file space')
472 else
473 ! set initial fill value if provided and create data set
474 if (present(init_val)) then
475 call h5pcreate_f(h5p_dataset_create_f,plist_id,ierr)
476 err_msg = 'Failed to create property list'
477 chckerr(err_msg)
478 call h5pset_fill_value_f(plist_id,hdf5_kind_64,init_val,ierr)
479 err_msg = 'Failed to set default fill value property'
480 chckerr(err_msg)
481 call h5dcreate_f(file_info%HDF5_i,trim(var_name),hdf5_kind_64,&
482 &filespace,dset_id,ierr,plist_id)
483 chckerr('Failed to create file data set')
484 call h5pclose_f(plist_id,ierr)
485 chckerr('Failed to close property list')
486 else
487 call h5dcreate_f(file_info%HDF5_i,trim(var_name),hdf5_kind_64,&
488 &filespace,dset_id,ierr)
489 chckerr('Failed to create file data set')
490 end if
491 end if
492
493 ! select hyperslab in the file.
494 mem_count = 1
495 mem_stride = 1
496 mem_block = loc_dim_loc
497 mem_offset = loc_offset_loc
498 call h5sselect_hyperslab_f(filespace,h5s_select_set_f,mem_offset,&
499 &mem_count,ierr,mem_stride,mem_block)
500 chckerr('Failed to select hyperslab')
501
502 ! create property list for collective dataset write
503 call h5pcreate_f(h5p_dataset_xfer_f,plist_id,ierr)
504 chckerr('Failed to create property list')
505 if (ind_plot_loc) then
506 plist_id = h5p_default_f
507 else
508 call h5pset_dxpl_mpio_f(plist_id,h5fd_mpio_collective_f,ierr)
509 chckerr('Failed to set parallel property')
510 end if
511
512 ! write the dataset collectively.
513 call h5dwrite_f(dset_id,hdf5_kind_64,var,dimsf,ierr,&
514 &file_space_id=filespace,mem_space_id=memspace,xfer_prp=plist_id)
515 chckerr('Failed to write data set')
516 call h5pclose_f(plist_id,ierr)
517 chckerr('Failed to close property list')
518
519 ! close dataspaces.
520 call h5sclose_f(filespace,ierr)
521 chckerr('Unable to close file space')
522 call h5sclose_f(memspace,ierr)
523 chckerr('Unable to close memory space')
524
525 ! close the dataset.
526 call h5dclose_f(dset_id,ierr)
527 chckerr('Failed to close data set')
528
529 ! only group master if parallel plot or current rank if individual plot,
530 ! if not continued plot
531 if (.not.cont_plot_loc) then
532 if (ind_plot_loc .or. .not.ind_plot_loc.and.rank.eq.0) then
533 ! set up dimensions string
534 dim_str = ''
535 do id = 1,size(dim_tot)
536 !if (dim_tot(id).gt.1) then
537 dim_str = trim(dim_str)//' '//trim(i2str(dim_tot(id)))
538 !end if
539 end do
540 dataitem_id%name = 'DataItem - '//trim(var_name)
541 allocate(dataitem_id%xml_str(3))
542 dataitem_id%xml_str(1) = '<DataItem Dimensions="'//&
543 &trim(dim_str)//'" NumberType="Float" Precision="8" &
544 &Format="HDF">'
545 dataitem_id%xml_str(2) = trim(file_info%name)//'.h5:/'//&
546 &trim(var_name)
547 dataitem_id%xml_str(3) = '</DataItem>'
548
549#if ldebug
550 if (debug_hdf5_ops) write(*,*,iostat=istat) &
551 &'created data item "'//trim(dataitem_id%name)//'"'
552#endif
553 end if
554 end if
555 contains
556 ! Check whether the dimensions provided are a valid parallel indicator
557 ! or not.
558 !> \private
559 integer function check_for_parallel_3d(dim_tot,loc_dim_out,&
560 &loc_offset_out,loc_dim_in,loc_offset_in) result(ierr)
561 character(*), parameter :: rout_name = 'check_for_parallel_3D'
562
563 ! input / output
564 integer, intent(in) :: dim_tot(3) ! total dimension
565 integer, intent(inout) :: loc_dim_out(3), loc_offset_out(3) ! output group dimension and offset
566 integer, intent(in), optional :: loc_dim_in(3), loc_offset_in(3) ! input group dimension and offset
567
568 ! local variables
569 character(len=max_str_ln) :: err_msg ! error message
570 integer :: id ! counter
571
572 ! initialize ierr
573 ierr = 0
574
575 if (present(loc_dim_in)) then
576 if (.not.present(loc_offset_in)) then
577 err_msg = 'Need to specify offset as well as group &
578 &dimensions'
579 ierr = 1
580 chckerr(err_msg)
581 else
582 loc_dim_out = loc_dim_in
583 loc_offset_out = loc_offset_in
584 end if
585 do id = 1,size(dim_tot)
586 if (loc_dim_in(id).gt.dim_tot(id)) then ! error in parallel file
587 err_msg = 'Total dimension '//trim(i2str(id))//&
588 &' cannot be smaller than group dimension'
589 ierr = 1
590 chckerr(err_msg)
591 end if
592 end do
593 else
594 loc_dim_out = dim_tot
595 loc_offset_out = 0
596 end if
597 end function check_for_parallel_3d
598 end function print_hdf5_3d_data_item
599
600 !> Joins dataitems in a vector.
601 subroutine merge_hdf5_3d_data_items(merged_id,dataitem_ids,var_name,&
602 &dim_tot,reset,ind_plot,cont_plot)
603 use num_vars, only: rank
604
605 ! input / output
606 type(xml_str_type), intent(inout) :: merged_id !< ID of merged data item
607 type(xml_str_type), intent(inout) :: dataitem_ids(:) !< ID of data items
608 character(len=*), intent(in) :: var_name !< name of variable
609 integer, intent(in) :: dim_tot(3) !< total dimensions of variable
610 logical, intent(in), optional :: reset !< whether to reset dataitems
611 logical, intent(in), optional :: ind_plot !< whether individual plot
612 logical, intent(in), optional :: cont_plot !< continued plot
613
614 ! local variables
615 integer :: dataitem_len ! length of data item
616 integer :: id, jd ! counters
617 integer :: jd_loc ! local jd
618 logical :: reset_loc ! local copy of reset
619 logical :: ind_plot_loc ! local version of ind_plot
620 logical :: cont_plot_loc ! local version of cont_plot
621 character(len=max_str_ln) :: dim_str ! string with dimensions
622 character(len=max_str_ln) :: fun_str ! string with function
623#if ldebug
624 integer :: istat ! status
625#endif
626
627 ! set up local ind_plot
628 ind_plot_loc = .false.
629 if (present(ind_plot)) ind_plot_loc = ind_plot
630
631 ! set up local cont_plot
632 cont_plot_loc = .false.
633 if (present(cont_plot)) cont_plot_loc = cont_plot
634
635 ! set local reset
636 reset_loc = .false.
637 if (present(reset)) reset_loc = reset
638
639 ! only group master if parallel plot or current rank if individual plot,
640 ! if not continued plot
641 if (.not.cont_plot_loc) then
642 if (ind_plot_loc .or. .not.ind_plot_loc.and.rank.eq.0) then
643 ! set dataitem_len
644 dataitem_len = 0
645 do id = 1,size(dataitem_ids)
646 dataitem_len = dataitem_len + size(dataitem_ids(id)%xml_str)
647 end do
648
649 ! set XDMF attribute ID
650 merged_id%name = 'DataItem - '//trim(var_name)
651 allocate(merged_id%xml_str(dataitem_len+2))
652
653 ! set up dimensions string
654 dim_str = ''
655 do id = 1,size(dim_tot)
656 !if (dim_tot(id).gt.1) then
657 dim_str = trim(dim_str)//' '//trim(i2str(dim_tot(id)))
658 !end if
659 end do
660 dim_str = trim(dim_str)//' '//trim(i2str(size(dataitem_ids)))
661
662 ! set up function string
663 fun_str = '"JOIN('
664 do id = 1,size(dataitem_ids)
665 if (id.gt.1) fun_str = trim(fun_str)//','
666 fun_str = trim(fun_str)//' $'//trim(i2str(id-1))
667 end do
668 fun_str = trim(fun_str)//')"'
669
670 merged_id%xml_str(1) = '<DataItem Dimensions="'//&
671 &trim(dim_str)//'" Function='//trim(fun_str)//&
672 &' ItemType="Function" >'
673 jd_loc = 2
674 do id = 1,size(dataitem_ids)
675 do jd = 1,size(dataitem_ids(id)%xml_str)
676 merged_id%xml_str(jd_loc) = dataitem_ids(id)%xml_str(jd)
677 jd_loc = jd_loc+1
678 end do
679 end do
680 merged_id%xml_str(jd_loc) = '</DataItem>'
681
682 ! reset if requested
683 if (reset_loc) call reset_hdf5_item(dataitem_ids,ind_plot_loc)
684
685#if ldebug
686 if (debug_hdf5_ops) write(*,*,iostat=istat) &
687 &'merged data items into "'//trim(merged_id%name)//'"'
688#endif
689 end if
690 end if
691 end subroutine merge_hdf5_3d_data_items
692
693 !> Prints an HDF5 attribute.
694 subroutine print_hdf5_att(att_id,att_dataitem,att_name,att_center,att_type,&
695 &reset,ind_plot)
696
697 use num_vars, only: rank
698
699 ! input / output
700 type(xml_str_type), intent(inout) :: att_id !< ID of attribute
701 type(xml_str_type), intent(inout) :: att_dataitem !< dataitem of attribute
702 character(len=*), intent(in) :: att_name !< name of attribute
703 integer, intent(in) :: att_center !< center of attribute
704 integer, intent(in) :: att_type !< type of attribute
705 logical, intent(in), optional :: reset !< whether to reset dataitems
706 logical, intent(in), optional :: ind_plot !< whether individual plot
707
708 ! local variables
709 integer :: dataitem_len ! length of data item
710 integer :: id ! counter
711 logical :: reset_loc ! local copy of reset
712 logical :: ind_plot_loc ! local version of ind_plot
713#if ldebug
714 integer :: istat ! status
715#endif
716
717 ! set up local ind_plot
718 ind_plot_loc = .false.
719 if (present(ind_plot)) ind_plot_loc = ind_plot
720
721 ! only group master if parallel plot or current rank if individual plot
722 if (ind_plot_loc .or. .not.ind_plot_loc.and.rank.eq.0) then
723 ! set dataitem_len
724 dataitem_len = size(att_dataitem%xml_str)
725
726 ! set local reset
727 reset_loc = .false.
728 if (present(reset)) reset_loc = reset
729
730 ! set XDMF attribute ID
731 att_id%name = 'Attribute - '//trim(att_name)
732 allocate(att_id%xml_str(dataitem_len+2))
733 att_id%xml_str(1) = '<Attribute Name="'//trim(att_name)//&
734 &'" AttributeType="'//trim(xdmf_att_types(att_type))//&
735 &'" Center="'//trim(xdmf_center_types(att_center))//'">'
736 do id = 1,dataitem_len
737 att_id%xml_str(id+1) = att_dataitem%xml_str(id)
738 end do
739 att_id%xml_str(dataitem_len+2) = '</Attribute>'
740
741#if ldebug
742 if (debug_hdf5_ops) write(*,*,iostat=istat) 'created attribute "'//&
743 &trim(att_id%name)//'"'
744#endif
745
746 ! reset if requested
747 if (reset_loc) call reset_hdf5_item(att_dataitem,ind_plot_loc)
748 end if
749 end subroutine print_hdf5_att
750
751 !> Prints an HDF5 topology.
752 !!
753 !> \note Currently only structured grids supported.
754 subroutine print_hdf5_top(top_id,top_type,top_n_elem,ind_plot)
755 use num_vars, only: rank
756
757 ! input / output
758 type(xml_str_type), intent(inout) :: top_id !< ID of topology
759 integer, intent(in) :: top_type !< type
760 integer, intent(in) :: top_n_elem(:) !< nr. of elements
761 logical, intent(in), optional :: ind_plot !< whether individual plot
762
763 ! local variables
764 integer :: id ! counter
765 integer :: n_dims ! nr. of dimensions
766 character(len=max_str_ln) :: work_str ! work string
767 logical :: ind_plot_loc ! local version of ind_plot
768#if ldebug
769 integer :: istat ! status
770#endif
771
772 ! set up local ind_plot
773 ind_plot_loc = .false.
774 if (present(ind_plot)) ind_plot_loc = ind_plot
775
776 ! only group master if parallel plot or current rank if individual plot
777 if (ind_plot_loc .or. .not.ind_plot_loc.and.rank.eq.0) then
778 ! set n_dims
779 n_dims = size(top_n_elem)
780
781 ! fill work string
782 work_str = ''
783 do id = n_dims,1,-1
784 !if (top_n_elem(id).gt.1) then
785 work_str = trim(work_str)//' '//trim(i2str(top_n_elem(id)))
786 !end if
787 end do
788
789 ! set XDMF topology ID
790 top_id%name = 'Topology'
791 allocate(top_id%xml_str(1))
792 top_id%xml_str(1) = '<Topology TopologyType="'//&
793 &trim(xdmf_top_types(top_type))//'" NumberOfElements="'//&
794 &trim(work_str)//'"/>'
795
796#if ldebug
797 if (debug_hdf5_ops) write(*,*,iostat=istat) 'created topology "'//&
798 &trim(top_id%name)//'"'
799#endif
800 end if
801 end subroutine print_hdf5_top
802
803 !> Prints an HDF5 geometry.
804 subroutine print_hdf5_geom(geom_id,geom_type,geom_dataitems,reset,ind_plot)
805 use num_vars, only: rank
806
807 ! input / output
808 type(xml_str_type), intent(inout) :: geom_id !< ID of geometry
809 integer, intent(in) :: geom_type !< type of geometry
810 type(xml_str_type), intent(inout) :: geom_dataitems(:) !< data items of geometry
811 logical, intent(in), optional :: reset !< whether to reset dataitems
812 logical, intent(in), optional :: ind_plot !< whether individual plot
813
814 ! local variables
815 integer :: id, jd ! counters
816 integer :: id_sum ! counter
817 integer, allocatable :: dataitem_len(:) ! length of data item
818 integer :: n_dataitems ! nr. of data items
819 logical :: reset_loc ! local copy of reset
820 logical :: ind_plot_loc ! local version of ind_plot
821#if ldebug
822 integer :: istat ! status
823#endif
824
825 ! set up local ind_plot
826 ind_plot_loc = .false.
827 if (present(ind_plot)) ind_plot_loc = ind_plot
828
829 ! only group master if parallel plot or current rank if individual plot
830 if (ind_plot_loc .or. .not.ind_plot_loc.and.rank.eq.0) then
831 ! set n_dataitems
832 n_dataitems = size(geom_dataitems)
833
834 ! set dataitem_len for every data item
835 allocate(dataitem_len(n_dataitems))
836 do id = 1,n_dataitems
837 dataitem_len(id) = size(geom_dataitems(id)%xml_str)
838 end do
839
840 ! set local reset
841 if (present(reset)) then
842 reset_loc = reset
843 else
844 reset_loc = .false.
845 end if
846
847 ! set XDMF geometry ID
848 geom_id%name = 'Geometry'
849 allocate(geom_id%xml_str(sum(dataitem_len)+2))
850 geom_id%xml_str(1) = '<Geometry GeometryType="'//&
851 &trim(xdmf_geom_types(geom_type))//'">'
852 id_sum = 2 ! starting index
853 do id = 1,n_dataitems
854 do jd = 1,dataitem_len(id)
855 geom_id%xml_str(id_sum) = geom_dataitems(id)%xml_str(jd)
856 id_sum = id_sum + 1
857 end do
858 end do
859 geom_id%xml_str(id_sum) = '</Geometry>'
860
861#if ldebug
862 if (debug_hdf5_ops) write(*,*,iostat=istat) 'created geometry "'//&
863 &trim(geom_id%name)//'"'
864#endif
865
866 ! reset if requested
867 if (reset_loc) call reset_hdf5_item(geom_dataitems,ind_plot_loc)
868 end if
869 end subroutine print_hdf5_geom
870
871 !> Prints an HDF5 grid.
872 !!
873 !! If this is is a uniform grid, the geometry and topology have to be
874 !! specified, or else it will be assumed that it is already present in the
875 !! XDMF domain, and reused.
876 !!
877 !! If the grid is a collection grid, the grids in the collection have to be
878 !! specified.
879 !!
880 !! Optionally, also a time can be specified (for the grids in a collection
881 !! grid).
882 !!
883 !! \return ierr
884 integer function print_hdf5_grid(grid_id,grid_name,grid_type,grid_time,&
885 &grid_top,grid_geom,grid_atts,grid_grids,reset,ind_plot) result(ierr)
886 use num_vars, only: rank
887
888 character(*), parameter :: rout_name = 'print_HDF5_grid'
889
890 ! input / output
891 type(xml_str_type), intent(inout) :: grid_id !< ID of grid
892 character(len=*), intent(in) :: grid_name !< name
893 integer, intent(in) :: grid_type !< type
894 real(dp), intent(in), optional :: grid_time !< time of grid
895 type(xml_str_type), optional :: grid_top !< topology
896 type(xml_str_type), optional :: grid_geom !< geometry
897 type(xml_str_type), optional :: grid_atts(:) !< attributes
898 type(xml_str_type), optional :: grid_grids(:) !< grids
899 logical, intent(in), optional :: reset !< whether top, geom and atts and grids are reset
900 logical, intent(in), optional :: ind_plot !< whether individual plot
901
902 ! local variables
903 integer :: id, jd ! counters
904 integer :: id_sum ! counter
905 integer :: n_grids ! nr. of grids
906 integer :: n_atts ! nr. of attributes
907 integer :: time_len ! length of time
908 integer :: top_len ! length of topology
909 integer :: geom_len ! length of geometry
910 integer, allocatable :: atts_len(:) ! lengths of attributes
911 integer, allocatable :: grids_len(:) ! lengths of grids
912 logical :: reset_loc ! local copy of reset
913 character(len=max_str_ln) :: err_msg ! error message
914 logical :: ind_plot_loc ! local version of ind_plot
915#if ldebug
916 integer :: istat ! status
917#endif
918
919 ! initialize ierr
920 ierr = 0
921
922 ! set up local ind_plot
923 ind_plot_loc = .false.
924 if (present(ind_plot)) ind_plot_loc = ind_plot
925
926 ! only group master if parallel plot or current rank if individual plot
927 if (ind_plot_loc .or. .not.ind_plot_loc.and.rank.eq.0) then
928 ! test whether the correct arguments are provided
929 if (grid_type.eq.1) then ! uniform grid
930 ! no requirements: topology and/or geometry can be defined in
931 ! domain for use throughout
932 else if (grid_type.eq.2 .or. grid_type.eq.3) then ! collection grid
933 if (.not.present(grid_grids)) then
934 ierr = 1
935 err_msg = 'For grid collections, the grids in the &
936 &collection have to be specified'
937 chckerr(err_msg)
938 end if
939 else
940 ierr = 1
941 err_msg = 'Grid type '//trim(i2str(grid_type))//' not supported'
942 chckerr(err_msg)
943 end if
944
945 ! set geom_len, atts_len and grids_len
946 time_len = 0
947 if (present(grid_time)) time_len = 1
948 top_len = 0
949 if (present(grid_top)) then
950 top_len = size(grid_top%xml_str)
951 else
952 if (grid_type.eq.1) top_len = 1 ! use of general domain topology
953 end if
954 geom_len = 0
955 if (present(grid_geom)) then
956 geom_len = size(grid_geom%xml_str)
957 else
958 if (grid_type.eq.1) geom_len = 1 ! use of general domain geometry
959 end if
960 n_atts = 0
961 if (present(grid_atts)) then
962 n_atts = size(grid_atts)
963 allocate(atts_len(n_atts))
964 atts_len = 0
965 do id = 1,n_atts
966 atts_len(id) = size(grid_atts(id)%xml_str)
967 end do
968 else
969 allocate(atts_len(0))
970 atts_len = 0
971 end if
972 n_grids = 0
973 if (present(grid_grids)) then
974 n_grids = size(grid_grids)
975 allocate(grids_len(n_grids))
976 grids_len = 0
977 do id = 1,n_grids
978 grids_len(id) = size(grid_grids(id)%xml_str)
979 end do
980 else
981 allocate(grids_len(0))
982 grids_len = 0
983 end if
984
985 ! set local reset
986 if (present(reset)) then
987 reset_loc = reset
988 else
989 reset_loc = .false.
990 end if
991
992 ! set XDMF grid ID
993 id_sum = 2 ! starting index
994 if (grid_type.eq.1) then ! uniform
995 grid_id%name = 'Uniform Grid - '//trim(grid_name)
996 allocate(&
997 &grid_id%xml_str(time_len+top_len+geom_len+sum(atts_len)+2))
998 grid_id%xml_str(1) = '<Grid Name="'//trim(grid_name)//&
999 &'" GridType="Uniform">'
1000 if (present(grid_time)) then ! time
1001 grid_id%xml_str(id_sum) = '<Time Value="'//&
1002 &trim(r2str(grid_time))//'" />'
1003 id_sum = id_sum + 1
1004 end if
1005 if (present(grid_top)) then
1006 do jd = 1,top_len ! topology
1007 grid_id%xml_str(id_sum) = grid_top%xml_str(jd)
1008 id_sum = id_sum + 1
1009 end do
1010 else
1011 grid_id%xml_str(id_sum) = '<Topology Reference="/Xdmf/&
1012 &Domain/Topology[1]"/>'
1013 id_sum = id_sum + 1
1014 end if
1015 if (present(grid_geom)) then
1016 do jd = 1,geom_len ! geometry
1017 grid_id%xml_str(id_sum) = grid_geom%xml_str(jd)
1018 id_sum = id_sum + 1
1019 end do
1020 else
1021 grid_id%xml_str(id_sum) = '<Geometry Reference="/Xdmf/&
1022 &Domain/Geometry[1]"/>'
1023 id_sum = id_sum + 1
1024 end if
1025 do id = 1,n_atts ! attributes
1026 do jd = 1,atts_len(id)
1027 grid_id%xml_str(id_sum) = grid_atts(id)%xml_str(jd)
1028 id_sum = id_sum + 1
1029 end do
1030 end do
1031 else ! collection
1032 grid_id%name = 'Collection Grid - '//trim(grid_name)
1033 allocate(grid_id%xml_str(time_len+sum(grids_len)+2))
1034 grid_id%xml_str(1) = '<Grid Name="'//trim(grid_name)//&
1035 &'" GridType="Collection" CollectionType="'//&
1036 &trim(xdmf_grid_types(grid_type))//'">'
1037 if (present(grid_time)) then ! time
1038 grid_id%xml_str(id_sum) = '<Time Value="'//&
1039 &trim(r2str(grid_time))//'" />'
1040 id_sum = id_sum + 1
1041 end if
1042 do id = 1,n_grids ! grids
1043 do jd = 1,grids_len(id)
1044 grid_id%xml_str(id_sum) = grid_grids(id)%xml_str(jd)
1045 id_sum = id_sum + 1
1046 end do
1047 end do
1048 end if
1049 grid_id%xml_str(id_sum) = '</Grid>'
1050
1051#if ldebug
1052 if (debug_hdf5_ops) write(*,*,iostat=istat) 'created grid "'//&
1053 &trim(grid_id%name)//'"'
1054#endif
1055
1056 ! reset if requested
1057 if (reset_loc) then
1058 if (grid_type.eq.1) then
1059 if (present(grid_top)) &
1060 &call reset_hdf5_item(grid_top,ind_plot_loc)
1061 if (present(grid_geom)) &
1062 &call reset_hdf5_item(grid_geom,ind_plot_loc)
1063 if (present(grid_atts)) &
1064 &call reset_hdf5_item(grid_atts,ind_plot_loc)
1065 else if (grid_type.eq.2 .or. grid_type.eq.3) then
1066 if (present(grid_grids)) &
1067 &call reset_hdf5_item(grid_grids,ind_plot_loc)
1068 end if
1069 end if
1070 end if
1071 end function print_hdf5_grid
1072
1073 !> Creates an HDF5 output file.
1074 integer function create_output_hdf5(HDF5_name) result(ierr)
1075 character(*), parameter :: rout_name = 'create_output_HDF5'
1076
1077 ! input / output
1078 character(len=*), intent(in) :: hdf5_name !< name of HDF5 file
1079
1080 ! local variables
1081 character(len=max_str_ln) :: err_msg ! error message
1082 integer(HID_T) :: hdf5_i ! file identifier
1083
1084 ! initialize ierr
1085 ierr = 0
1086
1087 call lvl_ud(1)
1088
1089 ! initialize FORTRAN predefined datatypes
1090 call h5open_f(ierr)
1091 chckerr('Failed to initialize HDF5')
1092
1093 ! create the file by group master
1094 call h5fcreate_f(trim(hdf5_name),h5f_acc_trunc_f,hdf5_i,ierr)
1095 err_msg = 'Failed to create file "'//trim(hdf5_name)//'"'
1096 chckerr(err_msg)
1097
1098 ! close the HDF5 file
1099 call h5fclose_f(hdf5_i,ierr)
1100 chckerr('failed to close HDF5 file')
1101
1102 ! close FORTRAN interfaces and HDF5 library.
1103 call h5close_f(ierr)
1104 err_msg = 'Failed to close FORTRAN HDF5 interface'
1105 chckerr(err_msg)
1106
1107 call lvl_ud(-1)
1108
1109 ! user output
1110 call writo('HDF5 output file '//trim(hdf5_name)//' created')
1111 end function create_output_hdf5
1112
1113 !> Prints a series of arrays, in the form of an array of pointers, to an
1114 !! HDF5 file.
1115 !!
1116 !! Optionally, output can be given about the variable being written. Also,
1117 !! if \c rich_lvl is provided, <tt>_R_[rich_lvl]</tt> is appended to the
1118 !! head name if it is > 0.
1119 !!
1120 !! Also optionally, previously encountered arrays can be removed. This is to
1121 !! be used with care, as it may disturb the internal workings of PB3D.
1122 !! Currently (v2.15) it is used only for the specific case of jumping to
1123 !! solutions for \c X_grid_style 1 or 3, when writing solutions and solution
1124 !! grids.
1125 !!
1126 !! \note See <https://www.hdfgroup.org/HDF5/doc/UG/12_Dataspaces.html>,
1127 !! 7.4.2.3 for an explanation of the selection of the dataspaces.
1128 !!
1129 !! \return ierr
1130 integer function print_hdf5_arrs(vars,PB3D_name,head_name,rich_lvl,&
1131 &disp_info,ind_print,remove_previous_arrs) result(ierr)
1132 use num_vars, only: n_procs, rank
1133 use mpi
1134 use mpi_vars, only: hdf5_lock
1136 use hdf5_utilities, only: set_1d_vars
1137
1138 character(*), parameter :: rout_name = 'print_HDF5_arrs'
1139
1140 ! input / output
1141 type(var_1d_type), intent(in) :: vars(:) !< variables to write
1142 character(len=*), intent(in) :: pb3d_name !< name of PB3D file
1143 character(len=*), intent(in) :: head_name !< head name of variables
1144 integer, intent(in), optional :: rich_lvl !< Richardson level to append to file name
1145 logical, intent(in), optional :: disp_info !< display additional information about variable being read
1146 logical, intent(in), optional :: ind_print !< individual write (possibly partial I/O)
1147 logical, intent(in), optional :: remove_previous_arrs !< remove previous variables if present
1148
1149 ! local variables
1150 integer :: id, jd ! counters
1151 integer :: mpi_comm_loc ! MPI Communicator used
1152 integer :: istat ! status
1153 integer :: n_dims ! nr. of dimensions
1154 integer, allocatable :: lim_tot(:,:) ! total limits
1155 integer, allocatable :: lim_loc(:,:) ! local limits
1156 character(len=max_str_ln) :: err_msg ! error message
1157 character(len=max_str_ln) :: head_name_loc ! local head_name
1158 logical :: ind_print_loc ! local ind_print
1159 logical :: disp_info_loc ! local disp_info
1160 logical :: remove_previous_arrs_loc ! local remove_previous_arrs
1161 logical :: group_exists ! the group exists and does not have to be created
1162 integer(HID_T) :: a_plist_id ! access property list identifier
1163 integer(HID_T) :: x_plist_id ! transfer property list identifier
1164 integer(HID_T) :: chunk_c_plist_id ! chunk create property list identifier
1165 integer(HID_T) :: hdf5_i ! file identifier
1166 integer(HID_T) :: hdf5_kind_64 ! HDF5 type corresponding to dp
1167 integer(HID_T) :: filespace ! dataspace identifier in file
1168 integer(HID_T) :: memspace ! Dataspace identifier in memory
1169 integer(HID_T) :: dset_id ! dataset identifier
1170 integer(HID_T) :: group_id ! group identifier
1171 integer(HID_T) :: head_group_id ! head group identifier
1172 integer(HSIZE_T) :: dimsf(1) ! total dataset dimensions
1173 integer(HSIZE_T) :: dimsm(1) ! group dataset dimensions
1174 integer :: disable_rw ! MPI info to disable read and write
1175#if ldebug
1176 real :: rdcc_w0 ! Preemption policy.
1177 integer(SIZE_T) :: rdcc_nslots ! Number of chunk slots in the raw data chunk cache hash table.
1178 integer(SIZE_T) :: rdcc_nbytes ! Total size of the raw data chunk cache, in bytes.
1179#endif
1180
1181 ! initialize ierr
1182 ierr = 0
1183
1184 ! set local disp_info
1185 disp_info_loc = .false.
1186 if (present(disp_info)) disp_info_loc = disp_info
1187
1188 ! set up local head_name
1189 head_name_loc = head_name
1190 if (present(rich_lvl)) then
1191 if (rich_lvl.gt.0) head_name_loc = trim(head_name_loc)//'_R_'//&
1192 &trim(i2str(rich_lvl))
1193 end if
1194
1195 ! set local remove_previous_arrs
1196 remove_previous_arrs_loc = .false.
1197 if (present(remove_previous_arrs)) remove_previous_arrs_loc = &
1198 &remove_previous_arrs
1199
1200 ! detect whether individual or collective print
1201 call detect_ind_print(ind_print_loc)
1202 if (present(ind_print)) ind_print_loc = ind_print
1203
1204 ! set up MPI Communicator
1205 if (ind_print_loc) then
1206 mpi_comm_loc = mpi_comm_self ! individual print
1207 else
1208 mpi_comm_loc = mpi_comm_world ! default world communicator
1209 end if
1210
1211 ! initialize FORTRAN predefined datatypes
1212 call h5open_f(ierr)
1213 chckerr('Failed to initialize HDF5')
1214
1215#if lIB
1216 ! disable file locking
1217 call mpi_info_create(disable_rw,ierr)
1218 chckerr('Failed to create MPI info')
1219 call mpi_info_set(disable_rw,'romio_ds_read','disable',ierr)
1220 chckerr('Failed to set MPI info')
1221 call mpi_info_set(disable_rw,'romio_ds_write','disable',ierr)
1222 chckerr('Failed to set MPI info')
1223#else
1224 disable_rw = mpi_info_null
1225#endif
1226
1227 ! setup file access property list with parallel I/O access if needed
1228 call h5pcreate_f(h5p_file_access_f,a_plist_id,ierr)
1229 chckerr('Failed to create property list')
1230 if (ind_print_loc) then
1231 call h5pset_fapl_stdio_f(a_plist_id,ierr)
1232 else
1233 call h5pset_fapl_mpio_f(a_plist_id,mpi_comm_loc,disable_rw,ierr)
1234 end if
1235 chckerr('Failed to set file access property')
1236
1237#if lIB
1238 ! free file locking info
1239 call mpi_info_free(disable_rw,ierr)
1240 chckerr('Failed to free MPI info')
1241#endif
1242
1243 ! wait for file access if individual print and multiple processes
1244 if (n_procs.gt.1 .and. ind_print_loc) then
1245 ierr = lock_req_acc(hdf5_lock)
1246 chckerr('')
1247 end if
1248
1249 ! open the file
1250 call h5fopen_f(trim(pb3d_name),h5f_acc_rdwr_f,hdf5_i,ierr,&
1251 &access_prp=a_plist_id)
1252 chckerr('Failed to open file')
1253 call h5pclose_f(a_plist_id,ierr)
1254 chckerr('Failed to close property list')
1255
1256 ! set HDF5 type corresponding to dp
1257 hdf5_kind_64 = h5kind_to_type(dp,h5_real_kind)
1258
1259 ! check if head group exists and if not create it
1260 call h5eset_auto_f(0,ierr)
1261 chckerr('Failed to disable error printing')
1262 call h5gopen_f(hdf5_i,trim(head_name_loc),head_group_id,istat)
1263 group_exists = istat.eq.0
1264 call h5eset_auto_f(1,ierr)
1265 if (group_exists .and. remove_previous_arrs_loc) then
1266 call h5gclose_f(head_group_id, ierr)
1267 chckerr('Failed to close head group')
1268 call h5ldelete_f(hdf5_i,trim(head_name_loc),ierr)
1269 chckerr('Failed to delete group')
1270 group_exists = .false.
1271#if ldebug
1272 if (debug_print_hdf5_arrs) call writo('group "'//&
1273 &trim(head_name_loc)//'" existed and was deleted')
1274#endif
1275 end if
1276 if (.not.group_exists) then ! group does not exist
1277 call h5gcreate_f(hdf5_i,trim(head_name_loc),head_group_id,ierr)
1278 chckerr('Failed to create group')
1279 end if
1280 chckerr('Failed to enable error printing')
1281
1282 ! user output
1283 call writo('Write data to PB3D output "'//trim(pb3d_name)//'/'//&
1284 &trim(head_name_loc)//'"')
1285 call lvl_ud(1)
1286
1287 ! loop over all elements in vars
1288 do id = 1,size(vars)
1289 ! user output
1290 if (disp_info_loc) then
1291 call writo('Writing '//trim(vars(id)%var_name))
1292 end if
1293
1294 ! check if group exists and if not create it
1295 call h5eset_auto_f(0,ierr)
1296 chckerr('Failed to disable error printing')
1297 call h5gopen_f(head_group_id,trim(vars(id)%var_name),group_id,istat)
1298 group_exists = istat.eq.0
1299 call h5eset_auto_f(1,ierr)
1300 chckerr('Failed to enable error printing')
1301 if (.not.group_exists) then ! group does not exist
1302 ! create group
1303 call h5gcreate_f(head_group_id,trim(vars(id)%var_name),&
1304 &group_id,ierr)
1305 chckerr('Failed to create group')
1306 end if
1307
1308 ! 1. Data itself
1309
1310 ! set up local and total limits
1311 n_dims = size(vars(id)%tot_i_min)
1312 allocate(lim_tot(n_dims,2))
1313 allocate(lim_loc(n_dims,2))
1314 lim_tot = &
1315 &reshape([vars(id)%tot_i_min,vars(id)%tot_i_max],[n_dims,2])
1316 lim_loc = &
1317 &reshape([vars(id)%loc_i_min,vars(id)%loc_i_max],[n_dims,2])
1318
1319 ! set dimsf
1320 dimsf = product(lim_tot(:,2)-lim_tot(:,1)+1) ! file space has total dimensions
1321
1322 ! create or open data set with filespace
1323 if (.not.group_exists) then ! group did not exist
1324 ! create file data space
1325 call h5screate_simple_f(1,dimsf,filespace,ierr)
1326 chckerr('Failed to create file space')
1327
1328 ! set up chunk creation property list
1329 ierr = set_1d_vars(lim_tot,lim_loc,c_plist_id=chunk_c_plist_id)
1330 chckerr('')
1331
1332 ! create file data set in group
1333 call h5dcreate_f(group_id,'var',hdf5_kind_64,filespace,&
1334 &dset_id,ierr,dcpl_id=chunk_c_plist_id)
1335 chckerr('Failed to create file data set')
1336
1337 ! close chunk property list
1338 call h5pclose_f(chunk_c_plist_id,ierr)
1339 chckerr('Failed to close property list')
1340 else ! group already exists
1341 ! open file data set
1342 call h5dopen_f(group_id,'var',dset_id,ierr)
1343 chckerr('Failed to open file data set')
1344
1345 ! get file data space
1346 call h5dget_space_f(dset_id,filespace,ierr)
1347 chckerr('Failed to get file space')
1348 end if
1349
1350#if ldebug
1351 if (debug_print_hdf5_arrs) then
1352 ! get data access property list
1353 call h5dget_access_plist_f(dset_id,a_plist_id,ierr)
1354 chckerr('Failed to get property list')
1355
1356 ! get chunk cache
1357 call h5pget_chunk_cache_f(a_plist_id,rdcc_nslots,&
1358 &rdcc_nbytes,rdcc_w0,ierr)
1359 write(*,*,iostat=istat) rank, 'Number of chunk slots in the &
1360 &raw data chunk cache hash table:', rdcc_nslots
1361 write(*,*,iostat=istat) rank, 'Total size of the raw data &
1362 &chunk cache, in Mbytes:', rdcc_nbytes*1.e-6_dp
1363 write(*,*,iostat=istat) rank, 'Preemption Policy:', rdcc_w0
1364 chckerr('Failed to get chunk cache')
1365
1366 ! close data access property list
1367 call h5pclose_f(a_plist_id,ierr)
1368 chckerr('Failed to close property list')
1369 end if
1370#endif
1371
1372 ! set 1D filespace hyperslab selection
1373 ierr = set_1d_vars(lim_tot,lim_loc,space_id=filespace)
1374 chckerr('')
1375
1376 ! create property list for collective dataset write
1377 call h5pcreate_f(h5p_dataset_xfer_f,x_plist_id,ierr)
1378 chckerr('Failed to create property list')
1379 if (ind_print_loc) then
1380 x_plist_id = h5p_default_f
1381 else
1382 call h5pset_dxpl_mpio_f(x_plist_id,h5fd_mpio_collective_f,ierr)
1383 chckerr('Failed to set parallel property')
1384 end if
1385
1386 ! set dimsm
1387 dimsm = product(lim_loc(:,2)-lim_loc(:,1)+1) ! memory space has local dimensions
1388
1389 ! create memory data space
1390 call h5screate_simple_f(1,dimsm,memspace,ierr)
1391 chckerr('Failed to create memory space')
1392
1393 ! write the dataset collectively.
1394 call h5dwrite_f(dset_id,hdf5_kind_64,vars(id)%p,dimsf,ierr,&
1395 &file_space_id=filespace,mem_space_id=memspace,&
1396 &xfer_prp=x_plist_id)
1397 if (ierr.ne.0) then
1398 call writo('Did you increase max_tot_mem while restarting &
1399 &Richardson or jumping to solution with different grid &
1400 &size?',alert=.true.)
1401 call lvl_ud(1)
1402 call writo('If so, must restart from lvl = 1.')
1403 call writo('Or modify the code to use "remove_previous_arrs".')
1404 call lvl_ud(-1)
1405 end if
1406 chckerr('Failed to write data data set')
1407 call h5pclose_f(x_plist_id,ierr)
1408 chckerr('Failed to close property list')
1409
1410 ! close dataspaces
1411 call h5sclose_f(filespace,ierr)
1412 chckerr('Unable to close file space')
1413 call h5sclose_f(memspace,ierr)
1414 chckerr('Unable to close memory space')
1415
1416 ! close the dataset.
1417 call h5dclose_f(dset_id,ierr)
1418 chckerr('Failed to close data set')
1419
1420 ! 2. Limit information
1421
1422 ! set dimsf
1423 dimsf = size(lim_tot) ! min. and max. limit value per dimension
1424
1425 ! create or open data set with filespace
1426 if (.not.group_exists) then ! group did not exist
1427 ! create file data space
1428 call h5screate_simple_f(1,dimsf,filespace,ierr)
1429 chckerr('Failed to create file space')
1430
1431 ! create file data set in group
1432 call h5dcreate_f(group_id,'lim',h5t_native_integer,&
1433 &filespace,dset_id,ierr)
1434 chckerr('Failed to create file data set')
1435
1436 ! close dataspace
1437 call h5sclose_f(filespace,ierr)
1438 chckerr('Unable to close file space')
1439 else ! group already exists
1440 ! open file data set
1441 call h5dopen_f(group_id,'lim',dset_id,ierr)
1442 chckerr('Failed to open file data set')
1443 end if
1444
1445 ! only leader writes
1446 if (rank.eq.0 .or. ind_print_loc) then
1447 ! write the dataset
1448 call h5dwrite_f(dset_id,h5t_native_integer,&
1449 &[vars(id)%tot_i_min,vars(id)%tot_i_max],dimsf,ierr)
1450
1451 chckerr('Failed to write limit data set')
1452 end if
1453
1454 ! close the dataset.
1455 call h5dclose_f(dset_id,ierr)
1456 chckerr('Failed to close data set')
1457
1458 ! deallocate limits
1459 deallocate(lim_tot,lim_loc)
1460
1461 ! close the group
1462 call h5gclose_f(group_id,ierr)
1463 chckerr('Failed to close group')
1464 end do
1465
1466 call lvl_ud(-1)
1467
1468 ! close the head group
1469 call h5gclose_f(head_group_id,ierr)
1470 chckerr('Failed to close group')
1471
1472 ! close the HDF5 and return lock
1473 call h5fclose_f(hdf5_i,ierr)
1474 chckerr('failed to close HDF5 file')
1475 if (n_procs.gt.1 .and. ind_print_loc) then
1476 ! return lock
1478 chckerr('')
1479 end if
1480
1481 ! close FORTRAN interfaces and HDF5 library.
1482 call h5close_f(ierr)
1483 err_msg = 'Failed to close FORTRAN HDF5 interface'
1484 chckerr(err_msg)
1485 contains
1486 ! Detects whether individual print.
1487 !> \private
1488 subroutine detect_ind_print(ind_print)
1489 ! input / output
1490 logical, intent(inout) :: ind_print ! whether an individual or collective print
1491
1492 ! initialize ind_print to true
1493 ind_print = .true.
1494
1495 ! one process ensures individual print
1496 if (n_procs.eq.1) return
1497
1498 ! loop over all elements in vars
1499 do id = 1,size(vars)
1500 do jd = 1,size(vars(id)%tot_i_min)
1501 if (vars(id)%tot_i_min(jd).ne.vars(id)%loc_i_min(jd) .or. &
1502 &vars(id)%tot_i_max(jd).ne.vars(id)%loc_i_max(jd)) then
1503 ind_print = .false.
1504 return
1505 end if
1506 end do
1507 end do
1508 end subroutine
1509 end function print_hdf5_arrs
1510
1511 !> Reads a PB3D output file in HDF5 format.
1512 !!
1513 !! This happens in a non-parallel way. By default, all variables are read,
1514 !! but an array of strings with acceptable variable names can be passed.
1515 !!
1516 !! Optionally, output can be given about the variable being read. Also, if
1517 !! \c rich_lvl is provided, <tt>_R_rich_lvl</tt> is appended to the head
1518 !! name if it is > 0.
1519 !!
1520 !! Furthermore, using \c lim_loc, a hyperslab of the variable can be read.
1521 !!
1522 !! \note If a limit of lim_loc is a negative value, the procedure just takes
1523 !! the entire range. This is necessary as sometimes the calling procuderes
1524 !! don't have, and don't need to have, knowledge of the underlying sizes,
1525 !! for example in the case of having multiple parallel jobs.
1526 !!
1527 !! \return ierr
1528 integer function read_hdf5_arr(var,PB3D_name,head_name,var_name,rich_lvl,&
1529 &disp_info,lim_loc) result(ierr)
1530 use hdf5_utilities, only: set_1d_vars
1531 use mpi_vars, only: hdf5_lock
1533#if ldebug
1535#endif
1536
1537 character(*), parameter :: rout_name = 'read_HDF5_arr_ind'
1538
1539 ! input / output
1540 type(var_1d_type), intent(inout) :: var !< variable to read
1541 character(len=*), intent(in) :: pb3d_name !< name of PB3D file
1542 character(len=*), intent(in) :: head_name !< head name of variables
1543 character(len=*), intent(in) :: var_name !< name of variable
1544 integer, intent(in), optional :: rich_lvl !< Richardson level to reconstruct
1545 logical, intent(in), optional :: disp_info !< display additional information about variable being read
1546 integer, intent(in), optional :: lim_loc(:,:) !< local limits
1547
1548 ! local variables
1549 character(len=max_str_ln) :: err_msg ! error message
1550 integer(HID_T) :: hdf5_i ! file identifier
1551 integer(HID_T) :: dset_id ! dataset identifier
1552 integer(HID_T) :: hdf5_kind_64 ! HDF5 type corresponding to dp
1553 integer(HID_T) :: group_id ! group identifier
1554 integer(HID_T) :: head_group_id ! head group identifier
1555 integer(HID_T) :: filespace ! dataspace identifier in file
1556 integer(HID_T) :: memspace ! Dataspace identifier in memory
1557 integer(HSIZE_T) :: id ! counter
1558 integer(HSIZE_T) :: data_size ! size of data set
1559 integer(HSIZE_T) :: n_dims ! nr. of dimensions
1560 integer(SIZE_T) :: name_len ! length of name of group
1561 integer :: storage_type ! type of storage used in HDF5 file
1562 integer :: nr_lnks_head ! number of links in head group
1563 integer :: max_corder ! current maximum creation order value for group
1564 integer, allocatable :: lim_tot(:,:) ! total limits
1565 integer, allocatable :: lim_loc_loc(:,:) ! local lim_loc
1566 character(len=max_str_ln) :: name_len_loc ! local copy of name_len
1567 character(len=max_str_ln) :: group_name ! name of group
1568 character(len=max_str_ln) :: head_name_loc ! local head_name
1569 logical :: disp_info_loc ! local disp_info
1570#if ldebug
1571 integer :: istat ! status
1572#endif
1573
1574 ! initialize ierr
1575 ierr = 0
1576
1577 ! set local disp_info
1578 disp_info_loc = .false.
1579 if (present(disp_info)) disp_info_loc = disp_info
1580
1581 ! set up local head_name
1582 head_name_loc = head_name
1583 if (present(rich_lvl)) then
1584 if (rich_lvl.gt.0) head_name_loc = trim(head_name_loc)//'_R_'//&
1585 &trim(i2str(rich_lvl))
1586 end if
1587
1588 ! user output
1589#if ldebug
1590 if (debug_hdf5_ops) then
1591 write(*,*,iostat=istat) 'Reading data from PB3D output "'//&
1592 &trim(pb3d_name)//'/'//trim(head_name_loc)//'/'//&
1593 &trim(var_name)//'"'
1594 end if
1595#endif
1596
1597 ! initialize FORTRAN predefined datatypes
1598 call h5open_f(ierr)
1599 chckerr('Failed to initialize HDF5')
1600
1601 ! preparation
1602 hdf5_kind_64 = h5kind_to_type(dp,h5_real_kind)
1603
1604 ! wait for file access in a non-blocking way
1605 ierr = lock_req_acc(hdf5_lock,blocking=.false.)
1606 chckerr('')
1607
1608 ! user output
1609 if (disp_info_loc) then
1610 call writo('Opening file '//trim(pb3d_name))
1611 end if
1612
1613 ! open the file
1614 call h5fopen_f(trim(pb3d_name),h5f_acc_rdonly_f,hdf5_i,ierr)
1615 chckerr('Failed to open file')
1616
1617 ! user output
1618 if (disp_info_loc) then
1619 call writo('Opening variable "'//trim(head_name_loc)//'"')
1620 end if
1621
1622 ! open head group
1623 call h5gopen_f(hdf5_i,trim(head_name_loc),head_group_id,ierr)
1624 err_msg = 'Failed to open head group "'//trim(head_name_loc)//'"'
1625 chckerr(err_msg)
1626
1627#if ldebug
1628 ! display all variables in group
1629 if (disp_info_loc) then
1630 ierr = list_all_vars_in_group(head_group_id)
1631 chckerr('')
1632 end if
1633#endif
1634
1635 ! get number of objects in group to allocate vars
1636 call h5gget_info_f(head_group_id,storage_type,nr_lnks_head,&
1637 &max_corder,ierr)
1638 chckerr('Failed to get group info')
1639
1640 ! iterate over all elements in group to save all acceptable variables
1641 do id = 1, nr_lnks_head
1642 call h5lget_name_by_idx_f(head_group_id,'.',h5_index_name_f,&
1643 &h5_iter_native_f,id-1,group_name,ierr,size=name_len)
1644 chckerr('Failed to get name')
1645
1646#if ldebug
1647 ! check length
1648 if (name_len.gt.max_str_ln) then
1649 write(name_len_loc,*) name_len
1650 ierr = 1
1651 err_msg = 'Recompile with max_str_ln > '//trim(name_len_loc)
1652 chckerr(err_msg)
1653 end if
1654#endif
1655
1656 if (trim(group_name).ne.trim(var_name)) then ! not found
1657 cycle
1658 end if
1659
1660 ! user output
1661 if (disp_info_loc) then
1662 call writo('Reading '//trim(group_name))
1663 end if
1664
1665 ! set name
1666 var%var_name = trim(group_name)
1667
1668 ! open group
1669 call h5gopen_f(head_group_id,trim(group_name),group_id,ierr)
1670
1671 chckerr('Failed to open group')
1672
1673 ! 1. limit information
1674
1675 ! open limit information dataset
1676 call h5dopen_f(group_id,'lim',dset_id,ierr)
1677 chckerr('Failed to open dataset')
1678
1679 ! get dataspace
1680 call h5dget_space_f(dset_id,filespace,ierr)
1681 chckerr('Failed to get file space')
1682
1683 ! get size to allocate the 1D variable
1684 call h5sget_simple_extent_npoints_f(filespace,data_size,ierr)
1685
1686 chckerr('Failed to get storage size')
1687 n_dims = data_size/2
1688 allocate(var%tot_i_min(n_dims))
1689 allocate(var%tot_i_max(n_dims))
1690
1691 ! close dataspace
1692 call h5sclose_f(filespace,ierr)
1693 chckerr('Failed to close file space')
1694
1695 ! allocate helper variables
1696 allocate(lim_tot(n_dims,2))
1697 allocate(lim_loc_loc(n_dims,2))
1698
1699 ! read into 1D variable
1700 call h5dread_f(dset_id,h5t_native_integer,lim_tot,[2*n_dims],&
1701 &ierr)
1702 chckerr('Failed to read dataset')
1703
1704 ! set up local limits
1705 if (present(lim_loc)) then
1706 lim_loc_loc = lim_loc
1707 where (lim_loc(:,1).lt.0) lim_loc_loc(:,1) = lim_tot(:,1)
1708 where (lim_loc(:,2).lt.0) lim_loc_loc(:,2) = lim_tot(:,2)
1709 else
1710 lim_loc_loc = lim_tot
1711 end if
1712
1713 ! copy into limits of var
1714 ! Note: tot_i_min is started from 1, the actual limits in the grid,
1715 ! eq_1, eq_2, X_1, X_2 or sol variables is set by the respective
1716 ! "init" procedure.
1717 var%tot_i_min = 1
1718 var%tot_i_max = lim_loc_loc(:,2)-lim_loc_loc(:,1)+1
1719
1720 ! close the dataset.
1721 call h5dclose_f(dset_id,ierr)
1722 chckerr('Failed to close data set')
1723
1724 ! 2. variable
1725
1726 ! set up local data size to allocate the 1D variable
1727 data_size = product(lim_loc_loc(:,2)-lim_loc_loc(:,1)+1)
1728 allocate(var%p(data_size))
1729
1730 ! open variable dataset
1731 call h5dopen_f(group_id,'var',dset_id,ierr)
1732 chckerr('Failed to open dataset')
1733
1734 ! get dataspace
1735 call h5dget_space_f(dset_id,filespace,ierr)
1736 chckerr('Failed to get file space')
1737
1738 ! set 1D filespace hyperslab selection
1739 ierr = set_1d_vars(lim_tot,lim_loc_loc,space_id=filespace)
1740 chckerr('')
1741
1742 ! create memory data space
1743 call h5screate_simple_f(1,[data_size],memspace,ierr)
1744 chckerr('Failed to create memory space')
1745
1746 ! read into 1D variable
1747 call h5dread_f(dset_id,hdf5_kind_64,var%p,[data_size],&
1748 &ierr,mem_space_id=memspace,file_space_id=filespace)
1749 chckerr('Failed to read dataset')
1750
1751 ! close dataspaces
1752 call h5sclose_f(filespace,ierr)
1753 chckerr('Failed to close file space')
1754 call h5sclose_f(memspace,ierr)
1755 chckerr('Unable to close memory space')
1756
1757 ! close the dataset.
1758 call h5dclose_f(dset_id,ierr)
1759 chckerr('Failed to close data set')
1760
1761 ! end of group
1762
1763 ! deallocate limits
1764 deallocate(lim_tot,lim_loc_loc)
1765
1766 ! close the group
1767 call h5gclose_f(group_id,ierr)
1768 chckerr('Failed to close group')
1769
1770 ! exit loop
1771 exit
1772 end do
1773
1774 ! close the head group
1775 call h5gclose_f(head_group_id,ierr)
1776 chckerr('Failed to close head group')
1777
1778 ! close the HDF5 file
1779 call h5fclose_f(hdf5_i,ierr)
1780 chckerr('failed to close HDF5 file')
1781
1782 ! return lock
1784 chckerr('')
1785
1786 ! close FORTRAN interfaces and HDF5 library.
1787 call h5close_f(ierr)
1788 err_msg = 'Failed to close FORTRAN HDF5 interface'
1789 chckerr(err_msg)
1790 end function read_hdf5_arr
1791
1792 !> \private array version
1793 subroutine reset_hdf5_item_arr(XDMF_items,ind_plot)
1794 use num_vars, only: rank
1795
1796 ! input / output
1797 type(xml_str_type), intent(inout) :: XDMF_items(:) !< XDMF items to reset
1798 logical, intent(in), optional :: ind_plot !< whether individual plot
1799
1800 ! local variables
1801 integer :: id ! counter
1802 integer :: n_items ! nr. of items
1803 logical :: ind_plot_loc ! local version of ind_plot
1804#if ldebug
1805 integer :: istat ! status
1806#endif
1807
1808 ! set up local ind_plot
1809 ind_plot_loc = .false.
1810 if (present(ind_plot)) ind_plot_loc = ind_plot
1811
1812 ! set n_items
1813 n_items = size(xdmf_items)
1814
1815 ! only group master if parallel plot or current rank if individual plot
1816 if (ind_plot_loc .or. .not.ind_plot_loc.and.rank.eq.0) then
1817 do id = 1,n_items
1818 if (.not.allocated(xdmf_items(id)%xml_str)) then
1819 call writo('Could not reset HDF5 XDMF item "'&
1820 &//trim(xdmf_items(id)%name)//'"',warning=.true.)
1821 else
1822#if ldebug
1823 if (debug_hdf5_ops) write(*,*,iostat=istat) 'reset "'//&
1824 &trim(xdmf_items(id)%name)//'"'
1825#endif
1826 xdmf_items(id)%name = ''
1827 deallocate(xdmf_items(id)%xml_str)
1828 end if
1829 end do
1830 end if
1831 end subroutine reset_hdf5_item_arr
1832 !> \private individual version
1833 subroutine reset_hdf5_item_ind(XDMF_item,ind_plot)
1834 use num_vars, only: rank
1835
1836 ! input / output
1837 type(xml_str_type), intent(inout) :: XDMF_item !< XDMF item to reset
1838 logical, intent(in), optional :: ind_plot !< whether individual plot
1839
1840 ! local variables
1841 logical :: ind_plot_loc ! local version of ind_plot
1842#if ldebug
1843 integer :: istat ! status
1844#endif
1845
1846 ! set up local ind_plot
1847 ind_plot_loc = .false.
1848 if (present(ind_plot)) ind_plot_loc = ind_plot
1849
1850 ! only group master if parallel plot or current rank if individual plot
1851 if (ind_plot_loc .or. .not.ind_plot_loc.and.rank.eq.0) then
1852 if (.not.allocated(xdmf_item%xml_str)) then
1853 call writo('Could not reset HDF5 XDMF item "'&
1854 &//trim(xdmf_item%name)//'"',warning=.true.)
1855 else
1856#if ldebug
1857 if (debug_hdf5_ops) write(*,*,iostat=istat) 'reset "'//&
1858 &trim(xdmf_item%name)//'"'
1859#endif
1860 xdmf_item%name = ''
1861 deallocate(xdmf_item%xml_str)
1862 end if
1863 end if
1864 end subroutine reset_hdf5_item_ind
1865end module hdf5_ops
Resets an HDF5 XDMF item.
Definition HDF5_ops.f90:57
Wrapper function to broadcast a single variable using MPI.
Numerical utilities related to files.
integer function, public nextunit(unit)
Search for available new unit.
Operations on HDF5 and XDMF variables.
Definition HDF5_ops.f90:27
logical, public debug_print_hdf5_arrs
set to true to debug print_HDF5_arrs
Definition HDF5_ops.f90:48
integer function, public print_hdf5_grid(grid_id, grid_name, grid_type, grid_time, grid_top, grid_geom, grid_atts, grid_grids, reset, ind_plot)
Prints an HDF5 grid.
Definition HDF5_ops.f90:886
integer function, public create_output_hdf5(hdf5_name)
Creates an HDF5 output file.
integer function, public print_hdf5_arrs(vars, pb3d_name, head_name, rich_lvl, disp_info, ind_print, remove_previous_arrs)
Prints a series of arrays, in the form of an array of pointers, to an HDF5 file.
subroutine, public print_hdf5_att(att_id, att_dataitem, att_name, att_center, att_type, reset, ind_plot)
Prints an HDF5 attribute.
Definition HDF5_ops.f90:696
integer function, public add_hdf5_item(file_info, xdmf_item, reset, ind_plot)
Add an XDMF item to a HDF5 file.
Definition HDF5_ops.f90:340
integer function, public open_hdf5_file(file_info, file_name, sym_type, descr, ind_plot, cont_plot)
Opens an HDF5 file and accompanying xmf file and returns the handles.
Definition HDF5_ops.f90:78
subroutine, public merge_hdf5_3d_data_items(merged_id, dataitem_ids, var_name, dim_tot, reset, ind_plot, cont_plot)
Joins dataitems in a vector.
Definition HDF5_ops.f90:603
logical, public debug_hdf5_ops
set to true to debug general information
Definition HDF5_ops.f90:47
subroutine, public print_hdf5_geom(geom_id, geom_type, geom_dataitems, reset, ind_plot)
Prints an HDF5 geometry.
Definition HDF5_ops.f90:805
integer function, public read_hdf5_arr(var, pb3d_name, head_name, var_name, rich_lvl, disp_info, lim_loc)
Reads a PB3D output file in HDF5 format.
integer function, public close_hdf5_file(file_info, ind_plot, cont_plot)
Closes an HDF5 file and writes the accompanying xmf file.
Definition HDF5_ops.f90:264
integer function, public print_hdf5_3d_data_item(dataitem_id, file_info, var_name, var, dim_tot, loc_dim, loc_offset, init_val, ind_plot, cont_plot)
Prints an HDF5 data item.
Definition HDF5_ops.f90:396
subroutine, public print_hdf5_top(top_id, top_type, top_n_elem, ind_plot)
Prints an HDF5 topology.
Definition HDF5_ops.f90:755
Utilities pertaining to HDF5 and XDMF.
integer function, public set_1d_vars(lim_tot, lim_loc, space_id, c_plist_id)
Sets up the chunk property list and/or the 1D hyperslabs that correspond to a local subset of lim_tot...
integer function, public list_all_vars_in_group(group_id)
Lists all variables in a HDF5 group.
Variables pertaining to HDF5 and XDMF.
Definition HDF5_vars.f90:4
character(len=max_str_ln), dimension(2), public xdmf_att_types
possible XDMF attribute types
Definition HDF5_vars.f90:28
character(len=max_str_ln), dimension(2), public xdmf_center_types
possible XDMF attribute center types
Definition HDF5_vars.f90:29
character(len=max_str_ln), dimension(3), public xdmf_grid_types
possible XDMF grid types
Definition HDF5_vars.f90:30
character(len=max_str_ln), dimension(2), public xdmf_geom_types
possible XDMF geometry types
Definition HDF5_vars.f90:26
character(len=max_str_ln), dimension(2), public xdmf_top_types
possible XDMF topology types
Definition HDF5_vars.f90:27
character(len=6), public xmf_fmt
format to write the xmf file
Definition HDF5_vars.f90:20
Numerical utilities related to giving output.
Definition messages.f90:4
subroutine, public lvl_ud(inc)
Increases/decreases lvl of output.
Definition messages.f90:254
subroutine, public writo(input_str, persistent, error, warning, alert)
Write output to file identified by output_i.
Definition messages.f90:275
Numerical utilities related to MPI.
integer function, public lock_req_acc(lock, blocking)
Request access to lock of a BL (blocking) or optionally a NB (non-blocking) type.
integer function, public lock_return_acc(lock)
Returns access to a lock.
Variables pertaining to MPI.
Definition MPI_vars.f90:4
type(lock_type), public hdf5_lock
HDF5 lock.
Definition MPI_vars.f90:76
Numerical variables used by most other modules.
Definition num_vars.f90:4
integer, parameter, public dp
double precision
Definition num_vars.f90:46
character(len=7), public script_dir
directory where to save scripts for plots
Definition num_vars.f90:154
integer, public n_procs
nr. of MPI processes
Definition num_vars.f90:69
integer, parameter, public max_str_ln
maximum length of strings
Definition num_vars.f90:50
character(len=5), public plot_dir
directory where to save plots
Definition num_vars.f90:153
character(len=max_str_ln), public pb3d_name
name of PB3D output file
Definition num_vars.f90:139
integer, public rank
MPI rank.
Definition num_vars.f90:68
character(len=4), public data_dir
directory where to save data for plots
Definition num_vars.f90:155
Operations on strings.
elemental character(len=max_str_ln) function, public i2str(k)
Convert an integer to string.
elemental character(len=max_str_ln) function, public r2str(k)
Convert a real (double) to string.
elemental character(len=max_str_ln) function, public r2strt(k)
Convert a real (double) to string.
HDF5 data type, containing the information about HDF5 files.
Definition HDF5_vars.f90:40
1D equivalent of multidimensional variables, used for internal HDF5 storage.
Definition HDF5_vars.f90:48
XML strings used in XDMF.
Definition HDF5_vars.f90:33