40 use,
intrinsic :: iso_fortran_env
95 class(space_t),
intent(in) :: space
96 type(grid_t),
intent(in) :: gr
97 type(ions_t),
intent(in) :: ions
98 type(epot_t),
intent(in) :: ep
99 type(states_elec_t),
intent(in) :: st
100 type(kpoints_t),
intent(in) :: kpoints
101 real(real64),
intent(inout) :: x(:)
102 integer,
intent(in) :: lda_u
122 type(grid_t),
intent(in) :: gr
123 type(namespace_t),
intent(in) :: namespace
124 type(ions_t),
intent(inout) :: ions
125 type(hamiltonian_elec_t),
intent(in) :: hm
126 type(states_elec_t),
intent(in) :: psi
127 type(states_elec_t),
intent(in) :: chi
128 real(real64),
intent(inout) :: ff(:, :)
129 real(real64),
intent(in) :: qq(:, :)
131 integer :: jatom, idim, jdim
132 integer,
target :: j, ist, ik, iatom
133 real(real64) :: rr, w2r, w1r, xx(ions%space%dim), dq, pdot3p, pdot3m, pdot3p2, pdot3m2, dforce1, dforce2
134 complex(real64),
allocatable :: zpsi(:, :), derpsi(:, :, :)
135 real(real64),
allocatable :: forceks1p(:), forceks1m(:), forceks1p2(:), forceks1m2(:), dforceks1(:)
143 do iatom = 1, ions%natoms
144 do jatom = 1, ions%natoms
145 if (jatom == iatom) cycle
146 xx(1:ions%space%dim) = ions%pos(:, jatom) - ions%pos(:, iatom)
147 rr = norm2(xx(1:ions%space%dim))
148 w1r = - ions%charge(iatom) * ions%charge(jatom) / rr**2
149 w2r =
m_two * ions%charge(iatom) * ions%charge(jatom) / rr**3
150 do idim = 1, ions%space%dim
151 do jdim = 1, ions%space%dim
152 ff(iatom, idim) = ff(iatom, idim) + (qq(jatom, jdim) - qq(iatom, jdim)) * w2r * (
m_one/rr**2) * xx(idim) * xx(jdim)
153 ff(iatom, idim) = ff(iatom, idim) - (qq(jatom, jdim) - qq(iatom, jdim)) * w1r * (
m_one/rr**3) * xx(idim) * xx(jdim)
154 if (jdim == idim)
then
155 ff(iatom, idim) = ff(iatom, idim) + (qq(jatom, jdim) - qq(iatom, jdim)) * w1r * (
m_one/rr)
162 safe_allocate(derpsi(1:gr%np_part, 1:ions%space%dim, 1:psi%d%dim))
166 safe_allocate(forceks1p(1:ions%space%dim))
167 safe_allocate(forceks1m(1:ions%space%dim))
168 safe_allocate(forceks1p2(1:ions%space%dim))
169 safe_allocate(forceks1m2(1:ions%space%dim))
170 safe_allocate(dforceks1(1:ions%space%dim))
171 safe_allocate(zpsi(1:gr%np_part, 1:psi%d%dim))
178 do iatom = 1, ions%natoms
179 do j = 1, ions%space%dim
180 call force1(ions%pos(j, iatom) + dq, forceks1p, pdot3p)
181 call force1(ions%pos(j, iatom) - dq, forceks1m, pdot3m)
182 call force1(ions%pos(j, iatom) + dq/
m_two, forceks1p2, pdot3p2)
183 call force1(ions%pos(j, iatom) - dq/
m_two, forceks1m2, pdot3m2)
184 dforceks1 = ((
m_four/
m_three) * (forceks1p2 - forceks1m2) - (
m_one / 6.0_real64) * (forceks1p - forceks1m)) / dq
185 dforce1 = sum(qq(iatom, :) * dforceks1(:))
186 dforce2 = ((
m_four/
m_three) * (pdot3p2 - pdot3m2) - (
m_one / 6.0_real64) * (pdot3p - pdot3m)) / dq
187 ff(iatom, j) = ff(iatom, j) -
m_two * psi%occ(ist, ik) * dforce1 +
m_two * dforce2
193 safe_deallocate_a(zpsi)
194 safe_deallocate_a(forceks1p)
195 safe_deallocate_a(forceks1m)
196 safe_deallocate_a(forceks1p2)
197 safe_deallocate_a(forceks1m2)
198 safe_deallocate_a(dforceks1)
199 safe_deallocate_a(derpsi)
206 subroutine force1(qq, res, pdot3)
207 real(real64),
intent(in) :: qq
208 real(real64),
contiguous,
intent(inout) :: res(:)
209 real(real64),
intent(inout) :: pdot3
213 complex(real64),
allocatable :: viapsi(:, :), zpsi(:, :)
215 qold = ions%pos(j, iatom)
216 ions%pos(j, iatom) = qq
217 safe_allocate(viapsi(1:gr%np_part, 1:psi%d%dim))
218 safe_allocate(zpsi(1:gr%np_part, 1:psi%d%dim))
222 ions%pos(:, iatom), iatom, gr, zpsi, viapsi)
225 do m = 1, ubound(res, 1)
226 res(m) = real(
zmf_dotp(gr, viapsi(:, 1), derpsi(:, m, 1), reduce = .false.), real64)
228 if (gr%parallel_in_domains)
call gr%allreduce(res)
231 pdot3 = real(
m_zi *
zmf_dotp(gr, zpsi(:, 1), viapsi(:, 1)), real64)
232 ions%pos(j, iatom) = qold
234 safe_deallocate_a(viapsi)
242 subroutine forces_calculate(gr, namespace, ions, hm, ext_partners, st, ks, vhxc_old, t, dt)
243 type(
grid_t),
intent(in) :: gr
245 type(
ions_t),
intent(inout) :: ions
249 type(
v_ks_t),
intent(in) :: ks
250 real(real64),
optional,
intent(in) :: vhxc_old(:,:)
251 real(real64),
optional,
intent(in) :: t
252 real(real64),
optional,
intent(in) :: dt
254 integer :: j, iatom, idir
255 real(real64) :: xx(ions%space%dim), time, global_force(ions%space%dim)
256 real(real64),
allocatable :: force(:, :), force_loc(:, :), force_nl(:, :), force_u(:, :)
257 real(real64),
allocatable :: force_nlcc(: ,:)
258 real(real64),
allocatable :: force_scf(:, :)
265 if (
present(t)) time = t
268 do iatom = 1, ions%natoms
269 ions%atom(iatom)%f_ii(1:ions%space%dim) =
m_zero
270 ions%atom(iatom)%f_vdw(1:ions%space%dim) =
m_zero
271 ions%atom(iatom)%f_loc(1:ions%space%dim) =
m_zero
272 ions%atom(iatom)%f_nl(1:ions%space%dim) =
m_zero
273 ions%atom(iatom)%f_u(1:ions%space%dim) =
m_zero
274 ions%atom(iatom)%f_fields(1:ions%space%dim) =
m_zero
275 ions%atom(iatom)%f_nlcc(1:ions%space%dim) =
m_zero
276 ions%atom(iatom)%f_scf(1:ions%space%dim) =
m_zero
277 ions%atom(iatom)%f_photons(1:ions%space%dim) =
m_zero
282 if (ks%vdw%vdw_correction == option__vdwcorrection__vdw_ts)
then
286 do iatom = 1, ions%natoms
287 ions%tot_force(:, iatom) = hm%ep%fii(1:ions%space%dim, iatom) + hm%ep%vdw_forces(1:ions%space%dim, iatom)
288 if (ks%has_photons)
then
289 ions%tot_force(:, iatom) = ions%tot_force(:, iatom) &
290 -
p_proton_charge*ions%charge(iatom)*hm%ep%photon_forces(1:ions%space%dim)
292 ions%atom(iatom)%f_ii(1:ions%space%dim) = hm%ep%fii(1:ions%space%dim, iatom)
293 ions%atom(iatom)%f_vdw(1:ions%space%dim) = hm%ep%vdw_forces(1:ions%space%dim, iatom)
294 ions%atom(iatom)%f_photons(1:ions%space%dim) = -
p_proton_charge*ions%charge(iatom)*hm%ep%photon_forces(1:ions%space%dim)
298 global_force = ions%global_force(time)
301 do iatom = 1, ions%natoms
302 ions%tot_force(:, iatom) = ions%tot_force(:, iatom) + global_force
303 ions%atom(iatom)%f_ii(1:ions%space%dim) = ions%atom(iatom)%f_ii(1:ions%space%dim) + global_force
307 safe_allocate(force(1:ions%space%dim, 1:ions%natoms))
308 safe_allocate(force_loc(1:ions%space%dim, 1:ions%natoms))
309 safe_allocate(force_nl(1:ions%space%dim, 1:ions%natoms))
310 safe_allocate(force_u(1:ions%space%dim, 1:ions%natoms))
311 safe_allocate(force_scf(1:ions%space%dim, 1:ions%natoms))
312 safe_allocate(force_nlcc(1:ions%space%dim, 1:ions%natoms))
320 if (
allocated(st%rho_core))
then
325 if (
present(vhxc_old))
then
326 call forces_from_scf(gr, ions, st%d%spin_channels, hm%vhxc, vhxc_old, force_scf)
331 if (ions%force_total_enforce)
then
340 do iatom = 1, ions%natoms
341 do idir = 1, ions%space%dim
342 ions%tot_force(idir, iatom) = ions%tot_force(idir, iatom) + force(idir, iatom) &
343 + force_scf(idir, iatom) + force_nlcc(idir, iatom)
344 ions%atom(iatom)%f_loc(idir) = force_loc(idir, iatom)
345 ions%atom(iatom)%f_nl(idir) = force_nl(idir, iatom)
346 ions%atom(iatom)%f_u(idir) = force_u(idir, iatom)
347 ions%atom(iatom)%f_nlcc(idir) = force_nlcc(idir, iatom)
348 ions%atom(iatom)%f_scf(idir) = force_scf(idir, iatom)
352 safe_deallocate_a(force)
353 safe_deallocate_a(force_loc)
354 safe_deallocate_a(force_nl)
355 safe_deallocate_a(force_u)
356 safe_deallocate_a(force_nlcc)
357 safe_deallocate_a(force_scf)
361 if (
present(t) .and.
associated(lasers))
then
362 do j = 1, lasers%no_lasers
367 do iatom = 1, ions%natoms
369 ions%tot_force(:, iatom) = ions%tot_force(:, iatom) + ions%charge(iatom)*xx(:)
370 ions%atom(iatom)%f_fields(1:ions%space%dim) = ions%atom(iatom)%f_fields(1:ions%space%dim) &
371 + ions%charge(iatom)*xx(:)
383 do iatom = 1, ions%natoms
385 ions%tot_force(:, iatom) = ions%tot_force(:, iatom) + ions%charge(iatom)*xx(:)
386 ions%atom(iatom)%f_fields(1:ions%space%dim) = ions%atom(iatom)%f_fields(1:ions%space%dim) &
387 + ions%charge(iatom)*xx(:)
391 write(
message(1),
'(a)')
'The forces are currently not supported for nondipole '
392 write(
message(2),
'(a)')
'strong-field approximation Hamiltonian approach.'
397 write(
message(1),
'(a)')
'The forces are currently not properly calculated if time-dependent'
398 write(
message(2),
'(a)')
'magnetic fields are present.'
404 if (
allocated(hm%ep%e_field))
then
405 do iatom = 1, ions%natoms
407 ions%tot_force(:, iatom) = ions%tot_force(:, iatom) + ions%charge(iatom)*hm%ep%e_field(1:ions%space%dim)
408 ions%atom(iatom)%f_fields(1:ions%space%dim) = ions%atom(iatom)%f_fields(1:ions%space%dim) &
409 + ions%charge(iatom)*hm%ep%e_field(1:ions%space%dim)
413 if (
allocated(hm%ep%b_field) .or.
allocated(hm%ep%a_static))
then
414 write(
message(1),
'(a)')
'The forces are currently not properly calculated if static'
415 write(
message(2),
'(a)')
'magnetic fields or static vector potentials are present.'
420 write(
message(1),
'(a)')
'The forces are currently not properly calculated if gauge-field'
421 write(
message(2),
'(a)')
'is applied.'
426 if(ions%space%is_periodic())
then
438 type(
ions_t),
intent(in) :: ions
439 real(real64),
intent(inout) :: force(:, :)
441 real(real64),
allocatable :: total_force(:)
446 safe_allocate(total_force(1:ions%space%dim))
448 total_force(1:ions%space%dim) = sum(force, dim=2) / ions%natoms
450 do iatom = 1, ions%natoms
451 force(1:ions%space%dim, iatom) = force(1:ions%space%dim, iatom) - total_force(1:ions%space%dim)
454 safe_deallocate_a(total_force)
461 type(
ions_t),
intent(in) :: ions
462 real(real64),
intent(inout) :: total_torque(:)
464 real(real64) :: center_of_mass(ions%space%dim), rr(3), ff(3)
469 center_of_mass = ions%center_of_mass()
474 do iatom = 1, ions%natoms
475 rr(1:ions%space%dim) = ions%pos(1:ions%space%dim, iatom) - center_of_mass
476 ff(1:ions%space%dim) = ions%tot_force(1:ions%space%dim, iatom)
487 integer,
intent(in) :: iunit
488 type(
ions_t),
intent(in) :: ions
489 character(len=*),
intent(in) :: dir
492 integer :: iatom, idir, ii, iunit2
493 real(real64) :: torque(1:3)
500 write(iunit,
'(a,10x,99(14x,a))')
' Ion', (
index2axis(idir), idir = 1, ions%space%dim)
501 do iatom = 1, ions%natoms
502 write(iunit,
'(i4,a10,10es17.8)') iatom, trim(ions%atom(iatom)%species%get_label()), &
505 write(iunit,
'(1x,100a1)') (
"-", ii = 1, 13 + ions%space%dim * 15)
506 write(iunit,
'(a14, 10es17.8)')
" Max abs force", &
508 write(iunit,
'(a14, 10es17.8)')
" Total force", &
511 if (ions%space%dim == 2 .or. ions%space%dim == 3 .and. .not. ions%space%is_periodic())
then
513 write(iunit,
'(a14, 10es17.8)')
' Total torque', &
519 iunit2 =
io_open(trim(dir)//
'/forces', namespace, action=
'write', position=
'asis')
520 write(iunit2,
'(a)') &
521 ' # Total force (x,y,z) Ion-Ion (x,y,z) VdW (x,y,z) Local (x,y,z) NL (x,y,z)' // &
522 ' Fields (x,y,z) Hubbard(x,y,z) SCF(x,y,z) NLCC(x,y,z) Phot (x,y,z)'
523 do iatom = 1, ions%natoms
524 write(iunit2,
'(i4,a10,30es17.8)') iatom, trim(ions%atom(iatom)%species%get_label()), &
546 class(
mesh_t),
intent(in) :: mesh
547 type(
ions_t),
intent(inout) :: ions
548 integer,
intent(in) :: spin_channels
549 real(real64),
intent(in) :: vxc(:,:)
550 real(real64),
contiguous,
intent(out) :: force_nlcc(:, :)
552 integer :: is, iatom, idir
553 real(real64),
allocatable :: drho(:,:)
560 safe_allocate(drho(1:mesh%np, 1:ions%space%dim))
564 do iatom = ions%atoms_dist%start, ions%atoms_dist%end
565 call species_get_nlcc_grad(ions%atom(iatom)%species, ions%space, ions%latt, ions%pos(:, iatom), mesh, drho)
567 do idir = 1, ions%space%dim
568 do is = 1, spin_channels
569 force_nlcc(idir, iatom) = force_nlcc(idir, iatom) &
570 -
dmf_dotp(mesh, drho(:,idir), vxc(1:mesh%np, is), reduce = .false.)/spin_channels
575 safe_deallocate_a(drho)
577 if (ions%atoms_dist%parallel)
call dforces_gather(ions, force_nlcc)
579 if (mesh%parallel_in_domains)
then
581 call mesh%allreduce(force_nlcc)
595 subroutine forces_from_scf(mesh, ions, spin_channels, vhxc, vhxc_old, force_scf)
596 class(
mesh_t),
intent(in) :: mesh
597 type(
ions_t),
intent(inout) :: ions
598 integer,
intent(in) :: spin_channels
599 real(real64),
intent(in) :: vhxc(:,:)
600 real(real64),
intent(in) :: vhxc_old(:,:)
601 real(real64),
contiguous,
intent(out) :: force_scf(:, :)
603 integer :: is, iatom, idir
604 real(real64),
allocatable :: dvhxc(:,:), drho(:,:,:)
610 safe_allocate(dvhxc(1:mesh%np, 1:spin_channels))
611 safe_allocate(drho(1:mesh%np, 1:spin_channels, 1:ions%space%dim))
614 do is = 1, spin_channels
615 dvhxc(1:mesh%np, is) = vhxc(1:mesh%np, is) - vhxc_old(1:mesh%np, is)
620 do iatom = ions%atoms_dist%start, ions%atoms_dist%end
621 select type(spec=>ions%atom(iatom)%species)
627 ions%pos(:, iatom), mesh, spin_channels, drho)
629 do idir = 1, ions%space%dim
630 do is = 1, spin_channels
631 force_scf(idir, iatom) = force_scf(idir, iatom) &
632 -
dmf_dotp(mesh, drho(:,is,idir), dvhxc(:,is), reduce = .false.)
639 safe_deallocate_a(dvhxc)
640 safe_deallocate_a(drho)
642 if (ions%atoms_dist%parallel)
call dforces_gather(ions, force_scf)
644 if (mesh%parallel_in_domains)
then
646 call mesh%allreduce(force_scf)
657 class(
mesh_t),
intent(in) :: mesh
658 class(
space_t),
intent(in) :: space
659 real(real64),
intent(in) :: vpsl(:)
660 real(real64),
intent(in) :: gdensity(:, :)
661 real(real64),
intent(inout) :: force(:)
664 real(real64) :: force_tmp(1:space%dim)
668 do idir = 1, space%dim
669 force_tmp(idir) =
dmf_dotp(mesh, vpsl(1:mesh%np), gdensity(:, idir), reduce = .false.)
672 if (mesh%parallel_in_domains)
call mesh%allreduce(force_tmp)
674 force(1:space%dim) = force(1:space%dim) + force_tmp(1:space%dim)
682#include "forces_inc.F90"
685#include "complex.F90"
686#include "forces_inc.F90"
subroutine force1(qq, res, pdot3)
This module implements batches of mesh functions.
This module implements common operations on batches of mesh functions.
Module implementing boundary conditions in Octopus.
This module implements a calculator for the density and defines related functions.
This module calculates the derivatives (gradients, Laplacians, etc.) of a function.
subroutine, public zderivatives_grad(der, ff, op_ff, ghost_update, set_bc, to_cartesian)
apply the gradient to a mesh function
logical function, public list_has_gauge_field(partners)
type(lasers_t) function, pointer, public list_get_lasers(partners)
subroutine, public zforces_from_potential(gr, namespace, space, ions, hm, st, force, force_loc, force_nl, force_u)
Ref: Kikuji Hirose, Tomoya Ono, Yoshitaka Fujimoto, and Shigeru Tsukamoto, First-principles calculati...
subroutine, public forces_costate_calculate(gr, namespace, ions, hm, psi, chi, ff, qq)
subroutine dtotal_force_from_potential(space, gr, ions, ep, st, kpoints, x, lda_u_level)
subroutine forces_from_scf(mesh, ions, spin_channels, vhxc, vhxc_old, force_scf)
subroutine, public zforces_born_charges(gr, namespace, space, ions, ep, st, kpoints, lr, lr2, born_charges, lda_u_level)
lr, lr2 are wfns from electric perturbation; lr is for +omega, lr2 is for -omega. for each atom,...
subroutine forces_compute_total_torque(ions, total_torque)
Computes the total torque acting on the system.
subroutine ztotal_force_from_potential(space, gr, ions, ep, st, kpoints, x, lda_u_level)
subroutine, public forces_write_info(iunit, ions, dir, namespace)
subroutine forces_set_total_to_zero(ions, force)
subroutine, public dforces_from_potential(gr, namespace, space, ions, hm, st, force, force_loc, force_nl, force_u)
Ref: Kikuji Hirose, Tomoya Ono, Yoshitaka Fujimoto, and Shigeru Tsukamoto, First-principles calculati...
subroutine, public zforces_derivative(gr, namespace, space, ions, ep, st, kpoints, lr, lr2, force_deriv, lda_u_level)
subroutine, public forces_calculate(gr, namespace, ions, hm, ext_partners, st, ks, vhxc_old, t, dt)
subroutine, public total_force_calculate(space, gr, ions, ep, st, kpoints, x, lda_u)
This computes the total forces on the ions created by the electrons (it excludes the force due to pos...
subroutine, public dforces_derivative(gr, namespace, space, ions, ep, st, kpoints, lr, lr2, force_deriv, lda_u_level)
subroutine, public dforces_born_charges(gr, namespace, space, ions, ep, st, kpoints, lr, lr2, born_charges, lda_u_level)
lr, lr2 are wfns from electric perturbation; lr is for +omega, lr2 is for -omega. for each atom,...
subroutine total_force_from_local_potential(mesh, space, vpsl, gdensity, force)
subroutine dforces_gather(ions, force)
subroutine forces_from_nlcc(mesh, ions, spin_channels, vxc, force_nlcc)
real(real64), parameter, public m_two
real(real64), parameter, public p_proton_charge
real(real64), parameter, public m_zero
real(real64), parameter, public m_four
complex(real64), parameter, public m_z0
complex(real64), parameter, public m_zi
real(real64), parameter, public m_one
real(real64), parameter, public m_three
This module implements the underlying real-space grid.
subroutine, public zhamiltonian_elec_apply_atom(hm, namespace, space, latt, species, pos, ia, mesh, psi, vpsi)
This module defines classes and functions for interaction partners.
subroutine, public io_close(iunit, grp)
integer function, public io_open(file, namespace, action, status, form, position, die, recl, grp)
logical function, public lasers_with_nondipole_field(lasers)
Check if a nondipole SFA correction should be computed for the given laser.
integer, parameter, public e_field_electric
integer, parameter, public e_field_vector_potential
subroutine, public laser_electric_field(laser, field, time, dt)
Returns a vector with the electric field, no matter whether the laser is described directly as an ele...
integer, parameter, public e_field_scalar_potential
integer pure elemental function, public laser_kind(laser)
subroutine, public laser_field(laser, field, time)
Retrieves the value of either the electric or the magnetic field. If the laser is given by a scalar p...
integer, parameter, public e_field_magnetic
This module is intended to contain "only mathematical" functions and procedures.
pure real(real64) function, dimension(1:3), public dcross_product(a, b)
This module defines various routines, operating on mesh functions.
This module defines the meshes, which are used in Octopus.
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
subroutine, public messages_fatal(no_lines, only_root_writes, namespace)
logical function mpi_grp_is_root(grp)
Is the current MPI process of grpcomm, root.
type(mpi_grp_t), public mpi_world
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.
pure logical function, public ps_has_density(ps)
subroutine, public species_get_nlcc_grad(species, space, latt, pos, mesh, rho_core_grad, gnlcc_x)
subroutine, public species_atom_density_grad(species, namespace, space, latt, pos, mesh, spin_channels, drho)
pure logical function, public states_are_real(st)
This module handles spin dimensions of the states and the k-point distribution.
brief This module defines the class unit_t which is used by the unit_systems_oct_m module.
character(len=20) pure function, public units_abbrev(this)
This module defines the unit system, used for input and output.
type(unit_system_t), public units_out
This module is intended to contain simple general-purpose utility functions and procedures.
character pure function, public index2axis(idir)
Tkatchenko-Scheffler pairwise method for van der Waals (vdW, dispersion) interactions.
subroutine, public vdw_ts_force_calculate(this, force_vdw, ions, mesh, nspin, density)
Description of the grid, containing information on derivatives, stencil, and symmetries.
Describes mesh distribution to nodes.
The states_elec_t class contains all electronic wave functions.