Octopus
energy_calc.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
22 use batch_oct_m
23 use comm_oct_m
24 use debug_oct_m
26 use energy_oct_m
31 use global_oct_m
32 use grid_oct_m
35 use ions_oct_m
37 use lda_u_oct_m
39 use mesh_oct_m
45 use pcm_oct_m
47 use smear_oct_m
48 use space_oct_m
52 use unit_oct_m
55 use xc_oct_m
56
57 implicit none
58
59 private
60 public :: &
66
67contains
68
69 ! ---------------------------------------------------------
73 subroutine energy_calc_total(namespace, space, hm, gr, st, ext_partners, iunit, full)
74 type(namespace_t), intent(in) :: namespace
75 class(space_t), intent(in) :: space
76 type(hamiltonian_elec_t), intent(inout) :: hm
77 type(grid_t), intent(in) :: gr
78 type(states_elec_t), intent(inout) :: st
79 type(partner_list_t), intent(in) :: ext_partners
80 integer, optional, intent(in) :: iunit
81 logical, optional, intent(in) :: full
82
83 logical :: full_
84 type(states_elec_t) :: xst
86 type(gauge_field_t), pointer :: gfield
87
88 push_sub(energy_calc_total)
89
90 full_ = .false.
91 if (present(full)) full_ = full
92
93 hm%energy%eigenvalues = states_elec_eigenvalues_sum(st)
94
95 if (full_ .or. hm%theory_level == hartree .or. hm%theory_level == hartree_fock &
96 .or. hm%theory_level == generalized_kohn_sham_dft) then
97 if (states_are_real(st)) then
98 hm%energy%kinetic = denergy_calc_electronic(namespace, hm, gr%der, st, terms = term_kinetic)
99 hm%energy%extern_local = denergy_calc_electronic(namespace, hm, gr%der, st, terms = term_local_external)
100 hm%energy%extern_non_local = denergy_calc_electronic(namespace, hm, gr%der, st, terms = term_non_local_potential)
101 hm%energy%extern = hm%energy%extern_local + hm%energy%extern_non_local
102 else
103 hm%energy%kinetic = zenergy_calc_electronic(namespace, hm, gr%der, st, terms = term_kinetic)
104
105 hm%energy%extern_local = zenergy_calc_electronic(namespace, hm, gr%der, st, terms = term_local_external)
106
107 hm%energy%extern_non_local = zenergy_calc_electronic(namespace, hm, gr%der, st, terms = term_non_local_potential)
108 hm%energy%extern = hm%energy%extern_local + hm%energy%extern_non_local
109 end if
110 end if
111
112 ! Computes the HF energy when not doing the ACE
113 if((hm%theory_level == hartree_fock .or. &
114 (hm%theory_level == generalized_kohn_sham_dft .and. family_is_hybrid(hm%xc))) &
115 .and. .not. hm%exxop%useACE ) then
116 call xst%nullify()
117 if (states_are_real(st)) then
118 call dexchange_operator_compute_potentials(hm%exxop, namespace, space, gr, st, &
119 xst, hm%kpoints)
120 hm%energy%exchange_hf = dexchange_operator_compute_ex(gr, st, xst)
121 else
122 call zexchange_operator_compute_potentials(hm%exxop, namespace, space, gr, st, &
123 xst, hm%kpoints)
124 hm%energy%exchange_hf = zexchange_operator_compute_ex(gr, st, xst)
125 end if
126 call states_elec_end(xst)
127 hm%energy%exchange_hf = hm%energy%exchange_hf + hm%exxop%singul%energy
128 else
129 if(.not. hm%exxop%useACE) hm%energy%exchange_hf = m_zero
130 end if
131
132 if (hm%pcm%run_pcm) then
133 hm%pcm%counter = hm%pcm%counter + 1
134 if (hm%pcm%localf) then
135 call pcm_elect_energy(hm%ions, hm%pcm, hm%energy%int_ee_pcm, hm%energy%int_en_pcm, &
136 hm%energy%int_ne_pcm, hm%energy%int_nn_pcm, &
137 e_int_e_ext = hm%energy%int_e_ext_pcm, &
138 e_int_n_ext = hm%energy%int_n_ext_pcm )
139 else
140 call pcm_elect_energy(hm%ions, hm%pcm, hm%energy%int_ee_pcm, hm%energy%int_en_pcm, &
141 hm%energy%int_ne_pcm, hm%energy%int_nn_pcm )
142 end if
143 end if
144
145 select case (hm%theory_level)
147 hm%energy%total = hm%ep%eii + hm%energy%eigenvalues
148
149 case (hartree)
150 hm%energy%total = hm%ep%eii + m_half * (hm%energy%eigenvalues + hm%energy%kinetic + hm%energy%extern)
151
153 hm%energy%total = hm%ep%eii + &
154 m_half*(hm%energy%eigenvalues + hm%energy%kinetic + hm%energy%extern - hm%energy%intnvxc &
155 - hm%energy%int_dft_u) &
156 + hm%energy%exchange + hm%energy%exchange_hf + hm%energy%correlation &
157 + hm%energy%vdw - hm%energy%intnvstatic + hm%energy%dft_u
158
159 ! FIXME: pcm terms are only added to total energy in DFT case
160
161 case (kohn_sham_dft)
162 hm%energy%total = hm%ep%eii + hm%energy%eigenvalues &
163 - hm%energy%hartree + hm%energy%exchange + hm%energy%correlation + hm%energy%vdw - hm%energy%intnvxc &
164 - hm%energy%pcm_corr + hm%energy%int_ee_pcm + hm%energy%int_en_pcm &
165 + hm%energy%int_nn_pcm + hm%energy%int_ne_pcm &
166 + hm%energy%int_e_ext_pcm + hm%energy%int_n_ext_pcm &
167 + hm%energy%dft_u - hm%energy%int_dft_u - hm%energy%intnvstatic &
168 + hm%energy%photon_exchange
169
170 case default
171 hm%energy%total = m_zero
172 end select
173
174 hm%energy%entropy = smear_calc_entropy(st%smear, st%eigenval, st%nik, st%nst, st%kweights, st%occ)
175 if (st%smear%method == smear_fixed_occ) then ! no temperature available
176 hm%energy%TS = m_zero
177 else
178 hm%energy%TS = st%smear%dsmear * hm%energy%entropy
179 end if
180
181 gfield => list_get_gauge_field(ext_partners)
182 if(associated(gfield)) hm%energy%total = hm%energy%total + gauge_field_get_energy(gfield)
183
184 if (allocated(hm%vberry)) then
185 hm%energy%total = hm%energy%total + hm%energy%berry
186 else
187 hm%energy%berry = m_zero
188 end if
189
190 ! Add the magnetic constrain energy
191 if (hm%magnetic_constrain%level /= constrain_none) then
192 hm%energy%total = hm%energy%total + hm%magnetic_constrain%energy
193 end if
194
195 if (optional_default(iunit, -1) /= -1) then
196 write(message(1), '(6x,a, f18.8)')'Total = ', units_from_atomic(units_out%energy, hm%energy%total)
197 write(message(2), '(6x,a, f18.8)')'Free = ', units_from_atomic(units_out%energy, hm%energy%total - hm%energy%TS)
198 write(message(3), '(6x,a)') '-----------'
199 call messages_info(3, iunit)
200
201 write(message(1), '(6x,a, f18.8)')'Ion-ion = ', units_from_atomic(units_out%energy, hm%ep%eii)
202 write(message(2), '(6x,a, f18.8)')'Eigenvalues = ', units_from_atomic(units_out%energy, hm%energy%eigenvalues)
203 write(message(3), '(6x,a, f18.8)')'Hartree = ', units_from_atomic(units_out%energy, hm%energy%hartree)
204 write(message(4), '(6x,a, f18.8)')'Int[n*v_xc] = ', units_from_atomic(units_out%energy, hm%energy%intnvxc)
205 write(message(5), '(6x,a, f18.8)')'Exchange = ', &
206 units_from_atomic(units_out%energy, hm%energy%exchange+hm%energy%exchange_hf)
207 write(message(6), '(6x,a, f18.8)')'Correlation = ', units_from_atomic(units_out%energy, hm%energy%correlation)
208 write(message(7), '(6x,a, f18.8)')'vanderWaals = ', units_from_atomic(units_out%energy, hm%energy%vdw)
209 write(message(8), '(6x,a, f18.8)')'Delta XC = ', units_from_atomic(units_out%energy, hm%energy%delta_xc)
210 write(message(9), '(6x,a, f18.8)')'Entropy = ', hm%energy%entropy ! the dimensionless sigma of Kittel&Kroemer
211 write(message(10), '(6x,a, f18.8)')'-TS = ', -units_from_atomic(units_out%energy, hm%energy%TS)
212 write(message(11), '(6x,a, f18.8)')'Photon ex. = ', units_from_atomic(units_out%energy, hm%energy%photon_exchange)
213 call messages_info(11, iunit)
214
215 if (hm%pcm%run_pcm) then
216 write(message(1),'(6x,a, f18.8)')'E_e-solvent = ', units_from_atomic(units_out%energy, hm%energy%int_ee_pcm + &
217 hm%energy%int_en_pcm + &
218 hm%energy%int_e_ext_pcm)
219 write(message(2),'(6x,a, f18.8)')'E_n-solvent = ', units_from_atomic(units_out%energy, hm%energy%int_nn_pcm + &
220 hm%energy%int_ne_pcm + &
221 hm%energy%int_n_ext_pcm)
222 write(message(3),'(6x,a, f18.8)')'E_M-solvent = ', units_from_atomic(units_out%energy, &
223 hm%energy%int_ee_pcm + hm%energy%int_en_pcm + &
224 hm%energy%int_nn_pcm + hm%energy%int_ne_pcm + &
225 hm%energy%int_e_ext_pcm + hm%energy%int_n_ext_pcm)
226 call messages_info(3, iunit)
227 end if
228
229 if (full_) then
230 write(message(1), '(6x,a, f18.8)')'Kinetic = ', units_from_atomic(units_out%energy, hm%energy%kinetic)
231 write(message(2), '(6x,a, f18.8)')'External = ', units_from_atomic(units_out%energy, hm%energy%extern)
232 write(message(3), '(6x,a, f18.8)')'Non-local = ', units_from_atomic(units_out%energy, hm%energy%extern_non_local)
233 write(message(4), '(6x,a, f18.8)')'Int[n*v_E] = ', units_from_atomic(units_out%energy, hm%energy%intnvstatic)
234 call messages_info(4, iunit)
235 end if
236 if (allocated(hm%vberry) .and. space%is_periodic()) then
237 write(message(1), '(6x,a, f18.8)')'Berry = ', units_from_atomic(units_out%energy, hm%energy%berry)
238 call messages_info(1, iunit)
239 end if
240 if (hm%lda_u_level /= dft_u_none) then
241 write(message(1), '(6x,a, f18.8)')'Hubbard = ', units_from_atomic(units_out%energy, hm%energy%dft_u)
242 write(message(2), '(6x,a, f18.8)')'Int[n*v_U] = ', units_from_atomic(units_out%energy, hm%energy%int_dft_u)
243 call messages_info(2, iunit)
244 end if
245 end if
246
247 pop_sub(energy_calc_total)
248 end subroutine energy_calc_total
249
250 ! --------------------------------------------------------------------
251
252 subroutine energy_calc_eigenvalues(namespace, hm, der, st)
253 type(namespace_t), intent(in) :: namespace
254 type(hamiltonian_elec_t), intent(inout) :: hm
255 type(derivatives_t), intent(in) :: der
256 type(states_elec_t), intent(inout) :: st
257
259
260 if (states_are_real(st)) then
261 call dcalculate_eigenvalues(namespace, hm, der, st)
262 else
263 call zcalculate_eigenvalues(namespace, hm, der, st)
264 end if
265
267 end subroutine energy_calc_eigenvalues
268
269 ! ---------------------------------------------------------
270 subroutine energy_calc_virial_ex(der, vxc, st, ex)
271 type(derivatives_t), intent(in) :: der
272 real(real64), intent(in) :: vxc(:,:)
273 type(states_elec_t), intent(in) :: st
274 real(real64), intent(out) :: ex
275
276 integer :: idir, ip, isp
277 real(real64), allocatable :: gradvx(:,:), nrgradvx(:)
278 real(real64) :: rr, xx(der%dim)
279
280 push_sub(energy_calc_virial_ex)
281
282 assert(st%d%ispin /= spinors)
283
284 safe_allocate(nrgradvx(1:der%mesh%np_part))
285 safe_allocate(gradvx(1:der%mesh%np, 1:der%dim))
286
287 ex = m_zero
288 do isp = 1, st%d%nspin
289 !We output the energy from the virial relation
290 nrgradvx(1:der%mesh%np) = vxc(1:der%mesh%np,isp)
291 call dderivatives_grad(der, nrgradvx, gradvx)
292 nrgradvx = m_zero
293 do idir = 1, der%dim
294 do ip = 1, der%mesh%np
295 call mesh_r(der%mesh, ip, rr, coords=xx)
296 nrgradvx(ip) = nrgradvx(ip) - gradvx(ip, idir) * st%rho(ip, isp) * xx(idir)
297 end do
298 end do
299 ex = ex + dmf_integrate(der%mesh, nrgradvx)
300 end do
301
302 safe_deallocate_a(gradvx)
303 safe_deallocate_a(nrgradvx)
304
305 pop_sub(energy_calc_virial_ex)
306 end subroutine energy_calc_virial_ex
307
308
309#include "undef.F90"
310#include "real.F90"
311#include "energy_calc_inc.F90"
312
313#include "undef.F90"
314#include "complex.F90"
315#include "energy_calc_inc.F90"
316
317end module energy_calc_oct_m
318
319!! Local Variables:
320!! mode: f90
321!! coding: utf-8
322!! End:
This module implements batches of mesh functions.
Definition: batch.F90:133
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
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,...
real(real64) function, public zenergy_calc_electronic(namespace, hm, der, st, terms)
subroutine dcalculate_eigenvalues(namespace, hm, der, st)
calculates the eigenvalues of the orbitals
subroutine, public energy_calc_virial_ex(der, vxc, st, ex)
subroutine zcalculate_eigenvalues(namespace, hm, der, st)
calculates the eigenvalues of the orbitals
real(real64) function, public denergy_calc_electronic(namespace, hm, der, st, terms)
subroutine, public energy_calc_eigenvalues(namespace, hm, der, st)
subroutine, public zexchange_operator_compute_potentials(this, namespace, space, gr, st, xst, kpoints, F_out)
subroutine, public dexchange_operator_compute_potentials(this, namespace, space, gr, st, xst, kpoints, F_out)
real(real64) function, public dexchange_operator_compute_ex(mesh, st, xst)
Compute the exact exchange energy.
real(real64) function, public zexchange_operator_compute_ex(mesh, st, xst)
Compute the exact exchange energy.
type(gauge_field_t) function, pointer, public list_get_gauge_field(partners)
real(real64) function, public gauge_field_get_energy(this)
real(real64), parameter, public m_zero
Definition: global.F90:188
real(real64), parameter, public m_half
Definition: global.F90:194
This module implements the underlying real-space grid.
Definition: grid.F90:117
integer, parameter, public term_local_external
integer, parameter, public term_non_local_potential
integer, parameter, public term_kinetic
This module defines classes and functions for interaction partners.
A module to handle KS potential, without the external potential.
integer, parameter, public hartree
integer, parameter, public hartree_fock
integer, parameter, public independent_particles
integer, parameter, public generalized_kohn_sham_dft
integer, parameter, public kohn_sham_dft
integer, parameter, public dft_u_none
Definition: lda_u.F90:201
This modules implements the routines for doing constrain DFT for noncollinear magnetism.
integer, parameter, public constrain_none
This module defines functions over batches of mesh functions.
Definition: mesh_batch.F90:116
This module defines various routines, operating on mesh functions.
This module defines the meshes, which are used in Octopus.
Definition: mesh.F90:118
pure subroutine, public mesh_r(mesh, ip, rr, origin, coords)
return the distance to the origin for a given grid point
Definition: mesh.F90:338
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
Definition: messages.F90:160
subroutine, public messages_info(no_lines, iunit, debug_only, stress, all_nodes, namespace)
Definition: messages.F90:616
subroutine, public pcm_elect_energy(ions, pcm, E_int_ee, E_int_en, E_int_ne, E_int_nn, E_int_e_ext, E_int_n_ext)
Calculates the solute-solvent electrostatic interaction energy .
Definition: pcm.F90:1545
real(real64) function, public smear_calc_entropy(this, eigenvalues, nik, nst, kweights, occ)
Definition: smear.F90:593
integer, parameter, public smear_fixed_occ
Definition: smear.F90:171
pure logical function, public states_are_real(st)
This module handles spin dimensions of the states and the k-point distribution.
subroutine, public states_elec_end(st)
finalize the states_elec_t object
real(real64) function, public states_elec_eigenvalues_sum(st, alt_eig)
function to calculate the eigenvalues sum using occupations as weights
brief This module defines the class unit_t which is used by the unit_systems_oct_m module.
Definition: unit.F90:132
This module defines the unit system, used for input and output.
type(unit_system_t), public units_out
Definition: xc.F90:114
logical pure function, public family_is_hybrid(xcs)
Returns true if the functional is an hybrid functional.
Definition: xc.F90:610
class representing derivatives
The states_elec_t class contains all electronic wave functions.