!WRF:MODEL_LAYER:PHYSICS
!
! Grenier-Bretherton mixing PBL scheme (GBM PBL):
!
! REFERENCES
! 1) Grenier, H., and C. S. Bretherton, 2001: A moist PBL parameterization
! for large-scale models and its application to subtropical cloud-topped
! marine boundary layers. Mon. Wea. Rev., 129, 357-377.
! ("GB01" in the comments)
! 2) Galperin, B., L. H. Kantha, S. Hassid, and A. Rosati, 1988:
! A quasi-equilibrium turbulent energy model for geophysical flows.
! J. Atmos. Sci., 45, 55-62.
! ("Gal88" in the comments)
! 3) Mellor, G., and T. Yamada, 1982: Development of a turbulence closure
! model for geophysical fluid problems. Rev. Astrophys.Space Phys.,
! 20, 851-875.
! ("MY82" in the comments)
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! Natalie Perlin, October 2012 nperlin@coas.oregonstate.edu
!!
!! GBM PBL Code history:
!!
!! Herve Grenier, Christopher Bretherton - original contribution
!! Jim McCaa - late 1990s, 2000-2001
!! Nicolai Thum 2004-2005(?)
!! Qingtao Song - 2007-2008
!! Natalie Perlin 2011-2012
!
MODULE module_bl_gbmpbl 2
USE module_model_constants
, ONLY: cp, g, rcp, r_d, &
r_v, svp1, svp2, svp3, &
svpt0, ep_1, ep_2, xlv, &
karman
public gbmpbl
public gbmpblinit
private
CONTAINS
SUBROUTINE GBMPBL(U3D,V3D,TH3D,T3D,QV3D,QC3D,QI3D,P3D,PI3D, & 1,1
RUBLTEN,RVBLTEN,RTHBLTEN, &
RQVBLTEN,RQCBLTEN,RQIBLTEN, &
KZM_GBM,KTH_GBM,KETHL_GBM,EL_GBM, &
dz8w,z,PSFC,TKE_PBL,RTHRATEN, &
ZNT,UST,ZOL,HOL,PBL,KPBL2D,REGIME,PSIM,PSIH, &
XLAND,HFX,QFX,TSK,GZ1OZ0,WSPD,BR, &
DT,DTMIN, &
ids,ide, jds,jde, kds,kde, &
ims,ime, jms,jme, kms,kme, &
its,ite, jts,jte, kts,kte )
!-------------------------------------------------------------------
IMPLICIT NONE
!-------------------------------------------------------------------
!-- U3D 3D u-velocity interpolated to theta points (m/s)
!-- V3D 3D v-velocity interpolated to theta points (m/s)
!-- TH3D 3D potential temperature (K)
!-- T3D temperature (K)
!-- QV3D 3D water vapor mixing ratio (Kg/Kg)
!-- QC3D 3D cloud mixing ratio (Kg/Kg)
!-- QI3D 3D ice mixing ratio (Kg/Kg)
!-- P3D 3D pressure (Pa)
!-- PI3D 3D exner function (dimensionless)
!-- RUBLTEN Rho_dU tendency due to
! PBL parameterization (kg/m^3 . m/s)
!-- RVBLTEN Rho_dV tendency due to
! PBL parameterization (kg/m^3 . m/s)
!-- RTHBLTEN Rho_dTheta_m tendency due to
! PBL parameterization (kg/m^3 . K)
!-- RQVBLTEN Rho_dQv tendency due to
! PBL parameterization (kg/m^3 . kg/kg)
!-- RQCBLTEN Rho_dQc tendency due to
! PBL parameterization (kg/m^3 . kg/kg)
!-- RQIBLTEN Rho_dQi tendency due to
! PBL parameterization (kg/m^3 . kg/kg)
!
!-- KZM_GBM exchange coefficient for momentum (m^2/s)
!-- KTH_GBM exchange coefficient for heat (K m/s)
!-- KETHL_GBM exchange coeff. for TKE enhanced (m^2/s)
!
! NB!! Vertical staggering of the GBM output variables
! is as follows:
! KZM_GBM, KTH_GBM are on full levels, starting from the sfc
! KETHL_GBM is on half-levels
! TKE_PBL and EL_GBM are on full levels, starting from the sfc
!
!-- cp heat capacity at constant pressure for dry air (J/kg/K)
!-- g acceleration due to gravity (m/s^2)
!-- rcp R/CP
!-- r_d gas constant for dry air (J/kg/K)
!-- P_QI species index for cloud ice
!-- dz8w dz between full levels (m)
!-- z height above sea level (m)
!-- XLV latent heat of vaporization (J/kg)
!-- r_v gas constant for water vapor (J/kg/K)
!-- PSFC pressure at the surface (Pa)
!-- ZNT roughness length (m)
!-- UST u* in similarity theory (m/s)
!-- ZOL z/L height over Monin-Obukhov length
!-- HOL PBL height over Monin-Obukhov length
!-- PBL PBL height (m)
!-- KPBL2D Layer index containing PBL top within or at the base interface
!-- REGIME flag indicating PBL regime (stable, unstable, etc.)
!-- PSIM similarity stability function for momentum
!-- PSIH similarity stability function for heat
!-- XLAND land mask (1 for land, 2 for water)
!-- HFX upward heat flux at the surface (W/m^2)
!-- QFX upward moisture flux at the surface (kg/m^2/s)
!-- TSK surface temperature (K)
!-- GZ1OZ0 log(z/z0) where z0 is roughness length
!-- WSPD wind speed at lowest model level (m/s)
!-- BR bulk Richardson number in surface layer
!-- DT time step (s)
!-- DTMIN time step (minute)
!-- svp1 constant for saturation vapor pressure (kPa)
!-- svp2 constant for saturation vapor pressure (dimensionless)
!-- svp3 constant for saturation vapor pressure (K)
!-- svpt0 constant for saturation vapor pressure (K)
!-- ep_1 constant for virtual temperature (r_v/r_d - 1) (dimensionless)
!-- ep_2 constant for specific humidity calculation
!-- karman Von Karman constant
!-- 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
!-------------------------------------------------------------------
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,DTMIN
REAL, DIMENSION( ims:ime, kms:kme, jms:jme ) , &
INTENT(IN ) :: QV3D, &
QC3D, &
QI3D, &
P3D, &
PI3D, &
TH3D, &
T3D, &
dz8w, &
z
!
REAL, DIMENSION( ims:ime, kms:kme, jms:jme ) , &
INTENT(INOUT) :: RUBLTEN, &
RVBLTEN, &
RTHBLTEN, &
RQVBLTEN, &
RQCBLTEN, &
RQIBLTEN
REAL, DIMENSION( ims:ime, kms:kme, jms:jme ) , &
INTENT(OUT) :: KZM_GBM,KTH_GBM,KETHL_GBM, EL_GBM
REAL, DIMENSION( ims:ime, jms:jme ) , &
INTENT(IN ) :: XLAND, &
HFX, &
QFX, &
REGIME
REAL, DIMENSION( ims:ime, jms:jme ) , &
INTENT(INOUT) :: HOL, &
UST, &
PBL, &
ZNT
INTEGER, DIMENSION( ims:ime, jms:jme ) , &
INTENT(INOUT) :: KPBL2D
!
!m The following 5 variables are changed to memory size from tile size--
!
REAL, DIMENSION( ims:ime, jms:jme ), INTENT(IN ) :: &
PSIM, &
PSIH
REAL, DIMENSION( ims:ime, jms:jme ), INTENT(INOUT) :: &
WSPD
REAL, DIMENSION( ims:ime, jms:jme ), INTENT(IN ) :: &
GZ1OZ0, &
BR
REAL, DIMENSION( ims:ime, jms:jme ) , &
INTENT(IN ) :: PSFC
REAL, DIMENSION( ims:ime, jms:jme ) , &
INTENT(IN ) :: TSK
REAL, DIMENSION( ims:ime, jms:jme ) , &
INTENT(INOUT) :: ZOL
REAL, DIMENSION( ims:ime, kms:kme, jms:jme ) , &
INTENT(IN ) :: U3D, &
V3D
REAL,DIMENSION(IMS:IME,KMS:KME,JMS:JME) &
,INTENT(INOUT) :: TKE_PBL
REAL,DIMENSION(IMS:IME,KMS:KME,JMS:JME) &
,INTENT(IN) :: RTHRATEN
! LOCAL VARIABLES
REAL, DIMENSION( its:ite, kts:kte ) :: dz8w2d, &
z2d,t2dten_ra
INTEGER :: I,J,K,NK,pass
CHARACTER(LEN=200) :: string
REAL,DIMENSION(IMS:IME,KMS:KME) :: TKE2d_1,TKE2d_2 , &
u2dblten_1,u2dblten_2, &
v2dblten_1,v2dblten_2
tke2d_1 = 0.0
tke2d_2 = 0.0
u2dblten_1 = 0.0
u2dblten_2 = 0.0
v2dblten_1 = 0.0
v2dblten_2 = 0.0
t2dten_ra = 0.0
DO J=jts,jte
DO k=kts,kte
NK=kme-k
DO i=its,ite
dz8w2d(I,K) = dz8w(i,K,j)
z2d(I,K) = z(i,NK,j)
t2dten_ra(i,k) = RTHRATEN(i,k,j)*PI3D(I,K,J)
!t2dten is flipped inside the code
! TKE_PBL = tke2d = 0.5 * (q**2) == e
! tke_2d_2 in gbmpbl is equivalent to "e" in GB01
tke2d_2(i,k)= TKE_PBL(i,k,j)
ENDDO
ENDDO
do pass=1,2
CALL GBM2D
(J,U3D(ims,kms,j),V3D(ims,kms,j),T3D(ims,kms,j),&
QV3D(ims,kms,j),QC3D(ims,kms,j),QI3D(ims,kms,j), &
P3D(ims,kms,j),u2dblten_2(ims,kms),v2dblten_2(ims,kms),&
RTHBLTEN(ims,kms,j),RQVBLTEN(ims,kms,j), &
RQCBLTEN(ims,kms,j),RQIBLTEN(ims,kms,j), &
KZM_GBM(ims,kms,j),KTH_GBM(ims,kms,j), &
KETHL_GBM(ims,kms,j),EL_GBM(ims,kms,j), &
TKE2d_2(ims,kms),t2dten_ra, &
dz8w2d,z2d, &
PSFC(ims,j),ZNT(ims,j),UST(ims,j),ZOL(ims,j), &
HOL(ims,j),PBL(ims,j),KPBL2D(ims,j),PSIM(ims,j), &
PSIH(ims,j),XLAND(ims,j),HFX(ims,j),QFX(ims,j), &
TSK(ims,j),GZ1OZ0(ims,j),WSPD(ims,j),BR(ims,j), &
DT,DTMIN, &
ids,ide, jds,jde, kds,kde, &
ims,ime, jms,jme, kms,kme, &
its,ite, jts,jte, kts,kte )
if(pass==1)then
TKE2d_1=tke2d_2 !tke at n+1
u2dblten_1=u2dblten_2
v2dblten_1=v2dblten_2
end if
if(pass==2)then
! tke_2d_2 in gbmpbl is equivalent to e == 2*(q**2)
TKE_PBL(:,:,j)=tke2d_1 !otherwise tke is advanced to n+2
rublten(:,:,j)=0.5*(u2dblten_2+u2dblten_1)
rvblten(:,:,j)=0.5*(v2dblten_2+v2dblten_1)
end if
end do
DO k=kts,kte
DO i=its,ite
RTHBLTEN(I,K,J)=RTHBLTEN(I,K,J)/PI3D(I,K,J)
ENDDO
ENDDO
ENDDO
END SUBROUTINE GBMPBL
SUBROUTINE GBM2D(J,U2D,V2D,T2D,QV2D,QC2D,QI2D,P2D, & 1,10
U2DTEN,V2DTEN,T2DTEN, &
QV2DTEN,QC2DTEN,QI2DTEN, &
KZM2D,KTH2D,KETHL2D,EL2D, &
TKE2D,T2DTEN_RA, &
dz8w2d,z2d,PSFCPA, &
ZNT,UST,ZOL,HOL,PBL,kpbl1d,PSIM,PSIH, &
XLAND,HFX,QFX,TSK,GZ1OZ0,WSPD,BR, &
DT,DTMIN, &
ids,ide, jds,jde, kds,kde, &
ims,ime, jms,jme, kms,kme, &
its,ite, jts,jte, kts,kte )
!-------------------------------------------------------------------
implicit none
!
INTEGER, INTENT(IN ) :: ids,ide, jds,jde, kds,kde, &
ims,ime, jms,jme, kms,kme, &
its,ite, jts,jte, kts,kte,J
!
REAL, INTENT(IN ) :: DT,DTMIN
REAL :: SVP1PA
REAL, DIMENSION( ims:ime, kms:kme ) , &
INTENT(IN ) :: QV2D, &
QC2D, &
QI2D, &
P2D, &
T2D
!
REAL, DIMENSION( ims:ime, kms:kme ) , &
INTENT(INOUT) :: U2DTEN, &
V2DTEN, &
T2DTEN, &
QV2DTEN, &
QC2DTEN, &
QI2DTEN, &
tke2d
!
REAL, DIMENSION( ims:ime, kms:kme ) , &
INTENT(OUT) :: KZM2d,KTH2d,KETHL2d,EL2D
REAL, DIMENSION( ims:ime ) , &
INTENT(INOUT) :: HOL, &
UST, &
PBL, &
ZNT
INTEGER, DIMENSION( ims:ime ) , &
INTENT(INOUT) :: kpbl1d
REAL, DIMENSION( ims:ime ) , &
INTENT(IN ) :: XLAND, &
HFX, &
QFX
!
REAL, DIMENSION( ims:ime ), INTENT(IN ) :: PSIM, &
PSIH
REAL, DIMENSION( ims:ime ), INTENT(INOUT) :: WSPD
REAL, DIMENSION( ims:ime ), INTENT(IN ) :: GZ1OZ0, &
BR
REAL, DIMENSION( ims:ime ) , &
INTENT(IN ) :: PSFCPA
REAL, DIMENSION( ims:ime ) , &
INTENT(IN ) :: TSK
REAL, DIMENSION( ims:ime ) , &
INTENT(INOUT) :: ZOL
!
REAL, DIMENSION( its:ite, kts:kte ) , &
INTENT(IN) :: dz8w2d, &
z2d,t2dten_ra
!
REAL, DIMENSION( ims:ime, kms:kme ) , &
INTENT(IN ) :: U2D, &
V2D
!CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
! PBL SCHEME C
! Questions? Contact mccaa@atmos.washington.edu C
!CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
!
! Order of events:
! 0. Preliminaries: Some things we only need to do once
! 1. First, save initial values and calculate some derivatives.
! 4. Calculate the buoyancy jump at flux levels
! 5. Calculate the pbl height and length scale
! 6. Compute diffusivity profiles
! 7. Implicit diffusion of thetal, total water
! 8. Implicit diffusion of momentum
! 9. Implicit diffusion of cloud ice
! 10. Prediction of TKE
! 11. Calculation of tendencies for output to model
!
! Local variables on full levels
real zqx(kts:kte+2)
REAL KTH(KTS:KTE+1),KZM(KTS:KTE+1),RHOXFL(KTS:KTE+1),tke(kts:kte+1),tkes(kts:kte+1), &
rrhoxfl(kts:kte+1),BBLS(KTS:KTE+1),NSQUAR(KTS:KTE+1),BOUYAN(KTS:KTE+1), &
DQWDZ(kts:kte+1),rdza(kts:kte+1),dza(kts:kte+1),SVS(KTS:KTE+1),presfl(kts:kte+1), &
exnerfl(kts:kte+1),SHEAR(KTS:KTE+1),rexnerfl(kts:kte+1),rcldb(kts:kte+1), &
epop(kts:kte+1),DTLDZ(KTS:KTE+1)
! Local variables on half levels
REAL UX(KTS:KTE),VX(KTS:KTE),THX(KTS:KTE),QX(KTS:KTE),THVX(KTS:KTE),zax(kts:kte),qix(kts:kte), &
KETHL(KTS:KTE),THLX(KTS:KTE),THXS(KTS:KTE),tx(kts:kte),tvx(kts:kte),rttenx(kts:kte), &
PRESHL(KTS:KTE),QCX(KTS:KTE),QWX(KTS:KTE),dzq(kts:kte),rRHOXHL(KTS:KTE),UXS(KTS:KTE), &
QXS(KTS:KTE),RHOXHL(KTS:KTE),exnerhl(kts:kte),rexnerhl(kts:kte),rdzq(kts:kte), &
VXS(KTS:KTE),qixs(kts:kte),qcxs(kts:kte)
REAL, DIMENSION( its:ite ) :: wspd1
REAL UFLXP,VFLXP,RHOXSF,Q0S, &
RDT,dt2, &
aone,atwo,czero,tskx, &
tvcon,fracz,dudz,dvdz,rvls,thv0,dthv,xfr, &
cpoxlv,r1cp,rczero, &
templ,temps,gamcrt,gamcrq,cell, &
rwspd,cfac, &
thgb,pblx,gothv,capcd,capch,capcq, &
ustx,ustxm,qfxx,hfxx,rlwp,tkeavg,wstar,xlvocp,wso,phih, &
rstbl,vk,tbbls,pref
integer i,k,l,iconv,ilay, &
ktop(kts:kte),kpbl2dx,kmix2dx, &
iteration,pass,kr,&
ktop_save(kts:kte) !NT new to store original height in case layers get merged
! Arrays for tridiagonal matrix solver
real aimp(kts:kte),bimp(kts:kte),cimp(kts:kte)
real uimp1(kts:kte),rimp1(kts:kte)
real uimp2(kts:kte),rimp2(kts:kte)
!NT some temporary variables to recompute n2
real THX_t,THVX_t,DTHV_t
!
parameter(XFR=0.1) !Fraction of turb layer to be considered in bbls
! parameter(aone=1.9*xfr,atwo=15.,cfac=7.8) orig, why is atwo 15!???? atn aone 1.9
parameter(aone=1.9*xfr,atwo=10.,cfac=7.8)
parameter(czero=5.869) ! b1/2**(3/2)
parameter(rstbl=1.5) ! empirical constant for l at stable interfaces
PARAMETER (GAMCRT=3.,GAMCRQ=2.E-3)
parameter(vk=0.4)
parameter(pref = 100000.)
!CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
!
! ---0--- Preliminaries: Some things we only need to do once
!
RDT=1./DT
dt2=dt
SVP1PA=svp1*10. ! NT actually this is svp1 in mb
cpoxlv = cp/xlv
xlvocp = xlv/cp
r1cp = 1./cp
rczero = 1./czero
!CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
! This is the beginning of big I loop
!
! ---1--- First, save initial values and calculate some derivatives.
!
DO I=its,ite
! Copy in j-dependent variables
tskx = tsk(i)
pblx = pbl(i)
qfxx = qfx(i)
hfxx = hfx(i)
zqx(kte+1)=0.0
zqx(kte+1+1)=0.0
tke(kte+1) = 0.0
DO K = kte,kts,-1
KR = kte+1-K
zqx(k)= zqx(k+1) + dz8w2d(i,kr)
zax(k)=0.5*(zqx(k)+zqx(k+1))
tke(k) = tke2d(i,kr)
! Wind components
UX(K)=U2D(I,KR) !
VX(K)=V2D(I,KR) !
TX(K)=T2D(I,KR)
QX(K)=QV2D(I,KR)
QCX(K)=QC2D(I,KR)
qix(k)=qi2D(i,kr)
rttenx(k)=t2dten_ra(i,kr)
ENDDO
! Done copying j-dependent variables
tkes(kte+1) = tke(kte+1)
do k = kts,kte
kr = kte+1-k
! Pressure at half levels
PRESHL(K)=p2d(i,kr)
DZQ(K)=ZQX(K)-ZQX(K+1)
rdzq(k)=1./dzq(k)
exnerhl(k)=(preshl(k)/pref)**rcp
rexnerhl(k)=1./exnerhl(k)
THX(K)=TX(K)*rexnerhl(k)
QWX(K) = QX(K) + QCX(K)
TVCON=(1.+ep_1*QX(K)-qcx(k))
TVX(K)=TX(K)*TVCON ! virtual temperature
THVX(K)=THX(K)*TVCON
THLX(K) = THX(K) - XLVOCP * rexnerhl(K) * QCX(K)
! SAVE INITIAL VALUES of winds, thx, and qx
tkes(k) = tke(k)
UXS(K) = UX(K)
VXS(K) = VX(K)
THXS(K) = THX(K)
QXS(K) = QX(K)
qixs(k) = qix(k)
qcxs(k) = qcx(k)
! Density at half levels
RHOXHL(K)=PRESHL(K)/(r_d*TVX(K))
rrhoxhl(k)=1./rhoxhl(k)
enddo
! Density and vertical derivatives at the full sigma levels.
presfl(1)=0.
DO K = 2, kte
kr = kte+1-k
! Pressure at full levels
PRESFL(K)=exp(0.5*(log(p2d(i,kr+1))+log(p2d(i,kr))))
epop(k)=ep_2/presfl(k)
DZA(K)=ZAX(K-1)-ZAX(K)
rdza(k)=1./dza(k)
exnerfl(k)=(presfl(k)/pref)**rcp
rexnerfl(k)=1./exnerfl(k)
FRACZ=(ZQX(K)-ZAX(K))*RDZA(K)
RHOXFL(K)=RHOXHL(K)+(RHOXHL(K-1)-RHOXHL(K))*FRACZ
RRHOXFL(K)=1./RHOXFL(K)
DUDZ = (UX(K-1) - UX(K)) *RDZA(K)
DVDZ = (VX(K-1) - VX(K)) *RDZA(K)
SVS(K)= DUDZ*DUDZ + DVDZ*DVDZ
DQWDZ(K) = (QWX(K-1) - QWX(K)) *RDZA(K)
DTLDZ(K) = (THLX(K-1) - THLX(K)) *RDZA(K)
ENDDO
!write(*,*)'dzq', dzq
!write(*,*)'dza', dza
! Pressure at the surface (in centibars)
PRESFL(KTE+1)=psfcpa(i)
rexnerfl(kte+1)=(pref/presfl(kte+1))**rcp
exnerfl(kte+1)=1./rexnerfl(kte+1)
! Saturation Mixing Ratio at Surface
q0s=ep_2/(PRESFL(KTE+1)/(100.*SVP1PA*EXP(svp2*(tskx-svpt0)/(tskx-svp3)))-1.)
! COMPUTE SOIL POTENTIAL TEMPERATURE
THGB = TSKX * rexnerfl(kte+1)
! DENSITY AT THE SURFACE
RHOXSF=(PRESFL(KTE+1))/(r_d*TVX(kte))
! More surface variables
WSPD1(i)=SQRT(UX(KTE)*UX(KTE)+VX(KTE)*VX(KTE))+1.e-4
THV0=THGB*(1.+ep_1*Q0S)
DTHV=(THVX(KTE)-THV0)
gothv = g/thvx(kte)
!CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
ustx = wspd1(i)*vk/(gz1oz0(i)-psim(i))
ustxm = amax1(ustx,0.1)
if ((xland(i)-1.5).lt.0) ustx = ustxm
!CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
!
!
! ---4--- Calculate the buoyancy jump at flux levels
!
call n2
(thlx,exnerfl,epop,qwx,cpoxlv,rdza, &
rexnerfl,kts,kte,nsquar,rcldb,xlvocp,svp1pa)
nsquar(kte+1)= g/thvx(kte) * dthv / zax(kte)
!CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
!
! ---5--- Calculate the pbl height and length scale
!
call pblhgt
( &
! input variables &
zqx,kts,kte, &
nsquar,tke,presfl,rhoxfl,rcldb,exnerfl, &
rttenx,thvx,thlx,thx,qwx,rexnerhl,qcx, &
xfr,xlvocp,aone,atwo,rstbl, &
! output variables &
bbls,pblx, &
ktop,iconv,kmix2dx,kpbl2dx)
!CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
!
! ---6--- Compute diffusivity profiles
!
do pass = 1,2
call my
( &
! Input variables &
bbls,nsquar,tke,iconv,ktop,thlx,thx,qwx, &
xlvocp,rcldb,rexnerhl,aone,atwo,kts,kte, &
! Output variables &
kzm,kth,kethl )
!CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
!
! ---7--- Implicit diffusion of thetal, total water
!
! First find the coefficients that apply to all scalars at half-levels
do k = 1, kte
if(k.eq.1)then
aimp(k)=0.
else
aimp(k)=-(rhoxfl(k)*rrhoxhl(k))* &
kth(k) * dt2 *rdzq(k)*rdza(k)
endif
if(k.eq.kte)then
cimp(k)=0.
else
cimp(k)=-(rhoxfl(k+1)*rrhoxhl(k))* &
kth(k+1) * dt2 *rdzq(k)*rdza(k+1)
endif
bimp(k) = 1 - aimp(k) - cimp(k)
! Now find right side for various scalars:
! No flux out top, so no (k.eq.1)
if(k.eq.kte)then ! at surface
! Include surface latent heat flux
rimp2(k) = qwx(k) + dt2 * qfxx*rrhoxhl(k)*rdzq(kte)
! Include surface sensible heat flux
rimp1(k) = thlx(k) + &
dt2 * hfxx*rrhoxhl(k)*r1cp*rdzq(kte)*rexnerhl(kte)
else
rimp2(k) = qwx(k)
rimp1(k) = thlx(k)
endif
enddo
call tridag
(aimp,bimp,cimp,rimp1,uimp1,kte)
call tridag
(aimp,bimp,cimp,rimp2,uimp2,kte)
!CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
!
! Recompute the buoyancy jump at flux levels
!
call n2
(uimp1,exnerfl,epop,uimp2,cpoxlv,rdza, &
rexnerfl, kts,kte,nsquar,rcldb,xlvocp,svp1pa)
!NT new recompute also n2 at sfc!!
! THLX(K) = THX(K) - XLVOCP * rexnerhl(K) * QCX(K)
THX_t = uimp1(KTE) + XLVOCP * rexnerhl(KTE) * QCX(KTE)
THVX_t=THX_t*TVCON
DTHV_t=(THVX_t-THV0)
nsquar(kte+1)= g/thvx_t * dthv_t / zax(kte)
!NT end
! Update only nsquar, then go back
!TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT
!
! Recompute pbl-height? since n2 changes; use uimp1 instead thlx
! TEST!!!
!
!NT call pblhgt( &
!NT ! input variables &
!NT zqx,kts,kte, &
!NT nsquar,tke,presfl,rhoxfl,rcldb,exnerfl, &
!NT rttenx,thvx,uimp1,thx,qwx,rexnerhl,qcx, &
!NT xfr,xlvocp,aone,atwo,rstbl, &
!NT ! output variables &
!NT bbls,pblx, &
!NT ktop,iconv,kmix2dx,kpbl2dx)
!TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT
enddo
!CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
!
! Update the scalars (only after second pass)
!
! Calculate new values of thx, qx and qcx using new values of thlx and qcx.
do k = 1, kte
thlx(k) = uimp1(k)
qwx(k) = uimp2(k)
if(k.ge.2) DQWDZ(K) = (QWX(K-1) - QWX(K)) *RDZA(K)
if(k.ge.2) DTLDZ(K) = (THLX(K-1) - THLX(K)) *RDZA(K)
templ = thlx(k)*exnerhl(k)
temps = templ
rvls = ep_2/ &
(preshl(k)/(100.*svp1pa*EXP(svp2*(temps-svpt0)/(temps-svp3)))-1.)
do iteration = 1, 3
temps = temps + ((templ-temps)*cp/xlv + qwx(k)-rvls)/ &
(cp/xlv+ep_2*xlv*rvls/r_d/temps/temps)
rvls = ep_2/ &
(preshl(k)/(100.*svp1pa*EXP(svp2*(temps-svpt0)/(temps-svp3)))-1.)
enddo
qcx(k)=max(qwx(k)-rvls,0.)
qx(k) = qwx(k) - qcx(k)
thx(k) = (templ+qcx(k)*xlv/cp) / exnerhl(k) ! theta_l
THVX(K)=THX(K)*(1.+ep_1*QX(K)-QCX(K)) !NT is this GB01:A13 then it should
!NT qx=q_v ; qwx=q_t; qcx=q_l
!nt thvx is theta virtual
ENDDO
!CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
!
! ---8--- Implicit diffusion of momentum
!
! First find the coefficients that apply to winds at half-levels
do k = 1, kte
if(k.eq.1)then
aimp(k)=0.
else
aimp(k)=-(rhoxfl(k)*rrhoxhl(k))* &
kzm(k) * dt2 *rdzq(k)*rdza(k)
endif
if(k.eq.kte)then
cimp(k)=0.
else
cimp(k)=-(rhoxfl(k+1)*rrhoxhl(k))* &
kzm(k+1) * dt2 *rdzq(k)*rdza(k+1)
endif
bimp(k) = 1 - aimp(k) - cimp(k)
! Now find right side
! No flux out top, so no (k.eq.1)
if(k.eq.kte)then
! At surface
UFLXP=-USTX*USTX*UX(KTE)/WSPD1(i)
VFLXP=-USTX*USTX*VX(KTE)/WSPD1(i)
! Include surface momentum fluxes
rimp1(k) = ux(k) + dt2 * &
uflxp * (rhoxsf*rrhoxhl(k)) *rdzq(kte)
rimp2(k) = vx(k) + dt2 * &
vflxp * (rhoxsf*rrhoxhl(k)) *rdzq(kte)
else
rimp1(k) = ux(k)
rimp2(k) = vx(k)
endif
enddo
call tridag
(aimp,bimp,cimp,rimp1,uimp1,kte)
call tridag
(aimp,bimp,cimp,rimp2,uimp2,kte)
! Update the winds
do k = 1, kte
ux(k) = uimp1(k)
vx(k) = uimp2(k)
if(k.ge.2)then
DUDZ = (UX(K-1) - UX(K)) *RDZA(K)
DVDZ = (VX(K-1) - VX(K)) *RDZA(K)
SVS(K)= DUDZ*DUDZ + DVDZ*DVDZ
endif
enddo
!CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
!
! ---9--- Implicit diffusion of cloud ice
!
! First find the coefficients that apply to all scalars at half-levels
do k = 1, kte
if(k.eq.1)then
aimp(k)=0.
else
aimp(k)=-(rhoxfl(k)*rrhoxhl(k))* &
kth(k) * dt2 *rdzq(k)*rdza(k)
endif
if(k.eq.kte)then
cimp(k)=0.
else
cimp(k)=-(rhoxfl(k+1)*rrhoxhl(k))* &
kth(k+1) * dt2 *rdzq(k)*rdza(k+1)
endif
bimp(k) = 1 - aimp(k) - cimp(k)
! Now find right side for various scalars:
! No flux out top, so no (k.eq.1)
! No flux in bottom, so no (k.eq.kte)
rimp1(k) = qix(k)
! rimp2(k) = qncx(k)
enddo
call tridag
(aimp,bimp,cimp,rimp1,qix,kte)
! call tridag(aimp,bimp,cimp,rimp2,qncx,kte)
!CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
!
! ---10--- Prediction of TKE
!
! Features:
! a. Explicit calculation of buoyancy and shear terms using
! time=t+1 values of thetal, qw, and winds
! b. Surface TKE is diagnosed
! c. Semi-implicit calculation of dissipation term and
! implicit calculation of turbulent transfer term
! First, buoyancy and shear terms
DO K=2,KTE
! Compute buoyancy term with new values of thetal
BOUYAN(K)=-KTH(K)*nsquar(K)
! Compute shear term with new values of svs
SHEAR(K) = KZM(K) * SVS(K)
ENDDO
do ilay = 1,iconv
k = ktop(ilay)
if(qcx(k).gt.1e-8.and.k.gt.1) bouyan(k) = bouyan(k) - & !NT GB01:A14
rttenx(k)*(presfl(k+1)-presfl(k)) * rrhoxfl(k) &
* rexnerfl(k) / thvx(k)
enddo
! TKE at top is fixed
tke(1)=0.
bbls(1)= 0.0
! Diagnose TKE at surface, following MY 82, B1 ** (2/3) / 2 = 3.25
tke(kte+1)=3.25 * ustx * ustx ! normal
! tke(kte+1)=.33*wstar**2 ! dryrun
! Now the implicit calculations
! First find the coefficients that apply for full levels
do k = 2, kte
if(k.eq.2)then
aimp(k-1)=0.
else
aimp(k-1)=-(rhoxhl(k-1)*rrhoxfl(k))* &
kethl(k-1)*dt2*rdzq(k-1)*rdza(k)
endif
if(k.eq.kte)then
cimp(k-1)=0.
! Account for implicit part of flux between level kte and surface
if(bbls(k).gt.0)then
bimp(k-1) = 1 - aimp(k-1) - cimp(k-1) + &
dt2 * ( sqrt(tke(k))*rczero/bbls(k) + &
rhoxhl(k)*rrhoxfl(k)*kethl(k)*rdzq(k)*rdza(k) )
else
bimp(k-1) = 1 - aimp(k-1) - cimp(k-1) + &
dt2 * rhoxhl(k)*rrhoxfl(k)* kethl(k)*rdzq(k)*rdza(k)
endif
else
cimp(k-1)=-(rhoxhl(k)*rrhoxfl(k))* &
kethl(k)*dt2*rdzq(k)*rdza(k)
tbbls = max(bbls(k),bbls(k+1))
if(tbbls.gt.0)then
bimp(k-1)= 1 - aimp(k-1) - cimp(k-1) + dt2 * sqrt(tke(k))*rczero/tbbls
else
bimp(k-1)= 1 - aimp(k-1) - cimp(k-1)
endif
endif
! Now find right side
if(k.eq.kte)then
! Account for fixed part of flux between level kte and surface
rimp1(k-1) = tke(k) + dt2 * ( SHEAR(K)+BOUYAN(K) + &
tke(kte+1)*(rhoxhl(k)*rrhoxfl(k))*kethl(k)*rdzq(k)*rdza(k) )
else
rimp1(k-1) = tke(k) + dt2 * (SHEAR(K)+BOUYAN(K))
endif
enddo
call tridag
(aimp,bimp,cimp,rimp1,uimp1,kte-1)
! Update the tke
do k = 2, kte
tke(k) = max(uimp1(k-1),0.001) ! background tke .001
enddo
!CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
!
! ---11--- Calculation of tendencies for output to model
!
DO K=KTS,KTE
kr = kte+1-k
U2DTEN(I,KR)= (UX(K)-UXS(K))*RDT
V2DTEN(I,KR)=(VX(K)-VXS(K))*RDT
T2DTEN(I,KR)=(THX(K)-THXS(K))*EXNERHL(K)*RDT
QV2DTEN(I,KR) = (QX(K)-QXS(K))*RDT
qi2Dten(i,kr) = (qix(k)-qixs(k))*rdt
qc2Dten(i,kr) = (qcx(k)-qcxs(k))*rdt
tke2d(i,kr)=tke(k)
kzm2d(i,kr)=kzm(k)
kth2d(i,kr)=kth(k)
kethl2d(i,kr)=kethl(k)
EL2D(i,kr) = bbls(k)
ENDDO
! Copy out j-dependent variables
pbl(i)=pblx
ust(i)=ustx
kpbl1d(i)=kte+1-kpbl2dx
end do
!CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
RETURN
END SUBROUTINE GBM2D
!CCCCCCCCCCCCCCCCCCCCC END OF PBL SUBROUTINE CCCCCCCCCCCCCCCCCCCCCCCCC
!
subroutine tridag(a,b,c,r,u,n) 7,2
! Solves tridiagonal matrix
! See "Numerical Recipes in Fortran 77", p. 42
implicit none
integer n,nmax
real a(n),b(n),c(n),r(n),u(n)
parameter (nmax=100)
integer j
real rbet,gam(nmax)
rbet=1./b(1)
u(1)=r(1)*rbet
do j=2,n
gam(j)=c(j-1)*rbet
rbet=1./(b(j)-a(j)*gam(j))
u(j)=(r(j)-a(j)*u(j-1))*rbet
end do
do j=n-1,1,-1
u(j)=u(j)-gam(j+1)*u(j+1)
end do
return
end subroutine tridag
subroutine pblhgt( & 1
! input variables
zqx,kts,kte, &
nsquar,tke,presfl,rhoxfl,rcldb,exnerfl, &
rttenx,thvx,thlx,thx,qwx,rexnerhl,qcx, &
xfr,xlvocp,aone,atwo,rstbl, &
! output variables
bbls,pblx, &
ktop,iconv,kmix2dx,kpbl2dx &
)
implicit none
! Input variables
real zqx(kts:kte+2)
real nsquar(kts:kte+1),tke(kts:kte+1),presfl(kts:kte+1),rhoxfl(kts:kte+1), &
rcldb(kts:kte+1),exnerfl(kts:kte+1)
real rttenx(kts:kte),thvx(kts:kte),thlx(kts:kte),thx(kts:kte),qwx(kts:kte), &
rexnerhl(kts:kte),qcx(kts:kte)
real xfr,xlvocp,aone,atwo,rstbl
! Output variables
real bbls(kts:kte+1), pblx
integer ktop(kts:kte+1), iconv,kmix2dx,kpbl2dx, &
ktop_save(kts:kte+1)
! Local variables
integer kbot(kts:kte+1),kts,kte,kstart
integer istabl,ibeg,ilay,nlev,k,itemp
real blinf,rnnll,tkeavg,trnnll,radnnll,delthvl,elambda, &
bige,biga,entnnll,tbbls
! Find noncontiguous convectively unstable layers
iconv = 0
istabl = 1
do k=2,kte+1 !nt nscquar is defined at kte+1 after the call to n2
if(nsquar(k).lt.0)then
if(istabl.eq.1)then
iconv = iconv + 1
ktop(iconv)=k
endif
istabl=0
kbot(iconv)=k
else
istabl=1
BBLS(K) = MIN(rstbl*SQRT(TKE(K)/NSQUAR(K)),karman*ZQX(K))
endif
enddo
!NT new
! if(ktop(iconv).eq.kte+1 .and. kbot(iconv).eq.kte+1)then
! iconv=iconv-1 !NT don't let the bottome layer be a convective top.
! end if
!NT end
! Now see if they have sufficient buoyant convection to connect
!NT save ktops to be able to reset top of a merged layers
ktop_save=ktop
!NT put this if-statement in to make sure;
IF(iconv.ge.1)THEN
!NT
ibeg = 1
2745 do ilay = ibeg, iconv
blinf = xfr*(zqx(ktop(ilay)-1) - zqx(kbot(ilay)+1))
! Find average n*n*l*l for layer
rnnll = 0.
tkeavg = 0.
nlev = kbot(ilay)-ktop(ilay)+1
do k = ktop(ilay), kbot(ilay)
bbls(k) = min(blinf,karman*ZQX(K))
rnnll = rnnll + nsquar(k)*bbls(k)*bbls(k) !NT is not averaged, but correct
tkeavg = tkeavg + tke(k) / nlev
enddo
! First extend up
kstart=ktop(ilay)-1
!NT orig do k = ktop(ilay)-1,2,-1
do k = kstart,2,-1
ktop(ilay)=k ! We always go up at least one, for the entrainment interface
bbls(k) = min(karman * ZQX(K),blinf)
trnnll = nsquar(k)*bbls(k)*bbls(k)
if(trnnll*nlev.ge.-0.5*rnnll) goto 2746 ! Is it the top?
!NT test if(trnnll*nlev.ge.-0.7*rnnll) goto 2746 ! Requires stronger jump to be top
!NT doesn't workkpbl if(trnnll*nlev.ge.-0.5*rnnll.and. &
!NT n2 gets recomputed nsquar(k).ge.1.e-6) goto 2746 ! Avoids weak layers with even weaker tops
!NT after pblhgt ! Imagine n2 small negative over several layers
! then average rnnll is very small and a very weak
! pos n2 is enough to be 'inversion' top. This makes
! sure that we go up at least one more.
if(ilay.gt.1.and.ktop(ilay).eq.kbot(ilay-1))then ! did we merge with layer above?
ibeg = ilay - 1
!NT orig ktop(ibeg)=ktop(ibeg)+1 !NT not correct if one up was not inversion, the new thicker
!NT layer might have different average properties, should
!NT reset to original ktop
ktop(ibeg)=ktop_save(ibeg) !NT new
kbot(ibeg)=kbot(ibeg+1)
iconv = iconv - 1
do itemp = ibeg+1,iconv !NT if there's a layer below decrease layer index
ktop(itemp)=ktop(itemp+1)
kbot(itemp)=kbot(itemp+1)
ktop_save(itemp)=ktop_save(itemp+1) !NT new
enddo
goto 2745 ! recompute for the new, deeper layer
endif
rnnll = rnnll + trnnll
nlev = nlev + 1 !NT moved up
enddo
! Add radiative/entrainment contribution to total
2746 k = ktop(ilay)
radnnll = 0.
if(qcx(k).gt.1e-8) radnnll = &
rttenx(k)*(presfl(k+1)-presfl(k))/ &
(rhoxfl(k)*thvx(k)*exnerfl(k))
entnnll = 0.
if(k.ge.3)then
delthvl = (thlx(k-2)+thx(k-2)*ep_1*qwx(k-2)) &
- (thlx(k) + thx(k)*ep_1*qwx(k))
elambda = xlvocp*rcldb(k)*rexnerhl(k)/max(delthvl,0.1)
bige = 0.8 * elambda
biga = aone * (1 + atwo * bige)
entnnll = biga * sqrt(tkeavg**3) / bbls(k)
endif
if(tkeavg.gt.0.) rnnll = rnnll + min(0.,bbls(k)/sqrt(tkeavg) * (radnnll + entnnll) )
! Now extend down
do k = kbot(ilay)+1,kte+1
tbbls = min(karman * ZQX(K),blinf)
trnnll = nsquar(k)*tbbls*tbbls
if(trnnll*nlev.ge.-0.5*rnnll)goto 2747 ! Is it the bottom?
kbot(ilay)=k
if(ilay.lt.iconv.and.kbot(ilay).eq.ktop(ilay+1))then ! did we merge with layer below?
!NT orig ktop(ilay)=ktop(ilay)+1
ktop(ilay)=ktop_save(ilay)
kbot(ilay)=kbot(ilay+1)
iconv = iconv - 1
do itemp = ilay+1,iconv
ktop(itemp)=ktop(itemp+1)
kbot(itemp)=kbot(itemp+1)
ktop_save(itemp)=ktop_save(itemp+1)
enddo
goto 2745 ! recompute for the new, deeper layer
endif
rnnll = rnnll + trnnll
bbls(k)=tbbls
nlev = nlev + 1
enddo
2747 continue
enddo !NT all sorting is done, go through layers and calk l
do ilay = 1, iconv
blinf = xfr*(zqx(ktop(ilay)-1) - zqx(kbot(ilay)+1))
do k = ktop(ilay),kbot(ilay)
bbls(k) = min(karman * ZQX(K),blinf)
enddo
enddo
!NT added to check if iconv .ge. 1
ENDIF
!NT end
! We should now have tops and bottoms for iconv layers
! NT not clear how kpbl2dx should work, but doesn't matter since
! NT only kmix2dx is used no matter what kpbl2dx is.
! NT Looks like it could be used to choose between mixing pbl and
! NT convective pbl height if there are more than 1 unstable layers
if(iconv.gt.0)then
if(kbot(iconv).eq.kte+1)then
kmix2dx = ktop(iconv)
if(kpbl2dx.ge.0)then
if(iconv.gt.1)then
kpbl2dx = ktop(iconv-1)
else
kpbl2dx = kmix2dx
endif
else
kpbl2dx=-kpbl2dx
endif
else
kmix2dx = kte
if(kpbl2dx.ge.0)then
kpbl2dx = ktop(iconv)
else
kpbl2dx = -kpbl2dx
endif
endif
else
kmix2dx = kte
if(kpbl2dx.ge.0)then
kpbl2dx = kmix2dx
else
kpbl2dx = -kpbl2dx
endif
endif
pblx=ZQX(KMIX2DX)
return
end subroutine pblhgt
subroutine roots(a,b,c,r1,r2) 3
implicit none
real a,b,c,r1,r2,q
if(a.eq.0)then ! form b*x + c = 0
if(b.eq.0)then ! failure: c = 0
r1 = -9.99e33
else ! b*x + c = 0
r1 = -c / b
endif
r2 = r1
else
if(b.eq.0.)then ! form a*x**2 + c = 0
if(a*c.gt.0.)then ! failure: x**2 = -c/a < 0
r1 = -9.99e33
else ! x**2 = -c/a
r1 = sqrt(-c/a)
endif
r2 = -r1
else ! form a*x**2 + b*x + c = 0
if((b**2 - 4*a*c).lt.0.)then ! failure, no real roots
r1 = -9.99e33
r2 = -r1
else
q = - 0.5 * ( b + sign(1.0,b) * &
sqrt(b**2 - 4*a*c) )
r1 = q/a
r2 = c/q
endif
endif
endif
return
end subroutine roots
subroutine n2(thlx,exnerfl,epop,qwx,cpoxlv,rdza, & 2
rexnerfl, kts,kte, nsquar,rcldb,xlvocp, svp1pa)
implicit none
! Input/output variables
real thlx(kts:kte),exnerfl(kts:kte+1),epop(kts:kte+1),qwx(kts:kte), &
rexnerfl(kts:kte+1),rdza(kts:kte+1),nsquar(kts:kte+1),rcldb(kts:kte+1)
real cpoxlv,xlvocp,svp1pa
! Local variables
real templ,rvls,temps,tempv,tvbl,rcld,tvab,thvxfl,dtvdz
integer k,kts,kte
DO K = 2, KTE
! Buoyancy is jump in thetav across flux level/dza
! First, layer below, go up and see if anything condenses.
templ = thlx(k)*exnerfl(k)
rvls = 100.*svp1pa*EXP(svp2*(templ-svpt0)/(templ-svp3))*epop(k)
temps=templ + (qwx(k)-rvls)/(cpoxlv + &
ep_2*xlv*rvls/(r_d*templ**2))
rvls = 100.*svp1pa*EXP(svp2*(temps-svpt0)/(temps-svp3))*epop(k)
rcldb(k)=max(qwx(k)-rvls,0.)
tempv = (templ + xlvocp*rcldb(k)) * &
(1 + ep_1*(qwx(k)-rcldb(k)) - rcldb(k))
tvbl = tempv*rexnerfl(k)
! Now do layer above; go down to see how much evaporates
templ = thlx(k-1)*exnerfl(k)
rvls = 100.*svp1pa*EXP(svp2*(templ-svpt0)/(templ-svp3))*epop(k)
temps=templ+(qwx(k-1)-rvls)/(cpoxlv+ &
ep_2*xlv*rvls/(r_d*templ**2))
rvls = 100.*svp1pa*EXP(svp2*(temps-svpt0)/(temps-svp3))*epop(k)
rcld=max(qwx(k-1)-rvls,0.)
tempv = (templ + xlvocp*rcld) * &
(1 + ep_1*(qwx(k-1)-rcld) - rcld)
tvab = tempv*rexnerfl(k)
!
thvxfl= .5 * (tvab+tvbl)
dtvdz = (tvab - tvbl) *rdza(k)
nsquar(k) = g/thvxfl * dtvdz
ENDDO
nsquar(1)=nsquar(2)
return
end subroutine n2
subroutine my( & 1
! Input variables &
bbls,nsquar,tke,iconv,ktop,thlx,thx,qwx, &
xlvocp,rcldb,rexnerhl,aone,atwo,kts,kte, &
! Output variables &
kzm,kth,kethl)
implicit none
real bbls(kts:kte+1),nsquar(kts:kte+1),tke(kts:kte+1),thlx(kts:kte),thx(kts:kte), &
qwx(kts:kte),kzm(kts:kte+1),kth(kts:kte+1),kethl(kts:kte)
real xlvocp,rcldb(kts:kte+1),rexnerhl(kts:kte),aone,atwo
integer iconv,ktop(kts:kte)
! Local variables
real gh,a1,b1,c1,a2,b2,a1ob1,nuk,delthvl,elambda,bige,biga,kmax,n2min
real sm(kts:kte+1),sh(kts:kte+1)
integer k,ilay,kts,kte
parameter(A1=0.92,B1=16.6,C1=0.08,A2=0.74,B2=10.1)
parameter(nuk=5.0) !multiplier for kethl, GB01 value
parameter(kmax=1000.) ! max for kethl
parameter(n2min=1.e-7) ! min for n2
a1ob1 = a1/b1
! Calculate the diffusivities for momentum, thetal, qw and tke
! KTH and KZM are at full levels.
! KETHL is at half levels. NT: BMG03:6/7
kzm(kte+1)=0.
kth(kte+1)=0.
kzm(1)=0.
kth(1)=0.
sm(kte+1)=1.
sh(kte+1)=1.
sm(1) = 1.
sh(1) = 1.
DO K = KTE, 2, -1
! According on how the TKE equiation is computed, the "tke" variable in gbmpbl !NP
! is equivalent to "e" in GB01 paper, or e==(q^2 / 2) in MY82 or Gal88. !NP
! Calculations of gh (MY82, Eq.33(b) and Gal88, Eq.26) contain q^2; !NP
! therefore, gh in the code below should contain (2*tke) !NP
gh =-bbls(k)*bbls(k)*nsquar(k)/(2*tke(k)+1e-9) ! MY82:33b/ Gal88:26
gh = min(gh,0.0233)
gh = max(gh,-0.28) ! according to Gal88:30; -0.28 < gh < 0.0233
sm(k) = a1 * (1. - 3.*c1 - 6.*a1ob1 - 3.*a2*gh* &
((b2-3.*a2)*(1.-6.*a1ob1) - 3.*c1*(b2+6.*a1))) / &
((1. - 3.*a2*gh*(6.*a1 + b2)) * (1. - 9.*a1*a2*gh))
sh(k) = a2 * (1. - 6.*a1ob1) / (1. - 3.*a2*gh*(6.*a1+b2))
! See the previous comments regarding the convention of "e", "q^2/2" and "tke".!NP
! In order to use "q" in the calculations of kzm and kzh, apply "sqrt(2*tke)" !NP
kzm(k) = min(bbls(k)*sqrt(2*tke(k))*sm(k),kmax)
kth(k) = min(bbls(k)*sqrt(2*tke(k))*sh(k),kmax)
!
kethl(k)=nuk*sqrt(kzm(k)*kzm(k+1)) ! GB01:A7
kethl(k)=min(kethl(k),kmax) ! keep in bounds
ENDDO
! Special case for tops of convective layers
! NT GB01 calls this local entrainment closure : 28
do ilay = 1,iconv
k = ktop(ilay)
IF(nsquar(k).ge.n2min)THEN !NTnew
kethl(k )=nuk*kzm(k+1)
if(k.ge.3)then !NT only in combination with previous n2 test.
kethl(k-1)=0.0 !NT no transport through inversion
delthvl = (thlx(k-2)+thx(k-2)*ep_1*qwx(k-2)) - & !NT GB01:18,B12
(thlx(k) + thx(k) * ep_1 * qwx(k))
elambda = xlvocp*rcldb(k)*rexnerhl(k)/max(delthvl,0.1)
bige = 0.8 * elambda
biga = aone * (1 + atwo * bige)
kth(k) = min(kth(k), biga*sqrt(TKE(k)**3)/NSQUAR(k)/ &
max(bbls(k),bbls(k+1)))
kzm(k) = min(kzm(k), kth(k) / sh(k+1) * sm(k+1)) ! prandtl number from layer below
endif
ENDIF !NTnew end
enddo
! Need KETHL at the top (top-down indexing)
KETHL(1) = kethl(2)
! Replace KETHL at the surface with something non-zero (top-down indexing)
kethl(kte) = nuk*0.5*kzm(kte)
return
end subroutine my
SUBROUTINE gbmpblinit(RUBLTEN,RVBLTEN,RTHBLTEN,RQVBLTEN, & 1
RQCBLTEN,RQIBLTEN,P_QI,P_FIRST_SCALAR, &
TKE_PBL,KTH_GBM, &
restart,allowed_to_read, &
ids, ide, jds, jde, kds, kde, &
ims, ime, jms, jme, kms, kme, &
its, ite, jts, jte, kts, kte )
!-------------------------------------------------------------------
IMPLICIT NONE
!-------------------------------------------------------------------
LOGICAL , INTENT(IN) :: restart,allowed_to_read
INTEGER , INTENT(IN) :: ids, ide, jds, jde, kds, kde, &
ims, ime, jms, jme, kms, kme, &
its, ite, jts, jte, kts, kte
INTEGER , INTENT(IN) :: P_QI,P_FIRST_SCALAR
REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) , INTENT(OUT) :: &
RUBLTEN, &
RVBLTEN, &
RTHBLTEN, &
RQVBLTEN, &
RQCBLTEN, &
RQIBLTEN, &
TKE_PBL, &
KTH_GBM
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
RUBLTEN(i,k,j)=0.
RVBLTEN(i,k,j)=0.
RTHBLTEN(i,k,j)=0.
RQVBLTEN(i,k,j)=0.
RQCBLTEN(i,k,j)=0.
TKE_PBL(i,k,j)=0.001 ! use array for TKE
KTH_GBM(i,k,j)=0.
ENDDO
ENDDO
ENDDO
ENDIF
IF (P_QI .ge. P_FIRST_SCALAR .and. .not.restart) THEN
DO j=jts,jtf
DO k=kts,ktf
DO i=its,itf
RQIBLTEN(i,k,j)=0.
ENDDO
ENDDO
ENDDO
ENDIF
END SUBROUTINE gbmpblinit
!-------------------------------------------------------------------
END MODULE module_bl_gbmpbl