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
44 use lasers_oct_m
45 use lda_u_oct_m
48 use math_oct_m
49 use mesh_oct_m
52 use mpi_oct_m
55 use parser_oct_m
56 use phase_oct_m
59 use ps_oct_m
61 use space_oct_m
69 use unit_oct_m
71 use utils_oct_m
72 use v_ks_oct_m
73 use vdw_ts_oct_m
75
76 implicit none
77
78 private
79 public :: &
91
92
93contains
94
95 ! ---------------------------------------------------------
98 subroutine total_force_calculate(space, namespace, gr, ions, hm, st, x)
99 class(space_t), intent(in) :: space
100 class(namespace_t), intent(in) :: namespace
101 type(grid_t), intent(in) :: gr
102 type(ions_t), intent(in) :: ions
103 type(hamiltonian_elec_t), intent(in) :: hm
104 type(states_elec_t), intent(in) :: st
105 real(real64), intent(inout) :: x(:)
106
107 push_sub(total_force_calculate)
108 call profiling_in("TOTAL_FORCE")
109
110 x = m_zero
111 if (states_are_real(st)) then
112 call dtotal_force_from_potential(space, namespace, gr, ions, hm, st, x)
113 else
114 call ztotal_force_from_potential(space, namespace, gr, ions, hm, st, x)
115 end if
117 call profiling_out("TOTAL_FORCE")
118 pop_sub(total_force_calculate)
119 end subroutine total_force_calculate
120
121 ! -------------------------------------------------------
122
123 subroutine forces_costate_calculate(gr, namespace, ions, hm, psi, chi, ff, qq)
124 type(grid_t), intent(in) :: gr
125 type(namespace_t), intent(in) :: namespace
126 type(ions_t), intent(inout) :: ions
127 type(hamiltonian_elec_t), intent(in) :: hm
128 type(states_elec_t), intent(in) :: psi
129 type(states_elec_t), intent(in) :: chi
130 real(real64), intent(inout) :: ff(:, :)
131 real(real64), intent(in) :: qq(:, :)
132
133 integer :: jatom, idim, jdim
134 integer, target :: j, ist, ik, iatom
135 real(real64) :: rr, w2r, w1r, xx(ions%space%dim), dq, pdot3p, pdot3m, pdot3p2, pdot3m2, dforce1, dforce2
136 complex(real64), allocatable :: zpsi(:, :), derpsi(:, :, :)
137 real(real64), allocatable :: forceks1p(:), forceks1m(:), forceks1p2(:), forceks1m2(:), dforceks1(:)
138
139 call profiling_in("FORCES_COSTATE")
141
142 ! FIXME: is the next section not basically the same as the routine ion_internamespace, action_calculate?
143
144 ff = m_zero
145 do iatom = 1, ions%natoms
146 do jatom = 1, ions%natoms
147 if (jatom == iatom) cycle
148 xx(1:ions%space%dim) = ions%pos(:, jatom) - ions%pos(:, iatom)
149 rr = norm2(xx(1:ions%space%dim))
150 w1r = - ions%charge(iatom) * ions%charge(jatom) / rr**2
151 w2r = m_two * ions%charge(iatom) * ions%charge(jatom) / rr**3
152 do idim = 1, ions%space%dim
153 do jdim = 1, ions%space%dim
154 ff(iatom, idim) = ff(iatom, idim) + (qq(jatom, jdim) - qq(iatom, jdim)) * w2r * (m_one/rr**2) * xx(idim) * xx(jdim)
155 ff(iatom, idim) = ff(iatom, idim) - (qq(jatom, jdim) - qq(iatom, jdim)) * w1r * (m_one/rr**3) * xx(idim) * xx(jdim)
156 if (jdim == idim) then
157 ff(iatom, idim) = ff(iatom, idim) + (qq(jatom, jdim) - qq(iatom, jdim)) * w1r * (m_one/rr)
158 end if
159 end do
160 end do
161 end do
162 end do
163
164 safe_allocate(derpsi(1:gr%np_part, 1:ions%space%dim, 1:psi%d%dim))
165
166 dq = 0.001_real64
167
168 safe_allocate(forceks1p(1:ions%space%dim))
169 safe_allocate(forceks1m(1:ions%space%dim))
170 safe_allocate(forceks1p2(1:ions%space%dim))
171 safe_allocate(forceks1m2(1:ions%space%dim))
172 safe_allocate(dforceks1(1:ions%space%dim))
173 safe_allocate(zpsi(1:gr%np_part, 1:psi%d%dim))
174
175 do ist = 1, psi%nst
176 do ik = 1, psi%nik
177 derpsi = m_z0
178 call states_elec_get_state(psi, gr, ist, ik, zpsi)
179 call zderivatives_grad(gr%der, zpsi(:, 1), derpsi(:, :, 1))
180 do iatom = 1, ions%natoms
181 do j = 1, ions%space%dim
182 call force1(ions%pos(j, iatom) + dq, forceks1p, pdot3p)
183 call force1(ions%pos(j, iatom) - dq, forceks1m, pdot3m)
184 call force1(ions%pos(j, iatom) + dq/m_two, forceks1p2, pdot3p2)
185 call force1(ions%pos(j, iatom) - dq/m_two, forceks1m2, pdot3m2)
186 dforceks1 = ((m_four/m_three) * (forceks1p2 - forceks1m2) - (m_one / 6.0_real64) * (forceks1p - forceks1m)) / dq
187 dforce1 = sum(qq(iatom, :) * dforceks1(:))
188 dforce2 = ((m_four/m_three) * (pdot3p2 - pdot3m2) - (m_one / 6.0_real64) * (pdot3p - pdot3m)) / dq
189 ff(iatom, j) = ff(iatom, j) - m_two * psi%occ(ist, ik) * dforce1 + m_two * dforce2
190 end do
191 end do
192 end do
193 end do
194
195 safe_deallocate_a(zpsi)
196 safe_deallocate_a(forceks1p)
197 safe_deallocate_a(forceks1m)
198 safe_deallocate_a(forceks1p2)
199 safe_deallocate_a(forceks1m2)
200 safe_deallocate_a(dforceks1)
201 safe_deallocate_a(derpsi)
202
204 call profiling_out("FORCES_COSTATE")
205
206 contains
207
208 subroutine force1(qq, res, pdot3)
209 real(real64), intent(in) :: qq
210 real(real64), contiguous, intent(inout) :: res(:)
211 real(real64), intent(inout) :: pdot3
212
213 integer :: m
214 real(real64) :: qold
215 complex(real64), allocatable :: viapsi(:, :), zpsi(:, :)
216
217 qold = ions%pos(j, iatom)
218 ions%pos(j, iatom) = qq
219 safe_allocate(viapsi(1:gr%np_part, 1:psi%d%dim))
220 safe_allocate(zpsi(1:gr%np_part, 1:psi%d%dim))
221 viapsi = m_z0
222 call states_elec_get_state(psi, gr, ist, ik, zpsi)
223 call zhamiltonian_elec_apply_atom(hm, namespace, ions%space, ions%latt, ions%atom(iatom)%species, &
224 ions%pos(:, iatom), iatom, gr, zpsi, viapsi)
225
226 res(:) = m_zero
227 do m = 1, ubound(res, 1)
228 res(m) = real( zmf_dotp(gr, viapsi(:, 1), derpsi(:, m, 1), reduce = .false.), real64)
229 end do
230 call gr%allreduce(res)
231
232 call states_elec_get_state(chi, gr, ist, ik, zpsi)
233 pdot3 = real(m_zi * zmf_dotp(gr, zpsi(:, 1), viapsi(:, 1)), real64)
234 ions%pos(j, iatom) = qold
235
236 safe_deallocate_a(viapsi)
237 end subroutine force1
238
239 end subroutine forces_costate_calculate
240 ! ---------------------------------------------------------
241
242
243 ! ---------------------------------------------------------
244 subroutine forces_calculate(gr, namespace, ions, hm, ext_partners, st, ks, vhxc_old, t, dt)
245 type(grid_t), intent(in) :: gr
246 type(namespace_t), intent(in) :: namespace
247 type(ions_t), intent(inout) :: ions
248 type(hamiltonian_elec_t), intent(inout) :: hm
249 type(partner_list_t),intent(in) :: ext_partners
250 type(states_elec_t), intent(inout) :: st
251 type(v_ks_t), intent(in) :: ks
252 real(real64), optional, intent(in) :: vhxc_old(:,:)
253 real(real64), optional, intent(in) :: t
254 real(real64), optional, intent(in) :: dt
255
256 integer :: j, iatom, idir
257 real(real64) :: xx(ions%space%dim), time, global_force(ions%space%dim)
258 real(real64), allocatable :: force(:, :), force_loc(:, :), force_nl(:, :), force_u(:, :)
259 real(real64), allocatable :: force_nlcc(: ,:)
260 real(real64), allocatable :: force_scf(:, :)
261 type(lasers_t), pointer :: lasers
262
263 call profiling_in("FORCES")
264 push_sub(forces_calculate)
265
266 time = m_zero
267 if (present(t)) time = t
268
269 !We initialize the different components of the force to zero
270 do iatom = 1, ions%natoms
271 ions%atom(iatom)%f_ii(1:ions%space%dim) = m_zero
272 ions%atom(iatom)%f_vdw(1:ions%space%dim) = m_zero
273 ions%atom(iatom)%f_loc(1:ions%space%dim) = m_zero
274 ions%atom(iatom)%f_nl(1:ions%space%dim) = m_zero
275 ions%atom(iatom)%f_u(1:ions%space%dim) = m_zero
276 ions%atom(iatom)%f_fields(1:ions%space%dim) = m_zero
277 ions%atom(iatom)%f_nlcc(1:ions%space%dim) = m_zero
278 ions%atom(iatom)%f_scf(1:ions%space%dim) = m_zero
279 ions%atom(iatom)%f_photons(1:ions%space%dim) = m_zero
280 end do
281
282 ! the ion-ion and vdw terms are already calculated
283 ! if we use vdw TS, we need to compute it now
284 if (ks%vdw%vdw_correction == option__vdwcorrection__vdw_ts) then
285 call vdw_ts_force_calculate(ks%vdw%vdw_ts, hm%ep%vdw_forces, ions, gr, st%d%nspin, st%rho)
286 end if
287
288 do iatom = 1, ions%natoms
289 ions%tot_force(:, iatom) = hm%ep%fii(1:ions%space%dim, iatom) + hm%ep%vdw_forces(1:ions%space%dim, iatom)
290 if (ks%has_photons) then
291 ions%tot_force(:, iatom) = ions%tot_force(:, iatom) &
292 - p_proton_charge*ions%charge(iatom)*hm%ep%photon_forces(1:ions%space%dim)
293 end if
294 ions%atom(iatom)%f_ii(1:ions%space%dim) = hm%ep%fii(1:ions%space%dim, iatom)
295 ions%atom(iatom)%f_vdw(1:ions%space%dim) = hm%ep%vdw_forces(1:ions%space%dim, iatom)
296 ions%atom(iatom)%f_photons(1:ions%space%dim) = - p_proton_charge*ions%charge(iatom)*hm%ep%photon_forces(1:ions%space%dim)
297 end do
298
299 if (present(t)) then
300 global_force = ions%global_force(time)
301
302 ! the ion-ion term is already calculated
303 do iatom = 1, ions%natoms
304 ions%tot_force(:, iatom) = ions%tot_force(:, iatom) + global_force
305 ions%atom(iatom)%f_ii(1:ions%space%dim) = ions%atom(iatom)%f_ii(1:ions%space%dim) + global_force
306 end do
307 end if
308
309 safe_allocate(force(1:ions%space%dim, 1:ions%natoms))
310 safe_allocate(force_loc(1:ions%space%dim, 1:ions%natoms))
311 safe_allocate(force_nl(1:ions%space%dim, 1:ions%natoms))
312 safe_allocate(force_u(1:ions%space%dim, 1:ions%natoms))
313 safe_allocate(force_scf(1:ions%space%dim, 1:ions%natoms))
314 safe_allocate(force_nlcc(1:ions%space%dim, 1:ions%natoms))
315
316 if (states_are_real(st)) then
317 call dforces_from_potential(gr, namespace, ions%space, ions, hm, st, force, force_loc, force_nl, force_u)
318 else
319 call zforces_from_potential(gr, namespace, ions%space, ions, hm, st, force, force_loc, force_nl, force_u)
320 end if
321
322 if (allocated(st%rho_core) .and. ks%theory_level /= independent_particles &
323 .and. ks%theory_level /= hartree .and. ks%theory_level /= rdmft) then
324 call forces_from_nlcc(gr, ions, st%d%spin_channels, hm%ks_pot%vxc, force_nlcc)
325 else
326 force_nlcc(:, :) = m_zero
327 end if
328 if (present(vhxc_old)) then
329 call forces_from_scf(gr, ions, st%d%spin_channels, hm%ks_pot%vhxc, vhxc_old, force_scf)
330 else
331 force_scf = m_zero
332 end if
333
334 if (ions%force_total_enforce) then
335 call forces_set_total_to_zero(ions, force)
336 call forces_set_total_to_zero(ions, force_loc)
337 call forces_set_total_to_zero(ions, force_nl)
338 call forces_set_total_to_zero(ions, force_u)
339 call forces_set_total_to_zero(ions, force_scf)
340 call forces_set_total_to_zero(ions, force_nlcc)
341 end if
342
343 do iatom = 1, ions%natoms
344 do idir = 1, ions%space%dim
345 ions%tot_force(idir, iatom) = ions%tot_force(idir, iatom) + force(idir, iatom) &
346 + force_scf(idir, iatom) + force_nlcc(idir, iatom)
347 ions%atom(iatom)%f_loc(idir) = force_loc(idir, iatom)
348 ions%atom(iatom)%f_nl(idir) = force_nl(idir, iatom)
349 ions%atom(iatom)%f_u(idir) = force_u(idir, iatom)
350 ions%atom(iatom)%f_nlcc(idir) = force_nlcc(idir, iatom)
351 ions%atom(iatom)%f_scf(idir) = force_scf(idir, iatom)
352 end do
353 end do
354
355 safe_deallocate_a(force)
356 safe_deallocate_a(force_loc)
357 safe_deallocate_a(force_nl)
358 safe_deallocate_a(force_u)
359 safe_deallocate_a(force_nlcc)
360 safe_deallocate_a(force_scf)
361
362 !\todo forces due to the magnetic fields (static and time-dependent)
363 lasers => list_get_lasers(ext_partners)
364 if (present(t) .and. associated(lasers)) then
365 do j = 1, lasers%no_lasers
366 select case (laser_kind(lasers%lasers(j)))
367 case (e_field_electric)
368 xx(:) = m_zero
369 call laser_field(lasers%lasers(j), xx, t)
370 do iatom = 1, ions%natoms
371 ! Here the proton charge is +1, since the electric field has the usual sign.
372 ions%tot_force(:, iatom) = ions%tot_force(:, iatom) + ions%charge(iatom)*xx(:)
373 ions%atom(iatom)%f_fields(1:ions%space%dim) = ions%atom(iatom)%f_fields(1:ions%space%dim) &
374 + ions%charge(iatom)*xx(:)
375 end do
376
378 ! Forces are correctly calculated only if the time-dependent
379 ! vector potential has no spatial dependence.
380 ! The full force taking account of the spatial dependence of A should be:
381 ! F = q [- dA/dt + v x \nabla x A]
382
383 !TODO: Add the gauge-field here
384 xx(:) = m_zero
385 call laser_electric_field(lasers%lasers(j), xx(:), t, dt) !convert in E field (E = -dA/ c dt)
386 do iatom = 1, ions%natoms
387 ! Also here the proton charge is +1
388 ions%tot_force(:, iatom) = ions%tot_force(:, iatom) + ions%charge(iatom)*xx(:)
389 ions%atom(iatom)%f_fields(1:ions%space%dim) = ions%atom(iatom)%f_fields(1:ions%space%dim) &
390 + ions%charge(iatom)*xx(:)
391 end do
392
393 if (lasers_with_nondipole_field(lasers)) then
394 write(message(1),'(a)') 'The forces are currently not supported for nondipole '
395 write(message(2),'(a)') 'strong-field approximation Hamiltonian approach.'
396 call messages_fatal(2, namespace=namespace)
397 end if
398
400 write(message(1),'(a)') 'The forces are currently not properly calculated if time-dependent'
401 write(message(2),'(a)') 'magnetic fields are present.'
402 call messages_fatal(2, namespace=namespace)
403 end select
404 end do
405 end if
406
407 if (allocated(hm%ep%e_field)) then
408 do iatom = 1, ions%natoms
409 ! Here the proton charge is +1, since the electric field has the usual sign.
410 ions%tot_force(:, iatom) = ions%tot_force(:, iatom) + ions%charge(iatom)*hm%ep%e_field(1:ions%space%dim)
411 ions%atom(iatom)%f_fields(1:ions%space%dim) = ions%atom(iatom)%f_fields(1:ions%space%dim) &
412 + ions%charge(iatom)*hm%ep%e_field(1:ions%space%dim)
413 end do
414 end if
415
416 if (allocated(hm%ep%b_field) .or. allocated(hm%ep%a_static)) then
417 write(message(1),'(a)') 'The forces are currently not properly calculated if static'
418 write(message(2),'(a)') 'magnetic fields or static vector potentials are present.'
419 call messages_fatal(2, namespace=namespace)
420 end if
421
422 if (list_has_gauge_field(ext_partners)) then
423 write(message(1),'(a)') 'The forces are currently not properly calculated if gauge-field'
424 write(message(2),'(a)') 'is applied.'
425 call messages_fatal(2, namespace=namespace)
426 end if
427
428 ! As the constrain is attached to the position of the atom, it contribute to the forces
429 if (hm%magnetic_constrain%level /= constrain_none) then
430 call messages_not_implemented("Forces with MagneticConstrain /= constrain_none")
431 end if
432
433 if (hm%kpoints%use_symmetries .or. st%symmetrize_density) then
434 call symmetrize_force(ions, ions%tot_force)
435 end if
436
437 ! For periodic systems, we substract the averaged force
438 if (ions%space%is_periodic()) then
439 call forces_set_total_to_zero(ions, ions%tot_force)
440 end if
441
442 pop_sub(forces_calculate)
443 call profiling_out("FORCES")
444
445 end subroutine forces_calculate
446
447 ! ----------------------------------------------------------------------
448
449 subroutine forces_set_total_to_zero(ions, force)
450 type(ions_t), intent(in) :: ions
451 real(real64), intent(inout) :: force(:, :)
452
453 real(real64), allocatable :: total_force(:)
454 integer :: iatom
455
457
458 safe_allocate(total_force(1:ions%space%dim))
459
460 total_force(1:ions%space%dim) = sum(force, dim=2) / ions%natoms
461
462 do iatom = 1, ions%natoms
463 force(1:ions%space%dim, iatom) = force(1:ions%space%dim, iatom) - total_force(1:ions%space%dim)
464 end do
465
466 safe_deallocate_a(total_force)
468 end subroutine forces_set_total_to_zero
469
470 ! ----------------------------------------------------------------------
472 subroutine forces_compute_total_torque(ions, total_torque)
473 type(ions_t), intent(in) :: ions
474 real(real64), intent(inout) :: total_torque(:)
475
476 real(real64) :: center_of_mass(ions%space%dim), rr(3), ff(3)
477 integer :: iatom
478
480
481 center_of_mass = ions%center_of_mass()
482
483 total_torque = m_zero
484 rr = m_zero
485 ff = m_zero
486 do iatom = 1, ions%natoms
487 rr(1:ions%space%dim) = ions%pos(1:ions%space%dim, iatom) - center_of_mass
488 ff(1:ions%space%dim) = ions%tot_force(1:ions%space%dim, iatom)
489 total_torque(1:3) = total_torque(1:3) + dcross_product(rr, ff)
490 end do
491
493 end subroutine forces_compute_total_torque
494
495
496 ! ----------------------------------------------------------------------
497
498 subroutine forces_write_info(iunit, ions, dir, namespace)
499 integer, intent(in) :: iunit
500 type(ions_t), intent(in) :: ions
501 character(len=*), intent(in) :: dir
502 type(namespace_t), intent(in) :: namespace
503
504 integer :: iatom, idir, ii, iunit2
505 real(real64) :: torque(1:3)
506
507 if (.not. mpi_world%is_root()) return
508
509 push_sub(forces_write_info)
510
511 write(iunit,'(3a)') 'Forces on the ions [', trim(units_abbrev(units_out%force)), "]"
512 write(iunit,'(a,10x,99(14x,a))') ' Ion', (index2axis(idir), idir = 1, ions%space%dim)
513 do iatom = 1, ions%natoms
514 write(iunit,'(i4,a10,10es17.8)') iatom, trim(ions%atom(iatom)%species%get_label()), &
515 units_from_atomic(units_out%force, ions%tot_force(:, iatom))
516 end do
517 write(iunit,'(1x,100a1)') ("-", ii = 1, 13 + ions%space%dim * 15)
518 write(iunit,'(a14, 10es17.8)') " Max abs force", &
519 (units_from_atomic(units_out%force, maxval(abs(ions%tot_force(idir, 1:ions%natoms)))), idir=1, ions%space%dim)
520 write(iunit,'(a14, 10es17.8)') " Total force", &
521 (units_from_atomic(units_out%force, sum(ions%tot_force(idir, 1:ions%natoms))), idir=1, ions%space%dim)
522
523 if (ions%space%dim == 2 .or. ions%space%dim == 3 .and. .not. ions%space%is_periodic()) then
524 call forces_compute_total_torque(ions, torque)
525 write(iunit,'(a14, 10es17.8)') ' Total torque', &
526 (units_from_atomic(units_out%force*units_out%length, torque(idir)), idir = 1, 3)
527 end if
528 write(iunit,'(1x)')
529
530
531 iunit2 = io_open(trim(dir)//'/forces', namespace, action='write', position='asis')
532 write(iunit2,'(a)') &
533 ' # Total force (x,y,z) Ion-Ion (x,y,z) VdW (x,y,z) Local (x,y,z) NL (x,y,z)' // &
534 ' Fields (x,y,z) Hubbard(x,y,z) SCF(x,y,z) NLCC(x,y,z) Phot (x,y,z)'
535 do iatom = 1, ions%natoms
536 write(iunit2,'(i4,a10,30es17.8)') iatom, trim(ions%atom(iatom)%species%get_label()), &
537 (units_from_atomic(units_out%force, ions%tot_force(idir, iatom)), idir=1, ions%space%dim), &
538 (units_from_atomic(units_out%force, ions%atom(iatom)%f_ii(idir)), idir=1, ions%space%dim), &
539 (units_from_atomic(units_out%force, ions%atom(iatom)%f_vdw(idir)), idir=1, ions%space%dim), &
540 (units_from_atomic(units_out%force, ions%atom(iatom)%f_loc(idir)), idir=1, ions%space%dim), &
541 (units_from_atomic(units_out%force, ions%atom(iatom)%f_nl(idir)), idir=1, ions%space%dim), &
542 (units_from_atomic(units_out%force, ions%atom(iatom)%f_fields(idir)), idir=1, ions%space%dim), &
543 (units_from_atomic(units_out%force, ions%atom(iatom)%f_u(idir)), idir=1, ions%space%dim), &
544 (units_from_atomic(units_out%force, ions%atom(iatom)%f_scf(idir)), idir=1, ions%space%dim), &
545 (units_from_atomic(units_out%force, ions%atom(iatom)%f_nlcc(idir)), idir=1, ions%space%dim), &
546 (units_from_atomic(units_out%force, ions%atom(iatom)%f_photons(idir)), idir=1, ions%space%dim)
547 end do
548 call io_close(iunit2)
549
550 pop_sub(forces_write_info)
551
552 end subroutine forces_write_info
553
554 ! ----------------------------------------------------------------------
555 ! This routine add the contribution to the forces from the nonlinear core correction
556 ! see Eq. 9 of Kronik et al., J. Chem. Phys. 115, 4322 (2001)
557 subroutine forces_from_nlcc(mesh, ions, spin_channels, vxc, force_nlcc)
558 class(mesh_t), intent(in) :: mesh
559 type(ions_t), intent(inout) :: ions
560 integer, intent(in) :: spin_channels
561 real(real64), intent(in) :: vxc(:,:)
562 real(real64), contiguous, intent(out) :: force_nlcc(:, :)
563
564 integer :: is, iatom, idir
565 real(real64), allocatable :: drho(:,:)
566
568 push_sub(forces_from_nlcc)
569
570 call profiling_in("FORCES_NLCC")
571
572 safe_allocate(drho(1:mesh%np, 1:ions%space%dim))
573
574 force_nlcc = m_zero
575
576 do iatom = ions%atoms_dist%start, ions%atoms_dist%end
577 call species_get_nlcc_grad(ions%atom(iatom)%species, ions%space, ions%latt, ions%pos(:, iatom), mesh, drho)
578
579 do idir = 1, ions%space%dim
580 do is = 1, spin_channels
581 force_nlcc(idir, iatom) = force_nlcc(idir, iatom) &
582 - dmf_dotp(mesh, drho(:,idir), vxc(1:mesh%np, is), reduce = .false.)/spin_channels
583 end do
584 end do
585 end do
586
587 safe_deallocate_a(drho)
588
589 if (ions%atoms_dist%parallel) call dforces_gather(ions, force_nlcc)
590
591 call profiling_in("FORCES_COMM")
592 call mesh%allreduce(force_nlcc)
593 call profiling_out("FORCES_COMM")
594
595 call profiling_out("FORCES_NLCC")
596
597 pop_sub(forces_from_nlcc)
598 end subroutine forces_from_nlcc
599
600 ! Implementation of the term from Chan et al., Phys. Rev. B 47, 4771 (1993).
601 ! Here we make the approximation that the "atomic densities" are just the one
602 ! from the pseudopotential.
603 ! NTD : No idea if this is good or bad, but this is easy to implement
604 ! and works well in practice
605 subroutine forces_from_scf(mesh, ions, spin_channels, vhxc, vhxc_old, force_scf)
606 class(mesh_t), intent(in) :: mesh
607 type(ions_t), intent(inout) :: ions
608 integer, intent(in) :: spin_channels
609 real(real64), intent(in) :: vhxc(:,:)
610 real(real64), intent(in) :: vhxc_old(:,:)
611 real(real64), contiguous, intent(out) :: force_scf(:, :)
612
613 integer :: is, iatom, idir
614 real(real64), allocatable :: dvhxc(:,:), drho(:,:,:)
615
616 push_sub(forces_from_scf)
617
618 call profiling_in("FORCES_SCF")
619
620 safe_allocate(dvhxc(1:mesh%np, 1:spin_channels))
621 safe_allocate(drho(1:mesh%np, 1:spin_channels, 1:ions%space%dim))
622
623 !We average over spin channels
624 do is = 1, spin_channels
625 dvhxc(1:mesh%np, is) = vhxc(1:mesh%np, is) - vhxc_old(1:mesh%np, is)
626 end do
627
628 force_scf = m_zero
629
630 do iatom = ions%atoms_dist%start, ions%atoms_dist%end
631 select type(spec=>ions%atom(iatom)%species)
632 type is(pseudopotential_t)
633
634 if (ps_has_density(spec%ps)) then
635
636 call species_atom_density_grad(spec, ions%namespace, ions%space, ions%latt, &
637 ions%pos(:, iatom), mesh, spin_channels, drho)
638
639 do idir = 1, ions%space%dim
640 do is = 1, spin_channels
641 force_scf(idir, iatom) = force_scf(idir, iatom) &
642 - dmf_dotp(mesh, drho(:,is,idir), dvhxc(:,is), reduce = .false.)
643 end do
644 end do
645 end if
646 end select
647 end do
648
649 safe_deallocate_a(dvhxc)
650 safe_deallocate_a(drho)
651
652 if (ions%atoms_dist%parallel) call dforces_gather(ions, force_scf)
653
654 call profiling_in("FORCES_COMM")
655 call mesh%allreduce(force_scf)
656 call profiling_out("FORCES_COMM")
657
658 call profiling_out("FORCES_SCF")
659
660 pop_sub(forces_from_scf)
661 end subroutine forces_from_scf
662
663 !---------------------------------------------------------------------------
664 subroutine total_force_from_local_potential(mesh, space, vpsl, gdensity, force)
665 class(mesh_t), intent(in) :: mesh
666 class(space_t), intent(in) :: space
667 real(real64), intent(in) :: vpsl(:)
668 real(real64), intent(in) :: gdensity(:, :)
669 real(real64), intent(inout) :: force(:)
670
671 integer :: idir
672 real(real64) :: force_tmp(1:space%dim)
673
674 push_sub_with_profile(total_force_from_local_potential)
675
676 do idir = 1, space%dim
677 force_tmp(idir) = dmf_dotp(mesh, vpsl(1:mesh%np), gdensity(:, idir), reduce = .false.)
678 end do
679
680 call mesh%allreduce(force_tmp)
681
682 force(1:space%dim) = force(1:space%dim) + force_tmp(1:space%dim)
683
684 pop_sub_with_profile(total_force_from_local_potential)
686
687 !---------------------------------------------------------------------------
689 subroutine symmetrize_force(ions, force)
690 type(ions_t), intent(in) :: ions
691 real(real64), intent(inout) :: force(:,:)
692
693 integer :: iatom, iop, iatom_symm
694 real(real64) :: symmetrized_force(ions%space%dim), force_tmp(ions%space%dim)
695 real(real64), allocatable :: force_sym(:,:)
696
697 push_sub(symmetrize_force)
698
699 safe_allocate(force_sym(1:ions%space%dim,1:ions%natoms))
700 do iatom = 1, ions%natoms
701 symmetrized_force = m_zero
702 do iop = 1, ions%symm%nops
703 iatom_symm = ions%inv_map_symm_atoms(iatom, iop)
704 force_tmp = symm_op_apply_inv_cart(ions%symm%ops(iop), force(:, iatom_symm))
705 symmetrized_force = symmetrized_force + force_tmp
706 end do
707
708 do iop = 1, ions%symm%nops_nonsymmorphic
709 iatom_symm = ions%inv_map_symm_atoms(iatom, iop + ions%symm%nops)
710 force_tmp = symm_op_apply_inv_cart(ions%symm%non_symmorphic_ops(iop), force(:, iatom_symm), rotation_only=.true.)
711 symmetrized_force = symmetrized_force + force_tmp
712 end do
713
714 force_sym(:, iatom) = symmetrized_force / (ions%symm%nops + ions%symm%nops_nonsymmorphic)
715 end do
716 force = force_sym
717
718 safe_deallocate_a(force_sym)
719
720 pop_sub(symmetrize_force)
721 end subroutine symmetrize_force
722
723
724#include "undef.F90"
725#include "real.F90"
726#include "forces_inc.F90"
727
728#include "undef.F90"
729#include "complex.F90"
730#include "forces_inc.F90"
731
732end module forces_oct_m
733
734!! Local Variables:
735!! mode: f90
736!! coding: utf-8
737!! End:
subroutine force1(qq, res, pdot3)
Definition: forces.F90:304
This module implements batches of mesh functions.
Definition: batch.F90:135
This module implements common operations on batches of mesh functions.
Definition: batch_ops.F90:118
Module implementing boundary conditions in Octopus.
Definition: boundaries.F90:124
This module implements a calculator for the density and defines related functions.
Definition: density.F90:122
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:1575
subroutine, public forces_costate_calculate(gr, namespace, ions, hm, psi, chi, ff, qq)
Definition: forces.F90:219
subroutine, public total_force_calculate(space, namespace, gr, ions, hm, st, x)
This computes the total forces on the ions created by the electrons (it excludes the force due to pos...
Definition: forces.F90:194
subroutine forces_from_scf(mesh, ions, spin_channels, vhxc, vhxc_old, force_scf)
Definition: forces.F90:701
subroutine ztotal_force_from_potential(space, namespace, gr, ions, hm, st, x)
Definition: forces.F90:1759
subroutine symmetrize_force(ions, force)
Given the forces on all atoms, this symmetrizes them using symmorphic and non-symmorphic operations.
Definition: forces.F90:785
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:1961
subroutine forces_compute_total_torque(ions, total_torque)
Computes the total torque acting on the system.
Definition: forces.F90:568
subroutine, public forces_write_info(iunit, ions, dir, namespace)
Definition: forces.F90:594
subroutine, public forces_set_total_to_zero(ions, force)
Definition: forces.F90:545
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:986
subroutine, public zforces_derivative(gr, namespace, space, ions, ep, st, kpoints, lr, lr2, force_deriv, lda_u_level)
Definition: forces.F90:1814
subroutine, public forces_calculate(gr, namespace, ions, hm, ext_partners, st, ks, vhxc_old, t, dt)
Definition: forces.F90:340
subroutine dtotal_force_from_potential(space, namespace, gr, ions, hm, st, x)
Definition: forces.F90:1170
subroutine, public dforces_derivative(gr, namespace, space, ions, ep, st, kpoints, lr, lr2, force_deriv, lda_u_level)
Definition: forces.F90:1225
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:1365
subroutine total_force_from_local_potential(mesh, space, vpsl, gdensity, force)
Definition: forces.F90:760
subroutine dforces_gather(ions, force)
Definition: forces.F90:887
subroutine forces_from_nlcc(mesh, ions, spin_channels, vxc, force_nlcc)
Definition: forces.F90:653
real(real64), parameter, public m_two
Definition: global.F90:193
real(real64), parameter, public p_proton_charge
Definition: global.F90:232
real(real64), parameter, public m_zero
Definition: global.F90:191
real(real64), parameter, public m_four
Definition: global.F90:195
integer, parameter, public rdmft
Definition: global.F90:237
integer, parameter, public independent_particles
Theory level.
Definition: global.F90:237
complex(real64), parameter, public m_z0
Definition: global.F90:201
complex(real64), parameter, public m_zi
Definition: global.F90:205
real(real64), parameter, public m_one
Definition: global.F90:192
real(real64), parameter, public m_three
Definition: global.F90:194
integer, parameter, public hartree
Definition: global.F90:237
This module implements the underlying real-space grid.
Definition: grid.F90:119
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:116
subroutine, public io_close(iunit, grp)
Definition: io.F90:466
integer function, public io_open(file, namespace, action, status, form, position, die, recl, grp)
Definition: io.F90:401
A module to handle KS potential, without the external potential.
logical function, public lasers_with_nondipole_field(lasers)
Check if a nondipole SFA correction should be computed for the given laser.
Definition: lasers.F90:741
integer, parameter, public e_field_electric
Definition: lasers.F90:179
integer, parameter, public e_field_vector_potential
Definition: lasers.F90:179
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:1193
integer, parameter, public e_field_scalar_potential
Definition: lasers.F90:179
integer pure elemental function, public laser_kind(laser)
Definition: lasers.F90:717
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:1117
integer, parameter, public e_field_magnetic
Definition: lasers.F90:179
This modules implements the routines for doing constrain DFT for noncollinear magnetism.
integer, parameter, public constrain_none
This module is intended to contain "only mathematical" functions and procedures.
Definition: math.F90:117
pure real(real64) function, dimension(1:3), public dcross_product(a, b)
Definition: math.F90:1941
This module defines various routines, operating on mesh functions.
This module defines the meshes, which are used in Octopus.
Definition: mesh.F90:120
subroutine, public messages_not_implemented(feature, namespace)
Definition: messages.F90:1091
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
Definition: messages.F90:162
subroutine, public messages_fatal(no_lines, only_root_writes, namespace)
Definition: messages.F90:410
type(mpi_grp_t), public mpi_world
Definition: mpi.F90:272
subroutine, public profiling_out(label)
Increment out counter and sum up difference between entry and exit time.
Definition: profiling.F90:625
subroutine, public profiling_in(label, exclude)
Increment in counter and save entry time.
Definition: profiling.F90:554
Definition: ps.F90:116
pure logical function, public ps_has_density(ps)
Definition: ps.F90:1641
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:134
character(len=20) pure function, public units_abbrev(this)
Definition: unit.F90:225
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:120
character pure function, public index2axis(idir)
Definition: utils.F90:205
Tkatchenko-Scheffler pairwise method for van der Waals (vdW, dispersion) interactions.
Definition: vdw_ts.F90:121
subroutine, public vdw_ts_force_calculate(this, force_vdw, ions, mesh, nspin, density)
Definition: vdw_ts.F90:430
Description of the grid, containing information on derivatives, stencil, and symmetries.
Definition: grid.F90:171
Describes mesh distribution to nodes.
Definition: mesh.F90:187
The states_elec_t class contains all electronic wave functions.
int true(void)