the derivative of utility_wgauss: an approximation to the delta function
(n>=0) : derivative of the corresponding Methfessel-Paxton utility_wgauss
(n=-1 ): derivative of cold smearing: 1/sqrt(pi)exp(-(x-1/sqrt(2))2)(2-sqrt(2)*x)
(n=-99): derivative of Fermi-Dirac function: 0.5/(1.0+cosh(x))
Type | Intent | Optional | Attributes | Name | ||
---|---|---|---|---|---|---|
real(kind=dp) | :: | x | ||||
integer | :: | n |
function utility_w0gauss(x, n)
!-----------------------------------------------------------------------
!
!! the derivative of utility_wgauss: an approximation to the delta function
!!
!! (n>=0) : derivative of the corresponding Methfessel-Paxton utility_wgauss
!!
!! (n=-1 ): derivative of cold smearing:
!! 1/sqrt(pi)*exp(-(x-1/sqrt(2))**2)*(2-sqrt(2)*x)
!!
!! (n=-99): derivative of Fermi-Dirac function: 0.5/(1.0+cosh(x))
!
use w90_constants, only: dp, pi
use w90_io, only: io_error
implicit none
real(kind=dp) :: utility_w0gauss, x
!! output: the value of the function
!! input: the point where to compute the function
integer :: n
!! input: the order of the smearing function
!
! here the local variables
!
real(kind=dp) :: a, arg, hp, hd, sqrtpm1
! the coefficients a_n
! the argument of the exponential
! the hermite function
! the hermite function
integer :: i, ni
! counter on n values
! counter on 2n values
! Fermi-Dirac smearing
sqrtpm1 = 1.0_dp/sqrt(pi)
if (n .eq. -99) then
if (abs(x) .le. 36.0) then
utility_w0gauss = 1.00_dp/(2.00_dp + exp(-x) + exp(+x))
! in order to avoid problems for large values of x in the e
else
utility_w0gauss = 0.0_dp
endif
return
endif
! cold smearing (Marzari-Vanderbilt)
if (n .eq. -1) then
arg = min(200.0_dp, (x - 1.00_dp/sqrt(2.00_dp))**2)
utility_w0gauss = sqrtpm1*exp(-arg)*(2.00_dp - sqrt(2.00_dp)*x)
return
endif
if (n .gt. 10 .or. n .lt. 0) &
call io_error('utility_w0gauss higher order smearing is untested and unstable')
! Methfessel-Paxton
arg = min(200.0_dp, x**2)
utility_w0gauss = exp(-arg)*sqrtpm1
if (n .eq. 0) return
hd = 0.00_dp
hp = exp(-arg)
ni = 0
a = sqrtpm1
do i = 1, n
hd = 2.00_dp*x*hp - 2.00_dp*DBLE(ni)*hd
ni = ni + 1
a = -a/(DBLE(i)*4.00_dp)
hp = 2.00_dp*x*hd - 2.00_dp*DBLE(ni)*hp
ni = ni + 1
utility_w0gauss = utility_w0gauss + a*hp
enddo
return
end function utility_w0gauss