(git:7fc1fe1)
Loading...
Searching...
No Matches
nlo_current_tensor_derivatives.F
Go to the documentation of this file.
1!--------------------------------------------------------------------------------------------------!
2! CP2K: A general program to perform molecular dynamics simulations !
3! Copyright 2000-2026 CP2K developers group <https://cp2k.org> !
4! !
5! SPDX-License-Identifier: GPL-2.0-or-later !
6!--------------------------------------------------------------------------------------------------!
7
8!> \brief Local full-tensor independent-particle current response through fifth field order.
9!> \note This is a Bloch-point kernel. It does not integrate the Brillouin zone,
10!> convert current to susceptibility, or build AO derivatives from CP2K data.
11! **************************************************************************************************
13 USE ieee_arithmetic, ONLY: ieee_is_finite
14 USE kinds, ONLY: dp
15 USE mathconstants, ONLY: gaussi
24#include "../base/base_uses.f90"
25
26 IMPLICIT NONE
27
28 PRIVATE
29
30 CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'nlo_current'
31
33
34CONTAINS
35
36! **************************************************************************************************
37!> \brief Compute intrinsically permutation-symmetric χ^(n) current at one k point.
38!> \param order Number of incident fields, 2:5
39!> \param omega Incident photon energies in Hartree
40!> \param energies Central band energies in Hartree
41!> \param rate1 Population damping energy in Hartree
42!> \param rate2 Coherence damping energy in Hartree
43!> \param transition_width Band-energy width of their smooth transition in Hartree
44!> \param hamiltonian Orthogonal Bloch Hamiltonian normalized k derivatives through grade n
45!> \param connection Orthogonal Bloch position connection derivatives through grade n-1
46!> \param curvature Three position-curvature matrices for this k point and spin
47!> \param rho0 Equilibrium density derivatives through grade n
48!> \param velocity Physical central-band velocity in bohr/atomic time
49!> \param current Complex current tensor, 3 by 3**order
50!> \param elements Optional output/input selection, same shape and indexing as current.
51!> Only required subset responses are evaluated. Unselected outputs remain zero.
52!> \note Label the n incident fields by j=1,...,n, each with frequency ω_j and
53!> Cartesian direction a_j. For every nonempty labeled subset S, form
54!> Ω_S=Σ_{j∈S}ω_j and the normalized density response
55!> ρ_S = |S|⁻¹ Σ_(j in S) R(Ω_S)L_(a_j)ρ_(S without j),
56!> where R L is the analytic normalized k-derivative step of nlo_density_step_derivatives.
57!> This average equals the sum of all ordered responses divided by n!.
58!> Only k-derivative grades n-|S| are retained for each subset. States
59!> with the same labeled subset and field directions are reused across
60!> all full-tensor components, retaining only two adjacent field orders
61!> in memory. The final current is -Tr[v_c ρ_{1,...,n}]
62!> minus n⁻¹ Σ_j Tr[F_(c,a_j) ρ_(S without j)], in atomic units.
63!> This follows from v_c(E)=i[H+E_a r_a,r_c]=v_c(0)+E_a F_ca,
64!> with [r_c,r_a]=iF_ca. The curvature term is always included. The second
65!> array index stores a_1,...,a_n as 1+Σ_j(a_j-1)3^(j-1).
66! **************************************************************************************************
67 SUBROUTINE nlo_current_tensor_derivatives(order, omega, energies, rate1, rate2, &
68 transition_width, hamiltonian, &
69 connection, curvature, rho0, velocity, current, &
70 elements)
71 INTEGER, INTENT(IN) :: order
72 REAL(kind=dp), INTENT(IN) :: omega(:), energies(:), rate1, rate2, &
73 transition_width
74 COMPLEX(dp), INTENT(IN) :: hamiltonian(:, :, :), &
75 connection(:, :, :, :), &
76 curvature(:, :, :), rho0(:, :, :), &
77 velocity(:, :, :)
78 COMPLEX(dp), INTENT(OUT) :: current(:, :)
79 LOGICAL, INTENT(IN), OPTIONAL :: elements(:, :)
80
81 CHARACTER(len=*), PARAMETER :: routinen = 'nlo_current_tensor_derivatives'
82
83 COMPLEX(dp) :: curvature_term, extra(3, 243)
84 COMPLEX(dp), ALLOCATABLE :: next_density(:, :, :), &
85 previous_density(:, :, :)
86 COMPLEX(dp), ALLOCATABLE, DIMENSION(:, :, :) :: density
87 INTEGER :: code, current_start, direction, field, full_mask, handle, i_code, i_field, &
88 i_mask, i_radix, i_subset_code, index, iother, iother_direction, iother_position, &
89 ioutput, mask, multiplicity, n, na, ncodes(0:31), ncoeff(0:31), nh, &
90 offset_current(0:242, 0:31), offset_previous(0:242, 0:31), order_subset, position, &
91 previous_code, previous_end, previous_mask, previous_start, radix, &
92 representative_code(0:242, 0:31), total_coefficients
93 LOGICAL :: evaluate(0:242, 0:31), &
94 required(0:242, 0:31), selected(3, 243)
95 REAL(kind=dp) :: subset_omega, weight
96
97 CALL timeset(routinen, handle)
98
99 current = 0.0_dp
100 n = SIZE(energies)
101 cpassert(.NOT. (order < 2 .OR. order > 5 .OR. n < 2))
102 cpassert(SIZE(omega) == order)
103 nh = nlo_derivative_count(order)
104 na = nlo_derivative_count(order - 1)
105 cpassert(all(shape(hamiltonian) == [n, n, nh]))
106 cpassert(all(shape(connection) == [n, n, 3, na]))
107 cpassert(all(shape(rho0) == [n, n, nh]))
108 cpassert(all(shape(curvature) == [n, n, 3]))
109 cpassert(all(shape(velocity) == [n, n, 3]))
110 cpassert(all(shape(current) == [3, 3**order]))
111 selected = .true.
112 IF (PRESENT(elements)) THEN
113 cpassert(all(shape(elements) == shape(current)))
114 IF (.NOT. any(elements)) THEN
115 CALL timestop(handle)
116 RETURN
117 END IF
118 selected(:, 1:3**order) = elements
119 END IF
120 ! Restrict every labeled subset to the input directions required by selected elements.
121 required = .false.
122 required(0, 0) = .true.
123 DO i_code = 0, 3**order - 1
124 IF (.NOT. any(selected(:, i_code + 1))) cycle
125 DO i_mask = 1, 2**order - 1
126 i_subset_code = 0
127 i_radix = 1
128 DO i_field = 1, order
129 IF (.NOT. btest(i_mask, i_field - 1)) cycle
130 i_subset_code = i_subset_code + mod(i_code/3**(i_field - 1), 3)*i_radix
131 i_radix = 3*i_radix
132 END DO
133 required(i_subset_code, i_mask) = .true.
134 END DO
135 END DO
136 IF (.NOT. all(ieee_is_finite(omega)) .OR. .NOT. all(ieee_is_finite(energies)) .OR. &
137 .NOT. ieee_is_finite(rate1) .OR. .NOT. ieee_is_finite(rate2) .OR. &
138 .NOT. ieee_is_finite(transition_width) .OR. &
139 .NOT. all(ieee_is_finite(real(velocity, kind=dp))) .OR. &
140 .NOT. all(ieee_is_finite(aimag(velocity))) .OR. &
141 .NOT. all(ieee_is_finite(real(hamiltonian, kind=dp))) .OR. &
142 .NOT. all(ieee_is_finite(aimag(hamiltonian))) .OR. &
143 .NOT. all(ieee_is_finite(real(connection, kind=dp))) .OR. &
144 .NOT. all(ieee_is_finite(aimag(connection))) .OR. &
145 .NOT. all(ieee_is_finite(real(rho0, kind=dp))) .OR. &
146 .NOT. all(ieee_is_finite(aimag(rho0))) .OR. rate1 <= 0.0_dp .OR. &
147 rate2 < rate1 .OR. transition_width <= 0.0_dp &
148 .OR. abs(sum(omega)) <= 1.e-14_dp) THEN
149 cpabort('NLO current response contains invalid data.')
150 END IF
151 full_mask = 2**order - 1
152 DO mask = 0, full_mask
153 ncoeff(mask) = nlo_derivative_count(order - popcnt(mask))
154 ncodes(mask) = 3**popcnt(mask)
155 END DO
156 ALLOCATE (previous_density(n, n, ncoeff(0)), &
157 next_density(n, n, nlo_derivative_count(order - 1)))
158 previous_density(:, :, :) = rho0(:, :, 1:ncoeff(0))
159 offset_previous = 0
160 offset_previous(0, 0) = 1
161 extra = 0.0_dp
162 DO order_subset = 1, order
163 ! Omega_S = sum_(j in S) omega_j; retain each required field subset S.
164 CALL subset_density_offsets(order, order_subset, omega, required, ncoeff, &
165 offset_current, evaluate, representative_code, &
166 total_coefficients)
167 ALLOCATE (density(n, n, total_coefficients))
168 density = 0.0_dp
169 DO mask = 1, full_mask
170 IF (popcnt(mask) /= order_subset) cycle
171 subset_omega = 0.0_dp
172 DO field = 1, order
173 IF (btest(mask, field - 1)) subset_omega = subset_omega + omega(field)
174 END DO
175 DO code = 0, ncodes(mask) - 1
176 IF (.NOT. evaluate(code, mask)) cycle
177 current_start = offset_current(code, mask)
178 DO field = 1, order
179 IF (.NOT. btest(mask, field - 1)) cycle
180 position = popcnt(iand(mask, 2**(field - 1) - 1))
181 radix = 3**position
182 direction = mod(code/radix, 3) + 1
183 multiplicity = 1
184 DO iother = 1, order
185 IF (iother == field .OR. .NOT. btest(mask, iother - 1)) cycle
186 IF (abs(omega(iother) - omega(field)) > 0.0_dp) cycle
187 iother_position = popcnt(iand(mask, 2**(iother - 1) - 1))
188 iother_direction = mod(code/3**iother_position, 3) + 1
189 IF (iother_direction /= direction) cycle
190 IF (iother < field) EXIT
191 multiplicity = multiplicity + 1
192 END DO
193 IF (iother <= order) cycle
194 previous_code = mod(code, radix) + (code/(3*radix))*radix
195 previous_mask = ibclr(mask, field - 1)
196 previous_start = offset_previous(previous_code, previous_mask)
197 IF (order_subset == order) THEN
198 DO ioutput = 1, 3
199 weight = real(multiplicity, kind=dp)/real(order, kind=dp)
200 curvature_term = curvature_density_trace(curvature, &
201 & previous_density(:, :, previous_start), ioutput, direction)
202 extra(ioutput, code + 1) = extra(ioutput, code + 1) - &
203 curvature_term*weight
204 END DO
205 END IF
206 previous_end = previous_start + ncoeff(previous_mask) - 1
207 ! (ε_m-ε_n-Ω_S-iγ_mn)ρ_S = source from lower-order responses.
208 CALL nlo_density_step_derivatives(order - order_subset, direction, &
209 subset_omega, energies, rate1, rate2, &
210 transition_width, &
211 hamiltonian, connection, &
212 previous_density(:, :, &
213 previous_start:previous_end), &
214 next_density(:, :, 1:ncoeff(mask)))
215 density(:, :, current_start:current_start + ncoeff(mask) - 1) = &
216 density(:, :, current_start:current_start + ncoeff(mask) - 1) + &
217 next_density(:, :, 1:ncoeff(mask))*real(multiplicity, &
218 kind=dp)/real(order_subset, kind=dp)
219 END DO
220 END DO
221 END DO
222 CALL move_alloc(density, previous_density)
223 offset_previous = offset_current
224 END DO
225 DO index = 1, 3**order
226 IF (.NOT. any(selected(:, index))) cycle
227 current_start = offset_previous(index - 1, full_mask)
228 DO field = 1, 3
229 IF (.NOT. selected(field, index)) cycle
230 ! J_i^(n) = -Tr[v_i rho^(n)] + curvature contribution.
231 current(field, index) = -sum(velocity(:, :, field)* &
232 transpose(previous_density(:, :, current_start))) + &
233 extra(field, representative_code(index - 1, full_mask) + 1)
234 END DO
235 END DO
236 IF (.NOT. all(ieee_is_finite(real(current, kind=dp))) .OR. &
237 .NOT. all(ieee_is_finite(aimag(current)))) THEN
238 cpabort('NLO current response contains invalid data.')
239 END IF
240
241 CALL timestop(handle)
242
243 END SUBROUTINE nlo_current_tensor_derivatives
244
245! **************************************************************************************************
246!> \brief Store each required density once per multiset of (frequency, direction) pairs.
247!> \param order Number of incident optical fields.
248!> \param degree Number of fields in each subset represented at this stage.
249!> \param omega Photon energies of the labeled incident fields.
250!> \param required Mask of subset densities needed by the requested tensor elements.
251!> \param ncoeff Number of retained k-derivative coefficients for each field subset.
252!> \param offsets Starting positions of the compact density arrays.
253!> \param evaluate Marks one representative density per equal-frequency field multiset.
254!> \param representative_code Tensor-direction code of the representative density.
255!> \param total Total retained matrix-derivative coefficients.
256!> \note The normalized subset recursion is invariant under relabeling equal-frequency
257!> fields. Integer multiplicities identify exactly equal multisets, with no frequency
258!> tolerance. Offsets address compact matrix-derivative slices of length ncoeff(mask).
259! **************************************************************************************************
260 SUBROUTINE subset_density_offsets(order, degree, omega, required, ncoeff, offsets, evaluate, &
261 representative_code, total)
262 INTEGER, INTENT(IN) :: order, degree
263 REAL(kind=dp), INTENT(IN) :: omega(:)
264 LOGICAL, INTENT(IN) :: required(0:242, 0:31)
265 INTEGER, INTENT(IN) :: ncoeff(0:31)
266 INTEGER, INTENT(OUT) :: offsets(0:242, 0:31)
267 LOGICAL, INTENT(OUT) :: evaluate(0:242, 0:31)
268 INTEGER, INTENT(OUT) :: representative_code(0:242, 0:31), total
269
270 INTEGER :: codes(1024), counts(3, 5), groups(5), icode, idir, ifield, imask, iposition, &
271 istate, jfield, nstates, signatures(3, 5, 1024), starts(1024)
272
273 groups = 0
274 DO ifield = 1, order
275 groups(ifield) = ifield
276 DO jfield = 1, ifield - 1
277 IF (abs(omega(ifield) - omega(jfield)) > 0.0_dp) cycle
278 groups(ifield) = groups(jfield)
279 EXIT
280 END DO
281 END DO
282 offsets = 0
283 evaluate = .false.
284 representative_code = 0
285 total = 0
286 nstates = 0
287 DO imask = 1, 2**order - 1
288 IF (popcnt(imask) /= degree) cycle
289 DO icode = 0, 3**degree - 1
290 IF (.NOT. required(icode, imask)) cycle
291 counts = 0
292 iposition = 0
293 DO ifield = 1, order
294 IF (.NOT. btest(imask, ifield - 1)) cycle
295 idir = mod(icode/3**iposition, 3) + 1
296 counts(idir, groups(ifield)) = counts(idir, groups(ifield)) + 1
297 iposition = iposition + 1
298 END DO
299 DO istate = 1, nstates
300 IF (all(signatures(:, :, istate) == counts)) EXIT
301 END DO
302 IF (istate > nstates) THEN
303 nstates = istate
304 signatures(:, :, istate) = counts
305 starts(istate) = total + 1
306 codes(istate) = icode
307 total = total + ncoeff(imask)
308 evaluate(icode, imask) = .true.
309 END IF
310 offsets(icode, imask) = starts(istate)
311 representative_code(icode, imask) = codes(istate)
312 END DO
313 END DO
314
315 END SUBROUTINE subset_density_offsets
316
317! **************************************************************************************************
318!> \brief Trace a precomputed curvature matrix against one lower-order density.
319!> \param curvature Three independent Cartesian position-curvature matrices.
320!> \param density Lower-order density matrix for the selected field subset.
321!> \param ic Cartesian direction of the output current.
322!> \param ia Cartesian direction of the incident field.
323!> \return Tr[F_(ic,ia) density], with antisymmetry under ic and ia.
324! **************************************************************************************************
325 FUNCTION curvature_density_trace(curvature, density, ic, ia) RESULT(value)
326 COMPLEX(dp), INTENT(IN) :: curvature(:, :, :), density(:, :)
327 INTEGER, INTENT(IN) :: ic, ia
328 COMPLEX(dp) :: value
329
330 INTEGER :: lower, pair, upper
331
332 value = 0.0_dp
333 IF (ic == ia) RETURN
334 lower = min(ic, ia)
335 upper = max(ic, ia)
336 pair = (lower - 1)*(6 - lower)/2 + upper - lower
337 value = sum(curvature(:, :, pair)*transpose(density))
338 IF (ic > ia) value = -value
339
340 END FUNCTION curvature_density_trace
341
342! **************************************************************************************************
343!> \brief Advance one optical field in the normalized Cartesian k-derivative recursion.
344!> \param max_grade Required highest k-derivative grade, 0:4
345!> \param direction Cartesian component of the new input field, 1:3
346!> \param omega Cumulative input photon energy in Hartree
347!> \param energies Central band energies in Hartree
348!> \param rate1 Population damping energy in Hartree
349!> \param rate2 Coherence damping energy in Hartree
350!> \param transition_width Band-energy width of their smooth transition in Hartree
351!> \param hamiltonian Orthogonal-frame Hamiltonian k derivatives through the active response order
352!> \param connection Connection k derivatives through one grade below the response order
353!> \param previous Previous-order density normalized k derivatives, at least through grade
354!> max_grade+1
355!> \param response This order's density normalized k derivatives, at least through grade max_grade
356!> \note Write X_α=(∂_k^α X)/α! and L_H(X)=[H,X]. At order p, after adding
357!> the field component j with cumulative photon energy Ω, solve
358!> (L_H0-Ω-iΓ_0)ρ_{p,α} = -i(α_j+1)ρ_{p-1,α+e_j}
359!> -Σ_{β+γ=α}[A_{j,β},ρ_{p-1,γ}]
360!> -Σ_{0<β≤α}[H_β,ρ_{p,α-β}]
361!> +iΣ_{0<β≤α}Γ_β(ρ_{p,α-β}).
362!> For equal times Γ_0=1/T1_T2 and all higher Γ derivatives vanish.
363!> For separate times, Γ_H(X)=γ₂X+(γ₁−γ₂)exp[−(ad_H/w)²]X.
364!> The known positive-grade Γ_H terms enter the right-hand side.
365!> The central H_0 is diagonal in this frame.
366!> \note If previous has grade <=g+1, this produces the next response through grade g.
367!> Denominators use exp(-i ω t): ε_m-ε_n-ω-iγ_mn.
368!> The field couples as +E.r for an electron, r=i ∂_k+A.
369! **************************************************************************************************
370 SUBROUTINE nlo_density_step_derivatives(max_grade, direction, omega, energies, rate1, &
371 rate2, transition_width, &
372 hamiltonian, connection, previous, response)
373 INTEGER, INTENT(IN) :: max_grade, direction
374 REAL(kind=dp), INTENT(IN) :: omega, energies(:), rate1, rate2, &
375 transition_width
376 COMPLEX(dp), INTENT(IN) :: hamiltonian(:, :, :), &
377 connection(:, :, :, :), &
378 previous(:, :, :)
379 COMPLEX(dp), INTENT(OUT) :: response(:, :, :)
380
381 CHARACTER(len=*), PARAMETER :: routinen = 'nlo_density_step_derivatives'
382
383 COMPLEX(dp), ALLOCATABLE :: matrix_term(:, :), rhs(:, :), &
384 transition_term(:, :, :)
385 INTEGER :: grade, handle, i, ia, ib, j, k, n, &
386 ngrade, nh, nlower, np, plus(3), &
387 remain(3)
388 INTEGER, DIMENSION(3, nlo_n_derivatives) :: alpha
389 LOGICAL :: separate_times
390 REAL(kind=dp) :: pair_rate
391 TYPE(nlo_band_transition_type) :: transition
392
393 CALL timeset(routinen, handle)
394
395 response = 0.0_dp
396 n = SIZE(energies)
397 cpassert(max_grade >= 0 .AND. max_grade <= 4)
398 cpassert(direction >= 1 .AND. direction <= 3)
399 cpassert(n >= 2)
400 nh = nlo_derivative_count(max_grade)
401 np = nlo_derivative_count(max_grade + 1)
402 cpassert(SIZE(hamiltonian, 1) == n)
403 cpassert(SIZE(hamiltonian, 2) == n)
404 cpassert(SIZE(hamiltonian, 3) >= nh)
405 cpassert(SIZE(connection, 1) == n)
406 cpassert(SIZE(connection, 2) == n)
407 cpassert(SIZE(connection, 3) == 3)
408 cpassert(SIZE(connection, 4) >= nh)
409 cpassert(SIZE(previous, 1) == n)
410 cpassert(SIZE(previous, 2) == n)
411 cpassert(SIZE(previous, 3) >= np)
412 cpassert(SIZE(response, 1) == n)
413 cpassert(SIZE(response, 2) == n)
414 cpassert(SIZE(response, 3) >= nh)
415 IF (.NOT. ieee_is_finite(omega) .OR. .NOT. all(ieee_is_finite(energies)) .OR. &
416 .NOT. ieee_is_finite(rate1) .OR. .NOT. ieee_is_finite(rate2) .OR. &
417 .NOT. ieee_is_finite(transition_width) .OR. rate1 <= 0.0_dp .OR. &
418 rate2 < rate1 .OR. transition_width <= 0.0_dp .OR. &
419 .NOT. all(ieee_is_finite(real(previous, kind=dp))) .OR. &
420 .NOT. all(ieee_is_finite(aimag(previous)))) THEN
421 cpabort('NLO density response contains invalid data.')
422 END IF
423 ALLOCATE (matrix_term(n, n), rhs(n, n))
424 separate_times = rate1 < rate2
425 IF (separate_times) THEN
426 ALLOCATE (transition_term(n, n, (max_grade + 1)*(max_grade + 2)/2))
427 CALL nlo_band_transition_prepare(energies, transition_width, rate1, rate2, transition)
428 END IF
429 CALL nlo_derivative_indices(alpha)
430 nlower = 0
431 DO ia = 1, nlo_derivative_count(max_grade)
432 grade = sum(alpha(:, ia))
433 IF (separate_times .AND. grade > 0) THEN
434 IF (ia == nlo_derivative_count(grade - 1) + 1) THEN
435 nlower = ia - 1
436 ngrade = nlo_derivative_count(grade) - nlower
437 CALL nlo_band_transition_correction(transition, hamiltonian, response, grade, &
438 transition_term(:, :, :ngrade))
439 END IF
440 END IF
441 plus = alpha(:, ia)
442 plus(direction) = plus(direction) + 1
443 ib = derivatives_index(alpha, plus)
444 cpassert(ib /= 0)
445 ! D_a rho = d_a rho - i[A_a,rho]; lower H derivatives enter recursively.
446 rhs(:, :) = -gaussi*real(plus(direction), kind=dp)*previous(:, :, ib)
447 DO ib = 1, ia
448 remain = alpha(:, ia) - alpha(:, ib)
449 j = derivatives_index(alpha, remain)
450 IF (j == 0) cycle
451 matrix_term(:, :) = matmul(connection(:, :, direction, ib), previous(:, :, j))
452 rhs(:, :) = rhs - matrix_term
453 matrix_term(:, :) = matmul(previous(:, :, j), connection(:, :, direction, ib))
454 rhs(:, :) = rhs + matrix_term
455 END DO
456 DO ib = 2, ia
457 remain = alpha(:, ia) - alpha(:, ib)
458 j = derivatives_index(alpha, remain)
459 IF (j == 0) cycle
460 matrix_term(:, :) = matmul(hamiltonian(:, :, ib), response(:, :, j))
461 rhs(:, :) = rhs - matrix_term
462 matrix_term(:, :) = matmul(response(:, :, j), hamiltonian(:, :, ib))
463 rhs(:, :) = rhs + matrix_term
464 END DO
465 IF (separate_times .AND. grade > 0) THEN
466 rhs(:, :) = rhs + gaussi*transition_term(:, :, ia - nlower)
467 END IF
468 DO k = 1, n
469 DO i = 1, n
470 pair_rate = rate1
471 IF (separate_times) pair_rate = nlo_band_transition_rate(transition, i, k)
472 response(i, k, ia) = rhs(i, k)/ &
473 cmplx(energies(i) - energies(k) - omega, -pair_rate, dp)
474 END DO
475 END DO
476 END DO
477 IF (.NOT. all(ieee_is_finite(real(response, kind=dp))) .OR. &
478 .NOT. all(ieee_is_finite(aimag(response)))) THEN
479 cpabort('NLO density response contains invalid data.')
480 END IF
481
482 CALL timestop(handle)
483
484 END SUBROUTINE nlo_density_step_derivatives
485
486END MODULE nlo_current
Defines the basic variable types.
Definition kinds.F:23
integer, parameter, public dp
Definition kinds.F:34
Definition of mathematical constants and functions.
real(kind=dp), parameter, public degree
complex(kind=dp), parameter, public gaussi
Local full-tensor independent-particle current response through fifth field order.
subroutine, public nlo_current_tensor_derivatives(order, omega, energies, rate1, rate2, transition_width, hamiltonian, connection, curvature, rho0, velocity, current, elements)
Compute intrinsically permutation-symmetric χ^(n) current at one k point.
Matrix algebra for analytic k derivatives through fifth order.
integer, parameter, public nlo_n_derivatives
integer function, public nlo_derivative_count(grade)
Number of Cartesian Taylor coefficients through the given total grade.
subroutine, public nlo_derivative_indices(alpha)
Enumerate the 56 three-dimensional multi-indices through total order five.
integer function, public derivatives_index(alpha, sought)
Find the Taylor coefficient for the requested (x,y,z) derivative counts.
Smooth band transition between population and coherence relaxation times.
real(dp) function, public nlo_band_transition_rate(relaxation, iband, jband)
Return the central relaxation rate for one band pair.
subroutine, public nlo_band_transition_prepare(energies, width, rate1, rate2, relaxation)
Prepare Γ_H(X)=γ₂X+(γ₁−γ₂)exp[−(ad_H/w)²]X, ad_H(X)=[H,X].
subroutine, public nlo_band_transition_correction(relaxation, hamiltonian, density, grade, correction)
Sum relaxation corrections for one complete Cartesian Taylor grade.