Octopus
xc_fbe.F90
Go to the documentation of this file.
1!! Copyright (C) 2002-2006 M. Marques, A. Castro, A. Rubio, G. Bertsch
2!! Copyright (C) 2023-2026 N. Tancogne-Dejean, C. Joens
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
22module xc_fbe_oct_m
23 use batch_oct_m
25 use comm_oct_m
26 use debug_oct_m
30 use global_oct_m
31 use grid_oct_m
35 use math_oct_m
37 use mesh_oct_m
39 use mpi_oct_m
42 use parser_oct_m
47 use space_oct_m
56
57 implicit none
58
59 private
60 public :: &
61 x_fbe_calc, &
62 lda_c_fbe, &
64
65contains
66
67 ! -------------------------------------------------------------------------------------
73 subroutine x_fbe_calc (id, namespace, psolver, sl_solver, gr, st, space, ex, vxc)
74 integer, intent(in) :: id
75 type(namespace_t), intent(in) :: namespace
76 type(poisson_t), intent(in) :: psolver
77 type(sturm_liouville_t), intent(inout) :: sl_solver
78 type(grid_t), target, intent(in) :: gr
79 type(states_elec_t), intent(inout) :: st
80 type(space_t), intent(in) :: space
81 real(real64), intent(inout) :: ex
82 real(real64), contiguous, optional, intent(inout) :: vxc(:,:)
83
84 integer :: ispin
85 real(real64), allocatable :: fxc(:,:,:), internal_vxc(:,:)
86 push_sub(x_fbe_calc)
87
88 select case(id)
89 case(xc_oep_x_fbe)
90 if (states_are_real(st)) then
91 call dx_fbe_calc(namespace, psolver, sl_solver, gr, st, ex, vxc=vxc)
92 else
93 call zx_fbe_calc(namespace, psolver, sl_solver, gr, st, ex, vxc=vxc)
94 end if
95 case(xc_oep_x_fbe_sl)
96 safe_allocate(fxc(1:gr%np_part, 1:gr%box%dim, 1:st%d%spin_channels))
97 safe_allocate(internal_vxc(1:gr%np, 1:st%d%spin_channels))
98 internal_vxc = m_zero
99 ! We first compute the force density
100 if (states_are_real(st)) then
101 call dx_fbe_calc(namespace, psolver, sl_solver, gr, st, ex, vxc=internal_vxc, fxc=fxc)
102 else
103 call zx_fbe_calc(namespace, psolver, sl_solver, gr, st, ex, vxc=internal_vxc, fxc=fxc)
104 end if
105
106 ! We solve the Sturm-Liouville equation
107 if (present(vxc)) then
108 do ispin = 1, st%d%spin_channels
109 call sturm_liouville_solve_from_div(sl_solver, namespace, st%rho(:, ispin), fxc(:, :, ispin), internal_vxc(:, ispin))
110 end do
111 end if
112
113 ! Get the energy from the virial relation
114 ex = get_virial_energy(gr, st%d%spin_channels, fxc)
115
116 ! Adds the calculated potential
117 if (present(vxc)) then
118 call lalg_axpy(gr%np, st%d%spin_channels, m_one, internal_vxc, vxc)
119 end if
120
121 safe_deallocate_a(fxc)
122 safe_deallocate_a(internal_vxc)
123 case default
124 assert(.false.)
125 end select
126
127 pop_sub(x_fbe_calc)
128 end subroutine x_fbe_calc
129
130 ! -------------------------------------------------------------------------------------
132 real(real64) function get_virial_energy(gr, nspin, fxc) result(exc)
133 type(grid_t), intent(in) :: gr
134 integer, intent(in) :: nspin
135 real(real64), intent(in) :: fxc(:,:,:)
136
137 integer :: isp, idir, ip
138 real(real64), allocatable :: rfxc(:)
139 real(real64) :: xx(gr%box%dim), rr
140
141 push_sub(get_virial_energy)
142
143 exc = m_zero
144 do isp = 1, nspin
145 safe_allocate(rfxc(1:gr%np))
146 do ip = 1, gr%np
147 rfxc(ip) = m_zero
148 call mesh_r(gr, ip, rr, coords=xx)
149 do idir = 1, gr%box%dim
150 rfxc(ip) = rfxc(ip) + fxc(ip, idir, isp) * xx(idir)
151 end do
152 end do
153 exc = exc + dmf_integrate(gr, rfxc)
154 safe_deallocate_a(rfxc)
155 end do
156
157 pop_sub(get_virial_energy)
158 end function get_virial_energy
159
160
161 ! -------------------------------------------------------------------------------------
168 subroutine lda_c_fbe (st, n_blocks, l_dens, l_dedd, l_zk)
169 type(states_elec_t), intent(in) :: st
170 integer, intent(in) :: n_blocks
171 real(real64), intent(in) :: l_dens(:,:)
172 real(real64), intent(inout) :: l_dedd(:,:)
173 real(real64), optional, intent(inout) :: l_zk(:)
174
175 integer :: ip, ispin
176 real(real64) :: rho, beta, beta2, e_c
177 real(real64) :: q
178
179 push_sub(lda_c_fbe)
180
181 ! Set q such that we get the leading order of the r_s->0 limit for the HEG
182 q = ((5.0_real64*sqrt(m_pi)**5)/(m_three*(m_one-log(m_two))))**(m_third)
183 if (present(l_zk)) l_zk = m_zero
184
185 do ip = 1, n_blocks
186 rho = sum(l_dens(1:st%d%spin_channels, ip))
187 if (rho < 1e-20_real64) then
188 l_dedd(1:st%d%spin_channels, ip) = m_zero
189 cycle
190 end if
191 rho = max(rho, 1e-12_real64)
192 beta = q*rho**m_third
193 beta2 = beta**2
194
195 ! Potential
196 ! First part of the potential
197 l_dedd(1:st%d%spin_channels, ip) = (m_pi/(q**3))*((sqrt(m_pi)*beta/(m_one+sqrt(m_pi)*beta))**2 -m_one) * beta
198 ! Second part of the potential
199 l_dedd(1:st%d%spin_channels, ip) = l_dedd(1:st%d%spin_channels, ip) &
200 - (5.0_real64*sqrt(m_pi))/(m_three*q**3)*(log(m_one+sqrt(m_pi)*beta) &
201 -m_half/(m_one+sqrt(m_pi)*beta)**2 + m_two/(m_one+sqrt(m_pi)*beta)) + (5.0_real64*sqrt(m_pi))/(m_two*q**3)
202
203 if (st%d%nspin == 1 .and. present(l_zk)) then
204 ! Energy density
205 ! First part of the energy density
206 e_c = (9.0_real64*q**3)/m_two/beta &
207 - m_two*q**3*sqrt(m_pi) &
208 - 12.0_real64/beta2*(q**3/sqrt(m_pi)) &
209 + m_three/(m_pi*rho)*(m_one/(m_one+sqrt(m_pi)*beta) - m_one &
210 + 5.0_real64*log(m_one+sqrt(m_pi)*beta))
211
212 ! Second part of the energy density
213 e_c = e_c - 5.0_real64/6.0_real64*( &
214 7.0_real64*q**3/beta &
215 + m_three/(m_pi*rho*(m_one+sqrt(m_pi)*beta)) &
216 - 17.0_real64*q**3/sqrt(m_pi)/beta2 &
217 - 11.0_real64*q**3*sqrt(m_pi)/(m_three) &
218 + (20.0_real64/(m_pi*rho) + m_two*sqrt(m_pi)*q**3)*log(m_one+sqrt(m_pi)*beta) &
219 - m_three/(m_pi*rho))
220 e_c = e_c/(q**6)
221 l_zk(ip) = e_c
222 else if(st%d%nspin == 2) then
223 ! Here we have no energy density, so leave the potential unchanged
224 ! This is the approximate potential that we implement here
225 do ispin = 1, st%d%spin_channels
226 l_dedd(ispin, ip) = l_dedd(ispin, ip) * m_two * l_dens(-ispin+3, ip) / rho
227 end do
228 end if
229 end do
230
231 pop_sub(lda_c_fbe)
232 end subroutine lda_c_fbe
233
234 ! -------------------------------------------------------------------------------------
236 subroutine fbe_c_lda_sl (namespace, psolver, sl_solver, gr, st, space, ec, vxc)
237 type(namespace_t), intent(in) :: namespace
238 type(poisson_t), intent(in) :: psolver
239 type(sturm_liouville_t), intent(inout) :: sl_solver
240 type(grid_t), target, intent(in) :: gr
241 type(states_elec_t), intent(inout) :: st
242 type(space_t), intent(in) :: space
243 real(real64), intent(inout) :: ec
244 real(real64), contiguous, optional, intent(inout) :: vxc(:,:)
245
246 integer :: idir, ip, ispin
247 real(real64), allocatable :: fxc(:,:,:), internal_vxc(:,:), grad_rho(:,:,:), tmp1(:,:), tmp2(:,:)
248 real(real64) :: q, beta, rho, l_gdens
249
250 push_sub(fbe_c_lda_sl)
251
252 safe_allocate(internal_vxc(1:gr%np, 1:st%d%spin_channels))
253
254 ! Needed to get the initial guess for the iterative solution of the Sturm-Liouville equation
255 safe_allocate(tmp1(1:st%d%spin_channels, 1:gr%np))
256 safe_allocate(tmp2(1:st%d%spin_channels, 1:gr%np))
257 tmp1 = transpose(st%rho(1:gr%np, 1:st%d%spin_channels))
258 call lda_c_fbe(st, gr%np, tmp1, tmp2)
259 internal_vxc = transpose(tmp2)
260 safe_deallocate_a(tmp1)
261 safe_deallocate_a(tmp2)
262
263 ! Set q such that we get the leading order of the r_s->0 limit for the HEG
264 q = ((5.0_real64*sqrt(m_pi)**5)/(m_three*(m_one-log(m_two))))**(m_third)
265
266 safe_allocate(fxc(1:gr%np_part, 1:gr%box%dim, 1:st%d%spin_channels))
267 safe_allocate(grad_rho(1:gr%np, 1:gr%box%dim, 1:st%d%spin_channels))
268 do ispin = 1, st%d%spin_channels
269 call dderivatives_grad(gr%der, st%rho(:, ispin), grad_rho(:, :, ispin))
270 end do
271
272 do ispin = 1, st%d%spin_channels
273 do idir = 1, gr%box%dim
274 do ip = 1, gr%np
275 rho = sum(st%rho(ip, 1:st%d%spin_channels))
276 if (st%rho(ip, ispin) < 1e-20_real64) then
277 fxc(ip, idir, ispin) = m_zero
278 cycle
279 end if
280 rho = max(rho, 1e-12_real64)
281 beta = rho**m_third * q
282
283 l_gdens = sum(grad_rho(ip, idir, 1:st%d%spin_channels))
284
285 if (st%d%spin_channels == 1) then
286 fxc(ip, idir, ispin) = l_gdens * &
287 ( m_pi * beta**2/((m_one + sqrt(m_pi)*beta)**2) - m_one &
288 + m_third * m_pi * beta**2 / ((m_one + sqrt(m_pi)*beta)**3) )
289 else
290 fxc(ip, idir, ispin) = m_two * (grad_rho(ip, idir, 3-ispin) * &
291 (m_pi * beta**2/((m_one + sqrt(m_pi)*beta)**2) - m_one ) &
292 + l_gdens * (m_third * m_pi * beta**2 / ((m_one + sqrt(m_pi)*beta)**3) ) &
293 * st%rho(ip, 3-ispin) / rho)
294 end if
295
296 fxc(ip, idir, ispin) = fxc(ip, idir, ispin) * m_pi/(m_three*beta**2) * st%rho(ip, ispin)
297 end do
298 end do
299 end do
300
301 ! We solve the Sturm-Liouville equation
302 if (present(vxc)) then
303 do ispin = 1, st%d%spin_channels
304 call sturm_liouville_solve_from_div(sl_solver, namespace, st%rho(:, ispin), fxc(:, :, ispin), internal_vxc(:, ispin))
305 end do
306 end if
307
308 ! Get the energy from the virial relation
309 ec = get_virial_energy(gr, st%d%spin_channels, fxc)
310
311 ! Adds the calculated potential
312 if (present(vxc)) then
313 call lalg_axpy(gr%np, st%d%spin_channels, m_one, internal_vxc, vxc)
314 end if
315
316 safe_deallocate_a(fxc)
317
318 pop_sub(fbe_c_lda_sl)
319 end subroutine fbe_c_lda_sl
320
321#include "undef.F90"
322#include "real.F90"
323#include "xc_fbe_inc.F90"
324
325#include "undef.F90"
326#include "complex.F90"
327#include "xc_fbe_inc.F90"
328
329end module xc_fbe_oct_m
330
331!! Local Variables:
332!! mode: f90
333!! coding: utf-8
334!! End:
constant times a vector plus a vector
Definition: lalg_basic.F90:173
double log(double __x) __attribute__((__nothrow__
double sqrt(double __x) __attribute__((__nothrow__
This module implements batches of mesh functions.
Definition: batch.F90:135
This module implements common operations on batches of mesh functions.
Definition: batch_ops.F90:118
This module calculates the derivatives (gradients, Laplacians, etc.) of a function.
real(real64), parameter, public m_zero
Definition: global.F90:200
real(real64), parameter, public m_one
Definition: global.F90:201
This module implements the underlying real-space grid.
Definition: grid.F90:119
Computes and , suitable as an operator callback for iterative solvers (CG, QMR, etc....
This module is intended to contain "only mathematical" functions and procedures.
Definition: math.F90:117
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:343
This module defines non-local operators.
This module is an helper to perform ring-pattern communications among all states.
This module is intended to contain "only mathematical" functions and procedures.
Definition: solvers.F90:117
pure logical function, public states_are_real(st)
This module provides routines for communicating all batches in a ring-pattern scheme.
This module handles spin dimensions of the states and the k-point distribution.
General Sturm-Liouville solver for equations of the form .
subroutine, public sturm_liouville_solve_from_div(this, namespace, rho, f, v, psolver)
Solve the Sturm-Liouville equation from a divergence.
subroutine, public lda_c_fbe(st, n_blocks, l_dens, l_dedd, l_zk)
Computes the local density correlation potential and energy obtained from the Colle-Salvetti approxim...
Definition: xc_fbe.F90:264
subroutine dx_fbe_calc(namespace, psolver, sl_solver, gr, st, ex, vxc, fxc)
Definition: xc_fbe.F90:486
subroutine, public fbe_c_lda_sl(namespace, psolver, sl_solver, gr, st, space, ec, vxc)
Sturm-Liouville version of the FBE local-density correlation functional.
Definition: xc_fbe.F90:332
subroutine zx_fbe_calc(namespace, psolver, sl_solver, gr, st, ex, vxc, fxc)
Definition: xc_fbe.F90:868
subroutine, public x_fbe_calc(id, namespace, psolver, sl_solver, gr, st, space, ex, vxc)
Interface to X(x_fbe_calc) Two possible run modes possible: adiabatic and Sturm-Liouville....
Definition: xc_fbe.F90:169
real(real64) function get_virial_energy(gr, nspin, fxc)
Computes the energy from the force virial relation.
Definition: xc_fbe.F90:228
integer, parameter, public xc_oep_x_fbe_sl
Exchange approximation based on the force balance equation - Sturn-Liouville version.
integer, parameter, public xc_oep_x_fbe
Exchange approximation based on the force balance equation.