(git:7fc1fe1)
Loading...
Searching...
No Matches
nlo_bz_integration.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!> \author Jan Wilhelm, with help from ChatGPT
9
12 USE ieee_arithmetic, ONLY: ieee_is_finite
13 USE kinds, ONLY: dp
15 USE machine, ONLY: m_flush,&
17 USE mathconstants, ONLY: gaussi,&
18 twopi
26 USE nlo_types, ONLY: nlo_type
27 USE physcon, ONLY: evolt
28#include "../base/base_uses.f90"
29
30 IMPLICIT NONE
31
32 PRIVATE
33
34 CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'nlo_integration'
35
36 PUBLIC :: nlo_bz_integration
37
38CONTAINS
39
40! **************************************************************************************************
41!> \brief Integrate the density-response current over the Brillouin zone.
42!> \param nlo_env NLO settings and data for the calculation
43! **************************************************************************************************
44 SUBROUTINE nlo_bz_integration(nlo_env)
45 TYPE(nlo_type), INTENT(INOUT) :: nlo_env
46
47 CHARACTER(len=*), PARAMETER :: routinen = 'nlo_bz_integration'
48
49 COMPLEX(dp), ALLOCATABLE :: curvature(:, :, :), matrix_term(:, :)
50 INTEGER :: handle, i_case, ia, ic, ik, iw, nocc, &
51 pair, spin
52 LOGICAL :: zero_output
53 REAL(kind=dp) :: energy_ev(5), k(3), local_projection, &
54 occ_factor, omega(5)
55
56 CALL timeset(routinen, handle)
57
58 CALL allocate_nlo_quantities(nlo_env)
59 ALLOCATE (curvature(nlo_env%n_bands, nlo_env%n_bands, 3), &
60 matrix_term(nlo_env%n_bands, nlo_env%n_bands))
61
62 nlo_env%projection_error = 0.0_dp
63 nlo_env%min_direct_gap = huge(1.0_dp)
64 nlo_env%progress_total = 1 + (nlo_env%n_kpoints - 1)/nlo_env%para_env%num_pe
65 IF (nlo_env%progress_total > huge(nlo_env%progress_total)/nlo_env%n_spin) THEN
66 cpabort('NLO work count exceeds integer indexing.')
67 END IF
68 nlo_env%progress_total = nlo_env%n_spin*nlo_env%progress_total
69 nlo_env%progress_done = 0
70 nlo_env%progress_next = 1
71 nlo_env%progress_start = m_walltime()
72
73 DO spin = 1, nlo_env%n_spin
74 IF (nlo_env%mos(spin)%maxocc <= 0.0_dp) THEN
75 cpabort('NONLINEAR_OPTICS requires positive band occupation.')
76 END IF
77 occ_factor = nlo_env%mos(spin)%maxocc
78 nocc = nint(real(nlo_env%mos(spin)%nelectron, kind=dp)/occ_factor)
79 IF (nocc < 1 .OR. nocc >= nlo_env%n_bands .OR. &
80 abs(nocc*occ_factor - nlo_env%mos(spin)%nelectron) > 1.e-8_dp) THEN
81 cpabort('NLO needs integer occupied-band count and empty bands.')
82 END IF
83 nlo_env%occupied = 0
84 nlo_env%occupied(1:nocc) = 1
85 DO ik = 1, nlo_env%n_kpoints
86 IF (mod(ik - 1, nlo_env%para_env%num_pe) /= nlo_env%para_env%mepos) cycle
87 k = real([mod(ik - 1, nlo_env%k_mesh(1)), &
88 mod((ik - 1)/nlo_env%k_mesh(1), nlo_env%k_mesh(2)), &
89 (ik - 1)/(nlo_env%k_mesh(1)*nlo_env%k_mesh(2))], kind=dp)/ &
90 REAL(nlo_env%k_mesh, kind=dp)
91 ! Build H(k), S(k), d(k) and their analytic Cartesian k derivatives.
92 CALL ao_derivatives_at_k(nlo_env, k, spin)
93 CALL hermitize_derivatives(nlo_env%hamiltonian_derivatives, local_projection)
94
95 nlo_env%projection_error = max(nlo_env%projection_error, local_projection)
96 IF (local_projection > 1.e-5_dp) THEN
97 cpabort('NLO Hamiltonian images are not Hermitian.')
98 END IF
99 ! X = S^(-1/2) orthonormalizes the AO basis; U diagonalizes X H X here.
100 ! Express all operator derivatives in this same eigenvector basis U.
101 CALL nlo_ao_to_band_derivatives( &
102 nlo_env%overlap_derivatives, nlo_env%hamiltonian_derivatives, &
103 nlo_env%position_derivatives, &
104 nlo_env%occupied, nlo_env%energies, nlo_env%band_hamiltonian_derivatives, &
105 nlo_env%band_connection_derivatives, nlo_env%rho0_derivatives, &
106 nlo_env%velocity, &
107 active_grade=nlo_env%order)
108
109 nlo_env%min_direct_gap = min( &
110 nlo_env%min_direct_gap, &
111 nlo_env%energies(nocc + 1) - nlo_env%energies(nocc))
112 ! F_ca = d_c A_a - d_a A_c - i[A_c,A_a], reused for every frequency.
113 DO ic = 1, 2
114 DO ia = ic + 1, 3
115 pair = (ic - 1)*(6 - ic)/2 + ia - ic
116 curvature(:, :, pair) = &
117 nlo_env%band_connection_derivatives(:, :, ia, ic + 1) - &
118 nlo_env%band_connection_derivatives(:, :, ic, ia + 1)
119 matrix_term(:, :) = matmul(nlo_env%band_connection_derivatives(:, :, ic, 1), &
120 nlo_env%band_connection_derivatives(:, :, ia, 1))
121 curvature(:, :, pair) = curvature(:, :, pair) - gaussi*matrix_term
122 matrix_term(:, :) = matmul(nlo_env%band_connection_derivatives(:, :, ia, 1), &
123 nlo_env%band_connection_derivatives(:, :, ic, 1))
124 curvature(:, :, pair) = curvature(:, :, pair) + gaussi*matrix_term
125 END DO
126 END DO
127 DO i_case = 1, nlo_env%n_frequency_combinations
128 CALL nlo_frequency_case(nlo_env%frequency, nlo_env%order, i_case, &
129 energy_ev, zero_output)
130 IF (zero_output) THEN
131 cpabort('Invalid NONLINEAR_OPTICS frequency case.')
132 END IF
133 omega = 0.0_dp
134 omega(1:nlo_env%order) = energy_ev(1:nlo_env%order)/evolt
135 ! Compute J_i^(n)(k) from rho^(n): -Tr[v_i rho^(n)] plus curvature current.
136 ! Each rho^(n) follows from lower orders at Omega = sum_j omega_j.
138 nlo_env%order, omega(1:nlo_env%order), nlo_env%energies, &
139 1.0_dp/nlo_env%t1_au, 1.0_dp/nlo_env%t2_au, &
140 nlo_env%transition_width_au, nlo_env%band_hamiltonian_derivatives, &
141 nlo_env%band_connection_derivatives, curvature, &
142 nlo_env%rho0_derivatives, &
143 nlo_env%velocity, &
144 nlo_env%current_flat, elements=nlo_env%elements)
145
146 ! Sum J_i^(n)(k) over spin and k; f_spin is the band occupation factor.
147 ! I_i^(n) = sum_(spin,k) f_spin J_i^(n)(k) / N_k.
148 nlo_env%current_spectrum(:, :, i_case) = &
149 nlo_env%current_spectrum(:, :, i_case) + &
150 occ_factor*nlo_env%current_flat/real(nlo_env%n_kpoints, kind=dp)
151 END DO
152 IF (nlo_env%para_env%mepos == 0) CALL report_nlo_progress(nlo_env)
153
154 END DO
155 END DO
156 CALL nlo_env%para_env%max(nlo_env%projection_error)
157 CALL nlo_env%para_env%min(nlo_env%min_direct_gap)
159 IF (iw > 0) THEN
160 WRITE (iw, '(T2,A,T69,F9.2,1X,A)') &
161 'NONLINEAR_OPTICS| Minimum occupied-empty gap:', &
162 nlo_env%min_direct_gap*evolt, 'eV'
163 END IF
164 CALL release_nlo_quantities(nlo_env)
165
166 CALL timestop(handle)
167
168 END SUBROUTINE nlo_bz_integration
169
170! **************************************************************************************************
171!> \brief Project all analytic Hamiltonian derivatives onto the Hermitian image subspace.
172!> \param derivatives AO Hamiltonian derivatives over lattice images
173!> \param relative_error Largest relative change from enforcing Hermiticity
174!> \note This linear projection commutes with all k derivatives.
175! **************************************************************************************************
176 SUBROUTINE hermitize_derivatives(derivatives, relative_error)
177 COMPLEX(dp), INTENT(INOUT) :: derivatives(:, :, :)
178 REAL(kind=dp), INTENT(OUT) :: relative_error
179
180 COMPLEX(dp) :: adjoint(size(derivatives, 1), size(derivatives, 2))
181 INTEGER :: ij
182 REAL(kind=dp) :: scale
183
184 relative_error = 0.0_dp
185 DO ij = 1, SIZE(derivatives, 3)
186 adjoint = conjg(transpose(derivatives(:, :, ij)))
187 scale = max(1.0_dp, maxval(abs(derivatives(:, :, ij))))
188 relative_error = max(relative_error, maxval(abs(derivatives(:, :, ij) - adjoint))/scale)
189 derivatives(:, :, ij) = 0.5_dp*(derivatives(:, :, ij) + adjoint)
190 END DO
191
192 END SUBROUTINE hermitize_derivatives
193
194! **************************************************************************************************
195!> \brief Fourier-transform AO H, S, and position matrices at one optical k point.
196!> \param nlo_env NLO settings and data for the calculation
197!> \param k Optical k point in fractional coordinates
198!> \param spin Spin channel of the converged SCF solution
199!> \note For X = H, S, or the AO position matrix d_a, and Cartesian k:
200!> dX(k)/dk_x = sum_R i R_x exp(i k·R) X(R).
201!> R is a real-space lattice vector. The input k uses fractional coordinates:
202!> k·R = 2 pi k_frac·R_int. Higher derivatives add factors i R_a;
203!> each stored Taylor coefficient is divided by its factorial.
204! **************************************************************************************************
205 SUBROUTINE ao_derivatives_at_k(nlo_env, k, spin)
206 TYPE(nlo_type), INTENT(INOUT) :: nlo_env
207 REAL(kind=dp), INTENT(IN) :: k(3)
208 INTEGER, INTENT(IN) :: spin
209
210 CHARACTER(len=*), PARAMETER :: routinen = 'ao_derivatives_at_k'
211
212 INTEGER :: alpha(3, nlo_n_derivatives), grade, &
213 handle, ia, ij, j, n, na, nh, ni
214 REAL(kind=dp) :: divisor
215
216 CALL timeset(routinen, handle)
217
218 associate(h_image => nlo_env%h_ao_R(spin, :, :, :), &
219 s_image => nlo_env%s_ao_R(1, :, :, :), &
220 moment_image => nlo_env%d_ao_R, &
221 image_cells => nlo_env%images%index_to_cell, &
222 hmat => nlo_env%cell%hmat, &
223 h_derivatives => nlo_env%hamiltonian_derivatives, &
224 s_derivatives => nlo_env%overlap_derivatives, &
225 moment_derivatives => nlo_env%position_derivatives)
226 h_derivatives = 0.0_dp
227 s_derivatives = 0.0_dp
228 moment_derivatives = 0.0_dp
229 n = SIZE(h_image, 1)
230 ni = SIZE(s_image, 3)
231 cpassert(n >= 2)
232 cpassert(SIZE(h_image, 2) == n)
233 cpassert(SIZE(h_image, 3) >= 1)
234 cpassert(SIZE(s_image, 1) == n)
235 cpassert(SIZE(s_image, 2) == n)
236 cpassert(ni >= 1)
237 cpassert(all(shape(moment_image) == [3, n, n, ni]))
238 cpassert(SIZE(h_image, 3) == ni)
239 cpassert(all(shape(image_cells) == [3, ni]))
240 nh = nlo_derivative_count(nlo_env%order)
241 na = nlo_derivative_count(nlo_env%order - 1)
242 cpassert(all(shape(h_derivatives) == [n, n, nh]))
243 cpassert(all(shape(s_derivatives) == [n, n, nh]))
244 cpassert(all(shape(moment_derivatives) == [n, n, 3, na]))
245 IF (.NOT. all(ieee_is_finite(h_image)) .OR. .NOT. all(ieee_is_finite(s_image)) .OR. &
246 .NOT. all(ieee_is_finite(moment_image)) .OR. &
247 .NOT. all(ieee_is_finite(k)) .OR. .NOT. all(ieee_is_finite(hmat))) THEN
248 cpabort('NONLINEAR_OPTICS numerical derivative construction failed.')
249 END IF
250 grade = nlo_env%order
251 cpassert(grade >= 2 .AND. grade <= 5)
252 CALL nlo_derivative_indices(alpha)
253 DO ij = 1, nlo_derivative_count(grade)
254 divisor = 1.0_dp
255 DO ia = 1, 3
256 DO j = 2, alpha(ia, ij)
257 divisor = divisor*real(j, kind=dp)
258 END DO
259 END DO
260 CALL rs_to_kp_multi_deriv(h_image, h_derivatives(:, :, ij), image_cells, k, &
261 alpha(:, ij), hmat)
262 CALL rs_to_kp_multi_deriv(s_image, s_derivatives(:, :, ij), image_cells, k, &
263 alpha(:, ij), hmat)
264 h_derivatives(:, :, ij) = h_derivatives(:, :, ij)/divisor
265 s_derivatives(:, :, ij) = s_derivatives(:, :, ij)/divisor
266 IF (sum(alpha(:, ij)) >= grade) cycle
267 DO ia = 1, 3
268 CALL rs_to_kp_multi_deriv(moment_image(ia, :, :, :), &
269 moment_derivatives(:, :, ia, ij), image_cells, k, &
270 alpha(:, ij), hmat)
271 moment_derivatives(:, :, ia, ij) = moment_derivatives(:, :, ia, ij)/divisor
272 END DO
273 END DO
274 IF (.NOT. all(ieee_is_finite(real(h_derivatives, kind=dp))) &
275 .OR. .NOT. all(ieee_is_finite(aimag(h_derivatives))) .OR. &
276 .NOT. all(ieee_is_finite(real(s_derivatives, kind=dp))) &
277 .OR. .NOT. all(ieee_is_finite(aimag(s_derivatives))) .OR. &
278 .NOT. all(ieee_is_finite(real(moment_derivatives, kind=dp))) .OR. &
279 .NOT. all(ieee_is_finite(aimag(moment_derivatives)))) THEN
280 cpabort('NONLINEAR_OPTICS numerical derivative construction failed.')
281 END IF
282
283 END associate
284
285 CALL timestop(handle)
286
287 END SUBROUTINE ao_derivatives_at_k
288
289! **************************************************************************************************
290!> \brief Convert AO operators to band matrices and build the equilibrium density.
291!> \param overlap AO overlap and its k derivatives
292!> \param hamiltonian AO Hamiltonian and its k derivatives
293!> \param moment AO position-matrix derivatives through one grade below the response order
294!> \param occupied One for an occupied band, zero for an empty band
295!> \param energies Band energies in Hartree at this k point
296!> \param band_h Hamiltonian derivatives in the eigenvector basis
297!> \param band_a Position connection derivatives in the eigenvector basis
298!> \param rho0 Equilibrium density and its k derivatives for unit occupation
299!> \param velocity Band velocity at this k point, in bohr per atomic time
300!> \param active_grade Highest derivative grade required for the response
301!> \note First X=S^(-1/2) makes the AO basis orthonormal. U diagonalizes
302!> X H X at this k point. The same U is applied to every k derivative
303!> of H and the position matrix, so no derivative of U is needed.
304!> Occupied bands then define rho0; field-driven densities are built later.
305! **************************************************************************************************
306 SUBROUTINE nlo_ao_to_band_derivatives(overlap, hamiltonian, moment, occupied, &
307 energies, band_h, band_a, rho0, velocity, &
308 active_grade)
309 COMPLEX(dp), DIMENSION(:, :, :), INTENT(IN) :: overlap, hamiltonian
310 COMPLEX(dp), INTENT(IN) :: moment(:, :, :, :)
311 INTEGER, INTENT(IN) :: occupied(:)
312 REAL(kind=dp), INTENT(OUT) :: energies(:)
313 COMPLEX(dp), INTENT(OUT) :: band_h(:, :, :), band_a(:, :, :, :), &
314 rho0(:, :, :), velocity(:, :, :)
315 INTEGER, INTENT(IN), OPTIONAL :: active_grade
316
317 CHARACTER(len=*), PARAMETER :: routinen = 'nlo_ao_to_band_derivatives'
318
319 COMPLEX(dp), ALLOCATABLE :: identity(:, :), matrix_term(:, :), &
320 orth_h(:, :, :), u(:, :)
321 COMPLEX(dp), ALLOCATABLE, DIMENSION(:, :, :, :) :: connection
322 INTEGER :: alpha(3, nlo_n_derivatives), grade, &
323 handle, ia, ideriv, ij, info, n, na, nh
324
325 CALL timeset(routinen, handle)
326
327 energies = 0.0_dp
328 band_h = 0.0_dp
329 band_a = 0.0_dp
330 rho0 = 0.0_dp
331 velocity = 0.0_dp
332 n = SIZE(energies)
333 cpassert(.NOT. (n < 2 .OR. SIZE(occupied) /= n))
334 grade = 5
335 IF (PRESENT(active_grade)) grade = active_grade
336 cpassert(grade >= 2 .AND. grade <= 5)
337 nh = nlo_derivative_count(grade)
338 na = nlo_derivative_count(grade - 1)
339 cpassert(all(shape(overlap) == [n, n, nh]))
340 cpassert(all(shape(hamiltonian) == [n, n, nh]))
341 cpassert(all(shape(moment) == [n, n, 3, na]))
342 cpassert(all(shape(band_h) == [n, n, nh]))
343 cpassert(all(shape(band_a) == [n, n, 3, na]))
344 cpassert(all(shape(rho0) == [n, n, nh]))
345 cpassert(all(shape(velocity) == [n, n, 3]))
346 ALLOCATE (connection(n, n, 3, na), identity(n, n), matrix_term(n, n), &
347 orth_h(n, n, nh), u(n, n))
348
349 CALL nlo_orthonormal_operator_derivatives(overlap, hamiltonian, moment, orth_h, &
350 connection, active_grade=grade)
351
352 identity = 0.0_dp
353 DO ij = 1, n
354 identity(ij, ij) = 1.0_dp
355 END DO
356
357 CALL projected_eigensystem(orth_h(:, :, 1), identity, energies, u, info)
358 IF (info /= 0) cpabort('NONLINEAR_OPTICS band eigensolver failed.')
359
360 DO ij = 1, nh
361 matrix_term(:, :) = matmul(orth_h(:, :, ij), u)
362 band_h(:, :, ij) = matmul(conjg(transpose(u)), matrix_term)
363 IF (ij > na) cycle
364 DO ia = 1, 3
365 matrix_term(:, :) = matmul(connection(:, :, ia, ij), u)
366 band_a(:, :, ia, ij) = matmul(conjg(transpose(u)), matrix_term)
367 END DO
368 END DO
369
370 CALL nlo_equilibrium_density_derivatives(energies, occupied, band_h, rho0, &
371 active_grade=grade)
372
373 CALL nlo_derivative_indices(alpha)
374 DO ia = 1, 3
375 ideriv = 0
376 DO ij = 1, nh
377 IF (alpha(ia, ij) == 1 .AND. sum(alpha(:, ij)) == 1) ideriv = ij
378 END DO
379 cpassert(ideriv /= 0)
380 matrix_term(:, :) = matmul(band_a(:, :, ia, 1), band_h(:, :, 1))
381 velocity(:, :, ia) = band_h(:, :, ideriv) - gaussi*matrix_term
382 matrix_term(:, :) = matmul(band_h(:, :, 1), band_a(:, :, ia, 1))
383 velocity(:, :, ia) = velocity(:, :, ia) + gaussi*matrix_term
384 END DO
385 IF (.NOT. all(ieee_is_finite(real(velocity, kind=dp))) .OR. &
386 .NOT. all(ieee_is_finite(aimag(velocity)))) THEN
387 cpabort('NONLINEAR_OPTICS numerical derivative construction failed.')
388 END IF
389
390 CALL timestop(handle)
391
392 END SUBROUTINE nlo_ao_to_band_derivatives
393
394! **************************************************************************************************
395!> \brief Analytic Cartesian mixed k derivative of a real-space AO matrix.
396!> \param rs_real Real-space matrix for every lattice image
397!> \param ks_complex Requested derivative in k space
398!> \param index_to_cell Integer lattice vector for each image
399!> \param xkp k point in reciprocal fractional coordinates
400!> \param deriv_orders Number of derivatives in Cartesian x, y, z
401!> \param hmat Direct-cell vectors as columns, in the same length units as k^-1
402!> \note The Fourier factor is exp(2πi k_frac dot R_int). Each Cartesian derivative
403!> contributes i R_cart. This avoids phase-sensitive finite differences.
404! **************************************************************************************************
405 SUBROUTINE rs_to_kp_multi_deriv(rs_real, ks_complex, index_to_cell, xkp, deriv_orders, hmat)
406 REAL(kind=dp), INTENT(IN) :: rs_real(:, :, :)
407 COMPLEX(dp), INTENT(OUT) :: ks_complex(:, :)
408 INTEGER, INTENT(IN) :: index_to_cell(:, :)
409 REAL(kind=dp), INTENT(IN) :: xkp(3)
410 INTEGER, INTENT(IN) :: deriv_orders(3)
411 REAL(kind=dp), INTENT(IN) :: hmat(3, 3)
412
413 COMPLEX(dp) :: factor
414 INTEGER :: i_axis, i_image, n_images
415 REAL(kind=dp) :: cell_index(3), cell_vector(3), phase
416
417 IF (any(deriv_orders < 0)) cpabort('Negative k derivative order requested.')
418 n_images = SIZE(rs_real, 3)
419 IF (n_images < 1) cpabort('No real-space lattice images supplied.')
420 IF (SIZE(index_to_cell, 1) /= 3 .OR. SIZE(index_to_cell, 2) /= n_images) THEN
421 cpabort('Real-space matrices and lattice-image indices are inconsistent.')
422 END IF
423 IF (SIZE(ks_complex, 1) /= SIZE(rs_real, 1) .OR. SIZE(ks_complex, 2) /= SIZE(rs_real, 2)) THEN
424 cpabort('Real-space and k-space matrix shapes are inconsistent.')
425 END IF
426 ks_complex = cmplx(0.0_dp, 0.0_dp, kind=dp)
427 DO i_image = 1, n_images
428 cell_index = real(index_to_cell(:, i_image), kind=dp)
429 cell_vector = matmul(hmat, cell_index)
430 phase = twopi*sum(xkp*cell_index)
431 factor = cmplx(cos(phase), sin(phase), kind=dp)
432 DO i_axis = 1, 3
433 factor = factor*cmplx(0.0_dp, cell_vector(i_axis), kind=dp)**deriv_orders(i_axis)
434 END DO
435 ks_complex = ks_complex + factor*rs_real(:, :, i_image)
436 END DO
437
438 END SUBROUTINE rs_to_kp_multi_deriv
439
440! **************************************************************************************************
441!> \brief Allocate the per-k matrices and rank-local frequency accumulators once.
442!> \param nlo_env NLO settings and data for the calculation
443! **************************************************************************************************
444 SUBROUTINE allocate_nlo_quantities(nlo_env)
445 TYPE(nlo_type), INTENT(INOUT) :: nlo_env
446
447 INTEGER :: na, nh
448
449 nh = nlo_derivative_count(nlo_env%order)
450 na = nlo_derivative_count(nlo_env%order - 1)
451 ALLOCATE (nlo_env%energies(nlo_env%n_bands))
452 ALLOCATE (nlo_env%occupied(nlo_env%n_bands))
453 ALLOCATE (nlo_env%hamiltonian_derivatives(nlo_env%n_bands, nlo_env%n_bands, nh))
454 ALLOCATE (nlo_env%overlap_derivatives(nlo_env%n_bands, nlo_env%n_bands, nh))
455 ALLOCATE (nlo_env%position_derivatives(nlo_env%n_bands, nlo_env%n_bands, 3, na))
456 ALLOCATE (nlo_env%band_hamiltonian_derivatives(nlo_env%n_bands, nlo_env%n_bands, nh))
457 ALLOCATE (nlo_env%band_connection_derivatives(nlo_env%n_bands, nlo_env%n_bands, 3, na))
458 ALLOCATE (nlo_env%rho0_derivatives(nlo_env%n_bands, nlo_env%n_bands, nh))
459 ALLOCATE (nlo_env%velocity(nlo_env%n_bands, nlo_env%n_bands, 3))
460 ALLOCATE (nlo_env%current_flat(3, 3**nlo_env%order))
461 ALLOCATE (nlo_env%current_spectrum(3, 3**nlo_env%order, nlo_env%n_frequency_combinations), &
462 source=(0.0_dp, 0.0_dp))
463
464 END SUBROUTINE allocate_nlo_quantities
465
466! **************************************************************************************************
467!> \brief Print completed spin/k tasks when the next percentage threshold is crossed.
468!> \param nlo_env NLO settings and data for the calculation
469! **************************************************************************************************
470 SUBROUTINE report_nlo_progress(nlo_env)
471 TYPE(nlo_type), INTENT(INOUT) :: nlo_env
472
473 REAL(kind=dp), PARAMETER :: &
474 marks(9) = [0.1_dp, 0.3_dp, 1.0_dp, 3.0_dp, 10.0_dp, 30.0_dp, 60.0_dp, 90.0_dp, 100.0_dp]
475
476 INTEGER :: iw
477 REAL(kind=dp) :: percent
478
479 nlo_env%progress_done = nlo_env%progress_done + 1
480 percent = 100.0_dp*real(nlo_env%progress_done, kind=dp)/real(nlo_env%progress_total, kind=dp)
481 cpassert(.NOT. (nlo_env%progress_next > SIZE(marks)))
482 IF (percent < marks(nlo_env%progress_next)) THEN
483 RETURN
484 END IF
485 iw = cp_logger_get_default_io_unit()
486 IF (iw > 0) THEN
487 IF (nlo_env%progress_total < 10000) THEN
488 WRITE (iw, '(T2,A,I0,A,I0,7X,F5.1,A,4X,A,T69,F10.2,1X,A)') &
489 'NONLINEAR_OPTICS| Progress: ', nlo_env%progress_done, ' / ', &
490 nlo_env%progress_total, percent, '%', 'Total time:', &
491 m_walltime() - nlo_env%progress_start, 's'
492 ELSE
493 WRITE (iw, '(T2,A,I0,A,I0,7X,F5.1,A)') &
494 'NONLINEAR_OPTICS| Progress: ', nlo_env%progress_done, ' / ', &
495 nlo_env%progress_total, percent, '%'
496 WRITE (iw, '(T2,A,T69,F10.2,1X,A)') &
497 'NONLINEAR_OPTICS| Total time:', m_walltime() - nlo_env%progress_start, 's'
498 END IF
499 CALL m_flush(iw)
500 END IF
501 DO WHILE (nlo_env%progress_next <= SIZE(marks))
502 IF (percent < marks(nlo_env%progress_next)) EXIT
503 nlo_env%progress_next = nlo_env%progress_next + 1
504 END DO
505
506 END SUBROUTINE report_nlo_progress
507
508! **************************************************************************************************
509!> \brief Free the per-k workspace after the MPI reduction and validation.
510!> \param nlo_env NLO settings and data for the calculation
511! **************************************************************************************************
512 SUBROUTINE release_nlo_quantities(nlo_env)
513 TYPE(nlo_type), INTENT(INOUT) :: nlo_env
514
515 DEALLOCATE (nlo_env%energies, nlo_env%occupied)
516 DEALLOCATE (nlo_env%hamiltonian_derivatives, nlo_env%overlap_derivatives)
517 DEALLOCATE (nlo_env%position_derivatives)
518 DEALLOCATE (nlo_env%band_hamiltonian_derivatives, nlo_env%band_connection_derivatives)
519 DEALLOCATE (nlo_env%rho0_derivatives, nlo_env%velocity, nlo_env%current_flat)
520
521 END SUBROUTINE release_nlo_quantities
522
523END MODULE nlo_integration
various routines to log and control the output. The idea is that decisions about where to log should ...
integer function, public cp_logger_get_default_io_unit(logger)
returns the unit nr for the ionode (-1 on all other processors) skips as well checks if the procs cal...
Defines the basic variable types.
Definition kinds.F:23
integer, parameter, public dp
Definition kinds.F:34
Finite projected-Hamiltonian current in a nonorthogonal, possibly spinor AO basis.
subroutine, public projected_eigensystem(h, s, energies, c, status)
Complete generalized eigensystem with a positive, well-conditioned AO metric.
Machine interface based on Fortran 2003 and POSIX.
Definition machine.F:17
subroutine, public m_flush(lunit)
flushes units if the &GLOBAL flag is set accordingly
Definition machine.F:127
real(kind=dp) function, public m_walltime()
returns time from a real-time clock, protected against rolling early/easily
Definition machine.F:144
Definition of mathematical constants and functions.
complex(kind=dp), parameter, public gaussi
real(kind=dp), parameter, public twopi
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.
subroutine, public nlo_orthonormal_operator_derivatives(overlap, hamiltonian, moment, orth_h, connection, active_grade)
Express H and the AO position matrix in an orthonormal AO basis.
subroutine, public nlo_equilibrium_density_derivatives(energies, occupied, hamiltonian, rho0, active_grade)
Derivatives of the equilibrium density matrix for filled Kohn-Sham bands.
subroutine, public nlo_bz_integration(nlo_env)
Integrate the density-response current over the Brillouin zone.
subroutine, public nlo_frequency_case(frequencies, order, i_case, energy_ev, zero_output)
Resolve one Cartesian-product case, preserving SAME_AS and MINUS_OF links.
Nonlinear optical environment: input parameters and data shared by calculation stages.
Definition nlo_types.F:10
Definition of physical constants:
Definition physcon.F:68
real(kind=dp), parameter, public evolt
Definition physcon.F:183