ddecbt.inc Source File


Source Code

!----------------------------------------------------------------------------------------------------------------------------------!
!()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()!
!----------------------------------------------------------------------------------------------------------------------------------!
!>
!!### NAME
!! ddecbt(3f) -[M_odepack] Block-tridiagonal matrix decomposition routine.
!!
!!### DESCRIPTION
!! The input matrix contains three blocks of elements in each block-row,
!! including blocks in the (1,3) and (N,N-2) block positions.
!! DDECBT uses block Gauss elimination and Subroutines DGEFA and DGESL
!! for solution of blocks.  Partial pivoting is done within
!! block-rows only.
!!
!! Note: this version uses LINPACK routines DGEFA/DGESL instead of
!! of dec/sol for solution of blocks, and it uses the BLAS routine DDOT
!! for dot product calculations.
!!
!!### INPUT
!!
!! M
!!
!! : order of each block.
!!
!! N
!!
!! : number of blocks in each direction of the matrix.
!!   N must be 4 or more.  The complete matrix has order M*N.
!!
!! A
!!
!! : M by M by N array containing diagonal blocks.
!!   A(i,j,k) contains the (i,j) element of the k-th block.
!!
!! B
!!
!! : M by M by N array containing the super-diagonal blocks
!!   (in B(*,*,k) for k = 1,...,N-1) and the block in the (N,N-2)
!!   block position (in B(*,*,N)).
!!
!! C
!!
!! : M by M by N array containing the subdiagonal blocks
!!   (in C(*,*,k) for k = 2,3,...,N) and the block in the
!!   (1,3) block position (in C(*,*,1)).
!!
!! IP
!!
!! : integer array of length M*N for working storage.
!!
!!### OUTPUT
!!
!! A,B,C
!!
!! : M by M by N arrays containing the block-LU decomposition
!!   of the input matrix.
!!
!! IP
!!
!! : M by N array of pivot information.  IP(*,k) contains
!!   information for the k-th digonal block.
!!
!! IER
!!
!! : 0  if no trouble occurred, or
!!       = -1 if the input value of M or N was illegal, or
!!       = k  if a singular matrix was found in the k-th diagonal block.
!!
!! Use DSOLBT to solve the associated linear system.
!!
!! External routines required: DGEFA and DGESL (from LINPACK) and
!! DDOT (from the BLAS, or Basic Linear Algebra package).
!-----------------------------------------------------------------------
!  Written by A. C. Hindmarsh.
!  Latest revision:  November 10, 1983 (ACH)
!  Reference:  UCID-30150
!              Solution of Block-Tridiagonal Systems of Linear
!              Algebraic Equations
!              A.C. Hindmarsh
!              February 1977
!-----------------------------------------------------------------------
subroutine ddecbt(M,N,A,B,C,Ip,Ier)
!
integer                     :: M
integer,intent(in)          :: N
real(kind=dp),intent(inout) :: A(M,M,N)
real(kind=dp),intent(inout) :: B(M,M,N)
real(kind=dp),intent(inout) :: C(M,M,N)
integer                     :: Ip(M,N)
integer, intent(inout)      :: Ier
!
real(kind=dp) :: dpp
integer :: i , j , k , km1 , nm1 , nm2
!
   if ( M<1 .or. N<4 ) then
      Ier = -1
      return
   else
      nm1 = N - 1
      nm2 = N - 2
   ! Process the first block-row. -----------------------------------------
      call dgefa(A,M,M,Ip,Ier)
      k = 1
      if ( Ier==0 ) then
         do j = 1 , M
            call dgesl(A,M,M,Ip,B(1,j,1),0)
            call dgesl(A,M,M,Ip,C(1,j,1),0)
         enddo
   ! Adjust B(*,*,2). -----------------------------------------------------
         do j = 1 , M
            do i = 1 , M
               dpp = ddot(M,C(i,1,2),M,C(1,j,1),1)
               B(i,j,2) = B(i,j,2) - dpp
            enddo
         enddo
   ! Main loop.  Process block-rows 2 to N-1. -----------------------------
         do k = 2 , nm1
            km1 = k - 1
            do j = 1 , M
               do i = 1 , M
                  dpp = ddot(M,C(i,1,k),M,B(1,j,km1),1)
                  A(i,j,k) = A(i,j,k) - dpp
               enddo
            enddo
            call dgefa(A(1,1,k),M,M,Ip(1,k),Ier)
            if ( Ier/=0 )then
               Ier = k
            return
         endif
            do j = 1 , M
               call dgesl(A(1,1,k),M,M,Ip(1,k),B(1,j,k),0)
            enddo
         enddo
   ! Process last block-row and return. -----------------------------------
         do j = 1 , M
            do i = 1 , M
               dpp = ddot(M,B(i,1,N),M,B(1,j,nm2),1)
               C(i,j,N) = C(i,j,N) - dpp
            enddo
         enddo
         do j = 1 , M
            do i = 1 , M
               dpp = ddot(M,C(i,1,N),M,B(1,j,nm1),1)
               A(i,j,N) = A(i,j,N) - dpp
            enddo
         enddo
         call dgefa(A(1,1,N),M,M,Ip(1,N),Ier)
         k = N
         if ( Ier==0 ) return
      endif
   endif
   ! Error returns. -------------------------------------------------------
   Ier = k
end subroutine ddecbt