Octopus
forces.F90
Go to the documentation of this file.
1!! Copyright (C) 2002-2006 M. Marques, A. Castro, A. Rubio, G. Bertsch
2!!
3!! This program is free software; you can redistribute it and/or modify
4!! it under the terms of the GNU General Public License as published by
5!! the Free Software Foundation; either version 2, or (at your option)
6!! any later version.
7!!
8!! This program is distributed in the hope that it will be useful,
9!! but WITHOUT ANY WARRANTY; without even the implied warranty of
10!! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11!! GNU General Public License for more details.
12!!
13!! You should have received a copy of the GNU General Public License
14!! along with this program; if not, write to the Free Software
15!! Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16!! 02110-1301, USA.
17!!
18
19#include "global.h"
20
21module forces_oct_m
22 use accel_oct_m
23 use batch_oct_m
27 use comm_oct_m
28 use debug_oct_m
31 use epot_oct_m
34 use global_oct_m
35 use grid_oct_m
38 use io_oct_m
39 use ions_oct_m
40 use, intrinsic :: iso_fortran_env
43 use lasers_oct_m
44 use lda_u_oct_m
46 use math_oct_m
47 use mesh_oct_m
50 use mpi_oct_m
53 use parser_oct_m
56 use ps_oct_m
58 use space_oct_m
66 use unit_oct_m
68 use utils_oct_m
69 use v_ks_oct_m
70 use vdw_ts_oct_m
72
73 implicit none
74
75 private
76 public :: &
87
88
89contains
90
91 ! ---------------------------------------------------------
94 subroutine total_force_calculate(space, gr, ions, ep, st, kpoints, x, lda_u)
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
103
104
105 call profiling_in("FORCES")
106 push_sub(total_force_calculate)
107
108 x = m_zero
109 if (states_are_real(st)) then
110 call dtotal_force_from_potential(space, gr, ions, ep, st, kpoints, x, lda_u)
111 else
112 call ztotal_force_from_potential(space, gr, ions, ep, st, kpoints, x, lda_u)
113 end if
115 pop_sub(total_force_calculate)
116 call profiling_out("FORCES")
117 end subroutine total_force_calculate
118
119 ! -------------------------------------------------------
120
121 subroutine forces_costate_calculate(gr, namespace, ions, hm, psi, chi, ff, qq)
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(:, :)
130
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(:)
136
137 call profiling_in("FORCES")
139
140 ! FIXME: is the next section not basically the same as the routine ion_internamespace, action_calculate?
141
142 ff = m_zero
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)
156 end if
157 end do
158 end do
159 end do
160 end do
161
162 safe_allocate(derpsi(1:gr%np_part, 1:ions%space%dim, 1:psi%d%dim))
163
164 dq = 0.001_real64
165
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))
172
173 do ist = 1, psi%nst
174 do ik = 1, psi%nik
175 derpsi = m_z0
176 call states_elec_get_state(psi, gr, ist, ik, zpsi)
177 call zderivatives_grad(gr%der, zpsi(:, 1), derpsi(:, :, 1))
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
188 end do
189 end do
190 end do
191 end do
192
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)
200
202 call profiling_out("FORCES")
203
204 contains
205
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
210
211 integer :: m
212 real(real64) :: qold
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))
219 viapsi = m_z0
220 call states_elec_get_state(psi, gr, ist, ik, zpsi)
221 call zhamiltonian_elec_apply_atom(hm, namespace, ions%space, ions%latt, ions%atom(iatom)%species, &
222 ions%pos(:, iatom), iatom, gr, zpsi, viapsi)
223
224 res(:) = m_zero
225 do m = 1, ubound(res, 1)
226 res(m) = real( zmf_dotp(gr, viapsi(:, 1), derpsi(:, m, 1), reduce = .false.), real64)
227 end do
228 if (gr%parallel_in_domains) call gr%allreduce(res)
229
230 call states_elec_get_state(chi, gr, ist, ik, zpsi)
231 pdot3 = real(m_zi * zmf_dotp(gr, zpsi(:, 1), viapsi(:, 1)), real64)
232 ions%pos(j, iatom) = qold
233
234 safe_deallocate_a(viapsi)
235 end subroutine force1
236
237 end subroutine forces_costate_calculate
238 ! ---------------------------------------------------------
239
240
241 ! ---------------------------------------------------------
242 subroutine forces_calculate(gr, namespace, ions, hm, ext_partners, st, ks, vhxc_old, t, dt)
243 type(grid_t), intent(in) :: gr
244 type(namespace_t), intent(in) :: namespace
245 type(ions_t), intent(inout) :: ions
246 type(hamiltonian_elec_t), intent(inout) :: hm
247 type(partner_list_t),intent(in) :: ext_partners
248 type(states_elec_t), intent(inout) :: st
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
253
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(:, :)
259 type(lasers_t), pointer :: lasers
260
261 call profiling_in("FORCES")
262 push_sub(forces_calculate)
263
264 time = m_zero
265 if (present(t)) time = t
266
267 !We initialize the different components of the force to zero
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
278 end do
279
280 ! the ion-ion and vdw terms are already calculated
281 ! if we use vdw TS, we need to compute it now
282 if (ks%vdw%vdw_correction == option__vdwcorrection__vdw_ts) then
283 call vdw_ts_force_calculate(ks%vdw%vdw_ts, hm%ep%vdw_forces, ions, gr, st%d%nspin, st%rho)
284 end if
285
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)
291 end if
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)
295 end do
296
297 if (present(t)) then
298 global_force = ions%global_force(time)
300 ! the ion-ion term is already calculated
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
304 end do
305 end if
306
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))
313
314 if (states_are_real(st)) then
315 call dforces_from_potential(gr, namespace, ions%space, ions, hm, st, force, force_loc, force_nl, force_u)
316 else
317 call zforces_from_potential(gr, namespace, ions%space, ions, hm, st, force, force_loc, force_nl, force_u)
318 end if
319
320 if (allocated(st%rho_core) .and. ks%theory_level /= independent_particles &
321 .and. ks%theory_level /= hartree .and. ks%theory_level /= rdmft) then
322 call forces_from_nlcc(gr, ions, st%d%spin_channels, hm%vxc, force_nlcc)
323 else
324 force_nlcc(:, :) = m_zero
325 end if
326 if (present(vhxc_old)) then
327 call forces_from_scf(gr, ions, st%d%spin_channels, hm%vhxc, vhxc_old, force_scf)
328 else
329 force_scf = m_zero
330 end if
331
332 if (ions%force_total_enforce) then
333 call forces_set_total_to_zero(ions, force)
334 call forces_set_total_to_zero(ions, force_loc)
335 call forces_set_total_to_zero(ions, force_nl)
336 call forces_set_total_to_zero(ions, force_u)
337 call forces_set_total_to_zero(ions, force_scf)
338 call forces_set_total_to_zero(ions, force_nlcc)
339 end if
340
341 do iatom = 1, ions%natoms
342 do idir = 1, ions%space%dim
343 ions%tot_force(idir, iatom) = ions%tot_force(idir, iatom) + force(idir, iatom) &
344 + force_scf(idir, iatom) + force_nlcc(idir, iatom)
345 ions%atom(iatom)%f_loc(idir) = force_loc(idir, iatom)
346 ions%atom(iatom)%f_nl(idir) = force_nl(idir, iatom)
347 ions%atom(iatom)%f_u(idir) = force_u(idir, iatom)
348 ions%atom(iatom)%f_nlcc(idir) = force_nlcc(idir, iatom)
349 ions%atom(iatom)%f_scf(idir) = force_scf(idir, iatom)
350 end do
351 end do
352
353 safe_deallocate_a(force)
354 safe_deallocate_a(force_loc)
355 safe_deallocate_a(force_nl)
356 safe_deallocate_a(force_u)
357 safe_deallocate_a(force_nlcc)
358 safe_deallocate_a(force_scf)
359
360 !\todo forces due to the magnetic fields (static and time-dependent)
361 lasers => list_get_lasers(ext_partners)
362 if (present(t) .and. associated(lasers)) then
363 do j = 1, lasers%no_lasers
364 select case (laser_kind(lasers%lasers(j)))
365 case (e_field_electric)
366 xx(:) = m_zero
367 call laser_field(lasers%lasers(j), xx, t)
368 do iatom = 1, ions%natoms
369 ! Here the proton charge is +1, since the electric field has the usual sign.
370 ions%tot_force(:, iatom) = ions%tot_force(:, iatom) + ions%charge(iatom)*xx(:)
371 ions%atom(iatom)%f_fields(1:ions%space%dim) = ions%atom(iatom)%f_fields(1:ions%space%dim) &
372 + ions%charge(iatom)*xx(:)
373 end do
374
376 ! Forces are correctly calculated only if the time-dependent
377 ! vector potential has no spatial dependence.
378 ! The full force taking account of the spatial dependence of A should be:
379 ! F = q [- dA/dt + v x \nabla x A]
380
381 !TODO: Add the gauge-field here
382 xx(:) = m_zero
383 call laser_electric_field(lasers%lasers(j), xx(:), t, dt) !convert in E field (E = -dA/ c dt)
384 do iatom = 1, ions%natoms
385 ! Also here the proton charge is +1
386 ions%tot_force(:, iatom) = ions%tot_force(:, iatom) + ions%charge(iatom)*xx(:)
387 ions%atom(iatom)%f_fields(1:ions%space%dim) = ions%atom(iatom)%f_fields(1:ions%space%dim) &
388 + ions%charge(iatom)*xx(:)
389 end do
390
391 if (lasers_with_nondipole_field(lasers)) then
392 write(message(1),'(a)') 'The forces are currently not supported for nondipole '
393 write(message(2),'(a)') 'strong-field approximation Hamiltonian approach.'
394 call messages_fatal(2, namespace=namespace)
395 end if
396
398 write(message(1),'(a)') 'The forces are currently not properly calculated if time-dependent'
399 write(message(2),'(a)') 'magnetic fields are present.'
400 call messages_fatal(2, namespace=namespace)
401 end select
402 end do
403 end if
404
405 if (allocated(hm%ep%e_field)) then
406 do iatom = 1, ions%natoms
407 ! Here the proton charge is +1, since the electric field has the usual sign.
408 ions%tot_force(:, iatom) = ions%tot_force(:, iatom) + ions%charge(iatom)*hm%ep%e_field(1:ions%space%dim)
409 ions%atom(iatom)%f_fields(1:ions%space%dim) = ions%atom(iatom)%f_fields(1:ions%space%dim) &
410 + ions%charge(iatom)*hm%ep%e_field(1:ions%space%dim)
411 end do
412 end if
413
414 if (allocated(hm%ep%b_field) .or. allocated(hm%ep%a_static)) then
415 write(message(1),'(a)') 'The forces are currently not properly calculated if static'
416 write(message(2),'(a)') 'magnetic fields or static vector potentials are present.'
417 call messages_fatal(2, namespace=namespace)
418 end if
419
420 if (list_has_gauge_field(ext_partners)) then
421 write(message(1),'(a)') 'The forces are currently not properly calculated if gauge-field'
422 write(message(2),'(a)') 'is applied.'
423 call messages_fatal(2, namespace=namespace)
424 end if
425
426 if (hm%kpoints%use_symmetries .or. st%symmetrize_density) then
427 call symmetrize_force(ions, ions%tot_force)
428 end if
429
430 ! For periodic systems, we substract the averaged force
431 if (ions%space%is_periodic()) then
432 call forces_set_total_to_zero(ions, ions%tot_force)
433 end if
434
435 pop_sub(forces_calculate)
436 call profiling_out("FORCES")
437
438 end subroutine forces_calculate
439
440 ! ----------------------------------------------------------------------
441
442 subroutine forces_set_total_to_zero(ions, force)
443 type(ions_t), intent(in) :: ions
444 real(real64), intent(inout) :: force(:, :)
445
446 real(real64), allocatable :: total_force(:)
447 integer :: iatom
448
450
451 safe_allocate(total_force(1:ions%space%dim))
452
453 total_force(1:ions%space%dim) = sum(force, dim=2) / ions%natoms
454
455 do iatom = 1, ions%natoms
456 force(1:ions%space%dim, iatom) = force(1:ions%space%dim, iatom) - total_force(1:ions%space%dim)
457 end do
458
459 safe_deallocate_a(total_force)
461 end subroutine forces_set_total_to_zero
462
463 ! ----------------------------------------------------------------------
465 subroutine forces_compute_total_torque(ions, total_torque)
466 type(ions_t), intent(in) :: ions
467 real(real64), intent(inout) :: total_torque(:)
468
469 real(real64) :: center_of_mass(ions%space%dim), rr(3), ff(3)
470 integer :: iatom
471
473
474 center_of_mass = ions%center_of_mass()
475
476 total_torque = m_zero
477 rr = m_zero
478 ff = m_zero
479 do iatom = 1, ions%natoms
480 rr(1:ions%space%dim) = ions%pos(1:ions%space%dim, iatom) - center_of_mass
481 ff(1:ions%space%dim) = ions%tot_force(1:ions%space%dim, iatom)
482 total_torque(1:3) = total_torque(1:3) + dcross_product(rr, ff)
483 end do
484
486 end subroutine forces_compute_total_torque
487
488
489 ! ----------------------------------------------------------------------
490
491 subroutine forces_write_info(iunit, ions, dir, namespace)
492 integer, intent(in) :: iunit
493 type(ions_t), intent(in) :: ions
494 character(len=*), intent(in) :: dir
495 type(namespace_t), intent(in) :: namespace
496
497 integer :: iatom, idir, ii, iunit2
498 real(real64) :: torque(1:3)
499
500 if (.not. mpi_grp_is_root(mpi_world)) return
501
502 push_sub(forces_write_info)
503
504 write(iunit,'(3a)') 'Forces on the ions [', trim(units_abbrev(units_out%force)), "]"
505 write(iunit,'(a,10x,99(14x,a))') ' Ion', (index2axis(idir), idir = 1, ions%space%dim)
506 do iatom = 1, ions%natoms
507 write(iunit,'(i4,a10,10es17.8)') iatom, trim(ions%atom(iatom)%species%get_label()), &
508 units_from_atomic(units_out%force, ions%tot_force(:, iatom))
509 end do
510 write(iunit,'(1x,100a1)') ("-", ii = 1, 13 + ions%space%dim * 15)
511 write(iunit,'(a14, 10es17.8)') " Max abs force", &
512 (units_from_atomic(units_out%force, maxval(abs(ions%tot_force(idir, 1:ions%natoms)))), idir=1, ions%space%dim)
513 write(iunit,'(a14, 10es17.8)') " Total force", &
514 (units_from_atomic(units_out%force, sum(ions%tot_force(idir, 1:ions%natoms))), idir=1, ions%space%dim)
515
516 if (ions%space%dim == 2 .or. ions%space%dim == 3 .and. .not. ions%space%is_periodic()) then
517 call forces_compute_total_torque(ions, torque)
518 write(iunit,'(a14, 10es17.8)') ' Total torque', &
519 (units_from_atomic(units_out%force*units_out%length, torque(idir)), idir = 1, 3)
520 end if
521 write(iunit,'(1x)')
522
523
524 iunit2 = io_open(trim(dir)//'/forces', namespace, action='write', position='asis')
525 write(iunit2,'(a)') &
526 ' # Total force (x,y,z) Ion-Ion (x,y,z) VdW (x,y,z) Local (x,y,z) NL (x,y,z)' // &
527 ' Fields (x,y,z) Hubbard(x,y,z) SCF(x,y,z) NLCC(x,y,z) Phot (x,y,z)'
528 do iatom = 1, ions%natoms
529 write(iunit2,'(i4,a10,30es17.8)') iatom, trim(ions%atom(iatom)%species%get_label()), &
530 (units_from_atomic(units_out%force, ions%tot_force(idir, iatom)), idir=1, ions%space%dim), &
531 (units_from_atomic(units_out%force, ions%atom(iatom)%f_ii(idir)), idir=1, ions%space%dim), &
532 (units_from_atomic(units_out%force, ions%atom(iatom)%f_vdw(idir)), idir=1, ions%space%dim), &
533 (units_from_atomic(units_out%force, ions%atom(iatom)%f_loc(idir)), idir=1, ions%space%dim), &
534 (units_from_atomic(units_out%force, ions%atom(iatom)%f_nl(idir)), idir=1, ions%space%dim), &
535 (units_from_atomic(units_out%force, ions%atom(iatom)%f_fields(idir)), idir=1, ions%space%dim), &
536 (units_from_atomic(units_out%force, ions%atom(iatom)%f_u(idir)), idir=1, ions%space%dim), &
537 (units_from_atomic(units_out%force, ions%atom(iatom)%f_scf(idir)), idir=1, ions%space%dim), &
538 (units_from_atomic(units_out%force, ions%atom(iatom)%f_nlcc(idir)), idir=1, ions%space%dim), &
539 (units_from_atomic(units_out%force, ions%atom(iatom)%f_photons(idir)), idir=1, ions%space%dim)
540 end do
541 call io_close(iunit2)
542
543 pop_sub(forces_write_info)
544
545 end subroutine forces_write_info
546
547 ! ----------------------------------------------------------------------
548 ! This routine add the contribution to the forces from the nonlinear core correction
549 ! see Eq. 9 of Kronik et al., J. Chem. Phys. 115, 4322 (2001)
550 subroutine forces_from_nlcc(mesh, ions, spin_channels, vxc, force_nlcc)
551 class(mesh_t), intent(in) :: mesh
552 type(ions_t), intent(inout) :: ions
553 integer, intent(in) :: spin_channels
554 real(real64), intent(in) :: vxc(:,:)
555 real(real64), contiguous, intent(out) :: force_nlcc(:, :)
556
557 integer :: is, iatom, idir
558 real(real64), allocatable :: drho(:,:)
559
560
561 push_sub(forces_from_nlcc)
562
563 call profiling_in("FORCES_NLCC")
564
565 safe_allocate(drho(1:mesh%np, 1:ions%space%dim))
566
567 force_nlcc = m_zero
568
569 do iatom = ions%atoms_dist%start, ions%atoms_dist%end
570 call species_get_nlcc_grad(ions%atom(iatom)%species, ions%space, ions%latt, ions%pos(:, iatom), mesh, drho)
571
572 do idir = 1, ions%space%dim
573 do is = 1, spin_channels
574 force_nlcc(idir, iatom) = force_nlcc(idir, iatom) &
575 - dmf_dotp(mesh, drho(:,idir), vxc(1:mesh%np, is), reduce = .false.)/spin_channels
576 end do
577 end do
578 end do
579
580 safe_deallocate_a(drho)
581
582 if (ions%atoms_dist%parallel) call dforces_gather(ions, force_nlcc)
583
584 if (mesh%parallel_in_domains) then
585 call profiling_in("FORCES_COMM")
586 call mesh%allreduce(force_nlcc)
587 call profiling_out("FORCES_COMM")
588 end if
589
590 call profiling_out("FORCES_NLCC")
591
592 pop_sub(forces_from_nlcc)
593 end subroutine forces_from_nlcc
594
595 ! Implementation of the term from Chan et al., Phys. Rev. B 47, 4771 (1993).
596 ! Here we make the approximation that the "atomic densities" are just the one
597 ! from the pseudopotential.
598 ! NTD : No idea if this is good or bad, but this is easy to implement
599 ! and works well in practice
600 subroutine forces_from_scf(mesh, ions, spin_channels, vhxc, vhxc_old, force_scf)
601 class(mesh_t), intent(in) :: mesh
602 type(ions_t), intent(inout) :: ions
603 integer, intent(in) :: spin_channels
604 real(real64), intent(in) :: vhxc(:,:)
605 real(real64), intent(in) :: vhxc_old(:,:)
606 real(real64), contiguous, intent(out) :: force_scf(:, :)
607
608 integer :: is, iatom, idir
609 real(real64), allocatable :: dvhxc(:,:), drho(:,:,:)
610
611 push_sub(forces_from_scf)
612
613 call profiling_in("FORCES_SCF")
614
615 safe_allocate(dvhxc(1:mesh%np, 1:spin_channels))
616 safe_allocate(drho(1:mesh%np, 1:spin_channels, 1:ions%space%dim))
617
618 !We average over spin channels
619 do is = 1, spin_channels
620 dvhxc(1:mesh%np, is) = vhxc(1:mesh%np, is) - vhxc_old(1:mesh%np, is)
621 end do
622
623 force_scf = m_zero
624
625 do iatom = ions%atoms_dist%start, ions%atoms_dist%end
626 select type(spec=>ions%atom(iatom)%species)
627 type is(pseudopotential_t)
628
629 if (ps_has_density(spec%ps)) then
630
631 call species_atom_density_grad(spec, ions%namespace, ions%space, ions%latt, &
632 ions%pos(:, iatom), mesh, spin_channels, drho)
633
634 do idir = 1, ions%space%dim
635 do is = 1, spin_channels
636 force_scf(idir, iatom) = force_scf(idir, iatom) &
637 - dmf_dotp(mesh, drho(:,is,idir), dvhxc(:,is), reduce = .false.)
638 end do
639 end do
640 end if
641 end select
642 end do
644 safe_deallocate_a(dvhxc)
645 safe_deallocate_a(drho)
646
647 if (ions%atoms_dist%parallel) call dforces_gather(ions, force_scf)
648
649 if (mesh%parallel_in_domains) then
650 call profiling_in("FORCES_COMM")
651 call mesh%allreduce(force_scf)
652 call profiling_out("FORCES_COMM")
653 end if
654
655 call profiling_out("FORCES_SCF")
656
657 pop_sub(forces_from_scf)
658 end subroutine forces_from_scf
659
660 !---------------------------------------------------------------------------
661 subroutine total_force_from_local_potential(mesh, space, vpsl, gdensity, force)
662 class(mesh_t), intent(in) :: mesh
663 class(space_t), intent(in) :: space
664 real(real64), intent(in) :: vpsl(:)
665 real(real64), intent(in) :: gdensity(:, :)
666 real(real64), intent(inout) :: force(:)
667
668 integer :: idir
669 real(real64) :: force_tmp(1:space%dim)
670
672
673 do idir = 1, space%dim
674 force_tmp(idir) = dmf_dotp(mesh, vpsl(1:mesh%np), gdensity(:, idir), reduce = .false.)
675 end do
676
677 if (mesh%parallel_in_domains) call mesh%allreduce(force_tmp)
678
679 force(1:space%dim) = force(1:space%dim) + force_tmp(1:space%dim)
680
683
684 !---------------------------------------------------------------------------
686 subroutine symmetrize_force(ions, force)
687 type(ions_t), intent(in) :: ions
688 real(real64), intent(inout) :: force(:,:)
689
690 integer :: iatom, iop, iatom_symm
691 real(real64) :: symmetrized_force(ions%space%dim), force_tmp(ions%space%dim)
692 real(real64), allocatable :: force_sym(:,:)
694 push_sub(symmetrize_force)
695
696 safe_allocate(force_sym(1:ions%space%dim,1:ions%natoms))
697 do iatom = 1, ions%natoms
698 symmetrized_force = m_zero
699 do iop = 1, ions%symm%nops
700 iatom_symm = ions%inv_map_symm_atoms(iatom, iop)
701 force_tmp = symm_op_apply_inv_cart(ions%symm%ops(iop), force(:, iatom_symm))
702 symmetrized_force = symmetrized_force + force_tmp
703 end do
704
705 do iop = 1, ions%symm%nops_nonsymmorphic
706 iatom_symm = ions%inv_map_symm_atoms(iatom, iop + ions%symm%nops)
707 force_tmp = symm_op_apply_inv_cart(ions%symm%non_symmorphic_ops(iop), force(:, iatom_symm), rotation_only=.true.)
708 symmetrized_force = symmetrized_force + force_tmp
709 end do
710
711 force_sym(:, iatom) = symmetrized_force / (ions%symm%nops + ions%symm%nops_nonsymmorphic)
712 end do
713 force = force_sym
714
715 safe_deallocate_a(force_sym)
716
717 pop_sub(symmetrize_force)
718 end subroutine symmetrize_force
719
720
721#include "undef.F90"
722#include "real.F90"
723#include "forces_inc.F90"
724
725#include "undef.F90"
726#include "complex.F90"
727#include "forces_inc.F90"
728
729end module forces_oct_m
730
731!! Local Variables:
732!! mode: f90
733!! coding: utf-8
734!! End:
subroutine force1(qq, res, pdot3)
Definition: forces.F90:300
This module implements batches of mesh functions.
Definition: batch.F90:133
This module implements common operations on batches of mesh functions.
Definition: batch_ops.F90:116
Module implementing boundary conditions in Octopus.
Definition: boundaries.F90:122
This module implements a calculator for the density and defines related functions.
Definition: density.F90:120
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...
Definition: forces.F90:1611
subroutine, public forces_costate_calculate(gr, namespace, ions, hm, psi, chi, ff, qq)
Definition: forces.F90:215
subroutine dtotal_force_from_potential(space, gr, ions, ep, st, kpoints, x, lda_u_level)
Definition: forces.F90:1148
subroutine forces_from_scf(mesh, ions, spin_channels, vhxc, vhxc_old, force_scf)
Definition: forces.F90:694
subroutine symmetrize_force(ions, force)
Given the forces on all atoms, this symmetrizes them using symmorphic and non-symmorphic operations.
Definition: forces.F90:780
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,...
Definition: forces.F90:2038
subroutine forces_compute_total_torque(ions, total_torque)
Computes the total torque acting on the system.
Definition: forces.F90:559
subroutine ztotal_force_from_potential(space, gr, ions, ep, st, kpoints, x, lda_u_level)
Definition: forces.F90:1778
subroutine, public forces_write_info(iunit, ions, dir, namespace)
Definition: forces.F90:585
subroutine forces_set_total_to_zero(ions, force)
Definition: forces.F90:536
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...
Definition: forces.F90:981
subroutine, public zforces_derivative(gr, namespace, space, ions, ep, st, kpoints, lr, lr2, force_deriv, lda_u_level)
Definition: forces.F90:1894
subroutine, public forces_calculate(gr, namespace, ions, hm, ext_partners, st, ks, vhxc_old, t, dt)
Definition: forces.F90:336
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...
Definition: forces.F90:188
subroutine, public dforces_derivative(gr, namespace, space, ions, ep, st, kpoints, lr, lr2, force_deriv, lda_u_level)
Definition: forces.F90:1264
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,...
Definition: forces.F90:1401
subroutine total_force_from_local_potential(mesh, space, vpsl, gdensity, force)
Definition: forces.F90:755
subroutine dforces_gather(ions, force)
Definition: forces.F90:882
subroutine forces_from_nlcc(mesh, ions, spin_channels, vxc, force_nlcc)
Definition: forces.F90:644
real(real64), parameter, public m_two
Definition: global.F90:189
real(real64), parameter, public p_proton_charge
Definition: global.F90:226
real(real64), parameter, public m_zero
Definition: global.F90:187
real(real64), parameter, public m_four
Definition: global.F90:191
complex(real64), parameter, public m_z0
Definition: global.F90:197
complex(real64), parameter, public m_zi
Definition: global.F90:201
real(real64), parameter, public m_one
Definition: global.F90:188
real(real64), parameter, public m_three
Definition: global.F90:190
This module implements the underlying real-space grid.
Definition: grid.F90:117
integer, parameter, public rdmft
integer, parameter, public hartree
integer, parameter, public independent_particles
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.
Definition: io.F90:114
subroutine, public io_close(iunit, grp)
Definition: io.F90:468
integer function, public io_open(file, namespace, action, status, form, position, die, recl, grp)
Definition: io.F90:395
logical function, public lasers_with_nondipole_field(lasers)
Check if a nondipole SFA correction should be computed for the given laser.
Definition: lasers.F90:735
integer, parameter, public e_field_electric
Definition: lasers.F90:176
integer, parameter, public e_field_vector_potential
Definition: lasers.F90:176
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...
Definition: lasers.F90:1187
integer, parameter, public e_field_scalar_potential
Definition: lasers.F90:176
integer pure elemental function, public laser_kind(laser)
Definition: lasers.F90:711
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...
Definition: lasers.F90:1111
integer, parameter, public e_field_magnetic
Definition: lasers.F90:176
This module is intended to contain "only mathematical" functions and procedures.
Definition: math.F90:115
pure real(real64) function, dimension(1:3), public dcross_product(a, b)
Definition: math.F90:1833
This module defines various routines, operating on mesh functions.
This module defines the meshes, which are used in Octopus.
Definition: mesh.F90:118
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
Definition: messages.F90:160
subroutine, public messages_fatal(no_lines, only_root_writes, namespace)
Definition: messages.F90:420
logical function mpi_grp_is_root(grp)
Is the current MPI process of grpcomm, root.
Definition: mpi.F90:430
type(mpi_grp_t), public mpi_world
Definition: mpi.F90:266
subroutine, public profiling_out(label)
Increment out counter and sum up difference between entry and exit time.
Definition: profiling.F90:623
subroutine, public profiling_in(label, exclude)
Increment in counter and save entry time.
Definition: profiling.F90:552
Definition: ps.F90:114
pure logical function, public ps_has_density(ps)
Definition: ps.F90:1644
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.
Definition: unit.F90:132
character(len=20) pure function, public units_abbrev(this)
Definition: unit.F90:223
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.
Definition: utils.F90:118
character pure function, public index2axis(idir)
Definition: utils.F90:202
Tkatchenko-Scheffler pairwise method for van der Waals (vdW, dispersion) interactions.
Definition: vdw_ts.F90:119
subroutine, public vdw_ts_force_calculate(this, force_vdw, ions, mesh, nspin, density)
Definition: vdw_ts.F90:427
Description of the grid, containing information on derivatives, stencil, and symmetries.
Definition: grid.F90:168
Describes mesh distribution to nodes.
Definition: mesh.F90:186
The states_elec_t class contains all electronic wave functions.
int true(void)