27 openpmd_attributable_type, &
28 openpmd_dynamic_memory_view_type_1d, &
29 openpmd_dynamic_memory_view_type_3d, &
31 openpmd_particle_species_type, &
32 openpmd_record_component_type, &
33 openpmd_record_type, openpmd_type_double, openpmd_type_int
45#include "../base/base_uses.f90"
54 CHARACTER(len=*),
PARAMETER,
PRIVATE :: moduleN =
'realspace_grid_openpmd'
55 LOGICAL,
PARAMETER,
PRIVATE :: debug_this_module = .false.
57 TYPE cp_openpmd_write_buffer_1d
58 REAL(KIND=
dp),
DIMENSION(:),
POINTER :: buffer => null()
59 END TYPE cp_openpmd_write_buffer_1d
72 SUBROUTINE pw_get_atom_types(particles_z, res_atom_types, res_atom_counts, res_len)
73 INTEGER,
DIMENSION(:),
INTENT(IN) :: particles_z
74 INTEGER,
ALLOCATABLE,
DIMENSION(:),
INTENT(OUT) :: res_atom_types, res_atom_counts
75 INTEGER,
INTENT(OUT) :: res_len
77 INTEGER :: current_atom_number, i
78 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: particles_z_sorted
81 ALLOCATE (particles_z_sorted(
SIZE(particles_z)))
82 particles_z_sorted(:) = particles_z(:)
85 ALLOCATE (res_atom_types(min(118,
SIZE(particles_z))))
86 ALLOCATE (res_atom_counts(min(118,
SIZE(particles_z))))
87 current_atom_number = -1
89 DO i = 1,
SIZE(particles_z_sorted)
90 IF (particles_z_sorted(i) /= current_atom_number)
THEN
92 current_atom_number = particles_z_sorted(i)
93 res_atom_types(res_len) = current_atom_number
94 res_atom_counts(res_len) = 1
96 res_atom_counts(res_len) = res_atom_counts(res_len) + 1
100 END SUBROUTINE pw_get_atom_types
112 SUBROUTINE pw_write_particle_species( &
121 INTEGER,
DIMENSION(:),
INTENT(IN) :: particles_z
122 REAL(KIND=
dp),
DIMENSION(:, :),
INTENT(IN) :: particles_r
123 REAL(KIND=
dp),
DIMENSION(:),
INTENT(IN),
OPTIONAL :: particles_zeff
124 INTEGER,
INTENT(IN) :: atom_type, atom_count
125 TYPE(cp_openpmd_per_call_value_type) :: openpmd_data
126 LOGICAL :: do_write_data
128 CHARACTER(len=1),
DIMENSION(3),
PARAMETER :: dims = [
"x",
"y",
"z"]
130 CHARACTER(len=3) :: atom_type_as_string
131 CHARACTER(len=default_string_length) :: species_name
133 INTEGER,
DIMENSION(1) :: global_extent, global_offset, &
135 TYPE(cp_openpmd_write_buffer_1d) :: charge_write_buffer
136 TYPE(cp_openpmd_write_buffer_1d),
DIMENSION(3) :: write_buffers
137 TYPE(openpmd_attributable_type) :: attr
138 TYPE(openpmd_dynamic_memory_view_type_1d) :: unresolved_charge_write_buffer
139 TYPE(openpmd_dynamic_memory_view_type_1d), &
140 DIMENSION(3) :: unresolved_write_buffers
141 TYPE(openpmd_particle_species_type) :: species
142 TYPE(openpmd_record_component_type) :: charge_component, position_component, &
143 position_offset_component
144 TYPE(openpmd_record_type) :: charge, position, position_offset
149 global_extent(1) = atom_count
150 IF (do_write_data)
THEN
152 local_extent(1) = atom_count
158 WRITE (atom_type_as_string,
'(I3)') atom_type
159 species_name = trim(openpmd_data%name_prefix)//
"-"//adjustl(atom_type_as_string)
161 CALL openpmd_data%iteration%open()
162 species = openpmd_data%iteration%get_particle_species(trim(species_name))
164 position_offset = species%get_record(
"positionOffset")
165 position = species%get_record(
"position")
167 CALL position%set_unit_dimension([1.0_dp, 0.0_dp, 0.0_dp, 0.0_dp, 0.0_dp, 0.0_dp, 0.0_dp])
169 position_offset_component = position_offset%get_component(dims(k))
170 CALL position_offset_component%make_constant_zero(openpmd_type_int, global_extent)
171 CALL position_offset_component%set_unit_SI(
a_bohr)
172 position_component = position%get_component(dims(k))
173 CALL position_component%reset_dataset(openpmd_type_double, global_extent)
174 CALL position_component%set_unit_SI(
a_bohr)
175 unresolved_write_buffers(k) = &
176 position_component%store_chunk_span_1d_double(global_offset, local_extent)
177 write_buffers(k)%buffer => unresolved_write_buffers(k)%resolve_double(deallocate=.false.)
180 IF (
PRESENT(particles_zeff))
THEN
181 charge = species%get_record(
"charge")
182 charge_component = charge%as_record_component()
184 CALL charge%set_unit_dimension([0.0_dp, 0.0_dp, 1.0_dp, 1.0_dp, 0.0_dp, 0.0_dp, 0.0_dp])
185 CALL charge_component%reset_dataset(openpmd_type_double, global_extent)
186 CALL charge_component%set_unit_SI(
e_charge)
187 unresolved_charge_write_buffer = charge_component%store_chunk_span_1d_double(global_offset, local_extent)
188 charge_write_buffer%buffer => unresolved_charge_write_buffer%resolve_double(deallocate=.false.)
193 write_buffers(k)%buffer = unresolved_write_buffers(k)%resolve_double(deallocate=.true.)
195 IF (
PRESENT(particles_zeff))
THEN
196 charge_write_buffer%buffer = unresolved_charge_write_buffer%resolve_double(deallocate=.true.)
198 IF (do_write_data)
THEN
200 DO i = 1,
SIZE(particles_z)
201 IF (particles_z(i) == atom_type)
THEN
203 write_buffers(k)%buffer(j) = particles_r(k, i)
205 IF (
PRESENT(particles_zeff))
THEN
206 charge_write_buffer%buffer(j) = particles_zeff(i)
212 attr = openpmd_data%iteration%as_attributable()
213 CALL attr%series_flush(
"hdf5.independent_stores = true")
214 END SUBROUTINE pw_write_particle_species
227 SUBROUTINE pw_write_particles( &
237 INTEGER,
DIMENSION(:),
INTENT(IN) :: particles_z
238 REAL(KIND=
dp),
DIMENSION(:, :),
INTENT(IN) :: particles_r
239 REAL(KIND=
dp),
DIMENSION(:),
INTENT(IN),
OPTIONAL :: particles_zeff
240 INTEGER,
DIMENSION(:),
INTENT(IN) :: atom_types, atom_counts
241 INTEGER,
INTENT(IN),
TARGET :: num_atom_types
242 TYPE(cp_openpmd_per_call_value_type) :: openpmd_data
243 TYPE(mp_comm_type),
OPTIONAL :: gid
245 INTEGER :: i, mpi_rank
246 LOGICAL :: do_write_data
248 IF (
PRESENT(gid))
THEN
249 CALL gid%get_rank(mpi_rank)
250 do_write_data = mpi_rank == 0
252 do_write_data = .true.
254 DO i = 1, num_atom_types
255 CALL pw_write_particle_species( &
265 END SUBROUTINE pw_write_particles
292 TYPE(pw_r3d_rs_type),
INTENT(IN) :: pw
294 CHARACTER(*),
INTENT(IN),
OPTIONAL :: title
295 REAL(KIND=
dp),
DIMENSION(:, :),
INTENT(IN), &
296 OPTIONAL :: particles_r
297 INTEGER,
DIMENSION(:),
INTENT(IN),
OPTIONAL :: particles_z
298 REAL(KIND=
dp),
DIMENSION(:),
INTENT(IN),
OPTIONAL :: particles_zeff
299 INTEGER,
DIMENSION(:),
OPTIONAL,
POINTER :: stride
300 LOGICAL,
INTENT(IN),
OPTIONAL :: zero_tails, silent, mpi_io
302 CHARACTER(len=*),
PARAMETER :: routineN =
'pw_to_openpmd'
304 CHARACTER(LEN=default_string_length) :: my_title
305 INTEGER :: count1, count2, count3, handle, i, I1, &
306 I2, I3, iat, L1, L2, L3, my_rank, &
307 my_stride(3), np, num_atom_types, &
309 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: atom_counts, atom_types
310 INTEGER,
DIMENSION(3) :: global_extent, local_extent, offset
311 LOGICAL :: be_silent, my_zero_tails, parallel_write
312 REAL(KIND=
dp),
DIMENSION(3) :: grid_spacing
313 REAL(KIND=
dp),
POINTER :: write_buffer(:, :, :)
314 TYPE(cp_openpmd_per_call_value_type) :: openpmd_data
315 TYPE(mp_comm_type) :: gid
316 TYPE(openpmd_attributable_type) :: attr
317 TYPE(openpmd_dynamic_memory_view_type_3d) :: unresolved_write_buffer
318 TYPE(openpmd_mesh_type) :: mesh
319 TYPE(openpmd_record_component_type) :: scalar_mesh
321 CALL timeset(routinen, handle)
323 my_zero_tails = .false.
325 parallel_write = .false.
326 gid = pw%pw_grid%para%group
327 IF (
PRESENT(title)) my_title = trim(title)
328 IF (
PRESENT(zero_tails)) my_zero_tails = zero_tails
329 IF (
PRESENT(silent)) be_silent = silent
330 IF (
PRESENT(mpi_io)) parallel_write = mpi_io
332 IF (
PRESENT(stride))
THEN
333 IF (
SIZE(stride) /= 1 .AND.
SIZE(stride) /= 3)
THEN
334 CALL cp_abort(__location__,
"STRIDE keyword can accept only 1 "// &
335 "(the same for X,Y,Z) or 3 values. Correct your input file.")
337 IF (
SIZE(stride) == 1)
THEN
339 my_stride(i) = stride(1)
342 my_stride = stride(1:3)
344 cpassert(my_stride(1) > 0)
345 cpassert(my_stride(2) > 0)
346 cpassert(my_stride(3) > 0)
351 cpassert(
PRESENT(particles_z) .EQV.
PRESENT(particles_r))
353 IF (
PRESENT(particles_z))
THEN
354 CALL pw_get_atom_types(particles_z,
atom_types, atom_counts, num_atom_types)
355 cpassert(
SIZE(particles_z) ==
SIZE(particles_r, dim=2))
356 np =
SIZE(particles_z)
364 grid_spacing(i) = sqrt(sum(pw%pw_grid%dh(:, i)**2))*real(my_stride(i),
dp)
367 IF (
PRESENT(particles_z))
THEN
368 IF (parallel_write)
THEN
369 CALL pw_write_particles( &
380 CALL pw_write_particles( &
393 global_extent(iat) = (pw%pw_grid%npts(iat) + my_stride(iat) - 1)/my_stride(iat)
395 offset(iat) = ((pw%pw_grid%bounds_local(1, iat) - pw%pw_grid%bounds(1, iat) + my_stride(iat) - 1)/my_stride(iat))
398 local_extent(iat) = ((pw%pw_grid%bounds_local(2, iat) + 1 - pw%pw_grid%bounds(1, iat) + my_stride(iat) - 1)/my_stride(iat))
400 local_extent = local_extent - offset
402 mesh = openpmd_data%iteration%get_mesh(trim(openpmd_data%name_prefix))
403 CALL mesh%set_axis_labels([
"x",
"y",
"z"])
404 CALL mesh%set_position([0.5_dp, 0.5_dp, 0.5_dp])
405 CALL mesh%set_grid_global_offset([ &
406 pw%pw_grid%bounds(1, 1)*grid_spacing(1), &
407 pw%pw_grid%bounds(1, 2)*grid_spacing(2), &
408 pw%pw_grid%bounds(1, 3)*grid_spacing(3)])
409 CALL mesh%set_grid_spacing(grid_spacing)
410 CALL mesh%set_grid_unit_SI(
a_bohr)
411 CALL mesh%set_unit_dimension(openpmd_data%unit_dimension)
412 scalar_mesh = mesh%as_record_component()
413 CALL scalar_mesh%set_unit_SI(openpmd_data%unit_si)
414 CALL scalar_mesh%reset_dataset(openpmd_type_double, global_extent)
421 l1 = pw%pw_grid%bounds(1, 1) + offset(1)*my_stride(1)
422 l2 = pw%pw_grid%bounds_local(1, 2)
423 l3 = pw%pw_grid%bounds_local(1, 3)
426 u1 = pw%pw_grid%bounds(1, 1) + (offset(1) + local_extent(1) - 1)*my_stride(1)
427 u2 = pw%pw_grid%bounds_local(2, 2)
428 u3 = pw%pw_grid%bounds_local(2, 3)
430 my_rank = pw%pw_grid%para%group%mepos
431 num_pe = pw%pw_grid%para%group%num_pe
433 IF (all(my_stride == 1))
THEN
434 CALL scalar_mesh%store_chunk(pw%array(l1:u1, l2:u2, l3:u3), offset)
436 attr = openpmd_data%iteration%as_attributable()
437 CALL attr%series_flush(
"hdf5.independent_stores = false")
440 DO i3 = l3, u3, my_stride(3)
444 unresolved_write_buffer = scalar_mesh%store_chunk_span_3d_double( &
445 [offset(1), offset(2), offset(3) + count3], &
446 [local_extent(1), local_extent(2), 1])
447 write_buffer => unresolved_write_buffer%resolve_double(deallocate=.true.)
450 cpassert(
ASSOCIATED(write_buffer))
451 cpassert(
SIZE(write_buffer, 1) == local_extent(1))
452 cpassert(
SIZE(write_buffer, 2) == local_extent(2))
453 cpassert(
SIZE(write_buffer, 3) == 1)
456 DO i2 = l2, u2, my_stride(2)
460 DO i1 = l1, u1, my_stride(1)
461 write_buffer(count1 + 1, count2 + 1, 1) = pw%array(i1, i2, i3)
472 CALL timestop(handle)
505 CHARACTER(*),
INTENT(IN),
OPTIONAL :: title
506 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN), &
507 OPTIONAL :: particles_r
508 INTEGER,
DIMENSION(:),
INTENT(IN),
OPTIONAL :: particles_z
509 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN),
OPTIONAL :: particles_zeff
510 INTEGER,
DIMENSION(:),
OPTIONAL,
POINTER :: stride
511 LOGICAL,
INTENT(IN),
OPTIONAL :: zero_tails, silent, mpi_io
516 mark_used(particles_r)
517 mark_used(particles_z)
518 mark_used(particles_zeff)
520 mark_used(zero_tails)
523 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_...
Definition of physical constants:
real(kind=dp), parameter, public a_bohr
real(kind=dp), parameter, public e_charge
real(kind=dp), parameter, public seconds
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.