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)
241 real(real64),
contiguous,
intent(in) :: x(:)
242 real(real64),
contiguous,
intent(out) :: hx(:)
243 type(c_ptr),
intent(in) :: userdata(:)
246 type(
grid_t),
pointer :: gr
248 assert(
size(userdata) == 1)
249 assert(c_associated(userdata(1)))
250 call c_f_pointer(userdata(1), gr)
254 hx(ip) = x(ip) / (max(rho_aux(ip), 1.0e-12_real64) * diag_lapl(ip))
261 real(real64) function get_virial_energy(gr, nspin, fxc) result(exc)
262 type(
grid_t),
intent(in) :: gr
263 integer,
intent(in) :: nspin
264 real(real64),
intent(in) :: fxc(:,:,:)
266 integer :: isp, idir, ip
267 real(real64),
allocatable :: rfxc(:)
268 real(real64) :: xx(gr%box%dim), rr
270 push_sub(get_virial_energy)
274 safe_allocate(rfxc(1:gr%np))
277 call mesh_r(gr, ip, rr, coords=xx)
278 do idir = 1, gr%box%dim
279 rfxc(ip) = rfxc(ip) + fxc(ip, idir, isp) * xx(idir)
283 safe_deallocate_a(rfxc)
286 pop_sub(get_virial_energy)
297 subroutine lda_c_fbe (st, n_blocks, l_dens, l_dedd, l_zk)
298 type(states_elec_t),
intent(in) :: st
299 integer,
intent(in) :: n_blocks
300 real(real64),
intent(in) :: l_dens(:,:)
301 real(real64),
intent(inout) :: l_dedd(:,:)
302 real(real64),
optional,
intent(inout) :: l_zk(:)
305 real(real64) :: rho, beta, beta2, e_c
311 q = ((5.0_real64*
sqrt(m_pi)**5)/(m_three*(m_one-
log(m_two))))**(m_third)
312 if (
present(l_zk)) l_zk = m_zero
315 rho = sum(l_dens(1:st%d%spin_channels, ip))
316 if (rho < 1e-20_real64)
then
317 l_dedd(1:st%d%spin_channels, ip) = m_zero
320 rho = max(rho, 1e-12_real64)
321 beta = q*rho**m_third
326 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
328 l_dedd(1:st%d%spin_channels, ip) = l_dedd(1:st%d%spin_channels, ip) &
329 - (5.0_real64*
sqrt(m_pi))/(m_three*q**3)*(
log(m_one+
sqrt(m_pi)*beta) &
330 -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)
332 if (st%d%nspin == 1 .and.
present(l_zk))
then
335 e_c = (9.0_real64*q**3)/m_two/beta &
336 - m_two*q**3*
sqrt(m_pi) &
337 - 12.0_real64/beta2*(q**3/
sqrt(m_pi)) &
338 + m_three/(m_pi*rho)*(m_one/(m_one+
sqrt(m_pi)*beta) - m_one &
339 + 5.0_real64*
log(m_one+
sqrt(m_pi)*beta))
342 e_c = e_c - 5.0_real64/6.0_real64*( &
343 7.0_real64*q**3/beta &
344 + m_three/(m_pi*rho*(m_one+
sqrt(m_pi)*beta)) &
345 - 17.0_real64*q**3/
sqrt(m_pi)/beta2 &
346 - 11.0_real64*q**3*
sqrt(m_pi)/(m_three) &
347 + (20.0_real64/(m_pi*rho) + m_two*
sqrt(m_pi)*q**3)*
log(m_one+
sqrt(m_pi)*beta) &
348 - m_three/(m_pi*rho))
351 else if(st%d%nspin == 2)
then
354 do ispin = 1, st%d%spin_channels
355 l_dedd(ispin, ip) = l_dedd(ispin, ip) * m_two * l_dens(-ispin+3, ip) / rho
365 subroutine fbe_c_lda_sl (namespace, gr, st, space, ec, vxc)
366 type(namespace_t),
intent(in) :: namespace
367 type(grid_t),
target,
intent(in) :: gr
368 type(states_elec_t),
intent(inout) :: st
369 type(space_t),
intent(in) :: space
370 real(real64),
intent(inout) :: ec
371 real(real64),
contiguous,
optional,
intent(inout) :: vxc(:,:)
373 integer :: idir, ip, ispin
374 real(real64),
allocatable :: fxc(:,:,:), internal_vxc(:,:), grad_rho(:,:,:), tmp1(:,:), tmp2(:,:)
375 real(real64) :: q, beta, rho, l_gdens
379 safe_allocate(internal_vxc(1:gr%np, 1:st%d%spin_channels))
382 safe_allocate(tmp1(1:st%d%spin_channels, 1:gr%np))
383 safe_allocate(tmp2(1:st%d%spin_channels, 1:gr%np))
384 tmp1 = transpose(st%rho(1:gr%np, 1:st%d%spin_channels))
386 internal_vxc = transpose(tmp2)
387 safe_deallocate_a(tmp1)
388 safe_deallocate_a(tmp2)
391 q = ((5.0_real64*
sqrt(m_pi)**5)/(m_three*(m_one-
log(m_two))))**(m_third)
393 safe_allocate(fxc(1:gr%np_part, 1:gr%box%dim, 1:st%d%spin_channels))
394 safe_allocate(grad_rho(1:gr%np, 1:gr%box%dim, 1:st%d%spin_channels))
395 do ispin = 1, st%d%spin_channels
396 call dderivatives_grad(gr%der, st%rho(:, ispin), grad_rho(:, :, ispin))
399 do ispin = 1, st%d%spin_channels
400 do idir = 1, gr%box%dim
402 rho = sum(st%rho(ip, 1:st%d%spin_channels))
403 if (st%rho(ip, ispin) < 1e-20_real64)
then
404 fxc(ip, idir, ispin) = m_zero
407 rho = max(rho, 1e-12_real64)
408 beta = rho**m_third * q
410 l_gdens = sum(grad_rho(ip, idir, 1:st%d%spin_channels))
412 if (st%d%spin_channels == 1)
then
413 fxc(ip, idir, ispin) = l_gdens * &
414 ( m_pi * beta**2/((m_one +
sqrt(m_pi)*beta)**2) - m_one &
415 + m_third * m_pi * beta**2 / ((m_one +
sqrt(m_pi)*beta)**3) )
417 fxc(ip, idir, ispin) = m_two * (grad_rho(ip, idir, 3-ispin) * &
418 (m_pi * beta**2/((m_one +
sqrt(m_pi)*beta)**2) - m_one ) &
419 + l_gdens * (m_third * m_pi * beta**2 / ((m_one +
sqrt(m_pi)*beta)**3) ) &
420 * st%rho(ip, 3-ispin) / rho)
423 fxc(ip, idir, ispin) = fxc(ip, idir, ispin) * m_pi/(m_three*beta**2) * st%rho(ip, ispin)
429 if (
present(vxc))
then
437 if (
present(vxc))
then
438 call lalg_axpy(gr%np, st%d%spin_channels, m_one, internal_vxc, vxc)
441 safe_deallocate_a(fxc)
448#include "xc_fbe_inc.F90"
451#include "complex.F90"
452#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 Ax = \nabla\cdot(\rho\nabla x) = 1/2(\nabla^2 (\rho x) - x \nabla^2 \rho + \rho \nabla^2 x) ...
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 \nabl...
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.