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
638 call lalg_copy(sphere%np, sphere%r, rho_sphere)
642 if(sphere%r(ip) <= radius_nlr)
then
654 norm_factor = abs(species%get_zval()/
dsm_integrate(mesh, sphere, rho_sphere))
656 rho(sphere%map(ip)) = rho(sphere%map(ip)) + norm_factor*rho_sphere(ip)
659 if (
present(nlr_x))
then
660 do idir = 1, space%dim
662 nlr_x(sphere%map(ip), idir) = nlr_x(sphere%map(ip), idir) + norm_factor*rho_sphere(ip)*sphere%rel_x(idir, ip)
667 safe_deallocate_a(rho_sphere)
669 if ( .not.
present(sphere_inout) )
then
680 if (mesh%mpi_grp%rank /= rankmin) have_point = .false.
683 if (mesh%use_curvilinear)
then
684 rho(ipos) = -species%get_z()/mesh%vol_pp(ipos)
686 rho(ipos) = -species%get_z()/mesh%vol_pp(1)
690 write(
message(1),
'(3a,f5.2,3a)') &
691 "Info: species_full_delta species ", trim(species%get_label()), &
699 if (space%is_periodic())
then
705 if (mesh%use_curvilinear)
then
715 safe_allocate(rho_p(1:mesh%np))
716 safe_allocate(grho_p(1:mesh%np, 1:space%dim))
722 delta = mesh%spacing(1)
723 alpha =
sqrt(
m_two)*species%get_sigma()*delta
727 startval(1:space%dim) = pos
735 write(
message(1),
'(a)')
'Root finding in species_get_density did not converge.'
739 if(
debug%info .and. space%dim == 3)
then
740 write(
message(1),
'(a,3(f6.3,a))')
'Debug: Gaussian charge position (', xx(1),
', ', xx(2),
', ', xx(3),
')'
745 rho = -species%get_z()*rho_p
749 safe_deallocate_a(grho_p)
750 safe_deallocate_a(rho_p)
761 range = latt%max_length()
765 do icell = 1, latt_iter%n_cells
766 yy = latt_iter%get(icell)
768 call mesh_r(mesh, ip, rr, origin = pos, coords = xx)
774 rho(ip) = rho(ip) - rerho
782 range = latt%max_length()
786 do icell = 1, latt_iter%n_cells
787 yy = latt_iter%get(icell)
789 call mesh_r(mesh, ip, rr, origin = pos, coords = xx)
795 rho(ip) = rho(ip) - rerho
800 rho(1:mesh%np) = rr * rho(1:mesh%np)
812 subroutine func(xin, ff, jacobian)
813 real(real64),
intent(in) :: xin(:)
814 real(real64),
intent(out) :: ff(:), jacobian(:,:)
816 real(real64),
allocatable :: xrho(:)
817 integer :: idir, jdir, dim, ip
824 safe_allocate(xrho(1:mesh_p%np))
830 xrho(ip) = rho_p(ip) * mesh_p%x(ip, idir)
840 xrho(ip) = grho_p(ip, jdir) * mesh_p%x(ip, idir)
846 safe_deallocate_a(xrho)
851 subroutine species_get_nlcc(species, space, latt, pos, mesh, rho_core, accumulate)
852 class(
species_t),
target,
intent(in) :: species
853 class(
space_t),
intent(in) :: space
855 real(real64),
intent(in) :: pos(1:space%dim)
856 type(
mesh_t),
intent(in) :: mesh
857 real(real64),
intent(inout) :: rho_core(:)
858 logical,
optional,
intent(in) :: accumulate
860 real(real64) :: center(space%dim), rr
863 type(
ps_t),
pointer :: ps
874 do icell = 1, latt_iter%n_cells
875 center = pos + latt_iter%get(icell)
877 rr = norm2(mesh%x(ip, 1:space%dim) - center)
879 rho_core(ip) = rho_core(ip) +
spline_eval(ps%core, rr)
892 class(
species_t),
target,
intent(in) :: species
893 class(
space_t),
intent(in) :: space
895 real(real64),
intent(in) :: pos(1:space%dim)
896 class(
mesh_t),
intent(in) :: mesh
897 real(real64),
intent(out) :: rho_core_grad(:,:)
898 real(real64),
optional,
intent(inout) :: gnlcc_x(:,:,:)
900 real(real64) :: center(space%dim), rr, spline
901 integer :: icell, ip, idir, jdir
903 type(
ps_t),
pointer :: ps
910 if (.not. species%is_ps())
then
925 do icell = 1, latt_iter%n_cells
926 center = pos + latt_iter%get(icell)
928 call mesh_r(mesh, ip, rr, origin = center)
932 if(abs(spline) < 1e-150_real64) cycle
934 do idir = 1, space%dim
935 rho_core_grad(ip, idir) = rho_core_grad(ip, idir) - spline*(mesh%x(ip, idir)-center(idir))/rr
936 if (
present(gnlcc_x))
then
937 do jdir = 1, space%dim
938 gnlcc_x(ip, idir, jdir) = gnlcc_x(ip, idir, jdir) &
939 - spline*(mesh%x(ip, idir)-center(idir))/rr*(mesh%x(ip, jdir)-center(jdir))
956 subroutine getrho(dim, xin)
957 integer,
intent(in) :: dim
958 real(real64),
intent(in) :: xin(1:dim)
961 real(real64) :: r2, chi(dim), norm, threshold
967 threshold = -
log(0.001_real64)*alpha2_p
971 chi(1:dim) = mesh_p%x(ip,1:dim)
972 r2 = sum((chi - xin(1:dim))**2)
974 if (r2 < threshold)
then
975 rho_p(ip) =
exp(-r2/alpha2_p)
981 grho_p(ip, idir) = (chi(idir) - xin(idir)) * rho_p(ip)
996 class(
species_t),
target,
intent(in) :: species
998 class(
space_t),
intent(in) :: space
1000 real(real64),
intent(in) :: pos(1:space%dim)
1001 type(
mesh_t),
intent(in) :: mesh
1002 real(real64),
intent(out) :: vl(:)
1004 real(real64) :: a1, a2, rb2, range, density
1005 real(real64) :: xx(space%dim), pos_pc(space%dim), r, r2, threshold
1006 integer :: ip, err, icell
1007 type(
ps_t),
pointer :: ps
1008 complex(real64) :: zpot
1010 real(real64) :: aa, bb
1017 select type(species)
1021 call parse_variable(namespace,
'SpeciesProjectorSphereThreshold', 0.001_real64, threshold)
1027 do icell = 1, latt_iter%n_cells
1028 pos_pc = pos + latt_iter%get(icell)
1030 call mesh_r(mesh, ip, r, origin = pos_pc)
1032 vl(ip) = vl(ip) -species%get_zval()/
sqrt(r2+species%get_softening2())
1038 range = 5.0_real64 * latt%max_length()
1041 do icell = 1, latt_iter%n_cells
1042 pos_pc = pos + latt_iter%get(icell)
1044 call mesh_r(mesh, ip, r, origin = pos_pc, coords = xx)
1046 zpot = species%user_pot(space%dim, xx, r)
1047 vl(ip) = vl(ip) + real(zpot, real64)
1053 assert(.not. space%is_periodic())
1055 call dio_function_input(trim(species%get_filename()), namespace, space, mesh, vl, err)
1057 write(
message(1),
'(a)')
'Error loading file '//trim(species%get_filename())//
'.'
1058 write(
message(2),
'(a,i4)')
'Error code returned = ', err
1064 assert(.not. space%is_periodic())
1066 a1 = species%get_z()/(
m_two*species%radius()**3)
1067 a2 = species%get_z()/species%radius()
1068 rb2= species%radius()**2
1072 xx = mesh%x(ip, :) - pos(1:space%dim)
1075 if (r <= species%radius())
then
1076 vl(ip) = (a1*(r*r - rb2) - a2)
1078 vl(ip) = -species%get_z()/r
1087 density = species%get_density(mesh%box%bounding_box_l)
1092 r = abs(mesh%x(ip, 3) - pos(3))
1094 if (r <= species%thickness()/
m_two)
then
1095 vl(ip) = a1 * (r * r / species%thickness() + species%thickness() /
m_four)
1104 assert(.not. space%is_periodic())
1109 r2 = sum((mesh%x(ip, :) - pos)**2)
1121 if (space%is_periodic())
then
1131 r2 = sum((mesh%x(ip, :) - pos)**2)*(species%get_z()*aa)**2
1142 vl(ip) = vl(ip) * (species%get_z())**2
Copies a vector x, to a vector y.
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.
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)
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 messages_info(no_lines, iunit, debug_only, stress, all_nodes, 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.
A type storing the information and data about a pseudopotential.
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 ...