56 subroutine poisson_test(this, space, mesh, latt, namespace, repetitions)
57 type(poisson_t),
intent(in) :: this
58 class(space_t),
intent(in) :: space
59 class(mesh_t),
intent(in) :: mesh
60 type(lattice_vectors_t),
intent(in) :: latt
61 type(namespace_t),
intent(in) :: namespace
62 integer,
intent(in) :: repetitions
64 real(real64),
allocatable :: rho(:), vh(:), vh_exact(:), xx(:, :), xx_per(:)
65 real(real64) :: alpha, beta, rr, delta, ralpha, hartree_nrg_num, &
66 hartree_nrg_analyt, lcl_hartree_nrg
67 real(real64) :: total_charge
68 integer :: ip, ierr, iunit, nn, n_gaussians, itime, icell
69 real(real64) :: threshold
70 type(lattice_iterator_t) :: latt_iter
74 if (mesh%box%dim == 1)
then
90 call parse_variable(namespace,
'PoissonTestPeriodicThreshold', 1e-5_real64, threshold)
95 safe_allocate( rho(1:mesh%np))
96 safe_allocate( vh(1:mesh%np))
97 safe_allocate(vh_exact(1:mesh%np))
98 safe_allocate(xx(1:space%dim, 1:n_gaussians))
99 safe_allocate(xx_per(1:space%dim))
105 alpha =
m_four*mesh%spacing(1)
106 write(
message(1),
'(a,f14.6)')
"Info: The alpha value is ", alpha
107 write(
message(2),
'(a)')
" Higher values of alpha lead to more physical densities and more reliable results."
111 write(
message(1),
'(a)')
'Building the Gaussian distribution of charge...'
117 if (space%dim == 3) xx(3, 1) =
m_two
120 if (space%dim == 3) xx(3, 2) = -
m_one
125 do nn = 1, n_gaussians
127 call mesh_r(mesh, ip, rr, origin = xx(:, nn))
128 rho(ip) = rho(ip) + (-1)**nn * beta*
exp(-(rr/alpha)**2)
134 write(
message(1),
'(a,e23.16)')
'Total charge of the Gaussian distribution', total_charge
137 write(
message(1),
'(a)')
'Computing exact potential.'
143 do nn = 1, n_gaussians
145 write(
message(1),
'(a,i2,a,i9,a)')
'Computing Gaussian ', nn,
' for ', latt_iter%n_cells,
' periodic copies.'
148 do icell = 1, latt_iter%n_cells
149 xx_per = xx(:, nn) + latt_iter%get(icell)
152 call mesh_r(mesh, ip, rr, origin=xx_per)
153 select case (space%dim)
156 vh_exact(ip) = vh_exact(ip) + (-1)**nn *
loct_erf(rr/alpha)/rr
158 vh_exact(ip) = vh_exact(ip) + (-1)**nn * (
m_two/
sqrt(
m_pi))/alpha
161 ralpha = rr**2/(
m_two*alpha**2)
162 if (ralpha < 100.0_real64)
then
166 vh_exact(ip) = vh_exact(ip) + (-1)**nn * beta * (
m_pi)**(
m_three*
m_half) * alpha * &
175 do itime = 1, repetitions
180 iunit =
io_open(
"hartree_results", namespace, action=
'write')
182 write(iunit,
'(a,e23.16)')
'Hartree test (abs.) = ', delta
183 delta = delta/
dmf_nrm2(mesh, vh_exact)
184 write(iunit,
'(a,e23.16)')
'Hartree test (rel.) = ', delta
189 lcl_hartree_nrg = lcl_hartree_nrg + rho(ip) * vh(ip)
191 lcl_hartree_nrg = lcl_hartree_nrg * mesh%spacing(1) * mesh%spacing(2) * mesh%spacing(3)/
m_two
193 call mpi_reduce(lcl_hartree_nrg, hartree_nrg_num, 1, &
194 mpi_double_precision, mpi_sum, 0, mpi_comm_world,
mpi_err)
196 write(
message(1),
'(a)')
"MPI error in MPI_Reduce; subroutine poisson_test of file poisson.F90"
200 hartree_nrg_num = lcl_hartree_nrg
206 lcl_hartree_nrg = lcl_hartree_nrg + rho(ip) * vh_exact(ip)
208 lcl_hartree_nrg = lcl_hartree_nrg * mesh%spacing(1) * mesh%spacing(2) * mesh%spacing(3) /
m_two
210 call mpi_reduce(lcl_hartree_nrg, hartree_nrg_analyt, 1, &
211 mpi_double_precision, mpi_sum, 0, mpi_comm_world,
mpi_err)
213 write(
message(1),
'(a)')
"MPI error in MPI_Reduce; subroutine poisson_test of file poisson.F90"
217 hartree_nrg_analyt = lcl_hartree_nrg
223 write(iunit,
'(a,e23.16)')
'Hartree Energy (numerical) =', hartree_nrg_num,
'Hartree Energy (analytical) =',hartree_nrg_analyt
242 safe_deallocate_a(rho)
243 safe_deallocate_a(vh)
244 safe_deallocate_a(vh_exact)
245 safe_deallocate_a(xx)
double exp(double __x) __attribute__((__nothrow__
real(real64), parameter, public m_two
real(real64), parameter, public r_small
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_half
real(real64), parameter, public m_one
real(real64), parameter, public m_three
subroutine, public dio_function_output(how, dir, fname, namespace, space, mesh, ff, unit, ierr, pos, atoms, grp, root)
Top-level IO routine for functions defined on the mesh.
integer(int64) function, public io_function_fill_how(where)
Use this function to quickly plot functions for debugging purposes: call dio_function_output(io_funct...
subroutine, public io_close(iunit, grp)
integer function, public io_open(file, namespace, action, status, form, position, die, recl, grp)
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.
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_warning(no_lines, all_nodes, namespace)
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)
type(mpi_grp_t), public mpi_world
integer, public mpi_err
used to store return values of mpi calls
subroutine, public dpoisson_solve(this, namespace, pot, rho, all_nodes, kernel, reset)
Calculates the Poisson equation. Given the density returns the corresponding potential.
subroutine, public poisson_test(this, space, mesh, latt, namespace, repetitions)
This routine checks the Hartree solver selected in the input file by calculating numerically and anal...
brief This module defines the class unit_t which is used by the unit_systems_oct_m module.
This module defines the unit system, used for input and output.
type(unit_t), public unit_one
some special units required for particular quantities
The following class implements a lattice iterator. It allows one to loop over all cells that are with...