51 real(real64),
parameter :: alpha_ =
m_five
53 integer,
parameter :: &
60 integer :: method = corr_none
62 real(real64),
allocatable :: phi(:, :)
63 real(real64),
allocatable :: aux(:, :)
64 real(real64),
allocatable :: gaussian(:)
67 type(derivatives_t),
pointer :: der_pointer
68 type(mesh_t),
pointer :: mesh_pointer
74 type(poisson_corr_t),
intent(out) :: this
75 type(namespace_t),
intent(in) :: namespace
76 class(space_t),
intent(in) :: space
77 integer,
intent(in) :: ml
78 type(mesh_t),
intent(in) :: mesh
80 real(real64) :: alpha, beta, ylm, rr, xx(space%dim)
81 integer :: ip, ll, add_lm, lldfac, jj, mm
85 assert(space%dim == 3)
87 if (space%is_periodic())
then
108 select case (this%method)
119 safe_allocate(this%phi(1:mesh%np, 1:add_lm))
120 safe_allocate(this%aux(1:mesh%np, 1:add_lm))
121 safe_allocate(this%gaussian(1:mesh%np))
123 alpha = alpha_ * mesh%spacing(1)
125 call mesh_r(mesh, ip, rr, coords = xx)
126 this%gaussian(ip) =
exp(-(rr/alpha)**2)
133 beta =
sqrt(
m_pi)*2**(ll+3) / lldfac
137 this%phi(ip, add_lm) = beta*
isubl(ll, rr/alpha)*ylm/rr**(ll+1)
138 this%aux(ip, add_lm) = rr**ll*ylm
140 this%phi(ip, add_lm) = beta*ylm / alpha
142 this%aux(ip, add_lm) = ylm
144 this%aux(ip, add_lm) =
m_zero
154 if (mesh%parallel_in_domains)
call messages_not_implemented(
'Exact Poisson solver boundaries with domain parallelization')
163 real(real64) function
isubl( ll, xx)
164 integer,
intent(in) :: ll
165 real(real64),
intent(in) :: xx
181 select case (this%method)
183 safe_deallocate_a(this%phi)
184 safe_deallocate_a(this%aux)
185 safe_deallocate_a(this%gaussian)
194 subroutine correct_rho(this, der, rho, rho_corrected, vh_correction)
196 type(derivatives_t),
intent(in) :: der
197 real(real64),
contiguous,
intent(in) :: rho(:)
198 real(real64),
contiguous,
intent(out) :: rho_corrected(:)
199 real(real64),
contiguous,
intent(out) :: vh_correction(:)
201 integer :: ip, add_lm, ll, mm, lldfac, jj, ip2
202 real(real64) :: alpha, vv, rr
203 real(real64),
allocatable :: mult(:)
204 real(real64),
allocatable :: betal(:)
207 call profiling_in(
"POISSON_CORRECT")
209 assert(ubound(vh_correction, dim = 1) == der%mesh%np_part)
211 select case (this%method)
214 safe_allocate(mult(1:(this%maxl+1)**2))
217 alpha =
alpha_ * der%mesh%spacing(1)
219 safe_allocate(betal(1:(this%maxl+1)**2))
227 betal(add_lm) = (2**(ll + 2)) / (alpha**(2*ll+3) *
sqrt(m_pi) * lldfac)
232 call lalg_copy(der%mesh%np, rho, rho_corrected)
233 vh_correction = m_zero
237 do ip = 1, der%mesh%np
238 rho_corrected(ip) = rho_corrected(ip) - mult(add_lm)*betal(add_lm)*this%aux(ip, add_lm)*this%gaussian(ip)
240 call lalg_axpy(der%mesh%np, mult(add_lm), this%phi(:, add_lm), vh_correction)
245 safe_deallocate_a(mult)
246 safe_deallocate_a(betal)
250 do ip = 1, der%mesh%np
251 vh_correction(ip) = m_zero
254 do ip = der%mesh%np + 1, der%mesh%np_part
256 do ip2 = 1, der%mesh%np
257 rr = norm2((der%mesh%x(1:der%dim, ip) - der%mesh%x(1:der%dim, ip2)))
258 vv = vv + rho(ip2)/rr
260 vh_correction(ip) = der%mesh%volume_element*vv
263 call dderivatives_lapl(der, vh_correction, rho_corrected, set_bc = .false.)
265 do ip = 1, der%mesh%np
266 rho_corrected(ip) = rho(ip) + m_one/(m_four*m_pi)*rho_corrected(ip)
271 call profiling_out(
"POISSON_CORRECT")
279 type(mesh_t),
intent(in) :: mesh
280 real(real64),
intent(in) :: rho(:)
281 integer,
intent(in) :: ml
282 real(real64),
intent(out) :: mult((ml+1)**2)
284 integer :: add_lm, ll, mm
292 mult(add_lm) = dmf_dotp(mesh, rho, this%aux(:, add_lm))
303 real(real64),
intent(in) :: xx(:)
304 real(real64),
intent(in) :: yy(:)
316 type(mesh_t),
intent(in) :: mesh
317 real(real64),
intent(in) :: rho(:)
318 real(real64),
intent(inout) :: pot(:)
320 integer :: ip, add_lm, ll, mm, bp_lower
321 real(real64) :: xx(mesh%box%dim), rr, s1, sa
322 real(real64),
allocatable :: mult(:)
326 assert(mesh%box%dim == 3)
328 safe_allocate(mult(1:(this%maxl+1)**2))
332 bp_lower = mesh%np + 1
333 if (mesh%parallel_in_domains)
then
334 bp_lower = bp_lower + mesh%pv%np_ghost
337 pot(bp_lower:mesh%np_part) = m_zero
338 do ip = bp_lower, mesh%np_part
339 call mesh_r(mesh, ip, rr, coords = xx)
342 s1 = m_four*m_pi/((m_two*ll + m_one)*rr**(ll + 1))
344 call ylmr_real(xx, ll, mm, sa)
345 pot(ip) = pot(ip) + sa * mult(add_lm) * s1
351 safe_deallocate_a(mult)
Define which routines can be seen from the outside.
double exp(double __x) __attribute__((__nothrow__
double sqrt(double __x) __attribute__((__nothrow__
This module calculates the derivatives (gradients, Laplacians, etc.) of a function.
real(real64), parameter, public m_zero
real(real64), parameter, public m_pi
some mathematical constants
real(real64), parameter, public m_epsilon
real(real64), parameter, public m_half
real(real64), parameter, public m_one
real(real64), parameter, public m_five
This module is intended to contain "only mathematical" functions and procedures.
subroutine, public ylmr_real(xx, li, mi, ylm)
This is a Numerical Recipes-based subroutine computes real spherical harmonics ylm at position (x,...
This module defines various routines, operating on mesh functions.
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
subroutine, public messages_not_implemented(feature, namespace)
subroutine, public messages_experimental(name, namespace)
This module defines non-local operators.
integer, parameter corr_multipole
subroutine get_multipoles(this, mesh, rho, ml, mult)
subroutine, public poisson_corrections_end(this)
real(real64) function, public internal_dotp(xx, yy)
subroutine, public poisson_boundary_conditions(this, mesh, rho, pot)
subroutine, public poisson_corrections_init(this, namespace, space, ml, mesh)
integer, parameter corr_exact
real(real64), parameter alpha_
type(mesh_t), pointer, public mesh_pointer
subroutine, public correct_rho(this, der, rho, rho_corrected, vh_correction)
type(derivatives_t), pointer, public der_pointer
real(real64) function isubl(ll, xx)