!+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
! File:  ctworkModule.f90
! Type definitions and subroutines for ctWork and ctGrid.
!
! 09 Feb 2010: Current version.
!+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

module ctWorkModule
  use precision, only : ip, rp
  implicit none

  private
  public  :: ctWork, ctGrid, c0grid, c0gtrsh, c0wtrsh

  ! Control/SNOPT workspace
  type ctWork
     integer(ip) :: n, m, nnCon, lenC, lenY, lenJ

     integer(ip), pointer :: indJ(:), locJ(:)
     real(rp),    pointer :: Jcol(:), bl(:), bu(:), pi(:), rc(:)
  end type ctWork


  ! Grid structure
  type ctGrid
     integer(ip) :: nInt, nNodes
     real(rp)    :: t0, tf
     integer(ip), pointer :: ndPtr(:), intPtr(:)
     real(rp),    pointer :: step(:)
  end type ctGrid

contains

   !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

  subroutine c0wtrsh ( work )
    type(ctWork) :: work

    integer(ip) :: info

    if ( associated(work%indJ) ) &
         deallocate ( work%indJ, stat=info )

    if ( associated(work%locJ) ) &
         deallocate ( work%locJ, stat=info )

    if ( associated(work%Jcol) ) &
         deallocate ( work%Jcol, stat=info )

    if ( associated(work%bl) ) &
         deallocate ( work%bl, stat=info )

    if ( associated(work%bu) ) &
         deallocate ( work%bu, stat=info )

    if ( associated(work%pi) ) &
         deallocate ( work%pi, stat=info )

    if ( associated(work%rc) ) &
         deallocate ( work%rc, stat=info )

  end subroutine c0wtrsh

   !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

  subroutine c0gtrsh ( grid )
    type(ctGrid) :: grid

    integer(ip) :: info

    if ( associated(grid%ndPtr) ) &
         deallocate ( grid%ndPtr,  stat=info )

    if ( associated(grid%intPtr) ) &
         deallocate ( grid%intPtr, stat=info )

    if ( associated(grid%step) ) &
         deallocate ( grid%step,   stat=info )

  end subroutine c0gtrsh

   !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

  subroutine c0grid ( iDisc, grid, nPhs, phsPt, npInt )
    integer(ip), intent(in) :: iDisc, nPhs, npInt(nPhs)
    real(rp),    intent(in) :: phsPt(nPhs+1)
    type(ctGrid) :: grid
    !===========================================================================
    ! Given the number of phases (nPhs), phsPt, and npInt (which are user-
    ! defined), this subroutine creates a new uniform grid.
    !
    ! 08 Feb 2010: Current version.
    !===========================================================================
    integer(ip) :: nInt, nNodes, ind, i, j
    real(rp)    :: hstep
    integer(ip), pointer :: ndPtr(:), intPtr(:)
    real(rp),    pointer :: step(:)

    nInt = sum ( npInt )
    grid%nInt = nInt
    grid%t0   = phsPt(1)
    grid%tf   = phsPt(nPhs+1)

    allocate ( grid%step(nInt), grid%intPtr(nPhs+1), grid%ndPtr(nPhs+1) )
    step   => grid%step
    intPtr => grid%intPtr
    ndPtr  => grid%ndPtr

    ind = 0
    do i = 1, nPhs
       hstep = ( phsPt(i+1) - phsPt(i) ) / npInt(i)
       intPtr(i) = ind + 1
       do j = 1, npInt(i)
          ind = ind + 1
          step(ind) = hstep
       end do
    end do
    intPtr(nPhs+1) = ind + 1

    ! Set up node stuff.
    if ( iDisc == 0 ) then
       nNodes = nInt + 1 + (nPhs-1)
       ndPtr  = intPtr

    else
       nNodes = 2*nInt + 1 + (nPhs-1)
       ndPtr  = 2*intPtr - 1

    end if

    grid%nNodes = nNodes

  end subroutine c0grid

   !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

end module ctWorkModule
