module cldwat2m_micro 2,13
!---------------------------------------------------------------------------------
! Purpose:
! CAM Interface for microphysics
!
! Author: Andrew Gettelman, Hugh Morrison.
! Contributions from: Xiaohong Liu and Steve Ghan
! December 2005-May 2010
! Description in: Morrison and Gettelman, 2008. J. Climate (MG2008)
! Gettelman et al., 2010 J. Geophys. Res. - Atmospheres (G2010)
! for questions contact Hugh Morrison, Andrew Gettelman
! e-mail: morrison@ucar.edu, andrew@ucar.edu
!--Pull out aerosols & activation from code? Probably to complex for now.
!---------------------------------------------------------------------------------
use shr_kind_mod
, only: r8=>shr_kind_r8
use spmd_utils
, only: masterproc
use ppgrid
, only: pcols, pver, pverp
use physconst
, only: gravit, rair, tmelt, cpair, rh2o, r_universal, mwh2o, rhoh2o
use physconst
, only: latvap, latice
use abortutils
, only: endrun
use error_function
, only: erf,erfc
use wv_saturation
, only: estblf, hlatv, tmin, hlatf, rgasv, pcf, cp, epsqs, ttrice, &
vqsatd2, vqsatd2_single,polysvp
use cam_history
, only: addfld, add_default, phys_decomp, outfld
use cam_logfile
, only: iulog
use rad_constituents
, only: rad_cnst_get_clim_info, rad_cnst_get_clim_aer_props
use phys_control
, only: phys_getopts
use cldwat2m_macro
, only: rhmini, rhmaxi
implicit none
private
save
logical, public :: liu_in = .true. ! True = Liu et al 2007 Ice nucleation
! False = cooper fixed ice nucleation (MG2008)
public :: ini_micro, mmicro_pcond,gamma,derf
! Private module data
logical :: wsubTKE ! If .true. (.false.), use UW's TKE (kkvh) for computing wsub
!constants remaped
real(r8), private:: g !gravity
real(r8), private:: mw !molecular weight of water
real(r8), private:: r !Dry air Gas constant
real(r8), private:: rv !water vapor gas contstant
real(r8), private:: rr !universal gas constant
real(r8), private:: cpp !specific heat of dry air
real(r8), private:: rhow !density of liquid water
real(r8), private:: xxlv ! latent heat of vaporization
real(r8), private:: xlf !latent heat of freezing
real(r8), private:: xxls !latent heat of sublimation
real(r8), private:: rhosn ! bulk density snow
real(r8), private:: rhoi ! bulk density ice
real(r8), private:: ac,bc,as,bs,ai,bi,ar,br !fall speed parameters
real(r8), private:: ci,di !ice mass-diameter relation parameters
real(r8), private:: cs,ds !snow mass-diameter relation parameters
real(r8), private:: cr,dr !drop mass-diameter relation parameters
real(r8), private:: f1s,f2s !ventilation param for snow
real(r8), private:: Eii !collection efficiency aggregation of ice
real(r8), private:: Ecc !collection efficiency
real(r8), private:: Ecr !collection efficiency cloud droplets/rain
real(r8), private:: f1r,f2r !ventilation param for rain
real(r8), private:: DCS !autoconversion size threshold
real(r8), private:: qsmall !min mixing ratio
real(r8), private:: bimm,aimm !immersion freezing
real(r8), private:: rhosu !typical 850mn air density
real(r8), private:: mi0 ! new crystal mass
real(r8), private:: rin ! radius of contact nuclei
real(r8), private:: qcvar ! 1/relative variance of sub-grid qc
real(r8), private:: pi ! pi
real(r8), private:: rn_dst1, rn_dst2, rn_dst3, rn_dst4 !dust number mean radius for contact freezing
! hm, add additional constants to help speed up code
real(r8), private:: cons1
real(r8), private:: cons2
real(r8), private:: cons3
real(r8), private:: cons4
real(r8), private:: cons5
real(r8), private:: cons6
real(r8), private:: cons7
real(r8), private:: cons8
real(r8), private:: cons9
real(r8), private:: cons10
real(r8), private:: cons11
real(r8), private:: cons12
real(r8), private:: cons13
real(r8), private:: cons14
real(r8), private:: cons15
real(r8), private:: cons16
real(r8), private:: cons17
real(r8), private:: cons18
real(r8), private:: cons19
real(r8), private:: cons20
real(r8), private:: cons21
real(r8), private:: cons22
real(r8), private:: cons23
real(r8), private:: cons24
real(r8), private:: cons25
real(r8), private:: cons26
real(r8), private:: cons27
real(r8), private:: cons28
real(r8), private:: lammini
real(r8), private:: lammaxi
real(r8), private:: lamminr
real(r8), private:: lammaxr
real(r8), private:: lammins
real(r8), private:: lammaxs
! parameters for snow/rain fraction for convective clouds
real(r8), private, parameter :: tmax_fsnow = tmelt ! max temperature for transition to convective snow
real(r8), private, parameter :: tmin_fsnow = tmelt-5._r8 ! min temperature for transition to convective snow
!needed for findsp
real(r8), private:: tt0 ! Freezing temperature
! activate parameters
integer, private:: psat
parameter (psat=6) ! number of supersaturations to calc ccn concentration
real(r8), private:: aten
real(r8), allocatable, private:: alogsig(:) ! natl log of geometric standard dev of aerosol
real(r8), allocatable, private:: exp45logsig(:)
real(r8), allocatable, private:: argfactor(:)
real(r8), allocatable, private:: amcube(:) ! cube of dry mode radius (m)
real(r8), allocatable, private:: smcrit(:) ! critical supersatuation for activation
real(r8), allocatable, private:: lnsm(:) ! ln(smcrit)
real(r8), private:: amcubesulfate(pcols) ! cube of dry mode radius (m) of sulfate
real(r8), private:: smcritsulfate(pcols) ! critical supersatuation for activation of sulfate
real(r8), allocatable, private:: amcubefactor(:) ! factors for calculating mode radius
real(r8), allocatable, private:: smcritfactor(:) ! factors for calculating critical supersaturation
real(r8), private:: super(psat)
real(r8), private:: alogten,alog2,alog3,alogaten
real(r8), private, parameter :: supersat(psat)= &! supersaturation (%) to determine ccn concentration
(/0.02,0.05,0.1,0.2,0.5,1.0/)
real(r8), allocatable, private:: ccnfact(:,:)
real(r8), allocatable, private:: f1(:),f2(:) ! abdul-razzak functions of width
real(r8), private:: third, sixth,zero
real(r8), private:: sq2, sqpi
integer :: naer_all ! number of aerosols affecting climate
integer :: idxsul = -1 ! index in aerosol list for sulfate
integer :: idxdst1 = -1 ! index in aerosol list for dust1
integer :: idxdst2 = -1 ! index in aerosol list for dust2
integer :: idxdst3 = -1 ! index in aerosol list for dust3
integer :: idxdst4 = -1 ! index in aerosol list for dust4
integer :: idxbcphi = -1 ! index in aerosol list for Soot (BCPHIL)
! aerosol properties
character(len=20), allocatable :: aername(:)
real(r8), allocatable :: dryrad_aer(:)
real(r8), allocatable :: density_aer(:)
real(r8), allocatable :: hygro_aer(:)
real(r8), allocatable :: dispersion_aer(:)
real(r8), allocatable :: num_to_mass_aer(:)
real(r8), private:: csmin,csmax,minrefl,mindbz
contains
!===============================================================================
subroutine ini_micro 1,65
!-----------------------------------------------------------------------
!
! Purpose:
! initialize constants for the morrison microphysics
! called from stratiform.F90
!
! Author: Andrew Gettelman Dec 2005
!
!-----------------------------------------------------------------------
use cloud_fraction
, only: cldfrc_getparams
integer k
integer l,m, iaer
real(r8) surften ! surface tension of water w/respect to air (N/m)
real(r8) arg
real(r8) derf
character(len=16) :: eddy_scheme = ' '
logical :: history_microphysics ! output variables for microphysics diagnostics package
! Query the PBL eddy scheme
call phys_getopts
(eddy_scheme_out = eddy_scheme, &
history_microphysics_out = history_microphysics )
wsubTKE = .false.
if (trim(eddy_scheme) .eq. 'diag_TKE') wsubTKE = .true.
! Access the physical properties of the aerosols that are affecting the climate
! by using routines from the rad_constituents module.
call rad_cnst_get_clim_info
(naero=naer_all)
allocate( &
aername(naer_all), &
dryrad_aer(naer_all), &
density_aer(naer_all), &
hygro_aer(naer_all), &
dispersion_aer(naer_all), &
num_to_mass_aer(naer_all) )
do iaer = 1, naer_all
call rad_cnst_get_clim_aer_props
(iaer, &
aername = aername(iaer), &
dryrad_aer = dryrad_aer(iaer), &
density_aer = density_aer(iaer), &
hygro_aer = hygro_aer(iaer), &
dispersion_aer = dispersion_aer(iaer), &
num_to_mass_aer = num_to_mass_aer(iaer) )
! Look for sulfate aerosol in this list (Bulk aerosol only)
if (trim(aername(iaer)) == 'SULFATE') idxsul = iaer
if (trim(aername(iaer)) == 'DUST1') idxdst1 = iaer
if (trim(aername(iaer)) == 'DUST2') idxdst2 = iaer
if (trim(aername(iaer)) == 'DUST3') idxdst3 = iaer
if (trim(aername(iaer)) == 'DUST4') idxdst4 = iaer
if (trim(aername(iaer)) == 'BCPHIL') idxbcphi = iaer
!addfield calls for outputting aerosol number concentration
call addfld
(aername(iaer)//'_m3', 'm-3', pver, 'A', 'aerosol number concentration', phys_decomp)
end do
if (masterproc) then
write(iulog,*) 'ini_micro: iaer, name, dryrad, density, hygro, dispersion, num_to_mass'
do iaer = 1, naer_all
write(iulog,*) iaer, aername(iaer), dryrad_aer(iaer), density_aer(iaer), hygro_aer(iaer), &
dispersion_aer(iaer), num_to_mass_aer(iaer)
end do
if (idxsul < 1) then
write(iulog,*) 'ini_micro: SULFATE aerosol properties NOT FOUND'
else
write(iulog,*) 'ini_micro: SULFATE aerosol properties FOUND at index ',idxsul
end if
end if
call addfld
('CCN1 ','#/cm3 ',pver, 'A','CCN concentration at S=0.02%',phys_decomp)
call addfld
('CCN2 ','#/cm3 ',pver, 'A','CCN concentration at S=0.05%',phys_decomp)
call addfld
('CCN3 ','#/cm3 ',pver, 'A','CCN concentration at S=0.1%',phys_decomp)
call addfld
('CCN4 ','#/cm3 ',pver, 'A','CCN concentration at S=0.2%',phys_decomp)
call addfld
('CCN5 ','#/cm3 ',pver, 'A','CCN concentration at S=0.5%',phys_decomp)
call addfld
('CCN6 ','#/cm3 ',pver, 'A','CCN concentration at S=1.0%',phys_decomp)
! diagnostic precip
call addfld
('QRAIN ','kg/kg ',pver, 'A','Diagnostic grid-mean rain mixing ratio' ,phys_decomp)
call addfld
('QSNOW ','kg/kg ',pver, 'A','Diagnostic grid-mean snow mixing ratio' ,phys_decomp)
call addfld
('NRAIN ','m-3 ',pver, 'A','Diagnostic grid-mean rain number conc' ,phys_decomp)
call addfld
('NSNOW ','m-3 ',pver, 'A','Diagnostic grid-mean snow number conc' ,phys_decomp)
! size of precip
call addfld
('RERCLD ','m ',pver, 'A','Diagnostic effective radius of Liquid Cloud and Rain' ,phys_decomp)
call addfld
('DSNOW ','m ',pver, 'A','Diagnostic grid-mean snow diameter' ,phys_decomp)
! precip flux variables for ciccs (instrument simulator package)
call addfld
('MGFLXPRC ','kg/m2/s ',pver+1, 'A','Diagnostic grid-mean rain flux at layer interface', phys_decomp)
call addfld
('MGFLXSNW ','kg/m2/s ',pver+1, 'A','Diagnostic grid-mean snow flux at layer interface', phys_decomp)
! diagnostic radar reflectivity, cloud-averaged
call addfld
('REFL ','DBz ',pver, 'A','94 GHz radar reflectivity' ,phys_decomp)
call addfld
('AREFL ','DBz ',pver, 'A','Average 94 GHz radar reflectivity' ,phys_decomp)
call addfld
('FREFL ','fraction ',pver, 'A','Fractional occurance of radar reflectivity' ,phys_decomp)
call addfld
('CSRFL ','DBz ',pver, 'A','94 GHz radar reflectivity (CloudSat thresholds)' ,phys_decomp)
call addfld
('ACSRFL ','DBz ',pver, 'A','Average 94 GHz radar reflectivity (CloudSat thresholds)' ,phys_decomp)
call addfld
('FCSRFL ','fraction ',pver, 'A','Fractional occurance of radar reflectivity (CloudSat thresholds)' &
,phys_decomp)
call addfld
('AREFLZ ','mm^6/m^3 ',pver, 'A','Average 94 GHz radar reflectivity' ,phys_decomp)
call addfld
('NCAL ','#/m3 ',pver, 'A','Number Concentation Activated for Liquid',phys_decomp)
call addfld
('NCAI ','#/m3 ',pver, 'A','Number Concentation Activated for Ice',phys_decomp)
call addfld
('NIHF ','#/m3 ',pver, 'A','Activated Ice Number Concentation due to homogenous freezing',phys_decomp)
call addfld
('NIDEP ','#/m3 ',pver, 'A','Activated Ice Number Concentation due to deposition nucleation',phys_decomp)
call addfld
('NIIMM ','#/m3 ',pver, 'A','Activated Ice Number Concentation due to immersion freezing',phys_decomp)
call addfld
('NIMEY ','#/m3 ',pver, 'A','Activated Ice Number Concentation due to meyers deposition',phys_decomp)
!--ag
! Average rain and snow mixing ratio (Q), number (N) and diameter (D), with frequency
call addfld
('AQRAIN ','kg/kg ',pver, 'A','Average rain mixing ratio' ,phys_decomp)
call addfld
('AQSNOW ','kg/kg ',pver, 'A','Average snow mixing ratio' ,phys_decomp)
call addfld
('ANRAIN ','m-3 ',pver, 'A','Average rain number conc' ,phys_decomp)
call addfld
('ANSNOW ','m-3 ',pver, 'A','Average snow number conc' ,phys_decomp)
call addfld
('ADRAIN ','Micron ',pver, 'A','Average rain effective Diameter' ,phys_decomp)
call addfld
('ADSNOW ','Micron ',pver, 'A','Average snow effective Diameter' ,phys_decomp)
call addfld
('FREQR ','fraction ',pver, 'A','Fractional occurance of rain' ,phys_decomp)
call addfld
('FREQS ','fraction ',pver, 'A','Fractional occurance of snow' ,phys_decomp)
if ( history_microphysics) then
call add_default
('AQSNOW ', 1, ' ')
call add_default
('CCN3 ', 1, ' ')
call add_default
('FREQR ', 1, ' ')
call add_default
('FREQS ', 1, ' ')
call add_default
('AQRAIN ', 1, ' ')
call add_default
('AQSNOW ', 1, ' ')
call add_default
('ANRAIN ', 1, ' ')
call add_default
('ANSNOW ', 1, ' ')
end if
!declarations for morrison codes (transforms variable names)
g= gravit !gravity
! mw = mwh2o / 1000._r8 !molecular weight of water
r= rair !Dry air Gas constant: note units(phys_constants are in J/K/kmol)
rv= rh2o !water vapor gas contstant
rr = r_universal !universal gas constant
cpp = cpair !specific heat of dry air
rhow = rhoh2o !density of liquid water
! latent heats
xxlv = latvap ! latent heat vaporization
xlf = latice ! latent heat freezing
xxls = xxlv + xlf ! latent heat of sublimation
! parameters below from Reisner et al. (1998)
! density parameters (kg/m3)
rhosn = 100._r8 ! bulk density snow
rhoi = 500._r8 ! bulk density ice
rhow = 1000._r8 ! bulk density liquid
! fall speed parameters, V = aD^b
! V is in m/s
! droplets
ac = 3.e7_r8
bc = 2._r8
! snow
as = 11.72_r8
bs = 0.41_r8
! cloud ice
ai = 700._r8
bi = 1._r8
! rain
ar = 841.99667_r8
br = 0.8_r8
! particle mass-diameter relationship
! currently we assume spherical particles for cloud ice/snow
! m = cD^d
pi= 3.1415927_r8
! cloud ice mass-diameter relationship
ci = rhoi*pi/6._r8
di = 3._r8
! snow mass-diameter relationship
cs = rhosn*pi/6._r8
ds = 3._r8
! drop mass-diameter relationship
cr = rhow*pi/6._r8
dr = 3._r8
! ventilation parameters for snow
! hall and prupacher
f1s = 0.86_r8
f2s = 0.28_r8
! collection efficiency, aggregation of cloud ice and snow
Eii = 0.1_r8
! collection efficiency, accretion of cloud water by rain
Ecr = 1.0_r8
! ventilation constants for rain
f1r = 0.78_r8
f2r = 0.32_r8
! autoconversion size threshold for cloud ice to snow (m)
Dcs = 325.e-6_r8
! smallest mixing ratio considered in microphysics
qsmall = 1.e-18_r8
! immersion freezing parameters, bigg 1953
bimm = 100._r8
aimm = 0.66_r8
! contact freezing due to dust
! dust number mean radius (m), Zender et al JGR 2003 assuming number mode radius of 0.6 micron, sigma=2
rn_dst1=0.258e-6_r8
rn_dst2=0.717e-6_r8
rn_dst3=1.576e-6_r8
rn_dst4=3.026e-6_r8
! typical air density at 850 mb
rhosu = 85000._r8/(rair * tmelt)
! mass of new crystal due to aerosol freezing and growth (kg)
mi0 = 4._r8/3._r8*pi*rhoi*(10.e-6_r8)*(10.e-6_r8)*(10.e-6_r8)
! radius of contact nuclei aerosol (m)
rin = 0.1e-6_r8
! 1 / relative variance of sub-grid cloud water distribution
! see morrison and gettelman, 2007, J. Climate for details
qcvar = 2._r8
! freezing temperature
tt0=273.15_r8
! set parameters for droplet activation, following abdul-razzak and ghan 2000, JGR
! mathematical constants
zero=0._r8
third=1./3._r8
sixth=1./6._r8
sq2=sqrt(2._r8)
pi=4._r8*atan(1.0_r8)
sqpi=sqrt(pi)
surften=0.076_r8
aten=2.*mwh2o*surften/(r_universal*tt0*rhoh2o)
alogaten=log(aten)
alog2=log(2._r8)
alog3=log(3._r8)
super(:)=0.01*supersat(:)
allocate(alogsig(naer_all), &
exp45logsig(naer_all), &
argfactor(naer_all), &
amcube(naer_all), &
smcrit(naer_all), &
lnsm(naer_all), &
amcubefactor(naer_all), &
smcritfactor(naer_all), &
ccnfact(psat,naer_all), &
f1(naer_all), &
f2(naer_all) )
do m=1,naer_all
! use only if width of size distribution is prescribed
alogsig(m)=log(dispersion_aer(m))
exp45logsig(m)=exp(4.5*alogsig(m)*alogsig(m))
argfactor(m)=2./(3.*sqrt(2.)*alogsig(m))
f1(m)=0.5*exp(2.5*alogsig(m)*alogsig(m))
f2(m)=1.+0.25*alogsig(m)
amcubefactor(m)=3._r8/(4._r8*pi*exp45logsig(m)*density_aer(m))
smcritfactor(m)=2._r8*aten*sqrt(aten/(27._r8*max(1.e-10_r8,hygro_aer(m))))
amcube(m)=amcubefactor(m)/(num_to_mass_aer(m))
if(hygro_aer(m).gt.1.e-10) then
smcrit(m)=smcritfactor(m)/sqrt(amcube(m))
else
smcrit(m)=100.
endif
lnsm(m)=log(smcrit(m))
do l=1,psat
arg=argfactor(m)*log(smcrit(m)/super(l))
if(arg<2)then
if(arg<-2)then
ccnfact(l,m)=1.e-6
else
ccnfact(l,m)=1.e-6_r8*0.5_r8*erfc(arg)
endif
else
ccnfact(l,m) = 0.
endif
enddo
end do
!Range of cloudsat reflectivities (dBz)
csmin= -30._r8
csmax= 26._r8
mindbz = -99._r8
! minrefl = 10._r8**(mindbz/10._r8) hard code below
minrefl = 1.26e-10_r8
! hm, add constants to help speed up code
cons1=gamma
(1._r8+di)
cons2=gamma
(qcvar+2.47_r8)
cons3=gamma
(qcvar)
cons4=gamma
(1._r8+br)
cons5=gamma
(4._r8+br)
cons6=gamma
(1._r8+ds)
cons7=gamma
(1._r8+bs)
cons8=gamma
(4._r8+bs)
cons9=gamma
(qcvar+2._r8)
cons10=gamma
(qcvar+1._r8)
cons11=gamma
(3._r8+bs)
cons12=gamma
(qcvar+1.15_r8)
cons13=gamma
(5._r8/2._r8+br/2._r8)
cons14=gamma
(5._r8/2._r8+bs/2._r8)
cons15=gamma
(qcvar+bc/3._r8)
cons16=gamma
(1._r8+bi)
cons17=gamma
(4._r8+bi)
cons18=qcvar**2.47_r8
cons19=qcvar**2
cons20=qcvar**1.15_r8
cons21=qcvar**(bc/3._r8)
cons22=(4._r8/3._r8*pi*rhow*(25.e-6_r8)**3)
cons23=dcs**3
cons24=dcs**2
cons25=dcs**bs
! cons26=pi**((1._r8-bs)/3._r8)*rhosn**((-2._r8-bs)/3._r8)
cons27=xxlv**2
cons28=xxls**2
lammaxi = 1._r8/10.e-6_r8
lammini = 1._r8/(2._r8*dcs)
lammaxr = 1._r8/20.e-6_r8
lamminr = 1._r8/500.e-6_r8
lammaxs = 1._r8/10.e-6_r8
lammins = 1._r8/2000.e-6_r8
return
end subroutine ini_micro
!===============================================================================
!microphysics routine for each timestep goes here...
subroutine mmicro_pcond ( & 1,77
lchnk, ncol, deltatin, tn, ttend, &
qn, qtend, cwtend, qc, qi, &
nc, ni, p, pdel, cldn, &
liqcldf, icecldf, &
cldo, pint, rpdel, zm, omega, &
#ifdef MODAL_AERO
qaer, cflx, qaertend, qqcw,dgnumwet,dgnum, &
rate1ord_cw2pr_st, & ! rce 2010/05/01
#else
aer_mmr, &
#endif
rhdfda, rhu00, fice, tlat, qvlat, &
qctend, qitend, nctend, nitend, effc, &
effc_fn, effi, prect, preci, kkvh, &
tke, turbtype, smaw, wsub, wsubi, nevapr, evapsnow, &
prain, prodsnow, cmeout, deffi, pgamrad, &
lamcrad,qsout,dsout, &
qcsevap,qisevap,qvres,cmeiout, &
vtrmc,vtrmi,qcsedten,qisedten, &
prao,prco,mnuccco,mnuccto,msacwio,psacwso,&
bergso,bergo,melto,homoo,qcreso,prcio,praio,qireso,&
mnuccro,pracso,meltsdt,frzrdt)
!Author: Hugh Morrison, Andrew Gettelman, NCAR
! e-mail: morrison@ucar.edu, andrew@ucar.edu
use wv_saturation
, only: vqsatd, vqsatd_water
use constituents
, only: pcnst
#ifdef MODAL_AERO
use ndrop
, only: dropmixnuc
use modal_aero_data, only: numptr_amode, modeptr_accum, modeptr_coarse, modeptr_aitken, &
lptr_dust_a_amode,lptr_nacl_a_amode,maxd_amode
#endif
! input arguments
integer, intent(in) :: lchnk
integer, intent(in) :: ncol
real(r8), intent(in) :: deltatin ! time step (s)
real(r8), intent(in) :: tn(pcols,pver) ! input temperature (K)
real(r8), intent(in) :: ttend(pcols,pver) ! non-microphysical temperature tendency (K/s)
real(r8), intent(in) :: qn(pcols,pver) ! input h20 vapor mixing ratio (kg/kg)
real(r8), intent(in) :: qtend(pcols,pver) ! non-microphysical qv tendency (1/s)
real(r8), intent(in) :: cwtend(pcols,pver) ! non-microphysical tendency of cloud water (1/s)
! note: all input cloud variables are grid-averaged
real(r8), intent(inout) :: qc(pcols,pver) ! cloud water mixing ratio (kg/kg)
real(r8), intent(inout) :: qi(pcols,pver) ! cloud ice mixing ratio (kg/kg)
real(r8), intent(inout) :: nc(pcols,pver) ! cloud water number conc (1/kg)
real(r8), intent(inout) :: ni(pcols,pver) ! cloud ice number conc (1/kg)
real(r8), intent(in) :: p(pcols,pver) ! air pressure (pa)
real(r8), intent(in) :: pdel(pcols,pver) ! pressure difference across level (pa)
real(r8), intent(in) :: cldn(pcols,pver) ! cloud fraction
real(r8), intent(in) :: icecldf(pcols,pver) ! ice cloud fraction
real(r8), intent(in) :: liqcldf(pcols,pver) ! liquid cloud fraction
real(r8), intent(inout) :: cldo(pcols,pver) ! old cloud fraction
real(r8), intent(in) :: pint(pcols,pverp) ! air pressure layer interfaces (pa)
real(r8), intent(in) :: rpdel(pcols,pver) ! inverse pressure difference across level (pa)
real(r8), intent(in) :: zm(pcols,pver) ! geopotential height of model levels (m)
real(r8), intent(in) :: omega(pcols,pver) ! vertical velocity (Pa/s)
#ifdef MODAL_AERO
real(r8), intent(in) :: qaer(pcols,pver,pcnst) ! aerosol number and mass mixing ratios
real(r8), intent(in) :: cflx(pcols,pcnst) ! constituent flux from surface
real(r8), intent(inout) :: qaertend(pcols,pver,pcnst) ! qaer tendency (1/s)
real(r8), intent(inout) :: qqcw(pcols,pver,pcnst) ! cloud-borne aerosol
real(r8), intent(in) :: dgnumwet(pcols,pver,maxd_amode) ! aerosol mode diameter
real(r8), intent(in) :: dgnum(pcols,pver,maxd_amode) ! aerosol mode dry diameter
real(r8), intent(out) :: rate1ord_cw2pr_st(pcols,pver) ! 1st order rate for direct cw to precip conversion ! rce 2010/05/01
#else
real(r8), intent(in) :: aer_mmr(:,:,:) ! aerosol mass mixing ratio
#endif
real(r8), intent(in) :: rhdfda(pcols,pver) ! dA/dRH
real(r8), intent(in) :: rhu00(pcols,pver) ! threshold rh for cloud
real(r8), intent(in) :: fice(pcols,pver) ! fraction of ice/liquid
real(r8), intent(in) :: kkvh(pcols,pver+1) ! vertical eddy diff coef (m2 s-1)
real(r8), intent(in) :: tke(pcols,pver+1) ! TKE from the UW PBL scheme (m2 s-2)
real(r8), intent(in) :: turbtype(pcols,pver+1) ! Turbulence type at each interface
real(r8), intent(in) :: smaw(pcols,pver+1) ! Normalized instability function of momentum. 0 <= <= 4.964 and 1 at neutral condition.
! output arguments
real(r8), intent(out) :: tlat(pcols,pver) ! latent heating rate (W/kg)
real(r8), intent(out) :: qvlat(pcols,pver) ! microphysical tendency qv (1/s)
real(r8), intent(out) :: qctend(pcols,pver) ! microphysical tendency qc (1/s)
real(r8), intent(out) :: qitend(pcols,pver) ! microphysical tendency qi (1/s)
real(r8), intent(out) :: nctend(pcols,pver) ! microphysical tendency nc (1/(kg*s))
real(r8), intent(out) :: nitend(pcols,pver) ! microphysical tendency ni (1/(kg*s))
real(r8), intent(out) :: effc(pcols,pver) ! droplet effective radius (micron)
real(r8), intent(out) :: effc_fn(pcols,pver) ! droplet effective radius, assuming nc = 1.e8 kg-1
real(r8), intent(out) :: effi(pcols,pver) ! cloud ice effective radius (micron)
real(r8), intent(out) :: prect(pcols) ! surface precip rate (m/s)
real(r8), intent(out) :: preci(pcols) ! cloud ice/snow precip rate (m/s)
real(r8), intent(out) :: wsub(pcols,pver) ! diagnosed sub-grid vertical velocity st. dev. (m/s)
real(r8), intent(out) :: wsubi(pcols,pver) ! diagnosed sub-grid vertical velocity ice (m/s)
real(r8), intent(out) :: nevapr(pcols,pver) ! evaporation rate of rain + snow
real(r8), intent(out) :: evapsnow(pcols,pver)! sublimation rate of snow
real(r8), intent(out) :: prain(pcols,pver) ! production of rain + snow
real(r8), intent(out) :: prodsnow(pcols,pver)! production of snow
real(r8), intent(out) :: cmeout(pcols,pver) ! evap/sub of cloud
real(r8), intent(out) :: deffi(pcols,pver) ! ice effective diameter for optics (radiation)
real(r8), intent(out) :: pgamrad(pcols,pver) ! ice gamma parameter for optics (radiation)
real(r8), intent(out) :: lamcrad(pcols,pver) ! slope of droplet distribution for optics (radiation)
real(r8), intent(out) :: qcsevap(pcols,pver) ! cloud water evaporation due to sedimentation
real(r8), intent(out) :: qisevap(pcols,pver) ! cloud ice sublimation due to sublimation
real(r8), intent(out) :: qvres(pcols,pver) ! residual condensation term to ensure RH < 100%
real(r8), intent(out) :: cmeiout(pcols,pver) ! grid-mean cloud ice sub/dep
real(r8), intent(out) :: vtrmc(pcols,pver) ! mass-weighted cloud water fallspeed
real(r8), intent(out) :: vtrmi(pcols,pver) ! mass-weighted cloud ice fallspeed
real(r8), intent(out) :: qcsedten(pcols,pver) ! qc sedimentation tendency
real(r8), intent(out) :: qisedten(pcols,pver) ! qi sedimentation tendency
! microphysical process rates for output (mixing ratio tendencies)
real(r8), intent(out) :: prao(pcols,pver) ! accretion of cloud by rain
real(r8), intent(out) :: prco(pcols,pver) ! autoconversion of cloud to rain
real(r8), intent(out) :: mnuccco(pcols,pver) ! mixing rat tend due to immersion freezing
real(r8), intent(out) :: mnuccto(pcols,pver) ! mixing ratio tend due to contact freezing
real(r8), intent(out) :: msacwio(pcols,pver) ! mixing ratio tend due to H-M splintering
real(r8), intent(out) :: psacwso(pcols,pver) ! collection of cloud water by snow
real(r8), intent(out) :: bergso(pcols,pver) ! bergeron process on snow
real(r8), intent(out) :: bergo(pcols,pver) ! bergeron process on cloud ice
real(r8), intent(out) :: melto(pcols,pver) ! melting of cloud ice
real(r8), intent(out) :: homoo(pcols,pver) ! homogeneos freezign cloud water
real(r8), intent(out) :: qcreso(pcols,pver) ! residual cloud condensation due to removal of excess supersat
real(r8), intent(out) :: prcio(pcols,pver) ! autoconversion of cloud ice to snow
real(r8), intent(out) :: praio(pcols,pver) ! accretion of cloud ice by snow
real(r8), intent(out) :: qireso(pcols,pver) ! residual ice deposition due to removal of excess supersat
real(r8), intent(out) :: mnuccro(pcols,pver) ! mixing ratio tendency due to heterogeneous freezing of rain to snow (1/s)
real(r8), intent(out) :: pracso (pcols,pver) ! mixing ratio tendency due to accretion of rain by snow (1/s)
real(r8), intent(out) :: meltsdt(pcols,pver) ! latent heating rate due to melting of snow (W/kg)
real(r8), intent(out) :: frzrdt (pcols,pver) ! latent heating rate due to homogeneous freezing of rain (W/kg)
real(r8) :: tkem(pcols,pver) ! Layer-mean TKE
real(r8) :: smm(pcols,pver) ! Layer-mean instability function
! local workspace
! all units mks unless otherwise stated
! temporary variables for sub-stepping
real(r8) :: t1(pcols,pver)
real(r8) :: q1(pcols,pver)
real(r8) :: qc1(pcols,pver)
real(r8) :: qi1(pcols,pver)
real(r8) :: nc1(pcols,pver)
real(r8) :: ni1(pcols,pver)
real(r8) :: tlat1(pcols,pver)
real(r8) :: qvlat1(pcols,pver)
real(r8) :: qctend1(pcols,pver)
real(r8) :: qitend1(pcols,pver)
real(r8) :: nctend1(pcols,pver)
real(r8) :: nitend1(pcols,pver)
real(r8) :: prect1(pcols)
real(r8) :: preci1(pcols)
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
real(r8) :: deltat ! sub-time step (s)
real(r8) :: omsm ! number near unity for round-off issues
real(r8) :: dto2 ! dt/2 (s)
real(r8) :: mincld ! minimum allowed cloud fraction
real(r8) :: q(pcols,pver) ! water vapor mixing ratio (kg/kg)
real(r8) :: t(pcols,pver) ! temperature (K)
real(r8) :: rho(pcols,pver) ! air density (kg m-3)
real(r8) :: dv(pcols,pver) ! diffusivity of water vapor in air
real(r8) :: mu(pcols,pver) ! viscocity of air
real(r8) :: sc(pcols,pver) ! schmidt number
real(r8) :: kap(pcols,pver) ! thermal conductivity of air
real(r8) :: rhof(pcols,pver) ! air density correction factor for fallspeed
real(r8) :: cldmax(pcols,pver) ! precip fraction assuming maximum overlap
real(r8) :: cldm(pcols,pver) ! cloud fraction
real(r8) :: icldm(pcols,pver) ! ice cloud fraction
real(r8) :: lcldm(pcols,pver) ! liq cloud fraction
real(r8) :: icwc(pcols) ! in cloud water content (liquid+ice)
real(r8) :: calpha(pcols) ! parameter for cond/evap (Zhang et al. 2003)
real(r8) :: cbeta(pcols) ! parameter for cond/evap (Zhang et al. 2003)
real(r8) :: cbetah(pcols) ! parameter for cond/evap (Zhang et al. 2003)
real(r8) :: cgamma(pcols) ! parameter for cond/evap (Zhang et al. 2003)
real(r8) :: cgamah(pcols) ! parameter for cond/evap (Zhang et al. 2003)
real(r8) :: rcgama(pcols) ! parameter for cond/evap (Zhang et al. 2003)
real(r8) :: cmec1(pcols) ! parameter for cond/evap (Zhang et al. 2003)
real(r8) :: cmec2(pcols) ! parameter for cond/evap (Zhang et al. 2003)
real(r8) :: cmec3(pcols) ! parameter for cond/evap (Zhang et al. 2003)
real(r8) :: cmec4(pcols) ! parameter for cond/evap (Zhang et al. 2003)
real(r8) :: qtmp ! dummy qv
real(r8) :: dum ! temporary dummy variable
real(r8) :: cme(pcols,pver) ! total (liquid+ice) cond/evap rate of cloud
real(r8) :: cmei(pcols,pver) ! dep/sublimation rate of cloud ice
real(r8) :: cwml(pcols,pver) ! cloud water mixing ratio
real(r8) :: cwmi(pcols,pver) ! cloud ice mixing ratio
real(r8) :: nnuccd(pver) ! ice nucleation rate from deposition/cond.-freezing
real(r8) :: mnuccd(pver) ! mass tendency from ice nucleation
real(r8) :: qcld ! total cloud water
real(r8) :: lcldn(pcols,pver) ! fractional coverage of new liquid cloud
real(r8) :: lcldo(pcols,pver) ! fractional coverage of old liquid cloud
real(r8) :: nctend_mixnuc(pcols,pver)
real(r8) :: arg ! argument of erfc
#ifdef MODAL_AERO
real(r8) :: qcsinksum_rate1ord(pver) ! sum over iterations of cw to precip sink ! rce 2010/05/01
real(r8) :: qcsum_rate1ord(pver) ! sum over iterations of cloud water ! rce 2010/05/01
#endif
real(r8) :: alpha
real(r8) :: dum1,dum2 !general dummy variables
real(r8) :: nihf2,niimm2,nidep2,nimey2 !dummy variables for activated ice nuclei by diffferent processes
real(r8) :: npccn(pver) ! droplet activation rate
real(r8) :: qcic(pcols,pver) ! in-cloud cloud liquid mixing ratio
real(r8) :: qiic(pcols,pver) ! in-cloud cloud ice mixing ratio
real(r8) :: qniic(pcols,pver) ! in-precip snow mixing ratio
real(r8) :: qric(pcols,pver) ! in-precip rain mixing ratio
real(r8) :: ncic(pcols,pver) ! in-cloud droplet number conc
real(r8) :: niic(pcols,pver) ! in-cloud cloud ice number conc
real(r8) :: nsic(pcols,pver) ! in-precip snow number conc
real(r8) :: nric(pcols,pver) ! in-precip rain number conc
real(r8) :: lami(pver) ! slope of cloud ice size distr
real(r8) :: n0i(pver) ! intercept of cloud ice size distr
real(r8) :: lamc(pver) ! slope of cloud liquid size distr
real(r8) :: n0c(pver) ! intercept of cloud liquid size distr
real(r8) :: lams(pver) ! slope of snow size distr
real(r8) :: n0s(pver) ! intercept of snow size distr
real(r8) :: lamr(pver) ! slope of rain size distr
real(r8) :: n0r(pver) ! intercept of rain size distr
real(r8) :: cdist1(pver) ! size distr parameter to calculate droplet freezing
! combined size of precip & cloud drops
real(r8) :: rercld(pcols,pver) ! effective radius calculation for rain + cloud
real(r8) :: arcld(pcols,pver) ! averaging control flag
real(r8) :: Actmp !area cross section of drops
real(r8) :: Artmp !area cross section of rain
real(r8) :: pgam(pver) ! spectral width parameter of droplet size distr
real(r8) :: lammax ! maximum allowed slope of size distr
real(r8) :: lammin ! minimum allowed slope of size distr
real(r8) :: nacnt ! number conc of contact ice nuclei
real(r8) :: mnuccc(pver) ! mixing ratio tendency due to freezing of cloud water
real(r8) :: nnuccc(pver) ! number conc tendency due to freezing of cloud water
real(r8) :: mnucct(pver) ! mixing ratio tendency due to contact freezing of cloud water
real(r8) :: nnucct(pver) ! number conc tendency due to contact freezing of cloud water
real(r8) :: msacwi(pver) ! mixing ratio tendency due to HM ice multiplication
real(r8) :: nsacwi(pver) ! number conc tendency due to HM ice multiplication
real(r8) :: prc(pver) ! qc tendency due to autoconversion of cloud droplets
real(r8) :: nprc(pver) ! number conc tendency due to autoconversion of cloud droplets
real(r8) :: nprc1(pver) ! qr tendency due to autoconversion of cloud droplets
real(r8) :: nsagg(pver) ! ns tendency due to self-aggregation of snow
real(r8) :: dc0 ! mean size droplet size distr
real(r8) :: ds0 ! mean size snow size distr (area weighted)
real(r8) :: eci ! collection efficiency for riming of snow by droplets
real(r8) :: psacws(pver) ! mixing rat tendency due to collection of droplets by snow
real(r8) :: npsacws(pver) ! number conc tendency due to collection of droplets by snow
real(r8) :: uni ! number-weighted cloud ice fallspeed
real(r8) :: umi ! mass-weighted cloud ice fallspeed
real(r8) :: uns(pver) ! number-weighted snow fallspeed
real(r8) :: ums(pver) ! mass-weighted snow fallspeed
real(r8) :: unr(pver) ! number-weighted rain fallspeed
real(r8) :: umr(pver) ! mass-weighted rain fallspeed
real(r8) :: unc ! number-weighted cloud droplet fallspeed
real(r8) :: umc ! mass-weighted cloud droplet fallspeed
real(r8) :: pracs(pver) ! mixing rat tendency due to collection of rain by snow
real(r8) :: npracs(pver) ! number conc tendency due to collection of rain by snow
real(r8) :: mnuccr(pver) ! mixing rat tendency due to freezing of rain
real(r8) :: nnuccr(pver) ! number conc tendency due to freezing of rain
real(r8) :: pra(pver) ! mixing rat tendnency due to accretion of droplets by rain
real(r8) :: npra(pver) ! nc tendnency due to accretion of droplets by rain
real(r8) :: nragg(pver) ! nr tendency due to self-collection of rain
real(r8) :: prci(pver) ! mixing rat tendency due to autoconversion of cloud ice to snow
real(r8) :: nprci(pver) ! number conc tendency due to autoconversion of cloud ice to snow
real(r8) :: prai(pver) ! mixing rat tendency due to accretion of cloud ice by snow
real(r8) :: nprai(pver) ! number conc tendency due to accretion of cloud ice by snow
real(r8) :: qvs ! liquid saturation vapor mixing ratio
real(r8) :: qvi ! ice saturation vapor mixing ratio
real(r8) :: dqsdt ! change of sat vapor mixing ratio with temperature
real(r8) :: dqsidt ! change of ice sat vapor mixing ratio with temperature
real(r8) :: ab ! correction factor for rain evap to account for latent heat
real(r8) :: qclr ! water vapor mixing ratio in clear air
real(r8) :: abi ! correction factor for snow sublimation to account for latent heat
real(r8) :: epss ! 1/ sat relaxation timescale for snow
real(r8) :: epsr ! 1/ sat relaxation timescale for rain
real(r8) :: pre(pver) ! rain mixing rat tendency due to evaporation
real(r8) :: prds(pver) ! snow mixing rat tendency due to sublimation
real(r8) :: qce ! dummy qc for conservation check
real(r8) :: qie ! dummy qi for conservation check
real(r8) :: nce ! dummy nc for conservation check
real(r8) :: nie ! dummy ni for conservation check
real(r8) :: ratio ! parameter for conservation check
real(r8) :: dumc(pcols,pver) ! dummy in-cloud qc
real(r8) :: dumnc(pcols,pver) ! dummy in-cloud nc
real(r8) :: dumi(pcols,pver) ! dummy in-cloud qi
real(r8) :: dumni(pcols,pver) ! dummy in-cloud ni
real(r8) :: dums(pcols,pver) ! dummy in-cloud snow mixing rat
real(r8) :: dumns(pcols,pver) ! dummy in-cloud snow number conc
real(r8) :: dumr(pcols,pver) ! dummy in-cloud rain mixing rat
real(r8) :: dumnr(pcols,pver) ! dummy in-cloud rain number conc
! below are parameters for cloud water and cloud ice sedimentation calculations
real(r8) :: fr(pver)
real(r8) :: fnr(pver)
real(r8) :: fc(pver)
real(r8) :: fnc(pver)
real(r8) :: fi(pver)
real(r8) :: fni(pver)
real(r8) :: fs(pver)
real(r8) :: fns(pver)
real(r8) :: faloutr(pver)
real(r8) :: faloutnr(pver)
real(r8) :: faloutc(pver)
real(r8) :: faloutnc(pver)
real(r8) :: falouti(pver)
real(r8) :: faloutni(pver)
real(r8) :: falouts(pver)
real(r8) :: faloutns(pver)
real(r8) :: faltndr
real(r8) :: faltndnr
real(r8) :: faltndc
real(r8) :: faltndnc
real(r8) :: faltndi
real(r8) :: faltndni
real(r8) :: faltnds
real(r8) :: faltndns
real(r8) :: faltndqie
real(r8) :: faltndqce
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
real(r8) :: relhum(pcols,pver) ! relative humidity
real(r8) :: csigma(pcols) ! parameter for cond/evap of cloud water/ice
real(r8) :: rgvm ! max fallspeed for all species
real(r8) :: arn(pcols,pver) ! air density corrected rain fallspeed parameter
real(r8) :: asn(pcols,pver) ! air density corrected snow fallspeed parameter
real(r8) :: acn(pcols,pver) ! air density corrected cloud droplet fallspeed parameter
real(r8) :: ain(pcols,pver) ! air density corrected cloud ice fallspeed parameter
real(r8) :: nsubi(pver) ! evaporation of cloud ice number
real(r8) :: nsubc(pver) ! evaporation of droplet number
real(r8) :: nsubs(pver) ! evaporation of snow number
real(r8) :: nsubr(pver) ! evaporation of rain number
real(r8) :: mtime ! factor to account for droplet activation timescale
real(r8) :: dz(pcols,pver) ! height difference across model vertical level
!fice variable
real(r8) :: nfice(pcols,pver)
!add variables for rain and snow flux at layer interfaces
real(r8) :: rflx(pcols,pver+1)
real(r8) :: sflx(pcols,pver+1)
!! also add precip flux variables for sub-stepping
real(r8) :: rflx1(pcols,pver+1)
real(r8) :: sflx1(pcols,pver+1)
! returns from function/subroutine calls
real(r8) :: tsp(pcols,pver) ! saturation temp (K)
real(r8) :: qsp(pcols,pver) ! saturation mixing ratio (kg/kg)
real(r8) :: qsphy(pcols,pver) ! saturation mixing ratio (kg/kg): hybrid rh
real(r8) :: qs(pcols) ! liquid-ice weighted sat mixing rat (kg/kg)
real(r8) :: es(pcols) ! liquid-ice weighted sat vapor press (pa)
real(r8) :: esl(pcols,pver) ! liquid sat vapor pressure (pa)
real(r8) :: esi(pcols,pver) ! ice sat vapor pressure (pa)
real(r8) :: gammas(pcols) ! parameter for cond/evap of cloud water
! sum of source/sink terms for diagnostic precip
real(r8) :: qnitend(pcols,pver) ! snow mixing ratio source/sink term
real(r8) :: nstend(pcols,pver) ! snow number concentration source/sink term
real(r8) :: qrtend(pcols,pver) ! rain mixing ratio source/sink term
real(r8) :: nrtend(pcols,pver) ! rain number concentration source/sink term
real(r8) :: qrtot ! vertically-integrated rain mixing rat source/sink term
real(r8) :: nrtot ! vertically-integrated rain number conc source/sink term
real(r8) :: qstot ! vertically-integrated snow mixing rat source/sink term
real(r8) :: nstot ! vertically-integrated snow number conc source/sink term
! new terms for Bergeron process
real(r8) :: dumnnuc ! provisional ice nucleation rate (for calculating bergeron)
real(r8) :: ninew ! provisional cloud ice number conc (for calculating bergeron)
real(r8) :: qinew ! provisional cloud ice mixing ratio (for calculating bergeron)
real(r8) :: qvl ! liquid sat mixing ratio
real(r8) :: epsi ! 1/ sat relaxation timecale for cloud ice
real(r8) :: prd ! provisional deposition rate of cloud ice at water sat
real(r8) :: berg(pcols,pver) ! mixing rat tendency due to bergeron process for cloud ice
real(r8) :: bergs(pver) ! mixing rat tendency due to bergeron process for snow
!bergeron terms
real(r8) :: bergtsf !bergeron timescale to remove all liquid
real(r8) :: rhin !modified RH for vapor deposition
! new aerosol variables
real(r8), allocatable :: naermod(:) ! aerosol number concentration (/m3)
real(r8), allocatable :: naer2(:,:,:) ! new aerosol number concentration (/m3)
real(r8), allocatable :: maerosol(:,:) ! aerosol mass conc (kg/m3)
real(r8) naer(pcols)
real(r8) ccn(pcols,pver,psat) ! number conc of aerosols activated at supersat
character*8, parameter :: ccn_name(psat)=(/'CCN1','CCN2','CCN3','CCN4','CCN5','CCN6'/)
! diagnostic rain/snow for output to history
! values are in-precip (local) !!!!
real(r8) :: qrout(pcols,pver) ! rain mixing ratio (kg/kg)
real(r8) :: nrout(pcols,pver) ! rain number concentration (1/m3)
real(r8) :: nsout(pcols,pver) ! snow number concentration (1/m3)
real(r8), intent(out) :: dsout(pcols,pver) ! snow diameter (m)
real(r8), intent(out) :: qsout(pcols,pver) ! snow mixing ratio (kg/kg)
!averageed rain/snow for history
real(r8) :: qrout2(pcols,pver)
real(r8) :: qsout2(pcols,pver)
real(r8) :: nrout2(pcols,pver)
real(r8) :: nsout2(pcols,pver)
real(r8) :: freqs(pcols,pver)
real(r8) :: freqr(pcols,pver)
real(r8) :: dumfice
real(r8) :: drout2(pcols,pver) ! mean rain particle diameter (m)
real(r8) :: dsout2(pcols,pver) ! mean snow particle diameter (m)
!ice nucleation, droplet activation
real(r8) :: dum2i(pcols,pver) ! number conc of ice nuclei available (1/kg)
real(r8) :: dum2l(pcols,pver) ! number conc of CCN (1/kg)
real(r8) :: ncmax
real(r8) :: nimax
!output fields for number conc
real(r8) :: ncai(pcols,pver) ! output number conc of ice nuclei available (1/m3)
real(r8) :: ncal(pcols,pver) ! output number conc of CCN (1/m3)
!output for ice nucleation
real(r8) :: nimey(pcols,pver) !output number conc of ice nuclei due to meyers deposition (1/m3)
real(r8) :: nihf(pcols,pver) !output number conc of ice nuclei due to heterogenous freezing (1/m3)
real(r8) :: nidep(pcols,pver) !output number conc of ice nuclei due to deoposion nucleation (hetero nuc) (1/m3)
real(r8) :: niimm(pcols,pver) !output number conc of ice nuclei due to immersion freezing (hetero nuc) (1/m3)
! loop array variables
integer i,k,nstep,n, l
integer ii,kk, m
integer, allocatable :: ntype(:)
integer ftrue ! integer used to determine cloud depth
! loop variables for sub-step solution
integer iter,it,ltrue(pcols)
! used in contact freezing via dust particles
real(r8) tcnt, viscosity, mfp
real(r8) slip1, slip2, slip3, slip4
real(r8) dfaer1, dfaer2, dfaer3, dfaer4
real(r8) nacon1,nacon2,nacon3,nacon4
! used in ice effective radius
real(r8) bbi, cci, ak, iciwc, rvi
! used in Bergeron processe and water vapor deposition
real(r8) Tk, deles, Aprpr, Bprpr, Cice, qi0, Crate, qidep
! mean cloud fraction over the time step
real(r8) cldmw(pcols,pver)
! used in secondary ice production
real(r8) ni_secp
! variabels to check for RH after rain evap
real(r8) :: esn
real(r8) :: qsn
real(r8) :: ttmp
real(r8) :: refl(pcols,pver) ! analytic radar reflectivity
real(r8) :: rainrt(pcols,pver) ! rain rate for reflectivity calculation
real(r8) :: rainrt1(pcols,pver)
real(r8) :: csrfl(pcols,pver) !cloudsat reflectivity
real(r8) :: arefl(pcols,pver) !average reflectivity will zero points outside valid range
real(r8) :: acsrfl(pcols,pver) !cloudsat average
real(r8) :: frefl(pcols,pver)
real(r8) :: fcsrfl(pcols,pver)
real(r8) :: areflz(pcols,pver) !average reflectivity in z.
real(r8) :: tmp
real(r8) dmc,ssmc,dstrn ! variables for modal scheme.
real(r8), parameter :: cdnl = 0.e6_r8 ! cloud droplet number limiter
!cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
! initialize output fields for number conc qand ice nucleation
ncai(1:ncol,1:pver)=0._r8
ncal(1:ncol,1:pver)=0._r8
nimey(1:ncol,1:pver)=0._r8
nihf(1:ncol,1:pver)=0._r8
nidep(1:ncol,1:pver)=0._r8
niimm(1:ncol,1:pver)=0._r8
!Initialize rain size
rercld(1:ncol,1:pver)=0._r8
arcld(1:ncol,1:pver)=0._r8
! TKE initialization
tkem(1:ncol,1:pver)=0._r8
smm(1:ncol,1:pver)=0._r8
!initialize radiation output variables
pgamrad(1:ncol,1:pver)=0._r8 ! liquid gamma parameter for optics (radiation)
lamcrad(1:ncol,1:pver)=0._r8 ! slope of droplet distribution for optics (radiation)
deffi (1:ncol,1:pver)=0._r8 ! slope of droplet distribution for optics (radiation)
!initialize radiation output variables
!initialize water vapor tendency term output
qcsevap(1:ncol,1:pver)=0._r8
qisevap(1:ncol,1:pver)=0._r8
qvres (1:ncol,1:pver)=0._r8
cmeiout (1:ncol,1:pver)=0._r8
vtrmc (1:ncol,1:pver)=0._r8
vtrmi (1:ncol,1:pver)=0._r8
qcsedten (1:ncol,1:pver)=0._r8
qisedten (1:ncol,1:pver)=0._r8
prao(1:ncol,1:pver)=0._r8
prco(1:ncol,1:pver)=0._r8
mnuccco(1:ncol,1:pver)=0._r8
mnuccto(1:ncol,1:pver)=0._r8
msacwio(1:ncol,1:pver)=0._r8
psacwso(1:ncol,1:pver)=0._r8
bergso(1:ncol,1:pver)=0._r8
bergo(1:ncol,1:pver)=0._r8
melto(1:ncol,1:pver)=0._r8
homoo(1:ncol,1:pver)=0._r8
qcreso(1:ncol,1:pver)=0._r8
prcio(1:ncol,1:pver)=0._r8
praio(1:ncol,1:pver)=0._r8
qireso(1:ncol,1:pver)=0._r8
mnuccro(1:ncol,1:pver)=0._r8
pracso (1:ncol,1:pver)=0._r8
meltsdt(1:ncol,1:pver)=0._r8
frzrdt (1:ncol,1:pver)=0._r8
allocate(naermod(naer_all), &
naer2(pcols,pver,naer_all), &
maerosol(1,naer_all), &
ntype(naer_all))
! assign variable deltat for sub-stepping...
deltat=deltatin
! parameters for scheme
omsm=0.99999_r8
dto2=0.5_r8*deltat
mincld=0.0001_r8
! initialize multi-level fields
q(1:ncol,1:pver)=qn(1:ncol,1:pver)
t(1:ncol,1:pver)=tn(1:ncol,1:pver)
! More refined computation of sub-grid vertical velocity
! Set to be zero at the surface by initialization.
if( wsubTKE ) then
do i = 1, ncol
do k = 1, pver
tkem(i,k) = 0.5_r8 * ( tke(i,k) + tke(i,k+1) )
smm(i,k) = 0.5_r8 * ( smaw(i,k) + smaw(i,k+1) )
if( turbtype(i,k) .eq. 3._r8 ) then ! Bottom entrainment interface
tkem(i,k) = 0.5_r8 * tke(i,k+1)
smm(i,k) = 0.5_r8 * smaw(i,k+1)
elseif( turbtype(i,k+1) .eq. 4._r8 ) then ! Top entrainment interface
tkem(i,k) = 0.5_r8 * tke(i,k)
smm(i,k) = 0.5_r8 * smaw(i,k)
endif
smm(i,k) = 0.259_r8*smm(i,k)
smm(i,k) = max(smm(i,k), 0.4743_r8)
end do
end do
endif
do i=1,ncol
ftrue=0
do k=1,pver
! get sub-grid vertical velocity from diff coef.
! following morrison et al. 2005, JAS
! assume mixing length of 30 m
dum=(kkvh(i,k)+kkvh(i,k+1))/2._r8/30._r8
! use maximum sub-grid vertical vel of 10 m/s
dum=min(dum,10._r8)
! set wsub to value at current vertical level
wsub(i,k)=dum
! new computation
if( wsubTKE ) then
wsub(i,k) = sqrt(0.5_r8*(tke(i,k)+tke(i,k+1))*(2._r8/3._r8))
wsub(i,k) = min(wsub(i,k),10._r8)
endif
wsubi(i,k) = max(0.001_r8,wsub(i,k))
wsubi(i,k) = min(wsubi(i,k),0.2_r8)
wsub(i,k) = max(0.20_r8,wsub(i,k))
end do
end do
! initialize time-varying parameters
do k=1,pver
do i=1,ncol
rho(i,k)=p(i,k)/(r*t(i,k))
dv(i,k) = 8.794E-5_r8*t(i,k)**1.81_r8/p(i,k)
mu(i,k) = 1.496E-6_r8*t(i,k)**1.5_r8/ &
(t(i,k)+120._r8)
sc(i,k) = mu(i,k)/(rho(i,k)*dv(i,k))
kap(i,k) = 1.414e3_r8*1.496e-6_r8*t(i,k)** &
1.5_r8/(t(i,k)+120._r8)
! air density adjustment for fallspeed parameters
! includes air density correction factor to the
! power of 0.54 following Heymsfield and Bansemer 2007
rhof(i,k)=(rhosu/rho(i,k))**0.54
arn(i,k)=ar*rhof(i,k)
asn(i,k)=as*rhof(i,k)
acn(i,k)=ac*rhof(i,k)
ain(i,k)=ai*rhof(i,k)
! get dz from dp and hydrostatic approx
! keep dz positive (define as layer k-1 - layer k)
dz(i,k)= pdel(i,k)/(rho(i,k)*g)
end do
end do
! initialization
t1(1:ncol,1:pver) = t(1:ncol,1:pver)
q1(1:ncol,1:pver) = q(1:ncol,1:pver)
qc1(1:ncol,1:pver) = qc(1:ncol,1:pver)
qi1(1:ncol,1:pver) = qi(1:ncol,1:pver)
nc1(1:ncol,1:pver) = nc(1:ncol,1:pver)
ni1(1:ncol,1:pver) = ni(1:ncol,1:pver)
! initialize tendencies to zero
tlat1(1:ncol,1:pver)=0._r8
qvlat1(1:ncol,1:pver)=0._r8
qctend1(1:ncol,1:pver)=0._r8
qitend1(1:ncol,1:pver)=0._r8
nctend1(1:ncol,1:pver)=0._r8
nitend1(1:ncol,1:pver)=0._r8
! initialize precip output
qrout(1:ncol,1:pver)=0._r8
qsout(1:ncol,1:pver)=0._r8
nrout(1:ncol,1:pver)=0._r8
nsout(1:ncol,1:pver)=0._r8
dsout(1:ncol,1:pver)=0._r8
! initialize variables for trop_mozart
nevapr(1:ncol,1:pver) = 0._r8
evapsnow(1:ncol,1:pver) = 0._r8
prain(1:ncol,1:pver) = 0._r8
prodsnow(1:ncol,1:pver) = 0._r8
cmeout(1:ncol,1:pver) = 0._r8
! for refl calc
rainrt1(1:ncol,1:pver) = 0._r8
! initialize precip fraction and output tendencies
cldmax(1:ncol,1:pver)=mincld
!initialize aerosol number
naer2(1:ncol,1:pver,:)=0._r8
dum2l(1:ncol,1:pver)=0._r8
dum2i(1:ncol,1:pver)=0._r8
! initialize avg precip rate
prect1(1:ncol)=0._r8
preci1(1:ncol)=0._r8
!cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
!Get humidity and saturation vapor pressures
! hm: tsp, qsp no longer used below
! call findsp1 (lchnk,ncol,qn,tn,p,tsp,qsphy)
! call findsp1_water (lchnk,ncol,qn,tn,p,tsp,qsp)
do k=1,pver
! find wet bulk temperature and saturation value for provisional t and q without
! condensation
call vqsatd_water
(t(1,k),p(1,k),es,qs,gammas,ncol) ! use rhw
do i=1,ncol
esl(i,k)=polysvp
(t(i,k),0)
esi(i,k)=polysvp
(t(i,k),1)
! hm fix, make sure when above freezing that esi=esl, not active yet
if (t(i,k).gt.tmelt)esi(i,k)=esl(i,k)
relhum(i,k)=q(i,k)/qs(i)
! get cloud fraction, check for minimum
cldm(i,k)=max(cldn(i,k),mincld)
cldmw(i,k)=max(cldn(i,k),mincld)
icldm(i,k)=max(icecldf(i,k),mincld)
lcldm(i,k)=max(liqcldf(i,k),mincld)
! calculate nfice based on liquid and ice mmr (no rain and snow mmr available yet)
nfice(i,k)=0._r8
dumfice=qc(i,k)+qi(i,k)
if (dumfice.gt.qsmall .and. qi(i,k).gt.qsmall) then
nfice(i,k)=qi(i,k)/dumfice
endif
if (t(i,k).lt.tmelt - 5._r8) then
if (liu_in) then
#ifndef MODAL_AERO
do m=1,naer_all
ntype(m)=1
maerosol(1,m)=aer_mmr(i,k,m)*rho(i,k)
! For bulk aerosols only:
! set number nucleated for sulfate based on Lohmann et al 2000 (JGR) eq 2
! Na=340.*(massSO4)^0.58 where Na=cm-3 and massSO4=ug/m3
! convert units to Na [m-3] and SO4 [kgm-3]
! Na(m-3)= 1.e6 cm3 m-3 Na(cm-3)=340. *(massSO4[kg/m3]*1.e9ug/kg)^0.58
! or Na(m-3)= 1.e6* 340.*(1.e9ug/kg)^0.58 * (massSO4[kg/m3])^0.58
if(m .eq. idxsul) then
naer2(i,k,m)= 5.64259e13_r8 * maerosol(1,m)**0.58
else
naer2(i,k,m)=maerosol(1,m)*num_to_mass_aer(m)
endif
enddo
#endif
! get ice nucleation rate
call nucleati
(wsubi(i,k),t(i,k),relhum(i,k),icldm(i,k),qc(i,k),nfice(i,k),rho(i,k), &
#ifdef MODAL_AERO
qaer(i,k,:)*rho(i,k),dgnum(i,k,:),1,naer_all,dum2,nihf2,niimm2,nidep2,nimey2)
#else
naer2(i,k,:),1,naer_all,dum2,nihf2,niimm2,nidep2,nimey2)
#endif
else
! cooper curve (factor of 1000 is to convert from L-1 to m-3)
dum2=0.005_r8*exp(0.304_r8*(273.15_r8-t(i,k)))*1000._r8
! put limit on number of nucleated crystals, set to number at T=-30 C
! cooper (limit to value at -35 C)
dum2=min(dum,208.9e3_r8)/rho(i,k) ! convert from m-3 to kg-1
endif
dumnnuc=(dum2-ni(i,k)/icldm(i,k))/deltat*icldm(i,k)
dumnnuc=max(dumnnuc,0._r8)
! get provisional ni and qi after nucleation in order to calculate
! Bergeron process below
ninew=ni(i,k)+dumnnuc*deltat
qinew=qi(i,k)+dumnnuc*deltat*mi0
!T>268
else
ninew=ni(i,k)
qinew=qi(i,k)
end if
! Initialize CME components
cme(i,k) = 0._r8
cmei(i,k)=0._r8
!-------------------------------------------------------------------
!Bergeron process
! make sure to initialize bergeron process to zero
berg(i,k)=0._r8
prd = 0._r8
!condensation loop.
! get in-cloud qi and ni after nucleation
if (icldm(i,k) .gt. 0._r8) then
qiic(i,k)=qinew/icldm(i,k)
niic(i,k)=ninew/icldm(i,k)
else
qiic(i,k)=0._r8
niic(i,k)=0._r8
endif
!if T < 0 C then bergeron.
if (t(i,k).lt.273.15) then
!if ice exists
if (qi(i,k).gt.qsmall) then
bergtsf = 0._r8 ! bergeron time scale (fraction of timestep)
qvi=epsqs*esi(i,k)/(p(i,k)-(1._r8-epsqs)*esi(i,k))
qvl=epsqs*esl(i,k)/(p(i,k)-(1._r8-epsqs)*esl(i,k))
dqsidt = xxls*qvi/(rv*t(i,k)**2)
abi = 1._r8+dqsidt*xxls/cpp
! get ice size distribution parameters
if (qiic(i,k).ge.qsmall) then
lami(k) = (cons1*ci* &
niic(i,k)/qiic(i,k))**(1._r8/di)
n0i(k) = niic(i,k)*lami(k)
! check for slope
! adjust vars
if (lami(k).lt.lammini) then
lami(k) = lammini
n0i(k) = lami(k)**(di+1._r8)*qiic(i,k)/(ci*cons1)
else if (lami(k).gt.lammaxi) then
lami(k) = lammaxi
n0i(k) = lami(k)**(di+1._r8)*qiic(i,k)/(ci*cons1)
end if
epsi = 2._r8*pi*n0i(k)*rho(i,k)*Dv(i,k) &
/(lami(k)*lami(k))
!if liquid exists
if (qc(i,k).gt. qsmall) then
!begin bergeron process
! do bergeron (vapor deposition with RHw=1)
! code to find berg (a rate) goes here
! calculate Bergeron process
prd = epsi*(qvl-qvi)/abi
else
prd = 0._r8
end if
! multiply by cloud fraction
prd = prd*min(icldm(i,k),lcldm(i,k))
! transfer of existing cloud liquid to ice
berg(i,k)=max(0._r8,prd)
end if !end liquid exists bergeron
if (berg(i,k).gt.0._r8) then
bergtsf=max(0._r8,(qc(i,k)/berg(i,k))/deltat)
if(bergtsf.lt.1._r8) berg(i,k) = max(0._r8,qc(i,k)/deltat)
endif
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
if (bergtsf.lt.1._r8.or.icldm(i,k).gt.lcldm(i,k)) then
if (qiic(i,k).ge.qsmall) then
! first case is for case when liquid water is present, but is completely depleted in time step, i.e., bergrsf > 0 but < 1
if (qc(i,k).ge.qsmall) then
rhin = (1.0_r8 + relhum(i,k)) / 2._r8
if ((rhin*esl(i,k)/esi(i,k)) > 1._r8) then
prd = epsi*(rhin*qvl-qvi)/abi
! multiply by cloud fraction assuming liquid/ice maximum overlap
prd = prd*min(icldm(i,k),lcldm(i,k))
! add to cmei
cmei(i,k) = cmei(i,k) + (prd * (1._r8- bergtsf))
end if ! rhin
end if ! qc > qsmall
! second case is for pure ice cloud, either no liquid, or icldm > lcldm
if (qc(i,k).lt.qsmall.or.icldm(i,k).gt.lcldm(i,k)) then
! note: for case of no liquid, need to set liquid cloud fraction to zero
! store liquid cloud fraction in 'dum'
if (qc(i,k).lt.qsmall) then
dum=0._r8
else
dum=lcldm(i,k)
end if
! set RH to grid-mean value for pure ice cloud
rhin = relhum(i,k)
if ((rhin*esl(i,k)/esi(i,k)) > 1._r8) then
prd = epsi*(rhin*qvl-qvi)/abi
! multiply by relevant cloud fraction for pure ice cloud
! assuming maximum overlap of liquid/ice
prd = prd*max((icldm(i,k)-dum),0._r8)
cmei(i,k) = cmei(i,k) + prd
end if ! rhin
end if ! qc or icldm > lcldm
end if ! qiic
end if ! bergtsf or icldm > lcldm
! if deposition, it should not reduce grid mean rhi below 1.0
if(cmei(i,k) > 0.0_r8 .and. (relhum(i,k)*esl(i,k)/esi(i,k)) > 1._r8 ) &
cmei(i,k)=min(cmei(i,k),(q(i,k)-qs(i)*esi(i,k)/esl(i,k))/abi/deltat)
end if !end ice exists loop
!this ends temperature < 0. loop
!-------------------------------------------------------------------
end if !
!..............................................................
! evaporation should not exceed available water
if ((-berg(i,k)).lt.-qc(i,k)/deltat) &
berg(i,k) = max(qc(i,k)/deltat,0._r8)
!sublimation process...
if ((relhum(i,k)*esl(i,k)/esi(i,k)).lt.1._r8 .and. qiic(i,k).ge.qsmall ) then
qvi=epsqs*esi(i,k)/(p(i,k)-(1._r8-epsqs)*esi(i,k))
qvl=epsqs*esl(i,k)/(p(i,k)-(1._r8-epsqs)*esl(i,k))
dqsidt = xxls*qvi/(rv*t(i,k)**2)
abi = 1._r8+dqsidt*xxls/cpp
! get ice size distribution parameters
lami(k) = (cons1*ci* &
niic(i,k)/qiic(i,k))**(1._r8/di)
n0i(k) = niic(i,k)*lami(k)
! check for slope
! adjust vars
if (lami(k).lt.lammini) then
lami(k) = lammini
n0i(k) = lami(k)**(di+1._r8)*qiic(i,k)/(ci*cons1)
else if (lami(k).gt.lammaxi) then
lami(k) = lammaxi
n0i(k) = lami(k)**(di+1._r8)*qiic(i,k)/(ci*cons1)
end if
epsi = 2._r8*pi*n0i(k)*rho(i,k)*Dv(i,k) &
/(lami(k)*lami(k))
! modify for ice fraction below
prd = epsi*(relhum(i,k)*qvl-qvi)/abi * icldm(i,k)
cmei(i,k)=min(prd,0._r8)
endif
! sublimation should not exceed available ice
if (cmei(i,k).lt.-qi(i,k)/deltat) &
cmei(i,k)=-qi(i,k)/deltat
! sublimation should not increase grid mean rhi above 1.0
if(cmei(i,k) < 0.0_r8 .and. (relhum(i,k)*esl(i,k)/esi(i,k)) < 1._r8 ) &
cmei(i,k)=min(0._r8,max(cmei(i,k),(q(i,k)-qs(i)*esi(i,k)/esl(i,k))/abi/deltat))
! limit cmei due for roundoff error
cmei(i,k)=cmei(i,k)*omsm
! conditional for ice nucleation
if (t(i,k).lt.(tmelt - 5._r8)) then
if ( liu_in ) then
! using Liu et al. (2007) ice nucleation with hooks into simulated aerosol
! ice nucleation rate (dum2) has already been calculated above and state unchanged since then.
dum2i(i,k)=dum2
nihf(i,k)=nihf2
niimm(i,k)=niimm2
nidep(i,k)=nidep2
nimey(i,k)=nimey2
else
! cooper curve (factor of 1000 is to convert from L-1 to m-3)
dum2i(i,k)=0.005_r8*exp(0.304_r8*(273.15_r8-t(i,k)))*1000._r8
! put limit on number of nucleated crystals, set to number at T=-30 C
! cooper (limit to value at -35 C)
dum2i(i,k)=min(dum2i(i,k),208.9e3_r8)/rho(i,k) ! convert from m-3 to kg-1
endif
else
dum2i(i,k)=0._r8
end if
#ifndef MODAL_AERO
! more general treatment with hooks into simulated aerosol
!
do m=1,naer_all
ntype(m)=1
maerosol(1,m)=aer_mmr(i,k,m)*rho(i,k)
! set number concentration for sulfate based on Lohmann et al 2000 (JGR) eq 2
! Na=340.*(massSO4)^0.58 where Na=cm-3 and massSO4=ug/m3
! convert units to Na [m-3] and SO4 [kgm-3]
! Na(m-3)= 1.e6 cm3 m-3 Na(cm-3)=340. *(massSO4[kg/m3]*1.e9ug/kg)^0.58
! or Na(m-3)= 1.e6* 340.*(1.e9ug/kg)^0.58 * (massSO4[kg/m3])^0.58
!
if(m .eq. idxSUL) then
naer2(i,k,m)= 5.64259e13_r8 * maerosol(1,m)**0.58
else
naer2(i,k,m)=maerosol(1,m)*num_to_mass_aer(m)
endif
enddo
if (qc(i,k).ge.qsmall) then
! get droplet activation rate
call activate
(wsub(i,k),t(i,k),rho(i,k), &
naer2(i,k,:), naer_all,naer_all, maerosol, &
dispersion_aer,hygro_aer, density_aer, dum2)
dum2l(i,k) = dum2
else
dum2l(i,k) = 0._r8
end if
#endif
end do ! i loop
end do ! k loop
#ifdef MODAL_AERO
! partition cloud fraction into liquid water part
do k=1,pver
do i=1,ncol
qcld=qc(i,k)+qi(i,k)
if(qcld.gt.qsmall)then
lcldn(i,k)=cldn(i,k)*qc(i,k)/qcld
lcldo(i,k)=cldo(i,k)*qc(i,k)/qcld
else
lcldn(i,k)=0._r8
lcldo(i,k)=0._r8
endif
enddo
enddo
call dropmixnuc
(lchnk, ncol, nc, nctend_mixnuc, t, omega, &
p, pint, pdel, rpdel, zm, kkvh, wsub, lcldn, lcldo, &
qaer, cflx, qaertend, qqcw, &
deltat)
cldo(:ncol,:)=cldn(:ncol,:)
#endif
!! initialize sub-step precip flux variables
do i=1,ncol
!! flux is zero at top interface, so these should stay as 0.
rflx1(i,1)=0._r8
sflx1(i,1)=0._r8
do k=1,pver
! initialize normal and sub-step precip flux variables
rflx1(i,k+1)=0._r8
sflx1(i,k+1)=0._r8
end do ! i loop
end do ! k loop
!! initialize final precip flux variables.
do i=1,ncol
!! flux is zero at top interface, so these should stay as 0.
rflx(i,1)=0._r8
sflx(i,1)=0._r8
do k=1,pver
! initialize normal and sub-step precip flux variables
rflx(i,k+1)=0._r8
sflx(i,k+1)=0._r8
end do ! i loop
end do ! k loop
do i=1,ncol
ltrue(i)=0
do k=1,pver
! skip microphysical calculations if no cloud water
if (qc(i,k).ge.qsmall.or.qi(i,k).ge.qsmall.or.cmei(i,k).ge.qsmall) ltrue(i)=1
end do
end do
! assign number of sub-steps to iter
! use 2 sub-steps, following tests described in MG2008
iter = 2
! get sub-step time step
deltat=deltat/real(iter)
! since activation/nucleation processes are fast, need to take into account
! factor mtime = mixing timescale in cloud / model time step
! mixing time can be interpreted as cloud depth divided by sub-grid vertical velocity
! for now mixing timescale is assumed to be 1 timestep for modal aerosols, 20 min bulk
#ifdef MODAL_AERO
mtime=1._r8
rate1ord_cw2pr_st(:,:)=0._r8 ! rce 2010/05/01
#else
mtime=deltat/1200._r8
#endif
!!!! skip calculations if no cloud water
do i=1,ncol
if (ltrue(i).eq.0) then
tlat(i,1:pver)=0._r8
qvlat(i,1:pver)=0._r8
qctend(i,1:pver)=0._r8
qitend(i,1:pver)=0._r8
qnitend(i,1:pver)=0._r8
qrtend(i,1:pver)=0._r8
nctend(i,1:pver)=0._r8
nitend(i,1:pver)=0._r8
nrtend(i,1:pver)=0._r8
nstend(i,1:pver)=0._r8
prect(i)=0._r8
preci(i)=0._r8
qniic(i,1:pver)=0._r8
qric(i,1:pver)=0._r8
nsic(i,1:pver)=0._r8
nric(i,1:pver)=0._r8
rainrt(i,1:pver)=0._r8
goto 300
end if
#ifdef MODAL_AERO
qcsinksum_rate1ord(1:pver)=0._r8 ! rce 2010/05/01
qcsum_rate1ord(1:pver)=0._r8 ! rce 2010/05/01
#endif
!!!!!!!!! begin sub-step!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!.....................................................................................................
do it=1,iter
! initialize sub-step microphysical tendencies
tlat(i,1:pver)=0._r8
qvlat(i,1:pver)=0._r8
qctend(i,1:pver)=0._r8
qitend(i,1:pver)=0._r8
qnitend(i,1:pver)=0._r8
qrtend(i,1:pver)=0._r8
nctend(i,1:pver)=0._r8
nitend(i,1:pver)=0._r8
nrtend(i,1:pver)=0._r8
nstend(i,1:pver)=0._r8
! initialize diagnostic precipitation to zero
qniic(i,1:pver)=0._r8
qric(i,1:pver)=0._r8
nsic(i,1:pver)=0._r8
nric(i,1:pver)=0._r8
rainrt(i,1:pver)=0._r8
! begin new i,k loop, calculate new cldmax after adjustment to cldm above
! initialize vertically-integrated rain and snow tendencies
qrtot = 0._r8
nrtot = 0._r8
qstot = 0._r8
nstot = 0._r8
! initialize precip at surface
prect(i)=0._r8
preci(i)=0._r8
do k=1,pver
! set cwml and cwmi to current qc and qi
cwml(i,k)=qc(i,k)
cwmi(i,k)=qi(i,k)
! initialize precip fallspeeds to zero
ums(k)=0._r8
uns(k)=0._r8
umr(k)=0._r8
unr(k)=0._r8
! calculate precip fraction based on maximum overlap assumption
if (k.eq.1) then
cldmax(i,k)=cldm(i,k)
else
! if rain or snow mix ratio is smaller than
! threshold, then set cldmax to cloud fraction at current level
if (qric(i,k-1).ge.qsmall.or.qniic(i,k-1).ge.qsmall) then
cldmax(i,k)=max(cldmax(i,k-1),cldm(i,k))
else
cldmax(i,k)=cldm(i,k)
end if
end if
! decrease in number concentration due to sublimation/evap
! divide by cloud fraction to get in-cloud decrease
! don't reduce Nc due to bergeron process
if (cmei(i,k) < 0._r8 .and. qi(i,k) > qsmall .and. cldm(i,k) > mincld) then
nsubi(k)=cmei(i,k)/qi(i,k)*ni(i,k)/cldm(i,k)
else
nsubi(k)=0._r8
end if
nsubc(k)=0._r8
!ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
!ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
! ice nucleation if activated nuclei exist at t<-5C AND rhmini + 5%
if (dum2i(i,k).gt.0._r8.and.t(i,k).lt.(tmelt - 5._r8).and. &
relhum(i,k)*esl(i,k)/esi(i,k).gt. rhmini+0.05_r8) then
!if NCAI > 0. then set numice = ncai (as before)
!note: this is gridbox averaged
nnuccd(k)=(dum2i(i,k)-ni(i,k)/icldm(i,k))/deltat*icldm(i,k)
nnuccd(k)=max(nnuccd(k),0._r8)
nimax = dum2i(i,k)*icldm(i,k)
!Calc mass of new particles using new crystal mass...
!also this will be multiplied by mtime as nnuccd is...
mnuccd(k) = nnuccd(k) * mi0
! add mnuccd to cmei....
cmei(i,k)= cmei(i,k) + mnuccd(k) * mtime
! limit cmei
qvi=epsqs*esi(i,k)/(p(i,k)-(1._r8-epsqs)*esi(i,k))
dqsidt = xxls*qvi/(rv*t(i,k)**2)
abi = 1._r8+dqsidt*xxls/cpp
cmei(i,k)=min(cmei(i,k),(q(i,k)-qvi)/abi/deltat)
! limit for roundoff error
cmei(i,k)=cmei(i,k)*omsm
else
nnuccd(k)=0._r8
nimax = 0._r8
mnuccd(k) = 0._r8
end if
!c............................................................................
!ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
! obtain in-cloud values of cloud water/ice mixing ratios and number concentrations
! for microphysical process calculations
! units are kg/kg for mixing ratio, 1/kg for number conc
! limit in-cloud values to 0.005 kg/kg
qcic(i,k)=min(cwml(i,k)/lcldm(i,k),5.e-3_r8)
qiic(i,k)=min(cwmi(i,k)/icldm(i,k),5.e-3_r8)
ncic(i,k)=max(nc(i,k)/lcldm(i,k),0._r8)
niic(i,k)=max(ni(i,k)/icldm(i,k),0._r8)
if (qc(i,k) - berg(i,k)*deltat.lt.qsmall) then
qcic(i,k)=0._r8
ncic(i,k)=0._r8
if (qc(i,k)-berg(i,k)*deltat.lt.0._r8) then
berg(i,k)=qc(i,k)/deltat*omsm
end if
end if
if (qi(i,k)+(cmei(i,k)+berg(i,k))*deltat.lt.qsmall) then
qiic(i,k)=0._r8
niic(i,k)=0._r8
if (qi(i,k)+(cmei(i,k)+berg(i,k))*deltat.lt.0._r8) then
cmei(i,k)=(-qi(i,k)/deltat-berg(i,k))*omsm
end if
end if
! add to cme output
cmeout(i,k) = cmeout(i,k)+cmei(i,k)
!ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
! droplet activation
! calculate potential for droplet activation if cloud water is present
! formulation from Abdul-Razzak and Ghan (2000) and Abdul-Razzak et al. (1998), AR98
! assume aerosols already activated are equal to number of existing droplets for simplicity
! multiply by cloud fraction to obtain grid-average tendency
#ifdef MODAL_AERO
if (qcic(i,k).ge.qsmall) then
npccn(k) = nctend_mixnuc(i,k)
npccn(k) = max(0._r8,npccn(k))
dum2l(i,k)=(nc(i,k)+npccn(k)*deltat)/cldm(i,k)
dum2l(i,k)=max(dum2l(i,k),cdnl/rho(i,k)) ! sghan minimum in #/cm3
ncmax = dum2l(i,k)*cldm(i,k)
else
npccn(k)=0._r8
dum2l(i,k)=0._r8
ncmax = 0._r8
end if
#else
if (qcic(i,k).ge.qsmall) then
npccn(k) = (dum2l(i,k)-nc(i,k)/lcldm(i,k))/deltat*lcldm(i,k)
! make sure number activated > 0
npccn(k) = max(0._r8,npccn(k))
ncmax = dum2l(i,k)*lcldm(i,k)
else
npccn(k)=0._r8
ncmax = 0._r8
end if
#endif
!ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
! get size distribution parameters based on in-cloud cloud water/ice
! these calculations also ensure consistency between number and mixing ratio
!cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
!......................................................................
! cloud ice
if (qiic(i,k).ge.qsmall) then
! add upper limit to in-cloud number concentration to prevent numerical error
niic(i,k)=min(niic(i,k),qiic(i,k)*1.e20_r8)
lami(k) = (cons1*ci* &
niic(i,k)/qiic(i,k))**(1._r8/di)
n0i(k) = niic(i,k)*lami(k)
! check for slope
! adjust vars
if (lami(k).lt.lammini) then
lami(k) = lammini
n0i(k) = lami(k)**(di+1._r8)*qiic(i,k)/(ci*cons1)
niic(i,k) = n0i(k)/lami(k)
else if (lami(k).gt.lammaxi) then
lami(k) = lammaxi
n0i(k) = lami(k)**(di+1._r8)*qiic(i,k)/(ci*cons1)
niic(i,k) = n0i(k)/lami(k)
end if
else
lami(k) = 0._r8
n0i(k) = 0._r8
end if
if (qcic(i,k).ge.qsmall) then
! add upper limit to in-cloud number concentration to prevent numerical error
ncic(i,k)=min(ncic(i,k),qcic(i,k)*1.e20_r8)
ncic(i,k)=max(ncic(i,k),cdnl/rho(i,k)) ! sghan minimum in #/cm
! get pgam from fit to observations of martin et al. 1994
! pgam(k)=0.0005714_r8*(ncic(i,k)/1.e6_r8/rho(i,k))+0.2714_r8
! hm fix, not active yet
pgam(k)=0.0005714_r8*(ncic(i,k)/1.e6_r8*rho(i,k))+0.2714_r8
pgam(k)=1._r8/(pgam(k)**2)-1._r8
pgam(k)=max(pgam(k),2._r8)
pgam(k)=min(pgam(k),15._r8)
! calculate lamc
lamc(k) = (pi/6._r8*rhow*ncic(i,k)*gamma
(pgam(k)+4._r8)/ &
(qcic(i,k)*gamma
(pgam(k)+1._r8)))**(1._r8/3._r8)
! lammin, 50 micron diameter max mean size
lammin = (pgam(k)+1._r8)/50.e-6_r8
lammax = (pgam(k)+1._r8)/2.e-6_r8
if (lamc(k).lt.lammin) then
lamc(k) = lammin
ncic(i,k) = 6._r8*lamc(k)**3*qcic(i,k)* &
gamma
(pgam(k)+1._r8)/ &
(pi*rhow*gamma
(pgam(k)+4._r8))
else if (lamc(k).gt.lammax) then
lamc(k) = lammax
ncic(i,k) = 6._r8*lamc(k)**3*qcic(i,k)* &
gamma
(pgam(k)+1._r8)/ &
(pi*rhow*gamma
(pgam(k)+4._r8))
end if
! parameter to calculate droplet freezing
cdist1(k) = ncic(i,k)/gamma
(pgam(k)+1._r8)
else
lamc(k) = 0._r8
cdist1(k) = 0._r8
end if
!cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
!cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
! begin micropysical process calculations
!.................................................................
! autoconversion of cloud liquid water to rain
! formula from Khrouditnov and Kogan (2000), modified for sub-grid distribution of qc
! minimum qc of 1 x 10^-8 prevents floating point error
if (qcic(i,k).ge.1.e-8_r8) then
! nprc is increase in rain number conc due to autoconversion
! nprc1 is decrease in cloud droplet conc due to autoconversion
! assume exponential sub-grid distribution of qc, resulting in additional
! factor related to qcvar below
prc(k) = cons2/(cons3*cons18)*1350._r8*qcic(i,k)**2.47_r8* &
(ncic(i,k)/1.e6_r8*rho(i,k))**(-1.79_r8)
! nprc(k) = prc(k)/(4._r8/3._r8*pi*rhow*(25.e-6_r8)**3)
nprc(k) = prc(k)/cons22
nprc1(k) = prc(k)/(qcic(i,k)/ncic(i,k))
else
prc(k)=0._r8
nprc(k)=0._r8
nprc1(k)=0._r8
end if
! add autoconversion to precip from above to get provisional rain mixing ratio
! and number concentration (qric and nric)
! 0.45 m/s is fallspeed of new rain drop (80 micron diameter)
dum=0.45_r8
dum1=0.45_r8
if (k.eq.1) then
qric(i,k)=prc(k)*lcldm(i,k)*dz(i,k)/cldmax(i,k)/dum
nric(i,k)=nprc(k)*lcldm(i,k)*dz(i,k)/cldmax(i,k)/dum
else
if (qric(i,k-1).ge.qsmall) then
dum=umr(k-1)
dum1=unr(k-1)
end if
! no autoconversion of rain number if rain/snow falling from above
! this assumes that new drizzle drops formed by autoconversion are rapidly collected
! by the existing rain/snow particles from above
if (qric(i,k-1).ge.1.e-9_r8.or.qniic(i,k-1).ge.1.e-9_r8) then
nprc(k)=0._r8
end if
qric(i,k) = (rho(i,k-1)*umr(k-1)*qric(i,k-1)*cldmax(i,k-1)+ &
(rho(i,k)*dz(i,k)*((pra(k-1)+prc(k))*lcldm(i,k)+(pre(k-1)-pracs(k-1)-mnuccr(k-1))*cldmax(i,k))))&
/(dum*rho(i,k)*cldmax(i,k))
nric(i,k) = (rho(i,k-1)*unr(k-1)*nric(i,k-1)*cldmax(i,k-1)+ &
(rho(i,k)*dz(i,k)*(nprc(k)*lcldm(i,k)+(nsubr(k-1)-npracs(k-1)-nnuccr(k-1)+nragg(k-1))*cldmax(i,k))))&
/(dum1*rho(i,k)*cldmax(i,k))
end if
!.......................................................................
! Autoconversion of cloud ice to snow
! similar to Ferrier (1994)
if (t(i,k).le.273.15_r8.and.qiic(i,k).ge.qsmall) then
! note: assumes autoconversion timescale of 180 sec
nprci(k) = n0i(k)/(lami(k)*180._r8)*exp(-lami(k)*dcs)
prci(k) = pi*rhoi*n0i(k)/(6._r8*180._r8)* &
(cons23/lami(k)+3._r8*cons24/lami(k)**2+ &
6._r8*dcs/lami(k)**3+6._r8/lami(k)**4)*exp(-lami(k)*dcs)
else
prci(k)=0._r8
nprci(k)=0._r8
end if
! add autoconversion to flux from level above to get provisional snow mixing ratio
! and number concentration (qniic and nsic)
dum=(asn(i,k)*cons25)
dum1=(asn(i,k)*cons25)
if (k.eq.1) then
qniic(i,k)=prci(k)*icldm(i,k)*dz(i,k)/cldmax(i,k)/dum
nsic(i,k)=nprci(k)*icldm(i,k)*dz(i,k)/cldmax(i,k)/dum
else
if (qniic(i,k-1).ge.qsmall) then
dum=ums(k-1)
dum1=uns(k-1)
end if
qniic(i,k) = (rho(i,k-1)*ums(k-1)*qniic(i,k-1)*cldmax(i,k-1)+ &
(rho(i,k)*dz(i,k)*((prci(k)+prai(k-1)+psacws(k-1)+bergs(k-1))*icldm(i,k)+(prds(k-1)+ &
pracs(k-1)+mnuccr(k-1))*cldmax(i,k))))&
/(dum*rho(i,k)*cldmax(i,k))
nsic(i,k) = (rho(i,k-1)*uns(k-1)*nsic(i,k-1)*cldmax(i,k-1)+ &
(rho(i,k)*dz(i,k)*(nprci(k)*icldm(i,k)+(nsubs(k-1)+nsagg(k-1)+nnuccr(k-1))*cldmax(i,k))))&
/(dum1*rho(i,k)*cldmax(i,k))
end if
! if precip mix ratio is zero so should number concentration
if (qniic(i,k).lt.qsmall) then
qniic(i,k)=0._r8
nsic(i,k)=0._r8
end if
if (qric(i,k).lt.qsmall) then
qric(i,k)=0._r8
nric(i,k)=0._r8
end if
! make sure number concentration is a positive number to avoid
! taking root of negative later
nric(i,k)=max(nric(i,k),0._r8)
nsic(i,k)=max(nsic(i,k),0._r8)
!.......................................................................
! get size distribution parameters for precip
!......................................................................
! rain
if (qric(i,k).ge.qsmall) then
lamr(k) = (pi*rhow*nric(i,k)/qric(i,k))**(1._r8/3._r8)
n0r(k) = nric(i,k)*lamr(k)
! check for slope
! adjust vars
if (lamr(k).lt.lamminr) then
lamr(k) = lamminr
n0r(k) = lamr(k)**4*qric(i,k)/(pi*rhow)
nric(i,k) = n0r(k)/lamr(k)
else if (lamr(k).gt.lammaxr) then
lamr(k) = lammaxr
n0r(k) = lamr(k)**4*qric(i,k)/(pi*rhow)
nric(i,k) = n0r(k)/lamr(k)
end if
! provisional rain number and mass weighted mean fallspeed (m/s)
unr(k) = min(arn(i,k)*cons4/lamr(k)**br,9.1_r8*rhof(i,k))
umr(k) = min(arn(i,k)*cons5/(6._r8*lamr(k)**br),9.1_r8*rhof(i,k))
else
lamr(k) = 0._r8
n0r(k) = 0._r8
umr(k) = 0._r8
unr(k) = 0._r8
end if
!......................................................................
! snow
if (qniic(i,k).ge.qsmall) then
lams(k) = (cons6*cs*nsic(i,k)/ &
qniic(i,k))**(1._r8/ds)
n0s(k) = nsic(i,k)*lams(k)
! check for slope
! adjust vars
if (lams(k).lt.lammins) then
lams(k) = lammins
n0s(k) = lams(k)**(ds+1._r8)*qniic(i,k)/(cs*cons6)
nsic(i,k) = n0s(k)/lams(k)
else if (lams(k).gt.lammaxs) then
lams(k) = lammaxs
n0s(k) = lams(k)**(ds+1._r8)*qniic(i,k)/(cs*cons6)
nsic(i,k) = n0s(k)/lams(k)
end if
! provisional snow number and mass weighted mean fallspeed (m/s)
ums(k) = min(asn(i,k)*cons8/(6._r8*lams(k)**bs),1.2_r8*rhof(i,k))
uns(k) = min(asn(i,k)*cons7/lams(k)**bs,1.2_r8*rhof(i,k))
else
lams(k) = 0._r8
n0s(k) = 0._r8
ums(k) = 0._r8
uns(k) = 0._r8
end if
!cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
! heterogeneous freezing of cloud water
if (qcic(i,k).ge.qsmall .and. t(i,k).lt.269.15_r8) then
! immersion freezing (Bigg, 1953)
mnuccc(k) = cons9/(cons3*cons19)* &
pi*pi/36._r8*rhow* &
cdist1(k)*gamma
(7._r8+pgam(k))* &
bimm*exp(aimm*(273.15_r8-t(i,k)))/ &
lamc(k)**3/lamc(k)**3
nnuccc(k) = cons10/(cons3*qcvar)* &
pi/6._r8*cdist1(k)*gamma
(pgam(k)+4._r8) &
*bimm* &
exp(aimm*(273.15_r8-t(i,k)))/lamc(k)**3
! contact freezing (-40<T<-3 C) (Young, 1974) with hooks into simulated dust
tcnt=(270.16_r8-t(i,k))**1.3_r8
viscosity=1.8e-5_r8*(t(i,k)/298.0_r8)**0.85_r8 ! Viscosity (kg/m/s)
mfp=2.0_r8*viscosity/(p(i,k) & ! Mean free path (m)
*sqrt(8.0_r8*28.96e-3_r8/(pi*8.314409_r8*t(i,k))))
slip1=1.0_r8+(mfp/rn_dst1)*(1.257_r8+(0.4_r8*Exp(-(1.1_r8*rn_dst1/mfp))))! Slip correction factor
slip2=1.0_r8+(mfp/rn_dst2)*(1.257_r8+(0.4_r8*Exp(-(1.1_r8*rn_dst2/mfp))))
slip3=1.0_r8+(mfp/rn_dst3)*(1.257_r8+(0.4_r8*Exp(-(1.1_r8*rn_dst3/mfp))))
slip4=1.0_r8+(mfp/rn_dst4)*(1.257_r8+(0.4_r8*Exp(-(1.1_r8*rn_dst4/mfp))))
dfaer1=1.381e-23_r8*t(i,k)*slip1/(6._r8*pi*viscosity*rn_dst1) ! aerosol diffusivity (m2/s)
dfaer2=1.381e-23_r8*t(i,k)*slip2/(6._r8*pi*viscosity*rn_dst2)
dfaer3=1.381e-23_r8*t(i,k)*slip3/(6._r8*pi*viscosity*rn_dst3)
dfaer4=1.381e-23_r8*t(i,k)*slip4/(6._r8*pi*viscosity*rn_dst4)
nacon1=0.0_r8
nacon2=0.0_r8
nacon3=0.0_r8
nacon4=0.0_r8
!use size '3' for dust coarse mode...
!scale by dust fraction in coarse mode
#ifdef MODAL_AERO
dmc= qaer(i,k,lptr_dust_a_amode(modeptr_coarse))
ssmc=qaer(i,k,lptr_nacl_a_amode(modeptr_coarse))
if (dmc.gt.0.0_r8) then
nacon3=dmc/(ssmc+dmc) * qaer(i,k,numptr_amode(modeptr_coarse))*rho(i,k)*tcnt
else
nacon3=0._r8
endif
!also redefine parameters based on size...
dstrn=0.5_r8*dgnumwet(i,k,modeptr_coarse)
if (dstrn.le.0._r8) then
dstrn=rn_dst3
endif
slip3=1.0_r8+(mfp/dstrn)*(1.257_r8+(0.4_r8*Exp(-(1.1_r8*dstrn/mfp))))
dfaer3=1.381e-23_r8*t(i,k)*slip3/(6._r8*pi*viscosity*dstrn)
#else
if (idxdst1.gt.0) then
nacon1=naer2(i,k,idxdst1)*tcnt *0.0_r8
endif
if (idxdst2.gt.0) then
nacon2=naer2(i,k,idxdst2)*tcnt ! 1/m3
endif
if (idxdst3.gt.0) then
nacon3=naer2(i,k,idxdst3)*tcnt
endif
if (idxdst4.gt.0) then
nacon4=naer2(i,k,idxdst4)*tcnt
endif
#endif
mnucct(k) = cons10/(cons3*qcvar)* &
(dfaer1*nacon1+dfaer2*nacon2+dfaer3*nacon3+dfaer4*nacon4)*pi*pi/3._r8*rhow* &
cdist1(k)*gamma
(pgam(k)+5._r8)/lamc(k)**4
nnucct(k) = (dfaer1*nacon1+dfaer2*nacon2+dfaer3*nacon3+dfaer4*nacon4)*2._r8*pi* &
cdist1(k)*gamma
(pgam(k)+2._r8)/lamc(k)
! make sure number of droplets frozen does not exceed available ice nuclei concentration
! this prevents 'runaway' droplet freezing
if (nnuccc(k)*lcldm(i,k).gt.nnuccd(k)) then
dum=(nnuccd(k)/(nnuccc(k)*lcldm(i,k)))
! scale mixing ratio of droplet freezing with limit
mnuccc(k)=mnuccc(k)*dum
nnuccc(k)=nnuccd(k)/lcldm(i,k)
end if
else
mnuccc(k)=0._r8
nnuccc(k)=0._r8
mnucct(k)=0._r8
nnucct(k)=0._r8
end if
!.......................................................................
! snow self-aggregation from passarelli, 1978, used by reisner, 1998
! this is hard-wired for bs = 0.4 for now
! ignore self-collection of cloud ice
if (qniic(i,k).ge.qsmall .and. t(i,k).le.273.15_r8) then
nsagg(k) = -1108._r8*asn(i,k)*Eii* &
pi**((1._r8-bs)/3._r8)*rhosn**((-2._r8-bs)/3._r8)*rho(i,k)** &
((2._r8+bs)/3._r8)*qniic(i,k)**((2._r8+bs)/3._r8)* &
(nsic(i,k)*rho(i,k))**((4._r8-bs)/3._r8)/ &
(4._r8*720._r8*rho(i,k))
else
nsagg(k)=0._r8
end if
!.......................................................................
! accretion of cloud droplets onto snow/graupel
! here use continuous collection equation with
! simple gravitational collection kernel
! ignore collisions between droplets/cloud ice
! since minimum size ice particle for accretion is 50 - 150 micron
! ignore collision of snow with droplets above freezing
if (qniic(i,k).ge.qsmall .and. t(i,k).le.tmelt .and. &
qcic(i,k).ge.qsmall) then
! put in size dependent collection efficiency
! mean diameter of snow is area-weighted, since
! accretion is function of crystal geometric area
! collection efficiency is approximation based on stoke's law (Thompson et al. 2004)
dc0 = (pgam(k)+1._r8)/lamc(k)
ds0 = 1._r8/lams(k)
dum = dc0*dc0*uns(k)*rhow/(9._r8*mu(i,k)*ds0)
eci = dum*dum/((dum+0.4_r8)*(dum+0.4_r8))
eci = max(eci,0._r8)
eci = min(eci,1._r8)
! no impact of sub-grid distribution of qc since psacws
! is linear in qc
psacws(k) = pi/4._r8*asn(i,k)*qcic(i,k)*rho(i,k)* &
n0s(k)*Eci*cons11/ &
lams(k)**(bs+3._r8)
npsacws(k) = pi/4._r8*asn(i,k)*ncic(i,k)*rho(i,k)* &
n0s(k)*Eci*cons11/ &
lams(k)**(bs+3._r8)
else
psacws(k)=0._r8
npsacws(k)=0._r8
end if
! add secondary ice production due to accretion of droplets by snow
! (Hallet-Mossop process) (from Cotton et al., 1986)
if((t(i,k).lt.270.16_r8) .and. (t(i,k).ge.268.16_r8)) then
ni_secp = 3.5e8_r8*(270.16_r8-t(i,k))/2.0_r8*psacws(k)
nsacwi(k) = ni_secp
msacwi(k) = min(ni_secp*mi0,psacws(k))
else if((t(i,k).lt.268.16_r8) .and. (t(i,k).ge.265.16_r8)) then
ni_secp = 3.5e8_r8*(t(i,k)-265.16_r8)/3.0_r8*psacws(k)
nsacwi(k) = ni_secp
msacwi(k) = min(ni_secp*mi0,psacws(k))
else
ni_secp = 0.0_r8
nsacwi(k) = 0.0_r8
msacwi(k) = 0.0_r8
endif
psacws(k) = max(0.0_r8,psacws(k)-ni_secp*mi0)
!.......................................................................
! accretion of rain water by snow
! formula from ikawa and saito, 1991, used by reisner et al., 1998
if (qric(i,k).ge.1.e-8_r8 .and. qniic(i,k).ge.1.e-8_r8 .and. &
t(i,k).le.273.15_r8) then
pracs(k) = pi*pi*ecr*(((1.2_r8*umr(k)-0.95_r8*ums(k))**2+ &
0.08_r8*ums(k)*umr(k))**0.5_r8*rhow*rho(i,k)* &
n0r(k)*n0s(k)* &
(5._r8/(lamr(k)**6*lams(k))+ &
2._r8/(lamr(k)**5*lams(k)**2)+ &
0.5_r8/(lamr(k)**4*lams(k)**3)))
npracs(k) = pi/2._r8*rho(i,k)*ecr*(1.7_r8*(unr(k)-uns(k))**2+ &
0.3_r8*unr(k)*uns(k))**0.5_r8*n0r(k)*n0s(k)* &
(1._r8/(lamr(k)**3*lams(k))+ &
1._r8/(lamr(k)**2*lams(k)**2)+ &
1._r8/(lamr(k)*lams(k)**3))
else
pracs(k)=0._r8
npracs(k)=0._r8
end if
!.......................................................................
! heterogeneous freezing of rain drops
! follows from Bigg (1953)
if (t(i,k).lt.269.15_r8 .and. qric(i,k).ge.qsmall) then
mnuccr(k) = 20._r8*pi*pi*rhow*nric(i,k)*bimm* &
exp(aimm*(273.15_r8-t(i,k)))/lamr(k)**3 &
/lamr(k)**3
nnuccr(k) = pi*nric(i,k)*bimm* &
exp(aimm*(273.15_r8-t(i,k)))/lamr(k)**3
else
mnuccr(k)=0._r8
nnuccr(k)=0._r8
end if
!.......................................................................
! accretion of cloud liquid water by rain
! formula from Khrouditnov and Kogan (2000)
! gravitational collection kernel, droplet fall speed neglected
if (qric(i,k).ge.qsmall .and. qcic(i,k).ge.qsmall) then
! include sub-grid distribution of cloud water
pra(k) = cons12/(cons3*cons20)* &
67._r8*(qcic(i,k)*qric(i,k))**1.15_r8
npra(k) = pra(k)/(qcic(i,k)/ncic(i,k))
else
pra(k)=0._r8
npra(k)=0._r8
end if
!.......................................................................
! Self-collection of rain drops
! from Beheng(1994)
if (qric(i,k).ge.qsmall) then
nragg(k) = -8._r8*nric(i,k)*qric(i,k)*rho(i,k)
else
nragg(k)=0._r8
end if
!.......................................................................
! Accretion of cloud ice by snow
! For this calculation, it is assumed that the Vs >> Vi
! and Ds >> Di for continuous collection
if (qniic(i,k).ge.qsmall.and.qiic(i,k).ge.qsmall &
.and.t(i,k).le.273.15_r8) then
prai(k) = pi/4._r8*asn(i,k)*qiic(i,k)*rho(i,k)* &
n0s(k)*Eii*cons11/ &
lams(k)**(bs+3._r8)
nprai(k) = pi/4._r8*asn(i,k)*niic(i,k)* &
rho(i,k)*n0s(k)*Eii*cons11/ &
lams(k)**(bs+3._r8)
else
prai(k)=0._r8
nprai(k)=0._r8
end if
!ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
! calculate evaporation/sublimation of rain and snow
! note: evaporation/sublimation occurs only in cloud-free portion of grid cell
! in-cloud condensation/deposition of rain and snow is neglected
! except for transfer of cloud water to snow through bergeron process
! initialize evap/sub tendncies
pre(k)=0._r8
prds(k)=0._r8
! evaporation of rain
! only calculate if there is some precip fraction > cloud fraction
if (qcic(i,k)+qiic(i,k).lt.1.e-6_r8.or.cldmax(i,k).gt.lcldm(i,k)) then
! set temporary cloud fraction to zero if cloud water + ice is very small
! this will ensure that evaporation/sublimation of precip occurs over
! entire grid cell, since min cloud fraction is specified otherwise
if (qcic(i,k)+qiic(i,k).lt.1.e-6_r8) then
dum=0._r8
else
dum=lcldm(i,k)
end if
! saturation vapor pressure
esn=polysvp
(t(i,k),0)
qsn=min(epsqs*esn/(p(i,k)-(1._r8-epsqs)*esn),1._r8)
! recalculate saturation vapor pressure for liquid and ice
esl(i,k)=esn
esi(i,k)=polysvp
(t(i,k),1)
! hm fix, make sure when above freezing that esi=esl, not active yet
if (t(i,k).gt.tmelt)esi(i,k)=esl(i,k)
! calculate q for out-of-cloud region
qclr=(q(i,k)-dum*qsn)/(1._r8-dum)
if (qric(i,k).ge.qsmall) then
qvs=epsqs*esl(i,k)/(p(i,k)-(1._r8-epsqs)*esl(i,k))
dqsdt = xxlv*qvs/(rv*t(i,k)**2)
ab = 1._r8+dqsdt*xxlv/cpp
epsr = 2._r8*pi*n0r(k)*rho(i,k)*Dv(i,k)* &
(f1r/(lamr(k)*lamr(k))+ &
f2r*(arn(i,k)*rho(i,k)/mu(i,k))**0.5_r8* &
sc(i,k)**(1._r8/3._r8)*cons13/ &
(lamr(k)**(5._r8/2._r8+br/2._r8)))
pre(k) = epsr*(qclr-qvs)/ab
! only evaporate in out-of-cloud region
! and distribute across cldmax
pre(k)=min(pre(k)*(cldmax(i,k)-dum),0._r8)
pre(k)=pre(k)/cldmax(i,k)
end if
! sublimation of snow
if (qniic(i,k).ge.qsmall) then
qvi=epsqs*esi(i,k)/(p(i,k)-(1._r8-epsqs)*esi(i,k))
dqsidt = xxls*qvi/(rv*t(i,k)**2)
abi = 1._r8+dqsidt*xxls/cpp
epss = 2._r8*pi*n0s(k)*rho(i,k)*Dv(i,k)* &
(f1s/(lams(k)*lams(k))+ &
f2s*(asn(i,k)*rho(i,k)/mu(i,k))**0.5_r8* &
sc(i,k)**(1._r8/3._r8)*cons14/ &
(lams(k)**(5._r8/2._r8+bs/2._r8)))
prds(k) = epss*(qclr-qvi)/abi
! only sublimate in out-of-cloud region and distribute over cldmax
prds(k)=min(prds(k)*(cldmax(i,k)-dum),0._r8)
prds(k)=prds(k)/cldmax(i,k)
end if
! make sure RH not pushed above 100% due to rain evaporation/snow sublimation
! get updated RH at end of time step based on cloud water/ice condensation/evap
qtmp=q(i,k)-(cmei(i,k)+(pre(k)+prds(k))*cldmax(i,k))*deltat
ttmp=t(i,k)+((pre(k)*cldmax(i,k))*xxlv+ &
(cmei(i,k)+prds(k)*cldmax(i,k))*xxls)*deltat/cpp
!limit range of temperatures!
ttmp=max(180._r8,min(ttmp,323._r8))
esn=polysvp
(ttmp,0) ! use rhw to allow ice supersaturation
qsn=min(epsqs*esn/(p(i,k)-(1._r8-epsqs)*esn),1._r8)
! modify precip evaporation rate if q > qsat
if (qtmp.gt.qsn) then
if (pre(k)+prds(k).lt.-1.e-20) then
dum1=pre(k)/(pre(k)+prds(k))
! recalculate q and t after cloud water cond but without precip evap
qtmp=q(i,k)-(cmei(i,k))*deltat
ttmp=t(i,k)+(cmei(i,k)*xxls)*deltat/cpp
esn=polysvp
(ttmp,0) ! use rhw to allow ice supersaturation
qsn=min(epsqs*esn/(p(i,k)-(1._r8-epsqs)*esn),1._r8)
dum=(qtmp-qsn)/(1._r8 + cons27*qsn/(cpp*rv*ttmp**2))
dum=min(dum,0._r8)
! modify rates if needed, divide by cldmax to get local (in-precip) value
pre(k)=dum*dum1/deltat/cldmax(i,k)
! do separately using RHI for prds....
esn=polysvp
(ttmp,1) ! use rhi to allow ice supersaturation
qsn=min(epsqs*esn/(p(i,k)-(1._r8-epsqs)*esn),1._r8)
dum=(qtmp-qsn)/(1._r8 + cons28*qsn/(cpp*rv*ttmp**2))
dum=min(dum,0._r8)
! modify rates if needed, divide by cldmax to get local (in-precip) value
prds(k)=dum*(1._r8-dum1)/deltat/cldmax(i,k)
end if
end if
end if
! bergeron process - evaporation of droplets and deposition onto snow
if (qniic(i,k).ge.qsmall.and.qcic(i,k).ge.qsmall.and.t(i,k).lt.tmelt) then
qvi=epsqs*esi(i,k)/(p(i,k)-(1._r8-epsqs)*esi(i,k))
qvs=epsqs*esl(i,k)/(p(i,k)-(1._r8-epsqs)*esl(i,k))
dqsidt = xxls*qvi/(rv*t(i,k)**2)
abi = 1._r8+dqsidt*xxls/cpp
epss = 2._r8*pi*n0s(k)*rho(i,k)*Dv(i,k)* &
(f1s/(lams(k)*lams(k))+ &
f2s*(asn(i,k)*rho(i,k)/mu(i,k))**0.5_r8* &
sc(i,k)**(1._r8/3._r8)*cons14/ &
(lams(k)**(5._r8/2._r8+bs/2._r8)))
bergs(k)=epss*(qvs-qvi)/abi
else
bergs(k)=0._r8
end if
!cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
! conservation to ensure no negative values of cloud water/precipitation
! in case microphysical process rates are large
! make sure and use end-of-time step values for cloud water, ice, due
! condensation/deposition
! note: for check on conservation, processes are multiplied by omsm
! to prevent problems due to round off error
! include mixing timescale (mtime)
qce=(qc(i,k) - berg(i,k)*deltat)
nce=(nc(i,k)+npccn(k)*deltat*mtime)
qie=(qi(i,k)+(cmei(i,k)+berg(i,k))*deltat)
nie=(ni(i,k)+nnuccd(k)*deltat*mtime)
! conservation of qc
dum = (prc(k)+pra(k)+mnuccc(k)+mnucct(k)+msacwi(k)+ &
psacws(k)+bergs(k))*lcldm(i,k)*deltat
if (dum.gt.qce) then
ratio = qce/deltat/lcldm(i,k)/(prc(k)+pra(k)+mnuccc(k)+mnucct(k)+msacwi(k)+psacws(k)+bergs(k))*omsm
prc(k) = prc(k)*ratio
pra(k) = pra(k)*ratio
mnuccc(k) = mnuccc(k)*ratio
mnucct(k) = mnucct(k)*ratio
msacwi(k) = msacwi(k)*ratio
psacws(k) = psacws(k)*ratio
bergs(k) = bergs(k)*ratio
end if
! conservation of nc
dum = (nprc1(k)+npra(k)+nnuccc(k)+nnucct(k)+ &
npsacws(k)-nsubc(k))*lcldm(i,k)*deltat
if (dum.gt.nce) then
ratio = nce/deltat/((nprc1(k)+npra(k)+nnuccc(k)+nnucct(k)+&
npsacws(k)-nsubc(k))*lcldm(i,k))*omsm
nprc1(k) = nprc1(k)*ratio
npra(k) = npra(k)*ratio
nnuccc(k) = nnuccc(k)*ratio
nnucct(k) = nnucct(k)*ratio !++xl
npsacws(k) = npsacws(k)*ratio
nsubc(k)=nsubc(k)*ratio
end if
! conservation of qi
dum = ((-mnuccc(k)-mnucct(k)-msacwi(k))*lcldm(i,k)+(prci(k)+ &
prai(k))*icldm(i,k))*deltat
if (dum.gt.qie) then
ratio = (qie/deltat+(mnuccc(k)+mnucct(k)+msacwi(k))*lcldm(i,k))/((prci(k)+prai(k))*icldm(i,k))*omsm
prci(k) = prci(k)*ratio
prai(k) = prai(k)*ratio
end if
! conservation of ni
dum = ((-nnucct(k)-nsacwi(k))*lcldm(i,k)+(nprci(k)+ &
nprai(k)-nsubi(k))*icldm(i,k))*deltat
if (dum.gt.nie) then
ratio = (nie/deltat+(nnucct(k)+nsacwi(k))*lcldm(i,k))/ &
((nprci(k)+nprai(k)-nsubi(k))*icldm(i,k))*omsm
nprci(k) = nprci(k)*ratio
nprai(k) = nprai(k)*ratio
nsubi(k) = nsubi(k)*ratio
end if
! for preciptiation conservation, use logic that vertical integral
! of tendency from current level to top of model (i.e., qrtot) cannot be negative
! conservation of rain mixing rat
if (((prc(k)+pra(k))*lcldm(i,k)+(-mnuccr(k)+pre(k)-pracs(k))*&
cldmax(i,k))*dz(i,k)*rho(i,k)+qrtot.lt.0._r8) then
if (-pre(k)+pracs(k)+mnuccr(k).ge.qsmall) then
ratio = (qrtot/(dz(i,k)*rho(i,k))+(prc(k)+pra(k))*lcldm(i,k))/&
((-pre(k)+pracs(k)+mnuccr(k))*cldmax(i,k))*omsm
pre(k) = pre(k)*ratio
pracs(k) = pracs(k)*ratio
mnuccr(k) = mnuccr(k)*ratio
end if
end if
! conservation of nr
! for now neglect evaporation of nr
nsubr(k)=0._r8
if ((nprc(k)*lcldm(i,k)+(-nnuccr(k)+nsubr(k)-npracs(k)&
+nragg(k))*cldmax(i,k))*dz(i,k)*rho(i,k)+nrtot.lt.0._r8) then
if (-nsubr(k)-nragg(k)+npracs(k)+nnuccr(k).ge.qsmall) then
ratio = (nrtot/(dz(i,k)*rho(i,k))+nprc(k)*lcldm(i,k))/&
((-nsubr(k)-nragg(k)+npracs(k)+nnuccr(k))*cldmax(i,k))*omsm
nsubr(k) = nsubr(k)*ratio
npracs(k) = npracs(k)*ratio
nnuccr(k) = nnuccr(k)*ratio
nragg(k) = nragg(k)*ratio
end if
end if
! conservation of snow mix ratio
if (((bergs(k)+psacws(k))*lcldm(i,k)+(prai(k)+prci(k))*icldm(i,k)+(pracs(k)+&
mnuccr(k)+prds(k))*cldmax(i,k))*dz(i,k)*rho(i,k)+qstot.lt.0._r8) then
if (-prds(k).ge.qsmall) then
ratio = (qstot/(dz(i,k)*rho(i,k))+(bergs(k)+psacws(k))*lcldm(i,k)+(prai(k)+prci(k))*icldm(i,k)+&
(pracs(k)+mnuccr(k))*cldmax(i,k))/(-prds(k)*cldmax(i,k))*omsm
prds(k) = prds(k)*ratio
end if
end if
! conservation of ns
! calculate loss of number due to sublimation
! for now neglect sublimation of ns
nsubs(k)=0._r8
if ((nprci(k)*icldm(i,k)+(nnuccr(k)+nsubs(k)+nsagg(k))*cldmax(i,k))*&
dz(i,k)*rho(i,k)+nstot.lt.0._r8) then
if (-nsubs(k)-nsagg(k).ge.qsmall) then
ratio = (nstot/(dz(i,k)*rho(i,k))+nprci(k)*icldm(i,k)+&
nnuccr(k)*cldmax(i,k))/((-nsubs(k)-nsagg(k))*cldmax(i,k))*omsm
nsubs(k) = nsubs(k)*ratio
nsagg(k) = nsagg(k)*ratio
end if
end if
! get tendencies due to microphysical conversion processes
! note: tendencies are multiplied by appropaiate cloud/precip
! fraction to get grid-scale values
! note: cmei is already grid-average values
qvlat(i,k) = qvlat(i,k)- &
(pre(k)+prds(k))*cldmax(i,k)-cmei(i,k)
tlat(i,k) = tlat(i,k)+((pre(k)*cldmax(i,k)) &
*xxlv+(prds(k)*cldmax(i,k)+cmei(i,k))*xxls+ &
((bergs(k)+psacws(k)+mnuccc(k)+mnucct(k)+msacwi(k))*lcldm(i,k)+(mnuccr(k)+ &
pracs(k))*cldmax(i,k)+berg(i,k))*xlf)
qctend(i,k) = qctend(i,k)+ &
(-pra(k)-prc(k)-mnuccc(k)-mnucct(k)-msacwi(k)- &
psacws(k)-bergs(k))*lcldm(i,k)-berg(i,k)
qitend(i,k) = qitend(i,k)+ &
(mnuccc(k)+mnucct(k)+msacwi(k))*lcldm(i,k)+(-prci(k)- &
prai(k))*icldm(i,k)+cmei(i,k)+berg(i,k)
qrtend(i,k) = qrtend(i,k)+ &
(pra(k)+prc(k))*lcldm(i,k)+(pre(k)-pracs(k)- &
mnuccr(k))*cldmax(i,k)
qnitend(i,k) = qnitend(i,k)+ &
(prai(k)+prci(k))*icldm(i,k)+(psacws(k)+bergs(k))*lcldm(i,k)+(prds(k)+ &
pracs(k)+mnuccr(k))*cldmax(i,k)
! add output for cmei (accumulate)
cmeiout(i,k) = cmeiout(i,k) + cmei(i,k)
! assign variables for trop_mozart, these are grid-average
! evaporation/sublimation is stored here as positive term
evapsnow(i,k) = evapsnow(i,k)-prds(k)*cldmax(i,k)
nevapr(i,k) = nevapr(i,k)-pre(k)*cldmax(i,k)
! change to make sure prain is positive: do not remove snow from
! prain used for wet deposition
prain(i,k) = prain(i,k)+(pra(k)+prc(k))*lcldm(i,k)+(-pracs(k)- &
mnuccr(k))*cldmax(i,k)
prodsnow(i,k) = prodsnow(i,k)+(prai(k)+prci(k))*icldm(i,k)+(psacws(k)+bergs(k))*lcldm(i,k)+(&
pracs(k)+mnuccr(k))*cldmax(i,k)
#ifdef MODAL_AERO
! rce 2010/05/01
! following are used to calculate 1st order conversion rate of cloud water
! to rain and snow (1/s), for later use in aerosol wet removal routine
! previously, wetdepa used (prain/qc) for this, and the qc in wetdepa may be smaller than the qc
! used to calculate pra, prc, ... in this routine
! qcsinksum_rate1ord = sum over iterations{ rate of direct transfer of cloud water to rain & snow }
! (no cloud ice or bergeron terms)
! qcsum_rate1ord = sum over iterations{ qc used in calculation of the transfer terms }
qcsinksum_rate1ord(k) = qcsinksum_rate1ord(k) + (pra(k)+prc(k)+psacws(k))*lcldm(i,k) ! rce 2010/05/01
qcsum_rate1ord(k) = qcsum_rate1ord(k) + qc(i,k) ! rce 2010/05/01
#endif
! microphysics output, note this is grid-averaged
prao(i,k)=prao(i,k)+pra(k)*lcldm(i,k)
prco(i,k)=prco(i,k)+prc(k)*lcldm(i,k)
mnuccco(i,k)=mnuccco(i,k)+mnuccc(k)*lcldm(i,k)
mnuccto(i,k)=mnuccto(i,k)+mnucct(k)*lcldm(i,k)
msacwio(i,k)=msacwio(i,k)+msacwi(k)*lcldm(i,k)
psacwso(i,k)=psacwso(i,k)+psacws(k)*lcldm(i,k)
bergso(i,k)=bergso(i,k)+bergs(k)*lcldm(i,k)
bergo(i,k)=bergo(i,k)+berg(i,k)
prcio(i,k)=prcio(i,k)+prci(k)*icldm(i,k)
praio(i,k)=praio(i,k)+prai(k)*icldm(i,k)
mnuccro(i,k)=mnuccro(i,k)+mnuccr(k)*cldmax(i,k)
pracso (i,k)=pracso (i,k)+pracs (k)*cldmax(i,k)
! multiply activation/nucleation by mtime to account for fast timescale
nctend(i,k) = nctend(i,k)+ npccn(k)*mtime+&
(-nnuccc(k)-nnucct(k)-npsacws(k)+nsubc(k) &
-npra(k)-nprc1(k))*lcldm(i,k)
nitend(i,k) = nitend(i,k)+ nnuccd(k)*mtime+ &
(nnucct(k)+nsacwi(k))*lcldm(i,k)+(nsubi(k)-nprci(k)- &
nprai(k))*icldm(i,k)
nstend(i,k) = nstend(i,k)+(nsubs(k)+ &
nsagg(k)+nnuccr(k))*cldmax(i,k)+nprci(k)*icldm(i,k)
nrtend(i,k) = nrtend(i,k)+ &
nprc(k)*lcldm(i,k)+(nsubr(k)-npracs(k)-nnuccr(k) &
+nragg(k))*cldmax(i,k)
! make sure that nc and ni at advanced time step do not exceed
! maximum (existing N + source terms*dt), which is possible due to
! fast nucleation timescale
if (nctend(i,k).gt.0._r8.and.nc(i,k)+nctend(i,k)*deltat.gt.ncmax) then
nctend(i,k)=max(0._r8,(ncmax-nc(i,k))/deltat)
end if
if (nitend(i,k).gt.0._r8.and.ni(i,k)+nitend(i,k)*deltat.gt.nimax) then
nitend(i,k)=max(0._r8,(nimax-ni(i,k))/deltat)
end if
! get final values for precipitation q and N, based on
! flux of precip from above, source/sink term, and terminal fallspeed
! see eq. 15-16 in MG2008
! rain
if (qric(i,k).ge.qsmall) then
if (k.eq.1) then
qric(i,k)=qrtend(i,k)*dz(i,k)/cldmax(i,k)/umr(k)
nric(i,k)=nrtend(i,k)*dz(i,k)/cldmax(i,k)/unr(k)
else
qric(i,k) = (rho(i,k-1)*umr(k-1)*qric(i,k-1)*cldmax(i,k-1)+ &
(rho(i,k)*dz(i,k)*qrtend(i,k)))/(umr(k)*rho(i,k)*cldmax(i,k))
nric(i,k) = (rho(i,k-1)*unr(k-1)*nric(i,k-1)*cldmax(i,k-1)+ &
(rho(i,k)*dz(i,k)*nrtend(i,k)))/(unr(k)*rho(i,k)*cldmax(i,k))
end if
else
qric(i,k)=0._r8
nric(i,k)=0._r8
end if
! snow
if (qniic(i,k).ge.qsmall) then
if (k.eq.1) then
qniic(i,k)=qnitend(i,k)*dz(i,k)/cldmax(i,k)/ums(k)
nsic(i,k)=nstend(i,k)*dz(i,k)/cldmax(i,k)/uns(k)
else
qniic(i,k) = (rho(i,k-1)*ums(k-1)*qniic(i,k-1)*cldmax(i,k-1)+ &
(rho(i,k)*dz(i,k)*qnitend(i,k)))/(ums(k)*rho(i,k)*cldmax(i,k))
nsic(i,k) = (rho(i,k-1)*uns(k-1)*nsic(i,k-1)*cldmax(i,k-1)+ &
(rho(i,k)*dz(i,k)*nstend(i,k)))/(uns(k)*rho(i,k)*cldmax(i,k))
end if
else
qniic(i,k)=0._r8
nsic(i,k)=0._r8
end if
! calculate precipitation flux at surface
! divide by density of water to get units of m/s
prect(i) = prect(i)+(qrtend(i,k)*dz(i,k)*rho(i,k)+&
qnitend(i,k)*dz(i,k)*rho(i,k))/rhow
preci(i) = preci(i)+qnitend(i,k)*dz(i,k)*rho(i,k)/rhow
! convert rain rate from m/s to mm/hr
rainrt(i,k)=qric(i,k)*rho(i,k)*umr(k)/rhow*3600._r8*1000._r8
! vertically-integrated precip source/sink terms (note: grid-averaged)
qrtot = max(qrtot+qrtend(i,k)*dz(i,k)*rho(i,k),0._r8)
qstot = max(qstot+qnitend(i,k)*dz(i,k)*rho(i,k),0._r8)
nrtot = max(nrtot+nrtend(i,k)*dz(i,k)*rho(i,k),0._r8)
nstot = max(nstot+nstend(i,k)*dz(i,k)*rho(i,k),0._r8)
! calculate melting and freezing of precip
! melt snow at +2 C
if (t(i,k)+tlat(i,k)/cp*deltat > 275.15_r8) then
if (qstot > 0._r8) then
! make sure melting snow doesn't reduce temperature below threshold
dum = -xlf/cp*qstot/(dz(i,k)*rho(i,k))
if (t(i,k)+tlat(i,k)/cp*deltat+dum.lt.275.15_r8) then
dum = (t(i,k)+tlat(i,k)/cp*deltat-275.15_r8)*cp/xlf
dum = dum/(xlf/cp*qstot/(dz(i,k)*rho(i,k)))
dum = max(0._r8,dum)
dum = min(1._r8,dum)
else
dum = 1._r8
end if
qric(i,k)=qric(i,k)+dum*qniic(i,k)
nric(i,k)=nric(i,k)+dum*nsic(i,k)
qniic(i,k)=(1._r8-dum)*qniic(i,k)
nsic(i,k)=(1._r8-dum)*nsic(i,k)
! heating tendency
tmp=-xlf*dum*qstot/(dz(i,k)*rho(i,k))
meltsdt(i,k)=meltsdt(i,k) + tmp
tlat(i,k)=tlat(i,k)+tmp
qrtot=qrtot+dum*qstot
nrtot=nrtot+dum*nstot
qstot=(1._r8-dum)*qstot
nstot=(1._r8-dum)*nstot
preci(i)=(1._r8-dum)*preci(i)
end if
end if
! freeze all rain at -5C for Arctic
if (t(i,k)+tlat(i,k)/cp*deltat < (tmelt - 5._r8)) then
if (qrtot > 0._r8) then
! make sure freezing rain doesn't increase temperature above threshold
dum = xlf/cp*qrtot/(dz(i,k)*rho(i,k))
if (t(i,k)+tlat(i,k)/cp*deltat+dum.gt.(tmelt - 5._r8)) then
dum = -(t(i,k)+tlat(i,k)/cp*deltat-(tmelt-5._r8))*cp/xlf
dum = dum/(xlf/cp*qrtot/(dz(i,k)*rho(i,k)))
dum = max(0._r8,dum)
dum = min(1._r8,dum)
else
dum = 1._r8
end if
qniic(i,k)=qniic(i,k)+dum*qric(i,k)
nsic(i,k)=nsic(i,k)+dum*nric(i,k)
qric(i,k)=(1._r8-dum)*qric(i,k)
nric(i,k)=(1._r8-dum)*nric(i,k)
! heating tendency
tmp = xlf*dum*qrtot/(dz(i,k)*rho(i,k))
frzrdt(i,k)=frzrdt(i,k) + tmp
tlat(i,k)=tlat(i,k)+tmp
qstot=qstot+dum*qrtot
qrtot=(1._r8-dum)*qrtot
nstot=nstot+dum*nrtot
nrtot=(1._r8-dum)*nrtot
preci(i)=preci(i)+dum*(prect(i)-preci(i))
end if
end if
! if rain/snow mix ratio is zero so should number concentration
if (qniic(i,k).lt.qsmall) then
qniic(i,k)=0._r8
nsic(i,k)=0._r8
end if
if (qric(i,k).lt.qsmall) then
qric(i,k)=0._r8
nric(i,k)=0._r8
end if
! make sure number concentration is a positive number to avoid
! taking root of negative
nric(i,k)=max(nric(i,k),0._r8)
nsic(i,k)=max(nsic(i,k),0._r8)
!.......................................................................
! get size distribution parameters for fallspeed calculations
!......................................................................
! rain
if (qric(i,k).ge.qsmall) then
lamr(k) = (pi*rhow*nric(i,k)/qric(i,k))**(1._r8/3._r8)
n0r(k) = nric(i,k)*lamr(k)
! check for slope
! change lammax and lammin for rain and snow
! adjust vars
if (lamr(k).lt.lamminr) then
lamr(k) = lamminr
n0r(k) = lamr(k)**4*qric(i,k)/(pi*rhow)
nric(i,k) = n0r(k)/lamr(k)
else if (lamr(k).gt.lammaxr) then
lamr(k) = lammaxr
n0r(k) = lamr(k)**4*qric(i,k)/(pi*rhow)
nric(i,k) = n0r(k)/lamr(k)
end if
! 'final' values of number and mass weighted mean fallspeed for rain (m/s)
unr(k) = min(arn(i,k)*cons4/lamr(k)**br,9.1_r8*rhof(i,k))
umr(k) = min(arn(i,k)*cons5/(6._r8*lamr(k)**br),9.1_r8*rhof(i,k))
else
lamr(k) = 0._r8
n0r(k) = 0._r8
umr(k)=0._r8
unr(k)=0._r8
end if
!calculate mean size of combined rain and snow
if (lamr(k).gt.0._r8) then
Artmp = n0r(k) * pi / (2 * lamr(k)**3._r8)
else
Artmp = 0._r8
endif
if (lamc(k).gt.0._r8) then
Actmp = cdist1(k) * pi * gamma
(pgam(k)+3._r8)/(4._r8 * lamc(k)**2._r8)
else
Actmp = 0._r8
endif
if (Actmp.gt.0_r8.or.Artmp.gt.0) then
rercld(i,k)=rercld(i,k) + 3._r8 *(qric(i,k) + qcic(i,k)) / (4._r8 * rhow * (Actmp + Artmp))
arcld(i,k)=arcld(i,k)+1._r8
endif
!......................................................................
! snow
if (qniic(i,k).ge.qsmall) then
lams(k) = (cons6*cs*nsic(i,k)/ &
qniic(i,k))**(1._r8/ds)
n0s(k) = nsic(i,k)*lams(k)
! check for slope
! adjust vars
if (lams(k).lt.lammins) then
lams(k) = lammins
n0s(k) = lams(k)**(ds+1._r8)*qniic(i,k)/(cs*cons6)
nsic(i,k) = n0s(k)/lams(k)
else if (lams(k).gt.lammaxs) then
lams(k) = lammaxs
n0s(k) = lams(k)**(ds+1._r8)*qniic(i,k)/(cs*cons6)
nsic(i,k) = n0s(k)/lams(k)
end if
! 'final' values of number and mass weighted mean fallspeed for snow (m/s)
ums(k) = min(asn(i,k)*cons8/(6._r8*lams(k)**bs),1.2_r8*rhof(i,k))
uns(k) = min(asn(i,k)*cons7/lams(k)**bs,1.2_r8*rhof(i,k))
else
lams(k) = 0._r8
n0s(k) = 0._r8
ums(k) = 0._r8
uns(k) = 0._r8
end if
!c........................................................................
! sum over sub-step for average process rates
! convert rain/snow q and N for output to history, note,
! output is for gridbox average
qrout(i,k)=qrout(i,k)+qric(i,k)*cldmax(i,k)
qsout(i,k)=qsout(i,k)+qniic(i,k)*cldmax(i,k)
nrout(i,k)=nrout(i,k)+nric(i,k)*rho(i,k)*cldmax(i,k)
nsout(i,k)=nsout(i,k)+nsic(i,k)*rho(i,k)*cldmax(i,k)
tlat1(i,k)=tlat1(i,k)+tlat(i,k)
qvlat1(i,k)=qvlat1(i,k)+qvlat(i,k)
qctend1(i,k)=qctend1(i,k)+qctend(i,k)
qitend1(i,k)=qitend1(i,k)+qitend(i,k)
nctend1(i,k)=nctend1(i,k)+nctend(i,k)
nitend1(i,k)=nitend1(i,k)+nitend(i,k)
t(i,k)=t(i,k)+tlat(i,k)*deltat/cpp
q(i,k)=q(i,k)+qvlat(i,k)*deltat
qc(i,k)=qc(i,k)+qctend(i,k)*deltat
qi(i,k)=qi(i,k)+qitend(i,k)*deltat
nc(i,k)=nc(i,k)+nctend(i,k)*deltat
ni(i,k)=ni(i,k)+nitend(i,k)*deltat
rainrt1(i,k)=rainrt1(i,k)+rainrt(i,k)
!divide rain radius over substeps for average
if (arcld(i,k) .gt. 0._r8) then
rercld(i,k)=rercld(i,k)/arcld(i,k)
end if
!calculate precip fluxes and adding them to summing sub-stepping variables
!! flux is zero at top interface
rflx(i,1)=0.0_r8
sflx(i,1)=0.0_r8
!! calculating the precip flux (kg/m2/s) as mixingratio(kg/kg)*airdensity(kg/m3)*massweightedfallspeed(m/s)
rflx(i,k+1)=qrout(i,k)*rho(i,k)*umr(k)
sflx(i,k+1)=qsout(i,k)*rho(i,k)*ums(k)
!! add to summing sub-stepping variable
rflx1(i,k+1)=rflx1(i,k+1)+rflx(i,k+1)
sflx1(i,k+1)=sflx1(i,k+1)+sflx(i,k+1)
!c........................................................................
end do ! k loop
prect1(i)=prect1(i)+prect(i)
preci1(i)=preci1(i)+preci(i)
end do ! it loop, sub-step
#ifdef MODAL_AERO ! rce 2010/05/01
do k = 1, pver
rate1ord_cw2pr_st(i,k) = qcsinksum_rate1ord(k)/max(qcsum_rate1ord(k),1.0e-30_r8)
end do
#endif
300 continue ! continue if no cloud water
end do ! i loop
! convert dt from sub-step back to full time step
deltat=deltat*real(iter)
!c.............................................................................
do i=1,ncol
! skip all calculations if no cloud water
if (ltrue(i).eq.0) then
do k=1,pver
! assign default values for effective radius
effc(i,k)=10._r8
effi(i,k)=25._r8
effc_fn(i,k)=10._r8
lamcrad(i,k)=0._r8
pgamrad(i,k)=0._r8
deffi(i,k)=0._r8
end do
goto 500
end if
! initialize nstep for sedimentation sub-steps
nstep = 1
! divide precip rate by number of sub-steps to get average over time step
prect(i)=prect1(i)/real(iter)
preci(i)=preci1(i)/real(iter)
do k=1,pver
! assign variables back to start-of-timestep values before updating after sub-steps
t(i,k)=t1(i,k)
q(i,k)=q1(i,k)
qc(i,k)=qc1(i,k)
qi(i,k)=qi1(i,k)
nc(i,k)=nc1(i,k)
ni(i,k)=ni1(i,k)
! divide microphysical tendencies by number of sub-steps to get average over time step
tlat(i,k)=tlat1(i,k)/real(iter)
qvlat(i,k)=qvlat1(i,k)/real(iter)
qctend(i,k)=qctend1(i,k)/real(iter)
qitend(i,k)=qitend1(i,k)/real(iter)
nctend(i,k)=nctend1(i,k)/real(iter)
nitend(i,k)=nitend1(i,k)/real(iter)
rainrt(i,k)=rainrt1(i,k)/real(iter)
! divide by number of sub-steps to find final values
rflx(i,k+1)=rflx1(i,k+1)/real(iter)
sflx(i,k+1)=sflx1(i,k+1)/real(iter)
! divide output precip q and N by number of sub-steps to get average over time step
qrout(i,k)=qrout(i,k)/real(iter)
qsout(i,k)=qsout(i,k)/real(iter)
nrout(i,k)=nrout(i,k)/real(iter)
nsout(i,k)=nsout(i,k)/real(iter)
! divide trop_mozart variables by number of sub-steps to get average over time step
nevapr(i,k) = nevapr(i,k)/real(iter)
evapsnow(i,k) = evapsnow(i,k)/real(iter)
prain(i,k) = prain(i,k)/real(iter)
prodsnow(i,k) = prodsnow(i,k)/real(iter)
cmeout(i,k) = cmeout(i,k)/real(iter)
cmeiout(i,k) = cmeiout(i,k)/real(iter)
meltsdt(i,k) = meltsdt(i,k)/real(iter)
frzrdt (i,k) = frzrdt (i,k)/real(iter)
! microphysics output
prao(i,k)=prao(i,k)/real(iter)
prco(i,k)=prco(i,k)/real(iter)
mnuccco(i,k)=mnuccco(i,k)/real(iter)
mnuccto(i,k)=mnuccto(i,k)/real(iter)
msacwio(i,k)=msacwio(i,k)/real(iter)
psacwso(i,k)=psacwso(i,k)/real(iter)
bergso(i,k)=bergso(i,k)/real(iter)
bergo(i,k)=bergo(i,k)/real(iter)
prcio(i,k)=prcio(i,k)/real(iter)
praio(i,k)=praio(i,k)/real(iter)
mnuccro(i,k)=mnuccro(i,k)/real(iter)
pracso (i,k)=pracso (i,k)/real(iter)
! modify to include snow. in prain & evap (diagnostic here: for wet dep)
nevapr(i,k) = nevapr(i,k) + evapsnow(i,k)
prain(i,k) = prain(i,k) + prodsnow(i,k)
!--ag
!ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
! calculate sedimentation for cloud water and ice
!ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
! update in-cloud cloud mixing ratio and number concentration
! with microphysical tendencies to calculate sedimentation, assign to dummy vars
! note: these are in-cloud values***, hence we divide by cloud fraction
dumc(i,k) = (qc(i,k)+qctend(i,k)*deltat)/lcldm(i,k)
dumi(i,k) = (qi(i,k)+qitend(i,k)*deltat)/icldm(i,k)
dumnc(i,k) = max((nc(i,k)+nctend(i,k)*deltat)/lcldm(i,k),0._r8)
dumni(i,k) = max((ni(i,k)+nitend(i,k)*deltat)/icldm(i,k),0._r8)
! obtain new slope parameter to avoid possible singularity
if (dumi(i,k).ge.qsmall) then
! add upper limit to in-cloud number concentration to prevent numerical error
dumni(i,k)=min(dumni(i,k),dumi(i,k)*1.e20_r8)
lami(k) = (cons1*ci* &
dumni(i,k)/dumi(i,k))**(1._r8/di)
lami(k)=max(lami(k),lammini)
lami(k)=min(lami(k),lammaxi)
else
lami(k)=0._r8
end if
if (dumc(i,k).ge.qsmall) then
! add upper limit to in-cloud number concentration to prevent numerical error
dumnc(i,k)=min(dumnc(i,k),dumc(i,k)*1.e20_r8)
! add lower limit to in-cloud number concentration
dumnc(i,k)=max(dumnc(i,k),cdnl/rho(i,k)) ! sghan minimum in #/cm3
! pgam(k)=0.0005714_r8*(dumnc(i,k)/1.e6_r8/rho(i,k))+0.2714_r8
! hm fix, not active yet
pgam(k)=0.0005714_r8*(ncic(i,k)/1.e6_r8*rho(i,k))+0.2714_r8
pgam(k)=1._r8/(pgam(k)**2)-1._r8
pgam(k)=max(pgam(k),2._r8)
pgam(k)=min(pgam(k),15._r8)
lamc(k) = (pi/6._r8*rhow*dumnc(i,k)*gamma
(pgam(k)+4._r8)/ &
(dumc(i,k)*gamma
(pgam(k)+1._r8)))**(1._r8/3._r8)
lammin = (pgam(k)+1._r8)/50.e-6_r8
lammax = (pgam(k)+1._r8)/2.e-6_r8
lamc(k)=max(lamc(k),lammin)
lamc(k)=min(lamc(k),lammax)
else
lamc(k)=0._r8
end if
! calculate number and mass weighted fall velocity for droplets
! include effects of sub-grid distribution of cloud water
if (dumc(i,k).ge.qsmall) then
! unc = cons15/(cons3*cons21)* &
! acn(i,k)*gamma(1._r8+bc+pgam(k))/ &
! (lamc(k)**bc*gamma(pgam(k)+1._r8))
! umc = cons15/(cons3*cons21)* &
! acn(i,k)*gamma(4._r8+bc+pgam(k))/ &
! (lamc(k)**bc*gamma(pgam(k)+4._r8))
! hm fix, remove sub-grid qc from fallspeed calculation
unc = &
acn(i,k)*gamma
(1._r8+bc+pgam(k))/ &
(lamc(k)**bc*gamma
(pgam(k)+1._r8))
umc = &
acn(i,k)*gamma
(4._r8+bc+pgam(k))/ &
(lamc(k)**bc*gamma
(pgam(k)+4._r8))
! fallspeed for output
vtrmc(i,k)=umc
else
umc = 0._r8
unc = 0._r8
end if
! calculate number and mass weighted fall velocity for cloud ice
if (dumi(i,k).ge.qsmall) then
uni = ain(i,k)*cons16/lami(k)**bi
umi = ain(i,k)*cons17/(6._r8*lami(k)**bi)
uni=min(uni,1.2_r8*rhof(i,k))
umi=min(umi,1.2_r8*rhof(i,k))
! fallspeed
vtrmi(i,k)=umi
else
umi = 0._r8
uni = 0._r8
end if
fi(k) = g*rho(i,k)*umi
fni(k) = g*rho(i,k)*uni
fc(k) = g*rho(i,k)*umc
fnc(k) = g*rho(i,k)*unc
! calculate number of split time steps to ensure courant stability criteria
! for sedimentation calculations
rgvm = max(fi(k),fc(k),fni(k),fnc(k))
nstep = max(int(rgvm*deltat/pdel(i,k)+1._r8),nstep)
! redefine dummy variables - sedimentation is calculated over grid-scale
! quantities to ensure conservation
dumc(i,k) = (qc(i,k)+qctend(i,k)*deltat)
dumi(i,k) = (qi(i,k)+qitend(i,k)*deltat)
dumnc(i,k) = max((nc(i,k)+nctend(i,k)*deltat),0._r8)
dumni(i,k) = max((ni(i,k)+nitend(i,k)*deltat),0._r8)
if (dumc(i,k).lt.qsmall) dumnc(i,k)=0._r8
if (dumi(i,k).lt.qsmall) dumni(i,k)=0._r8
end do !!! vertical loop
do n = 1,nstep !! loop over sub-time step to ensure stability
do k = 1,pver
falouti(k) = fi(k)*dumi(i,k)
faloutni(k) = fni(k)*dumni(i,k)
faloutc(k) = fc(k)*dumc(i,k)
faloutnc(k) = fnc(k)*dumnc(i,k)
end do
! top of model
k = 1
faltndi = falouti(k)/pdel(i,k)
faltndni = faloutni(k)/pdel(i,k)
faltndc = faloutc(k)/pdel(i,k)
faltndnc = faloutnc(k)/pdel(i,k)
! add fallout terms to microphysical tendencies
qitend(i,k) = qitend(i,k)-faltndi/nstep
nitend(i,k) = nitend(i,k)-faltndni/nstep
qctend(i,k) = qctend(i,k)-faltndc/nstep
nctend(i,k) = nctend(i,k)-faltndnc/nstep
! sedimentation tendencies for output
qcsedten(i,k)=qcsedten(i,k)-faltndc/nstep
qisedten(i,k)=qisedten(i,k)-faltndi/nstep
dumi(i,k) = dumi(i,k)-faltndi*deltat/nstep
dumni(i,k) = dumni(i,k)-faltndni*deltat/nstep
dumc(i,k) = dumc(i,k)-faltndc*deltat/nstep
dumnc(i,k) = dumnc(i,k)-faltndnc*deltat/nstep
do k = 2,pver
! for cloud liquid and ice, if cloud fraction increases with height
! then add flux from above to both vapor and cloud water of current level
! this means that flux entering clear portion of cell from above evaporates
! instantly
dum=lcldm(i,k)/lcldm(i,k-1)
dum=min(dum,1._r8)
dum1=icldm(i,k)/icldm(i,k-1)
dum1=min(dum1,1._r8)
faltndqie=(falouti(k)-falouti(k-1))/pdel(i,k)
faltndi=(falouti(k)-dum1*falouti(k-1))/pdel(i,k)
faltndni=(faloutni(k)-dum1*faloutni(k-1))/pdel(i,k)
faltndqce=(faloutc(k)-faloutc(k-1))/pdel(i,k)
faltndc=(faloutc(k)-dum*faloutc(k-1))/pdel(i,k)
faltndnc=(faloutnc(k)-dum*faloutnc(k-1))/pdel(i,k)
! add fallout terms to eulerian tendencies
qitend(i,k) = qitend(i,k)-faltndi/nstep
nitend(i,k) = nitend(i,k)-faltndni/nstep
qctend(i,k) = qctend(i,k)-faltndc/nstep
nctend(i,k) = nctend(i,k)-faltndnc/nstep
! sedimentation tendencies for output
qcsedten(i,k)=qcsedten(i,k)-faltndc/nstep
qisedten(i,k)=qisedten(i,k)-faltndi/nstep
! add terms to to evap/sub of cloud water
qvlat(i,k)=qvlat(i,k)-(faltndqie-faltndi)/nstep
! for output
qisevap(i,k)=qisevap(i,k)-(faltndqie-faltndi)/nstep
qvlat(i,k)=qvlat(i,k)-(faltndqce-faltndc)/nstep
! for output
qcsevap(i,k)=qcsevap(i,k)-(faltndqce-faltndc)/nstep
tlat(i,k)=tlat(i,k)+(faltndqie-faltndi)*xxls/nstep
tlat(i,k)=tlat(i,k)+(faltndqce-faltndc)*xxlv/nstep
dumi(i,k) = dumi(i,k)-faltndi*deltat/nstep
dumni(i,k) = dumni(i,k)-faltndni*deltat/nstep
dumc(i,k) = dumc(i,k)-faltndc*deltat/nstep
dumnc(i,k) = dumnc(i,k)-faltndnc*deltat/nstep
Fni(K)=MAX(Fni(K)/pdel(i,K),Fni(K-1)/pdel(i,K-1))*pdel(i,K)
FI(K)=MAX(FI(K)/pdel(i,K),FI(K-1)/pdel(i,K-1))*pdel(i,K)
fnc(k)=max(fnc(k)/pdel(i,k),fnc(k-1)/pdel(i,k-1))*pdel(i,k)
Fc(K)=MAX(Fc(K)/pdel(i,K),Fc(K-1)/pdel(i,K-1))*pdel(i,K)
end do !! k loop
! units below are m/s
! cloud water/ice sedimentation flux at surface
! is added to precip flux at surface to get total precip (cloud + precip water)
! rate
prect(i) = prect(i)+(faloutc(pver)+falouti(pver)) &
/g/nstep/1000._r8
preci(i) = preci(i)+(falouti(pver)) &
/g/nstep/1000._r8
end do !! nstep loop
! end sedimentation
!ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
! get new update for variables that includes sedimentation tendency
! note : here dum variables are grid-average, NOT in-cloud
do k=1,pver
dumc(i,k) = max(qc(i,k)+qctend(i,k)*deltat,0._r8)
dumi(i,k) = max(qi(i,k)+qitend(i,k)*deltat,0._r8)
dumnc(i,k) = max(nc(i,k)+nctend(i,k)*deltat,0._r8)
dumni(i,k) = max(ni(i,k)+nitend(i,k)*deltat,0._r8)
if (dumc(i,k).lt.qsmall) dumnc(i,k)=0._r8
if (dumi(i,k).lt.qsmall) dumni(i,k)=0._r8
! calculate instantaneous processes (melting, homogeneous freezing)
if (t(i,k)+tlat(i,k)/cp*deltat > tmelt) then
if (dumi(i,k) > 0._r8) then
! limit so that melting does not push temperature below freezing
dum = -dumi(i,k)*xlf/cp
if (t(i,k)+tlat(i,k)/cp*deltat+dum.lt.tmelt) then
dum = (t(i,k)+tlat(i,k)/cp*deltat-tmelt)*cp/xlf
dum = dum/dumi(i,k)*xlf/cp
dum = max(0._r8,dum)
dum = min(1._r8,dum)
else
dum = 1._r8
end if
qctend(i,k)=qctend(i,k)+dum*dumi(i,k)/deltat
! for output
melto(i,k)=dum*dumi(i,k)/deltat
! assume melting ice produces droplet
! mean volume radius of 8 micron
nctend(i,k)=nctend(i,k)+3._r8*dum*dumi(i,k)/deltat/ &
(4._r8*pi*5.12e-16_r8*rhow)
qitend(i,k)=((1._r8-dum)*dumi(i,k)-qi(i,k))/deltat
nitend(i,k)=((1._r8-dum)*dumni(i,k)-ni(i,k))/deltat
tlat(i,k)=tlat(i,k)-xlf*dum*dumi(i,k)/deltat
end if
end if
! homogeneously freeze droplets at -40 C
if (t(i,k)+tlat(i,k)/cp*deltat < 233.15_r8) then
if (dumc(i,k) > 0._r8) then
! limit so that freezing does not push temperature above threshold
dum = dumc(i,k)*xlf/cp
if (t(i,k)+tlat(i,k)/cp*deltat+dum.gt.233.15_r8) then
dum = -(t(i,k)+tlat(i,k)/cp*deltat-233.15_r8)*cp/xlf
dum = dum/dumc(i,k)*xlf/cp
dum = max(0._r8,dum)
dum = min(1._r8,dum)
else
dum = 1._r8
end if
qitend(i,k)=qitend(i,k)+dum*dumc(i,k)/deltat
! for output
homoo(i,k)=dum*dumc(i,k)/deltat
! assume 25 micron mean volume radius of homogeneously frozen droplets
! consistent with size of detrained ice in stratiform.F90
nitend(i,k)=nitend(i,k)+dum*3._r8*dumc(i,k)/(4._r8*3.14_r8*1.563e-14_r8* &
500._r8)/deltat
qctend(i,k)=((1._r8-dum)*dumc(i,k)-qc(i,k))/deltat
nctend(i,k)=((1._r8-dum)*dumnc(i,k)-nc(i,k))/deltat
tlat(i,k)=tlat(i,k)+xlf*dum*dumc(i,k)/deltat
end if
end if
! remove any excess over-saturation, which is possible due to non-linearity when adding
! together all microphysical processes
! follow code similar to old CAM scheme
qtmp=q(i,k)+qvlat(i,k)*deltat
ttmp=t(i,k)+tlat(i,k)/cpp*deltat
esn = polysvp
(ttmp,0) ! use rhw to allow ice supersaturation
qsn = min(epsqs*esn/(p(i,k)-(1._r8-epsqs)*esn),1._r8)
if (qtmp > qsn .and. qsn > 0) then
! expression below is approximate since there may be ice deposition
dum = (qtmp-qsn)/(1._r8+cons27*qsn/(cpp*rv*ttmp**2))/deltat
! add to output cme
cmeout(i,k) = cmeout(i,k)+dum
! now add to tendencies, partition between liquid and ice based on temperature
if (ttmp > 268.15_r8) then
dum1=0.0_r8
! now add to tendencies, partition between liquid and ice based on te
else if (ttmp < 238.15_r8) then
dum1=1.0_r8
else
dum1=(268.15_r8-ttmp)/30._r8
end if
dum = (qtmp-qsn)/(1._r8+(xxls*dum1+xxlv*(1._r8-dum1))**2 &
*qsn/(cpp*rv*ttmp**2))/deltat
qctend(i,k)=qctend(i,k)+dum*(1._r8-dum1)
! for output
qcreso(i,k)=dum*(1._r8-dum1)
qitend(i,k)=qitend(i,k)+dum*dum1
qireso(i,k)=dum*dum1
qvlat(i,k)=qvlat(i,k)-dum
! for output
qvres(i,k)=-dum
tlat(i,k)=tlat(i,k)+dum*(1._r8-dum1)*xxlv+dum*dum1*xxls
end if
!...............................................................................
! calculate effective radius for pass to radiation code
! if no cloud water, default value is 10 micron for droplets,
! 25 micron for cloud ice
! update cloud variables after instantaneous processes to get effective radius
! variables are in-cloud to calculate size dist parameters
dumc(i,k) = max(qc(i,k)+qctend(i,k)*deltat,0._r8)/lcldm(i,k)
dumi(i,k) = max(qi(i,k)+qitend(i,k)*deltat,0._r8)/icldm(i,k)
dumnc(i,k) = max(nc(i,k)+nctend(i,k)*deltat,0._r8)/lcldm(i,k)
dumni(i,k) = max(ni(i,k)+nitend(i,k)*deltat,0._r8)/icldm(i,k)
! limit in-cloud mixing ratio to reasonable value of 5 g kg-1
dumc(i,k)=min(dumc(i,k),5.e-3_r8)
dumi(i,k)=min(dumi(i,k),5.e-3_r8)
!...................
! cloud ice effective radius
if (dumi(i,k).ge.qsmall) then
! add upper limit to in-cloud number concentration to prevent numerical error
dumni(i,k)=min(dumni(i,k),dumi(i,k)*1.e20_r8)
lami(k) = (cons1*ci* &
dumni(i,k)/dumi(i,k))**(1._r8/di)
if (lami(k).lt.lammini) then
lami(k) = lammini
n0i(k) = lami(k)**(di+1._r8)*dumi(i,k)/(ci*cons1)
niic(i,k) = n0i(k)/lami(k)
! adjust number conc if needed to keep mean size in reasonable range
nitend(i,k)=(niic(i,k)*icldm(i,k)-ni(i,k))/deltat
else if (lami(k).gt.lammaxi) then
lami(k) = lammaxi
n0i(k) = lami(k)**(di+1._r8)*dumi(i,k)/(ci*cons1)
niic(i,k) = n0i(k)/lami(k)
! adjust number conc if needed to keep mean size in reasonable range
nitend(i,k)=(niic(i,k)*icldm(i,k)-ni(i,k))/deltat
end if
effi(i,k) = 1.5_r8/lami(k)*1.e6_r8
else
effi(i,k) = 25._r8
end if
!...................
! cloud droplet effective radius
if (dumc(i,k).ge.qsmall) then
! add upper limit to in-cloud number concentration to prevent numerical error
dumnc(i,k)=min(dumnc(i,k),dumc(i,k)*1.e20_r8)
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! set tendency to ensure minimum droplet concentration
! after update by microphysics, except when lambda exceeds bounds on mean drop
! size or if there is no cloud water
if (dumnc(i,k).lt.cdnl/rho(i,k)) then
nctend(i,k)=(cdnl/rho(i,k)*cldm(i,k)-nc(i,k))/deltat
end if
dumnc(i,k)=max(dumnc(i,k),cdnl/rho(i,k)) ! sghan minimum in #/cm3
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! pgam(k)=0.0005714_r8*(dumnc(i,k)/1.e6_r8/rho(i,k))+0.2714_r8
! hm fix, not active yet
pgam(k)=0.0005714_r8*(ncic(i,k)/1.e6_r8*rho(i,k))+0.2714_r8
pgam(k)=1._r8/(pgam(k)**2)-1._r8
pgam(k)=max(pgam(k),2._r8)
pgam(k)=min(pgam(k),15._r8)
lamc(k) = (pi/6._r8*rhow*dumnc(i,k)*gamma
(pgam(k)+4._r8)/ &
(dumc(i,k)*gamma
(pgam(k)+1._r8)))**(1._r8/3._r8)
lammin = (pgam(k)+1._r8)/50.e-6_r8
lammax = (pgam(k)+1._r8)/2.e-6_r8
if (lamc(k).lt.lammin) then
lamc(k) = lammin
ncic(i,k) = 6._r8*lamc(k)**3*dumc(i,k)* &
gamma
(pgam(k)+1._r8)/ &
(pi*rhow*gamma
(pgam(k)+4._r8))
! adjust number conc if needed to keep mean size in reasonable range
nctend(i,k)=(ncic(i,k)*lcldm(i,k)-nc(i,k))/deltat
else if (lamc(k).gt.lammax) then
lamc(k) = lammax
ncic(i,k) = 6._r8*lamc(k)**3*dumc(i,k)* &
gamma
(pgam(k)+1._r8)/ &
(pi*rhow*gamma
(pgam(k)+4._r8))
! adjust number conc if needed to keep mean size in reasonable range
nctend(i,k)=(ncic(i,k)*lcldm(i,k)-nc(i,k))/deltat
end if
effc(i,k) = &
gamma
(pgam(k)+4._r8)/ &
gamma
(pgam(k)+3._r8)/lamc(k)/2._r8*1.e6_r8
!assign output fields for shape here
lamcrad(i,k)=lamc(k)
pgamrad(i,k)=pgam(k)
else
effc(i,k) = 10._r8
lamcrad(i,k)=0._r8
pgamrad(i,k)=0._r8
end if
! ice effective diameter for david mitchell's optics
deffi(i,k)=effi(i,k)*rhoi/917._r8*2._r8
!!! recalculate effective radius for constant number, in order to separate
! first and second indirect effects
! assume constant number of 10^8 kg-1
dumnc(i,k)=1.e8
if (dumc(i,k).ge.qsmall) then
! pgam(k)=0.0005714_r8*(dumnc(i,k)/1.e6_r8/rho(i,k))+0.2714_r8
! hm fix, not active yet
pgam(k)=0.0005714_r8*(ncic(i,k)/1.e6_r8*rho(i,k))+0.2714_r8
pgam(k)=1._r8/(pgam(k)**2)-1._r8
pgam(k)=max(pgam(k),2._r8)
pgam(k)=min(pgam(k),15._r8)
lamc(k) = (pi/6._r8*rhow*dumnc(i,k)*gamma
(pgam(k)+4._r8)/ &
(dumc(i,k)*gamma
(pgam(k)+1._r8)))**(1._r8/3._r8)
lammin = (pgam(k)+1._r8)/50.e-6_r8
lammax = (pgam(k)+1._r8)/2.e-6_r8
if (lamc(k).lt.lammin) then
lamc(k) = lammin
else if (lamc(k).gt.lammax) then
lamc(k) = lammax
end if
! effc_fn(i,k) = gamma(qcvar+1._r8/3._r8)/(gamma(qcvar)*qcvar**(1._r8/3._r8))* &
! gamma(pgam(k)+4._r8)/ &
! gamma(pgam(k)+3._r8)/lamc(k)/2._r8*1.e6_r8
! hm, modify, don't include sub-grid qc
effc_fn(i,k) = &
gamma
(pgam(k)+4._r8)/ &
gamma
(pgam(k)+3._r8)/lamc(k)/2._r8*1.e6_r8
else
effc_fn(i,k) = 10._r8
end if
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!1!
end do ! vertical k loop
500 continue
do k=1,pver
! if updated q (after microphysics) is zero, then ensure updated n is also zero
if (qc(i,k)+qctend(i,k)*deltat.lt.qsmall) nctend(i,k)=-nc(i,k)/deltat
if (qi(i,k)+qitend(i,k)*deltat.lt.qsmall) nitend(i,k)=-ni(i,k)/deltat
end do
end do ! i loop
! ccn concentration as diagnostic
#ifndef MODAL_AERO
do k=1,pver
ccn(:ncol,k,:) = 0.
do m=1,naer_all
if(m.eq.idxsul)then
! Lohmann treatment for sulfate has variable size distribution
do i=1,ncol
if (naer2(i,k,m).gt.0._r8) then
amcubesulfate(i)=amcubefactor(m)*aer_mmr(i,k,m)*rho(i,k)/(naer2(i,k,m))
smcritsulfate(i)=smcritfactor(m)/sqrt(amcubesulfate(i))
else
smcritsulfate(i)=1._r8
endif
end do
end if
do l=1,psat
if(m.eq.idxsul)then
do i=1,ncol
arg=argfactor(m)*log(smcritsulfate(i)/super(l))
if(arg<2)then
if(arg<-2)then
ccnfact(l,m)=1.0e-6_r8
else
ccnfact(l,m)=0.5e-6_r8*erfc(arg)
endif
else
ccnfact(l,m)=0.0_r8
endif
ccn(i,k,l)=ccn(i,k,l)+naer2(i,k,m)*ccnfact(l,m)
end do
else
ccn(:ncol,k,l)=ccn(:ncol,k,l)+naer2(:ncol,k,m)*ccnfact(l,m)
endif
enddo
enddo
enddo
do l=1,psat
call outfld
(ccn_name(l), ccn(1,1,l) , pcols, lchnk )
enddo
#endif
do l=1,naer_all
call outfld
(aername(l)//'_m3', naer2(1,1,l), pcols, lchnk)
enddo
! hm add rain/snow mixing ratio and number concentration as diagnostic
call outfld
('QRAIN',qrout, pcols, lchnk)
call outfld
('QSNOW',qsout, pcols, lchnk)
call outfld
('NRAIN',nrout, pcols, lchnk)
call outfld
('NSNOW',nsout, pcols, lchnk)
! add snow ouptut
do i = 1,ncol
do k=1,pver
if (qsout(i,k).gt.1.e-7_r8.and.nsout(i,k).gt.0._r8) then
dsout(i,k)=(pi * rhosn * nsout(i,k)/qsout(i,k))**(-1._r8/3._r8)
endif
end do
end do
call outfld
('DSNOW',dsout, pcols, lchnk)
! add precip fluxes as output fields
call outfld
('MGFLXPRC',rflx, pcols, lchnk)
call outfld
('MGFLXSNW',sflx, pcols, lchnk)
! analytic radar reflectivity
! formulas from Matthew Shupe, NOAA/CERES
! *****note: radar reflectivity is local (in-precip average)
! units of mm^6/m^3
do i = 1,ncol
do k=1,pver
if (qc(i,k)+qctend(i,k)*deltat.ge.qsmall) then
dum=((qc(i,k)+qctend(i,k)*deltat)/lcldm(i,k)*rho(i,k)*1000._r8)**2 &
/(0.109_r8*(nc(i,k)+nctend(i,k)*deltat)/lcldm(i,k)*rho(i,k)/1.e6_r8)*lcldm(i,k)/cldmax(i,k)
else
dum=0._r8
end if
if (qi(i,k)+qitend(i,k)*deltat.ge.qsmall) then
dum1=((qi(i,k)+qitend(i,k)*deltat)*rho(i,k)/icldm(i,k)*1000._r8/0.1_r8)**(1._r8/0.63_r8)*icldm(i,k)/cldmax(i,k)
else
dum1=0._r8
end if
if (qsout(i,k).ge.qsmall) then
dum1=dum1+(qsout(i,k)*rho(i,k)*1000._r8/0.1_r8)**(1._r8/0.63_r8)
end if
refl(i,k)=dum+dum1
! add rain rate, but for 37 GHz formulation instead of 94 GHz
! formula approximated from data of Matrasov (2007)
! rainrt is the rain rate in mm/hr
! reflectivity (dum) is in DBz
if (rainrt(i,k).ge.0.001) then
dum=log10(rainrt(i,k)**6._r8)+16._r8
! convert from DBz to mm^6/m^3
dum = 10._r8**(dum/10._r8)
else
! don't include rain rate in R calculation for values less than 0.001 mm/hr
dum=0.
end if
! add to refl
refl(i,k)=refl(i,k)+dum
!output reflectivity in Z.
areflz(i,k)=refl(i,k)
! convert back to DBz
if (refl(i,k).gt.minrefl) then
refl(i,k)=10._r8*log10(refl(i,k))
else
refl(i,k)=-9999._r8
end if
!set averaging flag
if (refl(i,k).gt.mindbz) then
arefl(i,k)=refl(i,k)
frefl(i,k)=1.0_r8
else
arefl(i,k)=0._r8
areflz(i,k)=0._r8
frefl(i,k)=0._r8
end if
! bound cloudsat reflectivity
csrfl(i,k)=min(csmax,refl(i,k))
!set averaging flag
if (csrfl(i,k).gt.csmin) then
acsrfl(i,k)=refl(i,k)
fcsrfl(i,k)=1.0_r8
else
acsrfl(i,k)=0._r8
fcsrfl(i,k)=0._r8
end if
end do
end do
call outfld
('REFL',refl, pcols, lchnk)
call outfld
('AREFL',arefl, pcols, lchnk)
call outfld
('AREFLZ',areflz, pcols, lchnk)
call outfld
('FREFL',frefl, pcols, lchnk)
call outfld
('CSRFL',csrfl, pcols, lchnk)
call outfld
('ACSRFL',acsrfl, pcols, lchnk)
call outfld
('FCSRFL',fcsrfl, pcols, lchnk)
call outfld
('RERCLD',rercld, pcols, lchnk)
! averaging for snow and rain number and diameter
qrout2(:,:)=0._r8
qsout2(:,:)=0._r8
nrout2(:,:)=0._r8
nsout2(:,:)=0._r8
drout2(:,:)=0._r8
dsout2(:,:)=0._r8
freqs(:,:)=0._r8
freqr(:,:)=0._r8
do i = 1,ncol
do k=1,pver
if (qrout(i,k).gt.1.e-7_r8.and.nrout(i,k).gt.0._r8) then
qrout2(i,k)=qrout(i,k)
nrout2(i,k)=nrout(i,k)
drout2(i,k)=(pi * rhow * nrout(i,k)/qrout(i,k))**(-1._r8/3._r8)
freqr(i,k)=1._r8
endif
if (qsout(i,k).gt.1.e-7_r8.and.nsout(i,k).gt.0._r8) then
qsout2(i,k)=qsout(i,k)
nsout2(i,k)=nsout(i,k)
dsout2(i,k)=(pi * rhosn * nsout(i,k)/qsout(i,k))**(-1._r8/3._r8)
freqs(i,k)=1._r8
endif
end do
end do
! output activated liquid and ice (convert from #/kg -> #/m3)
do i = 1,ncol
do k=1,pver
ncai(i,k)=dum2i(i,k)*rho(i,k)
ncal(i,k)=dum2l(i,k)*rho(i,k)
nihf(i,k)=nihf(i,k)*rho(i,k)
niimm(i,k)=niimm(i,k)*rho(i,k)
nidep(i,k)=nidep(i,k)*rho(i,k)
nimey(i,k)=nimey(i,k)*rho(i,k)
end do
end do
call outfld
('NCAL',ncal, pcols,lchnk)
call outfld
('NCAI',ncai, pcols,lchnk)
call outfld
('NIHF',nihf, pcols,lchnk)
call outfld
('NIIMM',niimm, pcols,lchnk)
call outfld
('NIDEP',nidep, pcols,lchnk)
call outfld
('NIMEY',nimey, pcols,lchnk)
!add averaged output fields.
call outfld
('AQRAIN',qrout2, pcols,lchnk)
call outfld
('AQSNOW',qsout2, pcols,lchnk)
call outfld
('ANRAIN',nrout2, pcols,lchnk)
call outfld
('ANSNOW',nsout2, pcols,lchnk)
call outfld
('ADRAIN',drout2, pcols,lchnk)
call outfld
('ADSNOW',dsout2, pcols,lchnk)
call outfld
('FREQR',freqr, pcols,lchnk)
call outfld
('FREQS',freqs, pcols,lchnk)
!redefine fice here....
nfice(:,:)=0._r8
do k=1,pver
do i=1,ncol
dumc(i,k) = (qc(i,k)+qctend(i,k)*deltat)
dumi(i,k) = (qi(i,k)+qitend(i,k)*deltat)
dumfice=qsout(i,k) + qrout(i,k) + dumc(i,k) + dumi(i,k)
if (dumfice.gt.0._r8) then
nfice(i,k)=(qsout(i,k) + dumi(i,k))/dumfice
endif
enddo
enddo
call outfld
('FICE',nfice, pcols, lchnk)
deallocate( &
naermod, &
naer2, &
maerosol, &
ntype )
return
end subroutine mmicro_pcond
!##############################################################################
subroutine findsp1 (lchnk, ncol, q, t, p, tsp, qsp),6
!-----------------------------------------------------------------------
!
! Purpose:
! find the wet bulb temperature for a given t and q
! in a longitude height section
! wet bulb temp is the temperature and spec humidity that is
! just saturated and has the same enthalpy
! if q > qs(t) then tsp > t and qsp = qs(tsp) < q
! if q < qs(t) then tsp < t and qsp = qs(tsp) > q
!
! Method:
! a Newton method is used
! first guess uses an algorithm provided by John Petch from the UKMO
! we exclude points where the physical situation is unrealistic
! e.g. where the temperature is outside the range of validity for the
! saturation vapor pressure, or where the water vapor pressure
! exceeds the ambient pressure, or the saturation specific humidity is
! unrealistic
!
! Author: P. Rasch
!
!-----------------------------------------------------------------------
!
! input arguments
!
integer, intent(in) :: lchnk ! chunk identifier
integer, intent(in) :: ncol ! number of atmospheric columns
real(r8), intent(in) :: q(pcols,pver) ! water vapor (kg/kg)
real(r8), intent(in) :: t(pcols,pver) ! temperature (K)
real(r8), intent(in) :: p(pcols,pver) ! pressure (Pa)
!
! output arguments
!
real(r8), intent(out) :: tsp(pcols,pver) ! saturation temp (K)
real(r8), intent(out) :: qsp(pcols,pver) ! saturation mixing ratio (kg/kg)
!
! local variables
!
integer i ! work variable
integer k ! work variable
logical lflg ! work variable
integer iter ! work variable
integer l ! work variable
logical :: error_found
real(r8) omeps ! 1 minus epsilon
real(r8) trinv ! work variable
real(r8) es ! sat. vapor pressure
real(r8) desdt ! change in sat vap pressure wrt temperature
! real(r8) desdp ! change in sat vap pressure wrt pressure
real(r8) dqsdt ! change in sat spec. hum. wrt temperature
real(r8) dgdt ! work variable
real(r8) g ! work variable
real(r8) weight(pcols) ! work variable
real(r8) hlatsb ! (sublimation)
real(r8) hlatvp ! (vaporization)
real(r8) hltalt(pcols,pver) ! lat. heat. of vap.
real(r8) tterm ! work var.
real(r8) qs ! spec. hum. of water vapor
real(r8) tc ! crit temp of transition to ice
! work variables
real(r8) t1, q1, dt, dq
real(r8) dtm, dqm
real(r8) qvd, a1, tmp
real(r8) rair
real(r8) r1b, c1, c2, c3
real(r8) denom
real(r8) dttol
real(r8) dqtol
integer doit(pcols)
real(r8) enin(pcols), enout(pcols)
real(r8) tlim(pcols)
omeps = 1.0_r8 - epsqs
trinv = 1.0_r8/ttrice
a1 = 7.5_r8*log(10._r8)
rair = 287.04_r8
c3 = rair*a1/cp
dtm = 0._r8 ! needed for iter=0 blowup with f90 -ei
dqm = 0._r8 ! needed for iter=0 blowup with f90 -ei
dttol = 1.e-4_r8 ! the relative temp error tolerance required to quit the iteration
dqtol = 1.e-4_r8 ! the relative moisture error tolerance required to quit the iteration
! tmin = 173.16 ! the coldest temperature we can deal with
!
! max number of times to iterate the calculation
iter = 8
!
do k = 1,pver
!
! first guess on the wet bulb temperature
!
do i = 1,ncol
#ifdef DEBUG
if ( (lchnk == lchnklook(nlook) ) .and. (i == icollook(nlook) ) ) then
write (iulog,*) ' '
write (iulog,*) ' level, t, q, p', k, t(i,k), q(i,k), p(i,k)
endif
#endif
! limit the temperature range to that relevant to the sat vap pres tables
#if ( defined WACCM_PHYS )
tlim(i) = min(max(t(i,k),128._r8),373._r8)
#else
tlim(i) = min(max(t(i,k),173._r8),373._r8)
#endif
es = estblf
(tlim(i))
denom = p(i,k) - omeps*es
qs = epsqs*es/denom
doit(i) = 0
enout(i) = 1._r8
! make sure a meaningful calculation is possible
if (p(i,k) > 5._r8*es .and. qs > 0._r8 .and. qs < 0.5_r8) then
!
! Saturation specific humidity
!
qs = min(epsqs*es/denom,1._r8)
!
! "generalized" analytic expression for t derivative of es
! accurate to within 1 percent for 173.16 < t < 373.16
!
! Weighting of hlat accounts for transition from water to ice
! polynomial expression approximates difference between es over
! water and es over ice from 0 to -ttrice (C) (min of ttrice is
! -40): required for accurate estimate of es derivative in transition
! range from ice to water also accounting for change of hlatv with t
! above freezing where const slope is given by -2369 j/(kg c) = cpv - cw
!
tc = tlim(i) - tt0
lflg = (tc >= -ttrice .and. tc < 0.0_r8)
weight(i) = min(-tc*trinv,1.0_r8)
hlatsb = hlatv + weight(i)*hlatf
hlatvp = hlatv - 2369.0_r8*tc
if (tlim(i) < tt0) then
hltalt(i,k) = hlatsb
else
hltalt(i,k) = hlatvp
end if
enin(i) = cp*tlim(i) + hltalt(i,k)*q(i,k)
! make a guess at the wet bulb temp using a UKMO algorithm (from J. Petch)
tmp = q(i,k) - qs
c1 = hltalt(i,k)*c3
c2 = (tlim(i) + 36._r8)**2
r1b = c2/(c2 + c1*qs)
qvd = r1b*tmp
tsp(i,k) = tlim(i) + ((hltalt(i,k)/cp)*qvd)
#ifdef DEBUG
if ( (lchnk == lchnklook(nlook) ) .and. (i == icollook(nlook) ) ) then
write (iulog,*) ' relative humidity ', q(i,k)/qs
write (iulog,*) ' first guess ', tsp(i,k)
endif
#endif
es = estblf
(tsp(i,k))
qsp(i,k) = min(epsqs*es/(p(i,k) - omeps*es),1._r8)
else
doit(i) = 1
tsp(i,k) = tlim(i)
qsp(i,k) = q(i,k)
enin(i) = 1._r8
endif
end do ! end do i
!
! now iterate on first guess
!
do l = 1, iter
dtm = 0
dqm = 0
do i = 1,ncol
if (doit(i) == 0) then
es = estblf
(tsp(i,k))
!
! Saturation specific humidity
!
qs = min(epsqs*es/(p(i,k) - omeps*es),1._r8)
!
! "generalized" analytic expression for t derivative of es
! accurate to within 1 percent for 173.16 < t < 373.16
!
! Weighting of hlat accounts for transition from water to ice
! polynomial expression approximates difference between es over
! water and es over ice from 0 to -ttrice (C) (min of ttrice is
! -40): required for accurate estimate of es derivative in transition
! range from ice to water also accounting for change of hlatv with t
! above freezing where const slope is given by -2369 j/(kg c) = cpv - cw
!
tc = tsp(i,k) - tt0
lflg = (tc >= -ttrice .and. tc < 0.0_r8)
weight(i) = min(-tc*trinv,1.0_r8)
hlatsb = hlatv + weight(i)*hlatf
hlatvp = hlatv - 2369.0_r8*tc
if (tsp(i,k) < tt0) then
hltalt(i,k) = hlatsb
else
hltalt(i,k) = hlatvp
end if
if (lflg) then
tterm = pcf(1) + tc*(pcf(2) + tc*(pcf(3)+tc*(pcf(4) + tc*pcf(5))))
else
tterm = 0.0_r8
end if
desdt = hltalt(i,k)*es/(rgasv*tsp(i,k)*tsp(i,k)) + tterm*trinv
dqsdt = (epsqs + omeps*qs)/(p(i,k) - omeps*es)*desdt
! g = cp*(tlim(i)-tsp(i,k)) + hltalt(i,k)*q(i,k)- hltalt(i,k)*qsp(i,k)
g = enin(i) - (cp*tsp(i,k) + hltalt(i,k)*qsp(i,k))
dgdt = -(cp + hltalt(i,k)*dqsdt)
t1 = tsp(i,k) - g/dgdt
dt = abs(t1 - tsp(i,k))/t1
tsp(i,k) = max(t1,tmin)
es = estblf
(tsp(i,k))
q1 = min(epsqs*es/(p(i,k) - omeps*es),1._r8)
dq = abs(q1 - qsp(i,k))/max(q1,1.e-12_r8)
qsp(i,k) = q1
#ifdef DEBUG
if ( (lchnk == lchnklook(nlook) ) .and. (i == icollook(nlook) ) ) then
write (iulog,*) ' rel chg lev, iter, t, q ', k, l, dt, dq, g
endif
#endif
dtm = max(dtm,dt)
dqm = max(dqm,dq)
! if converged at this point, exclude it from more iterations
if (dt < dttol .and. dq < dqtol) then
doit(i) = 2
endif
enout(i) = cp*tsp(i,k) + hltalt(i,k)*qsp(i,k)
! bail out if we are too near the end of temp range
#if ( defined WACCM_PHYS )
if (tsp(i,k) < 130.16_r8) then
#else
if (tsp(i,k) < 174.16_r8) then
#endif
doit(i) = 4
endif
else
endif
end do ! do i = 1,ncol
if (dtm < dttol .and. dqm < dqtol) then
go to 10
endif
end do ! do l = 1,iter
10 continue
error_found = .false.
if (dtm > dttol .or. dqm > dqtol) then
do i = 1,ncol
if (doit(i) == 0) error_found = .true.
end do
if (error_found) then
do i = 1,ncol
if (doit(i) == 0) then
write (iulog,*) ' findsp not converging at point i, k ', i, k
write (iulog,*) ' t, q, p, enin ', t(i,k), q(i,k), p(i,k), enin(i)
write (iulog,*) ' tsp, qsp, enout ', tsp(i,k), qsp(i,k), enout(i)
call endrun
('FINDSP')
endif
end do
endif
endif
do i = 1,ncol
if (doit(i) == 2 .and. abs((enin(i)-enout(i))/(enin(i)+enout(i))) > 1.e-4_r8) then
error_found = .true.
endif
end do
if (error_found) then
do i = 1,ncol
if (doit(i) == 2 .and. abs((enin(i)-enout(i))/(enin(i)+enout(i))) > 1.e-4_r8) then
write (iulog,*) ' the enthalpy is not conserved for point ', &
i, k, enin(i), enout(i)
write (iulog,*) ' t, q, p, enin ', t(i,k), q(i,k), p(i,k), enin(i)
write (iulog,*) ' tsp, qsp, enout ', tsp(i,k), qsp(i,k), enout(i)
call endrun
('FINDSP')
endif
end do
endif
end do ! level loop (k=1,pver)
return
end subroutine findsp1
subroutine findsp1_water (lchnk, ncol, q, t, p, tsp, qsp),6
!-----------------------------------------------------------------------
!
! Purpose:
! find the wet bulb temperature for a given t and q
! in a longitude height section
! wet bulb temp is the temperature and spec humidity that is
! just saturated and has the same enthalpy
! if q > qs(t) then tsp > t and qsp = qs(tsp) < q
! if q < qs(t) then tsp < t and qsp = qs(tsp) > q
!
! Method:
! a Newton method is used
! first guess uses an algorithm provided by John Petch from the UKMO
! we exclude points where the physical situation is unrealistic
! e.g. where the temperature is outside the range of validity for the
! saturation vapor pressure, or where the water vapor pressure
! exceeds the ambient pressure, or the saturation specific humidity is
! unrealistic
!
! Author: P. Rasch
!
!-----------------------------------------------------------------------
!
! input arguments
!
integer, intent(in) :: lchnk ! chunk identifier
integer, intent(in) :: ncol ! number of atmospheric columns
real(r8), intent(in) :: q(pcols,pver) ! water vapor (kg/kg)
real(r8), intent(in) :: t(pcols,pver) ! temperature (K)
real(r8), intent(in) :: p(pcols,pver) ! pressure (Pa)
!
! output arguments
!
real(r8), intent(out) :: tsp(pcols,pver) ! saturation temp (K)
real(r8), intent(out) :: qsp(pcols,pver) ! saturation mixing ratio (kg/kg)
!
! local variables
!
integer i ! work variable
integer k ! work variable
logical lflg ! work variable
integer iter ! work variable
integer l ! work variable
logical :: error_found
real(r8) omeps ! 1 minus epsilon
real(r8) trinv ! work variable
real(r8) es ! sat. vapor pressure
real(r8) desdt ! change in sat vap pressure wrt temperature
! real(r8) desdp ! change in sat vap pressure wrt pressure
real(r8) dqsdt ! change in sat spec. hum. wrt temperature
real(r8) dgdt ! work variable
real(r8) g ! work variable
real(r8) weight(pcols) ! work variable
real(r8) hlatsb ! (sublimation)
real(r8) hlatvp ! (vaporization)
real(r8) hltalt(pcols,pver) ! lat. heat. of vap.
real(r8) tterm ! work var.
real(r8) qs ! spec. hum. of water vapor
real(r8) tc ! crit temp of transition to ice
! work variables
real(r8) t1, q1, dt, dq
real(r8) dtm, dqm
real(r8) qvd, a1, tmp
real(r8) rair
real(r8) r1b, c1, c2, c3
real(r8) denom
real(r8) dttol
real(r8) dqtol
integer doit(pcols)
real(r8) enin(pcols), enout(pcols)
real(r8) tlim(pcols)
omeps = 1.0_r8 - epsqs
a1 = 7.5_r8*log(10._r8)
rair = 287.04_r8
c3 = rair*a1/cp
dtm = 0._r8 ! needed for iter=0 blowup with f90 -ei
dqm = 0._r8 ! needed for iter=0 blowup with f90 -ei
dttol = 1.e-4_r8 ! the relative temp error tolerance required to quit the iteration
dqtol = 1.e-4_r8 ! the relative moisture error tolerance required to quit the iteration
!
! max number of times to iterate the calculation
iter = 8
!
do k = 1,pver
!
! first guess on the wet bulb temperature
!
do i = 1,ncol
#ifdef DEBUG
if ( (lchnk == lchnklook(nlook) ) .and. (i == icollook(nlook) ) ) then
write (iulog,*) ' '
write (iulog,*) ' level, t, q, p', k, t(i,k), q(i,k), p(i,k)
endif
#endif
! limit the temperature range to that relevant to the sat vap pres tables
#if ( defined WACCM_PHYS )
tlim(i) = min(max(t(i,k),128._r8),373._r8)
#else
tlim(i) = min(max(t(i,k),173._r8),373._r8)
#endif
es = polysvp
(tlim(i),0)
denom = p(i,k) - omeps*es
qs = epsqs*es/denom
doit(i) = 0
enout(i) = 1._r8
! make sure a meaningful calculation is possible
if (p(i,k) > 5._r8*es .and. qs > 0._r8 .and. qs < 0.5_r8) then
!
! Saturation specific humidity
!
qs = min(epsqs*es/denom,1._r8)
!
! "generalized" analytic expression for t derivative of es
! accurate to within 1 percent for 173.16 < t < 373.16
!
! No icephs or water to ice transition
!
hlatvp = hlatv - 2369.0*(tlim(i)-tt0)
hlatsb = hlatv
if (tlim(i) < tt0) then
hltalt(i,k) = hlatsb
else
hltalt(i,k) = hlatvp
end if
!--xl
enin(i) = cp*tlim(i) + hltalt(i,k)*q(i,k)
! make a guess at the wet bulb temp using a UKMO algorithm (from J. Petch)
tmp = q(i,k) - qs
c1 = hltalt(i,k)*c3
c2 = (tlim(i) + 36._r8)**2
r1b = c2/(c2 + c1*qs)
qvd = r1b*tmp
tsp(i,k) = tlim(i) + ((hltalt(i,k)/cp)*qvd)
#ifdef DEBUG
if ( (lchnk == lchnklook(nlook) ) .and. (i == icollook(nlook) ) ) then
write (iulog,*) ' relative humidity ', q(i,k)/qs
write (iulog,*) ' first guess ', tsp(i,k)
endif
#endif
es = polysvp
(tsp(i,k),0)
qsp(i,k) = min(epsqs*es/(p(i,k) - omeps*es),1._r8)
else
doit(i) = 1
tsp(i,k) = tlim(i)
qsp(i,k) = q(i,k)
enin(i) = 1._r8
endif
end do ! end do i
!
! now iterate on first guess
!
do l = 1, iter
dtm = 0
dqm = 0
do i = 1,ncol
if (doit(i) == 0) then
es = polysvp
(tsp(i,k),0)
!
! Saturation specific humidity
!
qs = min(epsqs*es/(p(i,k) - omeps*es),1._r8)
!
! "generalized" analytic expression for t derivative of es
! accurate to within 1 percent for 173.16 < t < 373.16
!
!
! No icephs or water to ice transition
!
hlatvp = hlatv - 2369.0*(tsp(i,k)-tt0)
hlatsb = hlatv
if (tsp(i,k) < tt0) then
hltalt(i,k) = hlatsb
else
hltalt(i,k) = hlatvp
end if
desdt = hltalt(i,k)*es/(rgasv*tsp(i,k)*tsp(i,k))
dqsdt = (epsqs + omeps*qs)/(p(i,k) - omeps*es)*desdt
g = enin(i) - (cp*tsp(i,k) + hltalt(i,k)*qsp(i,k))
dgdt = -(cp + hltalt(i,k)*dqsdt)
t1 = tsp(i,k) - g/dgdt
dt = abs(t1 - tsp(i,k))/t1
tsp(i,k) = max(t1,tmin)
es = polysvp
(tsp(i,k),0)
q1 = min(epsqs*es/(p(i,k) - omeps*es),1._r8)
dq = abs(q1 - qsp(i,k))/max(q1,1.e-12_r8)
qsp(i,k) = q1
#ifdef DEBUG
if ( (lchnk == lchnklook(nlook) ) .and. (i == icollook(nlook) ) ) then
write (iulog,*) ' rel chg lev, iter, t, q ', k, l, dt, dq, g
endif
#endif
dtm = max(dtm,dt)
dqm = max(dqm,dq)
! if converged at this point, exclude it from more iterations
if (dt < dttol .and. dq < dqtol) then
doit(i) = 2
endif
enout(i) = cp*tsp(i,k) + hltalt(i,k)*qsp(i,k)
! bail out if we are too near the end of temp range
#if ( defined WACCM_PHYS )
if (tsp(i,k) < 130.16_r8) then
#else
if (tsp(i,k) < 174.16_r8) then
#endif
doit(i) = 4
endif
else
endif
end do ! do i = 1,ncol
if (dtm < dttol .and. dqm < dqtol) then
go to 10
endif
end do ! do l = 1,iter
10 continue
error_found = .false.
if (dtm > dttol .or. dqm > dqtol) then
do i = 1,ncol
if (doit(i) == 0) error_found = .true.
end do
if (error_found) then
do i = 1,ncol
if (doit(i) == 0) then
write (iulog,*) ' findsp not converging at point i, k ', i, k
write (iulog,*) ' t, q, p, enin ', t(i,k), q(i,k), p(i,k), enin(i)
write (iulog,*) ' tsp, qsp, enout ', tsp(i,k), qsp(i,k), enout(i)
call endrun
('FINDSP')
endif
end do
endif
endif
do i = 1,ncol
if (doit(i) == 2 .and. abs((enin(i)-enout(i))/(enin(i)+enout(i))) > 1.e-4_r8) then
error_found = .true.
endif
end do
if (error_found) then
do i = 1,ncol
if (doit(i) == 2 .and. abs((enin(i)-enout(i))/(enin(i)+enout(i))) > 1.e-4_r8) then
write (iulog,*) ' the enthalpy is not conserved for point ', &
i, k, enin(i), enout(i)
write (iulog,*) ' t, q, p, enin ', t(i,k), q(i,k), p(i,k), enin(i)
write (iulog,*) ' tsp, qsp, enout ', tsp(i,k), qsp(i,k), enout(i)
call endrun
('FINDSP')
endif
end do
endif
end do ! level loop (k=1,pver)
return
end subroutine findsp1_water
!cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
! error function in single precision
!
! Copyright(C) 1996 Takuya OOURA (email: ooura@mmm.t.u-tokyo.ac.jp).
! You may use, copy, modify this code for any purpose and
! without fee. You may distribute this ORIGINAL package.
function derf(x) 1,1
implicit real (a - h, o - z)
real(r8) a,b,x
dimension a(0 : 64), b(0 : 64)
integer i,k
data (a(i), i = 0, 12) / &
0.00000000005958930743d0, -0.00000000113739022964d0, &
0.00000001466005199839d0, -0.00000016350354461960d0, &
0.00000164610044809620d0, -0.00001492559551950604d0, &
0.00012055331122299265d0, -0.00085483269811296660d0, &
0.00522397762482322257d0, -0.02686617064507733420d0, &
0.11283791670954881569d0, -0.37612638903183748117d0, &
1.12837916709551257377d0 /
data (a(i), i = 13, 25) / &
0.00000000002372510631d0, -0.00000000045493253732d0, &
0.00000000590362766598d0, -0.00000006642090827576d0, &
0.00000067595634268133d0, -0.00000621188515924000d0, &
0.00005103883009709690d0, -0.00037015410692956173d0, &
0.00233307631218880978d0, -0.01254988477182192210d0, &
0.05657061146827041994d0, -0.21379664776456006580d0, &
0.84270079294971486929d0 /
data (a(i), i = 26, 38) / &
0.00000000000949905026d0, -0.00000000018310229805d0, &
0.00000000239463074000d0, -0.00000002721444369609d0, &
0.00000028045522331686d0, -0.00000261830022482897d0, &
0.00002195455056768781d0, -0.00016358986921372656d0, &
0.00107052153564110318d0, -0.00608284718113590151d0, &
0.02986978465246258244d0, -0.13055593046562267625d0, &
0.67493323603965504676d0 /
data (a(i), i = 39, 51) / &
0.00000000000382722073d0, -0.00000000007421598602d0, &
0.00000000097930574080d0, -0.00000001126008898854d0, &
0.00000011775134830784d0, -0.00000111992758382650d0, &
0.00000962023443095201d0, -0.00007404402135070773d0, &
0.00050689993654144881d0, -0.00307553051439272889d0, &
0.01668977892553165586d0, -0.08548534594781312114d0, &
0.56909076642393639985d0 /
data (a(i), i = 52, 64) / &
0.00000000000155296588d0, -0.00000000003032205868d0, &
0.00000000040424830707d0, -0.00000000471135111493d0, &
0.00000005011915876293d0, -0.00000048722516178974d0, &
0.00000430683284629395d0, -0.00003445026145385764d0, &
0.00024879276133931664d0, -0.00162940941748079288d0, &
0.00988786373932350462d0, -0.05962426839442303805d0, &
0.49766113250947636708d0 /
data (b(i), i = 0, 12) / &
-0.00000000029734388465d0, 0.00000000269776334046d0, &
-0.00000000640788827665d0, -0.00000001667820132100d0, &
-0.00000021854388148686d0, 0.00000266246030457984d0, &
0.00001612722157047886d0, -0.00025616361025506629d0, &
0.00015380842432375365d0, 0.00815533022524927908d0, &
-0.01402283663896319337d0, -0.19746892495383021487d0,&
0.71511720328842845913d0 /
data (b(i), i = 13, 25) / &
-0.00000000001951073787d0, -0.00000000032302692214d0, &
0.00000000522461866919d0, 0.00000000342940918551d0, &
-0.00000035772874310272d0, 0.00000019999935792654d0, &
0.00002687044575042908d0, -0.00011843240273775776d0, &
-0.00080991728956032271d0, 0.00661062970502241174d0, &
0.00909530922354827295d0, -0.20160072778491013140d0, &
0.51169696718727644908d0 /
data (b(i), i = 26, 38) / &
0.00000000003147682272d0, -0.00000000048465972408d0, &
0.00000000063675740242d0, 0.00000003377623323271d0, &
-0.00000015451139637086d0, -0.00000203340624738438d0,&
0.00001947204525295057d0, 0.00002854147231653228d0, &
-0.00101565063152200272d0, 0.00271187003520095655d0, &
0.02328095035422810727d0, -0.16725021123116877197d0, &
0.32490054966649436974d0 /
data (b(i), i = 39, 51) / &
0.00000000002319363370d0, -0.00000000006303206648d0, &
-0.00000000264888267434d0, 0.00000002050708040581d0, &
0.00000011371857327578d0, -0.00000211211337219663d0, &
0.00000368797328322935d0, 0.00009823686253424796d0, &
-0.00065860243990455368d0, -0.00075285814895230877d0,&
0.02585434424202960464d0, -0.11637092784486193258d0, &
0.18267336775296612024d0 /
data (b(i), i = 52, 64) / &
-0.00000000000367789363d0, 0.00000000020876046746d0, &
-0.00000000193319027226d0, -0.00000000435953392472d0, &
0.00000018006992266137d0, -0.00000078441223763969d0, &
-0.00000675407647949153d0, 0.00008428418334440096d0, &
-0.00017604388937031815d0, -0.00239729611435071610d0, &
0.02064129023876022970d0, -0.06905562880005864105d0, &
0.09084526782065478489d0 /
w = abs(x)
if (w .lt. 2.2d0) then
t = w * w
k = int(t)
t = t - k
k = k * 13
y = ((((((((((((a(k) * t + a(k + 1)) * t + &
a(k + 2)) * t + a(k + 3)) * t + a(k + 4)) * t + &
a(k + 5)) * t + a(k + 6)) * t + a(k + 7)) * t + &
a(k + 8)) * t + a(k + 9)) * t + a(k + 10)) * t + &
a(k + 11)) * t + a(k + 12)) * w
else if (w .lt. 6.9d0) then
k = int(w)
t = w - k
k = 13 * (k - 2)
y = (((((((((((b(k) * t + b(k + 1)) * t + &
b(k + 2)) * t + b(k + 3)) * t + b(k + 4)) * t + &
b(k + 5)) * t + b(k + 6)) * t + b(k + 7)) * t + &
b(k + 8)) * t + b(k + 9)) * t + b(k + 10)) * t + &
b(k + 11)) * t + b(k + 12)
y = y * y
y = y * y
y = y * y
y = 1 - y * y
else
y = 1
end if
if (x .lt. 0) y = -y
derf = y
end function derf
!
!cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
FUNCTION GAMMA(X) 90
!cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
!D DOUBLE PRECISION FUNCTION DGAMMA(X)
!----------------------------------------------------------------------
!
! THIS ROUTINE CALCULATES THE GAMMA FUNCTION FOR A REAL ARGUMENT X.
! COMPUTATION IS BASED ON AN ALGORITHM OUTLINED IN REFERENCE 1.
! THE PROGRAM USES RATIONAL FUNCTIONS THAT APPROXIMATE THE GAMMA
! FUNCTION TO AT LEAST 20 SIGNIFICANT DECIMAL DIGITS. COEFFICIENTS
! FOR THE APPROXIMATION OVER THE INTERVAL (1,2) ARE UNPUBLISHED.
! THOSE FOR THE APPROXIMATION FOR X .GE. 12 ARE FROM REFERENCE 2.
! THE ACCURACY ACHIEVED DEPENDS ON THE ARITHMETIC SYSTEM, THE
! COMPILER, THE INTRINSIC FUNCTIONS, AND PROPER SELECTION OF THE
! MACHINE-DEPENDENT CONSTANTS.
!
!
!*******************************************************************
!*******************************************************************
!
! EXPLANATION OF MACHINE-DEPENDENT CONSTANTS
!
! BETA - RADIX FOR THE FLOATING-POINT REPRESENTATION
! MAXEXP - THE SMALLEST POSITIVE POWER OF BETA THAT OVERFLOWS
! XBIG - THE LARGEST ARGUMENT FOR WHICH GAMMA(X) IS REPRESENTABLE
! IN THE MACHINE, I.E., THE SOLUTION TO THE EQUATION
! GAMMA(XBIG) = BETA**MAXEXP
! XINF - THE LARGEST MACHINE REPRESENTABLE FLOATING-POINT NUMBER;
! APPROXIMATELY BETA**MAXEXP
! EPS - THE SMALLEST POSITIVE FLOATING-POINT NUMBER SUCH THAT
! 1.0+EPS .GT. 1.0
! XMININ - THE SMALLEST POSITIVE FLOATING-POINT NUMBER SUCH THAT
! 1/XMININ IS MACHINE REPRESENTABLE
!
! APPROXIMATE VALUES FOR SOME IMPORTANT MACHINES ARE:
!
! BETA MAXEXP XBIG
!
! CRAY-1 (S.P.) 2 8191 966.961
! CYBER 180/855
! UNDER NOS (S.P.) 2 1070 177.803
! IEEE (IBM/XT,
! SUN, ETC.) (S.P.) 2 128 35.040
! IEEE (IBM/XT,
! SUN, ETC.) (D.P.) 2 1024 171.624
! IBM 3033 (D.P.) 16 63 57.574
! VAX D-FORMAT (D.P.) 2 127 34.844
! VAX G-FORMAT (D.P.) 2 1023 171.489
!
! XINF EPS XMININ
!
! CRAY-1 (S.P.) 5.45E+2465 7.11E-15 1.84E-2466
! CYBER 180/855
! UNDER NOS (S.P.) 1.26E+322 3.55E-15 3.14E-294
! IEEE (IBM/XT,
! SUN, ETC.) (S.P.) 3.40E+38 1.19E-7 1.18E-38
! IEEE (IBM/XT,
! SUN, ETC.) (D.P.) 1.79D+308 2.22D-16 2.23D-308
! IBM 3033 (D.P.) 7.23D+75 2.22D-16 1.39D-76
! VAX D-FORMAT (D.P.) 1.70D+38 1.39D-17 5.88D-39
! VAX G-FORMAT (D.P.) 8.98D+307 1.11D-16 1.12D-308
!
!*******************************************************************
!*******************************************************************
!
! ERROR RETURNS
!
! THE PROGRAM RETURNS THE VALUE XINF FOR SINGULARITIES OR
! WHEN OVERFLOW WOULD OCCUR. THE COMPUTATION IS BELIEVED
! TO BE FREE OF UNDERFLOW AND OVERFLOW.
!
!
! INTRINSIC FUNCTIONS REQUIRED ARE:
!
! INT, DBLE, EXP, LOG, REAL, SIN
!
!
! REFERENCES: AN OVERVIEW OF SOFTWARE DEVELOPMENT FOR SPECIAL
! FUNCTIONS W. J. CODY, LECTURE NOTES IN MATHEMATICS,
! 506, NUMERICAL ANALYSIS DUNDEE, 1975, G. A. WATSON
! (ED.), SPRINGER VERLAG, BERLIN, 1976.
!
! COMPUTER APPROXIMATIONS, HART, ET. AL., WILEY AND
! SONS, NEW YORK, 1968.
!
! LATEST MODIFICATION: OCTOBER 12, 1989
!
! AUTHORS: W. J. CODY AND L. STOLTZ
! APPLIED MATHEMATICS DIVISION
! ARGONNE NATIONAL LABORATORY
! ARGONNE, IL 60439
!
!----------------------------------------------------------------------
INTEGER I,N
LOGICAL PARITY
real(r8) gamma
REAL(r8) &
!D DOUBLE PRECISION
C,CONV,EPS,FACT,HALF,ONE,P,PI,Q,RES,SQRTPI,SUM,TWELVE, &
TWO,X,XBIG,XDEN,XINF,XMININ,XNUM,Y,Y1,YSQ,Z,ZERO
DIMENSION C(7),P(8),Q(8)
!----------------------------------------------------------------------
! MATHEMATICAL CONSTANTS
!----------------------------------------------------------------------
DATA ONE,HALF,TWELVE,TWO,ZERO/1.0E0_r8,0.5E0_r8,12.0E0_r8,2.0E0_r8,0.0E0_r8/, &
SQRTPI/0.9189385332046727417803297E0_r8/, &
PI/3.1415926535897932384626434E0_r8/
!D DATA ONE,HALF,TWELVE,TWO,ZERO/1.0D0,0.5D0,12.0D0,2.0D0,0.0D0/,
!D 1 SQRTPI/0.9189385332046727417803297D0/,
!D 2 PI/3.1415926535897932384626434D0/
!----------------------------------------------------------------------
! MACHINE DEPENDENT PARAMETERS
!----------------------------------------------------------------------
DATA XBIG,XMININ,EPS/35.040E0_r8,1.18E-38_r8,1.19E-7_r8/, &
XINF/3.4E38_r8/
!D DATA XBIG,XMININ,EPS/171.624D0,2.23D-308,2.22D-16/,
!D 1 XINF/1.79D308/
!----------------------------------------------------------------------
! NUMERATOR AND DENOMINATOR COEFFICIENTS FOR RATIONAL MINIMAX
! APPROXIMATION OVER (1,2).
!----------------------------------------------------------------------
DATA P/-1.71618513886549492533811E+0_r8,2.47656508055759199108314E+1_r8,&
-3.79804256470945635097577E+2_r8,6.29331155312818442661052E+2_r8,&
8.66966202790413211295064E+2_r8,-3.14512729688483675254357E+4_r8,&
-3.61444134186911729807069E+4_r8,6.64561438202405440627855E+4_r8/
DATA Q/-3.08402300119738975254353E+1_r8,3.15350626979604161529144E+2_r8,&
-1.01515636749021914166146E+3_r8,-3.10777167157231109440444E+3_r8,&
2.25381184209801510330112E+4_r8,4.75584627752788110767815E+3_r8,&
-1.34659959864969306392456E+5_r8,-1.15132259675553483497211E+5_r8/
!D DATA P/-1.71618513886549492533811D+0,2.47656508055759199108314D+1,
!D 1 -3.79804256470945635097577D+2,6.29331155312818442661052D+2,
!D 2 8.66966202790413211295064D+2,-3.14512729688483675254357D+4,
!D 3 -3.61444134186911729807069D+4,6.64561438202405440627855D+4/
!D DATA Q/-3.08402300119738975254353D+1,3.15350626979604161529144D+2,
!D 1 -1.01515636749021914166146D+3,-3.10777167157231109440444D+3,
!D 2 2.25381184209801510330112D+4,4.75584627752788110767815D+3,
!D 3 -1.34659959864969306392456D+5,-1.15132259675553483497211D+5/
!----------------------------------------------------------------------
! COEFFICIENTS FOR MINIMAX APPROXIMATION OVER (12, INF).
!----------------------------------------------------------------------
DATA C/-1.910444077728E-03_r8,8.4171387781295E-04_r8, &
-5.952379913043012E-04_r8,7.93650793500350248E-04_r8,&
-2.777777777777681622553E-03_r8,8.333333333333333331554247E-02_r8,&
5.7083835261E-03_r8/
!D DATA C/-1.910444077728D-03,8.4171387781295D-04,
!D 1 -5.952379913043012D-04,7.93650793500350248D-04,
!D 2 -2.777777777777681622553D-03,8.333333333333333331554247D-02,
!D 3 5.7083835261D-03/
!----------------------------------------------------------------------
! STATEMENT FUNCTIONS FOR CONVERSION BETWEEN INTEGER AND FLOAT
!----------------------------------------------------------------------
CONV(I) = REAL(I,r8)
!D CONV(I) = DBLE(I)
PARITY=.FALSE.
FACT=ONE
N=0
Y=X
IF(Y.LE.ZERO)THEN
!----------------------------------------------------------------------
! ARGUMENT IS NEGATIVE
!----------------------------------------------------------------------
Y=-X
Y1=AINT(Y)
RES=Y-Y1
IF(RES.NE.ZERO)THEN
IF(Y1.NE.AINT(Y1*HALF)*TWO)PARITY=.TRUE.
FACT=-PI/SIN(PI*RES)
Y=Y+ONE
ELSE
RES=XINF
GOTO 900
ENDIF
ENDIF
!----------------------------------------------------------------------
! ARGUMENT IS POSITIVE
!----------------------------------------------------------------------
IF(Y.LT.EPS)THEN
!----------------------------------------------------------------------
! ARGUMENT .LT. EPS
!----------------------------------------------------------------------
IF(Y.GE.XMININ)THEN
RES=ONE/Y
ELSE
RES=XINF
GOTO 900
ENDIF
ELSEIF(Y.LT.TWELVE)THEN
Y1=Y
IF(Y.LT.ONE)THEN
!----------------------------------------------------------------------
! 0.0 .LT. ARGUMENT .LT. 1.0
!----------------------------------------------------------------------
Z=Y
Y=Y+ONE
ELSE
!----------------------------------------------------------------------
! 1.0 .LT. ARGUMENT .LT. 12.0, REDUCE ARGUMENT IF NECESSARY
!----------------------------------------------------------------------
N=INT(Y)-1
Y=Y-CONV(N)
Z=Y-ONE
ENDIF
!----------------------------------------------------------------------
! EVALUATE APPROXIMATION FOR 1.0 .LT. ARGUMENT .LT. 2.0
!----------------------------------------------------------------------
XNUM=ZERO
XDEN=ONE
DO 260 I=1,8
XNUM=(XNUM+P(I))*Z
XDEN=XDEN*Z+Q(I)
260 CONTINUE
RES=XNUM/XDEN+ONE
IF(Y1.LT.Y)THEN
!----------------------------------------------------------------------
! ADJUST RESULT FOR CASE 0.0 .LT. ARGUMENT .LT. 1.0
!----------------------------------------------------------------------
RES=RES/Y1
ELSEIF(Y1.GT.Y)THEN
!----------------------------------------------------------------------
! ADJUST RESULT FOR CASE 2.0 .LT. ARGUMENT .LT. 12.0
!----------------------------------------------------------------------
DO 290 I=1,N
RES=RES*Y
Y=Y+ONE
290 CONTINUE
ENDIF
ELSE
!----------------------------------------------------------------------
! EVALUATE FOR ARGUMENT .GE. 12.0,
!----------------------------------------------------------------------
IF(Y.LE.XBIG)THEN
YSQ=Y*Y
SUM=C(7)
DO 350 I=1,6
SUM=SUM/YSQ+C(I)
350 CONTINUE
SUM=SUM/Y-Y+SQRTPI
SUM=SUM+(Y-HALF)*LOG(Y)
RES=EXP(SUM)
ELSE
RES=XINF
GOTO 900
ENDIF
ENDIF
!----------------------------------------------------------------------
! FINAL ADJUSTMENTS AND RETURN
!----------------------------------------------------------------------
IF(PARITY)RES=-RES
IF(FACT.NE.ONE)RES=FACT/RES
900 GAMMA=RES
!D900 DGAMMA = RES
RETURN
! ---------- LAST LINE OF GAMMA ----------
END function gamma
subroutine activate(wbar, tair, rhoair, & 1,5
na, pmode, nmode, ma, sigman, hygro, rhodry, nact)
! calculates number fraction of aerosols activated as CCN
! assumes an internal mixture within each of up to pmode multiple aerosol modes
! a gaussiam spectrum of updrafts can be treated.
! mks units
! Abdul-Razzak and Ghan, A parameterization of aerosol activation.
! 2. Multiple aerosol types. J. Geophys. Res., 105, 6837-6844.
use physconst
, only: rair, epsilo, cpair, rh2o, latvap, gravit, &
rhoh2o, mwh2o, r_universal
use wv_saturation
, only: estblf, epsqs
implicit none
! input
integer pmode,ptype ! dimension of modes, types in modes
real(r8) wbar ! grid cell mean vertical velocity (m/s)
real(r8) tair ! air temperature (K)
real(r8) rhoair ! air density (kg/m3)
real(r8) na(pmode) ! aerosol number concentration (/m3)
integer nmode ! number of aerosol modes
real(r8) ma(pmode) ! aerosol mass concentration (kg/m3)
real(r8) rhodry(pmode) ! density of aerosol material
real(r8) sigman(pmode) ! geometric standard deviation of aerosol size distribution
real(r8) hygro(pmode) ! hygroscopicity of aerosol mode
! output
real(r8) nact ! number fraction of aerosols activated
! local
! external erf,erfc
! real(r8) erf,erfc
#if (defined AIX)
#define ERF erf
#define ERFC erfc
#else
#define ERF derf
#define ERFC derfc
real(r8) derf,derfc
#endif
integer, parameter:: nx=200
integer :: maxmodes
real(r8) surften ! surface tension of water w/respect to air (N/m)
data surften/0.076/
save surften
real(r8) p0 ! reference pressure (Pa)
data p0/1013.25e2/
save p0
real(r8), allocatable :: volc(:) ! total aerosol volume concentration (m3/m3)
real(r8) tmass ! total aerosol mass concentration (g/cm3)
real(r8) rm ! number mode radius of aerosol at max supersat (cm)
real(r8) pres ! pressure (Pa)
real(r8) path ! mean free path (m)
real(r8) diff ! diffusivity (m2/s)
real(r8) conduct ! thermal conductivity (Joule/m/sec/deg)
real(r8) diff0,conduct0
real(r8) qs ! water vapor saturation mixing ratio
real(r8) dqsdt ! change in qs with temperature
real(r8) dqsdp ! change in qs with pressure
real(r8) gloc ! thermodynamic function (m2/s)
real(r8) zeta
real(r8), allocatable :: eta(:)
real(r8), allocatable :: smc(:)
real(r8) lnsmax ! ln(smax)
real(r8) alpha
real(r8) gammaloc
real(r8) beta
real(r8) sqrtg
real(r8) alogam
real(r8) rlo,rhi,xint1,xint2,xint3,xint4
real(r8) w,wnuc,wb
real(r8) alw,sqrtalw
real(r8) smax
real(r8) x,arg
real(r8) xmincoeff,xcut,volcut,surfcut
real(r8) z,z1,z2,wf1,wf2,zf1,zf2,gf1,gf2,gf
real(r8) :: etafactor1,etafactor2max
real(r8),allocatable :: etafactor2(:)
real(r8) es
integer m,n
real(r8),allocatable :: amcubeloc(:)
real(r8),allocatable :: lnsmloc(:)
maxmodes = naer_all
allocate( &
volc(maxmodes), &
eta(maxmodes), &
smc(maxmodes), &
etafactor2(maxmodes), &
amcubeloc(maxmodes), &
lnsmloc(maxmodes) )
if(maxmodes<pmode)then
write(iulog,*)'maxmodes,pmode in activate =',maxmodes,pmode
call endrun
('activate')
endif
nact=0._r8
if(nmode.eq.1.and.na(1).lt.1.e-20)return
if(wbar.le.0.)return
pres=rair*rhoair*tair
diff0=0.211e-4*(p0/pres)*(tair/tt0)**1.94
conduct0=(5.69+0.017*(tair-tt0))*4.186e2*1.e-5 ! convert to J/m/s/deg
es = estblf
(tair)
qs = epsilo*es/(pres-(1.0_r8 - epsqs)*es)
dqsdt=latvap/(rh2o*tair*tair)*qs
alpha=gravit*(latvap/(cpair*rh2o*tair*tair)-1./(rair*tair))
gammaloc=(1+latvap/cpair*dqsdt)/(rhoair*qs)
! growth coefficent Abdul-Razzak & Ghan 1998 eqn 16
! should depend on mean radius of mode to account for gas kinetic effects
gloc=1./(rhoh2o/(diff0*rhoair*qs) &
+latvap*rhoh2o/(conduct0*tair)*(latvap/(rh2o*tair)-1.))
sqrtg=sqrt(gloc)
beta=4.*pi*rhoh2o*gloc*gammaloc
etafactor2max=1.e10/(alpha*wbar)**1.5 ! this should make eta big if na is very small.
do m=1,nmode
! internal mixture of aerosols
volc(m)=ma(m)/(rhodry(m)) ! only if variable size dist
if(volc(m).gt.1.e-39.and.na(m).gt.1.e-39)then
etafactor2(m)=1./(na(m)*beta*sqrtg) !fixed or variable size dist
! number mode radius (m)
amcubeloc(m)=(3.*volc(m)/(4.*pi*exp45logsig(m)*na(m))) ! only if variable size dist
smc(m)=smcrit(m) ! only for prescribed size dist
if(hygro(m).gt.1.e-10)then ! loop only if variable size dist
smc(m)=2.*aten*sqrt(aten/(27.*hygro(m)*amcubeloc(m)))
else
smc(m)=100.
endif
else
smc(m)=1.
etafactor2(m)=etafactor2max ! this should make eta big if na is very small.
endif
lnsmloc(m)=log(smc(m)) ! only if variable size dist
enddo
! single updraft
wnuc=wbar
w=wbar
alw=alpha*wnuc
sqrtalw=sqrt(alw)
zeta=2.*sqrtalw*aten/(3.*sqrtg)
etafactor1=2.*alw*sqrtalw
do m=1,nmode
eta(m)=etafactor1*etafactor2(m)
enddo
call maxsat
(zeta,eta,nmode,smc,smax)
lnsmax=log(smax)
xmincoeff=alogaten-2.*third*(lnsmax-alog2)-alog3
nact=0._r8
do m=1,nmode
x=2*(lnsmloc(m)-lnsmax)/(3*sq2*alogsig(m))
nact=nact+0.5*(1.-erf(x))*na(m)
enddo
nact=nact/rhoair ! convert from #/m3 to #/kg
deallocate( &
volc, &
eta, &
smc, &
etafactor2, &
amcubeloc, &
lnsmloc )
return
end subroutine activate
subroutine maxsat(zeta,eta,nmode,smc,smax) 3
! calculates maximum supersaturation for multiple
! competing aerosol modes.
! Abdul-Razzak and Ghan, A parameterization of aerosol activation.
! 2. Multiple aerosol types. J. Geophys. Res., 105, 6837-6844.
implicit none
! integer pmode
! parameter (pmode=naer_all)
integer nmode ! number of modes
real(r8) :: smc(:) ! critical supersaturation for number mode radius
real(r8) zeta
real(r8) :: eta(:)
real(r8) smax ! maximum supersaturation
integer m ! mode index
real(r8) sum, g1, g2
do m=1,nmode
if(zeta.gt.1.e5*eta(m).or.smc(m)*smc(m).gt.1.e5*eta(m))then
! weak forcing. essentially none activated
smax=1.e-20
else
! significant activation of this mode. calc activation all modes.
go to 1
endif
enddo
return
1 continue
sum=0
do m=1,nmode
if(eta(m).gt.1.e-20)then
g1=sqrt(zeta/eta(m))
g1=g1*g1*g1
g2=smc(m)/sqrt(eta(m)+3*zeta)
g2=sqrt(g2)
g2=g2*g2*g2
sum=sum+(f1(m)*g1+f2(m)*g2)/(smc(m)*smc(m))
else
sum=1.e20
endif
enddo
smax=1./sqrt(sum)
return
end subroutine maxsat
subroutine nucleati(wbar, tair, relhum, cldn, qc, nfice, rhoair, & 1,11
#ifdef MODAL_AERO
qaerpt, dgnum, ptype, naer_all, nuci, onihf, oniimm, onidep, onimey)
#else
na, ptype, naer_all, nuci, onihf, oniimm, onidep, onimey)
#endif
!---------------------------------------------------------------
! Purpose:
! The parameterization of ice nucleation.
!
! Method: The current method is based on Liu & Penner (2005)
! It related the ice nucleation with the aerosol number, temperature and the
! updraft velocity. It includes homogeneous freezing of sulfate, immersion
! freezing of soot, and Meyers et al. (1992) deposition nucleation
!
! Authors: Xiaohong Liu, 01/2005, modifications by A. Gettelman 2009-2010
!----------------------------------------------------------------
#ifdef MODAL_AERO
use modal_aero_data, only: numptr_amode, modeptr_accum, modeptr_coarse, modeptr_aitken, &
maxd_amode, sigmag_amode, &
lptr_dust_a_amode,lptr_nacl_a_amode
use constituents
, only: pcnst
#endif
!-----------------------------------------------------
! Input Arguments
!
integer ptype, naer_all
real(r8), intent(in) :: wbar ! grid cell mean vertical velocity (m/s)
real(r8), intent(in) :: tair ! temperature (K)
real(r8), intent(in) :: relhum ! relative humidity with respective to liquid
real(r8), intent(in) :: cldn ! new value of cloud fraction (fraction)
real(r8), intent(in) :: qc ! liquid water mixing ratio (kg/kg)
real(r8), intent(in) :: nfice ! ice mass fraction
real(r8), intent(in) :: rhoair ! air density (kg/m3)
#ifdef MODAL_AERO
real(r8), intent(in) :: qaerpt(pcnst) ! aerosol number and mass mixing ratios
real(r8), intent(in) :: dgnum(maxd_amode) ! aerosol mode dry diameter (m)
#else
real(r8), intent(in) :: na(naer_all) ! aerosol number concentration (/m3)
#endif
!
! Output Arguments
!
real(r8), intent(out) :: nuci ! ice number nucleated (#/kg)
real(r8), intent(out) :: onihf ! nucleated number from homogeneous freezing of so4
real(r8), intent(out) :: oniimm ! nucleated number from immersion freezing
real(r8), intent(out) :: onidep ! nucleated number from deposition nucleation
real(r8), intent(out) :: onimey ! nucleated number from deposition nucleation (meyers: mixed phase)
!
! Local workspace
!
real(r8) so4_num ! so4 aerosol number (#/cm^3)
real(r8) soot_num ! soot (hydrophilic) aerosol number (#/cm^3)
real(r8) dst1_num,dst2_num,dst3_num,dst4_num ! dust aerosol number (#/cm^3)
real(r8) dst_num ! total dust aerosol number (#/cm^3)
real(r8) nihf ! nucleated number from homogeneous freezing of so4
real(r8) niimm ! nucleated number from immersion freezing
real(r8) nidep ! nucleated number from deposition nucleation
real(r8) nimey ! nucleated number from deposition nucleation (meyers)
real(r8) n1,ni ! nucleated number
real(r8) tc,A,B,C,regm,RHw ! work variable
real(r8) esl,esi,deles ! work variable
real(r8) dst_scale
real(r8) subgrid
real(r8) dmc,ssmc ! variables for modal scheme.
so4_num=0.0_r8
soot_num=0.0_r8
dst_num=0.0_r8
dst1_num = 0.0_r8
dst2_num = 0.0_r8
dst3_num = 0.0_r8
dst4_num = 0.0_r8
!For modal aerosols, assume for the upper troposphere:
! soot = accumulation mode
! sulfate = aiken mode
! dust = coarse mode
! since modal has internal mixtures.
#ifdef MODAL_AERO
soot_num = qaerpt(numptr_amode(modeptr_accum))*1.0e-6_r8 !#/cm^3
dmc= qaerpt(lptr_dust_a_amode(modeptr_coarse))
ssmc=qaerpt(lptr_nacl_a_amode(modeptr_coarse))
if (dmc.gt.0._r8) then
dst_num=dmc/(ssmc+dmc) * qaerpt(numptr_amode(modeptr_coarse))*1.0e-6_r8 !#/cm^3
else
dst_num=0.0_r8
endif
if (dgnum(modeptr_aitken) .gt. 0._r8 ) then
so4_num = qaerpt(numptr_amode(modeptr_aitken))*1.0e-6_r8 & !#/cm^3, only allow so4 with D>0.1 um in ice nucleation
* (0.5_r8 - 0.5_r8*erf(log(0.1e-6_r8/dgnum(modeptr_aitken))/ &
(2._r8**0.5_r8*log(sigmag_amode(modeptr_aitken)))))
else
so4_num = 0.0_r8
endif
so4_num = max(0.0_r8,so4_num)
#else
if(idxsul .gt. 0) then
so4_num=na(idxsul)*1.0e-6_r8 ! #/cm^3
end if
!continue above philosophy here....
if(idxbcphi .gt. 0) then
soot_num=na(idxbcphi)*1.0e-6_r8 !#/cm^3
end if
if(idxdst1 .gt. 0) then
dst1_num=na(idxdst1) *1.0e-6_r8 !#/cm^3
end if
if(idxdst2 .gt. 0) then
dst2_num=na(idxdst2)*1.0e-6_r8 !#/cm^3
end if
if(idxdst3 .gt. 0) then
dst3_num=na(idxdst3)*1.0e-6_r8 !#/cm^3
end if
if(idxdst4 .gt. 0) then
dst4_num=na(idxdst4)*1.0e-6_r8 !#/cm^3
end if
dst_num =dst1_num+dst2_num+dst3_num+dst4_num
#endif
! no soot nucleation for now.
soot_num=0.0_r8
ni=0._r8
tc=tair-273.15_r8
! initialize
niimm=0._r8
nidep=0._r8
nihf=0._r8
if(so4_num.ge.1.0e-10_r8 .and. (soot_num+dst_num).ge.1.0e-10_r8 .and. cldn.gt.0._r8) then
!-----------------------------
! RHw parameterization for heterogeneous immersion nucleation
A = 0.0073_r8
B = 1.477_r8
C = 131.74_r8
RHw=(A*tc*tc+B*tc+C)*0.01_r8 ! RHi ~ 120-130%
subgrid = 1.2_r8
if((tc.le.-35.0_r8) .and. ((relhum*polysvp
(tair,0)/polysvp
(tair,1)*subgrid).ge.1.2_r8)) then ! use higher RHi threshold
A = -1.4938_r8 * log(soot_num+dst_num) + 12.884_r8
B = -10.41_r8 * log(soot_num+dst_num) - 67.69_r8
regm = A * log(wbar) + B
if(tc.gt.regm) then ! heterogeneous nucleation only
if(tc.lt.-40._r8 .and. wbar.gt.1._r8) then ! exclude T<-40 & W>1m/s from hetero. nucleation
call hf
(tc,wbar,relhum,subgrid,so4_num,nihf)
niimm=0._r8
nidep=0._r8
n1=nihf
else
call hetero
(tc,wbar,soot_num+dst_num,niimm,nidep)
nihf=0._r8
n1=niimm+nidep
endif
elseif (tc.lt.regm-5._r8) then ! homogeneous nucleation only
call hf
(tc,wbar,relhum,subgrid,so4_num,nihf)
niimm=0._r8
nidep=0._r8
n1=nihf
else ! transition between homogeneous and heterogeneous: interpolate in-between
if(tc.lt.-40._r8 .and. wbar.gt.1._r8) then ! exclude T<-40 & W>1m/s from hetero. nucleation
call hf
(tc,wbar,relhum,subgrid,so4_num,nihf)
niimm=0._r8
nidep=0._r8
n1=nihf
else
call hf
(regm-5._r8,wbar,relhum,subgrid,so4_num,nihf)
call hetero
(regm,wbar,soot_num+dst_num,niimm,nidep)
if(nihf.le.(niimm+nidep)) then
n1=nihf
else
n1=(niimm+nidep)*((niimm+nidep)/nihf)**((tc-regm)/5._r8)
endif
endif
endif
ni=n1
endif
endif
1100 continue
! deposition/condensation nucleation in mixed clouds (-40<T<0C) (Meyers, 1992)
if(tc.lt.0._r8 .and. tc.gt.-37._r8 .and. qc.gt.1.e-12_r8) then
esl = polysvp
(tair,0) ! over water in mixed clouds
esi = polysvp
(tair,1) ! over ice
deles = (esl - esi)
nimey=1.e-3_r8*exp(12.96_r8*deles/esi - 0.639_r8)
else
nimey=0._r8
endif
nuci=ni+nimey
if(nuci.gt.9999._r8.or.nuci.lt.0._r8) then
write(iulog, *) 'incorrect ice nucleation number'
write(iulog, *) ni, tair, relhum, wbar, nihf, niimm, nidep,deles,esi,dst2_num,dst3_num,dst4_num
nuci=0._r8
endif
nuci=nuci*1.e+6_r8/rhoair ! change unit from #/cm3 to #/kg
onimey=nimey*1.e+6_r8/rhoair
onidep=nidep*1.e+6_r8/rhoair
oniimm=niimm*1.e+6_r8/rhoair
onihf=nihf*1.e+6_r8/rhoair
return
end subroutine nucleati
subroutine hetero(T,ww,Ns,Nis,Nid) 2
real(r8), intent(in) :: T, ww, Ns
real(r8), intent(out) :: Nis, Nid
real(r8) A11,A12,A21,A22,B11,B12,B21,B22
real(r8) A,B,C
!---------------------------------------------------------------------
! parameters
A11 = 0.0263_r8
A12 = -0.0185_r8
A21 = 2.758_r8
A22 = 1.3221_r8
B11 = -0.008_r8
B12 = -0.0468_r8
B21 = -0.2667_r8
B22 = -1.4588_r8
! ice from immersion nucleation (cm-3)
B = (A11+B11*log(Ns)) * log(ww) + (A12+B12*log(Ns))
C = A21+B21*log(Ns)
Nis = exp(A22) * Ns**B22 * exp(B*T) * ww**C
Nis = min(Nis,Ns)
Nid = 0.0_r8 ! don't include deposition nucleation for cirrus clouds when T<-37C
return
end subroutine hetero
subroutine hf(T,ww,RH,subgrid,Na,Ni) 4
real(r8), intent(in) :: T, ww, RH, subgrid, Na
real(r8), intent(out) :: Ni
real(r8) A1_fast,A21_fast,A22_fast,B1_fast,B21_fast,B22_fast
real(r8) A2_fast,B2_fast
real(r8) C1_fast,C2_fast,k1_fast,k2_fast
real(r8) A1_slow,A2_slow,B1_slow,B2_slow,B3_slow
real(r8) C1_slow,C2_slow,k1_slow,k2_slow
real(r8) regm
real(r8) A,B,C
real(r8) RHw
!---------------------------------------------------------------------
! parameters
A1_fast =0.0231_r8
A21_fast =-1.6387_r8 !(T>-64 deg)
A22_fast =-6.045_r8 !(T<=-64 deg)
B1_fast =-0.008_r8
B21_fast =-0.042_r8 !(T>-64 deg)
B22_fast =-0.112_r8 !(T<=-64 deg)
C1_fast =0.0739_r8
C2_fast =1.2372_r8
A1_slow =-0.3949_r8
A2_slow =1.282_r8
B1_slow =-0.0156_r8
B2_slow =0.0111_r8
B3_slow =0.0217_r8
C1_slow =0.120_r8
C2_slow =2.312_r8
Ni = 0.0_r8
!----------------------------
!RHw xiaohong's parameter
A = 6.0e-4_r8*log(ww)+6.6e-3_r8
B = 6.0e-2_r8*log(ww)+1.052_r8
C = 1.68_r8 *log(ww)+129.35_r8
RHw=(A*T*T+B*T+C)*0.01_r8
if((T.le.-37.0_r8) .and. ((RH*subgrid).ge.RHw)) then
regm = 6.07_r8*log(ww)-55.0_r8
if(T.ge.regm) then ! fast-growth regime
if(T.gt.-64.0_r8) then
A2_fast=A21_fast
B2_fast=B21_fast
else
A2_fast=A22_fast
B2_fast=B22_fast
endif
k1_fast = exp(A2_fast + B2_fast*T + C2_fast*log(ww))
k2_fast = A1_fast+B1_fast*T+C1_fast*log(ww)
Ni = k1_fast*Na**(k2_fast)
Ni = min(Ni,Na)
else ! slow-growth regime
k1_slow = exp(A2_slow + (B2_slow+B3_slow*log(ww))*T + C2_slow*log(ww))
k2_slow = A1_slow+B1_slow*T+C1_slow*log(ww)
Ni = k1_slow*Na**(k2_slow)
Ni = min(Ni,Na)
endif
end if
return
end subroutine hf
!--xl
end module cldwat2m_micro