65 INTEGER,
INTENT(IN) ::
degree
68 INTEGER :: a, b, i, j, k, l, lambda, m, n, &
69 nsimpson, p, powers(3), q, s
70 REAL(kind=
dp),
ALLOCATABLE :: moments(:, :), weights(:)
74 cpabort(
"Spin-orbit UPF projectors are not supported")
76 cpassert(pot%number_of_proj > 0)
77 cpassert(all(pot%lbeta >= 0))
79 projectors%lmax = maxval(pot%lbeta)
80 projectors%harmonic_max =
degree + projectors%lmax
82 cpassert(projectors%harmonic_max <= min(20,
maxfac/2))
89 cpassert(
SIZE(pot%rab) == n)
90 cpassert(
SIZE(pot%beta, 1) == n)
91 cpassert(
SIZE(pot%beta, 2) == pot%number_of_proj)
92 cpassert(all(pot%r(2:) > pot%r(:n - 1)))
93 cpassert(all(pot%rab > 0.0_dp))
94 ALLOCATE (projectors%r(n), projectors%lbeta(pot%number_of_proj))
95 projectors%r(:) = pot%r
96 projectors%lbeta(:) = pot%lbeta
101 nsimpson = n - 1 +
modulo(n, 2)
102 weights(1:nsimpson:2) = 2.0_dp/3.0_dp
103 weights(2:nsimpson - 1:2) = 4.0_dp/3.0_dp
104 weights(1) = 1.0_dp/3.0_dp
105 weights(nsimpson) = 1.0_dp/3.0_dp
106 IF (nsimpson < n) weights(n - 1:n) = weights(n - 1:n) + 0.5_dp
107 weights(:) = weights*pot%rab*pot%r**2
108 ALLOCATE (projectors%weighted_beta(n, pot%number_of_proj))
109 DO i = 1, pot%number_of_proj
110 projectors%weighted_beta(:, i) = weights*pot%beta(:, i)
112 IF (pot%beta(j, i) /= 0.0_dp)
THEN
113 projectors%radius = max(projectors%radius, pot%r(j))
119 projectors%nproj = sum(2*pot%lbeta + 1)
120 ALLOCATE (projectors%radial_index(projectors%nproj), projectors%angular_index(projectors%nproj))
122 DO i = 1, pot%number_of_proj
126 projectors%radial_index(p) = i
127 projectors%angular_index(p) = l*l + m
130 ALLOCATE (projectors%d(projectors%nproj, projectors%nproj))
131 projectors%d = 0.0_dp
132 DO p = 1, projectors%nproj
133 DO q = 1, projectors%nproj
134 i = projectors%radial_index(p)
135 j = projectors%radial_index(q)
136 IF (projectors%angular_index(p) == projectors%angular_index(q))
THEN
137 projectors%d(p, q) = pot%dion(i, j)
138 ELSE IF (pot%lbeta(i) /= pot%lbeta(j))
THEN
139 cpassert(abs(pot%dion(i, j)) < 1.e-12_dp)
145 ALLOCATE (projectors%gaunt(
ncoset(
degree), (projectors%lmax + 1)**2, &
146 (projectors%harmonic_max + 1)**2))
147 projectors%gaunt = 0.0_dp
150 DO l = 0, projectors%lmax
151 IF (.NOT. any(pot%lbeta == l)) cycle
152 DO lambda = max(0, l - k), l + k
153 IF (
modulo(k + l + lambda, 2) /= 0) cycle
154 ALLOCATE (moments(
nco(l),
nco(lambda)))
155 DO b = 1,
nco(lambda)
158 moments(a, b) = 0.0_dp
159 IF (all(
modulo(powers, 2) == 0))
THEN
160 moments(a, b) =
fourpi*product(
dfac(powers - 1))/
dfac(sum(powers) + 1)
164 projectors%gaunt(s, l*l + 1:(l + 1)**2, lambda*lambda + 1:(lambda + 1)**2) = &
185 INTEGER,
INTENT(IN) :: la
186 REAL(kind=
dp),
INTENT(IN) :: zeta(:), rac(3)
187 INTEGER,
INTENT(IN) :: nder
188 REAL(kind=
dp),
INTENT(OUT) :: integrals(:, :, :)
189 REAL(kind=
dp),
INTENT(IN),
OPTIONAL :: moment_origin(3)
191 INTEGER :: a(3), axis, b(3),
degree, deriv(3), i, &
192 id, ip, j, k, l, lambda, nb, nc, nh, &
193 nr, p, power, s, shifted(3), step, t
194 REAL(kind=
dp) :: alpha, direction(3), distance, factor
195 REAL(kind=
dp),
ALLOCATABLE :: angular(:, :, :), cartesian(:, :), centered(:, :), &
196 coeff(:, :), envelope(:), harmonics(:), monomials(:), next_coeff(:), radial(:, :, :), &
197 radial_power(:), radial_work(:), shift(:, :)
200 cpassert(la >= 0 .AND. nder >= 0)
201 cpassert(
degree <= projectors%degree)
202 cpassert(all(zeta > 0.0_dp))
203 cpassert(
SIZE(integrals, 1) ==
SIZE(zeta)*
ncoset(la))
204 cpassert(
SIZE(integrals, 2) == projectors%nproj)
205 cpassert(
SIZE(integrals, 3) ==
ncoset(nder))
207 nh =
degree + projectors%lmax
208 nr =
SIZE(projectors%r)
209 nb =
SIZE(projectors%weighted_beta, 2)
210 ALLOCATE (harmonics((nh + 1)**2), monomials(
ncoset(nh)))
211 distance = norm2(rac)
212 direction = [0.0_dp, 0.0_dp, 1.0_dp]
213 IF (distance > 0.0_dp) direction = -rac/distance
215 monomials(i) = product(direction**
indco(:, i))
218 harmonics(l*l + 1:(l + 1)**2) = &
221 ALLOCATE (angular(nc, (projectors%lmax + 1)**2, 0:nh))
223 DO i = 1,
SIZE(angular, 2)
224 angular(:, i, lambda) = matmul( &
225 projectors%gaunt(:nc, i, lambda*lambda + 1:(lambda + 1)**2), &
226 harmonics(lambda*lambda + 1:(lambda + 1)**2))
229 ALLOCATE (shift(nc, nc))
235 IF (any(b > a)) cycle
238 factor = factor*
binomial(a(axis), b(axis))*rac(axis)**(a(axis) - b(axis))
243 ALLOCATE (radial(0:
degree, nb, 0:nh), radial_work(nr), radial_power(nr), envelope(nr))
244 ALLOCATE (centered(nc, projectors%nproj), cartesian(nc, projectors%nproj))
247 DO ip = 1,
SIZE(zeta)
249 envelope(:) = exp(-alpha*(projectors%r - distance)**2)
252 radial_work(i) = envelope(i)*
scaled_bessel(int(lambda, c_int), &
253 REAL(2.0_dp*alpha*projectors%r(i)*distance, c_double))
255 radial_power(:) = radial_work
257 radial(k, :, lambda) = matmul(radial_power, projectors%weighted_beta)
258 radial_power(:) = radial_power*projectors%r
262 DO p = 1, projectors%nproj
263 i = projectors%radial_index(p)
264 j = projectors%angular_index(p)
267 centered(s, p) =
fourpi*dot_product(angular(s, j, :), radial(k, i, :))
270 cartesian(:, :) = matmul(shift, centered)
277 coeff(a(axis), axis) = 1.0_dp
278 IF (
PRESENT(moment_origin))
THEN
279 coeff(:, axis) = 0.0_dp
280 DO power = 0, deriv(axis)
281 coeff(a(axis) + power, axis) =
binomial(deriv(axis), power)* &
282 moment_origin(axis)**(deriv(axis) - power)
285 DO step = 1, deriv(axis)
287 DO power = 0, a(axis) + step - 1
288 next_coeff(power + 1) = next_coeff(power + 1) + 2.0_dp*alpha*coeff(power, axis)
289 IF (power > 0) next_coeff(power - 1) = next_coeff(power - 1) - power*coeff(power, axis)
291 coeff(:, axis) = next_coeff
296 shifted =
indco(:, s)
297 factor = coeff(shifted(1), 1)*coeff(shifted(2), 2)*coeff(shifted(3), 3)
298 IF (factor == 0.0_dp) cycle
299 integrals((ip - 1)*
ncoset(la) + t, :, id) = integrals((ip - 1)*
ncoset(la) + t, :, id) + &
300 factor*cartesian(s, :)