def test_rcm_emanuel():
    num_lev = 30
    water_depth = 5.
    # Temperatures in a single column
    state = climlab.column_state(num_lev=num_lev, water_depth=water_depth)
    #  Initialize a nearly dry column (small background stratospheric humidity)
    state['q'] = np.ones_like(state.Tatm) * 5.E-6
    #  ASYNCHRONOUS COUPLING -- the radiation uses a much longer timestep
    short_timestep = climlab.constants.seconds_per_hour
    #  The top-level model
    model = climlab.TimeDependentProcess(name='Radiative-Convective Model',
                        state=state,
                        timestep=short_timestep)
    #  Radiation coupled to water vapor
    rad = climlab.radiation.RRTMG(name='Radiation',
                        state=state,
                        specific_humidity=state.q,
                        albedo=0.3,
                        timestep=24*short_timestep)
    #  Convection scheme -- water vapor is a state variable
    conv = climlab.convection.EmanuelConvection(name='Convection',
                                  state=state,
                                  timestep=short_timestep)
    #  Surface heat flux processes
    shf = climlab.surface.SensibleHeatFlux(name='SHF',
                                  state=state, Cd=0.5E-3,
                                  timestep=climlab.constants.seconds_per_hour)
    lhf = climlab.surface.LatentHeatFlux(name='LHF',
                                  state=state, Cd=0.5E-3,
                                  timestep=short_timestep)
    #  Couple all the submodels together
    for proc in [rad, conv, shf, lhf]:
        model.add_subprocess(proc.name, proc)
    model.step_forward()
    to_xarray(model)
Esempio n. 2
0
def test_radiative_forcing():
    '''Run a single-column radiative-convective model with RRTMG radiation
    out to equilibrium. Clone the model, double CO2 and measure the instantaneous
    change in TOA flux. It should be positive net downward flux.'''
    #  State variables (Air and surface temperature)
    state = climlab.column_state(num_lev=30, water_depth=1.)
    #  Parent model process
    rcm = climlab.TimeDependentProcess(state=state)
    #  Fixed relative humidity
    h2o = climlab.radiation.ManabeWaterVapor(state=state)
    #  Couple water vapor to radiation
    #   Set icld=0 for clear-sky only (no need to call cloud overlap routine)
    rad = climlab.radiation.RRTMG(state=state, specific_humidity=h2o.q, icld=0)
    #  Convective adjustment
    conv = climlab.convection.ConvectiveAdjustment(state=state,
                                                   adj_lapse_rate=6.5)
    #  Couple everything together
    rcm.add_subprocess('Radiation', rad)
    rcm.add_subprocess('WaterVapor', h2o)
    rcm.add_subprocess('Convection', conv)

    rcm.integrate_years(5.)
    assert np.abs(rcm.ASR - rcm.OLR) < 0.1  # close to energy balance
    rcm2 = climlab.process_like(rcm)
    rcm2.subprocess['Radiation'].absorber_vmr['CO2'] *= 2.
    rcm2.compute_diagnostics()
    assert (rcm2.ASR - rcm2.OLR) > 1.  # positive radiative forcing
    #  Test the xarray interface
    to_xarray(rcm2)
Esempio n. 3
0
def test_latitude():
    '''
    Run a radiative equilibrum model with RRTMG radiation out to equilibrium
    with an annual mean insolation profile as a function of latitude.
    '''
    num_lat = 8
    #  State variables (Air and surface temperature)
    state = climlab.column_state(num_lev=30, num_lat=num_lat, water_depth=1.)
    #  Parent model process
    model = climlab.TimeDependentProcess(state=state)
    #  insolation
    sol = climlab.radiation.AnnualMeanInsolation(domains=model.Ts.domain)
    #  radiation module with insolation as input
    #   Set icld=0 for clear-sky only (no need to call cloud overlap routine)
    rad = climlab.radiation.RRTMG(state=state, icld=0,
                                  S0=sol.S0,
                                  insolation=sol.insolation,
                                  coszen=sol.coszen)
    #  Couple everything together
    model.add_subprocess('Radiation', rad)
    model.add_subprocess('Insolation', sol)
    #  Run out to equilibrium
    model.integrate_years(2.)
    #  Test for energy balance
    assert np.all(np.abs(model.ASR - model.OLR) < 0.1)
    #  Test for reasonable surface temperature gradient
    #  reversal of gradient at equator
    grad = np.diff(model.Ts, axis=0)
    assert np.all(grad[0:(int(num_lat/2)-1)] > 0.)
    assert np.all(grad[int(num_lat/2):] < 0.)
