27 use,
intrinsic :: iso_fortran_env
42 use dictionaries, dict_set => set
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.)
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*(-
expm1(-modq2/((
m_two*mu)**2)))
255 call pkernel_free(this%kernel)
256 call f_lib_finalize()
257 call dict_free(this%inputs)
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*(-
expm1(-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)
subroutine, public dmesh_to_cube(mesh, mf, cube, cf)
Convert a function from the mesh to the cube.
subroutine, public dcube_to_submesh(cube, cf, sm, mf)
subroutine, public dcube_to_mesh(cube, cf, mesh, mf)
Convert a function from the cube to the mesh.
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 is intended to contain "only mathematical" functions and procedures.
This module defines various routines, operating on mesh functions.
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 ...