modified_bessel_temme_algorithm Subroutine

public subroutine modified_bessel_temme_algorithm(v, x, ck, dk, ek)

Implementation of the Temme's algorithm [N. M. Temme, J. Comput. Phys. 19 (1975) 324] to calculating modified Bessel functions of the second kind. This is a direct modernization of the "mbessk" subroutine in MOLSCAT: https://github.com/molscat/molscat/blob/master/source_code/rbessk.f

Arguments

Type IntentOptional Attributes Name
real(kind=dp), intent(in) :: v
real(kind=dp), intent(in) :: x
real(kind=dp), intent(out) :: ck
real(kind=dp), intent(out) :: dk
real(kind=dp), intent(out) :: ek

Calls

proc~~modified_bessel_temme_algorithm~~CallsGraph proc~modified_bessel_temme_algorithm modified_bessel_temme_algorithm proc~write_error write_error proc~modified_bessel_temme_algorithm->proc~write_error proc~rgamma rgamma proc~modified_bessel_temme_algorithm->proc~rgamma proc~write_message write_message proc~write_error->proc~write_message

Called by

proc~~modified_bessel_temme_algorithm~~CalledByGraph proc~modified_bessel_temme_algorithm modified_bessel_temme_algorithm proc~modified_bessel_k_ratio modified_bessel_k_ratio proc~modified_bessel_k_ratio->proc~modified_bessel_temme_algorithm proc~calculate_k_matrix calculate_k_matrix proc~calculate_k_matrix->proc~modified_bessel_k_ratio program~scattering SCATTERING program~scattering->proc~calculate_k_matrix

Contents


Variables

Type Visibility Attributes Name Initial
real(kind=dp), public :: a
real(kind=dp), public :: ak
real(kind=dp), public :: ak1
real(kind=dp), public :: b
real(kind=dp), public :: c
real(kind=dp), public :: d
real(kind=dp), public :: e
real(kind=dp), public, parameter :: eps = 1.0e-15_dp
real(kind=dp), public :: ex
real(kind=dp), public :: f
real(kind=dp), public :: g
real(kind=dp), public :: h
integer, public :: m
integer, public :: maxit
integer, public :: n
integer, public :: na
real(kind=dp), public :: p
real(kind=dp), public :: pi
real(kind=dp), public :: q
real(kind=dp), public :: s
real(kind=dp), public :: sk
real(kind=dp), public, parameter :: xmin = 1.0_dp
real(kind=dp), public :: y

Source Code

      subroutine modified_bessel_temme_algorithm(v, x, ck, dk, ek)
         !! Implementation of the Temme's algorithm
         !! [N. M. Temme, J. Comput. Phys. 19 (1975) 324] to calculating
         !! modified Bessel functions of the second kind.
         !! This is a direct modernization of the "mbessk" subroutine
         !! in MOLSCAT:
         !! https://github.com/molscat/molscat/blob/master/source_code/rbessk.f
         !---------------------------------------------------------------------!
         real(dp), intent(in) :: v, x
         real(dp), intent(out) :: ck, dk, ek
         real(dp) :: a, b, c, d, e, f, g, h, p, q, s, sk, y, ak, ak1, ex, pi
         integer :: n, m, na, maxit
         real(dp), parameter :: eps = 1.0e-15_dp, xmin = 1.0_dp
         !---------------------------------------------------------------------!
         pi = acos(-1.0_dp)
         if (v < 0.0_dp .or. x <= 0.0_dp) then
            call write_error("modified_bessel_temme_algorithm: Invalid input"//&
               " values for v or x")
         endif

         na = int(v + 0.5_dp)
         a = v - na
         if (x < xmin) then
         ! Small x: Temme's series for small x
            b = x / 2.0_dp
            d = -log(b)
            e = a * d
            c = a * pi
            if (abs(c) < eps) then
             c = 1.0_dp
            else
             c = c / sin(c)
            endif
            if (abs(e) < eps) then
             s = 1.0_dp
            else
             s = sinh(e) / e
            endif
            e = exp(e)
            ! Compute the gamma function and its derivatives P and Q
            ! Replace RGAMMA(A,P,Q) with a modern equivalent if necessary
            g = e * rgamma(a, p, q)
            e = (e + 1.0_dp / e) / 2.0_dp
            f = c * (p * e + q * s * d)
            e = a * a
            p = 0.5_dp * g * c
            q = 0.5_dp / g
            c = 1.0_dp
            d = b * b
            ak = f
            ak1 = p
            do n = 1, maxit
             f = (f * n + p + q) / (n * n - e)
             c = c * d / n
             p = p / (n - a)
             q = q / (n + a)
             g = c * (p - n * f)
             h = c * f
             ak = ak + h
             ak1 = ak1 + g
             if (abs(h / ak) + abs(g / ak1) < eps) exit
            end do
            f = ak
            g = ak1 / b
            ex = 0.0_dp
         else
         ! Large x: Temme's PQ method for large x
            c = 0.25_dp - a * a
            g = 1.0_dp
            f = 0.0_dp
            e = x * cos(a * pi) / pi / eps
            do n = 1, maxit
             h = (2 * (n + x) * g - (n - 1 + c / n) * f) / (n + 1)
             f = g
             g = h
             if (h * n > e) exit
            end do

            p = f / g
            q = p
            b = x + x
            e = b - 2.0_dp
            do m = n, 1, -1
             p = (m - 1 + c / m) / (e + (m + 1) * (2.0_dp - p))
             q = p * (q + 1.0_dp)
            end do
            f = sqrt(pi / b) / (1.0_dp + q)
            g = f * (a + x + 0.5_dp - p) / x
            ex = x
         endif

         ! Upward recursion
         p = 0.0_dp
         if (na > 0) then
            y = 2.0_dp / x
            do n = 1, na
              h = y * (a + n) * g + f
              f = g
              g = h
              if (abs(f) > 4.0_dp) then
                p = p + 1.0_dp
                f = 0.0625_dp * f
                g = 0.0625_dp * g
              endif
            end do
         endif

         ck = f
         dk = (v / x) * f - g
         sk = sqrt(ck * ck + dk * dk)
         ck = ck / sk
         dk = dk / sk
         ek = log(sk) + p * log(16.0_dp) - ex
      end subroutine modified_bessel_temme_algorithm