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 call this%mesh%allreduce(this%free_volume)
155 safe_deallocate_a(atom_density)
169 safe_deallocate_a(this%total_density)
170 safe_deallocate_a(this%free_volume)
171 safe_deallocate_a(this%free_vol_r3)
185 class(
space_t),
intent(in) :: space
186 integer,
intent(in) :: iatom
187 real(real64),
intent(in) :: density(:, :)
188 real(real64),
intent(out) :: charge
191 real(real64) :: dens_ip
192 real(real64),
allocatable :: atom_density(:, :), hirshfeld_density(:)
198 assert(
allocated(this%total_density))
200 safe_allocate(atom_density(1:this%mesh%np, 1:this%nspin))
201 safe_allocate(hirshfeld_density(1:this%mesh%np))
204 this%pos(:, iatom), this%mesh, this%nspin, atom_density)
207 do ip = 1, this%mesh%np
208 dens_ip = sum(atom_density(ip, 1:this%nspin))
209 if (abs(dens_ip) > tol_hirshfeld)
then
210 hirshfeld_density(ip) = sum(density(ip, 1:this%nspin))*dens_ip/this%total_density(ip)
212 hirshfeld_density(ip) = 0.0_real64
218 safe_deallocate_a(atom_density)
219 safe_deallocate_a(hirshfeld_density)
230 integer,
intent(in) :: iatom
231 real(real64),
intent(in) :: density(:, :)
232 real(real64),
intent(out) :: volume_ratio
235 real(real64),
allocatable :: hirshfeld_density(:)
242 assert(
allocated(this%total_density))
244 safe_allocate(hirshfeld_density(1:this%mesh%np))
247 do ip = 1, this%mesh%np
248 if (this%total_density(ip) > tol_hirshfeld)
then
249 hirshfeld_density(ip) = this%free_vol_r3(ip, iatom)*sum(density(ip, 1:this%nspin))/this%total_density(ip)
251 hirshfeld_density(ip) = 0.0_real64
255 volume_ratio =
dmf_integrate(this%mesh, hirshfeld_density)/this%free_volume(iatom)
257 safe_deallocate_a(hirshfeld_density)
268 integer,
intent(in) :: iatom
269 real(real64),
intent(out) :: ddensity(:)
272 real(real64),
allocatable :: atom_density(:, :)
278 safe_allocate(atom_density(1:this%mesh%np, 1:this%nspin))
281 do ip = 1, this%mesh%np
282 if (abs(this%total_density(ip)) > tol_hirshfeld)
then
283 ddensity(ip) = this%free_vol_r3(ip, iatom)/(this%total_density(ip)*this%free_volume(iatom))
289 safe_deallocate_a(atom_density)
300 class(
space_t),
intent(in) :: space
301 integer,
intent(in) :: iatom
302 integer,
intent(in) :: jatom
303 real(real64),
intent(in) :: density(:, :)
304 real(real64),
contiguous,
intent(out) :: dposition(:)
306 integer :: ip, idir, icell, jcell, isp
307 real(real64) :: atom_dens, atom_der,rri, rri2, rrj, tdensity, rij, rmax_isqu, rmax_jsqu
308 real(real64) :: pos_i(space%dim), pos_j(space%dim), rmax_i, rmax_j
309 real(real64),
allocatable :: grad(:, :), atom_density(:, :), atom_derivative(:, :)
311 type(
ps_t),
pointer :: ps_i, ps_j
312 real(real64) :: tmp, xxi(space%dim), xxj(space%dim)
314 real(real64) :: tol_spacing
318 tol_spacing = maxval(this%mesh%spacing(1:space%dim))
322 dposition(1:space%dim) =
m_zero
324 select type(spec=> this%atom(iatom)%species)
330 select type(spec=> this%atom(jatom)%species)
339 do isp = 1, this%nspin
340 rmax_i = max(rmax_i, ps_i%density(isp)%x_threshold)
341 rmax_j = max(rmax_j, ps_j%density_der(isp)%x_threshold)
344 rmax_isqu = rmax_i**2
345 rmax_jsqu = rmax_j**2
347 safe_allocate(grad(1:this%mesh%np, 1:space%dim))
348 grad(1:this%mesh%np, 1:space%dim) =
m_zero
349 safe_allocate(atom_derivative(1:this%mesh%np, 1:this%nspin))
350 safe_allocate(atom_density(1:this%mesh%np, 1:this%nspin))
353 do jcell = 1, latt_iter_j%n_cells
355 pos_j = this%pos(:, jatom) + latt_iter_j%get(jcell)
356 atom_derivative(1:this%mesh%np, 1:this%nspin) =
m_zero
358 min(this%nspin, 2), atom_derivative(1:this%mesh%np, 1:this%nspin))
362 do icell = 1, latt_iter_i%n_cells
364 pos_i = pos_j + latt_iter_i%get(icell) + (this%pos(:, iatom) - this%pos(:, jatom))
365 rij = norm2(pos_i - pos_j)
367 if (rij - (rmax_j+rmax_i) < tol_spacing)
then
372 atom_density(1:this%mesh%np, 1:this%nspin))
375 do ip = 1, this%mesh%np
376 if (this%total_density(ip)< tol_hirshfeld) cycle
378 xxi = this%mesh%x(ip, :) - pos_i
380 if (rri2 - rmax_isqu > tol_spacing) cycle
382 xxj = this%mesh%x(ip, :) - pos_j
384 if (rrj - rmax_jsqu > tol_spacing) cycle
389 tdensity = sum(density(ip, 1:this%nspin))
390 atom_dens = sum(atom_density(ip, 1:this%nspin))
391 atom_der = sum(atom_derivative(ip, 1:this%nspin))
393 if (rrj > tol_hirshfeld)
then
394 tmp = rri*rri2*atom_dens*tdensity/this%total_density(ip)**2
395 do idir = 1, space%dim
396 grad(ip, idir) = grad(ip, idir) - tmp*atom_der*xxj(idir)/rrj
401 if (iatom == jatom .and. rij < tol_hirshfeld)
then
402 grad(ip, :) = grad(ip, :) + (
m_three*rri*atom_dens + rri2*atom_der)*tdensity/this%total_density(ip)*xxi
411 dposition =
dmf_integrate(this%mesh, space%dim, grad) / this%free_volume(iatom)
413 safe_deallocate_a(atom_density)
414 safe_deallocate_a(atom_derivative)
415 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.
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...
A type storing the information and data about a pseudopotential.