subroutine dyndrv(grlps1,  grt1,    grz1,    grd1,    grfu1,    &
                  grfv1,   grut1,   grvt1,   grrh1,   grlps2,   &
                  grt2,    grz2,    grd2,    grfu2,   grfv2,    &
                  grut2,   grvt2,   grrh2,   vmax2d,  vmax2dt,  &
                  vcour, ztodt   )
!-----------------------------------------------------------------------
!
! Driving routine for Gaussian quadrature, semi-implicit equation
! solution and linear part of horizontal diffusion.
! The need for this interface routine is to have a multitasking
! driver for the spectral space routines it invokes.
!
!---------------------------Code history--------------------------------
!
! Original version:  J. Rosinski
! Standardized:      J. Rosinski, June 1992
! Reviewed:          D. Williamson, B. Boville, J. Hack, August 1992
! Reviewed:          D. Williamson, March 1996
! Modified:          P. Worley, September 2002
!
!-----------------------------------------------------------------------
   use shr_kind_mod, only: r8 => shr_kind_r8
   use pmgrid
   use pspect
   use comspe
   use commap
!   use time_manager, only: get_step_size, is_first_step
   use spmd_utils, only: iam
   use perf_mod

   implicit none

!
! Input arguments
!
   real(r8), intent(in) :: grlps1(2*maxm,(plat+1)/2)       ! ----------------------------
   real(r8), intent(in) :: grt1(2*maxm,plev,(plat+1)/2)    ! |
   real(r8), intent(in) :: grz1(2*maxm,plev,(plat+1)/2)    ! |
   real(r8), intent(in) :: grd1(2*maxm,plev,(plat+1)/2)    ! |
   real(r8), intent(in) :: grfu1(2*maxm,plev,(plat+1)/2)   ! |
   real(r8), intent(in) :: grfv1(2*maxm,plev,(plat+1)/2)   ! |
   real(r8), intent(in) :: grut1(2*maxm,plev,(plat+1)/2)   ! |
   real(r8), intent(in) :: grvt1(2*maxm,plev,(plat+1)/2)   ! |
   real(r8), intent(in) :: grrh1(2*maxm,plev,(plat+1)/2)   ! |- see linems and quad for
   real(r8), intent(in) :: grlps2(2*maxm,(plat+1)/2)       ! |  definitions: these variables are
   real(r8), intent(in) :: grt2(2*maxm,plev,(plat+1)/2)    ! |  declared here for data scoping
   real(r8), intent(in) :: grz2(2*maxm,plev,(plat+1)/2)    ! |
   real(r8), intent(in) :: grd2(2*maxm,plev,(plat+1)/2)    ! |
   real(r8), intent(in) :: grfu2(2*maxm,plev,(plat+1)/2)   ! |
   real(r8), intent(in) :: grfv2(2*maxm,plev,(plat+1)/2)   ! |
   real(r8), intent(in) :: grut2(2*maxm,plev,(plat+1)/2)   ! |
   real(r8), intent(in) :: grvt2(2*maxm,plev,(plat+1)/2)   ! |
   real(r8), intent(in) :: grrh2(2*maxm,plev,(plat+1)/2)   ! ----------------------------
   real(r8), intent(inout) :: vmax2d(plev,plat)        ! max. wind at each level, latitude
   real(r8), intent(inout) :: vmax2dt(plev,plat)       ! max. truncated wind at each lvl,lat
   real(r8), intent(inout) :: vcour(plev,plat)         ! maximum Courant number in slice
   real(r8), intent(in) :: ztodt               
!
!---------------------------Local workspace-----------------------------
!
   real(r8) ztdtsq(pnmax)                ! 2dt*(n(n+1)/a^2)
   real(r8) zdt                          ! dt unless nstep = 0
   real(r8) ztdt                         ! 2*zdt (2dt)
   integer irow                      ! latitude pair index
   integer lm                        ! local longitudinal wavenumber index
   integer n                         ! total wavenumber index
   integer k                         ! level index

   call t_startf('dyn')

!$OMP PARALLEL DO PRIVATE (IROW)
   do irow=1,plat/2
      call dyn(irow,   grlps1(1,irow),   grt1(1,1,irow),    &
               grz1(1,1,irow),   grd1(1,1,irow),   &
               grfu1(1,1,irow),  grfv1(1,1,irow),  &
               grut1(1,1,irow),  grvt1(1,1,irow),  &
               grrh1(1,1,irow),  &
               grlps2(1,irow),   grt2(1,1,irow),   &
               grz2(1,1,irow),   grd2(1,1,irow),   &
               grfu2(1,1,irow),  &
               grfv2(1,1,irow),  grut2(1,1,irow),  &
               grvt2(1,1,irow),  grrh2(1,1,irow),ztodt  )
   end do

   call t_stopf('dyn')
!
!-----------------------------------------------------------------------
!
! Build vector with del^2 response function
!

   ztdt = ztodt
   zdt = ztdt/2       	
!   zdt = get_step_size()
!   if (is_first_step()) zdt = .5_r8*zdt
!   ztdt = 2._r8*zdt

   
   do n=1,pnmax
      ztdtsq(n) = ztdt*sq(n)
   end do

   call t_startf ('quad-tstep')

#ifdef OUTER_OMP
!$OMP PARALLEL DO PRIVATE(LM)
#endif
   do lm=1,numm(iam)
!
! Perform Gaussian quadrature
!
      call quad(lm,     zdt,     ztdtsq,  grlps1,  grlps2,  &
                grt1,   grz1,    grd1,    grfu1,   grfv1,   &
                grvt1,  grrh1,   grt2,    grz2,    grd2,   &
                grfu2,  grfv2,   grvt2,   grrh2   )
!
! Complete time advance, solve vertically coupled semi-implicit system
!
      call tstep(lm,zdt,ztdtsq)
   end do
   call t_stopf  ('quad-tstep')
!
! Find out if courant limit has been exceeded.  If so, the limiter will be
! applied in HORDIF
!
   call t_startf('courlim')
   call courlim(vmax2d,  vmax2dt, vcour   )
   call t_stopf('courlim')
!
! Linear part of horizontal diffusion
!
   call t_startf('hordif')

!$OMP PARALLEL DO PRIVATE(K)
   do k=1,plev
      call hordif(k,ztdt)
   end do

   call t_stopf('hordif')

   return
end subroutine dyndrv
