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 :: &
90
91
92contains
93
94 ! ---------------------------------------------------------
97 subroutine total_force_calculate(space, gr, ions, ep, st, phase, x, lda_u)
98 class(space_t), intent(in) :: space
99 type(grid_t), intent(in) :: gr
100 type(ions_t), intent(in) :: ions
101 type(epot_t), intent(in) :: ep
102 type(states_elec_t), intent(in) :: st
103 type(phase_t), intent(in) :: phase
104 real(real64), intent(inout) :: x(:)
105 integer, intent(in) :: lda_u
106
107
108 call profiling_in("FORCES")
109 push_sub(total_force_calculate)
110
111 x = m_zero
112 if (states_are_real(st)) then
113 call dtotal_force_from_potential(space, gr, ions, ep, st, phase, x, lda_u)
114 else
115 call ztotal_force_from_potential(space, gr, ions, ep, st, phase, x, lda_u)
116 end if
117
118 pop_sub(total_force_calculate)
119 call profiling_out("FORCES")
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), 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")
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")
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(:, :)
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 if (gr%parallel_in_domains) 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), 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 time = m_zero
268 if (present(t)) time = t
269
270 !We initialize the different components of the force to zero
271 do iatom = 1, ions%natoms
272 ions%atom(iatom)%f_ii(1:ions%space%dim) = m_zero
273 ions%atom(iatom)%f_vdw(1:ions%space%dim) = m_zero
274 ions%atom(iatom)%f_loc(1:ions%space%dim) = m_zero
275 ions%atom(iatom)%f_nl(1:ions%space%dim) = m_zero
276 ions%atom(iatom)%f_u(1:ions%space%dim) = m_zero
277 ions%atom(iatom)%f_fields(1:ions%space%dim) = m_zero
278 ions%atom(iatom)%f_nlcc(1:ions%space%dim) = m_zero
279 ions%atom(iatom)%f_scf(1:ions%space%dim) = m_zero
280 ions%atom(iatom)%f_photons(1:ions%space%dim) = m_zero
281 end do
282
283 ! the ion-ion and vdw terms are already calculated
284 ! if we use vdw TS, we need to compute it now
285 if (ks%vdw%vdw_correction == option__vdwcorrection__vdw_ts) then
286 call vdw_ts_force_calculate(ks%vdw%vdw_ts, hm%ep%vdw_forces, ions, gr, st%d%nspin, st%rho)
287 end if
288
289 do iatom = 1, ions%natoms
290 ions%tot_force(:, iatom) = hm%ep%fii(1:ions%space%dim, iatom) + hm%ep%vdw_forces(1:ions%space%dim, iatom)
291 if (ks%has_photons) then
292 ions%tot_force(:, iatom) = ions%tot_force(:, iatom) &
293 - p_proton_charge*ions%charge(iatom)*hm%ep%photon_forces(1:ions%space%dim)
294 end if
295 ions%atom(iatom)%f_ii(1:ions%space%dim) = hm%ep%fii(1:ions%space%dim, iatom)
296 ions%atom(iatom)%f_vdw(1:ions%space%dim) = hm%ep%vdw_forces(1:ions%space%dim, iatom)
297 ions%atom(iatom)%f_photons(1:ions%space%dim) = - p_proton_charge*ions%charge(iatom)*hm%ep%photon_forces(1:ions%space%dim)
298 end do
299
300 if (present(t)) then
301 global_force = ions%global_force(time)
303 ! the ion-ion term is already calculated
304 do iatom = 1, ions%natoms
305 ions%tot_force(:, iatom) = ions%tot_force(:, iatom) + global_force
306 ions%atom(iatom)%f_ii(1:ions%space%dim) = ions%atom(iatom)%f_ii(1:ions%space%dim) + global_force
307 end do
308 end if
309
310 safe_allocate(force(1:ions%space%dim, 1:ions%natoms))
311 safe_allocate(force_loc(1:ions%space%dim, 1:ions%natoms))
312 safe_allocate(force_nl(1:ions%space%dim, 1:ions%natoms))
313 safe_allocate(force_u(1:ions%space%dim, 1:ions%natoms))
314 safe_allocate(force_scf(1:ions%space%dim, 1:ions%natoms))
315 safe_allocate(force_nlcc(1:ions%space%dim, 1:ions%natoms))
316
317 if (states_are_real(st)) then
318 call dforces_from_potential(gr, namespace, ions%space, ions, hm, st, force, force_loc, force_nl, force_u)
319 else
320 call zforces_from_potential(gr, namespace, ions%space, ions, hm, st, force, force_loc, force_nl, force_u)
321 end if
322
323 if (allocated(st%rho_core) .and. ks%theory_level /= independent_particles &
324 .and. ks%theory_level /= hartree .and. ks%theory_level /= rdmft) then
325 call forces_from_nlcc(gr, ions, st%d%spin_channels, hm%ks_pot%vxc, force_nlcc)
326 else
327 force_nlcc(:, :) = m_zero
328 end if
329 if (present(vhxc_old)) then
330 call forces_from_scf(gr, ions, st%d%spin_channels, hm%ks_pot%vhxc, vhxc_old, force_scf)
331 else
332 force_scf = m_zero
333 end if
334
335 if (ions%force_total_enforce) then
336 call forces_set_total_to_zero(ions, force)
337 call forces_set_total_to_zero(ions, force_loc)
338 call forces_set_total_to_zero(ions, force_nl)
339 call forces_set_total_to_zero(ions, force_u)
340 call forces_set_total_to_zero(ions, force_scf)
341 call forces_set_total_to_zero(ions, force_nlcc)
342 end if
343
344 do iatom = 1, ions%natoms
345 do idir = 1, ions%space%dim
346 ions%tot_force(idir, iatom) = ions%tot_force(idir, iatom) + force(idir, iatom) &
347 + force_scf(idir, iatom) + force_nlcc(idir, iatom)
348 ions%atom(iatom)%f_loc(idir) = force_loc(idir, iatom)
349 ions%atom(iatom)%f_nl(idir) = force_nl(idir, iatom)
350 ions%atom(iatom)%f_u(idir) = force_u(idir, iatom)
351 ions%atom(iatom)%f_nlcc(idir) = force_nlcc(idir, iatom)
352 ions%atom(iatom)%f_scf(idir) = force_scf(idir, iatom)
353 end do
354 end do
355
356 safe_deallocate_a(force)
357 safe_deallocate_a(force_loc)
358 safe_deallocate_a(force_nl)
359 safe_deallocate_a(force_u)
360 safe_deallocate_a(force_nlcc)
361 safe_deallocate_a(force_scf)
362
363 !\todo forces due to the magnetic fields (static and time-dependent)
364 lasers => list_get_lasers(ext_partners)
365 if (present(t) .and. associated(lasers)) then
366 do j = 1, lasers%no_lasers
367 select case (laser_kind(lasers%lasers(j)))
368 case (e_field_electric)
369 xx(:) = m_zero
370 call laser_field(lasers%lasers(j), xx, t)
371 do iatom = 1, ions%natoms
372 ! Here the proton charge is +1, since the electric field has the usual sign.
373 ions%tot_force(:, iatom) = ions%tot_force(:, iatom) + ions%charge(iatom)*xx(:)
374 ions%atom(iatom)%f_fields(1:ions%space%dim) = ions%atom(iatom)%f_fields(1:ions%space%dim) &
375 + ions%charge(iatom)*xx(:)
376 end do
377
379 ! Forces are correctly calculated only if the time-dependent
380 ! vector potential has no spatial dependence.
381 ! The full force taking account of the spatial dependence of A should be:
382 ! F = q [- dA/dt + v x \nabla x A]
383
384 !TODO: Add the gauge-field here
385 xx(:) = m_zero
386 call laser_electric_field(lasers%lasers(j), xx(:), t, dt) !convert in E field (E = -dA/ c dt)
387 do iatom = 1, ions%natoms
388 ! Also here the proton charge is +1
389 ions%tot_force(:, iatom) = ions%tot_force(:, iatom) + ions%charge(iatom)*xx(:)
390 ions%atom(iatom)%f_fields(1:ions%space%dim) = ions%atom(iatom)%f_fields(1:ions%space%dim) &
391 + ions%charge(iatom)*xx(:)
392 end do
393
394 if (lasers_with_nondipole_field(lasers)) then
395 write(message(1),'(a)') 'The forces are currently not supported for nondipole '
396 write(message(2),'(a)') 'strong-field approximation Hamiltonian approach.'
397 call messages_fatal(2, namespace=namespace)
398 end if
399
401 write(message(1),'(a)') 'The forces are currently not properly calculated if time-dependent'
402 write(message(2),'(a)') 'magnetic fields are present.'
403 call messages_fatal(2, namespace=namespace)
404 end select
405 end do
406 end if
407
408 if (allocated(hm%ep%e_field)) then
409 do iatom = 1, ions%natoms
410 ! Here the proton charge is +1, since the electric field has the usual sign.
411 ions%tot_force(:, iatom) = ions%tot_force(:, iatom) + ions%charge(iatom)*hm%ep%e_field(1:ions%space%dim)
412 ions%atom(iatom)%f_fields(1:ions%space%dim) = ions%atom(iatom)%f_fields(1:ions%space%dim) &
413 + ions%charge(iatom)*hm%ep%e_field(1:ions%space%dim)
414 end do
415 end if
416
417 if (allocated(hm%ep%b_field) .or. allocated(hm%ep%a_static)) then
418 write(message(1),'(a)') 'The forces are currently not properly calculated if static'
419 write(message(2),'(a)') 'magnetic fields or static vector potentials are present.'
420 call messages_fatal(2, namespace=namespace)
421 end if
422
423 if (list_has_gauge_field(ext_partners)) then
424 write(message(1),'(a)') 'The forces are currently not properly calculated if gauge-field'
425 write(message(2),'(a)') 'is applied.'
426 call messages_fatal(2, namespace=namespace)
427 end if
428
429 ! As the constrain is attached to the position of the atom, it contribute to the forces
430 if (hm%magnetic_constrain%level /= constrain_none) then
431 call messages_not_implemented("Forces with MagneticConstrain /= constrain_none")
432 end if
433
434 if (hm%kpoints%use_symmetries .or. st%symmetrize_density) then
435 call symmetrize_force(ions, ions%tot_force)
436 end if
437
438 ! For periodic systems, we substract the averaged force
439 if (ions%space%is_periodic()) then
440 call forces_set_total_to_zero(ions, ions%tot_force)
441 end if
442
443 pop_sub(forces_calculate)
444 call profiling_out("FORCES")
445
446 end subroutine forces_calculate
447
448 ! ----------------------------------------------------------------------
449
450 subroutine forces_set_total_to_zero(ions, force)
451 type(ions_t), intent(in) :: ions
452 real(real64), intent(inout) :: force(:, :)
453
454 real(real64), allocatable :: total_force(:)
455 integer :: iatom
456
458
459 safe_allocate(total_force(1:ions%space%dim))
460
461 total_force(1:ions%space%dim) = sum(force, dim=2) / ions%natoms
462
463 do iatom = 1, ions%natoms
464 force(1:ions%space%dim, iatom) = force(1:ions%space%dim, iatom) - total_force(1:ions%space%dim)
465 end do
466
467 safe_deallocate_a(total_force)
469 end subroutine forces_set_total_to_zero
470
471 ! ----------------------------------------------------------------------
473 subroutine forces_compute_total_torque(ions, total_torque)
474 type(ions_t), intent(in) :: ions
475 real(real64), intent(inout) :: total_torque(:)
476
477 real(real64) :: center_of_mass(ions%space%dim), rr(3), ff(3)
478 integer :: iatom
479
481
482 center_of_mass = ions%center_of_mass()
483
484 total_torque = m_zero
485 rr = m_zero
486 ff = m_zero
487 do iatom = 1, ions%natoms
488 rr(1:ions%space%dim) = ions%pos(1:ions%space%dim, iatom) - center_of_mass
489 ff(1:ions%space%dim) = ions%tot_force(1:ions%space%dim, iatom)
490 total_torque(1:3) = total_torque(1:3) + dcross_product(rr, ff)
491 end do
492
494 end subroutine forces_compute_total_torque
495
496
497 ! ----------------------------------------------------------------------
498
499 subroutine forces_write_info(iunit, ions, dir, namespace)
500 integer, intent(in) :: iunit
501 type(ions_t), intent(in) :: ions
502 character(len=*), intent(in) :: dir
503 type(namespace_t), intent(in) :: namespace
504
505 integer :: iatom, idir, ii, iunit2
506 real(real64) :: torque(1:3)
507
508 if (.not. mpi_grp_is_root(mpi_world)) return
509
510 push_sub(forces_write_info)
511
512 write(iunit,'(3a)') 'Forces on the ions [', trim(units_abbrev(units_out%force)), "]"
513 write(iunit,'(a,10x,99(14x,a))') ' Ion', (index2axis(idir), idir = 1, ions%space%dim)
514 do iatom = 1, ions%natoms
515 write(iunit,'(i4,a10,10es17.8)') iatom, trim(ions%atom(iatom)%species%get_label()), &
516 units_from_atomic(units_out%force, ions%tot_force(:, iatom))
517 end do
518 write(iunit,'(1x,100a1)') ("-", ii = 1, 13 + ions%space%dim * 15)
519 write(iunit,'(a14, 10es17.8)') " Max abs force", &
520 (units_from_atomic(units_out%force, maxval(abs(ions%tot_force(idir, 1:ions%natoms)))), idir=1, ions%space%dim)
521 write(iunit,'(a14, 10es17.8)') " Total force", &
522 (units_from_atomic(units_out%force, sum(ions%tot_force(idir, 1:ions%natoms))), idir=1, ions%space%dim)
523
524 if (ions%space%dim == 2 .or. ions%space%dim == 3 .and. .not. ions%space%is_periodic()) then
525 call forces_compute_total_torque(ions, torque)
526 write(iunit,'(a14, 10es17.8)') ' Total torque', &
527 (units_from_atomic(units_out%force*units_out%length, torque(idir)), idir = 1, 3)
528 end if
529 write(iunit,'(1x)')
530
531
532 iunit2 = io_open(trim(dir)//'/forces', namespace, action='write', position='asis')
533 write(iunit2,'(a)') &
534 ' # Total force (x,y,z) Ion-Ion (x,y,z) VdW (x,y,z) Local (x,y,z) NL (x,y,z)' // &
535 ' Fields (x,y,z) Hubbard(x,y,z) SCF(x,y,z) NLCC(x,y,z) Phot (x,y,z)'
536 do iatom = 1, ions%natoms
537 write(iunit2,'(i4,a10,30es17.8)') iatom, trim(ions%atom(iatom)%species%get_label()), &
538 (units_from_atomic(units_out%force, ions%tot_force(idir, iatom)), idir=1, ions%space%dim), &
539 (units_from_atomic(units_out%force, ions%atom(iatom)%f_ii(idir)), idir=1, ions%space%dim), &
540 (units_from_atomic(units_out%force, ions%atom(iatom)%f_vdw(idir)), idir=1, ions%space%dim), &
541 (units_from_atomic(units_out%force, ions%atom(iatom)%f_loc(idir)), idir=1, ions%space%dim), &
542 (units_from_atomic(units_out%force, ions%atom(iatom)%f_nl(idir)), idir=1, ions%space%dim), &
543 (units_from_atomic(units_out%force, ions%atom(iatom)%f_fields(idir)), idir=1, ions%space%dim), &
544 (units_from_atomic(units_out%force, ions%atom(iatom)%f_u(idir)), idir=1, ions%space%dim), &
545 (units_from_atomic(units_out%force, ions%atom(iatom)%f_scf(idir)), idir=1, ions%space%dim), &
546 (units_from_atomic(units_out%force, ions%atom(iatom)%f_nlcc(idir)), idir=1, ions%space%dim), &
547 (units_from_atomic(units_out%force, ions%atom(iatom)%f_photons(idir)), idir=1, ions%space%dim)
548 end do
549 call io_close(iunit2)
550
551 pop_sub(forces_write_info)
552
553 end subroutine forces_write_info
554
555 ! ----------------------------------------------------------------------
556 ! This routine add the contribution to the forces from the nonlinear core correction
557 ! see Eq. 9 of Kronik et al., J. Chem. Phys. 115, 4322 (2001)
558 subroutine forces_from_nlcc(mesh, ions, spin_channels, vxc, force_nlcc)
559 class(mesh_t), intent(in) :: mesh
560 type(ions_t), intent(inout) :: ions
561 integer, intent(in) :: spin_channels
562 real(real64), intent(in) :: vxc(:,:)
563 real(real64), contiguous, intent(out) :: force_nlcc(:, :)
564
565 integer :: is, iatom, idir
566 real(real64), allocatable :: drho(:,:)
567
568
569 push_sub(forces_from_nlcc)
570
571 call profiling_in("FORCES_NLCC")
572
573 safe_allocate(drho(1:mesh%np, 1:ions%space%dim))
574
575 force_nlcc = m_zero
576
577 do iatom = ions%atoms_dist%start, ions%atoms_dist%end
578 call species_get_nlcc_grad(ions%atom(iatom)%species, ions%space, ions%latt, ions%pos(:, iatom), mesh, drho)
579
580 do idir = 1, ions%space%dim
581 do is = 1, spin_channels
582 force_nlcc(idir, iatom) = force_nlcc(idir, iatom) &
583 - dmf_dotp(mesh, drho(:,idir), vxc(1:mesh%np, is), reduce = .false.)/spin_channels
584 end do
585 end do
586 end do
587
588 safe_deallocate_a(drho)
589
590 if (ions%atoms_dist%parallel) call dforces_gather(ions, force_nlcc)
591
592 if (mesh%parallel_in_domains) then
593 call profiling_in("FORCES_COMM")
594 call mesh%allreduce(force_nlcc)
595 call profiling_out("FORCES_COMM")
596 end if
597
598 call profiling_out("FORCES_NLCC")
599
600 pop_sub(forces_from_nlcc)
601 end subroutine forces_from_nlcc
602
603 ! Implementation of the term from Chan et al., Phys. Rev. B 47, 4771 (1993).
604 ! Here we make the approximation that the "atomic densities" are just the one
605 ! from the pseudopotential.
606 ! NTD : No idea if this is good or bad, but this is easy to implement
607 ! and works well in practice
608 subroutine forces_from_scf(mesh, ions, spin_channels, vhxc, vhxc_old, force_scf)
609 class(mesh_t), intent(in) :: mesh
610 type(ions_t), intent(inout) :: ions
611 integer, intent(in) :: spin_channels
612 real(real64), intent(in) :: vhxc(:,:)
613 real(real64), intent(in) :: vhxc_old(:,:)
614 real(real64), contiguous, intent(out) :: force_scf(:, :)
615
616 integer :: is, iatom, idir
617 real(real64), allocatable :: dvhxc(:,:), drho(:,:,:)
618
619 push_sub(forces_from_scf)
620
621 call profiling_in("FORCES_SCF")
622
623 safe_allocate(dvhxc(1:mesh%np, 1:spin_channels))
624 safe_allocate(drho(1:mesh%np, 1:spin_channels, 1:ions%space%dim))
625
626 !We average over spin channels
627 do is = 1, spin_channels
628 dvhxc(1:mesh%np, is) = vhxc(1:mesh%np, is) - vhxc_old(1:mesh%np, is)
629 end do
630
631 force_scf = m_zero
632
633 do iatom = ions%atoms_dist%start, ions%atoms_dist%end
634 select type(spec=>ions%atom(iatom)%species)
635 type is(pseudopotential_t)
636
637 if (ps_has_density(spec%ps)) then
638
639 call species_atom_density_grad(spec, ions%namespace, ions%space, ions%latt, &
640 ions%pos(:, iatom), mesh, spin_channels, drho)
641
642 do idir = 1, ions%space%dim
643 do is = 1, spin_channels
644 force_scf(idir, iatom) = force_scf(idir, iatom) &
645 - dmf_dotp(mesh, drho(:,is,idir), dvhxc(:,is), reduce = .false.)
646 end do
647 end do
648 end if
649 end select
650 end do
652 safe_deallocate_a(dvhxc)
653 safe_deallocate_a(drho)
654
655 if (ions%atoms_dist%parallel) call dforces_gather(ions, force_scf)
656
657 if (mesh%parallel_in_domains) then
658 call profiling_in("FORCES_COMM")
659 call mesh%allreduce(force_scf)
660 call profiling_out("FORCES_COMM")
661 end if
662
663 call profiling_out("FORCES_SCF")
664
665 pop_sub(forces_from_scf)
666 end subroutine forces_from_scf
667
668 !---------------------------------------------------------------------------
669 subroutine total_force_from_local_potential(mesh, space, vpsl, gdensity, force)
670 class(mesh_t), intent(in) :: mesh
671 class(space_t), intent(in) :: space
672 real(real64), intent(in) :: vpsl(:)
673 real(real64), intent(in) :: gdensity(:, :)
674 real(real64), intent(inout) :: force(:)
675
676 integer :: idir
677 real(real64) :: force_tmp(1:space%dim)
678
680
681 do idir = 1, space%dim
682 force_tmp(idir) = dmf_dotp(mesh, vpsl(1:mesh%np), gdensity(:, idir), reduce = .false.)
683 end do
684
685 if (mesh%parallel_in_domains) call mesh%allreduce(force_tmp)
686
687 force(1:space%dim) = force(1:space%dim) + force_tmp(1:space%dim)
688
691
692 !---------------------------------------------------------------------------
694 subroutine symmetrize_force(ions, force)
695 type(ions_t), intent(in) :: ions
696 real(real64), intent(inout) :: force(:,:)
697
698 integer :: iatom, iop, iatom_symm
699 real(real64) :: symmetrized_force(ions%space%dim), force_tmp(ions%space%dim)
700 real(real64), allocatable :: force_sym(:,:)
702 push_sub(symmetrize_force)
703
704 safe_allocate(force_sym(1:ions%space%dim,1:ions%natoms))
705 do iatom = 1, ions%natoms
706 symmetrized_force = m_zero
707 do iop = 1, ions%symm%nops
708 iatom_symm = ions%inv_map_symm_atoms(iatom, iop)
709 force_tmp = symm_op_apply_inv_cart(ions%symm%ops(iop), force(:, iatom_symm))
710 symmetrized_force = symmetrized_force + force_tmp
711 end do
712
713 do iop = 1, ions%symm%nops_nonsymmorphic
714 iatom_symm = ions%inv_map_symm_atoms(iatom, iop + ions%symm%nops)
715 force_tmp = symm_op_apply_inv_cart(ions%symm%non_symmorphic_ops(iop), force(:, iatom_symm), rotation_only=.true.)
716 symmetrized_force = symmetrized_force + force_tmp
717 end do
718
719 force_sym(:, iatom) = symmetrized_force / (ions%symm%nops + ions%symm%nops_nonsymmorphic)
720 end do
721 force = force_sym
722
723 safe_deallocate_a(force_sym)
724
725 pop_sub(symmetrize_force)
726 end subroutine symmetrize_force
727
728
729#include "undef.F90"
730#include "real.F90"
731#include "forces_inc.F90"
732
733#include "undef.F90"
734#include "complex.F90"
735#include "forces_inc.F90"
736
737end module forces_oct_m
738
739!! Local Variables:
740!! mode: f90
741!! coding: utf-8
742!! End:
subroutine force1(qq, res, pdot3)
Definition: forces.F90:303
This module implements batches of mesh functions.
Definition: batch.F90:133
This module implements common operations on batches of mesh functions.
Definition: batch_ops.F90:116
Module implementing boundary conditions in Octopus.
Definition: boundaries.F90:122
This module implements a calculator for the density and defines related functions.
Definition: density.F90:120
This module calculates the derivatives (gradients, Laplacians, etc.) of a function.
subroutine, public zderivatives_grad(der, ff, op_ff, ghost_update, set_bc, to_cartesian)
apply the gradient to a mesh function
logical function, public list_has_gauge_field(partners)
type(lasers_t) function, pointer, public list_get_lasers(partners)
subroutine, public zforces_from_potential(gr, namespace, space, ions, hm, st, force, force_loc, force_nl, force_u)
Ref: Kikuji Hirose, Tomoya Ono, Yoshitaka Fujimoto, and Shigeru Tsukamoto, First-principles calculati...
Definition: forces.F90:1612
subroutine, public forces_costate_calculate(gr, namespace, ions, hm, psi, chi, ff, qq)
Definition: forces.F90:218
subroutine forces_from_scf(mesh, ions, spin_channels, vhxc, vhxc_old, force_scf)
Definition: forces.F90:702
subroutine symmetrize_force(ions, force)
Given the forces on all atoms, this symmetrizes them using symmorphic and non-symmorphic operations.
Definition: forces.F90:788
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:2032
subroutine forces_compute_total_torque(ions, total_torque)
Computes the total torque acting on the system.
Definition: forces.F90:567
subroutine, public forces_write_info(iunit, ions, dir, namespace)
Definition: forces.F90:593
subroutine forces_set_total_to_zero(ions, force)
Definition: forces.F90:544
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:989
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:1156
subroutine, public forces_calculate(gr, namespace, ions, hm, ext_partners, st, ks, vhxc_old, t, dt)
Definition: forces.F90:339
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:191
subroutine, public dforces_derivative(gr, namespace, space, ions, ep, st, kpoints, lr, lr2, force_deriv, lda_u_level)
Definition: forces.F90:1263
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:763
subroutine dforces_gather(ions, force)
Definition: forces.F90:890
subroutine forces_from_nlcc(mesh, ions, spin_channels, vxc, force_nlcc)
Definition: forces.F90:652
real(real64), parameter, public m_two
Definition: global.F90:190
real(real64), parameter, public p_proton_charge
Definition: global.F90:227
real(real64), parameter, public m_zero
Definition: global.F90:188
real(real64), parameter, public m_four
Definition: global.F90:192
complex(real64), parameter, public m_z0
Definition: global.F90:198
complex(real64), parameter, public m_zi
Definition: global.F90:202
real(real64), parameter, public m_one
Definition: global.F90:189
real(real64), parameter, public m_three
Definition: global.F90:191
This module implements the underlying real-space grid.
Definition: grid.F90:117
subroutine, public zhamiltonian_elec_apply_atom(hm, namespace, space, latt, species, pos, ia, mesh, psi, vpsi)
This module defines classes and functions for interaction partners.
Definition: io.F90:114
subroutine, public io_close(iunit, grp)
Definition: io.F90:418
integer function, public io_open(file, namespace, action, status, form, position, die, recl, grp)
Definition: io.F90:352
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:739
integer, parameter, public e_field_electric
Definition: lasers.F90:177
integer, parameter, public e_field_vector_potential
Definition: lasers.F90:177
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:1191
integer, parameter, public e_field_scalar_potential
Definition: lasers.F90:177
integer pure elemental function, public laser_kind(laser)
Definition: lasers.F90:715
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:1115
integer, parameter, public e_field_magnetic
Definition: lasers.F90:177
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:115
pure real(real64) function, dimension(1:3), public dcross_product(a, b)
Definition: math.F90:1859
This module defines various routines, operating on mesh functions.
This module defines the meshes, which are used in Octopus.
Definition: mesh.F90:118
subroutine, public messages_not_implemented(feature, namespace)
Definition: messages.F90:1113
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
Definition: messages.F90:160
subroutine, public messages_fatal(no_lines, only_root_writes, namespace)
Definition: messages.F90:414
logical function mpi_grp_is_root(grp)
Is the current MPI process of grpcomm, root.
Definition: mpi.F90:430
type(mpi_grp_t), public mpi_world
Definition: mpi.F90:266
subroutine, public profiling_out(label)
Increment out counter and sum up difference between entry and exit time.
Definition: profiling.F90:623
subroutine, public profiling_in(label, exclude)
Increment in counter and save entry time.
Definition: profiling.F90:552
Definition: ps.F90:114
pure logical function, public ps_has_density(ps)
Definition: ps.F90:1645
subroutine, public species_get_nlcc_grad(species, space, latt, pos, mesh, rho_core_grad, gnlcc_x)
subroutine, public species_atom_density_grad(species, namespace, space, latt, pos, mesh, spin_channels, drho)
pure logical function, public states_are_real(st)
This module handles spin dimensions of the states and the k-point distribution.
brief This module defines the class unit_t which is used by the unit_systems_oct_m module.
Definition: unit.F90:132
character(len=20) pure function, public units_abbrev(this)
Definition: unit.F90:223
This module defines the unit system, used for input and output.
type(unit_system_t), public units_out
This module is intended to contain simple general-purpose utility functions and procedures.
Definition: utils.F90:118
character pure function, public index2axis(idir)
Definition: utils.F90:202
Tkatchenko-Scheffler pairwise method for van der Waals (vdW, dispersion) interactions.
Definition: vdw_ts.F90:119
subroutine, public vdw_ts_force_calculate(this, force_vdw, ions, mesh, nspin, density)
Definition: vdw_ts.F90:427
Description of the grid, containing information on derivatives, stencil, and symmetries.
Definition: grid.F90:168
Describes mesh distribution to nodes.
Definition: mesh.F90:186
The states_elec_t class contains all electronic wave functions.
int true(void)