27 use,
intrinsic :: iso_fortran_env
41 use dictionaries, dict_set => set
42 use yaml_output,
only: yaml_map
43 use wrapper_mpi,
only: mpi_environment, mpi_environment_set
62 type(fourier_space_op_t) :: coulb
64 type(coulomb_operator) :: kernel
65 type(dictionary),
pointer :: inputs
79 character(len = 1) :: geocode =
"F"
89 character(len = 1),
public :: datacode =
"G"
92 integer :: localnscatterarr(5)
93 real(real64) :: offset
97 logical,
save :: flib_initialized = .false.
100 real(real64),
parameter :: TOL_VANISHING_Q = 1e-6_real64
106 type(poisson_psolver_t),
intent(out) :: this
107 type(namespace_t),
intent(in) :: namespace
108 class(space_t),
intent(in) :: space
109 type(cube_t),
intent(inout) :: cube
110 real(real64),
intent(in) :: mu
111 real(real64),
intent(in) :: qq(:)
112 logical,
optional,
intent(in) :: force_isolated
114 logical data_is_parallel
116 real(real64) :: alpha, beta, gamma
117 real(real64) :: modq2
118 type(mpi_environment) mpi_env
125 if (.not. flib_initialized)
then
126 call f_lib_initialize()
127 flib_initialized = .
true.
129 call dict_init(this%inputs)
135 select case (space%periodic_dim)
150 call messages_experimental(
"PSolver support for 3D periodic boundary conditions", namespace=namespace)
156 call dict_set(this%inputs//
'setup'//
'verbose', .false.)
158 call dict_set(this%inputs//
'kernel'//
'isf_order', 16)
160 call dict_set(this%inputs//
'kernel'//
'screening', mu)
162 call dict_set(this%inputs//
'kernel'//
'stress_tensor', .false.)
180 call parse_variable(namespace,
'PoissonSolverPSolverParallelData', .
true., data_is_parallel)
181 if (.not. cube%parallel_in_domains)
then
182 data_is_parallel = .false.
188 if (data_is_parallel)
then
189 call dict_set(this%inputs//
'setup'//
'global_data', .false.)
191 call dict_set(this%inputs//
'setup'//
'global_data', .
true.)
194 if (data_is_parallel)
then
202 call dict_set(this%inputs//
'setup'//
'verbose',
debug%info)
204 alpha = cube%latt%alpha*
m_pi/(180.0_real64)
205 beta = cube%latt%beta*
m_pi/(180.0_real64)
206 gamma = cube%latt%gamma*
m_pi/(180.0_real64)
215 call mpi_environment_set(mpi_env, cube%mpi_grp%rank, cube%mpi_grp%size, cube%mpi_grp%comm%MPI_VAL, cube%mpi_grp%size)
217 dom=domain_new(units=atomic_units, bc=geocode_to_bc_enum(this%geocode),&
218 alpha_bc=alpha, beta_ac=beta, gamma_ab=gamma, acell=cube%rs_n_global*cube%spacing)
220 this%kernel = pkernel_init(cube%mpi_grp%rank, cube%mpi_grp%size, this%inputs, dom, cube%rs_n_global, &
221 cube%spacing, alpha_bc = alpha, beta_ac = beta, gamma_ab = gamma, mpi_env = mpi_env)
223 call pkernel_set(this%kernel, verbose=
debug%info)
226 modq2 = sum(qq(1:space%periodic_dim)**2)
228 this%offset =
m_one/modq2
236 this%offset = this%offset*(
m_one -
exp(-modq2/((
m_two*mu)**2)))
255 call pkernel_free(this%kernel)
256 call f_lib_finalize()
257 call dict_free(this%inputs)
266 class(
space_t),
intent(in) :: space
267 type(
cube_t),
intent(inout) :: cube
269 real(real64),
intent(in) :: qq_in(:)
271 real(real64) :: alpha, beta, gamma
272 real(real64) :: qq_abs(1:space%dim), qq(1:space%dim)
273 real(real64) :: modq2
286 call pkernel_free(this%kernel)
290 alpha = cube%latt%alpha*
m_pi/(180.0_real64)
291 beta = cube%latt%beta*
m_pi/(180.0_real64)
292 gamma = cube%latt%gamma*
m_pi/(180.0_real64)
295 call dict_set(this%inputs//
'kernel'//
'screening', coulb%mu)
297 dom=domain_new(units=atomic_units, bc=geocode_to_bc_enum(this%geocode),&
298 alpha_bc=alpha, beta_ac=beta, gamma_ab=gamma, acell=cube%rs_n_global*cube%spacing)
300 this%kernel = pkernel_init(cube%mpi_grp%rank, cube%mpi_grp%size, this%inputs,&
301 dom,cube%rs_n_global, cube%spacing, &
302 alpha_bc = alpha, beta_ac = beta, gamma_ab = gamma)
304 call pkernel_set(this%kernel, verbose=
debug%info)
309 do idim = 1, space%periodic_dim
310 qq(idim) = qq_in(idim) - anint(qq_in(idim) +
m_half*1e-8_real64)
312 qq(space%periodic_dim + 1:space%dim) =
m_zero
314 modq2 = norm2(qq_abs)
315 if (modq2 > tol_vanishing_q)
then
318 this%offset = coulb%singularity
323 if (modq2 > tol_vanishing_q)
then
324 this%offset = this%offset*(
m_one -
exp(-modq2/((
m_two*coulb%mu)**2)))
337 type(
mesh_t),
intent(in) :: mesh
338 type(
cube_t),
intent(in) :: cube
339 real(real64),
intent(out) :: pot(:)
340 real(real64),
intent(in) :: rho(:)
346 type(coulomb_operator),
pointer :: kernel_pointer
347 real(real64) :: hartree_energy
348 real(real64) :: offset
355 real(real64),
allocatable :: pot_ion(:,:,:)
356 character(len=3) :: quiet
362 safe_allocate(pot_ion(1:cube%rs_n(1),1:cube%rs_n(2),1:cube%rs_n(3)))
365 if (
debug%info) quiet =
"NO"
379 kernel_pointer => this%kernel
380 call h_potential(this%datacode, kernel_pointer, cf%dRS, pot_ion, hartree_energy, offset, .false., quiet = quiet)
383 safe_deallocate_a(pot_ion)
395 type(
mesh_t),
intent(in) :: mesh
396 type(
cube_t),
intent(in) :: cube
397 real(real64),
contiguous,
intent(out) :: pot(:)
398 real(real64),
contiguous,
intent(in) :: rho(:)
399 type(
submesh_t),
optional,
intent(in) :: sm
401 character(len=3) :: quiet
405 type(coulomb_operator),
pointer :: kernel_pointer
406 real(real64) :: hartree_energy
407 real(real64) :: offset
415 real(real64),
allocatable :: pot_ion(:,:,:)
421 if (
present(sm))
then
427 safe_allocate(pot_ion(1:cube%rs_n(1), 1:cube%rs_n(2), 1:cube%rs_n(3)))
430 if (
debug%info) quiet =
"NO"
445 kernel_pointer => this%kernel
446 call h_potential(this%datacode, kernel_pointer, &
447 cf%dRS, pot_ion, hartree_energy, offset, .false., &
450 safe_deallocate_a(pot_ion)
452 if (
present(sm))
then
465 type(
cube_t),
intent(inout) :: cube
499 logical :: use_gradient
501 logical :: use_wb_corr
508 use_gradient = .false.
509 use_wb_corr = .false.
510 call ps_dim4allocation(this%geocode, this%datacode, cube%mpi_grp%rank, cube%mpi_grp%size, &
511 cube%rs_n_global(1), cube%rs_n_global(2), cube%rs_n_global(3), &
512 use_gradient, use_wb_corr, &
513 0, n3d, n3p, n3pi, i3xcsh, i3s)
514 this%localnscatterarr(:) = (/ n3d, n3p, n3pi, i3xcsh, i3s /)
516 cube%rs_n(1:2) = cube%rs_n_global(1:2)
517 cube%rs_n(3) = this%localnscatterarr(1)
518 cube%rs_istart(1:2) = 1
519 cube%rs_istart(3) = this%localnscatterarr(5)
523 cube%fs_n_global(1) = cube%rs_n_global(1)
524 cube%fs_n_global(2) = cube%rs_n_global(2)
525 cube%fs_n_global(3) = cube%rs_n_global(3)
526 cube%fs_n(1:2) = cube%rs_n_global(1:2)
527 cube%fs_n(3) = this%localnscatterarr(1)
528 cube%fs_istart(1:2) = 1
529 cube%fs_istart(3) = this%localnscatterarr(5)
double exp(double __x) __attribute__((__nothrow__
subroutine, public dmesh_to_cube(mesh, mf, cube, cf)
The next two subroutines convert a function between the normal mesh and the cube.
subroutine, public dcube_to_submesh(cube, cf, sm, mf)
subroutine, public dcube_to_mesh(cube, cf, mesh, mf)
subroutine, public dcube_function_alloc_rs(cube, cf, in_device, force_alloc)
Allocates locally the real space grid, if PFFT library is not used. Otherwise, it assigns the PFFT re...
subroutine, public dcube_function_free_rs(cube, cf)
Deallocates the real space grid.
subroutine, public dsubmesh_to_cube(sm, mf, cube, cf)
The next two subroutines convert a function between a submesh and the cube.
subroutine, public dmesh_to_cube_parallel(mesh, mf, cube, cf, map)
The next two subroutines convert a function between the normal mesh and the cube in parallel.
subroutine, public dcube_to_mesh_parallel(cube, cf, mesh, mf, map)
type(debug_t), save, public debug
real(real64), parameter, public m_two
real(real64), parameter, public m_zero
real(real64), parameter, public m_four
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
subroutine, public kpoints_to_absolute(latt, kin, kout)
This module defines various routines, operating on mesh functions.
real(real64) function, public dmf_integrate(mesh, ff, mask, reduce)
Integrate a function on the mesh.
This module defines the meshes, which are used in Octopus.
subroutine, public messages_not_implemented(feature, namespace)
subroutine, public messages_obsolete_variable(namespace, name, rep)
subroutine, public messages_experimental(name, namespace)
subroutine, public poisson_psolver_global_solve(this, mesh, cube, pot, rho, sm)
subroutine, public poisson_psolver_parallel_solve(this, mesh, cube, pot, rho, mesh_cube_map)
subroutine, public poisson_psolver_end(this)
subroutine, public poisson_psolver_reinit(this, space, cube, coulb, qq_in)
subroutine, public poisson_psolver_get_dims(this, cube)
subroutine, public poisson_psolver_init(this, namespace, space, cube, mu, qq, force_isolated)
subroutine, public profiling_out(label)
Increment out counter and sum up difference between entry and exit time.
subroutine, public profiling_in(label, exclude)
Increment in counter and save entry time.
Describes mesh distribution to nodes.
A submesh is a type of mesh, used for the projectors in the pseudopotentials It contains points on a ...