LCOV - code coverage report
Current view: top level - physics/pumas - micro_pumas_utils.F90 (source / functions) Hit Total Coverage
Test: coverage.info Lines: 505 822 61.4 %
Date: 2024-12-17 22:39:59 Functions: 37 57 64.9 %

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

Generated by: LCOV version 1.14