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))) ) then
115 if (.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 end if
129 ! If (useACE) is handled elsewhere
130 else
131 ! If exact exchange is not required, zero the term regardless
132 hm%energy%exchange_hf = m_zero
133 end if
134
135 if (hm%pcm%run_pcm) then
136 hm%pcm%counter = hm%pcm%counter + 1
137 if (hm%pcm%localf) then
138 call pcm_elect_energy(hm%ions, hm%pcm, hm%energy%int_ee_pcm, hm%energy%int_en_pcm, &
139 hm%energy%int_ne_pcm, hm%energy%int_nn_pcm, &
140 e_int_e_ext = hm%energy%int_e_ext_pcm, &
141 e_int_n_ext = hm%energy%int_n_ext_pcm )
142 else
143 call pcm_elect_energy(hm%ions, hm%pcm, hm%energy%int_ee_pcm, hm%energy%int_en_pcm, &
144 hm%energy%int_ne_pcm, hm%energy%int_nn_pcm )
145 end if
146 end if
147
148 select case (hm%theory_level)
150 hm%energy%total = hm%ep%eii + hm%energy%eigenvalues
151
152 case (hartree)
153 hm%energy%total = hm%ep%eii + m_half * (hm%energy%eigenvalues + hm%energy%kinetic + hm%energy%extern)
154
156 hm%energy%total = hm%ep%eii + &
157 m_half*(hm%energy%eigenvalues + hm%energy%kinetic + hm%energy%extern - hm%energy%intnvxc &
158 - hm%energy%int_dft_u) &
159 + hm%energy%exchange + hm%energy%exchange_hf + hm%energy%correlation &
160 + hm%energy%vdw - hm%energy%intnvstatic + hm%energy%dft_u
161
162 ! FIXME: pcm terms are only added to total energy in DFT case
163
164 case (kohn_sham_dft)
165 hm%energy%total = hm%ep%eii + hm%energy%eigenvalues &
166 - hm%energy%hartree + hm%energy%exchange + hm%energy%correlation + hm%energy%vdw - hm%energy%intnvxc &
167 - hm%energy%pcm_corr + hm%energy%int_ee_pcm + hm%energy%int_en_pcm &
168 + hm%energy%int_nn_pcm + hm%energy%int_ne_pcm &
169 + hm%energy%int_e_ext_pcm + hm%energy%int_n_ext_pcm &
170 + hm%energy%dft_u - hm%energy%int_dft_u - hm%energy%intnvstatic &
171 + hm%energy%photon_exchange
172
173 case default
174 hm%energy%total = m_zero
175 end select
176
177 hm%energy%entropy = smear_calc_entropy(st%smear, st%eigenval, st%nik, st%nst, st%kweights, st%occ)
178 if (st%smear%method == smear_fixed_occ) then ! no temperature available
179 hm%energy%TS = m_zero
180 else
181 hm%energy%TS = st%smear%dsmear * hm%energy%entropy
182 end if
183
184 gfield => list_get_gauge_field(ext_partners)
185 if(associated(gfield)) hm%energy%total = hm%energy%total + gauge_field_get_energy(gfield)
186
187 if (allocated(hm%vberry)) then
188 hm%energy%total = hm%energy%total + hm%energy%berry
189 else
190 hm%energy%berry = m_zero
191 end if
192
193 ! Add the magnetic constrain energy
194 if (hm%magnetic_constrain%level /= constrain_none) then
195 hm%energy%total = hm%energy%total + hm%magnetic_constrain%energy
196 end if
197
198 if (optional_default(iunit, -1) /= -1) then
199 write(message(1), '(6x,a, f18.8)')'Total = ', units_from_atomic(units_out%energy, hm%energy%total)
200 write(message(2), '(6x,a, f18.8)')'Free = ', units_from_atomic(units_out%energy, hm%energy%total - hm%energy%TS)
201 write(message(3), '(6x,a)') '-----------'
202 call messages_info(3, iunit)
203
204 write(message(1), '(6x,a, f18.8)')'Ion-ion = ', units_from_atomic(units_out%energy, hm%ep%eii)
205 write(message(2), '(6x,a, f18.8)')'Eigenvalues = ', units_from_atomic(units_out%energy, hm%energy%eigenvalues)
206 write(message(3), '(6x,a, f18.8)')'Hartree = ', units_from_atomic(units_out%energy, hm%energy%hartree)
207 write(message(4), '(6x,a, f18.8)')'Int[n*v_xc] = ', units_from_atomic(units_out%energy, hm%energy%intnvxc)
208 write(message(5), '(6x,a, f18.8)')'Exchange = ', &
209 units_from_atomic(units_out%energy, hm%energy%exchange+hm%energy%exchange_hf)
210 write(message(6), '(6x,a, f18.8)')'Correlation = ', units_from_atomic(units_out%energy, hm%energy%correlation)
211 write(message(7), '(6x,a, f18.8)')'vanderWaals = ', units_from_atomic(units_out%energy, hm%energy%vdw)
212 write(message(8), '(6x,a, f18.8)')'Delta XC = ', units_from_atomic(units_out%energy, hm%energy%delta_xc)
213 write(message(9), '(6x,a, f18.8)')'Entropy = ', hm%energy%entropy ! the dimensionless sigma of Kittel&Kroemer
214 write(message(10), '(6x,a, f18.8)')'-TS = ', -units_from_atomic(units_out%energy, hm%energy%TS)
215 write(message(11), '(6x,a, f18.8)')'Photon ex. = ', units_from_atomic(units_out%energy, hm%energy%photon_exchange)
216 call messages_info(11, iunit)
217
218 if (hm%pcm%run_pcm) then
219 write(message(1),'(6x,a, f18.8)')'E_e-solvent = ', units_from_atomic(units_out%energy, hm%energy%int_ee_pcm + &
220 hm%energy%int_en_pcm + &
221 hm%energy%int_e_ext_pcm)
222 write(message(2),'(6x,a, f18.8)')'E_n-solvent = ', units_from_atomic(units_out%energy, hm%energy%int_nn_pcm + &
223 hm%energy%int_ne_pcm + &
224 hm%energy%int_n_ext_pcm)
225 write(message(3),'(6x,a, f18.8)')'E_M-solvent = ', units_from_atomic(units_out%energy, &
226 hm%energy%int_ee_pcm + hm%energy%int_en_pcm + &
227 hm%energy%int_nn_pcm + hm%energy%int_ne_pcm + &
228 hm%energy%int_e_ext_pcm + hm%energy%int_n_ext_pcm)
229 call messages_info(3, iunit)
230 end if
231
232 if (full_) then
233 write(message(1), '(6x,a, f18.8)')'Kinetic = ', units_from_atomic(units_out%energy, hm%energy%kinetic)
234 write(message(2), '(6x,a, f18.8)')'External = ', units_from_atomic(units_out%energy, hm%energy%extern)
235 write(message(3), '(6x,a, f18.8)')'Non-local = ', units_from_atomic(units_out%energy, hm%energy%extern_non_local)
236 write(message(4), '(6x,a, f18.8)')'Int[n*v_E] = ', units_from_atomic(units_out%energy, hm%energy%intnvstatic)
237 call messages_info(4, iunit)
238 end if
239 if (allocated(hm%vberry) .and. space%is_periodic()) then
240 write(message(1), '(6x,a, f18.8)')'Berry = ', units_from_atomic(units_out%energy, hm%energy%berry)
241 call messages_info(1, iunit)
242 end if
243 if (hm%lda_u_level /= dft_u_none) then
244 write(message(1), '(6x,a, f18.8)')'Hubbard = ', units_from_atomic(units_out%energy, hm%energy%dft_u)
245 write(message(2), '(6x,a, f18.8)')'Int[n*v_U] = ', units_from_atomic(units_out%energy, hm%energy%int_dft_u)
246 call messages_info(2, iunit)
247 end if
248 end if
249
250 pop_sub(energy_calc_total)
251 end subroutine energy_calc_total
252
253 ! --------------------------------------------------------------------
254
255 subroutine energy_calc_eigenvalues(namespace, hm, der, st)
256 type(namespace_t), intent(in) :: namespace
257 type(hamiltonian_elec_t), intent(inout) :: hm
258 type(derivatives_t), intent(in) :: der
259 type(states_elec_t), intent(inout) :: st
260
262
263 if (states_are_real(st)) then
264 call dcalculate_eigenvalues(namespace, hm, der, st)
265 else
266 call zcalculate_eigenvalues(namespace, hm, der, st)
267 end if
268
270 end subroutine energy_calc_eigenvalues
271
272 ! ---------------------------------------------------------
273 subroutine energy_calc_virial_ex(der, vxc, st, ex)
274 type(derivatives_t), intent(in) :: der
275 real(real64), intent(in) :: vxc(:,:)
276 type(states_elec_t), intent(in) :: st
277 real(real64), intent(out) :: ex
278
279 integer :: idir, ip, isp
280 real(real64), allocatable :: gradvx(:,:), nrgradvx(:)
281 real(real64) :: rr, xx(der%dim)
282
283 push_sub(energy_calc_virial_ex)
284
285 assert(st%d%ispin /= spinors)
286
287 safe_allocate(nrgradvx(1:der%mesh%np_part))
288 safe_allocate(gradvx(1:der%mesh%np, 1:der%dim))
289
290 ex = m_zero
291 do isp = 1, st%d%nspin
292 !We output the energy from the virial relation
293 nrgradvx(1:der%mesh%np) = vxc(1:der%mesh%np,isp)
294 call dderivatives_grad(der, nrgradvx, gradvx)
295 nrgradvx = m_zero
296 do idir = 1, der%dim
297 do ip = 1, der%mesh%np
298 call mesh_r(der%mesh, ip, rr, coords=xx)
299 nrgradvx(ip) = nrgradvx(ip) - gradvx(ip, idir) * st%rho(ip, isp) * xx(idir)
300 end do
301 end do
302 ex = ex + dmf_integrate(der%mesh, nrgradvx)
303 end do
304
305 safe_deallocate_a(gradvx)
306 safe_deallocate_a(nrgradvx)
307
308 pop_sub(energy_calc_virial_ex)
309 end subroutine energy_calc_virial_ex
310
311
312#include "undef.F90"
313#include "real.F90"
314#include "energy_calc_inc.F90"
315
316#include "undef.F90"
317#include "complex.F90"
318#include "energy_calc_inc.F90"
319
320end module energy_calc_oct_m
321
322!! Local Variables:
323!! mode: f90
324!! coding: utf-8
325!! End:
This module implements batches of mesh functions.
Definition: batch.F90:135
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:190
integer, parameter, public hartree_fock
Definition: global.F90:236
integer, parameter, public independent_particles
Theory level.
Definition: global.F90:236
integer, parameter, public generalized_kohn_sham_dft
Definition: global.F90:236
integer, parameter, public kohn_sham_dft
Definition: global.F90:236
real(real64), parameter, public m_half
Definition: global.F90:196
integer, parameter, public hartree
Definition: global.F90:236
This module implements the underlying real-space grid.
Definition: grid.F90:119
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 dft_u_none
Definition: lda_u.F90:203
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:118
This module defines various routines, operating on mesh functions.
This module defines the meshes, which are used in Octopus.
Definition: mesh.F90:120
pure subroutine, public mesh_r(mesh, ip, rr, origin, coords)
return the distance to the origin for a given grid point
Definition: mesh.F90:339
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
Definition: messages.F90:162
subroutine, public messages_info(no_lines, iunit, debug_only, stress, all_nodes, namespace)
Definition: messages.F90:600
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:1546
real(real64) function, public smear_calc_entropy(this, eigenvalues, nik, nst, kweights, occ)
Definition: smear.F90:598
integer, parameter, public smear_fixed_occ
Definition: smear.F90:173
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:134
This module defines the unit system, used for input and output.
type(unit_system_t), public units_out
Definition: xc.F90:116
logical pure function, public family_is_hybrid(xcs)
Returns true if the functional is an hybrid functional.
Definition: xc.F90:635
class representing derivatives
The states_elec_t class contains all electronic wave functions.