#define MODAL_AERO #define WRF_PORT ! Updated to CESM1.0.3 (CAM5.1.01) by Balwinder.Singh@pnnl.gov module cldwat2m_micro 2,6 !--------------------------------------------------------------------------------- ! 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 !--------------------------------------------------------------------------------- ! modification for sub-columns, HM, (orig 8/11/10) ! This is done using the logical 'sub_column' set to .true. = subcolumns !--------------------------------------------------------------------------------- use shr_kind_mod, only: r8=>shr_kind_r8 #ifndef WRF_PORT use spmd_utils, only: masterproc use ppgrid, only: pcols, pver, pverp #else use module_cam_support, only: masterproc, pcols, pver, pverp #endif use physconst, only: gravit, rair, tmelt, cpair, rh2o, rhoh2o use physconst, only: latvap, latice use wv_saturation, only: polysvp, epsqs #ifndef WRF_PORT use cam_history, only: addfld, add_default, phys_decomp, outfld use cam_history_support, only : fillvalue use cam_logfile, only: iulog use phys_control, only: phys_getopts use cldwat2m_macro, only: rhmini #else use module_cam_support, only: addfld, add_default, phys_decomp, outfld, & fillvalue, iulog #endif implicit none private save #ifdef WRF_PORT !Macrophysics is not ported yet therefore rhmini is defined here (obtained from Cam5's cldwat2_macro)-Balwinder.Singh@pnnl.gov real(r8), public, parameter :: rhmini = 0.80_r8 ! Minimum rh for ice cloud fraction > 0. #endif logical, public :: liu_in = .true. ! True = Liu et al 2007 Ice nucleation ! False = cooper fixed ice nucleation (MG2008) public :: ini_micro, mmicro_pcond,gamma !constants remaped real(r8), private:: g !gravity real(r8), private:: r !Dry air Gas constant real(r8), private:: rv !water vapor gas contstant 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 ! 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:: 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:: tmax_fsnow ! max temperature for transition to convective snow real(r8), private:: tmin_fsnow ! min temperature for transition to convective snow !needed for findsp real(r8), private:: tt0 ! Freezing temperature real(r8), private:: csmin,csmax,minrefl,mindbz contains !=============================================================================== subroutine ini_micro 1,47 !----------------------------------------------------------------------- ! ! Purpose: ! initialize constants for the morrison microphysics ! called from stratiform.F90 ! ! Author: Andrew Gettelman Dec 2005 ! !----------------------------------------------------------------------- integer k integer l,m, iaer real(r8) surften ! surface tension of water w/respect to air (N/m) real(r8) arg character(len=16) :: eddy_scheme = ' ' logical :: history_microphysics ! output variables for microphysics diagnostics package #ifndef WRF_PORT ! Query the PBL eddy scheme call phys_getopts(eddy_scheme_out = eddy_scheme, & history_microphysics_out = history_microphysics ) #else history_microphysics = .FALSE. #endif ! 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) ! 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) ! Aerosol information 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) ! 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 ('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 r= rair !Dry air Gas constant: note units(phys_constants are in J/K/kmol) rv= rh2o !water vapor gas contstant 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 for snow/rain fraction for convective clouds tmax_fsnow = tmelt tmin_fsnow = tmelt-5._r8 ! parameters below from Reisner et al. (1998) ! density parameters (kg/m3) rhosn = 250._r8 ! bulk density snow (++ ceh) 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 = 400.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 ! 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 pi=4._r8*atan(1.0_r8) !Range of cloudsat reflectivities (dBz) for analytic simulator csmin= -30._r8 csmax= 26._r8 mindbz = -99._r8 ! minrefl = 10._r8**(mindbz/10._r8) minrefl = 1.26e-10_r8 ! Define constants to help speed up code (limit calls to gamma function) 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 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 ( sub_column, & 1,36 lchnk, ncol, deltatin, tn, & qn, qc, qi, & nc, ni, p, pdel, cldn, & liqcldf, icecldf, & cldo, & rate1ord_cw2pr_st, & naai, npccnin, rndst,nacon, & tlat, qvlat, & qctend, qitend, nctend, nitend, effc, & effc_fn, effi, prect, preci, & nevapr, evapsnow, & prain, prodsnow, cmeout, deffi, pgamrad, & lamcrad,qsout,dsout, & rflx,sflx, qrout,reff_rain,reff_snow, & 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,mnuccdo & #ifdef WRF_PORT , nsout, nrout & #endif ) !Author: Hugh Morrison, Andrew Gettelman, NCAR ! e-mail: morrison@ucar.edu, andrew@ucar.edu use wv_saturation, only: vqsatd_water ! input arguments logical, intent(in) :: sub_column ! True = configure for sub-columns False = use w/o sub-columns (standard) 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) :: qn(pcols,pver) ! input h20 vapor mixing ratio (kg/kg) ! 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(out) :: rate1ord_cw2pr_st(pcols,pver) ! 1st order rate for direct cw to precip conversion ! used for scavenging ! Inputs for aerosol activation real(r8), intent(in) :: naai(pcols,pver) ! ice nulceation number (from microp_aero_ts) real(r8), intent(in) :: npccnin(pcols,pver) ! ccn activated number tendency (from microp_aero_ts) real(r8), intent(in) :: rndst(pcols,pver,4) ! radius of 4 dust bins for contact freezing (from microp_aero_ts) real(r8), intent(in) :: nacon(pcols,pver,4) ! number in 4 dust bins for contact freezing (from microp_aero_ts) ! 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) :: 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) :: rflx(pcols,pver+1) ! grid-box average rain flux (kg m^-2 s^-1) real(r8), intent(out) :: sflx(pcols,pver+1) ! grid-box average snow flux (kg m^-2 s^-1) 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), intent(out) :: mnuccdo(pcols,pver) ! mass tendency from ice nucleation ! 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 ! for calculation of rate1ord_cw2pr_st real(r8) :: qcsinksum_rate1ord(pver) ! sum over iterations of cw to precip sink real(r8) :: qcsum_rate1ord(pver) ! sum over iterations of cloud water real(r8) :: alpha real(r8) :: dum1,dum2 !general dummy variables 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 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 ! diagnostic rain/snow for output to history ! values are in-precip (local) !!!! real(r8), intent(out) :: qrout(pcols,pver) ! grid-box average rain mixing ratio (kg/kg) real(r8), intent(out) :: reff_rain(pcols,pver) ! rain effective radius (micron) real(r8), intent(out) :: reff_snow(pcols,pver) ! snow effective radius (micron) real(r8) :: drout(pcols,pver) ! rain diameter (m) #ifndef WRF_PORT real(r8) :: nrout(pcols,pver) ! rain number concentration (1/m3) real(r8) :: nsout(pcols,pver) ! snow number concentration (1/m3) #else !WRF needs nrout and nsout to be the ouput variables real(r8), intent(out) :: nrout(pcols,pver) ! rain number concentration (1/m3) real(r8), intent(out) :: nsout(pcols,pver) ! snow number concentration (1/m3) #endif 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) ! loop array variables integer i,k,nstep,n, l integer ii,kk, m ! 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 real(r8) ndfaer1, ndfaer2, ndfaer3, ndfaer4 real(r8) nslip1, nslip2, nslip3, nslip4 ! 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 !Initialize rain size rercld(1:ncol,1:pver)=0._r8 arcld(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 mnuccdo(1:ncol,1:pver)=0._r8 ! 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) ! 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 drout(1:ncol,1:pver)=0._r8 !! initialize as fillvalue to avoid Floating Exceptions reff_rain(1:ncol,1:pver)=fillvalue reff_snow(1:ncol,1:pver)=fillvalue ! 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 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) ! subcolumns, set cloud fraction variables to one ! if cloud water or ice is present, if not present ! set to mincld (mincld used instead of zero, to prevent ! possible division by zero errors if (sub_column) then cldm(i,k)=mincld cldmw(i,k)=mincld icldm(i,k)=mincld lcldm(i,k)=mincld if (qc(i,k).ge.qsmall) then lcldm(i,k)=1. cldm(i,k)=1. cldmw(i,k)=1. end if if (qi(i,k).ge.qsmall) then cldm(i,k)=1. icldm(i,k)=1. end if end if ! sub-columns ! 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 ! if aerosols interact with ice set number of activated ice nuclei dum2=naai(i,k) 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 and read in (naai) dum2i(i,k)=naai(i,k) 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 end do ! i loop end do ! k loop cldo(:ncol,:)=cldn(:ncol,:) !! 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 ! note: mtime for bulk aerosols was set to: mtime=deltat/1200._r8 mtime=1._r8 rate1ord_cw2pr_st(:,:)=0._r8 ! rce 2010/05/01 !!!! 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 qcsinksum_rate1ord(1:pver)=0._r8 qcsum_rate1ord(1:pver)=0._r8 !!!!!!!!! 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 ! for sub-columns cldm has already been set to 1 if cloud ! water or ice is present, so cldmax will be correctly set below ! and nothing extra needs to be done here 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 ! number tendency (npccnin) is read in from companion routine ! assume aerosols already activated are equal to number of existing droplets for simplicity ! multiply by cloud fraction to obtain grid-average tendency if (qcic(i,k).ge.qsmall) then npccn(k) = max(0._r8,npccnin(i,k)) dum2l(i,k)=(nc(i,k)+npccn(k)*deltat)/lcldm(i,k) dum2l(i,k)=max(dum2l(i,k),cdnl/rho(i,k)) ! sghan minimum in #/cm3 ncmax = dum2l(i,k)*lcldm(i,k) else npccn(k)=0._r8 dum2l(i,k)=0._r8 ncmax = 0._r8 end if !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 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 ! hm switch for sub-columns, don't include sub-grid qc if (sub_column) then prc(k) = 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) nprc1(k) = prc(k)/(qcic(i,k)/ncic(i,k)) else 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)/cons22 nprc1(k) = prc(k)/(qcic(i,k)/ncic(i,k)) end if ! sub-column switch 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) ! subcolumns if (sub_column) then mnuccc(k) = & pi*pi/36._r8*rhow* & cdist1(k)*gamma(7._r8+pgam(k))* & bimm*(exp(aimm*(273.15_r8-t(i,k)))-1._r8)/ & lamc(k)**3/lamc(k)**3 nnuccc(k) = & pi/6._r8*cdist1(k)*gamma(pgam(k)+4._r8) & *bimm* & (exp(aimm*(273.15_r8-t(i,k)))-1._r8)/lamc(k)**3 else 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)))-1._r8)/ & 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)))-1._r8)/lamc(k)**3 end if ! sub-columns ! contact freezing (-40<T<-3 C) (Young, 1974) with hooks into simulated dust ! dust size and number in 4 bins are read in from companion routine 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)))) nslip1=1.0_r8+(mfp/rndst(i,k,1))*(1.257_r8+(0.4_r8*Exp(-(1.1_r8*rndst(i,k,1)/mfp))))! Slip correction factor nslip2=1.0_r8+(mfp/rndst(i,k,2))*(1.257_r8+(0.4_r8*Exp(-(1.1_r8*rndst(i,k,2)/mfp)))) nslip3=1.0_r8+(mfp/rndst(i,k,3))*(1.257_r8+(0.4_r8*Exp(-(1.1_r8*rndst(i,k,3)/mfp)))) nslip4=1.0_r8+(mfp/rndst(i,k,4))*(1.257_r8+(0.4_r8*Exp(-(1.1_r8*rndst(i,k,4)/mfp)))) ndfaer1=1.381e-23_r8*t(i,k)*nslip1/(6._r8*pi*viscosity*rndst(i,k,1)) ! aerosol diffusivity (m2/s) ndfaer2=1.381e-23_r8*t(i,k)*nslip2/(6._r8*pi*viscosity*rndst(i,k,2)) ndfaer3=1.381e-23_r8*t(i,k)*nslip3/(6._r8*pi*viscosity*rndst(i,k,3)) ndfaer4=1.381e-23_r8*t(i,k)*nslip4/(6._r8*pi*viscosity*rndst(i,k,4)) if (sub_column) then mnucct(k) = & (ndfaer1*(nacon(i,k,1)*tcnt)+ndfaer2*(nacon(i,k,2)*tcnt)+ndfaer3*(nacon(i,k,3)*tcnt)+ndfaer4*(nacon(i,k,4)*tcnt))*pi*pi/3._r8*rhow* & cdist1(k)*gamma(pgam(k)+5._r8)/lamc(k)**4 nnucct(k) = (ndfaer1*(nacon(i,k,1)*tcnt)+ndfaer2*(nacon(i,k,2)*tcnt)+ndfaer3*(nacon(i,k,3)*tcnt)+ndfaer4*(nacon(i,k,4)*tcnt))*2._r8*pi* & cdist1(k)*gamma(pgam(k)+2._r8)/lamc(k) else mnucct(k) = gamma(qcvar+4._r8/3._r8)/(cons3*qcvar**(4._r8/3._r8))* & (ndfaer1*(nacon(i,k,1)*tcnt)+ndfaer2*(nacon(i,k,2)*tcnt)+ndfaer3*(nacon(i,k,3)*tcnt)+ndfaer4*(nacon(i,k,4)*tcnt))*pi*pi/3._r8*rhow* & cdist1(k)*gamma(pgam(k)+5._r8)/lamc(k)**4 nnucct(k) = gamma(qcvar+1._r8/3._r8)/(cons3*qcvar**(1._r8/3._r8))* & (ndfaer1*(nacon(i,k,1)*tcnt)+ndfaer2*(nacon(i,k,2)*tcnt)+ndfaer3*(nacon(i,k,3)*tcnt)+ndfaer4*(nacon(i,k,4)*tcnt))*2._r8*pi* & cdist1(k)*gamma(pgam(k)+2._r8)/lamc(k) end if ! sub-column switch ! 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)))-1._r8)/lamr(k)**3 & /lamr(k)**3 nnuccr(k) = pi*nric(i,k)*bimm* & (exp(aimm*(273.15_r8-t(i,k)))-1._r8)/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 ! add sub-column switch if (sub_column) then pra(k) = & 67._r8*(qcic(i,k)*qric(i,k))**1.15_r8 npra(k) = pra(k)/(qcic(i,k)/ncic(i,k)) else 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)) end if ! sub-column switch 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 !PMA if (abs(prc(k)+pra(k)+mnuccc(k)+mnucct(k)+msacwi(k)+psacws(k)+bergs(k)) > 1.e-20_r8) then ratio = qce/deltat/lcldm(i,k)/(prc(k)+pra(k)+mnuccc(k)+mnucct(k)+msacwi(k)+psacws(k)+bergs(k))*omsm else ratio = 0.5_r8 end if 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 !PMA if (abs(nprc1(k)+npra(k)+nnuccc(k)+nnucct(k)+npsacws(k)-nsubc(k)) > 1.e-20_r8) then ratio = nce/deltat/((nprc1(k)+npra(k)+nnuccc(k)+nnucct(k)+& npsacws(k)-nsubc(k))*lcldm(i,k))*omsm else ratio = 0.5_r8 end if nprc1(k) = nprc1(k)*ratio npra(k) = npra(k)*ratio nnuccc(k) = nnuccc(k)*ratio nnucct(k) = nnucct(k)*ratio 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 !jdf if(abs(prci(k)+prai(k)).gt.1.0e-20) then ratio = (qie/deltat+(mnuccc(k)+mnucct(k)+msacwi(k))*lcldm(i,k))/((prci(k)+prai(k))*icldm(i,k))*omsm else ratio=0.5 endif !jdf 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 if(abs( ((nprci(k)+nprai(k)-nsubi(k))*icldm(i,k))*omsm ) .gt. 1.0e-20_r8) then ratio = (nie/deltat+(nnucct(k)+nsacwi(k))*lcldm(i,k))/ & ((nprci(k)+nprai(k)-nsubi(k))*icldm(i,k))*omsm else ratio = 0.5 endif 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) ! 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) qcsum_rate1ord(k) = qcsum_rate1ord(k) + qc(i,k) ! 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) mnuccdo(i,k)=mnuccdo(i,k)+mnuccd(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)/cpp*deltat > 275.15_r8) then if (qstot > 0._r8) then ! make sure melting snow doesn't reduce temperature below threshold dum = -xlf/cpp*qstot/(dz(i,k)*rho(i,k)) if (t(i,k)+tlat(i,k)/cpp*deltat+dum.lt.275.15_r8) then dum = (t(i,k)+tlat(i,k)/cpp*deltat-275.15_r8)*cpp/xlf dum = dum/(xlf/cpp*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)/cpp*deltat < (tmelt - 5._r8)) then if (qrtot > 0._r8) then ! make sure freezing rain doesn't increase temperature above threshold dum = xlf/cpp*qrtot/(dz(i,k)*rho(i,k)) if (t(i,k)+tlat(i,k)/cpp*deltat+dum.gt.(tmelt - 5._r8)) then dum = -(t(i,k)+tlat(i,k)/cpp*deltat-(tmelt-5._r8))*cpp/xlf dum = dum/(xlf/cpp*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 do k = 1, pver rate1ord_cw2pr_st(i,k) = qcsinksum_rate1ord(k)/max(qcsum_rate1ord(k),1.0e-30_r8) end do 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) mnuccdo(i,k)=mnuccdo(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) !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*(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 = & 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)/cpp*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/cpp if (t(i,k)+tlat(i,k)/cpp*deltat+dum.lt.tmelt) then dum = (t(i,k)+tlat(i,k)/cpp*deltat-tmelt)*cpp/xlf dum = dum/dumi(i,k)*xlf/cpp 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)/cpp*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/cpp if (t(i,k)+tlat(i,k)/cpp*deltat+dum.gt.233.15_r8) then dum = -(t(i,k)+tlat(i,k)/cpp*deltat-233.15_r8)*cpp/xlf dum = dum/dumc(i,k)*xlf/cpp 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)*lcldm(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*(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*(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(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 ! 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)=3._r8*rhosn/917._r8*(pi * rhosn * nsout(i,k)/qsout(i,k))**(-1._r8/3._r8) endif end do end do call outfld('DSNOW',dsout, pcols, lchnk) !calculate effective radius of rain and snow in microns for COSP using Eq. 9 of COSP v1.3 manual do i = 1,ncol do k=1,pver !! RAIN if (qrout(i,k).gt.1.e-7_r8.and.nrout(i,k).gt.0._r8) then reff_rain(i,k)=1.5_r8*(pi * rhow * nrout(i,k)/qrout(i,k))**(-1._r8/3._r8)*1.e6_r8 endif !! SNOW if (qsout(i,k).gt.1.e-7_r8.and.nsout(i,k).gt.0._r8) then reff_snow(i,k)=1.5_r8*(pi * rhosn * nsout(i,k)/qsout(i,k))**(-1._r8/3._r8)*1.e6_r8 endif end do end do ! 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) end do end do call outfld('NCAL',ncal, pcols,lchnk) call outfld('NCAI',ncai, 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.qsmall.and.(qsout(i,k)+dumi(i,k).gt.qsmall)) then nfice(i,k)=(qsout(i,k) + dumi(i,k))/dumfice endif if (nfice(i,k).gt.1._r8) then nfice(i,k)=1._r8 endif enddo enddo call outfld('FICE',nfice, pcols, lchnk) return end subroutine mmicro_pcond ! !cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc FUNCTION GAMMA(X) 124 !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 end module cldwat2m_micro