solve_trl Subroutine

public pure subroutine solve_trl(n, t, ldt, b, job)

Uses

  • proc~~solve_trl~~UsesGraph proc~solve_trl solve_trl module~odrpack_kinds odrpack_kinds proc~solve_trl->module~odrpack_kinds iso_fortran_env iso_fortran_env module~odrpack_kinds->iso_fortran_env

Solve systems of the form:

t * x = b or trans(t) * x = b

where t is an upper or lower triangular matrix of order n, and the solution x overwrites the RHS b.

Arguments

Type IntentOptional Attributes Name
integer, intent(in) :: n

Number of rows and columns of data in array t.

real(kind=wp), intent(in) :: t(ldt,n)

Upper or lower tridiagonal system.

integer, intent(in) :: ldt

Leading dimension of array t.

real(kind=wp), intent(inout) :: b(:)

On input: the right hand side; On exit: the solution.

integer, intent(in) :: job

What kind of system is to be solved: 1: Solve t * x = b, where t is lower triangular, 2: Solve t * x = b, where t is upper triangular, 3: Solve trans(t) * x = b, where t is lower triangular, 4: Solve trans(t) * x = b, where t is upper triangular.


Called by

proc~~solve_trl~~CalledByGraph proc~solve_trl solve_trl proc~lcstep lcstep proc~lcstep->proc~solve_trl proc~vevtr vevtr proc~lcstep->proc~vevtr proc~vevtr->proc~solve_trl proc~trust_region trust_region proc~trust_region->proc~lcstep proc~vcv_beta vcv_beta proc~vcv_beta->proc~lcstep proc~odr odr proc~odr->proc~trust_region proc~odr->proc~vcv_beta proc~odr_long_c odr_long_c proc~odr_long_c->proc~odr proc~odr_medium_c odr_medium_c proc~odr_medium_c->proc~odr proc~odr_short_c odr_short_c proc~odr_short_c->proc~odr program~example1 example1 program~example1->proc~odr program~example2 example2 program~example2->proc~odr program~example3 example3 program~example3->proc~odr program~example4 example4 program~example4->proc~odr program~example5 example5 program~example5->proc~odr

Variables

Type Visibility Attributes Name Initial
real(kind=wp), public :: temp
integer, public :: j1
integer, public :: j
integer, public :: jn

Source Code

   pure subroutine solve_trl(n, t, ldt, b, job)
   !! Solve systems of the form:
   !!
   !!  `t * x = b  or  trans(t) * x = b`
   !!
   !! where `t` is an upper or lower triangular matrix of order `n`, and the solution `x`
   !! overwrites the RHS `b`.
      ! Adapted from LINPACK subroutine DTRSL.
      ! @note: This is one of the most time-consuming subroutines in ODRPACK (~25% of total).

      use odrpack_kinds, only: zero

      integer, intent(in) :: n
         !! Number of rows and columns of data in array `t`.
      real(wp), intent(in) :: t(ldt, n)
         !! Upper or lower tridiagonal system.
      integer, intent(in) :: ldt
         !! Leading dimension of array `t`.
      real(wp), intent(inout) :: b(:)
         !! On input: the right hand side; On exit: the solution.
      integer, intent(in) :: job
         !! What kind of system is to be solved:
         !!   1: Solve `t * x = b`, where `t` is lower triangular,
         !!   2: Solve `t * x = b`, where `t` is upper triangular,
         !!   3: Solve `trans(t) * x = b`, where `t` is lower triangular,
         !!   4: Solve `trans(t) * x = b`, where `t` is upper triangular.

      ! Local scalars
      real(wp) :: temp
      integer :: j1, j, jn

      ! Variable Definitions (alphabetically)
      !  B:       On input: the right hand side; On exit: the solution
      !  J1:      The first nonzero entry in T.
      !  J:       An indexing variable.
      !  JN:      The last nonzero entry in T.
      !  JOB:     What kind of system is to be solved, where if JOB is
      !           1   Solve T*X=B, T lower triangular,
      !           2   Solve T*X=B, T upper triangular,
      !           3   Solve trans(T)*X=B, T lower triangular,
      !           4   Solve trans(T)*X=B, T upper triangular.
      !  LDT:     The leading dimension of array T.
      !  N:       The number of rows and columns of data in array T.
      !  T:       The upper or lower tridiagonal system.

      !  Find first nonzero diagonal entry in T
      j1 = 0
      do j = 1, n
         if (j1 == 0 .and. t(j, j) /= zero) then
            j1 = j
         elseif (t(j, j) == zero) then
            b(j) = zero
         end if
      end do
      if (j1 == 0) return

      ! Find last nonzero diagonal entry in T
      jn = 0
      do j = n, j1, -1
         if (jn == 0 .and. t(j, j) /= zero) then
            jn = j
         elseif (t(j, j) == zero) then
            b(j) = zero
         end if
      end do

      select case (job)
      case (1)
         ! Solve T*X=B for T lower triangular
         b(j1) = b(j1)/t(j1, j1)
         do j = j1 + 1, jn
            temp = -b(j - 1)
            b(j:jn) = b(j:jn) + temp*t(j:jn, j - 1)
            if (t(j, j) /= zero) then
               b(j) = b(j)/t(j, j)
            else
               b(j) = zero
            end if
         end do

      case (2)
         ! Solve T*X=B for T upper triangular.
         b(jn) = b(jn)/t(jn, jn)
         do j = jn - 1, j1, -1
            temp = -b(j + 1)
            b(1:j) = b(1:j) + temp*t(1:j, j + 1)
            if (t(j, j) /= zero) then
               b(j) = b(j)/t(j, j)
            else
               b(j) = zero
            end if
         end do

      case (3)
         ! Solve trans(T)*X=B for T lower triangular.
         b(jn) = b(jn)/t(jn, jn)
         do j = jn - 1, j1, -1
            b(j) = b(j) - dot_product(t(j + 1:jn + 1, j), b(j + 1:jn + 1))
            if (t(j, j) /= zero) then
               b(j) = b(j)/t(j, j)
            else
               b(j) = zero
            end if
         end do

      case (4)
         ! Solve trans(T)*X=B for T upper triangular
         b(j1) = b(j1)/t(j1, j1)
         do j = j1 + 1, jn
            b(j) = b(j) - dot_product(t(1:j - 1, j), b(1:j - 1))
            if (t(j, j) /= zero) then
               b(j) = b(j)/t(j, j)
            else
               b(j) = zero
            end if
         end do
      case default
         error stop "Invalid value of JOB."
      end select

   end subroutine solve_trl