63 real(real64),
pointer :: rho_aux(:) => null()
64 real(real64),
pointer :: lapl_rho_aux(:) => null()
65 real(real64),
allocatable :: diag_lapl(:)
76 subroutine x_fbe_calc (id, namespace, psolver, gr, st, space, ex, vxc)
77 integer,
intent(in) :: id
78 type(namespace_t),
intent(in) :: namespace
79 type(poisson_t),
intent(in) :: psolver
80 type(grid_t),
target,
intent(in) :: gr
81 type(states_elec_t),
intent(inout) :: st
82 type(space_t),
intent(in) :: space
83 real(real64),
intent(inout) :: ex
84 real(real64),
contiguous,
optional,
intent(inout) :: vxc(:,:)
86 real(real64),
allocatable :: fxc(:,:,:), internal_vxc(:,:)
93 call dx_fbe_calc(namespace, psolver, gr, st, ex, vxc=vxc)
95 call zx_fbe_calc(namespace, psolver, gr, st, ex, vxc=vxc)
98 safe_allocate(fxc(1:gr%np_part, 1:gr%box%dim, 1:st%d%spin_channels))
99 safe_allocate(internal_vxc(1:gr%np, 1:st%d%spin_channels))
103 call dx_fbe_calc(namespace, psolver, gr, st, ex, vxc=internal_vxc, fxc=fxc)
105 call zx_fbe_calc(namespace, psolver, gr, st, ex, vxc=internal_vxc, fxc=fxc)
109 if (
present(vxc))
then
119 safe_deallocate_a(fxc)
120 safe_deallocate_a(internal_vxc)
132 type(namespace_t),
intent(in) :: namespace
133 type(grid_t),
target,
intent(in) :: gr
134 type(states_elec_t),
target,
intent(in) :: st
135 type(space_t),
intent(in) :: space
136 real(real64),
contiguous,
intent(inout) :: fxc(:,:,:)
137 real(real64),
contiguous,
intent(inout) :: vxc(:,:)
139 real(real64),
allocatable :: rhs(:)
140 integer :: iter, ispin
142 real(real64),
parameter :: threshold = 1e-7_real64
143 character(len=80) :: name
145 type(nl_operator_t) :: op(1)
149 assert(ubound(fxc, dim=1) >= gr%np_part)
154 name =
'FBE preconditioner'
156 safe_allocate(diag_lapl(1:op(1)%np))
160 safe_allocate(rhs(1:gr%np))
161 safe_allocate(lapl_rho_aux(1:gr%np))
163 do ispin = 1, st%d%spin_channels
166 rho_aux => st%rho(:, ispin)
172 iter, userdata=[c_loc(gr)], residue = res, threshold = threshold, showprogress = .false.)
174 write(
message(1),
'(a, i6, a)')
"Info: Sturm-Liouville solver converged in ", iter,
" iterations."
175 write(
message(2),
'(a, es14.6)')
"Info: The residue is ", res
179 safe_deallocate_p(lapl_rho_aux)
180 safe_deallocate_a(rhs)
181 safe_deallocate_a(diag_lapl)
195 real(real64),
contiguous,
intent(in) :: x(:)
196 real(real64),
contiguous,
intent(out) :: hx(:)
197 type(c_ptr),
intent(in) :: userdata(:)
200 real(real64),
allocatable :: vxc(:)
201 real(real64),
allocatable :: prod(:)
202 real(real64),
allocatable :: lapl_vxc(:)
203 real(real64),
allocatable :: lapl_product(:)
204 type(
grid_t),
pointer :: gr
206 assert(
size(userdata) == 1)
207 assert(c_associated(userdata(1)))
208 call c_f_pointer(userdata(1), gr)
210 safe_allocate(vxc(1:gr%np_part))
211 safe_allocate(lapl_vxc(1:gr%np))
215 safe_allocate(prod(1:gr%np_part))
216 safe_allocate(lapl_product(1:gr%np))
217 do ip = 1, gr%np_part
218 prod(ip) = rho_aux(ip) * vxc(ip)
223 hx(ip) =
m_half * (rho_aux(ip) * lapl_vxc(ip) - vxc(ip) * lapl_rho_aux(ip) + lapl_product(ip))
226 safe_deallocate_a(vxc)
227 safe_deallocate_a(prod)
228 safe_deallocate_a(lapl_vxc)
229 safe_deallocate_a(lapl_product)
238 real(real64),
contiguous,
intent(in) :: x(:)
239 real(real64),
contiguous,
intent(out) :: hx(:)
240 type(c_ptr),
intent(in) :: userdata(:)
243 type(
grid_t),
pointer :: gr
245 assert(
size(userdata) == 1)
246 assert(c_associated(userdata(1)))
247 call c_f_pointer(userdata(1), gr)
251 hx(ip) = x(ip) / (max(rho_aux(ip), 1.0e-12_real64) * diag_lapl(ip))
258 real(real64) function get_virial_energy(gr, nspin, fxc) result(exc)
259 type(
grid_t),
intent(in) :: gr
260 integer,
intent(in) :: nspin
261 real(real64),
intent(in) :: fxc(:,:,:)
263 integer :: isp, idir, ip
264 real(real64),
allocatable :: rfxc(:)
265 real(real64) :: xx(gr%box%dim), rr
267 push_sub(get_virial_energy)
271 safe_allocate(rfxc(1:gr%np))
274 call mesh_r(gr, ip, rr, coords=xx)
275 do idir = 1, gr%box%dim
276 rfxc(ip) = rfxc(ip) + fxc(ip, idir, isp) * xx(idir)
280 safe_deallocate_a(rfxc)
283 pop_sub(get_virial_energy)
294 subroutine lda_c_fbe (st, n_blocks, l_dens, l_dedd, l_zk)
295 type(states_elec_t),
intent(in) :: st
296 integer,
intent(in) :: n_blocks
297 real(real64),
intent(in) :: l_dens(:,:)
298 real(real64),
intent(inout) :: l_dedd(:,:)
299 real(real64),
optional,
intent(inout) :: l_zk(:)
302 real(real64) :: rho, beta, beta2, e_c
308 q = ((5.0_real64*
sqrt(m_pi)**5)/(m_three*(m_one-
log(m_two))))**(m_third)
309 if (
present(l_zk)) l_zk = m_zero
312 rho = sum(l_dens(1:st%d%spin_channels, ip))
313 if (rho < 1e-20_real64)
then
314 l_dedd(1:st%d%spin_channels, ip) = m_zero
317 rho = max(rho, 1e-12_real64)
318 beta = q*rho**m_third
323 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
325 l_dedd(1:st%d%spin_channels, ip) = l_dedd(1:st%d%spin_channels, ip) &
326 - (5.0_real64*
sqrt(m_pi))/(m_three*q**3)*(
log(m_one+
sqrt(m_pi)*beta) &
327 -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)
329 if (st%d%nspin == 1 .and.
present(l_zk))
then
332 e_c = (9.0_real64*q**3)/m_two/beta &
333 - m_two*q**3*
sqrt(m_pi) &
334 - 12.0_real64/beta2*(q**3/
sqrt(m_pi)) &
335 + m_three/(m_pi*rho)*(m_one/(m_one+
sqrt(m_pi)*beta) - m_one &
336 + 5.0_real64*
log(m_one+
sqrt(m_pi)*beta))
339 e_c = e_c - 5.0_real64/6.0_real64*( &
340 7.0_real64*q**3/beta &
341 + m_three/(m_pi*rho*(m_one+
sqrt(m_pi)*beta)) &
342 - 17.0_real64*q**3/
sqrt(m_pi)/beta2 &
343 - 11.0_real64*q**3*
sqrt(m_pi)/(m_three) &
344 + (20.0_real64/(m_pi*rho) + m_two*
sqrt(m_pi)*q**3)*
log(m_one+
sqrt(m_pi)*beta) &
345 - m_three/(m_pi*rho))
348 else if(st%d%nspin == 2)
then
351 do ispin = 1, st%d%spin_channels
352 l_dedd(ispin, ip) = l_dedd(ispin, ip) * m_two * l_dens(-ispin+3, ip) / rho
362 subroutine fbe_c_lda_sl (namespace, gr, st, space, ec, vxc)
363 type(namespace_t),
intent(in) :: namespace
364 type(grid_t),
target,
intent(in) :: gr
365 type(states_elec_t),
intent(inout) :: st
366 type(space_t),
intent(in) :: space
367 real(real64),
intent(inout) :: ec
368 real(real64),
contiguous,
optional,
intent(inout) :: vxc(:,:)
370 integer :: idir, ip, ispin
371 real(real64),
allocatable :: fxc(:,:,:), internal_vxc(:,:), grad_rho(:,:,:), tmp1(:,:), tmp2(:,:)
372 real(real64) :: q, beta, rho, l_gdens
376 safe_allocate(internal_vxc(1:gr%np, 1:st%d%spin_channels))
379 safe_allocate(tmp1(1:st%d%spin_channels, 1:gr%np))
380 safe_allocate(tmp2(1:st%d%spin_channels, 1:gr%np))
381 tmp1 = transpose(st%rho(1:gr%np, 1:st%d%spin_channels))
383 internal_vxc = transpose(tmp2)
384 safe_deallocate_a(tmp1)
385 safe_deallocate_a(tmp2)
388 q = ((5.0_real64*
sqrt(m_pi)**5)/(m_three*(m_one-
log(m_two))))**(m_third)
390 safe_allocate(fxc(1:gr%np_part, 1:gr%box%dim, 1:st%d%spin_channels))
391 safe_allocate(grad_rho(1:gr%np, 1:gr%box%dim, 1:st%d%spin_channels))
392 do ispin = 1, st%d%spin_channels
393 call dderivatives_grad(gr%der, st%rho(:, ispin), grad_rho(:, :, ispin))
396 do ispin = 1, st%d%spin_channels
397 do idir = 1, gr%box%dim
399 rho = sum(st%rho(ip, 1:st%d%spin_channels))
400 if (st%rho(ip, ispin) < 1e-20_real64)
then
401 fxc(ip, idir, ispin) = m_zero
404 rho = max(rho, 1e-12_real64)
405 beta = rho**m_third * q
407 l_gdens = sum(grad_rho(ip, idir, 1:st%d%spin_channels))
409 if (st%d%spin_channels == 1)
then
410 fxc(ip, idir, ispin) = l_gdens * &
411 ( m_pi * beta**2/((m_one +
sqrt(m_pi)*beta)**2) - m_one &
412 + m_third * m_pi * beta**2 / ((m_one +
sqrt(m_pi)*beta)**3) )
414 fxc(ip, idir, ispin) = m_two * (grad_rho(ip, idir, 3-ispin) * &
415 (m_pi * beta**2/((m_one +
sqrt(m_pi)*beta)**2) - m_one ) &
416 + l_gdens * (m_third * m_pi * beta**2 / ((m_one +
sqrt(m_pi)*beta)**3) ) &
417 * st%rho(ip, 3-ispin) / rho)
420 fxc(ip, idir, ispin) = fxc(ip, idir, ispin) * m_pi/(m_three*beta**2) * st%rho(ip, ispin)
426 if (
present(vxc))
then
434 call lalg_axpy(gr%np, st%d%spin_channels, m_one, internal_vxc, vxc)
436 safe_deallocate_a(fxc)
444 real(real64),
contiguous,
intent(in) :: x(:)
445 real(real64),
contiguous,
intent(out) :: hx(:)
446 type(c_ptr),
intent(in) :: userdata(:)
448 real(real64),
allocatable :: tmpx(:)
449 type(grid_t),
pointer :: gr
451 assert(
size(userdata) == 1)
452 assert(c_associated(userdata(1)))
453 call c_f_pointer(userdata(1), gr)
455 safe_allocate(tmpx(1:gr%np_part))
456 call lalg_copy(gr%np, x, tmpx)
457 call dderivatives_lapl(gr%der, tmpx, hx, factor=-m_one)
458 safe_deallocate_a(tmpx)
465#include "xc_fbe_inc.F90"
468#include "complex.F90"
469#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.
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 dlaplacian_op(x, hx, userdata)
Computes .
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.