123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485 |
- !
- ! Subgrid stuff from TMPP.
- !
- ! Copied from:
- ! TMPP/SOURCE/tmpp_sub_subg.f90
- ! TMPP/SOURCE/tmpp_sub_work.f90
- ! TMPP/SOURCE/tmpp_geometry.f90
- ! TMPP/SOURCE/phys_geopot.f90
- !
- module phys_convec_tmpp
- implicit none
-
- ! --- in/out -------------------------------
- private
-
- public :: subscal
- public :: subscal_2d
- public :: mid2bound_uv
- public :: mid2bound_w
- public :: mid2bound_t
- public :: mid2bound_q
- public :: mid2bound_z
- public :: mid2bound_p
-
- public :: phlev_ec_rev
- public :: geopot
- contains
- ! ==========================================================
- ! ===
- ! === TMPP/SOURCE/tmpp_sub_subg.f90
- ! ===
- ! ==========================================================
-
- !-----------------------------------------------------------------------
- ! calculate subscal parameters at a given horizontal location.
- ! Three different pressure levels are used in this subroutine:
- ! ppress (boundaries ECMWF levels)
- ! ppresg (boundaries TM3)
- ! zpl (centers ECMWF levels)
- ! zplg (centers TM3)
- !
- !-----------------------------------------------------------------------
- !subroutine subscal(pz,ppress,pu,pv,pw,pt,pq,pqac,pqam,pevap, &
- ! pentug,pdetug,pentdg,pdetdg,pdkg,pzg)
- subroutine subscal_2d( np, lme, at, bt, &
- pz,ppress,pw,pt,pq,pqac,pqam,pevap, &
- pentug,pdetug,pentdg,pdetdg)
- ! --- in/out -----------------------------------
-
- integer, intent(in) :: np
- integer, intent(in) :: lme
- real, intent(in) :: at(0:lme), bt(0:lme)
- real, intent(in) :: pz(np,0:lme)
- real, intent(in) :: ppress(np,0:lme)
- real, intent(in) :: pw(np,0:lme)
- real, intent(in) :: pt(np,0:lme)
- real, intent(in) :: pq(np,0:lme)
- real, intent(in) :: pqac(np,0:lme)
- real, intent(in) :: pqam(np,0:lme)
- real, intent(in) :: pevap(np)
- real, intent(out) :: pentug(np,lme)
- real, intent(out) :: pdetug(np,lme)
- real, intent(out) :: pentdg(np,lme)
- real, intent(out) :: pdetdg(np,lme)
-
- ! --- local -------------------------------------
-
- integer :: i
-
- ! --- begin ------------------------------------
- ! 18 Apr 2012 - P. Le Sager - Commented openMP loop, since it gives
- ! wrong results: large differences with serial case results in eu/ed/du
- ! /dd fields
-
- !testPLS !$OMP PARALLEL &
- !testPLS !$OMP default ( none ) &
- !testPLS !$OMP shared ( np, lme, at, bt ) &
- !testPLS !$OMP shared ( pz, ppress, pw, pt, pq ) &
- !testPLS !$OMP shared ( pqac, pqam, pevap ) &
- !testPLS !$OMP shared ( pentug, pdetug, pentdg, pdetdg ) &
- !testPLS !$OMP private ( i )
- !testPLS !$OMP DO
- do i = 1, np
- call subscal( lme, at, bt, &
- pz(i,:), ppress(i,:), pw(i,:), pt(i,:), pq(i,:), &
- pqac(i,:), pqam(i,:), pevap(i), &
- pentug(i,:), pdetug(i,:), pentdg(i,:), pdetdg(i,:) )
- end do
- !testPLS !$OMP END DO
- !testPLS !$OMP END PARALLEL
-
- end subroutine subscal_2d
-
- ! *
-
- subroutine subscal( lme, at, bt, &
- pz,ppress,pw,pt,pq,pqac,pqam,pevap, &
- pentug,pdetug,pentdg,pdetdg) !,pdkg,pzg)
- ! >>> adhoc: not from ECMWF to TM levels >>>>>>>>>>>>>>>>>>
- ! (set tm stuff to ec stuff)
- !use Geometry, only : lm
- !use Geometry, only : at => a_tm, bt => b_tm
- ! use Geometry, only : lm => lme
- ! use Geometry, only : at => a_ec, bt => b_ec
- ! <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
- ! use Geometry, only : lme
- use Num, only : IntervalQuad_Lin
- use Num, only : interp_muherm
- ! --- const ------------------------------------
- ! integer, parameter :: jplm = lme
- !integer, parameter :: jplmg = lm
- !integer, parameter :: jplmgp1 = lm+1
- ! integer, parameter :: jplmg = lme
- ! integer, parameter :: jplmgp1 = lme+1
- real, parameter :: ppg = 9.80665
- ! --- in/out ------------------------------------
-
- integer :: status
- integer, intent(in) :: lme
- real, intent(in) :: at(0:lme), bt(0:lme)
- real, intent(in) :: pz(0:lme)
- real, intent(in) :: ppress(0:lme)
- real, intent(in) :: pw(0:lme)
- real, intent(in) :: pt(0:lme)
- real, intent(in) :: pq(0:lme)
- real, intent(in) :: pqac(0:lme)
- real, intent(in) :: pqam(0:lme)
- real, intent(in) :: pevap
- !real, intent(in) :: pu(0:lme)
- !real, intent(in) :: pv(0:lme)
- ! entrainment, detrainment rates, diffusion coefficient
- real, intent(out) :: pentug(lme)
- real, intent(out) :: pdetug(lme)
- real, intent(out) :: pentdg(lme)
- real, intent(out) :: pdetdg(lme)
- ! real, intent(out) :: pdkg(lme)
- ! real, intent(out) :: pzg(0:lme)
- ! --- local ------------------------------------
- integer :: jl,ilast
- real :: sumup, sumdown
- ! output variables on TM vertical grid
- real :: zamu(0:lme),zptc(0:lme),zpqc(0:lme),zplc(0:lme), &
- zpqp(0:lme),ppresg(0:lme)
- ! real :: zpdk(0:lme)
- real :: zpam(lme),zped(lme),zpdd(lme),zpeu(lme),zpdu(lme)
- real :: zpl(lme),zplg(lme)
- real :: zam
- integer :: lct
- ! --- begin -------------------------------------------
- ! calculate convection by clouds
- call cloud( lme, pz,ppress,pt,pq,pw,pqac,pqam,pevap, &
- zamu,zptc,zpqc,zplc,zpqp, &
- zpam,zpeu,zpdu,zped,zpdd)
- ! ! calculate turbulent diffusion coefficient
- !
- ! call louis(pz,pt,pu,pv,zpdk)
- ! generate pressures on TM3 level boundaries and centers respectively
- do jl=0,lme
- ppresg(jl)=at(jl)+ppress(lme)*bt(jl)
- end do
- do jl=1,lme
- zplg(jl)=0.5*(ppresg(jl)+ppresg(jl-1))
- end do
- ! --- Vertical averaging of variables defined on level centers
-
- ! * interpolate entrainment/detrainment rates on TM3 vertical coordinate:
- ! Dirk Olivie, 12 May 2004
- ! No interpolation needed if lme = lme
- if ( lme .ne. lme ) then
- do jl=1,lme
- zpl(jl)=0.5*(ppress(jl)+ppress(jl-1))
- zpeu(jl)=zpeu(jl)/(ppress(jl)-ppress(jl-1))
- zpdu(jl)=zpdu(jl)/(ppress(jl)-ppress(jl-1))
- zped(jl)=zped(jl)/(ppress(jl)-ppress(jl-1))
- zpdd(jl)=zpdd(jl)/(ppress(jl)-ppress(jl-1))
- end do
- ilast=1
- do jl=1,lme
- call IntervalQuad_Lin(zpl,zpeu,ppresg(jl-1),ppresg(jl),pentug(jl), ilast, status )
- if (status/=0) stop 'ERROR in subscal'
- call IntervalQuad_Lin(zpl,zpdu,ppresg(jl-1),ppresg(jl),pdetug(jl), ilast, status )
- if (status/=0) stop 'ERROR in subscal'
- call IntervalQuad_Lin(zpl,zped,ppresg(jl-1),ppresg(jl),pentdg(jl), ilast, status )
- if (status/=0) stop 'ERROR in subscal'
- call IntervalQuad_Lin(zpl,zpdd,ppresg(jl-1),ppresg(jl),pdetdg(jl), ilast, status )
- if (status/=0) stop 'ERROR in subscal'
- end do
- else
-
- pentug = zpeu
- pdetug = zpdu
- pentdg = zped
- pdetdg = zpdd
-
- endif
- ! ! * Interpolate diffusion coefficients from upper boundaries of ECMWF layers to
- ! ! upper boundaries of TM3 layers and
- ! ! reorganize the vertical index of the diffusion coefficient
- ! ! pdkg(1) is diffusion coefficient at the top of layer 1 (TOA)
- ! ! pdkg(lme) is diffusion coefficient at the top of layer lme
- !
- ! call interp_muherm( ppress, zpdk, ppresg, pdkg )
- ! pdkg(1)=0.
- !
- ! ! * Interpolate geopotential height from ECMWF layer boundaries to TM3 layer
- ! ! boundaries
- !
- ! call interp_muherm( ppress, pz, ppresg, pzg )
- ! pzg(0)=pz(0)
- ! pzg(lme)=pz(lme)
- !--------------------------------------------------------------------------
- ! correct massfluxes on TM3 grid to conserve mass
- !
- ! updraft
- ! correction level is uppermost level with nonzero detrainment
- lct=lme
- do jl=1,lme
- if ( pdetug(jl) > 0.0 ) then
- lct=jl
- exit
- endif
- end do
- zam=0.
- do jl=lme,1,-1
- zam=zam+pentug(jl)-pdetug(jl)
- end do
- pdetug(lct)=pdetug(lct)+zam
- ! downdraft
- ! correction level is lowermost level
- lct=lme
- zam=0.
- do jl=lme,1,-1
- zam=zam+pentdg(jl)-pdetdg(jl)
- end do
- pdetdg(lct)=pdetdg(lct)+zam
- !
- ! check conservation
- !
- sumup=0.
- sumdown=0.
- do jl=1,lme
- sumup=sumup+pentug(jl)-pdetug(jl)
- sumdown=sumdown+pentdg(jl)-pdetdg(jl)
- enddo
- if ( abs(sumup) > 1.0e-5 ) then
- write(*,*)' ERROR no massconserv in updraft'
- stop
- endif
- if ( abs(sumdown) > 1.0e-5 ) then
- write(*,*)' ERROR no massconserv in downdraft'
- stop
- endif
- !!pentug = 0.0
- !!pdetug = 0.0
- !!pentdg = 0.0
- !!pdetdg = 0.0
- end subroutine subscal
- ! =================================================
-
- !***********************************************************************
- !**** cloud - routine to calculate cloud properties
- !
- ! m.heimann mpi HH Nov-12-1990
- !
- ! Purpose
- ! -------
- ! cloud calculates all properties associated with subgridscale
- ! cloud mixing, i.e. massflux in updraft and downdraft, entrainment
- ! and detrainment rates per level, and cloud properties: temperature,
- ! moisture and liquid water and precipitation rate on each level
- ! boundary.
- !
- !** interface
- ! ---------
- !
- ! call cloud(pz,ppress,pt,pq,pw,pqac,pqam,
- ! . pqtur,pamu,ptc,pqc,plc,pgp,
- ! . pam,peu,pdu,ped,pdd,
- ! . klc,klt)
- !
- ! input: (all variables are defined on level boundaries)
- ! pz geopotential height (m)
- ! ppress pressure (Pa)
- ! pt temperature (K)
- ! pq moisture (kg water/kg air)
- ! pw vertcal velocity (negative upward) (Pa s**-1)
- ! pqac div(q v) (kg water/kg air s**-1)
- ! pqam div(v) (s**-1)
- ! pqtur Fq surf-air (kg water/m**2 s**-1)
- !
- ! output: variables defined on level boundaries:
- ! pamu massflux (kg m**-2 s**-1)
- ! ptc updraft temperature (K)
- ! pqc updraft moisture (kg water/kg air)
- ! plc updraft liquid water (kg water/kg air)
- ! pgp updraft precipitation (kg water m**-2 s**-1)
- !
- ! variables defined on each model level:
- ! pam air mass (kg m**-2)
- ! peu entrainment in updraft (kg m**-2 s**-1)
- ! pdu detrainment in updraft (same)
- ! ped entrainment in downdraft (kg m**-2 s**-1)
- ! pdd detrainment in downdraft (same)
- ! klc lowest level in cloud
- ! klt first level above cloud
- !
- ! method
- ! ------
- !
- ! updraft cloud properties are calculated according to Tiedke scheme
- !
- ! externals
- ! ---------
- !
- ! needs functions qsat and dqsat_dt
- !
- ! references
- ! ----------
- !
- ! Tiedke, Mon. Wea. Rev., 117, 1779-1800, 1989.
- !
- ! revisions
- ! ---------
- ! 26-jan-1995 , sr
- !
- ! including now cumulus downdraft and midlevel convection.
- ! Calculates corresponding entrainment and detrainment rates
- !
- !-------------------------------------------------------------------------
- subroutine cloud(lme, pz,ppress,pt,pq,pw,pqac,pqam, pqtur,&
- pamu,ptc,pqc,plc,pgp, &
- pam,peu,pdu,ped,pdd)
-
- use phys_humidity, only : QSat, dQSat_dt
- ! --- flags -----------------------------------------
- ! parameter llcudo=.true. : cumulus downdraft turned on
- ! parameter llcudo=.false. : cumulus downdraft turned off
- ! parameter llmilc=.true. : midlevel convection turned on
- ! parameter llmilc=.false. : midlevel convection turned off
- logical :: llcudo = .true.
- logical :: llmilc = .true.
- ! --- const (dims) -------------------------------------
-
- !! vertical resolution (no of model layers)
- !integer :: jplm = lme
- !integer :: jplmm1 = jplm-1
- ! --- in/out ----------------------------------------
- integer, intent(in) :: lme
- real, intent(in) :: pz(0:lme)
- real, intent(in) :: pt(0:lme)
- real, intent(in) :: pq(0:lme)
- real, intent(in) :: pw(0:lme)
- real, intent(in) :: ppress(0:lme)
- real, intent(in) :: pqac(0:lme),pqam(0:lme)
- real, intent(in) :: pqtur
- real, intent(out) :: pam(lme),peu(lme),pdu(lme),ped(lme),pdd(lme)
- real, intent(out) :: pamu(0:lme),ptc(0:lme),pqc(0:lme),plc(0:lme),pgp(0:lme)
-
- ! --- const (phys) -------------------------------------
- ! physical constants
- real, parameter :: pprgasd = 287.05
- real, parameter :: pprgasv = 461.51
- real, parameter :: ppeps = pprgasd/pprgasv
- real, parameter :: ppg = 9.80665
- real, parameter :: ppcpd = 1005.46
- real, parameter :: ppalv = 2.5008e6
- real, parameter :: ppzeta = ppalv/ppcpd
- real, parameter :: ppvtcf = (1.0-ppeps)/ppeps
- ! * constants for turbulent entrainment and detrainment rates
- ! penetrative and midlevel convection
- real, parameter :: ppepsu = 1.e-4
- real, parameter :: ppdeltu = 1.e-4
- ! shallow convection
- real, parameter :: ppepsus = 3.e-4
- real, parameter :: ppdeltus = 3.e-4
- ! downdraft
- real, parameter :: ppepsd = 2.e-4
- real, parameter :: ppdeltd = 2.e-4
- ! * constants for precipitation parametrization
- real, parameter :: ppkmin = 1500.0
- real, parameter :: ppkval = 2.e-3
- ! * parameter beta determines the overshoot of the detrainment plumes
- ! above level of no buoyancy (beta=0 : no overshoot)
- ! penetrative and midlevel convection
- real, parameter :: ppbeta = 0.0
- ! shallow convection
- real, parameter :: ppbetas = 0.15
- ! * parameter gamma determines downward massflux at the level of free
- ! sinking (LFS)
- real, parameter :: ppgamma = 0.3
- ! parameter alpha determines specific humidity of air parcel at surface
- ! before starting the dry adiabatic ascent
- ! (alpha = 0 : air parcel has the specific humidity of the environment,
- ! alpha = 1 : air parcel has saturation specific humidity of the
- ! environment)
- real, parameter :: ppalpha = 0.2
- ! no of iterations for saturation calculation
- integer, parameter :: jpitermax = 5
-
- ! --- local --------------------------------------
- integer :: klc,klt,klfs
- real :: zfck,zamub,zamdlfs
- real :: zamu,zamd
- real :: zlc,zqc,ztc
- real :: zlcklc,zqcklc,ztcklc
- real :: ztd,zqd
-
- real :: zdq1,zdq2,zsv,zscv,zgp
- real :: zpgp(lme)
- real :: zepsu,zdeltu
- real :: zbeta
- integer :: jl,jjl,jiter
- integer :: imlc
- real :: zdqcmin,zdqdmin
- real :: ztenwb,zqenwb
- real :: zttest,zqtest,zstv
- ! extra
- character(len=10) :: convection_type
-
- ! --- begin ----------------------------------------------
- convection_type = 'none'
- ! default cloud properties on each layer boundary
- do jl = 0, lme
- pamu(jl) = 0.0
- ptc(jl) = pt(jl)
- pqc(jl) = pq(jl)
- plc(jl) = 0.0
- pgp(jl) = 0.0
- end do
- ! air-masses (kg/m**2) in each layer, default entrainment/detrainment
- ! and precipitation rates
- do jl = 1, lme
- pam(jl)=(ppress(jl)-ppress(jl-1))/ppg
- peu(jl)=0.
- pdu(jl)=0.
- ped(jl)=0.
- pdd(jl)=0.
- zpgp(jl)=0.
- end do
- ! find condensation level by lifting an air parcel until supersaturation occurs
- ! we start the ascent with moisture and temperature of the upper boundary of
- ! the surface layer
- ztc = pt(lme-1)
- zqc = pq(lme-1) + ppalpha * ( qsat(pt(lme-1),ppress(lme-1)) - pq(lme-1) )
- do jl = lme-1-1, 1, -1
- ! preliminary value of parcel temperature (dry adiabatic ascent)
- ztc = ztc - ppg*(pz(jl)-pz(jl+1))/ppcpd
- ! check for supersaturation
- if ( zqc > qsat(ztc,ppress(jl)) ) then
- ! if supersaturation is detected we adjust moisture and
- ! temperature by condensation
- ! and set liquid water content equal to the condensate
- zdq2 = 0.0
- do jiter=1,jpitermax
- zdq1=(zqc-QSat(ztc,ppress(jl))) &
- /(1.+ppzeta*dQSat_dt(ztc,ppress(jl)))
- zqc=zqc-zdq1
- ztc=ztc+zdq1*ppzeta
- zdq2=zdq2+zdq1
- end do
- zlc = zdq2
- ! check if parcel is buoyant:
- ! virtual temperature of parcel
- zscv = ztc*( 1.0 + ppvtcf*zqc - zlc )
- ! virtual temperature of environment
- zsv = pt(jl) * ( 1.0 + ppvtcf*pq(jl) )
- if ( zscv > zsv ) then
- ! if parcel is still buoyant then we have detected the cloud base
- klc=jl
- goto 20
- else
- ! if parcel is not buoyant then there is no penetrative or shallow
- ! convection
- if (llmilc) then
- goto 700
- else
- goto 3000
- endif
- endif
-
- endif
- end do
- ! no condensation level found
- goto 3000
- 20 continue
- ! if we arrive here a cloud base is detected:
- ! klc is cloud base level, ztc is cloud temperature, zqc moisture (at
- ! saturation)
- ! and zlc the liquid water content in the updraft at base level
- ztcklc = ztc
- zqcklc = zqc
- zlcklc = zlc
- ! calculate large scale moisture convergence below cloud base
- ! (use trapezoidal integration formula)
- !zfck=
- ! ((pq(klc)*pqam(klc)-pqac(klc))*pam(klc)+
- ! Correction Zoe Stockwell - Peter van Velthoven, 5 January 2000 &
- zfck = ((pq(klc)*pqam(klc) -pqac(klc) )*pam(klc+1)+ &
- (pq(klc)*pqam(lme)-pqac(lme))*pam(lme) )
- do jl=klc+1,lme-1
- zfck=zfck+(pq(klc)*pqam(jl)-pqac(jl))*(pam(jl)+pam(jl+1))
- end do
- ! check for shallow or penetrative convection, set proper parameter
- ! values
- if (zfck.gt.0.) then
- ! penetrative and midlevel convection
- zepsu=ppepsu
- zdeltu=ppdeltu
- zbeta=ppbeta
- convection_type = 'deep'
- else
- ! shallow convection
- zepsu=ppepsus
- zdeltu=ppdeltus
- zbeta=ppbetas
- convection_type = 'shallow'
- endif
- zfck=pqtur+0.5*zfck
- ! if no moisture convergence then no penetrative or shallow
- ! convection is present
- if (zfck <= 0.0 ) then
- if (llmilc) then
- goto 700
- else
- goto 3000
- endif
- else
- goto 900
- endif
- 700 continue
- ! check possibility for midlevel convection
- imlc = 0
- ! Check atmosphere from 2 layers above the surface to the middle of
- ! the atmosphere to see if midlevel convection might occur
- do jl=lme-1-1,lme-int(lme/2.),-1
- ! large scale ascent and an environmental relative humidity of more than
- ! 90% are needed for midlevel convection to occur
- if ( (pq(jl).gt.(0.9*qsat(pt(jl),ppress(jl))) ).and. &
- (pw(jl).lt.0.)) then
- if (imlc.eq.0) then
- ztc = pt(jl+1)
- zqc = pq(jl+1)
- zlc = 0.
- imlc = jl
- else if (imlc.gt.0) then
- if ((imlc-jl).eq.1) then
- imlc = jl
- goto 720
- else
- ztc = pt(jl+1)
- zqc = pq(jl+1)
- zlc = 0.
- imlc = jl
- end if
- end if
- 720 continue
- ! do adiabatic ascent
- ztc = ztc - ppg*(pz(jl)-pz(jl+1))/ppcpd
- ! check for supersaturation
- if (zqc.gt.qsat(ztc,ppress(jl))) then
-
- ! if supersaturation is detected we adjust moisture and
- ! temperature by condensation
- ! and set liquid water content equal to the condensate
- zdq2=0.
- do jiter=1,jpitermax
- zdq1 = (zqc-qsat(ztc,ppress(jl)))/(1.+ppzeta*dqsat_dt(ztc,ppress(jl)))
- zqc=zqc-zdq1
- ztc=ztc+zdq1*ppzeta
- zdq2=zdq2+zdq1
- end do
- zlc=zdq2
- endif
- ! check if parcel is buoyant
- ! virtual temperature of parcel
- zscv = ztc*(1.+ppvtcf*zqc-zlc)
- ! virtual temperature of environment
- zsv = pt(jl)*(1.+ppvtcf*pq(jl))
- if (zscv.gt.zsv) then
- ! parcel is buoyant and we have detected the cloud base of midlevel
- ! convection
- klc = jl
- zamub = -pw(klc)/ppg
- zepsu = ppepsu
- zdeltu = ppdeltu
- zbeta = ppbeta
- llcudo = .false.
- convection_type = 'mid-level'
- goto 1000
- endif
- endif
- end do
-
- goto 3000
- 900 continue
- ! massflux at base of cloud
- ! limit specific humidity difference between cloud and environment at
- ! cloud base
- zdqcmin = max(0.01*pq(klc),1.e-10)
- zdqcmin = max(zdqcmin,zqc+zlc-pq(klc))
- zamub=zfck/zdqcmin
- 1000 continue
- ! limit mass flux at cloud base
- zamub=min(zamub,1.0)
- ! set updraft entrainment rates below cloud base proportional
- ! to layer air masses
- ! set updraft detrainment rates below cloud base to zero
- do jl=lme,klc+1,-1
- peu(jl) = zamub*pam(jl)*ppg/(ppress(lme)-ppress(klc))
- pdu(jl) = 0.0
- end do
- ! calculate now parcel ascent within cloud updraft
- ! cloud mass flux zamu,
- ! cloud moisture zqc,
- ! cloud temperature ztc,
- ! cloud liquid water zlc
- zamu = zamub
- do jl = klc,2,-1
- ! mass entrainment and detrainment
- peu(jl)=zepsu*zamu*(pz(jl-1)-pz(jl))
- pdu(jl)=zdeltu*zamu*(pz(jl-1)-pz(jl))
-
- ! preliminary values of cloud temperature, moisture and cloud liquid water
- ztc=ztc &
- -ppg*(pz(jl-1)-pz(jl))/ppcpd &
- +zepsu*(pz(jl-1)-pz(jl))*(pt(jl)-ztc)
- zqc=zqc &
- +zepsu*(pz(jl-1)-pz(jl))*(pq(jl)-zqc)
- zlc=zlc &
- +zepsu*(pz(jl-1)-pz(jl))*(-zlc)
- ! adjust moisture and temperature by condensation
- zdq2=0.
- do jiter=1,jpitermax
- zdq1=(zqc-qsat(ztc,ppress(jl))) &
- /(1.+ppzeta*dqsat_dt(ztc,ppress(jl)))
- zqc=zqc-zdq1
- ztc=ztc+zdq1*ppzeta
- zdq2=zdq2+zdq1
- end do
- ! precipitation rate out of layer jl
- if ((pz(jl)+pz(jl-1))*0.5-pz(klc) .gt. ppkmin) then
- zgp=pam(jl)*ppkval/zamu
- else
- zgp=0.
- endif
-
- ! adjust liquid cloud water in updraft (use implicit scheme to prevent
- ! instability)
- zgp = zgp*zlc/(1+zgp)
-
- zpgp(jl) = zgp*zamu
-
- zlc = zlc-zgp+zdq2
- ! check for level of free sinking (LFS) where cumulus downdraft starts
- if (.not.llcudo) then
-
- ! downdraft calculation already done or turned off
-
- goto 800
- end if
- if ( zpgp(jl) == 0.0 ) then
-
- ! no downdraft exists since downdrafts are associated with convective
- ! precipitation from the updrafts
-
- goto 800
- end if
- if (jl.lt.3) then
- ! no downdraft since maximum possible cloud height is reached
- goto 800
- end if
- ! The LFS is assumed to be the highest model level where a mixture of equal
- ! parts of cloud air and environmental air (at wet bulb temperature) becomes
- ! negative buoyant with respect to the environmental air
- ! first step :
- ! calculate wet bulb temperature and moisture of the environmental air
- ztenwb = pt(jl-1)
- zqenwb = pq(jl-1)
- ! adjust temperature and moisture by evaporation
- ! zdq1 must be less equal 0 (zdq1=0 : environmental air is saturated,
- ! i.e. zqenwb = pq)
- do jiter = 1,jpitermax
- zdq1 = (zqenwb-qsat(ztenwb,ppress(jl-1)))/ &
- (1.+ppzeta*dqsat_dt(ztenwb,ppress(jl-1)))
- zqenwb = zqenwb-zdq1
- ztenwb = ztenwb+zdq1*ppzeta
- end do
- ! second step :
- ! do mixing with cloud air
- zttest = 0.5*(ztc+ztenwb)
- zqtest = 0.5*(zqc+zqenwb)
- ! third step :
- ! check for negative buoyancy
- ! virtual temperature of the air mixture
- zstv = zttest*(1.+ppvtcf*zqtest)
- ! virtual temperature of the environmental air
- zsv = pt(jl-1)*(1.+ppvtcf*pq(jl-1))
- if (zstv.lt.zsv) then
- ! level of free sinking (LFS) is found, start downdraft calculation
- ! massflux at LFS is assumed to be directly proportional to the (preliminary)
- ! upward massflux at cloud base
- klfs = jl
- zamdlfs = -ppgamma*zamub
- zamd = zamdlfs
- ztd = zttest
- zqd = zqtest
- ped(klfs) = (-zamd)
- pdd(klfs) = 0.
- if (klfs.eq.klc) goto 45
- do jjl = klfs+1,klc,1
- ! mass entrainment and detrainment
- ped(jjl) = ppepsd*zamd*(pz(jjl)-pz(jjl-1))
- pdd(jjl) = ppdeltd*zamd*(pz(jjl)-pz(jjl-1))
- ! preliminary values of cloud temperature and moisture in downdraft
- ztd = ztd &
- -ppg*(pz(jjl)-pz(jjl-1))/ppcpd &
- +ppepsd*(pz(jjl)-pz(jjl-1))*(ztd-pt(jjl-1))
- zqd = zqd &
- +ppepsd*(pz(jjl)-pz(jjl-1))*(zqd-pq(jjl-1))
- ! adjust moisture and temperature by evaporation
- do jiter=1,jpitermax
- zdq1 = (zqd-qsat(ztd,ppress(jjl-1)))/ &
- (1.+ppzeta*dqsat_dt(ztd,ppress(jjl-1)))
- zqd = zqd-zdq1
- ztd = ztd+zdq1*ppzeta
- end do
- ! downdraft massflux at lower layer boundary
- zamd = zamd - ped(jjl) + pdd(jjl)
- end do
- 45 continue
- zamd = min(0.,zamd)
- ! set downdraft detrainment rates below cloud base proportional to layer
- ! air masses
- ! set downdraft entrainment rates below cloud base to zero
- do jjl = lme,klc+1,-1
- ped(jjl) = 0.
- pdd(jjl) = zamd*pam(jjl)*ppg/(ppress(klc)-ppress(lme))
- end do
- ! recalculate updraft massflux at cloud base,
- ! now allowing for the downdraft massflux
- if (zamd.lt.0.) then
- zdqdmin = zqd-pq(klc)
- zamub = (zfck-zamd*zdqdmin)/zdqcmin
- if (zamub.le.0.) then
- do jjl=1,lme
- peu(jjl)=0.
- pdu(jjl)=0.
- ped(jjl)=0.
- pdd(jjl)=0.
- end do
- goto 3000
- endif
- ! go back to cloud base and start updraft calculation again
- ztc = ztcklc
- zqc = zqcklc
- zlc = zlcklc
- llcudo = .false.
- goto 1000
- else
- goto 800
- endif
- else
- goto 800
- endif
- 800 continue
- ! check for buoyancy (in updraft)
- ! virtual temperature in updraft at upper boundary of layer jl:
- zscv=ztc*(1.+ppvtcf*zqc-zlc)
- ! virtual temperature outside of cloud
- zsv=pt(jl-1)*(1.+ppvtcf*pq(jl-1))
- if ( zscv <= zsv ) then
- klt=jl
- goto 400
- endif
- ! updraft massflux at upper layer boundary
- zamu=zamu+peu(jl)-pdu(jl)
- ! store cloud properties on upper layer boundary
- ptc(jl-1)=ztc
- pqc(jl-1)=zqc
- plc(jl-1)=zlc
-
- end do
- klt=2
- 400 continue
- ! set detrainment in two layers above cloud
- pdu(klt-1)=zbeta*zamu
- peu(klt-1)=0.
- pdu(klt)=(1-zbeta)*zamu
- peu(klt)=0.
- ! add up rainrate on each of the layer boundaries
- do jl=klt+1,lme
- pgp(jl)=pgp(jl-1)+zpgp(jl)
- end do
- ! determine net mass flux on each of the layer boundaries
- do jl=lme,1,-1
- pamu(jl-1)=pamu(jl)+(peu(jl)-pdu(jl))-(ped(jl)-pdd(jl))
- end do
- llcudo = .true.
- llmilc = .true.
- return
- ! no cloud present, set cloud base and top to 0 and return
- 3000 continue
- klc=0
- klt=0
- llcudo = .true.
- llmilc = .true.
- convection_type = 'none'
- end subroutine cloud
- ! ==========================================================
- ! ===
- ! === TMPP/SOURCE/tmpp_sub_work.f90
- ! ===
- ! ==========================================================
-
- !---------------------------------------------------------------------
- ! calculate en/detrainment rates and diffusion coefficient on TM grid
- !---------------------------------------------------------------------
- ! History:
- ! Increased vertical dimension of z,t,q,u,v,w from lme to lme + 1
- ! in order to be able to use the same memory location in worksub
- ! for u and wu, for t and wt, etc.
- ! Added subroutine cen2bound for the same reason
- ! Removed dummy fields for geopotential height and zonal means
- ! Program just fits into memory of SGI machines (max stacksize = 524288) if
- ! TM and ECMWF both have 1x1 degree resolution and 60 levels
- ! pvv, 5-2-2000
- !---------------------------------------------------------------------
- ! =========================================================
-
- ! interpolate variables from the center of parent-model layers to the
- ! boundaries of parent-model layers and save result in same memory location
-
- subroutine mid2bound_uv( lme, npe, u, v, ps, mask, a, b )
-
- ! --- in/out ----------------------------------
-
- integer, intent(in) :: lme, npe
- real, intent(inout) :: u(npe,0:lme)
- real, intent(inout) :: v(npe,0:lme)
- real, intent(in) :: ps(npe)
- logical, intent(in) :: mask(npe)
- real, intent(in) :: a(0:lme)
- real, intent(in) :: b(0:lme)
-
- ! --- local ---------------------------------
-
- integer :: i
- real :: wcol(0:lme)
-
- ! --- begin -------------------------
-
- do i = 1, npe
- if ( mask(i) ) then
- call cen2bound_col( lme, u(i,1:lme), ps(i), 1, wcol, a, b )
- u(i,:) = wcol
- call cen2bound_col( lme, v(i,1:lme), ps(i), 1, wcol, a, b )
- v(i,:) = wcol
- end if
- end do
-
- end subroutine mid2bound_uv
-
-
- ! ===
-
-
- subroutine mid2bound_w( lme, npe, w, ps, mask, a, b )
-
- ! --- in/out ----------------------------------
-
- integer, intent(in) :: lme, npe
- real, intent(inout) :: w(npe,0:lme)
- real, intent(in) :: ps(npe)
- logical, intent(in) :: mask(npe)
- real, intent(in) :: a(0:lme)
- real, intent(in) :: b(0:lme)
-
- ! --- local ---------------------------------
-
- integer :: i
- real :: wcol(0:lme)
-
- ! --- begin -------------------------
-
- do i = 1, npe
- if ( mask(i) ) then
- call cen2bound_col( lme, w(i,1:lme), ps(i), 1, wcol, a, b )
- w(i,:) = wcol
- ! set to zero at top
- w(i,0) = 0.0
- end if
- end do
-
- end subroutine mid2bound_w
-
-
- ! ===
-
-
- subroutine mid2bound_t( lme, npe, t, ps, mask, a, b )
-
- ! --- in/out ----------------------------------
-
- integer, intent(in) :: lme, npe
- real, intent(inout) :: t(npe,0:lme)
- real, intent(in) :: ps(npe)
- logical, intent(in) :: mask(npe)
- real, intent(in) :: a(0:lme)
- real, intent(in) :: b(0:lme)
-
- ! --- local ---------------------------------
-
- integer :: i
- real :: wcol(0:lme)
-
- ! --- begin -------------------------
-
- do i = 1, npe
- if ( mask(i) ) then
- call cen2bound_col( lme, t(i,1:lme), ps(i), 1, wcol, a, b )
- t(i,:) = wcol
- end if
- end do
-
- end subroutine mid2bound_t
-
-
- ! ===
-
-
- subroutine mid2bound_q( lme, npe, q, ps, mask, a, b, t )
-
- use phys_humidity, only : qsat
-
- ! --- in/out ----------------------------------
-
- integer, intent(in) :: lme, npe
- real, intent(inout) :: q(npe,0:lme)
- real, intent(in) :: ps(npe)
- logical, intent(in) :: mask(npe)
- real, intent(in) :: a(0:lme)
- real, intent(in) :: b(0:lme)
- real, intent(in) :: t(npe,0:lme)
-
- ! --- local ---------------------------------
-
- integer :: i, l
- real :: wcol(0:lme)
- real :: tmpress(0:lme)
-
- ! --- begin -------------------------
-
- do i = 1, npe
- if ( mask(i) ) then
- call cen2bound_col( lme, q(i,1:lme), ps(i), 1, wcol, a, b )
- q(i,:) = wcol
- ! limit specific humidity at 0 and qsat(t,p)
- ! first establish hybrid vertical coordinate at i,j ;
- ! note that ps is expressed in Pa
- do l = 0, lme
- tmpress(l) = a(l) + ps(i)*b(l)
- end do
- do l = 0, lme
- q(i,l) = min( qsat(t(i,l),tmpress(l)), max(0.0,q(i,l)) )
- end do
- end if
- end do
-
- end subroutine mid2bound_q
-
-
- ! ===
-
-
- subroutine mid2bound_z( lme, npe, z, ps, mask, a, b, zsurf )
-
- use Binas, only : g => grav
- ! --- in/out ----------------------------------
-
- integer, intent(in) :: lme, npe
- real, intent(inout) :: z(npe,0:lme)
- real, intent(in) :: ps(npe)
- logical, intent(in) :: mask(npe)
- real, intent(in) :: a(0:lme)
- real, intent(in) :: b(0:lme)
- real, intent(in) :: zsurf(npe)
-
- ! --- local ---------------------------------
-
- integer :: i
- real :: wcol(0:lme)
- ! --- begin -------------------------
-
- do i = 1, npe
- if ( mask(i) ) then
- call cen2bound_col( lme, z(i,1:lme), ps(i), 1, wcol, a, b )
- z(i,:) = wcol
- ! set to known value at surface:
- z(i,lme) = zsurf(i)/g
- end if
- end do
-
- end subroutine mid2bound_z
-
-
- ! ===
-
-
- subroutine mid2bound_p( lme, npe, p, ps, mask, a, b )
-
- ! --- in/out ----------------------------------
-
- integer, intent(in) :: lme, npe
- real, intent(inout) :: p(npe,0:lme)
- real, intent(in) :: ps(npe)
- logical, intent(in) :: mask(npe)
- real, intent(in) :: a(0:lme)
- real, intent(in) :: b(0:lme)
-
- ! --- local ---------------------------------
-
- integer :: i, j
- real :: wcol(0:lme)
-
- ! --- begin -------------------------
-
- do i = 1, npe
- if ( mask(i) ) then
- call cen2bound_col( lme, p(i,:), ps(i), 0, wcol, a, b )
- p(i,:) = wcol
- end if
- end do
-
- end subroutine mid2bound_p
-
-
- ! interpolate from mid-levels of parent model to
- ! level boundaries
- !
- ! Peter van Velthoven - 4 January 2000
- ! This subroutine is included to save memory
- ! field and field2 use the same space in memory
- !
- ! iopt = 0 : no field as input : fill wfield with pressure
- ! iopt = other: use field as input
- !
- subroutine cen2bound_col( lme, field, ps, iopt, wfield, a, b )
- use Num, only : interp_muherm
- ! --- in/out -------------------------------
- integer, intent(in) :: lme
- real, intent(in) :: field(lme) ! input on (mid-)levels
- real, intent(in) :: ps ! surface pressure
- integer, intent(in) :: iopt
- real, intent(out) :: wfield(0:lme) ! output on vertical level boundaries
- real, intent(in) :: a(0:lme)
- real, intent(in) :: b(0:lme)
-
- ! --- begin -------------------------------
- integer :: status
- real :: ztemp(lme)
- real :: tmpress(0:lme) ! pressure at ECMWF vertical level boundaries
- real :: tcmpress(lme) ! pressure at ECMWF (mid-)levels
- integer :: l
-
- ! --- begin --------------------------------
- ! establish hybrid vertical coordinate at i,j
- ! note that ps is expressed in Pa
- tmpress = a + ps * b
- ! calculate pressure at model layer center
- do l=1,lme
- tcmpress(l) = (tmpress(l-1)+tmpress(l))/2.
- end do
- if ( iopt == 0 ) then
- wfield = tmpress
- else
- call interp_muherm( tcmpress, field, tmpress, wfield, status )
- if (status/=0) stop 'ERROR in cen2bound_col'
- end if
- end subroutine cen2bound_col
-
-
-
- ! ==========================================================
- ! ===
- ! === TMPP/SOURCE/tmpp_geometry.f90
- ! ===
- ! ==========================================================
-
- ! pressure at half leves from bottom to top
-
- subroutine phlev_ec_rev( lme, a_ec, b_ec, ps, pb )
-
- ! --- in/out --------------------------
-
- integer, intent(in) :: lme
- real, intent(in) :: a_ec(0:lme)
- real, intent(in) :: b_ec(0:lme)
- real, intent(in) :: ps
- real, intent(out) :: pb(0:lme)
-
- ! --- local --------------------------
-
- integer :: l
-
- ! --- in/out -------------------------
-
- do l = 0, lme
- pb(lme-l) = a_ec(l) + b_ec(l) * ps
- end do
-
- end subroutine phlev_ec_rev
-
-
- ! ==========================================================
- ! ===
- ! === TMPP/SOURCE/phys_geopot.f90
- ! ===
- ! ==========================================================
-
- !
- ! NAME
- ! GeoPot_col - calculate geopotential height
- !
- ! DESCRIPTION
- ! Calculate geopotential height from halflevel pressures
- ! and full level virtual temperature.
- !
- ! USAGE
- !
- ! call GeoPot( z, zsurf, pt, pq, pb, lm )
- !
- ! integer, intent(in) :: lm ! number of levels
- !
- ! (levels numbered downwards (top -> down) )
- !
- ! real, intent(out) :: z(lm) ! geopotential height (m ?).
- ! real, intent(in) :: zsurf ! orography (m ?)
- ! real, intent(in) :: pt(lm) ! temperature (K ?)
- ! real, intent(in) :: pq(lm) ! specific humidity (??)
- !
- ! (levels numbered upwards (bottom -> up) )
- !
- ! real, intent(in) :: pb(0:lm) ! pressure at half levels
- !
- ! HISTORY
- !
- ! 06-11-2001, Arjo Segers
- ! Extracted from original routines 'geopot' and 'auxhyb'
- ! by Ad Jeuken
- !
- subroutine GeoPot( lm, zsurf, pt, pq, pb, z )
- ! --- in/out -------------------------
- integer, intent(in) :: lm
- real, intent(out) :: z(lm)
- real, intent(in) :: zsurf
- real, intent(in) :: pt(lm)
- real, intent(in) :: pq(lm)
- real, intent(in) :: pb(0:lm)
- ! --- const ------------------------
- real, parameter :: rd = 287.05
- real, parameter :: g0 = 9.801
- ! --- local ------------------------------
- integer :: linv
- real :: pdelp, prdelp
- real :: palfa(lm)
- real :: plnr(lm)
- real :: tv(lm)
- integer :: l, lp1
- ! --- begin ---------------------------------
-
- ! >>> former routine 'auxhyb' >>>>>>>>>>>>>>>>>>>>>>
- ! loop from top to bottom:
- do l = 1, lm
- linv = lm - l ! lm-1, 0
- pdelp = pb(linv) - pb(linv+1)
- prdelp = 1.0 / pdelp
- if ( l == 1 ) then
- plnr(l) = rd * 1.3862944
- else
- plnr(l) = rd * log( pb(linv)/pb(linv+1) )
- end if
- palfa(l) = rd - pb(linv+1) * plnr(l) * prdelp
- end do
- ! <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
- ! loop from bottom to top:
- do l = lm, 1, -1
- tv(l) = pt(l) * ( 1.0 + 0.608*pq(l) )
- if ( l == lm ) then
- z(l) = palfa(l)*tv(l)/g0 + zsurf/g0
- else
- lp1=l+1
- z(l) = z(lp1) + ( palfa(l)*tv(l) + (plnr(lp1)-palfa(lp1))*tv(lp1) )/g0
- end if
- end do
- end subroutine GeoPot
- end module phys_convec_tmpp
|