Contribution from point k to the complex interband optical conductivity, separated into Hermitian (H) and anti-Hermitian (AH) parts. Also returns the joint density of states
Type | Intent | Optional | Attributes | Name | ||
---|---|---|---|---|---|---|
real(kind=dp), | intent(in) | :: | kpt(3) | |||
complex(kind=dp), | intent(out), | dimension(:, :, :) | :: | kubo_H_k | ||
complex(kind=dp), | intent(out), | dimension(:, :, :) | :: | kubo_AH_k | ||
real(kind=dp), | intent(out), | dimension(:) | :: | jdos_k | ||
complex(kind=dp), | intent(out), | optional | dimension(:, :, :, :) | :: | kubo_H_k_spn | |
complex(kind=dp), | intent(out), | optional | dimension(:, :, :, :) | :: | kubo_AH_k_spn | |
real(kind=dp), | intent(out), | optional | dimension(:, :) | :: | jdos_k_spn |
subroutine berry_get_kubo_k(kpt, kubo_H_k, kubo_AH_k, jdos_k, &
kubo_H_k_spn, kubo_AH_k_spn, jdos_k_spn)
!====================================================================!
! !
!! Contribution from point k to the complex interband optical
!! conductivity, separated into Hermitian (H) and anti-Hermitian (AH)
!! parts. Also returns the joint density of states
! !
!====================================================================!
use w90_constants, only: dp, cmplx_0, cmplx_i, pi
use w90_utility, only: utility_diagonalize, utility_rotate, utility_w0gauss
use w90_parameters, only: num_wann, kubo_nfreq, kubo_freq_list, &
fermi_energy_list, kubo_eigval_max, &
kubo_adpt_smr, kubo_smr_fixed_en_width, &
kubo_adpt_smr_max, kubo_adpt_smr_fac, &
kubo_smr_index, berry_kmesh, spin_decomp
use w90_postw90_common, only: pw90common_get_occ, pw90common_fourier_R_to_k_new, &
pw90common_fourier_R_to_k_vec, pw90common_kmesh_spacing
use w90_wan_ham, only: wham_get_D_h, wham_get_eig_deleig
use w90_get_oper, only: HH_R, AA_R
use w90_spin, only: spin_get_nk
! Arguments
!
! Last three arguments should be present iff spin_decomp=T (but
! this is not checked: do it?)
!
real(kind=dp), intent(in) :: kpt(3)
complex(kind=dp), dimension(:, :, :), intent(out) :: kubo_H_k
complex(kind=dp), dimension(:, :, :), intent(out) :: kubo_AH_k
real(kind=dp), dimension(:), intent(out) :: jdos_k
complex(kind=dp), optional, dimension(:, :, :, :), intent(out) :: kubo_H_k_spn
complex(kind=dp), optional, dimension(:, :, :, :), intent(out) :: kubo_AH_k_spn
real(kind=dp), optional, dimension(:, :), intent(out) :: jdos_k_spn
complex(kind=dp), allocatable :: HH(:, :)
complex(kind=dp), allocatable :: delHH(:, :, :)
complex(kind=dp), allocatable :: UU(:, :)
complex(kind=dp), allocatable :: D_h(:, :, :)
complex(kind=dp), allocatable :: AA(:, :, :)
! Adaptive smearing
!
real(kind=dp) :: del_eig(num_wann, 3), joint_level_spacing, &
eta_smr, Delta_k, arg, vdum(3)
integer :: i, j, n, m, ifreq, ispn
real(kind=dp) :: eig(num_wann), occ(num_wann), delta, &
rfac1, rfac2, occ_prod, spn_nk(num_wann)
complex(kind=dp) :: cfac, omega
allocate (HH(num_wann, num_wann))
allocate (delHH(num_wann, num_wann, 3))
allocate (UU(num_wann, num_wann))
allocate (D_h(num_wann, num_wann, 3))
allocate (AA(num_wann, num_wann, 3))
if (kubo_adpt_smr) then
call wham_get_eig_deleig(kpt, eig, del_eig, HH, delHH, UU)
Delta_k = pw90common_kmesh_spacing(berry_kmesh)
else
call pw90common_fourier_R_to_k_new(kpt, HH_R, OO=HH, &
OO_dx=delHH(:, :, 1), &
OO_dy=delHH(:, :, 2), &
OO_dz=delHH(:, :, 3))
call utility_diagonalize(HH, num_wann, eig, UU)
endif
call pw90common_get_occ(eig, occ, fermi_energy_list(1))
call wham_get_D_h(delHH, UU, eig, D_h)
call pw90common_fourier_R_to_k_vec(kpt, AA_R, OO_true=AA)
do i = 1, 3
AA(:, :, i) = utility_rotate(AA(:, :, i), UU, num_wann)
enddo
AA = AA + cmplx_i*D_h ! Eq.(25) WYSV06
! Replace imaginary part of frequency with a fixed value
if (.not. kubo_adpt_smr .and. kubo_smr_fixed_en_width /= 0.0_dp) &
kubo_freq_list = real(kubo_freq_list, dp) &
+ cmplx_i*kubo_smr_fixed_en_width
kubo_H_k = cmplx_0
kubo_AH_k = cmplx_0
jdos_k = 0.0_dp
if (spin_decomp) then
call spin_get_nk(kpt, spn_nk)
kubo_H_k_spn = cmplx_0
kubo_AH_k_spn = cmplx_0
jdos_k_spn = 0.0_dp
end if
do m = 1, num_wann
do n = 1, num_wann
if (n == m) cycle
if (eig(m) > kubo_eigval_max .or. eig(n) > kubo_eigval_max) cycle
if (spin_decomp) then
if (spn_nk(n) >= 0 .and. spn_nk(m) >= 0) then
ispn = 1 ! up --> up transition
elseif (spn_nk(n) < 0 .and. spn_nk(m) < 0) then
ispn = 2 ! down --> down
else
ispn = 3 ! spin-flip
end if
end if
if (kubo_adpt_smr) then
! Eq.(35) YWVS07
vdum(:) = del_eig(m, :) - del_eig(n, :)
joint_level_spacing = sqrt(dot_product(vdum(:), vdum(:)))*Delta_k
eta_smr = min(joint_level_spacing*kubo_adpt_smr_fac, &
kubo_adpt_smr_max)
else
eta_smr = kubo_smr_fixed_en_width
endif
rfac1 = (occ(m) - occ(n))*(eig(m) - eig(n))
occ_prod = occ(n)*(1.0_dp - occ(m))
do ifreq = 1, kubo_nfreq
!
! Complex frequency for the anti-Hermitian conductivity
!
if (kubo_adpt_smr) then
omega = real(kubo_freq_list(ifreq), dp) + cmplx_i*eta_smr
else
omega = kubo_freq_list(ifreq)
endif
!
! Broadened delta function for the Hermitian conductivity and JDOS
!
arg = (eig(m) - eig(n) - real(omega, dp))/eta_smr
! If only Hermitean part were computed, could speed up
! by inserting here 'if(abs(arg)>10.0_dp) cycle'
delta = utility_w0gauss(arg, kubo_smr_index)/eta_smr
!
! Lorentzian shape (for testing purposes)
! delta=1.0_dp/(1.0_dp+arg*arg)/pi
! delta=delta/eta_smr
!
jdos_k(ifreq) = jdos_k(ifreq) + occ_prod*delta
if (spin_decomp) &
jdos_k_spn(ispn, ifreq) = jdos_k_spn(ispn, ifreq) + occ_prod*delta
cfac = cmplx_i*rfac1/(eig(m) - eig(n) - omega)
rfac2 = -pi*rfac1*delta
do j = 1, 3
do i = 1, 3
kubo_H_k(i, j, ifreq) = kubo_H_k(i, j, ifreq) &
+ rfac2*AA(n, m, i)*AA(m, n, j)
kubo_AH_k(i, j, ifreq) = kubo_AH_k(i, j, ifreq) &
+ cfac*AA(n, m, i)*AA(m, n, j)
if (spin_decomp) then
kubo_H_k_spn(i, j, ispn, ifreq) = &
kubo_H_k_spn(i, j, ispn, ifreq) &
+ rfac2*AA(n, m, i)*AA(m, n, j)
kubo_AH_k_spn(i, j, ispn, ifreq) = &
kubo_AH_k_spn(i, j, ispn, ifreq) &
+ cfac*AA(n, m, i)*AA(m, n, j)
endif
enddo
enddo
enddo
enddo
enddo
end subroutine berry_get_kubo_k