climt icon indicating copy to clipboard operation
climt copied to clipboard

Equilibrium precipitation doesn't match equilibrium latent heat flux in moist convective scheme

Open HaynesStephens opened this issue 5 years ago • 0 comments

  • CliMT version: 0.16.3
  • Python version: 3.6.5
  • Operating System: OSx

Description

I'm running a one-dimensional model that uses:

  • an ocean SlabSurface
  • both RRTMG schemes
  • SimplePhysics
  • EmanuelConvection

I'm trying to determine equilibrium precipitation rates for various amount of CO2. I manually input a surface wind of 5 m/s to stir convection. I'm checking to see whether the equilibrium latent heat flux (LH) matches the equilibrium precipitation rate (precip) according to the equation: (latent heat flux) = (precipitation) * (latent heat of vaporization) * (density of water)

However, when using only the Emanuel Convection scheme, I get an equilibrium latent heat flux of 64 Wm^-2 and a precip rate of 3.15 mm/day. If I use the precip value in the equation above, then I get a calculated LH of 93 Wm^-2 (too hight). When I include a dry convective adjustment (DryConvectiveAdjustment) along with the Emanuel scheme, I get an LH of 60 Wm^-2 and a precip rate of 2.08 mm/day. Again, using the precip value in the equation above, I get a calculated LH of 61.5 Wm^-2, which is much closer to the value outputted by CliMT.

This leads me to 3 questions:

  1. Is my comparison of LH and precip values valid for the equation that I used?
  2. Could there be a bug that allows for non-conservative water treatment in the Emanuel scheme, in which there's more precip that LH at equilibrium?
  3. Is it more realistic then, to include a dry convective adjustment when trying to model global precipitation?

What I Did

Here's the run where I include DryConvectiveAdjustment. The one without the adjustment scheme simply has the appropriate lines deleted.

from sympl import (
    DataArray, AdamsBashforth, get_constant, set_constant, NetCDFMonitor
)
import numpy as np
from datetime import timedelta

from climt import (
    EmanuelConvection, DryConvectiveAdjustment, RRTMGShortwave, RRTMGLongwave,
    SlabSurface, SimplePhysics, get_default_state
)
store_quantities = ['air_temperature',
                    'surface_temperature',
                    'air_pressure',
                    'specific_humidity',
                    'air_pressure_on_interface_levels',
                    'air_temperature_tendency_from_convection',
                    'air_temperature_tendency_from_longwave',
                    'air_temperature_tendency_from_shortwave',
                    'mole_fraction_of_carbon_dioxide_in_air',
                    'convective_precipitation_rate',
                    'stratiform_precipitation_rate',
                    'surface_upward_sensible_heat_flux',
                    'surface_upward_latent_heat_flux',
                    'upwelling_longwave_flux_in_air',
                    'upwelling_shortwave_flux_in_air',
                    'downwelling_longwave_flux_in_air',
                    'downwelling_shortwave_flux_in_air']

netcdf_monitor = NetCDFMonitor(nc_name,
                               store_names=store_quantities,
                               write_on_store=True)

# Set timestep at 10 minutes
dt_minutes = 10
timestep = timedelta(minutes=dt_minutes)

radiation_sw = RRTMGShortwave(ignore_day_of_year=True)
radiation_lw = RRTMGLongwave()
slab = SlabSurface()
simple_physics = SimplePhysics()
moist_convection = EmanuelConvection()
dry_convection = DryConvectiveAdjustment()

state = get_default_state([simple_physics, moist_convection, dry_convection,
                           radiation_lw, radiation_sw, slab])

state['air_temperature'].values[:]                          = 283.15
state['surface_albedo_for_direct_shortwave'].values[:]      = 0.07
state['surface_albedo_for_direct_near_infrared'].values[:]  = 0.07
state['surface_albedo_for_diffuse_shortwave'].values[:]     = 0.07
state['surface_albedo_for_diffuse_near_infrared'].values[:] = 0.07
state['zenith_angle'].values[:]                             = (2 * np.pi) / 5
state['surface_temperature'].values[:]                      = state['air_temperature'].values[0,0,0]
state['area_type'].values[:]                                = 'sea'
# Surface wind included to stir convection
state['eastward_wind'].values[0]                            = 5.0

state['mole_fraction_of_carbon_dioxide_in_air'].values[:]  = float(270) * 10**(-6)

time_stepper = AdamsBashforth([radiation_lw, radiation_sw, slab, moist_convection])
old_enthalpy = calc_moist_enthalpy(state)

# Day length to match Shanshan
run_days = 10950
run_length = int((run_days * 24 * 60) / dt_minutes)

for i in range(run_length):
    diagnostics, state = time_stepper(state, timestep)
    state.update(diagnostics)

    diagnostics, new_state = simple_physics(state, timestep)
    state.update(diagnostics)

    state.update(new_state)  #Update new simple_physics state   # These lines included w/
                                                                # the Dry Convective Scheme,
    diagnostics, new_state = dry_convection(state, timestep)    # Introduced for
    state.update(diagnostics)                                   # More realistic temperature profile

    if (i % 36 == 0):
        netcdf_monitor.store(state)

HaynesStephens avatar Sep 19 '19 18:09 HaynesStephens