Octopus
stress.F90
Go to the documentation of this file.
1!! Copyright (C) 2002-2016 M. Marques, A. Castro, A. Rubio, G. Bertsch
2!! Copyright (C) 2023 N. Tancogne-Dejean
3!!
4!! This program is free software; you can redistribute it and/or modify
5!! it under the terms of the GNU General Public License as published by
6!! the Free Software Foundation; either version 2, or (at your option)
7!! any later version.
8!!
9!! This program is distributed in the hope that it will be useful,
10!! but WITHOUT ANY WARRANTY; without even the implied warranty of
11!! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12!! GNU General Public License for more details.
13!!
14!! You should have received a copy of the GNU General Public License
15!! along with this program; if not, write to the Free Software
16!! Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17!! 02110-1301, USA.
18!!
19
20#include "global.h"
21
22! ---------------------------------------------------------
25module stress_oct_m
28 use comm_oct_m
29 use debug_oct_m
33 use energy_oct_m
35 use epot_oct_m
36 use global_oct_m
37 use grid_oct_m
39 use io_oct_m
41 use ions_oct_m
43 use, intrinsic :: iso_fortran_env
46 use lda_u_oct_m
48 use math_oct_m
49 use mesh_oct_m
53 use mpi_oct_m
58 use ps_oct_m
60 use space_oct_m
70 use types_oct_m
71 use unit_oct_m
73 use v_ks_oct_m
75 use xc_oct_m
76 use xc_f03_lib_m
78 implicit none
79
80 private
81 public :: &
85
86contains
87
88 ! ---------------------------------------------------------
90 subroutine stress_calculate(namespace, gr, hm, st, ions, ks, ext_partners)
91 type(namespace_t), intent(in) :: namespace
92 type(grid_t), intent(inout) :: gr
93 type(hamiltonian_elec_t), intent(inout) :: hm
94 type(states_elec_t), target, intent(inout) :: st
95 type(ions_t), intent(inout) :: ions
96 type(v_ks_t), intent(in) :: ks
97 type(partner_list_t), intent(in) :: ext_partners
98
99 real(real64), allocatable :: rho_total(:)
100 real(real64) :: stress(3,3) ! stress tensor in Cartesian coordinate
101 real(real64) :: stress_kin(3,3), stress_Hartree(3,3), stress_xc(3,3), stress_xc_nlcc(3,3)
102 real(real64) :: stress_ps(3,3), stress_ps_nl(3,3), stress_ps_local(3,3), stress_ii(3,3)
103 real(real64) :: stress_hubbard(3,3)
104 integer :: ip
105 real(real64), allocatable :: vh(:)
106 real(real64), allocatable :: grad_vh(:,:)
107 real(real64) :: ehartree
108 real(real64), contiguous, pointer :: rho(:)
109
110 call profiling_in("STRESS_CALCULATE")
111 push_sub(stress_calculate)
112
113 if (st%wfs_type /= type_cmplx) then
114 write(message(1),'(a)') 'The stress tensors for real wavefunctions has not been implemented!'
115
116 if (hm%kpoints%full%npoints == 1) then
117 write(message(2),'(a)') 'For testing this feature, you can add ForceComplex=yes to the input file'
118 call messages_fatal(2, namespace=namespace)
119 end if
120
121 call messages_fatal(1, namespace=namespace)
122 end if
123
124 if (ions%space%periodic_dim == 1) then
125 call messages_not_implemented("Stress tensor for 1D periodic systems", namespace=namespace)
126 end if
127
128 if ( .not. (ks%theory_level == kohn_sham_dft .and. in_family(hm%xc%family, [xc_family_lda, xc_family_gga])) &
129 .and. .not. (ks%theory_level == independent_particles)) then
130 write(message(1),'(a)') 'The stress tensor computation is currently only possible at the Kohn-Sham DFT level'
131 write(message(2),'(a)') 'with LDA and GGA functionals or for independent particles.'
132 call messages_fatal(2, namespace=namespace)
133 end if
134
135 if (in_family(hm%xc%family, [xc_family_gga]) .and. st%d%ispin == spinors) then
136 call messages_not_implemented("Stress tensor for GGAs with spinors", namespace=namespace)
137 end if
138
139 if (ks%vdw%vdw_correction /= option__vdwcorrection__none .and. .not. any(ks%vdw%vdw_correction == d3_lib_options)) then
140 write(message(1),'(a)') 'The stress tensor is currently only implemented with DFT-D3 vdW correction'
141 call messages_fatal(1, namespace=namespace)
142 end if
143
144 if (hm%pcm%run_pcm) then
145 call messages_not_implemented('Stress tensor with PCM')
146 end if
147
148 if (allocated(hm%v_static)) then
149 call messages_not_implemented('Stress tensor with static electric fields')
150 end if
151
152 if (ks%has_photons) then
153 call messages_not_implemented('Stress tensor with photon modes')
154 end if
155
156 if (.not. hm%vnl%apply_projector_matrices) then
157 call messages_not_implemented('Stress tensor with relativistic Kleinman-Bylander pseudopotential')
158 end if
159
160 if (hm%ep%reltype == scalar_relativistic_zora .or. hm%ep%reltype == fully_relativistic_zora) then
161 call messages_not_implemented('Stress tensor with ZORA')
162 end if
163
164 stress(:,:) = m_zero
165
166 safe_allocate(rho_total(1:gr%np_part))
167 do ip = 1, gr%np
168 rho_total(ip) = sum(st%rho(ip, 1:st%d%nspin))
169 end do
170
171 ! As we rely on some of the full energy components, we need to recompute it first
172 ! TODO: We should restrict the components of the energy needed to be computed
173 call energy_calc_total(namespace, ions%space, hm, gr, st, ext_partners, iunit = 0, full = .true.)
174
175 ! In order to get the electrostatic part (Hartree and local pseudopotential part),
176 ! we need to get the Hartree potential and its gradient
177 safe_allocate(vh(1:gr%np_part))
178 safe_allocate(grad_vh(1:gr%np, 1:gr%der%dim))
179 if (ks%theory_level /= independent_particles) then
180 call lalg_copy(gr%np, hm%vhartree, vh)
181 else
182 if (poisson_solver_is_iterative(hm%psolver)) then
183 vh(1:gr%np) = m_zero
184 end if
185 if (hm%d%spin_channels > 1) then
186 safe_allocate(rho(1:gr%np_part))
187 call lalg_copy(gr%np, st%rho(:,1), rho)
188 call lalg_axpy(gr%np, m_one, st%rho(:,2), rho)
189 else
190 rho => st%rho(:,1)
191 end if
192 ! In the case of independent particles, we use the electron density without NLCC
193 call dpoisson_solve(hm%psolver, ions%namespace, vh, rho, all_nodes = .true.)
194 if (hm%d%spin_channels > 1) then
195 safe_deallocate_p(rho)
196 else
197 nullify(rho)
198 end if
199 end if
200 ehartree = hm%energy%hartree
201 ! We also compute the gradient here
202 call dderivatives_grad(gr%der, vh, grad_vh)
203
204 ! We now compute the various contributions to the stress tensor
205
206 ! Stress from kinetic energy of electrons
207 call stress_from_kinetic(gr, ions%space, hm, st, gr%symm, ions%latt%rcell_volume, stress_kin)
208 stress = stress + stress_kin
209
210 if (ks%theory_level == independent_particles) then
211 stress_hartree = m_zero
212 stress_xc = m_zero
213 else
214 call stress_from_hartree(gr, ions%space, ions%latt%rcell_volume, vh, grad_vh, ehartree, stress_hartree)
215 stress = stress + stress_hartree
216
217 call stress_from_xc(hm%energy, ions%latt%rcell_volume, ions%space%periodic_dim, stress_xc)
218
219 ! Nonlinear core correction contribution
220 if (allocated(st%rho_core)) then
221 call stress_from_xc_nlcc(ions%latt%rcell_volume, gr, st, ions, hm%vxc, stress_xc_nlcc)
222 stress_xc = stress_xc + stress_xc_nlcc
223 end if
224 ! Adds the beyond LDA contribution to the stress tensor
225 stress_xc = stress_xc + ks%stress_xc_gga / ions%latt%rcell_volume
226 stress = stress + stress_xc
227 end if
228
229 call stress_from_pseudo_local(gr, st, hm, ions, rho_total, vh, grad_vh, stress_ps_local)
230 stress_ps = stress_ps_local
231 stress = stress + stress_ps_local
232
233 safe_deallocate_a(vh)
234 safe_deallocate_a(grad_vh)
235
236 call stress_from_pseudo_nonloc(gr, st, hm, ions, stress_ps_nl)
237 stress_ps = stress_ps + stress_ps_nl
238 stress = stress + stress_ps_nl
239
240 call stress_from_hubbard(namespace, gr, st, hm, ions%space, ions%latt%rcell_volume, stress_hubbard)
241 stress = stress + stress_hubbard
242
243 call ion_interaction_stress(ions%ion_interaction, ions%space, ions%latt, ions%atom, ions%natoms, ions%pos, stress_ii)
244 stress = stress + stress_ii
245 ! Stress from kinetic energy of ion
246 ! Stress from ion-field interaction
247
248 ! Sign changed to fit conventional definition
249 stress = -stress
250
251 st%stress_tensors%kinetic = stress_kin
252 st%stress_tensors%Hartree = stress_hartree
253 st%stress_tensors%xc = stress_xc
254 st%stress_tensors%ps_local = stress_ps_local
255 st%stress_tensors%ps_nl = stress_ps_nl
256 st%stress_tensors%hubbard = stress_hubbard
257 st%stress_tensors%ion_ion = stress_ii
258
259 ! Stress contribution from vdW D3
260 if (ks%vdw%vdw_correction /= option__vdwcorrection__none) then
261 st%stress_tensors%vdw = hm%ep%vdw_stress
262 else
263 st%stress_tensors%vdw = m_zero
264 end if
265 stress = stress + st%stress_tensors%vdw
266
267 ! Symmetrize the stress tensor if we use k-point symmetries
268 if (hm%kpoints%use_symmetries) then
269 call dsymmetrize_tensor_cart(gr%symm, stress, use_non_symmorphic=.true.)
270 ! We guarantee that the matrix is truely symmetric. There could be small numerical assymetries after symmetrization
271 call dsymmetrize_matrix(ions%space%periodic_dim, stress)
272 end if
273
274 st%stress_tensors%total = stress
275
276 ! Some sumrule for validation
277 ! Sumrule is -3P_{kin}\Omega = 2 E_{kin}
278 st%stress_tensors%kinetic_sumrule = m_zero
279 ! Sumrule is -3P_{Hartree}\Omega = E_{Hartree}
280 st%stress_tensors%Hartree_sumrule = m_zero
281 if(ions%space%periodic_dim == 3) then
282 st%stress_tensors%kinetic_sumrule = (stress_kin(1,1) + stress_kin(2,2) + stress_kin(3,3))*ions%latt%rcell_volume
283 st%stress_tensors%kinetic_sumrule = st%stress_tensors%kinetic_sumrule - m_two * hm%energy%kinetic
284
285 st%stress_tensors%hartree_sumrule = (stress_hartree(1,1) + stress_hartree(2,2) + stress_hartree(3,3))*ions%latt%rcell_volume
286 st%stress_tensors%hartree_sumrule = st%stress_tensors%hartree_sumrule - hm%energy%hartree
287 end if
288
289 safe_deallocate_a(rho_total)
290
291 pop_sub(stress_calculate)
292 call profiling_out("STRESS_CALCULATE")
293 end subroutine stress_calculate
294
295 ! -------------------------------------------------------
310 subroutine stress_from_kinetic(gr, space, hm, st, symm, rcell_volume, stress_kin)
311 type(grid_t), intent(in) :: gr
312 class(space_t), intent(in) :: space
313 type(hamiltonian_elec_t), intent(in) :: hm
314 type(states_elec_t), intent(inout) :: st
315 type(symmetries_t), intent(in) :: symm
316 real(real64), intent(in) :: rcell_volume
317 real(real64), intent(out) :: stress_kin(3, 3)
318
319 integer :: ik, ist, idir, jdir, ib, minst, maxst
320 complex(real64), allocatable :: stress_l_block(:)
321 type(wfs_elec_t) :: psib, gpsib(space%dim)
322
323 call profiling_in("STRESS_FROM_KINETIC")
324 push_sub(stress_from_kinetic)
325
326 stress_kin(:,:) = m_zero
327
328 safe_allocate(stress_l_block(1:st%block_size))
329
330 do ik = st%d%kpt%start, st%d%kpt%end
331 if (st%kweights(ik) <= m_epsilon) cycle
332
333 do ib = st%group%block_start, st%group%block_end
334 minst = states_elec_block_min(st, ib)
335 maxst = states_elec_block_max(st, ib)
336
337 call hamiltonian_elec_copy_and_set_phase(hm, gr, st%d%kpt, st%group%psib(ib, ik), psib)
338
339 ! calculate the gradient
340 call zderivatives_batch_grad(gr%der, psib, gpsib, set_bc=.false.)
341
342 ! Accumulate the result
343 do idir = 1, space%periodic_dim
344 do jdir = idir, space%periodic_dim
345 call zmesh_batch_dotp_vector(gr, gpsib(idir), gpsib(jdir), stress_l_block)
346
347 do ist = minst, maxst
348 stress_kin(idir,jdir) = stress_kin(idir,jdir) &
349 + st%kweights(ik) * st%occ(ist, ik) &
350 * real(stress_l_block(ist - minst + 1), real64)
351 end do
352 end do
353 end do
354
355 do idir = 1, space%dim
356 call gpsib(idir)%end()
357 end do
358 call psib%end()
359
360 end do
361 end do
362
363 if (st%parallel_in_states .or. st%d%kpt%parallel) then
364 call comm_allreduce(st%st_kpt_mpi_grp, stress_kin)
365 end if
366
367
368 ! Symmetrize the kinetic stress tensor
369 call upper_triangular_to_hermitian(space%periodic_dim, stress_kin)
370
371 ! Symmetrize the stress tensor if we use k-point symmetries
372 if (hm%kpoints%use_symmetries) then
373 call dsymmetrize_tensor_cart(symm, stress_kin, use_non_symmorphic=.true.)
374 end if
375
376 stress_kin = stress_kin / rcell_volume
377
378 call profiling_out("STRESS_FROM_KINETIC")
379 pop_sub(stress_from_kinetic)
380 end subroutine stress_from_kinetic
381
382 ! -------------------------------------------------------
399 subroutine stress_from_hartree(gr, space, volume, vh, grad_vh, ehartree, stress_Hartree)
400 type(grid_t), intent(in) :: gr
401 class(space_t), intent(in) :: space
402 real(real64), intent(in) :: volume
403 real(real64), intent(in) :: vh(:)
404 real(real64), intent(in) :: grad_vh(:,:)
405 real(real64), intent(in) :: ehartree
406 real(real64), intent(out) :: stress_Hartree(3, 3)
407
408 integer :: idir, jdir
409
410 call profiling_in("STRESS_FROM_HARTREE")
411 push_sub(stress_from_hartree)
412
413 stress_hartree(:,:) = m_zero
414
415 do idir = 1, space%periodic_dim
416 do jdir = idir, space%periodic_dim
417 stress_hartree(idir, jdir) = -dmf_dotp(gr, grad_vh(:,idir), grad_vh(:, jdir))/m_four/m_pi
418 end do
419 stress_hartree(idir, idir) = stress_hartree(idir, idir) + ehartree
420 end do
421
422 call upper_triangular_to_hermitian(space%periodic_dim, stress_hartree)
423
424 stress_hartree = stress_hartree/volume
425
426 call profiling_out("STRESS_FROM_HARTREE")
427 pop_sub(stress_from_hartree)
428 end subroutine stress_from_hartree
429
430
431 ! -------------------------------------------------------
445 !
446 ! Note: We assume hm%energy%echange, correlation, and intnvxc
447 ! have already been calculated somewhere else.
448 subroutine stress_from_xc(energy, rcell_volume, periodic_dim, stress_xc)
449 type(energy_t), intent(in) :: energy
450 real(real64), intent(in) :: rcell_volume
451 integer, intent(in) :: periodic_dim
452 real(real64), intent(out) :: stress_xc(3, 3)
453
454 integer :: idir
455
456 call profiling_in("STRESS_FROM_XC")
457 push_sub(stress_from_xc)
458
459 stress_xc = m_zero
460 do idir = 1, periodic_dim
461 stress_xc(idir, idir) = - energy%exchange - energy%correlation + energy%intnvxc
462 end do
463 stress_xc(:,:) = stress_xc(:,:) / rcell_volume
464
465 call profiling_out("STRESS_FROM_XC")
466 pop_sub(stress_from_xc)
467 end subroutine stress_from_xc
468
469
470 ! -------------------------------------------------------
477 subroutine stress_from_xc_nlcc(rcell_volume, gr, st, ions, vxc, stress_xc_nlcc)
478 real(real64), intent(in) :: rcell_volume
479 type(grid_t), intent(in) :: gr
480 type(states_elec_t), intent(in) :: st
481 type(ions_t), intent(in) :: ions
482 real(real64), intent(in) :: vxc(:,:)
483 real(real64), intent(out) :: stress_xc_nlcc(3, 3)
484
485 integer :: idir, jdir, iat
486 real(real64), allocatable :: gnlcc(:,:), gnlcc_x(:,:,:), vxc_tot(:)
487
488 call profiling_in("STRESS_FROM_XC_NLCC")
489 push_sub(stress_from_xc_nlcc)
490
491 assert(allocated(st%rho_core))
493 stress_xc_nlcc = m_zero
494
495 ! We first accumulate the contribution from all the pseudo-ions
496 safe_allocate(gnlcc(gr%np, gr%der%dim))
497 safe_allocate(gnlcc_x(gr%np, gr%der%dim, gr%der%dim))
498 gnlcc_x = m_zero
499 do iat = ions%atoms_dist%start, ions%atoms_dist%end
500 assert(ions%atom(iat)%species%is_ps())
501 call species_get_nlcc_grad(ions%atom(iat)%species, ions%space, ions%latt, &
502 ions%pos(:,iat), gr, gnlcc, gnlcc_x)
503 end do
504 safe_deallocate_a(gnlcc)
505
506 if (ions%atoms_dist%parallel) then
507 call comm_allreduce(ions%atoms_dist%mpi_grp, gnlcc_x)
508 end if
509
510 ! Sum over spin of the xc potential
511 safe_allocate(vxc_tot(1:gr%np))
512 vxc_tot = vxc(1:gr%np, 1)
513 if(st%d%nspin > 1) vxc_tot = vxc_tot + vxc(1:gr%np, 2)
514
515 do idir = 1, ions%space%periodic_dim
516 do jdir = idir, ions%space%periodic_dim
517 stress_xc_nlcc(idir, jdir) = dmf_dotp(gr, vxc_tot, gnlcc_x(:,idir, jdir))
518 end do
519 end do
520 safe_deallocate_a(vxc_tot)
521 safe_deallocate_a(gnlcc_x)
522
523 call upper_triangular_to_hermitian(ions%space%periodic_dim, stress_xc_nlcc)
524
525 stress_xc_nlcc(:,:) = stress_xc_nlcc(:,:) / rcell_volume
526
527 call profiling_out("STRESS_FROM_XC_NLCC")
528 pop_sub(stress_from_xc_nlcc)
529 end subroutine stress_from_xc_nlcc
530
531 ! -------------------------------------------------------
550 subroutine stress_from_pseudo_nonloc(gr, st, hm, ions, stress_ps_nl)
551 type(grid_t), target, intent(in) :: gr
552 type(states_elec_t), intent(inout) :: st
553 type(hamiltonian_elec_t), intent(in) :: hm
554 type(ions_t), intent(in) :: ions
555 real(real64), intent(out) :: stress_ps_nl(3, 3)
556
557 integer :: ik, ist, idir, jdir
558 integer :: ib, minst, maxst
559 type(wfs_elec_t) :: psib, rvnl_psib(3), gpsib(3)
560 complex(real64), allocatable :: stress_tmp(:)
561
562 call profiling_in("STRESS_FROM_PSEUDO_NL")
564
565 assert(st%wfs_type == type_cmplx)
566
567 safe_allocate(stress_tmp(1:st%block_size))
568
569 stress_ps_nl = m_zero
571 do ik = st%d%kpt%start, st%d%kpt%end
572
573 if (st%kweights(ik) <= m_epsilon) cycle
574
575 do ib = st%group%block_start, st%group%block_end
576 minst = states_elec_block_min(st, ib)
577 maxst = states_elec_block_max(st, ib)
578
579 call hamiltonian_elec_copy_and_set_phase(hm, gr, st%d%kpt, st%group%psib(ib, ik), psib)
580
581 ! calculate the gradient
582 call zderivatives_batch_grad(gr%der, psib, gpsib, set_bc=.false.)
583
584
585 ! Get rV_NL |\psi> for all atoms
586 do idir = 1, gr%der%dim
587 call psib%copy_to(rvnl_psib(idir))
588 call batch_set_zero(rvnl_psib(idir))
589 end do
590 call hm%vnl%zr_vn_local(gr, st%d, gr%der%boundaries%spiral, psib, rvnl_psib)
591
592 do idir = 1, ions%space%periodic_dim
593 do jdir = idir, ions%space%periodic_dim
594 call zmesh_batch_dotp_vector(gr, gpsib(idir), rvnl_psib(jdir), stress_tmp)
595
596 do ist = minst, maxst
597 stress_ps_nl(idir, jdir) = stress_ps_nl(idir, jdir) &
598 + m_two * st%kweights(ik) * st%occ(ist, ik) * real(stress_tmp(ist-minst+1), real64)
599 end do
600
601 end do
602 end do
603
604 do idir = 1, gr%der%dim
605 call rvnl_psib(idir)%end()
606 call gpsib(idir)%end()
607 end do
608 call psib%end()
609 end do
610 end do
611
612 safe_deallocate_a(stress_tmp)
613
614 if (st%parallel_in_states .or. st%d%kpt%parallel) then
615 call comm_allreduce(st%st_kpt_mpi_grp, stress_ps_nl)
616 end if
617
618 ! Symmetrize the kinetic stress tensor
619 call upper_triangular_to_hermitian(ions%space%periodic_dim, stress_ps_nl)
620
621 ! Symmetrize the stress tensor if we use k-point symmetries
622 if (hm%kpoints%use_symmetries) then
623 call dsymmetrize_tensor_cart(gr%symm, stress_ps_nl, use_non_symmorphic=.true.)
624 end if
625
626 ! Add the nonlocal energy
627 do idir = 1, ions%space%periodic_dim
628 stress_ps_nl(idir, idir) = stress_ps_nl(idir, idir) + hm%energy%extern_non_local
629 end do
630
631 stress_ps_nl = stress_ps_nl/ions%latt%rcell_volume
632
633 call profiling_out("STRESS_FROM_PSEUDO_NL")
635
636 end subroutine stress_from_pseudo_nonloc
637
638
639 ! -------------------------------------------------------
656 subroutine stress_from_pseudo_local(gr, st, hm, ions, rho_total, vh, grad_vh, stress_ps_local)
657 type(grid_t), target, intent(in) :: gr
658 type(states_elec_t), intent(inout) :: st
659 type(hamiltonian_elec_t), intent(in) :: hm
660 type(ions_t), intent(in) :: ions
661 real(real64), contiguous, intent(inout) :: rho_total(:)
662 real(real64), intent(in) :: vh(:)
663 real(real64), intent(in) :: grad_vh(:,:)
664 real(real64), intent(out) :: stress_ps_local(3, 3)
665
666
667 real(real64) :: stress_SR(3, 3), stress_LR(3, 3)
668 real(real64) :: energy_ps_SR, charge, zi
669 real(real64), allocatable :: vloc(:), rvloc(:,:), rho_local_lr(:), rho_lr(:)
670 real(real64), allocatable :: grad_rho(:,:), rho_lr_x(:,:), vlr(:), grad_vlr(:,:)
671 integer :: idir, jdir, iatom
672 type(ps_t), pointer :: spec_ps
673
674 call profiling_in("STRESS_FROM_PSEUDO_LOC")
676
677 ! calculate stress from short-range local pseudopotentials
678 stress_sr = m_zero
679
680 safe_allocate(vloc(1:gr%np))
681 vloc = m_zero
682 safe_allocate(rvloc(1:gr%np, 1:gr%der%dim))
683 rvloc = m_zero
684 do iatom = 1, ions%natoms
685 call epot_local_pseudopotential_sr(gr, ions, iatom, vloc, rvloc)
686 end do
687 safe_deallocate_a(vloc)
688
689 safe_allocate(grad_rho(1:gr%np,1:gr%der%dim))
690 call dderivatives_grad(gr%der, rho_total, grad_rho)
691
692 energy_ps_sr = hm%energy%extern_local
693 do idir = 1, ions%space%periodic_dim
694 do jdir = idir, ions%space%periodic_dim
695 stress_sr(idir, jdir) = stress_sr(idir, jdir) &
696 +dmf_dotp(gr, rvloc(:, jdir), grad_rho(:, idir))
697 end do
698 stress_sr(idir,idir) = stress_sr(idir,idir) + energy_ps_sr
699 end do
700
701 call upper_triangular_to_hermitian(ions%space%periodic_dim, stress_sr)
702
703 stress_sr = stress_sr/ions%latt%rcell_volume
704
705 safe_deallocate_a(rvloc)
706 safe_deallocate_a(grad_rho)
707
708
709 ! calculate stress from long-range local pseudopotentials
710 stress_lr = m_zero
711
712 ! We treat the long-range part of the local potential as the Hartree term
713 ! We first sum the long range densities from atoms
714 safe_allocate(rho_lr(1:gr%np_part))
715 safe_allocate(rho_lr_x(1:gr%np, 1:gr%der%dim))
716 rho_lr = m_zero
717 rho_lr_x = m_zero
718 safe_allocate(rho_local_lr(1:gr%np))
719 do iatom = ions%atoms_dist%start, ions%atoms_dist%end
720 assert(ions%atom(iatom)%species%is_ps())
721 call species_get_long_range_density(ions%atom(iatom)%species, ions%namespace, ions%space, ions%latt, &
722 ions%pos(:, iatom), gr, rho_local_lr, nlr_x=rho_lr_x)
723
724 call lalg_axpy(gr%np, m_one, rho_local_lr, rho_lr)
725 end do
726 safe_deallocate_a(rho_local_lr)
727
728 if (ions%atoms_dist%parallel) then
729 call comm_allreduce(ions%atoms_dist%mpi_grp, rho_lr)
730 call comm_allreduce(ions%atoms_dist%mpi_grp, rho_lr_x)
731 end if
732
733 do idir = 1, ions%space%periodic_dim
734 do jdir = idir, ions%space%periodic_dim
735 stress_lr(idir, jdir) = stress_lr(idir, jdir) + dmf_dotp(gr, rho_lr_x(:,jdir), grad_vh(:, idir))
736 end do
737 end do
738 safe_deallocate_a(rho_lr_x)
739
740 safe_allocate(vlr(1:gr%np_part))
741 if (poisson_solver_is_iterative(hm%psolver)) then
742 ! vl has to be initialized before entering routine
743 ! and our best guess for the potential is zero
744 vlr(1:gr%np) = m_zero
745 end if
746 call dpoisson_solve(hm%psolver, ions%namespace, vlr, rho_lr, all_nodes = .true.)
747 safe_deallocate_a(rho_lr)
748
749 safe_allocate(grad_vlr(1:gr%np, 1:gr%der%dim))
750 call dderivatives_grad(gr%der, vlr, grad_vlr)
751 safe_deallocate_a(vlr)
752
753 do idir = 1, ions%space%periodic_dim
754 do jdir = idir, ions%space%periodic_dim
755 stress_lr(idir, jdir) = stress_lr(idir, jdir) - dmf_dotp(gr, grad_vh(:,idir), grad_vlr(:, jdir))/m_two/m_pi
756 end do
757 end do
758
759 call upper_triangular_to_hermitian(ions%space%periodic_dim, stress_lr)
760
761 safe_deallocate_a(grad_vlr)
762
763 ! Contribution from G=0 component of the long-range part
764 !
765 if (ions%space%periodic_dim == 3) then
766 charge = m_zero
767 do iatom = 1, ions%natoms
768 charge = charge + ions%atom(iatom)%species%get_zval()
769 end do
770
771 do iatom = 1, ions%natoms
772 select type(spec => ions%atom(iatom)%species)
773 type is(pseudopotential_t)
774 zi = spec%get_zval()
775 spec_ps => spec%ps
776
777 do idir = 1, ions%space%periodic_dim
778 stress_lr(idir, idir) = stress_lr(idir, idir) &
779 + m_two*m_pi*spec_ps%sigma_erf**2*charge*zi /ions%latt%rcell_volume
780 end do
781 end select
782 end do
783 end if
784
785 stress_lr = stress_lr/ions%latt%rcell_volume
786
787 stress_ps_local = stress_sr + stress_lr
788
789 call profiling_out("STRESS_FROM_PSEUDO_LOC")
791
792 end subroutine stress_from_pseudo_local
793
794 ! -------------------------------------------------------
795 subroutine epot_local_pseudopotential_sr(mesh, ions, iatom, vpsl, rvpsl)
796 class(mesh_t), intent(in) :: mesh
797 type(ions_t), intent(in) :: ions
798 integer, intent(in) :: iatom
799 real(real64), intent(inout) :: vpsl(:)
800 real(real64), intent(inout) :: rvpsl(:,:)
801
802 integer :: ip
803 real(real64) :: radius, vl_ip
804 type(submesh_t) :: sphere
805 type(ps_t), pointer :: ps
806
808
809 if (.not. ions%atom(iatom)%species%is_ps()) then
811 return
812 endif
813
814 call profiling_in("EPOT_LOCAL_PS_SR")
815
816 select type(spec=>ions%atom(iatom)%species)
817 type is(pseudopotential_t)
818
819 ps => spec%ps
820
821 radius = ps%vl%x_threshold*1.05_real64
822
823 call submesh_init(sphere, ions%space, mesh, ions%latt, ions%pos(:, iatom), radius)
824
825 ! Cannot be written (correctly) as a vector expression since for periodic systems,
826 ! there can be values ip, jp such that sphere%map(ip) == sphere%map(jp).
827 do ip = 1, sphere%np
828 vl_ip = spline_eval(ps%vl, sphere%r(ip))
829 vpsl(sphere%map(ip)) = vpsl(sphere%map(ip)) + vl_ip
830 rvpsl(sphere%map(ip), 1:ions%space%periodic_dim) = rvpsl(sphere%map(ip), 1:ions%space%periodic_dim) &
831 + sphere%rel_x(1:ions%space%periodic_dim, ip) * vl_ip
832 end do
833
834 call submesh_end(sphere)
835
836 nullify(ps)
837
838 end select
839
840 call profiling_out("EPOT_LOCAL_PS_SR")
842 end subroutine epot_local_pseudopotential_sr
843
844
845 ! -------------------------------------------------------
859 subroutine stress_from_hubbard(namespace, gr, st, hm, space, rcell_volume, stress_hubbard)
860 type(namespace_t), intent(in) :: namespace
861 type(grid_t), target, intent(in) :: gr
862 type(states_elec_t), intent(inout) :: st
863 type(hamiltonian_elec_t), intent(in) :: hm
864 type(space_t), intent(in) :: space
865 real(real64), intent(in) :: rcell_volume
866 real(real64), intent(out) :: stress_hubbard(3, 3)
867
868 integer :: ik, ist, idir, jdir
869 integer :: ib, minst, maxst
870 type(wfs_elec_t) :: psib, rvu_psib(3), gpsib(3)
871 complex(real64), allocatable :: stress_tmp(:)
872
873 if (hm%lda_u%level == dft_u_none) then
874 stress_hubbard = m_zero
875 return
876 end if
877
878 push_sub_with_profile(stress_from_hubbard)
879
880 assert(st%wfs_type == type_cmplx)
881
882 safe_allocate(stress_tmp(1:st%block_size))
883
884 stress_hubbard = m_zero
885
886 do ik = st%d%kpt%start, st%d%kpt%end
887
888 if (st%kweights(ik) <= m_epsilon) cycle
889
890 do ib = st%group%block_start, st%group%block_end
891 minst = states_elec_block_min(st, ib)
892 maxst = states_elec_block_max(st, ib)
893
894 call hamiltonian_elec_copy_and_set_phase(hm, gr, st%d%kpt, st%group%psib(ib, ik), psib)
895
896 ! calculate the gradient
897 call zderivatives_batch_grad(gr%der, psib, gpsib, set_bc=.false.)
898
899 ! Get rV_U |\psi> for all atoms
900 do idir = 1, gr%der%dim
901 call psib%copy_to(rvu_psib(idir))
902 call batch_set_zero(rvu_psib(idir))
903 end do
904
905 call zlda_u_rvu(hm%lda_u, gr, space, hm%d, namespace, psib, rvu_psib)
906
907 do idir = 1,3
908 do jdir = idir,3
909 call zmesh_batch_dotp_vector(gr, gpsib(idir), rvu_psib(jdir), stress_tmp)
910
911 do ist = minst, maxst
912 stress_hubbard(idir, jdir) = stress_hubbard(idir, jdir) &
913 + m_two * st%kweights(ik) * st%occ(ist, ik) * real(stress_tmp(ist-minst+1), real64)
914 end do
915
916 end do
917 end do
918
919 do idir = 1, gr%der%dim
920 call rvu_psib(idir)%end()
921 call gpsib(idir)%end()
922 end do
923 call psib%end()
924 end do
925 end do
926
927 safe_deallocate_a(stress_tmp)
928
929 if (st%parallel_in_states .or. st%d%kpt%parallel) then
930 call comm_allreduce(st%st_kpt_mpi_grp, stress_hubbard)
931 end if
932
933 ! Symmetrize the kinetic stress tensor
934 call upper_triangular_to_hermitian(gr%der%dim, stress_hubbard)
935
936 ! Symmetrize the stress tensor if we use k-point symmetries
937 if (hm%kpoints%use_symmetries) then
938 call dsymmetrize_tensor_cart(gr%symm, stress_hubbard)
939 end if
940
941 ! Add the Hubbard energy
942 do idir = 1,3
943 stress_hubbard(idir, idir) = stress_hubbard(idir, idir) + hm%energy%int_dft_u
944 end do
945
946 stress_hubbard = stress_hubbard/rcell_volume
947
948 pop_sub_with_profile(stress_from_hubbard)
949 end subroutine stress_from_hubbard
950
951
952 ! -------------------------------------------------------
953 subroutine output_stress(iunit, space_dim, stress_tensors, all_terms)
954 integer, intent(in) :: iunit
955 integer, intent(in) :: space_dim
956 type(stress_t), intent(in) :: stress_tensors
957 logical, optional, intent(in) :: all_terms
958
959 logical :: write_all_terms
960 character(len=16) :: stress_unit
961
962 write_all_terms = optional_default(all_terms, .true.)
963
964 write(stress_unit, '(4a,i1)') trim(units_abbrev(units_out%energy)), '/', &
965 trim(units_abbrev(units_out%length)), '^', space_dim
966
967 if (mpi_grp_is_root(mpi_world)) then
968
969 if (write_all_terms) then
970 write(iunit, '(3a)') 'Kinetic stress tensor [', trim(stress_unit), '] ='
971 call print_stress_tensor(iunit, space_dim, stress_tensors%kinetic)
972 if (space_dim == 3) then
973 write(iunit, '(a, es15.6, 3a)') 'Kinetic pressure sumrule violation: ', &
974 units_from_atomic(units_out%energy, stress_tensors%kinetic_sumrule), &
975 ' [', trim(units_abbrev(units_out%energy)), ']'
976 write(iunit,*)
977 end if
978
979
980 write(iunit, '(3a)') 'Hartree stress tensor [', trim(stress_unit), '] ='
981 call print_stress_tensor(iunit, space_dim, stress_tensors%Hartree)
982 if (space_dim == 3) then
983 write(iunit, '(a, es15.6, 3a)') 'Hartree pressure sumrule violation: ', &
984 units_from_atomic(units_out%energy, stress_tensors%hartree_sumrule), &
985 ' [', trim(units_abbrev(units_out%energy)), ']'
986 write(iunit,*)
987 end if
988
989 write(iunit, '(3a)') 'XC stress tensor [', trim(stress_unit), '] ='
990 call print_stress_tensor(iunit, space_dim, stress_tensors%xc)
991
992 write(iunit, '(3a)') 'Local pseudo. stress tensor [', trim(stress_unit), '] ='
993 call print_stress_tensor(iunit, space_dim, stress_tensors%ps_local)
994
995 write(iunit, '(3a)') 'Nonlocal pseudo. stress tensor [', trim(stress_unit), '] ='
996 call print_stress_tensor(iunit, space_dim, stress_tensors%ps_nl)
997
998 write(iunit, '(3a)') 'Ion-ion stress tensor [', trim(stress_unit), '] ='
999 call print_stress_tensor(iunit, space_dim, stress_tensors%ion_ion)
1000
1001 write(iunit, '(3a)') 'vdW stress tensor [', trim(stress_unit), '] ='
1002 call print_stress_tensor(iunit, space_dim, stress_tensors%vdw)
1003
1004 write(iunit, '(3a)') 'Hubbard stress tensor [', trim(stress_unit), '] ='
1005 call print_stress_tensor(iunit, space_dim, stress_tensors%hubbard)
1006 end if
1007
1008 write(iunit, '(3a)') 'Total stress tensor [', trim(stress_unit), '] ='
1009 call print_stress_tensor(iunit, space_dim, stress_tensors%total)
1010
1011 end if
1012 end subroutine output_stress
1013
1014
1015 subroutine output_pressure(iunit, space_dim, total_stress_tensor)
1016 integer, intent(in) :: iunit
1017 integer, intent(in) :: space_dim
1018 real(real64), intent(in) :: total_stress_tensor(3,3)
1019
1020 ! TODO(Alex). Issue 884. Move this to unit_system.F90
1021 real(real64), parameter :: au_to_GPa = 29421.02648438959_real64
1022
1023 integer :: idim
1024 real(real64) :: pressure = m_zero
1025 character(len=16) :: stress_unit
1026
1027 write(stress_unit, '(4a,i1)') trim(units_abbrev(units_out%energy)), '/', &
1028 trim(units_abbrev(units_out%length)), '^', space_dim
1029
1030 do idim = 1, space_dim
1031 pressure = pressure - total_stress_tensor(idim, idim) / real(space_dim, real64)
1032 end do
1033
1034 write(iunit,'(3a,es16.8)', advance="no") 'Pressure [', trim(stress_unit), '] = ', &
1035 units_from_atomic(units_out%energy/units_out%length**space_dim, pressure)
1036 if (space_dim == 3) then
1037 write(iunit,'(2x,a,f16.8)') 'Pressure [GPa] = ', pressure * au_to_gpa
1038 else
1039 write(iunit,*)
1040 end if
1041
1042 end subroutine output_pressure
1043
1044 subroutine print_stress_tensor(ounit, space_dim, tensor)
1045 integer, intent(in) :: ounit
1046 integer, intent(in) :: space_dim
1047 real(real64), intent(in) :: tensor(3,3)
1048
1049 real(real64) :: tensor_with_unit(3,3)
1050 integer :: idim, jdim
1051
1052 tensor_with_unit = units_from_atomic(units_out%energy/units_out%length**space_dim, tensor)
1053
1054 write(ounit,'(a9,2x)', advance="no")"T_{ij}"
1055 do jdim = 1, space_dim
1056 write(ounit,'(i18)', advance="no") jdim
1057 end do
1058 write(ounit,*)
1059 do idim = 1, space_dim
1060 write(ounit,'(i9,2x)', advance="no") idim
1061 do jdim = 1, space_dim
1062 write(ounit,'(es18.9)', advance="no") tensor_with_unit(idim, jdim)
1063 end do
1064 write(ounit,*)
1065 end do
1066 write(ounit,*)
1067
1068 end subroutine print_stress_tensor
1069
1070
1071end module stress_oct_m
1072
1073!! Local Variables:
1074!! mode: f90
1075!! coding: utf-8
1076!! End:
constant times a vector plus a vector
Definition: lalg_basic.F90:170
Copies a vector x, to a vector y.
Definition: lalg_basic.F90:185
This module implements common operations on batches of mesh functions.
Definition: batch_ops.F90:116
subroutine, public batch_set_zero(this, np, async)
fill all mesh functions of the batch with zero
Definition: batch_ops.F90:240
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 dderivatives_grad(der, ff, op_ff, ghost_update, set_bc, to_cartesian)
apply the gradient to a mesh function
subroutine, public zderivatives_batch_grad(der, ffb, opffb, ghost_update, set_bc, to_cartesian, metric, factor)
apply the gradient to a batch of mesh functions
integer, parameter, public spinors
subroutine, public energy_calc_total(namespace, space, hm, gr, st, ext_partners, iunit, full)
This subroutine calculates the total energy of the system. Basically, it adds up the KS eigenvalues,...
integer, parameter, public scalar_relativistic_zora
Definition: epot.F90:166
integer, parameter, public fully_relativistic_zora
Definition: epot.F90:166
real(real64), parameter, public m_two
Definition: global.F90:189
real(real64), parameter, public m_zero
Definition: global.F90:187
real(real64), parameter, public m_four
Definition: global.F90:191
real(real64), parameter, public m_pi
some mathematical constants
Definition: global.F90:185
real(real64), parameter, public m_epsilon
Definition: global.F90:203
real(real64), parameter, public m_one
Definition: global.F90:188
This module implements the underlying real-space grid.
Definition: grid.F90:117
subroutine, public hamiltonian_elec_copy_and_set_phase(hm, gr, kpt, psib, psib_with_phase)
Copy a batch to another batch and apply the Bloch phase to it.
integer, parameter, public independent_particles
integer, parameter, public kohn_sham_dft
This module defines classes and functions for interaction partners.
Definition: io.F90:114
subroutine, public ion_interaction_stress(this, space, latt, atom, natoms, pos, stress_ii)
Computes the contribution to the stress tensor the ion-ion energy.
integer, parameter, public dft_u_none
Definition: lda_u.F90:200
subroutine, public zlda_u_rvu(this, mesh, space, d, namespace, psib, gpsib)
This routine computes .
Definition: lda_u.F90:5293
This module is intended to contain "only mathematical" functions and procedures.
Definition: math.F90:115
subroutine, public dsymmetrize_matrix(nn, aa)
Definition: math.F90:1445
This module defines functions over batches of mesh functions.
Definition: mesh_batch.F90:116
subroutine, public zmesh_batch_dotp_vector(mesh, aa, bb, dot, reduce, cproduct)
calculate the vector of dot-products of mesh functions between two batches
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:1125
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
Definition: messages.F90:160
subroutine, public messages_fatal(no_lines, only_root_writes, namespace)
Definition: messages.F90:420
logical function mpi_grp_is_root(grp)
Definition: mpi.F90:426
type(mpi_grp_t), public mpi_world
Definition: mpi.F90:262
logical pure function, public poisson_solver_is_iterative(this)
Definition: poisson.F90:1324
subroutine, public dpoisson_solve(this, namespace, pot, rho, all_nodes, kernel)
Calculates the Poisson equation. Given the density returns the corresponding potential.
Definition: poisson.F90:913
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
subroutine, public species_get_long_range_density(species, namespace, space, latt, pos, mesh, rho, sphere_inout, nlr_x)
subroutine, public species_get_nlcc_grad(species, space, latt, pos, mesh, rho_core_grad, gnlcc_x)
real(real64) function, public spline_eval(spl, x)
Definition: splines.F90:441
This module handles spin dimensions of the states and the k-point distribution.
integer pure function, public states_elec_block_max(st, ib)
return index of last state in block ib
integer pure function, public states_elec_block_min(st, ib)
return index of first state in block ib
This module implements the calculation of the stress tensor.
Definition: stress.F90:118
subroutine stress_from_kinetic(gr, space, hm, st, symm, rcell_volume, stress_kin)
Computes the contribution to the stress tensor from the kinetic energy.
Definition: stress.F90:404
subroutine stress_from_xc(energy, rcell_volume, periodic_dim, stress_xc)
Computes the contribution to the stress tensor from the xc energy.
Definition: stress.F90:542
subroutine print_stress_tensor(ounit, space_dim, tensor)
Definition: stress.F90:1138
subroutine, public output_pressure(iunit, space_dim, total_stress_tensor)
Definition: stress.F90:1109
subroutine epot_local_pseudopotential_sr(mesh, ions, iatom, vpsl, rvpsl)
Definition: stress.F90:889
subroutine, public stress_calculate(namespace, gr, hm, st, ions, ks, ext_partners)
This computes the total stress on the lattice.
Definition: stress.F90:184
subroutine stress_from_hubbard(namespace, gr, st, hm, space, rcell_volume, stress_hubbard)
Computes the contribution to the stress tensor from the Hubbard energy.
Definition: stress.F90:953
subroutine stress_from_xc_nlcc(rcell_volume, gr, st, ions, vxc, stress_xc_nlcc)
Computes the NLCC contribution to the stress tensor from the xc energy.
Definition: stress.F90:571
subroutine stress_from_pseudo_nonloc(gr, st, hm, ions, stress_ps_nl)
Computes the contribution to the stress tensor from the nonlocal part of the pseudopotentials.
Definition: stress.F90:644
subroutine stress_from_hartree(gr, space, volume, vh, grad_vh, ehartree, stress_Hartree)
Computes the contribution to the stress tensor from the Hartree energy.
Definition: stress.F90:493
subroutine, public output_stress(iunit, space_dim, stress_tensors, all_terms)
Definition: stress.F90:1047
subroutine stress_from_pseudo_local(gr, st, hm, ions, rho_total, vh, grad_vh, stress_ps_local)
Computes the contribution from the local part of the pseudopotential.
Definition: stress.F90:750
subroutine, public submesh_end(this)
Definition: submesh.F90:737
subroutine, public submesh_init(this, space, mesh, latt, center, rc)
Definition: submesh.F90:282
subroutine, public dsymmetrize_tensor_cart(symm, tensor, use_non_symmorphic)
Symmetric a rank-2 tensor defined in Cartesian space.
type(type_t), public type_cmplx
Definition: types.F90:134
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
Definition: xc.F90:114
pure logical function, public in_family(family, xc_families)
Definition: xc.F90:604
A module that takes care of xc contribution from vdW interactions.
Definition: xc_vdw.F90:116
integer(int64), dimension(5), parameter, public d3_lib_options
VDWCORRECTION options that correspond to the DFT-D3 library.
Definition: xc_vdw.F90:169
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.
A submesh is a type of mesh, used for the projectors in the pseudopotentials It contains points on a ...
Definition: submesh.F90:177
batches of electronic states
Definition: wfs_elec.F90:138
int true(void)