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)) then
321 call forces_from_nlcc(gr, ions, st%d%spin_channels, hm%vxc, force_nlcc)
322 else
323 force_nlcc(:, :) = m_zero
324 end if
325 if (present(vhxc_old)) then
326 call forces_from_scf(gr, ions, st%d%spin_channels, hm%vhxc, vhxc_old, force_scf)
327 else
328 force_scf = m_zero
329 end if
330
331 if (ions%force_total_enforce) then
332 call forces_set_total_to_zero(ions, force)
333 call forces_set_total_to_zero(ions, force_loc)
334 call forces_set_total_to_zero(ions, force_nl)
335 call forces_set_total_to_zero(ions, force_u)
336 call forces_set_total_to_zero(ions, force_scf)
337 call forces_set_total_to_zero(ions, force_nlcc)
338 end if
339
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)
349 end do
350 end do
351
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)
358
359 !\todo forces due to the magnetic fields (static and time-dependent)
360 lasers => list_get_lasers(ext_partners)
361 if (present(t) .and. associated(lasers)) then
362 do j = 1, lasers%no_lasers
363 select case (laser_kind(lasers%lasers(j)))
364 case (e_field_electric)
365 xx(:) = m_zero
366 call laser_field(lasers%lasers(j), xx, t)
367 do iatom = 1, ions%natoms
368 ! Here the proton charge is +1, since the electric field has the usual sign.
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(:)
372 end do
373
375 ! Forces are correctly calculated only if the time-dependent
376 ! vector potential has no spatial dependence.
377 ! The full force taking account of the spatial dependence of A should be:
378 ! F = q [- dA/dt + v x \nabla x A]
379
380 !TODO: Add the gauge-field here
381 xx(:) = m_zero
382 call laser_electric_field(lasers%lasers(j), xx(:), t, dt) !convert in E field (E = -dA/ c dt)
383 do iatom = 1, ions%natoms
384 ! Also here the proton charge is +1
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(:)
388 end do
389
390 if (lasers_with_nondipole_field(lasers)) then
391 write(message(1),'(a)') 'The forces are currently not supported for nondipole '
392 write(message(2),'(a)') 'strong-field approximation Hamiltonian approach.'
393 call messages_fatal(2, namespace=namespace)
394 end if
395
397 write(message(1),'(a)') 'The forces are currently not properly calculated if time-dependent'
398 write(message(2),'(a)') 'magnetic fields are present.'
399 call messages_fatal(2, namespace=namespace)
400 end select
401 end do
402 end if
403
404 if (allocated(hm%ep%e_field)) then
405 do iatom = 1, ions%natoms
406 ! Here the proton charge is +1, since the electric field has the usual sign.
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)
410 end do
411 end if
412
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.'
416 call messages_fatal(2, namespace=namespace)
417 end if
418
419 if (list_has_gauge_field(ext_partners)) then
420 write(message(1),'(a)') 'The forces are currently not properly calculated if gauge-field'
421 write(message(2),'(a)') 'is applied.'
422 call messages_fatal(2, namespace=namespace)
423 end if
424
425 ! For periodic systems, we substract the averaged force
426 if(ions%space%is_periodic()) then
427 call forces_set_total_to_zero(ions, ions%tot_force)
428 end if
429
430 pop_sub(forces_calculate)
431 call profiling_out("FORCES")
432
433 end subroutine forces_calculate
434
435 ! ----------------------------------------------------------------------
436
437 subroutine forces_set_total_to_zero(ions, force)
438 type(ions_t), intent(in) :: ions
439 real(real64), intent(inout) :: force(:, :)
440
441 real(real64), allocatable :: total_force(:)
442 integer :: iatom
443
445
446 safe_allocate(total_force(1:ions%space%dim))
447
448 total_force(1:ions%space%dim) = sum(force, dim=2) / ions%natoms
449
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)
452 end do
453
454 safe_deallocate_a(total_force)
456 end subroutine forces_set_total_to_zero
457
458 ! ----------------------------------------------------------------------
460 subroutine forces_compute_total_torque(ions, total_torque)
461 type(ions_t), intent(in) :: ions
462 real(real64), intent(inout) :: total_torque(:)
463
464 real(real64) :: center_of_mass(ions%space%dim), rr(3), ff(3)
465 integer :: iatom
466
468
469 center_of_mass = ions%center_of_mass()
470
471 total_torque = m_zero
472 rr = m_zero
473 ff = m_zero
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)
477 total_torque(1:3) = total_torque(1:3) + dcross_product(rr, ff)
478 end do
479
481 end subroutine forces_compute_total_torque
482
483
484 ! ----------------------------------------------------------------------
485
486 subroutine forces_write_info(iunit, ions, dir, namespace)
487 integer, intent(in) :: iunit
488 type(ions_t), intent(in) :: ions
489 character(len=*), intent(in) :: dir
490 type(namespace_t), intent(in) :: namespace
491
492 integer :: iatom, idir, ii, iunit2
493 real(real64) :: torque(1:3)
494
495 if (.not. mpi_grp_is_root(mpi_world)) return
496
497 push_sub(forces_write_info)
498
499 write(iunit,'(3a)') 'Forces on the ions [', trim(units_abbrev(units_out%force)), "]"
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()), &
503 units_from_atomic(units_out%force, ions%tot_force(:, iatom))
504 end do
505 write(iunit,'(1x,100a1)') ("-", ii = 1, 13 + ions%space%dim * 15)
506 write(iunit,'(a14, 10es17.8)') " Max abs force", &
507 (units_from_atomic(units_out%force, maxval(abs(ions%tot_force(idir, 1:ions%natoms)))), idir=1, ions%space%dim)
508 write(iunit,'(a14, 10es17.8)') " Total force", &
509 (units_from_atomic(units_out%force, sum(ions%tot_force(idir, 1:ions%natoms))), idir=1, ions%space%dim)
510
511 if (ions%space%dim == 2 .or. ions%space%dim == 3 .and. .not. ions%space%is_periodic()) then
512 call forces_compute_total_torque(ions, torque)
513 write(iunit,'(a14, 10es17.8)') ' Total torque', &
514 (units_from_atomic(units_out%force*units_out%length, torque(idir)), idir = 1, 3)
515 end if
516 write(iunit,'(1x)')
517
518
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()), &
525 (units_from_atomic(units_out%force, ions%tot_force(idir, iatom)), idir=1, ions%space%dim), &
526 (units_from_atomic(units_out%force, ions%atom(iatom)%f_ii(idir)), idir=1, ions%space%dim), &
527 (units_from_atomic(units_out%force, ions%atom(iatom)%f_vdw(idir)), idir=1, ions%space%dim), &
528 (units_from_atomic(units_out%force, ions%atom(iatom)%f_loc(idir)), idir=1, ions%space%dim), &
529 (units_from_atomic(units_out%force, ions%atom(iatom)%f_nl(idir)), idir=1, ions%space%dim), &
530 (units_from_atomic(units_out%force, ions%atom(iatom)%f_fields(idir)), idir=1, ions%space%dim), &
531 (units_from_atomic(units_out%force, ions%atom(iatom)%f_u(idir)), idir=1, ions%space%dim), &
532 (units_from_atomic(units_out%force, ions%atom(iatom)%f_scf(idir)), idir=1, ions%space%dim), &
533 (units_from_atomic(units_out%force, ions%atom(iatom)%f_nlcc(idir)), idir=1, ions%space%dim), &
534 (units_from_atomic(units_out%force, ions%atom(iatom)%f_photons(idir)), idir=1, ions%space%dim)
535 end do
536 call io_close(iunit2)
537
538 pop_sub(forces_write_info)
539
540 end subroutine forces_write_info
541
542 ! ----------------------------------------------------------------------
543 ! This routine add the contribution to the forces from the nonlinear core correction
544 ! see Eq. 9 of Kronik et al., J. Chem. Phys. 115, 4322 (2001)
545 subroutine forces_from_nlcc(mesh, ions, spin_channels, vxc, force_nlcc)
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(:, :)
551
552 integer :: is, iatom, idir
553 real(real64), allocatable :: drho(:,:)
554
555
556 push_sub(forces_from_nlcc)
557
558 call profiling_in("FORCES_NLCC")
559
560 safe_allocate(drho(1:mesh%np, 1:ions%space%dim))
561
562 force_nlcc = m_zero
563
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)
566
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
571 end do
572 end do
573 end do
574
575 safe_deallocate_a(drho)
576
577 if (ions%atoms_dist%parallel) call dforces_gather(ions, force_nlcc)
578
579 if (mesh%parallel_in_domains) then
580 call profiling_in("FORCES_COMM")
581 call mesh%allreduce(force_nlcc)
582 call profiling_out("FORCES_COMM")
583 end if
584
585 call profiling_out("FORCES_NLCC")
586
587 pop_sub(forces_from_nlcc)
588 end subroutine forces_from_nlcc
589
590 ! Implementation of the term from Chan et al., Phys. Rev. B 47, 4771 (1993).
591 ! Here we make the approximation that the "atomic densities" are just the one
592 ! from the pseudopotential.
593 ! NTD : No idea if this is good or bad, but this is easy to implement
594 ! and works well in practice
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(:, :)
602
603 integer :: is, iatom, idir
604 real(real64), allocatable :: dvhxc(:,:), drho(:,:,:)
605
606 push_sub(forces_from_scf)
607
608 call profiling_in("FORCES_SCF")
609
610 safe_allocate(dvhxc(1:mesh%np, 1:spin_channels))
611 safe_allocate(drho(1:mesh%np, 1:spin_channels, 1:ions%space%dim))
612
613 !We average over spin channels
614 do is = 1, spin_channels
615 dvhxc(1:mesh%np, is) = vhxc(1:mesh%np, is) - vhxc_old(1:mesh%np, is)
616 end do
617
618 force_scf = m_zero
619
620 do iatom = ions%atoms_dist%start, ions%atoms_dist%end
621 select type(spec=>ions%atom(iatom)%species)
622 type is(pseudopotential_t)
623
624 if (ps_has_density(spec%ps)) then
625
626 call species_atom_density_grad(spec, ions%namespace, ions%space, ions%latt, &
627 ions%pos(:, iatom), mesh, spin_channels, drho)
628
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.)
633 end do
634 end do
635 end if
636 end select
637 end do
639 safe_deallocate_a(dvhxc)
640 safe_deallocate_a(drho)
641
642 if (ions%atoms_dist%parallel) call dforces_gather(ions, force_scf)
643
644 if (mesh%parallel_in_domains) then
645 call profiling_in("FORCES_COMM")
646 call mesh%allreduce(force_scf)
647 call profiling_out("FORCES_COMM")
648 end if
649
650 call profiling_out("FORCES_SCF")
651
652 pop_sub(forces_from_scf)
653 end subroutine forces_from_scf
654
655!---------------------------------------------------------------------------
656 subroutine total_force_from_local_potential(mesh, space, vpsl, gdensity, force)
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(:)
662
663 integer :: idir
664 real(real64) :: force_tmp(1:space%dim)
665
667
668 do idir = 1, space%dim
669 force_tmp(idir) = dmf_dotp(mesh, vpsl(1:mesh%np), gdensity(:, idir), reduce = .false.)
670 end do
671
672 if (mesh%parallel_in_domains) call mesh%allreduce(force_tmp)
673
674 force(1:space%dim) = force(1:space%dim) + force_tmp(1:space%dim)
675
678
679
680#include "undef.F90"
681#include "real.F90"
682#include "forces_inc.F90"
683
684#include "undef.F90"
685#include "complex.F90"
686#include "forces_inc.F90"
687
688end module forces_oct_m
689
690!! Local Variables:
691!! mode: f90
692!! coding: utf-8
693!! 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:1592
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:1129
subroutine forces_from_scf(mesh, ions, spin_channels, vhxc, vhxc_old, force_scf)
Definition: forces.F90:689
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:2041
subroutine forces_compute_total_torque(ions, total_torque)
Computes the total torque acting on the system.
Definition: forces.F90:554
subroutine ztotal_force_from_potential(space, gr, ions, ep, st, kpoints, x, lda_u_level)
Definition: forces.F90:1781
subroutine, public forces_write_info(iunit, ions, dir, namespace)
Definition: forces.F90:580
subroutine forces_set_total_to_zero(ions, force)
Definition: forces.F90:531
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:940
subroutine, public zforces_derivative(gr, namespace, space, ions, ep, st, kpoints, lr, lr2, force_deriv, lda_u_level)
Definition: forces.F90:1897
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:1245
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:1382
subroutine total_force_from_local_potential(mesh, space, vpsl, gdensity, force)
Definition: forces.F90:750
subroutine dforces_gather(ions, force)
Definition: forces.F90:841
subroutine forces_from_nlcc(mesh, ions, spin_channels, vxc, force_nlcc)
Definition: forces.F90:639
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
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:1643
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.