!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