27 use,
intrinsic :: iso_fortran_env
56 class(mesh_t),
pointer :: mesh
57 type(atom_t),
pointer :: atom(:)
58 real(real64),
pointer :: pos(:,:)
60 type(lattice_vectors_t),
pointer :: latt
61 real(real64),
allocatable :: total_density(:)
62 real(real64),
allocatable :: free_volume(:)
63 real(real64),
allocatable :: free_vol_r3(:,:)
65 type(namespace_t) :: namespace
68 real(real64),
parameter,
public :: TOL_HIRSHFELD = 1e-9_real64
72 subroutine hirshfeld_init(this, mesh, namespace, space, latt, atom, natoms, pos, nspin)
73 type(hirshfeld_t),
intent(out) :: this
74 class(mesh_t),
target,
intent(in) :: mesh
75 type(namespace_t),
intent(in) :: namespace
76 class(space_t),
intent(in) :: space
77 type(lattice_vectors_t),
target,
intent(in):: latt
78 type(atom_t),
target,
intent(in) :: atom(:)
79 integer,
intent(in) :: natoms
80 real(real64),
target,
intent(in) :: pos(1:space%dim,1:natoms)
81 integer,
intent(in) :: nspin
83 integer :: iatom, ip, isp
84 real(real64) :: rr, atom_pos(space%dim), rmax, den
85 real(real64),
allocatable :: atom_density(:, :)
86 type(ps_t),
pointer :: ps
87 type(lattice_iterator_t) :: latt_iter
99 this%namespace = namespace
101 safe_allocate(this%total_density(1:mesh%np))
102 safe_allocate(this%free_volume(1:natoms))
103 safe_allocate(this%free_vol_r3(1:mesh%np, 1:natoms))
104 safe_allocate(atom_density(1:mesh%np, 1:nspin))
109 this%total_density(ip) =
m_zero
115 this%free_vol_r3(ip, iatom) =
m_zero
122 select type(spec=>atom(iatom)%species)
131 rmax = max(rmax, ps%density(isp)%x_threshold)
135 do icell = 1, latt_iter%n_cells
136 atom_pos = pos(:, iatom) + latt_iter%get(icell)
143 rr = norm2(mesh%x(ip, :) - atom_pos)
144 den = sum(atom_density(ip, 1:nspin))
146 this%total_density(ip) = this%total_density(ip) + den
147 this%free_vol_r3(ip, iatom) = this%free_vol_r3(ip, iatom) + den*rr**3
150 this%free_volume(iatom) =
dmf_integrate(this%mesh, this%free_vol_r3(:, iatom), reduce = .false.)
153 if (this%mesh%parallel_in_domains)
then
154 call this%mesh%allreduce(this%free_volume)
157 safe_deallocate_a(atom_density)
171 safe_deallocate_a(this%total_density)
172 safe_deallocate_a(this%free_volume)
173 safe_deallocate_a(this%free_vol_r3)
187 class(
space_t),
intent(in) :: space
188 integer,
intent(in) :: iatom
189 real(real64),
intent(in) :: density(:, :)
190 real(real64),
intent(out) :: charge
193 real(real64) :: dens_ip
194 real(real64),
allocatable :: atom_density(:, :), hirshfeld_density(:)
200 assert(
allocated(this%total_density))
202 safe_allocate(atom_density(1:this%mesh%np, 1:this%nspin))
203 safe_allocate(hirshfeld_density(1:this%mesh%np))
206 this%pos(:, iatom), this%mesh, this%nspin, atom_density)
209 do ip = 1, this%mesh%np
210 dens_ip = sum(atom_density(ip, 1:this%nspin))
211 if (abs(dens_ip) > tol_hirshfeld)
then
212 hirshfeld_density(ip) = sum(density(ip, 1:this%nspin))*dens_ip/this%total_density(ip)
214 hirshfeld_density(ip) = 0.0_real64
220 safe_deallocate_a(atom_density)
221 safe_deallocate_a(hirshfeld_density)
232 integer,
intent(in) :: iatom
233 real(real64),
intent(in) :: density(:, :)
234 real(real64),
intent(out) :: volume_ratio
237 real(real64),
allocatable :: hirshfeld_density(:)
244 assert(
allocated(this%total_density))
246 safe_allocate(hirshfeld_density(1:this%mesh%np))
249 do ip = 1, this%mesh%np
250 if (this%total_density(ip) > tol_hirshfeld)
then
251 hirshfeld_density(ip) = this%free_vol_r3(ip, iatom)*sum(density(ip, 1:this%nspin))/this%total_density(ip)
253 hirshfeld_density(ip) = 0.0_real64
257 volume_ratio =
dmf_integrate(this%mesh, hirshfeld_density)/this%free_volume(iatom)
259 safe_deallocate_a(hirshfeld_density)
270 integer,
intent(in) :: iatom
271 real(real64),
intent(out) :: ddensity(:)
274 real(real64),
allocatable :: atom_density(:, :)
280 safe_allocate(atom_density(1:this%mesh%np, 1:this%nspin))
283 do ip = 1, this%mesh%np
284 if (abs(this%total_density(ip)) > tol_hirshfeld)
then
285 ddensity(ip) = this%free_vol_r3(ip, iatom)/(this%total_density(ip)*this%free_volume(iatom))
291 safe_deallocate_a(atom_density)
302 class(
space_t),
intent(in) :: space
303 integer,
intent(in) :: iatom
304 integer,
intent(in) :: jatom
305 real(real64),
intent(in) :: density(:, :)
306 real(real64),
contiguous,
intent(out) :: dposition(:)
308 integer :: ip, idir, icell, jcell, isp
309 real(real64) :: atom_dens, atom_der,rri, rri2, rrj, tdensity, rij, rmax_isqu, rmax_jsqu
310 real(real64) :: pos_i(space%dim), pos_j(space%dim), rmax_i, rmax_j
311 real(real64),
allocatable :: grad(:, :), atom_density(:, :), atom_derivative(:, :)
313 type(
ps_t),
pointer :: ps_i, ps_j
314 real(real64) :: tmp, xxi(space%dim), xxj(space%dim)
316 real(real64) :: tol_spacing
320 tol_spacing = maxval(this%mesh%spacing(1:space%dim))
324 dposition(1:space%dim) =
m_zero
326 select type(spec=> this%atom(iatom)%species)
332 select type(spec=> this%atom(jatom)%species)
341 do isp = 1, this%nspin
342 rmax_i = max(rmax_i, ps_i%density(isp)%x_threshold)
343 rmax_j = max(rmax_j, ps_j%density_der(isp)%x_threshold)
346 rmax_isqu = rmax_i**2
347 rmax_jsqu = rmax_j**2
349 safe_allocate(grad(1:this%mesh%np, 1:space%dim))
350 grad(1:this%mesh%np, 1:space%dim) =
m_zero
351 safe_allocate(atom_derivative(1:this%mesh%np, 1:this%nspin))
352 safe_allocate(atom_density(1:this%mesh%np, 1:this%nspin))
355 do jcell = 1, latt_iter_j%n_cells
357 pos_j = this%pos(:, jatom) + latt_iter_j%get(jcell)
358 atom_derivative(1:this%mesh%np, 1:this%nspin) =
m_zero
360 min(this%nspin, 2), atom_derivative(1:this%mesh%np, 1:this%nspin))
363 do icell = 1, latt_iter_i%n_cells
365 pos_i = pos_j + latt_iter_i%get(icell) + (this%pos(:, iatom) - this%pos(:, jatom))
366 rij = norm2(pos_i - pos_j)
368 if (rij - (rmax_j+rmax_i) < tol_spacing)
then
373 atom_density(1:this%mesh%np, 1:this%nspin))
376 do ip = 1, this%mesh%np
377 if (this%total_density(ip)< tol_hirshfeld) cycle
379 xxi = this%mesh%x(ip, :) - pos_i
381 if (rri2 - rmax_isqu > tol_spacing) cycle
383 xxj = this%mesh%x(ip, :) - pos_j
385 if (rrj - rmax_jsqu > tol_spacing) cycle
390 tdensity = sum(density(ip, 1:this%nspin))
391 atom_dens = sum(atom_density(ip, 1:this%nspin))
392 atom_der = sum(atom_derivative(ip, 1:this%nspin))
394 if (rrj > tol_hirshfeld)
then
395 tmp = rri*rri2*atom_dens*tdensity/this%total_density(ip)**2
396 do idir = 1, space%dim
397 grad(ip, idir) = grad(ip, idir) - tmp*atom_der*xxj(idir)/rrj
402 if (iatom == jatom .and. rij < tol_hirshfeld)
then
403 grad(ip, :) = grad(ip, :) + (
m_three*rri*atom_dens + rri2*atom_der)*tdensity/this%total_density(ip)*xxi
412 do idir = 1, space%dim
413 dposition(idir) =
dmf_integrate(this%mesh, grad(1:this%mesh%np, idir), reduce = .false.) &
414 /this%free_volume(iatom)
417 if (this%mesh%parallel_in_domains)
then
418 call this%mesh%allreduce(dposition, dim = space%dim)
421 safe_deallocate_a(atom_density)
422 safe_deallocate_a(atom_derivative)
423 safe_deallocate_a(grad)
double sqrt(double __x) __attribute__((__nothrow__
This module calculates the derivatives (gradients, Laplacians, etc.) of a function.
real(real64), parameter, public m_zero
real(real64), parameter, public m_three
subroutine, public hirshfeld_init(this, mesh, namespace, space, latt, atom, natoms, pos, nspin)
subroutine, public hirshfeld_charge(this, space, iatom, density, charge)
subroutine, public hirshfeld_end(this)
subroutine, public hirshfeld_density_derivative(this, iatom, ddensity)
subroutine, public hirshfeld_position_derivative(this, space, iatom, jatom, density, dposition)
subroutine, public hirshfeld_volume_ratio(this, iatom, density, volume_ratio)
This module defines various routines, operating on mesh functions.
real(real64) function, public dmf_integrate(mesh, ff, mask, reduce)
Integrate a function on the mesh.
This module defines the meshes, which are used in Octopus.
subroutine, public profiling_out(label)
Increment out counter and sum up difference between entry and exit time.
subroutine, public profiling_in(label, exclude)
Increment in counter and save entry time.
subroutine, public species_atom_density_np(species, namespace, pos, mesh, spin_channels, rho)
subroutine, public species_atom_density_derivative_np(species, namespace, pos, mesh, spin_channels, drho)
subroutine, public species_atom_density(species, namespace, space, latt, pos, mesh, spin_channels, rho)
The following class implements a lattice iterator. It allows one to loop over all cells that are with...