MODULE rocketduststorm_mod IMPLICIT NONE REAL, SAVE, ALLOCATABLE :: dustliftday(:) ! dust lifting rate (s-1) !$OMP THREADPRIVATE(dustliftday) CONTAINS !======================================================================= ! ROCKET DUST STORM - vertical transport and detrainment !======================================================================= ! calculation of the vertical flux ! call of van_leer : Van Leer transport scheme of the dust tracers ! detrainement of stormdust in the background dust ! ----------------------------------------------------------------------- ! Authors: M. Vals; C. Wang; F. Forget; T. Bertrand ! Institution: Laboratoire de Meteorologie Dynamique (LMD) Paris, France ! ----------------------------------------------------------------------- SUBROUTINE rocketduststorm(ngrid,nlayer,nq,ptime,ptimestep, & pq,pdqfi,pt,pdtfi,pplev,pplay,pzlev, & pzlay,pdtsw,pdtlw, & ! input for radiative transfer clearatm,icount,zday,zls, & tsurf,igout,totstormfract, & tauscaling,dust_rad_adjust, & IRtoVIScoef, & ! input sub-grid scale cloud clearsky,totcloudfrac, & ! input sub-grid scale topography nohmons, & ! output pdqrds,wrad,dsodust,dsords,dsotop, & tau_pref_scenario,tau_pref_gcm) USE tracer_mod, only: igcm_stormdust_mass,igcm_stormdust_number & ,igcm_dust_mass,igcm_dust_number & ,rho_dust USE comcstfi_h, only: r,g,cpp,rcp USE dimradmars_mod, only: albedo,naerkind USE comsaison_h, only: dist_sol,mu0,fract USE surfdat_h, only: emis,co2ice,zmea, zstd, zsig, hmons USE callradite_mod, only: callradite IMPLICIT NONE include "callkeys.h" !-------------------------------------------------------- ! Input Variables !-------------------------------------------------------- INTEGER, INTENT(IN) :: ngrid ! number of horizontal grid points INTEGER, INTENT(IN) :: nlayer ! number of vertical grid points INTEGER, INTENT(IN) :: nq ! number of tracer species REAL, INTENT(IN) :: ptime REAL, INTENT(IN) :: ptimestep REAL, INTENT(IN) :: pq(ngrid,nlayer,nq) ! advected field nq REAL, INTENT(IN) :: pdqfi(ngrid,nlayer,nq)! tendancy field pq REAL, INTENT(IN) :: pt(ngrid,nlayer) ! temperature at mid-layer (K) REAL, INTENT(IN) :: pdtfi(ngrid,nlayer) ! tendancy temperature at mid-layer (K) REAL, INTENT(IN) :: pplay(ngrid,nlayer) ! pressure at middle of the layers REAL, INTENT(IN) :: pplev(ngrid,nlayer+1) ! pressure at intermediate levels REAL, INTENT(IN) :: pzlay(ngrid,nlayer) ! altitude at the middle of the layers REAL, INTENT(IN) :: pzlev(ngrid,nlayer+1) ! altitude at layer boundaries REAL, INTENT(IN) :: pdtsw(ngrid,nlayer) ! (K/s) env REAL, INTENT(IN) :: pdtlw(ngrid,nlayer) ! (K/s) env ! input for second radiative transfer LOGICAL, INTENT(IN) :: clearatm INTEGER, INTENT(INOUT) :: icount REAL, INTENT(IN) :: zday REAL, INTENT(IN) :: zls REAL, INTENT(IN) :: tsurf(ngrid) INTEGER, INTENT(IN) :: igout REAL, INTENT(IN) :: totstormfract(ngrid) REAL, INTENT(INOUT) :: tauscaling(ngrid) REAL,INTENT(INOUT) :: dust_rad_adjust(ngrid) REAL,INTENT(INOUT) :: IRtoVIScoef(ngrid) ! NB: not modified by this call to callradite, ! the OUT is just here because callradite needs it ! subgrid scale water ice clouds logical, intent(in) :: clearsky real, intent(in) :: totcloudfrac(ngrid) ! subgrid scale topography LOGICAL, INTENT(IN) :: nohmons !-------------------------------------------------------- ! Output Variables !-------------------------------------------------------- REAL, INTENT(OUT) :: pdqrds(ngrid,nlayer,nq) ! tendancy field for dust when detraining REAL, INTENT(OUT) :: wrad(ngrid,nlayer+1) ! vertical speed within the rocket dust storm REAL, INTENT(OUT) :: dsodust(ngrid,nlayer) ! density scaled opacity of env. dust REAL, INTENT(OUT) :: dsords(ngrid,nlayer) ! density scaled opacity of storm dust REAL, INTENT(OUT) :: dsotop(ngrid,nlayer) ! density scaled opacity of topmons dust REAL,INTENT(OUT) :: tau_pref_scenario(ngrid) ! prescribed dust column ! visible opacity at odpref REAL,INTENT(OUT) :: tau_pref_gcm(ngrid) ! dust column visible opacity at ! odpref in the GCM !-------------------------------------------------------- ! Local variables !-------------------------------------------------------- INTEGER l,ig,iq,ll ! local variables from callradite.F REAL zdtlw1(ngrid,nlayer) ! (K/s) storm REAL zdtsw1(ngrid,nlayer) ! (K/s) storm REAL zt(ngrid,nlayer) ! actual temperature at mid-layer (K) REAL zdtvert(ngrid,nlayer) ! dT/dz , lapse rate REAL ztlev(ngrid,nlayer) ! temperature at intermediate levels l+1/2 without last level REAL zdtlw1_lev(nlayer),zdtsw1_lev(nlayer) ! rad. heating rate at intermediate levels l+1/2 for stormdust REAL zdtlw_lev(nlayer),zdtsw_lev(nlayer) ! rad. heating rate at intermediate levels l+1/2 for background dust REAL zq_stormdust_mass(ngrid,nlayer) ! intermediate tracer stormdust mass REAL zq_stormdust_number(ngrid,nlayer) ! intermediate tracer stormdust number REAL zq_dust_mass(ngrid,nlayer) ! intermediate tracer dust mass REAL zq_dust_number(ngrid,nlayer) ! intermediate tracer dust number REAL mr_stormdust_mass(ngrid,nlayer) ! intermediate mixing ratio to calculate van leer transport with the "real" concentration (stormdust mass) REAL mr_stormdust_number(ngrid,nlayer) ! intermediate mixing ratio to calculate van leer transport with the "real" concentration (stormdust number) REAL mr_dust_mass(ngrid,nlayer) ! intermediate mixing ratio to calculate van leer transport with the "real" concentration (dust mass) REAL mr_dust_number(ngrid,nlayer) ! intermediate mixing ratio to calculate van leer transport with the "real" concentration (sdust number) REAL dqvl_stormdust_mass(ngrid,nlayer) ! tendancy of vertical transport (stormdust mass) REAL dqvl_stormdust_number(ngrid,nlayer) ! tendancy of vertical transport (stormdust number) REAL dqvl_dust_mass(ngrid,nlayer) ! tendancy of vertical transport (dust mass) REAL dqvl_dust_number(ngrid,nlayer) ! tendancy of vertical transport (dust number) REAL dqdet_stormdust_mass(ngrid,nlayer) ! tendancy of detrainement (stormdust mass) REAL dqdet_stormdust_number(ngrid,nlayer) ! tendancy of detrainement (stormdust number) REAL masse_col(nlayer) ! mass of atmosphere (kg/m2) REAL zq(ngrid,nlayer,nq) ! updated tracers REAL w(ngrid,nlayer) ! air mass flux (calculated with the vertical wind velocity profile) used as input in Van Leer (kgair/m2) REAL wqmass(ngrid,nlayer+1) ! tracer (dust_mass) mass flux in Van Leer (kg/m2) REAL wqnumber(ngrid,nlayer+1) ! tracer (dust_number) mass flux in Van Leer (kg/m2) LOGICAL storm(ngrid) ! true when there is a dust storm (if the opacity is high): trigger the rocket dust storm scheme REAL detrain(ngrid,nlayer) ! coefficient for detrainment : % of stormdust detrained INTEGER scheme(ngrid) ! triggered scheme REAL,PARAMETER:: coefmin =0.025 ! 0 see vlz_fi.F) !*********************************************************************** SUBROUTINE van_leer(nlay,q,pente_max,masse,w,wq) IMPLICIT NONE !-------------------------------------------------------- ! Input/Output Variables !-------------------------------------------------------- INTEGER,INTENT(IN) :: nlay ! number of atmospheric layers REAL,INTENT(IN) :: masse(nlay) ! mass of the layer Dp/g REAL,INTENT(IN) :: pente_max != 2 conseillee REAL,INTENT(INOUT) :: q(nlay) ! mixing ratio (kg/kg) REAL,INTENT(INOUT) :: w(nlay) ! atmospheric mass "transferred" at each timestep (kg.m-2) REAL,INTENT(INOUT) :: wq(nlay+1) !-------------------------------------------------------- ! Local Variables !-------------------------------------------------------- INTEGER i,l,j,ii REAL dzq(nlay),dzqw(nlay),adzqw(nlay),dzqmax REAL newmasse REAL sigw, Mtot, MQtot INTEGER m ! ********************************************************************** ! Mixing ratio vertical gradient at the levels ! ********************************************************************** do l=2,nlay dzqw(l)=q(l-1)-q(l) adzqw(l)=abs(dzqw(l)) enddo do l=2,nlay-1 if(dzqw(l)*dzqw(l+1).gt.0.) then dzq(l)=0.5*(dzqw(l)+dzqw(l+1)) else dzq(l)=0. endif dzqmax=pente_max*min(adzqw(l),adzqw(l+1)) dzq(l)=sign(min(abs(dzq(l)),dzqmax),dzq(l)) enddo dzq(1)=0. dzq(nlay)=0. ! ********************************************************************** ! Vertical advection ! ********************************************************************** !! No flux at the model top: wq(nlay+1)=0. !! Surface flux up: if(w(1).lt.0.) wq(1)=0. ! warning : not always valid do l = 1,nlay-1 ! 1) Compute wq where w < 0 (up) (UPWARD TRANSPORT) ! =============================== if(w(l+1).le.0)then ! Regular scheme (transfered mass < 1 layer) ! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if(-w(l+1).le.masse(l))then sigw=w(l+1)/masse(l) wq(l+1)=w(l+1)*(q(l)-0.5*(1.+sigw)*dzq(l)) !!------------------------------------------------------- ! The following part should not be needed in the ! case of an integration over subtimesteps !!------------------------------------------------------- ! Extended scheme (transfered mass > 1 layer) ! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ else m = l-1 Mtot = masse(m+1) MQtot = masse(m+1)*q(m+1) if (m.le.0)goto 77 do while(-w(l+1).gt.(Mtot+masse(m))) ! do while(-w(l+1).gt.Mtot) m=m-1 Mtot = Mtot + masse(m+1) MQtot = MQtot + masse(m+1)*q(m+1) if (m.le.0)goto 77 end do 77 continue if (m.gt.0) then sigw=(w(l+1)+Mtot)/masse(m) wq(l+1)= -(MQtot + (-w(l+1)-Mtot)* & (q(m)-0.5*(1.+sigw)*dzq(m)) ) else w(l+1) = -Mtot wq(l+1) = -MQtot end if endif ! (-w(l+1).le.masse(l)) ! 2) Compute wq where w > 0 (down) (DOWNWARD TRANSPORT) ! =============================== else if(w(l).gt.0.)then ! Regular scheme (transfered mass < 1 layer) ! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if(w(l).le.masse(l))then sigw=w(l)/masse(l) wq(l)=w(l)*(q(l)+0.5*(1.-sigw)*dzq(l)) !!------------------------------------------------------- ! The following part should not be needed in the ! case of an integration over subtimesteps !!------------------------------------------------------- ! Extended scheme (transfered mass > 1 layer) ! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ else m=l Mtot = masse(m) MQtot = masse(m)*q(m) if(m.ge.nlay)goto 88 do while(w(l).gt.(Mtot+masse(m+1))) m=m+1 Mtot = Mtot + masse(m) MQtot = MQtot + masse(m)*q(m) if(m.ge.nlay)goto 88 end do 88 continue if (m.lt.nlay) then sigw=(w(l)-Mtot)/masse(m+1) wq(l)=(MQtot + (w(l)-Mtot)* & (q(m+1)+0.5*(1.-sigw)*dzq(m+1)) ) else w(l) = Mtot wq(l) = MQtot end if end if end if ! w<0 (up) enddo ! l = 1,nlay-1 do l = 1,nlay ! it cannot entrain more than available mass ! if ( (wq(l+1)-wq(l)) .lt. -(masse(l)*q(l)) ) then wq(l+1) = wq(l)-masse(l)*q(l) end if q(l)=q(l) + (wq(l+1)-wq(l))/masse(l) enddo END SUBROUTINE van_leer !======================================================================= ! Initialization of the module variables subroutine ini_rocketduststorm_mod(ngrid) implicit none integer, intent(in) :: ngrid allocate(dustliftday(ngrid)) end subroutine ini_rocketduststorm_mod subroutine end_rocketduststorm_mod implicit none if (allocated(dustliftday)) deallocate(dustliftday) end subroutine end_rocketduststorm_mod END MODULE rocketduststorm_mod