⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 grmult.f90

📁 CCSM Research Tools: Community Atmosphere Model (CAM)
💻 F90
字号:
#include <misc.h>#include <params.h>subroutine grmult(rcoslat ,d       ,qm1     ,tm1     ,um1     ,&                  vm1     ,z       ,tm2     ,phis    ,dpsl    ,&                  dpsm    ,omga    ,pdel    ,pbot    ,logpsm2 ,&                  logpsm1 ,rpmid   ,rpdel   ,fu      ,fv      ,&                  t2      ,ut      ,vt      ,drhs    ,pmid    ,&                  etadot  ,etamid  ,engy    ,ddpn    ,vpdsn   ,&                  dpslon  ,dpslat  ,nlon    )!----------------------------------------------------------------------- ! ! Purpose: ! Non-linear dynamics calculations in grid point space! ! Method: ! ! Author: ! Original version:  CCM1! Standardized:      J. Rosinski, June 1992! Reviewed:          B. Boville, D. Williamson, J. Hack, August 1992! Reviewed:          B. Boville, D. Williamson, April 1996!!-----------------------------------------------------------------------!! $Id: grmult.F90,v 1.5.8.1 2002/04/22 19:09:44 erik Exp $! $Author: erik $!!-----------------------------------------------------------------------   use precision   use pmgrid   use pspect   use commap   use physconst, only: rair, cappa, cpvir, zvir   implicit none#include <comhyb.h>!! Input arguments!   real(r8), intent(in) :: rcoslat               ! 1./cosine(latitude)   real(r8), intent(in) :: d(plond,plev)         ! divergence   real(r8), intent(in) :: qm1(plond,plev)         ! specific humidity   real(r8), intent(in) :: tm1(plond,plev)         ! temperature   real(r8), intent(in) :: um1(plond,plev)         ! zonal wind * cos(lat)   real(r8), intent(in) :: vm1(plond,plev)         ! meridional wind * cos(lat)   real(r8), intent(in) :: z(plond,plev)         ! vorticity   real(r8), intent(in) :: phis(plond)           ! surface geopotential   real(r8), intent(in) :: dpsl(plond)           ! longitudinal component of grad ln(ps)   real(r8), intent(in) :: dpsm(plond)           ! latitudinal component of grad ln(ps)   real(r8), intent(in) :: omga(plond,plev)      ! vertical pressure velocity   real(r8), intent(in) :: pdel(plond,plev)      ! layer thicknesses (pressure)   real(r8), intent(in) :: pbot(plond)           ! bottom interface pressure   real(r8), intent(in) :: logpsm2(plond)        ! log(psm2)   real(r8), intent(in) :: logpsm1(plond)          ! log(ps)   real(r8), intent(in) :: rpmid(plond,plev)     ! 1./pmid   real(r8), intent(in) :: rpdel(plond,plev)     ! 1./pdel   real(r8), intent(in) :: tm2(plond,plev)       ! temperature at previous time step   integer, intent(in) :: nlon!! Input/Output arguments!   real(r8), intent(inout) :: fu(plond,plev)        ! nonlinear term - u momentum eqn   real(r8), intent(inout) :: fv(plond,plev)        ! nonlinear term - v momentum eqn   real(r8), intent(inout) :: t2(plond,plev)        ! nonlinear term - temperature   real(r8), intent(inout) :: ut(plond,plev)        ! (u*TM1) - heat flux - zonal    real(r8), intent(inout) :: vt(plond,plev)        ! (u*TM1) - heat flux - meridional   real(r8), intent(inout) :: drhs(plond,plev)      ! RHS of divergence eqn (del^2 term)   real(r8), intent(inout) :: pmid(plond,plev)      ! pressure at full levels   real(r8), intent(inout) :: etadot(plon,plevp)    ! vertical velocity in eta coordinates   real(r8), intent(in)    :: etamid(plev)          ! midpoint values of eta (a+b)   real(r8), intent(inout) :: engy(plond,plev)      ! kinetic energy!! Output arguments!   real(r8), intent(out) :: ddpn(plond)           ! complete sum of d*delta p   real(r8), intent(out) :: vpdsn(plond)          ! complete sum V dot grad(ln(ps)) delta b   real(r8), intent(out) :: dpslat(plond,plev)    ! ln(ps) component of lon press gradient   real(r8), intent(out) :: dpslon(plond,plev)    ! ln(ps) component of lat press gradient!!---------------------------Local workspace-----------------------------!   real(r8) tv(plond,plev)        ! virtual temperature   real(r8) ddpk(plond)           ! partial sum of d*delta p   real(r8) vkdp                  ! V dot grad(ln(ps))   real(r8) vpdsk(plond)          ! partial sum  V dot grad(ln(ps)) delta b   real(r8) tk0(plond)            ! tm1 at phony level 0   real(r8) uk0(plond)            ! u at phony level 0   real(r8) vk0(plond)            ! v at phone level 0   real(r8) rtv(plond,plev)       ! rair*tv   real(r8) pterm(plond,plev)     ! intermediate term for hydrostatic eqn   real(r8) tterm(plond,plev)     ! intermediate term for hydrostatic eqn   real(r8) tmp                   ! temporary workspace   real(r8) tmpk                  ! temporary workspace   real(r8) tmpkp1                ! temporary workspace   real(r8) edotdpde(plond,plevp) ! etadot*dp/deta   real(r8) udel(plond,0:plev-1)  ! vertical u difference   real(r8) vdel(plond,0:plev-1)  ! vertical v difference   real(r8) tdel(plond,0:plev-1)  ! vertical TM1 difference   integer i,k,kk             ! longitude, level indices!! Initialize arrays which represent vertical sums (ddpk, ddpn, vpdsk,! vpdsn).  Set upper boundary condition arrays (k=0: tk0, uk0, vk0).!   do i=1,nlon      ddpk(i)  = 0.0      ddpn(i)  = 0.0      vpdsk(i) = 0.0      vpdsn(i) = 0.0      tk0(i)  = 0.0      uk0(i)  = 0.0      vk0(i)  = 0.0   end do!! Virtual temperature!   call virtem(nlon,plond,plev,tm1,qm1,zvir,tv)!! sum(plev)(d(k)*dp(k))!   do k=1,plev      do i=1,nlon         ddpn(i) = ddpn(i) + d(i,k)*pdel(i,k)         rtv(i,k) = rair*tv(i,k)      end do   end do!! sum(plev)(v(k)*grad(lnps)*db(k))!   do k=nprlev,plev      do i=1,nlon         vkdp = rcoslat*(um1(i,k)*dpsl(i) + vm1(i,k)*dpsm(i))*pbot(i)         vpdsn(i) = vpdsn(i) + vkdp*hybd(k)      end do   end do!! Compute etadot (dp/deta) (k+1/2).  Note: sum(k)(d(j)*dp(j)) required in! pressure region. sum(k)(d(j)*dp(j)) and sum(k)(v(j)*grad(ps)*db(j)) ! required in hybrid region!   do i=1,nlon      edotdpde(i,1) = 0.      edotdpde(i,plevp) = 0.   end do   do k=1,nprlev-1      do i=1,nlon         ddpk(i) = ddpk(i) + d(i,k)*pdel(i,k)         edotdpde(i,k+1) = -ddpk(i)      end do   end do   do k=nprlev,plev-1      do i=1,nlon         ddpk(i) = ddpk(i) + d(i,k)*pdel(i,k)         vkdp = rcoslat*(um1(i,k)*dpsl(i) + vm1(i,k)*dpsm(i))*pbot(i)         vpdsk(i) = vpdsk(i) + vkdp*hybd(k)         edotdpde(i,k+1) = -ddpk(i) - vpdsk(i) + hybi(k+1)*(ddpn(i)+vpdsn(i))      end do   end do!! Nonlinear advection terms.  u*tm1, v*tm1, kinetic energy first!   do k=1,plev      do i=1,nlon         ut(i,k) = um1(i,k)*tm1(i,k)         vt(i,k) = vm1(i,k)*tm1(i,k)         engy(i,k) = 0.5*(um1(i,k)**2 + vm1(i,k)**2)      end do   end do!! Compute workspace arrays for delta-u, delta-v, delta-tm1 (k)!   do i=1,nlon      udel(i,0) = um1(i,1) - uk0(i)      vdel(i,0) = vm1(i,1) - vk0(i)      tdel(i,0) = tm1(i,1) - tk0(i)   end do   do k=1,plev-1      do i=1,nlon         udel(i,k) = um1(i,k+1) - um1(i,k)         vdel(i,k) = vm1(i,k+1) - vm1(i,k)         tdel(i,k) = tm1(i,k+1) - tm1(i,k)      end do   end do!! Horizontal advection: u*z, v*z, energy conversion term (omega/p),! vertical advection for interface above.  Pure pressure region first.!   do k=1,nprlev-1      do i=1,nlon         dpslat(i,k) = 0.         dpslon(i,k) = 0.         tmpk   = 0.5*rpdel(i,k)*edotdpde(i,k  )         tmpkp1 = 0.5*rpdel(i,k)*edotdpde(i,k+1)         fu(i,k) = fu(i,k) + vm1(i,k)*z(i,k) - udel(i,k-1)*tmpk - udel(i,k  )*tmpkp1         fv(i,k) = fv(i,k) - um1(i,k)*z(i,k) - vdel(i,k-1)*tmpk - vdel(i,k  )*tmpkp1#ifdef HADVTEST!!jr Modify so TM1 only has horizontal advection!         t2(i,k) = t2(i,k) + d(i,k)*tm1(i,k)#else         t2(i,k) = t2(i,k) + d(i,k)*tm1(i,k) - tdel(i,k-1)*tmpk + &            cappa*tv(i,k)/(1. + cpvir*qm1(i,k))* &            omga(i,k)*rpmid(i,k) - tdel(i,k)*tmpkp1#endif      end do   end do!! Hybrid region above bottom level: Computations are the same as in pure! pressure region, except that pressure gradient terms are added to ! momentum tendencies.!   do k=nprlev,plev-1      do i=1,nlon         tmpk   = 0.5*rpdel(i,k)*edotdpde(i,k  )         tmpkp1 = 0.5*rpdel(i,k)*edotdpde(i,k+1)         tmp = rtv(i,k)*hybm(k)*rpmid(i,k)*pbot(i)         dpslon(i,k) = rcoslat*tmp*dpsl(i)         dpslat(i,k) = rcoslat*tmp*dpsm(i)         fu(i,k) = fu(i,k) + vm1(i,k)*z(i,k) - udel(i,k-1)*tmpk - &            udel(i,k  )*tmpkp1 - dpslon(i,k)         fv(i,k) = fv(i,k) - um1(i,k)*z(i,k) - vdel(i,k-1)*tmpk - &            vdel(i,k  )*tmpkp1 - dpslat(i,k)#ifdef HADVTEST!!jr Modify so TM1 only has horizontal advection!         t2(i,k) = t2(i,k) + d(i,k)*tm1(i,k)#else         t2(i,k) = t2(i,k) + d(i,k)*tm1(i,k) - tdel(i,k-1)*tmpk + &            cappa*tv(i,k)/(1. + cpvir*qm1(i,k))* &            omga(i,k)*rpmid(i,k) - tdel(i,k)*tmpkp1#endif      end do   end do!! Bottom level!   do i=1,nlon      tmpk = 0.5*rpdel(i,plev)*edotdpde(i,plev  )      tmp  = rtv(i,plev)*hybm(plev)*rpmid(i,plev)*pbot(i)      dpslon(i,plev) = rcoslat*tmp*dpsl(i)      dpslat(i,plev) = rcoslat*tmp*dpsm(i)      fu(i,plev) = fu(i,plev) + vm1(i,plev)*z(i,plev) - &         udel(i,plev-1)*tmpk - dpslon(i,plev)      fv(i,plev) = fv(i,plev) - um1(i,plev)*z(i,plev) - &         vdel(i,plev-1)*tmpk - dpslat(i,plev)#ifdef HADVTEST!!jr Modify so TM1 only has horizontal advection!      t2(i,plev) = t2(i,plev) + d(i,plev)*tm1(i,plev)#else      t2(i,plev) = t2(i,plev) + d(i,plev)*tm1(i,plev) - &         tdel(i,plev-1)*tmpk + &         cappa*tv(i,plev)/(1. + cpvir*qm1(i,plev))* &         omga(i,plev)*rpmid(i,plev)#endif   end do!! Convert eta-dot(dp/deta) to eta-dot (top and bottom = 0.)!   do i=1,nlon      etadot(i,1) = 0.      etadot(i,plevp) = 0.   end do   do k=2,plev      tmp = etamid(k) - etamid(k-1)      do i=1,nlon#ifdef HADVTEST!!jr Set etadot to zero for horizontal advection test!         etadot(i,k) = 0.#else         etadot(i,k) = edotdpde(i,k)*tmp/(pmid(i,k) - pmid(i,k-1))#endif      end do   end do!!-----------------------------------------------------------------------!! Divergence and hydrostatic equations! Store some temporary terms!   do k=2,plev-1      do i=1,nlon         pterm(i,k) = rtv(i,k)*rpmid(i,k)*pdel(i,k)         tterm(i,k) = 0.5*tm2(i,k) - tm1(i,k)      end do   end do   do i=1,nlon      tterm(i,1) = 0.5*tm2(i,1) - tm1(i,1)      tterm(i,plev) = 0.5*tm2(i,plev) - tm1(i,plev)   end do!! Del squared part of RHS of divergence equation.! Kinetic energy and diagonal term of hydrostatic equation.! Total temperature as opposed to  perturbation temperature is acceptable! since del-square operator will operate on this term.!   do k=1,plev-1      do i=1,nlon         drhs(i,k) = phis(i) + engy(i,k) + rtv(i,k)*0.5* &            rpmid(i,k)*pdel(i,k) + href(k,k)*tterm(i,k) + &            bps(k)*(0.5*logpsm2(i) - logpsm1(i))      end do   end do   do i=1,nlon      drhs(i,plev) = phis(i) + engy(i,plev) + rtv(i,plev)*0.5* &         rpmid(i,plev)*pdel(i,plev) + &         href(plev,plev)*tterm(i,plev) + &         bps(plev)*(0.5*logpsm2(i) - logpsm1(i))   end do!! Bottom level term of hydrostatic equation!   do k=1,plev-1      do i=1,nlon         drhs(i,k) = drhs(i,k) + rtv(i,plev)* &            rpmid(i,plev)*pdel(i,plev) + &            href(plev,k)*tterm(i,plev)      end do   end do!! Interior terms of hydrostatic equation!   do k=1,plev-2      do kk=k+1,plev-1         do i=1,nlon            drhs(i,k) = drhs(i,k) + pterm(i,kk) + href(kk,k)*tterm(i,kk)         end do      end do   end do!       returnend subroutine grmult

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -