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