25#if defined(__parallel)
27 USE mpi_f08,
ONLY: mpi_allreduce, mpi_integer, mpi_bxor, mpi_allgather
29 USE mpi,
ONLY: mpi_allreduce, mpi_integer, mpi_bxor, mpi_allgather
34 openpmd_attributable_type, &
35 openpmd_dynamic_memory_view_type_1d, &
36 openpmd_dynamic_memory_view_type_3d, &
38 openpmd_particle_species_type, &
39 openpmd_record_component_type, &
40 openpmd_record_type, openpmd_type_double, openpmd_type_int
52#include "../base/base_uses.f90"
61 CHARACTER(len=*),
PARAMETER,
PRIVATE :: moduleN =
'realspace_grid_openpmd'
62 LOGICAL,
PARAMETER,
PRIVATE :: debug_this_module = .false.
63 LOGICAL,
PRIVATE :: parses_linebreaks = .false., &
66 TYPE cp_openpmd_write_buffer_1d
67 REAL(KIND=
dp),
POINTER :: buffer(:)
68 END TYPE cp_openpmd_write_buffer_1d
81 SUBROUTINE pw_get_atom_types(particles_z, res_atom_types, res_atom_counts, res_len)
82 INTEGER,
DIMENSION(:),
INTENT(IN) :: particles_z
83 INTEGER,
ALLOCATABLE,
DIMENSION(:),
INTENT(OUT) :: res_atom_types, res_atom_counts
84 INTEGER,
INTENT(OUT) :: res_len
86 INTEGER :: current_atom_number, i
87 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: particles_z_sorted
90 ALLOCATE (particles_z_sorted(
SIZE(particles_z)))
91 particles_z_sorted(:) = particles_z(:)
94 ALLOCATE (res_atom_types(min(118,
SIZE(particles_z))))
95 ALLOCATE (res_atom_counts(min(118,
SIZE(particles_z))))
96 current_atom_number = -1
98 DO i = 1,
SIZE(particles_z_sorted)
99 IF (particles_z_sorted(i) /= current_atom_number)
THEN
100 res_len = res_len + 1
101 current_atom_number = particles_z_sorted(i)
102 res_atom_types(res_len) = current_atom_number
103 res_atom_counts(res_len) = 1
105 res_atom_counts(res_len) = res_atom_counts(res_len) + 1
109 END SUBROUTINE pw_get_atom_types
121 SUBROUTINE pw_write_particle_species( &
130 INTEGER,
DIMENSION(:),
INTENT(IN) :: particles_z
131 REAL(KIND=
dp),
DIMENSION(:, :),
INTENT(IN) :: particles_r
132 REAL(KIND=
dp),
DIMENSION(:),
INTENT(IN),
OPTIONAL :: particles_zeff
133 INTEGER,
INTENT(IN) :: atom_type, atom_count
134 TYPE(cp_openpmd_per_call_value_type) :: openpmd_data
135 LOGICAL :: do_write_data
137 CHARACTER(len=1),
DIMENSION(3),
PARAMETER :: dims = [
"x",
"y",
"z"]
139 CHARACTER(len=3) :: atom_type_as_string
140 CHARACTER(len=default_string_length) :: species_name
142 INTEGER,
DIMENSION(1) :: global_extent, global_offset, &
144 TYPE(cp_openpmd_write_buffer_1d) :: charge_write_buffer
145 TYPE(cp_openpmd_write_buffer_1d),
DIMENSION(3) :: write_buffers
146 TYPE(openpmd_attributable_type) :: attr
147 TYPE(openpmd_dynamic_memory_view_type_1d) :: unresolved_charge_write_buffer
148 TYPE(openpmd_dynamic_memory_view_type_1d), &
149 DIMENSION(3) :: unresolved_write_buffers
150 TYPE(openpmd_particle_species_type) :: species
151 TYPE(openpmd_record_component_type) :: charge_component, position_component, &
152 position_offset_component
153 TYPE(openpmd_record_type) :: charge, position, position_offset
158 global_extent(1) = atom_count
159 IF (do_write_data)
THEN
161 local_extent(1) = atom_count
167 WRITE (atom_type_as_string,
'(I3)') atom_type
168 species_name = trim(openpmd_data%name_prefix)//
"-"//adjustl(atom_type_as_string)
170 species = openpmd_data%iteration%get_particle_species(trim(species_name))
172 position_offset = species%get_record(
"positionOffset")
173 position = species%get_record(
"position")
175 position_offset_component = position_offset%get_component(dims(k))
176 CALL position_offset_component%make_constant_zero(openpmd_type_int, global_extent)
177 position_component = position%get_component(dims(k))
178 CALL position_component%reset_dataset(openpmd_type_double, global_extent)
179 IF (do_write_data)
THEN
180 unresolved_write_buffers(k) = &
181 position_component%store_chunk_span_1d_double(global_offset, local_extent)
182 write_buffers(k)%buffer => unresolved_write_buffers(k)%resolve_double(deallocate=.false.)
186 IF (
PRESENT(particles_zeff))
THEN
187 charge = species%get_record(
"charge")
188 charge_component = charge%as_record_component()
189 CALL charge_component%reset_dataset(openpmd_type_double, global_extent)
190 IF (do_write_data)
THEN
191 unresolved_charge_write_buffer = charge_component%store_chunk_span_1d_double(global_offset, local_extent)
192 charge_write_buffer%buffer => unresolved_charge_write_buffer%resolve_double(deallocate=.false.)
196 IF (do_write_data)
THEN
199 write_buffers(k)%buffer = unresolved_write_buffers(k)%resolve_double(deallocate=.true.)
201 IF (
PRESENT(particles_zeff))
THEN
202 charge_write_buffer%buffer = unresolved_charge_write_buffer%resolve_double(deallocate=.true.)
205 DO i = 1,
SIZE(particles_z)
206 IF (particles_z(i) == atom_type)
THEN
208 write_buffers(k)%buffer(j) = particles_r(k, i)
210 IF (
PRESENT(particles_zeff))
THEN
211 charge_write_buffer%buffer(j) = particles_zeff(i)
217 attr = openpmd_data%iteration%as_attributable()
218 CALL attr%series_flush(
"hdf5.independent_stores = true")
219 END SUBROUTINE pw_write_particle_species
232 SUBROUTINE pw_write_particles( &
242 INTEGER,
DIMENSION(:),
INTENT(IN) :: particles_z
243 REAL(KIND=
dp),
DIMENSION(:, :),
INTENT(IN) :: particles_r
244 REAL(KIND=
dp),
DIMENSION(:),
INTENT(IN),
OPTIONAL :: particles_zeff
245 INTEGER,
DIMENSION(:),
INTENT(IN) :: atom_types, atom_counts
246 INTEGER,
INTENT(IN),
TARGET :: num_atom_types
247 TYPE(cp_openpmd_per_call_value_type) :: openpmd_data
248 TYPE(mp_comm_type),
OPTIONAL :: gid
250 INTEGER :: i, mpi_rank
251 LOGICAL :: do_write_data
253 IF (
PRESENT(gid))
THEN
254 CALL gid%get_rank(mpi_rank)
255 do_write_data = mpi_rank == 0
257 do_write_data = .true.
259 DO i = 1, num_atom_types
260 CALL pw_write_particle_species( &
270 END SUBROUTINE pw_write_particles
297 TYPE(pw_r3d_rs_type),
INTENT(IN) :: pw
299 CHARACTER(*),
INTENT(IN),
OPTIONAL :: title
300 REAL(KIND=
dp),
DIMENSION(:, :),
INTENT(IN), &
301 OPTIONAL :: particles_r
302 INTEGER,
DIMENSION(:),
INTENT(IN),
OPTIONAL :: particles_z
303 REAL(KIND=
dp),
DIMENSION(:),
INTENT(IN),
OPTIONAL :: particles_zeff
304 INTEGER,
DIMENSION(:),
OPTIONAL,
POINTER :: stride
305 LOGICAL,
INTENT(IN),
OPTIONAL :: zero_tails, silent, mpi_io
307 CHARACTER(len=*),
PARAMETER :: routineN =
'pw_to_openpmd'
308 INTEGER,
PARAMETER :: entry_len = 13, num_entries_line = 6
310 INTEGER :: count1, count2, count3, handle, i, I1, &
311 I2, I3, iat, L1, L2, L3, my_rank, &
312 my_stride(3), np, num_atom_types, &
314 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: atom_counts, atom_types
315 INTEGER,
DIMENSION(3) :: global_extent, local_extent, offset
316 LOGICAL :: be_silent, my_zero_tails, parallel_write
317 REAL(KIND=
dp),
DIMENSION(3) :: grid_spacing
318 REAL(KIND=
dp),
POINTER :: write_buffer(:, :, :)
319 TYPE(cp_openpmd_per_call_value_type) :: openpmd_data
320 TYPE(mp_comm_type) :: gid
321 TYPE(openpmd_attributable_type) :: attr
322 TYPE(openpmd_dynamic_memory_view_type_3d) :: unresolved_write_buffer
323 TYPE(openpmd_mesh_type) :: mesh
324 TYPE(openpmd_record_component_type) :: scalar_mesh
326 CALL timeset(routinen, handle)
328 my_zero_tails = .false.
330 parallel_write = .false.
331 gid = pw%pw_grid%para%group
332 IF (
PRESENT(zero_tails)) my_zero_tails = zero_tails
333 IF (
PRESENT(silent)) be_silent = silent
334 IF (
PRESENT(mpi_io)) parallel_write = mpi_io
336 IF (
PRESENT(stride))
THEN
337 IF (
SIZE(stride) /= 1 .AND.
SIZE(stride) /= 3) &
338 CALL cp_abort(__location__,
"STRIDE keyword can accept only 1 "// &
339 "(the same for X,Y,Z) or 3 values. Correct your input file.")
340 IF (
SIZE(stride) == 1)
THEN
342 my_stride(i) = stride(1)
345 my_stride = stride(1:3)
347 cpassert(my_stride(1) > 0)
348 cpassert(my_stride(2) > 0)
349 cpassert(my_stride(3) > 0)
354 cpassert(
PRESENT(particles_z) .EQV.
PRESENT(particles_r))
356 IF (
PRESENT(particles_z))
THEN
357 CALL pw_get_atom_types(particles_z,
atom_types, atom_counts, num_atom_types)
358 cpassert(
SIZE(particles_z) ==
SIZE(particles_r, dim=2))
359 np =
SIZE(particles_z)
367 grid_spacing(i) = sqrt(sum(pw%pw_grid%dh(:, i)**2))*real(my_stride(i),
dp)
370 IF (
PRESENT(particles_z))
THEN
371 IF (parallel_write)
THEN
372 CALL pw_write_particles( &
383 CALL pw_write_particles( &
396 global_extent(iat) = (pw%pw_grid%npts(iat) + my_stride(iat) - 1)/my_stride(iat)
398 offset(iat) = ((pw%pw_grid%bounds_local(1, iat) - pw%pw_grid%bounds(1, iat) + my_stride(iat) - 1)/my_stride(iat))
400 local_extent(iat) = ((pw%pw_grid%bounds_local(2, iat) + 1 - pw%pw_grid%bounds(1, iat) + my_stride(iat) - 1)/my_stride(iat))
402 local_extent = local_extent - offset
404 mesh = openpmd_data%iteration%get_mesh(trim(openpmd_data%name_prefix))
405 CALL mesh%set_axis_labels([
"x",
"y",
"z"])
406 CALL mesh%set_position([0.5_dp, 0.5_dp, 0.5_dp])
407 CALL mesh%set_grid_global_offset([0._dp, 0._dp, 0._dp])
408 CALL mesh%set_grid_spacing(grid_spacing)
409 scalar_mesh = mesh%as_record_component()
410 CALL scalar_mesh%reset_dataset(openpmd_type_double, global_extent)
417 l1 = offset(1)*my_stride(1)
418 l2 = pw%pw_grid%bounds_local(1, 2)
419 l3 = pw%pw_grid%bounds_local(1, 3)
423 u1 = (offset(1) + local_extent(1) - 1)*my_stride(1)
424 u2 = pw%pw_grid%bounds_local(2, 2)
425 u3 = pw%pw_grid%bounds_local(2, 3)
427 my_rank = pw%pw_grid%para%group%mepos
428 num_pe = pw%pw_grid%para%group%num_pe
430 IF (all(my_stride == 1))
THEN
431 CALL scalar_mesh%store_chunk(pw%array(l1:u1, l2:u2, l3:u3), offset)
433 attr = openpmd_data%iteration%as_attributable()
434 CALL attr%series_flush(
"hdf5.independent_stores = false")
437 DO i3 = l3, u3, my_stride(3)
441 unresolved_write_buffer = scalar_mesh%store_chunk_span_3d_double( &
442 [offset(1), offset(2), offset(3) + count3], &
443 [local_extent(1), local_extent(2), 1])
444 write_buffer => unresolved_write_buffer%resolve_double(deallocate=.true.)
447 cpassert(
ASSOCIATED(write_buffer))
448 cpassert(
SIZE(write_buffer, 1) == local_extent(1))
449 cpassert(
SIZE(write_buffer, 2) == local_extent(2))
450 cpassert(
SIZE(write_buffer, 3) == 1)
453 DO i2 = l2, u2, my_stride(2)
457 DO i1 = l1, u1, my_stride(1)
458 write_buffer(count1 + 1, count2 + 1, 1) = pw%array(i1, i2, i3)
469 CALL timestop(handle)
502 CHARACTER(*),
INTENT(IN),
OPTIONAL :: title
503 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN), &
504 OPTIONAL :: particles_r
505 INTEGER,
DIMENSION(:),
INTENT(IN),
OPTIONAL :: particles_z
506 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN),
OPTIONAL :: particles_zeff
507 INTEGER,
DIMENSION(:),
OPTIONAL,
POINTER :: stride
508 LOGICAL,
INTENT(IN),
OPTIONAL :: zero_tails, silent, mpi_io
513 mark_used(particles_r)
514 mark_used(particles_z)
515 mark_used(particles_zeff)
517 mark_used(zero_tails)
520 cpabort(
"CP2K compiled without the openPMD-api")
Define the atom type and its sub types.
Utility routines to open and close files. Tracking of preconnections.
subroutine, public open_file(file_name, file_status, file_form, file_action, file_position, file_pad, unit_number, debug, skip_get_unit_number, file_access)
Opens the requested file using a free unit number.
subroutine, public close_file(unit_number, file_status, keep_preconnection)
Close an open file given by its logical unit number. Optionally, keep the file and unit preconnected.
various routines to log and control the output. The idea is that decisions about where to log should ...
integer function, public cp_logger_get_default_io_unit(logger)
returns the unit nr for the ionode (-1 on all other processors) skips as well checks if the procs cal...
routines to handle the output, The idea is to remove the decision of wheter to output and what to out...
type(cp_openpmd_per_call_value_type) function, public cp_openpmd_get_value_unit_nr(key)
Defines the basic variable types.
integer, parameter, public dp
integer, parameter, public default_string_length
Interface to the message passing library MPI.
type(mp_file_descriptor_type) function, public mp_file_type_hindexed_make_chv(count, lengths, displs)
Creates an indexed MPI type for arrays of strings using bytes for spacing (hindexed type)
subroutine, public mp_file_type_free(type_descriptor)
Releases the type used for MPI I/O.
integer, parameter, public mpi_character_size
integer, parameter, public file_offset
integer, parameter, public file_amode_rdonly
subroutine, public mp_file_type_set_view_chv(fh, offset, type_descriptor)
Uses a previously created indexed MPI character type to tell the MPI processes how to partition (set_...
integer, parameter, public pw_mode_local
Generate Gaussian cube files.
subroutine, public pw_to_openpmd(pw, unit_nr, title, particles_r, particles_z, particles_zeff, stride, zero_tails, silent, mpi_io)
...
All kind of helpful little routines.