85 COMPLEX(dp),
INTENT(IN) :: left(:, :, :), right(:, :, :)
86 COMPLEX(dp),
INTENT(OUT) :: product(:, :, :)
87 INTEGER,
INTENT(IN),
OPTIONAL :: active_grade
89 CHARACTER(len=*),
PARAMETER :: routinen =
'nlo_derivative_product'
91 COMPLEX(dp),
ALLOCATABLE :: term(:, :)
92 INTEGER :: handle, ib, ij, ik, nj
94 CALL timeset(routinen, handle)
99 ALLOCATE (term(
SIZE(left, 1),
SIZE(right, 2)))
104 term(:, :) = matmul(left(:, :, ib), right(:, :, ik))
105 product(:, :, ij) = product(:, :, ij) + term
109 CALL timestop(handle)
120 COMPLEX(dp),
INTENT(IN) :: overlap(:, :, :)
121 COMPLEX(dp),
INTENT(OUT) :: inverse_root(:, :, :)
122 INTEGER,
INTENT(IN),
OPTIONAL :: active_grade
124 CHARACTER(len=*),
PARAMETER :: routinen =
'nlo_lowdin_derivatives'
126 COMPLEX(dp),
ALLOCATABLE :: matrix_work(:, :), metric_u(:, :), &
128 COMPLEX(dp),
ALLOCATABLE,
DIMENSION(:, :) :: matrix_product
129 INTEGER :: handle, ib, ic, id, ij, n, nj
130 INTEGER,
DIMENSION(3, nlo_n_derivatives) :: alpha
131 REAL(kind=
dp) :: scale
132 REAL(kind=
dp),
ALLOCATABLE :: metric_e(:)
134 CALL timeset(routinen, handle)
137 inverse_root = 0.0_dp
140 cpassert(.NOT. (n < 1 .OR. any(shape(overlap) /= [n, n, nj])))
141 cpassert(.NOT. (any(shape(inverse_root) /= [n, n, nj])))
144 scale = max(1.0_dp, maxval(abs(overlap(:, :, ij))))
145 IF (.NOT. all(ieee_is_finite(real(overlap(:, :, ij), kind=
dp))) .OR. &
146 .NOT. all(ieee_is_finite(aimag(overlap(:, :, ij)))) .OR. &
147 maxval(abs(overlap(:, :, ij) - &
148 conjg(transpose(overlap(:, :, ij))))) > 1.e-10_dp*scale)
THEN
149 cpabort(
'NONLINEAR_OPTICS Löwdin derivative check failed.')
152 ALLOCATE (metric_u(n, n), rhs(n, n), matrix_work(n, n), &
153 matrix_product(n, n), metric_e(n))
157 IF (maxval(metric_e) <= 0.0_dp .OR. minval(metric_e) <= 1.e-10_dp*maxval(metric_e))
THEN
158 cpabort(
'NONLINEAR_OPTICS Löwdin derivative check failed.')
162 rhs(ib, ib) = 1.0_dp/sqrt(metric_e(ib))
164 matrix_work(:, :) = matmul(rhs, conjg(transpose(metric_u)))
165 inverse_root(:, :, 1) = matmul(metric_u, matrix_work)
174 IF (ib == ij .OR. id == ij) cycle
175 matrix_work(:, :) = matmul(overlap(:, :, ic), inverse_root(:, :, id))
176 matrix_product(:, :) = matmul(inverse_root(:, :, ib), matrix_work)
177 rhs(:, :) = rhs - matrix_product
180 matrix_work(:, :) = matmul(rhs, metric_u)
181 rhs(:, :) = matmul(conjg(transpose(metric_u)), matrix_work)
184 rhs(ib, ic) = rhs(ib, ic)/(sqrt(metric_e(ib)) + sqrt(metric_e(ic)))
187 matrix_work(:, :) = matmul(rhs, conjg(transpose(metric_u)))
188 inverse_root(:, :, ij) = matmul(metric_u, matrix_work)
189 scale = max(1.0_dp, maxval(abs(inverse_root(:, :, ij))))
190 IF (maxval(abs(inverse_root(:, :, ij) - &
191 conjg(transpose(inverse_root(:, :, ij))))) > 1.e-9_dp*scale)
THEN
192 cpabort(
'NONLINEAR_OPTICS Löwdin derivative check failed.')
196 CALL timestop(handle)
216 connection, active_grade)
217 COMPLEX(dp),
DIMENSION(:, :, :),
INTENT(IN) :: overlap, hamiltonian
218 COMPLEX(dp),
INTENT(IN) :: moment(:, :, :, :)
219 COMPLEX(dp),
INTENT(OUT) :: orth_h(:, :, :), connection(:, :, :, :)
220 INTEGER,
INTENT(IN),
OPTIONAL :: active_grade
222 CHARACTER(len=*),
PARAMETER :: routinen =
'nlo_orthonormal_operator_derivatives'
224 COMPLEX(dp),
ALLOCATABLE :: derivative_x(:, :, :), &
225 inverse_root(:, :, :), &
226 matrix_derivatives(:, :, :), &
227 moment_derivatives(:, :, :)
229 handle, ia, ij, ik, n, na, nh, &
231 REAL(kind=
dp) :: scale
233 CALL timeset(routinen, handle)
240 IF (
PRESENT(active_grade)) grade = active_grade
243 cpassert(grade >= 2 .AND. nh >= 1)
244 cpassert(all(shape(overlap) == [n, n, nh]))
245 cpassert(all(shape(hamiltonian) == [n, n, nh]))
246 cpassert(all(shape(moment) == [n, n, 3, na]))
247 cpassert(all(shape(orth_h) == [n, n, nh]))
248 cpassert(all(shape(connection) == [n, n, 3, na]))
249 IF (.NOT. all(ieee_is_finite(real(hamiltonian, kind=
dp))) .OR. &
250 .NOT. all(ieee_is_finite(aimag(hamiltonian))) .OR. &
251 .NOT. all(ieee_is_finite(real(moment, kind=
dp))) .OR. &
252 .NOT. all(ieee_is_finite(aimag(moment))))
THEN
253 cpabort(
'NONLINEAR_OPTICS AO operator derivatives are inconsistent.')
257 scale = max(1.0_dp, maxval(abs(hamiltonian(:, :, ij))))
258 IF (maxval(abs(hamiltonian(:, :, ij) - &
259 conjg(transpose(hamiltonian(:, :, ij))))) > 1.e-9_dp*scale)
THEN
260 cpabort(
'NONLINEAR_OPTICS AO operator derivatives are inconsistent.')
262 IF (sum(alpha(:, ij)) >= grade) cycle
264 sought = alpha(:, ij)
265 sought(ia) = sought(ia) + 1
267 scale = max(1.0_dp, maxval(abs(moment(:, :, ia, ij))), &
268 maxval(abs(overlap(:, :, ik))))
269 IF (maxval(abs(moment(:, :, ia, ij) - &
270 conjg(transpose(moment(:, :, ia, ij))) + &
271 gaussi*real(sought(ia), kind=
dp)*overlap(:, :, ik))) > &
273 cpabort(
'NONLINEAR_OPTICS AO operator derivatives are inconsistent.')
277 ALLOCATE (inverse_root(n, n, nh), derivative_x(n, n, na), &
278 matrix_derivatives(n, n, nh), moment_derivatives(n, n, na))
290 derivative_x = 0.0_dp
292 IF (sum(alpha(:, ij)) >= grade) cycle
293 sought = alpha(:, ij)
294 sought(ia) = sought(ia) + 1
296 derivative_x(:, :, ij) = real(alpha(ia, ij) + 1, kind=
dp)*inverse_root(:, :, ik)
299 active_grade=grade - 1)
301 moment_derivatives, active_grade=grade - 1)
302 connection(:, :, ia, :) = -
gaussi*moment_derivatives
304 matrix_derivatives, active_grade=grade - 1)
306 moment_derivatives, active_grade=grade - 1)
307 connection(:, :, ia, :) = connection(:, :, ia, :) + moment_derivatives
309 scale = max(1.0_dp, maxval(abs(connection(:, :, ia, ij))))
310 IF (maxval(abs(connection(:, :, ia, ij) - &
311 conjg(transpose(connection(:, :, ia, ij))))) > 1.e-9_dp*scale)
THEN
312 cpabort(
'NONLINEAR_OPTICS AO operator derivatives are inconsistent.')
317 CALL timestop(handle)
339 REAL(kind=
dp),
INTENT(IN) :: energies(:)
340 INTEGER,
INTENT(IN) :: occupied(:)
341 COMPLEX(dp),
INTENT(IN) :: hamiltonian(:, :, :)
342 COMPLEX(dp),
INTENT(OUT) :: rho0(:, :, :)
343 INTEGER,
INTENT(IN),
OPTIONAL :: active_grade
345 CHARACTER(len=*),
PARAMETER :: routinen =
'nlo_equilibrium_density_derivatives'
347 COMPLEX(dp),
ALLOCATABLE :: block(:, :), forcing(:, :), &
349 INTEGER :: handle, ib, ic, ij, ik, n, nj
350 INTEGER,
DIMENSION(3, nlo_n_derivatives) :: alpha
351 REAL(kind=
dp) :: gap, scale, symmetry_error
353 CALL timeset(routinen, handle)
357 cpassert(.NOT. (n < 2 .OR.
SIZE(occupied) /= n))
360 cpassert(all(shape(hamiltonian) == [n, n, nj]))
361 cpassert(all(shape(rho0) == [n, n, nj]))
362 cpassert(.NOT. (any(occupied < 0) .OR. any(occupied > 1)))
363 cpassert(.NOT. (all(occupied == 0) .OR. all(occupied == 1)))
364 IF (.NOT. all(ieee_is_finite(energies)) .OR. &
365 .NOT. all(ieee_is_finite(real(hamiltonian, kind=
dp))) .OR. &
366 .NOT. all(ieee_is_finite(aimag(hamiltonian))))
THEN
367 cpabort(
'NONLINEAR_OPTICS equilibrium density input is not finite.')
369 scale = max(1.0_dp, maxval(abs(energies)))
371 gap = minval(energies, mask=occupied == 0) - maxval(energies, mask=occupied == 1)
372 IF (gap <= 1.e-10_dp*scale)
THEN
373 cpabort(
'NONLINEAR_OPTICS requires a positive occupied-empty gap.')
375 ALLOCATE (block(n, n), forcing(n, n), matrix_term(n, n))
376 matrix_term(:, :) = hamiltonian(:, :, 1)
378 matrix_term(ib, ib) = matrix_term(ib, ib) - energies(ib)
380 IF (maxval(abs(matrix_term)) > 1.e-9_dp*scale)
THEN
381 cpabort(
'NONLINEAR_OPTICS Hamiltonian is not diagonal in the band basis.')
386 rho0(ib, ib, 1) = occupied(ib)
395 matrix_term(:, :) = matmul(hamiltonian(:, :, ik), rho0(:, :, ic))
396 forcing(:, :) = forcing + matrix_term
397 matrix_term(:, :) = matmul(rho0(:, :, ic), hamiltonian(:, :, ik))
398 forcing(:, :) = forcing - matrix_term
400 matrix_term(:, :) = matmul(rho0(:, :, ik), rho0(:, :, ic))
401 block(:, :) = block + matrix_term
407 IF (occupied(ib) /= occupied(ic))
THEN
408 rho0(ib, ic, ij) = -forcing(ib, ic)/(energies(ib) - energies(ic))
409 ELSE IF (occupied(ib) == 1)
THEN
410 rho0(ib, ic, ij) = -block(ib, ic)
412 rho0(ib, ic, ij) = block(ib, ic)
417 symmetry_error = 0.0_dp
419 symmetry_error = max(symmetry_error, &
420 maxval(abs(rho0(:, :, ij) - conjg(transpose(rho0(:, :, ij)))))/ &
421 max(1.0_dp, maxval(abs(rho0(:, :, ij)))))
423 IF (.NOT. all(ieee_is_finite(real(rho0, kind=
dp))) .OR. &
424 .NOT. all(ieee_is_finite(aimag(rho0))) .OR. symmetry_error > 1.e-8_dp)
THEN
425 cpabort(
'NONLINEAR_OPTICS equilibrium density derivatives are invalid.')
428 CALL timestop(handle)