!WRF:model_layer:physics
!
!
!
!
module module_shcu_grims 2
!
integer,parameter :: nxtdp = 5001
integer,parameter :: nxthe = 241,nythe = 151
integer,parameter :: nxma = 151,nyma = 121
integer,parameter :: nxsvp = 7501
!
real,parameter :: t0c = 2.7315e+2
real,parameter :: psat = 6.1078e+2
real,parameter :: rd = 2.8705e+2
real,parameter :: rv = 4.6150e+2
real,parameter :: cp = 1.0046e+3
real,parameter :: hvap = 2.5000e+6
real,parameter :: cvap = 1.8460e+3
real,parameter :: cliq = 4.1855e+3
real,parameter :: cice = 2.1060E+3
real,parameter :: hsub = 2.8340E+6
real,parameter :: terrm = 1.e-4
!
real,parameter :: rocp=rd/cp
real,parameter :: cpor=cp/rd
real,parameter :: eps=rd/rv
real,parameter :: ttp=t0c+0.01
real,parameter :: psatk=psat*1.e-3
real,parameter :: psatb=psatk*1.e-2
real,parameter :: dldt=cvap-cliq,xa=-dldt/rv,xb=xa+hvap/(rv*ttp)
real,parameter :: dldti=cvap-cice,xai=-dldti/rv,xbi=xai+hsub/(rv*ttp)
!
real,save :: c1xma,c2xma,c1yma,c2yma,c1xpvs,c2xpvs
real,save :: c1xtdp,c2xtdp,c1xthe,c2xthe,c1ythe,c2ythe
real,save :: tbtdp(nxtdp)
real,save :: tbthe(nxthe,nythe)
real,save :: tbtma(nxma,nyma), tbqma(nxma,nyma)
real,save :: tbpvs(nxsvp)
contains
!
!-------------------------------------------------------------------------------
subroutine grims(qv3d,t3d,p3di,p3d,pi3d,z3di, & 1,1
wstar,hpbl,delta, &
rthshten,rqvshten, &
dt,g,xlv,rd,rv,rcp,p1000mb, &
kpbl2d,znu,raincv, &
ids,ide, jds,jde, kds,kde, &
ims,ime, jms,jme, kms,kme, &
its,ite, jts,jte, kts,kte)
!-------------------------------------------------------------------------------
implicit none
!-------------------------------------------------------------------------------
!
! input argument
!
!-- qv3d 3d specific humidity (kgkg-1)
!-- t3d 3d temperature (k)
!-- p3di 3d pressure (pa) at interface level
!-- p3d 3d pressure (pa)
!-- pi3d 3d exner function (dimensionless)
!-- z3di 3d z at interface level (m)
!-- wstar convective velocity scale (ms-1) from pbl
!-- hpbl pbl height (m)
!-- delta entrainment layer depth (m)
!-- rthshten computed theta tendency due to shallow convection scheme
!-- rqvshten computed q_v tendency due to shallow convection scheme
!-- dt time step (s)
!-- g acceleration due to gravity (m/s^2)
!-- xlv latent heat of vaporization (j/kg)
!-- rd gas constant for dry air (j/kg/k)
!-- rv gas constant for water vapor (j/kg/k)
!-- kpbl2d k-index for pbl top
!-- raincv time-step precipitation from cumulus convection scheme
!-- znu eta values (sigma values)
!-- ids start index for i in domain
!-- ide end index for i in domain
!-- jds start index for j in domain
!-- jde end index for j in domain
!-- kds start index for k in domain
!-- kde end index for k in domain
!-- ims start index for i in memory
!-- ime end index for i in memory
!-- jms start index for j in memory
!-- jme end index for j in memory
!-- kms start index for k in memory
!-- kme end index for k in memory
!-- its start index for i in tile
!-- ite end index for i in tile
!-- jts start index for j in tile
!-- jte end index for j in tile
!-- kts start index for k in tile
!-- kte end index for k in tile
!
! output argument
!-- rthshten computed theta tendency due to shallow convection scheme
!-- rqvshten computed q_v tendency due to shallow convection scheme
!-------------------------------------------------------------------------------
!
! local
!
!-- icps cps index, =1 for deep convection
!-- pi2di 2d exner function at interface level (dimensionless)
!-- delp2di 2d pressuer depth (pa) between interface levels
!-- zl 2d z (m)
!-- t1 2d temperature (k) will be changed by shallow convection
!-- q1 2d specific humidity (kgkg-1) will be changed by shallow convection
!-- levshc maximum k-level for shallow convection
!
integer, intent(in ) :: ids,ide, jds,jde, kds,kde, &
ims,ime, jms,jme, kms,kme, &
its,ite, jts,jte, kts,kte
!
real, intent(in ) :: dt,g,xlv,rd,rv,rcp,p1000mb
!
integer, dimension( ims:ime, jms:jme ) , &
intent(in ) :: kpbl2d
!
real, dimension( ims:ime, kms:kme, jms:jme ) , &
intent(in ) :: qv3d, &
t3d, &
p3di, &
p3d, &
pi3d, &
z3di
!
real, dimension( ims:ime, jms:jme ) , &
intent(in ) :: hpbl, &
wstar, &
delta, &
raincv
!
real, dimension( kms:kme ) , &
intent(in ) :: znu
!
real, dimension( ims:ime, kms:kme, jms:jme ) , &
optional , &
intent(inout) :: rthshten, &
rqvshten
!
! local variables
!
integer :: i,j,k,levshc
real :: sigshc,rdelt
!
integer, dimension( its:ite ) :: icps
real, dimension( its:ite, kts:kte+1 ) :: pi2di
real, dimension( its:ite, kts:kte ) :: delp2di, &
zl, &
t1, &
q1
!
rdelt = 1.0/dt
sigshc = 0.6
levshc = 0
!
do k = kts,kte
if(znu(k).gt.sigshc) levshc = k + 1
enddo
!
pi2di(:,:) = 0.0
delp2di(:,:) = 0.0
zl(:,:) = 0.0
t1(:,:) = 0.0
q1(:,:) = 0.0
!
do j = jts,jte ! outmost j loop
icps(:) = 0
do k = kts,kte
do i = its,ite
pi2di(i,k) = (p3di(i,k,j)/p1000mb)**rcp
enddo
enddo
do i = its,ite
pi2di(i,kte+1) = (p3di(i,kte+1,j)/p1000mb)**rcp
enddo
!
do k = kts,kte
do i = its,ite
delp2di(i,k) = p3di(i,k,j)-p3di(i,k+1,j)
zl(i,k) = 0.5*(z3di(i,k,j)+z3di(i,k+1,j))
t1(i,k) = t3d(i,k,j)
q1(i,k) = qv3d(i,k,j)
enddo
enddo
!
do i = its,ite
if(raincv(i,j) .gt. 1.e-30) icps(i)=1
enddo
!
call grims2d
(q=q1(its,kts),t=t1(its,kts),prsi=p3di(ims,kms,j), &
prsik=pi2di(its,kts),delprsi=delp2di(its,kts), &
prsl=p3d(ims,kms,j),prslk=pi3d(ims,kms,j),zl=zl(its,kts), &
wstar=wstar(ims,j),hpbl=hpbl(ims,j),delta=delta(ims,j), &
dt=dt,cp=cp,g=g,xlv=xlv,rd=rd,rv=rv, &
icps=icps(its),kpbl=kpbl2d(ims,j),levshc=levshc, &
ids=ids,ide=ide, jds=jds,jde=jde, kds=kds,kde=kde, &
ims=ims,ime=ime, jms=jms,jme=jme, kms=kms,kme=kme, &
its=its,ite=ite, jts=jts,jte=jte, kts=kts,kte=kte )
!
if(present(rthshten).and.present(rqvshten)) then
do k = kts,kte
do i = its,ite
rthshten(i,k,j)=(t1(i,k)-t3d(i,k,j))/pi3d(i,k,j)*rdelt
rqvshten(i,k,j)=(q1(i,k)-qv3d(i,k,j))*rdelt
enddo
enddo
endif
!
enddo ! end outmost j loop
!
end subroutine grims
!-------------------------------------------------------------------------------
!
!-------------------------------------------------------------------------------
subroutine grims2d(q,t,prsi,prsik,delprsi,prsl,prslk,zl, & 1,3
wstar,hpbl,delta, &
dt,cp,g,xlv,rd,rv, &
icps,kpbl,levshc, &
ids,ide, jds,jde, kds,kde, &
ims,ime, jms,jme, kms,kme, &
its,ite, jts,jte, kts,kte)
!-------------------------------------------------------------------------------
implicit none
!-------------------------------------------------------------------------------
!
! this scheme applies an eddy-diffusion approach within the shallow convective
! layer defined by the moist static energy profile and is coupled to the
! ysu pbl properties. this scheme names after the grims
! shallow convection scheme since it was developed/evaluated in grims.
!
! coded by song-you hong (yonsei university; ysu) and
! implemented by jihyeon jang, junhong lee (ysu), and wei wang (ncar)
! winter 2012
!
! references:
! hong et al. (2013, manuscript in preparation)
! hong et al. (2013, asia-pacific j. atmos. sci.) the global/regional
! integrated model system (grims)
!
!-------------------------------------------------------------------------------
!
integer, intent(in ) :: levshc, &
ids,ide, jds,jde, kds,kde, &
ims,ime, jms,jme, kms,kme, &
its,ite, jts,jte, kts,kte
!
real, intent(in ) :: dt,cp,g,xlv,rd,rv
!
integer, dimension( ims:ime ) , &
intent(in ) :: kpbl
!
real, dimension( ims:ime, kms:kme ) , &
intent(in ) :: prsi
!
real, dimension( its:ite, kts:kte+1 ) , &
intent(in ) :: prsik
!
real, dimension( its:ite, kts:kte ) , &
intent(in ) :: delprsi, &
zl
!
real, dimension( ims:ime, kms:kme ) , &
intent(in ) :: prsl, &
prslk
!
integer, dimension( its:ite ) , &
intent(in ) :: icps
!
real, dimension( its:ite, kts:kte ) , &
intent(inout) :: q, &
t
!
real, dimension( ims:ime ) , &
intent(in ) :: hpbl, &
wstar, &
delta
!
! profile shape parameter
!
real,parameter :: pfac = 3.
!
! maximum and minimum diffusivity
!
real,parameter :: xkzmax = 50., xkzmin = 0.001
!
! maxium distance of a parcel to lcl (m)
!
real,parameter :: zdiffcr1 = 1500., zdiffcr2 = 1500.
!
! bounds of parcel origin
!
integer,parameter :: kliftl=2,kliftu=2
!
! scale factor for wstar
!
real,parameter :: wsfac = 1.47
!
! local variables and arrays
!
logical :: lshc(its:ite),flg(ite-its+1)
integer :: i,ik,ik1,iku,k,k1,k2,kt,n2
integer :: index2(ite-its+1)
integer :: klcl(ite-its+1),kbot(ite-its+1)
integer :: ktop(ite-its+1)
integer :: lmin(ite-its+1)
integer :: kb(ite-its+1),kbcon(ite-its+1)
real :: eps,epsm1
real :: eldq,xkzh,cpdt,rtdls
real :: dmse,dtodsu,dtodsl,dsig,dsdz1,dsdz2
real :: q2((ite-its+1)*kte)
real :: t2((ite-its+1)*kte)
real :: al((ite-its+1)*(kte-1))
real :: ad((ite-its+1)*kte)
real :: au((ite-its+1)*(kte-1))
real :: delprsi2((ite-its+1)*kte)
real :: prsi2((ite-its+1)*kte),prsik2((ite-its+1)*kte)
real :: prsl2((ite-its+1)*kte),prslk2((ite-its+1)*kte)
real :: qeso2((ite-its+1)*kte),rh2(ite-its+1)
real :: depth(ite-its+1),zdiff1(ite-its+1),zdiff2(ite-its+1)
real :: hmin(ite-its+1),hmax(ite-its+1)
real :: z(1:(ite-its+1),kts:kte)
real :: heo(1:(ite-its+1),kts:kte)
real :: heso(1:(ite-its+1),kts:kte)
real :: pik,height,xkzfac
!-------------------------------------------------------------------------------
!
eps = rd/rv
epsm1 = eps-1
!
do i = its,ite
lshc(i)=.false.
enddo
!
! check for moist static instability to trigger convection
!
do k = kts,levshc-1
do i = its,ite
if(icps(i).eq.0.and.kpbl(i).ge.2) then
eldq = xlv*(q(i,k)-q(i,k+1))
cpdt = cp*(t(i,k)-t(i,k+1))
rtdls = (prsl(i,k)-prsl(i,k+1))/prsi(i,k+1)*rd*0.5*(t(i,k)+t(i,k+1))
dmse = eldq+cpdt-rtdls
lshc(i) = lshc(i).or.dmse.gt.0.
endif
enddo
enddo
do i = its,ite
if(wstar(i).lt.0.001) lshc(i)=.false.
enddo
!
! reset i-dimension for active clouds
!
n2 = 0
do i = its,ite
if(lshc(i)) then
n2 = n2+1
index2(n2) = i
endif
enddo
!
if(n2.eq.0) return
!
! prepare the variables
!
do k = kts,levshc
do i = 1,n2
if(lshc(index2(i))) then
ik = (k-1)*n2+i
pik = prsl(index2(i),k)
q2(ik) = q(index2(i),k)
t2(ik) = t(index2(i),k)
delprsi2(ik) = delprsi(index2(i),k)
prsi2(ik) = prsi(index2(i),k)
prsl2(ik) = prsl(index2(i),k)
prsik2(ik)= prsik(index2(i),k)
prslk2(ik)= prslk(index2(i),k)
z(i,k) = zl(index2(i),k)
qeso2(ik) = fpvs_pa
(t2(ik))
qeso2(ik) = eps * qeso2(ik) / (pik + epsm1 * qeso2(ik))
qeso2(ik) = max(qeso2(ik),1.E-8)
heo(i,k) = g * z(i,k) + cp* t2(ik) + xlv * q2(ik)
heso(i,k) = g * z(i,k) + cp* t2(ik) + xlv * qeso2(ik)
endif
enddo
enddo
!
! determine largest moist static energy for updraft originating level
!
do i = 1,n2
if(lshc(index2(i))) then
hmax(i) = heo(i,1)
kb(i) = 1
kbcon(i) = levshc
flg(i) = .true.
zdiff1(i) = -1.0
zdiff2(i) = -1.0
endif
enddo
!
do k = kts+1,levshc-1
do i = 1,n2
if(lshc(index2(i))) then
if(heo(i,k).gt.hmax(i).and.k.le.kpbl(index2(i))) then
kb(i) = k
hmax(i) = heo(i,k)
endif
endif
enddo
enddo
!
! check the buoyancy of a parcel by the distance to lcl and lfc
!
do k = kts+1,levshc-1
do i = 1,n2
if(lshc(index2(i)).and.flg(i)) then
if(k.gt.kb(i).and.heo(i,kb(i)).gt.heso(i,k)) then
flg(i) = .false.
kbcon(i) = k
endif
endif
enddo
enddo
!
do i = 1,n2
if(lshc(index2(i))) then
zdiff1(i) = z(i,kpbl(index2(i)))-z(i,kb(i))
zdiff2(i) = z(i,kbcon(i))-z(i,kb(I))
if(zdiff1(i).gt.zdiffcr1.or.zdiff1(i).lt.0.) lshc(index2(i)) = .false.
if(zdiff2(i).gt.zdiffcr2) lshc(index2(i)) = .false.
endif
enddo
!
! compute moist adiabat and determine cloud top
!
call phys_moist_adiabat_pa
(n2,levshc-1,kliftl,kliftu, &
prsl2,prsik2,prslk2,t2,q2, &
klcl,kbot,ktop,al,au,rd,rv, &
ids,ide, jds,jde, kds,kde, &
ims,ime, jms,jme, kms,kme, &
its,ite, jts,jte, kts,kte)
!
do i = 1,n2
if(lshc(index2(i))) then
kbot(i) = max(kpbl(index2(i)),2)
kbot(i) = min(kbot(i),levshc)
ktop(i) = ktop(i)+1
endif
enddo
!
! revise the cloud top below minimum moist static energy
!
do i = 1,n2
if(lshc(index2(i))) then
hmin(i) = heo(i,kbot(i))
lmin(i) = levshc
endif
enddo
!
do k = kts,levshc
do i = 1,n2
if(lshc(index2(i))) then
if(heo(i,k).lt.hmin(i).and.k.ge.kbot(i).and.k.le.ktop(i)) then
lmin(i) = k + 1
hmin(i) = heo(i,k)
endif
endif
enddo
enddo
!
do i = 1,n2
if(lshc(index2(i))) then
ktop(i) = min(ktop(i),lmin(i))
endif
enddo
!
do i = 1,n2
if(lshc(index2(i))) then
if((ktop(i)-kbot(i)).le.1) then
lshc(index2(i)) = .false.
endif
endif
enddo
!
! compute diffusion properties
!
do i = 1,n2
if(lshc(index2(i))) then
k = kbot(i)-1
ik=(k-1)*n2+i
rh2(i) = q2(ik)/qeso2(ik)
endif
enddo
!
k1 = levshc+1
k2 = 0
do i = 1,n2
if(.not.lshc(index2(i))) then
kbot(i) = levshc+1
ktop(i) = 0
else
depth(i) = z(i,ktop(i))-z(i,kbot(i))
endif
k1 = min(k1,kbot(i))
k2 = max(k2,ktop(i))
enddo
kt = k2-k1+1
if(kt.lt.2) return
!
! set eddy viscosity coefficient xkzh at sigma interfaces
!
do i = 1,n2
ik = (k1-1)*n2+i
ad(ik) = 1.
enddo
!
do k = kts,levshc-1
do i = 1,n2
if(k.ge.kbot(i).and.k.lt.ktop(i)) then
ik = (k-1)*n2+i
iku = k*n2+i
rtdls = (prsl2(ik)-prsl2(iku))/prsi2(iku)*rd*0.5*(t2(ik)+t2(iku))
au(ik) = g/rtdls
endif
enddo
enddo
!
do k = k1,k2-1
do i = 1,n2
ik = (k-1)*n2+i
iku = k*n2+i
dtodsl = 2.*dt/delprsi2(ik)
dtodsu = 2.*dt/delprsi2(iku)
dsig = prsl2(ik)-prsl2(iku)
if(k.ge.kbot(i).and.k.lt.ktop(i)) then
height = z(i,k)-z(i,kbot(i))
xkzfac = rh2(i)*wsfac*wstar(index2(i))*delta(index2(i))
xkzh = min(max(xkzfac*(1.-height/depth(i))**pfac,xkzmin),xkzmax)
else
xkzh = 0.
endif
dsdz1 = xkzh*dsig*au(ik)*g/cp
dsdz2 = xkzh*dsig*au(ik)*au(ik)
au(ik) = -dtodsl*dsdz2
al(ik) = -dtodsu*dsdz2
ad(ik) = ad(ik)-au(ik)
ad(iku) = 1.-al(ik)
t2(ik) = t2(ik)+dtodsl*dsdz1
t2(iku) = t2(iku)-dtodsu*dsdz1
enddo
enddo
!
! solve tri-diagonal matrix
!
ik1 = (k1-1)*n2+1
call scv_tri_diagonal_grims
(n2,n2,kt,al(ik1),ad(ik1),au(ik1), &
q2(ik1),t2(ik1),au(ik1),q2(ik1),t2(ik1))
!
! feedback to large-scale variables
!
do k = k1,k2
do i = 1,n2
if(lshc(index2(i))) then
ik = (k-1)*n2+i
q(index2(i),k) = q2(ik)
t(index2(i),k) = t2(ik)
endif
enddo
enddo
!
return
end subroutine grims2d
!-------------------------------------------------------------------------------
!
!-------------------------------------------------------------------------------
subroutine scv_tri_diagonal_grims(lons2,l,n,cl,cm,cu,r1,r2,au,a1,a2) 1
!-------------------------------------------------------------------------------
!
! subprogram: scv_tri_diagonal
!
! abstract: this routine solves multiple tridiagonal matrix problems
! with 2 right-hand-side and solution vectors for every matrix.
! the solutions are found by eliminating off-diagonal coefficients,
! marching first foreward then backward along the matrix diagonal.
! the computations are vectorized around the number of matrices.
! no checks are made for zeroes on the diagonal or singularity.
!
! program history log:
! 1991-05-07 iredell
! 2009-03-01 jung-eun kim fortran 90 and modules
!
! usage: call scv_tri_diagonal(l,n,cl,cm,cu,r1,r2,au,a1,a2)
!
! input argument list:
! l - integer number of tridiagonal matrices
! n - integer order of the matrices
! cl - real (l,2:n) lower diagonal matrix elements
! cm - real (l,n) main diagonal matrix elements
! cu - real (l,n-1) upper diagonal matrix elements
! (may be equivalent to au if no longer needed)
! r1 - real (l,n) 1st right-hand-side vector elements
! (may be equivalent to a1 if no longer needed)
! r2 - real (l,n) 2nd right-hand-side vector elements
! (may be equivalent to a2 if no longer needed)
!
! output argument list:
! au - real (l,n-1) work array
! a1 - real (l,n) 1st solution vector elements
! a2 - real (l,n) 2nd solution vector elements
!
! remarks: this routine can be easily modified to solve a different
! number of right-hand-sides and solutions per matrix besides 2.
!
!-------------------------------------------------------------------------------
implicit none
integer :: lons2,l,n,i,k
real :: fk
real :: cl(l,2:n),cm(l,n),cu(l,n-1),r1(l,n),r2(l,n), &
au(l,n-1),a1(l,n),a2(l,n)
!-------------------------------------------------------------------------------
do i = 1,lons2
fk = 1./cm(i,1)
au(i,1)= fk*cu(i,1)
a1(i,1)= fk*r1(i,1)
a2(i,1)= fk*r2(i,1)
enddo
!
do k = 2,n-1
do i = 1,lons2
fk = 1./(cm(i,k)-cl(i,k)*au(i,k-1))
au(i,k) = fk*cu(i,k)
a1(i,k) = fk*(r1(i,k)-cl(i,k)*a1(i,k-1))
a2(i,k) = fk*(r2(i,k)-cl(i,k)*a2(i,k-1))
enddo
enddo
!
do i = 1,lons2
fk = 1./(cm(i,n)-cl(i,n)*au(i,n-1))
a1(i,n) = fk*(r1(i,n)-cl(i,n)*a1(i,n-1))
a2(i,n) = fk*(r2(i,n)-cl(i,n)*a2(i,n-1))
enddo
do k = n-1,1,-1
do i = 1,lons2
a1(i,k) = a1(i,k)-au(i,k)*a1(i,k+1)
a2(i,k) = a2(i,k)-au(i,k)*a2(i,k+1)
enddo
enddo
!
return
end subroutine scv_tri_diagonal_grims
!-------------------------------------------------------------------------------
!
!-------------------------------------------------------------------------------
subroutine phys_moist_adiabat_pa(ilev,klev,k1,k2, & 1,2
prsl,prsik,prslk,tenv,qenv, &
klcl,kbot,ktop,tcld,qcld,rd,rv, &
ids,ide, jds,jde, kds,kde, &
ims,ime, jms,jme, kms,kme, &
its,ite, jts,jte, kts,kte)
!-------------------------------------------------------------------------------
!
! subprogram: phys_moist_adiabat_pa
!
! abstract:
! - compute moist adiabatic cloud soundings
! - atmospheric columns of temperature and specific humidity
! are examined by this routine for conditional instability.
! the test parcel is chosen from the layer between layers k1 and k2
! that has the warmest potential wet-bulb temperature.
! excess cloud temperatures and specific humidities are returned
! where the lifted parcel is found to be buoyant.
! fast inlinable functions are invoked to compute
! dewpoint and lifting condensation level temperatures,
! equivalent potential temperature at the lcl, and
! temperature and specific humidity of the ascending parcel.
!
! program history log:
! 1983-11-01 phillips
! 1991-05-07 iredell arguments changed, code tidied
! 2000-01-01 song-you hong physcis options
! 2009-10-01 jung-eun kim f90 format with standard physics modules
! 2010-07-01 myung-seo koo dimension allocatable with namelist input
!
! usage: call phys_moist_adiabat_pa(ilev,klev,k1,k2, &
! prsl,prslk,prsik,tenv,qenv, &
! klcl,kbot,ktop,tcld,qcld,rd,rv, &
! ids,ide, jds,jde, kds,kde, &
! ims,ime, jms,jme, kms,kme, &
! its,ite, jts,jte, kts,kte)
!
! input argument list:
! ilev - integer number of atmospheric columns
! klev - integer number of sigma levels in a column
! k1 - integer lowest level from which a parcel can originate
! k2 - integer highest level from which a parcel can originate
! prsl - real (ilev,klev) pressure values
! prslk,prsik - real (ilev,klev) pressure values to the kappa
! tenv - real (ilev,klev) environment temperatures
! qenv - real (ilev,klev) environment specific humidities
!
! output argument list:
! klcl - integer (ilev) level just above lcl (klev+1 if no lcl)
! kbot - integer (ilev) level just above cloud bottom
! ktop - integer (ilev) level just below cloud top
! - note that kbot(i) gt ktop(i) if no cloud.
! tcld - real (ilev,klev) of excess cloud temperatures.
! (parcel t minus environ t, or 0. where no cloud)
! qcld - real (ilev,klev) of excess cloud specific humidities.
! (parcel q minus environ q, or 0. where no cloud)
!
! subprograms called:
! ftdp - function to compute dewpoint temperature
! ftlcl - function to compute lcl temperature
! fthe - function to compute equivalent potential temperature
! ftma - function to compute parcel temperature and humidity
!
! remarks: all functions are inlined by fpp.
! nonstandard automatic arrays are used.
!
!-------------------------------------------------------------------------------
implicit none
!
integer,parameter :: nx=151,ny=121
integer :: ilev,klev,k1,k2
real :: prsl(ilev,klev),prslk(ilev,klev),prsik(ilev,klev)
real :: tenv(ilev,klev),qenv(ilev,klev)
integer :: klcl(ilev),kbot(ilev),ktop(ilev)
real :: tcld(ilev,klev),qcld(ilev,klev)
real :: rd,rv
integer :: ids,ide, jds,jde, kds,kde, &
ims,ime, jms,jme, kms,kme, &
its,ite, jts,jte, kts,kte
!
! local arrays
!
real :: slkma(ilev)
real :: thema(ilev)
real :: pv,tdpd
real :: slklcl,thelcl,tlcl
real :: xj,yj
real :: ftx1,ftx2,ftma1,qx1,qx2,qma,tma,tvcld,tvenv
real :: eps,epsm1,ftv
integer :: i,k,jx,jy
!-------------------------------------------------------------------------------
!
! compute parameters
!
eps=rd/rv
epsm1=rd/rv-1.
ftv=rv/rd-1.
!
! determine warmest potential wet-bulb temperature between k1 and k2.
! compute its lifting condensation level.
!
do i = 1,ilev
slkma(i)=0.
thema(i)=0.
enddo
!
do k = k1,k2
do i = 1,ilev
pv=prsl(i,k)*1.e-3*qenv(i,k)/(eps-epsm1*qenv(i,k))
tdpd=tenv(i,k)-ftdp(pv)
if(tdpd.gt.0.) then
tlcl=ftlcl
(tenv(i,k),tdpd)
slklcl=prslk(i,k)/prsik(i,1)*tlcl/tenv(i,k)
else
tlcl=tenv(i,k)
slklcl=prslk(i,k)/prsik(i,1)
endif
thelcl=fthe
(tlcl,slklcl*prsik(i,1))
if(thelcl.gt.thema(i)) then
slkma(i)=slklcl
thema(i)=thelcl
endif
enddo
enddo
!
! set cloud temperatures and humidities wherever the parcel lifted up
! the moist adiabat is buoyant with respect to the environment.
!
do i = 1,ilev
klcl(i)=klev+1
kbot(i)=klev+1
ktop(i)=0
enddo
!
do k = kts,klev
do i = 1,ilev
tcld(i,k)=0.
qcld(i,k)=0.
enddo
enddo
!
do k = k1,klev
do i = 1,ilev
if(prslk(i,k)/prsik(i,1).le.slkma(i)) then
klcl(i)=min(klcl(i),k)
!
! insert ftma tma=ftma(thema(i),prslk(i,k),qma)
!
xj=min(max(c1xma+c2xma*thema(i),1.),float(nx))
yj=min(max(c1yma+c2yma*prslk(i,k),1.),float(ny))
jx=min(xj,nx-1.)
jy=min(yj,ny-1.)
ftx1=tbtma(jx,jy)+(xj-jx)*(tbtma(jx+1,jy)-tbtma(jx,jy))
ftx2=tbtma(jx,jy+1)+(xj-jx)*(tbtma(jx+1,jy+1)-tbtma(jx,jy+1))
ftma1=ftx1+(yj-jy)*(ftx2-ftx1)
qx1=tbqma(jx,jy)+(xj-jx)*(tbqma(jx+1,jy)-tbqma(jx,jy))
qx2=tbqma(jx,jy+1)+(xj-jx)*(tbqma(jx+1,jy+1)-tbqma(jx,jy+1))
qma=qx1+(yj-jy)*(qx2-qx1)
tma=ftma1
!
tvcld=tma*(1.+ftv*qma)
tvenv=tenv(i,k)*(1.+ftv*qenv(i,k))
if(tvcld.gt.tvenv) then
kbot(i)=min(kbot(i),k)
ktop(i)=max(ktop(i),k)
tcld(i,k)=tma-tenv(i,k)
qcld(i,k)=qma-qenv(i,k)
endif
endif
enddo
enddo
!
return
end subroutine phys_moist_adiabat_pa
!-------------------------------------------------------------------------------
!
!-------------------------------------------------------------------------------
function ftdp(pv) 1
!-------------------------------------------------------------------------------
implicit none
!-------------------------------------------------------------------------------
real :: ftdp
!
integer :: jx
real :: xj
real :: xmax,xmin,xinc
real :: pv
!
xmin= 0.001
xmax=10.001
xinc=(xmax-xmin)/(nxtdp-1)
c1xtdp=1.-xmin/xinc
c2xtdp=1./xinc
!
xj=min(max(c1xtdp+c2xtdp*pv,1.),float(nxtdp))
jx=min(xj,nxtdp-1.)
ftdp=tbtdp(jx)+(xj-jx)*(tbtdp(jx+1)-tbtdp(jx))
!
return
end function
!-------------------------------------------------------------------------------
!
!-------------------------------------------------------------------------------
function ftlcl(t,tdpd) 3
!-------------------------------------------------------------------------------
implicit none
!-------------------------------------------------------------------------------
real :: ftlcl
!
real,parameter :: clcl1=0.954442e+0, clcl2=0.967772e-3, &
clcl3=-0.710321e-3,clcl4=-0.270742e-5
real :: t,tdpd
!
ftlcl=t-tdpd*(clcl1+clcl2*t+tdpd*(clcl3+clcl4*t))
!
return
end function
!-------------------------------------------------------------------------------
!
!-------------------------------------------------------------------------------
function fthe(t,pk) 3
!-------------------------------------------------------------------------------
implicit none
!-------------------------------------------------------------------------------
real :: fthe
!
integer :: jx,jy
real :: xmin,xmax,xinc,ymin,ymax,yinc
real :: xj,yj
real :: ftx1,ftx2
real :: t,pk
!
xmin=ttp-90.
xmax=ttp+30.
xinc=(xmax-xmin)/(nxthe-1)
c1xthe=1.-xmin/xinc
c2xthe=1./xinc
ymin=0.04**rocp
ymax=1.10**rocp
yinc=(ymax-ymin)/(nythe-1)
c1ythe=1.-ymin/yinc
c2ythe=1./yinc
!
xj=min(c1xthe+c2xthe*t,float(nxthe))
yj=min(c1ythe+c2ythe*pk,float(nythe))
if(xj.ge.1..and.yj.ge.1.) then
jx=min(xj,nxthe-1.)
jy=min(yj,nythe-1.)
ftx1=tbthe(jx,jy)+(xj-jx)*(tbthe(jx+1,jy)-tbthe(jx,jy))
ftx2=tbthe(jx,jy+1)+(xj-jx)*(tbthe(jx+1,jy+1)-tbthe(jx,jy+1))
fthe=ftx1+(yj-jy)*(ftx2-ftx1)
else
fthe=0.
endif
!
return
end function
!-------------------------------------------------------------------------------
!
!-------------------------------------------------------------------------------
function fpvs_pa(t) 1
!-------------------------------------------------------------------------------
implicit none
!-------------------------------------------------------------------------------
real :: fpvs_pa
!
integer :: jx
real :: xmax,xmin,xinc
real :: xj
real :: t
!
xmin=180.0
xmax=330.0
!
xj=min(max(c1xpvs+c2xpvs*t,1.),float(nxsvp))
jx=min(xj,nxsvp-1.)
fpvs_pa=tbpvs(jx)+(xj-jx)*(tbpvs(jx+1)-tbpvs(jx))
fpvs_pa=fpvs_pa * 1.e3
!
return
end function
!-------------------------------------------------------------------------------
!
!-------------------------------------------------------------------------------
subroutine grimsinit(rthshten,rqvshten, & 1,4
restart, &
ids,ide, jds,jde, kds,kde, &
ims,ime, jms,jme, kms,kme, &
its,ite, jts,jte, kts,kte )
!-------------------------------------------------------------------------------
implicit none
!-------------------------------------------------------------------------------
logical , intent(in) :: restart
integer , intent(in) :: ids, ide, jds, jde, kds, kde, &
ims, ime, jms, jme, kms, kme, &
its, ite, jts, jte, kts, kte
real, dimension( ims:ime , kms:kme , jms:jme ) , intent(out) :: &
rthshten, &
rqvshten
integer :: i, j, k, itf, jtf, ktf
!
jtf=min0(jte,jde-1)
ktf=min0(kte,kde-1)
itf=min0(ite,ide-1)
if(.not.restart)then
do j = jts,jtf
do k = kts,ktf
do i = its,itf
rthshten(i,k,j)=0.
rqvshten(i,k,j)=0.
enddo
enddo
enddo
endif
!
call funct_dew_point_temp_init
call funct_pot_temp_init
call funct_moist_adiabat_init
call funct_svp_init
!
end subroutine grimsinit
!-------------------------------------------------------------------------------
!
!-------------------------------------------------------------------------------
subroutine funct_dew_point_temp_init 1,1
!-------------------------------------------------------------------------------
implicit none
!-------------------------------------------------------------------------------
integer :: jx
real :: xmax,xmin,xinc,pv,x,t
!
xmin= 0.001
xmax=10.001
xinc=(xmax-xmin)/(nxtdp-1)
c1xtdp=1.-xmin/xinc
c2xtdp=1./xinc
t=208.0
do jx=1,nxtdp
x=xmin+(jx-1)*xinc
pv=x
t=ftdpxg
(t,pv)
tbtdp(jx)=t
enddo
!
return
end subroutine funct_dew_point_temp_init
!-------------------------------------------------------------------------------
!
!-------------------------------------------------------------------------------
subroutine funct_pot_temp_init 1,1
!-------------------------------------------------------------------------------
implicit none
!-------------------------------------------------------------------------------
integer :: jx,jy
real :: xmin,xmax,xinc,ymin,ymax,yinc
real :: x,y,t,pk
!
xmin=ttp-90.
xmax=ttp+30.
xinc=(xmax-xmin)/(nxthe-1)
c1xthe=1.-xmin/xinc
c2xthe=1./xinc
ymin=0.04**rocp
ymax=1.10**rocp
yinc=(ymax-ymin)/(nythe-1)
c1ythe=1.-ymin/yinc
c2ythe=1./yinc
!
do jy = 1,nythe
y=ymin+(jy-1)*yinc
pk=y
do jx = 1,nxthe
x=xmin+(jx-1)*xinc
t=x
tbthe(jx,jy)=fthex
(t,pk)
enddo
enddo
!
return
end subroutine funct_pot_temp_init
!-------------------------------------------------------------------------------
!
!-------------------------------------------------------------------------------
subroutine funct_moist_adiabat_init 1,1
!-------------------------------------------------------------------------------
implicit none
!-------------------------------------------------------------------------------
integer :: jx,jy
real :: xmin,xmax,xinc,ymin,ymax,yinc
real :: y,pk,t,x,the,q
!
xmin=200.
xmax=500.
xinc=(xmax-xmin)/(nxma-1)
c1xma=1.-xmin/xinc
c2xma=1./xinc
ymin=0.01**rocp
ymax=1.10**rocp
yinc=(ymax-ymin)/(nyma-1)
c1yma=1.-ymin/yinc
c2yma=1./yinc
!
do jy = 1,nyma
y=ymin+(jy-1)*yinc
pk=y
t=xmin*y
do jx = 1,nxma
x=xmin+(jx-1)*xinc
the=x
t=ftmaxg
(t,the,pk,q)
tbtma(jx,jy)=t
tbqma(jx,jy)=q
enddo
enddo
!
return
end subroutine funct_moist_adiabat_init
!-------------------------------------------------------------------------------
!
!-------------------------------------------------------------------------------
subroutine funct_svp_init 1,1
!-------------------------------------------------------------------------------
implicit none
!-------------------------------------------------------------------------------
integer :: jx
real :: xmin,xmax,xinc
real :: t,x
!
xmin=180.0
xmax=330.0
xinc=(xmax-xmin)/(nxsvp-1)
c1xpvs=1.-xmin/xinc
c2xpvs=1./xinc
do jx = 1,nxsvp
x=xmin+(jx-1)*xinc
t=x
tbpvs(jx)=fpvsx
(t)
enddo
!
return
end subroutine funct_svp_init
!-------------------------------------------------------------------------------
!
!-------------------------------------------------------------------------------
function ftdpxg(tg,pv) 3
!-------------------------------------------------------------------------------
implicit none
!-------------------------------------------------------------------------------
real :: ftdpxg
!
real :: tg,pv
real :: t,tr,pvt,el,dpvt,terr
!
t=tg
tr=ttp/t
pvt=psatk*(tr**xa)*exp(xb*(1.-tr))
el=hvap+dldt*(t-ttp)
dpvt=el*pvt/(rv*t**2)
terr=(pvt-pv)/dpvt
t=t-terr
!
do while(abs(terr).gt.terrm)
tr=ttp/t
pvt=psatk*(tr**xa)*exp(xb*(1.-tr))
el=hvap+dldt*(t-ttp)
dpvt=el*pvt/(rv*t**2)
terr=(pvt-pv)/dpvt
t=t-terr
enddo
ftdpxg=t
!
return
end function
!-------------------------------------------------------------------------------
!
!-------------------------------------------------------------------------------
function fthex(t,pk) 2
!-------------------------------------------------------------------------------
implicit none
!-------------------------------------------------------------------------------
real :: fthex
!
real :: t,pk,p
real :: tr, pv, pd, el, expo
!
p=pk**cpor
tr=ttp/t
pv=psatb*(tr**xa)*exp(xb*(1.-tr))
pd=p-pv
if(pd.gt.0.) then
el=hvap+dldt*(t-ttp)
expo=el*eps*pv/(cp*t*pd)
expo = min(expo,100.0)
fthex=t*pd**(-rocp)*exp(expo)
else
fthex=0.
endif
!
return
end function
!-------------------------------------------------------------------------------
!
!-------------------------------------------------------------------------------
function ftmaxg(tg,the,pk,qma) 1
!-------------------------------------------------------------------------------
implicit none
!-------------------------------------------------------------------------------
real :: ftmaxg
real :: tg,the,pk,t,p,tr,pv,pd,el,expo,thet,dthet,terr,qma
!
t=tg
p=pk**cpor
tr=ttp/t
pv=psatb*(tr**xa)*exp(xb*(1.-tr))
pd=p-pv
el=hvap+dldt*(t-ttp)
expo=el*eps*pv/(cp*t*pd)
thet=t*pd**(-rocp)*exp(expo)
dthet=thet/t*(1.+expo*(dldt*t/el+el*p/(rv*t*pd)))
terr=(thet-the)/dthet
t=t-terr
!
do while(abs(terr).gt.terrm)
tr=ttp/t
pv=psatb*(tr**xa)*exp(xb*(1.-tr))
pd=p-pv
el=hvap+dldt*(t-ttp)
expo=el*eps*pv/(cp*t*pd)
thet=t*pd**(-rocp)*exp(expo)
dthet=thet/t*(1.+expo*(dldt*t/el+el*p/(rv*t*pd)))
terr=(thet-the)/dthet
t=t-terr
enddo
ftmaxg=t
tr=ttp/t
pv=psatb*(tr**xa)*exp(xb*(1.-tr))
pd=p-pv
qma=eps*pv/(pd+eps*pv)
!
return
end function
!-------------------------------------------------------------------------------
!
!-------------------------------------------------------------------------------
function fpvsx(t) 5
!-------------------------------------------------------------------------------
implicit none
!-------------------------------------------------------------------------------
real :: fpvsx
!
real :: t
real :: tr
!
tr=ttp/t
if(t.ge.ttp) then
fpvsx=psatk*(tr**xa)*exp(xb*(1.-tr))
else
fpvsx=psatk*(tr**xai)*exp(xbi*(1.-tr))
endif
!
return
end function
!-------------------------------------------------------------------------------
end module module_shcu_grims