57#include "./base/base_uses.f90"
63 CHARACTER(len=*),
PARAMETER,
PRIVATE :: moduleN =
'floquet_utils'
68 INTEGER,
PARAMETER,
PRIVATE :: n_fm_work_copies = 8
93 SUBROUTINE calculate_epsilon_derivative(qs_env, xkp, e_k, de_dk, do_parallel)
94 TYPE(qs_environment_type),
POINTER :: qs_env
95 REAL(KIND=
dp),
ALLOCATABLE,
DIMENSION(:, :), &
97 REAL(KIND=
dp),
ALLOCATABLE,
DIMENSION(:, :, :), &
98 INTENT(OUT),
OPTIONAL :: e_k
99 REAL(KIND=
dp),
ALLOCATABLE, &
100 DIMENSION(:, :, :, :),
INTENT(OUT),
OPTIONAL :: de_dk
101 LOGICAL,
INTENT(IN),
OPTIONAL :: do_parallel
103 CHARACTER(LEN=*),
PARAMETER :: routineN =
'calculate_epsilon_derivative'
105 COMPLEX(KIND=dp),
ALLOCATABLE,
DIMENSION(:, :) :: C_dH_C, C_dS_C, C_k, dH_dk_i, dS_dk_i, &
107 INTEGER :: handle, i_dir, ikp, ispin, mepos, n, &
108 n_img_all, n_spin, nao, nkp, num_copy, &
110 INTEGER,
DIMENSION(:, :),
POINTER :: index_to_cell_all
111 INTEGER,
DIMENSION(:, :, :),
POINTER :: cell_to_index_all
112 LOGICAL :: my_do_parallel, present_dedk, present_ek
113 REAL(KIND=
dp),
ALLOCATABLE,
DIMENSION(:) :: eigenvals
114 REAL(KIND=
dp),
ALLOCATABLE,
DIMENSION(:, :, :, :) :: h_rs, s_rs
115 REAL(KIND=
dp),
DIMENSION(3, 3) :: hmat
116 TYPE(cell_type),
POINTER :: cell
117 TYPE(dbcsr_p_type),
DIMENSION(:, :),
POINTER :: matrix_ks_kp, matrix_s_kp
118 TYPE(kpoint_type),
POINTER :: kpoints_all, kpoints_scf
119 TYPE(mo_set_type),
DIMENSION(:),
POINTER :: mos
120 TYPE(mp_para_env_type),
POINTER :: para_env
121 TYPE(neighbor_list_set_p_type),
DIMENSION(:), &
124 CALL timeset(routinen, handle)
126 present_ek =
PRESENT(e_k)
127 present_dedk =
PRESENT(de_dk)
129 IF (.NOT. (present_ek .OR. present_dedk)) cpabort(
"Subroutine needs either e_k or de_dk")
131 my_do_parallel = .false.
132 IF (
PRESENT(do_parallel)) my_do_parallel = do_parallel
135 matrix_ks_kp=matrix_ks_kp, &
136 matrix_s_kp=matrix_s_kp, &
139 kpoints=kpoints_scf, &
146 n_spin =
SIZE(matrix_ks_kp, 1)
155 IF (my_do_parallel)
THEN
156 mepos = para_env%mepos
157 num_pe = para_env%num_pe
158 num_copy = ceiling(real(nkp)/num_pe)
163 NULLIFY (kpoints_all)
166 CALL get_kpoint_info(kpoints_all, cell_to_index=cell_to_index_all, index_to_cell=index_to_cell_all)
168 ALLOCATE (s_rs(1, nao, nao, n_img_all), h_rs(n_spin, nao, nao, n_img_all), source=0.0_dp)
174 IF (present_dedk)
ALLOCATE (de_dk(n_spin, num_copy, 3, nao), source=0.0_dp)
175 IF (present_ek)
ALLOCATE (e_k(n_spin, num_copy, nao), source=0.0_dp)
181 IF (present_dedk)
ALLOCATE (ds_dk_i(nao, nao), c_ds_c(nao, nao), &
182 dh_dk_i(nao, nao), c_dh_c(nao, nao), source=
z_zero)
183 ALLOCATE (c_k(nao, nao), s_k(nao, nao), h_k(nao, nao), source=
z_zero)
184 ALLOCATE (eigenvals(nao), source=0.0_dp)
188 IF (mod(ikp - 1, num_pe) /= mepos) cycle
193 CALL rs_to_kp(s_rs(1, :, :, :), s_k, index_to_cell_all, xkp(:, ikp))
194 CALL rs_to_kp(h_rs(ispin, :, :, :), h_k, index_to_cell_all, xkp(:, ikp))
198 IF (present_ek) e_k(ispin, ceiling(real(ikp)/num_pe), :) = eigenvals(:)
200 IF (present_dedk)
THEN
204 CALL rs_to_kp(s_rs(1, :, :, :), ds_dk_i, index_to_cell_all, xkp(:, ikp), i_dir, hmat)
205 CALL rs_to_kp(h_rs(ispin, :, :, :), dh_dk_i, index_to_cell_all, xkp(:, ikp), i_dir, hmat)
207 CALL gemm_square(c_k,
'C', ds_dk_i,
'N', c_k,
'N', c_ds_c)
208 CALL gemm_square(c_k,
'C', dh_dk_i,
'N', c_k,
'N', c_dh_c)
211 de_dk(ispin, ceiling(real(ikp)/num_pe), i_dir, n) = &
212 dble(c_dh_c(n, n)) - dble(eigenvals(n)*c_ds_c(n, n))
219 IF (present_dedk)
DEALLOCATE (ds_dk_i, c_ds_c, dh_dk_i, c_dh_c)
220 DEALLOCATE (s_k, h_k, c_k, eigenvals)
222 DEALLOCATE (s_rs, h_rs)
225 CALL timestop(handle)
227 END SUBROUTINE calculate_epsilon_derivative
236 SUBROUTINE build_momentum_matrix(e_k_kp_spin, de_dk_kp_spin, dipole_kp_spin, momentum)
237 REAL(KIND=
dp),
DIMENSION(:),
INTENT(IN) :: e_k_kp_spin
238 REAL(KIND=
dp),
DIMENSION(:, :),
INTENT(IN) :: de_dk_kp_spin
239 COMPLEX(KIND=dp),
DIMENSION(:, :, :),
INTENT(IN) :: dipole_kp_spin
240 COMPLEX(KIND=dp),
DIMENSION(:, :, :),
INTENT(OUT) :: momentum
242 CHARACTER(LEN=*),
PARAMETER :: routineN =
'build_momentum_matrix'
244 INTEGER :: handle, i, i_dir, j, nao
246 CALL timeset(routinen, handle)
248 nao =
SIZE(e_k_kp_spin)
262 momentum(i_dir, i, j) = de_dk_kp_spin(i_dir, i)
264 momentum(i_dir, i, j) =
gaussi*(e_k_kp_spin(i) - e_k_kp_spin(j))* &
265 dipole_kp_spin(i_dir, i, j)
273 CALL timestop(handle)
274 END SUBROUTINE build_momentum_matrix
284 SUBROUTINE build_off_diagonal_matrix(bs_env, e_k_kp_spin, de_dk_kp_spin, dipole_kp_spin, off_diag_m)
285 TYPE(post_scf_bandstructure_type),
POINTER :: bs_env
286 REAL(KIND=
dp),
DIMENSION(:),
INTENT(IN) :: e_k_kp_spin
287 REAL(KIND=
dp),
DIMENSION(:, :),
INTENT(IN) :: de_dk_kp_spin
288 COMPLEX(KIND=dp),
DIMENSION(:, :, :),
INTENT(IN) :: dipole_kp_spin
289 COMPLEX(KIND=dp),
DIMENSION(:, :),
INTENT(OUT) :: off_diag_m
291 CHARACTER(LEN=*),
PARAMETER :: routineN =
'build_off_diagonal_matrix'
293 COMPLEX(KIND=dp),
ALLOCATABLE,
DIMENSION(:, :, :) :: momentum
294 COMPLEX(KIND=dp),
DIMENSION(3) :: efactor
295 INTEGER :: handle, i, i_dir, j, nao
296 REAL(KIND=
dp) :: amplitude, omega
297 REAL(KIND=
dp),
DIMENSION(3) :: e_vec, phi, polarisation
299 CALL timeset(routinen, handle)
303 nao =
SIZE(e_k_kp_spin)
305 polarisation(:) = bs_env%floquet_polarisation(:)
306 IF (sqrt(sum(polarisation**2)) < epsilon(0.0_dp))
THEN
307 cpabort(
"Invalid (too small) polarisation vector specified for POLARISATION")
310 amplitude = bs_env%floquet_amplitude
311 e_vec(:) = amplitude*polarisation
312 phi(:) =
pi*bs_env%floquet_phi(:)
313 omega = bs_env%floquet_omega
315 ALLOCATE (momentum(3, nao, nao), source=
z_zero)
316 CALL build_momentum_matrix(e_k_kp_spin, de_dk_kp_spin, dipole_kp_spin, momentum)
320 efactor(i_dir) =
gaussi*e_vec(i_dir)*cmplx(cos(phi(i_dir)), sin(phi(i_dir)), kind=
dp)/(2*omega)
328 off_diag_m(i, j) = off_diag_m(i, j) + &
329 momentum(i_dir, i, j)*efactor(i_dir)
333 DEALLOCATE (momentum)
335 CALL timestop(handle)
337 END SUBROUTINE build_off_diagonal_matrix
346 SUBROUTINE build_diagonal_matrix(bs_env, e_k_kp_spin, f_index, diag_e)
347 TYPE(post_scf_bandstructure_type),
POINTER :: bs_env
348 REAL(KIND=
dp),
DIMENSION(:),
INTENT(IN) :: e_k_kp_spin
349 INTEGER,
INTENT(IN) :: f_index
350 COMPLEX(KIND=dp),
DIMENSION(:, :),
INTENT(OUT) :: diag_e
352 CHARACTER(LEN=*),
PARAMETER :: routineN =
'build_diagonal_matrix'
354 INTEGER :: handle, i, nao
355 REAL(KIND=
dp) :: omega
357 CALL timeset(routinen, handle)
360 nao =
SIZE(e_k_kp_spin)
361 omega = bs_env%floquet_omega
364 diag_e(i, i) = e_k_kp_spin(i) + f_index*omega
367 CALL timestop(handle)
369 END SUBROUTINE build_diagonal_matrix
383 CHARACTER(LEN=*),
PARAMETER :: routinen =
'build_floquet_matrix'
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, &
389 CALL timeset(routinen, handle)
391 nao = floquet_env%nao
392 max_f_index = floquet_env%max_f_index
393 n_fbands = 1 + 2*max_f_index
396 ALLOCATE (diag_e(nao, nao), source=
z_zero)
397 ALLOCATE (off_diag_m(nao, nao), source=
z_zero)
398 ALLOCATE (conj_off_diag_m(nao, nao), source=
z_zero)
400 CALL build_off_diagonal_matrix(bs_env, floquet_env%e_k_kp_spin, floquet_env%de_dk_kp_spin, &
401 floquet_env%dipole_kp_spin, off_diag_m)
402 conj_off_diag_m(:, :) = conjg(transpose(off_diag_m(:, :)))
404 floquet_matrix%local_data(:, :) =
z_zero
406 i_f = 1 + (i - 1)*nao
407 f_index = i - max_f_index - 1
408 CALL build_diagonal_matrix(bs_env, floquet_env%e_k_kp_spin, f_index, diag_e)
415 DEALLOCATE (diag_e, off_diag_m, conj_off_diag_m)
417 CALL timestop(handle)
434 INTEGER,
INTENT(IN) :: ispin, ikp
435 REAL(kind=
dp),
DIMENSION(:, :, :),
INTENT(IN) :: e_k
436 REAL(kind=
dp),
DIMENSION(:, :, :, :),
INTENT(IN) :: de_dk
437 COMPLEX(KIND=dp),
DIMENSION(:, :, :, :, :), &
441 CHARACTER(LEN=*),
PARAMETER :: routinen =
'distribute_floquet_kp_data'
443 INTEGER :: handle, loc_idx, local_src, owner
445 CALL timeset(routinen, handle)
448 owner = mod(ikp - 1, para_env%num_pe)
451 IF (para_env%mepos == owner) local_src = para_env_sub%mepos
452 CALL para_env_sub%max(local_src)
456 IF (para_env%mepos == owner)
THEN
457 loc_idx = ceiling(real(ikp)/para_env%num_pe)
458 floquet_env%e_k_kp_spin(:) = e_k(ispin, loc_idx, :)
459 floquet_env%de_dk_kp_spin(:, :) = de_dk(ispin, loc_idx, :, :)
460 floquet_env%dipole_kp_spin(:, :, :) = dipole(ispin, loc_idx, :, :, :)
462 CALL para_env_sub%bcast(floquet_env%e_k_kp_spin, local_src)
463 CALL para_env_sub%bcast(floquet_env%de_dk_kp_spin, local_src)
464 CALL para_env_sub%bcast(floquet_env%dipole_kp_spin, local_src)
466 CALL timestop(handle)
482 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :, :), &
484 REAL(kind=
dp),
ALLOCATABLE, &
485 DIMENSION(:, :, :, :),
INTENT(OUT) :: de_dk
486 COMPLEX(KIND=dp),
ALLOCATABLE, &
487 DIMENSION(:, :, :, :, :),
INTENT(OUT) :: dipole
489 CHARACTER(LEN=*),
PARAMETER :: routinen =
'compute_e_k_de_dk_dipole'
491 INTEGER :: handle, ikp, nkp_only_bs, nkp_start
492 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: xkp_all
494 CALL timeset(routinen, handle)
498 nkp_start = bs_env%nkp_only_DOS
499 nkp_only_bs = bs_env%nkp_only_bs
502 ALLOCATE (xkp_all(3, nkp_only_bs))
503 DO ikp = 1, nkp_only_bs
504 xkp_all(:, ikp) = bs_env%kpoints_DOS%xkp(1:3, nkp_start + ikp)
510 CALL calculate_epsilon_derivative(qs_env, xkp_all, e_k=e_k, de_dk=de_dk, do_parallel=.true.)
515 CALL timestop(handle)
524 FUNCTION find_ranks_per_node(para_env)
RESULT(ranks_per_node)
526 INTEGER :: ranks_per_node
531 ranks_per_node = max(1, node_comm%num_pe)
532 CALL node_comm%free()
534 END FUNCTION find_ranks_per_node
542 FUNCTION floquet_determine_subgroup_size(qs_env, bs_env)
RESULT(group_size)
545 INTEGER :: group_size
547 CHARACTER(LEN=*),
PARAMETER :: routinen =
'floquet_determine_subgroup_size'
549 INTEGER :: g_load, g_mem, handle, n_f_size, nao, &
550 nkp_only_bs, ranks_per_node, unit_nr
551 INTEGER(KIND=int_8) :: buffers, cached, memfree, memlikelyfree, &
552 memtotal, needed_bytes, slab, &
553 sreclaimable, usable_per_rank
554 REAL(kind=
dp) :: mem_fill_fraction
558 CALL timeset(routinen, handle)
560 CALL get_qs_env(qs_env, para_env=para_env, mos=mos)
563 unit_nr = bs_env%unit_nr
564 n_f_size = nao*(1 + 2*bs_env%max_floquet_index)
565 nkp_only_bs = bs_env%nkp_only_bs
566 mem_fill_fraction = bs_env%floquet_mem_fill_fraction
578 CALL m_memory_details(memtotal, memfree, buffers, cached, slab, sreclaimable, memlikelyfree)
579 ranks_per_node = find_ranks_per_node(para_env)
580 usable_per_rank = int(mem_fill_fraction*real(memfree,
dp),
int_8)/int(ranks_per_node,
int_8)
584 needed_bytes = 16_int_8*int(n_fm_work_copies,
int_8)*int(n_f_size,
int_8)**2
586 IF (usable_per_rank <= 0_int_8)
THEN
588 g_mem = para_env%num_pe
591 g_mem = int(min((needed_bytes + usable_per_rank - 1_int_8)/usable_per_rank, &
592 int(para_env%num_pe,
int_8)))
595 IF (g_mem > para_env%num_pe) cpwarn(
"Total Memory Likely Insufficient, process may be killed")
598 g_load = para_env%num_pe/max(nkp_only_bs, 1)
600 group_size = max(g_mem, g_load)
601 group_size = min(group_size, para_env%num_pe)
602 group_size = max(group_size, 1)
603 CALL para_env%max(group_size)
605 IF (unit_nr > 0)
THEN
606 WRITE (unit_nr,
'(T2,A)')
""
607 WRITE (unit_nr,
'(T2,A,T66,I15)')
"FLOQUET MEMORY | Detected MPI ranks per node:", ranks_per_node
608 WRITE (unit_nr,
'(T2,A,T66,I12,A)')
"FLOQUET MEMORY | Free memory per rank:", &
609 (memlikelyfree/int(ranks_per_node,
int_8))/1048576_int_8,
" MB"
610 WRITE (unit_nr,
'(T2,A,T66,I12,A)')
"FLOQUET MEMORY | Usable per rank (reserve applied):", &
611 usable_per_rank/1048576_int_8,
" MB"
612 WRITE (unit_nr,
'(T2,A,T66,I15)')
"FLOQUET MEMORY | Floquet copies needed:", n_fm_work_copies
613 WRITE (unit_nr,
'(T2,A,T66,I12,A)')
"FLOQUET MEMORY | Total Floquet working set:", &
614 needed_bytes/1048576_int_8,
" MB"
615 WRITE (unit_nr,
'(T2,A,T66,I12,A)')
"FLOQUET MEMORY | Floquet working set per rank:", &
616 (needed_bytes/int(max(group_size, 1),
int_8))/1048576_int_8,
" MB"
617 WRITE (unit_nr,
'(T2,A,T66,I15)')
"FLOQUET MEMORY | Memory floor (ranks/subgroup):", g_mem
618 WRITE (unit_nr,
'(T2,A,T66,I15)')
"FLOQUET MEMORY | K-point floor (ranks/subgroup):", g_load
619 WRITE (unit_nr,
'(T2,A,T66,I15)')
"FLOQUET MEMORY | Chosen MPI ranks per subgroup:", group_size
622 CALL timestop(handle)
623 END FUNCTION floquet_determine_subgroup_size
636 group_distribution, ngroups)
641 INTEGER,
ALLOCATABLE,
DIMENSION(:),
INTENT(OUT) :: group_distribution
642 INTEGER,
INTENT(OUT) :: ngroups
644 CHARACTER(LEN=*),
PARAMETER :: routinen =
'make_floquet_subgroups'
646 INTEGER :: group_size, handle, n_spin, nkp_only_bs, &
650 CALL timeset(routinen, handle)
653 unit_nr = bs_env%unit_nr
654 nkp_only_bs = bs_env%nkp_only_bs
655 n_spin = bs_env%n_spin
659 group_size = floquet_determine_subgroup_size(qs_env, bs_env)
661 IF (nkp_only_bs < para_env%num_pe)
THEN
662 stride_kp = para_env%num_pe/group_size
666 ALLOCATE (group_distribution(0:para_env%num_pe - 1))
667 ALLOCATE (para_env_sub)
668 CALL para_env_sub%from_split(comm=para_env, ngroups=ngroups, &
669 group_distribution=group_distribution, &
670 subgroup_min_size=group_size, stride=stride_kp)
671 IF (unit_nr > 0)
THEN
672 WRITE (unit_nr,
'(T2,A,T66,I15)')
"FLOQUET MEMORY | Subgroup rank stride:", stride_kp
673 WRITE (unit_nr,
'(T2,A,T66,I15)')
"FLOQUET MEMORY | Number of subgroups:", ngroups
674 WRITE (unit_nr,
'(/,T2,A,I5,A,I1,A)')
"FLOQUET CALCULATIONS PROGRESS OUT OF", nkp_only_bs, &
675 " K-POINTS AND ", n_spin,
" SPINS"
678 NULLIFY (blacs_env_sub)
681 CALL timestop(handle)
695 CHARACTER(LEN=*),
PARAMETER :: routinen =
'floquet_sector_weights'
697 COMPLEX(KIND=dp),
ALLOCATABLE,
DIMENSION(:, :) :: v_block
698 INTEGER :: handle, max_f_index, n_f_size, nao
700 CALL timeset(routinen, handle)
702 nao = floquet_env%nao
703 max_f_index = floquet_env%max_f_index
704 n_f_size = floquet_env%n_f_size
706 ALLOCATE (v_block(nao, n_f_size))
710 floquet_env%w0(:) = sum(abs(v_block)**2, dim=1)
713 floquet_env%wE(:) = 0.0_dp
714 IF (max_f_index >= 1)
THEN
716 floquet_env%wE(:) = sum(abs(v_block)**2, dim=1)
719 floquet_env%wE(:) = floquet_env%wE(:) + sum(abs(v_block)**2, dim=1)
725 cpassert(abs(sum(floquet_env%w0) - real(nao,
dp)) < 1.0e-6_dp*real(nao,
dp))
727 CALL timestop(handle)
741 CHARACTER(LEN=*),
PARAMETER :: routinen =
'check_floquet_convergence'
743 CHARACTER(LEN=default_string_length) :: msg
745 REAL(kind=
dp) :: leak
748 CALL timeset(routinen, handle)
751 IF (bs_env%max_floquet_index < 1)
THEN
752 CALL timestop(handle)
758 IF (.NOT. any(floquet_env%w0 > 0.5_dp))
THEN
759 cpwarn(
"Floquet: no m=0-dominated state; cannot assess MAX_FLOQUET_INDEX convergence.")
760 CALL timestop(handle)
764 leak = maxval(floquet_env%wE, mask=(floquet_env%w0 > 0.5_dp))
766 IF (bs_env%eps_floquet > 0.0_dp .AND. leak > bs_env%eps_floquet)
THEN
767 WRITE (msg,
'(A,ES10.2E2,A,ES10.2E2)') &
768 "MAX_FLOQUET_INDEX is too small. Leak: ", leak,
"exceeds EPS_FLOQUET: ", bs_env%eps_floquet
772 CALL timestop(handle)
781 FUNCTION floquet_reference_energy(bs_env)
RESULT(mu)
785 IF (bs_env%do_gw .OR. &
787 mu = bs_env%band_edges_scf%VBM
788 ELSE IF (bs_env%n_spin == 1)
THEN
789 mu = bs_env%eigenval_scf_Gamma(bs_env%n_occ(1), 1)
791 mu = max(bs_env%eigenval_scf_Gamma(bs_env%n_occ(1), 1), &
792 bs_env%eigenval_scf_Gamma(bs_env%n_occ(2), 2))
795 END FUNCTION floquet_reference_energy
810 INTEGER,
INTENT(IN) :: ispin, ikp
813 CHARACTER(LEN=*),
PARAMETER :: routinen =
'calculate_floquet_observables'
815 INTEGER :: handle, i, i_e, j, n_e, n_f_size, nao
816 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: work
817 REAL(kind=
dp) :: broad, cum, e_min, energy, energy_step, &
818 mu, omega, target_level
820 CALL timeset(routinen, handle)
822 n_f_size = floquet_env%n_f_size
823 nao = floquet_env%nao
824 n_e = floquet_env%n_E
826 mu = floquet_reference_energy(bs_env)
827 omega = bs_env%floquet_omega
828 broad = bs_env%broadening_floquet
829 energy_step = bs_env%energy_step_floquet
830 e_min = mu - bs_env%energy_window_floquet
839 energy = e_min + i_e*energy_step
840 floquet_env%a_k(i_e) = -sum(floquet_env%w0(:)* &
842 floquet_env%eigenvalues(:))))/
pi
849 target_level = real(i,
dp) - 0.5_dp
850 DO WHILE (cum < target_level .AND. j < n_f_size)
852 cum = cum + floquet_env%w0(j)
854 floquet_env%m0_energies(i) = floquet_env%eigenvalues(j) - mu
855 floquet_env%m0_weights(i) = floquet_env%w0(j)
859 floquet_env%quasi_energies(:) = floquet_env%m0_energies &
860 - omega*real(ceiling(floquet_env%m0_energies/omega - 0.5_dp),
dp)
864 CALL sort(floquet_env%quasi_energies, nao, work)
869 IF (para_env_sub%is_source())
THEN
870 floquet_env%all_quasi_energies(:, ispin, ikp) = floquet_env%quasi_energies(:)
871 floquet_env%all_a_k(:, ispin, ikp) = floquet_env%a_k(:)
872 floquet_env%all_m0_energies(:, ispin, ikp) = floquet_env%m0_energies(:)
873 floquet_env%all_m0_weights(:, ispin, ikp) = floquet_env%m0_weights(:)
876 CALL timestop(handle)
887 CHARACTER(LEN=*),
PARAMETER :: routinen =
'write_floquet_header'
889 INTEGER :: handle, n_f_size, unit_nr
891 CALL timeset(routinen, handle)
893 unit_nr = bs_env%unit_nr
894 n_f_size = bs_env%n_ao*(1 + 2*bs_env%max_floquet_index)
896 IF (unit_nr > 0)
THEN
898 WRITE (unit_nr,
'(T2,A)')
' '
899 WRITE (unit_nr,
'(T2,A)') repeat(
'-', 79)
900 WRITE (unit_nr,
'(T2,A,A78)')
'-',
'-'
901 WRITE (unit_nr,
'(T2,A,A51,A27)')
'-',
'FLOQUET BANDSTRUCTURE CALCULATION',
'-'
902 WRITE (unit_nr,
'(T2,A,A78)')
'-',
'-'
903 WRITE (unit_nr,
'(T2,A)') repeat(
'-', 79)
904 WRITE (unit_nr,
'(T2,A)')
' '
906 WRITE (unit_nr,
'(T2,A,T37,A,T67,ES12.2E2)')
"FLOQUET PARAMETERS",
"Amplitude [V/m]:", &
908 WRITE (unit_nr,
'(T37,A,T67,F12.4)')
"Frequency [eV]:", bs_env%floquet_omega*
evolt
909 WRITE (unit_nr,
'(T37,A)') repeat(
"-", 44)
910 WRITE (unit_nr,
'(T37,A,T55,3F8.4)')
"Polarisation:", bs_env%floquet_polarisation(1:3)
911 WRITE (unit_nr,
'(T37,A,T55,3F8.4)')
"Phase offsets:",
pi*bs_env%floquet_phi(1:3)
912 WRITE (unit_nr,
'(T37,A)') repeat(
"-", 44)
913 WRITE (unit_nr,
'(T37,A,T67,I12)')
"Max Floquet index:", bs_env%max_floquet_index
914 WRITE (unit_nr,
'(T37,A,T67,I12)')
"Floquet Hamiltonian Size:", n_f_size
915 WRITE (unit_nr,
'(T37,A)') repeat(
"-", 44)
916 WRITE (unit_nr,
'(T37,A,T67,F12.4)') &
917 "Energy window [eV]:", bs_env%energy_window_floquet*
evolt
918 WRITE (unit_nr,
'(T37,A,T67,F12.4)')
"Energy step [eV]:", bs_env%energy_step_floquet*
evolt
919 WRITE (unit_nr,
'(T37,A,T67,F12.4)')
"Broadening [eV]:", bs_env%broadening_floquet*
evolt
920 WRITE (unit_nr,
'(T37,A)') repeat(
"-", 44)
921 WRITE (unit_nr,
'(A)')
""
923 WRITE (unit_nr,
'(T2,A)') &
924 "We construct the Floquet-Bloch Hamiltonian and diagonalise it. Projecting the"
925 WRITE (unit_nr,
'(T2,A)') &
926 Σα²
"eigenvectors onto the Floquet sectors gives the weights w = _n |<n,m|>|,"
927 WRITE (unit_nr,
'(T2,A)') &
928 "from which all of the following are obtained."
929 WRITE (unit_nr,
'(A)')
""
930 WRITE (unit_nr,
'(T2,A)') &
931 "The m=0 bands are the eigenvectors with the largest central-sector weight; they"
932 WRITE (unit_nr,
'(T2,A)') &
933 "reduce to the equilibrium bands at zero field and are stored, with their"
934 WRITE (unit_nr,
'(T2,A)') &
935 " weights, in FLOQUET_BANDSTRUCTURE.bs"
936 WRITE (unit_nr,
'(A)')
""
937 WRITE (unit_nr,
'(T2,A)') &
938 "Folding those bands into the first Floquet Brillouin zone, relative to the VBM,"
939 WRITE (unit_nr,
'(T2,A)') &
940 "gives the quasi-energies stored in QUASI_ENERGIES.bs"
941 WRITE (unit_nr,
'(A)')
""
942 WRITE (unit_nr,
'(T2,A)') &
943 "The k-resolved density of states is obtained by computing the trace of"
944 WRITE (unit_nr,
'(T2,A)') &
945 "the retarded Green's function and stored in FLOQUET_DOS.out"
946 WRITE (unit_nr,
'(T2,A)') &
947 ωπω
"DOS(,k) = -1/*Im[Tr_KS(G^R(,k))]"
948 WRITE (unit_nr,
'(A)')
""
951 CALL timestop(handle)
965 CHARACTER(LEN=*),
PARAMETER :: routinen =
'write_floquet_results'
967 CHARACTER(LEN=default_string_length) :: fname
968 INTEGER :: bunit, handle, i, i_e, ikp_for_file, &
969 ispin, n_e, n_spin, nao, nkp_only_bs, &
970 nkp_start, qunit, wunit
971 REAL(kind=
dp) :: e_min, energy, energy_step, f_occ, kt, &
973 REAL(kind=
dp),
DIMENSION(3) :: xkp
975 CALL timeset(routinen, handle)
978 CALL bs_env%para_env%sum(floquet_env%all_quasi_energies)
979 CALL bs_env%para_env%sum(floquet_env%all_a_k)
980 CALL bs_env%para_env%sum(floquet_env%all_m0_energies)
981 CALL bs_env%para_env%sum(floquet_env%all_m0_weights)
983 IF (bs_env%para_env%is_source())
THEN
985 nao = floquet_env%nao
986 n_spin = floquet_env%n_spin
987 nkp_only_bs = floquet_env%nkp_only_bs
988 n_e = floquet_env%n_E
989 nkp_start = bs_env%nkp_only_DOS
992 mu = floquet_reference_energy(bs_env)
993 energy_step = bs_env%energy_step_floquet
994 e_min = mu - bs_env%energy_window_floquet
997 kt = bs_env%floquet_temperature/
kelvin
1002 WRITE (fname,
"(2A)") trim(bs_env%floquet_bs_file),
".bs"
1003 CALL open_file(trim(fname), unit_number=bunit, file_status=
"REPLACE", file_action=
"WRITE")
1004 WRITE (bunit,
"(A)")
"# Floquet m=0 (central-sector) band structure"
1005 WRITE (bunit,
"(A)")
"# (in units of eV, relative to the VBM, not folded)"
1006 WRITE (bunit,
"(A)")
"# w = sum_n |<n,m=0|alpha>|^2 in [0,1]: w~1 clean m=0 replica,"
1007 WRITE (bunit,
"(A)")
"# w~0.5 hybridised with a sideband (drive near resonance)"
1010 WRITE (fname,
"(2A)") trim(bs_env%floquet_qe_file),
".bs"
1011 CALL open_file(trim(fname), unit_number=qunit, file_status=
"REPLACE", file_action=
"WRITE")
1012 WRITE (qunit,
"(A)")
"# Quasi-energies obtained by diagonalising the Floquet Hamiltonian"
1013 WRITE (qunit,
"(A)")
"# (in units of eV, the m=0 bands relative to the VBM, folded to"
1014 WRITE (qunit,
"(A)")
"# the first Floquet Brillouin zone -hbar*Omega/2 < e <= hbar*Omega/2)"
1017 WRITE (fname,
"(2A)") trim(bs_env%floquet_dos_file),
".out"
1018 CALL open_file(trim(fname), unit_number=wunit, file_status=
"REPLACE", file_action=
"WRITE")
1019 WRITE (wunit,
"(A)") ωπω
"# Floquet Density of States: D(,k) = -1/*Im[Tr_KS(G^R(,k))]"
1021 DO ikp_for_file = 1, nkp_only_bs
1022 xkp(1:3) = bs_env%kpoints_DOS%xkp(1:3, nkp_start + ikp_for_file)
1023 DO ispin = 1, n_spin
1026 WRITE (bunit,
"(A,I0,T10,A,I0,A,T24,3(1X,F14.8))") &
1027 "# Spin ", ispin,
" Point ", ikp_for_file,
": ", xkp(1:3)
1028 WRITE (bunit,
"(A)")
"# Floquet band Energy [eV] m=0 weight"
1030 WRITE (bunit,
"(I8,F21.8,F17.5)") i, &
1031 floquet_env%all_m0_energies(i, ispin, ikp_for_file)*
evolt, &
1032 floquet_env%all_m0_weights(i, ispin, ikp_for_file)
1036 WRITE (qunit,
"(A,I0,T10,A,I0,A,T24,3(1X,F14.8))") &
1037 "# Spin ", ispin,
" Point ", ikp_for_file,
": ", xkp(1:3)
1038 WRITE (qunit,
"(A)")
"# Floquet band Quasi-energy [eV]"
1040 WRITE (qunit,
"(I8,F21.8)") i, &
1041 floquet_env%all_quasi_energies(i, ispin, ikp_for_file)*
evolt
1046 WRITE (wunit,
"(A,I0,T10,A,I0,A,T24,3(1X,F14.8))") &
1047 "# Spin ", ispin,
" Point ", ikp_for_file,
": ", xkp(1:3)
1048 IF (bs_env%floquet_temperature > 0.0_dp)
THEN
1049 WRITE (wunit,
"(A)") ω
"#Energy-VBM (eV) A(,k) = DOS (1/eV) f*A = occupied DOS (1/eV)"
1051 energy = e_min + i_e*energy_step
1052 x = (energy - mu)/kt
1053 IF (x > 40.0_dp)
THEN
1055 ELSE IF (x < -40.0_dp)
THEN
1058 f_occ = 1.0_dp/(exp(x) + 1.0_dp)
1060 WRITE (wunit,
"(2X,3G13.4)") (energy - mu)*
evolt, &
1061 floquet_env%all_a_k(i_e, ispin, ikp_for_file)/
evolt, &
1062 f_occ*floquet_env%all_a_k(i_e, ispin, ikp_for_file)/
evolt
1065 WRITE (wunit,
"(A)") ω
"#Energy-VBM (eV) A(,k) = DOS (1/eV)"
1067 energy = e_min + i_e*energy_step
1068 WRITE (wunit,
"(2X,2G13.4)") (energy - mu)*
evolt, &
1069 floquet_env%all_a_k(i_e, ispin, ikp_for_file)/
evolt
1081 CALL timestop(handle)
Handles all functions related to the CELL.
subroutine, public get_cell(cell, alpha, beta, gamma, deth, orthorhombic, abc, periodic, h, h_inv, symmetry_id, tag)
Get informations about a simulation cell.
methods related to the blacs parallel environment
subroutine, public cp_blacs_env_create(blacs_env, para_env, blacs_grid_layout, blacs_repeatable, row_major, grid_2d)
allocates and initializes a type that represent a blacs context
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_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) = ...
Utility routines to open and close files. Tracking of preconnections.
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.
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.
Environment type holding the work and accumulation arrays of the Floquet-Bloch band-structure calcula...
Helper routines for the Floquet-Bloch band-structure calculation (floquet_main).
subroutine, public floquet_sector_weights(floquet_env, cfm_eigenvectors)
Central and boundary-sector weights of every Floquet eigenvector, stored into floquet_envw0 and floqu...
subroutine, public check_floquet_convergence(bs_env, floquet_env)
Checks that MAX_FLOQUET_INDEX is large enough and the Floquet Hamiltonian was truncated far enough aw...
subroutine, public make_floquet_subgroups(qs_env, bs_env, para_env_sub, blacs_env_sub, group_distribution, ngroups)
Split the para_env into subgroups so that the Floquet Hamiltonian is distributed across the ranks of ...
subroutine, public write_floquet_header(bs_env)
Print the Floquet header with the input parameters and a short description of the output.
subroutine, public write_floquet_results(bs_env, floquet_env)
Sum the accumulated results across MPI ranks and write the m=0 band structure, the quasi-energies and...
subroutine, public compute_e_k_de_dk_dipole(qs_env, bs_env, e_k, de_dk, dipole)
Precompute, on the global communicator, the band quantities needed to assemble the Floquet-Bloch Hami...
subroutine, public build_floquet_matrix(bs_env, floquet_env, floquet_matrix)
Builds the Floquet-Bloch Hamiltonian H_F(k) for a single k-point and spin channel from the band data ...
subroutine, public calculate_floquet_observables(bs_env, para_env_sub, ispin, ikp, floquet_env)
Calculate all Floquet observables for one k-point and spin: the DOS (a_k), the m=0 bands,...
subroutine, public distribute_floquet_kp_data(para_env, para_env_sub, ispin, ikp, e_k, de_dk, dipole, floquet_env)
Make this k-point/spin's band data available to every rank of the owning subgroup.
Defines the basic variable types.
integer, parameter, public int_8
integer, parameter, public dp
integer, parameter, public default_string_length
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.
Machine interface based on Fortran 2003 and POSIX.
subroutine, public m_memory_details(memtotal, memfree, buffers, cached, slab, sreclaimable, memlikelyfree)
get more detailed memory info, all units are bytes. the only 'useful' option is MemLikelyFree which i...
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.
subroutine, public geeig_right(a_in, b_in, eigenvalues, eigenvectors)
Solve the generalized eigenvalue equation for complex matrices A*v = B*v*λ
Interface to the message passing library MPI.
type(mp_split_type), parameter, public mp_comm_split_type_shared
Definition of physical constants:
real(kind=dp), parameter, public a_bohr
real(kind=dp), parameter, public kelvin
real(kind=dp), parameter, public evolt
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, matrix_vhxc, 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.
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>
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.
Type defining parameters related to the simulation cell.
represent a blacs multidimensional parallel environment (for the mpi corrispective see cp_paratypes/m...
Represent a complex full matrix.
Work and accumulation arrays for one Floquet-Bloch band-structure run, plus the derived sizes....
Contains information about kpoints.
stores all the informations relevant to an mpi environment