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