28 use,
intrinsic :: iso_fortran_env
67 type(mesh_t),
pointer :: mesh_p
68 real(real64),
allocatable :: rho_p(:)
69 real(real64),
allocatable :: grho_p(:, :)
70 real(real64) :: alpha2_p
71 real(real64),
pointer :: pos_p(:)
78 class(species_t),
target,
intent(in) :: species
79 type(namespace_t),
intent(in) :: namespace
80 class(space_t),
intent(in) :: space
81 type(lattice_vectors_t),
intent(in) :: latt
82 real(real64),
intent(in) :: pos(1:space%dim)
83 type(mesh_t),
intent(in) :: mesh
84 integer,
intent(in) :: spin_channels
85 real(real64),
intent(inout) :: rho(:, :)
87 integer :: isp, ip, in_points, icell
88 real(real64) :: rr, x, pos_pc(space%dim), nrm, rmax
89 real(real64) :: xx(space%dim), yy(space%dim), rerho, imrho
90 real(real64),
allocatable :: dorbital(:)
91 type(ps_t),
pointer :: ps
92 type(volume_t) :: volume
93 integer :: in_points_red
94 type(lattice_iterator_t) :: latt_iter
95 integer :: iorb, ii, nn, ll, mm
96 real(real64) :: radius, density
97 type(submesh_t) :: sphere
101 assert(spin_channels == 1 .or. spin_channels == 2)
106 select type (species)
118 do isp = 1, spin_channels
119 do iorb = 1, species%get_niwfs()
120 call species%get_iwf_ilm(iorb, isp, ii, ll, mm)
122 call species%get_iwf_n(iorb, isp, nn)
124 radius = species%get_iwf_radius(nn, isp)
126 radius = max(radius,
m_two*maxval(mesh%spacing))
128 call submesh_init(sphere, space, mesh, latt, pos, radius)
129 safe_allocate(dorbital(1:sphere%np))
136 dorbital(ip) = species%conf%occ(ii, isp)/real(2*ll+1, real64) *dorbital(ip)*dorbital(ip)
139 safe_deallocate_a(dorbital)
153 rmax = latt%max_length()
156 do icell = 1, latt_iter%n_cells
157 yy = latt_iter%get(icell)
159 call mesh_r(mesh, ip, rr, origin = pos, coords = xx)
165 rho(ip, 1) = rho(ip, 1) + rerho
171 if (spin_channels > 1)
then
172 rho(:, 1) =
m_half*rho(:, 1)
173 rho(:, 2) = rho(:, 1)
177 do isp = 1, spin_channels
179 rho(1:mesh%np, isp) = x * rho(1:mesh%np, isp)
187 rmax = latt%max_length()
190 do icell = 1, latt_iter%n_cells
191 yy = latt_iter%get(icell)
193 call mesh_r(mesh, ip, rr, origin = pos, coords = xx)
199 rho(ip, 1) = rho(ip, 1) + rerho
203 if (spin_channels > 1)
then
204 rho(:, 1) =
m_half*rho(:, 1)
205 rho(:, 2) = rho(:, 1)
209 do isp = 1, spin_channels
211 rho(1:mesh%np, isp) = x * rho(1:mesh%np, isp)
218 call mesh_r(mesh, ip, rr, origin = pos)
219 if (rr <= species%radius())
then
220 in_points = in_points + 1
224 if (mesh%parallel_in_domains)
then
225 call mesh%mpi_grp%allreduce(in_points, in_points_red, 1, mpi_integer, mpi_sum)
226 in_points = in_points_red
229 if (in_points > 0)
then
232 if (mesh%use_curvilinear)
then
234 call mesh_r(mesh, ip, rr, origin = pos)
235 if (rr <= species%radius())
then
236 rho(ip, 1:spin_channels) = species%get_zval() / &
237 (mesh%vol_pp(ip) * real(in_points*spin_channels, real64) )
242 call mesh_r(mesh, ip, rr, origin = pos)
243 if (rr <= species%radius())
then
244 rho(ip, 1:spin_channels) = species%get_zval() / &
245 (mesh%vol_pp(1) * real(in_points * spin_channels, real64) )
252 density = species%get_density(mesh%box%bounding_box_l) / spin_channels
255 rr = abs(mesh%x(ip, 3) - pos(3))
256 if (rr <= species%thickness() /
m_two)
then
257 rho(ip, 1:spin_channels) = density
268 assert(
allocated(ps%density))
271 do isp = 1, spin_channels
272 rmax = max(rmax, ps%density(isp)%x_threshold)
276 do icell = 1, latt_iter%n_cells
277 pos_pc = pos + latt_iter%get(icell)
279 call mesh_r(mesh, ip, rr, origin = pos_pc)
282 do isp = 1, spin_channels
284 rho(ip, isp) = rho(ip, isp) +
spline_eval(ps%density(isp), rr)
295 do icell = 1, latt_iter%n_cells
296 pos_pc = pos + latt_iter%get(icell)
298 call mesh_r(mesh, ip, rr, origin = pos_pc)
303 do isp = 1, spin_channels
312 do isp = 1, spin_channels
316 rho(1:mesh%np, 1:spin_channels) = rho(1:mesh%np, 1:spin_channels)*species%get_zval()/nrm
326 do isp = 1, spin_channels
327 rho(1:mesh%np, isp) =
m_one
328 x = (species%get_zval()/real(spin_channels, real64) ) /
dmf_integrate(mesh, rho(:, isp))
329 rho(1:mesh%np, isp) = x * rho(1:mesh%np, isp)
339 class(
species_t),
target,
intent(in) :: species
341 real(real64),
intent(in) :: pos(:)
342 type(
mesh_t),
intent(in) :: mesh
343 integer,
intent(in) :: spin_channels
344 real(real64),
intent(inout) :: rho(:, :)
347 real(real64) :: rr, nrm
348 type(
ps_t),
pointer :: ps
362 assert(
allocated(ps%density))
365 do isp = 1, spin_channels
368 call mesh_r(mesh, ip, rr, origin = pos)
371 rho(ip, isp) = rho(ip, isp) +
spline_eval(ps%density(isp), rr)
382 call mesh_r(mesh, ip, rr, origin = pos)
387 do isp = 1, spin_channels
395 do isp = 1, spin_channels
399 rho(1:mesh%np, 1:spin_channels) = rho(1:mesh%np, 1:spin_channels)*species%get_zval()/nrm
416 class(
species_t),
target,
intent(in) :: species
420 real(real64),
intent(in) :: pos(1:space%dim)
421 type(
mesh_t),
intent(in) :: mesh
422 integer,
intent(in) :: spin_channels
423 real(real64),
intent(inout) :: drho(:, :)
426 real(real64) :: pos_pc(space%dim), range
427 type(
ps_t),
pointer :: ps
432 assert(spin_channels == 1 .or. spin_channels == 2)
444 range = ps%density_der(1)%x_threshold
445 if (spin_channels == 2) range = max(range, ps%density_der(2)%x_threshold)
448 do icell = 1, latt_iter%n_cells
449 pos_pc = pos + latt_iter%get(icell)
455 call messages_not_implemented(
'species_atom_density_derivative for non-pseudopotential species', namespace=namespace)
465 class(
species_t),
target,
intent(in) :: species
467 real(real64),
intent(in) :: pos(:)
468 type(
mesh_t),
intent(in) :: mesh
469 integer,
intent(in) :: spin_channels
470 real(real64),
intent(inout) :: drho(:, :)
474 type(
ps_t),
pointer :: ps
486 do isp = 1, spin_channels
489 call mesh_r(mesh, ip, rr, origin = pos)
492 drho(ip, isp) = drho(ip, isp) +
spline_eval(ps%density_der(isp), rr)
517 class(
species_t),
target,
intent(in) :: species
519 class(
space_t),
intent(in) :: space
521 real(real64),
intent(in) :: pos(1:space%dim)
522 type(
mesh_t),
intent(in) :: mesh
523 integer,
intent(in) :: spin_channels
524 real(real64),
intent(inout) :: drho(:, :, :)
526 integer :: isp, ip, icell, idir
527 real(real64) :: rr, pos_pc(space%dim), range, spline
528 type(
ps_t),
pointer :: ps
533 assert(spin_channels == 1 .or. spin_channels == 2)
545 range = ps%density_der(1)%x_threshold
546 if (spin_channels == 2) range = max(range, ps%density_der(2)%x_threshold)
549 do icell = 1, latt_iter%n_cells
550 pos_pc = pos + latt_iter%get(icell)
553 call mesh_r(mesh, ip, rr, origin = pos_pc)
556 do isp = 1, spin_channels
560 if(abs(spline) < 1e-150_real64) cycle
562 do idir = 1, space%dim
563 drho(ip, isp, idir) = drho(ip, isp, idir) - spline*(mesh%x(ip, idir) - pos_pc(idir))/rr
587 class(
species_t),
target,
intent(in) :: species
589 class(
space_t),
intent(in) :: space
591 real(real64),
target,
intent(in) :: pos(1:space%dim)
592 class(
mesh_t),
target,
intent(in) :: mesh
593 real(real64),
intent(out) :: rho(:)
594 type(
submesh_t),
optional,
target,
intent(inout) :: sphere_inout
595 real(real64),
optional,
intent(inout) :: nlr_x(:,:)
599 real(real64) :: startval(space%dim)
600 real(real64) :: delta, alpha, xx(space%dim), yy(space%dim), rr, imrho1, rerho
601 real(real64) :: dist2_min
602 integer :: icell, ipos, ip, idir, rankmin
604 type(
ps_t),
pointer :: ps
608 logical :: have_point
609 real(real64),
allocatable :: rho_sphere(:)
610 real(real64),
parameter :: threshold = 1e-6_real64
611 real(real64) :: norm_factor, range, radius, radius_nlr, radius_vl
617 if(
present(nlr_x))
then
618 assert(species%is_ps())
621 select type (species)
625 if (
present(sphere_inout))
then
626 radius_vl = ps%vl%x_threshold*1.05_real64
627 radius = max(radius_nlr, radius_vl)
628 call submesh_init(sphere_inout, space, mesh, latt, pos, radius)
629 sphere => sphere_inout
632 call submesh_init(sphere_local, space, mesh, latt, pos, radius)
633 sphere => sphere_local
636 safe_allocate(rho_sphere(1:sphere%np))
637 if (.not.
present(sphere_inout) .and. sphere%np > 0)
then
639 rho_sphere(ip) = sphere%r(ip)
644 if(sphere%r(ip) <= radius_nlr)
then
656 norm_factor = abs(species%get_zval()/
dsm_integrate(mesh, sphere, rho_sphere))
658 rho(sphere%map(ip)) = rho(sphere%map(ip)) + norm_factor*rho_sphere(ip)
661 if (
present(nlr_x))
then
662 do idir = 1, space%dim
664 nlr_x(sphere%map(ip), idir) = nlr_x(sphere%map(ip), idir) + norm_factor*rho_sphere(ip)*sphere%rel_x(idir, ip)
669 safe_deallocate_a(rho_sphere)
671 if ( .not.
present(sphere_inout) )
then
682 if (mesh%mpi_grp%rank /= rankmin) have_point = .false.
685 if (mesh%use_curvilinear)
then
686 rho(ipos) = -species%get_z()/mesh%vol_pp(ipos)
688 rho(ipos) = -species%get_z()/mesh%vol_pp(1)
692 write(
message(1),
'(3a,f5.2,3a)') &
693 "Info: species_full_delta species ", trim(species%get_label()), &
701 if (space%is_periodic())
then
707 if (mesh%use_curvilinear)
then
717 safe_allocate(rho_p(1:mesh%np))
718 safe_allocate(grho_p(1:mesh%np, 1:space%dim))
724 delta = mesh%spacing(1)
725 alpha =
sqrt(
m_two)*species%get_sigma()*delta
729 startval(1:space%dim) = pos
737 write(
message(1),
'(a)')
'Root finding in species_get_density did not converge.'
741 if(
debug%info .and. space%dim == 3)
then
742 write(
message(1),
'(a,3(f6.3,a))')
'Debug: Gaussian charge position (', xx(1),
', ', xx(2),
', ', xx(3),
')'
747 rho = -species%get_z()*rho_p
751 safe_deallocate_a(grho_p)
752 safe_deallocate_a(rho_p)
763 range = latt%max_length()
767 do icell = 1, latt_iter%n_cells
768 yy = latt_iter%get(icell)
770 call mesh_r(mesh, ip, rr, origin = pos, coords = xx)
776 rho(ip) = rho(ip) - rerho
784 range = latt%max_length()
788 do icell = 1, latt_iter%n_cells
789 yy = latt_iter%get(icell)
791 call mesh_r(mesh, ip, rr, origin = pos, coords = xx)
797 rho(ip) = rho(ip) - rerho
802 rho(1:mesh%np) = rr * rho(1:mesh%np)
814 subroutine func(xin, ff, jacobian)
815 real(real64),
intent(in) :: xin(:)
816 real(real64),
intent(out) :: ff(:), jacobian(:,:)
818 real(real64),
allocatable :: xrho(:)
819 integer :: idir, jdir, dim, ip
826 safe_allocate(xrho(1:mesh_p%np))
832 xrho(ip) = rho_p(ip) * mesh_p%x(ip, idir)
842 xrho(ip) = grho_p(ip, jdir) * mesh_p%x(ip, idir)
848 safe_deallocate_a(xrho)
853 subroutine species_get_nlcc(species, space, latt, pos, mesh, rho_core, accumulate)
854 class(
species_t),
target,
intent(in) :: species
855 class(
space_t),
intent(in) :: space
857 real(real64),
intent(in) :: pos(1:space%dim)
858 type(
mesh_t),
intent(in) :: mesh
859 real(real64),
intent(inout) :: rho_core(:)
860 logical,
optional,
intent(in) :: accumulate
862 real(real64) :: center(space%dim), rr
865 type(
ps_t),
pointer :: ps
876 do icell = 1, latt_iter%n_cells
877 center = pos + latt_iter%get(icell)
879 rr = norm2(mesh%x(ip, 1:space%dim) - center)
881 rho_core(ip) = rho_core(ip) +
spline_eval(ps%core, rr)
894 class(
species_t),
target,
intent(in) :: species
895 class(
space_t),
intent(in) :: space
897 real(real64),
intent(in) :: pos(1:space%dim)
898 class(
mesh_t),
intent(in) :: mesh
899 real(real64),
intent(out) :: rho_core_grad(:,:)
900 real(real64),
optional,
intent(inout) :: gnlcc_x(:,:,:)
902 real(real64) :: center(space%dim), rr, spline
903 integer :: icell, ip, idir, jdir
905 type(
ps_t),
pointer :: ps
912 if (.not. species%is_ps())
then
927 do icell = 1, latt_iter%n_cells
928 center = pos + latt_iter%get(icell)
930 call mesh_r(mesh, ip, rr, origin = center)
934 if(abs(spline) < 1e-150_real64) cycle
936 do idir = 1, space%dim
937 rho_core_grad(ip, idir) = rho_core_grad(ip, idir) - spline*(mesh%x(ip, idir)-center(idir))/rr
938 if (
present(gnlcc_x))
then
939 do jdir = 1, space%dim
940 gnlcc_x(ip, idir, jdir) = gnlcc_x(ip, idir, jdir) &
941 - spline*(mesh%x(ip, idir)-center(idir))/rr*(mesh%x(ip, jdir)-center(jdir))
958 subroutine getrho(dim, xin)
959 integer,
intent(in) :: dim
960 real(real64),
intent(in) :: xin(1:dim)
963 real(real64) :: r2, chi(dim), norm, threshold
969 threshold = -
log(0.001_real64)*alpha2_p
973 chi(1:dim) = mesh_p%x(ip,1:dim)
974 r2 = sum((chi - xin(1:dim))**2)
976 if (r2 < threshold)
then
977 rho_p(ip) =
exp(-r2/alpha2_p)
983 grho_p(ip, idir) = (chi(idir) - xin(idir)) * rho_p(ip)
998 class(
species_t),
target,
intent(in) :: species
1000 class(
space_t),
intent(in) :: space
1002 real(real64),
intent(in) :: pos(1:space%dim)
1003 type(
mesh_t),
intent(in) :: mesh
1004 real(real64),
intent(out) :: vl(:)
1006 real(real64) :: a1, a2, rb2, range, density
1007 real(real64) :: xx(space%dim), pos_pc(space%dim), r, r2, threshold
1008 integer :: ip, err, icell
1009 type(
ps_t),
pointer :: ps
1010 complex(real64) :: zpot
1012 real(real64) :: aa, bb
1019 select type(species)
1023 call parse_variable(namespace,
'SpeciesProjectorSphereThreshold', 0.001_real64, threshold)
1029 do icell = 1, latt_iter%n_cells
1030 pos_pc = pos + latt_iter%get(icell)
1032 call mesh_r(mesh, ip, r, origin = pos_pc)
1034 vl(ip) = vl(ip) -species%get_zval()/
sqrt(r2+species%get_softening())
1040 range = 5.0_real64 * latt%max_length()
1043 do icell = 1, latt_iter%n_cells
1044 pos_pc = pos + latt_iter%get(icell)
1046 call mesh_r(mesh, ip, r, origin = pos_pc, coords = xx)
1048 zpot = species%user_pot(space%dim, xx, r)
1049 vl(ip) = vl(ip) + real(zpot, real64)
1055 assert(.not. space%is_periodic())
1057 call dio_function_input(trim(species%get_filename()), namespace, space, mesh, vl, err)
1059 write(
message(1),
'(a)')
'Error loading file '//trim(species%get_filename())//
'.'
1060 write(
message(2),
'(a,i4)')
'Error code returned = ', err
1066 assert(.not. space%is_periodic())
1068 a1 = species%get_z()/(
m_two*species%radius()**3)
1069 a2 = species%get_z()/species%radius()
1070 rb2= species%radius()**2
1074 xx = mesh%x(ip, :) - pos(1:space%dim)
1077 if (r <= species%radius())
then
1078 vl(ip) = (a1*(r*r - rb2) - a2)
1080 vl(ip) = -species%get_z()/r
1089 density = species%get_density(mesh%box%bounding_box_l)
1094 r = abs(mesh%x(ip, 3) - pos(3))
1096 if (r <= species%thickness()/
m_two)
then
1097 vl(ip) = a1 * (r * r / species%thickness() + species%thickness() /
m_four)
1106 assert(.not. space%is_periodic())
1111 r2 = sum((mesh%x(ip, :) - pos)**2)
1123 if (space%is_periodic())
then
1133 r2 = sum((mesh%x(ip, :) - pos)**2)*(species%get_z()*aa)**2
1144 vl(ip) = vl(ip) * (species%get_z())**2
scales a vector by a constant
Both the filling of the function, and the retrieval of the values may be done using single- or double...
double log(double __x) __attribute__((__nothrow__
double exp(double __x) __attribute__((__nothrow__
subroutine, public datomic_orbital_get_submesh(species, submesh, ii, ll, mm, ispin, phi, derivative)
type(debug_t), save, public debug
real(real64), parameter, public m_two
real(real64), parameter, public p_proton_charge
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
This module implements the index, used for the mesh points.
subroutine, public dio_function_input(filename, namespace, space, mesh, ff, ierr, map)
Reads a mesh function from file filename, and puts it into ff. If the map argument is passed,...
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.
integer function, public mesh_nearest_point(mesh, pos, dmin, rankmin)
Returns the index of the point which is nearest to a given vector position pos.
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_info(no_lines, iunit, verbose_limit, stress, all_nodes, namespace)
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
subroutine, public messages_fatal(no_lines, only_root_writes, namespace)
subroutine, public messages_experimental(name, namespace)
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.
pure logical function, public ps_has_density(ps)
pure logical function, public ps_has_nlcc(ps)
integer, parameter, public root_newton
subroutine, public root_solver_init(rs, namespace, dimensionality, solver_type, maxiter, rel_tolerance, abs_tolerance)
subroutine, public droot_solver_run(rs, func, root, success, startval)
subroutine, public species_get_local(species, namespace, space, latt, pos, mesh, vl)
used when the density is not available, or otherwise the Poisson eqn would be used instead
subroutine func(xin, ff, jacobian)
subroutine, public species_atom_density_np(species, namespace, pos, mesh, spin_channels, rho)
subroutine, public species_get_long_range_density(species, namespace, space, latt, pos, mesh, rho, sphere_inout, nlr_x)
subroutine, public species_atom_density_derivative_np(species, namespace, pos, mesh, spin_channels, drho)
subroutine, public species_get_nlcc_grad(species, space, latt, pos, mesh, rho_core_grad, gnlcc_x)
subroutine, public species_atom_density_grad(species, namespace, space, latt, pos, mesh, spin_channels, drho)
subroutine getrho(dim, xin)
subroutine, public species_get_nlcc(species, space, latt, pos, mesh, rho_core, accumulate)
subroutine, public species_atom_density(species, namespace, space, latt, pos, mesh, spin_channels, rho)
subroutine, public species_atom_density_derivative(species, namespace, space, latt, pos, mesh, spin_channels, drho)
real(real64) function, public spline_x_threshold(spl, threshold)
Determines the largest value of x for which the spline values are above the threshold.
real(real64) function, public spline_eval(spl, x)
real(real64) pure function, public spline_range_max(this)
real(real64) function, public dsm_integrate(mesh, sm, ff, reduce)
subroutine, public submesh_end(this)
subroutine, public submesh_init(this, space, mesh, latt, center, rc)
brief This module defines the class unit_t which is used by the unit_systems_oct_m module.
character(len=20) pure function, public units_abbrev(this)
This module defines the unit system, used for input and output.
type(unit_system_t), public units_out
subroutine, public volume_read_from_block(vol, namespace, block_name)
logical function, public volume_in_volume(space, vol, xx)
subroutine, public volume_end(vol)
subroutine, public volume_init(vol)
subroutine generate_uniform_density()
An abstract type for all electron species.
The following class implements a lattice iterator. It allows one to loop over all cells that are with...
Describes mesh distribution to nodes.
An abstract class for species. Derived classes include jellium, all electron, and pseudopotential spe...
A submesh is a type of mesh, used for the projectors in the pseudopotentials It contains points on a ...