Esempio n. 4
0
        ## climlab setup
        # create surface and atmosperic domains
        sfc, atm = climlab.domain.single_column(lev=g.p / 100.)

        # create atmosheric state
        state = AttrDict()

        # assign surface temperature and vertical temperature profiles
        Ts_ = climlab.Field(np.array([Ts]), domain=sfc)
        state['Ts'] = Ts_

        Tatm = climlab.Field(g.T, domain=atm)
        state['Tatm'] = Tatm

        #  Parent model process
        rcm = climlab.TimeDependentProcess(state=state)
        rad = climlab.radiation.RRTMG(state=state,
                                      specific_humidity=g.q,
                                      albedo=0.3,
                                      ozone_file=None)
        rad.subprocess['LW'].absorber_vmr = {
            'CO2': CO2 * 1.e-6,
            'CH4': 0.,
            'N2O': 0.,
            'O2': 0.,
            'CFC11': 0.,
            'CFC12': 0.,
            'CFC22': 0.,
            'CCL4': 0.,
            'O3': 0.
        }
Esempio n. 5
0
def init_ram_no_advection(
        ds,
        m,
        CO2,
        timestep,
        surface_diffk=None,
        albedo=.77  #<- calculated value vs. first estimate = .8
):
    #create two domains: atm and surface
    sfc, atm = climlab.domain.single_column(
        lev=ds['Pressure'].sel(month=m).values, water_depth=1.)
    #create an atmospheric state
    state = AttrDict()
    #set up a surface temperature profile
    Ts_dict = {}
    for month in ds['month'].values:
        Ts_dict[month] = (ds['Temperature'].sel(month=month)[-1] - 52 *
                          (ds['Temperature'].sel(month=month)[-2] -
                           ds['Temperature'].sel(month=month)[-1]) /
                          (ds['Altitude'].sel(month=month)[-2] -
                           ds['Altitude'].sel(month=month)[-1])).values
    T_s = climlab.Field(Ts_dict[m], domain=sfc)
    state['Ts'] = T_s  #K
    #set up an atmospheric temperature profile
    T_atm = climlab.Field(ds['Temperature'].sel(month=m).values, domain=atm)
    state['Tatm'] = T_atm  #K

    #radiation model setup
    rad = climlab.radiation.RRTMG(
        name='Radiation(all gases)',
        state=state,
        specific_humidity=ds['spec_humidity'].sel(month=m).values,
        albedo=albedo,
        timestep=timestep,
        ozone_file=None,
        S0=1365.2,
        insolation=ds['monthly_insolation'].sel(month=m).values,
        isolvar=
        1  #see https://climlab.readthedocs.io/en/latest/_modules/climlab/radiation/rrtm/rrtmg_sw.html#RRTMG_SW._compute_heating_rates 
        #1 = Solar variability (using NRLSSI2  solar
        # model) with solar cycle contribution
        # determined by fraction of solar cycle
        # with facular and sunspot variations
        # fixed to their mean variations over the
        # average of Solar Cycles 13-24;
        # two amplitude scale factors allow
        # facular and sunspot adjustments from
        # mean solar cycle as defined by indsolvar
    )
    rad.absorber_vmr['O3'] = ds['O3'].sel(month=m).values  #kg/kg
    rad.absorber_vmr['CO2'] = CO2  #kg/kg
    #create ram
    ram = climlab.TimeDependentProcess(state=state, timestep=timestep)
    #add latitude axis
    lat = climlab.domain.axis.Axis(axis_type='lat', points=-90.)
    ram.domains['Ts'].axes['lat'] = lat
    #add radiation
    ram.add_subprocess('Radiation', rad)
    #compute ram
    ram.compute()
    #turbulence model setup (coupled to rad model, ds, and month)
    turb = Turbulence(surface_diffk=surface_diffk,
                      name='Turbulence',
                      state=state,
                      rad=rad,
                      m=m,
                      ds=ds,
                      timestep=timestep)
    #add turbulence
    ram.add_subprocess('Turbulence', turb)  #add insolation subprocess
    #compute ram
    ram.compute()

    return ram
