26 use,
intrinsic :: iso_fortran_env
55 class(mesh_t),
pointer :: mesh
56 type(atom_t),
pointer :: atom(:)
57 real(real64),
pointer :: pos(:,:)
59 type(lattice_vectors_t),
pointer :: latt
60 real(real64),
allocatable :: total_density(:)
61 real(real64),
allocatable :: free_volume(:)
62 real(real64),
allocatable :: free_vol_r3(:,:)
64 type(namespace_t) :: namespace
67 real(real64),
parameter,
public :: TOL_HIRSHFELD = 1e-9_real64
71 subroutine hirshfeld_init(this, mesh, namespace, space, latt, atom, natoms, pos, nspin)
72 type(hirshfeld_t),
intent(out) :: this
73 class(mesh_t),
target,
intent(in) :: mesh
74 type(namespace_t),
intent(in) :: namespace
75 class(space_t),
intent(in) :: space
76 type(lattice_vectors_t),
target,
intent(in):: latt
77 type(atom_t),
target,
intent(in) :: atom(:)
78 integer,
intent(in) :: natoms
79 real(real64),
target,
intent(in) :: pos(1:space%dim,1:natoms)
80 integer,
intent(in) :: nspin
82 integer :: iatom, ip, isp
83 real(real64) :: rr, atom_pos(space%dim), rmax, den
84 real(real64),
allocatable :: atom_density(:, :)
85 type(ps_t),
pointer :: ps
86 type(lattice_iterator_t) :: latt_iter
98 this%namespace = namespace
100 safe_allocate(this%total_density(1:mesh%np))
101 safe_allocate(this%free_volume(1:natoms))
102 safe_allocate(this%free_vol_r3(1:mesh%np, 1:natoms))
103 safe_allocate(atom_density(1:mesh%np, 1:nspin))
108 this%total_density(ip) =
m_zero
114 this%free_vol_r3(ip, iatom) =
m_zero
121 select type(spec=>atom(iatom)%species)
130 rmax = max(rmax, ps%density(isp)%x_threshold)
134 do icell = 1, latt_iter%n_cells
135 atom_pos = pos(:, iatom) + latt_iter%get(icell)
142 rr = norm2(mesh%x(:, ip) - atom_pos)
143 den = sum(atom_density(ip, 1:nspin))
145 this%total_density(ip) = this%total_density(ip) + den
146 this%free_vol_r3(ip, iatom) = this%free_vol_r3(ip, iatom) + den*rr**3
149 this%free_volume(iatom) =
dmf_integrate(this%mesh, this%free_vol_r3(:, iatom), reduce = .false.)
152 call this%mesh%allreduce(this%free_volume)
154 safe_deallocate_a(atom_density)
168 safe_deallocate_a(this%total_density)
169 safe_deallocate_a(this%free_volume)
170 safe_deallocate_a(this%free_vol_r3)
184 class(
space_t),
intent(in) :: space
185 integer,
intent(in) :: iatom
186 real(real64),
intent(in) :: density(:, :)
187 real(real64),
intent(out) :: charge
190 real(real64) :: dens_ip
191 real(real64),
allocatable :: atom_density(:, :), hirshfeld_density(:)
197 assert(
allocated(this%total_density))
199 safe_allocate(atom_density(1:this%mesh%np, 1:this%nspin))
200 safe_allocate(hirshfeld_density(1:this%mesh%np))
203 this%pos(:, iatom), this%mesh, this%nspin, atom_density)
206 do ip = 1, this%mesh%np
207 dens_ip = sum(atom_density(ip, 1:this%nspin))
208 if (abs(dens_ip) > tol_hirshfeld)
then
209 hirshfeld_density(ip) = sum(density(ip, 1:this%nspin))*dens_ip/this%total_density(ip)
211 hirshfeld_density(ip) = 0.0_real64
217 safe_deallocate_a(atom_density)
218 safe_deallocate_a(hirshfeld_density)
229 integer,
intent(in) :: iatom
230 real(real64),
intent(in) :: density(:, :)
231 real(real64),
intent(out) :: volume_ratio
234 real(real64),
allocatable :: hirshfeld_density(:)
241 assert(
allocated(this%total_density))
243 safe_allocate(hirshfeld_density(1:this%mesh%np))
246 do ip = 1, this%mesh%np
247 if (this%total_density(ip) > tol_hirshfeld)
then
248 hirshfeld_density(ip) = this%free_vol_r3(ip, iatom)*sum(density(ip, 1:this%nspin))/this%total_density(ip)
250 hirshfeld_density(ip) = 0.0_real64
254 volume_ratio =
dmf_integrate(this%mesh, hirshfeld_density)/this%free_volume(iatom)
256 safe_deallocate_a(hirshfeld_density)
267 integer,
intent(in) :: iatom
268 real(real64),
intent(out) :: ddensity(:)
271 real(real64),
allocatable :: atom_density(:, :)
277 safe_allocate(atom_density(1:this%mesh%np, 1:this%nspin))
280 do ip = 1, this%mesh%np
281 if (abs(this%total_density(ip)) > tol_hirshfeld)
then
282 ddensity(ip) = this%free_vol_r3(ip, iatom)/(this%total_density(ip)*this%free_volume(iatom))
288 safe_deallocate_a(atom_density)
299 class(
space_t),
intent(in) :: space
300 integer,
intent(in) :: iatom
301 integer,
intent(in) :: jatom
302 real(real64),
intent(in) :: density(:, :)
303 real(real64),
contiguous,
intent(out) :: dposition(:)
305 integer :: ip, idir, icell, jcell, isp
306 real(real64) :: atom_dens, atom_der,rri, rri2, rrj, tdensity, rij, rmax_isqu, rmax_jsqu
307 real(real64) :: pos_i(space%dim), pos_j(space%dim), rmax_i, rmax_j
308 real(real64),
allocatable :: grad(:, :), atom_density(:, :), atom_derivative(:, :)
310 type(
ps_t),
pointer :: ps_i, ps_j
311 real(real64) :: tmp, xxi(space%dim), xxj(space%dim)
313 real(real64) :: tol_spacing
317 tol_spacing = maxval(this%mesh%spacing(1:space%dim))
321 dposition(1:space%dim) =
m_zero
323 select type(spec=> this%atom(iatom)%species)
329 select type(spec=> this%atom(jatom)%species)
338 do isp = 1, this%nspin
339 rmax_i = max(rmax_i, ps_i%density(isp)%x_threshold)
340 rmax_j = max(rmax_j, ps_j%density_der(isp)%x_threshold)
343 rmax_isqu = rmax_i**2
344 rmax_jsqu = rmax_j**2
346 safe_allocate(grad(1:this%mesh%np, 1:space%dim))
347 grad(1:this%mesh%np, 1:space%dim) =
m_zero
348 safe_allocate(atom_derivative(1:this%mesh%np, 1:this%nspin))
349 safe_allocate(atom_density(1:this%mesh%np, 1:this%nspin))
352 do jcell = 1, latt_iter_j%n_cells
354 pos_j = this%pos(:, jatom) + latt_iter_j%get(jcell)
355 atom_derivative(1:this%mesh%np, 1:this%nspin) =
m_zero
357 min(this%nspin, 2), atom_derivative(1:this%mesh%np, 1:this%nspin))
361 do icell = 1, latt_iter_i%n_cells
363 pos_i = pos_j + latt_iter_i%get(icell) + (this%pos(:, iatom) - this%pos(:, jatom))
364 rij = norm2(pos_i - pos_j)
366 if (rij - (rmax_j+rmax_i) < tol_spacing)
then
371 atom_density(1:this%mesh%np, 1:this%nspin))
374 do ip = 1, this%mesh%np
375 if (this%total_density(ip)< tol_hirshfeld) cycle
377 xxi = this%mesh%x(:, ip) - pos_i
379 if (rri2 - rmax_isqu > tol_spacing) cycle
381 xxj = this%mesh%x(:, ip) - pos_j
383 if (rrj - rmax_jsqu > tol_spacing) cycle
388 tdensity = sum(density(ip, 1:this%nspin))
389 atom_dens = sum(atom_density(ip, 1:this%nspin))
390 atom_der = sum(atom_derivative(ip, 1:this%nspin))
392 if (rrj > tol_hirshfeld)
then
393 tmp = rri*rri2*atom_dens*tdensity/this%total_density(ip)**2
394 do idir = 1, space%dim
395 grad(ip, idir) = grad(ip, idir) - tmp*atom_der*xxj(idir)/rrj
400 if (iatom == jatom .and. rij < tol_hirshfeld)
then
401 grad(ip, :) = grad(ip, :) + (
m_three*rri*atom_dens + rri2*atom_der)*tdensity/this%total_density(ip)*xxi
410 dposition =
dmf_integrate(this%mesh, space%dim, grad) / this%free_volume(iatom)
412 safe_deallocate_a(atom_density)
413 safe_deallocate_a(atom_derivative)
414 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.