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
45#ifdef HAVE_PSOLVER_NEW_API
63 type(fourier_space_op_t) :: coulb
65 type(coulomb_operator) :: kernel
66 type(dictionary),
pointer :: inputs
80 character(len = 1) :: geocode =
"F"
90 character(len = 1),
public :: datacode =
"G"
93 integer :: localnscatterarr(5)
94 real(real64) :: offset
98 logical,
save :: flib_initialized = .false.
101 real(real64),
parameter :: TOL_VANISHING_Q = 1e-6_real64
107 type(poisson_psolver_t),
intent(out) :: this
108 type(namespace_t),
intent(in) :: namespace
109 class(space_t),
intent(in) :: space
110 type(cube_t),
intent(inout) :: cube
111 real(real64),
intent(in) :: mu
112 real(real64),
intent(in) :: qq(:)
113 logical,
optional,
intent(in) :: force_isolated
115 logical data_is_parallel
117 real(real64) :: alpha, beta, gamma
118 real(real64) :: modq2
119 type(mpi_environment) mpi_env
120#ifdef HAVE_PSOLVER_NEW_API
128 if (.not. flib_initialized)
then
129 call f_lib_initialize()
130 flib_initialized = .
true.
132 call dict_init(this%inputs)
138 select case (space%periodic_dim)
153 call messages_experimental(
"PSolver support for 3D periodic boundary conditions", namespace=namespace)
159 call dict_set(this%inputs//
'setup'//
'verbose', .false.)
161 call dict_set(this%inputs//
'kernel'//
'isf_order', 16)
163 call dict_set(this%inputs//
'kernel'//
'screening', mu)
165 call dict_set(this%inputs//
'kernel'//
'stress_tensor', .false.)
184 if (.not. cube%parallel_in_domains)
then
185 data_is_parallel = .false.
191 if (data_is_parallel)
then
192 call dict_set(this%inputs//
'setup'//
'global_data', .false.)
194 call dict_set(this%inputs//
'setup'//
'global_data', .
true.)
197 if (data_is_parallel)
then
205 call dict_set(this%inputs//
'setup'//
'verbose',
debug%info)
207 alpha = cube%latt%alpha*
m_pi/(180.0_real64)
208 beta = cube%latt%beta*
m_pi/(180.0_real64)
209 gamma = cube%latt%gamma*
m_pi/(180.0_real64)
218 call mpi_environment_set(mpi_env, cube%mpi_grp%rank, cube%mpi_grp%size, cube%mpi_grp%comm%MPI_VAL, cube%mpi_grp%size)
220#ifdef HAVE_PSOLVER_NEW_API
221 dom=domain_new(units=atomic_units, bc=geocode_to_bc_enum(this%geocode),&
222 alpha_bc=alpha, beta_ac=beta, gamma_ab=gamma, acell=cube%rs_n_global*cube%spacing)
225 this%kernel = pkernel_init(cube%mpi_grp%rank, cube%mpi_grp%size, this%inputs, dom, cube%rs_n_global, &
226 cube%spacing, alpha_bc = alpha, beta_ac = beta, gamma_ab = gamma, mpi_env = mpi_env)
228 this%kernel = pkernel_init(cube%mpi_grp%rank, cube%mpi_grp%size, this%inputs, this%geocode, cube%rs_n_global, &
229 cube%spacing, alpha_bc = alpha, beta_ac = beta, gamma_ab = gamma, mpi_env = mpi_env)
232 call pkernel_set(this%kernel, verbose=
debug%info)
235 modq2 = sum(qq(1:space%periodic_dim)**2)
237 this%offset =
m_one/modq2
245 this%offset = this%offset*(
m_one -
exp(-modq2/((
m_two*mu)**2)))
264 call pkernel_free(this%kernel)
265 call f_lib_finalize()
266 call dict_free(this%inputs)
275 class(
space_t),
intent(in) :: space
276 type(
cube_t),
intent(inout) :: cube
278 real(real64),
intent(in) :: qq_in(:)
280 real(real64) :: alpha, beta, gamma
281 real(real64) :: qq_abs(1:space%dim), qq(1:space%dim)
282 real(real64) :: modq2
284#ifdef HAVE_PSOLVER_NEW_API
296 call pkernel_free(this%kernel)
300 alpha = cube%latt%alpha*
m_pi/(180.0_real64)
301 beta = cube%latt%beta*
m_pi/(180.0_real64)
302 gamma = cube%latt%gamma*
m_pi/(180.0_real64)
305 call dict_set(this%inputs//
'kernel'//
'screening', coulb%mu)
306#ifdef HAVE_PSOLVER_NEW_API
307 dom=domain_new(units=atomic_units, bc=geocode_to_bc_enum(this%geocode),&
308 alpha_bc=alpha, beta_ac=beta, gamma_ab=gamma, acell=cube%rs_n_global*cube%spacing)
310 this%kernel = pkernel_init(cube%mpi_grp%rank, cube%mpi_grp%size, this%inputs,&
311 dom,cube%rs_n_global, cube%spacing, &
312 alpha_bc = alpha, beta_ac = beta, gamma_ab = gamma)
314 this%kernel = pkernel_init(cube%mpi_grp%rank, cube%mpi_grp%size, this%inputs,&
315 this%geocode, cube%rs_n_global, cube%spacing, &
316 alpha_bc = alpha, beta_ac = beta, gamma_ab = gamma)
318 call pkernel_set(this%kernel, verbose=
debug%info)
323 do idim = 1, space%periodic_dim
324 qq(idim) = qq_in(idim) - anint(qq_in(idim) +
m_half*1e-8_real64)
326 qq(space%periodic_dim + 1:space%dim) =
m_zero
328 modq2 = norm2(qq_abs)
329 if (modq2 > tol_vanishing_q)
then
332 this%offset = coulb%singularity
337 if (modq2 > tol_vanishing_q)
then
338 this%offset = this%offset*(
m_one -
exp(-modq2/((
m_two*coulb%mu)**2)))
351 type(
mesh_t),
intent(in) :: mesh
352 type(
cube_t),
intent(in) :: cube
353 real(real64),
intent(out) :: pot(:)
354 real(real64),
intent(in) :: rho(:)
360 type(coulomb_operator),
pointer :: kernel_pointer
361 real(real64) :: hartree_energy
362 real(real64) :: offset
369 real(real64),
allocatable :: pot_ion(:,:,:)
370 character(len=3) :: quiet
376 safe_allocate(pot_ion(1:cube%rs_n(1),1:cube%rs_n(2),1:cube%rs_n(3)))
379 if (
debug%info) quiet =
"NO"
393 kernel_pointer => this%kernel
394 call h_potential(this%datacode, kernel_pointer, cf%dRS, pot_ion, hartree_energy, offset, .false., quiet = quiet)
397 safe_deallocate_a(pot_ion)
409 type(
mesh_t),
intent(in) :: mesh
410 type(
cube_t),
intent(in) :: cube
411 real(real64),
contiguous,
intent(out) :: pot(:)
412 real(real64),
contiguous,
intent(in) :: rho(:)
413 type(
submesh_t),
optional,
intent(in) :: sm
415 character(len=3) :: quiet
419 type(coulomb_operator),
pointer :: kernel_pointer
420 real(real64) :: hartree_energy
421 real(real64) :: offset
429 real(real64),
allocatable :: pot_ion(:,:,:)
435 if (
present(sm))
then
441 safe_allocate(pot_ion(1:cube%rs_n(1), 1:cube%rs_n(2), 1:cube%rs_n(3)))
444 if (
debug%info) quiet =
"NO"
459 kernel_pointer => this%kernel
460 call h_potential(this%datacode, kernel_pointer, &
461 cf%dRS, pot_ion, hartree_energy, offset, .false., &
464 safe_deallocate_a(pot_ion)
466 if (
present(sm))
then
479 type(
cube_t),
intent(inout) :: cube
513 logical :: use_gradient
515 logical :: use_wb_corr
522 use_gradient = .false.
523 use_wb_corr = .false.
524 call ps_dim4allocation(this%geocode, this%datacode, cube%mpi_grp%rank, cube%mpi_grp%size, &
525 cube%rs_n_global(1), cube%rs_n_global(2), cube%rs_n_global(3), &
526 use_gradient, use_wb_corr, &
527 0, n3d, n3p, n3pi, i3xcsh, i3s)
528 this%localnscatterarr(:) = (/ n3d, n3p, n3pi, i3xcsh, i3s /)
530 cube%rs_n(1:2) = cube%rs_n_global(1:2)
531 cube%rs_n(3) = this%localnscatterarr(1)
532 cube%rs_istart(1:2) = 1
533 cube%rs_istart(3) = this%localnscatterarr(5)
537 cube%fs_n_global(1) = cube%rs_n_global(1)
538 cube%fs_n_global(2) = cube%rs_n_global(2)
539 cube%fs_n_global(3) = cube%rs_n_global(3)
540 cube%fs_n(1:2) = cube%rs_n_global(1:2)
541 cube%fs_n(3) = this%localnscatterarr(1)
542 cube%fs_istart(1:2) = 1
543 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 ...