Esempio n. 6
0
def init_ram(
        ds,
        m,
        CO2,
        timestep,
        turbulence_on,
        advection_on,
        advection=None,
        surface_diffk=None,
        albedo=.77  #<- calculated value vs. first estimate = .8
):
    #create two domains: atm and surface
    sfc, atm = climlab.domain.single_column(
        lev=ds['Pressure'].sel(month=m).values, water_depth=1.)
    #change the level bounds
    atm.axes['lev'].bounds[0] = atm.axes['lev'].bounds[1] - 2 * (
        atm.axes['lev'].bounds[1] - atm.axes['lev'].points[0])
    atm.axes['lev'].bounds[-1] = atm.axes['lev'].bounds[-2] + 2 * (
        atm.axes['lev'].points[-1] - atm.axes['lev'].bounds[-2])
    #change the level delta
    atm.axes['lev'].delta = atm.axes['lev'].bounds[1:] - atm.axes[
        'lev'].bounds[0:-1]
    #update heat capacity
    atm.set_heat_capacity()
    #create an atmospheric state
    state = AttrDict()
    #set up a surface temperature profile
    Ts_dict = {}
    for month in ds['month'].values:
        Ts_dict[month] = (ds['Temperature'].sel(month=month)[-1] - 52 *
                          (ds['Temperature'].sel(month=month)[-2] -
                           ds['Temperature'].sel(month=month)[-1]) /
                          (ds['Altitude'].sel(month=month)[-2] -
                           ds['Altitude'].sel(month=month)[-1])).values
    T_s = climlab.Field(Ts_dict[m], domain=sfc)
    state['Ts'] = T_s  #K
    #set up an atmospheric temperature profile
    T_atm = climlab.Field(ds['Temperature'].sel(month=m).values, domain=atm)
    state['Tatm'] = T_atm  #K

    #radiation model setup
    rad = climlab.radiation.RRTMG(
        name='Radiation(all gases)',
        state=state,
        specific_humidity=ds['spec_humidity'].sel(month=m).values,
        albedo=albedo,
        timestep=timestep,
        ozone_file=None,
        S0=1365.2,
        insolation=ds['monthly_insolation'].sel(month=m).values,
        isolvar=
        1  #see https://climlab.readthedocs.io/en/latest/_modules/climlab/radiation/rrtm/rrtmg_sw.html#RRTMG_SW._compute_heating_rates 
        #1 = Solar variability (using NRLSSI2  solar
        # model) with solar cycle contribution
        # determined by fraction of solar cycle
        # with facular and sunspot variations
        # fixed to their mean variations over the
        # average of Solar Cycles 13-24;
        # two amplitude scale factors allow
        # facular and sunspot adjustments from
        # mean solar cycle as defined by indsolvar
    )
    rad.absorber_vmr['O3'] = ds['O3'].sel(month=m).values  #kg/kg
    rad.absorber_vmr['CO2'] = CO2  #kg/kg
    #create ram
    ram = climlab.TimeDependentProcess(state=state, timestep=timestep)
    #add latitude axis
    lat = climlab.domain.axis.Axis(axis_type='lat', points=-90.)
    ram.domains['Ts'].axes['lat'] = lat
    #add radiation
    ram.add_subprocess('Radiation', rad)
    #compute ram
    ram.compute()
    if turbulence_on == True:
        #turbulence model setup (coupled to rad model, ds, and month)
        turb = Turbulence(surface_diffk=surface_diffk,
                          name='Turbulence',
                          state=state,
                          rad=rad,
                          m=m,
                          ds=ds,
                          timestep=timestep)
        #add turbulence
        ram.add_subprocess('Turbulence', turb)  #add insolation subprocess
        #compute ram
        ram.compute()
    if turbulence_on == False:
        turb = None
    if advection_on:
        #advective model setup (coupled to rad model)
        adv = climlab.process.external_forcing.ExternalForcing(state=state,
                                                               ram=ram,
                                                               turb=turb)
        if turbulence_on:
            normal_advection = -(
                (ram.TdotSW_clr + ram.TdotLW_clr) /
                climlab.constants.seconds_per_day + turb.turb_atm_hr
            )  #(K/day + K/day)/(sec/day) + K/sec
        if advection == None:
            adv.forcing_tendencies['Tatm'] = normal_advection
        else:
            adv.forcing_tendencies['Tatm'] = np.copy(advection[m])
        #add advection
        ram.add_subprocess('Advection', adv)
        #compute ram
        ram.compute()

    return ram