#include <misc.h>
#include <params.h>
subroutine stepon 1,38
!-----------------------------------------------------------------------
!
! Purpose:
! Loop over time, calling driving routines for physics, dynamics, transport
!
! Original version: CCM1
!
!-----------------------------------------------------------------------
use shr_kind_mod
, only: r8 => shr_kind_r8
use history
, only: wshist, wrapup
use pmgrid
use pspect
use comslt
use rgrid
use prognostics
use commap
use restart
, only: write_restart
use physconst
, only: cappa, gravit
#if ( defined SPMD )
use mpishorthand
use spmd_dyn
, only: npes, compute_gsfactors
#endif
#if (defined COUP_CSM)
use ccsm_msg
, only: csmstop, ccsmfin
#endif
use ppgrid
, only: begchunk, endchunk
use physics_types
, only: physics_state, physics_tend
use phys_buffer
, only: pbuf
use dp_coupling
, only: d_p_coupling, p_d_coupling
use time_manager
, only: advance_timestep, get_step_size, get_nstep, &
is_first_step, is_first_restart_step, &
is_last_step, is_end_curr_day
implicit none
#include <comctl.h>
#include <comhyb.h>
#include <comlun.h>
#include <comqfl.h>
!------------------------------Parameters-------------------------------
!
integer, parameter :: pmap = 20000 ! max dimension of evenly spaced vert. grid used
! ! by SLT code to map the departure pts into true
! ! model levels.
!
!---------------------------Local workspace-----------------------------
!
integer kdpmpf (pmap) ! artificial full vert grid indices
integer kdpmph (pmap) ! artificial half vert grid indices
type(physics_state), allocatable :: phys_state(:)
type(physics_tend ), allocatable :: phys_tend(:)
real(r8) hyad (plev) ! del (A)
real(r8) lam (plond,platd) ! longitude coords of extended grid
real(r8) phi (platd) ! latitude coords of extended grid
real(r8) dphi (platd) ! latitude intervals (radians)
real(r8) gw (plat) ! Gaussian weights
real(r8) sinlam (plond,platd) ! sin(lam) model domain only
real(r8) coslam (plond,platd) ! cos(lam) model domain only
real(r8) lbasdy (4,2,platd) ! latitude derivative weights
real(r8) lbasdz (4,2,plev) ! vert (full levels) deriv wghts
real(r8) lbassd (4,2,plevp) ! vert (half levels) deriv wghts
real(r8) lbasiy (4,2,platd) ! Lagrange cubic interp wghts (lat.)
real(r8) lbasiz (4,2,plev) ! Lagrange cubic interp wghts (vert)
real(r8) lbassi (4,2,plevp) ! Lagrange cubic interp wghts (vert)
real(r8) detam (plev) ! intervals between vert full levs.
real(r8) detai (plevp) ! intervals between vert half levs.
real(r8) dlam (platd) ! longitudinal grid interval (radians)
real(r8) cwava (plat) ! weight applied to global integrals
real(r8) etamid (plev) ! vertical coords at midpoints
real(r8) etaint (plevp) ! vertical coords at interfaces
real(r8), allocatable :: t2(:,:,:) ! temp tendency
real(r8), allocatable :: fu(:,:,:) ! u wind tendency
real(r8), allocatable :: fv(:,:,:) ! v wind tendency
real(r8) flx_net(plond,beglat:endlat) ! net flux from physics
real(r8) coslat(plond)
real(r8) rcoslat(plond)
real(r8) rpmid(plond,plev)
real(r8) pdel(plond,plev)
real(r8) pint(plond,plevp)
real(r8) pmid(plond,plev)
real(r8) ztodt ! time step
real(r8) :: wcstart, wcend ! wallclock timestamp at start, end of timestep
real(r8) :: usrstart, usrend ! user timestamp at start, end of timestep
real(r8) :: sysstart, sysend ! sys timestamp at start, end of timestep
integer kk ! |
integer kk1 ! |
integer kk2 ! | - indices
integer kstep ! |
integer l ! |
integer lvsum ! counter
integer lsum ! counter
real(r8) vsum ! accumulator for SLD binning statistics
logical vflag ! logical flag to indicate that binning has been done
! ! correctly
integer i,k,lat,j,begj ! longitude,level,latitude indices
real(r8) tmp1 ! temp space
integer year,month,day,tod ! date info
integer ntspdy ! Number of timesteps per day
#ifdef SPMD
integer :: numsend ! number of items to be sent
integer :: numrecv(0:npes-1)! number of items to be received
integer :: displs(0:npes-1) ! displacement array
integer :: numperlat ! number of items per latitude band
#endif
!
! Externals
!
logical, external :: rstwr ! whether or not to write restart files
!
!-----------------------------------------------------------------------
!
! Define eta coordinates: Used for calculation etadot vertical velocity
! for slt.
!
call t_startf ('stepon_startup')
do k=1,plev
etamid(k) = hyam(k) + hybm(k)
end do
do k=1,plevp
etaint(k) = hyai(k) + hybi(k)
end do
!
! Initialize matrix gamma (used in sld T computation)
!
gamma(:,:) = 0.
do k = 1,plev
tmp1 = cappa*t0(k)*hypi(plevp)/hypm(k)
gamma(k,k) = 0.5*tmp1
do l=1,k-1
gamma(l,k) = tmp1
end do
end do
!
! Set slt common block variables
!
call grdini
(pmap ,etamid ,etaint ,gravit ,dlam , &
lam ,phi ,dphi ,gw ,sinlam , &
coslam ,lbasdy ,lbasdz ,lbassd ,lbasiy , &
lbasiz ,lbassi ,detam ,detai ,kdpmpf , &
kdpmph ,cwava ,phigs )
if (is_first_step()) then
do lat=beglat,endlat
j = j1 - 1 + lat
do i=1,nlon(lat)
coslat(i) = cos(clat(lat))
rcoslat(i) = 1./coslat(i)
end do
!
! Set current time pressure arrays for model levels etc.
!
call plevs0
(nlon(lat), plond, plev, ps(1,lat,n3), pint, pmid, pdel)
!
do k=1,plev
do i=1,nlon(lat)
rpmid(i,k) = 1./pmid(i,k)
end do
end do
!
! Compute appropriate (1/ps)etadot(dp/deta)
!
call etadt0
(lat, nlon(lat), &
rcoslat ,div(1,1,lat,n3), u3(i1,1,j,n3), v3(i1,1,j,n3), dpsl(1,lat), &
dpsm(1,lat), pdel, ps(1,lat,n3), ed1(1,1,lat))
!
! Calculate vertical motion field
!
call omcalc
(rcoslat, div(1,1,lat,n3), u3(i1,1,j,n3), v3(i1,1,j,n3), dpsl(1,lat), &
dpsm(1,lat), pmid, pdel, rpmid, pint(1,plevp), &
omga(1,1,lat), nlon(lat))
end do
end if
!
! Compute pdel from "A" portion of hybrid vertical grid
!
do k=1,plev
hyad(k) = hyai(k+1) - hyai(k)
end do
do k=1,plev
do i=1,plon
pdela(i,k) = hyad(k)*ps0
end do
end do
!
!----------------------------------------------------------
! Initialize departure point bin arrays to 0.
!----------------------------------------------------------
!
kstep = 0
do lat = beglat,endlat
do k = 1,plev
do kk = 1,plev
levkntl(kk,k,lat) = 0.
end do
end do
end do
allocate(phys_state(begchunk:endchunk))
allocate(phys_tend(begchunk:endchunk))
allocate(t2(plond,plev,beglat:endlat))
allocate(fu(plond,plev,beglat:endlat))
allocate(fv(plond,plev,beglat:endlat))
!
! Beginning of basic time step loop
!
call t_stopf ('stepon_startup')
do
if (masterproc .and. print_step_cost) then
call t_stampf (wcstart, usrstart, sysstart)
end if
ztodt = get_step_size
()
!
!----------------------------------------------------------
! PHYSPKG Call the Physics package
!----------------------------------------------------------
!
begj = beglatex + numbnd
call t_startf('d_p_coupling')
call d_p_coupling
(ps(1,beglat,n3), t3(i1,1,begj,n3), u3(i1,1,begj,n3), &
v3(i1,1,begj,n3), q3(i1,1,1,begj,n3), &
omga, phis, phys_state, phys_tend, pbuf)
call t_stopf('d_p_coupling')
call t_startf('phys_driver')
if (ideal_phys) then
call phys_idealized
(phys_state, phys_tend, ztodt, etamid)
else if (adiabatic) then
call phys_adiabatic
(phys_state, phys_tend)
else
call physpkg
(phys_state, gw, ztodt, phys_tend, pbuf)
end if
call t_stopf('phys_driver')
call t_startf('p_d_coupling')
call p_d_coupling
(phys_state, phys_tend, t2, fu, fv, flx_net,q3(i1,1,1,begj,n3))
call t_stopf('p_d_coupling')
if (is_first_step() .or. is_first_restart_step()) then
call print_memusage
('stepon after p_d_coupling')
end if
!----------------------------------------------------------
! DYNPKG Call the Dynamics Package
!----------------------------------------------------------
call t_startf ('dynpkg')
call dynpkg
(pmap ,t2 ,fu ,fv ,etamid , &
etaint ,cwava ,detam ,dlam ,lam , &
phi ,dphi ,sinlam ,coslam ,lbasdy , &
lbasdz ,lbasiy ,lbassi ,lbasiz ,detai , &
kdpmpf ,kdpmph ,flx_net , ztodt )
call t_stopf ('dynpkg')
if (is_first_restart_step()) then
call print_memusage
('stepon after dynpkg')
end if
call t_startf('stepon_single')
! Set end of run flag.
#if ( ! defined COUP_CSM )
if (is_last_step()) nlend = .true.
#else
if (csmstop) then
if ( masterproc ) write(6,*)'atm: Stopping at the end of this day'
if (is_end_curr_day()) nlend = .true.
end if
#endif
!
!----------------------------------------------------------
! History and restart logic
!----------------------------------------------------------
!
! Write and/or dispose history tapes if required
!
call t_startf ('wshist')
call wshist
()
call t_stopf ('wshist')
!
! Write restart file
!
if (rstwr() .and. nrefrq /= 0) then
call t_startf ('write_restart')
call write_restart
call t_stopf ('write_restart')
end if
!
! Dispose necessary files
!
call t_startf ('wrapup')
call wrapup
call t_stopf ('wrapup')
if (masterproc .and. print_step_cost) then
call t_stampf (wcend, usrend, sysend)
write(6,'(a,3f8.3,a)')'Prv timestep wallclock, usr, sys=', &
wcend-wcstart, usrend-usrstart, sysend-sysstart, ' seconds'
end if
!
! Increment nstep before returning to top of loop
!
call advance_timestep
()
kstep = kstep + 1
!
! Compute some statistical info
!
if (nlend) then
#if ( defined SPMD )
numperlat = plev*plev
call compute_gsfactors
(numperlat, numsend, numrecv, displs)
call mpigatherv
(levkntl(1,1,beglat), numsend, mpir8, &
levkntl , numrecv, displs, mpir8, 0, mpicom)
#endif
if (masterproc) then
do k = 1,plev
do kk = 1,plev
levknt(kk,k) = 0.
do lat = 1,plat
levknt(kk,k) = levknt(kk,k) + levkntl(kk,k,lat)
end do
end do
end do
lsum = 0
do lat = 1,plat
lsum = lsum + nlon(lat)
end do
vflag = .false.
do k = 1,plev
vsum = 0.
do kk = 1,plev
vsum = vsum + levknt(kk,k)
end do
lvsum = vsum + 0.01
if( lvsum .ne. lsum*kstep ) vflag = .true.
end do
do k = 1,plev
do kk = 1,plev
levknt(kk,k) = levknt(kk,k)/float(lsum*kstep)
if (levknt(kk,k) .eq. 0.) levknt(kk,k) = 1.e+36
end do
end do
if(vflag) then
write(6,*) '********************************************'
write(6,1000)
write(6,*) '********************************************'
else
write(6,2000)
k = 1
write(6,3001) hypm(k)/100.,(levknt(kk,k),kk = 1, 6)
k = 2
write(6,3002) hypm(k)/100.,(levknt(kk,k),kk = 1, 7)
k = 3
write(6,3003) hypm(k)/100.,(levknt(kk,k),kk = 1, 8)
k = 4
write(6,3004) hypm(k)/100.,(levknt(kk,k),kk = 1, 9)
k = 5
write(6,3005) hypm(k)/100.,(levknt(kk,k),kk = 1,10)
do k = 6,plev
kk1 = k-5
kk2 = k+5
if(kk2 .gt. plev) kk2 = plev
write(6,3000) hypm(k)/100.,(levknt(kk,k),kk = kk1,kk2)
end do
end if
end if
end if
call t_stopf('stepon_single')
!
! Check for end of run
!
if (nlend) then
call print_memusage
('End stepon')
deallocate(phys_state)
deallocate(phys_tend)
deallocate(t2)
deallocate(fu)
deallocate(fv)
#ifdef COUP_CSM
call ccsmfin
#endif
return
end if
end do ! End of timestep loop
1000 format(' ERROR in binning departure points; sums were done'// &
' incorrectly. not printing results.')
2000 format(/40x,' BINNING STATISTICS FOR VERTICAL DEPARTURE POINTS'// &
' level -5 -4 -3 -2 ', &
' -1 0 (arr pt) 1 2 3 4 ', &
' 5'/)
3000 format(' ',f9.4, 4x,11f10.5)
3001 format(' ',f9.4,54x,11f10.5)
3002 format(' ',f9.4,44x,11f10.5)
3003 format(' ',f9.4,34x,11f10.5)
3004 format(' ',f9.4,24x,11f10.5)
3005 format(' ',f9.4,14x,11f10.5)
end subroutine stepon