! Note: Comments starting with "!!" are directly taken from CAM's driver routine for the micro-physics (stratiform.F90)
! Updated to CESM1.0.3 (CAM5.1.01) by Balwinder.Singh@pnnl.gov
!----------------------------------------------------------------------------------------------------------
!Possible future Modifications:
!1. *** IMPORTANT-WARNING *** conv_water_in_rad is hardwired to be equal to 1. It should be a namelist variable
!2. QME3D computation is WRONG as it doesn't include CMELIQ contribution as CMELIQ is
! computed in macrophysics, which is not ported into WRF yet
!3. Computations such as cldfsnow,icswp etc. are not correct as CONCLD (convective
! cloud fraction) variable is not avaible to microphysics
!4. The code ouputs variables which can be used in RRTMG radiation but RRTMG radiation doesn't
! use these variables as of now
!5. More robust cloud fraction calculation can be included in the future versions
!----------------------------------------------------------------------------------------------------------
!----------------------------------------------------------------------------------------------------------
!Important Notes:
!1. New cloud fraction computations are added by Po-Lun Ma (PMA)
!2. Macrophysics processes are added by PMA into this driver
!----------------------------------------------------------------------------------------------------------
#define MODAL_AERO
module module_mp_cammgmp_driver 4
!!-------------------------------------------------------------------------------------------------------
!! Purpose:
!!
!! Provides the CAM interface to the prognostic cloud microphysics
!!
!! Author: Andrew Gettelman, Cheryl Craig, October 2010
!! Origin: modified from stratiform.F90
!! (Boville 2002, Coleman 2004, Park 2009, Kay 2010)
! Ported to WRF by Balwinder.Singh@pnnl.gov
!!-------------------------------------------------------------------------------------------------------
use shr_kind_mod
, only: r8=>shr_kind_r8
use physconst
, only: gravit
use module_cam_support
, only: pcnst =>pcnst_mp, pcols, pver, pverp
#ifdef WRF_CHEM
use module_cam_support
, only: cam_mam_aerosols
#endif
use constituents
, only: cnst_get_ind, cnst_name, qmin
#ifdef WRF_CHEM
use module_state_description, only: num_chem, param_first_scalar, &
CBMZ_CAM_MAM7_NOAQ, CBMZ_CAM_MAM7_AQ, CBMZ_CAM_MAM3_NOAQ, &
CBMZ_CAM_MAM3_AQ
#endif
implicit none
private
save
public :: CAMMGMP_INIT
public :: CAMMGMP
#ifdef WRF_CHEM
public :: physics_ptend_init ! Mimics CAM's physics ptend init. Also used in wet scavaging code in WRF_CHEM
public :: physics_update ! Mimics CAM's physics update. Also used in wet scavaging code in WRF_CHEM
#endif
!! ------------------------- !
!! Private Module Parameters !
!! ------------------------- !
!! Choose either 'intermediate' ('inter') or complete ('compl') cloud microphysics
!! inter : Microphysics assumes 'liquid stratus frac = ice stratus frac = max( liquid stratus frac, ice stratus frac )'.
!! compl : Microphysics explicitly treats 'liquid stratus frac .ne. ice stratus frac'
!! for CAM5, only 'inter' is functional
character(len=5), private, parameter :: micro_treatment = 'inter'
logical, private :: sub_column = .false. ! True = configure microphysics for sub-columns
!! False = use in regular mode w/o sub-columns
!! -------------------------------- !
!! End of Private Module Parameters !
!! -------------------------------- !
integer :: &
ixcldliq, &! cloud liquid amount index
ixcldice, &! cloud ice amount index
ixnumliq, &! cloud liquid number index
ixnumice ! cloud ice water index
integer :: chem_opt, ptend_top_level, ptend_bot_level
real(r8), parameter :: qthresh_mass = 1.0e-11 ! Typical val: 1e-6 kg/kg ; Negligible val: 1e-11 kg/kg
real(r8), parameter :: qthresh_numl = 5.0e2 ! Typical val: 5E7 #/kg ; Negligible val: 5e2 #/kg
real(r8), parameter :: qthresh_numi = 1.0e-1 ! Typical val: 1E4 #/kg ; Negligible val: 1e-1 #/kg
!Following constants (dp1 and dp2) are obtained from cloud_fraction.F90 of CAM for highest resolution(0.23x0.31)
real(r8), parameter :: dp1 = 0.10_r8
real(r8), parameter :: dp2 = 500.0_r8
contains
subroutine CAMMGMP(itimestep, dt, p8w, p_hyd & 1,25
, t_phy, pi_phy, z_at_w, qfx &
, tke_pbl, turbtype3d, smaw3d &
, dlf3d, dlf2_3d, rliq2d, z_sea_level &
, kvh3d, ht, alt, accum_mode &
, aitken_mode, coarse_mode, icwmrsh3d &
, icwmrdp3d, shfrc3d, cmfmc3d, cmfmc2_3d &
, config_flags, f_ice_phy, f_rain_phy &
#ifdef WRF_CHEM
, dgnum4d, dgnumwet4d &
#endif
, ids, ide, jds, jde, kds, kde &
, ims, ime, jms, jme, kms, kme &
, its, ite, jts, jte, kts, kte &
!Output variables from CAMMGMP
, th, cldfra_old_mp, cldfra_mp,cldfra_mp_all,cldfrai &
, cldfral, cldfra_conv,wsedl3d, rainnc &
, rainncv, snownc, snowncv,sr &
, qv_curr, qc_curr, qi_curr,qs_curr &
, qr_curr, nc3d, ni3d,ns3d,nr3d,qndrop &
, rh_old_mp,lcd_old_mp & !PMA- added for macrophysics
#ifdef WRF_CHEM
, chem &
, qme3d,prain3d,nevapr3d &
, rate1ord_cw2pr_st3d &
#endif
, xland,snowh )
!!-------------------------------------------------------- !
!! !
!! Purpose: !
!! !
!! Interface to sedimentation, detrain, cloud fraction and !
!! cloud macro - microphysics subroutines !
!! !
!! Author: D.B. Coleman !
!! Date: Apr 2004 !
!! !
! Polun Ma added simple macrophysics scheme
!!-------------------------------------------------------- !
use shr_kind_mod
, only: r8 => shr_kind_r8
use cldwat2m_micro
, only: mmicro_pcond
use microp_aero
, only: microp_aero_ts
use physconst
, only: cpair, tmelt ! tmelt is added for computing saturation specific humidity for ice and liquid
#ifdef MODAL_AERO
use modal_aero_data
, only: modeptr_accum => modeptr_accum_mp, &
numptr_amode => numptr_amode_mp , lspectype_amode => lspectype_amode_mp, &
specdens_amode => specdens_amode_mp, voltonumb_amode => voltonumb_amode_mp, &
lmassptr_amode => lmassptr_amode_mp, modeptr_aitken => modeptr_aitken_mp, &
modeptr_coarse => modeptr_coarse_mp, ntot_amode => ntot_amode_mp, &
nspec_amode => nspec_amode_mp
#endif
#ifdef WRF_CHEM
use module_data_cam_mam_asect
, only: lptr_chem_to_q, lptr_chem_to_qqcw, factconv_chem_to_q
#endif
use wv_saturation
, only: epsqs, polysvp ! Added for computing saturation specific humidity for ice and liquid
use conv_water
, only: conv_water_4rad
use cldwat
, only: cldwat_fice
use module_state_description, only: CAMZMSCHEME, CAMUWSHCUSCHEME,F_QV, F_QC, F_QI, F_QS
use module_configure
, only: grid_config_rec_type
implicit none
!
! Input arguments
!
TYPE(grid_config_rec_type), INTENT(IN ) :: config_flags
integer, intent(in) :: itimestep !Timestep count
integer, intent(in) :: ids,ide, jds,jde, kds,kde
integer, intent(in) :: ims,ime, jms,jme, kms,kme
integer, intent(in) :: its,ite, jts,jte, kts,kte
real, intent(in) :: dt !Timestep
real, intent(in) :: accum_mode, aitken_mode, coarse_mode
real, dimension( ims:ime, jms:jme ), intent(in) :: ht !Terrain height (m)
real, dimension( ims:ime, jms:jme ), intent(in) :: qfx !Upward moisture flux at the surface(kg m-2 s-1)
real, dimension( ims:ime, jms:jme ), intent(in) :: rliq2d !Vertically-integrated reserved cloud condensate(m s-1)
real, dimension( ims:ime, jms:jme ), intent(in) :: xland
real, dimension( ims:ime, jms:jme ), intent(in) :: snowh
real, dimension( ims:ime, kms:kme, jms:jme ), intent(in) :: dlf3d !Detraining cloud water tendency from convection
real, dimension( ims:ime, kms:kme, jms:jme ), intent(in) :: dlf2_3d !dq/dt due to export of cloud water into environment by shallow convection(kg/kg/s)
real, dimension( ims:ime, kms:kme, jms:jme ), intent(in) :: p8w !Hydrostatic Pressure at level interface (Pa)
real, dimension( ims:ime, kms:kme, jms:jme ), intent(in) :: p_hyd !Hydrostatic pressure(Pa)
real, dimension( ims:ime, kms:kme, jms:jme ), intent(in) :: z_sea_level !Height above sea level at mid-level (m)
real, dimension( ims:ime, kms:kme, jms:jme ), intent(in) :: t_phy !Temperature (K)
real, dimension( ims:ime, kms:kme, jms:jme ), intent(in) :: z_at_w !Height above sea level at layer interfaces (m)
real, dimension( ims:ime, kms:kme, jms:jme ), intent(in) :: pi_phy !Dimensionless pressure [unitless]
real, dimension( ims:ime, kms:kme, jms:jme ), intent(in) :: tke_pbl !Turbulence kinetic energy from Mellor-Yamada-Janjic (MYJ) (m^2/s^2)
real, dimension( ims:ime, kms:kme, jms:jme ), intent(in) :: kvh3d !Eddy diffusivity for heat(m^2/s)
real, dimension( ims:ime, kms:kme, jms:jme ), intent(in) :: turbtype3d !Turbulent interface types [ no unit ]
real, dimension( ims:ime, kms:kme, jms:jme ), intent(in) :: smaw3d !Normalized Galperin instability function for momentum ( 0<= <=4.964 and 1 at neutral ) [no units]
real, dimension( ims:ime, kms:kme, jms:jme ), intent(in) :: alt !inverse density(m3/kg)
real, dimension( ims:ime, kms:kme, jms:jme ), intent(in) :: F_ICE_PHY !Fraction of ice
real, dimension( ims:ime, kms:kme, jms:jme ), intent(in) :: F_RAIN_PHY !Fraction of rain
!For conv_water_4rad
real, dimension( ims:ime, kms:kme, jms:jme ), intent(in) :: shfrc3d !Shallow cloud fraction
real, dimension( ims:ime, kms:kme, jms:jme ), intent(in) :: cmfmc3d !Deep + Shallow Convective mass flux [ kg /s/m^2 ]
real, dimension( ims:ime, kms:kme, jms:jme ), intent(in) :: cmfmc2_3d !Shallow convective mass flux [ kg/s/m^2 ]
real, dimension( ims:ime, kms:kme, jms:jme ), intent(in) :: icwmrsh3d !Shallow cumulus in-cloud water mixing ratio (kg/m2)
real, dimension( ims:ime, kms:kme, jms:jme ), intent(in) :: icwmrdp3d !Deep Convection in-cloud water mixing ratio (kg/m2)
#ifdef WRF_CHEM
real, dimension( ims:ime, kms:kme, jms:jme, ntot_amode ), intent(in) :: dgnum4d, dgnumwet4d ! 4-dimensional Number mode diameters
#endif
!2d in-outs
real, dimension( ims:ime , jms:jme ), intent(inout) :: rainnc !grid scale precipitation (mm)
real, dimension( ims:ime , jms:jme ), intent(inout) :: rainncv !one time step grid scale precipitation (mm/step)
real, dimension( ims:ime , jms:jme ), intent(inout) :: snownc !grid scale snow and ice (mm)
real, dimension( ims:ime , jms:jme ), intent(inout) :: snowncv !one time step grid scale snow and ice (mm/step)
!3d in-outs
real, dimension( ims:ime, kms:kme, jms:jme ), intent(inout) :: cldfra_old_mp !Old Cloud fraction
real, dimension( ims:ime, kms:kme, jms:jme ), intent(inout) :: rh_old_mp !Old RH
real, dimension( ims:ime, kms:kme, jms:jme ), intent(inout) :: lcd_old_mp !Old liquid cloud fraction
real, dimension( ims:ime, kms:kme, jms:jme ), intent(inout) :: qv_curr !Water vapor mixing ratio - Moisture (kg/kg)
real, dimension( ims:ime, kms:kme, jms:jme ), intent(inout) :: qc_curr !Cloud water mixing ratio - Cloud liq (kg/kg)
real, dimension( ims:ime, kms:kme, jms:jme ), intent(inout) :: qi_curr !Ice mixing ratio -Cloud ice (kg/kg)
real, dimension( ims:ime, kms:kme, jms:jme ), intent(inout) :: qs_curr !Snow mixing ratio -Cloud ice (kg/kg)
real, dimension( ims:ime, kms:kme, jms:jme ), intent(inout) :: qr_curr !Rain mixing ratio -Cloud ice (kg/kg)
real, dimension( ims:ime, kms:kme, jms:jme ), intent(inout) :: ni3d !Cloud ice number concentration (#/kg)
real, dimension( ims:ime, kms:kme, jms:jme ), intent(inout) :: nc3d !Cloud water number concentration (#/kg)
real, dimension( ims:ime, kms:kme, jms:jme ), intent(inout) :: ns3d !Snow number concentration (#/kg)
real, dimension( ims:ime, kms:kme, jms:jme ), intent(inout) :: nr3d !rain number concentration (#/kg)
real, dimension( ims:ime, kms:kme, jms:jme ), intent(inout) :: qndrop !droplet number mixing ratio (#/kg)
real, dimension( ims:ime, kms:kme, jms:jme ), intent(inout) :: th !Potential temperature (K)
real, dimension( ims:ime, kms:kme, jms:jme ), intent(inout) :: wsedl3d !Sedimentation velocity of stratiform liquid cloud droplet (m/s)
real, dimension( ims:ime, kms:kme, jms:jme ), intent(inout) :: cldfra_mp !New Cloud fraction
real, dimension( ims:ime, kms:kme, jms:jme ), intent(inout) :: cldfra_conv !New Cloud fraction
real, dimension( ims:ime, kms:kme, jms:jme ), intent(inout) :: cldfra_mp_all !New Cloud fraction
real, dimension( ims:ime, kms:kme, jms:jme ), intent(inout) :: cldfrai
real, dimension( ims:ime, kms:kme, jms:jme ), intent(inout) :: cldfral
#ifdef WRF_CHEM
real, dimension( ims:ime, kms:kme, jms:jme ), intent(inout) :: qme3d !Net condensation rate (kg/kg/s)
real, dimension( ims:ime, kms:kme, jms:jme ), intent(inout) :: prain3d !Rate of conversion of condensate to precipitation (kg/kg/s)
real, dimension( ims:ime, kms:kme, jms:jme ), intent(inout) :: nevapr3d !Evaporation rate of rain + snow (kg/kg/s)
real, dimension( ims:ime, kms:kme, jms:jme ), intent(inout) :: rate1ord_cw2pr_st3d !1st order rate for direct conversion of strat. cloud water to precip (1/s)
#endif
#ifdef WRF_CHEM
!4d in-outs
real, dimension( ims:ime, kms:kme, jms:jme, num_chem ), intent(inout) :: chem !Chem array
#endif
!2d outs
real, dimension( ims:ime , jms:jme ), intent( out) :: sr !one time step mass ratio of snow to total precip
!
! Local variables
!
!Other variables
character*250 :: wrfmessage
logical :: is_first_step !Flag to know if this a first time step
logical :: ptend_loc_ls, ptend_all_ls !Flag for updating tendencies
logical :: ptend_loc_lq(pcnst),ptend_all_lq(pcnst) !Flag for updating tendencies
integer :: i,k,m,n,iw,jw,kw,imode,itsm1,itile_len,ktep1,kflip,ips,kcam
#ifdef WRF_CHEM
integer :: p1st,l2 !For iterating loop of NUM_CHEM for CHEM array
#endif
integer :: lchnk !Chunk identifier
integer :: ncol !Number of atmospheric columns
integer :: conv_water_in_rad
real (r8) :: multFrc
real(r8) :: dtime !Timestep in real(8) format
real(r8) :: dp
real(r8) :: phis(pcols) !Geopotential at terrain height (m2/s2)
real(r8) :: state_t(pcols,kte)
real(r8) :: state_q(pcols,kte,pcnst)
real(r8) :: state_s(pcols,kte)
real(r8) :: state_pmid(pcols,kte)
real(r8) :: state_pdel(pcols,kte)
real(r8) :: state_rpdel(pcols,kte)
real(r8) :: state_zm(pcols,kte)
real(r8) :: state_omega(pcols,kte)
real(r8) :: state_pint(pcols,kte+1)
real(r8) :: state1_t(pcols,kte)
real(r8) :: state1_q(pcols,kte,pcnst)
real(r8) :: state1_s(pcols,kte)
real(r8) :: state1_pmid(pcols,kte)
real(r8) :: state1_pdel(pcols,kte)
real(r8) :: state1_rpdel(pcols,kte)
real(r8) :: state1_zm(pcols,kte)
real(r8) :: state1_omega(pcols,kte)
real(r8) :: state1_pint(pcols,kte+1)
character*24 :: ptend_loc_name
real(r8) :: ptend_loc_s(pcols,kte)
real(r8) :: ptend_loc_q(pcols,kte,pcnst)
character*24 :: ptend_all_name
real(r8) :: ptend_all_s(pcols,kte)
real(r8) :: ptend_all_q(pcols,kte,pcnst)
real(r8) :: tmpnaer,tmpmaer
real(r8) :: cmeliq(pcols,kte) ! Rate of cond-evap of liq within the cloud
real(r8) :: nrout(pcols,kte) ! rain number concentration (1/m3)
real(r8) :: nsout(pcols,kte) ! snow number concentration (1/m3)
real(r8) :: sh_icwmr(pcols,kte) ! Shallow conv. cloud water
real(r8) :: dp_icwmr(pcols,kte) ! Deep conv. cloud water
real(r8) :: fice(pcols,kte) ! Ice partitioning ratio
real(r8) :: fsnow(pcols,kte) ! Fractional snow content for convection
real(r8) :: sh_frac(pcols,kte) ! Shallow convective cloud fraction
real(r8) :: dp_frac(pcols,kte) ! Deep convective cloud fraction
real(r8) :: cmfmc(pcols,kte+1)
real(r8) :: cmfmc2(pcols,kte+1)
real(r8), dimension(pcols,kte) :: esl ! liquid sat vapor pressure (pa) ! for phil suggested modifications
real(r8), dimension(pcols,kte) :: esi ! ice sat vapor pressure (pa)
real(r8), dimension(pcols,kte) :: qvs ! liquid saturation vapor mixing ratio ! for phil suggested modifications
real(r8), dimension(pcols,kte) :: qvi ! ice saturation vapor mixing ratio
!Following variables are added by PMA for Macrophysics
real(r8), dimension(pcols,kte) :: ttt ! Temperature (PMA)
real(r8), dimension(pcols,kte) :: rh_old ! RH at previous timestep (PMA)
real(r8), dimension(pcols,kte) :: qi_mac ! Temperature (PMA)
!End variables addition by PMA
!Variables with CAM data structure
real(r8) :: rliq(pcols) !Vertical integral of liquid not yet in q(ixcldliq) or vertically-integrated reserved cloud condensate (m/s)
!Following 6 variables are intent-out in CAM's driver for micro-physics
real(r8) :: prec_str(pcols) ! [Total] Sfc flux of precip from stratiform [ m/s ]
real(r8) :: snow_str(pcols) ! [Total] Sfc flux of snow from stratiform [ m/s ]
real(r8) :: prec_sed(pcols) ! Surface flux of total cloud water from sedimentation
real(r8) :: snow_sed(pcols) ! Surface flux of cloud ice from sedimentation
real(r8) :: prec_pcw(pcols) ! Sfc flux of precip from microphysics [ m/s ]
real(r8) :: snow_pcw(pcols) ! Sfc flux of snow from microphysics [ m/s ]
real(r8) :: cflx(pcols,pcnst) ! Constituent flux from surface
real(r8) :: dlf(pcols,kte) ! Detrained water from convection schemes
real(r8) :: dlf2(pcols,kte) ! Detrained water from shallow convection scheme
real(r8) :: rate1cld(pcols,kte) ! array to hold rate1ord_cw2pr_st from microphysics
! Physics buffer fields
real(r8), dimension(pcols,kte) :: cld ! Total cloud fraction
real(r8), dimension(pcols,kte) :: ast ! Relative humidity cloud fraction
real(r8), dimension(pcols,kte) :: aist ! Physical ice stratus fraction
real(r8), dimension(pcols,kte) :: alst ! Physical liquid stratus fraction
real(r8), dimension(pcols,kte) :: concld ! Convective cloud fraction
real(r8), dimension(pcols,kte) :: qme
real(r8), dimension(pcols,kte) :: prain ! Total precipitation (rain + snow)
real(r8), dimension(pcols,kte) :: nevapr ! Evaporation of total precipitation (rain + snow)
real(r8), dimension(pcols,kte) :: rel ! Liquid effective drop radius (microns)
real(r8), dimension(pcols,kte) :: rei ! Ice effective drop size (microns)
real(r8), dimension(pcols,kte) :: rel2 ! Liquid effective drop radius (microns)
real(r8), dimension(pcols,kte) :: rei2 ! Ice effective drop size (microns)
real(r8), dimension(pcols,kte) :: cldo ! Old cloud fraction
real(r8), dimension(pcols,kte) :: wsedl ! Sedimentation velocity of liquid stratus cloud droplet [ m/s ]
real(r8), dimension(pcols,kte) :: rel_fn ! Ice effective drop size at fixed number (indirect effect) (microns)
real(r8), dimension(pcols,kte+1) :: kkvh ! Vertical eddy diffusivity
#ifdef MODAL_AERO
real(r8), target, dimension(pcols,kte,pcnst) :: qqcw ! Cloud-borne aerosol
real(r8), dimension(pcols,kte,ntot_amode) :: dgnumwet ! Number mode diameter
real(r8), dimension(pcols,kte,ntot_amode) :: dgnum ! Number mode diameter
real(r8), dimension(pcols,kte) :: rate1ord_cw2pr_st ! 1st order rate for direct conversion of
! strat. cloud water to precip (1/s) ! rce 2010/05/01
#endif
! physics buffer fields for COSP simulator
real(r8), dimension(pcols,kte+1) :: mgflxprc ! MG grid-box mean flux_large_scale_cloud_rain+snow at interfaces (kg/m2/s)
real(r8), dimension(pcols,kte+1) :: mgflxsnw ! MG grid-box mean flux_large_scale_cloud_snow at interfaces (kg/m2/s)
real(r8), dimension(pcols,kte) :: mgmrprc ! MG grid-box mean mixingratio_large_scale_cloud_rain+snow at interfaces (kg/kg)
real(r8), dimension(pcols,kte) :: mgmrsnw ! MG grid-box mean mixingratio_large_scale_cloud_snow at interfaces (kg/kg)
real(r8), dimension(pcols,kte) :: mgreffrain ! MG diagnostic rain effective radius (um)
real(r8), dimension(pcols,kte) :: mgreffsnow ! MG diagnostic snow effective radius (um)
real(r8), dimension(pcols,kte) :: cvreffliq ! convective cloud liquid effective radius (um)
real(r8), dimension(pcols,kte) :: cvreffice ! convective cloud ice effective radius (um)
! physics buffer fields for radiation
real(r8), dimension(pcols,kte) :: dei ! Ice effective diameter (meters) (AG: microns?)
real(r8), dimension(pcols,kte) :: mu ! Size distribution shape parameter for radiation
real(r8), dimension(pcols,kte) :: lambdac ! Size distribution slope parameter for radiation
real(r8), dimension(pcols,kte) :: iciwp ! In-cloud ice water path for radiation
real(r8), dimension(pcols,kte) :: iclwp ! In-cloud liquid water path for radiation
! For rrtm optics. specificed distribution.
real(r8) :: mucon ! Convective size distribution shape parameter
real(r8) :: dcon ! Convective size distribution effective radius (meters)
real(r8) :: lamcon ! Convective size distribution slope parameter (meters-1)
real(r8) :: deicon ! Convective ice effective diameter (meters)
! Physics buffer fields
real(r8), dimension(pcols,kte) :: deiconv ! Ice effective diameter (microns)
real(r8), dimension(pcols,kte) :: muconv ! Size distribution shape parameter for radiation
real(r8), dimension(pcols,kte) :: lambdaconv ! Size distribution slope parameter for radiation
real(r8), dimension(pcols,kte) :: iciwpst ! Stratiform in-cloud ice water path for radiation
real(r8), dimension(pcols,kte) :: iclwpst ! Stratiform in-cloud liquid water path for radiation
real(r8), dimension(pcols,kte) :: iciwpconv ! Convective in-cloud ice water path for radiation
real(r8), dimension(pcols,kte) :: iclwpconv ! Convective in-cloud liquid water path for radiation
real(r8), dimension(pcols,kte+1) :: tke ! TKE from the moist PBL scheme
real(r8), dimension(pcols,kte+1) :: turbtype ! Turbulence type from the moist PBL scheme
real(r8), dimension(pcols,kte+1) :: smaw ! Instability function of momentum from the moist PBL scheme
! Local variables for in-cloud water quantities adjusted for convective water
real(r8) allcld_ice (pcols,kte) ! All-cloud cloud ice
real(r8) allcld_liq (pcols,kte) ! All-cloud liquid
! Snow
real(r8), dimension(pcols,kte) :: cldfsnow ! Cloud fraction for liquid+snow
real(r8), dimension(pcols,kte) :: icswp ! In-cloud snow water path
real(r8), dimension(pcols,kte) :: des ! Snow effective diameter (m)
real(r8) qsout(pcols,kte) ! Snow mixing ratio
real(r8) :: qrout(pcols,kte) ! Rain mixing ratio
real(r8) :: rflx(pcols,kte+1) ! grid-box average rain flux (kg m^-2 s^-1)
real(r8) :: sflx(pcols,kte+1) ! grid-box average snow flux (kg m^-2 s^-1)
real(r8) :: reff_rain(pcols,kte) ! rain effective radius (um)
real(r8) :: reff_snow(pcols,kte) ! snow effective radius (um)
real(r8) icecldf(pcols,kte) ! Ice cloud fraction
real(r8) liqcldf(pcols,kte) ! Liquid cloud fraction (combined into cloud)
real(r8) icecldf_out(pcols,kte) ! Ice cloud fraction
real(r8) liqcldf_out(pcols,kte) ! Liquid cloud fraction (combined into cloud)
! Local variables for microphysics
real(r8) rdtime ! 1./dtime
real(r8) qtend(pcols,kte) ! Moisture tendencies
real(r8) ttend(pcols,kte) ! Temperature tendencies
real(r8) ltend(pcols,kte) ! Cloud liquid water tendencies
real(r8) evapsnow(pcols,kte) ! Local evaporation of snow
real(r8) prodsnow(pcols,kte) ! Local production of snow
real(r8) icimr(pcols,kte) ! In cloud ice mixing ratio
real(r8) icwmr(pcols,kte) ! In cloud water mixing ratio
real(r8) icimrst(pcols,kte) ! In stratus ice mixing ratio
real(r8) icwmrst(pcols,kte) ! In stratus water mixing ratio
real(r8) icimrst_out(pcols,kte) ! In stratus ice mixing ratio
real(r8) icwmrst_out(pcols,kte) ! In stratus water mixing ratio
real(r8) cmeice(pcols,kte) ! Rate of cond-evap of ice within the cloud
real(r8) temp(pcols)
real(r8) res(pcols,kte)
! MG micro diagnostics
real(r8) qcsevap(pcols,kte) ! Evaporation of falling cloud water
real(r8) qisevap(pcols,kte) ! Sublimation of falling cloud ice
real(r8) qvres(pcols,kte) ! Residual condensation term to remove excess saturation
real(r8) cmeiout(pcols,kte) ! Deposition/sublimation rate of cloud ice
real(r8) vtrmc(pcols,kte) ! Mass-weighted cloud water fallspeed
real(r8) vtrmi(pcols,kte) ! Mass-weighted cloud ice fallspeed
real(r8) qcsedten(pcols,kte) ! Cloud water mixing ratio tendency from sedimentation
real(r8) qisedten(pcols,kte) ! Cloud ice mixing ratio tendency from sedimentation
real(r8) prao(pcols,kte)
real(r8) prco(pcols,kte)
real(r8) mnuccco(pcols,kte)
real(r8) mnuccto(pcols,kte)
real(r8) mnuccdo(pcols,kte)
real(r8) mnuccdohet(pcols,kte)
real(r8) msacwio(pcols,kte)
real(r8) psacwso(pcols,kte)
real(r8) bergso(pcols,kte)
real(r8) bergo(pcols,kte)
real(r8) melto(pcols,kte)
real(r8) homoo(pcols,kte)
real(r8) qcreso(pcols,kte)
real(r8) prcio(pcols,kte)
real(r8) praio(pcols,kte)
real(r8) qireso(pcols,kte)
real(r8) ftem(pcols,kte)
real(r8) mnuccro(pcols,kte)
real(r8) pracso (pcols,kte)
real(r8) meltsdt(pcols,kte)
real(r8) frzrdt (pcols,kte)
real(r8) dpdlfliq(pcols,kte)
real(r8) dpdlfice(pcols,kte)
real(r8) shdlfliq(pcols,kte)
real(r8) shdlfice(pcols,kte)
real(r8) dpdlft (pcols,kte)
real(r8) shdlft (pcols,kte)
#ifdef MODAL_AERO
integer l, lnum, lnumcw, lmass, lmasscw
#endif
! Variables for MG microphysics
real(r8) dum1,dum2
real(r8) qc(pcols,kte)
real(r8) qi(pcols,kte)
real(r8) nc(pcols,kte)
real(r8) ni(pcols,kte)
real(r8) icinc(pcols,kte) ! In cloud ice number conc
real(r8) cdnumc(pcols) ! Vertically-integrated droplet concentration
real(r8) icwnc(pcols,kte) ! In cloud water number conc
real(r8) iwc(pcols,kte) ! Grid box average ice water content
real(r8) lwc(pcols,kte) ! Grid box average liquid water content
real(r8) effliq(pcols,kte) ! In cloud liq eff rad
real(r8) effice(pcols,kte) ! In cloud ice eff rad
real(r8) effliq_fn(pcols,kte) ! In cloud liq eff rad at fixed number concentration
real(r8) wsub(pcols,kte) ! Sub-grid vertical velocity (m/s)
real(r8) wsubi(pcols,kte) ! Sub-grid vertical velocity for ice (m/s)
! Output from mmicro_pcond
real(r8) tlat(pcols,kte)
real(r8) qvlat(pcols,kte)
real(r8) qcten(pcols,kte)
real(r8) qiten(pcols,kte)
real(r8) ncten(pcols,kte)
real(r8) niten(pcols,kte)
real(r8) effc(pcols,kte)
real(r8) effc_fn(pcols,kte) ! Liquid effective radius at fixed number (for indirect calc)
real(r8) effi(pcols,kte)
real(r8) prect(pcols)
real(r8) preci(pcols)
! Output from microp_aero_ts for aerosol actication
real(r8) naai(pcols,kte) !ice nucleation number
real(r8) naai_hom(pcols,kte) !ice nucleation number (homogeneous)
real(r8) npccn(pcols,kte) !liquid activation number tendency
real(r8) rndst(pcols,kte,4)
real(r8) nacon(pcols,kte,4)
! Averaging arrays for effective radius and number....
real(r8) efiout(pcols,kte)
real(r8) efcout(pcols,kte)
real(r8) ncout(pcols,kte)
real(r8) niout(pcols,kte)
real(r8) freqi(pcols,kte)
real(r8) freql(pcols,kte)
! Average cloud top radius & number
real(r8) ctrel(pcols)
real(r8) ctrei(pcols)
real(r8) ctnl(pcols)
real(r8) ctni(pcols)
real(r8) fcti(pcols)
real(r8) fctl(pcols)
! Gather mass mixing ratio for all aerosols affecting the climate
integer :: naer_all
real(r8) :: aermmr1(pcols,kte)
real(r8), allocatable :: aer_mmr(:,:,:) ! Aerosol mass mixing ratio
real(r8) zeros(pcols,kte)
real(r8) alst_mic(pcols,kte)
real(r8) aist_mic(pcols,kte)
real(r8), pointer :: fldcw(:,:)
real(r8) :: xland_pt
real(r8) :: snowh_pt
! ======================================================================
!cmeliq is an output from Macro physics. Its assigned zero here as Macrophysics is NOT implemented yet
!*** IMPORTANT-WARNING ***: The following assignment will produce an incorrect value of QME3D
cmeliq(:,:)=0.0_r8
!*** IMPORTANT-WARNING *** :Should be in the namelist file. Hardwired currently
conv_water_in_rad = 1
#ifdef WRF_CHEM
p1st = param_first_scalar ! Obtain CHEM array's first element's index
#endif
! Specify diameter for each mode
#ifndef WRF_CHEM
dgnumwet(:,:,:) = 0.1e-6_r8 !*** IMPORTANT-WARNING *** :Constant value for the whole domain (prescribed value). The value match precribe_aerosol_mixactivate, but units change
dgnumwet(:,:,modeptr_aitken) = 0.02e-6
dgnumwet(:,:,modeptr_coarse) = 1.0e-6
#else
if(chem_opt == 0 ) then
dgnumwet(:,:,:) = 0.1e-6_r8 !*** IMPORTANT-WARNING *** :Constant value for the whole domain (prescribed value). The value match precribe_aerosol_mixactivate, but units change
dgnumwet(:,:,modeptr_aitken) = 0.02e-6
dgnumwet(:,:,modeptr_coarse) = 1.0e-6
endif
#endif
!dgnum wet and dry are assumed to be same for now
dgnum(:,:,:) = dgnumwet(:,:,:)
!Time step is stored in the (r8) format in dtime
dtime = dt
!Flag for first time step
is_first_step = .false.
if(itimestep == 1) then
is_first_step = .true.
cldfra_old_mp(:,:,:) = 0.0_r8
rate1ord_cw2pr_st(:,:) = 0.0_r8
cldfrai(:,:,:) = 0._r8
cldfral(:,:,:) = 0._r8
cldfra_mp(:,:,:) = 0._r8
cldfra_mp_all(:,:,:) = 0._r8
cldfra_conv(:,:,:) = 0._r8
if(config_flags%shcu_physics .NE. CAMUWSHCUSCHEME) call wrf_message
('WARNING: sh_icwmr,cmfmc,cmfmc2 and sh_frac are set to zero in CAMMGMP')
if(config_flags%cu_physics .NE. CAMZMSCHEME) call wrf_message
('WARNING: dp_icwmr is set to zero in CAMMGMP')
endif
ncol = pcols
!This subroutine requires that ncol == 1
if(ncol .NE. 1) then
call wrf_error_fatal
('Number of CAM Columns (NCOL) in CAMMGMP scheme must be 1')
endif
!*** IMPORTANT-WARNING ***:Initializing variables which are **NEVER** used but required for call consistency for CAM specific subroutine calls
concld(:,:) =0.0_r8 !Required for computing some diagnostic variables. These diagnostic variables are
!commented out for now as we didn't map 'concld' with the WRF sided variables
state_omega(:,:) = 0.0_r8 !Required for calling mmicro_pcond and microp_aero_ts. Used in microp_aero_ts for
!calling dropmixnuc but **NEVER** used for any output from dropmixnuc
!Divide domain in chuncks and map WRF variables into CAM
!Loop counters are named iw,jw,kw to represent that they index WRF sided variables
!The CAM's side variables are kept almost same by just replacing '%' with an '_' [e.g state%t in CAM is state_t in WRF]
itsm1 = its - 1
itile_len = ite - itsm1
do jw = jts , jte
do iw = its , ite
xland_pt = xland(iw,jw)
snowh_pt = snowh(iw,jw)
lchnk = (jw - jts) * itile_len + (iw - itsm1) !1-D index location from a 2-D tile
phis(1) = ht(iw,jw) * gravit
ktep1 = kte + 1
!Flip vertically quantities computed at the mid points
do kw = kts, kte
kflip = ktep1 - kw
state_pmid(1,kflip) = p_hyd(iw,kw,jw) !Pressure at the mid-points (Pa) [state%pmid in CAM]
dp = p8w(iw,kw,jw) - p8w(iw,kw+1,jw) !Change in pressure (Pa)
state_pdel(1,kflip) = dp
state_rpdel(1,kflip) = 1.0_r8/dp !Reciprocal of pressure difference (1/Pa) [state%rpdel in CAM]
state_zm(1,kflip) = z_sea_level(iw,kw,jw) - ht(iw,jw) !Height above the ground at the midpoints (m) [state%zm in CAM]
state_t(1,kflip) = t_phy(iw,kw,jw) !Temprature at the mid points (K) [state%t in CAM]
state_s(1,kflip) = cpair *th(iw,kw,jw)*pi_phy(iw,kw,jw) + gravit*state_zm(1,kflip) + phis(1) ! Dry static energy (m2/s2) [state%s in CAM]-Formula tested in vertical_diffusion.F90 of CAM
!Following three formulas are obtained from ported CAM's ZM cumulus scheme
!Values of 0 cause a crash in entropy
multFrc = 1._r8/(1._r8 + qv_curr(iw,kw,jw))
state_q(1,kflip,1) = qv_curr(iw,kw,jw)*multFrc !Specific humidity [state%q(:,:,1) in CAM]
state_q(1,kflip,ixcldliq) = qc_curr(iw,kw,jw)*multFrc !Convert to moist mix ratio-cloud liquid [state%q(:,:,2) in CAM]
state_q(1,kflip,ixcldice) = qi_curr(iw,kw,jw)*multFrc !cloud ice [state%q(:,:,3) in CAM]
state_q(1,kflip,ixnumliq) = nc3d(iw,kw,jw)*multFrc
state_q(1,kflip,ixnumice) = ni3d(iw,kw,jw)*multFrc
qi_mac(1,kflip) = qi_curr(iw,kw,jw)*multFrc
!Check for negative constituents, value below 'qthresh_...' are reset to qmin
!For mass mixing ratio
if(abs(state_q(1,kflip,1)) < qthresh_mass .and. state_q(1,kflip,1) < qmin(1)) state_q(1,kflip,1) = qmin(1)
if(abs(state_q(1,kflip,ixcldliq)) < qthresh_mass .and. state_q(1,kflip,ixcldliq) < qmin(ixcldliq)) state_q(1,kflip,ixcldliq) = qmin(ixcldliq)
if(abs(state_q(1,kflip,ixcldice)) < qthresh_mass .and. state_q(1,kflip,ixcldice) < qmin(ixcldice)) state_q(1,kflip,ixcldice) = qmin(ixcldice)
!For number mixing ratio
if(abs(state_q(1,kflip,ixnumliq)) < qthresh_numl .and. state_q(1,kflip,ixnumliq) < qmin(ixnumliq)) state_q(1,kflip,ixnumliq) = qmin(ixnumliq)
if(abs(state_q(1,kflip,ixnumice)) < qthresh_numi .and. state_q(1,kflip,ixnumice) < qmin(ixnumice)) state_q(1,kflip,ixnumice) = qmin(ixnumice)
!Set negative values to qmin and generate a warning message
if(state_q(1,kflip,1) < 0.0_r8)then
!write(wrfmessage,*)'Water vapor mass mixing ratio was:', state_q(1,kflip,1),'; Reset to',qmin(1), 'in CAMMGMP driver'
!call wrf_message(wrfmessage)
state_q(1,kflip,1) = qmin(1)
endif
if(state_q(1,kflip,ixcldliq) < 0.0_r8) then
!write(wrfmessage,*)'Liquid cloud mass mixing ratio was:', state_q(1,kflip,ixcldliq),'; Reset to',qmin(ixcldliq), 'in CAMMGMP driver'
!call wrf_message(wrfmessage)
state_q(1,kflip,ixcldliq) = qmin(ixcldliq)
endif
if(state_q(1,kflip,ixcldice) < 0.0_r8) then
!write(wrfmessage,*)'Ice cloud mass mixing ratio was:', state_q(1,kflip,ixcldice),'; Reset to',qmin(ixcldice), 'in CAMMGMP driver'
!call wrf_message(wrfmessage)
state_q(1,kflip,ixcldice) = qmin(ixcldice)
endif
if(state_q(1,kflip,ixnumliq) < 0.0_r8) then
!write(wrfmessage,*)'Liquid droplet number was:', state_q(1,kflip,ixnumliq),'; Reset to',qmin(ixnumliq), 'in CAMMGMP driver'
!call wrf_message(wrfmessage)
state_q(1,kflip,ixnumliq) = qmin(ixnumliq)
endif
if(state_q(1,kflip,ixnumice) < 0.0_r8) then
!write(wrfmessage,*)'Ice crystal number was:', state_q(1,kflip,ixnumice),'; Reset to',qmin(ixnumice), 'in CAMMGMP driver'
!call wrf_message(wrfmessage)
state_q(1,kflip,ixnumice) = qmin(ixnumice)
endif
! For prescribed aerosols
qqcw(1,kflip,:) = 1.e-38_r8 !used in microp_aero for dropmicnuc, presently set to a constant value
#ifdef WRF_CHEM
if(chem_opt.NE.0 .and. config_flags%CAM_MP_MAM_cpled ) then
!Following Do-Loop is obtained from chem/module_cam_mam_aerchem_driver.F
do l = p1st, num_chem
l2 = lptr_chem_to_q(l)
if ((l2 >= 1) .and. (l2 <= pcnst)) then
state_q(1,kflip,l2) = chem(iw,kw,jw,l)*factconv_chem_to_q(l)
if(state_q(1,kflip,l2) < 0.0_r8) then
!write(wrfmessage,*)'Chem species with index', l,' was:', state_q(1,kflip,l2),'; Reset to 0.0 in CAMMGMP driver'
!call wrf_message(wrfmessage)
state_q(1,kflip,l2) = 0.0_r8
endif
end if
l2 = lptr_chem_to_qqcw(l)
if ((l2 >= 1) .and. (l2 <= pcnst)) then
qqcw(1,kflip,l2) = chem(iw,kw,jw,l)*factconv_chem_to_q(l)
if(qqcw(1,kflip,l2)< 0.0_r8) then
!write(wrfmessage,*)'Chem species with index', l,' was:', qqcw(1,kflip,l2),'; Reset to 0.0 in CAMMGMP driver'
!call wrf_message(wrfmessage)
qqcw(1,kflip,l2) = 0.0_r8
endif
end if
end do ! l
!Populate dgnums appropriately
do imode = 1 , ntot_amode
if(is_first_step) then
dgnum(1,kflip,imode) = 0.0_r8 !Set it to zero for the first time step
dgnumwet(1,kflip,imode) = 0.0_r8
else
dgnum(1,kflip,imode) = dgnum4D(iw,kw,jw,imode) !Obtained from 4D arrays
dgnumwet(1,kflip,imode) = dgnumwet4D(iw,kw,jw,imode)
endif
enddo
endif
#endif
cldo(1,kflip) = cldfra_mp_all(iw,kw,jw)
!New code by PMA
rh_old(1,kflip) = rh_old_mp(iw,kw,jw)
dlf(1,kflip) = 0.0_r8
dlf2(1,kflip) = 0.0_r8
sh_icwmr(1,kflip) = 0.0_r8
sh_frac(1,kflip) = 0.0_r8
dp_frac(1,kflip) = 0._r8
if(config_flags%shcu_physics==CAMUWSHCUSCHEME) then
sh_icwmr(1,kflip) = icwmrsh3d(iw,kw,jw) !Shallow cumulus in-cloud water mixing ratio (kg/m2)
sh_frac(1,kflip) = shfrc3d(iw,kw,jw) !Shallow convective cloud fraction
dlf2(1,kflip) = dlf2_3d(iw,kw,jw) !PMA QC detrained from shallow
endif
dp_icwmr(1,kflip) = 0.0_r8
if(config_flags%cu_physics==CAMZMSCHEME)then
dp_icwmr(1,kflip) = icwmrdp3d(iw,kw,jw) !Deep conv. cloud water
dlf(1,kflip) = dlf3d(iw,kw,jw) !PMA Qc detrained from deep+shallow
endif
enddo
do kw = kts, kte+1
kflip = kte - kw + 2
state_pint(1,kflip) = p8w(iw,kw,jw) !Pressure at interfaces [state%pint in CAM]
tke(1,kflip) = tke_pbl(iw,kw,jw) !Turbulent kinetic energy
kkvh(1,kflip) = kvh3d(iw,kw,jw) !Vertical diffusivity (m2/s)
turbtype(1,kflip) = turbtype3d(iw,kw,jw) !Turbulent interface types [ no unit ]
smaw(1,kflip) = smaw3d(iw,kw,jw) !Normalized Galperin instability function for momentum ( 0<= <=4.964 and 1 at neutral ) [no units]
cmfmc(1,kflip) = 0.0_r8
cmfmc2(1,kflip) = 0.0_r8
if(config_flags%shcu_physics==CAMUWSHCUSCHEME .or. config_flags%cu_physics == CAMZMSCHEME ) then
cmfmc(1,kflip) = cmfmc3d(iw,kw,jw) !Deep + Shallow Convective mass flux [ kg /s/m^2 ]
endif
if(config_flags%shcu_physics==CAMUWSHCUSCHEME ) then
cmfmc2(1,kflip) = cmfmc2_3d(iw,kw,jw) !Shallow convective mass flux [ kg/s/m^2 ]
endif
end do
do kcam = 1, kte
!Formulation for dp_frac is obtained from cloud_fraction.F90 of CAM
dp_frac(1,kcam) = max(0.0_r8,min(dp1*log(1.0_r8+dp2*(cmfmc(1,kcam+1)-cmfmc2(1,kcam+1))),0.60_r8)) ! Deep convective cloud fraction
end do
!set cflx zero for all the constituents, update the water vapor surface flux after that
cflx(:pcols,:) = 0.0_r8 !Surface constituent flux (kg/m2/s)
cflx(:pcols,1) = qfx(iw,jw) !Surface constituent flux (kg/m2/s)
rliq(:pcols) = rliq2d(iw,jw) !Vertically-integrated reserved cloud condensate (m/s)
!Following assignments mimics CAM's 'physics_state_copy' call
state1_pmid(:,:) = state_pmid(:,:)
state1_pdel(:,:) = state_pdel(:,:)
state1_rpdel(:,:) = state_rpdel(:,:)
state1_zm(:,:) = state_zm(:,:)
state1_t(:,:) = state_t(:,:)
state1_s(:,:) = state_s(:,:)
state1_pint(:,:) = state_pint(:,:)
state1_q(:,:,:) = state_q(:,:,:)
state1_omega(:,:) = state_omega(:,:) !*** IMPORTANT-WARNING ***:State_omega is *NOT* used for any meaningful computation at this time
call physics_ptend_init
(ptend_loc_name,ptend_loc_q,ptend_loc_s,ptend_loc_lq,ptend_loc_ls,pcnst) !! Initialize local ptend type
call physics_ptend_init
(ptend_all_name,ptend_all_q,ptend_all_s,ptend_all_lq,ptend_all_ls,pcnst) !! Initialize output ptend type
#ifdef MODAL_AERO
if( is_first_step) then
do i=1,pcnst
fldcw => qqcw(:,:,i)
if(associated(fldcw)) then
fldcw(1:pcols,1:pver) = 1.e-38_r8
end if
end do
endif
#endif
!! If first timestep, initialize heatflux....in pbuf at all time levels.
if( is_first_step) then
kkvh(:,:) = 0._r8
tke(:,:) = 0._r8
! *** IMPORTANT-WARNING ***:turbtype and smaw are used to compute 'smm' in microp_aero_ts subroutine but 'smm' is NEVER
! again used for any output from microp_aero_ts. Therefore, these variables are NOT used in any
! meaningful computations
turbtype(:,:) = 0._r8
smaw(:,:) = 0._r8
dlf(:,:) = 0._r8
dlf2(:,:) = 0._r8
endif
!! Assign default size distribution parameters for no-stratiform clouds (convection only)
!! Also put into physics buffer for possible separate use by radiation
dcon = 25.e-6_r8
mucon = 5.3_r8
deicon = 50._r8
muconv(:,:) = mucon
lambdaconv(:,:) = (mucon + 1._r8)/dcon
deiconv(:,:) = deicon
!BSINGH - CALL Macrophysics
call Macrophysics_simple
(is_first_step, pcnst, pcols, kte, ixcldliq, ixnumliq, &
lchnk, dtime, state1_t, state_pmid, state_q, dp_icwmr, sh_icwmr, dp_frac, &
sh_frac, ast,aist,alst,qi_mac,xland_pt,snowh_pt, &
!intent-inout
state1_s, state1_q, rh_old, cldo, esl, qvs, ptend_loc_name, ptend_loc_ls, &
ptend_loc_lq, ptend_loc_s,ptend_loc_q, ptend_all_name, ptend_all_ls, &
ptend_all_lq,ptend_all_s,ptend_all_q )
do kw = kts , kte
kflip = kte-kw+1
cldfral(iw,kw,jw) = alst(1,kflip)
cldfrai(iw,kw,jw) = aist(1,kflip)
CLDFRA_MP(iw,kw,jw) = ast(1,kflip)
cld(1,kflip) = ast(1,kflip)
CLDFRA_MP_all(iw,kw,jw) = min(ast(1,kflip)+min(0.8_r8,dp_frac(1,kflip)+sh_frac(1,kflip)),1._r8)
CLDFRA_CONV(iw,kw,jw) = max(min(0.8_r8,dp_frac(1,kflip)+sh_frac(1,kflip)),0._r8)
concld(1,kflip) = CLDFRA_CONV(iw,kw,jw)
cldo(1,kflip) = cldfra_old_mp(iw,kw,jw)
end do
!! ------------------------------------- !
!! From here, process computation begins !
!! ------------------------------------- !
!! ----------------------- !
!! Microp_Driver Microphysics !
!! ----------------------- !
ptend_loc_name = 'microp'
ptend_loc_ls = .true.
ptend_loc_lq(1) = .true.
ptend_loc_lq(ixcldliq) = .true.
ptend_loc_lq(ixcldice) = .true.
ptend_loc_lq(ixnumliq) = .true.
ptend_loc_lq(ixnumice) = .true.
#ifndef MODAL_AERO
call rad_cnst_get_info( 0, naero = naer_all )
allocate( aer_mmr( pcols, pver, naer_all ) )
do m = 1, naer_all
call rad_cnst_get_aer_mmr( 0, m, state1, pbuf, aermmr1 )
aer_mmr(:ncol,:,m) = aermmr1(:ncol,:)
enddo
#endif
#ifdef MODAL_AERO
#ifdef WRF_CHEM
do m = 1, ntot_amode
lnum = numptr_amode(m)
if( lnum > 0 ) then
ptend_loc_lq(lnum)= .true.
endif
do l = 1, nspec_amode(m)
lmass = lmassptr_amode(l,m)
ptend_loc_lq(lmass)= .true.
enddo
enddo
!Do not update dummy aerosols in state if chem_opt is 0 or CAM_MP_MAM_cpled == .false.
if(chem_opt == 0 .or. .NOT.config_flags%CAM_MP_MAM_cpled) then
do m = 6 , pcnst !First m = 1 to 5 are water species
ptend_loc_lq(m)= .false.
enddo
endif
#endif
#endif
zeros(:ncol,:pver) = 0._r8
qc(:ncol,:pver) = state1_q(:ncol,:pver,ixcldliq)
qi(:ncol,:pver) = state1_q(:ncol,:pver,ixcldice)
nc(:ncol,:pver) = state1_q(:ncol,:pver,ixnumliq)
ni(:ncol,:pver) = state1_q(:ncol,:pver,ixnumice)
if( micro_treatment .eq. 'inter' ) then
alst_mic(:ncol,:pver) = ast(:ncol,:pver)
aist_mic(:ncol,:pver) = ast(:ncol,:pver)
elseif( micro_treatment .eq. 'compl' ) then
alst_mic(:ncol,:pver) = alst(:ncol,:pver)
aist_mic(:ncol,:pver) = aist(:ncol,:pver)
endif
#ifndef WRF_CHEM
!Adding 7 new fields to state1_q(# mixing ratio and mass mixing ratio
!for 3 modes of prescribed aerosols[s04,dust(+sea salt),aitken]) array.
!state%q holds 5 constituents already therefore the prescribed aerosol
!are defined from 6th to 12th constituents
n = modeptr_accum !Adding 7th constituent (# mixing ratio)
!tmpnaer = 1000.0e6 !This value is taken from precribe_aerosol_mixactivate! 1.e9 #/kg ~= 1.e3 #/cm3
tmpnaer = accum_mode !172.7e6 -For ISDAC case ONLY
l = numptr_amode(n)
state1_q(:,:,l) = tmpnaer
m = 1 !Adding 6th constituent (mass mixing ratio)
tmpmaer = specdens_amode(lspectype_amode(m,n)) * tmpnaer / voltonumb_amode(n)
l = lmassptr_amode(m,n)
state1_q(:,:,l) = tmpmaer
n = modeptr_aitken !Adding 9th constituent (# mixing ratio)
!tmpnaer = 300.0e6
tmpnaer = aitken_mode !0.0e6 -For ISDAC case ONLY
l = numptr_amode(n)
state1_q(:,:,l) = tmpnaer
m = 1 !Adding 8th constituent (mass mixing ratio)
tmpmaer = specdens_amode(lspectype_amode(m,n)) * tmpnaer / voltonumb_amode(n)
l = lmassptr_amode(m,n)
state1_q(:,:,l) = tmpmaer
n = modeptr_coarse !Adding 12th constituent (# mixing ratio)
!tmpnaer = 0.2e6
tmpnaer = coarse_mode !1.1e6 -For ISDAC case ONLY
l = numptr_amode(n)
state1_q(:,:,l) = tmpnaer
tmpmaer = specdens_amode(lspectype_amode(m,n)) * tmpnaer / voltonumb_amode(n)
m = 1 !Adding 10th constituent (mass mixing ratio)
l = lmassptr_amode(m,n)
state1_q(:,:,l) = tmpmaer*0.5
m = 2 !Adding 11th constituent (mass mixing ratio)
l = lmassptr_amode(m,n)
state1_q(:,:,l) = tmpmaer*0.5
#else
if(chem_opt==0 .or. .NOT. config_flags%CAM_MP_MAM_cpled) then
do k = 1, pver
n = modeptr_accum !Adding 7th constituent (# mixing ratio)
tmpnaer = accum_mode !172.7e6 -For ISDAC case ONLY
l = numptr_amode(n)
qqcw(1,k,l) = tmpnaer*alst(1,k)*0.8
state1_q(1,k,l) = tmpnaer-qqcw(1,k,l)
m = 1 !Adding 6th constituent (mass mixing ratio)
tmpmaer = specdens_amode(lspectype_amode(m,n)) * tmpnaer / voltonumb_amode(n)
l = lmassptr_amode(m,n)
qqcw(1,k,l) = tmpmaer*alst(1,k)*0.8
state1_q(1,k,l) = tmpmaer-qqcw(1,k,l)
n = modeptr_aitken !Adding 9th constituent (# mixing ratio)
tmpnaer = aitken_mode !0.0e6 -For ISDAC case ONLY
l = numptr_amode(n)
qqcw(1,k,l) = tmpnaer*alst(1,k)*0.8
state1_q(1,k,l) = tmpnaer-qqcw(1,k,l)
m = 1 !Adding 8th constituent (mass mixing ratio)
tmpmaer = specdens_amode(lspectype_amode(m,n)) * tmpnaer / voltonumb_amode(n)
l = lmassptr_amode(m,n)
qqcw(1,k,l) = tmpmaer*alst(1,k)*0.8
state1_q(1,k,l) = tmpmaer-qqcw(1,k,l)
n = modeptr_coarse !Adding 12th constituent (# mixing ratio)
tmpnaer = coarse_mode !1.1e6 -For ISDAC case ONLY
l = numptr_amode(n)
qqcw(1,k,l) = tmpnaer*alst(1,k)*0.8
state1_q(1,k,l) = tmpnaer-qqcw(1,k,l)
tmpmaer = specdens_amode(lspectype_amode(m,n)) * tmpnaer / voltonumb_amode(n)
m = 1 !Adding 10th constituent (mass mixing ratio)
l = lmassptr_amode(m,n)
qqcw(1,k,l) = tmpmaer*alst(1,k)*0.8*0.5
state1_q(1,k,l) = tmpmaer*0.5-qqcw(1,k,l)
m = 2 !Adding 11th constituent (mass mixing ratio)
l = lmassptr_amode(m,n)
qqcw(1,k,l) = tmpmaer*alst(1,k)*0.8*0.5
state1_q(1,k,l) = tmpmaer*0.5-qqcw(1,k,l)
enddo
endif
#endif
!! calculate aerosol activation (naai for ice, npccn for liquid) and
!! dust size (rndst) and number (nacon) for contact nucleation
! Output from the following call:wsub, wsubi, naai, naai_hom, npccn, rndst,nacon
! In-out from the following call: ptend_loc_q, qqcw
!*NOTE*: Added QQCW as an output
call microp_aero_ts
( lchnk, ncol, dtime, state1_t, zeros, &
state1_q(1,1,1), qc, qi, &
nc, ni, state1_pmid, state1_pdel, ast, &
alst_mic, aist_mic, &
cldo, state1_pint, state1_rpdel, state1_zm, state1_omega, &
#ifdef MODAL_AERO
state1_q, cflx, ptend_loc_q, dgnumwet, dgnum, &
#else
aer_mmr, &
#endif
kkvh, tke, turbtype, smaw, wsub, wsubi, &
naai,naai_hom, npccn, rndst,nacon,qqcw)
!! Call MG Microphysics
!Output from the following call:rate1cld,tlat,qvlat,qcten,qiten,
! ncten,niten,effc,effc_fn,effi,prect,preci,nevapr,evapsnow,
! prain,prodsnow,cmeice,dei,mu,lambdac,qsout,des,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
!in-out from the following call: qc,qi,nc,ni,cldo
!*NOTE*: Added nsout and nrout as an ouput
call mmicro_pcond
( sub_column, lchnk, ncol, dtime, state1_t, &
state1_q(1,1,1), qc, qi, &
nc, ni, state1_pmid, state1_pdel, ast, &
alst_mic, aist_mic, &
cldo, &
rate1cld, &
naai, npccn, rndst,nacon, &
tlat, qvlat, &
qcten, qiten, ncten, niten, effc, &
effc_fn, effi, prect, preci, &
nevapr, evapsnow, &
prain, prodsnow, cmeice, dei, mu, &
lambdac, qsout, des, &
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, nsout, nrout )
do k=1,pver
do i=1,ncol
if (naai(i,k) .gt. 0._r8) then
mnuccdohet(i,k) = mnuccdo(i,k) - (naai_hom(i,k)/naai(i,k))*mnuccdo(i,k)
else
mnuccdohet(i,k) = 0._r8
end if
end do
end do
mgflxprc(:ncol,:pverp) = rflx(:ncol,:pverp) + sflx(:ncol,:pverp)
mgflxsnw(:ncol,:pverp) = sflx(:ncol,:pverp)
mgmrprc(:ncol,:pver) = qrout(:ncol,:pver) + qsout(:ncol,:pver)
mgmrsnw(:ncol,:pver) = qsout(:ncol,:pver)
mgreffrain(:ncol,:pver) = reff_rain(:ncol,:pver)
mgreffsnow(:ncol,:pver) = reff_snow(:ncol,:pver)
!! calculate effective radius of convective liquid and ice using dcon and deicon (not used by code, not useful for COSP)
cvreffliq(:ncol,:pver) = 9.0_r8 !! hard-coded as average of hard-coded values used for deep/shallow convective detrainment (near line 1502)
cvreffice(:ncol,:pver) = 37.0_r8 !! hard-coded as average of hard-coded values used for deep/shallow convective detrainment (near line 1505)
!! Reassign rate1 if modal aerosols
#ifdef MODAL_AERO
rate1ord_cw2pr_st(1:ncol,1:pver)=rate1cld(1:ncol,1:pver)
#endif
!! Sedimentation velocity for liquid stratus cloud droplet
wsedl(:ncol,:pver) = vtrmc(:ncol,:pver)
!! Nominal values for no microp_driver (convective only) cloud.
!! Convert snow mixing ratio to microns
do k = 1, pver
do i = 1, ncol
des(i,k) = des(i,k) * 1.e6_r8
if( ast(i,k) .lt. 1.e-4_r8 ) then
mu(i,k) = mucon
lambdac(i,k) = (mucon + 1._r8)/dcon
dei(i,k) = deicon
endif
end do
end do
!! Net microp_driver condensation rate
!*** IMPORTANT-WARNING ***: Following computation of QME will yeild WRONG answer as CMELIQ is set to zero
qme(:ncol,:pver) = cmeliq(:ncol,:pver) + cmeiout(:ncol,:pver)
#ifndef MODAL_AERO
deallocate(aer_mmr)
#endif
do k = 1, pver
do i = 1, ncol
ptend_loc_s(i,k) = tlat(i,k)
ptend_loc_q(i,k,1) = qvlat(i,k)
ptend_loc_q(i,k,ixcldliq) = qcten(i,k)
ptend_loc_q(i,k,ixcldice) = qiten(i,k)
ptend_loc_q(i,k,ixnumliq) = ncten(i,k)
ptend_loc_q(i,k,ixnumice) = niten(i,k)
enddo
enddo
!! For precip, accumulate only total precip in prec_pwc and snow_pwc variables.
!! Other precip output varirables are set to 0
prec_pcw(:ncol) = prect(:ncol)
snow_pcw(:ncol) = preci(:ncol)
prec_sed(:ncol) = 0._r8
snow_sed(:ncol) = 0._r8
prec_str(:ncol) = prec_pcw(:ncol) + prec_sed(:ncol) - rliq(:ncol)
snow_str(:ncol) = snow_pcw(:ncol) + snow_sed(:ncol)
!! ------------------------------- !
!! Update microphysical tendencies !
!! ------------------------------- !
call physics_ptend_sum
(ptend_loc_ls,ptend_loc_lq,ptend_loc_s,ptend_loc_q,ptend_all_ls,ptend_all_lq,ptend_all_s,ptend_all_q,pcnst)
ptend_all_name = 'cldwat'
call physics_update
( lchnk,dtime,state1_q,ptend_loc_q,state1_s,ptend_loc_s,ptend_loc_name,ptend_loc_lq,ptend_loc_ls,pcnst)
call physics_ptend_init
( ptend_loc_name,ptend_loc_q,ptend_loc_s, ptend_loc_lq,ptend_loc_ls,pcnst)
if( micro_treatment .eq. 'inter' ) then
icecldf(:ncol,:pver) = ast(:ncol,:pver)
liqcldf(:ncol,:pver) = ast(:ncol,:pver)
elseif( micro_treatment .eq. 'compl' ) then
icecldf(:ncol,:pver) = aist(:ncol,:pver)
liqcldf(:ncol,:pver) = alst(:ncol,:pver)
endif
!! Effective droplet radius
rel(:ncol,:pver) = effc(:ncol,:pver)
rel_fn(:ncol,:pver) = effc_fn(:ncol,:pver)
rei(:ncol,:pver) = effi(:ncol,:pver)
rel2(:ncol,:pver) = rel(:ncol,:pver) * 0.9071_r8 !! Convect to effective volume radius assuming pgam = 8
rei2(:ncol,:pver) = rei(:ncol,:pver) * 0.6057_r8 !! Convect to effective volume radius at pgam = 0 for ice
!! ----------------------------------------------------------- !
!! Adjust in-cloud water values to take account of convective !
!! in-cloud water. It is used to calculate the values of !
!! icwlp and iciwp to pass to the radiation. !
!! ----------------------------------------------------------- !
allcld_ice(:ncol,:pver) = 0._r8 !! Grid-avg all cloud liquid
allcld_liq(:ncol,:pver) = 0._r8 !! Grid-avg all cloud ice
if( conv_water_in_rad /= 0 ) then
!Following formulation is obtained from macrop_driver.F90 of CAM
call cldwat_fice
( ncol, state1_t, fice, fsnow )
!Balwinder.Singh@pnnl.gov: Changed the argument list to avoid pbuf
call conv_water_4rad
( lchnk, ncol, ast, sh_icwmr, dp_icwmr, &
fice, sh_frac, dp_frac, conv_water_in_rad, rei, state1_pdel, &
state1_q(:,:,ixcldliq), state1_q(:,:,ixcldice), &
allcld_liq, allcld_ice )
else
allcld_liq(:ncol,:) = state1_q(:ncol,:,ixcldliq) ! Grid-ave all cloud liquid
allcld_ice(:ncol,:) = state1_q(:ncol,:,ixcldice) ! " ice
end if
!! ------------------------------------------------------------ !
!! Compute in cloud ice and liquid mixing ratios !
!! Note that 'iclwp, iciwp' are used for radiation computation. !
!! ------------------------------------------------------------ !
do k = 1, pver
do i = 1, ncol
!! Limits for in-cloud mixing ratios consistent with MG microphysics
!! in-cloud mixing ratio 0.0001 to 0.005 kg/kg
icimr(i,k) = min( allcld_ice(i,k) / max(0.0001_r8,cld(i,k)),0.005_r8 )
icwmr(i,k) = min( allcld_liq(i,k) / max(0.0001_r8,cld(i,k)),0.005_r8 )
icimrst(i,k) = min( state1_q(i,k,ixcldice) / max(0.0001_r8,icecldf(i,k)),0.005_r8 )
icwmrst(i,k) = min( state1_q(i,k,ixcldliq) / max(0.0001_r8,liqcldf(i,k)),0.005_r8 )
icinc(i,k) = state1_q(i,k,ixnumice) / max(0.0001_r8,icecldf(i,k)) * state1_pmid(i,k) / (287.15_r8*state1_t(i,k))
icwnc(i,k) = state1_q(i,k,ixnumliq) / max(0.0001_r8,liqcldf(i,k)) * state1_pmid(i,k) / (287.15_r8*state1_t(i,k))
iwc(i,k) = allcld_ice(i,k) * state1_pmid(i,k) / (287.15_r8*state1_t(i,k))
lwc(i,k) = allcld_liq(i,k) * state1_pmid(i,k) / (287.15_r8*state1_t(i,k))
effliq(i,k) = effc(i,k)
effliq_fn(i,k) = effc_fn(i,k)
effice(i,k) = effi(i,k)
!! Calculate total cloud water paths in each layer
iciwp(i,k) = icimr(i,k) * state1_pdel(i,k) / gravit
iclwp(i,k) = icwmr(i,k) * state1_pdel(i,k) / gravit
!! Calculate microp_driver cloud water paths in each layer
!! Note: uses stratiform cloud fraction!
iciwpst(i,k) = min(state1_q(i,k,ixcldice)/max(0.0001_r8,ast(i,k)),0.005_r8) * state1_pdel(i,k) / gravit
iclwpst(i,k) = min(state1_q(i,k,ixcldliq)/max(0.0001_r8,ast(i,k)),0.005_r8) * state1_pdel(i,k) / gravit
!! Calculate convective in-cloud LWP.
!Commented the following two diagnostics as 'concld' is not mapped correctly with variables on WRF side
!iclwpconv(i,k) = max(allcld_liq(i,k) - state_q(i,k,ixcldliq),0._r8)/max(0.0001_r8,concld(i,k))
!iciwpconv(i,k) = max(allcld_ice(i,k) - state_q(i,k,ixcldice),0._r8)/max(0.0001_r8,concld(i,k))
!! ------------------------------ !
!! Adjust cloud fraction for snow !
!! ------------------------------ !
cldfsnow(i,k) = cld(i,k)
!! If cloud and only ice ( no convective cloud or ice ), then set to 0.
if( ( cldfsnow(i,k) .gt. 1.e-4_r8 ) .and. &
( concld(i,k) .lt. 1.e-4_r8 ) .and. &
( state1_q(i,k,ixcldliq) .lt. 1.e-10_r8 ) ) then
!Commented the following diagnostics as 'concld' is not mapped correctly with variables on WRF side
!cldfsnow(i,k) = 0._r8
endif
!! If no cloud and snow, then set to 0.25
if( ( cldfsnow(i,k) .lt. 1.e-4_r8 ) .and. ( qsout(i,k) .gt. 1.e-6_r8 ) ) then
!Commented the following diagnostics as 'concld' is not mapped correctly with variables on WRF side
!cldfsnow(i,k) = 0.25_r8
endif
!! Calculate in-cloud snow water path
!Commented the following diagnostics as 'concld' is not mapped correctly with variables on WRF side
!icswp(i,k) = qsout(i,k) / max( 0.0001_r8, cldfsnow(i,k) ) * state1_pdel(i,k) / gravit
enddo
enddo
!! --------------------- !
!! History Output Fields !
!! --------------------- !
!! Column droplet concentration
do i = 1, ncol
cdnumc(i) = 0._r8
do k = 1, pver
cdnumc(i) = cdnumc(i) + state1_q(i,k,ixnumliq)*state1_pdel(i,k)/gravit
end do
end do
!! Averaging for new output fields
efcout(:,:) = 0._r8
efiout(:,:) = 0._r8
ncout(:,:) = 0._r8
niout(:,:) = 0._r8
freql(:,:) = 0._r8
freqi(:,:) = 0._r8
liqcldf_out(:,:) = 0._r8
icecldf_out(:,:) = 0._r8
icwmrst_out(:,:) = 0._r8
icimrst_out(:,:) = 0._r8
do k = 1, pver
do i = 1, ncol
if( liqcldf(i,k) .gt. 0.01_r8 .and. icwmrst(i,k) .gt. 5.e-5_r8 ) then
efcout(i,k) = effc(i,k)
ncout(i,k) = icwnc(i,k)
freql(i,k) = 1._r8
liqcldf_out(i,k) = liqcldf(i,k)
icwmrst_out(i,k) = icwmrst(i,k)
endif
if( icecldf(i,k) .gt. 0.01_r8 .and. icimrst(i,k) .gt. 1.e-6_r8 ) then
efiout(i,k) = effi(i,k)
niout(i,k) = icinc(i,k)
freqi(i,k) = 1._r8
icecldf_out(i,k) = icecldf(i,k)
icimrst_out(i,k) = icimrst(i,k)
endif
end do
end do
!! Cloud top effective radius and number.
fcti(:) = 0._r8
fctl(:) = 0._r8
ctrel(:) = 0._r8
ctrei(:) = 0._r8
ctnl(:) = 0._r8
ctni(:) = 0._r8
do i = 1, ncol
do k = 1, pver
if( liqcldf(i,k) .gt. 0.01_r8 .and. icwmrst(i,k) .gt. 1.e-7_r8 ) then
ctrel(i) = effc(i,k)
ctnl(i) = icwnc(i,k)
fctl(i) = 1._r8
exit
endif
if( icecldf(i,k) .gt. 0.01_r8 .and. icimrst(i,k) .gt. 1.e-7_r8 ) then
ctrei(i) = effi(i,k)
ctni(i) = icinc(i,k)
fcti(i) = 1._r8
exit
endif
enddo
enddo
!Following update finally updates the state variables
call physics_update
( lchnk,dtime,state_q,ptend_all_q,state_s,ptend_all_s,ptend_all_name,ptend_all_lq,ptend_all_ls,pcnst)
!Post processing of the output from CAMMGMP
do kw=kts,kte
kflip = kte-kw+1
!Following equation are derived following UWPBL and CAMZM schemes
qv_curr(iw,kw,jw) = state_q(1,kflip,1) / (1.0_r8 - state_q(1,kflip,1))
multFrc = 1._r8 + qv_curr(iw,kw,jw)
qc_curr(iw,kw,jw) = state_q(1,kflip,2) * multFrc
qi_curr(iw,kw,jw) = state_q(1,kflip,3) * multFrc
qs_curr(iw,kw,jw) = qsout(1,kflip) * multFrc
qr_curr(iw,kw,jw) = qrout(1,kflip) * multFrc
nc3d(iw,kw,jw) = state_q(1,kflip,4) * multFrc
qndrop(iw,kw,jw) = nc3d(iw,kw,jw) !QNDROP is used in RRTMG radiation scheme
ni3d(iw,kw,jw) = state_q(1,kflip,5) * multFrc
!nr3d ans ns3d are in the units of #/kg but nrout and nsout are in the units of #/m3.
!Therefore these variables are multiplied by ALT (inverse density(m3/kg))
ns3d(iw,kw,jw) = nsout(1,kflip) * alt(iw,kw,jw) * multFrc
nr3d(iw,kw,jw) = nrout(1,kflip) * alt(iw,kw,jw) * multFrc
th(iw,kw,jw) = (state_s(1,kflip)-gravit*z_sea_level(iw,kw,jw))/(cpair*pi_phy(iw,kw,jw))
wsedl3d(iw,kw,jw) = wsedl(1,kflip)
cldfra_old_mp(iw,kw,jw) = ast(1,kflip)
!Update RH - PMA
ttt(1,kflip) = (state_s(1,kflip)-gravit*z_sea_level(iw,kw,jw))/cpair
esl(1,kflip) = polysvp
(ttt(1,kflip),0)
qvs(1,kflip) = max(1.e-30_r8,epsqs*esl(1,kflip)/(state_pmid(1,kflip)-(1._r8-epsqs)*esl(1,kflip)))
rh_old_mp(iw,kw,jw) = max(0._r8,state_q(1,kflip,1) / qvs(1,kflip))
lcd_old_mp(iw,kw,jw) = alst(1,kflip)
#ifdef WRF_CHEM
if(chem_opt .NE. 0 .and. config_flags%CAM_MP_MAM_cpled ) then
do l = p1st, num_chem
l2 = lptr_chem_to_q(l)
if ((l2 >= 1) .and. (l2 <= pcnst)) then
chem(iw,kw,jw,l) = state_q(1,kflip,l2)/factconv_chem_to_q(l)
end if
l2 = lptr_chem_to_qqcw(l)
if ((l2 >= 1) .and. (l2 <= pcnst)) then
chem(iw,kw,jw,l) = qqcw(1,kflip,l2)/factconv_chem_to_q(l)
end if
end do ! l
endif
qme3d(iw,kw,jw) = qme(1,kflip)
prain3d(iw,kw,jw) = prain(1,kflip)
nevapr3d(iw,kw,jw) = nevapr(1,kflip)
rate1ord_cw2pr_st3d(iw,kw,jw) = rate1ord_cw2pr_st(1,kflip)
#endif
end do
! Precipitation(for each time step) is stored in RAINNCV variable of WRF. Following precipitation
! calculation is taken from 'PRECL'variable of CAM. In 'cam_diagnostic.F90' file of CAM, PRECL is
! computed as PRECL=PREC_SED+PREC_PCW.
! PREC_PCW and PREC_SED are output from CAMMGMP (or stratiform.F90 in CAM). Here, we store PREC_SED+PREC_PCW
! (i.e. PRECL) in RAINNCV variable of WRF. Units of PRECL are m/s. We convert it to mm (millimeter)
! by multiplying it by 1.e3 and multiplying it by 'DT'
rainncv(iw,jw) = (prec_sed(1) + prec_pcw(1))*dtime*1.0e3_r8 ! in mm
rainnc (iw,jw) = rainnc(iw,jw)+ rainncv(iw,jw)
!Similar to RAINNCV, SNOWNCV is computed following CAM's SNOWL variable in 'cam_diagnostic.F90'
snowncv(iw,jw) = (snow_sed(1) + snow_pcw(1))*dtime*1.0e3_r8 ! in mm
snownc (iw,jw) = snownc(iw,jw) + snowncv(iw,jw)
sr(iw,jw) = snowncv(iw,jw)/(rainncv(iw,jw) + 1.E-12_r8)
enddo !iw loop
enddo !jw loop
end subroutine CAMMGMP
!---------------------------------------------------------------------------------------------
subroutine physics_update(state_lchnk,dt,state_q,ptend_q,state_s,ptend_s,ptend_name,ptend_lq,ptend_ls,pcnst_in) 7,6
! This subroutine partially mimics CAM's subroutine by similar name in physics_type.F90 module
! Please note that it is implimented just to serve the purpose of porting CAMMGMP scheme
!
!Author: Balwinder.Singh@pnl.gov
!---------------------------------------------------------------------------------------------
implicit none
integer , intent(in) :: state_lchnk, pcnst_in
real(r8), intent(in) :: dt
character*24, intent(inout) :: ptend_name
logical , intent(inout) :: ptend_ls
logical , intent(inout) :: ptend_lq(pcnst_in)
real(r8), intent(inout) :: ptend_s(pcols,pver)
real(r8), intent(inout) :: ptend_q(pcols,pver,pcnst_in)
real(r8), intent(inout) :: state_q(pcols,pver,pcnst_in)
real(r8), intent(inout) :: state_s(pcols,pver)
character*40 :: name ! param and tracer name for qneg3
character(len=16) :: microp_scheme
integer :: m,i,k,ncol
integer :: ixcldice, ixcldliq, ixnumice, ixnumliq
microp_scheme = 'MG'
ptend_top_level = 1
ptend_bot_level = pver
ncol = pcols
! Update dry static energy
if(ptend_ls) then
do k = ptend_top_level, ptend_bot_level
do i = 1, ncol
state_s(i,k) = state_s(i,k) + ptend_s(i,k) * dt
end do
end do
end if
! Update constituents, all schemes use time split q: no tendency kept
call cnst_get_ind
('CLDICE', ixcldice, abort=.false.)
call cnst_get_ind
('CLDLIQ', ixcldliq, abort=.false.)
! Check for number concentration of cloud liquid and cloud ice (if not present
! the indices will be set to -1)
call cnst_get_ind
('NUMICE', ixnumice, abort=.false.)
call cnst_get_ind
('NUMLIQ', ixnumliq, abort=.false.)
do m = 1, pcnst_in
if(ptend_lq(m)) then
do k = ptend_top_level, ptend_bot_level
do i = 1,ncol
state_q(i,k,m) = state_q(i,k,m) + ptend_q(i,k,m) * dt
end do
end do
! now test for mixing ratios which are too small
! don't call qneg3 for number concentration variables
if (m .ne. ixnumice .and. m .ne. ixnumliq) then
name = trim(ptend_name) // '/' // trim(cnst_name(m))
call qneg3
(trim(name), state_lchnk, ncol, pcols, pver, m, m, qmin(m), state_q(1,1,m))
else
do k = ptend_top_level, ptend_bot_level
do i = 1,ncol
! checks for number concentration
state_q(i,k,m) = max(1.e-12_r8,state_q(i,k,m))
state_q(i,k,m) = min(1.e10_r8,state_q(i,k,m))
end do
end do
end if
end if
end do
! special tests for cloud liquid
if (ixcldliq > 1) then
if(ptend_lq(ixcldliq)) then
if (ptend_name == 'stratiform' .or. ptend_name == 'cldwat' ) then
else if (ptend_name == 'convect_deep') then
where (state_q(:ncol,:pver,ixcldliq) < 1.e-36_r8)
state_q(:ncol,:pver,ixcldliq) = 0._r8
end where
! also zero out number concentration
if ( microp_scheme .eq. 'MG' ) then
where (state_q(:ncol,:pver,ixcldliq) < 1.e-36_r8)
state_q(:ncol,:pver,ixnumliq) = 0._r8
end where
end if
end if
end if
end if
! special tests for cloud ice
if (ixcldice > 1) then
if(ptend_lq(ixcldice)) then
if (ptend_name == 'stratiform' .or. ptend_name == 'cldwat' ) then
else if (ptend_name == 'convect_deep') then
where (state_q(:ncol,:pver,ixcldice) < 1.e-36_r8)
state_q(:ncol,:pver,ixcldice) = 0._r8
end where
! also zero out number concentration
if ( microp_scheme .eq. 'MG' ) then
where (state_q(:ncol,:pver,ixcldice) < 1.e-36_r8)
state_q(:ncol,:pver,ixnumice) = 0._r8
end where
end if
end if
end if
end if
! Derive new temperature and geopotential fields if heating or water tendency not 0.
!if (ptend_ls .or. ptend_lq(1)) then
! call geopotential_dse( &
! state_lnpint, state_lnpmid, state_pint , state_pmid , state_pdel , state_rpdel , &
! state_s , state_q(1,1,1),state_phis , rair , gravit , cpair , &
! zvir , state_t , state_zi , state_zm , ncol )
!end if
! Reset all parameterization tendency flags to false
call physics_ptend_reset
(ptend_name,ptend_q,ptend_s,ptend_lq,ptend_ls,pcnst_in)
end subroutine physics_update
!---------------------------------------------------------------------------------------------
subroutine physics_ptend_init(ptend_name,ptend_q,ptend_s,ptend_lq,ptend_ls,pcnst_in) 7,1
! This subroutine partially mimics CAM's subroutine by similar name in physics_type.F90 module
! Please note that it is implimented just to serve the purpose of porting CAMMGMP scheme
!Author: Balwinder.Singh@pnl.gov
!---------------------------------------------------------------------------------------------
implicit none
integer, intent(in) :: pcnst_in
character*24, intent(inout) :: ptend_name
logical , intent(inout):: ptend_ls
logical , intent(inout):: ptend_lq(pcnst_in)
real(r8), intent(inout):: ptend_s(pcols,pver)
real(r8), intent(inout):: ptend_q(pcols,pver,pcnst_in)
ptend_name = "none"
ptend_lq(:) = .TRUE.
ptend_ls = .TRUE.
call physics_ptend_reset
(ptend_name,ptend_q,ptend_s,ptend_lq,ptend_ls,pcnst_in)
return
end subroutine physics_ptend_init
!---------------------------------------------------------------------------------------------
subroutine physics_ptend_reset(ptend_name,ptend_q,ptend_s,ptend_lq,ptend_ls,pcnst_in) 2
! This subroutine partially mimics CAM's subroutine by similar name in physics_type.F90 module
! Please note that it is implimented just to serve the purpose of porting CAMMGMP scheme
!Author: Balwinder.Singh@pnl.gov
!---------------------------------------------------------------------------------------------
implicit none
integer, intent(in) :: pcnst_in
character*24, intent(inout) :: ptend_name
logical , intent(inout):: ptend_ls
logical , intent(inout):: ptend_lq(pcnst_in)
real(r8), intent(inout):: ptend_s(pcols,pver)
real(r8), intent(inout):: ptend_q(pcols,pver,pcnst_in)
integer :: m
if(ptend_ls) then
ptend_s = 0._r8
endif
do m = 1, pcnst_in
if(ptend_lq(m)) then
ptend_q(:,:,m) = 0._r8
endif
end do
ptend_name = "none"
ptend_lq(:) = .FALSE.
ptend_ls = .FALSE.
ptend_top_level = 1
ptend_bot_level = pver
return
end subroutine physics_ptend_reset
!---------------------------------------------------------------------------------------------
subroutine physics_ptend_sum(ptend_ls,ptend_lq,ptend_s,ptend_q,ptend_sum_ls,ptend_sum_lq,ptend_sum_s,ptend_sum_q, pcnst_in) 4
! This subroutine partially mimics CAM's subroutine by similar name in physics_type.F90 module
! Please note that it is implimented just to serve the purpose of porting CAMMGMP scheme
!Author: Balwinder.Singh@pnl.gov
!---------------------------------------------------------------------------------------------
!-----------------------------------------------------------------------
! Add ptend fields to ptend_sum for ptend logical flags = .true.
! Where ptend logical flags = .false, don't change ptend_sum
!-----------------------------------------------------------------------
!------------------------------Arguments--------------------------------
integer, intent(in) :: pcnst_in
logical, intent(in) :: ptend_ls ! New parameterization flag
logical, intent(in) :: ptend_lq(pcnst_in) ! New parameterization flag
real(r8), intent(in) :: ptend_s(pcols,pver) ! New parameterization tendency
real(r8), intent(in) :: ptend_q(pcols,pver,pcnst_in) ! New parameterization tendency
logical, intent(inout) :: ptend_sum_ls ! Flag for ptend_sum
logical, intent(inout) :: ptend_sum_lq(pcnst_in) ! Flag for ptend_sum
real(r8), intent(inout) :: ptend_sum_s(pcols,pver) ! Sum of incoming ptend_sum and ptend
real(r8), intent(inout) :: ptend_sum_q(pcols,pver,pcnst_in) ! Sum of incoming ptend_sum and ptend
!---------------------------Local storage-------------------------------
integer :: k,m ! constituent indices
integer :: ncol,i
!-----------------------------------------------------------------------
ptend_top_level = 1
ptend_bot_level = pver
ncol = pcols
if(ptend_ls) then
ptend_sum_ls = .true.
do i = 1, ncol
do k = ptend_top_level, ptend_bot_level
ptend_sum_s(i,k) = ptend_sum_s(i,k) + ptend_s(i,k)
end do
end do
end if
! Update constituents
do m = 1, pcnst_in
if(ptend_lq(m)) then
ptend_sum_lq(m) = .true.
do i = 1,ncol
do k = ptend_top_level, ptend_bot_level
ptend_sum_q(i,k,m) = ptend_sum_q(i,k,m) + ptend_q(i,k,m)
end do
end do
end if
end do
end subroutine physics_ptend_sum
!---------------------------------------------------------------------------------------------
subroutine cal_cldfra_mp_1d(cldl,cldi,qqv, qqc, qqi,tt,pp,xland_pt,snowh_pt) 3,5
!Author: Po-Lun Ma
!Ported by: Balwinder Singh
!---------------------------------------------------------------------------------------------
use wv_saturation
, only: epsqs, polysvp
use shr_kind_mod
, only: r8=>shr_kind_r8
use physconst
, only: tmelt
real(r8), intent(in) :: qqv
real(r8), intent(in) :: qqc
real(r8), intent(in) :: qqi
real(r8), intent(in) :: tt
real(r8), intent(in) :: pp
real(r8), intent(in) :: xland_pt
real(r8), intent(in) :: snowh_pt
real(r8), intent(inout) :: cldl,cldi
REAL(r8):: rhl,dV,esl,omeps,cldrh,qvl
real(r8):: cldcr,esi,qvi,rhi,rhdif,icimr,qv,qc,qi
qv=max(qqv,0._r8)
qc=max(qqc,0._r8)
qi=max(qqi,0._r8)
cldi= 0._r8
cldl= 0._r8
cldrh=1._r8
if (pp >= 70000._r8) then
if (xland_pt < 1.1_r8 .and. snowh_pt < 0.001_r8) then !xland_pt=1: land, snowh_pt<1e-6m=1e-3kgm-2
cldcr = 0.7875_r8
else
cldcr = 0.8875_r8
endif
elseif (pp <= 40000._r8) then
cldcr = 0.8_r8
else
cldcr = (0.8875_r8 - 0.8_r8)/30000._r8*(pp-40000._r8)+0.8_r8
end if
cldcr=min(max(0._r8,cldcr),1._r8)
dV=cldrh-cldcr
omeps = 1._r8 - 0.622_r8
rhdif = 0._r8
icimr = 0._r8
esl = polysvp
(tt,0)
qvl = max(1.e-12_r8,epsqs*esl/(pp-(1._r8-epsqs)*esl))
rhl = (qv+qc)/qvl
rhl = min(1.1_r8,max(0._r8,rhl))
if( rhl .ge. 1._r8 ) then
cldl = 1._r8
elseif( rhl .gt. (cldrh-dV/6._r8) .and. rhl .lt. 1._r8 ) then
cldl = 1._r8 - (-3._r8/sqrt(2._r8)*(rhl-cldrh)/dV)**(2._r8/3._r8)
elseif( rhl .gt. (cldrh-dV) .and. rhl .le. (cldrh-dV/6._r8) ) then
cldl = 4._r8*(cos((1._r8/3._r8)*(acos((3._r8/2._r8/sqrt(2._r8))* &
(1._r8+(rhl-cldrh)/dV))-2._r8*3.14159_r8)))**2._r8
elseif( rhl .le. (cldrh-dV) ) then
cldl = 0._r8
endif
esi = polysvp
(tt,1)
if (tt.gt.tmelt) esi=esl
qvi = max(1.e-12_r8,epsqs*esi/(pp-(1._r8-epsqs)*esi))
rhi = (qv+qi)/qvi
rhi = min(1.1_r8,max(0._r8,rhi))
if (tt < 273.15_r8) then
rhdif = (rhi-0.8_r8) / 0.3_r8 ! rhmaxi=1.1 - rhmini=0.8
cldi = min(1._r8, max(rhdif,0._r8)**2._r8)
if (qi.lt.1.e-12_r8) then
cldi=0._r8
else
cldi=max(1.e-4_r8,cldi)
endif
if (qi.ge.1.e-12_r8) then
icimr=qi/(max(cldi,1.e-20_r8))
if (icimr.lt.1.e-7_r8) then
cldi = max(0._r8,min(1._r8,qi/1.e-7_r8))
endif
if (icimr.gt.5.e-3_r8) then
cldi = max(0._r8,min(1._r8,qi/5.e-3_r8))
endif
endif
endif
cldl=min(max(0._r8,cldl),1._r8)
cldi=min(max(0._r8,cldi),1._r8)
end subroutine cal_cldfra_mp_1d
!---------------------------------------------------------------------------------------------
subroutine Macrophysics_simple(is_first_step, pcnst, pcols, kte, ixcldliq, ixnumliq, & 1,20
lchnk, dtime, state1_t, state_pmid, state_q, dp_icwmr, sh_icwmr, dp_frac, &
sh_frac, ast,aist,alst,qi_mac,xland_pt,snowh_pt, &
!intent-inout
state1_s, state1_q, rh_old, cldo, esl, qvs, ptend_loc_name, ptend_loc_ls, &
ptend_loc_lq, ptend_loc_s,ptend_loc_q, ptend_all_name, ptend_all_ls, &
ptend_all_lq,ptend_all_s,ptend_all_q )
! This subroutine implements macrophysical processes
!
! Author: Po-Lun Ma
! Ported by Balwinder Singh
!-------------------------------------------------------------------------------------------
!PMA
!-------------------------------------------------------------------------------------------
!This simple scheme does the followings:
!(1) QC detrained from convections are converted to (a) cloud water and (b) cloud ice in the
! cloudy part; and (c) vapor in the cloud-free part then latent heating from the phase
! change
!(2) RH change, then apportion the change of Qv to cloudy part and cloud-free part, then
! latent heating from phase change
!!(3) If a grid is super-saturated, condense to Qc and update latent heating
!(4) Brutal positive moisture fixer
!
!The idea is to take the essential formulations from Macrophysics in CAM5, but simplify the
!computation. When the full CAM5 macrophysics is implemented, this scheme should be removed
!Cloud fraction calculation is in this module
!-------------------------------------------------------------------------------------------
use wv_saturation
, only: epsqs, polysvp
use physconst
, only: latvap,cpair
!Subroutine arguments
!Intent -ins
logical, intent(in) :: is_first_step
integer, intent(in) :: pcnst, pcols, kte, ixcldliq, ixnumliq, lchnk
real(r8), intent(in) :: dtime,xland_pt,snowh_pt
real(r8), dimension(pcols,kte), intent(in) :: state_pmid
real(r8), dimension(pcols,kte), intent(in) :: dp_icwmr
real(r8), dimension(pcols,kte), intent(in) :: sh_icwmr
real(r8), dimension(pcols,kte), intent(in) :: dp_frac
real(r8), dimension(pcols,kte), intent(in) :: sh_frac
real(r8), dimension(pcols,kte), intent(in) :: qi_mac
real(r8), dimension(pcols,kte,pcnst), intent(in) :: state_q
!Intents-inouts
character*24, intent(inout) :: ptend_loc_name, ptend_all_name
logical, intent(inout) :: ptend_loc_ls, ptend_all_ls !Flag for updating tendencies
logical, dimension(pcnst),intent(inout) :: ptend_loc_lq !Flag for updating tendencies
logical, dimension(pcnst),intent(inout) :: ptend_all_lq !Flag for updating tendencies
real(r8), dimension(pcols,kte),intent(inout) :: ptend_loc_s
real(r8), dimension(pcols,kte),intent(inout) :: ptend_all_s
real(r8), dimension(pcols,kte),intent(inout) :: rh_old ! RH at previous timestep (PMA)
real(r8), dimension(pcols,kte),intent(inout) :: ast
real(r8), dimension(pcols,kte),intent(inout) :: alst
real(r8), dimension(pcols,kte),intent(inout) :: aist
real(r8), dimension(pcols,kte),intent(inout) :: cldo ! Old cloud fraction
real(r8), dimension(pcols,kte),intent(inout) :: esl ! liquid sat vapor pressure (pa) ! for phil suggested modifications
real(r8), dimension(pcols,kte),intent(inout) :: qvs ! liquid saturation vapor mixing ratio ! for phil suggested modifications
real(r8), dimension(pcols,kte),intent(inout) :: state1_s
real(r8), dimension(pcols,kte),intent(inout) :: state1_t
real(r8), dimension(pcols,kte,pcnst), intent(inout) :: ptend_loc_q
real(r8), dimension(pcols,kte,pcnst), intent(inout) :: ptend_all_q
real(r8), dimension(pcols,kte,pcnst), intent(inout) :: state1_q
!Local workspace
integer :: k
real(r8), dimension(pcols,kte) :: cv_frac ! Total convective cloud fraction (PMA)
real(r8), dimension(pcols,kte) :: st_frac ! Total stratiform cloud fraction (PMA)
real(r8), dimension(pcols,kte) :: ttt ! Temperature (PMA)
real(r8), dimension(pcols,kte) :: rh_curr ! RH at current timestep (PMA)
real(r8), dimension(pcols,kte) :: del_rh ! RH difference between 2 timesteps (PMA)
real(r8), dimension(pcols,kte) :: qc_nc ! non-convective LWC (PMA)
real(r8), dimension(pcols,kte) :: del_qq ! Qv difference between 2 timesteps (PMA)
real(r8), dimension(pcols,kte) :: del_cf ! Qv difference between 2 timesteps (PMA)
real(r8), dimension(pcols,kte) :: rh_temp !
real(r8), dimension(pcols) :: qsll !
real(r8), dimension(pcols) :: tsp !
real(r8) :: cldcr
real(r8) :: factcc,fact_adj
character*250 :: wrfmessage
!
!restore flags to true
!
ptend_loc_name = 'Macro1'
ptend_loc_ls = .true.
ptend_loc_lq(1) = .true.
ptend_loc_lq(ixcldliq) = .true.
ptend_loc_lq(ixnumliq) = .true.
factcc = 0.1_r8
fact_adj = 0.35_r8
cldcr = 0.8875_r8
!
!Simple computation for condensation/evaporation
!
do k=1,pver
if (state_pmid(1,k) >= 70000._r8) then
if (xland_pt < 1.1_r8 .and. snowh_pt < 0.001_r8) then !xland_pt=1: land, snowh_pt<1e-6m=1e-3kgm-2
cldcr = 0.7875_r8
else
cldcr = 0.8875_r8
endif
elseif (state_pmid(1,k)<= 40000._r8) then
cldcr = 0.8_r8
else
cldcr = (0.8875_r8 - 0.8_r8)/30000._r8*(state_pmid(1,k)-40000._r8)+0.8_r8
end if
cldcr=min(max(0._r8,cldcr),1._r8)
call cal_cldfra_mp_1d
(alst(1,k),aist(1,k),state1_q(1,k,1), state1_q(1,k,ixcldliq), qi_mac(1,k),state1_t(1,k),state_pmid(1,k),xland_pt,snowh_pt)
qsll = 0._r8
tsp = 0._r8
del_qq(1,k) = 0._r8
rh_temp(1,k) = 0._r8
cv_frac(1,k) = max(0._r8,min(0.8_r8,dp_frac(1,k)+sh_frac(1,k)))
alst(1,k) = (1._r8-cv_frac(1,k))*alst(1,k)
aist(1,k) = (1._r8-cv_frac(1,k))*aist(1,k)
ast(1,k) = max(alst(1,k),aist(1,k))
st_frac(1,k) = min(1._r8,ast(1,k)+cv_frac(1,k))
esl(1,k) = polysvp
(state1_t(1,k),0)
qvs(1,k) = max(1.e-30_r8,epsqs*esl(1,k)/(state_pmid(1,k)-(1._r8-epsqs)*esl(1,k)))
rh_curr(1,k) = max(0._r8,state1_q(1,k,1) / qvs(1,k))
qc_nc(1,k) = state1_q(1,k,ixcldliq)
if( is_first_step ) then
rh_old(1,k) = rh_curr(1,k)
cldo(1,k) = min(1._r8,ast(1,k)+cv_frac(1,k))
endif
!
!if super-saturate, condense delta RH
!
if (rh_curr(1,k) > 1._r8) then
call findsp_water
(lchnk,pcols,state1_q(1,k,1),state1_t(1,k),state_pmid(1,k),tsp,qsll)
del_qq(1,k) = min(3.e-3_r8,max(0._r8,(state1_q(1,k,1)-qsll(1))*0.999_r8))
ptend_loc_q(1,k,ixcldliq) = del_qq(1,k) /dtime
ptend_loc_s(1,k) = del_qq(1,k) * latvap/dtime !condensational heating
ptend_loc_q(1,k,1) = -del_qq(1,k)/dtime
!
!if not super-saturate, compare RH diff between two timesteps,
!then condense/evaporate the cloudy part
!
else if (rh_curr(1,k) > cldcr .and. rh_curr(1,k) <= 1._r8 ) then
del_cf(1,k) = st_frac(1,k)-cldo(1,k)
if( del_cf(1,k) < 0._r8 ) then
del_qq(1,k) = qc_nc(1,k)*del_cf(1,k)/cldo(1,k)*factcc
ptend_loc_q(1,k,ixcldliq) = del_qq(1,k) /dtime
ptend_loc_s(1,k) = del_qq(1,k) * latvap/dtime !evaporative cooling
ptend_loc_q(1,k,1) = -del_qq(1,k) /dtime
ptend_loc_q(1,k,ixnumliq) = ptend_loc_q(1,k,ixcldliq)*state1_q(1,k,ixnumliq)/max(1.e-30_r8,state1_q(1,k,ixcldliq))
ptend_loc_q(1,k,ixnumliq) = min(0._r8,max(ptend_loc_q(1,k,ixnumliq),-state1_q(1,k,ixnumliq)/dtime))
else if( del_cf(1,k) > 0._r8 .and. cldo(1,k) > 1.e-8_r8) then
del_qq(1,k) = min(state1_q(1,k,1)*0.1_r8,min(3.e-3_r8*st_frac(1,k),qc_nc(1,k)*del_cf(1,k)/cldo(1,k)))*factcc
ptend_loc_q(1,k,ixcldliq) = del_qq(1,k) /dtime
ptend_loc_s(1,k) = del_qq(1,k) * latvap/dtime !condensational heating
ptend_loc_q(1,k,1) = -del_qq(1,k) /dtime
ptend_loc_q(1,k,ixnumliq) = 0._r8
else if( del_cf(1,k) > 0._r8 .and. cldo(1,k) < 1.e-8_r8) then
del_qq(1,k) = min(state1_q(1,k,1)*0.1_r8,2.e-5_r8*st_frac(1,k))*factcc
ptend_loc_q(1,k,ixcldliq) = del_qq(1,k) /dtime
ptend_loc_s(1,k) = del_qq(1,k) * latvap/dtime !condensational heating
ptend_loc_q(1,k,1) = -del_qq(1,k) /dtime
ptend_loc_q(1,k,ixnumliq) = 0._r8
else
del_qq(1,k) = 0._r8
ptend_loc_q(1,k,ixcldliq) = 0._r8
ptend_loc_s(1,k) = 0._r8
ptend_loc_q(1,k,1) = 0._r8
ptend_loc_q(1,k,ixnumliq) = 0._r8
end if
else if (rh_curr(1,k) < cldcr .and. cldo(1,k) <1.e-2_r8 .and. qc_nc(1,k) >1.e-12_r8) then !RH<cldcr, evaporate qc
call findsp_water
(lchnk,pcols,state1_q(1,k,1),state1_t(1,k),state_pmid(1,k),tsp,qsll)
del_qq(1,k)= max(min(qc_nc(1,k), (qsll(1)-state1_q(1,k,1))),0._r8)*0.99_r8
ptend_loc_q(1,k,ixcldliq) = -del_qq(1,k) /dtime
ptend_loc_s(1,k) = -del_qq(1,k) * latvap/dtime !evaporative cooling
ptend_loc_q(1,k,1) = del_qq(1,k)/dtime
ptend_loc_q(1,k,ixnumliq) = ptend_loc_q(1,k,ixcldliq)*state1_q(1,k,ixnumliq)/max(1.e-30_r8,state1_q(1,k,ixcldliq))
ptend_loc_q(1,k,ixnumliq) = min(0._r8,max(ptend_loc_q(1,k,ixnumliq),-state1_q(1,k,ixnumliq)/dtime))
else if (rh_curr(1,k) < cldcr .and. cldo(1,k) >=1.e-2_r8 .and. qc_nc(1,k) >1.e-12_r8) then !RH<cldcr, evaporate qc
call findsp_water
(lchnk,pcols,state1_q(1,k,1),state1_t(1,k),state_pmid(1,k),tsp,qsll)
del_qq(1,k)= max(min(qc_nc(1,k), qsll(1)-state1_q(1,k,1)),0._r8)*factcc
ptend_loc_q(1,k,ixcldliq) = -del_qq(1,k) /dtime
ptend_loc_s(1,k) = -del_qq(1,k) * latvap/dtime !evaporative cooling
ptend_loc_q(1,k,1) = del_qq(1,k)/dtime
ptend_loc_q(1,k,ixnumliq) = ptend_loc_q(1,k,ixcldliq)*state1_q(1,k,ixnumliq)/max(1.e-30_r8,state1_q(1,k,ixcldliq))
! ptend_loc_q(1,k,ixnumliq) = ptend_loc_q(1,k,ixcldliq)*state1_q(1,k,ixnumliq)/max(1.e-30_r8,qc_nc(1,k))
ptend_loc_q(1,k,ixnumliq) = min(0._r8,max(ptend_loc_q(1,k,ixnumliq),-state1_q(1,k,ixnumliq)/dtime))
else
ptend_loc_q(1,k,ixcldliq) = 0._r8
ptend_loc_s(1,k) = 0._r8
ptend_loc_q(1,k,1) = 0._r8
ptend_loc_q(1,k,ixnumliq) = 0._r8
end if
state1_t(1,k)=state1_t(1,k)+ptend_loc_s(1,k)*dtime/cpair
end do !k loop
!
!Update state1 variables and tendencies
!
call physics_ptend_sum
(ptend_loc_ls,ptend_loc_lq,ptend_loc_s,ptend_loc_q,ptend_all_ls,ptend_all_lq,ptend_all_s,ptend_all_q,pcnst)
ptend_all_name = 'cldwat'
call physics_update
( lchnk,dtime,state1_q,ptend_loc_q,state1_s,ptend_loc_s,ptend_loc_name,ptend_loc_lq,ptend_loc_ls,pcnst)
call physics_ptend_init
( ptend_loc_name,ptend_loc_q,ptend_loc_s, ptend_loc_lq,ptend_loc_ls,pcnst)
!
!restore flags to true
!
ptend_loc_name = 'Macro2'
ptend_loc_ls = .true.
ptend_loc_lq(1) = .true.
ptend_loc_lq(ixcldliq) = .true.
ptend_loc_lq(ixnumliq) = .true.
!
!Some limiters
!
do k = 1 , pver
del_qq(1,k)=0._r8
call cal_cldfra_mp_1d
(alst(1,k),aist(1,k),state1_q(1,k,1), state1_q(1,k,ixcldliq), qi_mac(1,k),state1_t(1,k),state_pmid(1,k),xland_pt,snowh_pt)
alst(1,k) = (1._r8-cv_frac(1,k))*alst(1,k)
aist(1,k) = (1._r8-cv_frac(1,k))*aist(1,k)
ast(1,k) = max(alst(1,k),aist(1,k))
st_frac(1,k) = alst(1,k)
qc_nc(1,k) = max(0._r8, state1_q(1,k,ixcldliq) - &
max(0._r8,(dp_frac(1,k)*dp_icwmr(1,k) +sh_frac(1,k)*sh_icwmr(1,k))))
!
!Case 1: unrealistic cloud: evaporate qc under no cldfra
!
! THIS SHOULD NO LONGER HAPPEN
!
! if (st_frac(1,k) < 1.e-8_r8 ) then
! if ( qc_nc(1,k) > 0._r8 ) then
! ptend_loc_q(1,k,ixcldliq) = -(qc_nc(1,k))/dtime*0.99_r8
! ptend_loc_q(1,k,1)= qc_nc(1,k)/dtime*0.99_r8
! ptend_loc_s(1,k) =-(qc_nc(1,k)) * latvap /dtime*0.99_r8 !evaporative cooling
! ptend_loc_q(1,k,ixnumliq) = -state1_q(1,k,ixnumliq)/dtime*0.99_r8
! ptend_loc_q(1,k,ixnumliq) = min(0._r8,-0.99_r8*state1_q(1,k,ixnumliq)/dtime)
! end if
if (st_frac(1,k) > 1.e-5_r8 ) then
! else !if stratiform cldfra not zero
!
!Case 2: dense cloud: evaporate some stratiform qc until qc_max
!
if (qc_nc(1,k) > 3.e-3_r8 * st_frac(1,k)) then
del_qq(1,k) = qc_nc(1,k)-3.e-3_r8* st_frac(1,k)*fact_adj
ptend_loc_q(1,k,ixcldliq) = -del_qq(1,k)/dtime
ptend_loc_q(1,k,1) = del_qq(1,k)/dtime
ptend_loc_s(1,k) = -del_qq(1,k) * latvap /dtime !evaporative cooling
ptend_loc_q(1,k,ixnumliq) = ptend_loc_q(1,k,ixcldliq)*state1_q(1,k,ixnumliq)/max(1.e-20_r8,state1_q(1,k,ixcldliq))
ptend_loc_q(1,k,ixnumliq) = min(0._r8,max(ptend_loc_q(1,k,ixnumliq),-state1_q(1,k,ixnumliq)/dtime))
!
!Case 3: empty cloud: condense stratiform qc until qc_min when cldfra is not zero
!
else if (qc_nc(1,k) < 2.e-5_r8 * st_frac(1,k)) then
del_qq(1,k) = 2.e-5_r8 *st_frac(1,k)-qc_nc(1,k)
del_qq(1,k) = max(0._r8,min(del_qq(1,k), state1_q(1,k,1)*0.1_r8))*fact_adj
ptend_loc_q(1,k,ixcldliq) = del_qq(1,k)/dtime
ptend_loc_q(1,k,1) = -del_qq(1,k)/dtime
ptend_loc_s(1,k) = del_qq(1,k)* latvap / dtime !condensational heating
end if
end if
state1_t(1,k)=state1_t(1,k)+ptend_loc_s(1,k)*dtime/cpair
end do
!
!Update state1 variables and tendencies
!
call physics_ptend_sum
(ptend_loc_ls,ptend_loc_lq,ptend_loc_s,ptend_loc_q,ptend_all_ls,ptend_all_lq,ptend_all_s,ptend_all_q,pcnst)
ptend_all_name = 'cldwat'
call physics_update
( lchnk,dtime,state1_q,ptend_loc_q,state1_s,ptend_loc_s,ptend_loc_name,ptend_loc_lq,ptend_loc_ls,pcnst)
call physics_ptend_init
( ptend_loc_name,ptend_loc_q,ptend_loc_s, ptend_loc_lq,ptend_loc_ls,pcnst)
go to 2000
!
!restore flags to true
!
ptend_loc_name = 'Macro3'
ptend_loc_ls = .true.
ptend_loc_lq(1) = .true.
ptend_loc_lq(ixcldliq) = .true.
!
!Last checker to remove supersaturation
!
do k=1,pver
qsll = 0._r8
tsp = 0._r8
del_qq(1,k) = 0._r8
esl(1,k) = polysvp
(state1_t(1,k),0)
qvs(1,k) = max(1.e-30_r8,epsqs*esl(1,k)/(state_pmid(1,k)-(1._r8-epsqs)*esl(1,k)))
rh_curr(1,k) = state1_q(1,k,1) / qvs(1,k)
if (rh_curr(1,k) > 1._r8) then
call findsp_water
(lchnk,pcols,state1_q(1,k,1),state1_t(1,k),state_pmid(1,k),tsp,qsll)
del_qq(1,k)=min(2.e-2_r8,max(0._r8,(state1_q(1,k,1)-qsll(1))*0.999_r8))
ptend_loc_q(1,k,ixcldliq) = del_qq(1,k) /dtime
ptend_loc_s(1,k) = del_qq(1,k) * latvap/dtime !condensational heating
ptend_loc_q(1,k,1) = -del_qq(1,k)/dtime
end if
state1_t(1,k)=state1_t(1,k)+ptend_loc_s(1,k)*dtime/cpair
end do
!Update state1 variables and tendencies
!
call physics_ptend_sum
(ptend_loc_ls,ptend_loc_lq,ptend_loc_s,ptend_loc_q,ptend_all_ls,ptend_all_lq,ptend_all_s,ptend_all_q,pcnst)
ptend_all_name = 'cldwat'
call physics_update
( lchnk,dtime,state1_q,ptend_loc_q,state1_s,ptend_loc_s,ptend_loc_name,ptend_loc_lq,ptend_loc_ls,pcnst)
call physics_ptend_init
( ptend_loc_name,ptend_loc_q,ptend_loc_s, ptend_loc_lq,ptend_loc_ls,pcnst)
!
!positive state1 variables
!
2000 continue
do k = 1 , pver
state1_q(1,k,1) = max(qmin(1),state1_q(1,k,1))
state1_q(1,k,ixcldliq) = max(qmin(ixcldliq),state1_q(1,k,ixcldliq))
state1_q(1,k,ixcldice) = max(qmin(ixcldice),state1_q(1,k,ixcldice))
state1_q(1,k,ixnumliq) = max(qmin(ixnumliq),state1_q(1,k,ixnumliq))
state1_q(1,k,ixnumice) = max(qmin(ixnumice),state1_q(1,k,ixnumice))
call cal_cldfra_mp_1d
(alst(1,k),aist(1,k),state1_q(1,k,1), state1_q(1,k,ixcldliq), qi_mac(1,k),state1_t(1,k),state_pmid(1,k),xland_pt,snowh_pt)
! ast(1,k)=max(alst(1,k),aist(1,k))
aist(1,k) = (1._r8-cv_frac(1,k))*aist(1,k)
alst(1,k) = (1._r8-cv_frac(1,k))*alst(1,k)
ast(1,k)=max(alst(1,k),aist(1,k))
end do
!
!PMA<<<
!
end subroutine Macrophysics_simple
subroutine CAMMGMP_INIT(ixcldliq_in,ixcldice_in & 1,8
,ixnumliq_in,ixnumice_in,chem_opt_in &
,ids, ide, jds, jde, kds, kde &
,ims, ime, jms, jme, kms, kme &
,its, ite, jts, jte, kts, kte )
!!-------------------------------------------- !
!! !
!! Initialize the cloud water parameterization !
!! !
!!-------------------------------------------- !
use microp_aero
, only: ini_microp_aero
use cldwat2m_micro
, only: ini_micro
#ifdef MODAL_AERO
use ndrop
, only: activate_init
#endif
!!-----------------------------------------------------------------------
implicit none
integer, intent(in) :: ixcldliq_in, ixcldice_in, ixnumliq_in, ixnumice_in
integer, intent(in) :: chem_opt_in
integer, intent(in) :: ids, ide, jds, jde, kds, kde &
,ims, ime, jms, jme, kms, kme &
,its, ite, jts, jte, kts, kte
!Local variables
character(len=1000) :: msg
integer :: jtf,ktf,itf
chem_opt = chem_opt_in
jtf = min(jte,jde-1)
ktf = min(kte,kde-1)
itf = min(ite,ide-1)
!Map CAM veritcal level variables
pver = ktf - kts + 1
pverp = pver + 1
!!-----------------------------------------------------------------------
ixcldliq = ixcldliq_in
ixcldice = ixcldice_in
ixnumliq = ixnumliq_in
ixnumice = ixnumice_in
!! Initialization routine for cloud macrophysics and microphysics
call ini_micro
call ini_microp_aero
#ifdef MODAL_AERO
#ifndef WRF_CHEM
!When WRF_CHEM is 1, activate_init is called from MODULE_CAM_MAM_INIT after initializing aerosols
call activate_init
#else
!BSINGH:02/01/2013: Sanity check for Non-MAM simulations
if(.NOT.cam_mam_aerosols .AND. chem_opt .NE. 0) then
write(msg,*)'CAMMGMP DRIVER - cammgmp is valid for only MAM aerosols ', &
'(chem_opts:',CBMZ_CAM_MAM3_NOAQ,CBMZ_CAM_MAM3_AQ,CBMZ_CAM_MAM7_NOAQ,CBMZ_CAM_MAM7_AQ ,')'
call wrf_error_fatal
( msg )
endif
if(chem_opt == 0)then
!NOTE*: Not tested yet for other CHEM packages except MAM packages
call activate_init
endif
#endif
#endif
return
end subroutine CAMMGMP_INIT
subroutine findsp_water (lchnk, ncol, q, t, p, tsp, qsp) 4,7
!-----------------------------------------------------------------------
!
! Purpose:
! find the wet bulb temperature for a given t and q
! in a longitude height section
! wet bulb temp is the temperature and spec humidity that is
! just saturated and has the same enthalpy
! if q > qs(t) then tsp > t and qsp = qs(tsp) < q
! if q < qs(t) then tsp < t and qsp = qs(tsp) > q
!
! Method:
! a Newton method is used
! first guess uses an algorithm provided by John Petch from the UKMO
! we exclude points where the physical situation is unrealistic
! e.g. where the temperature is outside the range of validity for the
! saturation vapor pressure, or where the water vapor pressure
! exceeds the ambient pressure, or the saturation specific humidity is
! unrealistic
!
! Author: P. Rasch
!
!-----------------------------------------------------------------------
use wv_saturation
, only: estblf, hlatv, tmin, hlatf, rgasv, pcf, &
cp, epsqs, ttrice,polysvp
!
! input arguments
!
integer, intent(in) :: lchnk ! chunk identifier
integer, intent(in) :: ncol ! number of atmospheric columns
real(r8), intent(in) :: q(pcols) ! water vapor (kg/kg)
real(r8), intent(in) :: t(pcols) ! temperature (K)
real(r8), intent(in) :: p(pcols) ! pressure (Pa)
!
! output arguments
!
real(r8), intent(out) :: tsp(pcols) ! saturation temp (K)
real(r8), intent(out) :: qsp(pcols) ! saturation mixing ratio (kg/kg)
!
! local variables
!
character*250 :: iulog
integer i ! work variable
! integer k ! work variable
logical lflg ! work variable
integer iter ! work variable
integer l ! work variable
logical :: error_found
real(r8) omeps ! 1 minus epsilon
real(r8) trinv ! work variable
real(r8) es ! sat. vapor pressure
real(r8) desdt ! change in sat vap pressure wrt temperature
! real(r8) desdp ! change in sat vap pressure wrt pressure
real(r8) dqsdt ! change in sat spec. hum. wrt temperature
real(r8) dgdt ! work variable
real(r8) g ! work variable
real(r8) weight(pcols) ! work variable
real(r8) hlatsb ! (sublimation)
real(r8) hlatvp ! (vaporization)
real(r8) hltalt(pcols) ! lat. heat. of vap.
real(r8) tterm ! work var.
real(r8) qs ! spec. hum. of water vapor
real(r8) tc ! crit temp of transition to ice
real(r8) tt0 ! Freezing temperature. Needed for findsp
! work variables
real(r8) t1, q1, dt, dq
real(r8) dtm, dqm
real(r8) qvd, a1, tmp
real(r8) rair
real(r8) r1b, c1, c2, c3
real(r8) denom
real(r8) dttol
real(r8) dqtol
integer doit(pcols)
real(r8) enin(pcols), enout(pcols)
real(r8) tlim(pcols)
omeps = 1.0_r8 - epsqs
! trinv = 1.0_r8/ttrice ! put just before it is used, in case ttrice = 0.0 !++xl
a1 = 7.5_r8*log(10._r8)
rair = 287.04_r8
c3 = rair*a1/cp
dtm = 0._r8 ! needed for iter=0 blowup with f90 -ei
dqm = 0._r8 ! needed for iter=0 blowup with f90 -ei
dttol = 1.e-4_r8 ! the relative temp error tolerance required to quit the iteration
dqtol = 1.e-4_r8 ! the relative moisture error tolerance required to quit the iteration
! tmin = 173.16 ! the coldest temperature we can deal with
tt0 = 273.15_r8
!
! max number of times to iterate the calculation
iter = 8
!
! Sungsu comment out k loop
! do k = 1,pver
!
! first guess on the wet bulb temperature
!
do i = 1,ncol
!#ifdef DEBUG
! if ( (lchnk == lchnklook(nlook) ) .and. (i == icollook(nlook) ) ) then
! write (iulog,*) ' '
! write (iulog,*) ' level, t, q, p', t(i), q(i), p(i)
! endif
!#endif
! limit the temperature range to that relevant to the sat vap pres tables
!#if ( ! defined WACCM_MOZART )
! tlim(i) = min(max(t(i),173._r8),373._r8)
!#else
tlim(i) = min(max(t(i),128._r8),373._r8)
!#endif
! es = estblf(tlim(i))
es = polysvp
(tlim(i),0) !++xl
denom = p(i) - omeps*es
qs = epsqs*es/denom
doit(i) = 0
enout(i) = 1._r8
! make sure a meaningful calculation is possible
if (p(i) > 5._r8*es .and. qs > 0._r8 .and. qs < 0.5_r8) then
!
! Saturation specific humidity
!
qs = min(epsqs*es/denom,1._r8)
!
! "generalized" analytic expression for t derivative of es
! accurate to within 1 percent for 173.16 < t < 373.16
!++xl
! Weighting of hlat accounts for transition from water to ice
! polynomial expression approximates difference between es over
! water and es over ice from 0 to -ttrice (C) (min of ttrice is
! -40): required for accurate estimate of es derivative in transition
! range from ice to water also accounting for change of hlatv with t
! above freezing where const slope is given by -2369 j/(kg c) = cpv - cw
!
! tc = tlim(i) - tt0
! lflg = (tc >= -ttrice .and. tc < 0.0_r8)
! weight(i) = min(-tc*trinv,1.0_r8)
! hlatsb = hlatv + weight(i)*hlatf
! hlatvp = hlatv - 2369.0_r8*tc
! if (tlim(i) < tt0) then
! hltalt(i) = hlatsb
! else
! hltalt(i) = hlatvp
! end if
!
! No icephs or water to ice transition
!
hlatvp = hlatv - 2369.0*(tlim(i)-tt0)
hlatsb = hlatv
if (tlim(i) < tt0) then
hltalt(i) = hlatsb
else
hltalt(i) = hlatvp
end if
!--xl
enin(i) = cp*tlim(i) + hltalt(i)*q(i)
! make a guess at the wet bulb temp using a UKMO algorithm (from J. Petch)
tmp = q(i) - qs
c1 = hltalt(i)*c3
c2 = (tlim(i) + 36._r8)**2
r1b = c2/(c2 + c1*qs)
qvd = r1b*tmp
tsp(i) = tlim(i) + ((hltalt(i)/cp)*qvd)
!#ifdef DEBUG
! if ( (lchnk == lchnklook(nlook) ) .and. (i == icollook(nlook) ) ) then
! write (iulog,*) ' relative humidity ', q(i)/qs
! write (iulog,*) ' first guess ', tsp(i)
! endif
!#endif
! es = estblf(tsp(i))
es = polysvp
(tsp(i),0) !++xl
qsp(i) = min(epsqs*es/(p(i) - omeps*es),1._r8)
else
doit(i) = 1
tsp(i) = tlim(i)
qsp(i) = q(i)
enin(i) = 1._r8
endif
end do ! end do i
!
! now iterate on first guess
!
do l = 1, iter
dtm = 0
dqm = 0
do i = 1,ncol
if (doit(i) == 0) then
! es = estblf(tsp(i))
es = polysvp
(tsp(i),0) !++xl
!
! Saturation specific humidity
!
qs = min(epsqs*es/(p(i) - omeps*es),1._r8)
!
! "generalized" analytic expression for t derivative of es
! accurate to within 1 percent for 173.16 < t < 373.16
!
!++xl
! Weighting of hlat accounts for transition from water to ice
! polynomial expression approximates difference between es over
! water and es over ice from 0 to -ttrice (C) (min of ttrice is
! -40): required for accurate estimate of es derivative in transition
! range from ice to water also accounting for change of hlatv with t
! above freezing where const slope is given by -2369 j/(kg c) = cpv - cw
!
! tc = tsp(i) - tt0
! lflg = (tc >= -ttrice .and. tc < 0.0_r8)
! weight(i) = min(-tc*trinv,1.0_r8)
! hlatsb = hlatv + weight(i)*hlatf
! hlatvp = hlatv - 2369.0_r8*tc
! if (tsp(i) < tt0) then
! hltalt(i) = hlatsb
! else
! hltalt(i) = hlatvp
! end if
! if (lflg) then
! tterm = pcf(1) + tc*(pcf(2) + tc*(pcf(3)+tc*(pcf(4) + tc*pcf(5))))
! else
! tterm = 0.0_r8
! end if
! desdt = hltalt(i)*es/(rgasv*tsp(i)*tsp(i)) + tterm*trinv
!
! No icephs or water to ice transition
!
hlatvp = hlatv - 2369.0*(tsp(i)-tt0)
hlatsb = hlatv
if (tsp(i) < tt0) then
hltalt(i) = hlatsb
else
hltalt(i) = hlatvp
end if
desdt = hltalt(i)*es/(rgasv*tsp(i)*tsp(i))
!--xl
dqsdt = (epsqs + omeps*qs)/(p(i) - omeps*es)*desdt
! g = cp*(tlim(i)-tsp(i)) + hltalt(i)*q(i)- hltalt(i)*qsp(i)
g = enin(i) - (cp*tsp(i) + hltalt(i)*qsp(i))
dgdt = -(cp + hltalt(i)*dqsdt)
t1 = tsp(i) - g/dgdt
dt = abs(t1 - tsp(i))/t1
tsp(i) = max(t1,tmin)
! es = estblf(tsp(i))
es = polysvp
(tsp(i),0) !++xl
q1 = min(epsqs*es/(p(i) - omeps*es),1._r8)
dq = abs(q1 - qsp(i))/max(q1,1.e-12_r8)
qsp(i) = q1
!#ifdef DEBUG
! if ( (lchnk == lchnklook(nlook) ) .and. (i == icollook(nlook) ) ) then
! write (iulog,*) ' rel chg lev, iter, t, q ', l, dt, dq, g
! endif
!#endif
dtm = max(dtm,dt)
dqm = max(dqm,dq)
! if converged at this point, exclude it from more iterations
if (dt < dttol .and. dq < dqtol) then
doit(i) = 2
endif
enout(i) = cp*tsp(i) + hltalt(i)*qsp(i)
! bail out if we are too near the end of temp range
!#if ( ! defined WACCM_MOZART )
if (tsp(i) < 174.16_r8) then
!#else
! if (tsp(i) < 130.16_r8) then
!#endif
doit(i) = 4
endif
else
endif
end do ! do i = 1,ncol
if (dtm < dttol .and. dqm < dqtol) then
go to 10
endif
end do ! do l = 1,iter
10 continue
error_found = .false.
if (dtm > dttol .or. dqm > dqtol) then
do i = 1,ncol
if (doit(i) == 0) error_found = .true.
end do
if (error_found) then
do i = 1,ncol
if (doit(i) == 0) then
write (iulog,*) ' findsp not converging at point i ', i
write (iulog,*) ' t, q, p, enin ', t(i), q(i), p(i), enin(i)
write (iulog,*) ' tsp, qsp, enout ', tsp(i), qsp(i), enout(i)
call wrf_error_fatal
('FINDSP')
endif
end do
endif
endif
do i = 1,ncol
if (doit(i) == 2 .and. abs((enin(i)-enout(i))/(enin(i)+enout(i))) > 1.e-4_r8) then
error_found = .true.
endif
end do
if (error_found) then
do i = 1,ncol
if (doit(i) == 2 .and. abs((enin(i)-enout(i))/(enin(i)+enout(i))) > 1.e-4_r8) then
write (iulog,*) ' the enthalpy is not conserved for point ', &
i, enin(i), enout(i)
write (iulog,*) ' t, q, p, enin ', t(i), q(i), p(i), enin(i)
write (iulog,*) ' tsp, qsp, enout ', tsp(i), qsp(i), enout(i)
call wrf_error_fatal
('FINDSP')
endif
end do
endif
! end do ! level loop (k=1,pver)
return
end subroutine findsp_water
end module module_mp_cammgmp_driver