64 real(real64),
pointer :: rho_aux(:) => null()
65 real(real64),
pointer :: lapl_rho_aux(:) => null()
66 real(real64),
allocatable :: diag_lapl(:)
77 subroutine x_fbe_calc (id, namespace, psolver, gr, st, space, ex, vxc)
78 integer,
intent(in) :: id
79 type(namespace_t),
intent(in) :: namespace
80 type(poisson_t),
intent(in) :: psolver
81 type(grid_t),
target,
intent(in) :: gr
82 type(states_elec_t),
intent(inout) :: st
83 type(space_t),
intent(in) :: space
84 real(real64),
intent(inout) :: ex
85 real(real64),
contiguous,
optional,
intent(inout) :: vxc(:,:)
87 real(real64),
allocatable :: fxc(:,:,:), internal_vxc(:,:)
94 call dx_fbe_calc(namespace, psolver, gr, st, ex, vxc=vxc)
96 call zx_fbe_calc(namespace, psolver, gr, st, ex, vxc=vxc)
99 safe_allocate(fxc(1:gr%np_part, 1:gr%box%dim, 1:st%d%spin_channels))
100 safe_allocate(internal_vxc(1:gr%np, 1:st%d%spin_channels))
104 call dx_fbe_calc(namespace, psolver, gr, st, ex, vxc=internal_vxc, fxc=fxc)
106 call zx_fbe_calc(namespace, psolver, gr, st, ex, vxc=internal_vxc, fxc=fxc)
110 if (
present(vxc))
then
118 if (
present(vxc))
then
119 call lalg_axpy(gr%np, st%d%spin_channels,
m_one, internal_vxc, vxc)
122 safe_deallocate_a(fxc)
123 safe_deallocate_a(internal_vxc)
135 type(namespace_t),
intent(in) :: namespace
136 type(grid_t),
target,
intent(in) :: gr
137 type(states_elec_t),
target,
intent(in) :: st
138 type(space_t),
intent(in) :: space
139 real(real64),
contiguous,
intent(inout) :: fxc(:,:,:)
140 real(real64),
contiguous,
intent(inout) :: vxc(:,:)
142 real(real64),
allocatable :: rhs(:)
143 integer :: iter, ispin
145 real(real64),
parameter :: threshold = 1e-7_real64
146 character(len=80) :: name
148 type(nl_operator_t) :: op(1)
152 assert(ubound(fxc, dim=1) >= gr%np_part)
157 name =
'FBE preconditioner'
159 safe_allocate(diag_lapl(1:op(1)%np))
163 safe_allocate(rhs(1:gr%np))
164 safe_allocate(lapl_rho_aux(1:gr%np))
166 do ispin = 1, st%d%spin_channels
169 rho_aux => st%rho(:, ispin)
175 iter, userdata=[c_loc(gr)], residue = res, threshold = threshold, showprogress = .false.)
177 write(
message(1),
'(a, i6, a)')
"Info: Sturm-Liouville solver converged in ", iter,
" iterations."
178 write(
message(2),
'(a, es14.6)')
"Info: The residue is ", res
182 safe_deallocate_p(lapl_rho_aux)
183 safe_deallocate_a(rhs)
184 safe_deallocate_a(diag_lapl)
198 real(real64),
contiguous,
intent(in) :: x(:)
199 real(real64),
contiguous,
intent(out) :: hx(:)
200 type(c_ptr),
intent(in) :: userdata(:)
203 real(real64),
allocatable :: vxc(:)
204 real(real64),
allocatable :: prod(:)
205 real(real64),
allocatable :: lapl_vxc(:)
206 real(real64),
allocatable :: lapl_product(:)
207 type(
grid_t),
pointer :: gr
209 assert(
size(userdata) == 1)
210 assert(c_associated(userdata(1)))
211 call c_f_pointer(userdata(1), gr)
213 safe_allocate(vxc(1:gr%np_part))
214 safe_allocate(lapl_vxc(1:gr%np))
218 safe_allocate(prod(1:gr%np_part))
219 safe_allocate(lapl_product(1:gr%np))
220 do ip = 1, gr%np_part
221 prod(ip) = rho_aux(ip) * vxc(ip)
226 hx(ip) =
m_half * (rho_aux(ip) * lapl_vxc(ip) - vxc(ip) * lapl_rho_aux(ip) + lapl_product(ip))
229 safe_deallocate_a(vxc)
230 safe_deallocate_a(prod)
231 safe_deallocate_a(lapl_vxc)
232 safe_deallocate_a(lapl_product)
242 real(real64),
contiguous,
intent(in) :: x(:)
243 real(real64),
contiguous,
intent(out) :: hx(:)
244 type(c_ptr),
intent(in) :: userdata(:)
247 type(
grid_t),
pointer :: gr
249 assert(
size(userdata) == 1)
250 assert(c_associated(userdata(1)))
251 call c_f_pointer(userdata(1), gr)
255 hx(ip) = x(ip) / (max(rho_aux(ip), 1.0e-12_real64) * diag_lapl(ip))
262 real(real64) function get_virial_energy(gr, nspin, fxc) result(exc)
263 type(
grid_t),
intent(in) :: gr
264 integer,
intent(in) :: nspin
265 real(real64),
intent(in) :: fxc(:,:,:)
267 integer :: isp, idir, ip
268 real(real64),
allocatable :: rfxc(:)
269 real(real64) :: xx(gr%box%dim), rr
271 push_sub(get_virial_energy)
275 safe_allocate(rfxc(1:gr%np))
278 call mesh_r(gr, ip, rr, coords=xx)
279 do idir = 1, gr%box%dim
280 rfxc(ip) = rfxc(ip) + fxc(ip, idir, isp) * xx(idir)
284 safe_deallocate_a(rfxc)
287 pop_sub(get_virial_energy)
298 subroutine lda_c_fbe (st, n_blocks, l_dens, l_dedd, l_zk)
299 type(states_elec_t),
intent(in) :: st
300 integer,
intent(in) :: n_blocks
301 real(real64),
intent(in) :: l_dens(:,:)
302 real(real64),
intent(inout) :: l_dedd(:,:)
303 real(real64),
optional,
intent(inout) :: l_zk(:)
306 real(real64) :: rho, beta, beta2, e_c
312 q = ((5.0_real64*
sqrt(m_pi)**5)/(m_three*(m_one-
log(m_two))))**(m_third)
313 if (
present(l_zk)) l_zk = m_zero
316 rho = sum(l_dens(1:st%d%spin_channels, ip))
317 if (rho < 1e-20_real64)
then
318 l_dedd(1:st%d%spin_channels, ip) = m_zero
321 rho = max(rho, 1e-12_real64)
322 beta = q*rho**m_third
327 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
329 l_dedd(1:st%d%spin_channels, ip) = l_dedd(1:st%d%spin_channels, ip) &
330 - (5.0_real64*
sqrt(m_pi))/(m_three*q**3)*(
log(m_one+
sqrt(m_pi)*beta) &
331 -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)
333 if (st%d%nspin == 1 .and.
present(l_zk))
then
336 e_c = (9.0_real64*q**3)/m_two/beta &
337 - m_two*q**3*
sqrt(m_pi) &
338 - 12.0_real64/beta2*(q**3/
sqrt(m_pi)) &
339 + m_three/(m_pi*rho)*(m_one/(m_one+
sqrt(m_pi)*beta) - m_one &
340 + 5.0_real64*
log(m_one+
sqrt(m_pi)*beta))
343 e_c = e_c - 5.0_real64/6.0_real64*( &
344 7.0_real64*q**3/beta &
345 + m_three/(m_pi*rho*(m_one+
sqrt(m_pi)*beta)) &
346 - 17.0_real64*q**3/
sqrt(m_pi)/beta2 &
347 - 11.0_real64*q**3*
sqrt(m_pi)/(m_three) &
348 + (20.0_real64/(m_pi*rho) + m_two*
sqrt(m_pi)*q**3)*
log(m_one+
sqrt(m_pi)*beta) &
349 - m_three/(m_pi*rho))
352 else if(st%d%nspin == 2)
then
355 do ispin = 1, st%d%spin_channels
356 l_dedd(ispin, ip) = l_dedd(ispin, ip) * m_two * l_dens(-ispin+3, ip) / rho
366 subroutine fbe_c_lda_sl (namespace, gr, st, space, ec, vxc)
367 type(namespace_t),
intent(in) :: namespace
368 type(grid_t),
target,
intent(in) :: gr
369 type(states_elec_t),
intent(inout) :: st
370 type(space_t),
intent(in) :: space
371 real(real64),
intent(inout) :: ec
372 real(real64),
contiguous,
optional,
intent(inout) :: vxc(:,:)
374 integer :: idir, ip, ispin
375 real(real64),
allocatable :: fxc(:,:,:), internal_vxc(:,:), grad_rho(:,:,:), tmp1(:,:), tmp2(:,:)
376 real(real64) :: q, beta, rho, l_gdens
380 safe_allocate(internal_vxc(1:gr%np, 1:st%d%spin_channels))
383 safe_allocate(tmp1(1:st%d%spin_channels, 1:gr%np))
384 safe_allocate(tmp2(1:st%d%spin_channels, 1:gr%np))
385 tmp1 = transpose(st%rho(1:gr%np, 1:st%d%spin_channels))
387 internal_vxc = transpose(tmp2)
388 safe_deallocate_a(tmp1)
389 safe_deallocate_a(tmp2)
392 q = ((5.0_real64*
sqrt(m_pi)**5)/(m_three*(m_one-
log(m_two))))**(m_third)
394 safe_allocate(fxc(1:gr%np_part, 1:gr%box%dim, 1:st%d%spin_channels))
395 safe_allocate(grad_rho(1:gr%np, 1:gr%box%dim, 1:st%d%spin_channels))
396 do ispin = 1, st%d%spin_channels
397 call dderivatives_grad(gr%der, st%rho(:, ispin), grad_rho(:, :, ispin))
400 do ispin = 1, st%d%spin_channels
401 do idir = 1, gr%box%dim
403 rho = sum(st%rho(ip, 1:st%d%spin_channels))
404 if (st%rho(ip, ispin) < 1e-20_real64)
then
405 fxc(ip, idir, ispin) = m_zero
408 rho = max(rho, 1e-12_real64)
409 beta = rho**m_third * q
411 l_gdens = sum(grad_rho(ip, idir, 1:st%d%spin_channels))
413 if (st%d%spin_channels == 1)
then
414 fxc(ip, idir, ispin) = l_gdens * &
415 ( m_pi * beta**2/((m_one +
sqrt(m_pi)*beta)**2) - m_one &
416 + m_third * m_pi * beta**2 / ((m_one +
sqrt(m_pi)*beta)**3) )
418 fxc(ip, idir, ispin) = m_two * (grad_rho(ip, idir, 3-ispin) * &
419 (m_pi * beta**2/((m_one +
sqrt(m_pi)*beta)**2) - m_one ) &
420 + l_gdens * (m_third * m_pi * beta**2 / ((m_one +
sqrt(m_pi)*beta)**3) ) &
421 * st%rho(ip, 3-ispin) / rho)
424 fxc(ip, idir, ispin) = fxc(ip, idir, ispin) * m_pi/(m_three*beta**2) * st%rho(ip, ispin)
430 if (
present(vxc))
then
438 if (
present(vxc))
then
439 call lalg_axpy(gr%np, st%d%spin_channels, m_one, internal_vxc, vxc)
442 safe_deallocate_a(fxc)
449#include "xc_fbe_inc.F90"
452#include "complex.F90"
453#include "xc_fbe_inc.F90"
constant times a vector plus a vector
Copies a vector x, to a vector y.
double log(double __x) __attribute__((__nothrow__
double sqrt(double __x) __attribute__((__nothrow__
This module implements batches of mesh functions.
This module implements common operations on batches of mesh functions.
This module calculates the derivatives (gradients, Laplacians, etc.) of a function.
subroutine, public derivatives_get_lapl(this, namespace, op, space, name, order)
subroutine, public dderivatives_lapl(der, ff, op_ff, ghost_update, set_bc, factor)
apply the Laplacian to a mesh function
subroutine, public dderivatives_div(der, ff, op_ff, ghost_update, set_bc, to_cartesian)
apply the divergence operator to a vector of mesh functions
real(real64), parameter, public m_zero
real(real64), parameter, public m_half
real(real64), parameter, public m_one
This module implements the underlying real-space grid.
Computes and , suitable as an operator callback for iterative solvers (CG, QMR, etc....
This module is intended to contain "only mathematical" functions and procedures.
This module defines various routines, operating on mesh functions.
real(real64) function, public dmf_dotu_aux(f1, f2)
dot product between two vectors (mesh functions) without conjugation
subroutine, public mesh_init_mesh_aux(mesh)
Initialise a pointer to the grid/mesh, that is globally exposed, such that low level mesh operations ...
real(real64) function, public dmf_nrm2_aux(ff)
calculate norm2 of a vector (mesh function)
This module defines the meshes, which are used in Octopus.
pure subroutine, public mesh_r(mesh, ip, rr, origin, coords)
return the distance to the origin for a given grid point
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
subroutine, public messages_info(no_lines, iunit, debug_only, stress, all_nodes, namespace)
This module defines non-local operators.
subroutine, public dnl_operator_operate_diag(op, fo)
subroutine, public nl_operator_end(op)
This module is an helper to perform ring-pattern communications among all states.
This module is intended to contain "only mathematical" functions and procedures.
subroutine, public dqmr_sym_gen_dotu(np, x, b, op, dotu, nrm2, prec, iter, userdata, residue, threshold, showprogress, converged, use_initial_guess)
for complex symmetric matrices W Chen and B Poirier, J Comput Phys 219, 198-209 (2006)
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.
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...
subroutine dx_fbe_calc(namespace, psolver, gr, st, ex, vxc, fxc)
subroutine solve_sturm_liouville(namespace, gr, st, space, fxc, vxc)
Solve the Sturm-Liouville equation On entry, vxc is the adiabatic one, on exit, it is the solution of...
subroutine sl_operator(x, hx, userdata)
Computes . This is equivalent to . The last equation is used because it only uses Laplace operators a...
subroutine zx_fbe_calc(namespace, psolver, gr, st, ex, vxc, fxc)
subroutine, public x_fbe_calc(id, namespace, psolver, gr, st, space, ex, vxc)
Interface to X(x_fbe_calc) Two possible run modes possible: adiabatic and Sturm-Liouville....
subroutine, public fbe_c_lda_sl(namespace, gr, st, space, ec, vxc)
Sturm-Liouville version of the FBE local-density correlation functional.
subroutine preconditioner(x, hx, userdata)
Simple preconditioner Here we need to approximate P^-1 We use the Jacobi approximation and that .
real(real64) function get_virial_energy(gr, nspin, fxc)
Computes the energy from the force virial relation.
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.
Description of the grid, containing information on derivatives, stencil, and symmetries.