(git:7fc1fe1)
Loading...
Searching...
No Matches
nlo_T1_T2_band_transition.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! **************************************************************************************************
9!> \brief Smooth band transition between population and coherence relaxation times.
10! **************************************************************************************************
12 USE ieee_arithmetic, ONLY: ieee_is_finite
13 USE kinds, ONLY: dp
14 USE mathconstants, ONLY: gaussi,&
15 pi
20#include "../base/base_uses.f90"
21
22 IMPLICIT NONE
23
24 PRIVATE
25
26 CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'nlo_T1_T2_band_transition'
27
31
33 REAL(dp), ALLOCATABLE :: energies(:), pair_rate(:, :)
34 REAL(dp) :: width = 0.0_dp, rate_difference = 0.0_dp
35 COMPLEX(dp), ALLOCATABLE :: integration_points(:), integration_weights(:)
37
38CONTAINS
39
40! **************************************************************************************************
41!> \brief Prepare Γ_H(X)=γ₂X+(γ₁−γ₂)exp[−(ad_H/w)²]X, ad_H(X)=[H,X].
42!> \param energies Band energies in Hartree
43!> \param width Energy scale of the smooth transition in Hartree
44!> \param rate1 Population damping energy in Hartree
45!> \param rate2 Coherence damping energy in Hartree
46!> \param relaxation Prepared band transition state
47!> \note Central rates use EXP exactly. Positive grades use Cauchy's formula
48!> on two horizontal contours and Gauss-Hermite integration. The contour
49!> shifts and factors are generated from the Hermite Jacobi matrix; no
50!> fitted or tabulated coefficients enter the relaxation model.
51!> Taylor derivatives follow analytically from the resolvent equation.
52!> Contour points share one workspace; lower grades are reconstructed
53!> once per requested grade from the already solved physical density.
54! **************************************************************************************************
55 SUBROUTINE nlo_band_transition_prepare(energies, width, rate1, rate2, relaxation)
56 REAL(dp), INTENT(IN) :: energies(:), width, rate1, rate2
57 TYPE(nlo_band_transition_type), INTENT(INOUT) :: relaxation
58
59 INTEGER :: iband, jband, nband
60 REAL(dp) :: difference, gaussian
61
62 IF (.NOT. all(ieee_is_finite(energies)) .OR. .NOT. ieee_is_finite(width) .OR. &
63 .NOT. ieee_is_finite(rate1) .OR. .NOT. ieee_is_finite(rate2) .OR. &
64 width <= 0.0_dp .OR. rate1 <= 0.0_dp .OR. rate2 < rate1) THEN
65 cpabort('Invalid NLO band-transition relaxation parameters.')
66 END IF
67 IF (ALLOCATED(relaxation%pair_rate)) DEALLOCATE (relaxation%pair_rate)
68 IF (ALLOCATED(relaxation%energies)) DEALLOCATE (relaxation%energies)
69 ALLOCATE (relaxation%energies(SIZE(energies)))
70 relaxation%energies(:) = energies
71 relaxation%width = width
72 relaxation%rate_difference = rate1 - rate2
73 CALL nlo_gaussian_quadrature(relaxation%integration_points, relaxation%integration_weights)
74 nband = SIZE(energies)
75 cpassert(nband >= 2)
76 ALLOCATE (relaxation%pair_rate(nband, nband))
77 DO jband = 1, nband
78 DO iband = 1, nband
79 difference = energies(iband) - energies(jband)
80 gaussian = 0.0_dp
81 IF (width >= abs(difference)/26.0_dp) gaussian = exp(-(difference/width)**2)
82 relaxation%pair_rate(iband, jband) = rate1 + (rate2 - rate1)*(1.0_dp - gaussian)
83 END DO
84 END DO
85 END SUBROUTINE nlo_band_transition_prepare
86
87! **************************************************************************************************
88!> \brief Return the central relaxation rate for one band pair.
89!> \param relaxation Prepared band transition state
90!> \param iband First band index
91!> \param jband Second band index
92!> \return Central damping rate of the selected band pair
93! **************************************************************************************************
94 FUNCTION nlo_band_transition_rate(relaxation, iband, jband) RESULT(rate)
95 TYPE(nlo_band_transition_type), INTENT(IN) :: relaxation
96 INTEGER, INTENT(IN) :: iband, jband
97 REAL(dp) :: rate
98
99 cpassert(ALLOCATED(relaxation%pair_rate))
100 cpassert(iband >= 1)
101 cpassert(iband <= SIZE(relaxation%pair_rate, 1))
102 cpassert(jband >= 1)
103 cpassert(jband <= SIZE(relaxation%pair_rate, 2))
104 rate = relaxation%pair_rate(iband, jband)
105 END FUNCTION nlo_band_transition_rate
106
107! **************************************************************************************************
108!> \brief Sum relaxation corrections for one complete Cartesian Taylor grade.
109!> \param relaxation Prepared band transition state
110!> \param hamiltonian Hamiltonian Taylor coefficients in the band basis
111!> \param density Physical Taylor coefficients; only lower grades are read
112!> \param grade Requested total Cartesian derivative order, between one and four
113!> \param correction Corrections of this grade in nlo_derivative_indices order
114!> \note For Y_l=(ad_H−w z_l)⁻¹ρ and R_l,α=−Σ_{0<β≤α}[H_β,Y_l,α−β],
115!> Y_l,α=(ρ_α+R_l,α)/(Δε−w z_l). Only grades below the requested grade
116!> are needed in R_l,α. Reconstruct them for one contour point, accumulate
117!> all corrections of the requested grade, then reuse the workspace.
118!> No band-sized array carries a contour-point dimension. At grade four,
119!> 20 lower-grade matrices replace 35 matrices for each of 96 points.
120! **************************************************************************************************
121 SUBROUTINE nlo_band_transition_correction(relaxation, hamiltonian, density, grade, correction)
122 TYPE(nlo_band_transition_type), INTENT(IN) :: relaxation
123 COMPLEX(dp), INTENT(IN) :: hamiltonian(:, :, :), density(:, :, :)
124 INTEGER, INTENT(IN) :: grade
125 COMPLEX(dp), INTENT(OUT) :: correction(:, :, :)
126
127 COMPLEX(dp) :: weight
128 COMPLEX(dp), ALLOCATABLE :: inverse(:, :), lower_density(:, :, :), &
129 matrix_term(:, :), remainder(:, :)
130 INTEGER :: alpha(3, nlo_n_derivatives), ia, iband, ibeta, igamma, ipoint, jband, nband, &
131 ncoeff, nlower, partner(nlo_n_derivatives, nlo_n_derivatives)
132
133 cpassert(grade >= 1 .AND. grade <= 4)
134 cpassert(ALLOCATED(relaxation%pair_rate))
135 nband = SIZE(relaxation%pair_rate, 1)
136 nlower = nlo_derivative_count(grade - 1)
137 ncoeff = nlo_derivative_count(grade)
138 cpassert(SIZE(hamiltonian, 1) == nband)
139 cpassert(SIZE(hamiltonian, 2) == nband)
140 cpassert(SIZE(hamiltonian, 3) >= ncoeff)
141 cpassert(SIZE(density, 1) == nband)
142 cpassert(SIZE(density, 2) == nband)
143 cpassert(SIZE(density, 3) >= nlower)
144 cpassert(SIZE(correction, 1) == nband)
145 cpassert(SIZE(correction, 2) == nband)
146 cpassert(SIZE(correction, 3) == ncoeff - nlower)
147 ALLOCATE (inverse(nband, nband), lower_density(nband, nband, nlower), &
148 remainder(nband, nband), matrix_term(nband, nband))
149 CALL nlo_derivative_indices(alpha)
150 partner = 0
151 DO ia = 2, ncoeff
152 DO ibeta = 2, ia
153 partner(ibeta, ia) = derivatives_index(alpha, alpha(:, ia) - alpha(:, ibeta))
154 END DO
155 END DO
156 correction = cmplx(0.0_dp, 0.0_dp, dp)
157 DO ipoint = 1, SIZE(relaxation%integration_points)
158 DO jband = 1, nband
159 DO iband = 1, nband
160 inverse(iband, jband) = 1.0_dp/ &
161 (relaxation%energies(iband) - relaxation%energies(jband) - &
162 relaxation%width*relaxation%integration_points(ipoint))
163 END DO
164 END DO
165 weight = relaxation%width*relaxation%integration_weights(ipoint)
166 DO ia = 1, ncoeff
167 remainder = cmplx(0.0_dp, 0.0_dp, dp)
168 DO ibeta = 2, ia
169 igamma = partner(ibeta, ia)
170 IF (igamma == 0) cycle
171 matrix_term(:, :) = matmul(hamiltonian(:, :, ibeta), lower_density(:, :, igamma))
172 remainder(:, :) = remainder - matrix_term
173 matrix_term(:, :) = matmul(lower_density(:, :, igamma), hamiltonian(:, :, ibeta))
174 remainder(:, :) = remainder + matrix_term
175 END DO
176 remainder(:, :) = remainder*inverse
177 IF (ia <= nlower) THEN
178 lower_density(:, :, ia) = density(:, :, ia)*inverse + remainder
179 ELSE
180 correction(:, :, ia - nlower) = correction(:, :, ia - nlower) + weight*remainder
181 END IF
182 END DO
183 END DO
184 correction = cmplx(relaxation%rate_difference, 0.0_dp, dp)*correction
185 END SUBROUTINE nlo_band_transition_correction
186
187! **************************************************************************************************
188!> \brief Generate integration points and weights for the Gaussian matrix function.
189!> \param points Complex contour integration points
190!> \param weights Weights for the complex contour integration
191!> \note f(x)=exp(-x²) equals the difference of Cauchy integrals on the
192!> lines Im(z)=±h. Along each line, f(x±ih)=exp(h²)exp(-x²)exp(∓2ixh).
193!> Eigenvalues of the Hermite Jacobi matrix are quadrature nodes; the
194!> squared first-row eigenvector entries determine quadrature weights.
195!> The numerical rule uses 48 nodes per line at height h=2.5. These
196!> choices resolve f and its first four derivatives to about 2e-14
197!> scaled absolute error in checks over −10≤x≤10; they are not model
198!> parameters. Points and weights belong to the calling transition state.
199! **************************************************************************************************
200 SUBROUTINE nlo_gaussian_quadrature(points, weights)
201 COMPLEX(dp), ALLOCATABLE, INTENT(OUT) :: points(:), weights(:)
202
203 INTEGER, PARAMETER :: n_hermite = 48
204 REAL(dp), PARAMETER :: height = 2.5_dp
205
206 COMPLEX(dp) :: factor
207 INTEGER :: info, ipoint
208 REAL(dp) :: jacobi(n_hermite, n_hermite), &
209 nodes(n_hermite), quadrature_weight, &
210 work(3*n_hermite), x
211
212 ALLOCATE (points(2*n_hermite), weights(2*n_hermite))
213 jacobi = 0.0_dp
214 DO ipoint = 1, n_hermite - 1
215 jacobi(ipoint, ipoint + 1) = sqrt(real(ipoint, dp)/2.0_dp)
216 jacobi(ipoint + 1, ipoint) = jacobi(ipoint, ipoint + 1)
217 END DO
218 CALL dsyev('V', 'U', n_hermite, jacobi, n_hermite, nodes, work, SIZE(work), info)
219 IF (info /= 0) cpabort('NLO Gaussian contour quadrature failed.')
220 DO ipoint = 1, n_hermite
221 x = nodes(ipoint)
222 quadrature_weight = sqrt(pi)*jacobi(1, ipoint)**2
223 factor = quadrature_weight*exp(height**2)/(2.0_dp*pi*gaussi)
224 points(ipoint) = cmplx(x, -height, dp)
225 points(ipoint + n_hermite) = cmplx(x, height, dp)
226 weights(ipoint) = -factor*exp(2.0_dp*gaussi*x*height)
227 weights(ipoint + n_hermite) = factor*exp(-2.0_dp*gaussi*x*height)
228 END DO
229 END SUBROUTINE nlo_gaussian_quadrature
230
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 pi
complex(kind=dp), parameter, public gaussi
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.