(git:e8f5963)
Loading...
Searching...
No Matches
floquet_utils.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 Floquet stuff
10!> \par History
11!> \author Shridhar Shanbhag (27.01.2026)
12! **************************************************************************************************
14 USE cell_types, ONLY: cell_type,&
18 USE cp_cfm_types, ONLY: cp_cfm_create,&
25 USE cp_dbcsr_api, ONLY: dbcsr_p_type
26 USE cp_files, ONLY: close_file,&
28 USE kinds, ONLY: default_string_length,&
29 dp
33 USE kpoint_types, ONLY: get_kpoint_info,&
37 USE mathconstants, ONLY: gaussi,&
38 pi,&
39 z_one,&
40 z_zero
41 USE mathlib, ONLY: geeig_right,&
44 USE physcon, ONLY: evolt
48 USE qs_mo_types, ONLY: get_mo_set,&
52 USE util, ONLY: sort
53#include "./base/base_uses.f90"
54
55 IMPLICIT NONE
56
57 PRIVATE
58
59 CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'floquet_utils'
60
61 ! Public subroutines
62 PUBLIC :: build_floquet_matrix, &
69
70CONTAINS
71
72! **************************************************************************************************
73!> \brief ...
74!> \param qs_env ...
75!> \param xkp ...
76!> \param e_k ...
77!> \param de_dk ...
78! **************************************************************************************************
79 SUBROUTINE calculate_epsilon_derivative(qs_env, xkp, e_k, de_dk)
80 TYPE(qs_environment_type), POINTER :: qs_env
81 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :) :: xkp
82 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :, :), &
83 OPTIONAL :: e_k
84 REAL(kind=dp), ALLOCATABLE, &
85 DIMENSION(:, :, :, :), OPTIONAL :: de_dk
86
87 CHARACTER(LEN=*), PARAMETER :: routinen = 'calculate_epsilon_derivative'
88
89 COMPLEX(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: c_dh_c, c_ds_c, c_k, dh_dk_i, ds_dk_i, &
90 h_k, s_k
91 INTEGER :: handle, i_dir, ikp, ispin, n, n_img_all, &
92 n_spin, nao, nkp
93 INTEGER, DIMENSION(:, :), POINTER :: index_to_cell_all
94 INTEGER, DIMENSION(:, :, :), POINTER :: cell_to_index_all
95 LOGICAL :: present_dedk, present_ek
96 REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: eigenvals
97 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :, :, :) :: h_rs, s_rs
98 REAL(kind=dp), DIMENSION(3, 3) :: hmat
99 TYPE(cell_type), POINTER :: cell
100 TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: matrix_ks_kp, matrix_s_kp
101 TYPE(kpoint_type), POINTER :: kpoints_all, kpoints_scf
102 TYPE(mo_set_type), DIMENSION(:), POINTER :: mos
103 TYPE(mp_para_env_type), POINTER :: para_env
104 TYPE(neighbor_list_set_p_type), DIMENSION(:), &
105 POINTER :: sab_all
106
107 CALL timeset(routinen, handle)
108
109 present_ek = PRESENT(e_k) ! calculate band energies, ε_k for all kpoints xkp
110 present_dedk = PRESENT(de_dk) ! calculate derivative, ∇_k ε_k of band energies for all kpoints xkp
111
112 IF (.NOT. (present_ek .OR. present_dedk)) cpabort("Subroutine needs either e_k or de_dk")
113
114 CALL get_qs_env(qs_env, &
115 matrix_ks_kp=matrix_ks_kp, &
116 matrix_s_kp=matrix_s_kp, &
117 sab_all=sab_all, &
118 cell=cell, &
119 kpoints=kpoints_scf, &
120 para_env=para_env, &
121 mos=mos)
122
123 CALL get_mo_set(mo_set=mos(1), nao=nao)
124 CALL get_cell(cell=cell, h=hmat)
125
126 n_spin = SIZE(matrix_ks_kp, 1)
127 nkp = SIZE(xkp, 2)
128
129 ! create kpoint environment kpoints_all which contains all neighbor cells R
130 ! without considering any lattice symmetry
131 NULLIFY (kpoints_all)
132 CALL kpoint_create(kpoints_all)
133 CALL kpoint_init_cell_index(kpoints_all, sab_all, para_env, n_img_all)
134 CALL get_kpoint_info(kpoints_all, cell_to_index=cell_to_index_all, index_to_cell=index_to_cell_all)
135
136 ALLOCATE (s_rs(1, nao, nao, n_img_all), h_rs(n_spin, nao, nao, n_img_all), source=0.0_dp)
137
138 ! Convert real-space dbcsr matrices into arrays
139 CALL replicate_rs_matrices(matrix_s_kp, kpoints_scf, s_rs, cell_to_index_all)
140 CALL replicate_rs_matrices(matrix_ks_kp, kpoints_scf, h_rs, cell_to_index_all)
141
142 IF (present_dedk) ALLOCATE (de_dk(n_spin, nkp, 3, nao), source=0.0_dp)
143 IF (present_ek) ALLOCATE (e_k(n_spin, nkp, nao), source=0.0_dp)
144
145!$OMP PARALLEL DEFAULT(NONE) &
146!$OMP PRIVATE(ikp, ispin, S_k, H_k, eigenvals, C_k, dS_dk_i, dH_dk_i, C_dS_C, C_dH_C) &
147!$OMP SHARED(nao, n_spin, de_dk, e_k, present_ek, present_dedk, &
148!$OMP nkp, xkp, S_rs, H_rs, index_to_cell_all, hmat)
149 IF (present_dedk) ALLOCATE (ds_dk_i(nao, nao), c_ds_c(nao, nao), &
150 dh_dk_i(nao, nao), c_dh_c(nao, nao), source=z_zero)
151 ALLOCATE (c_k(nao, nao), s_k(nao, nao), h_k(nao, nao), source=z_zero)
152 ALLOCATE (eigenvals(nao), source=0.0_dp)
153!$OMP DO COLLAPSE(2)
154 DO ispin = 1, n_spin
155 DO ikp = 1, nkp
156
157 ! S^R -> S(k), H^R -> H(k)
158 s_k = 0
159 h_k = 0
160 CALL rs_to_kp(s_rs(1, :, :, :), s_k, index_to_cell_all, xkp(:, ikp))
161 CALL rs_to_kp(h_rs(ispin, :, :, :), h_k, index_to_cell_all, xkp(:, ikp))
162
163 ! Diagonalize H(k)C(k) = S(k)C(k)ε(k)
164 CALL geeig_right(h_k, s_k, eigenvals, c_k)
165 IF (present_ek) e_k(ispin, ikp, :) = eigenvals(:)
166
167 IF (present_dedk) THEN
168 ! Evaluate the derivatives using
169 ! ∇ ε_k = C^H(k) ∇ H_k C(k) - ε_k C^H(k) ∇ S_k C(k)
170 DO i_dir = 1, 3
171 CALL rs_to_kp(s_rs(1, :, :, :), ds_dk_i, index_to_cell_all, xkp(:, ikp), i_dir, hmat)
172 CALL rs_to_kp(h_rs(ispin, :, :, :), dh_dk_i, index_to_cell_all, xkp(:, ikp), i_dir, hmat)
173
174 CALL gemm_square(c_k, 'C', ds_dk_i, 'N', c_k, 'N', c_ds_c)
175 CALL gemm_square(c_k, 'C', dh_dk_i, 'N', c_k, 'N', c_dh_c)
176
177 DO n = 1, nao
178 de_dk(ispin, ikp, i_dir, n) = dble(c_dh_c(n, n)) - dble(eigenvals(n)*c_ds_c(n, n))
179 END DO
180 END DO
181 END IF
182 END DO
183 END DO
184!$OMP END DO
185 IF (present_dedk) DEALLOCATE (ds_dk_i, c_ds_c, dh_dk_i, c_dh_c)
186 DEALLOCATE (s_k, h_k, c_k, eigenvals)
187!$OMP END PARALLEL
188 DEALLOCATE (s_rs, h_rs)
189 CALL kpoint_release(kpoints_all)
190
191 CALL timestop(handle)
192
193 END SUBROUTINE calculate_epsilon_derivative
194
195! **************************************************************************************************
196!> \brief ...
197!> \param qs_env ...
198!> \param xkp ...
199!> \param momentum ...
200! **************************************************************************************************
201 SUBROUTINE build_momentum_matrix(qs_env, xkp, momentum)
202 TYPE(qs_environment_type), POINTER :: qs_env
203 REAL(kind=dp), DIMENSION(3) :: xkp
204 COMPLEX(KIND=dp), ALLOCATABLE, &
205 DIMENSION(:, :, :, :) :: momentum
206
207 CHARACTER(LEN=*), PARAMETER :: routinen = 'build_momentum_matrix'
208
209 COMPLEX(KIND=dp), ALLOCATABLE, &
210 DIMENSION(:, :, :, :, :) :: dipole
211 INTEGER :: handle, i, i_dir, ispin, j, n_spin, nao
212 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :) :: xkp1
213 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :, :) :: e_k
214 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :, :, :) :: de_dk
215 TYPE(dft_control_type), POINTER :: dft_control
216 TYPE(mo_set_type), DIMENSION(:), POINTER :: mos
217
218 CALL timeset(routinen, handle)
219
220 ! We calculate momentum matrix elements p_nm = <ψ_n|-iħ∇_r|ψ_m>
221 ! p_nm = <u_n|(ħk - iħ∇_r)|u_m>
222 ! p_nm = i d_nm (ε_n - ε_m) + ∇_k ε_n δ_nm
223
224 NULLIFY (dft_control)
225 CALL get_qs_env(qs_env, dft_control=dft_control, mos=mos)
226 CALL get_mo_set(mo_set=mos(1), nao=nao)
227
228 ALLOCATE (xkp1(3, 1), source=0.0_dp)
229 xkp1(:, 1) = xkp(:)
230 CALL calculate_epsilon_derivative(qs_env, xkp1, e_k, de_dk)
231 n_spin = dft_control%nspins
232 CALL qs_moment_kpoints_deep(qs_env, xkp1, dipole)
233
234!$OMP PARALLEL DEFAULT(NONE) &
235!$OMP PRIVATE(ispin, i_dir, i, j) &
236!$OMP SHARED(nao, n_spin, momentum, dipole, e_k, de_dk)
237!$OMP DO COLLAPSE(4)
238 DO ispin = 1, n_spin
239 DO i_dir = 1, 3
240 DO i = 1, nao
241 DO j = 1, nao
242 IF (j == i) THEN
243 momentum(ispin, i_dir, i, j) = de_dk(ispin, 1, i_dir, i)
244 ELSE
245 momentum(ispin, i_dir, i, j) = gaussi*(e_k(ispin, 1, i) - e_k(ispin, 1, j))* &
246 dipole(ispin, 1, i_dir, i, j)
247 END IF
248 END DO
249 END DO
250 END DO
251 END DO
252!$OMP END DO
253!$OMP END PARALLEL
254 DEALLOCATE (xkp1, dipole, e_k, de_dk)
255
256 CALL timestop(handle)
257 END SUBROUTINE build_momentum_matrix
258
259! **************************************************************************************************
260!> \brief ...
261!> \param qs_env ...
262!> \param bs_env ...
263!> \param xkp ...
264!> \param ispin ...
265!> \param off_diag_m ...
266! **************************************************************************************************
267 SUBROUTINE build_off_diagonal_matrix(qs_env, bs_env, xkp, ispin, off_diag_m)
268 TYPE(qs_environment_type), POINTER :: qs_env
269 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
270 REAL(kind=dp), DIMENSION(3) :: xkp
271 INTEGER :: ispin
272 COMPLEX(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: off_diag_m
273
274 CHARACTER(LEN=*), PARAMETER :: routinen = 'build_off_diagonal_matrix'
275
276 COMPLEX(KIND=dp), ALLOCATABLE, &
277 DIMENSION(:, :, :, :) :: momentum
278 COMPLEX(KIND=dp), DIMENSION(3) :: efactor
279 INTEGER :: handle, i, i_dir, j, n_spin, nao
280 REAL(kind=dp) :: amplitude, omega
281 REAL(kind=dp), DIMENSION(3) :: e_vec, phi, polarisation
282 TYPE(mo_set_type), DIMENSION(:), POINTER :: mos
283
284 CALL timeset(routinen, handle)
285
286 ! Builds the matrix that occupies the off diagonal blocks in the Floquet Matrix H_F
287
288 polarisation(:) = bs_env%floquet_polarisation(:)
289 IF (sqrt(sum(polarisation**2)) < epsilon(0.0_dp)) THEN
290 cpabort("Invalid (too small) polarisation vector specified for POLARISATION_PUMP")
291 END IF
292
293 amplitude = bs_env%floquet_amplitude
294 e_vec(:) = amplitude*polarisation
295 phi(:) = pi*bs_env%floquet_phi(:)
296 omega = bs_env%floquet_omega
297 n_spin = bs_env%n_spin
298
299 CALL get_qs_env(qs_env, mos=mos)
300 CALL get_mo_set(mo_set=mos(1), nao=nao)
301 ALLOCATE (momentum(n_spin, 3, nao, nao), source=z_zero)
302 CALL build_momentum_matrix(qs_env, xkp, momentum)
303
304 ! E_factor(α) = (i E(α) exp(i·φ(α)))/(2ω) where α = x,y,z
305 DO i_dir = 1, 3
306 efactor(i_dir) = gaussi*e_vec(i_dir)*cmplx(dcos(phi(i_dir)), dsin(phi(i_dir)), kind=dp)/(2*omega)
307 END DO
308
309 DO i_dir = 1, 3
310 DO i = 1, nao
311 DO j = 1, nao
312 off_diag_m(i, j) = off_diag_m(i, j) + &
313 momentum(ispin, i_dir, i, j)*efactor(i_dir)
314 END DO
315 END DO
316 END DO
317 DEALLOCATE (momentum)
318
319 CALL timestop(handle)
320
321 END SUBROUTINE build_off_diagonal_matrix
322
323! **************************************************************************************************
324!> \brief ...
325!> \param qs_env ...
326!> \param bs_env ...
327!> \param xkp ...
328!> \param ispin ...
329!> \param f_index ...
330!> \param diag_e ...
331! **************************************************************************************************
332 SUBROUTINE build_diagonal_matrix(qs_env, bs_env, xkp, ispin, f_index, diag_e)
333 TYPE(qs_environment_type), POINTER :: qs_env
334 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
335 REAL(kind=dp), DIMENSION(3) :: xkp
336 INTEGER :: ispin, f_index
337 COMPLEX(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: diag_e
338
339 CHARACTER(LEN=*), PARAMETER :: routinen = 'build_diagonal_matrix'
340
341 INTEGER :: handle, i, n_spin, nao
342 REAL(kind=dp) :: omega
343 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :) :: xkp1
344 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :, :) :: e_k
345 TYPE(mo_set_type), DIMENSION(:), POINTER :: mos
346
347 CALL timeset(routinen, handle)
348
349 ! Builds the matrix that occupies the off diagonal blocks in the Floquet Matrix H_F
350
351 omega = bs_env%floquet_omega
352 n_spin = bs_env%n_spin
353
354 CALL get_qs_env(qs_env, mos=mos)
355 CALL get_mo_set(mo_set=mos(1), nao=nao)
356 ALLOCATE (xkp1(3, 1), source=0.0_dp)
357 xkp1(:, 1) = xkp(:)
358 CALL calculate_epsilon_derivative(qs_env, xkp1, e_k)
359
360 DO i = 1, nao
361 diag_e(i, i) = e_k(ispin, 1, i) + f_index*omega
362 END DO
363 DEALLOCATE (xkp1, e_k)
364 CALL timestop(handle)
365
366 END SUBROUTINE build_diagonal_matrix
367
368! **************************************************************************************************
369!> \brief ...
370!> \param qs_env ...
371!> \param bs_env ...
372!> \param xkp ...
373!> \param ispin ...
374!> \param floquet_matrix ...
375! **************************************************************************************************
376 SUBROUTINE build_floquet_matrix(qs_env, bs_env, xkp, ispin, floquet_matrix)
377 TYPE(qs_environment_type), POINTER :: qs_env
378 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
379 REAL(kind=dp), DIMENSION(3) :: xkp
380 INTEGER :: ispin
381 TYPE(cp_cfm_type) :: floquet_matrix
382
383 CHARACTER(LEN=*), PARAMETER :: routinen = 'build_floquet_matrix'
384
385 COMPLEX(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: conj_off_diag_m, diag_e, off_diag_m
386 INTEGER :: f_index, handle, i, i_f, max_f_index, &
387 n_fbands, n_spin, nao
388 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :) :: xkp1
389 TYPE(mo_set_type), DIMENSION(:), POINTER :: mos
390
391 CALL timeset(routinen, handle)
392
393 CALL get_qs_env(qs_env, &
394 mos=mos)
395 CALL get_mo_set(mo_set=mos(1), nao=nao)
396 max_f_index = bs_env%max_floquet_index
397 n_fbands = 1 + 2*max_f_index
398 n_spin = bs_env%n_spin
399
400 ! Creates the floquet matrix H_F by placing the diagonal and off diagonal blocks
401
402 ALLOCATE (xkp1(3, 1), source=0.0_dp)
403 ALLOCATE (diag_e(nao, nao), source=z_zero)
404 ALLOCATE (off_diag_m(nao, nao), source=z_zero)
405 ALLOCATE (conj_off_diag_m(nao, nao), source=z_zero)
406 xkp1(:, 1) = xkp(:)
407 CALL build_off_diagonal_matrix(qs_env, bs_env, xkp, ispin, off_diag_m)
408 conj_off_diag_m(:, :) = conjg(transpose(off_diag_m(:, :)))
409
410 floquet_matrix%local_data(:, :) = z_zero
411 DO i = 1, n_fbands
412 i_f = 1 + (i - 1)*nao
413 f_index = i - max_f_index - 1
414 CALL build_diagonal_matrix(qs_env, bs_env, xkp, ispin, f_index, diag_e)
415 CALL cp_cfm_set_submatrix(floquet_matrix, diag_e, i_f, i_f)
416 IF (i > 1) THEN
417 CALL cp_cfm_set_submatrix(floquet_matrix, off_diag_m, i_f, i_f - nao)
418 CALL cp_cfm_set_submatrix(floquet_matrix, conj_off_diag_m, i_f - nao, i_f)
419 END IF
420 END DO
421 DEALLOCATE (diag_e, off_diag_m, conj_off_diag_m, xkp1)
422
423 CALL timestop(handle)
424 END SUBROUTINE build_floquet_matrix
425
426! **************************************************************************************************
427!> \brief ...
428!> \param qs_env ...
429!> \param bs_env ...
430!> \param cfm_eigenvectors ...
431! **************************************************************************************************
432 SUBROUTINE check_floquet_conversion(qs_env, bs_env, cfm_eigenvectors)
433 TYPE(qs_environment_type), POINTER :: qs_env
434 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
435 TYPE(cp_cfm_type) :: cfm_eigenvectors
436
437 CHARACTER(LEN=*), PARAMETER :: routinen = 'check_floquet_conversion'
438
439 COMPLEX(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: vector_block_0, vector_block_1
440 INTEGER :: handle, max_f_index, nao, start_row_0, &
441 start_row_1
442 TYPE(mo_set_type), DIMENSION(:), POINTER :: mos
443
444 CALL timeset(routinen, handle)
445
446 CALL get_qs_env(qs_env, mos=mos)
447 CALL get_mo_set(mo_set=mos(1), nao=nao)
448
449 max_f_index = bs_env%max_floquet_index
450
451 start_row_0 = 1 + nao*max_f_index
452 start_row_1 = 1 + nao*(max_f_index + 1)
453
454 ALLOCATE (vector_block_0(3*nao, nao), vector_block_1(3*nao, nao), source=z_zero)
455 CALL cp_cfm_get_submatrix(cfm_eigenvectors, vector_block_0, start_row_0, start_row_0)
456 CALL cp_cfm_get_submatrix(cfm_eigenvectors, vector_block_1, start_row_1, start_row_1)
457 IF (bs_env%eps_floquet > 0) THEN
458 IF (abs(maxval(abs(vector_block_0)) - maxval(abs(vector_block_1))) > bs_env%eps_floquet) THEN
459 cpabort("FLOQUET DIAGONALIZATION DID NOT CONVERGE. MAX_FLOQUET_INDEX TOO SMALL")
460 END IF
461 END IF
462 DEALLOCATE (vector_block_0, vector_block_1)
463 CALL timestop(handle)
464
465 END SUBROUTINE check_floquet_conversion
466
467! **************************************************************************************************
468!> \brief ...
469!> \param qs_env ...
470!> \param bs_env ...
471!> \param floquet_matrix ...
472!> \param a_k ...
473! **************************************************************************************************
474 SUBROUTINE calculate_floquet_spectral_function(qs_env, bs_env, floquet_matrix, a_k)
475 TYPE(qs_environment_type), POINTER :: qs_env
476 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
477 TYPE(cp_cfm_type) :: floquet_matrix
478 REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: a_k
479
480 CHARACTER(LEN=*), PARAMETER :: routinen = 'calculate_floquet_spectral_function'
481
482 COMPLEX(KIND=dp) :: diag
483 COMPLEX(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: g00
484 INTEGER :: handle, i, i_e, max_f_index, n_e, nao, &
485 start_row_g00
486 REAL(kind=dp) :: broad, e_min, energy, energy_step, mu
487 TYPE(cp_cfm_type) :: g_r
488 TYPE(mo_set_type), DIMENSION(:), POINTER :: mos
489
490 CALL timeset(routinen, handle)
491
492 CALL get_qs_env(qs_env, mos=mos)
493
494 CALL get_mo_set(mo_set=mos(1), mu=mu, nao=nao)
495
496 broad = bs_env%broadening_floquet
497 energy_step = bs_env%energy_step_floquet
498 e_min = mu - bs_env%energy_window_floquet
499 max_f_index = bs_env%max_floquet_index
500 n_e = SIZE(a_k)
501 start_row_g00 = 1 + nao*max_f_index
502
503 ALLOCATE (g00(nao, nao))
504 CALL cp_cfm_create(g_r, floquet_matrix%matrix_struct, set_zero=.true.)
505
506 DO i_e = 1, n_e
507 energy = e_min + i_e*energy_step
508 diag = energy + gaussi*broad/2.0_dp
509 CALL cp_cfm_set_all(g_r, z_zero, diag)
510 CALL cp_cfm_scale_and_add(z_one, g_r, -z_one, floquet_matrix)
511 CALL cp_cfm_lu_invert(g_r)
512 g00(:, :) = 0.0_dp
513 CALL cp_cfm_get_submatrix(g_r, g00, start_row_g00, start_row_g00)
514 a_k(i_e) = -aimag(sum([(g00(i, i), i=1, nao)]))/pi
515 END DO
516
517 DEALLOCATE (g00)
518 CALL cp_cfm_release(g_r)
519
520 CALL timestop(handle)
521
523
524! **************************************************************************************************
525!> \brief ...
526!> \param qs_env ...
527!> \param bs_env ...
528!> \param ispin ...
529!> \param ikp_for_file ...
530!> \param xkp ...
531!> \param eigenvalues ...
532! **************************************************************************************************
533 SUBROUTINE write_quasi_energy(qs_env, bs_env, ispin, ikp_for_file, xkp, eigenvalues)
534 TYPE(qs_environment_type), POINTER :: qs_env
535 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
536 INTEGER :: ispin, ikp_for_file
537 REAL(kind=dp), DIMENSION(3) :: xkp
538 REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: eigenvalues
539
540 CHARACTER(LEN=*), PARAMETER :: routinen = 'write_quasi_energy'
541
542 CHARACTER(LEN=default_string_length) :: fname
543 INTEGER :: handle, i, j, n, nao, nkp_start, qunit
544 INTEGER, ALLOCATABLE, DIMENSION(:) :: indices, work
545 REAL(kind=dp) :: fbz_max, fbz_min, omega, qe
546 REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: quasi_energies
547 TYPE(mo_set_type), DIMENSION(:), POINTER :: mos
548
549 CALL timeset(routinen, handle)
550
551 CALL get_qs_env(qs_env, mos=mos)
552 CALL get_mo_set(mo_set=mos(1), nao=nao)
553
554 nkp_start = bs_env%nkp_only_DOS
555 omega = bs_env%floquet_omega
556 fbz_max = omega/2.0_dp
557 fbz_min = -omega/2.0_dp
558
559 n = SIZE(eigenvalues)
560 ALLOCATE (indices(nao), work(nao), quasi_energies(nao))
561 indices(:) = [(i, i=1, nao)]
562 DO i = 1, nao
563 DO j = 1, n
564 IF (any(indices == j)) cycle
565 IF (abs(eigenvalues(j)) < abs(eigenvalues(indices(i)))) indices(i) = j
566 END DO
567 END DO
568 CALL sort(indices, nao, work)
569
570 quasi_energies(:) = eigenvalues(indices(:))
571
572 IF (bs_env%para_env%is_source()) THEN
573 WRITE (fname, "(2A)") trim(bs_env%floquet_qe_file), ".bs"
574 IF (ikp_for_file == 1) THEN
575 CALL open_file(trim(fname), unit_number=qunit, file_status="REPLACE", &
576 file_action="WRITE")
577 ELSE
578 CALL open_file(trim(fname), unit_number=qunit, file_status="OLD", &
579 file_action="WRITE", file_position="APPEND")
580 END IF
581
582 WRITE (qunit, "(A)") "# Quasi-energies obtained by diagonalising the Floquet Hamiltonian"
583 WRITE (qunit, "(A)") "# (in units of eV, folded to Floquet Brillouin zone)"
584 WRITE (qunit, "(A,I0,T10,A,I0,A,T24,3(1X,F14.8))") &
585 "# Spin ", ispin, " Point ", ikp_for_file, ": ", xkp(1:3)
586 WRITE (qunit, "(A)") "# Floquet band Quasi-energy [eV]"
587 DO i = 1, nao
588 qe = quasi_energies(i)
589 WRITE (qunit, "(I8,F21.8)") i, qe*evolt
590 END DO
591 CALL close_file(qunit)
592 END IF
593 DEALLOCATE (indices, work, quasi_energies)
594
595 CALL timestop(handle)
596
597 END SUBROUTINE write_quasi_energy
598! **************************************************************************************************
599!> \brief ...
600!> \param qs_env ...
601!> \param bs_env ...
602!> \param ispin ...
603!> \param ikp_for_file ...
604!> \param xkp ...
605!> \param a_k ...
606! **************************************************************************************************
607 SUBROUTINE write_floquet_spectral_function(qs_env, bs_env, ispin, ikp_for_file, xkp, a_k)
608 TYPE(qs_environment_type), POINTER :: qs_env
609 TYPE(post_scf_bandstructure_type), POINTER :: bs_env
610 INTEGER :: ispin, ikp_for_file
611 REAL(kind=dp), DIMENSION(3) :: xkp
612 REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: a_k
613
614 CHARACTER(LEN=*), PARAMETER :: routinen = 'write_floquet_spectral_function'
615
616 CHARACTER(LEN=default_string_length) :: fname
617 INTEGER :: handle, i_e, n_e, nkp_start, wunit
618 REAL(kind=dp) :: e_min, energy, energy_step, mu
619 TYPE(mo_set_type), DIMENSION(:), POINTER :: mos
620
621 CALL timeset(routinen, handle)
622
623 CALL get_qs_env(qs_env, mos=mos)
624
625 CALL get_mo_set(mo_set=mos(1), mu=mu)
626
627 energy_step = bs_env%energy_step_floquet
628 e_min = mu - bs_env%energy_window_floquet
629 n_e = SIZE(a_k)
630 nkp_start = bs_env%nkp_only_DOS
631
632 IF (bs_env%para_env%is_source()) THEN
633 WRITE (fname, "(2A)") trim(bs_env%floquet_dos_file), ".out"
634 IF (ikp_for_file == 1) THEN
635 CALL open_file(trim(fname), unit_number=wunit, file_status="REPLACE", &
636 file_action="WRITE")
637 ELSE
638 CALL open_file(trim(fname), unit_number=wunit, file_status="OLD", &
639 file_action="WRITE", file_position="APPEND")
640 END IF
641
642 WRITE (wunit, "(A)") ωπω"# Floquet Density of States: D(,k) = -1/*Im[Tr_KS(G^R(,k))]"
643 WRITE (wunit, "(A,I0,T10,A,I0,A,T24,3(1X,F14.8))") &
644 "# Spin ", ispin, " Point ", ikp_for_file, ": ", xkp(1:3)
645 WRITE (wunit, "(A)") ω"#Energy-E_F (eV) A(,k) = DOS (1/eV)"
646 DO i_e = 1, n_e
647 energy = e_min + i_e*energy_step
648 WRITE (wunit, "(2X,2G13.4)") energy*evolt, a_k(i_e)/evolt
649 END DO
650 CALL close_file(wunit)
651 END IF
652
653 CALL timestop(handle)
654
656
657END MODULE floquet_utils
Handles all functions related to the CELL.
Definition cell_types.F:15
subroutine, public get_cell(cell, alpha, beta, gamma, deth, orthorhombic, abc, periodic, h, h_inv, symmetry_id, tag)
Get informations about a simulation cell.
Definition cell_types.F:210
Basic linear algebra operations for complex full matrices.
subroutine, public cp_cfm_scale_and_add(alpha, matrix_a, beta, matrix_b)
Scale and add two BLACS matrices (a = alpha*a + beta*b).
subroutine, public cp_cfm_lu_invert(matrix, info_out)
Inverts a matrix using LU decomposition. The input matrix will be overwritten.
Represents a complex full matrix distributed on many processors.
subroutine, public cp_cfm_get_submatrix(fm, target_m, start_row, start_col, n_rows, n_cols, transpose)
Extract a sub-matrix from the full matrix: op(target_m)(1:n_rows,1:n_cols) = fm(start_row:start_row+n...
subroutine, public cp_cfm_release(matrix)
Releases a full matrix.
subroutine, public cp_cfm_create(matrix, matrix_struct, name, nrow, ncol, set_zero)
Creates a new full matrix with the given structure.
subroutine, public cp_cfm_set_submatrix(matrix, new_values, start_row, start_col, n_rows, n_cols, alpha, beta, transpose)
Set a sub-matrix of the full matrix: matrix(start_row:start_row+n_rows,start_col:start_col+n_cols) = ...
subroutine, public cp_cfm_set_all(matrix, alpha, beta)
Set all elements of the full matrix to alpha. Besides, set all diagonal matrix elements to beta (if g...
Defines control structures, which contain the parameters and the settings for the DFT-based calculati...
Utility routines to open and close files. Tracking of preconnections.
Definition cp_files.F:16
subroutine, public open_file(file_name, file_status, file_form, file_action, file_position, file_pad, unit_number, debug, skip_get_unit_number, file_access)
Opens the requested file using a free unit number.
Definition cp_files.F:311
subroutine, public close_file(unit_number, file_status, keep_preconnection)
Close an open file given by its logical unit number. Optionally, keep the file and unit preconnected.
Definition cp_files.F:122
Floquet stuff.
subroutine, public build_momentum_matrix(qs_env, xkp, momentum)
...
subroutine, public write_floquet_spectral_function(qs_env, bs_env, ispin, ikp_for_file, xkp, a_k)
...
subroutine, public check_floquet_conversion(qs_env, bs_env, cfm_eigenvectors)
...
subroutine, public calculate_floquet_spectral_function(qs_env, bs_env, floquet_matrix, a_k)
...
subroutine, public calculate_epsilon_derivative(qs_env, xkp, e_k, de_dk)
...
subroutine, public build_floquet_matrix(qs_env, bs_env, xkp, ispin, floquet_matrix)
...
subroutine, public write_quasi_energy(qs_env, bs_env, ispin, ikp_for_file, xkp, eigenvalues)
...
Defines the basic variable types.
Definition kinds.F:23
integer, parameter, public dp
Definition kinds.F:34
integer, parameter, public default_string_length
Definition kinds.F:57
Implements transformations from k-space to R-space for Fortran array matrices.
subroutine, public rs_to_kp(rs_real, ks_complex, index_to_cell, xkp, deriv_direction, hmat)
Integrate RS matrices (stored as Fortran array) into a kpoint matrix at given kp.
subroutine, public replicate_rs_matrices(rs_dbcsr_in, kpoint_in, rs_array_out, cell_to_index_out)
Convert dbcsr matrices representing operators in real-space image cells to arrays.
Routines needed for kpoint calculation.
subroutine, public kpoint_init_cell_index(kpoint, sab_nl, para_env, nimages)
Generates the mapping of cell indices and linear RS index CELL (0,0,0) is always mapped to index 1.
Types and basic routines needed for a kpoint calculation.
subroutine, public get_kpoint_info(kpoint, kp_scheme, nkp_grid, kp_shift, symmetry, verbose, full_grid, use_real_wfn, eps_geo, parallel_group_size, kp_range, nkp, xkp, wkp, para_env, blacs_env_all, para_env_kp, para_env_inter_kp, blacs_env, kp_env, kp_aux_env, mpools, iogrp, nkp_groups, kp_dist, cell_to_index, index_to_cell, sab_nl, sab_nl_nosym, inversion_symmetry_only, symmetry_backend, symmetry_reduction_method, gamma_centered)
Retrieve information from a kpoint environment.
subroutine, public kpoint_release(kpoint)
Release a kpoint environment, deallocate all data.
subroutine, public kpoint_create(kpoint)
Create a kpoint environment.
Definition of mathematical constants and functions.
real(kind=dp), parameter, public pi
complex(kind=dp), parameter, public z_one
complex(kind=dp), parameter, public gaussi
complex(kind=dp), parameter, public z_zero
Collection of simple mathematical functions and subroutines.
Definition mathlib.F:15
subroutine, public diag(n, a, d, v)
Diagonalize matrix a. The eigenvalues are returned in vector d and the eigenvectors are returned in m...
Definition mathlib.F:1503
subroutine, public geeig_right(a_in, b_in, eigenvalues, eigenvectors)
Solve the generalized eigenvalue equation for complex matrices A*v = B*v*λ
Definition mathlib.F:2034
Interface to the message passing library MPI.
Definition of physical constants:
Definition physcon.F:68
real(kind=dp), parameter, public evolt
Definition physcon.F:183
subroutine, public get_qs_env(qs_env, atomic_kind_set, qs_kind_set, cell, super_cell, cell_ref, use_ref_cell, kpoints, dft_control, mos, sab_orb, sab_all, qmmm, qmmm_periodic, mimic, sac_ae, sac_ppl, sac_lri, sap_ppnl, sab_vdw, sab_scp, sap_oce, sab_lrc, sab_se, sab_xtbe, sab_tbe, sab_core, sab_xb, sab_xtb_pp, sab_xtb_nonbond, sab_almo, sab_kp, sab_kp_nosym, sab_cneo, particle_set, energy, force, matrix_h, matrix_h_im, matrix_ks, matrix_ks_im, matrix_vxc, run_rtp, rtp, matrix_h_kp, matrix_h_im_kp, matrix_ks_kp, matrix_ks_im_kp, matrix_vxc_kp, kinetic_kp, matrix_s_kp, matrix_w_kp, matrix_s_ri_aux_kp, matrix_s, matrix_s_ri_aux, matrix_w, matrix_p_mp2, matrix_p_mp2_admm, rho, rho_xc, pw_env, ewald_env, ewald_pw, active_space, mpools, input, para_env, blacs_env, scf_control, rel_control, kinetic, qs_charges, vppl, xcint_weights, rho_core, rho_nlcc, rho_nlcc_g, ks_env, ks_qmmm_env, wf_history, scf_env, local_particles, local_molecules, distribution_2d, dbcsr_dist, molecule_kind_set, molecule_set, subsys, cp_subsys, oce, local_rho_set, rho_atom_set, task_list, task_list_soft, rho0_atom_set, rho0_mpole, rhoz_set, rhoz_cneo_set, ecoul_1c, rho0_s_rs, rho0_s_gs, rhoz_cneo_s_rs, rhoz_cneo_s_gs, do_kpoints, has_unit_metric, requires_mo_derivs, mo_derivs, mo_loc_history, nkind, natom, nelectron_total, nelectron_spin, efield, neighbor_list_id, linres_control, xas_env, virial, cp_ddapc_env, cp_ddapc_ewald, outer_scf_history, outer_scf_ihistory, x_data, et_coupling, dftb_potential, results, se_taper, se_store_int_env, se_nddo_mpole, se_nonbond_env, admm_env, lri_env, lri_density, exstate_env, ec_env, harris_env, dispersion_env, gcp_env, vee, rho_external, external_vxc, mask, mp2_env, bs_env, kg_env, wanniercentres, atprop, ls_scf_env, do_transport, transport_env, v_hartree_rspace, s_mstruct_changed, rho_changed, potential_changed, forces_up_to_date, mscfg_env, almo_scf_env, gradient_history, variable_history, embed_pot, spin_embed_pot, polar_env, mos_last_converged, eeq, rhs, do_rixs, tb_tblite)
Get the QUICKSTEP environment.
Definition and initialisation of the mo data type.
Definition qs_mo_types.F:22
subroutine, public get_mo_set(mo_set, maxocc, homo, lfomo, nao, nelectron, n_el_f, nmo, eigenvalues, occupation_numbers, mo_coeff, mo_coeff_b, uniform_occupation, kts, mu, flexible_electron_count)
Get the components of a MO set data structure.
Calculates the moment integrals <a|r^m|b> and <a|r x d/dr|b>
Definition qs_moments.F:14
subroutine, public qs_moment_kpoints_deep(qs_env, xkp, dipole, rcc, berry_c, do_parallel)
Calculates the dipole moments and berry curvature for periodic systems for kpoints.
Define the neighbor list data types and the corresponding functionality.
All kind of helpful little routines.
Definition util.F:14
Type defining parameters related to the simulation cell.
Definition cell_types.F:60
Represent a complex full matrix.
Contains information about kpoints.
stores all the informations relevant to an mpi environment