LCOV - code coverage report
Current view: top level - physics/pumas-frozen - micro_pumas_utils.F90 (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 815 0.0 %
Date: 2025-01-13 21:54:50 Functions: 0 56 0.0 %

          Line data    Source code
       1             : module micro_pumas_utils
       2             : 
       3             : !--------------------------------------------------------------------------
       4             : !
       5             : ! This module contains process rates and utility functions used by the MG
       6             : ! microphysics.
       7             : !
       8             : ! Original MG authors: Andrew Gettelman, Hugh Morrison
       9             : ! Contributions from: Peter Caldwell, Xiaohong Liu and Steve Ghan
      10             : !
      11             : ! Separated from MG 1.5 by B. Eaton.
      12             : ! Separated module switched to MG 2.0 and further changes by S. Santos.
      13             : !
      14             : ! for questions contact Hugh Morrison, Andrew Gettelman
      15             : ! e-mail: morrison@ucar.edu, andrew@ucar.edu
      16             : !
      17             : !--------------------------------------------------------------------------
      18             : !
      19             : ! List of required external functions that must be supplied:
      20             : !   gamma --> standard mathematical gamma function (if gamma is an
      21             : !       intrinsic, define HAVE_GAMMA_INTRINSICS)
      22             : !
      23             : !--------------------------------------------------------------------------
      24             : !
      25             : ! Constants that must be specified in the "init" method (module variables):
      26             : !
      27             : ! kind            kind of reals (to verify correct linkage only) -
      28             : ! gravit          acceleration due to gravity                    m s-2
      29             : ! rair            dry air gas constant for air                   J kg-1 K-1
      30             : ! rh2o            gas constant for water vapor                   J kg-1 K-1
      31             : ! cpair           specific heat at constant pressure for dry air J kg-1 K-1
      32             : ! tmelt           temperature of melting point for water         K
      33             : ! latvap          latent heat of vaporization                    J kg-1
      34             : ! latice          latent heat of fusion                          J kg-1
      35             : !
      36             : !--------------------------------------------------------------------------
      37             : 
      38             : #ifndef HAVE_GAMMA_INTRINSICS
      39             : use shr_spfn_mod, only: gamma => shr_spfn_gamma
      40             : #endif
      41             : 
      42             : implicit none
      43             : private
      44             : save
      45             : 
      46             : public :: &
      47             :      micro_pumas_utils_init, &
      48             :      size_dist_param_liq, &
      49             :      size_dist_param_basic, &
      50             :      avg_diameter, &
      51             :      rising_factorial, &
      52             :      ice_deposition_sublimation, &
      53             :      ice_deposition_sublimation_mg4, &  !! ktc 
      54             :      sb2001v2_liq_autoconversion,&
      55             :      sb2001v2_accre_cld_water_rain,&       
      56             :      kk2000_liq_autoconversion, &
      57             :      ice_autoconversion, &
      58             :      immersion_freezing, &
      59             :      contact_freezing, &
      60             :      snow_self_aggregation, &
      61             :      ice_self_aggregation, &  !! mg4 added for using instead of snow_self_agg
      62             :      accrete_cloud_water_snow, &
      63             :      accrete_cloud_water_ice, &  !! mg4 added for using instead of cloud_water_snow
      64             :      secondary_ice_production, &
      65             :      accrete_rain_snow, &
      66             :      accrete_rain_ice, &  !! mg4 added for using instead of rain_snow
      67             :      heterogeneous_rain_freezing, &
      68             :      accrete_cloud_water_rain, &
      69             :      self_collection_rain, &
      70             :      accrete_cloud_ice_snow, &
      71             :      evaporate_sublimate_precip, &
      72             :      bergeron_process_snow, &
      73             :      graupel_collecting_snow, &
      74             :      graupel_collecting_rain, &
      75             :      graupel_collecting_cld_water, &
      76             :      graupel_riming_liquid_snow, &
      77             :      graupel_rain_riming_snow, &
      78             :      graupel_rime_splintering, &
      79             :      evaporate_sublimate_precip_graupel, &
      80             :      evaporate_sublimate_precip_mg4, &
      81             :      evaporate_sublimate_precip_graupel_mg4, &
      82             :      access_lookup_table, & !! mg4
      83             :      access_lookup_table_coll, & !! mg4
      84             :      init_lookup_table, &      !! mg4
      85             :      avg_diameter_vec
      86             : 
      87             : ! 8 byte real and integer
      88             : integer, parameter, public :: r8 = selected_real_kind(12)
      89             : integer, parameter, public :: i8 = selected_int_kind(18)
      90             : integer, parameter         :: VLENS = 128  ! vector length of a GPU compute kernel
      91             : 
      92             : public :: MGHydrometeorProps
      93             : 
      94             : type :: MGHydrometeorProps
      95             :    ! Density (kg/m^3)
      96             :    real(r8) :: rho
      97             :    ! Information for size calculations.
      98             :    ! Basic calculation of mean size is:
      99             :    !     lambda = (shape_coef*nic/qic)^(1/eff_dim)
     100             :    ! Then lambda is constrained by bounds.
     101             :    real(r8) :: eff_dim
     102             :    real(r8) :: shape_coef
     103             :    real(r8) :: lambda_bounds(2)
     104             :    ! Minimum average particle mass (kg).
     105             :    ! Limit is applied at the beginning of the size distribution calculations.
     106             :    real(r8) :: min_mean_mass
     107             : end type MGHydrometeorProps
     108             : 
     109             : interface MGHydrometeorProps
     110             :    module procedure NewMGHydrometeorProps
     111             : end interface
     112             : 
     113             : type(MGHydrometeorProps), public :: mg_liq_props
     114             : type(MGHydrometeorProps), public :: mg_ice_props
     115             : type(MGHydrometeorProps), public :: mg_rain_props
     116             : type(MGHydrometeorProps), public :: mg_snow_props
     117             : type(MGHydrometeorProps), public :: mg_graupel_props
     118             : type(MGHydrometeorProps), public :: mg_hail_props
     119             : 
     120             : interface size_dist_param_liq
     121             :   module procedure size_dist_param_liq_2D
     122             :   module procedure size_dist_param_liq_vect
     123             :   module procedure size_dist_param_liq_line
     124             : end interface
     125             : interface size_dist_param_basic
     126             :   module procedure size_dist_param_basic_2D
     127             :   module procedure size_dist_param_basic_vect
     128             :   module procedure size_dist_param_basic_line
     129             : end interface
     130             : interface calc_ab
     131             :   module procedure calc_ab_line
     132             :   module procedure calc_ab_vect
     133             : end interface
     134             : 
     135             : !=================================================
     136             : ! Public module parameters (mostly for MG itself)
     137             : !=================================================
     138             : 
     139             : ! Pi to 20 digits; more than enough to reach the limit of double precision.
     140             : real(r8), parameter, public :: pi = 3.14159265358979323846_r8
     141             : 
     142             : ! "One minus small number": number near unity for round-off issues.
     143             : real(r8), parameter, public :: omsm   = 1._r8 - 1.e-5_r8
     144             : 
     145             : ! Smallest mixing ratio considered in microphysics.
     146             : real(r8), parameter, public :: qsmall = 1.e-18_r8
     147             : 
     148             : ! minimum allowed cloud fraction
     149             : real(r8), parameter, public :: mincld = 0.0001_r8
     150             : 
     151             : real(r8), parameter, public :: rhosn = 250._r8  ! bulk density snow
     152             : real(r8), parameter, public :: rhoi = 500._r8   ! bulk density ice
     153             : real(r8), parameter, public :: rhow = 1000._r8  ! bulk density liquid
     154             : real(r8), parameter, public :: rhows = 917._r8  ! bulk density water solid
     155             : 
     156             : !Hail and Graupel (set in MG3)
     157             : real(r8), parameter, public :: rhog = 500._r8 
     158             : real(r8), parameter, public :: rhoh = 900._r8 
     159             : 
     160             : ! fall speed parameters, V = aD^b (V is in m/s)
     161             : ! droplets
     162             : real(r8), parameter, public :: ac = 3.e7_r8
     163             : real(r8), parameter, public :: bc = 2._r8
     164             : ! snow
     165             : real(r8), parameter, public :: as = 11.72_r8
     166             : real(r8), parameter, public :: bs = 0.41_r8
     167             : ! cloud ice
     168             : real(r8), parameter, public :: ai = 700._r8
     169             : real(r8), parameter, public :: bi = 1._r8
     170             : ! small cloud ice (r< 10 um) - sphere, bulk density
     171             : real(r8), parameter, public :: aj = ac*((rhoi/rhows)**(bc/3._r8))*rhows/rhow
     172             : real(r8), parameter, public :: bj = bc
     173             : ! rain
     174             : real(r8), parameter, public :: ar = 841.99667_r8
     175             : real(r8), parameter, public :: br = 0.8_r8
     176             : ! graupel
     177             : real(r8), parameter, public :: ag = 19.3_r8
     178             : real(r8), parameter, public :: bg = 0.37_r8
     179             : ! hail
     180             : real(r8), parameter, public :: ah = 114.5_r8 
     181             : real(r8), parameter, public :: bh = 0.5_r8
     182             : 
     183             : ! mass of new crystal due to aerosol freezing and growth (kg)
     184             : ! Make this consistent with the lower bound, to support UTLS and
     185             : ! stratospheric ice, and the smaller ice size limit.
     186             : real(r8), parameter, public :: mi0 = 4._r8/3._r8*pi*rhoi*(1.e-6_r8)**3
     187             : 
     188             : ! mass of new graupel particle  (assume same as mi0 for now, may want to make bigger?)
     189             : !real(r8), parameter, public :: mg0 = 4._r8/3._r8*pi*rhoi*(1.e-6_r8)**3
     190             : !or set based on M2005:
     191             : real(r8), parameter, public :: mg0 = 1.6e-10_r8
     192             : ! radius of contact nuclei
     193             : real(r8), parameter, public :: mmult = 4._r8/3._r8*pi*rhoi*(5.e-6_r8)**3
     194             : 
     195             : !=================================================
     196             : ! Private module parameters
     197             : !=================================================
     198             : 
     199             : ! Signaling NaN bit pattern that represents a limiter that's turned off.
     200             : integer(i8), parameter :: limiter_off = int(Z'7FF1111111111111', i8)
     201             : 
     202             : ! alternate threshold used for some in-cloud mmr
     203             : real(r8), parameter, public :: icsmall = 1.e-8_r8
     204             : 
     205             : ! particle mass-diameter relationship
     206             : ! currently we assume spherical particles for cloud ice/snow
     207             : ! m = cD^d
     208             : ! exponent
     209             : real(r8), parameter :: dsph = 3._r8
     210             : 
     211             : ! Bounds for mean diameter for different constituents.
     212             : real(r8), parameter :: lam_bnd_rain(2) = 1._r8/[500.e-6_r8, 20.e-6_r8]
     213             : real(r8), parameter :: lam_bnd_snow(2) = 1._r8/[2000.e-6_r8, 10.e-6_r8]
     214             : 
     215             : ! Minimum average mass of particles.
     216             : real(r8), parameter :: min_mean_mass_liq = 1.e-20_r8
     217             : real(r8), parameter :: min_mean_mass_ice = 1.e-20_r8
     218             : 
     219             : ! ventilation parameters
     220             : ! for snow
     221             : real(r8), parameter :: f1s = 0.86_r8
     222             : real(r8), parameter :: f2s = 0.28_r8
     223             : ! for rain
     224             : real(r8), parameter :: f1r = 0.78_r8
     225             : real(r8), parameter :: f2r = 0.308_r8
     226             : 
     227             : ! collection efficiencies
     228             : ! aggregation of cloud ice and snow
     229             : real(r8), parameter :: eii = 0.5_r8
     230             : ! collection efficiency, ice-droplet collisions
     231             : real(r8), parameter, public :: ecid = 0.7_r8
     232             : ! collection efficiency between droplets/rain and snow/rain
     233             : real(r8), parameter, public :: ecr = 1.0_r8
     234             : 
     235             : ! immersion freezing parameters, bigg 1953
     236             : real(r8), parameter :: bimm = 100._r8
     237             : real(r8), parameter :: aimm = 0.66_r8
     238             : 
     239             : ! Mass of each raindrop created from autoconversion.
     240             : real(r8), parameter :: droplet_mass_25um = 4._r8/3._r8*pi*rhow*(25.e-6_r8)**3
     241             : real(r8), parameter :: droplet_mass_40um = 4._r8/3._r8*pi*rhow*(40.e-6_r8)**3
     242             : 
     243             : !!!!!!
     244             : ! MG4 look up table parameters
     245             : !!!!!!
     246             : ! ice microphysics lookup table array dimensions
     247             : integer, parameter, public :: tsize     = 3
     248             : integer, parameter, public :: isize     = 20
     249             : integer, parameter, public :: jsize     = 20
     250             : integer, parameter, public :: rcollsize = 30
     251             : 
     252             : ! number of ice microphysical quantities used from lookup table
     253             : integer, parameter, public :: tabsize   = 14
     254             : 
     255             : ! number of ice-rain collection microphysical quantities used from lookup table
     256             : integer, parameter, public :: colltabsize = 2
     257             : 
     258             : 
     259             : !ice lookup table values
     260             : real(r8) :: itab(tsize,isize,jsize,tabsize)
     261             : 
     262             : !ice lookup table values for ice-rain collision/collection
     263             : real(r8) :: itabcoll(tsize,isize,jsize,rcollsize,colltabsize)
     264             : 
     265             : private :: itab,itabcoll   
     266             : 
     267             : !=========================================================
     268             : ! Constants set in initialization
     269             : !=========================================================
     270             : 
     271             : ! Set using arguments to micro_pumas_init
     272             : real(r8) :: rv          ! water vapor gas constant
     273             : real(r8) :: cpp         ! specific heat of dry air
     274             : real(r8) :: tmelt       ! freezing point of water (K)
     275             : 
     276             : real(r8) :: ra        ! dry air gas constant
     277             : 
     278             : ! latent heats of:
     279             : real(r8) :: xxlv        ! vaporization
     280             : real(r8) :: xlf         ! freezing
     281             : real(r8) :: xxls        ! sublimation
     282             : 
     283             : ! additional constants to help speed up code
     284             : real(r8) :: gamma_bs_plus3
     285             : real(r8) :: gamma_half_br_plus5
     286             : real(r8) :: gamma_half_bs_plus5
     287             : real(r8) :: gamma_2bs_plus2
     288             : 
     289             : !$acc declare create (rv,cpp,tmelt,xxlv,xxls,gamma_bs_plus3,   &
     290             : !$acc                 gamma_half_br_plus5,gamma_half_bs_plus5, &
     291             : !$acc                 gamma_2bs_plus2)
     292             : 
     293             : !=========================================================
     294             : ! Utilities that are cheaper if the compiler knows that
     295             : ! some argument is an integer.
     296             : !=========================================================
     297             : 
     298             : interface rising_factorial
     299             :    module procedure rising_factorial_r8
     300             :    module procedure rising_factorial_r8_vec
     301             :    module procedure rising_factorial_integer
     302             :    module procedure rising_factorial_integer_vec
     303             : end interface rising_factorial
     304             : 
     305             : interface var_coef
     306             :    module procedure var_coef_r8
     307             :    module procedure var_coef_r8_vect
     308             :    module procedure var_coef_integer
     309             :    module procedure var_coef_integer_vect
     310             : end interface var_coef
     311             : 
     312             : !==========================================================================
     313             : contains
     314             : !==========================================================================
     315             : 
     316             : ! Initialize module variables.
     317             : !
     318             : ! "kind" serves no purpose here except to check for unlikely linking
     319             : ! issues; always pass in the kind for a double precision real.
     320             : !
     321             : ! "errstring" is the only output; it is blank if there is no error, or set
     322             : ! to a message if there is an error.
     323             : !
     324             : ! Check the list at the top of this module for descriptions of all other
     325             : ! arguments.
     326           0 : subroutine micro_pumas_utils_init( kind, rair, rh2o, cpair, tmelt_in, latvap, &
     327           0 :      latice, dcs, errstring)
     328             : 
     329             :   integer,  intent(in)  :: kind
     330             :   real(r8), intent(in)  :: rair
     331             :   real(r8), intent(in)  :: rh2o
     332             :   real(r8), intent(in)  :: cpair
     333             :   real(r8), intent(in)  :: tmelt_in
     334             :   real(r8), intent(in)  :: latvap
     335             :   real(r8), intent(in)  :: latice
     336             :   real(r8), intent(in)  :: dcs
     337             : 
     338             :   character(128), intent(out) :: errstring
     339             : 
     340             :   ! Name this array to workaround an XLF bug (otherwise could just use the
     341             :   ! expression that sets it).
     342             :   real(r8) :: ice_lambda_bounds(2)
     343             : 
     344             :   !-----------------------------------------------------------------------
     345             : 
     346           0 :   errstring = ' '
     347             : 
     348           0 :   if( kind .ne. r8 ) then
     349           0 :      errstring = 'micro_pumas_init: KIND of reals does not match'
     350           0 :      return
     351             :   endif
     352             : 
     353             :   ! declarations for MG code (transforms variable names)
     354             : 
     355           0 :   rv    = rh2o          ! water vapor gas constant
     356           0 :   cpp   = cpair         ! specific heat of dry air
     357           0 :   tmelt = tmelt_in
     358           0 :   ra    = rair          ! dry air gas constant
     359             : 
     360             :   ! latent heats
     361             : 
     362           0 :   xxlv = latvap         ! latent heat vaporization
     363           0 :   xlf  = latice         ! latent heat freezing
     364           0 :   xxls = xxlv + xlf     ! latent heat of sublimation
     365             : 
     366             :   ! Define constants to help speed up code (this limits calls to gamma function)
     367           0 :   gamma_bs_plus3      = gamma(3._r8+bs)
     368           0 :   gamma_half_br_plus5 = gamma(5._r8/2._r8+br/2._r8)
     369           0 :   gamma_half_bs_plus5 = gamma(5._r8/2._r8+bs/2._r8)
     370           0 :   gamma_2bs_plus2     = gamma(2._r8*bs+2._r8)  
     371             : 
     372             :   ! Don't specify lambda bounds for cloud liquid, as they are determined by
     373             :   ! pgam dynamically.
     374             :   mg_liq_props = MGHydrometeorProps(rhow, dsph, &
     375           0 :        min_mean_mass=min_mean_mass_liq)
     376             : 
     377             :   ! Mean ice diameter can not grow bigger than twice the autoconversion
     378             :   ! threshold for snow.
     379           0 :   ice_lambda_bounds = 1._r8/[2._r8*dcs, 1.e-6_r8]
     380             : 
     381             :   mg_ice_props = MGHydrometeorProps(rhoi, dsph, &
     382           0 :        ice_lambda_bounds, min_mean_mass_ice)
     383             : 
     384           0 :   mg_rain_props = MGHydrometeorProps(rhow, dsph, lam_bnd_rain)
     385           0 :   mg_snow_props = MGHydrometeorProps(rhosn, dsph, lam_bnd_snow)
     386           0 :   mg_graupel_props = MGHydrometeorProps(rhog, dsph, lam_bnd_snow)
     387           0 :   mg_hail_props = MGHydrometeorProps(rhoh, dsph, lam_bnd_snow)
     388             : 
     389             :   !$acc update device (rv,cpp,tmelt,xxlv,xxls,gamma_bs_plus3,   &
     390             :   !$acc                gamma_half_br_plus5,gamma_half_bs_plus5, &
     391             :   !$acc                gamma_2bs_plus2)
     392             : 
     393             : end subroutine micro_pumas_utils_init
     394             : 
     395             : ! Constructor for a constituent property object.
     396           0 : function NewMGHydrometeorProps(rho, eff_dim, lambda_bounds, min_mean_mass) &
     397             :      result(res)
     398             :   real(r8), intent(in) :: rho, eff_dim
     399             :   real(r8), intent(in), optional :: lambda_bounds(2), min_mean_mass
     400             :   type(MGHydrometeorProps) :: res
     401             : 
     402           0 :   res%rho = rho
     403           0 :   res%eff_dim = eff_dim
     404           0 :   if (present(lambda_bounds)) then
     405           0 :      res%lambda_bounds = lambda_bounds
     406             :   else
     407           0 :      res%lambda_bounds = no_limiter()
     408             :   end if
     409           0 :   if (present(min_mean_mass)) then
     410           0 :      res%min_mean_mass = min_mean_mass
     411             :   else
     412           0 :      res%min_mean_mass = no_limiter()
     413             :   end if
     414             : 
     415           0 :   res%shape_coef = rho*pi*gamma(eff_dim+1._r8)/6._r8
     416             : 
     417           0 : end function NewMGHydrometeorProps
     418             : 
     419             : !========================================================================
     420             : !FORMULAS
     421             : !========================================================================
     422             : 
     423             : ! Use gamma function to implement rising factorial extended to the reals.
     424           0 : subroutine rising_factorial_r8(x, n, res)
     425             :   !$acc routine seq
     426             :   real(r8), intent(in) :: x, n
     427             :   real(r8), intent(out) :: res
     428             : 
     429             :   !$acc data present (x,res)
     430             : 
     431           0 :   res = gamma(x+n)/gamma(x)
     432             :   
     433             :   !$acc end data
     434           0 : end subroutine rising_factorial_r8
     435             : 
     436           0 : subroutine rising_factorial_r8_vec(x, n, res,vlen)
     437             :   integer, intent(in)   :: vlen
     438             :   real(r8), intent(in)  :: x(vlen), n
     439             :   real(r8), intent(out) :: res(vlen)
     440             :   integer :: i
     441             :   real(r8) :: tmp
     442             : 
     443             :   !$acc data present (x,res)
     444             : 
     445             :   !$acc parallel vector_length(VLENS) default(present)
     446             :   !$acc loop gang vector private(tmp)
     447           0 :   do i=1,vlen
     448           0 :      tmp = x(i)+n
     449           0 :      res(i) = gamma(tmp)
     450           0 :      tmp = gamma(x(i))
     451           0 :      res(i) = res(i)/tmp
     452             :   end do
     453             :   !$acc end parallel
     454             : 
     455             :   !$acc end data
     456             : 
     457           0 : end subroutine rising_factorial_r8_vec
     458             : 
     459             : ! Rising factorial can be performed much cheaper if n is a small integer.
     460           0 : subroutine rising_factorial_integer(x, n, res)
     461             :   !$acc routine seq
     462             :   real(r8), intent(in)  :: x
     463             :   integer,  intent(in)  :: n
     464             :   real(r8), intent(out) :: res
     465             : 
     466             :   integer :: i
     467             :   real(r8) :: factor
     468             : 
     469             :   !$acc data present (x,res)
     470             : 
     471           0 :   res = 1._r8
     472           0 :   factor = x
     473             : 
     474             :   !$acc loop seq
     475           0 :   do i = 1, n
     476           0 :      res = res * factor
     477           0 :      factor = factor + 1._r8
     478             :   end do
     479             : 
     480             :   !$acc end data
     481           0 : end subroutine rising_factorial_integer
     482             : 
     483           0 : subroutine rising_factorial_integer_vec(x, n, res,vlen)
     484             :   integer,  intent(in)  :: vlen
     485             :   real(r8), intent(in)  :: x(vlen)
     486             :   integer,  intent(in)  :: n
     487             :   real(r8), intent(out) :: res(vlen)
     488             : 
     489             :   integer  :: i,j
     490           0 :   real(r8) :: factor(vlen)
     491             : 
     492             :   !$acc data present (x,res) &
     493             :   !$acc      create  (factor)
     494             : 
     495             :   !$acc parallel vector_length(VLENS) default(present)
     496             :   !$acc loop gang vector
     497           0 :   do i=1,vlen
     498           0 :      res(i)    = 1._r8
     499           0 :      factor(i) = x(i)
     500             :   end do
     501             : 
     502           0 :   if (n == 3) then
     503             :     !$acc loop gang vector
     504           0 :     do i=1,vlen
     505           0 :        res(i)    = res(i) * factor(i)
     506           0 :        factor(i) = factor(i) + 1._r8
     507           0 :        res(i)    = res(i) * factor(i)
     508           0 :        factor(i) = factor(i) + 1._r8
     509           0 :        res(i)    = res(i) * factor(i)
     510             :     end do
     511           0 :   elseif (n == 2) then
     512             :     !$acc loop gang vector
     513           0 :     do i=1,vlen
     514           0 :        res(i)    = res(i) * factor(i)
     515           0 :        factor(i) = factor(i) + 1._r8
     516           0 :        res(i)    = res(i) * factor(i)
     517             :     end do
     518             :   else
     519             :     !$acc loop seq
     520           0 :     do j = 1, n
     521             :        !$acc loop gang vector
     522           0 :        do i = 1, vlen
     523           0 :           res(i)    = res(i) * factor(i)
     524           0 :           factor(i) = factor(i) + 1._r8
     525             :        end do
     526             :     end do
     527             :   end if
     528             :   !$acc end parallel
     529             : 
     530             :   !$acc end data
     531           0 : end subroutine rising_factorial_integer_vec
     532             : 
     533             : ! Calculate correction due to latent heat for evaporation/sublimation
     534           0 : subroutine calc_ab_line(t, qv, xxl, ab)
     535             :   !$acc routine seq
     536             :   real(r8), intent(in)  :: t     ! Temperature
     537             :   real(r8), intent(in)  :: qv    ! Saturation vapor pressure
     538             :   real(r8), intent(in)  :: xxl   ! Latent heat
     539             :   real(r8), intent(out) :: ab
     540             : 
     541             :   real(r8) :: dqsdt
     542             : 
     543             :   !$acc data present (t,qv,xxl,ab)
     544             : 
     545           0 :   dqsdt = xxl*qv / (rv * t**2)
     546           0 :   ab = 1._r8 + dqsdt*xxl/cpp
     547             : 
     548             :   !$acc end data
     549           0 : end subroutine calc_ab_line
     550             : 
     551             : ! Calculate correction due to latent heat for evaporation/sublimation
     552           0 : subroutine calc_ab_vect(t, qv, xxl, ab, vlen)
     553             :   integer,  intent(in) :: vlen
     554             :   real(r8), intent(in) :: t(vlen)     ! Temperature
     555             :   real(r8), intent(in) :: qv(vlen)    ! Saturation vapor pressure
     556             :   real(r8), intent(in) :: xxl         ! Latent heat
     557             : 
     558             :   real(r8), intent(out) :: ab(vlen)
     559             :   real(r8) :: dqsdt
     560             :   integer :: i
     561             : 
     562             :   !$acc data present (t,qv,xxl,ab)
     563             : 
     564             :   !$acc parallel vector_length(VLENS) default(present)
     565             :   !$acc loop gang vector private(dqsdt)
     566           0 :   do i=1,vlen
     567           0 :      dqsdt = xxl*qv(i) / (rv * t(i)**2)
     568           0 :      ab(i) = 1._r8 + dqsdt*xxl/cpp
     569             :   end do
     570             :   !$acc end parallel
     571             : 
     572             :   !$acc end data
     573           0 : end subroutine calc_ab_vect
     574             : 
     575             : ! get cloud droplet size distribution parameters
     576           0 : subroutine size_dist_param_liq_line(props, qcic, ncic, rho, pgam, lamc)
     577             :   !$acc routine seq
     578             :   type(MGHydrometeorProps), intent(in)    :: props
     579             :   real(r8),                 intent(in)    :: qcic
     580             :   real(r8),                 intent(inout) :: ncic
     581             :   real(r8),                 intent(in)    :: rho
     582             :   real(r8),                 intent(out)   :: pgam
     583             :   real(r8),                 intent(out)   :: lamc
     584             : 
     585             :   ! local variables
     586             :   type(MGHydrometeorProps)                :: props_loc
     587             :   real(r8)                                :: tmp
     588             : 
     589             :   !$acc data present (props,qcic,ncic,rho,pgam,lamc)
     590             : 
     591           0 :   if (qcic > qsmall) then
     592             :      ! Local copy of properties that can be modified.
     593             :      ! (Elemental routines that operate on arrays can't modify scalar
     594             :      ! arguments.)
     595           0 :      props_loc = props
     596             : 
     597             :      ! Get pgam from fit Rotstayn and Liu 2003 (changed from Martin 1994 for CAM6)
     598           0 :      pgam = 1.0_r8 - 0.7_r8 * exp(-0.008_r8*1.e-6_r8*ncic*rho)
     599           0 :      pgam = 1._r8/(pgam**2) - 1._r8
     600           0 :      pgam = max(pgam, 2._r8)
     601             : 
     602             :      ! Set coefficient for use in size_dist_param_basic.
     603             :      ! The 3D case is so common and optimizable that we specialize it:
     604           0 :      if (props_loc%eff_dim == 3._r8) then
     605           0 :         call rising_factorial(pgam+1._r8, 3, tmp)
     606           0 :         props_loc%shape_coef = pi / 6._r8 * props_loc%rho * tmp
     607             :      else
     608           0 :         call rising_factorial(pgam+1._r8, props_loc%eff_dim, tmp)
     609           0 :         props_loc%shape_coef = pi / 6._r8 * props_loc%rho * tmp
     610             :      end if
     611             : 
     612             :      ! Limit to between 2 and 50 microns mean size.
     613           0 :      props_loc%lambda_bounds = (pgam+1._r8)*1._r8/[50.e-6_r8, 2.e-6_r8]
     614             : 
     615           0 :      call size_dist_param_basic(props_loc, qcic, ncic, lamc)
     616             :   else
     617             :      ! pgam not calculated in this case, so set it to a value likely to
     618             :      ! cause an error if it is accidentally used
     619             :      ! (gamma function undefined for negative integers)
     620           0 :      pgam = -100._r8
     621           0 :      lamc = 0._r8
     622             :   end if
     623             : 
     624             :   !$acc end data
     625           0 : end subroutine size_dist_param_liq_line
     626             : 
     627             : ! get cloud droplet size distribution parameters
     628             : 
     629           0 : subroutine size_dist_param_liq_2D(props, qcic, ncic, rho, pgam, lamc, dim1, dim2)
     630             : 
     631             :   type(mghydrometeorprops),       intent(in)    :: props
     632             :   integer,                        intent(in)    :: dim1, dim2
     633             :   real(r8), dimension(dim1,dim2), intent(in)    :: qcic
     634             :   real(r8), dimension(dim1,dim2), intent(inout) :: ncic
     635             :   real(r8), dimension(dim1,dim2), intent(in)    :: rho
     636             :   real(r8), dimension(dim1,dim2), intent(out)   :: pgam
     637             :   real(r8), dimension(dim1,dim2), intent(out)   :: lamc
     638             : 
     639             :   ! local variables
     640             :   integer  :: i, k
     641           0 :   real(r8) :: tmp(dim1,dim2),pgamp1(dim1,dim2)
     642           0 :   real(r8) :: shapeC(dim1,dim2),lbnd(dim1,dim2),ubnd(dim1,dim2)
     643             : 
     644             :   !$acc data present (props,qcic,ncic,rho,pgam,lamc) &
     645             :   !$acc      create  (tmp,pgamp1,shapeC,lbnd,ubnd)
     646             : 
     647             :   !$acc parallel vector_length(VLENS) default(present)
     648             :   !$acc loop gang vector collapse(2)
     649           0 :   do k = 1, dim2
     650           0 :      do i = 1, dim1
     651           0 :         if (qcic(i,k) > qsmall) then
     652             :            ! Get pgam from fit Rotstayn and Liu 2003 (changed from Martin 1994 for CAM6)
     653           0 :            pgam(i,k) = 1.0_r8 - 0.7_r8 * exp(-0.008_r8*1.e-6_r8*ncic(i,k)*rho(i,k))
     654           0 :            pgam(i,k) = 1._r8/(pgam(i,k)**2) - 1._r8
     655           0 :            pgam(i,k) = max(pgam(i,k), 2._r8)
     656           0 :            pgamp1(i,k) = pgam(i,k)+1._r8
     657             :         else
     658           0 :            pgamp1(i,k) = 0._r8
     659             :         end if
     660             :      end do
     661             :   end do
     662             :   !$acc end parallel
     663             : 
     664             :   ! Set coefficient for use in size_dist_param_basic.
     665             :   ! The 3D case is so common and optimizable that we specialize it:
     666           0 :   if (props%eff_dim == 3._r8) then
     667           0 :      call rising_factorial_integer_vec(pgamp1,3,tmp,dim1*dim2)
     668             :   else
     669           0 :      call rising_factorial_r8_vec(pgamp1, props%eff_dim,tmp,dim1*dim2)
     670             :   end if
     671             : 
     672             :   !$acc parallel vector_length(VLENS) default(present)
     673             :   !$acc loop gang vector collapse(2)
     674           0 :   do k = 1, dim2
     675           0 :      do i = 1, dim1
     676           0 :         if (qcic(i,k) > qsmall) then
     677           0 :            shapeC(i,k) = pi / 6._r8 * props%rho * tmp(i,k)
     678             :            ! Limit to between 2 and 50 microns mean size.
     679           0 :            lbnd(i,k)   = pgamp1(i,k)*1._r8/50.e-6_r8
     680           0 :            ubnd(i,k)   = pgamp1(i,k)*1._r8/2.e-6_r8
     681             :         else
     682           0 :            shapeC(i,k) = 0._r8
     683           0 :            lbnd(i,k) = 0._r8
     684           0 :            ubnd(i,k) = 0._r8
     685             :         end if
     686             :      end do
     687             :   end do
     688             :   !$acc end parallel 
     689             : 
     690           0 :   call size_dist_param_basic_vect2(props, qcic, ncic, shapeC, lbnd, ubnd, lamc, dim1*dim2)
     691             : 
     692             :   !$acc parallel vector_length(VLENS) default(present)
     693             :   !$acc loop gang vector collapse(2)
     694           0 :   do k = 1, dim2
     695           0 :      do i = 1, dim1
     696           0 :         if (qcic(i,k) <= qsmall) then
     697             :            ! pgam not calculated in this case, so set it to a value likely to
     698             :            ! cause an error if it is accidentally used
     699             :            ! (gamma function undefined for negative integers)
     700           0 :            pgam(i,k) = -100._r8
     701           0 :            lamc(i,k) = 0._r8
     702             :         end if
     703             :      end do
     704             :   end do
     705             :   !$acc end parallel
     706             : 
     707             :   !$acc end data
     708           0 : end subroutine size_dist_param_liq_2D
     709             : 
     710             : ! get cloud droplet size distribution parameters
     711             : 
     712           0 : subroutine size_dist_param_liq_vect(props, qcic, ncic, rho, pgam, lamc, vlen)
     713             : 
     714             :   type(mghydrometeorprops),  intent(in)    :: props
     715             :   integer,                   intent(in)    :: vlen 
     716             :   real(r8), dimension(vlen), intent(in)    :: qcic
     717             :   real(r8), dimension(vlen), intent(inout) :: ncic
     718             :   real(r8), dimension(vlen), intent(in)    :: rho
     719             :   real(r8), dimension(vlen), intent(out)   :: pgam
     720             :   real(r8), dimension(vlen), intent(out)   :: lamc
     721             : 
     722             :   ! local variables
     723             :   integer  :: i
     724           0 :   real(r8) :: tmp(vlen),pgamp1(vlen)
     725           0 :   real(r8) :: shapeC(vlen),lbnd(vlen),ubnd(vlen)
     726             : 
     727             :   !$acc data present (props,qcic,ncic,rho,pgam,lamc) &
     728             :   !$acc      create  (tmp,pgamp1,shapeC,lbnd,ubnd)
     729             : 
     730             :   !$acc parallel vector_length(VLENS) default(present)
     731             :   !$acc loop gang vector
     732           0 :   do i = 1, vlen
     733           0 :      if (qcic(i) > qsmall) then
     734             :         ! Get pgam from fit Rotstayn and Liu 2003 (changed from Martin 1994 for CAM6)
     735           0 :         pgam(i) = 1.0_r8 - 0.7_r8 * exp(-0.008_r8*1.e-6_r8*ncic(i)*rho(i))
     736           0 :         pgam(i) = 1._r8/(pgam(i)**2) - 1._r8
     737           0 :         pgam(i) = max(pgam(i), 2._r8)
     738           0 :         pgamp1(i) = pgam(i)+1._r8
     739             :      else
     740           0 :         pgamp1(i) = 0._r8   
     741             :      end if
     742             :   end do
     743             :   !$acc end parallel
     744             : 
     745             :   ! Set coefficient for use in size_dist_param_basic.
     746             :   ! The 3D case is so common and optimizable that we specialize it:
     747           0 :   if (props%eff_dim == 3._r8) then
     748           0 :      call rising_factorial_integer_vec(pgamp1,3,tmp,vlen)
     749             :   else
     750           0 :      call rising_factorial_r8_vec(pgamp1, props%eff_dim,tmp,vlen)
     751             :   end if
     752             : 
     753             :   !$acc parallel vector_length(VLENS) default(present)
     754             :   !$acc loop gang vector
     755           0 :   do i = 1, vlen 
     756           0 :      if (qcic(i) > qsmall) then
     757           0 :         shapeC(i) = pi / 6._r8 * props%rho * tmp(i)
     758             :         ! Limit to between 2 and 50 microns mean size.
     759           0 :         lbnd(i)   = pgamp1(i)*1._r8/50.e-6_r8
     760           0 :         ubnd(i)   = pgamp1(i)*1._r8/2.e-6_r8
     761             :      else
     762           0 :         shapeC(i) = 0._r8
     763           0 :         lbnd(i) = 0._r8
     764           0 :         ubnd(i) = 0._r8
     765             :      end if
     766             :   end do
     767             :   !$acc end parallel 
     768             : 
     769           0 :   call size_dist_param_basic_vect2(props, qcic, ncic, shapeC, lbnd, ubnd, lamc, vlen)
     770             : 
     771             :   !$acc parallel vector_length(VLENS) default(present)
     772             :   !$acc loop gang vector
     773           0 :   do i = 1, vlen
     774           0 :      if (qcic(i) <= qsmall) then
     775             :         ! pgam not calculated in this case, so set it to a value likely to
     776             :         ! cause an error if it is accidentally used
     777             :         ! (gamma function undefined for negative integers)
     778           0 :         pgam(i) = -100._r8
     779           0 :         lamc(i) = 0._r8
     780             :      end if
     781             :   end do
     782             :   !$acc end parallel
     783             : 
     784             :   !$acc end data
     785           0 : end subroutine size_dist_param_liq_vect
     786             : 
     787             : ! Basic routine for getting size distribution parameters.
     788           0 : subroutine size_dist_param_basic_line(props, qic, nic, lam, n0)
     789             :   !$acc routine seq
     790             :   type(MGHydrometeorProps), intent(in)    :: props
     791             :   real(r8),                 intent(in)    :: qic
     792             :   real(r8),                 intent(inout) :: nic
     793             :   real(r8),                 intent(out)           :: lam
     794             :   real(r8),                 intent(out), optional :: n0
     795             :   
     796             :   logical :: present_n0 
     797           0 :   present_n0 = present(n0)
     798             : 
     799             :   !$acc data present (props,qic,nic,lam,n0)
     800             : 
     801           0 :   if (qic > qsmall) then
     802             :      ! add upper limit to in-cloud number concentration to prevent
     803             :      ! numerical error
     804           0 :      if (limiter_is_on(props%min_mean_mass)) then
     805           0 :         nic = min(nic, qic / props%min_mean_mass)
     806             :      end if
     807             : 
     808             :      ! lambda = (c n/q)^(1/d)
     809           0 :      lam = (props%shape_coef * nic/qic)**(1._r8/props%eff_dim)
     810             : 
     811             :      ! check for slope
     812             :      ! adjust vars
     813           0 :      if (lam < props%lambda_bounds(1)) then
     814           0 :         lam = props%lambda_bounds(1)
     815           0 :         nic = lam**(props%eff_dim) * qic/props%shape_coef
     816           0 :      else if (lam > props%lambda_bounds(2)) then
     817           0 :         lam = props%lambda_bounds(2)
     818           0 :         nic = lam**(props%eff_dim) * qic/props%shape_coef
     819             :      end if
     820             :   else
     821           0 :      lam = 0._r8
     822             :   end if
     823             : 
     824           0 :   if (present_n0) n0 = nic * lam
     825             : 
     826             :   !$acc end data
     827           0 : end subroutine size_dist_param_basic_line
     828             : 
     829           0 : subroutine size_dist_param_basic_vect(props, qic, nic, lam, vlen, n0)
     830             : 
     831             :   type (mghydrometeorprops), intent(in)    :: props
     832             :   integer,                   intent(in)    :: vlen
     833             :   real(r8), dimension(vlen), intent(in)    :: qic
     834             :   real(r8), dimension(vlen), intent(inout) :: nic
     835             :   real(r8), dimension(vlen), intent(out)   :: lam
     836             :   real(r8), dimension(vlen), intent(out), optional :: n0
     837             :   integer  :: i
     838             :   logical  :: limiterActive, present_n0
     839             :   real(r8) :: effDim,shapeCoef,ubnd,lbnd, minMass
     840             : 
     841             :   !$acc data present (props,qic,nic,lam,n0)
     842             : 
     843           0 :   limiterActive = limiter_is_on(props%min_mean_mass)
     844           0 :   effDim    = props%eff_dim
     845           0 :   shapeCoef = props%shape_coef
     846           0 :   lbnd      = props%lambda_bounds(1)
     847           0 :   ubnd      = props%lambda_bounds(2)
     848           0 :   minMass   = props%min_mean_mass
     849           0 :   present_n0 = present(n0)
     850             : 
     851             :   !$acc parallel vector_length(VLENS) default(present)
     852             :   !$acc loop gang vector
     853           0 :   do i = 1, vlen
     854           0 :      if (qic(i) > qsmall) then
     855             :         ! add upper limit to in-cloud number concentration to prevent
     856             :         ! numerical error
     857           0 :         if (limiterActive) then
     858           0 :            nic(i) = min(nic(i), qic(i) / minMass)
     859             :         end if
     860             : 
     861             :         ! lambda = (c n/q)^(1/d)
     862           0 :         lam(i) = (shapeCoef * nic(i)/qic(i))**(1._r8/effDim)
     863             : 
     864             :         ! check for slope
     865             :         ! adjust vars
     866           0 :         if (lam(i) < lbnd) then
     867           0 :            lam(i) = lbnd
     868           0 :            nic(i) = lam(i)**(effDim) * qic(i)/shapeCoef
     869           0 :         else if (lam(i) > ubnd) then
     870           0 :            lam(i) = ubnd
     871           0 :            nic(i) = lam(i)**(effDim) * qic(i)/shapeCoef
     872             :         end if
     873             : 
     874             :      else
     875           0 :         lam(i) = 0._r8
     876             :      end if
     877             :   end do
     878             : 
     879           0 :   if (present_n0) then
     880             :      !$acc loop gang vector
     881           0 :      do i = 1, vlen 
     882           0 :         n0(i) = nic(i) * lam(i)
     883             :      end do
     884             :   end if
     885             :   !$acc end parallel
     886             : 
     887             :   !$acc end data
     888           0 : end subroutine size_dist_param_basic_vect
     889             : 
     890           0 : subroutine size_dist_param_basic_2D(props, qic, nic, lam, dim1, dim2, n0)
     891             : 
     892             :   type (mghydrometeorprops),      intent(in)    :: props
     893             :   integer,                        intent(in)    :: dim1, dim2
     894             :   real(r8), dimension(dim1,dim2), intent(in)    :: qic
     895             :   real(r8), dimension(dim1,dim2), intent(inout) :: nic
     896             :   real(r8), dimension(dim1,dim2), intent(out)   :: lam
     897             :   real(r8), dimension(dim1,dim2), intent(out), optional :: n0
     898             :   integer  :: i, k 
     899             :   logical  :: limiterActive, present_n0
     900             :   real(r8) :: effDim,shapeCoef,ubnd,lbnd, minMass
     901             : 
     902           0 :   limiterActive = limiter_is_on(props%min_mean_mass)
     903           0 :   effDim    = props%eff_dim
     904           0 :   shapeCoef = props%shape_coef
     905           0 :   lbnd      = props%lambda_bounds(1)
     906           0 :   ubnd      = props%lambda_bounds(2)
     907           0 :   minMass   = props%min_mean_mass
     908           0 :   present_n0 = present(n0)
     909             : 
     910             :   !$acc data present (props,qic,nic,lam,n0)
     911             : 
     912             :   !$acc parallel vector_length(VLENS) default(present)
     913             :   !$acc loop gang vector collapse(2)
     914           0 :   do k = 1, dim2
     915           0 :      do i = 1, dim1
     916           0 :         if (qic(i,k) > qsmall) then
     917             :            ! add upper limit to in-cloud number concentration to prevent
     918             :            ! numerical error
     919           0 :            if (limiterActive) then
     920           0 :               nic(i,k) = min(nic(i,k), qic(i,k) / minMass)
     921             :            end if
     922             :    
     923             :            ! lambda = (c n/q)^(1/d)
     924           0 :            lam(i,k) = (shapeCoef * nic(i,k)/qic(i,k))**(1._r8/effDim)
     925             :    
     926             :            ! check for slope
     927             :            ! adjust vars
     928           0 :            if (lam(i,k) < lbnd) then
     929           0 :               lam(i,k) = lbnd
     930           0 :               nic(i,k) = lam(i,k)**(effDim) * qic(i,k)/shapeCoef
     931           0 :            else if (lam(i,k) > ubnd) then
     932           0 :               lam(i,k) = ubnd
     933           0 :               nic(i,k) = lam(i,k)**(effDim) * qic(i,k)/shapeCoef
     934             :            end if
     935             :    
     936             :         else
     937           0 :            lam(i,k) = 0._r8
     938             :         end if
     939             :      end do
     940             :   end do
     941             : 
     942           0 :   if (present_n0) then
     943             :      !$acc loop gang vector collapse(2)
     944           0 :      do k = 1, dim2
     945           0 :         do i = 1, dim1
     946           0 :            n0(i,k) = nic(i,k) * lam(i,k)
     947             :         end do
     948             :      end do
     949             :   end if
     950             :   !$acc end parallel
     951             : 
     952             :   !$acc end data
     953           0 : end subroutine size_dist_param_basic_2D
     954             : 
     955           0 : subroutine size_dist_param_basic_vect2(props, qic, nic, shapeC, lbnd, ubnd, lam, vlen, n0)
     956             : 
     957             :   type (mghydrometeorprops), intent(in)    :: props
     958             :   integer,                   intent(in)    :: vlen
     959             :   real(r8), dimension(vlen), intent(in)    :: qic
     960             :   real(r8), dimension(vlen), intent(inout) :: nic
     961             :   real(r8), dimension(vlen), intent(in)    :: shapeC,lbnd,ubnd
     962             :   real(r8), dimension(vlen), intent(out)   :: lam
     963             :   real(r8), dimension(vlen), intent(out), optional :: n0
     964             :   integer  :: i
     965             :   integer  :: cnt
     966             :   logical  :: limiterActive, present_n0
     967             :   real(r8) :: effDim,shapeCoef, minMass
     968             : 
     969           0 :   limiterActive = limiter_is_on(props%min_mean_mass)
     970           0 :   effDim        = props%eff_dim
     971           0 :   minMass       = props%min_mean_mass
     972           0 :   present_n0    = present(n0)
     973             : 
     974             :   !$acc data present (props,qic,nic,shapeC,lbnd,ubnd,lam,n0)
     975             : 
     976             :   !$acc parallel vector_length(VLENS) default(present)
     977             :   !$acc loop gang vector
     978           0 :   do i=1,vlen
     979             : 
     980           0 :      if (qic(i) > qsmall) then
     981             :         ! add upper limit to in-cloud number concentration to prevent
     982             :         ! numerical error
     983             : 
     984           0 :         if (limiterActive) then
     985           0 :            nic(i) = min(nic(i), qic(i) / minMass)
     986             :         end if
     987             :         ! lambda = (c n/q)^(1/d)
     988             : 
     989           0 :         lam(i) = (shapeC(i) * nic(i)/qic(i))**(1._r8/effDim)
     990             :         ! check for slope
     991             :         ! adjust vars
     992             : 
     993           0 :         if (lam(i) < lbnd(i)) then
     994           0 :            lam(i) = lbnd(i)
     995           0 :            nic(i) = lam(i)**(effDim) * qic(i)/shapeC(i)
     996           0 :         else if (lam(i) > ubnd(i)) then
     997           0 :            lam(i) = ubnd(i)
     998           0 :            nic(i) = lam(i)**(effDim) * qic(i)/shapeC(i)
     999             :         end if
    1000             :      else
    1001           0 :         lam(i) = 0._r8
    1002             :      end if
    1003             : 
    1004             :   end do
    1005             : 
    1006           0 :   if (present_n0) then
    1007             :      !$acc loop gang vector
    1008           0 :      do i = 1,vlen
    1009           0 :         n0(i) = nic(i) * lam(i)
    1010             :      end do
    1011             :   end if
    1012             :   !$acc end parallel
    1013             : 
    1014             :   !$acc end data
    1015           0 : end subroutine size_dist_param_basic_vect2
    1016             : 
    1017           0 : real(r8) elemental function avg_diameter(q, n, rho_air, rho_sub)
    1018             :   ! Finds the average diameter of particles given their density, and
    1019             :   ! mass/number concentrations in the air.
    1020             :   ! Assumes that diameter follows an exponential distribution.
    1021             :   real(r8), intent(in) :: q         ! mass mixing ratio
    1022             :   real(r8), intent(in) :: n         ! number concentration (per volume)
    1023             :   real(r8), intent(in) :: rho_air   ! local density of the air
    1024             :   real(r8), intent(in) :: rho_sub   ! density of the particle substance
    1025             : 
    1026           0 :   avg_diameter = (q*rho_air/(pi * rho_sub * n))**(1._r8/3._r8)
    1027             : 
    1028           0 : end function avg_diameter
    1029             : 
    1030           0 : subroutine avg_diameter_vec (q, n, rho_air, rho_sub, avg_diameter, vlen)
    1031             :    ! Finds the average diameter of particles given their density, and
    1032             :    ! mass/number concentrations in the air.
    1033             :    ! Assumes that diameter follows an exponential distribution.
    1034             :    integer,  intent(in)  :: vlen
    1035             :    real(r8), intent(in)  :: q(vlen)         ! mass mixing ratio
    1036             :    real(r8), intent(in)  :: n(vlen)         ! number concentration (per volume)
    1037             :    real(r8), intent(in)  :: rho_air(vlen)   ! local density of the air
    1038             :    real(r8), intent(in)  :: rho_sub   ! density of the particle substance
    1039             :    real(r8), intent(out) :: avg_diameter(vlen)
    1040             :    integer :: i
    1041             : 
    1042             :    !$acc data present (q,n,rho_air,avg_diameter)
    1043             : 
    1044             :    !$acc parallel vector_length(VLENS) default(present)
    1045             :    !$acc loop gang vector
    1046           0 :    do i=1,vlen
    1047           0 :       avg_diameter(i) = (q(i)*rho_air(i)/(pi * rho_sub * n(i)))**(1._r8/3._r8)
    1048             :    end do
    1049             :    !$acc end parallel
    1050             : 
    1051             :    !$acc end data
    1052           0 : end subroutine avg_diameter_vec
    1053             : 
    1054           0 : subroutine var_coef_r8(relvar, a, res)
    1055             :   !$acc routine seq
    1056             : 
    1057             :   ! Finds a coefficient for process rates based on the relative variance
    1058             :   ! of cloud water.
    1059             :   real(r8), intent(in)  :: relvar
    1060             :   real(r8), intent(in)  :: a
    1061             :   real(r8), intent(out) :: res
    1062             : 
    1063             :   !$acc data present (relvar,res)
    1064             : 
    1065           0 :   call rising_factorial(relvar, a, res) 
    1066           0 :   res = res / relvar**a
    1067             : 
    1068             :   !$acc end data
    1069           0 : end subroutine var_coef_r8
    1070             : 
    1071           0 : subroutine var_coef_r8_vect(relvar, a, res, vlen)
    1072             :   ! Finds a coefficient for process rates based on the relative variance
    1073             :   ! of cloud water.
    1074             :   integer,  intent(in)  :: vlen
    1075             :   real(r8), intent(in)  :: relvar(vlen)
    1076             :   real(r8), intent(in)  :: a
    1077             :   real(r8), intent(out) :: res(vlen)
    1078             :   integer  :: i
    1079           0 :   real(r8) :: tmpA(vlen)
    1080             : 
    1081             :   !$acc data present (relvar,res) &
    1082             :   !$acc      create  (tmpA)
    1083             : 
    1084           0 :   call rising_factorial(relvar,a,tmpA,vlen)
    1085             :   !$acc parallel vector_length(VLENS) default(present)
    1086             :   !$acc loop gang vector
    1087           0 :   do i=1,vlen
    1088           0 :      res(i) = tmpA(i)/relvar(i)**a
    1089             :   end do
    1090             :   !$acc end parallel
    1091             : 
    1092             :   !$acc end data
    1093           0 : end subroutine var_coef_r8_vect
    1094             : 
    1095             : subroutine var_coef_integer(relvar, a, res)
    1096             :   !$acc routine seq
    1097             : 
    1098             :   ! Finds a coefficient for process rates based on the relative variance
    1099             :   ! of cloud water.
    1100             :   real(r8), intent(in) :: relvar
    1101             :   integer, intent(in) :: a
    1102             :   real(r8), intent(out) :: res
    1103             : 
    1104             :   !$acc data present (relvar,res)
    1105             : 
    1106             :   call rising_factorial(relvar, a, res)
    1107             :   res = res / relvar**a
    1108             : 
    1109             :   !$acc end data
    1110             : end subroutine var_coef_integer
    1111             : 
    1112           0 : subroutine var_coef_integer_vect(relvar, a, res, vlen)
    1113             :   ! Finds a coefficient for process rates based on the relative variance
    1114             :   ! of cloud water.
    1115             :   integer, intent(in)   :: vlen
    1116             :   real(r8), intent(in)  :: relvar(vlen)
    1117             :   integer, intent(in)   :: a
    1118             :   real(r8), intent(out) :: res(vlen)
    1119             :   integer  :: i
    1120           0 :   real(r8) :: tmp(vlen)
    1121             : 
    1122             :   !$acc data present (relvar,res) &
    1123             :   !$acc      create  (tmp)
    1124             : 
    1125           0 :   call rising_factorial(relvar, a,tmp,vlen)
    1126             :   !$acc parallel vector_length(VLENS) default(present)
    1127             :   !$acc loop gang vector
    1128           0 :   do i=1,vlen
    1129           0 :      res(i) = tmp(i) / relvar(i)**a
    1130             :   end do
    1131             :   !$acc end parallel
    1132             : 
    1133             :   !$acc end data
    1134           0 : end subroutine var_coef_integer_vect
    1135             : 
    1136             : !========================================================================
    1137             : !MICROPHYSICAL PROCESS CALCULATIONS
    1138             : !========================================================================
    1139             : !========================================================================
    1140             : ! Initial ice deposition and sublimation loop.
    1141             : ! Run before the main loop
    1142             : ! This subroutine written by Peter Caldwell
    1143             : 
    1144           0 : subroutine ice_deposition_sublimation(t, qv, qi, ni, &
    1145           0 :                                       icldm, rho, dv,qvl, qvi, &
    1146           0 :                                       berg, vap_dep, ice_sublim, vlen)
    1147             : 
    1148             :   !INPUT VARS:
    1149             :   !===============================================
    1150             :   integer,  intent(in)                  :: vlen
    1151             :   real(r8), dimension(vlen), intent(in) :: t
    1152             :   real(r8), dimension(vlen), intent(in) :: qv
    1153             :   real(r8), dimension(vlen), intent(in) :: qi
    1154             :   real(r8), dimension(vlen), intent(in) :: ni
    1155             :   real(r8), dimension(vlen), intent(in) :: icldm
    1156             :   real(r8), dimension(vlen), intent(in) :: rho
    1157             :   real(r8), dimension(vlen), intent(in) :: dv
    1158             :   real(r8), dimension(vlen), intent(in) :: qvl
    1159             :   real(r8), dimension(vlen), intent(in) :: qvi
    1160             : 
    1161             :   !OUTPUT VARS:
    1162             :   !===============================================
    1163             :   real(r8), dimension(vlen), intent(out) :: vap_dep !ice deposition (cell-ave value)
    1164             :   real(r8), dimension(vlen), intent(out) :: ice_sublim !ice sublimation (cell-ave value)
    1165             :   real(r8), dimension(vlen), intent(out) :: berg !bergeron enhancement (cell-ave value)
    1166             : 
    1167             :   !INTERNAL VARS:
    1168             :   !===============================================
    1169           0 :   real(r8) :: ab(vlen)
    1170             :   real(r8) :: epsi
    1171           0 :   real(r8) :: qiic(vlen)
    1172           0 :   real(r8) :: niic(vlen)
    1173           0 :   real(r8) :: lami(vlen)
    1174           0 :   real(r8) :: n0i(vlen)
    1175             :   integer :: i
    1176             : 
    1177             :   !$acc data present (t,qv,qi,ni,icldm,rho,dv,qvl) &
    1178             :   !$acc      present (qvi,vap_dep,ice_sublim,berg) &
    1179             :   !$acc      create  (ab,qiic,niic,lami,n0i)
    1180             : 
    1181             :   !GET IN-CLOUD qi, ni
    1182             :   !===============================================
    1183             : 
    1184             :   !Compute linearized condensational heating correction
    1185           0 :   call calc_ab(t, qvi, xxls, ab, vlen)
    1186             : 
    1187             :   !$acc parallel vector_length(VLENS) default(present)
    1188             :   !$acc loop gang vector
    1189           0 :   do i = 1,vlen
    1190           0 :      qiic(i) = qi(i)/icldm(i)
    1191           0 :      niic(i) = ni(i)/icldm(i)
    1192           0 :      if (qi(i)<qsmall) then
    1193           0 :         qiic(i) = 0._r8
    1194           0 :         niic(i) = 0._r8
    1195           0 :         ab(i)   = 0._r8
    1196             :      end if
    1197             :   end do
    1198             :   !$acc end parallel
    1199             : 
    1200             :   !Get slope and intercept of gamma distn for ice.
    1201           0 :   call size_dist_param_basic_vect(mg_ice_props, qiic, niic, lami, vlen, n0i)
    1202             : 
    1203             :   !$acc parallel vector_length(VLENS) default(present)
    1204             :   !$acc loop gang vector private(epsi)
    1205           0 :   do i=1,vlen
    1206           0 :      if (qi(i)>=qsmall) then
    1207             :         !Get depletion timescale=1/eps
    1208           0 :         epsi = 2._r8*pi*n0i(i)*rho(i)*Dv(i)/(lami(i)*lami(i))
    1209             : 
    1210             :         !Compute deposition/sublimation
    1211           0 :         vap_dep(i) = epsi/ab(i)*(qv(i) - qvi(i))
    1212             : 
    1213             :         !Make this a grid-averaged quantity
    1214           0 :         vap_dep(i) = vap_dep(i)*icldm(i)
    1215             : 
    1216             :         !Split into deposition or sublimation.
    1217           0 :         if (t(i) < tmelt .and. vap_dep(i) > 0._r8) then
    1218           0 :            ice_sublim(i) = 0._r8
    1219             :         else
    1220             :         ! make ice_sublim negative for consistency with other evap/sub processes
    1221           0 :            ice_sublim(i) = min(vap_dep(i),0._r8)
    1222           0 :            vap_dep(i)    = 0._r8
    1223             :         end if
    1224             : 
    1225             :         !sublimation occurs @ any T. Not so for berg.
    1226           0 :         if (t(i) < tmelt) then
    1227             : 
    1228             :            !Compute bergeron rate assuming cloud for whole step.
    1229           0 :            berg(i) = max(epsi/ab(i)*(qvl(i) - qvi(i)), 0._r8)
    1230             :         else   !T>frz
    1231           0 :            berg(i)=0._r8
    1232             :         end if !T<frz
    1233             :      else      !where qi<qsmall
    1234           0 :         berg(i)       = 0._r8
    1235           0 :         vap_dep(i)    = 0._r8
    1236           0 :         ice_sublim(i) = 0._r8
    1237             :      end if    !qi>qsmall
    1238             :   end do
    1239             :   !$acc end parallel
    1240             : 
    1241             :   !$acc end data
    1242           0 : end subroutine ice_deposition_sublimation
    1243             : 
    1244           0 : subroutine ice_deposition_sublimation_mg4(t, qv, qi, niic, &
    1245           0 :                                       icldm, rho, dv,qvl, qvi, &
    1246           0 :                                       berg, vap_dep, ice_sublim, &
    1247           0 :                                       af1pr5, af1pr14, rhof, mu, sc, &
    1248             :                                       vlen)
    1249             : 
    1250             :   !INPUT VARS:
    1251             :   !===============================================
    1252             :   integer,  intent(in)                  :: vlen
    1253             :   real(r8), dimension(vlen), intent(in) :: t
    1254             :   real(r8), dimension(vlen), intent(in) :: qv
    1255             :   real(r8), dimension(vlen), intent(in) :: qi
    1256             :   real(r8), dimension(vlen), intent(in) :: niic ! trude: input nicc as other routines
    1257             :   real(r8), dimension(vlen), intent(in) :: icldm
    1258             :   real(r8), dimension(vlen), intent(in) :: rho
    1259             :   real(r8), dimension(vlen), intent(in) :: dv
    1260             :   real(r8), dimension(vlen), intent(in) :: qvl
    1261             :   real(r8), dimension(vlen), intent(in) :: qvi
    1262             :   real(r8), dimension(vlen), intent(in) :: af1pr5, af1pr14
    1263             :   real(r8), dimension(vlen), intent(in) :: rhof
    1264             :   real(r8), dimension(vlen), intent(in) :: mu
    1265             :   real(r8), dimension(vlen), intent(in) :: sc
    1266             : 
    1267             :   !OUTPUT VARS:
    1268             :   !===============================================
    1269             :   real(r8), dimension(vlen), intent(out) :: vap_dep !ice deposition (cell-ave value)
    1270             :   real(r8), dimension(vlen), intent(out) :: ice_sublim !ice sublimation (cell-ave value)
    1271             :   real(r8), dimension(vlen), intent(out) :: berg !bergeron enhancement (cell-ave value)
    1272             : 
    1273             :   !INTERNAL VARS:
    1274             :   !===============================================
    1275           0 :   real(r8) :: ab(vlen)
    1276             :   real(r8) :: epsi
    1277           0 :   real(r8) :: qiic(vlen)
    1278             :   real(r8) :: lami(vlen)
    1279             :   real(r8) :: n0i(vlen)
    1280             :   real(r8), parameter :: thrd = 1._r8/3._r8
    1281             :   integer :: i
    1282             : 
    1283             :   !$acc data present (t,qv,qi,icldm,rho,dv,qvl) &
    1284             :   !$acc      present (qvi,vap_dep,ice_sublim,berg) &
    1285             :   !$acc      present (niic,af1pr5,af1pr14,rhof,mu,sc) &
    1286             :   !$acc      create  (ab,qiic,lami,n0i)
    1287             : 
    1288             :   !GET IN-CLOUD qi, ni
    1289             :   !===============================================
    1290             :   !$acc parallel vector_length(VLENS) default(present)
    1291             :   !$acc loop gang vector
    1292           0 :   do i = 1,vlen
    1293           0 :      if (qi(i)>=qsmall) then
    1294           0 :         qiic(i) = qi(i)/icldm(i)
    1295             :         !Compute linearized condensational heating correction
    1296             :         call calc_ab(t(i), qvi(i), xxls, ab(i))
    1297             :      end if
    1298             :   end do
    1299             :   !$acc end parallel
    1300             : 
    1301             :   !$acc parallel vector_length(VLENS) default(present)
    1302             :   !$acc loop gang vector private(epsi)
    1303           0 :   do i=1,vlen
    1304           0 :      if (qi(i)>=qsmall) then
    1305           0 :         if ( t(i) .lt. tmelt ) then
    1306             :            epsi = (af1pr5(i)+af1pr14(i)*sc(i)**thrd*(rhof(i)*rho(i)/mu(i))**0.5_r8)*2._r8*pi* &
    1307           0 :              rho(i)*dv(i)
    1308             :         else
    1309             :            epsi = 0._r8
    1310             :         end if
    1311             : 
    1312             :         !Compute deposition/sublimation
    1313           0 :         vap_dep(i) = epsi/ab(i)*(qv(i) - qvi(i))
    1314             : 
    1315             :         !Make this a grid-averaged quantity
    1316           0 :         vap_dep(i) = vap_dep(i)*icldm(i)
    1317             : 
    1318             :         !Split into deposition or sublimation.
    1319           0 :         if (t(i) < tmelt .and. vap_dep(i) > 0._r8) then
    1320           0 :            ice_sublim(i)=0._r8
    1321             :         else
    1322             :            ! make ice_sublim negative for consistency with other evap/sub processes
    1323           0 :            ice_sublim(i)=min(vap_dep(i),0._r8)
    1324           0 :            vap_dep(i)=0._r8
    1325             :         end if
    1326             : 
    1327             :         !sublimation occurs @ any T. Not so for berg.
    1328           0 :         if (t(i) < tmelt) then
    1329             :            !Compute bergeron rate assuming cloud for whole step.
    1330           0 :            berg(i) = max(epsi/ab(i)*(qvl(i) - qvi(i)), 0._r8)
    1331             :         else   !T>frz
    1332           0 :            berg(i) = 0._r8
    1333             :         end if !T<frz
    1334             :      else      !where qi<qsmall
    1335           0 :         berg(i)       = 0._r8
    1336           0 :         vap_dep(i)    = 0._r8
    1337           0 :         ice_sublim(i) = 0._r8
    1338             :      end if    !qi>qsmall
    1339             :   end do
    1340             :   !$acc end parallel
    1341             : 
    1342             :   !$acc end data
    1343           0 : end subroutine ice_deposition_sublimation_mg4
    1344             : 
    1345             : !========================================================================
    1346             : ! autoconversion of cloud liquid water to rain
    1347             : ! formula from Khrouditnov and Kogan (2000), modified for sub-grid distribution of qc
    1348             : ! minimum qc of 1 x 10^-8 prevents floating point error
    1349             : 
    1350           0 : subroutine kk2000_liq_autoconversion(microp_uniform, qcic, &
    1351           0 :      ncic, rho, relvar, prc, nprc, nprc1, micro_mg_autocon_fact, &
    1352             :      micro_mg_autocon_nd_exp, micro_mg_autocon_lwp_exp, vlen)
    1353             : 
    1354             :   integer, intent(in) :: vlen
    1355             :   logical, intent(in) :: microp_uniform
    1356             : 
    1357             :   real(r8), dimension(vlen), intent(in) :: qcic
    1358             :   real(r8), dimension(vlen), intent(in) :: ncic
    1359             :   real(r8), dimension(vlen), intent(in) :: rho
    1360             : 
    1361             :   real(r8), dimension(vlen), intent(in) :: relvar
    1362             : 
    1363             :   real(r8), dimension(vlen), intent(out) :: prc
    1364             :   real(r8), dimension(vlen), intent(out) :: nprc
    1365             :   real(r8), dimension(vlen), intent(out) :: nprc1
    1366             : 
    1367           0 :   real(r8), dimension(vlen) :: prc_coef
    1368             :   integer :: i
    1369             : 
    1370             :   real(r8), intent(in) :: micro_mg_autocon_fact
    1371             :   real(r8), intent(in) :: micro_mg_autocon_nd_exp
    1372             :   real(r8), intent(in) :: micro_mg_autocon_lwp_exp
    1373             : 
    1374             :   !$acc data present (qcic,ncic,rho,relvar,prc,nprc,nprc1) &
    1375             :   !$acc      create  (prc_coef)
    1376             : 
    1377             :   ! Take variance into account, or use uniform value.
    1378           0 :   if (.not. microp_uniform) then
    1379           0 :      call var_coef(relvar, micro_mg_autocon_lwp_exp, prc_coef,vlen)
    1380             :   else
    1381             :      !$acc parallel vector_length(VLENS) default(present)
    1382             :      !$acc loop gang vector
    1383           0 :      do i = 1,vlen
    1384           0 :         prc_coef(i) = 1._r8
    1385             :      end do
    1386             :      !$acc end parallel
    1387             :   end if
    1388             : 
    1389             :   !$acc parallel vector_length(VLENS) default(present)
    1390             :   !$acc loop gang vector
    1391           0 :   do i=1,vlen
    1392           0 :      if (qcic(i) >= icsmall) then
    1393             :         ! nprc is increase in rain number conc due to autoconversion
    1394             :         ! nprc1 is decrease in cloud droplet conc due to autoconversion
    1395             : 
    1396             :         ! assume exponential sub-grid distribution of qc, resulting in additional
    1397             :         ! factor related to qcvar below
    1398             :         ! switch for sub-columns, don't include sub-grid qc
    1399             :         prc(i)   = prc_coef(i) * &
    1400             :              micro_mg_autocon_fact * 1350._r8 * qcic(i)**micro_mg_autocon_lwp_exp * &
    1401           0 :              (ncic(i)*1.e-6_r8*rho(i))**(micro_mg_autocon_nd_exp)
    1402             : 
    1403           0 :         nprc(i)  = prc(i) * (1._r8/droplet_mass_25um)
    1404           0 :         nprc1(i) = prc(i)*ncic(i)/qcic(i)
    1405             : 
    1406             :      else
    1407           0 :         prc(i)   = 0._r8
    1408           0 :         nprc(i)  = 0._r8
    1409           0 :         nprc1(i) = 0._r8
    1410             :      end if
    1411             :   end do
    1412             :   !$acc end parallel
    1413             : 
    1414             :   !$acc end data
    1415           0 : end subroutine kk2000_liq_autoconversion
    1416             :   
    1417             : !========================================================================
    1418             : 
    1419           0 : subroutine sb2001v2_liq_autoconversion(pgam,qc,nc,qr,rho,relvar,au,nprc,nprc1,vlen)
    1420             :   !
    1421             :   ! ---------------------------------------------------------------------
    1422             :   ! AUTO_SB:  calculates the evolution of mass- and number mxg-ratio for
    1423             :   ! drizzle drops due to autoconversion. The autoconversion rate assumes
    1424             :   ! f(x)=A*x**(nu_c)*exp(-Bx) in drop MASS x. 
    1425             : 
    1426             :   ! Code from Hugh Morrison, Sept 2014
    1427             : 
    1428             :   ! autoconversion
    1429             :   ! use simple lookup table of dnu values to get mass spectral shape parameter
    1430             :   ! equivalent to the size spectral shape parameter pgam
    1431             :     
    1432             :   integer,                   intent(in)     :: vlen  
    1433             :   real(r8), dimension(vlen), intent (in)    :: pgam
    1434             :   real(r8), dimension(vlen), intent (in)    :: qc  ! = qc (cld water mixing ratio)
    1435             :   real(r8), dimension(vlen), intent (in)    :: nc  ! = nc (cld water number conc /kg)    
    1436             :   real(r8), dimension(vlen), intent (in)    :: qr  ! = qr (rain water mixing ratio)
    1437             :   real(r8), dimension(vlen), intent (in)    :: rho ! = rho : density profile
    1438             :   real(r8), dimension(vlen), intent (in)    :: relvar 
    1439             :   
    1440             :   real(r8), dimension(vlen), intent (out)   :: au ! = prc autoconversion rate
    1441             :   real(r8), dimension(vlen), intent (out)   :: nprc1 ! = number tendency
    1442             :   real(r8), dimension(vlen), intent (out)   :: nprc ! = number tendency fixed size for rain
    1443             :  
    1444             :   ! parameters for droplet mass spectral shape, 
    1445             :   !used by Seifert and Beheng (2001)                             
    1446             :   ! warm rain scheme only (iparam = 1)                                                                        
    1447             :   real(r8), parameter :: dnu(16) = [0._r8,-0.557_r8,-0.430_r8,-0.307_r8, & 
    1448             :      -0.186_r8,-0.067_r8,0.050_r8,0.167_r8,0.282_r8,0.397_r8,0.512_r8, &
    1449             :      0.626_r8,0.739_r8,0.853_r8,0.966_r8,0.966_r8]
    1450             : 
    1451             :   ! parameters for Seifert and Beheng (2001) autoconversion/accretion                                         
    1452             :   real(r8), parameter :: kc = 9.44e9_r8
    1453             :   real(r8), parameter :: kr = 5.78e3_r8
    1454             :   real(r8) :: dum, dum1, nu
    1455             :   integer  :: dumi, i
    1456             : 
    1457             :   !$acc data present (pgam,qc,nc,qr,rho,relvar,au,nprc1,nprc)
    1458             : 
    1459             :   !$acc parallel vector_length(VLENS) default(present)
    1460             :   !$acc loop gang vector private(dumi,nu,dum,dum1)
    1461           0 :   do i=1,vlen
    1462           0 :      if (qc(i) > qsmall) then
    1463           0 :        dumi = int(pgam(i))
    1464           0 :        nu   = dnu(dumi)+(dnu(dumi+1)-dnu(dumi))* &
    1465           0 :                (pgam(i)-dumi)
    1466             : 
    1467           0 :        dum  = 1._r8-qc(i)/(qc(i)+qr(i))
    1468           0 :        dum1 = 600._r8*dum**0.68_r8*(1._r8-dum**0.68_r8)**3
    1469             : 
    1470             :        au(i) = kc/(20._r8*2.6e-7_r8)* &
    1471             :          (nu+2._r8)*(nu+4._r8)/(nu+1._r8)**2._r8* &
    1472             :          (rho(i)*qc(i)/1000._r8)**4._r8/(rho(i)*nc(i)/1.e6_r8)**2._r8* &
    1473           0 :          (1._r8+dum1/(1._r8-dum)**2)*1000._r8 / rho(i)
    1474             : 
    1475           0 :        nprc1(i) = au(i)*2._r8/2.6e-7_r8*1000._r8
    1476           0 :        nprc(i)  = au(i)/droplet_mass_40um
    1477             :      else
    1478           0 :        au(i)    = 0._r8
    1479           0 :        nprc1(i) = 0._r8
    1480           0 :        nprc(i)  = 0._r8
    1481             :      end if
    1482             :   end do
    1483             :   !$acc end parallel
    1484             : 
    1485             :   !$acc end data
    1486           0 : end subroutine sb2001v2_liq_autoconversion 
    1487             :   
    1488             : !========================================================================
    1489             : !SB2001 Accretion V2
    1490             : 
    1491           0 : subroutine sb2001v2_accre_cld_water_rain(qc,nc,qr,rho,relvar,pra,npra,vlen)
    1492             :   !
    1493             :   ! ---------------------------------------------------------------------
    1494             :   ! ACCR_SB calculates the evolution of mass mxng-ratio due to accretion
    1495             :   ! and self collection following Seifert & Beheng (2001).  
    1496             :   !
    1497             :   
    1498             :   integer, intent(in) :: vlen
    1499             :   
    1500             :   real(r8), dimension(vlen), intent (in)    :: qc  ! = qc (cld water mixing ratio)
    1501             :   real(r8), dimension(vlen), intent (in)    :: nc  ! = nc (cld water number conc /kg)    
    1502             :   real(r8), dimension(vlen), intent (in)    :: qr  ! = qr (rain water mixing ratio)
    1503             :   real(r8), dimension(vlen), intent (in)    :: rho ! = rho : density profile
    1504             :   real(r8), dimension(vlen), intent (in)    :: relvar
    1505             : 
    1506             :   ! Output tendencies
    1507             :   real(r8), dimension(vlen), intent(out) :: pra  ! MMR
    1508             :   real(r8), dimension(vlen), intent(out) :: npra ! Number
    1509             : 
    1510             :   ! parameters for Seifert and Beheng (2001) autoconversion/accretion                                         
    1511             :   real(r8), parameter :: kc = 9.44e9_r8
    1512             :   real(r8), parameter :: kr = 5.78e3_r8
    1513             : 
    1514             :   real(r8) :: dum, dum1
    1515             :   integer :: i
    1516             : 
    1517             :   ! accretion
    1518             : 
    1519             :   !$acc data present (qc,nc,qr,rho,relvar,pra,npra)
    1520             : 
    1521             :   !$acc parallel vector_length(VLENS) default(present)
    1522             :   !$acc loop gang vector private(dum,dum1)
    1523           0 :   do i = 1,vlen
    1524           0 :     if (qc(i) > qsmall) then
    1525           0 :       dum     = 1._r8-qc(i)/(qc(i)+qr(i))
    1526           0 :       dum1    = (dum/(dum+5.e-4_r8))**4._r8
    1527           0 :       pra(i)  = kr*rho(i)*0.001_r8*qc(i)*qr(i)*dum1
    1528             :       npra(i) = pra(i)*rho(i)*0.001_r8*(nc(i)*rho(i)*1.e-6_r8)/ &
    1529           0 :            (qc(i)*rho(i)*0.001_r8)*1.e6_r8 / rho(i)
    1530             :     else
    1531           0 :       pra(i)  = 0._r8
    1532           0 :       npra(i) = 0._r8
    1533             :     end if 
    1534             :   end do
    1535             :   !$acc end parallel
    1536             : 
    1537             :   !$acc end data
    1538           0 : end subroutine sb2001v2_accre_cld_water_rain   
    1539             : 
    1540             : !========================================================================
    1541             : ! Autoconversion of cloud ice to snow
    1542             : ! similar to Ferrier (1994)
    1543             : 
    1544           0 : subroutine ice_autoconversion(t, qiic, lami, n0i, dcs, prci, nprci, vlen)
    1545             : 
    1546             :   integer, intent(in) :: vlen
    1547             :   real(r8), dimension(vlen), intent(in) :: t
    1548             :   real(r8), dimension(vlen), intent(in) :: qiic
    1549             :   real(r8), dimension(vlen), intent(in) :: lami
    1550             :   real(r8), dimension(vlen), intent(in) :: n0i
    1551             :   real(r8),                    intent(in) :: dcs
    1552             : 
    1553             :   real(r8), dimension(vlen), intent(out) :: prci
    1554             :   real(r8), dimension(vlen), intent(out) :: nprci
    1555             : 
    1556             :   ! Assume autoconversion timescale of 180 seconds.
    1557             :   real(r8), parameter :: ac_time = 180._r8
    1558             : 
    1559             :   ! Average mass of an ice particle.
    1560             :   real(r8) :: m_ip
    1561             :   ! Ratio of autoconversion diameter to average diameter.
    1562             :   real(r8) :: d_rat
    1563             :   integer :: i
    1564             : 
    1565             :   !$acc data present (t,qiic,lami,n0i,prci,nprci)
    1566             : 
    1567             :   !$acc parallel vector_length(VLENS) default(present)
    1568             :   !$acc loop gang vector private(d_rat,m_ip)
    1569           0 :   do i=1,vlen
    1570           0 :      if (t(i) <= tmelt .and. qiic(i) >= qsmall) then
    1571           0 :         d_rat = lami(i)*dcs
    1572             : 
    1573             :         ! Rate of ice particle conversion (number).
    1574           0 :         nprci(i) = n0i(i)/(lami(i)*ac_time)*exp(-d_rat)
    1575           0 :         m_ip = (rhoi*pi/6._r8) / lami(i)**3
    1576             : 
    1577             :         ! Rate of mass conversion.
    1578             :         ! Note that this is:
    1579             :         ! m n (d^3 + 3 d^2 + 6 d + 6)
    1580             :         prci(i) = m_ip * nprci(i) * &
    1581           0 :              (((d_rat + 3._r8)*d_rat + 6._r8)*d_rat + 6._r8)
    1582             :      else
    1583           0 :         prci(i)  = 0._r8
    1584           0 :         nprci(i) = 0._r8
    1585             :      end if
    1586             :   end do
    1587             :   !$acc end parallel
    1588             : 
    1589             :   !$acc end data
    1590           0 : end subroutine ice_autoconversion
    1591             : 
    1592             : ! immersion freezing (Bigg, 1953)
    1593             : !===================================
    1594             : 
    1595           0 : subroutine immersion_freezing(microp_uniform, t, pgam, lamc, &
    1596           0 :      qcic, ncic, relvar, mnuccc, nnuccc, vlen)
    1597             : 
    1598             :   integer, intent(in) :: vlen
    1599             :   logical, intent(in) :: microp_uniform
    1600             : 
    1601             :   ! Temperature
    1602             :   real(r8), dimension(vlen), intent(in) :: t
    1603             : 
    1604             :   ! Cloud droplet size distribution parameters
    1605             :   real(r8), dimension(vlen), intent(in) :: pgam
    1606             :   real(r8), dimension(vlen), intent(in) :: lamc
    1607             : 
    1608             :   ! MMR and number concentration of in-cloud liquid water
    1609             :   real(r8), dimension(vlen), intent(in) :: qcic
    1610             :   real(r8), dimension(vlen), intent(in) :: ncic
    1611             : 
    1612             :   ! Relative variance of cloud water
    1613             :   real(r8), dimension(vlen), intent(in) :: relvar
    1614             : 
    1615             :   ! Output tendencies
    1616             :   real(r8), dimension(vlen), intent(out) :: mnuccc ! MMR
    1617             :   real(r8), dimension(vlen), intent(out) :: nnuccc ! Number
    1618             : 
    1619             :   ! Coefficients that will be omitted for sub-columns
    1620           0 :   real(r8), dimension(vlen) :: dum
    1621             :   integer  :: i
    1622             :   real(r8) :: tmp
    1623             : 
    1624             :   !$acc data present (t,pgam,lamc,qcic,ncic) &
    1625             :   !$acc      present (relvar,mnuccc,nnuccc)  &
    1626             :   !$acc      create  (dum)
    1627             : 
    1628           0 :   if (.not. microp_uniform) then
    1629           0 :      call var_coef(relvar, 2, dum, vlen)
    1630             :   else
    1631             :      !$acc parallel vector_length(VLENS) default(present)
    1632             :      !$acc loop gang vector
    1633           0 :      do i =1,vlen
    1634           0 :         dum(i) = 1._r8
    1635             :      end do
    1636             :      !$acc end parallel
    1637             :   end if
    1638             : 
    1639             :   !$acc parallel vector_length(VLENS) default(present)
    1640             :   !$acc loop gang vector private(tmp)
    1641           0 :   do i=1,vlen
    1642           0 :      if (qcic(i) >= qsmall .and. t(i) < 269.15_r8) then
    1643           0 :         call rising_factorial(pgam(i)+1._r8, 3, tmp)
    1644             :         nnuccc(i) = &
    1645             :              pi/6._r8*ncic(i)*tmp* &
    1646           0 :              bimm*(exp(aimm*(tmelt - t(i)))-1._r8)/lamc(i)**3
    1647             : 
    1648           0 :         call rising_factorial(pgam(i)+4._r8, 3, tmp)
    1649             :         mnuccc(i) = dum(i) * nnuccc(i) * &
    1650             :              pi/6._r8*rhow* &
    1651           0 :              tmp/lamc(i)**3
    1652             :      else
    1653           0 :         mnuccc(i) = 0._r8
    1654           0 :         nnuccc(i) = 0._r8
    1655             :      end if ! qcic > qsmall and t < 4 deg C
    1656             :   end do
    1657             :   !$acc end parallel
    1658             : 
    1659             :   !$acc end data
    1660           0 : end subroutine immersion_freezing
    1661             : 
    1662             : ! contact freezing (-40<T<-3 C) (Young, 1974) with hooks into simulated dust
    1663             : !===================================================================
    1664             : ! dust size and number in multiple bins are read in from companion routine
    1665             : 
    1666           0 : subroutine contact_freezing (microp_uniform, t, p, rndst, nacon, &
    1667           0 :      pgam, lamc, qcic, ncic, relvar, mnucct, nnucct, vlen, mdust)
    1668             : 
    1669             :   logical, intent(in) :: microp_uniform
    1670             : 
    1671             :   integer, intent(in) :: vlen
    1672             :   integer, intent(in) :: mdust
    1673             : 
    1674             :   real(r8), dimension(vlen), intent(in) :: t            ! Temperature
    1675             :   real(r8), dimension(vlen), intent(in) :: p            ! Pressure
    1676             :   real(r8), dimension(vlen, mdust), intent(in) :: rndst ! Radius (for multiple dust bins)
    1677             :   real(r8), dimension(vlen, mdust), intent(in) :: nacon ! Number (for multiple dust bins)
    1678             : 
    1679             :   ! Size distribution parameters for cloud droplets
    1680             :   real(r8), dimension(vlen), intent(in) :: pgam
    1681             :   real(r8), dimension(vlen), intent(in) :: lamc
    1682             : 
    1683             :   ! MMR and number concentration of in-cloud liquid water
    1684             :   real(r8), dimension(vlen), intent(in) :: qcic
    1685             :   real(r8), dimension(vlen), intent(in) :: ncic
    1686             : 
    1687             :   ! Relative cloud water variance
    1688             :   real(r8), dimension(vlen), intent(in) :: relvar
    1689             : 
    1690             :   ! Output tendencies
    1691             :   real(r8), dimension(vlen), intent(out) :: mnucct ! MMR
    1692             :   real(r8), dimension(vlen), intent(out) :: nnucct ! Number
    1693             : 
    1694             :   real(r8) :: tcnt                  ! scaled relative temperature
    1695             :   real(r8) :: viscosity             ! temperature-specific viscosity (kg/m/s)
    1696             :   real(r8) :: mfp                   ! temperature-specific mean free path (m)
    1697             : 
    1698             :   ! Dimension these according to number of dust bins, inferred from rndst size
    1699           0 :   real(r8) :: nslip(size(rndst,2))  ! slip correction factors
    1700           0 :   real(r8) :: ndfaer(size(rndst,2)) ! aerosol diffusivities (m^2/sec)
    1701             : 
    1702             :   ! Coefficients not used for subcolumns
    1703             :   real(r8) :: dum, dum1, tmp
    1704             : 
    1705             :   ! Common factor between mass and number.
    1706             :   real(r8) :: contact_factor
    1707             : 
    1708             :   integer  :: i, j
    1709             : 
    1710             :   !$acc data present (t,p,rndst,nacon,pgam,lamc) &
    1711             :   !$acc      present (qcic,ncic,relvar,mnucct,nnucct) &
    1712             :   !$acc      create  (nslip,ndfaer)
    1713             : 
    1714             :   !$acc parallel vector_length(VLENS) default(present)
    1715             :   !$acc loop gang vector private(dum,dum1,tcnt,viscosity,mfp,contact_factor,tmp)
    1716           0 :   do i = 1,vlen
    1717           0 :      if (qcic(i) >= qsmall .and. t(i) < 269.15_r8) then
    1718           0 :         if (microp_uniform) then
    1719           0 :            dum  = 1._r8
    1720           0 :            dum1 = 1._r8
    1721             :         else
    1722           0 :            call var_coef(relvar(i), 4._r8/3._r8, dum)
    1723           0 :            call var_coef(relvar(i), 1._r8/3._r8, dum1)
    1724             :         end if
    1725             : 
    1726           0 :         tcnt=(270.16_r8-t(i))**1.3_r8
    1727           0 :         viscosity = 1.8e-5_r8*(t(i)/298.0_r8)**0.85_r8    ! Viscosity (kg/m/s)
    1728             :         mfp = 2.0_r8*viscosity/ &                         ! Mean free path (m)
    1729           0 :                      (p(i)*sqrt( 8.0_r8*28.96e-3_r8/(pi*8.314409_r8*t(i)) ))
    1730             : 
    1731           0 :         do j = 1, mdust
    1732             :            ! Note that these two are vectors.
    1733           0 :            nslip(j) = 1.0_r8+(mfp/rndst(i,j))*(1.257_r8+(0.4_r8*exp(-(1.1_r8*rndst(i,j)/mfp))))! Slip correction factor
    1734             :    
    1735           0 :            ndfaer(j) = 1.381e-23_r8*t(i)*nslip(j)/(6._r8*pi*viscosity*rndst(i,j))  ! aerosol diffusivity (m2/s)
    1736             :         end do
    1737             : 
    1738           0 :         contact_factor = dot_product(ndfaer,nacon(i,:)*tcnt) * pi * &
    1739           0 :                                      ncic(i) * (pgam(i) + 1._r8) / lamc(i)
    1740           0 :         call rising_factorial(pgam(i)+2._r8, 3, tmp)
    1741           0 :         mnucct(i) = dum * contact_factor * pi/3._r8*rhow*tmp/lamc(i)**3
    1742           0 :         nnucct(i) = dum1 * 2._r8 * contact_factor
    1743             :      else
    1744           0 :         mnucct(i) = 0._r8
    1745           0 :         nnucct(i) = 0._r8
    1746             :      end if ! qcic > qsmall and t < 4 deg C
    1747             :   end do
    1748             :   !$acc end parallel
    1749             : 
    1750             :   !$acc end data
    1751           0 : end subroutine contact_freezing
    1752             : 
    1753             : ! snow self-aggregation from passarelli, 1978, used by reisner, 1998
    1754             : !===================================================================
    1755             : ! this is hard-wired for bs = 0.4 for now
    1756             : ! ignore self-collection of cloud ice
    1757             : 
    1758           0 : subroutine snow_self_aggregation(t, rho, asn, rhosn, qsic, nsic, nsagg, vlen)
    1759             : 
    1760             :   integer,                   intent(in) :: vlen
    1761             : 
    1762             :   real(r8), dimension(vlen), intent(in) :: t     ! Temperature
    1763             :   real(r8), dimension(vlen), intent(in) :: rho   ! Density
    1764             :   real(r8), dimension(vlen), intent(in) :: asn   ! fall speed parameter for snow
    1765             :   real(r8),                  intent(in) :: rhosn ! density of snow
    1766             : 
    1767             :   ! In-cloud snow
    1768             :   real(r8), dimension(vlen), intent(in) :: qsic ! MMR
    1769             :   real(r8), dimension(vlen), intent(in) :: nsic ! Number
    1770             : 
    1771             :   ! Output number tendency
    1772             :   real(r8), dimension(vlen), intent(out) :: nsagg
    1773             : 
    1774             :   integer :: i
    1775             : 
    1776             :   !$acc data present (t,rho,asn,qsic,nsic,nsagg)
    1777             : 
    1778             :   !$acc parallel vector_length(VLENS) default(present)
    1779             :   !$acc loop gang vector
    1780           0 :   do i=1,vlen
    1781           0 :      if (qsic(i) >= qsmall .and. t(i) <= tmelt) then
    1782             :         nsagg(i) = -1108._r8*eii/(4._r8*720._r8*rhosn)*asn(i)*qsic(i)*nsic(i)*rho(i)*&
    1783           0 :              ((qsic(i)/nsic(i))*(1._r8/(rhosn*pi)))**((bs-1._r8)/3._r8)
    1784             :      else
    1785           0 :         nsagg(i) = 0._r8
    1786             :      end if
    1787             :   end do
    1788             :   !$acc end parallel
    1789             : 
    1790             :   !$acc end data
    1791           0 : end subroutine snow_self_aggregation
    1792             : 
    1793             : ! ice self-aggregation used in mg4 
    1794             : !===================================================================
    1795             : 
    1796           0 : subroutine ice_self_aggregation(t, rho, rhof, af1pr3, qiic, nsagg, vlen)
    1797             : 
    1798             :   integer,                   intent(in) :: vlen
    1799             : 
    1800             :   real(r8), dimension(vlen), intent(in) :: t        ! Temperature
    1801             :   real(r8), dimension(vlen), intent(in) :: rho      ! Density
    1802             :   real(r8), dimension(vlen), intent(in) :: rhof     ! Density correction
    1803             :   
    1804             :   real(r8), dimension(vlen), intent(in) :: af1pr3   ! process rate 
    1805             : 
    1806             :   ! In-cloud ice
    1807             :   real(r8), dimension(vlen), intent(in) :: qiic ! MMR
    1808             : 
    1809             :   ! Collection efficiency
    1810             :   real(r8), parameter :: eii = 0.1_r8
    1811             : 
    1812             :   ! Output number tendency
    1813             :   real(r8), dimension(vlen), intent(out) :: nsagg
    1814             : 
    1815             :   integer :: i
    1816             : 
    1817             :   !$acc data present (t,rho,rhof,af1pr3,qiic,nsagg)
    1818             : 
    1819             :   !$acc parallel vector_length(VLENS) default(present)
    1820             :   !$acc loop gang vector
    1821           0 :   do i=1,vlen  
    1822           0 :      if (qiic(i) >= qsmall .and. t(i) <= tmelt) then
    1823           0 :         nsagg(i) = af1pr3(i)*rho(i)*eii*rhof(i)
    1824             :      else
    1825           0 :         nsagg(i)=0._r8
    1826             :      end if
    1827             :   end do
    1828             :   !$acc end parallel
    1829             : 
    1830             :   !$acc end data
    1831           0 : end subroutine ice_self_aggregation
    1832             : 
    1833             : ! accretion of cloud droplets onto snow/graupel
    1834             : !===================================================================
    1835             : ! here use continuous collection equation with
    1836             : ! simple gravitational collection kernel
    1837             : ! ignore collisions between droplets/cloud ice
    1838             : ! since minimum size ice particle for accretion is 50 - 150 micron
    1839             : 
    1840           0 : subroutine accrete_cloud_water_snow(t, rho, asn, uns, mu, qcic, ncic, qsic, &
    1841           0 :      pgam, lamc, lams, n0s, psacws, npsacws, vlen)
    1842             : 
    1843             :   integer,                   intent(in) :: vlen
    1844             :   real(r8), dimension(vlen), intent(in) :: t   ! Temperature
    1845             :   real(r8), dimension(vlen), intent(in) :: rho ! Density
    1846             :   real(r8), dimension(vlen), intent(in) :: asn ! Fallspeed parameter (snow)
    1847             :   real(r8), dimension(vlen), intent(in) :: uns ! Current fallspeed   (snow)
    1848             :   real(r8), dimension(vlen), intent(in) :: mu  ! Viscosity
    1849             : 
    1850             :   ! In-cloud liquid water
    1851             :   real(r8), dimension(vlen), intent(in) :: qcic ! MMR
    1852             :   real(r8), dimension(vlen), intent(in) :: ncic ! Number
    1853             : 
    1854             :   ! In-cloud snow
    1855             :   real(r8), dimension(vlen), intent(in) :: qsic ! MMR
    1856             : 
    1857             :   ! Cloud droplet size parameters
    1858             :   real(r8), dimension(vlen), intent(in) :: pgam
    1859             :   real(r8), dimension(vlen), intent(in) :: lamc
    1860             : 
    1861             :   ! Snow size parameters
    1862             :   real(r8), dimension(vlen), intent(in) :: lams
    1863             :   real(r8), dimension(vlen), intent(in) :: n0s
    1864             : 
    1865             :   ! Output tendencies
    1866             :   real(r8), dimension(vlen), intent(out) :: psacws  ! Mass mixing ratio
    1867             :   real(r8), dimension(vlen), intent(out) :: npsacws ! Number concentration
    1868             : 
    1869             :   real(r8) :: dc0 ! Provisional mean droplet size
    1870             :   real(r8) :: dum
    1871             :   real(r8) :: eci ! collection efficiency for riming of snow by droplets
    1872             : 
    1873             :   ! Fraction of cloud droplets accreted per second
    1874             :   real(r8) :: accrete_rate
    1875             :   integer :: i
    1876             : 
    1877             :   ! ignore collision of snow with droplets above freezing
    1878             : 
    1879             :   !$acc data present (t,rho,asn,uns,mu,qcic,ncic,qsic) &
    1880             :   !$acc      present (pgam,lamc,lams,n0s,psacws,npsacws)
    1881             : 
    1882             :   !$acc parallel vector_length(VLENS) default(present)
    1883             :   !$acc loop gang vector private(dc0,dum,eci,accrete_rate)
    1884           0 :   do i=1,vlen
    1885           0 :      if (qsic(i) >= qsmall .and. t(i) <= tmelt .and. qcic(i) >= qsmall) then
    1886             :         ! put in size dependent collection efficiency
    1887             :         ! mean diameter of snow is area-weighted, since
    1888             :         ! accretion is function of crystal geometric area
    1889             :         ! collection efficiency is approximation based on stoke's law (Thompson et al. 2004)
    1890           0 :         dc0 = (pgam(i)+1._r8)/lamc(i)
    1891           0 :         dum = dc0*dc0*uns(i)*rhow*lams(i)/(9._r8*mu(i))
    1892           0 :         eci = dum*dum/((dum+0.4_r8)*(dum+0.4_r8))
    1893           0 :         eci = max(eci,0._r8)
    1894           0 :         eci = min(eci,1._r8)
    1895             : 
    1896             :         ! no impact of sub-grid distribution of qc since psacws
    1897             :         ! is linear in qc
    1898           0 :         accrete_rate = pi/4._r8*asn(i)*rho(i)*n0s(i)*eci*gamma_bs_plus3 / lams(i)**(bs+3._r8)
    1899           0 :         psacws(i)  = accrete_rate*qcic(i)
    1900           0 :         npsacws(i) = accrete_rate*ncic(i)
    1901             :      else
    1902           0 :         psacws(i)  = 0._r8
    1903           0 :         npsacws(i) = 0._r8
    1904             :      end if
    1905             :   end do
    1906             :   !$acc end parallel
    1907             : 
    1908             :   !$acc end data
    1909           0 : end subroutine accrete_cloud_water_snow
    1910             : 
    1911             : ! Version used in MG4
    1912           0 : subroutine accrete_cloud_water_ice(t, rho, rhof, af1pr4, qcic, ncic, qiic, psacws, npsacws, vlen)
    1913             : 
    1914             :   integer,                   intent(in) :: vlen
    1915             :   real(r8), dimension(vlen), intent(in) :: t        ! Temperature
    1916             :   real(r8), dimension(vlen), intent(in) :: rho      ! Density
    1917             :   real(r8), dimension(vlen), intent(in) :: rhof     ! Density correction factor 
    1918             :   real(r8), dimension(vlen), intent(in) :: af1pr4   ! Process rate from look-up table
    1919             :   ! In-cloud liquid water
    1920             :   real(r8), dimension(vlen), intent(in) :: qcic     ! MMR
    1921             :   real(r8), dimension(vlen), intent(in) :: ncic     ! Number
    1922             :   ! In-cloud ice
    1923             :   real(r8), dimension(vlen), intent(in) :: qiic     ! MMR
    1924             :   ! Output tendencies
    1925             :   real(r8), dimension(vlen), intent(out) :: psacws  ! Mass mixing ratio
    1926             :   real(r8), dimension(vlen), intent(out) :: npsacws ! Number concentration
    1927             : 
    1928             :   real(r8) :: eci     ! collection efficiency for riming of snow by droplets
    1929             :   integer  :: i
    1930             : 
    1931             :   ! ignore collision of snow with droplets above freezing
    1932           0 :   eci = 0.5_r8 ! from p3 program
    1933             :  
    1934             :   !$acc data present (t,rho,rhof,af1pr4,qcic) &
    1935             :   !$acc      present (ncic,qiic,psacws,npsacws)
    1936             : 
    1937             :   !$acc parallel vector_length(VLENS) default(present)
    1938             :   !$acc loop gang vector
    1939           0 :   do i=1,vlen
    1940           0 :      if (qiic(i) >= qsmall .and. t(i) <= tmelt .and. qcic(i) >= qsmall) then
    1941           0 :          psacws(i)  = rhof(i)*af1pr4(i)*qcic(i)*eci*rho(i)
    1942           0 :          npsacws(i) = rhof(i)*af1pr4(i)*ncic(i)*eci*rho(i)
    1943             :      else
    1944           0 :          psacws(i)  = 0._r8
    1945           0 :          npsacws(i) = 0._r8
    1946             :      end if
    1947             :   end do
    1948             :   !$acc end parallel
    1949             : 
    1950             :   !$acc end data
    1951           0 : end subroutine accrete_cloud_water_ice
    1952             : 
    1953             : ! add secondary ice production due to accretion of droplets by snow
    1954             : !===================================================================
    1955             : ! (Hallet-Mossop process) (from Cotton et al., 1986)
    1956             : 
    1957           0 : subroutine secondary_ice_production(t, psacws, msacwi, nsacwi, vlen)
    1958             : 
    1959             :   integer,                   intent(in) :: vlen
    1960             :   real(r8), dimension(vlen), intent(in) :: t ! Temperature
    1961             : 
    1962             :   ! Accretion of cloud water to snow tendencies
    1963             :   real(r8), dimension(vlen), intent(inout) :: psacws ! MMR
    1964             : 
    1965             :   ! Output (ice) tendencies
    1966             :   real(r8), dimension(vlen), intent(out) :: msacwi ! MMR
    1967             :   real(r8), dimension(vlen), intent(out) :: nsacwi ! Number
    1968             :   integer :: i
    1969             : 
    1970             :   !$acc data present (t,psacws,msacwi,nsacwi)
    1971             : 
    1972             :   !$acc parallel vector_length(VLENS) default(present)
    1973             :   !$acc loop gang vector
    1974           0 :   do i=1,vlen
    1975           0 :      if((t(i) < 270.16_r8) .and. (t(i) >= 268.16_r8)) then
    1976           0 :         nsacwi(i) = 3.5e8_r8*(270.16_r8-t(i))/2.0_r8*psacws(i)
    1977           0 :      else if((t(i) < 268.16_r8) .and. (t(i) >= 265.16_r8)) then
    1978           0 :         nsacwi(i) = 3.5e8_r8*(t(i)-265.16_r8)/3.0_r8*psacws(i)
    1979             :      else
    1980           0 :         nsacwi(i) = 0.0_r8
    1981             :      endif
    1982             :   end do
    1983             : 
    1984             :   !$acc loop gang vector
    1985           0 :   do i=1,vlen
    1986           0 :      msacwi(i) = min(nsacwi(i)*mi0, psacws(i))
    1987           0 :      psacws(i) = psacws(i) - msacwi(i)
    1988             :   end do
    1989             :   !$acc end parallel
    1990             : 
    1991             :   !$acc end data
    1992           0 : end subroutine secondary_ice_production
    1993             : 
    1994             : ! accretion of rain water by snow
    1995             : !===================================================================
    1996             : ! formula from ikawa and saito, 1991, used by reisner et al., 1998
    1997             : 
    1998           0 : subroutine accrete_rain_snow(t, rho, umr, ums, unr, uns, qric, qsic, &
    1999           0 :      lamr, n0r, lams, n0s, pracs, npracs, vlen)
    2000             : 
    2001             :   integer,                   intent(in) :: vlen
    2002             :   real(r8), dimension(vlen), intent(in) :: t   ! Temperature
    2003             :   real(r8), dimension(vlen), intent(in) :: rho ! Density
    2004             :   ! Fallspeeds
    2005             :   ! mass-weighted
    2006             :   real(r8), dimension(vlen), intent(in) :: umr ! rain
    2007             :   real(r8), dimension(vlen), intent(in) :: ums ! snow
    2008             :   ! number-weighted
    2009             :   real(r8), dimension(vlen), intent(in) :: unr ! rain
    2010             :   real(r8), dimension(vlen), intent(in) :: uns ! snow
    2011             :   ! In cloud MMRs
    2012             :   real(r8), dimension(vlen), intent(in) :: qric ! rain
    2013             :   real(r8), dimension(vlen), intent(in) :: qsic ! snow
    2014             :   ! Size distribution parameters
    2015             :   ! rain
    2016             :   real(r8), dimension(vlen), intent(in) :: lamr
    2017             :   real(r8), dimension(vlen), intent(in) :: n0r
    2018             :   ! snow
    2019             :   real(r8), dimension(vlen), intent(in) :: lams
    2020             :   real(r8), dimension(vlen), intent(in) :: n0s
    2021             :   ! Output tendencies
    2022             :   real(r8), dimension(vlen), intent(out) :: pracs  ! MMR
    2023             :   real(r8), dimension(vlen), intent(out) :: npracs ! Number
    2024             :   ! Collection efficiency for accretion of rain by snow
    2025             :   real(r8), parameter :: ecr = 1.0_r8
    2026             :   ! Ratio of average snow diameter to average rain diameter.
    2027             :   real(r8) :: d_rat
    2028             :   ! Common factor between mass and number expressions
    2029             :   real(r8) :: common_factor
    2030             :   integer  :: i
    2031             : 
    2032             :   !$acc data present (t,rho,umr,ums,unr,uns,qric,qsic) &
    2033             :   !$acc      present (lamr,n0r,lams,n0s,pracs,npracs)
    2034             : 
    2035             :   !$acc parallel vector_length(VLENS) default(present)
    2036             :   !$acc loop gang vector private(common_factor,d_rat)
    2037           0 :   do i=1,vlen
    2038           0 :      if (qric(i) >= icsmall .and. qsic(i) >= icsmall .and. t(i) <= tmelt) then
    2039           0 :         common_factor = pi*ecr*rho(i)*n0r(i)*n0s(i)/(lamr(i)**3 * lams(i))
    2040           0 :         d_rat = lamr(i)/lams(i)
    2041             :         pracs(i) = common_factor*pi*rhow* &
    2042             :              sqrt((1.2_r8*umr(i)-0.95_r8*ums(i))**2 + 0.08_r8*ums(i)*umr(i)) / lamr(i)**3 * &
    2043           0 :              ((0.5_r8*d_rat + 2._r8)*d_rat + 5._r8)
    2044             :         npracs(i) = common_factor*0.5_r8* &
    2045             :              sqrt(1.7_r8*(unr(i)-uns(i))**2 + 0.3_r8*unr(i)*uns(i)) * &
    2046           0 :              ((d_rat + 1._r8)*d_rat + 1._r8)
    2047             :      else
    2048           0 :         pracs(i) = 0._r8
    2049           0 :         npracs(i) = 0._r8
    2050             :      end if
    2051             :   end do
    2052             :   !$acc end parallel
    2053             : 
    2054             :   !$acc end data
    2055           0 : end subroutine accrete_rain_snow
    2056             : 
    2057             : ! Version used in MG4
    2058           0 : subroutine accrete_rain_ice(t, rho, rhof, af1pr8, af1pr7, qric, qiic, &
    2059           0 :       n0r, pracs, npracs, vlen )
    2060             : 
    2061             :   integer,                   intent(in) :: vlen
    2062             :   real(r8), dimension(vlen), intent(in) :: rhof ! Density correction factor 
    2063             :   real(r8), dimension(vlen), intent(in) :: rho  ! Density
    2064             :   real(r8), dimension(vlen), intent(in) :: t    ! Temperature
    2065             :   ! In cloud MMRs
    2066             :   real(r8), dimension(vlen), intent(in) :: qric ! rain
    2067             :   real(r8), dimension(vlen), intent(in) :: qiic ! combined snow and ice
    2068             :   ! Size distribution parameters
    2069             :   ! rain
    2070             :   real(r8), dimension(vlen), intent(in) :: n0r
    2071             :   ! Processrates 
    2072             :   real(r8), dimension(vlen), intent(in) :: af1pr8  
    2073             :   real(r8), dimension(vlen), intent(in) :: af1pr7  
    2074             :   ! Output tendencies
    2075             :   real(r8), dimension(vlen), intent(out) :: pracs  ! MMR
    2076             :   real(r8), dimension(vlen), intent(out) :: npracs ! Number
    2077             :   ! Collection efficiency for accretion of rain by snow
    2078             :   real(r8), parameter :: ecr = 1.0_r8
    2079             :   integer :: i
    2080             : 
    2081             :   !$acc data present (t,rho,rhof,qric,qiic,n0r) &
    2082             :   !$acc      present (af1pr8,af1pr7,pracs,npracs)
    2083             : 
    2084             :   !$acc parallel vector_length(VLENS) default(present)
    2085             :   !$acc loop gang vector
    2086           0 :   do i=1,vlen
    2087           0 :      if (qric(i) >= icsmall .and. qiic(i) >= icsmall .and. t(i) <= tmelt) then
    2088           0 :         pracs(i)  = 10._r8**(af1pr8(i)+dlog10(n0r(i)))*rho(i)*rhof(i)*ecr
    2089           0 :         npracs(i) = 10._r8**(af1pr7(i)+dlog10(n0r(i)))*rho(i)*rhof(i)*ecr
    2090             :      else
    2091           0 :         pracs(i)  = 0._r8
    2092           0 :         npracs(i) = 0._r8
    2093             :      end if
    2094             :   end do
    2095             :   !$acc end parallel
    2096             : 
    2097             :   !$acc end data
    2098           0 : end subroutine accrete_rain_ice
    2099             : 
    2100             : ! heterogeneous freezing of rain drops
    2101             : !===================================================================
    2102             : ! follows from Bigg (1953)
    2103             : 
    2104           0 : subroutine heterogeneous_rain_freezing(t, qric, nric, lamr, mnuccr, nnuccr, vlen)
    2105             : 
    2106             :   integer,                   intent(in) :: vlen
    2107             :   real(r8), dimension(vlen), intent(in) :: t    ! Temperature
    2108             :   ! In-cloud rain
    2109             :   real(r8), dimension(vlen), intent(in) :: qric ! MMR
    2110             :   real(r8), dimension(vlen), intent(in) :: nric ! Number
    2111             :   real(r8), dimension(vlen), intent(in) :: lamr ! size parameter
    2112             :   ! Output tendencies
    2113             :   real(r8), dimension(vlen), intent(out) :: mnuccr ! MMR
    2114             :   real(r8), dimension(vlen), intent(out) :: nnuccr ! Number
    2115             :   integer :: i
    2116             : 
    2117             :   !$acc data present (t,qric,nric,lamr,mnuccr,nnuccr)
    2118             : 
    2119             :   !$acc parallel vector_length(VLENS) default(present)
    2120             :   !$acc loop gang vector
    2121           0 :   do i=1,vlen
    2122           0 :      if (t(i) < 269.15_r8 .and. qric(i) >= qsmall) then
    2123             :         nnuccr(i) = pi*nric(i)*bimm* &
    2124           0 :              (exp(aimm*(tmelt - t(i)))-1._r8)/lamr(i)**3
    2125           0 :         mnuccr(i) = nnuccr(i) * 20._r8*pi*rhow/lamr(i)**3
    2126             :      else
    2127           0 :         mnuccr(i) = 0._r8
    2128           0 :         nnuccr(i) = 0._r8
    2129             :      end if
    2130             :   end do
    2131             :   !$acc end parallel
    2132             : 
    2133             :   !$acc end data
    2134           0 : end subroutine heterogeneous_rain_freezing
    2135             : 
    2136             : ! accretion of cloud liquid water by rain
    2137             : !===================================================================
    2138             : ! formula from Khrouditnov and Kogan (2000)
    2139             : ! gravitational collection kernel, droplet fall speed neglected
    2140             : 
    2141           0 : subroutine accrete_cloud_water_rain(microp_uniform, qric, qcic, &
    2142           0 :      ncic, relvar, accre_enhan, pra, npra, vlen)
    2143             : 
    2144             :   logical, intent(in) :: microp_uniform
    2145             :   integer, intent(in) :: vlen
    2146             :   ! In-cloud rain
    2147             :   real(r8), dimension(vlen), intent(in) :: qric ! MMR
    2148             :   ! Cloud droplets
    2149             :   real(r8), dimension(vlen), intent(in) :: qcic ! MMR
    2150             :   real(r8), dimension(vlen), intent(in) :: ncic ! Number
    2151             :   ! SGS variability
    2152             :   real(r8), dimension(vlen), intent(in) :: relvar
    2153             :   real(r8), dimension(vlen), intent(in) :: accre_enhan
    2154             :   ! Output tendencies
    2155             :   real(r8), dimension(vlen), intent(out) :: pra  ! MMR
    2156             :   real(r8), dimension(vlen), intent(out) :: npra ! Number
    2157             :   ! Coefficient that varies for subcolumns
    2158           0 :   real(r8), dimension(vlen) :: pra_coef
    2159             :   integer :: i
    2160             : 
    2161             :   !$acc data present (qric,qcic,ncic,relvar,accre_enhan,pra,npra) &
    2162             :   !$acc      create  (pra_coef)
    2163             : 
    2164           0 :   if (.not. microp_uniform) then
    2165           0 :      call var_coef(relvar, 1.15_r8, pra_coef, vlen)
    2166             :      !$acc parallel vector_length(VLENS) default(present)
    2167             :      !$acc loop gang vector
    2168           0 :      do i = 1, vlen
    2169           0 :         pra_coef(i) = accre_enhan(i) * pra_coef(i)
    2170             :      end do
    2171             :      !$acc end parallel
    2172             :   else
    2173             :      !$acc parallel vector_length(VLENS) default(present)
    2174             :      !$acc loop gang vector
    2175           0 :      do i = 1, vlen
    2176           0 :         pra_coef(i) = 1._r8
    2177             :      end do
    2178             :      !$acc end parallel
    2179             :   end if
    2180             : 
    2181             :   !$acc parallel vector_length(VLENS) default(present)
    2182             :   !$acc loop gang vector
    2183           0 :   do i=1,vlen
    2184           0 :      if (qric(i) >= qsmall .and. qcic(i) >= qsmall) then
    2185             :         ! include sub-grid distribution of cloud water
    2186           0 :         pra(i)  = pra_coef(i) * 67._r8*(qcic(i)*qric(i))**1.15_r8
    2187           0 :         npra(i) = pra(i)*ncic(i)/qcic(i)
    2188             :      else
    2189           0 :         pra(i)  = 0._r8
    2190           0 :         npra(i) = 0._r8
    2191             :      end if
    2192             :   end do
    2193             :   !$acc end parallel
    2194             : 
    2195             :   !$acc end data
    2196           0 : end subroutine accrete_cloud_water_rain
    2197             : 
    2198             : ! Self-collection of rain drops
    2199             : !===================================================================
    2200             : ! from Beheng(1994)
    2201             : 
    2202           0 : subroutine self_collection_rain(rho, qric, nric, nragg, vlen)
    2203             : 
    2204             :   integer,                   intent(in) :: vlen
    2205             :   real(r8), dimension(vlen), intent(in) :: rho  ! Air density
    2206             :   ! Rain
    2207             :   real(r8), dimension(vlen), intent(in) :: qric ! MMR
    2208             :   real(r8), dimension(vlen), intent(in) :: nric ! Number
    2209             :   ! Output number tendency
    2210             :   real(r8), dimension(vlen), intent(out) :: nragg
    2211             :   integer :: i
    2212             : 
    2213             :   !$acc data present (rho,qric,nric,nragg)
    2214             : 
    2215             :   !$acc parallel vector_length(VLENS) default(present)
    2216             :   !$acc loop gang vector
    2217           0 :   do i=1,vlen
    2218           0 :      if (qric(i) >= qsmall) then
    2219           0 :         nragg(i) = -8._r8*nric(i)*qric(i)*rho(i)
    2220             :      else
    2221           0 :         nragg(i) = 0._r8
    2222             :      end if
    2223             :   end do
    2224             :   !$acc end parallel
    2225             : 
    2226             :   !$acc end data
    2227           0 : end subroutine self_collection_rain
    2228             : 
    2229             : ! Accretion of cloud ice by snow
    2230             : !===================================================================
    2231             : ! For this calculation, it is assumed that the Vs >> Vi
    2232             : ! and Ds >> Di for continuous collection
    2233             : 
    2234           0 : subroutine accrete_cloud_ice_snow(t, rho, asn, qiic, niic, qsic, &
    2235           0 :      lams, n0s, prai, nprai, vlen)
    2236             : 
    2237             :   integer,                   intent(in) :: vlen
    2238             :   real(r8), dimension(vlen), intent(in) :: t    ! Temperature
    2239             :   real(r8), dimension(vlen), intent(in) :: rho   ! Density
    2240             :   real(r8), dimension(vlen), intent(in) :: asn  ! Snow fallspeed parameter
    2241             :   ! Cloud ice
    2242             :   real(r8), dimension(vlen), intent(in) :: qiic ! MMR
    2243             :   real(r8), dimension(vlen), intent(in) :: niic ! Number
    2244             :   real(r8), dimension(vlen), intent(in) :: qsic ! Snow MMR
    2245             :   ! Snow size parameters
    2246             :   real(r8), dimension(vlen), intent(in) :: lams
    2247             :   real(r8), dimension(vlen), intent(in) :: n0s
    2248             :   ! Output tendencies
    2249             :   real(r8), dimension(vlen), intent(out) :: prai ! MMR
    2250             :   real(r8), dimension(vlen), intent(out) :: nprai ! Number
    2251             :   ! Fraction of cloud ice particles accreted per second
    2252             :   real(r8) :: accrete_rate
    2253             :   integer  :: i
    2254             : 
    2255             :   !$acc data present (t,rho,asn,qiic,niic,qsic,lams,n0s,prai,nprai)
    2256             : 
    2257             :   !$acc parallel vector_length(VLENS) default(present)
    2258             :   !$acc loop gang vector private(accrete_rate)
    2259           0 :   do i=1,vlen
    2260           0 :      if (qsic(i) >= qsmall .and. qiic(i) >= qsmall .and. t(i) <= tmelt) then
    2261             :         accrete_rate = pi/4._r8 * eii * asn(i) * rho(i) * n0s(i) * gamma_bs_plus3/ &
    2262           0 :              lams(i)**(bs+3._r8)
    2263           0 :         prai(i)  = accrete_rate * qiic(i)
    2264           0 :         nprai(i) = accrete_rate * niic(i)
    2265             :      else
    2266           0 :         prai(i)  = 0._r8
    2267           0 :         nprai(i) = 0._r8
    2268             :      end if
    2269             :   end do
    2270             :   !$acc end parallel
    2271             : 
    2272             :   !$acc end data
    2273           0 : end subroutine accrete_cloud_ice_snow
    2274             : 
    2275             : ! calculate evaporation/sublimation of rain and snow
    2276             : !===================================================================
    2277             : ! note: evaporation/sublimation occurs only in cloud-free portion of grid cell
    2278             : ! in-cloud condensation/deposition of rain and snow is neglected
    2279             : ! except for transfer of cloud water to snow through bergeron process
    2280             : 
    2281           0 : subroutine evaporate_sublimate_precip(t, rho, dv, mu, sc, q, qvl, qvi, &
    2282           0 :      lcldm, precip_frac, arn, asn, qcic, qiic, qric, qsic, lamr, n0r, lams, n0s, &
    2283           0 :      pre, prds, am_evp_st, vlen, evap_rhthrsh)
    2284             : 
    2285             :   integer,                   intent(in) :: vlen
    2286             :   real(r8), dimension(vlen), intent(in) :: t           ! temperature
    2287             :   real(r8), dimension(vlen), intent(in) :: rho         ! air density
    2288             :   real(r8), dimension(vlen), intent(in) :: dv          ! water vapor diffusivity
    2289             :   real(r8), dimension(vlen), intent(in) :: mu          ! viscosity
    2290             :   real(r8), dimension(vlen), intent(in) :: sc          ! schmidt number
    2291             :   real(r8), dimension(vlen), intent(in) :: q           ! humidity
    2292             :   real(r8), dimension(vlen), intent(in) :: qvl         ! saturation humidity (water)
    2293             :   real(r8), dimension(vlen), intent(in) :: qvi         ! saturation humidity (ice)
    2294             :   real(r8), dimension(vlen), intent(in) :: lcldm       ! liquid cloud fraction
    2295             :   real(r8), dimension(vlen), intent(in) :: precip_frac ! precipitation fraction (maximum overlap)
    2296             :   ! fallspeed parameters
    2297             :   real(r8), dimension(vlen), intent(in) :: arn         ! rain
    2298             :   real(r8), dimension(vlen), intent(in) :: asn         ! snow
    2299             :   ! In-cloud MMRs
    2300             :   real(r8), dimension(vlen), intent(in) :: qcic        ! cloud liquid
    2301             :   real(r8), dimension(vlen), intent(in) :: qiic        ! cloud ice
    2302             :   real(r8), dimension(vlen), intent(in) :: qric        ! rain
    2303             :   real(r8), dimension(vlen), intent(in) :: qsic        ! snow
    2304             :   ! Size parameters
    2305             :   ! rain
    2306             :   real(r8), dimension(vlen), intent(in) :: lamr
    2307             :   real(r8), dimension(vlen), intent(in) :: n0r
    2308             :   ! snow
    2309             :   real(r8), dimension(vlen), intent(in) :: lams
    2310             :   real(r8), dimension(vlen), intent(in) :: n0s
    2311             :   ! Output tendencies
    2312             :   real(r8), dimension(vlen), intent(out) :: pre
    2313             :   real(r8), dimension(vlen), intent(out) :: prds
    2314             :   real(r8), dimension(vlen), intent(out) :: am_evp_st  ! Fractional area where rain evaporates.
    2315             :   ! Switch
    2316             :   logical, intent(in)                    :: evap_rhthrsh 
    2317             : 
    2318             :   real(r8) :: qclr   ! water vapor mixing ratio in clear air
    2319             :   real(r8) :: ab,abr ! correction to account for latent heat
    2320             :   real(r8) :: eps    ! 1/ sat relaxation timescale
    2321           0 :   real(r8), dimension(vlen) :: dum
    2322             :   integer :: i
    2323             : 
    2324             :   !$acc data present (t,rho,dv,mu,sc,q,qvl,qvi,lcldm,precip_frac,arn,asn) &
    2325             :   !$acc      present (qcic,qiic,qric,qsic,lamr,n0r,lams,n0s,pre,prds,am_evp_st) &
    2326             :   !$acc      create  (dum)
    2327             : 
    2328             :   ! set temporary cloud fraction to zero if cloud water + ice is very small
    2329             :   ! this will ensure that evaporation/sublimation of precip occurs over
    2330             :   ! entire grid cell, since min cloud fraction is specified otherwise
    2331             : 
    2332             :   !$acc parallel vector_length(VLENS) default(present)
    2333             :   !$acc loop gang vector
    2334           0 :   do i=1,vlen
    2335           0 :      am_evp_st(i) = 0._r8
    2336           0 :      if (qcic(i)+qiic(i) < 1.e-6_r8) then
    2337           0 :         dum(i) = 0._r8
    2338             :      else
    2339           0 :         dum(i) = lcldm(i)
    2340             :      end if
    2341             :   end do
    2342             : 
    2343             :   !$acc loop gang vector private(qclr,eps,abr,ab)
    2344           0 :   do i=1,vlen
    2345             :      ! only calculate if there is some precip fraction > cloud fraction
    2346           0 :      if (precip_frac(i) > dum(i)) then
    2347           0 :         if (qric(i) >= qsmall .or. qsic(i) >= qsmall) then
    2348           0 :            am_evp_st(i) = precip_frac(i) - dum(i)
    2349             :            ! calculate q for out-of-cloud region
    2350           0 :            qclr=(q(i)-dum(i)*qvl(i))/(1._r8-dum(i))
    2351             :         end if
    2352             : 
    2353             :         ! evaporation of rain
    2354           0 :         if (qric(i) >= qsmall) then
    2355           0 :            if (.not.evap_rhthrsh.or.(evap_rhthrsh.and.qclr/qvl(i).le.0.9_r8)) then
    2356           0 :               call calc_ab(t(i), qvl(i), xxlv, abr)
    2357             :               eps = 2._r8*pi*n0r(i)*rho(i)*Dv(i)* &
    2358             :                     (f1r/(lamr(i)*lamr(i))+ &
    2359             :                     f2r*(arn(i)*rho(i)/mu(i))**0.5_r8* &
    2360             :                     sc(i)**(1._r8/3._r8)*gamma_half_br_plus5/ &
    2361           0 :                     (lamr(i)**(5._r8/2._r8+br/2._r8)))
    2362           0 :               pre(i) = eps*(qclr-qvl(i))/abr
    2363             :               ! only evaporate in out-of-cloud region
    2364             :               ! and distribute across precip_frac
    2365           0 :               pre(i)=min(pre(i)*am_evp_st(i),0._r8)
    2366           0 :               pre(i)=pre(i)/precip_frac(i)
    2367             :            else
    2368           0 :               pre(i) = 0._r8
    2369             :            end if
    2370             :         else
    2371           0 :            pre(i) = 0._r8
    2372             :         end if
    2373             : 
    2374             :         ! sublimation of snow
    2375           0 :         if (qsic(i) >= qsmall) then
    2376           0 :            call calc_ab(t(i), qvi(i), xxls, ab)
    2377             :            eps = 2._r8*pi*n0s(i)*rho(i)*Dv(i)* &
    2378             :                 (f1s/(lams(i)*lams(i))+ &
    2379             :                 f2s*(asn(i)*rho(i)/mu(i))**0.5_r8* &
    2380             :                 sc(i)**(1._r8/3._r8)*gamma_half_bs_plus5/ &
    2381           0 :                 (lams(i)**(5._r8/2._r8+bs/2._r8)))
    2382           0 :            prds(i) = eps*(qclr-qvi(i))/ab
    2383             :            ! only sublimate in out-of-cloud region and distribute over precip_frac
    2384           0 :            prds(i) = min(prds(i)*am_evp_st(i),0._r8)
    2385           0 :            prds(i) = prds(i)/precip_frac(i)
    2386             :         else
    2387           0 :            prds(i) = 0._r8
    2388             :         end if
    2389             :      else
    2390           0 :         prds(i) = 0._r8
    2391           0 :         pre(i)  = 0._r8
    2392             :      end if
    2393             :   end do
    2394             :   !$acc end parallel
    2395             : 
    2396             :   !$acc end data
    2397           0 : end subroutine evaporate_sublimate_precip
    2398             : 
    2399             : ! calculate evaporation/sublimation of rain (no snow in mg4)
    2400             : !===================================================================
    2401             : ! note: evaporation/sublimation occurs only in cloud-free portion of grid cell
    2402             : ! in-cloud condensation/deposition of rain and snow is neglected
    2403             : ! except for transfer of cloud water to snow through bergeron process
    2404             : 
    2405           0 : subroutine evaporate_sublimate_precip_mg4(t, rho, dv, mu, sc, q, qvl, qvi, &
    2406           0 :      lcldm, precip_frac, arn, qcic, qiic, qric, lamr, n0r, &
    2407           0 :      pre, am_evp_st, vlen, evap_rhthrsh)
    2408             : 
    2409             :   integer,  intent(in)                   :: vlen
    2410             :   real(r8), dimension(vlen), intent(in)  :: t           ! temperature
    2411             :   real(r8), dimension(vlen), intent(in)  :: rho         ! air density
    2412             :   real(r8), dimension(vlen), intent(in)  :: dv          ! water vapor diffusivity
    2413             :   real(r8), dimension(vlen), intent(in)  :: mu          ! viscosity
    2414             :   real(r8), dimension(vlen), intent(in)  :: sc          ! schmidt number
    2415             :   real(r8), dimension(vlen), intent(in)  :: q           ! humidity
    2416             :   real(r8), dimension(vlen), intent(in)  :: qvl         ! saturation humidity (water)
    2417             :   real(r8), dimension(vlen), intent(in)  :: qvi         ! saturation humidity (ice)
    2418             :   real(r8), dimension(vlen), intent(in)  :: lcldm       ! liquid cloud fraction
    2419             :   real(r8), dimension(vlen), intent(in)  :: precip_frac ! precipitation fraction (maximum overlap)
    2420             :   ! fallspeed parameters
    2421             :   real(r8), dimension(vlen), intent(in)  :: arn         ! rain
    2422             :   ! In-cloud MMRs
    2423             :   real(r8), dimension(vlen), intent(in)  :: qcic        ! cloud liquid
    2424             :   real(r8), dimension(vlen), intent(in)  :: qiic        ! cloud ice
    2425             :   real(r8), dimension(vlen), intent(in)  :: qric        ! rain
    2426             :   ! Size parameters
    2427             :   ! rain
    2428             :   real(r8), dimension(vlen), intent(in)  :: lamr
    2429             :   real(r8), dimension(vlen), intent(in)  :: n0r
    2430             :   ! Output tendencies
    2431             :   real(r8), dimension(vlen), intent(out) :: pre
    2432             :   real(r8), dimension(vlen), intent(out) :: am_evp_st   ! Fractional area where rain evaporates.
    2433             :   ! Switch
    2434             :   logical, intent(in)                    :: evap_rhthrsh 
    2435             :   real(r8) :: qclr   ! water vapor mixing ratio in clear air
    2436             :   real(r8) :: abr    ! correction to account for latent heat
    2437             :   real(r8) :: eps    ! 1/ sat relaxation timescale
    2438           0 :   real(r8), dimension(vlen) :: dum
    2439             :   integer :: i
    2440             : 
    2441             :   !$acc data present (t,rho,dv,mu,sc,q,qvl,qvi,lcldm,precip_frac,arn) &
    2442             :   !$acc      present (qcic,qiic,qric,lamr,n0r,pre,am_evp_st) &
    2443             :   !$acc      create  (dum)
    2444             : 
    2445             :   ! set temporary cloud fraction to zero if cloud water + ice is very small
    2446             :   ! this will ensure that evaporation/sublimation of precip occurs over
    2447             :   ! entire grid cell, since min cloud fraction is specified otherwise
    2448             : 
    2449             :   !$acc parallel vector_length(VLENS) default(present)
    2450             :   !$acc loop gang vector
    2451           0 :   do i=1,vlen
    2452           0 :      am_evp_st(i) = 0._r8
    2453           0 :      if (qcic(i)+qiic(i) < 1.e-6_r8) then
    2454           0 :         dum(i) = 0._r8
    2455             :      else
    2456           0 :         dum(i) = lcldm(i)
    2457             :      end if
    2458             :   end do
    2459             : 
    2460             :   !$acc loop gang vector private(qclr,eps,abr)
    2461           0 :   do i=1,vlen
    2462             :      ! only calculate if there is some precip fraction > cloud fraction
    2463           0 :      if (precip_frac(i) > dum(i)) then
    2464           0 :         if (qric(i) >= qsmall) then
    2465           0 :            am_evp_st(i) = precip_frac(i) - dum(i)
    2466             :            ! calculate q for out-of-cloud region
    2467           0 :            qclr=(q(i)-dum(i)*qvl(i))/(1._r8-dum(i))
    2468             :         end if
    2469             : 
    2470             :         ! evaporation of rain
    2471           0 :         if (qric(i) >= qsmall) then
    2472           0 :            if (.not.evap_rhthrsh.or.(evap_rhthrsh.and.qclr/qvl(i).le.0.9_r8)) then
    2473           0 :               call calc_ab(t(i), qvl(i), xxlv, abr)
    2474             :               eps = 2._r8*pi*n0r(i)*rho(i)*Dv(i)* &
    2475             :                  (f1r/(lamr(i)*lamr(i))+ &
    2476             :                  f2r*(arn(i)*rho(i)/mu(i))**0.5_r8* &
    2477             :                  sc(i)**(1._r8/3._r8)*gamma_half_br_plus5/ &
    2478           0 :                  (lamr(i)**(5._r8/2._r8+br/2._r8)))
    2479           0 :               pre(i) = eps*(qclr-qvl(i))/abr
    2480             :               ! only evaporate in out-of-cloud region
    2481             :               ! and distribute across precip_frac
    2482           0 :               pre(i) = min(pre(i)*am_evp_st(i),0._r8)
    2483           0 :               pre(i) = pre(i)/precip_frac(i)
    2484             :            else
    2485           0 :               pre(i) = 0._r8
    2486             :            end if
    2487             :         else
    2488           0 :            pre(i) = 0._r8
    2489             :         end if
    2490             :      else
    2491           0 :         pre(i) = 0._r8
    2492             :      end if
    2493             :   end do
    2494             :   !$acc end parallel
    2495             : 
    2496             :   !$acc end data
    2497           0 : end subroutine evaporate_sublimate_precip_mg4
    2498             : 
    2499             : ! evaporation/sublimation of rain, snow and graupel
    2500             : !===================================================================
    2501             : ! note: evaporation/sublimation occurs only in cloud-free portion of grid cell
    2502             : ! in-cloud condensation/deposition of rain and snow is neglected
    2503             : ! except for transfer of cloud water to snow through bergeron process
    2504             : 
    2505           0 : subroutine evaporate_sublimate_precip_graupel(t, rho, dv, mu, sc, q, qvl, qvi, &
    2506           0 :      lcldm, precip_frac, arn, asn, agn, bg, qcic, qiic, qric, qsic, qgic, lamr, n0r, lams, n0s, lamg, n0g, &
    2507           0 :      pre, prds, prdg, am_evp_st, vlen, evap_rhthrsh)
    2508             : 
    2509             :   integer,                   intent(in)  :: vlen
    2510             :   real(r8), dimension(vlen), intent(in)  :: t           ! temperature
    2511             :   real(r8), dimension(vlen), intent(in)  :: rho         ! air density
    2512             :   real(r8), dimension(vlen), intent(in)  :: dv          ! water vapor diffusivity
    2513             :   real(r8), dimension(vlen), intent(in)  :: mu          ! viscosity
    2514             :   real(r8), dimension(vlen), intent(in)  :: sc          ! schmidt number
    2515             :   real(r8), dimension(vlen), intent(in)  :: q           ! humidity
    2516             :   real(r8), dimension(vlen), intent(in)  :: qvl         ! saturation humidity (water)
    2517             :   real(r8), dimension(vlen), intent(in)  :: qvi         ! saturation humidity (ice)
    2518             :   real(r8), dimension(vlen), intent(in)  :: lcldm       ! liquid cloud fraction
    2519             :   real(r8), dimension(vlen), intent(in)  :: precip_frac ! precipitation fraction (maximum overlap)
    2520             :   ! fallspeed parameters
    2521             :   real(r8), dimension(vlen), intent(in)  :: arn         ! rain
    2522             :   real(r8), dimension(vlen), intent(in)  :: asn         ! snow
    2523             :   real(r8), dimension(vlen), intent(in)  :: agn         ! graupel
    2524             :   real(r8),                  intent(in)  :: bg 
    2525             :   ! In-cloud MMRs
    2526             :   real(r8), dimension(vlen), intent(in)  :: qcic        ! cloud liquid
    2527             :   real(r8), dimension(vlen), intent(in)  :: qiic        ! cloud ice
    2528             :   real(r8), dimension(vlen), intent(in)  :: qric        ! rain
    2529             :   real(r8), dimension(vlen), intent(in)  :: qsic        ! snow
    2530             :   real(r8), dimension(vlen), intent(in)  :: qgic        ! graupel
    2531             :   ! Size parameters
    2532             :   ! rain
    2533             :   real(r8), dimension(vlen), intent(in)  :: lamr
    2534             :   real(r8), dimension(vlen), intent(in)  :: n0r
    2535             :   ! snow
    2536             :   real(r8), dimension(vlen), intent(in)  :: lams
    2537             :   real(r8), dimension(vlen), intent(in)  :: n0s
    2538             :   ! graupel
    2539             :   real(r8), dimension(vlen), intent(in)  :: lamg
    2540             :   real(r8), dimension(vlen), intent(in)  :: n0g
    2541             :   ! Output tendencies
    2542             :   real(r8), dimension(vlen), intent(out) :: pre
    2543             :   real(r8), dimension(vlen), intent(out) :: prds
    2544             :   real(r8), dimension(vlen), intent(out) :: prdg
    2545             :   real(r8), dimension(vlen), intent(out) :: am_evp_st   ! Fractional area where rain evaporates.
    2546             :   ! Switch
    2547             :   logical, intent(in) :: evap_rhthrsh 
    2548             : 
    2549             :   real(r8) :: qclr   ! water vapor mixing ratio in clear air
    2550             :   real(r8) :: ab, abr, abg    ! correction to account for latent heat
    2551             :   real(r8) :: eps    ! 1/ sat relaxation timescale
    2552           0 :   real(r8), dimension(vlen) :: dum
    2553             :   integer :: i
    2554             : 
    2555             :   !$acc data present (t,rho,dv,mu,sc,q,qvl,qvi,lcldm,precip_frac) &
    2556             :   !$acc      present (arn,asn,agn,qcic,qiic,qric,qsic,qgic,lamr)  &
    2557             :   !$acc      present (n0r,lams,n0s,lamg,n0g,pre,prds,prdg,am_evp_st) &
    2558             :   !$acc      create  (dum)
    2559             : 
    2560             :   ! set temporary cloud fraction to zero if cloud water + ice is very small
    2561             :   ! this will ensure that evaporation/sublimation of precip occurs over
    2562             :   ! entire grid cell, since min cloud fraction is specified otherwise
    2563             : 
    2564             :   !$acc parallel vector_length(VLENS) default(present)
    2565             :   !$acc loop gang vector
    2566           0 :   do i=1,vlen
    2567           0 :      am_evp_st(i) = 0._r8
    2568           0 :      if (qcic(i)+qiic(i) < 1.e-6_r8) then
    2569           0 :         dum(i) = 0._r8
    2570             :      else
    2571           0 :         dum(i) = lcldm(i)
    2572             :      end if
    2573             :   end do
    2574             : 
    2575             :   !$acc loop gang vector private(qclr,eps,abr,ab,abg)
    2576           0 :   do i=1,vlen
    2577             :      ! only calculate if there is some precip fraction > cloud fraction
    2578           0 :      if (precip_frac(i) > dum(i)) then
    2579           0 :         if (qric(i) >= qsmall .or. qsic(i) >= qsmall .or. qgic(i) >= qsmall) then
    2580           0 :            am_evp_st(i) = precip_frac(i) - dum(i)
    2581             :            ! calculate q for out-of-cloud region
    2582           0 :            qclr=(q(i)-dum(i)*qvl(i))/(1._r8-dum(i))
    2583             :         end if
    2584             : 
    2585             :         ! evaporation of rain
    2586           0 :         if (qric(i) >= qsmall) then
    2587           0 :            if (.not.evap_rhthrsh.or.(evap_rhthrsh.and.qclr/qvl(i).le.0.9_r8)) then
    2588           0 :               call calc_ab(t(i), qvl(i), xxlv, abr)
    2589             :               eps = 2._r8*pi*n0r(i)*rho(i)*Dv(i)* &
    2590             :                  (f1r/(lamr(i)*lamr(i))+ &
    2591             :                  f2r*(arn(i)*rho(i)/mu(i))**0.5_r8* &
    2592             :                  sc(i)**(1._r8/3._r8)*gamma_half_br_plus5/ &
    2593           0 :                  (lamr(i)**(5._r8/2._r8+br/2._r8)))
    2594           0 :               pre(i) = eps*(qclr-qvl(i))/abr
    2595             :               ! only evaporate in out-of-cloud region
    2596             :               ! and distribute across precip_frac
    2597           0 :               pre(i) = min(pre(i)*am_evp_st(i),0._r8)
    2598           0 :               pre(i) = pre(i)/precip_frac(i)
    2599             :            else
    2600           0 :               pre(i) = 0._r8
    2601             :            end if
    2602             :         else
    2603           0 :            pre(i) = 0._r8
    2604             :         end if
    2605             : 
    2606             :         ! sublimation of snow
    2607           0 :         if (qsic(i) >= qsmall) then
    2608           0 :            call calc_ab(t(i), qvi(i), xxls, ab)
    2609             :            eps = 2._r8*pi*n0s(i)*rho(i)*Dv(i)* &
    2610             :                 (f1s/(lams(i)*lams(i))+ &
    2611             :                 f2s*(asn(i)*rho(i)/mu(i))**0.5_r8* &
    2612             :                 sc(i)**(1._r8/3._r8)*gamma_half_bs_plus5/ &
    2613           0 :                 (lams(i)**(5._r8/2._r8+bs/2._r8)))
    2614           0 :            prds(i) = eps*(qclr-qvi(i))/ab
    2615             :            ! only sublimate in out-of-cloud region and distribute over precip_frac
    2616           0 :            prds(i) = min(prds(i)*am_evp_st(i),0._r8)
    2617           0 :            prds(i) = prds(i)/precip_frac(i)
    2618             :         else
    2619           0 :            prds(i) = 0._r8
    2620             :         end if
    2621             : 
    2622             :         ! ADD GRAUPEL, do Same with prdg.
    2623           0 :         if (qgic(i).ge.qsmall) then
    2624           0 :            call calc_ab(t(i), qvi(i), xxls, abg)
    2625             :            eps = 2._r8*pi*n0g(i)*rho(i)*Dv(i)*                    &
    2626             :                 (f1s/(lamg(i)*lamg(i))+                           &
    2627             :                 f2s*(agn(i)*rho(i)/mu(i))**0.5_r8*                &
    2628             :                 sc(i)**(1._r8/3._r8)*gamma(5._r8/2._r8+bg/2._r8)/ &
    2629           0 :                 (lamg(i)**(5._r8/2._r8+bs/2._r8)))
    2630           0 :            prdg(i) = eps*(qclr-qvi(i))/abg
    2631             :            ! only sublimate in out-of-cloud region and distribute over precip_frac
    2632           0 :            prdg(i) = min(prdg(i)*am_evp_st(i),0._r8)
    2633           0 :            prdg(i) = prdg(i)/precip_frac(i)
    2634             :         else
    2635           0 :            prdg(i) = 0._r8
    2636             :         end if
    2637             : 
    2638             :      else
    2639           0 :         prds(i) = 0._r8
    2640           0 :         pre(i)  = 0._r8
    2641           0 :         prdg(i) = 0._r8
    2642             :      end if
    2643             :   end do
    2644             :   !$acc end parallel
    2645             : 
    2646             :   !$acc end data
    2647           0 : end subroutine evaporate_sublimate_precip_graupel
    2648             : 
    2649             : ! evaporation/sublimation of rain and graupel (no snow in mg4)
    2650             : !===================================================================
    2651             : ! note: evaporation/sublimation occurs only in cloud-free portion of grid cell
    2652             : ! in-cloud condensation/deposition of rain and graupel is neglected
    2653             : ! except for transfer of cloud water to snow through bergeron process
    2654             : 
    2655           0 : subroutine evaporate_sublimate_precip_graupel_mg4(t, rho, dv, mu, sc, q, qvl, qvi, &
    2656           0 :      lcldm, precip_frac, arn, agn, bg, qcic, qiic, qric, qgic, lamr, n0r, lamg, n0g, &
    2657           0 :      pre, prdg, am_evp_st, vlen)
    2658             : 
    2659             :   integer,                   intent(in) :: vlen
    2660             :   real(r8), dimension(vlen), intent(in) :: t            ! temperature
    2661             :   real(r8), dimension(vlen), intent(in) :: rho          ! air density
    2662             :   real(r8), dimension(vlen), intent(in) :: dv           ! water vapor diffusivity
    2663             :   real(r8), dimension(vlen), intent(in) :: mu           ! viscosity
    2664             :   real(r8), dimension(vlen), intent(in) :: sc           ! schmidt number
    2665             :   real(r8), dimension(vlen), intent(in) :: q            ! humidity
    2666             :   real(r8), dimension(vlen), intent(in) :: qvl          ! saturation humidity (water)
    2667             :   real(r8), dimension(vlen), intent(in) :: qvi          ! saturation humidity (ice)
    2668             :   real(r8), dimension(vlen), intent(in) :: lcldm        ! liquid cloud fraction
    2669             :   real(r8), dimension(vlen), intent(in) :: precip_frac  ! precipitation fraction (maximum overlap)
    2670             :   ! fallspeed parameters
    2671             :   real(r8), dimension(vlen), intent(in) :: arn          ! rain
    2672             :   real(r8), dimension(vlen), intent(in) :: agn          ! graupel
    2673             :   real(r8),                  intent(in) :: bg 
    2674             :   ! In-cloud MMRs
    2675             :   real(r8), dimension(vlen), intent(in) :: qcic         ! cloud liquid
    2676             :   real(r8), dimension(vlen), intent(in) :: qiic         ! cloud ice
    2677             :   real(r8), dimension(vlen), intent(in) :: qric         ! rain
    2678             :   real(r8), dimension(vlen), intent(in) :: qgic         ! graupel
    2679             :   ! Size parameters
    2680             :   ! rain
    2681             :   real(r8), dimension(vlen), intent(in) :: lamr
    2682             :   real(r8), dimension(vlen), intent(in) :: n0r
    2683             :   ! graupel
    2684             :   real(r8), dimension(vlen), intent(in) :: lamg
    2685             :   real(r8), dimension(vlen), intent(in) :: n0g
    2686             :   ! Output tendencies
    2687             :   real(r8), dimension(vlen), intent(out) :: pre
    2688             :   real(r8), dimension(vlen), intent(out) :: prdg
    2689             :   real(r8), dimension(vlen), intent(out) :: am_evp_st   ! Fractional area where rain evaporates.
    2690             : 
    2691             :   real(r8) :: qclr                                      ! water vapor mixing ratio in clear air
    2692             :   real(r8) :: abr, abg                                  ! correction to account for latent heat
    2693             :   real(r8) :: eps                                       ! 1/ sat relaxation timescale
    2694           0 :   real(r8), dimension(vlen) :: dum
    2695             :   integer :: i
    2696             : 
    2697             :   !$acc data present (t,rho,dv,mu,sc,q,qvl,qvi,lcldm,precip_frac) &
    2698             :   !$acc      present (arn,agn,qcic,qiic,qric,qgic,lamr,n0r,lamg)  &
    2699             :   !$acc      present (n0g,pre,prdg,am_evp_st) &
    2700             :   !$acc      create  (dum)
    2701             : 
    2702             :   ! set temporary cloud fraction to zero if cloud water + ice is very small
    2703             :   ! this will ensure that evaporation/sublimation of precip occurs over
    2704             :   ! entire grid cell, since min cloud fraction is specified otherwise
    2705             :   !$acc parallel vector_length(VLENS) default(present)
    2706             :   !$acc loop gang vector
    2707           0 :   do i=1,vlen
    2708           0 :      am_evp_st(i) = 0._r8
    2709           0 :      if (qcic(i)+qiic(i) < 1.e-6_r8) then
    2710           0 :         dum(i) = 0._r8
    2711             :      else
    2712           0 :         dum(i) = lcldm(i)
    2713             :      end if
    2714             :   end do
    2715             : 
    2716             :   !$acc loop gang vector private(qclr,eps,abr,abg)
    2717           0 :   do i=1,vlen
    2718             :      ! only calculate if there is some precip fraction > cloud fraction
    2719           0 :      if (precip_frac(i) > dum(i)) then
    2720           0 :         if (qric(i) >= qsmall .or. qgic(i) >= qsmall) then
    2721           0 :            am_evp_st(i) = precip_frac(i) - dum(i)
    2722             :            ! calculate q for out-of-cloud region
    2723           0 :            qclr = (q(i)-dum(i)*qvl(i))/(1._r8-dum(i))
    2724             :         end if
    2725             : 
    2726             :         ! evaporation of rain
    2727           0 :         if (qric(i) >= qsmall) then
    2728           0 :            call calc_ab(t(i), qvl(i), xxlv, abr)
    2729             :            eps = 2._r8*pi*n0r(i)*rho(i)*Dv(i)* &
    2730             :                 (f1r/(lamr(i)*lamr(i))+ &
    2731             :                 f2r*(arn(i)*rho(i)/mu(i))**0.5_r8* &
    2732             :                 sc(i)**(1._r8/3._r8)*gamma_half_br_plus5/ &
    2733           0 :                 (lamr(i)**(5._r8/2._r8+br/2._r8)))
    2734           0 :            pre(i) = eps*(qclr-qvl(i))/abr
    2735             :            ! only evaporate in out-of-cloud region
    2736             :            ! and distribute across precip_frac
    2737           0 :            pre(i) = min(pre(i)*am_evp_st(i),0._r8)
    2738           0 :            pre(i) = pre(i)/precip_frac(i)
    2739             :         else
    2740           0 :            pre(i) = 0._r8
    2741             :         end if
    2742             : 
    2743             :         ! ADD GRAUPEL, do Same with prdg.
    2744           0 :         if (qgic(i).ge.qsmall) then
    2745           0 :            call calc_ab(t(i), qvi(i), xxls, abg)
    2746             :            eps = 2._r8*pi*n0g(i)*rho(i)*Dv(i)*                    &
    2747             :                 (f1s/(lamg(i)*lamg(i))+                           &
    2748             :                 f2s*(agn(i)*rho(i)/mu(i))**0.5_r8*                &
    2749             :                 sc(i)**(1._r8/3._r8)*gamma(5._r8/2._r8+bg/2._r8)/ &
    2750           0 :                 (lamg(i)**(5._r8/2._r8+bs/2._r8)))
    2751           0 :            prdg(i) = eps*(qclr-qvi(i))/abg
    2752             :            ! only sublimate in out-of-cloud region and distribute over precip_frac
    2753           0 :            prdg(i) = min(prdg(i)*am_evp_st(i),0._r8)
    2754           0 :            prdg(i) = prdg(i)/precip_frac(i)
    2755             :         else
    2756           0 :            prdg(i) = 0._r8
    2757             :         end if
    2758             :      else
    2759           0 :         pre(i) = 0._r8
    2760           0 :         prdg(i) = 0._r8
    2761             :      end if
    2762             :   end do
    2763             :   !$acc end parallel
    2764             : 
    2765             :   !$acc end data
    2766           0 : end subroutine evaporate_sublimate_precip_graupel_mg4
    2767             : 
    2768             : ! bergeron process - evaporation of droplets and deposition onto snow
    2769             : !===================================================================
    2770             : 
    2771           0 : subroutine bergeron_process_snow(t, rho, dv, mu, sc, qvl, qvi, asn, &
    2772           0 :      qcic, qsic, lams, n0s, bergs, vlen)
    2773             : 
    2774             :   integer,                   intent(in) :: vlen
    2775             :   real(r8), dimension(vlen), intent(in) :: t    ! temperature
    2776             :   real(r8), dimension(vlen), intent(in) :: rho  ! air density
    2777             :   real(r8), dimension(vlen), intent(in) :: dv   ! water vapor diffusivity
    2778             :   real(r8), dimension(vlen), intent(in) :: mu   ! viscosity
    2779             :   real(r8), dimension(vlen), intent(in) :: sc   ! schmidt number
    2780             :   real(r8), dimension(vlen), intent(in) :: qvl  ! saturation humidity (water)
    2781             :   real(r8), dimension(vlen), intent(in) :: qvi  ! saturation humidity (ice)
    2782             :   ! fallspeed parameter for snow
    2783             :   real(r8), dimension(vlen), intent(in) :: asn
    2784             :   ! In-cloud MMRs
    2785             :   real(r8), dimension(vlen), intent(in) :: qcic ! cloud liquid mixing ratio
    2786             :   real(r8), dimension(vlen), intent(in) :: qsic ! snow mixing ratio
    2787             :   ! Size parameters for snow
    2788             :   real(r8), dimension(vlen), intent(in) :: lams
    2789             :   real(r8), dimension(vlen), intent(in) :: n0s
    2790             :   ! Output tendencies
    2791             :   real(r8), dimension(vlen), intent(out) :: bergs
    2792             : 
    2793             :   real(r8) :: ab     ! correction to account for latent heat
    2794             :   real(r8) :: eps    ! 1/ sat relaxation timescale
    2795             :   integer :: i
    2796             : 
    2797             :   !$acc data present (t,rho,dv,mu,sc,qvl,qvi) &
    2798             :   !$acc      present (asn,qcic,qsic,lams,n0s,bergs)
    2799             : 
    2800             :   !$acc parallel vector_length(VLENS) default(present)
    2801             :   !$acc loop gang vector private(eps,ab)
    2802           0 :   do i=1,vlen
    2803           0 :      if (qsic(i) >= qsmall.and. qcic(i) >= qsmall .and. t(i) < tmelt) then
    2804           0 :         call calc_ab(t(i), qvi(i), xxls, ab)
    2805             :         eps = 2._r8*pi*n0s(i)*rho(i)*Dv(i)* &
    2806             :              (f1s/(lams(i)*lams(i))+ &
    2807             :              f2s*(asn(i)*rho(i)/mu(i))**0.5_r8* &
    2808             :              sc(i)**(1._r8/3._r8)*gamma_half_bs_plus5/ &
    2809           0 :              (lams(i)**(5._r8/2._r8+bs/2._r8)))
    2810           0 :         bergs(i) = eps*(qvl(i)-qvi(i))/ab
    2811             :      else
    2812           0 :         bergs(i) = 0._r8
    2813             :      end if
    2814             :   end do
    2815             :   !$acc end parallel
    2816             : 
    2817             :   !$acc end data
    2818           0 : end subroutine bergeron_process_snow
    2819             : 
    2820             : !========================================================================
    2821             : ! Collection of snow by rain to form graupel
    2822             : !========================================================================
    2823             : 
    2824           0 : subroutine graupel_collecting_snow(qsic,qric,umr,ums,rho,lamr,n0r,lams,n0s, &
    2825           0 :      psacr, vlen)
    2826             :   
    2827             :   integer,                   intent(in)  :: vlen
    2828             :   ! In-cloud MMRs
    2829             :   real(r8), dimension(vlen), intent(in)  :: qsic  ! snow
    2830             :   real(r8), dimension(vlen), intent(in)  :: qric  ! rain
    2831             :   ! mass-weighted fall speeds
    2832             :   real(r8), dimension(vlen), intent(in)  :: umr   ! rain
    2833             :   real(r8), dimension(vlen), intent(in)  :: ums   ! snow
    2834             :   real(r8), dimension(vlen), intent(in)  :: rho   ! air density
    2835             :   ! Size parameters for rain
    2836             :   real(r8), dimension(vlen), intent(in)  :: lamr
    2837             :   real(r8), dimension(vlen), intent(in)  :: n0r
    2838             :   ! Size parameters for snow
    2839             :   real(r8), dimension(vlen), intent(in)  :: lams
    2840             :   real(r8), dimension(vlen), intent(in)  :: n0s
    2841             :   real(r8), dimension(vlen), intent(out) :: psacr ! conversion due to coll of snow by rain
    2842             : 
    2843             :   real(r8), parameter :: cons31 = pi*pi*ecr*rhosn
    2844             :   integer :: i
    2845             : 
    2846             :   !$acc data present (qsic,qric,umr,ums,rho,lamr) &
    2847             :   !$acc      present (n0r,lams,n0s,psacr)
    2848             : 
    2849             :   !$acc parallel vector_length(VLENS) default(present)
    2850             :   !$acc loop gang vector
    2851           0 :   do i=1,vlen
    2852           0 :      if (qsic(i).ge.0.1e-3_r8 .and. qric(i).ge.0.1e-3_r8) then
    2853             :         psacr(i) = cons31*(((1.2_r8*umr(i)-0.95_r8*ums(i))**2+ &
    2854             :              0.08_r8*ums(i)*umr(i))**0.5_r8*rho(i)*            &
    2855             :              n0r(i)*n0s(i)/lams(i)**3*                         &
    2856             :              (5._r8/(lams(i)**3*lamr(i))+                      &
    2857             :              2._r8/(lams(i)**2*lamr(i)**2)+                    &
    2858           0 :              0.5_r8/(lams(i)*lamr(i)**3)))            
    2859             :      else
    2860           0 :         psacr(i) = 0._r8
    2861             :      end if
    2862             :   end do
    2863             :   !$acc end parallel
    2864             : 
    2865             :   !$acc end data
    2866           0 : end subroutine graupel_collecting_snow
    2867             : 
    2868             : !========================================================================
    2869             : ! Collection of cloud water by graupel
    2870             : !========================================================================
    2871             : 
    2872           0 : subroutine graupel_collecting_cld_water(qgic,qcic,ncic,rho,n0g,lamg,bg,agn, &
    2873           0 :      psacwg, npsacwg, vlen)
    2874             : 
    2875             :   integer,                   intent(in) :: vlen
    2876             :   ! In-cloud MMRs
    2877             :   real(r8), dimension(vlen), intent(in) :: qgic ! graupel
    2878             :   real(r8), dimension(vlen), intent(in) :: qcic ! cloud water
    2879             :   real(r8), dimension(vlen), intent(in) :: ncic ! cloud water number conc
    2880             :   real(r8), dimension(vlen), intent(in) :: rho  ! air density
    2881             :   ! Size parameters for graupel
    2882             :   real(r8), dimension(vlen), intent(in) :: lamg
    2883             :   real(r8), dimension(vlen), intent(in) :: n0g
    2884             :   ! fallspeed parameters for graupel
    2885             :   ! Set AGN and BG  as input (in micro_pumas_v1.F90)  (select hail or graupel as appropriate)
    2886             :   real(r8),                  intent(in) :: bg
    2887             :   real(r8), dimension(vlen), intent(in) :: agn
    2888             :   ! Output tendencies
    2889             :   real(r8), dimension(vlen), intent(out) :: psacwg
    2890             :   real(r8), dimension(vlen), intent(out) :: npsacwg
    2891             : 
    2892             :   real(r8) :: cons
    2893             :   integer  :: i 
    2894             : 
    2895           0 :   cons = gamma(bg + 3._r8)*pi/4._r8 * ecid
    2896             : 
    2897             :   !$acc data present (qgic,qcic,ncic,rho,lamg,n0g,agn,psacwg,npsacwg)
    2898             : 
    2899             :   !$acc parallel vector_length(VLENS) default(present)
    2900             :   !$acc loop gang vector
    2901           0 :   do i=1,vlen
    2902           0 :      if (qgic(i).ge.1.e-8_r8 .and. qcic(i).ge.qsmall) then
    2903             :         psacwg(i) = cons*agn(i)*qcic(i)*rho(i)*  &
    2904             :                n0g(i)/                           &
    2905           0 :                lamg(i)**(bg+3._r8)
    2906             :         npsacwg(i) = cons*agn(i)*ncic(i)*rho(i)* &
    2907             :                n0g(i)/                           &
    2908           0 :                lamg(i)**(bg+3._r8)
    2909             :      else
    2910           0 :         psacwg(i)  = 0._r8
    2911           0 :         npsacwg(i) = 0._r8
    2912             :      end if
    2913             :   end do
    2914             :   !$acc end parallel
    2915             : 
    2916             :   !$acc end data
    2917           0 : end subroutine graupel_collecting_cld_water
    2918             : 
    2919             : !========================================================================
    2920             : ! Conversion of rimed cloud water onto snow to graupel/hail
    2921             : !========================================================================
    2922             : 
    2923           0 : subroutine graupel_riming_liquid_snow(psacws,qsic,qcic,nsic,rho,rhosn,rhog,asn,lams,n0s,dtime, &
    2924           0 :      pgsacw,nscng,vlen)
    2925             : 
    2926             :   integer,                   intent(in)    :: vlen
    2927             :   ! Accretion of cloud water to snow tendency (modified)
    2928             :   real(r8), dimension(vlen), intent(inout) :: psacws
    2929             :   real(r8), dimension(vlen), intent(in)    :: qsic    ! snow mixing ratio
    2930             :   real(r8), dimension(vlen), intent(in)    :: qcic    ! cloud liquid mixing ratio
    2931             :   real(r8), dimension(vlen), intent(in)    :: nsic    ! snow number concentration
    2932             :   real(r8), dimension(vlen), intent(in)    :: rho     ! air density
    2933             :   real(r8),                  intent(in)    :: rhosn   ! snow density
    2934             :   real(r8),                  intent(in)    :: rhog    ! graupel density
    2935             :   real(r8), dimension(vlen), intent(in)    :: asn     ! fall speed parameter for snow
    2936             :   ! Size parameters for snow
    2937             :   real(r8), dimension(vlen), intent(in)    :: lams
    2938             :   real(r8), dimension(vlen), intent(in)    :: n0s
    2939             :   real(r8),                  intent(in)    :: dtime
    2940             :   !Output process rates
    2941             :   real(r8), dimension(vlen), intent(out)   :: pgsacw  ! dQ graupel due to collection droplets by snow
    2942             :   real(r8), dimension(vlen), intent(out)   :: nscng   ! dN graupel due to collection droplets by snow
    2943             : 
    2944             :   real(r8) :: cons
    2945             :   real(r8) :: rhosu
    2946             :   real(r8) :: dum
    2947             :   integer  :: i 
    2948             : 
    2949             : !........................................................................
    2950             : !Input: PSACWS,qs,qc,n0s,rho,lams,rhos,rhog
    2951             : !Output:PSACWS,PGSACW,NSCNG
    2952             : 
    2953           0 :   rhosu = 85000._r8/(ra * tmelt)    ! typical air density at 850 mb
    2954             : 
    2955           0 :   cons  = 4._r8 *2._r8 *3._r8*rhosu*pi*ecid*ecid*gamma_2bs_plus2/(8._r8*(rhog-rhosn))
    2956             : 
    2957             :   !$acc data present (psacws,qsic,qcic,nsic,rho,asn,lams,n0s,pgsacw,nscng)
    2958             : 
    2959             :   !$acc parallel vector_length(VLENS) default(present)
    2960             :   !$acc loop gang vector private(dum)
    2961           0 :   do i=1,vlen
    2962           0 :      if (psacws(i).gt.0._r8 .and. qsic(i).GE.0.1e-3_r8 .AND. qcic(i).GE.0.5E-3_r8) then
    2963             :         ! Only allow conversion if qni > 0.1 and qc > 0.5 g/kg following Rutledge and Hobbs (1984)
    2964             :         ! if (qsic(i).GE.0.1e-3_r8 .AND. qcic(i).GE.0.5E-3_r8) then
    2965             : 
    2966             :         ! portion of riming converted to graupel (Reisner et al. 1998, originally IS1991)
    2967             :         ! dtime here is correct.
    2968             :         pgsacw(i) = min(psacws(i),cons*dtime*n0s(i)*qcic(i)*qcic(i)* &
    2969             :              asn(i)*asn(i)/ &
    2970           0 :              (rho(i)*lams(i)**(2._r8*bs+2._r8))) 
    2971             : 
    2972             :         ! Mix rat converted into graupel as embryo (Reisner et al. 1998, orig M1990)
    2973           0 :         dum       = max(rhosn/(rhog-rhosn)*pgsacw(i),0._r8) 
    2974             : 
    2975             :         ! Number concentraiton of embryo graupel from riming of snow
    2976           0 :         nscng(i)  = dum/mg0*rho(i)
    2977             :         ! Limit max number converted to snow number  (dtime here correct? We think yes)
    2978           0 :         nscng(i)  = min(nscng(i),nsic(i)/dtime)
    2979             : 
    2980             :         ! Portion of riming left for snow
    2981           0 :         psacws(i) = psacws(i) - pgsacw(i)
    2982             :      else
    2983           0 :         pgsacw(i) = 0._r8
    2984           0 :         nscng(i)  = 0._r8
    2985             :      end if
    2986             :   end do
    2987             :   !$acc end parallel
    2988             : 
    2989             :   !$acc end data
    2990           0 : end subroutine graupel_riming_liquid_snow
    2991             : 
    2992             : !========================================================================
    2993             : !CHANGE IN Q,N COLLECTION RAIN BY GRAUPEL
    2994             : !========================================================================
    2995             : 
    2996           0 : subroutine graupel_collecting_rain(qric,qgic,umg,umr,ung,unr,rho,n0r,lamr,n0g,lamg,&
    2997           0 :      pracg,npracg,vlen)
    2998             : 
    2999             :   integer,                   intent(in) :: vlen
    3000             :   !MMR
    3001             :   real(r8), dimension(vlen), intent(in) :: qric  !rain mixing ratio
    3002             :   real(r8), dimension(vlen), intent(in) :: qgic  !graupel mixing ratio
    3003             :   !Mass weighted Fall speeds
    3004             :   real(r8), dimension(vlen), intent(in) :: umg ! graupel fall speed
    3005             :   real(r8), dimension(vlen), intent(in) :: umr ! rain fall speed
    3006             :   !Number weighted fall speeds
    3007             :   real(r8), dimension(vlen), intent(in) :: ung ! graupel fall speed
    3008             :   real(r8), dimension(vlen), intent(in) :: unr ! rain fall speed
    3009             :   real(r8), dimension(vlen), intent(in) :: rho   ! air density
    3010             :   ! Size parameters for rain
    3011             :   real(r8), dimension(vlen), intent(in) :: n0r
    3012             :   real(r8), dimension(vlen), intent(in) :: lamr
    3013             :   ! Size parameters for graupel
    3014             :   real(r8), dimension(vlen), intent(in) :: n0g
    3015             :   real(r8), dimension(vlen), intent(in) :: lamg
    3016             :   !Output process rates
    3017             :   real(r8), dimension(vlen), intent(out) :: pracg   ! Q collection rain by graupel
    3018             :   real(r8), dimension(vlen), intent(out) :: npracg  ! N collection rain by graupel
    3019             : 
    3020             : ! Add collection of graupel by rain above freezing
    3021             : ! assume all rain collection by graupel above freezing is shed
    3022             : ! assume shed drops are 1 mm in size
    3023             :   integer  :: i 
    3024             :   real(r8), parameter :: cons41 = pi*pi*ecr*rhow
    3025             :   real(r8), parameter :: cons32 = pi/2._r8*ecr
    3026             :   real(r8) :: dum
    3027             : 
    3028             :   !$acc data present (qric,qgic,umg,umr,ung,unr,rho) &
    3029             :   !$acc      present (n0r,lamr,n0g,lamg,pracg,npracg)
    3030             : 
    3031             :   !$acc parallel vector_length(VLENS) default(present)
    3032             :   !$acc loop gang vector private(dum)
    3033           0 :   do i=1,vlen
    3034           0 :      if (qric(i).ge.1.e-8_r8.and.qgic(i).ge.1.e-8_r8) then
    3035             :         ! pracg is mixing ratio of rain per sec collected by graupel/hail
    3036             :         pracg(i) = cons41*(((1.2_r8*umr(i)-0.95_r8*umg(i))**2._r8+  &
    3037             :              0.08_r8*umg(i)*umr(i))**0.5_r8*rho(i)*                 &
    3038             :              n0r(i)*n0g(i)/lamr(i)**3._r8*                          &
    3039             :              (5._r8/(lamr(i)**3._r8*lamg(i))+                       &
    3040             :              2._r8/(lamr(i)**2._r8*lamg(i)**2._r8)+                 &
    3041           0 :              0.5_r8/(lamr(i)*lamg(i)**3._r8)))
    3042             : 
    3043             : ! assume 1 mm drops are shed, get number shed per sec
    3044           0 :         dum = pracg(i)/5.2e-7_r8
    3045             :         npracg(i) = cons32*rho(i)*(1.7_r8*(unr(i)-ung(i))**2._r8+   &
    3046             :              0.3_r8*unr(i)*ung(i))**0.5_r8*n0r(i)*n0g(i)*           &
    3047             :              (1._r8/(lamr(i)**3._r8*lamg(i))+                       &
    3048             :              1._r8/(lamr(i)**2._r8*lamg(i)**2._r8)+                 &
    3049           0 :              1._r8/(lamr(i)*lamg(i)**3._r8))
    3050             :         
    3051             : ! hm 7/15/13, remove limit so that the number of collected drops can smaller than 
    3052             : ! number of shed drops
    3053             : !            NPRACG(K)=MAX(NPRACG(K)-DUM,0.)
    3054           0 :         npracg(i) = npracg(i) - dum
    3055             :      else
    3056           0 :         npracg(i) = 0._r8
    3057           0 :         pracg(i)  = 0._r8
    3058             :      end if
    3059             :   end do
    3060             :   !$acc end parallel
    3061             : 
    3062             :   !$acc end data
    3063           0 : end subroutine graupel_collecting_rain
    3064             : 
    3065             : !========================================================================
    3066             : ! Rain riming snow to graupel
    3067             : !========================================================================
    3068             : ! Conversion of rimed rainwater onto snow converted to graupel
    3069             : 
    3070           0 : subroutine graupel_rain_riming_snow(pracs,npracs,psacr,qsic,qric,nric,nsic,n0s,lams,n0r,lamr,dtime,&
    3071           0 :      pgracs,ngracs,vlen)
    3072             : 
    3073             :   integer,                   intent(in)    :: vlen
    3074             :   ! Accretion of rain by snow
    3075             :   real(r8), dimension(vlen), intent(inout) :: pracs
    3076             :   real(r8), dimension(vlen), intent(inout) :: npracs
    3077             :   real(r8), dimension(vlen), intent(inout) :: psacr  ! conversion due to coll of snow by rain
    3078             :   !MMR
    3079             :   real(r8), dimension(vlen), intent(in)    :: qsic   ! snow mixing ratio
    3080             :   real(r8), dimension(vlen), intent(in)    :: qric   ! rain mixing ratio
    3081             :   real(r8), dimension(vlen), intent(in)    :: nric   ! rain number concentration
    3082             :   real(r8), dimension(vlen), intent(in)    :: nsic   ! snow number concentration
    3083             :   ! Size parameters for snow
    3084             :   real(r8), dimension(vlen), intent(in)    :: n0s
    3085             :   real(r8), dimension(vlen), intent(in)    :: lams
    3086             :   ! Size parameters for rain
    3087             :   real(r8), dimension(vlen), intent(in)    :: n0r
    3088             :   real(r8), dimension(vlen), intent(in)    :: lamr
    3089             :   real(r8),                  intent(in)    :: dtime
    3090             :   !Output process rates
    3091             :   real(r8), dimension(vlen), intent(out)   :: pgracs  ! Q graupel due to collection rain by snow
    3092             :   real(r8), dimension(vlen), intent(out)   :: ngracs  ! N graupel due to collection rain by snow
    3093             : 
    3094             : !Input: PRACS,NPRACS,PSACR,qni,qr,lams,lamr,nr,ns  Note: No PSACR in MG2
    3095             : !Output:PGRACS,NGRACS,PRACS,PSACR
    3096             :   integer  :: i 
    3097             :   real(r8), parameter :: cons18 = rhosn*rhosn
    3098             :   real(r8), parameter :: cons19 = rhow*rhow
    3099             :   real(r8) :: dum
    3100             : 
    3101             :   !$acc data present (pracs,npracs,psacr,qsic,qric,nric)  &
    3102             :   !$acc      present (nsic,n0s,lams,n0r,lamr,pgracs,ngracs)
    3103             : 
    3104             :   !$acc parallel vector_length(VLENS) default(present)
    3105             :   !$acc loop gang vector private(dum)
    3106           0 :   do i=1,vlen
    3107           0 :      if (pracs(i).gt.0._r8.and.qsic(i).ge.0.1e-3_r8.and.qric(i).ge.0.1e-3_r8) then
    3108             :         ! only allow conversion if qs > 0.1 and qr > 0.1 g/kg following rutledge and hobbs (1984)
    3109             :         !if (qsic(i).ge.0.1e-3_r8.and.qric(i).ge.0.1e-3_r8) then
    3110             :            ! portion of collected rainwater converted to graupel (reisner et al. 1998)
    3111             :         dum = cons18*(4._r8/lams(i))**3*(4._r8/lams(i))**3 &    
    3112             :              /(cons18*(4._r8/lams(i))**3*(4._r8/lams(i))**3+ &  
    3113           0 :              cons19*(4._r8/lamr(i))**3*(4._r8/lamr(i))**3)
    3114           0 :         dum = min(dum,1._r8)
    3115           0 :         dum = max(dum,0._r8)
    3116           0 :         pgracs(i) = (1._r8-dum)*pracs(i)
    3117           0 :         ngracs(i) = (1._r8-dum)*npracs(i)
    3118             :         ! limit max number converted to min of either rain or snow number concentration
    3119           0 :         ngracs(i) = min(ngracs(i),nric(i)/dtime)
    3120           0 :         ngracs(i) = min(ngracs(i),nsic(i)/dtime)
    3121             :         
    3122             :         ! amount left for snow production
    3123           0 :         pracs(i)  = pracs(i) - pgracs(i)
    3124           0 :         npracs(i) = npracs(i) - ngracs(i)
    3125             :         
    3126             :         ! conversion to graupel due to collection of snow by rain
    3127           0 :         psacr(i)=psacr(i)*(1._r8-dum)
    3128             :      else
    3129           0 :         pgracs(i) = 0._r8
    3130           0 :         ngracs(i) = 0._r8
    3131             :      end if
    3132             :   end do 
    3133             :   !$acc end parallel
    3134             : 
    3135             :   !$acc end data
    3136           0 : end subroutine graupel_rain_riming_snow
    3137             : 
    3138             : !========================================================================
    3139             : ! Rime Splintering
    3140             : !========================================================================
    3141           0 : subroutine graupel_rime_splintering(t,qcic,qric,qgic,psacwg,pracg,&
    3142           0 :      qmultg,nmultg,qmultrg,nmultrg,vlen)
    3143             : 
    3144             :   integer,                   intent(in)    :: vlen
    3145             :   real(r8), dimension(vlen), intent(in)    :: t        ! temperature
    3146             :   !MMR
    3147             :   real(r8), dimension(vlen), intent(in)    :: qcic     ! liquid mixing ratio
    3148             :   real(r8), dimension(vlen), intent(in)    :: qric     ! rain mixing ratio
    3149             :   real(r8), dimension(vlen), intent(in)    :: qgic     ! graupel mixing ratio
    3150             :   ! Already calculated terms for collection 
    3151             :   real(r8), dimension(vlen), intent(inout) :: psacwg   ! collection droplets by graupel
    3152             :   real(r8), dimension(vlen), intent(inout) :: pracg    ! collection rain by graupel
    3153             :   !Output process rates for splintering
    3154             :   real(r8), dimension(vlen), intent(out)   :: qmultg   ! Q ice mult of droplets/graupel
    3155             :   real(r8), dimension(vlen), intent(out)   :: nmultg   ! N ice mult of droplets/graupel
    3156             :   real(r8), dimension(vlen), intent(out)   :: qmultrg  ! Q ice mult of rain/graupel
    3157             :   real(r8), dimension(vlen), intent(out)   :: nmultrg  ! N ice mult of rain/graupel
    3158             : 
    3159             : !Input: qg,qc,qr, PSACWG,PRACG,T
    3160             : !Output: NMULTG,QMULTG,NMULTRG,QMULTRG,PSACWG,PRACG
    3161             :   integer  :: i 
    3162             :   real(r8) :: fmult
    3163             :   real(r8) :: tm_3, tm_5, tm_8
    3164             :  
    3165           0 :   tm_3 = tmelt - 3._r8
    3166           0 :   tm_5 = tmelt - 5._r8
    3167           0 :   tm_8 = tmelt - 8._r8
    3168             : 
    3169             :   !$acc data present (t,qcic,qric,qgic,psacwg,pracg) &
    3170             :   !$acc      present (qmultg,nmultg,qmultrg,nmultrg)
    3171             : 
    3172             : !nmultg,qmultg                                                                             .
    3173             : !========================================================================
    3174             : 
    3175             :   !$acc parallel vector_length(VLENS) default(present)
    3176             :   !$acc loop gang vector private(fmult)
    3177           0 :   do i=1,vlen
    3178           0 :      nmultrg(i) = 0._r8
    3179           0 :      qmultrg(i) = 0._r8
    3180           0 :      nmultg(i)  = 0._r8
    3181           0 :      qmultg(i)  = 0._r8
    3182           0 :      if (qgic(i).ge.0.1e-3_r8) then
    3183           0 :         if (qcic(i).ge.0.5e-3_r8.or.qric(i).ge.0.1e-3_r8) then
    3184           0 :            if (psacwg(i).gt.0._r8.or.pracg(i).gt.0._r8) then
    3185           0 :               if (t(i).lt.tm_3 .and. t(i).gt.tm_8) then
    3186           0 :                  if (t(i).gt.tm_3) then
    3187             :                     fmult = 0._r8
    3188           0 :                  else if (t(i).le.tm_3.and.t(i).gt.tm_5)  then
    3189           0 :                     fmult = (tm_3-t(i))/2._r8
    3190           0 :                  else if (t(i).ge.tm_8.and.t(i).le.tm_5)   then
    3191           0 :                     fmult = (t(i)-tm_8)/3._r8
    3192           0 :                  else if (t(i).lt.tm_8) then
    3193           0 :                     fmult = 0._r8
    3194             :                  end if
    3195             : ! 1000 is to convert from kg to g  (Check if needed for MG)
    3196             : ! splintering from droplets accreted onto graupel
    3197           0 :                  if (psacwg(i).gt.0._r8) then
    3198           0 :                     nmultg(i) = 35.e4_r8*psacwg(i)*fmult*1000._r8
    3199           0 :                     qmultg(i) = nmultg(i)*mmult
    3200             : ! constrain so that transfer of mass from graupel to ice cannot be more mass
    3201             : ! than was rimed onto graupel
    3202           0 :                     qmultg(i) = min(qmultg(i),psacwg(i))
    3203           0 :                     psacwg(i) = psacwg(i)-qmultg(i)
    3204             :                  end if
    3205             : 
    3206             : !nmultrg,qmultrg                                                                             .
    3207             : !========================================================================
    3208             : ! riming and splintering from accreted raindrops
    3209             : ! Factor of 1000. again (Check)
    3210           0 :                  if (pracg(i).gt.0._r8) then
    3211           0 :                     nmultrg(i) = 35.e4_r8*pracg(i)*fmult*1000._r8
    3212           0 :                     qmultrg(i) = nmultrg(i)*mmult
    3213             : ! constrain so that transfer of mass from graupel to ice cannot be more mass
    3214             : ! than was rimed onto graupel
    3215           0 :                     qmultrg(i) = min(qmultrg(i),pracg(i))
    3216           0 :                     pracg(i)   = pracg(i)-qmultrg(i)
    3217             :                  end if
    3218             :               end if
    3219             :            end if
    3220             :         end if
    3221             :      end if
    3222             :   end do
    3223             :   !$acc end parallel
    3224             : 
    3225             :   !$acc end data
    3226           0 : end subroutine graupel_rime_splintering
    3227             : 
    3228             : !========================================================================
    3229             : ! Evaporation and sublimation of graupel  
    3230             : !========================================================================
    3231             : 
    3232             : !MERGE WITH RAIN AND SNOW EVAP
    3233             : !
    3234             : !subroutine graupel_sublimate_evap(t,q,qgic,rho,n0g,lamg,qvi,dv,mu,sc,bg,agn,&
    3235             : !     prdg,eprdg,vlen)
    3236             : !
    3237             : !  integer, intent(in) :: vlen
    3238             : !  
    3239             : !  real(r8), dimension(vlen), intent(in) :: t  !temperature
    3240             : !  real(r8), dimension(vlen), intent(in) :: q  !specific humidity (mixing ratio)
    3241             : !
    3242             : !  !MMR
    3243             : !  real(r8), dimension(vlen), intent(in) :: qgic  !graupel mixing ratio
    3244             : !
    3245             : !  real(r8), dimension(vlen), intent(in) :: rho   ! air density
    3246             : !
    3247             : ! ! Size parameters for graupel
    3248             : !  real(r8), dimension(vlen), intent(in) :: n0g
    3249             : !  real(r8), dimension(vlen), intent(in) :: lamg
    3250             : !
    3251             : !  real(r8), dimension(vlen), intent(in) :: qvi  !saturation humidity (ice)
    3252             : !
    3253             : !  real(r8), dimension(vlen), intent(in) :: dv   ! water vapor diffusivity
    3254             : !  real(r8), dimension(vlen), intent(in) :: mu   ! viscosity
    3255             : !  real(r8), dimension(vlen), intent(in) :: sc   ! schmidt number
    3256             : !
    3257             : !  ! fallspeed parameters for graupel
    3258             : !  ! Set AGN and BG  as input (in micro_pumas_v1.F90)  (select hail or graupel as appropriate)
    3259             : !  real(r8),                    intent(in) :: bg
    3260             : !  real(r8), dimension(vlen), intent(in) :: agn
    3261             : !
    3262             : !  ! Output tendencies (sublimation or evaporation of graupel)
    3263             : !  real(r8), dimension(vlen), intent(out) :: prdg
    3264             : !  real(r8), dimension(vlen), intent(out) :: eprdg
    3265             : !
    3266             : !  real(r8) :: cons11,cons36
    3267             : !  real(r8) :: abi
    3268             : !  real(r8) :: epsg
    3269             : !  integer :: i 
    3270             : !
    3271             : !  cons11=gamma(2.5_r8+bg/2._r8)  !bg will be different for graupel (bg) or hail (bh)
    3272             : !  cons36=(2.5_r8+bg/2._r8)  
    3273             : !
    3274             : !  
    3275             : !  do i=1,vlen
    3276             : ! 
    3277             : !     abi = calc_ab(t(i), qvi(i), xxls)
    3278             : !
    3279             : !      if (qgic(i).ge.qsmall) then
    3280             : !         epsg = 2._r8*pi*n0g(i)*rho(i)*dv(i)*                                &
    3281             : !              (f1s/(lamg(i)*lamg(i))+                               &
    3282             : !              f2s*(agn(i)*rho(i)/mu(i))**0.5_r8*                      &
    3283             : !              sc(i)**(1._r8/3._r8)*cons11/                   &
    3284             : !              (lamg(i)**cons36))
    3285             : !      else
    3286             : !         epsg = 0.
    3287             : !      end if
    3288             : !
    3289             : !! vapor dpeosition on graupel
    3290             : !      prdg(i) = epsg*(q(i)-qvi(i))/abi
    3291             : !
    3292             : !! make sure not pushed into ice supersat/subsat
    3293             : !! put this in main mg3 code…..check for it…
    3294             : !! formula from reisner 2 scheme  
    3295             : !!
    3296             : !!          dum = (qv3d(k)-qvi(k))/dt
    3297             : !!
    3298             : !!           fudgef = 0.9999
    3299             : !!           sum_dep = prd(k)+prds(k)+mnuccd(k)+prdg(k)
    3300             : !!
    3301             : !!           if( (dum.gt.0. .and. sum_dep.gt.dum*fudgef) .or.                      &
    3302             : !!               (dum.lt.0. .and. sum_dep.lt.dum*fudgef) ) then
    3303             : !!             prdg(k) = fudgef*prdg(k)*dum/sum_dep
    3304             : !!           endif
    3305             : !
    3306             : !! if cloud ice/snow/graupel vap deposition is neg, then assign to sublimation processes
    3307             : !
    3308             : !      eprdg(i)=0._r8
    3309             : !
    3310             : !      if (prdg(i).lt.0._r8) then
    3311             : !         eprdg(i)=prdg(i)
    3312             : !         prdg(i)=0.
    3313             : !      end if
    3314             : !
    3315             : !   enddo
    3316             : !
    3317             : !end subroutine graupel_sublimate_evap
    3318             : 
    3319             : !========================================================================
    3320             : !MG4 Lookup Table
    3321             : !========================================================================
    3322             : 
    3323           0 : SUBROUTINE init_lookup_table(lkuptable_filename)
    3324             : 
    3325             :   implicit none
    3326             :     !character(100) :: lkuptable_filename = "/home/katec/mg4work/lookup_table.dat"
    3327             :     !character(100) :: lkuptable_filename = "/glade/p/work/katec/mg3work/lookup_table.dat"
    3328             :     !character(100) :: lkuptable_filename = "./lookup_table.dat"
    3329             :     character(len=256), intent(in) :: lkuptable_filename 
    3330             :     integer :: i,j,k,ii,jj,kk, tt
    3331             :     real(r8)    :: dum
    3332             : 
    3333             :     ! ++ trude
    3334           0 :     open(unit=10,file=lkuptable_filename,status='old')
    3335             : 
    3336             :     !------------------------------------------------------------------------------------------!
    3337             :     ! read in ice microphysics table
    3338           0 :      do tt = 1, tsize
    3339           0 :        do i = 1,isize
    3340           0 :           do k = 1,jsize
    3341           0 :              read(10,*) dum,dum,itab(tt,i,k,1),itab(tt,i,k,2),             &
    3342           0 :                   itab(tt,i,k,3),itab(tt,i,k,4),itab(tt,i,k,5),            &
    3343           0 :                   itab(tt,i,k,6),itab(tt,i,k,7),itab(tt,i,k,8),            &
    3344           0 :                   itab(tt,i,k,13),itab(tt,i,k,9),itab(tt,i,k,10),          &
    3345           0 :                   itab(tt,i,k,11),itab(tt,i,k,12),itab(tt,i,k,14) 
    3346             :             enddo
    3347             :        enddo
    3348             :        ! read in table for ice-rain collection
    3349           0 :        do i = 1,isize
    3350           0 :           do k = 1,jsize
    3351           0 :              do j = 1,rcollsize
    3352           0 :                 read(10,*) dum,dum,dum,itabcoll(tt,i,k,j,1),                  &
    3353           0 :                      itabcoll(tt,i,k,j,2),dum
    3354           0 :                 itabcoll(tt,i,k,j,1) = dlog10(itabcoll(tt,i,k,j,1))
    3355           0 :                 itabcoll(tt,i,k,j,2) = dlog10(itabcoll(tt,i,k,j,2))
    3356             :              end do
    3357             :           end do
    3358             :        end do
    3359             :     end do
    3360             : 
    3361           0 :     close(unit=10)
    3362             : 
    3363           0 : END SUBROUTINE init_lookup_table
    3364             : 
    3365           0 : pure SUBROUTINE access_lookup_table(dumii,dumi,dumk,index,dum1,dum2,dum4,proc)
    3366             : 
    3367             :   implicit none
    3368             : 
    3369             :   real(r8), intent(in) :: dum1,dum2,dum4
    3370             :   real(r8), intent(out) :: proc
    3371             :   real(r8) :: dproc1,dproc2,iproc1,gproc1,tmp1,tmp2
    3372             :   integer, intent(in) :: dumi,dumk,dumii,index
    3373             : 
    3374             : 
    3375             :   !(trude,  dumii could be the same as dumt)
    3376             :   ! get value at current density index
    3377             :   !***** without temperature dependence *******
    3378             :   ! first interpolate for current rimed fraction index
    3379             :   !   dproc1 = itab(dumi,dumk,index)+(dum1-real(dumi))*(itab(       &
    3380             :   !            dumi+1,dumk,index)-itab(dumi,dumk,index))
    3381             : 
    3382             :   !   dproc2 = itab(dumi,dumk+1,index)+(dum1-real(dumi))*(itab(     &
    3383             :   !          dumi+1,dumk+1,index)-itab(dumi,dumk+1,index))
    3384             : 
    3385             :   !   iproc1 = dproc1+(dum2-real(dumk))*(dproc2-dproc1)
    3386             : 
    3387             :   !   proc    = iproc1
    3388             :   !! ***** end without temperature dependence ***********
    3389             :   ! ******************* from orig P3 ********************
    3390             : 
    3391             :   ! trude comment, dumjj is for density index, dumii is for rime, which is subsituted by temperature. All dumjj should be removed. 
    3392             :   ! first interpolate for current temperature 
    3393           0 :   dproc1 = itab(dumii,dumi,dumk,index)+(dum1-real(dumi))*(itab(dumii,       &
    3394           0 :        dumi+1,dumk,index)-itab(dumii,dumi,dumk,index))
    3395             : 
    3396           0 :   dproc2 = itab(dumii,dumi,dumk+1,index)+(dum1-real(dumi))*(itab(dumii,     &
    3397           0 :        dumi+1,dumk+1,index)-itab(dumii,dumi,dumk+1,index))
    3398             : 
    3399           0 :   iproc1 = dproc1+(dum2-real(dumk))*(dproc2-dproc1)
    3400             : 
    3401             :   ! linearly interpolate to get process rates for temperature index + 1
    3402           0 :   dproc1 = itab(dumii+1,dumi,dumk,index)+(dum1-real(dumi))*(itab(dumii+1,   &
    3403           0 :        dumi+1,dumk,index)-itab(dumii+1,dumi,dumk,index))
    3404             : 
    3405             :   dproc2 = itab(dumii+1,dumi,dumk+1,index)+(dum1-real(dumi))*(itab(dumii+1, &
    3406           0 :        dumi+1,dumk+1,index)-itab(dumii+1,dumi,dumk+1,index))
    3407             : 
    3408           0 :   gproc1 = dproc1+(dum2-real(dumk))*(dproc2-dproc1)
    3409           0 :   tmp1   = iproc1+(dum4-real(dumii))*(gproc1-iproc1)
    3410           0 :   proc   = tmp1
    3411             : 
    3412             :   ! ********** end from orig P3 **************
    3413             : 
    3414           0 : END SUBROUTINE access_lookup_table
    3415             : 
    3416             : !------------------------------------------------------------------------------------------!
    3417           0 : pure SUBROUTINE access_lookup_table_coll(dumii,dumj,dumi,dumk,index,dum1,dum2,dum3,     &
    3418             :      dum4,proc)
    3419             : 
    3420             :   implicit none
    3421             : 
    3422             :   real(r8),intent(in)    :: dum1,dum2,dum3,dum4
    3423             :   real(r8), intent(out) :: proc
    3424             :   real(r8) :: dproc1,dproc2,iproc1,gproc1,tmp1,tmp2,dproc11, &
    3425             :        dproc12,dproc21,dproc22
    3426             :   integer, intent(in) :: dumii,dumj,dumi,dumk,index
    3427             : 
    3428             : 
    3429             :   ! This subroutine interpolates lookup table values for rain/ice collection processes
    3430             :   !!******for without temperature dependeny *****
    3431             :   !   dproc11 = itabcoll(dumi,dumk,dumj,index)+(dum1-real(dumi))*               &
    3432             :   !             (itabcoll(dumi+1,dumk,dumj,index)-itabcoll(dumi,    &
    3433             :   !             dumk,dumj,index))
    3434             : 
    3435             :   !   dproc21 = itabcoll(dumi,dumk+1,dumj,index)+(dum1-real(dumi))*             &
    3436             :   !             (itabcoll(dumi+1,dumk+1,dumj,index)-itabcoll(dumi,  &
    3437             :   !             dumk+1,dumj,index))
    3438             : 
    3439             :   !   dproc1  = dproc11+(dum2-real(dumk))*(dproc21-dproc11)
    3440             : 
    3441             :   !   dproc12 = itabcoll(dumi,dumk,dumj+1,index)+(dum1-real(dumi))*             &
    3442             :   !             (itabcoll(dumi+1,dumk,dumj+1,index)-itabcoll(dumi,  &
    3443             :   !             dumk,dumj+1,index))
    3444             : 
    3445             :   !   dproc22 = itabcoll(dumi,dumk+1,dumj+1,index)+(dum1-real(dumi))*           &
    3446             :   !             (itabcoll(dumi+1,dumk+1,dumj+1,index)-itabcoll(     &
    3447             :   !             dumi,dumk+1,dumj+1,index))
    3448             : 
    3449             :   !   dproc2  = dproc12+(dum2-real(dumk))*(dproc22-dproc12)
    3450             :   !   iproc1  = dproc1+(dum3-real(dumj))*(dproc2-dproc1)
    3451             : 
    3452             :   !   proc    = iproc1 
    3453             :   !!******end for without temperature dependeny *****
    3454             : 
    3455             :   ! ************ from original P3 ************
    3456             :   ! current density index
    3457             : 
    3458             :   ! current temp index
    3459           0 :   dproc11 = itabcoll(dumii,dumi,dumk,dumj,index)+(dum1-real(dumi))*               &
    3460           0 :        (itabcoll(dumii,dumi+1,dumk,dumj,index)-itabcoll(dumii,dumi,    &
    3461           0 :        dumk,dumj,index))
    3462             : 
    3463           0 :   dproc21 = itabcoll(dumii,dumi,dumk+1,dumj,index)+(dum1-real(dumi))*             &
    3464             :        (itabcoll(dumii,dumi+1,dumk+1,dumj,index)-itabcoll(dumii,dumi,  &
    3465           0 :        dumk+1,dumj,index))
    3466             : 
    3467           0 :   dproc1  = dproc11+(dum2-real(dumk))*(dproc21-dproc11)
    3468           0 :   dproc12 = itabcoll(dumii,dumi,dumk,dumj+1,index)+(dum1-real(dumi))*             &
    3469             :        (itabcoll(dumii,dumi+1,dumk,dumj+1,index)-itabcoll(dumii,dumi,  &
    3470           0 :        dumk,dumj+1,index))
    3471             : 
    3472             :   dproc22 = itabcoll(dumii,dumi,dumk+1,dumj+1,index)+(dum1-real(dumi))*           &
    3473             :        (itabcoll(dumii,dumi+1,dumk+1,dumj+1,index)-itabcoll(dumii,     &
    3474           0 :        dumi,dumk+1,dumj+1,index))
    3475             : 
    3476           0 :   dproc2  = dproc12+(dum2-real(dumk))*(dproc22-dproc12)
    3477           0 :   iproc1  = dproc1+(dum3-real(dumj))*(dproc2-dproc1)
    3478             : 
    3479             :   ! temp index + 1
    3480             : 
    3481           0 :   dproc11 = itabcoll(dumii+1,dumi,dumk,dumj,index)+(dum1-real(dumi))*             &
    3482             :        (itabcoll(dumii+1,dumi+1,dumk,dumj,index)-itabcoll(dumii+1,     &
    3483           0 :        dumi,dumk,dumj,index))
    3484             : 
    3485             :   dproc21 = itabcoll(dumii+1,dumi,dumk+1,dumj,index)+(dum1-real(dumi))*           &
    3486             :        (itabcoll(dumii+1,dumi+1,dumk+1,dumj,index)-itabcoll(dumii+1,   &
    3487           0 :        dumi,dumk+1,dumj,index))
    3488             : 
    3489           0 :   dproc1  = dproc11+(dum2-real(dumk))*(dproc21-dproc11)
    3490             : 
    3491             :   dproc12 = itabcoll(dumii+1,dumi,dumk,dumj+1,index)+(dum1-real(dumi))*           &
    3492             :        (itabcoll(dumii+1,dumi+1,dumk,dumj+1,index)-itabcoll(dumii+1,   &
    3493           0 :        dumi,dumk,dumj+1,index))
    3494             : 
    3495             :   dproc22 = itabcoll(dumii+1,dumi,dumk+1,dumj+1,index)+(dum1-real(dumi))*         &
    3496             :        (itabcoll(dumii+1,dumi+1,dumk+1,dumj+1,index)-itabcoll(dumii+1, &
    3497           0 :        dumi,dumk+1,dumj+1,index))
    3498             : 
    3499           0 :   dproc2  = dproc12+(dum2-real(dumk))*(dproc22-dproc12)
    3500             : 
    3501           0 :   gproc1  = dproc1+(dum3-real(dumj))*(dproc2-dproc1)
    3502           0 :   tmp1    = iproc1+(dum4-real(dumii))*(gproc1-iproc1)
    3503           0 :   proc    = tmp1
    3504             : 
    3505             :   ! ********** end orig P3 *******
    3506           0 : END SUBROUTINE access_lookup_table_coll
    3507             : 
    3508             : !========================================================================
    3509             : !UTILITIES
    3510             : !========================================================================
    3511             : 
    3512           0 : pure function no_limiter()
    3513             :   real(r8) :: no_limiter
    3514             : 
    3515           0 :   no_limiter = transfer(limiter_off, no_limiter)
    3516             : 
    3517           0 : end function no_limiter
    3518             : 
    3519           0 : pure function limiter_is_on(lim)
    3520             :   !$acc routine seq
    3521             : 
    3522             :   real(r8), intent(in) :: lim
    3523             :   logical :: limiter_is_on
    3524             : 
    3525           0 :   limiter_is_on = transfer(lim, limiter_off) /= limiter_off
    3526             : 
    3527           0 : end function limiter_is_on
    3528             : 
    3529           0 : end module micro_pumas_utils

Generated by: LCOV version 1.14