37 dbcsr_type, dbcsr_type_antisymmetric, dbcsr_type_no_symmetry, dbcsr_type_symmetric
115#include "base/base_uses.f90"
127 CHARACTER(len=*),
PARAMETER,
PRIVATE :: moduleN =
'post_scf_bandstructure_utils'
138 CHARACTER(LEN=*),
PARAMETER :: routinen =
'allocate_GW_eigenvalues'
140 INTEGER :: handle, n_ao, n_spin, nkp
142 CALL timeset(routinen, handle)
145 nkp = bs_env%nkp_bs_and_DOS
146 n_spin = bs_env%n_spin
148 IF (.NOT.
ALLOCATED(bs_env%eigenval_GW))
THEN
149 ALLOCATE (bs_env%eigenval_GW(n_ao, nkp, n_spin))
151 IF (.NOT.
ALLOCATED(bs_env%eigenval_HF))
THEN
152 ALLOCATE (bs_env%eigenval_HF(n_ao, nkp, n_spin))
155 SELECT CASE (bs_env%gw_flavour)
157 IF (.NOT.
ALLOCATED(bs_env%eigenval_G0W0))
THEN
158 ALLOCATE (bs_env%eigenval_G0W0(n_ao, nkp, n_spin))
162 IF (bs_env%gw_flavour ==
evgw0 .AND. .NOT.
ALLOCATED(bs_env%eigenval_evGW0))
THEN
163 ALLOCATE (bs_env%eigenval_evGW0(n_ao, nkp, n_spin))
166 CALL timestop(handle)
177 CHARACTER(LEN=default_string_length) :: label
179 SELECT CASE (bs_env%gw_flavour)
199 CHARACTER(LEN=*),
PARAMETER :: routinen =
'create_and_init_bs_env'
203 CALL timeset(routinen, handle)
207 CALL print_header(bs_env)
209 CALL read_bandstructure_input_parameters(bs_env, post_scf_bandstructure_section, qs_env)
211 CALL get_parameters_from_qs_env(qs_env, bs_env)
213 CALL set_heuristic_parameters(bs_env)
215 SELECT CASE (bs_env%small_cell_full_kp_or_large_cell_Gamma)
218 CALL setup_kpoints_dos_large_cell_gamma(qs_env, bs_env, bs_env%kpoints_DOS)
220 CALL allocate_and_fill_fm_ks_fm_s(qs_env, bs_env)
222 CALL diagonalize_ks_matrix(bs_env)
224 CALL check_positive_definite_overlap_mat(bs_env, qs_env)
228 CALL setup_kpoints_scf_desymm(qs_env, bs_env, bs_env%kpoints_scf_desymm, .true.)
229 CALL setup_kpoints_scf_desymm(qs_env, bs_env, bs_env%kpoints_scf_desymm_2, .false.)
231 CALL setup_kpoints_dos_small_cell_full_kp(bs_env, bs_env%kpoints_DOS)
233 CALL allocate_and_fill_fm_ks_fm_s(qs_env, bs_env)
235 CALL compute_cfm_mo_coeff_kp_and_eigenval_scf_kp(qs_env, bs_env)
239 CALL timestop(handle)
249 SUBROUTINE read_bandstructure_input_parameters(bs_env, bs_sec, qs_env)
254 CHARACTER(LEN=*),
PARAMETER :: routinen =
'read_bandstructure_input_parameters'
256 CHARACTER(LEN=default_string_length) :: ustr
257 CHARACTER(LEN=default_string_length), &
258 DIMENSION(:),
POINTER :: string_ptr
259 CHARACTER(LEN=max_line_length) :: error_msg
260 INTEGER :: handle, i, ikp
261 REAL(kind=
dp),
DIMENSION(3) :: kpptr
262 REAL(kind=
dp),
DIMENSION(3, 3) :: cart_hmat
265 kp_bs_sec, ldos_sec, soc_sec
267 CALL timeset(routinen, handle)
270 cart_hmat(:, :) = cell%hmat(:, :)
271 IF (cell%input_cell_canonicalized) cart_hmat(:, :) = cell%input_hmat(:, :)
286 NULLIFY (dos_pdos_sec)
309 NULLIFY (floquet_sec)
321 CALL section_vals_val_get(floquet_sec,
"MEM_FILL_FRACTION", r_val=bs_env%floquet_mem_fill_fraction)
324 CALL section_vals_val_get(floquet_sec,
"QUASI_ENERGIES_FILE_NAME", c_val=bs_env%floquet_qe_file)
328 ALLOCATE (bs_env%xkp_special(3, bs_env%input_kp_bs_n_sp_pts))
329 DO ikp = 1, bs_env%input_kp_bs_n_sp_pts
331 cpassert(
SIZE(string_ptr(:), 1) == 4)
334 IF (len_trim(error_msg) > 0) cpabort(trim(error_msg))
338 bs_env%xkp_special(1:3, ikp) = kpptr(1:3)
339 CASE (
"CART_ANGSTROM")
340 bs_env%xkp_special(1:3, ikp) = (kpptr(1)*cart_hmat(1, 1:3) + &
341 kpptr(2)*cart_hmat(2, 1:3) + &
344 bs_env%xkp_special(1:3, ikp) = (kpptr(1)*cart_hmat(1, 1:3) + &
345 kpptr(2)*cart_hmat(2, 1:3) + &
346 kpptr(3)*cart_hmat(3, 1:3))/
twopi
348 cpabort(
"Unknown unit <"//trim(ustr)//
"> specified for k-point definition")
352 CALL timestop(handle)
354 END SUBROUTINE read_bandstructure_input_parameters
360 SUBROUTINE print_header(bs_env)
364 CHARACTER(LEN=*),
PARAMETER :: routinen =
'print_header'
368 CALL timeset(routinen, handle)
375 WRITE (u,
'(T2,A)')
' '
376 WRITE (u,
'(T2,A)') repeat(
'-', 79)
377 WRITE (u,
'(T2,A,A78)')
'-',
'-'
378 WRITE (u,
'(T2,A,A51,A27)')
'-',
'BANDSTRUCTURE CALCULATION',
'-'
379 WRITE (u,
'(T2,A,A78)')
'-',
'-'
380 WRITE (u,
'(T2,A)') repeat(
'-', 79)
381 WRITE (u,
'(T2,A)')
' '
384 CALL timestop(handle)
386 END SUBROUTINE print_header
394 SUBROUTINE setup_kpoints_dos_large_cell_gamma(qs_env, bs_env, kpoints)
400 CHARACTER(LEN=*),
PARAMETER :: routinen =
'setup_kpoints_DOS_large_cell_Gamma'
402 INTEGER :: handle, i_dim, i_kp_in_line, &
403 i_special_kp, ikk, n_kp_in_line, &
404 n_special_kp, nkp, nkp_only_bs, &
406 INTEGER,
DIMENSION(3) :: nkp_grid, periodic
408 CALL timeset(routinen, handle)
414 kpoints%kp_scheme =
"GENERAL"
416 n_special_kp = bs_env%input_kp_bs_n_sp_pts
417 n_kp_in_line = bs_env%input_kp_bs_npoints
419 periodic(1:3) = bs_env%periodic(1:3)
423 cpassert(periodic(i_dim) == 0 .OR. periodic(i_dim) == 1)
425 IF (bs_env%nkp_grid_DOS_input(i_dim) < 0)
THEN
426 IF (periodic(i_dim) == 1) nkp_grid(i_dim) = 2
427 IF (periodic(i_dim) == 0) nkp_grid(i_dim) = 1
429 nkp_grid(i_dim) = bs_env%nkp_grid_DOS_input(i_dim)
435 IF (nkp_grid(1) > 1)
THEN
436 nkp_only_dos = (nkp_grid(1) + 1)/2*nkp_grid(2)*nkp_grid(3)
437 ELSE IF (nkp_grid(2) > 1)
THEN
438 nkp_only_dos = nkp_grid(1)*(nkp_grid(2) + 1)/2*nkp_grid(3)
439 ELSE IF (nkp_grid(3) > 1)
THEN
440 nkp_only_dos = nkp_grid(1)*nkp_grid(2)*(nkp_grid(3) + 1)/2
447 IF (n_special_kp > 0)
THEN
448 nkp_only_bs = n_kp_in_line*(n_special_kp - 1) + 1
453 nkp = nkp_only_dos + nkp_only_bs
455 kpoints%nkp_grid(1:3) = nkp_grid(1:3)
458 bs_env%nkp_bs_and_DOS = nkp
459 bs_env%nkp_only_bs = nkp_only_bs
460 bs_env%nkp_only_DOS = nkp_only_dos
462 ALLOCATE (kpoints%xkp(3, nkp), kpoints%wkp(nkp))
463 kpoints%wkp(1:nkp_only_dos) = 1.0_dp/real(nkp_only_dos, kind=
dp)
465 CALL compute_xkp(kpoints%xkp, 1, nkp_only_dos, nkp_grid)
467 IF (n_special_kp > 0)
THEN
468 kpoints%xkp(1:3, nkp_only_dos + 1) = bs_env%xkp_special(1:3, 1)
469 ikk = nkp_only_dos + 1
470 DO i_special_kp = 2, n_special_kp
471 DO i_kp_in_line = 1, n_kp_in_line
473 kpoints%xkp(1:3, ikk) = bs_env%xkp_special(1:3, i_special_kp - 1) + &
474 REAL(i_kp_in_line, kind=
dp)/real(n_kp_in_line, kind=
dp)* &
475 (bs_env%xkp_special(1:3, i_special_kp) - &
476 bs_env%xkp_special(1:3, i_special_kp - 1))
477 kpoints%wkp(ikk) = 0.0_dp
487 IF (nkp_only_bs > 0)
THEN
488 WRITE (u, fmt=
"(T2,1A,T77,I4)") &
489 "Number of special k-points for the bandstructure", n_special_kp
490 WRITE (u, fmt=
"(T2,1A,T77,I4)")
"Number of k-points for the bandstructure", nkp
491 WRITE (u, fmt=
"(T2,1A,T69,3I4)") &
492 "K-point mesh for the density of states (DOS)", nkp_grid(1:3)
494 WRITE (u, fmt=
"(T2,1A,T69,3I4)") &
495 "K-point mesh for the density of states (DOS) and the self-energy", nkp_grid(1:3)
499 CALL timestop(handle)
501 END SUBROUTINE setup_kpoints_dos_large_cell_gamma
510 SUBROUTINE setup_kpoints_scf_desymm(qs_env, bs_env, kpoints, do_print)
515 CHARACTER(LEN=*),
PARAMETER :: routinen =
'setup_kpoints_scf_desymm'
517 INTEGER :: handle, i_cell_x, i_dim, img, j_cell_y, &
518 k_cell_z, nimages, nkp, u
519 INTEGER,
DIMENSION(3) :: cell_grid, cixd, nkp_grid
524 CALL timeset(routinen, handle)
529 CALL get_qs_env(qs_env=qs_env, kpoints=kpoints_scf)
531 nkp_grid(1:3) = kpoints_scf%nkp_grid(1:3)
532 nkp = nkp_grid(1)*nkp_grid(2)*nkp_grid(3)
536 IF (bs_env%periodic(i_dim) == 1)
THEN
537 cpassert(nkp_grid(i_dim) >= 4)
541 kpoints%kp_scheme =
"GENERAL"
542 kpoints%nkp_grid(1:3) = nkp_grid(1:3)
544 bs_env%nkp_scf_desymm = nkp
546 ALLOCATE (kpoints%xkp(1:3, nkp))
549 ALLOCATE (kpoints%wkp(nkp))
550 kpoints%wkp(:) = 1.0_dp/real(nkp, kind=
dp)
554 cell_grid(1:3) = nkp_grid(1:3) -
modulo(nkp_grid(1:3) + 1, 2)
557 cixd(1:3) = cell_grid(1:3)/2
559 nimages = cell_grid(1)*cell_grid(2)*cell_grid(3)
561 bs_env%nimages_scf_desymm = nimages
562 bs_env%cell_grid_scf_desymm(1:3) = cell_grid(1:3)
564 IF (
ASSOCIATED(kpoints%index_to_cell))
DEALLOCATE (kpoints%index_to_cell)
565 IF (
ASSOCIATED(kpoints%cell_to_index))
DEALLOCATE (kpoints%cell_to_index)
567 ALLOCATE (kpoints%cell_to_index(-cixd(1):cixd(1), -cixd(2):cixd(2), -cixd(3):cixd(3)))
568 ALLOCATE (kpoints%index_to_cell(3, nimages))
571 DO i_cell_x = -cixd(1), cixd(1)
572 DO j_cell_y = -cixd(2), cixd(2)
573 DO k_cell_z = -cixd(3), cixd(3)
575 kpoints%cell_to_index(i_cell_x, j_cell_y, k_cell_z) = img
576 kpoints%index_to_cell(1:3, img) = [i_cell_x, j_cell_y, k_cell_z]
582 IF (u > 0 .AND. do_print)
THEN
583 WRITE (u, fmt=
"(T2,A,I49)")
"Number of cells for G, χ, W, Σ", nimages
586 CALL timestop(handle)
588 END SUBROUTINE setup_kpoints_scf_desymm
595 SUBROUTINE setup_kpoints_dos_small_cell_full_kp(bs_env, kpoints)
600 CHARACTER(LEN=*),
PARAMETER :: routinen =
'setup_kpoints_DOS_small_cell_full_kp'
602 INTEGER :: handle, i_kp_in_line, i_special_kp, ikk, &
603 n_kp_in_line, n_special_kp, nkp, &
604 nkp_only_bs, nkp_scf_desymm, u
606 CALL timeset(routinen, handle)
612 n_special_kp = bs_env%input_kp_bs_n_sp_pts
613 n_kp_in_line = bs_env%input_kp_bs_npoints
614 nkp_scf_desymm = bs_env%nkp_scf_desymm
618 IF (n_special_kp > 0)
THEN
619 nkp_only_bs = n_kp_in_line*(n_special_kp - 1) + 1
623 nkp = nkp_only_bs + nkp_scf_desymm
625 ALLOCATE (kpoints%xkp(3, nkp))
626 ALLOCATE (kpoints%wkp(nkp))
630 bs_env%nkp_bs_and_DOS = nkp
631 bs_env%nkp_only_bs = nkp_only_bs
632 bs_env%nkp_only_DOS = nkp_scf_desymm
634 kpoints%xkp(1:3, 1:nkp_scf_desymm) = bs_env%kpoints_scf_desymm%xkp(1:3, 1:nkp_scf_desymm)
635 kpoints%wkp(1:nkp_scf_desymm) = 1.0_dp/real(nkp_scf_desymm, kind=
dp)
637 IF (n_special_kp > 0)
THEN
638 kpoints%xkp(1:3, nkp_scf_desymm + 1) = bs_env%xkp_special(1:3, 1)
639 ikk = nkp_scf_desymm + 1
640 DO i_special_kp = 2, n_special_kp
641 DO i_kp_in_line = 1, n_kp_in_line
643 kpoints%xkp(1:3, ikk) = bs_env%xkp_special(1:3, i_special_kp - 1) + &
644 REAL(i_kp_in_line, kind=
dp)/real(n_kp_in_line, kind=
dp)* &
645 (bs_env%xkp_special(1:3, i_special_kp) - &
646 bs_env%xkp_special(1:3, i_special_kp - 1))
647 kpoints%wkp(ikk) = 0.0_dp
652 IF (
ASSOCIATED(kpoints%index_to_cell))
DEALLOCATE (kpoints%index_to_cell)
654 ALLOCATE (kpoints%index_to_cell(3, bs_env%nimages_scf_desymm))
655 kpoints%index_to_cell(:, :) = bs_env%kpoints_scf_desymm%index_to_cell(:, :)
660 WRITE (u, fmt=
"(T2,1A,T77,I4)")
"Number of special k-points for the bandstructure", &
662 WRITE (u, fmt=
"(T2,1A,T77,I4)")
"Number of k-points for the bandstructure", nkp
665 CALL timestop(handle)
667 END SUBROUTINE setup_kpoints_dos_small_cell_full_kp
674 SUBROUTINE compute_cfm_mo_coeff_kp_and_eigenval_scf_kp(qs_env, bs_env)
678 CHARACTER(LEN=*),
PARAMETER :: routinen =
'compute_cfm_mo_coeff_kp_and_eigenval_scf_kp'
680 INTEGER :: handle, ikp, ispin, nkp_bs_and_dos, &
682 INTEGER,
DIMENSION(:, :, :),
POINTER :: cell_to_index_scf
683 REAL(kind=
dp) :: cbm, vbm
684 REAL(kind=
dp),
DIMENSION(3) :: xkp
686 TYPE(
dbcsr_p_type),
DIMENSION(:, :),
POINTER :: matrix_ks, matrix_s
691 CALL timeset(routinen, handle)
694 matrix_ks_kp=matrix_ks, &
695 matrix_s_kp=matrix_s, &
699 CALL get_kpoint_info(kpoints_scf, sab_nl=sab_nl, cell_to_index=cell_to_index_scf)
703 CALL cp_cfm_create(cfm_mos, bs_env%cfm_work_mo%matrix_struct)
706 nkp_bs_and_dos = bs_env%nkp_bs_and_DOS
710 ALLOCATE (bs_env%cfm_mo_coeff_kp(nkp_bs_and_dos, bs_env%n_spin))
711 ALLOCATE (bs_env%cfm_ks_kp(nkp_bs_and_dos, bs_env%n_spin))
712 ALLOCATE (bs_env%cfm_s_kp(nkp_bs_and_dos))
713 DO ikp = 1, nkp_bs_and_dos
714 DO ispin = 1, bs_env%n_spin
715 CALL cp_cfm_create(bs_env%cfm_mo_coeff_kp(ikp, ispin), bs_env%cfm_work_mo%matrix_struct)
716 CALL cp_cfm_create(bs_env%cfm_ks_kp(ikp, ispin), bs_env%cfm_work_mo%matrix_struct)
718 CALL cp_cfm_create(bs_env%cfm_s_kp(ikp), bs_env%cfm_work_mo%matrix_struct)
721 DO ispin = 1, bs_env%n_spin
722 DO ikp = 1, nkp_bs_and_dos
724 xkp(1:3) = bs_env%kpoints_DOS%xkp(1:3, ikp)
727 CALL rsmat_to_kp(matrix_ks, ispin, xkp, cell_to_index_scf, sab_nl, bs_env, cfm_ks)
730 CALL rsmat_to_kp(matrix_s, 1, xkp, cell_to_index_scf, sab_nl, bs_env, cfm_s)
740 bs_env%eigenval_scf(:, ikp, ispin), &
741 bs_env%cfm_work_mo, bs_env%eps_eigval_mat_s, &
742 nmo_retained=nmo_retained)
743 bs_env%n_mo_retained = min(bs_env%n_mo_retained, nmo_retained)
747 CALL cp_cfm_to_cfm(cfm_mos, bs_env%cfm_mo_coeff_kp(ikp, ispin))
751 vbm = maxval(bs_env%eigenval_scf(bs_env%n_occ(ispin), :, ispin))
752 cbm = minval(bs_env%eigenval_scf(bs_env%n_occ(ispin) + 1, :, ispin))
754 bs_env%e_fermi(ispin) = 0.5_dp*(vbm + cbm)
764 CALL timestop(handle)
766 END SUBROUTINE compute_cfm_mo_coeff_kp_and_eigenval_scf_kp
779 SUBROUTINE rsmat_to_kp(mat_rs, ispin, xkp, cell_to_index_scf, sab_nl, bs_env, cfm_kp, imag_rs_mat)
782 REAL(kind=
dp),
DIMENSION(3) :: xkp
783 INTEGER,
DIMENSION(:, :, :),
POINTER :: cell_to_index_scf
788 LOGICAL,
OPTIONAL :: imag_rs_mat
790 CHARACTER(LEN=*),
PARAMETER :: routinen =
'rsmat_to_kp'
793 LOGICAL :: imag_rs_mat_private
794 TYPE(
dbcsr_type),
POINTER :: cmat, nsmat, rmat
796 CALL timeset(routinen, handle)
798 ALLOCATE (rmat, cmat, nsmat)
800 imag_rs_mat_private = .false.
801 IF (
PRESENT(imag_rs_mat)) imag_rs_mat_private = imag_rs_mat
803 IF (imag_rs_mat_private)
THEN
804 CALL dbcsr_create(rmat, template=mat_rs(1, 1)%matrix, matrix_type=dbcsr_type_antisymmetric)
805 CALL dbcsr_create(cmat, template=mat_rs(1, 1)%matrix, matrix_type=dbcsr_type_symmetric)
807 CALL dbcsr_create(rmat, template=mat_rs(1, 1)%matrix, matrix_type=dbcsr_type_symmetric)
808 CALL dbcsr_create(cmat, template=mat_rs(1, 1)%matrix, matrix_type=dbcsr_type_antisymmetric)
810 CALL dbcsr_create(nsmat, template=mat_rs(1, 1)%matrix, matrix_type=dbcsr_type_no_symmetry)
816 CALL rskp_transform(rmatrix=rmat, cmatrix=cmat, rsmat=mat_rs, ispin=ispin, &
817 xkp=xkp, cell_to_index=cell_to_index_scf, sab_nl=sab_nl)
823 CALL cp_fm_to_cfm(bs_env%fm_work_mo(1), bs_env%fm_work_mo(2), cfm_kp)
829 CALL timestop(handle)
837 SUBROUTINE diagonalize_ks_matrix(bs_env)
840 CHARACTER(LEN=*),
PARAMETER :: routinen =
'diagonalize_ks_matrix'
842 INTEGER :: handle, ikp, ispin, nmo_retained
843 REAL(kind=
dp) :: cbm, vbm
845 CALL timeset(routinen, handle)
847 ALLOCATE (bs_env%eigenval_scf_Gamma(bs_env%n_ao, bs_env%n_spin))
849 DO ispin = 1, bs_env%n_spin
852 CALL cp_fm_to_fm(bs_env%fm_ks_Gamma(ispin), bs_env%fm_work_mo(1))
853 CALL cp_fm_to_fm(bs_env%fm_s_Gamma, bs_env%fm_work_mo(2))
858 bs_env%fm_work_mo(2), &
859 bs_env%fm_mo_coeff_Gamma(ispin), &
860 bs_env%eigenval_scf_Gamma(:, ispin), &
861 bs_env%fm_work_mo(3), &
862 bs_env%eps_eigval_mat_s, &
863 nmo_retained=nmo_retained)
864 bs_env%n_mo_retained = min(bs_env%n_mo_retained, nmo_retained)
866 vbm = bs_env%eigenval_scf_Gamma(bs_env%n_occ(ispin), ispin)
867 cbm = bs_env%eigenval_scf_Gamma(bs_env%n_occ(ispin) + 1, ispin)
869 bs_env%band_edges_scf_Gamma(ispin)%VBM = vbm
870 bs_env%band_edges_scf_Gamma(ispin)%CBM = cbm
871 bs_env%e_fermi(ispin) = 0.5_dp*(vbm + cbm)
875 CALL timestop(handle)
878 DO ispin = 1, bs_env%n_spin
879 DO ikp = 1, bs_env%nkp_bs_and_DOS
880 bs_env%eigenval_scf(:, ikp, ispin) = bs_env%eigenval_scf_Gamma(:, ispin)
884 END SUBROUTINE diagonalize_ks_matrix
891 SUBROUTINE check_positive_definite_overlap_mat(bs_env, qs_env)
895 CHARACTER(LEN=*),
PARAMETER :: routinen =
'check_positive_definite_overlap_mat'
897 INTEGER :: handle, ikp, info, u
900 CALL timeset(routinen, handle)
902 DO ikp = 1, bs_env%kpoints_DOS%nkp
906 ikp, qs_env, bs_env%kpoints_DOS,
"ORB")
917 WRITE (u, fmt=
"(T2,A)")
""
918 WRITE (u, fmt=
"(T2,A)")
"ERROR: The Cholesky decomposition "// &
919 "of the k-point overlap matrix failed. This is"
920 WRITE (u, fmt=
"(T2,A)")
"because the algorithm is "// &
921 "only correct in the limit of large cells. The cell of "
922 WRITE (u, fmt=
"(T2,A)")
"the calculation is too small. "// &
923 "Use MULTIPLE_UNIT_CELL to create a larger cell "
924 WRITE (u, fmt=
"(T2,A)")
"and to prevent this error."
927 CALL bs_env%para_env%sync()
928 cpabort(
"Please see information on the error above.")
936 CALL timestop(handle)
938 END SUBROUTINE check_positive_definite_overlap_mat
945 SUBROUTINE get_parameters_from_qs_env(qs_env, bs_env)
949 CHARACTER(LEN=*),
PARAMETER :: routinen =
'get_parameters_from_qs_env'
951 INTEGER :: color_sub, handle, homo, n_ao, n_atom, u
952 INTEGER,
DIMENSION(3) :: periodic
953 REAL(kind=
dp),
DIMENSION(3, 3) :: hmat
962 CALL timeset(routinen, handle)
965 dft_control=dft_control, &
966 scf_control=scf_control, &
969 bs_env%n_spin = dft_control%nspins
970 IF (bs_env%n_spin == 1) bs_env%spin_degeneracy = 2.0_dp
971 IF (bs_env%n_spin == 2) bs_env%spin_degeneracy = 1.0_dp
973 CALL get_mo_set(mo_set=mos(1), nao=n_ao, homo=homo)
976 bs_env%n_mo_retained = n_ao
977 bs_env%n_occ(1:2) = homo
978 bs_env%n_vir(1:2) = n_ao - homo
980 IF (bs_env%n_spin == 2)
THEN
982 bs_env%n_occ(2) = homo
983 bs_env%n_vir(2) = n_ao - homo
986 bs_env%eps_eigval_mat_s = scf_control%eps_eigval
991 ALLOCATE (bs_env%para_env)
992 CALL bs_env%para_env%from_split(para_env, color_sub)
994 CALL get_qs_env(qs_env, particle_set=particle_set)
996 n_atom =
SIZE(particle_set)
997 bs_env%n_atom = n_atom
1000 CALL get_cell(cell=cell, periodic=periodic, h=hmat)
1001 bs_env%periodic(1:3) = periodic(1:3)
1002 bs_env%hmat(1:3, 1:3) = hmat
1003 bs_env%nimages_scf = dft_control%nimages
1004 IF (dft_control%nimages == 1)
THEN
1005 IF (bs_env%do_gw_ri_rs)
THEN
1006 IF (any(periodic /= 0))
THEN
1014 ELSE IF (dft_control%nimages > 1)
THEN
1015 IF (bs_env%do_gw_ri_rs)
THEN
1016 cpabort(
"RI-RS Not Implemented for K-point Calculations")
1021 cpabort(
"Wrong number of cells from DFT calculation.")
1028 CALL section_vals_val_get(input,
"DFT%REAL_TIME_PROPAGATION%RTBSE%_SECTION_PARAMETERS_", i_val=bs_env%rtp_method)
1031 WRITE (u, fmt=
"(T2,2A,T73,I8)")
"Number of occupied molecular orbitals (MOs) ", &
1032 "= Number of occupied bands", homo
1033 WRITE (u, fmt=
"(T2,2A,T73,I8)")
"Number of unoccupied (= virtual) MOs ", &
1034 "= Number of unoccupied bands", n_ao - homo
1035 WRITE (u, fmt=
"(T2,A,T73,I8)")
"Number of Gaussian basis functions for MOs", n_ao
1037 WRITE (u, fmt=
"(T2,2A,T73,I8)")
"Number of cells considered in the DFT ", &
1038 "calculation", bs_env%nimages_scf
1042 CALL timestop(handle)
1044 END SUBROUTINE get_parameters_from_qs_env
1050 SUBROUTINE set_heuristic_parameters(bs_env)
1053 CHARACTER(LEN=*),
PARAMETER :: routinen =
'set_heuristic_parameters'
1057 CALL timeset(routinen, handle)
1059 bs_env%n_bins_max_for_printing = 5000
1061 CALL timestop(handle)
1063 END SUBROUTINE set_heuristic_parameters
1070 SUBROUTINE allocate_and_fill_fm_ks_fm_s(qs_env, bs_env)
1074 CHARACTER(LEN=*),
PARAMETER :: routinen =
'allocate_and_fill_fm_ks_fm_s'
1076 INTEGER :: handle, i_work, ispin
1079 TYPE(
dbcsr_p_type),
DIMENSION(:, :),
POINTER :: matrix_ks, matrix_s
1082 CALL timeset(routinen, handle)
1085 para_env=para_env, &
1086 blacs_env=blacs_env, &
1087 matrix_ks_kp=matrix_ks, &
1088 matrix_s_kp=matrix_s)
1092 ncol_global=bs_env%n_ao, para_env=para_env)
1094 DO i_work = 1,
SIZE(bs_env%fm_work_mo)
1095 CALL cp_fm_create(bs_env%fm_work_mo(i_work), fm_struct)
1104 DO ispin = 1, bs_env%n_spin
1105 CALL cp_fm_create(bs_env%fm_ks_Gamma(ispin), fm_struct)
1106 CALL copy_dbcsr_to_fm(matrix_ks(ispin, 1)%matrix, bs_env%fm_ks_Gamma(ispin))
1107 CALL cp_fm_create(bs_env%fm_mo_coeff_Gamma(ispin), fm_struct)
1112 NULLIFY (bs_env%mat_ao_ao%matrix)
1113 ALLOCATE (bs_env%mat_ao_ao%matrix)
1114 CALL dbcsr_create(bs_env%mat_ao_ao%matrix, template=matrix_s(1, 1)%matrix, &
1115 matrix_type=dbcsr_type_no_symmetry)
1117 ALLOCATE (bs_env%eigenval_scf(bs_env%n_ao, bs_env%nkp_bs_and_DOS, bs_env%n_spin))
1119 CALL timestop(handle)
1121 END SUBROUTINE allocate_and_fill_fm_ks_fm_s
1132 CHARACTER(LEN=*),
PARAMETER :: routinen =
'eval_bandstructure_properties'
1134 CHARACTER(LEN=default_string_length) :: gw_label, gw_soc_label
1135 INTEGER :: handle, homo, homo_1, homo_2, &
1136 homo_spinor, ikp, ikp_for_file, ispin, &
1137 n_ao, n_e, nkind, nkp
1138 LOGICAL :: is_bandstruc_kpoint, print_dos_kpoints, &
1140 REAL(kind=
dp) :: broadening, e_max, e_max_g0w0, e_min, &
1141 e_min_g0w0, e_total_window, &
1142 energy_step_dos, energy_window_dos, t1
1143 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: dos_g0w0, dos_g0w0_soc, dos_scf, dos_scf_soc, &
1144 eigenval, eigenval_spinor, eigenval_spinor_g0w0, eigenval_spinor_no_soc
1145 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: pdos_g0w0, pdos_g0w0_soc, pdos_scf, &
1146 pdos_scf_soc, proj_mo_on_kind
1147 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :, :) :: ldos_g0w0_2d, ldos_scf_2d, &
1150 band_edges_scf, band_edges_scf_guess, &
1152 TYPE(
cp_cfm_type) :: cfm_ks_ikp, cfm_ks_ikp_spinor, cfm_mos_ikp_spinor, cfm_s_ikp, &
1153 cfm_s_ikp_copy, cfm_s_ikp_spinor, cfm_s_ikp_spinor_copy, cfm_soc_ikp_spinor, &
1154 cfm_spinor_wf_ikp, cfm_work_ikp, cfm_work_ikp_spinor
1157 CALL timeset(routinen, handle)
1161 energy_window_dos = bs_env%energy_window_DOS
1162 energy_step_dos = bs_env%energy_step_DOS
1163 broadening = bs_env%broadening_DOS
1166 IF (bs_env%do_gw .OR. &
1168 band_edges_scf = bs_env%band_edges_scf
1169 band_edges_scf_guess = band_edges_scf
1172 IF (bs_env%n_spin == 1)
THEN
1173 homo = bs_env%n_occ(1)
1174 band_edges_scf_guess%VBM = bs_env%eigenval_scf_Gamma(homo, 1)
1175 band_edges_scf_guess%CBM = bs_env%eigenval_scf_Gamma(homo + 1, 1)
1177 homo_1 = bs_env%n_occ(1)
1178 homo_2 = bs_env%n_occ(2)
1179 band_edges_scf_guess%VBM = max(bs_env%eigenval_scf_Gamma(homo_1, 1), &
1180 bs_env%eigenval_scf_Gamma(homo_2, 2))
1181 band_edges_scf_guess%CBM = min(bs_env%eigenval_scf_Gamma(homo_1 + 1, 1), &
1182 bs_env%eigenval_scf_Gamma(homo_2 + 1, 2))
1186 band_edges_scf%VBM = -1000.0_dp
1187 band_edges_scf%CBM = 1000.0_dp
1188 band_edges_scf%DBG = 1000.0_dp
1191 e_min = band_edges_scf_guess%VBM - 0.5_dp*energy_window_dos
1192 e_max = band_edges_scf_guess%CBM + 0.5_dp*energy_window_dos
1194 IF (bs_env%do_gw)
THEN
1195 band_edges_g0w0 = bs_env%band_edges_GW
1196 e_min_g0w0 = band_edges_g0w0%VBM - 0.5_dp*energy_window_dos
1197 e_max_g0w0 = band_edges_g0w0%CBM + 0.5_dp*energy_window_dos
1198 e_min = min(e_min, e_min_g0w0)
1199 e_max = max(e_max, e_max_g0w0)
1202 e_total_window = e_max - e_min
1204 n_e = int(e_total_window/energy_step_dos)
1208 ALLOCATE (proj_mo_on_kind(n_ao, nkind))
1209 proj_mo_on_kind(:, :) = 0.0_dp
1211 ALLOCATE (eigenval(n_ao))
1212 ALLOCATE (eigenval_spinor(2*n_ao))
1213 ALLOCATE (eigenval_spinor_no_soc(2*n_ao))
1214 ALLOCATE (eigenval_spinor_g0w0(2*n_ao))
1216 IF (bs_env%do_dos_pdos)
THEN
1218 ALLOCATE (dos_scf(n_e))
1220 ALLOCATE (pdos_scf(n_e, nkind))
1221 pdos_scf(:, :) = 0.0_dp
1223 IF (bs_env%do_soc)
THEN
1225 ALLOCATE (dos_scf_soc(n_e))
1226 dos_scf_soc(:) = 0.0_dp
1227 ALLOCATE (pdos_scf_soc(n_e, nkind))
1228 pdos_scf_soc(:, :) = 0.0_dp
1232 IF (bs_env%do_gw)
THEN
1234 ALLOCATE (dos_g0w0(n_e))
1235 dos_g0w0(:) = 0.0_dp
1236 ALLOCATE (pdos_g0w0(n_e, nkind))
1237 pdos_g0w0(:, :) = 0.0_dp
1239 IF (bs_env%do_soc)
THEN
1241 ALLOCATE (dos_g0w0_soc(n_e))
1242 dos_g0w0_soc(:) = 0.0_dp
1243 ALLOCATE (pdos_g0w0_soc(n_e, nkind))
1244 pdos_g0w0_soc(:, :) = 0.0_dp
1250 CALL cp_cfm_create(cfm_mos_ikp(1), bs_env%fm_ks_Gamma(1)%matrix_struct)
1251 CALL cp_cfm_create(cfm_mos_ikp(2), bs_env%fm_ks_Gamma(1)%matrix_struct)
1252 CALL cp_cfm_create(cfm_work_ikp, bs_env%fm_ks_Gamma(1)%matrix_struct)
1253 CALL cp_cfm_create(cfm_s_ikp_copy, bs_env%fm_ks_Gamma(1)%matrix_struct)
1255 IF (bs_env%do_soc)
THEN
1257 CALL cp_cfm_create(cfm_mos_ikp_spinor, bs_env%cfm_SOC_spinor_ao(1)%matrix_struct)
1258 CALL cp_cfm_create(cfm_work_ikp_spinor, bs_env%cfm_SOC_spinor_ao(1)%matrix_struct)
1259 CALL cp_cfm_create(cfm_s_ikp_spinor_copy, bs_env%cfm_SOC_spinor_ao(1)%matrix_struct)
1260 CALL cp_cfm_create(cfm_ks_ikp_spinor, bs_env%cfm_SOC_spinor_ao(1)%matrix_struct)
1261 CALL cp_cfm_create(cfm_soc_ikp_spinor, bs_env%cfm_SOC_spinor_ao(1)%matrix_struct)
1262 CALL cp_cfm_create(cfm_s_ikp_spinor, bs_env%cfm_SOC_spinor_ao(1)%matrix_struct)
1263 CALL cp_cfm_create(cfm_spinor_wf_ikp, bs_env%cfm_SOC_spinor_ao(1)%matrix_struct)
1265 homo_spinor = bs_env%n_occ(1) + bs_env%n_occ(bs_env%n_spin)
1267 band_edges_scf_soc%VBM = -1000.0_dp
1268 band_edges_scf_soc%CBM = 1000.0_dp
1269 band_edges_scf_soc%DBG = 1000.0_dp
1271 IF (bs_env%do_gw)
THEN
1272 band_edges_g0w0_soc%VBM = -1000.0_dp
1273 band_edges_g0w0_soc%CBM = 1000.0_dp
1274 band_edges_g0w0_soc%DBG = 1000.0_dp
1277 IF (bs_env%unit_nr > 0)
THEN
1278 WRITE (bs_env%unit_nr,
'(A)')
''
1279 IF (bs_env%soc_window_occ > 0.0_dp)
THEN
1280 WRITE (bs_env%unit_nr,
'(T2,A,T71,F10.2)')
'SOC requested, SOC energy window occ (eV):', &
1281 bs_env%soc_window_occ*
evolt
1283 WRITE (bs_env%unit_nr,
'(T2,A,T71,A10)')
'SOC requested, SOC energy window occ (eV):', &
1286 IF (bs_env%soc_window_virt > 0.0_dp)
THEN
1287 WRITE (bs_env%unit_nr,
'(T2,A,T71,F10.2)')
'SOC requested, SOC energy window virt (eV):', &
1288 bs_env%soc_window_virt*
evolt
1290 WRITE (bs_env%unit_nr,
'(T2,A,T71,A10)')
'SOC requested, SOC energy window virt (eV):', &
1293 IF (bs_env%soc_window_occ > 0.0_dp .OR. bs_env%soc_window_virt > 0.0_dp)
THEN
1294 WRITE (bs_env%unit_nr,
'(T2,A,T71,F10.2)')
'SOC requested, SOC window smearing (eV):', &
1295 bs_env%soc_window_smearing*
evolt
1300 IF (bs_env%do_ldos)
THEN
1304 IF (bs_env%unit_nr > 0)
THEN
1305 WRITE (bs_env%unit_nr,
'(A)')
''
1309 CALL cp_cfm_create(cfm_ks_ikp, bs_env%cfm_ks_kp(1, 1)%matrix_struct)
1310 CALL cp_cfm_create(cfm_s_ikp, bs_env%cfm_ks_kp(1, 1)%matrix_struct)
1313 DO ikp = 1, bs_env%nkp_bs_and_DOS
1317 DO ispin = 1, bs_env%n_spin
1319 SELECT CASE (bs_env%small_cell_full_kp_or_large_cell_Gamma)
1324 ikp, qs_env, bs_env%kpoints_DOS,
"ORB")
1328 ikp, qs_env, bs_env%kpoints_DOS,
"ORB")
1332 CALL cp_cfm_geeig(cfm_ks_ikp, cfm_s_ikp_copy, cfm_mos_ikp(ispin), &
1333 eigenval, cfm_work_ikp)
1338 CALL cp_cfm_to_cfm(bs_env%cfm_ks_kp(ikp, ispin), cfm_ks_ikp)
1344 CALL cp_cfm_to_cfm(bs_env%cfm_mo_coeff_kp(ikp, ispin), cfm_mos_ikp(ispin))
1345 eigenval(:) = bs_env%eigenval_scf(:, ikp, ispin)
1351 CALL compute_proj_mo_on_kind(proj_mo_on_kind, qs_env, cfm_mos_ikp(ispin), cfm_s_ikp)
1354 IF (bs_env%do_dos_pdos)
THEN
1355 CALL add_to_dos_pdos(dos_scf, pdos_scf, eigenval, ikp, bs_env, n_e, e_min, &
1358 IF (bs_env%do_gw)
THEN
1359 CALL add_to_dos_pdos(dos_g0w0, pdos_g0w0, bs_env%eigenval_GW(:, ikp, ispin), &
1360 ikp, bs_env, n_e, e_min, proj_mo_on_kind)
1364 IF (bs_env%do_ldos)
THEN
1365 CALL add_to_ldos_2d(ldos_scf_2d, qs_env, ikp, bs_env, cfm_mos_ikp(ispin), &
1366 eigenval(:), band_edges_scf_guess)
1368 IF (bs_env%do_gw)
THEN
1369 CALL add_to_ldos_2d(ldos_g0w0_2d, qs_env, ikp, bs_env, cfm_mos_ikp(ispin), &
1370 bs_env%eigenval_GW(:, ikp, 1), band_edges_g0w0)
1375 homo = bs_env%n_occ(ispin)
1377 band_edges_scf%VBM = max(band_edges_scf%VBM, eigenval(homo))
1378 band_edges_scf%CBM = min(band_edges_scf%CBM, eigenval(homo + 1))
1379 band_edges_scf%DBG = min(band_edges_scf%DBG, eigenval(homo + 1) - eigenval(homo))
1384 IF (bs_env%do_soc)
THEN
1387 print_dos_kpoints = (bs_env%nkp_only_bs <= 0)
1389 is_bandstruc_kpoint = (ikp > bs_env%nkp_only_DOS)
1390 print_ikp = print_dos_kpoints .OR. is_bandstruc_kpoint
1392 IF (print_dos_kpoints)
THEN
1393 nkp = bs_env%nkp_only_DOS
1396 nkp = bs_env%nkp_only_bs
1397 ikp_for_file = ikp - bs_env%nkp_only_DOS
1401 CALL soc_ev(bs_env, qs_env, ikp, bs_env%eigenval_scf, &
1402 e_min, cfm_mos_ikp, dos_scf_soc, pdos_scf_soc, &
1403 band_edges_scf_soc, eigenval_spinor, cfm_spinor_wf_ikp)
1405 IF (.NOT. bs_env%do_gw .AND. print_ikp)
THEN
1406 CALL write_soc_eigenvalues(eigenval_spinor, ikp_for_file, ikp, bs_env)
1409 IF (bs_env%do_ldos)
THEN
1410 CALL add_to_ldos_2d(ldos_scf_2d_soc, qs_env, ikp, bs_env, cfm_spinor_wf_ikp, &
1411 eigenval_spinor, band_edges_scf_guess, .true., cfm_work_ikp)
1414 IF (bs_env%do_gw)
THEN
1417 CALL soc_ev(bs_env, qs_env, ikp, bs_env%eigenval_GW, &
1418 e_min, cfm_mos_ikp, dos_g0w0_soc, pdos_g0w0_soc, &
1419 band_edges_g0w0_soc, eigenval_spinor_g0w0, cfm_spinor_wf_ikp)
1424 CALL write_soc_eigenvalues(eigenval_spinor, ikp_for_file, ikp, bs_env, &
1425 eigenval_spinor_g0w0)
1432 IF (bs_env%unit_nr > 0 .AND.
m_walltime() - t1 > 20.0_dp)
THEN
1433 WRITE (bs_env%unit_nr,
'(T2,A,T43,I5,A,I3,A,F7.1,A)') &
1434 'Compute DOS, LDOS for k-point ', ikp,
' /', bs_env%nkp_bs_and_DOS, &
1440 band_edges_scf%IDBG = band_edges_scf%CBM - band_edges_scf%VBM
1441 IF (bs_env%do_soc)
THEN
1442 band_edges_scf_soc%IDBG = band_edges_scf_soc%CBM - band_edges_scf_soc%VBM
1443 IF (bs_env%do_gw)
THEN
1444 band_edges_g0w0_soc%IDBG = band_edges_g0w0_soc%CBM - band_edges_g0w0_soc%VBM
1448 CALL write_band_edges(band_edges_scf,
"SCF", bs_env)
1449 IF (bs_env%do_dos_pdos)
THEN
1450 CALL write_dos_pdos(dos_scf, pdos_scf, bs_env, qs_env,
"SCF", e_min, band_edges_scf%VBM)
1452 IF (bs_env%do_ldos)
THEN
1453 CALL print_ldos_main(ldos_scf_2d, bs_env, band_edges_scf,
"SCF")
1456 IF (bs_env%do_soc)
THEN
1457 CALL write_band_edges(band_edges_scf_soc,
"SCF+SOC", bs_env)
1458 IF (bs_env%do_dos_pdos)
THEN
1459 CALL write_dos_pdos(dos_scf_soc, pdos_scf_soc, bs_env, qs_env,
"SCF_SOC", &
1460 e_min, band_edges_scf_soc%VBM)
1462 IF (bs_env%do_ldos)
THEN
1465 CALL print_ldos_main(ldos_scf_2d_soc, bs_env, band_edges_scf, &
1473 gw_soc_label = trim(gw_label)//
"+SOC"
1475 IF (bs_env%do_gw)
THEN
1476 CALL write_band_edges(band_edges_g0w0, trim(gw_label), bs_env)
1477 CALL write_band_edges(bs_env%band_edges_HF,
"Hartree-Fock with SCF orbitals", bs_env)
1478 IF (bs_env%do_dos_pdos)
THEN
1479 CALL write_dos_pdos(dos_g0w0, pdos_g0w0, bs_env, qs_env,
"G0W0", e_min, &
1480 band_edges_g0w0%VBM)
1482 IF (bs_env%do_ldos)
THEN
1483 CALL print_ldos_main(ldos_g0w0_2d, bs_env, band_edges_g0w0,
"G0W0")
1487 IF (bs_env%do_soc .AND. bs_env%do_gw)
THEN
1488 CALL write_band_edges(band_edges_g0w0_soc, trim(gw_soc_label), bs_env)
1489 IF (bs_env%do_dos_pdos)
THEN
1490 CALL write_dos_pdos(dos_g0w0_soc, pdos_g0w0_soc, bs_env, qs_env,
"G0W0_SOC", e_min, &
1491 band_edges_g0w0_soc%VBM)
1510 CALL timestop(handle)
1521 SUBROUTINE print_ldos_main(LDOS_2d, bs_env, band_edges, scf_gw_soc)
1522 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :, :) :: ldos_2d
1525 CHARACTER(LEN=*) :: scf_gw_soc
1527 CHARACTER(LEN=*),
PARAMETER :: routinen =
'print_LDOS_main'
1529 INTEGER :: handle, i_x, i_x_bin, i_x_end, i_x_end_bin, i_x_end_glob, i_x_start, &
1530 i_x_start_bin, i_x_start_glob, i_y, i_y_bin, i_y_end, i_y_end_bin, i_y_end_glob, &
1531 i_y_start, i_y_start_bin, i_y_start_glob, n_e
1532 INTEGER,
ALLOCATABLE,
DIMENSION(:, :) :: n_sum_for_bins
1533 INTEGER,
DIMENSION(2) :: bin_mesh
1534 LOGICAL :: do_xy_bins
1535 REAL(kind=
dp) :: e_min, energy_step, energy_window
1536 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :, :) :: ldos_2d_bins
1538 CALL timeset(routinen, handle)
1540 n_e =
SIZE(ldos_2d, 3)
1542 energy_window = bs_env%energy_window_DOS
1543 energy_step = bs_env%energy_step_DOS
1544 e_min = band_edges%VBM - 0.5_dp*energy_window
1546 bin_mesh(1:2) = bs_env%bin_mesh(1:2)
1547 do_xy_bins = (bin_mesh(1) > 0 .AND. bin_mesh(2) > 0)
1549 i_x_start = lbound(ldos_2d, 1)
1550 i_x_end = ubound(ldos_2d, 1)
1551 i_y_start = lbound(ldos_2d, 2)
1552 i_y_end = ubound(ldos_2d, 2)
1554 IF (do_xy_bins)
THEN
1556 i_x_end_bin = bin_mesh(1)
1558 i_y_end_bin = bin_mesh(2)
1560 i_x_start_bin = i_x_start
1561 i_x_end_bin = i_x_end
1562 i_y_start_bin = i_y_start
1563 i_y_end_bin = i_y_end
1566 ALLOCATE (ldos_2d_bins(i_x_start_bin:i_x_end_bin, i_y_start_bin:i_y_end_bin, n_e))
1567 ldos_2d_bins(:, :, :) = 0.0_dp
1569 IF (do_xy_bins)
THEN
1571 i_x_start_glob = i_x_start
1572 i_x_end_glob = i_x_end
1573 i_y_start_glob = i_y_start
1574 i_y_end_glob = i_y_end
1576 CALL bs_env%para_env%min(i_x_start_glob)
1577 CALL bs_env%para_env%max(i_x_end_glob)
1578 CALL bs_env%para_env%min(i_y_start_glob)
1579 CALL bs_env%para_env%max(i_y_end_glob)
1581 ALLOCATE (n_sum_for_bins(bin_mesh(1), bin_mesh(2)), source=0)
1584 DO i_y = i_y_start, i_y_end
1585 DO i_x = i_x_start, i_x_end
1586 i_x_bin = bin_mesh(1)*(i_x - i_x_start_glob)/(i_x_end_glob - i_x_start_glob + 1) + 1
1587 i_y_bin = bin_mesh(2)*(i_y - i_y_start_glob)/(i_y_end_glob - i_y_start_glob + 1) + 1
1588 ldos_2d_bins(i_x_bin, i_y_bin, :) = ldos_2d_bins(i_x_bin, i_y_bin, :) + &
1589 ldos_2d(i_x, i_y, :)
1590 n_sum_for_bins(i_x_bin, i_y_bin) = n_sum_for_bins(i_x_bin, i_y_bin) + 1
1594 CALL bs_env%para_env%sum(ldos_2d_bins)
1595 CALL bs_env%para_env%sum(n_sum_for_bins)
1598 DO i_y_bin = 1, bin_mesh(2)
1599 DO i_x_bin = 1, bin_mesh(1)
1600 ldos_2d_bins(i_x_bin, i_y_bin, :) = ldos_2d_bins(i_x_bin, i_y_bin, :)/ &
1601 REAL(n_sum_for_bins(i_x_bin, i_y_bin), kind=
dp)
1607 ldos_2d_bins(:, :, :) = ldos_2d(:, :, :)
1611 IF (bin_mesh(1)*bin_mesh(2) < bs_env%n_bins_max_for_printing)
THEN
1612 CALL print_ldos_2d_bins(ldos_2d_bins, bs_env, e_min, scf_gw_soc)
1614 cpwarn(
"The number of bins for the LDOS is too large. Decrease BIN_MESH.")
1617 CALL timestop(handle)
1619 END SUBROUTINE print_ldos_main
1628 SUBROUTINE print_ldos_2d_bins(LDOS_2d_bins, bs_env, E_min, scf_gw_soc)
1629 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :, :) :: ldos_2d_bins
1631 REAL(kind=
dp) :: e_min
1632 CHARACTER(LEN=*) :: scf_gw_soc
1634 CHARACTER(LEN=*),
PARAMETER :: routinen =
'print_LDOS_2d_bins'
1636 CHARACTER(LEN=18) :: print_format
1637 CHARACTER(LEN=4) :: print_format_1, print_format_2
1638 CHARACTER(len=default_string_length) :: fname
1639 INTEGER :: handle, i_e, i_x, i_x_end, i_x_start, &
1640 i_y, i_y_end, i_y_start, iunit, n_e, &
1642 REAL(kind=
dp) :: energy
1643 REAL(kind=
dp),
DIMENSION(3) :: coord,
idx
1645 CALL timeset(routinen, handle)
1647 i_x_start = lbound(ldos_2d_bins, 1)
1648 i_x_end = ubound(ldos_2d_bins, 1)
1649 i_y_start = lbound(ldos_2d_bins, 2)
1650 i_y_end = ubound(ldos_2d_bins, 2)
1651 n_e =
SIZE(ldos_2d_bins, 3)
1653 n_x = i_x_end - i_x_start + 1
1654 n_y = i_y_end - i_y_start + 1
1656 IF (bs_env%para_env%is_source())
THEN
1658 DO i_y = i_y_start, i_y_end
1659 DO i_x = i_x_start, i_x_end
1661 idx(1) = (real(i_x, kind=
dp) - 0.5_dp)/real(n_x, kind=
dp)
1662 idx(2) = (real(i_y, kind=
dp) - 0.5_dp)/real(n_y, kind=
dp)
1664 coord(1:3) = matmul(bs_env%hmat,
idx)
1666 CALL get_print_format(coord(1), print_format_1)
1667 CALL get_print_format(coord(2), print_format_2)
1669 print_format =
"(3A,"//print_format_1//
",A,"//print_format_2//
",A)"
1671 WRITE (fname, print_format)
"LDOS_", scf_gw_soc, &
1674 CALL open_file(trim(fname), unit_number=iunit, file_status=
"REPLACE", &
1675 file_action=
"WRITE")
1677 WRITE (iunit,
"(2A)")
" Energy E (eV) average LDOS(x,y,E) (1/(eV*Å^2), ", &
1678 "integrated over z, averaged inside bin)"
1681 energy = e_min + i_e*bs_env%energy_step_DOS
1682 WRITE (iunit,
"(2F17.3)") energy*
evolt, &
1683 ldos_2d_bins(i_x, i_y, i_e)* &
1684 bs_env%unit_ldos_int_z_inv_Ang2_eV
1694 CALL timestop(handle)
1696 END SUBROUTINE print_ldos_2d_bins
1703 SUBROUTINE get_print_format(coord, print_format)
1704 REAL(kind=
dp) :: coord
1705 CHARACTER(LEN=4) :: print_format
1707 CHARACTER(LEN=*),
PARAMETER :: routinen =
'get_print_format'
1711 CALL timeset(routinen, handle)
1714 print_format =
"F9.2"
1715 ELSE IF (coord < -1000/
angstrom)
THEN
1716 print_format =
"F8.2"
1717 ELSE IF (coord < -100/
angstrom)
THEN
1718 print_format =
"F7.2"
1719 ELSE IF (coord < -10/
angstrom)
THEN
1720 print_format =
"F6.2"
1722 print_format =
"F5.2"
1724 print_format =
"F4.2"
1725 ELSE IF (coord < 100/
angstrom)
THEN
1726 print_format =
"F5.2"
1727 ELSE IF (coord < 1000/
angstrom)
THEN
1728 print_format =
"F6.2"
1729 ELSE IF (coord < 10000/
angstrom)
THEN
1730 print_format =
"F7.2"
1732 print_format =
"F8.2"
1735 CALL timestop(handle)
1737 END SUBROUTINE get_print_format
1753 SUBROUTINE soc_ev(bs_env, qs_env, ikp, eigenval_no_SOC, E_min, cfm_mos_ikp, &
1754 DOS, PDOS, band_edges, eigenval_spinor, cfm_spinor_wf_ikp)
1759 REAL(kind=
dp),
DIMENSION(:, :, :) :: eigenval_no_soc
1760 REAL(kind=
dp) :: e_min
1762 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: dos
1763 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: pdos
1765 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: eigenval_spinor
1768 CHARACTER(LEN=*),
PARAMETER :: routinen =
'SOC_ev'
1770 INTEGER :: handle, homo_spinor, n_ao, n_e, nkind
1771 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: eigenval_spinor_no_soc
1772 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: proj_mo_on_kind_spinor
1774 cfm_ks_ikp_spinor, cfm_mos_ikp_spinor, &
1775 cfm_soc_ikp_spinor, cfm_work_ikp_spinor
1779 CALL timeset(routinen, handle)
1782 homo_spinor = bs_env%n_occ(1) + bs_env%n_occ(bs_env%n_spin)
1785 CALL cp_cfm_create(cfm_ks_ikp_spinor, bs_env%cfm_SOC_spinor_ao(1)%matrix_struct)
1786 CALL cp_cfm_create(cfm_soc_ikp_spinor, bs_env%cfm_SOC_spinor_ao(1)%matrix_struct)
1787 CALL cp_cfm_create(cfm_mos_ikp_spinor, bs_env%cfm_SOC_spinor_ao(1)%matrix_struct)
1788 CALL cp_cfm_create(cfm_work_ikp_spinor, bs_env%cfm_SOC_spinor_ao(1)%matrix_struct)
1789 CALL cp_cfm_create(cfm_eigenvec_ikp_spinor, bs_env%cfm_SOC_spinor_ao(1)%matrix_struct)
1791 ALLOCATE (eigenval_spinor_no_soc(2*n_ao))
1792 ALLOCATE (proj_mo_on_kind_spinor(2*n_ao, nkind))
1794 proj_mo_on_kind_spinor(:, :) = 0.0_dp
1797 SELECT CASE (bs_env%small_cell_full_kp_or_large_cell_Gamma)
1801 CALL cfm_ikp_from_cfm_spinor_gamma(cfm_soc_ikp_spinor, &
1802 bs_env%cfm_SOC_spinor_ao(1), &
1803 bs_env%fm_s_Gamma%matrix_struct, &
1804 ikp, qs_env, bs_env%kpoints_DOS,
"ORB")
1809 CALL cp_cfm_to_cfm(bs_env%cfm_SOC_spinor_ao(ikp), cfm_soc_ikp_spinor)
1819 CALL add_cfm_submat(cfm_mos_ikp_spinor, cfm_mos_ikp(bs_env%n_spin), n_ao + 1, n_ao + 1)
1823 cfm_mos_ikp_spinor, cfm_soc_ikp_spinor, &
1824 z_zero, cfm_work_ikp_spinor)
1828 cfm_work_ikp_spinor, cfm_mos_ikp_spinor, &
1829 z_zero, cfm_ks_ikp_spinor)
1834 eigenval_spinor_no_soc(1:n_ao) = eigenval_no_soc(1:n_ao, ikp, 1)
1835 eigenval_spinor_no_soc(n_ao + 1:) = eigenval_no_soc(1:n_ao, ikp, bs_env%n_spin)
1836 IF (bs_env%soc_window_occ > 0.0_dp .OR. bs_env%soc_window_virt > 0.0_dp)
THEN
1838 bs_env%soc_window_virt, &
1839 bs_env%soc_window_smearing, &
1840 eigenval_spinor_no_soc, &
1849 CALL cp_cfm_heevd(cfm_ks_ikp_spinor, cfm_eigenvec_ikp_spinor, eigenval_spinor)
1852 IF (bs_env%do_dos_pdos)
THEN
1854 CALL add_to_dos_pdos(dos, pdos, eigenval_spinor, &
1855 ikp, bs_env, n_e, e_min, proj_mo_on_kind_spinor)
1859 band_edges%VBM = max(band_edges%VBM, eigenval_spinor(homo_spinor))
1860 band_edges%CBM = min(band_edges%CBM, eigenval_spinor(homo_spinor + 1))
1861 band_edges%DBG = min(band_edges%DBG, eigenval_spinor(homo_spinor + 1) &
1862 - eigenval_spinor(homo_spinor))
1866 cfm_mos_ikp_spinor, cfm_eigenvec_ikp_spinor, &
1867 z_zero, cfm_spinor_wf_ikp)
1875 CALL timestop(handle)
1877 END SUBROUTINE soc_ev
1890 SUBROUTINE add_to_dos_pdos(DOS, PDOS, eigenval, ikp, bs_env, n_E, E_min, proj_mo_on_kind)
1892 REAL(kind=
dp),
DIMENSION(:) :: dos
1893 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: pdos
1894 REAL(kind=
dp),
DIMENSION(:) :: eigenval
1898 REAL(kind=
dp) :: e_min
1899 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: proj_mo_on_kind
1901 CHARACTER(LEN=*),
PARAMETER :: routinen =
'add_to_DOS_PDOS'
1903 INTEGER :: handle, i_e, i_kind, i_mo, n_mo, nkind
1904 REAL(kind=
dp) :: broadening, energy, energy_step_dos, wkp
1906 CALL timeset(routinen, handle)
1908 energy_step_dos = bs_env%energy_step_DOS
1909 broadening = bs_env%broadening_DOS
1911 n_mo =
SIZE(eigenval)
1912 nkind =
SIZE(proj_mo_on_kind, 2)
1915 wkp = bs_env%kpoints_DOS%wkp(ikp)*bs_env%spin_degeneracy
1917 energy = e_min + i_e*energy_step_dos
1920 dos(i_e) = dos(i_e) + wkp*
gaussian(energy - eigenval(i_mo), broadening)
1923 DO i_kind = 1, nkind
1924 IF (proj_mo_on_kind(i_mo, i_kind) > 0.0_dp)
THEN
1925 pdos(i_e, i_kind) = pdos(i_e, i_kind) + &
1926 proj_mo_on_kind(i_mo, i_kind)*wkp* &
1927 gaussian(energy - eigenval(i_mo), broadening)
1933 CALL timestop(handle)
1935 END SUBROUTINE add_to_dos_pdos
1949 SUBROUTINE add_to_ldos_2d(LDOS_2d, qs_env, ikp, bs_env, cfm_mos_ikp, eigenval, &
1950 band_edges, do_spinor, cfm_non_spinor)
1951 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :, :) :: ldos_2d
1956 REAL(kind=
dp),
DIMENSION(:) :: eigenval
1958 LOGICAL,
OPTIONAL :: do_spinor
1961 CHARACTER(LEN=*),
PARAMETER :: routinen =
'add_to_LDOS_2d'
1963 INTEGER :: handle, i_e, i_x_end, i_x_start, i_y_end, i_y_start, i_z, i_z_end, i_z_start, &
1964 j_col, j_mo, n_e, n_mo, n_z, ncol_local, nimages, z_end_global, z_start_global
1965 INTEGER,
DIMENSION(:),
POINTER :: col_indices
1966 LOGICAL :: is_any_weight_non_zero, my_do_spinor
1967 REAL(kind=
dp) :: broadening, e_max, e_min, &
1968 e_total_window, energy, energy_step, &
1969 energy_window, spin_degeneracy, weight
1970 TYPE(
cp_cfm_type) :: cfm_weighted_dm_ikp, cfm_work
1971 TYPE(
cp_fm_type) :: fm_non_spinor, fm_weighted_dm_mic
1972 TYPE(
dbcsr_p_type),
DIMENSION(:),
POINTER :: weighted_dm_mic
1980 CALL timeset(routinen, handle)
1982 my_do_spinor = .false.
1983 IF (
PRESENT(do_spinor)) my_do_spinor = do_spinor
1985 CALL get_qs_env(qs_env, ks_env=ks_env, pw_env=pw_env, dft_control=dft_control)
1988 nimages = dft_control%nimages
1989 dft_control%nimages = bs_env%nimages_scf
1991 energy_window = bs_env%energy_window_DOS
1992 energy_step = bs_env%energy_step_DOS
1993 broadening = bs_env%broadening_DOS
1995 e_min = band_edges%VBM - 0.5_dp*energy_window
1996 e_max = band_edges%CBM + 0.5_dp*energy_window
1997 e_total_window = e_max - e_min
1999 n_e = int(e_total_window/energy_step)
2001 CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool)
2003 CALL auxbas_pw_pool%create_pw(ldos_3d)
2004 CALL auxbas_pw_pool%create_pw(rho_g)
2006 i_x_start = lbound(ldos_3d%array, 1)
2007 i_x_end = ubound(ldos_3d%array, 1)
2008 i_y_start = lbound(ldos_3d%array, 2)
2009 i_y_end = ubound(ldos_3d%array, 2)
2010 i_z_start = lbound(ldos_3d%array, 3)
2011 i_z_end = ubound(ldos_3d%array, 3)
2013 z_start_global = i_z_start
2014 z_end_global = i_z_end
2016 CALL bs_env%para_env%min(z_start_global)
2017 CALL bs_env%para_env%max(z_end_global)
2018 n_z = z_end_global - z_start_global + 1
2020 IF (any(abs(bs_env%hmat(1:2, 3)) > 1.0e-6_dp) .OR. any(abs(bs_env%hmat(3, 1:2)) > 1.0e-6_dp))
THEN
2021 cpabort(
"Please choose a cell that has 90° angles to the z-direction.")
2024 bs_env%unit_ldos_int_z_inv_Ang2_eV = bs_env%hmat(3, 3)/real(n_z, kind=
dp)/
evolt/
angstrom**2
2027 ALLOCATE (ldos_2d(i_x_start:i_x_end, i_y_start:i_y_end, n_e))
2028 ldos_2d(:, :, :) = 0.0_dp
2032 CALL cp_cfm_create(cfm_weighted_dm_ikp, cfm_mos_ikp%matrix_struct)
2033 CALL cp_fm_create(fm_weighted_dm_mic, cfm_mos_ikp%matrix_struct)
2034 IF (my_do_spinor)
THEN
2035 CALL cp_fm_create(fm_non_spinor, cfm_non_spinor%matrix_struct)
2040 ncol_local=ncol_local, &
2041 col_indices=col_indices)
2043 NULLIFY (weighted_dm_mic)
2045 ALLOCATE (weighted_dm_mic(1)%matrix)
2046 CALL dbcsr_create(weighted_dm_mic(1)%matrix, template=bs_env%mat_ao_ao%matrix, &
2047 matrix_type=dbcsr_type_symmetric)
2051 energy = e_min + i_e*energy_step
2053 is_any_weight_non_zero = .false.
2055 DO j_col = 1, ncol_local
2057 j_mo = col_indices(j_col)
2059 IF (my_do_spinor)
THEN
2060 spin_degeneracy = 1.0_dp
2062 spin_degeneracy = bs_env%spin_degeneracy
2065 weight =
gaussian(energy - eigenval(j_mo), broadening)*spin_degeneracy
2067 cfm_work%local_data(:, j_col) = cfm_mos_ikp%local_data(:, j_col)*weight
2069 IF (weight > 1.0e-5_dp) is_any_weight_non_zero = .true.
2073 CALL bs_env%para_env%sync()
2074 CALL bs_env%para_env%sum(is_any_weight_non_zero)
2075 CALL bs_env%para_env%sync()
2078 IF (is_any_weight_non_zero)
THEN
2081 cfm_mos_ikp, cfm_work,
z_zero, cfm_weighted_dm_ikp)
2083 IF (my_do_spinor)
THEN
2089 cfm_non_spinor, ikp, bs_env%kpoints_DOS, &
2090 "ORB", bs_env%kpoints_DOS%wkp(ikp))
2093 CALL get_cfm_submat(cfm_non_spinor, cfm_weighted_dm_ikp, n_mo/2, n_mo/2)
2095 cfm_non_spinor, ikp, bs_env%kpoints_DOS, &
2096 "ORB", bs_env%kpoints_DOS%wkp(ikp))
2098 keep_sparsity=.false.)
2102 cfm_weighted_dm_ikp, ikp, bs_env%kpoints_DOS, &
2103 "ORB", bs_env%kpoints_DOS%wkp(ikp))
2105 keep_sparsity=.false.)
2108 ldos_3d%array(:, :, :) = 0.0_dp
2115 DO i_z = i_z_start, i_z_end
2116 ldos_2d(:, :, i_e) = ldos_2d(:, :, i_e) + ldos_3d%array(:, :, i_z)
2124 dft_control%nimages = nimages
2126 CALL auxbas_pw_pool%give_back_pw(ldos_3d)
2127 CALL auxbas_pw_pool%give_back_pw(rho_g)
2136 IF (my_do_spinor)
THEN
2140 CALL timestop(handle)
2142 END SUBROUTINE add_to_ldos_2d
2152 SUBROUTINE write_soc_eigenvalues(eigenval_spinor, ikp_for_file, ikp, bs_env, eigenval_spinor_G0W0)
2154 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: eigenval_spinor
2155 INTEGER :: ikp_for_file, ikp
2157 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:),
OPTIONAL :: eigenval_spinor_g0w0
2159 CHARACTER(LEN=*),
PARAMETER :: routinen =
'write_SOC_eigenvalues'
2161 CHARACTER(len=3) :: occ_vir
2162 CHARACTER(LEN=default_string_length) :: fname
2163 INTEGER :: handle, i_mo, iunit, n_occ_spinor
2165 CALL timeset(routinen, handle)
2167 fname =
"bandstructure_SCF_and_G0W0_plus_SOC"
2169 IF (bs_env%para_env%is_source())
THEN
2171 IF (ikp_for_file == 1)
THEN
2172 CALL open_file(trim(fname), unit_number=iunit, file_status=
"REPLACE", &
2173 file_action=
"WRITE")
2175 CALL open_file(trim(fname), unit_number=iunit, file_status=
"OLD", &
2176 file_action=
"WRITE", file_position=
"APPEND")
2179 WRITE (iunit,
"(A)")
" "
2180 WRITE (iunit,
"(A10,I7,A25,3F10.4)")
"kpoint: ", ikp_for_file,
"coordinate: ", &
2181 bs_env%kpoints_DOS%xkp(:, ikp)
2182 WRITE (iunit,
"(A)")
" "
2184 IF (
PRESENT(eigenval_spinor_g0w0))
THEN
2186 WRITE (iunit,
"(A5,A12,2A22)")
"n",
"k",
"ϵ_nk^DFT+SOC (eV)",
"ϵ_nk^G0W0+SOC (eV)"
2189 WRITE (iunit,
"(A5,A12,A22)")
"n",
"k",
"ϵ_nk^DFT+SOC (eV)"
2192 n_occ_spinor = bs_env%n_occ(1) + bs_env%n_occ(bs_env%n_spin)
2194 DO i_mo = 1,
SIZE(eigenval_spinor)
2195 IF (i_mo <= n_occ_spinor) occ_vir =
'occ'
2196 IF (i_mo > n_occ_spinor) occ_vir =
'vir'
2197 IF (
PRESENT(eigenval_spinor_g0w0))
THEN
2199 WRITE (iunit,
"(I5,3A,I5,4F16.3,2F17.3)") i_mo,
' (', occ_vir,
') ', &
2200 ikp_for_file, eigenval_spinor(i_mo)*
evolt, eigenval_spinor_g0w0(i_mo)*
evolt
2203 WRITE (iunit,
"(I5,3A,I5,4F16.3,F17.3)") i_mo,
' (', occ_vir,
') ', &
2204 ikp_for_file, eigenval_spinor(i_mo)*
evolt
2212 CALL timestop(handle)
2214 END SUBROUTINE write_soc_eigenvalues
2221 PURE FUNCTION count_digits(int_number)
2223 INTEGER,
INTENT(IN) :: int_number
2224 INTEGER :: count_digits
2226 INTEGER :: digitcount, tempint
2230 tempint = int_number
2232 DO WHILE (tempint /= 0)
2233 tempint = tempint/10
2234 digitcount = digitcount + 1
2237 count_digits = digitcount
2239 END FUNCTION count_digits
2247 SUBROUTINE write_band_edges(band_edges, scf_gw_soc, bs_env)
2250 CHARACTER(LEN=*) :: scf_gw_soc
2253 CHARACTER(LEN=*),
PARAMETER :: routinen =
'write_band_edges'
2255 CHARACTER(LEN=17) :: print_format
2256 INTEGER :: handle, u
2258 CALL timeset(routinen, handle)
2261 print_format =
"(T2,2A,T61,F20.3)"
2265 WRITE (u,
'(T2,A)')
''
2266 WRITE (u, print_format) scf_gw_soc,
' valence band maximum (eV):', band_edges%VBM*
evolt
2267 WRITE (u, print_format) scf_gw_soc,
' conduction band minimum (eV):', band_edges%CBM*
evolt
2268 WRITE (u, print_format) scf_gw_soc,
' indirect band gap (eV):', band_edges%IDBG*
evolt
2269 WRITE (u, print_format) scf_gw_soc,
' direct band gap (eV):', band_edges%DBG*
evolt
2272 CALL timestop(handle)
2274 END SUBROUTINE write_band_edges
2286 SUBROUTINE write_dos_pdos(DOS, PDOS, bs_env, qs_env, scf_gw_soc, E_min, E_VBM)
2287 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: dos
2288 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: pdos
2291 CHARACTER(LEN=*) :: scf_gw_soc
2292 REAL(kind=
dp) :: e_min, e_vbm
2294 CHARACTER(LEN=*),
PARAMETER :: routinen =
'write_dos_pdos'
2296 CHARACTER(LEN=3),
DIMENSION(100) :: elements
2297 CHARACTER(LEN=default_string_length) :: atom_name, fname, output_string
2298 INTEGER :: handle, i_e, i_kind, iatom, iunit, n_a, &
2300 REAL(kind=
dp) :: energy
2303 CALL timeset(routinen, handle)
2305 WRITE (fname,
"(3A)")
"DOS_PDOS_", scf_gw_soc,
".out"
2308 nkind =
SIZE(pdos, 2)
2309 CALL get_qs_env(qs_env, particle_set=particle_set)
2311 IF (bs_env%para_env%is_source())
THEN
2313 CALL open_file(trim(fname), unit_number=iunit, file_status=
"REPLACE", file_action=
"WRITE")
2317 DO iatom = 1, bs_env%n_atom
2319 kind_number=i_kind, name=atom_name)
2320 elements(i_kind) = atom_name(1:3)
2323 WRITE (output_string,
"(A,I1,A)")
"(", n_a,
"A)"
2325 WRITE (iunit, trim(output_string))
"Energy-E_F (eV) DOS (1/eV) PDOS (1/eV) ", &
2326 " of atom type ", elements(1:nkind)
2328 WRITE (output_string,
"(A,I1,A)")
"(", n_a,
"F13.5)"
2332 energy = e_min + i_e*bs_env%energy_step_DOS - e_vbm
2333 WRITE (iunit, trim(output_string)) energy*
evolt, dos(i_e)/
evolt, pdos(i_e, :)/
evolt
2340 CALL timestop(handle)
2342 END SUBROUTINE write_dos_pdos
2350 PURE FUNCTION gaussian(energy, broadening)
2352 REAL(kind=
dp),
INTENT(IN) :: energy, broadening
2355 IF (abs(energy) < 5*broadening)
THEN
2356 gaussian = 1.0_dp/broadening/sqrt(
twopi)*exp(-0.5_dp*energy**2/broadening**2)
2370 SUBROUTINE compute_proj_mo_on_kind(proj_mo_on_kind, qs_env, cfm_mos, cfm_s)
2371 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: proj_mo_on_kind
2375 CHARACTER(LEN=*),
PARAMETER :: routinen =
'compute_proj_mo_on_kind'
2377 INTEGER :: handle, i_atom, i_global, i_kind, i_row, &
2378 j_col, n_ao, n_mo, ncol_local, nkind, &
2380 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: atom_from_bf, kind_of
2381 INTEGER,
DIMENSION(:),
POINTER :: col_indices, row_indices
2383 TYPE(
cp_cfm_type) :: cfm_proj, cfm_s_i_kind, cfm_work
2386 CALL timeset(routinen, handle)
2388 CALL get_qs_env(qs_env, atomic_kind_set=atomic_kind_set, nkind=nkind)
2393 nrow_local=nrow_local, &
2394 ncol_local=ncol_local, &
2395 row_indices=row_indices, &
2396 col_indices=col_indices)
2398 n_ao = qs_env%bs_env%n_ao
2400 ALLOCATE (atom_from_bf(n_ao))
2403 proj_mo_on_kind(:, :) = 0.0_dp
2411 DO i_kind = 1, nkind
2416 DO j_col = 1, ncol_local
2417 DO i_row = 1, nrow_local
2419 i_global = row_indices(i_row)
2421 IF (i_global <= n_ao)
THEN
2422 i_atom = atom_from_bf(i_global)
2423 ELSE IF (i_global <= 2*n_ao)
THEN
2424 i_atom = atom_from_bf(i_global - n_ao)
2426 cpabort(
"Wrong indices.")
2429 IF (i_kind /= kind_of(i_atom))
THEN
2430 cfm_s_i_kind%local_data(i_row, j_col) =
z_zero
2437 cfm_s_i_kind, cfm_mos,
z_zero, cfm_work)
2439 cfm_mos, cfm_work,
z_zero, cfm_proj)
2454 CALL timestop(handle)
2456 END SUBROUTINE compute_proj_mo_on_kind
2468 SUBROUTINE cfm_ikp_from_cfm_spinor_gamma(cfm_spinor_ikp, cfm_spinor_Gamma, fm_struct_non_spinor, &
2469 ikp, qs_env, kpoints, basis_type)
2470 TYPE(
cp_cfm_type) :: cfm_spinor_ikp, cfm_spinor_gamma
2475 CHARACTER(LEN=*) :: basis_type
2477 CHARACTER(LEN=*),
PARAMETER :: routinen =
'cfm_ikp_from_cfm_spinor_Gamma'
2479 INTEGER :: handle, i_block, i_offset, j_block, &
2481 TYPE(
cp_cfm_type) :: cfm_non_spinor_gamma, cfm_non_spinor_ikp
2482 TYPE(
cp_fm_type) :: fm_non_spinor_gamma_im, &
2483 fm_non_spinor_gamma_re
2485 CALL timeset(routinen, handle)
2487 CALL cp_cfm_create(cfm_non_spinor_gamma, fm_struct_non_spinor)
2488 CALL cp_cfm_create(cfm_non_spinor_ikp, fm_struct_non_spinor)
2489 CALL cp_fm_create(fm_non_spinor_gamma_re, fm_struct_non_spinor)
2490 CALL cp_fm_create(fm_non_spinor_gamma_im, fm_struct_non_spinor)
2498 i_offset = i_block*n_ao + 1
2499 j_offset = j_block*n_ao + 1
2500 CALL get_cfm_submat(cfm_non_spinor_gamma, cfm_spinor_gamma, i_offset, j_offset)
2501 CALL cp_cfm_to_fm(cfm_non_spinor_gamma, fm_non_spinor_gamma_re, fm_non_spinor_gamma_im)
2505 ikp, qs_env, kpoints, basis_type)
2506 CALL add_cfm_submat(cfm_spinor_ikp, cfm_non_spinor_ikp, i_offset, j_offset)
2510 ikp, qs_env, kpoints, basis_type)
2521 CALL timestop(handle)
2523 END SUBROUTINE cfm_ikp_from_cfm_spinor_gamma
2540 CHARACTER(LEN=*) :: basis_type
2542 CHARACTER(LEN=*),
PARAMETER :: routinen =
'cfm_ikp_from_fm_Gamma'
2544 INTEGER :: col_global, handle, i_atom, i_atom_old, i_cell, i_mic_cell, i_row, j_atom, &
2545 j_atom_old, j_cell, j_col, n_bf, ncol_local, nrow_local, num_cells, row_global
2546 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: atom_from_bf
2547 INTEGER,
DIMENSION(:),
POINTER :: col_indices, row_indices
2548 INTEGER,
DIMENSION(:, :),
POINTER :: index_to_cell
2549 LOGICAL :: i_cell_is_the_minimum_image_cell
2550 REAL(kind=
dp) :: abs_rab_cell_i, abs_rab_cell_j, arg
2551 REAL(kind=
dp),
DIMENSION(3) :: cell_vector, cell_vector_j, rab_cell_i, &
2553 REAL(kind=
dp),
DIMENSION(3, 3) :: hmat
2557 CALL timeset(routinen, handle)
2559 IF (.NOT.
ASSOCIATED(cfm_ikp%local_data))
THEN
2565 nrow_local=nrow_local, &
2566 ncol_local=ncol_local, &
2567 row_indices=row_indices, &
2568 col_indices=col_indices)
2571 IF (basis_type ==
"ORB")
THEN
2572 n_bf = qs_env%bs_env%n_ao
2573 ELSE IF (basis_type ==
"RI_AUX")
THEN
2574 n_bf = qs_env%bs_env%n_RI
2576 cpabort(
"Only ORB and RI_AUX basis implemented.")
2579 ALLOCATE (atom_from_bf(n_bf))
2582 NULLIFY (cell, particle_set)
2583 CALL get_qs_env(qs_env, cell=cell, particle_set=particle_set)
2586 index_to_cell => kpoints%index_to_cell
2588 num_cells =
SIZE(index_to_cell, 2)
2592 DO j_col = 1, ncol_local
2593 DO i_row = 1, nrow_local
2595 row_global = row_indices(i_row)
2596 col_global = col_indices(j_col)
2598 i_atom = atom_from_bf(row_global)
2599 j_atom = atom_from_bf(col_global)
2602 IF (i_atom /= i_atom_old .OR. j_atom /= j_atom_old)
THEN
2603 DO i_cell = 1, num_cells
2606 IF (any(abs(index_to_cell(1:3, i_cell)) > 1)) cycle
2608 cell_vector(1:3) = matmul(hmat, real(index_to_cell(1:3, i_cell),
dp))
2610 rab_cell_i(1:3) =
pbc(particle_set(i_atom)%r(1:3), cell) - &
2611 (
pbc(particle_set(j_atom)%r(1:3), cell) + cell_vector(1:3))
2612 abs_rab_cell_i = sqrt(rab_cell_i(1)**2 + rab_cell_i(2)**2 + rab_cell_i(3)**2)
2615 i_cell_is_the_minimum_image_cell = .true.
2616 DO j_cell = 1, num_cells
2617 cell_vector_j(1:3) = matmul(hmat, real(index_to_cell(1:3, j_cell),
dp))
2618 rab_cell_j(1:3) =
pbc(particle_set(i_atom)%r(1:3), cell) - &
2619 (
pbc(particle_set(j_atom)%r(1:3), cell) + cell_vector_j(1:3))
2620 abs_rab_cell_j = sqrt(rab_cell_j(1)**2 + rab_cell_j(2)**2 + rab_cell_j(3)**2)
2622 IF (abs_rab_cell_i > abs_rab_cell_j + 1.0e-6_dp)
THEN
2623 i_cell_is_the_minimum_image_cell = .false.
2627 IF (i_cell_is_the_minimum_image_cell)
THEN
2634 arg = real(index_to_cell(1, i_mic_cell),
dp)*kpoints%xkp(1, ikp) + &
2635 REAL(index_to_cell(2, i_mic_cell),
dp)*kpoints%xkp(2, ikp) + &
2636 REAL(index_to_cell(3, i_mic_cell),
dp)*kpoints%xkp(3, ikp)
2638 cfm_ikp%local_data(i_row, j_col) = cos(
twopi*arg)*fm_gamma%local_data(i_row, j_col)*
z_one + &
2639 sin(
twopi*arg)*fm_gamma%local_data(i_row, j_col)*
gaussi
2647 CALL timestop(handle)
2663 cfm_W_ikp_freq_j, ikp, kpoints, basis_type, wkp_ext)
2668 INTEGER,
INTENT(IN) :: ikp
2670 CHARACTER(LEN=*) :: basis_type
2671 REAL(kind=
dp),
OPTIONAL :: wkp_ext
2673 CHARACTER(LEN=*),
PARAMETER :: routinen =
'MIC_contribution_from_ikp'
2675 INTEGER :: handle, i_bf, iatom, iatom_old, irow, &
2676 j_bf, jatom, jatom_old, jcol, n_bf, &
2677 ncol_local, nrow_local, num_cells
2678 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: atom_from_bf_index
2679 INTEGER,
DIMENSION(:),
POINTER :: col_indices, row_indices
2680 INTEGER,
DIMENSION(:, :),
POINTER :: index_to_cell
2681 REAL(kind=
dp) :: contribution, weight_im, weight_re, &
2683 REAL(kind=
dp),
DIMENSION(3, 3) :: hmat
2684 REAL(kind=
dp),
DIMENSION(:),
POINTER :: wkp
2685 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: xkp
2689 CALL timeset(routinen, handle)
2692 IF (basis_type ==
"ORB")
THEN
2693 n_bf = qs_env%bs_env%n_ao
2694 ELSE IF (basis_type ==
"RI_AUX")
THEN
2695 n_bf = qs_env%bs_env%n_RI
2697 cpabort(
"Only ORB and RI_AUX basis implemented.")
2700 ALLOCATE (atom_from_bf_index(n_bf))
2703 NULLIFY (cell, particle_set)
2704 CALL get_qs_env(qs_env, cell=cell, particle_set=particle_set)
2708 nrow_local=nrow_local, &
2709 ncol_local=ncol_local, &
2710 row_indices=row_indices, &
2711 col_indices=col_indices)
2714 index_to_cell => kpoints%index_to_cell
2715 num_cells =
SIZE(index_to_cell, 2)
2720 DO jcol = 1, ncol_local
2721 DO irow = 1, nrow_local
2723 i_bf = row_indices(irow)
2724 j_bf = col_indices(jcol)
2726 iatom = atom_from_bf_index(i_bf)
2727 jatom = atom_from_bf_index(j_bf)
2729 IF (
PRESENT(wkp_ext))
THEN
2730 wkp_of_ikp = wkp_ext
2732 SELECT CASE (bs_env%l_RI(i_bf) + bs_env%l_RI(j_bf))
2735 wkp_of_ikp = wkp(ikp)
2738 wkp_of_ikp = bs_env%wkp_s_p(ikp)
2741 wkp_of_ikp = bs_env%wkp_no_extra(ikp)
2745 IF (iatom /= iatom_old .OR. jatom /= jatom_old)
THEN
2748 num_cells, iatom, jatom, xkp(1:3, ikp), wkp_of_ikp, &
2749 cell, index_to_cell, hmat, particle_set)
2756 contribution = weight_re*real(cfm_w_ikp_freq_j%local_data(irow, jcol)) + &
2757 weight_im*aimag(cfm_w_ikp_freq_j%local_data(irow, jcol))
2759 fm_w_mic_freq_j%local_data(irow, jcol) = fm_w_mic_freq_j%local_data(irow, jcol) &
2765 CALL timestop(handle)
2778 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: xkp
2779 INTEGER :: ikp_start, ikp_end
2780 INTEGER,
DIMENSION(3) :: grid
2782 CHARACTER(LEN=*),
PARAMETER :: routinen =
'compute_xkp'
2784 INTEGER :: handle, i, ix, iy, iz
2786 CALL timeset(routinen, handle)
2793 IF (i > ikp_end) cycle
2795 xkp(1, i) = real(2*ix - grid(1) - 1, kind=
dp)/(2._dp*real(grid(1), kind=
dp))
2796 xkp(2, i) = real(2*iy - grid(2) - 1, kind=
dp)/(2._dp*real(grid(2), kind=
dp))
2797 xkp(3, i) = real(2*iz - grid(3) - 1, kind=
dp)/(2._dp*real(grid(3), kind=
dp))
2804 CALL timestop(handle)
2818 CHARACTER(LEN=*),
PARAMETER :: routinen =
'kpoint_init_cell_index_simple'
2820 INTEGER :: handle, nimages
2825 CALL timeset(routinen, handle)
2827 NULLIFY (para_env, sab_orb)
2828 CALL get_qs_env(qs_env=qs_env, para_env=para_env, sab_orb=sab_orb)
2831 CALL timestop(handle)
2840 SUBROUTINE soc(qs_env, bs_env)
2844 CHARACTER(LEN=*),
PARAMETER :: routinen =
'soc'
2848 CALL timeset(routinen, handle)
2856 SELECT CASE (bs_env%small_cell_full_kp_or_large_cell_Gamma)
2860 CALL h_ks_spinor_gamma(bs_env)
2865 CALL h_ks_spinor_kp(qs_env, bs_env)
2869 CALL timestop(handle)
2877 SUBROUTINE h_ks_spinor_gamma(bs_env)
2881 CHARACTER(LEN=*),
PARAMETER :: routinen =
'H_KS_spinor_Gamma'
2883 INTEGER :: handle, nao, s
2886 CALL timeset(routinen, handle)
2890 ALLOCATE (bs_env%cfm_SOC_spinor_ao(1))
2891 CALL create_cfm_double(bs_env%cfm_SOC_spinor_ao(1), fm_orig=bs_env%fm_ks_Gamma(1))
2894 str => bs_env%fm_ks_Gamma(1)%matrix_struct
2902 CALL add_dbcsr_submat(bs_env%cfm_SOC_spinor_ao(1), bs_env%mat_V_SOC_xyz(1, 1)%matrix, &
2903 str, 1, s,
z_one, .false.)
2905 CALL add_dbcsr_submat(bs_env%cfm_SOC_spinor_ao(1), bs_env%mat_V_SOC_xyz(1, 1)%matrix, &
2906 str, s, 1,
z_one, .false.)
2910 CALL add_dbcsr_submat(bs_env%cfm_SOC_spinor_ao(1), bs_env%mat_V_SOC_xyz(2, 1)%matrix, &
2911 str, 1, s,
gaussi, .false.)
2913 CALL add_dbcsr_submat(bs_env%cfm_SOC_spinor_ao(1), bs_env%mat_V_SOC_xyz(2, 1)%matrix, &
2914 str, s, 1, -
gaussi, .false.)
2918 CALL add_dbcsr_submat(bs_env%cfm_SOC_spinor_ao(1), bs_env%mat_V_SOC_xyz(3, 1)%matrix, &
2919 str, 1, 1,
z_one, .false.)
2921 CALL add_dbcsr_submat(bs_env%cfm_SOC_spinor_ao(1), bs_env%mat_V_SOC_xyz(3, 1)%matrix, &
2922 str, s, s, -
z_one, .false.)
2924 CALL timestop(handle)
2926 END SUBROUTINE h_ks_spinor_gamma
2933 SUBROUTINE h_ks_spinor_kp(qs_env, bs_env)
2937 CHARACTER(LEN=*),
PARAMETER :: routinen =
'H_KS_spinor_kp'
2939 INTEGER :: handle, i_dim, ikp, n_spin, &
2941 INTEGER,
DIMENSION(:, :, :),
POINTER :: cell_to_index_scf
2942 REAL(kind=
dp),
DIMENSION(3) :: xkp
2949 CALL timeset(routinen, handle)
2951 nkp_bs_and_dos = bs_env%nkp_bs_and_DOS
2952 n_spin = bs_env%n_spin
2954 str => bs_env%cfm_ks_kp(1, 1)%matrix_struct
2956 CALL cp_cfm_create(cfm_v_soc_xyz_ikp, bs_env%cfm_work_mo%matrix_struct)
2958 CALL alloc_cfm_double_array_1d(bs_env%cfm_SOC_spinor_ao, bs_env%cfm_ks_kp(1, 1), nkp_bs_and_dos)
2963 CALL get_kpoint_info(kpoints_scf, sab_nl=sab_nl, cell_to_index=cell_to_index_scf)
2967 DO ikp = 1, nkp_bs_and_dos
2969 xkp(1:3) = bs_env%kpoints_DOS%xkp(1:3, ikp)
2973 CALL rsmat_to_kp(bs_env%mat_V_SOC_xyz, i_dim, xkp, cell_to_index_scf, &
2974 sab_nl, bs_env, cfm_v_soc_xyz_ikp, imag_rs_mat=.true.)
2982 CALL add_cfm_submat(bs_env%cfm_SOC_spinor_ao(ikp), cfm_v_soc_xyz_ikp, 1, s)
2983 CALL add_cfm_submat(bs_env%cfm_SOC_spinor_ao(ikp), cfm_v_soc_xyz_ikp, s, 1)
2987 CALL add_cfm_submat(bs_env%cfm_SOC_spinor_ao(ikp), cfm_v_soc_xyz_ikp, 1, s)
2989 CALL add_cfm_submat(bs_env%cfm_SOC_spinor_ao(ikp), cfm_v_soc_xyz_ikp, s, 1)
2992 CALL add_cfm_submat(bs_env%cfm_SOC_spinor_ao(ikp), cfm_v_soc_xyz_ikp, 1, 1)
2994 CALL add_cfm_submat(bs_env%cfm_SOC_spinor_ao(ikp), cfm_v_soc_xyz_ikp, s, s)
3003 CALL timestop(handle)
3005 END SUBROUTINE h_ks_spinor_kp
3013 SUBROUTINE alloc_cfm_double_array_1d(cfm_array, cfm_template, n)
3014 TYPE(
cp_cfm_type),
ALLOCATABLE,
DIMENSION(:) :: cfm_array
3018 CHARACTER(LEN=*),
PARAMETER :: routinen =
'alloc_cfm_double_array_1d'
3020 INTEGER :: handle, i
3022 CALL timeset(routinen, handle)
3024 ALLOCATE (cfm_array(n))
3030 CALL timestop(handle)
3032 END SUBROUTINE alloc_cfm_double_array_1d
3042 CHARACTER(LEN=*),
PARAMETER :: routinen =
'get_all_VBM_CBM_bandgaps'
3046 CALL timeset(routinen, handle)
3052 CALL check_qp_gap_sanity(bs_env)
3054 CALL check_scf_gw_level_ordering(bs_env)
3056 CALL timestop(handle)
3065 SUBROUTINE check_qp_gap_sanity(bs_env)
3069 CHARACTER(LEN=default_string_length) :: gw_label
3070 REAL(kind=
dp) :: gap, gap_scf
3072 gap = bs_env%band_edges_GW%IDBG
3073 gap_scf = bs_env%band_edges_scf%IDBG
3078 CALL cp_warn(__location__, &
3079 trim(gw_label)//
" band gap is negative ("// &
3080 trim(adjustl(
cp_to_string(gap*
evolt,
'(F12.3)')))//
" eV): the quasiparticle "// &
3081 "spectrum is inverted. Check numerical parameters.")
3083 CALL cp_warn(__location__, &
3084 trim(gw_label)//
" band gap is implausibly large ("// &
3085 trim(adjustl(
cp_to_string(gap*
evolt,
'(F12.3)')))//
" eV): the quasiparticle "// &
3086 "solve has likely diverged. Check numerical parameters.")
3089 END SUBROUTINE check_qp_gap_sanity
3100 SUBROUTINE check_scf_gw_level_ordering(bs_env)
3104 CHARACTER(LEN=*),
PARAMETER :: routinen =
'check_scf_gw_level_ordering'
3105 REAL(kind=
dp),
PARAMETER :: eps_degeneracy = 1.0e-05_dp
3107 CHARACTER(LEN=default_string_length) :: gw_label, level_gw, level_scf, &
3109 CHARACTER(LEN=max_line_length) :: msg
3110 INTEGER :: handle, homo, ispin, n_mo
3111 INTEGER,
DIMENSION(2) :: loc_gw, loc_scf
3113 CALL timeset(routinen, handle)
3118 DO ispin = 1, bs_env%n_spin
3120 homo = bs_env%n_occ(ispin)
3122 IF (bs_env%n_spin == 2)
THEN
3123 WRITE (spin_string,
'(A,I0,A)')
" (spin ", ispin,
")"
3129 loc_scf(:) = maxloc(bs_env%eigenval_scf(1:homo, :, ispin))
3130 loc_gw(:) = maxloc(bs_env%eigenval_GW(1:homo, :, ispin))
3133 IF (bs_env%eigenval_scf(loc_scf(1), loc_scf(2), ispin) - &
3134 bs_env%eigenval_scf(loc_gw(1), loc_gw(2), ispin) > eps_degeneracy)
THEN
3136 CALL level_string(level_scf, loc_scf, bs_env)
3137 CALL level_string(level_gw, loc_gw, bs_env)
3139 msg = trim(gw_label)//
" reorders the occupied levels"//trim(spin_string)// &
3140 ": the SCF valence band maximum (SCF HOMO) is "//trim(level_scf)// &
3141 ", whereas the "//trim(gw_label)//
" valence band maximum ("// &
3142 trim(gw_label)//
" HOMO) is "//trim(level_gw)//
". The SCF and "// &
3143 trim(gw_label)//
" band edges printed below therefore belong to different "// &
3144 "orbitals; see the eigenvalues in the file bandstructure_SCF_and_G0W0."
3150 loc_scf(:) = minloc(bs_env%eigenval_scf(homo + 1:n_mo, :, ispin))
3151 loc_gw(:) = minloc(bs_env%eigenval_GW(homo + 1:n_mo, :, ispin))
3152 loc_scf(1) = loc_scf(1) + homo
3153 loc_gw(1) = loc_gw(1) + homo
3155 IF (bs_env%eigenval_scf(loc_gw(1), loc_gw(2), ispin) - &
3156 bs_env%eigenval_scf(loc_scf(1), loc_scf(2), ispin) > eps_degeneracy)
THEN
3158 CALL level_string(level_scf, loc_scf, bs_env)
3159 CALL level_string(level_gw, loc_gw, bs_env)
3161 msg = trim(gw_label)//
" reorders the empty levels"//trim(spin_string)// &
3162 ": the SCF conduction band minimum (SCF LUMO) is "//trim(level_scf)// &
3163 ", whereas the "//trim(gw_label)//
" conduction band minimum ("// &
3164 trim(gw_label)//
" LUMO) is "//trim(level_gw)//
". The SCF and "// &
3165 trim(gw_label)//
" band edges printed below therefore belong to different "// &
3166 "orbitals; see the eigenvalues in the file bandstructure_SCF_and_G0W0."
3173 CALL timestop(handle)
3175 END SUBROUTINE check_scf_gw_level_ordering
3183 SUBROUTINE level_string(string, loc, bs_env)
3185 CHARACTER(LEN=*),
INTENT(OUT) :: string
3186 INTEGER,
DIMENSION(2),
INTENT(IN) :: loc
3189 IF (bs_env%nkp_bs_and_DOS > 1)
THEN
3190 WRITE (string,
'(A,I0,A,I0)')
"level ", loc(1),
" at k-point ", loc(2)
3192 WRITE (string,
'(A,I0)')
"level ", loc(1)
3195 END SUBROUTINE level_string
3205 REAL(kind=
dp),
DIMENSION(:, :, :) :: ev
3208 CHARACTER(LEN=*),
PARAMETER :: routinen =
'get_VBM_CBM_bandgaps'
3210 INTEGER :: handle, homo, homo_1, homo_2, ikp, &
3211 ispin, lumo, lumo_1, lumo_2, n_mo
3212 REAL(kind=
dp) :: e_dbg_at_ikp
3214 CALL timeset(routinen, handle)
3218 band_edges%DBG = 1000.0_dp
3220 SELECT CASE (bs_env%n_spin)
3222 homo = bs_env%n_occ(1)
3224 band_edges%VBM = maxval(ev(1:homo, :, 1))
3225 band_edges%CBM = minval(ev(homo + 1:n_mo, :, 1))
3227 homo_1 = bs_env%n_occ(1)
3229 homo_2 = bs_env%n_occ(2)
3231 band_edges%VBM = max(maxval(ev(1:homo_1, :, 1)), maxval(ev(1:homo_2, :, 2)))
3232 band_edges%CBM = min(minval(ev(homo_1 + 1:n_mo, :, 1)), minval(ev(homo_2 + 1:n_mo, :, 2)))
3234 cpabort(
"Error with number of spins.")
3237 band_edges%IDBG = band_edges%CBM - band_edges%VBM
3239 DO ispin = 1, bs_env%n_spin
3241 homo = bs_env%n_occ(ispin)
3243 DO ikp = 1, bs_env%nkp_bs_and_DOS
3245 e_dbg_at_ikp = -maxval(ev(1:homo, ikp, ispin)) + minval(ev(homo + 1:n_mo, ikp, ispin))
3247 IF (e_dbg_at_ikp < band_edges%DBG) band_edges%DBG = e_dbg_at_ikp
3253 CALL timestop(handle)
static GRID_HOST_DEVICE int modulo(int a, int m)
Equivalent of Fortran's MODULO, which always return a positive number. https://gcc....
static GRID_HOST_DEVICE int idx(const orbital a)
Return coset index of given orbital angular momentum.
Define the atomic kind types and their sub types.
subroutine, public get_atomic_kind_set(atomic_kind_set, atom_of_kind, kind_of, natom_of_kind, maxatom, natom, nshell, fist_potential_present, shell_present, shell_adiabatic, shell_check_distance, damping_present)
Get attributes of an atomic kind set.
subroutine, public get_atomic_kind(atomic_kind, fist_potential, element_symbol, name, mass, kind_number, natom, atom_list, rcov, rvdw, z, qeff, apol, cpol, mm_radius, shell, shell_active, damping)
Get attributes of an atomic kind.
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
Basic linear algebra operations for complex full matrices.
various cholesky decomposition related routines
subroutine, public cp_cfm_cholesky_decompose(matrix, n, info_out)
Used to replace a symmetric positive definite matrix M with its Cholesky decomposition U: M = U^T * U...
used for collecting diagonalization schemes available for cp_cfm_type
subroutine, public cp_cfm_geeig_canon(amatrix, bmatrix, eigenvectors, eigenvalues, work, epseig, nmo_retained)
General Eigenvalue Problem AX = BXE Use canonical orthogonalization.
subroutine, public cp_cfm_heevd(matrix, eigenvectors, eigenvalues)
Perform a diagonalisation of a complex matrix.
subroutine, public cp_cfm_geeig(amatrix, bmatrix, eigenvectors, eigenvalues, work, lowest_subset)
General Eigenvalue Problem AX = BXE Single option version: Cholesky decomposition of B.
Represents a complex full matrix distributed on many processors.
subroutine, public cp_cfm_release(matrix)
Releases a full matrix.
subroutine, public cp_fm_to_cfm(msourcer, msourcei, mtarget)
Construct a complex full matrix by taking its real and imaginary parts from two separate real-value f...
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_get_info(matrix, name, nrow_global, ncol_global, nrow_block, ncol_block, nrow_local, ncol_local, row_indices, col_indices, local_data, context, matrix_struct, para_env)
Returns information about a full matrix.
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...
subroutine, public cp_cfm_to_fm(msource, mtargetr, mtargeti)
Copy real and imaginary parts of a complex full matrix into separate real-value full matrices.
Defines control structures, which contain the parameters and the settings for the DFT-based calculati...
subroutine, public dbcsr_deallocate_matrix(matrix)
...
subroutine, public dbcsr_desymmetrize(matrix_a, matrix_b)
...
subroutine, public dbcsr_set(matrix, alpha)
...
Routines that link DBCSR and CP2K concepts together.
subroutine, public cp_dbcsr_alloc_block_from_nbl(matrix, sab_orb, desymmetrize)
allocate the blocks of a dbcsr based on the neighbor list
DBCSR operations in CP2K.
subroutine, public copy_dbcsr_to_fm(matrix, fm)
Copy a DBCSR matrix to a BLACS matrix.
subroutine, public copy_fm_to_dbcsr(fm, matrix, keep_sparsity)
Copy a BLACS matrix to a dbcsr matrix.
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.
used for collecting some of the diagonalization schemes available for cp_fm_type. cp_fm_power also mo...
subroutine, public cp_fm_geeig_canon(amatrix, bmatrix, eigenvectors, eigenvalues, work, epseig, nmo_retained)
General Eigenvalue Problem AX = BXE Use canonical diagonalization : U*s**(-1/2).
represent the structure of a full matrix
subroutine, public cp_fm_struct_create(fmstruct, para_env, context, nrow_global, ncol_global, nrow_block, ncol_block, descriptor, first_p_pos, local_leading_dimension, template_fmstruct, square_blocks, force_block)
allocates and initializes a full matrix structure
subroutine, public cp_fm_struct_release(fmstruct)
releases a full matrix structure
represent a full matrix distributed on many processors
subroutine, public cp_fm_get_diag(matrix, diag)
returns the diagonal elements of a fm
subroutine, public cp_fm_get_info(matrix, name, nrow_global, ncol_global, nrow_block, ncol_block, nrow_local, ncol_local, row_indices, col_indices, local_data, context, nrow_locals, ncol_locals, matrix_struct, para_env)
returns all kind of information about the full matrix
subroutine, public cp_fm_set_all(matrix, alpha, beta)
set all elements of a matrix to the same value, and optionally the diagonal to a different one
subroutine, public cp_fm_create(matrix, matrix_struct, name, nrow, ncol, set_zero)
creates a new full matrix with the given structure
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...
Utility routines to read data from files. Kept as close as possible to the old parser because.
elemental subroutine, public read_float_object(string, object, error_message)
Returns a floating point number read from a string including fraction like z1/z2.
Defines the basic variable types.
integer, parameter, public max_line_length
integer, parameter, public dp
integer, parameter, public default_string_length
Routines needed for kpoint calculation.
subroutine, public rskp_transform(rmatrix, cmatrix, rsmat, ispin, xkp, cell_to_index, sab_nl, is_complex, rs_sign)
Transformation of real space matrices to a kpoint.
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, lattice_fft)
Retrieve information from a kpoint environment.
subroutine, public kpoint_create(kpoint)
Create a kpoint environment.
Machine interface based on Fortran 2003 and POSIX.
real(kind=dp) function, public m_walltime()
returns time from a real-time clock, protected against rolling early/easily
Definition of mathematical constants and functions.
complex(kind=dp), parameter, public z_one
complex(kind=dp), parameter, public gaussi
real(kind=dp), parameter, public twopi
complex(kind=dp), parameter, public z_zero
Interface to the message passing library MPI.
basic linear algebra operations for full matrixes
Define the data structure for the particle information.
Definition of physical constants:
real(kind=dp), parameter, public evolt
real(kind=dp), parameter, public angstrom
real(kind=dp), parameter, public max_qp_gap
real(kind=dp), parameter, public eps_qp_gap
subroutine, public eval_bandstructure_properties(qs_env, bs_env)
...
subroutine, public rsmat_to_kp(mat_rs, ispin, xkp, cell_to_index_scf, sab_nl, bs_env, cfm_kp, imag_rs_mat)
...
subroutine, public kpoint_init_cell_index_simple(kpoints, qs_env)
...
subroutine, public allocate_gw_eigenvalues(bs_env)
Allocate the arrays holding the GW quasiparticle energies.
character(len=default_string_length) function, public gw_flavour_label(bs_env)
Name of the GW flavour that was requested, for printing.
subroutine, public cfm_ikp_from_fm_gamma(cfm_ikp, fm_gamma, ikp, qs_env, kpoints, basis_type)
...
subroutine, public get_all_vbm_cbm_bandgaps(bs_env)
...
subroutine, public soc(qs_env, bs_env)
...
subroutine, public mic_contribution_from_ikp(bs_env, qs_env, fm_w_mic_freq_j, cfm_w_ikp_freq_j, ikp, kpoints, basis_type, wkp_ext)
...
subroutine, public compute_xkp(xkp, ikp_start, ikp_end, grid)
...
subroutine, public create_and_init_bs_env(qs_env, bs_env, post_scf_bandstructure_section)
...
subroutine, public get_vbm_cbm_bandgaps(band_edges, ev, bs_env)
...
container for various plainwaves related things
subroutine, public pw_env_get(pw_env, pw_pools, cube_info, gridlevel_info, auxbas_pw_pool, auxbas_grid, auxbas_rs_desc, auxbas_rs_grid, rs_descs, rs_grids, xc_pw_pool, vdw_pw_pool, poisson_env, interp_section)
returns the various attributes of the pw env
Manages a pool of grids (to be used for example as tmp objects), but can also be used to instantiate ...
Calculate the plane wave density by collocating the primitive Gaussian functions (pgf).
subroutine, public calculate_rho_elec(matrix_p, matrix_p_kp, rho, rho_gspace, total_rho, ks_env, soft_valid, compute_tau, compute_grad, basis_type, der_type, idir, task_list_external, pw_env_external)
computes the density corresponding to a given density matrix on the grid
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.
Define the neighbor list data types and the corresponding functionality.
Utility routines for GW with imaginary time.
subroutine, public compute_weight_re_im(weight_re, weight_im, num_cells, iatom, jatom, xkp, wkp_w, cell, index_to_cell, hmat, particle_set)
...
subroutine, public get_atom_index_from_basis_function_index(qs_env, atom_from_basis_index, basis_size, basis_type, first_bf_from_atom)
...
parameters that control an scf iteration
subroutine, public v_soc_xyz_from_pseudopotential(qs_env, mat_v_soc_xyz)
V^SOC_µν^(α),R = ħ/2 < ϕ_µ cell O | sum_ℓ ΔV_ℓ^SO(r,r') L^(α) | ϕ_ν cell R>, α = x,...
subroutine, public remove_soc_outside_energy_window_mo(cfm_ks_spinor, e_win_cbm, temp_smear, eigenval, e_fermi)
...
subroutine, public create_cfm_double(cfm_double, fm_orig, cfm_orig)
...
subroutine, public add_dbcsr_submat(cfm_mat_target, mat_source, fm_struct_source, nstart_row, nstart_col, factor, add_also_herm_conj)
...
subroutine, public add_cfm_submat(cfm_mat_target, cfm_mat_source, nstart_row, nstart_col, factor)
...
subroutine, public get_cfm_submat(cfm_mat_target, cfm_mat_source, nstart_row, nstart_col)
...
subroutine, public cfm_add_on_diag(cfm, alpha)
...
Utilities for string manipulations.
elemental subroutine, public uppercase(string)
Convert all lower case characters in a string to upper case.
Provides all information about an atomic kind.
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.
keeps the information about the structure of a full matrix
Contains information about kpoints.
stores all the informations relevant to an mpi environment
contained for different pw related things
Manages a pool of grids (to be used for example as tmp objects), but can also be used to instantiate ...
calculation environment to calculate the ks matrix, holds all the needed vars. assumes that the core ...