#include <misc.h>
#include <params.h>
subroutine grcalcs (irow ,ztodt ,grts ,grths ,grds ,& 2,8
grzs ,grus ,gruhs ,grvs ,grvhs ,&
grpss ,grdpss ,grpms ,grpls ,tmpSPEcoef)
!-----------------------------------------------------------------------
!
! Complete inverse Legendre transforms from spectral to Fourier space at
! the the given latitude. Only positive latitudes are considered and
! symmetric and antisymmetric (about equator) components are computed.
! The sum and difference of these components give the actual fourier
! coefficients for the latitude circle in the northern and southern
! hemispheres respectively.
!
! The naming convention is as follows:
! - The fourier coefficient arrays all begin with "gr";
! - "t, q, d, z, ps" refer to temperature, specific humidity,
! divergence, vorticity, and surface pressure;
! - "h" refers to the horizontal diffusive tendency for the field.
! - "s" suffix to an array => symmetric component;
! - "a" suffix to an array => antisymmetric component.
! Thus "grts" contains the symmetric Fourier coeffs of temperature and
! "grtha" contains the antisymmetric Fourier coeffs of the temperature
! tendency due to horizontal diffusion.
! Three additional surface pressure related quantities are returned:
! 1. "grdpss" and "grdpsa" contain the surface pressure factor
! (proportional to del^4 ps) used for the partial correction of
! the horizontal diffusion to pressure surfaces.
! 2. "grpms" and "grpma" contain the longitudinal component of the
! surface pressure gradient.
! 3. "grpls" and "grpla" contain the latitudinal component of the
! surface pressure gradient.
!
!---------------------------Code history--------------------------------
!
! Original version: CCM1
! Standardized: J. Rosinski, June 1992
! Reviewed: B. Boville, D. Williamson, J. Hack, August 1992
! Reviewed: B. Boville, D. Williamson, April 1996
! Modified: P. Worley, October 2002
!
!-----------------------------------------------------------------------
!
! $Id: grcalc.F90,v 1.5.6.9 2004/04/28 23:43:54 eaton Exp $
! $Author: eaton $
!
use shr_kind_mod
, only: r8 => shr_kind_r8
use pmgrid
use pspect
use comspe
use rgrid
use commap
use dynconst
, only: ra, ez
use comhd
implicit none
!
! Input arguments
!
integer, intent(in) :: irow ! latitude pair index
real(r8), intent(in) :: ztodt ! twice the timestep unless nstep = 0
real(r8), intent(in) :: tmpSPEcoef(plev*24,pnmax,maxm) ! rearranged variables array
!
! Output arguments: symmetric fourier coefficients
!
real(r8), intent(out) :: grts(2*maxm,plev) ! sum(n) of t(n,m)*P(n,m)
real(r8), intent(out) :: grths(2*maxm,plev) ! sum(n) of K(2i)*t(n,m)*P(n,m)
real(r8), intent(out) :: grds(2*maxm,plev) ! sum(n) of d(n,m)*P(n,m)
real(r8), intent(out) :: grzs(2*maxm,plev) ! sum(n) of z(n,m)*P(n,m)
real(r8), intent(out) :: grus(2*maxm,plev) ! sum(n) of z(n,m)*H(n,m)*a/(n(n+1))
real(r8), intent(out) :: gruhs(2*maxm,plev) ! sum(n) of K(2i)*z(n,m)*H(n,m)*a/(n(n+1))
real(r8), intent(out) :: grvs(2*maxm,plev) ! sum(n) of d(n,m)*H(n,m)*a/(n(n+1))
real(r8), intent(out) :: grvhs(2*maxm,plev) ! sum(n) of K(2i)*d(n,m)*H(n,m)*a/(n(n+1))
real(r8), intent(out) :: grpss(2*maxm) ! sum(n) of lnps(n,m)*P(n,m)
real(r8), intent(out) :: grdpss(2*maxm) ! sum(n) of K(4)*(n(n+1)/a**2)**2*2dt*lnps(n,m)*P(n,m)
real(r8), intent(out) :: grpms(2*maxm) ! sum(n) of lnps(n,m)*H(n,m)
real(r8), intent(out) :: grpls(2*maxm) ! sum(n) of lnps(n,m)*P(n,m)*m/a
!
!---------------------------Local workspace-----------------------------
!
real(r8) dalpn(pspt) ! (a/(n(n+1)))*derivative of Legendre functions (complex)
real(r8) zurcor ! conversion term relating abs. & rel. vort.
real(r8) tmpGRcoef(plev*24,maxm) ! temporal storage for Fourier coeffs
integer k ! level index
integer lm, m ! local and global Fourier wavenumber indices of spectral array
integer mlength ! number of local wavenumbers
integer n ! meridional wavenumber index
integer ir,ii ! spectral indices
integer lmr,lmc ! spectral indices
integer lmwave0 ! local index for wavenumber 0
integer lmrwave0 ! local offset for wavenumber 0
integer kv ! level x variable index
!
!-----------------------------------------------------------------------
!
! Compute alpn and dalpn
!
!DIR$ NOSTREAM
lmwave0 = -1
lmrwave0 = 0
dalpn(2) = 0.0
mlength = numm(iam)
!cdir novector
do lm=1,mlength
m = locm(lm,iam)
lmr = lnstart(lm)
if (m .eq. 1) then
lmwave0 = lm
lmrwave0 = lmr
endif
do n=1,nlen(m)
dalpn(lmr+n) = ldalp(lmr+n,irow)*rsq(m+n-1)*ra
end do
end do
zurcor = ez*dalpn(lmrwave0 + 2)
!
! Initialize sums
!
grpss (:) = 0.
grpls (:) = 0.
grpms (:) = 0.
grdpss(:) = 0.
!cdir collapse
tmpGRcoef (:,:) = 0.
!
! Loop over n for t,q,d,and end of u and v
!
!cdir novector
do lm=1,mlength
m = locm(lm,iam)
lmr = lnstart(lm)
do n=2,nlen(m),2
do kv=1,plev*8
tmpGRcoef(kv,lm) = tmpGRcoef(kv,lm) + tmpSPEcoef(kv,n,lm)*dalpn(lmr+n)
end do
end do
end do
!
!cdir novector
do lm=1,mlength
m = locm(lm,iam)
lmr = lnstart(lm)
do n=1,nlen(m),2
do kv=plev*8+1,plev*24
tmpGRcoef(kv,lm) = tmpGRcoef(kv,lm) + tmpSPEcoef(kv,n,lm)*lalp(lmr+n,irow)
end do
end do
end do
!
! Combine the two parts of u(m) and v(m)
!
do lm=1,mlength
do kv=1,plev*8
tmpGRcoef(kv,lm) = tmpGRcoef(kv,lm) + tmpGRcoef(kv+plev*16,lm)
end do
end do
!
! Save accumulated results to gr* arrays
!
do lm=1,mlength
!DIR$ PREFERVECTOR
do k=1,plev
grus (2*lm-1,k) = tmpGRcoef(k ,lm)
grus (2*lm ,k) = tmpGRcoef(k+plev ,lm)
grvs (2*lm-1,k) = tmpGRcoef(k+plev*2 ,lm)
grvs (2*lm ,k) = tmpGRcoef(k+plev*3 ,lm)
gruhs(2*lm-1,k) = tmpGRcoef(k+plev*4 ,lm)
gruhs(2*lm ,k) = tmpGRcoef(k+plev*5 ,lm)
grvhs(2*lm-1,k) = tmpGRcoef(k+plev*6 ,lm)
grvhs(2*lm ,k) = tmpGRcoef(k+plev*7 ,lm)
grts (2*lm-1,k) = tmpGRcoef(k+plev*8 ,lm)
grts (2*lm ,k) = tmpGRcoef(k+plev*9 ,lm)
grths(2*lm-1,k) = tmpGRcoef(k+plev*10,lm)
grths(2*lm ,k) = tmpGRcoef(k+plev*11,lm)
grds (2*lm-1,k) = tmpGRcoef(k+plev*12,lm)
grds (2*lm ,k) = tmpGRcoef(k+plev*13,lm)
grzs (2*lm-1,k) = tmpGRcoef(k+plev*14,lm)
grzs (2*lm ,k) = tmpGRcoef(k+plev*15,lm)
end do
end do
!
! Remove Coriolis contribution to absolute vorticity from u(m)
! Correction for u:zeta=vz-ez=(zeta+f)-f
!
if (lmwave0 .ne. -1) then
do k=1,plev
! grus(1,k) = grus(1,k) - zurcor
grus(2*lmwave0-1,k) = grus(2*lmwave0-1,k) - zurcor
end do
endif
!
!-----------------------------------------------------------------------
!
! Computation for 1-level variables (ln(p*) and derivatives).
!
!cdir novector
do lm=1,mlength
m = locm(lm,iam)
lmr = lnstart(lm)
lmc = 2*lmr
!cdir shortloop
do n=1,nlen(m),2
ir = lmc + 2*n - 1
ii = ir + 1
!
grpss (2*lm-1) = grpss (2*lm-1) + alps(ir)*lalp(lmr+n,irow)
grpss (2*lm ) = grpss (2*lm ) + alps(ii)*lalp(lmr+n,irow)
!
grdpss(2*lm-1) = grdpss(2*lm-1) + alps(ir)*lalp(lmr+n,irow)*hdfst4(m+n-1)*ztodt
grdpss(2*lm ) = grdpss(2*lm ) + alps(ii)*lalp(lmr+n,irow)*hdfst4(m+n-1)*ztodt
end do
end do
!cdir novector
do lm=1,mlength
m = locm(lm,iam)
lmr = lnstart(lm)
lmc = 2*lmr
!cdir shortloop
do n=2,nlen(m),2
ir = lmc + 2*n - 1
ii = ir + 1
!
grpms(2*lm-1) = grpms(2*lm-1) + alps(ir)*ldalp(lmr+n,irow)*ra
grpms(2*lm ) = grpms(2*lm ) + alps(ii)*ldalp(lmr+n,irow)*ra
end do
!
! Multiply by m/a to get d(ln(p*))/dlamda
! and by 1/a to get (1-mu**2)d(ln(p*))/dmu
!
grpls(2*lm-1) = -grpss(2*lm )*ra*xm(m)
grpls(2*lm ) = grpss(2*lm-1)*ra*xm(m)
end do
!
return
end subroutine grcalcs
subroutine grcalca (irow ,ztodt ,grta ,grtha ,grda ,& 2,8
grza ,grua ,gruha ,grva ,grvha ,&
grpsa ,grdpsa ,grpma ,grpla ,tmpSPEcoef)
!-----------------------------------------------------------------------
!
! Complete inverse Legendre transforms from spectral to Fourier space at
! the the given latitude. Only positive latitudes are considered and
! symmetric and antisymmetric (about equator) components are computed.
! The sum and difference of these components give the actual fourier
! coefficients for the latitude circle in the northern and southern
! hemispheres respectively.
!
! The naming convention is as follows:
! - The fourier coefficient arrays all begin with "gr";
! - "t, q, d, z, ps" refer to temperature, specific humidity,
! divergence, vorticity, and surface pressure;
! - "h" refers to the horizontal diffusive tendency for the field.
! - "s" suffix to an array => symmetric component;
! - "a" suffix to an array => antisymmetric component.
! Thus "grts" contains the symmetric Fourier coeffs of temperature and
! "grtha" contains the antisymmetric Fourier coeffs of the temperature
! tendency due to horizontal diffusion.
! Three additional surface pressure related quantities are returned:
! 1. "grdpss" and "grdpsa" contain the surface pressure factor
! (proportional to del^4 ps) used for the partial correction of
! the horizontal diffusion to pressure surfaces.
! 2. "grpms" and "grpma" contain the longitudinal component of the
! surface pressure gradient.
! 3. "grpls" and "grpla" contain the latitudinal component of the
! surface pressure gradient.
!
!---------------------------Code history--------------------------------
!
! Original version: CCM1
! Standardized: J. Rosinski, June 1992
! Reviewed: B. Boville, D. Williamson, J. Hack, August 1992
! Reviewed: B. Boville, D. Williamson, April 1996
! Modified: P. Worley, October 2002
!
!-----------------------------------------------------------------------
!
! $Id: grcalc.F90,v 1.5.6.9 2004/04/28 23:43:54 eaton Exp $
! $Author: eaton $
!
use shr_kind_mod
, only: r8 => shr_kind_r8
use pmgrid
use pspect
use comspe
use rgrid
use commap
use dynconst
, only: ra
use comhd
implicit none
!
! Input arguments
!
integer, intent(in) :: irow ! latitude pair index
real(r8), intent(in) :: ztodt ! twice the timestep unless nstep = 0
real(r8), intent(in) :: tmpSPEcoef(plev*24,pnmax,maxm) ! array for rearranged variables
!
!
! Output arguments: antisymmetric fourier coefficients
!
real(r8), intent(out) :: grta(2*maxm,plev) ! sum(n) of t(n,m)*P(n,m)
real(r8), intent(out) :: grtha(2*maxm,plev) ! sum(n) of K(2i)*t(n,m)*P(n,m)
real(r8), intent(out) :: grda(2*maxm,plev) ! sum(n) of d(n,m)*P(n,m)
real(r8), intent(out) :: grza(2*maxm,plev) ! sum(n) of z(n,m)*P(n,m)
real(r8), intent(out) :: grua(2*maxm,plev) ! sum(n) of z(n,m)*H(n,m)*a/(n(n+1))
real(r8), intent(out) :: gruha(2*maxm,plev) ! sum(n) of K(2i)*z(n,m)*H(n,m)*a/(n(n+1))
real(r8), intent(out) :: grva(2*maxm,plev) ! sum(n) of d(n,m)*H(n,m)*a/(n(n+1))
real(r8), intent(out) :: grvha(2*maxm,plev) ! sum(n) of K(2i)*d(n,m)*H(n,m)*a/(n(n+1))
real(r8), intent(out) :: grpsa(2*maxm) ! sum(n) of lnps(n,m)*P(n,m)
real(r8), intent(out) :: grdpsa(2*maxm) ! sum(n) of K(4)*(n(n+1)/a**2)**2*2dt*lnps(n,m)*P(n,m)
real(r8), intent(out) :: grpma(2*maxm) ! sum(n) of lnps(n,m)*H(n,m)
real(r8), intent(out) :: grpla(2*maxm) ! sum(n) of lnps(n,m)*P(n,m)*m/a
!
!---------------------------Local workspace-----------------------------
!
real(r8) dalpn(pspt) ! (a/(n(n+1)))*derivative of Legendre functions (complex)
real(r8) tmpGRcoef(plev*24,maxm) ! temporal storage for Fourier coefficients
integer k ! level index
integer lm, m ! local and global Fourier wavenumber indices of spectral array
integer mlength ! number of local wavenumbers
integer n ! meridional wavenumber index
integer ir,ii ! spectral indices
integer lmr,lmc ! spectral indices
integer kv ! level x variable index
!
!-----------------------------------------------------------------------
!
! Compute alpn and dalpn
!
!DIR$ NOSTREAM
mlength = numm(iam)
!cdir novector
do lm=1,mlength
m = locm(lm,iam)
lmr = lnstart(lm)
do n=1,nlen(m)
dalpn(lmr+n) = ldalp(lmr+n,irow)*rsq(m+n-1)*ra
end do
end do
!
! Initialize sums
!
grpsa (:) = 0.
grpla (:) = 0.
grpma (:) = 0.
grdpsa(:) = 0.
!cdir collapse
tmpGRcoef(:,:) = 0.
!
! Loop over n for t,q,d,and end of u and v
!
!cdir novector
do lm=1,mlength
m = locm(lm,iam)
lmr = lnstart(lm)
do n=1,nlen(m),2
do kv=1,plev*8
tmpGRcoef(kv,lm) = tmpGRcoef(kv,lm) + tmpSPEcoef(kv,n,lm)*dalpn(lmr+n)
end do
end do
end do
!cdir novector
do lm=1,mlength
m = locm(lm,iam)
lmr = lnstart(lm)
do n=2,nlen(m),2
do kv=plev*8+1,plev*24
tmpGRcoef(kv,lm) = tmpGRcoef(kv,lm) + tmpSPEcoef(kv,n,lm)*lalp(lmr+n,irow)
end do
end do
end do
!
! Combine the two parts of u(m) and v(m)
!
do lm=1,mlength
do kv=1,plev*8
tmpGRcoef(kv,lm) = tmpGRcoef(kv,lm) + tmpGRcoef(kv+plev*16,lm)
end do
end do
!
! Save accumulated results to gr* arrays
!
do lm=1,mlength
!DIR$ PREFERVECTOR
do k=1,plev
grua (2*lm-1,k) = tmpGRcoef(k ,lm)
grua (2*lm ,k) = tmpGRcoef(k+plev ,lm)
grva (2*lm-1,k) = tmpGRcoef(k+plev*2 ,lm)
grva (2*lm ,k) = tmpGRcoef(k+plev*3 ,lm)
gruha(2*lm-1,k) = tmpGRcoef(k+plev*4 ,lm)
gruha(2*lm ,k) = tmpGRcoef(k+plev*5 ,lm)
grvha(2*lm-1,k) = tmpGRcoef(k+plev*6 ,lm)
grvha(2*lm ,k) = tmpGRcoef(k+plev*7 ,lm)
grta (2*lm-1,k) = tmpGRcoef(k+plev*8 ,lm)
grta (2*lm ,k) = tmpGRcoef(k+plev*9 ,lm)
grtha(2*lm-1,k) = tmpGRcoef(k+plev*10,lm)
grtha(2*lm ,k) = tmpGRcoef(k+plev*11,lm)
grda (2*lm-1,k) = tmpGRcoef(k+plev*12,lm)
grda (2*lm ,k) = tmpGRcoef(k+plev*13,lm)
grza (2*lm-1,k) = tmpGRcoef(k+plev*14,lm)
grza (2*lm ,k) = tmpGRcoef(k+plev*15,lm)
end do
end do
!
!-----------------------------------------------------------------------
!
! Computation for 1-level variables (ln(p*) and derivatives).
!
!cdir novector
do lm=1,mlength
m = locm(lm,iam)
lmr = lnstart(lm)
lmc = 2*lmr
!cdir shortloop
do n=1,nlen(m),2
ir = lmc + 2*n - 1
ii = ir + 1
grpma(2*lm-1) = grpma(2*lm-1) + alps(ir)*ldalp(lmr+n,irow)*ra
grpma(2*lm ) = grpma(2*lm ) + alps(ii)*ldalp(lmr+n,irow)*ra
end do
end do
!cdir novector
do lm=1,mlength
m = locm(lm,iam)
lmr = lnstart(lm)
lmc = 2*lmr
!cdir shortloop
do n=2,nlen(m),2
ir = lmc + 2*n - 1
ii = ir + 1
!
grpsa (2*lm-1) = grpsa (2*lm-1) + alps(ir)*lalp(lmr+n,irow)
grpsa (2*lm ) = grpsa (2*lm ) + alps(ii)*lalp(lmr+n,irow)
!
grdpsa(2*lm-1) = grdpsa(2*lm-1) + alps(ir)*lalp(lmr+n,irow)*hdfst4(m+n-1)*ztodt
grdpsa(2*lm ) = grdpsa(2*lm ) + alps(ii)*lalp(lmr+n,irow)*hdfst4(m+n-1)*ztodt
end do
!
! Multiply by m/a to get d(ln(p*))/dlamda
! and by 1/a to get (1-mu**2)d(ln(p*))/dmu
!
grpla(2*lm-1) = -grpsa(2*lm )*ra*xm(m)
grpla(2*lm ) = grpsa(2*lm-1)*ra*xm(m)
end do
!
return
end subroutine grcalca
subroutine prepGRcalc(tmpSPEcoef) 1,8
!-----------------------------------------------------------------------
!
! Rearrange multi-level spectral coefficients for vectorization.
! The results are saved to "tmpSPEcoef" and will be used in
! "grcalcs" and "grcalca".
!
!-----------------------------------------------------------------------
!
use shr_kind_mod
, only: r8 => shr_kind_r8
use pmgrid
use pspect
use comspe
use rgrid
use commap
use dynconst
, only: ra
use comhd
, only: hdiftq, hdifzd
!
implicit none
!
!
!---------------------------Output argument-----------------------------
!
real(r8), intent(out) :: tmpSPEcoef(plev*24,pnmax,maxm) ! array for rearranged variables
!
!---------------------------Local workspace-----------------------------
!
real(r8) raxm
!
integer lm, m, n, k
integer lmr, lmc
integer ir ,ii
!
!-----------------------------------------------------------------------
!
do lm=1,numm(iam)
m = locm(lm,iam)
lmr = lnstart(lm)
lmc = 2*lmr
raxm = ra*xm(m)
do n=1,nlen(m)
ir = lmc + 2*n - 1
ii = ir + 1
do k=1,plev
tmpSPEcoef(k ,n,lm) = vz(ir,k)
tmpSPEcoef(k+plev ,n,lm) = vz(ii,k)
tmpSPEcoef(k+plev*2 ,n,lm) = -d(ir,k)
tmpSPEcoef(k+plev*3 ,n,lm) = -d(ii,k)
tmpSPEcoef(k+plev*4 ,n,lm) = -vz(ir,k)*hdifzd(n+m-1,k)
tmpSPEcoef(k+plev*5 ,n,lm) = -vz(ii,k)*hdifzd(n+m-1,k)
tmpSPEcoef(k+plev*6 ,n,lm) = d(ir,k)*hdifzd(n+m-1,k)
tmpSPEcoef(k+plev*7 ,n,lm) = d(ii,k)*hdifzd(n+m-1,k)
tmpSPEcoef(k+plev*8 ,n,lm) = t(ir,k)
tmpSPEcoef(k+plev*9 ,n,lm) = t(ii,k)
tmpSPEcoef(k+plev*10,n,lm) = -t(ir,k)*hdiftq(n+m-1,k)
tmpSPEcoef(k+plev*11,n,lm) = -t(ii,k)*hdiftq(n+m-1,k)
tmpSPEcoef(k+plev*12,n,lm) = d(ir,k)
tmpSPEcoef(k+plev*13,n,lm) = d(ii,k)
tmpSPEcoef(k+plev*14,n,lm) = vz(ir,k)
tmpSPEcoef(k+plev*15,n,lm) = vz(ii,k)
tmpSPEcoef(k+plev*16,n,lm) = d (ii,k)*rsq(m+n-1)*raxm
tmpSPEcoef(k+plev*17,n,lm) = -d (ir,k)*rsq(m+n-1)*raxm
tmpSPEcoef(k+plev*18,n,lm) = vz(ii,k)*rsq(m+n-1)*raxm
tmpSPEcoef(k+plev*19,n,lm) = -vz(ir,k)*rsq(m+n-1)*raxm
tmpSPEcoef(k+plev*20,n,lm) = -d (ii,k)*hdifzd(n+m-1,k)*rsq(m+n-1)*raxm
tmpSPEcoef(k+plev*21,n,lm) = d (ir,k)*hdifzd(n+m-1,k)*rsq(m+n-1)*raxm
tmpSPEcoef(k+plev*22,n,lm) = -vz(ii,k)*hdifzd(n+m-1,k)*rsq(m+n-1)*raxm
tmpSPEcoef(k+plev*23,n,lm) = vz(ir,k)*hdifzd(n+m-1,k)*rsq(m+n-1)*raxm
end do
end do
end do
!
return
end subroutine prepGRcalc