Latitude-dependent grey radiation

Here is a quick example of using the climlab.GreyRadiationModel with a latitude dimension and seasonally varying insolation.


In [1]:
from __future__ import division, print_function
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
import climlab

In [2]:
model = climlab.GreyRadiationModel(num_lev=30, num_lat=90)
print(model)


climlab Process of type <class 'climlab.model.column.GreyRadiationModel'>. 
State variables and domain shapes: 
  Ts: (90, 1) 
  Tatm: (90, 30) 
The subprocess tree: 
top: <class 'climlab.model.column.GreyRadiationModel'>
   LW: <class 'climlab.radiation.greygas.GreyGas'>
   SW: <class 'climlab.radiation.greygas.GreyGasSW'>
   insolation: <class 'climlab.radiation.insolation.FixedInsolation'>


In [3]:
print(model.lat)


[-89. -87. -85. -83. -81. -79. -77. -75. -73. -71. -69. -67. -65. -63. -61.
 -59. -57. -55. -53. -51. -49. -47. -45. -43. -41. -39. -37. -35. -33. -31.
 -29. -27. -25. -23. -21. -19. -17. -15. -13. -11.  -9.  -7.  -5.  -3.  -1.
   1.   3.   5.   7.   9.  11.  13.  15.  17.  19.  21.  23.  25.  27.  29.
  31.  33.  35.  37.  39.  41.  43.  45.  47.  49.  51.  53.  55.  57.  59.
  61.  63.  65.  67.  69.  71.  73.  75.  77.  79.  81.  83.  85.  87.  89.]

In [4]:
insolation = climlab.radiation.DailyInsolation(domains=model.Ts.domain)

In [5]:
model.add_subprocess('insolation', insolation)
model.subprocess.SW.flux_from_space = insolation.insolation

In [6]:
print(model)


climlab Process of type <class 'climlab.model.column.GreyRadiationModel'>. 
State variables and domain shapes: 
  Ts: (90, 1) 
  Tatm: (90, 30) 
The subprocess tree: 
top: <class 'climlab.model.column.GreyRadiationModel'>
   LW: <class 'climlab.radiation.greygas.GreyGas'>
   SW: <class 'climlab.radiation.greygas.GreyGasSW'>
   insolation: <class 'climlab.radiation.insolation.DailyInsolation'>


In [7]:
model.compute_diagnostics()

In [8]:
plt.plot(model.lat, model.SW_down_TOA)


Out[8]:
[<matplotlib.lines.Line2D at 0x126670198>]

In [9]:
model.Tatm.shape


Out[9]:
(90, 30)

In [10]:
model.integrate_years(1)


Integrating for 365 steps, 365.2422 days, or 1 years.
/Users/br546577/anaconda3/lib/python3.6/site-packages/climlab/model/column.py:141: RuntimeWarning: divide by zero encountered in true_divide
  self.subprocess['SW'].flux_from_space)
Total elapsed time is 0.9993368783782377 years.

In [11]:
plt.plot(model.lat, model.Ts)


Out[11]:
[<matplotlib.lines.Line2D at 0x126648b38>]

In [12]:
model.integrate_years(1)


Integrating for 365 steps, 365.2422 days, or 1 years.
/Users/br546577/anaconda3/lib/python3.6/site-packages/climlab/model/column.py:141: RuntimeWarning: divide by zero encountered in true_divide
  self.subprocess['SW'].flux_from_space)
Total elapsed time is 1.9986737567564754 years.

In [13]:
plt.plot(model.lat, model.timeave['Ts'])


Out[13]:
[<matplotlib.lines.Line2D at 0x1266c1048>]

In [14]:
def plot_temp_section(model, timeave=True):
    fig = plt.figure()
    ax = fig.add_subplot(111)
    if timeave:
        field = model.timeave['Tatm'].transpose()
    else:
        field = model.Tatm.transpose()
    cax = ax.contourf(model.lat, model.lev, field)
    ax.invert_yaxis()
    ax.set_xlim(-90,90)
    ax.set_xticks([-90, -60, -30, 0, 30, 60, 90])
    fig.colorbar(cax)

In [15]:
plot_temp_section(model)



In [16]:
model2 = climlab.RadiativeConvectiveModel(num_lev=30, num_lat=90)
insolation = climlab.radiation.DailyInsolation(domains=model2.Ts.domain)
model2.add_subprocess('insolation', insolation)
model2.subprocess.SW.flux_from_space = insolation.insolation

In [17]:
model2.integrate_years(1)


Integrating for 365 steps, 365.2422 days, or 1 years.
/Users/br546577/anaconda3/lib/python3.6/site-packages/climlab/model/column.py:141: RuntimeWarning: divide by zero encountered in true_divide
  self.subprocess['SW'].flux_from_space)
Total elapsed time is 0.9993368783782377 years.

In [18]:
model2.integrate_years(1)


Integrating for 365 steps, 365.2422 days, or 1 years.
/Users/br546577/anaconda3/lib/python3.6/site-packages/climlab/model/column.py:141: RuntimeWarning: divide by zero encountered in true_divide
  self.subprocess['SW'].flux_from_space)
Total elapsed time is 1.9986737567564754 years.

In [19]:
plot_temp_section(model2)


Testing out multi-dimensional Band Models


In [20]:
#  Put in some ozone
import netCDF4 as nc

datapath = "http://ramadda.atmos.albany.edu:8080/repository/opendap/latest/Top/Users/BrianRose/CESM_runs/"
endstr = "/entry.das"

ozone = nc.Dataset( datapath + 'som_input/ozone_1.9x2.5_L26_2000clim_c091112.nc' + endstr )

#  Dimensions of the ozone file
lat = ozone.variables['lat'][:]
lon = ozone.variables['lon'][:]
lev = ozone.variables['lev'][:]

# Taking annual, zonal average of the ozone data
O3_zon = np.mean( ozone.variables['O3'],axis=(0,3) )

In [21]:
#  make a model on the same grid as the ozone
model3 = climlab.BandRCModel(lev=lev, lat=lat)
insolation = climlab.radiation.DailyInsolation(domains=model3.Ts.domain)
model3.add_subprocess('insolation', insolation)
model3.subprocess.SW.flux_from_space = insolation.insolation
print(model3)


climlab Process of type <class 'climlab.model.column.BandRCModel'>. 
State variables and domain shapes: 
  Ts: (96, 1) 
  Tatm: (96, 26) 
The subprocess tree: 
top: <class 'climlab.model.column.BandRCModel'>
   LW: <class 'climlab.radiation.nband.FourBandLW'>
   SW: <class 'climlab.radiation.nband.ThreeBandSW'>
   insolation: <class 'climlab.radiation.insolation.DailyInsolation'>
   convective adjustment: <class 'climlab.convection.convadj.ConvectiveAdjustment'>
   H2O: <class 'climlab.radiation.water_vapor.ManabeWaterVapor'>


In [22]:
#  Set the ozone mixing ratio
O3_trans = np.transpose(O3_zon)
#  model and ozone data are on the same grid, after the transpose.
print(O3_trans.shape)
print(lev)
print(model3.lev)


(96, 26)
[   3.544638     7.3888135   13.967214    23.944625    37.23029     53.114605
   70.05915     85.439115   100.514695   118.250335   139.115395   163.66207
  192.539935   226.513265   266.481155   313.501265   368.81798    433.895225
  510.455255   600.5242     696.79629    787.70206    867.16076    929.648875
  970.55483    992.5561   ]
[   3.544638     7.3888135   13.967214    23.944625    37.23029     53.114605
   70.05915     85.439115   100.514695   118.250335   139.115395   163.66207
  192.539935   226.513265   266.481155   313.501265   368.81798    433.895225
  510.455255   600.5242     696.79629    787.70206    867.16076    929.648875
  970.55483    992.5561   ]

In [23]:
# Put in the ozone
model3.absorber_vmr['O3'] = O3_trans

In [24]:
print(model3.absorber_vmr['O3'].shape)
print(model3.Tatm.shape)


(96, 26)
(96, 26)

In [25]:
model3.step_forward()

In [26]:
model3.integrate_years(1.)


Integrating for 365 steps, 365.2422 days, or 1.0 years.
/Users/br546577/anaconda3/lib/python3.6/site-packages/climlab/model/column.py:141: RuntimeWarning: divide by zero encountered in true_divide
  self.subprocess['SW'].flux_from_space)
Total elapsed time is 1.0020747876340685 years.

In [27]:
model3.integrate_years(1.)


Integrating for 365 steps, 365.2422 days, or 1.0 years.
/Users/br546577/anaconda3/lib/python3.6/site-packages/climlab/model/column.py:141: RuntimeWarning: divide by zero encountered in true_divide
  self.subprocess['SW'].flux_from_space)
Total elapsed time is 2.0014116660123062 years.

In [28]:
#plt.contour(model3.lat, model3.lev, model3.Tatm.transpose())
plot_temp_section(model3)


This is now working. Will need to do some model tuning.

And start to add dynamics!

Adding meridional diffusion!


In [29]:
print(model2)


climlab Process of type <class 'climlab.model.column.RadiativeConvectiveModel'>. 
State variables and domain shapes: 
  Ts: (90, 1) 
  Tatm: (90, 30) 
The subprocess tree: 
top: <class 'climlab.model.column.RadiativeConvectiveModel'>
   LW: <class 'climlab.radiation.greygas.GreyGas'>
   SW: <class 'climlab.radiation.greygas.GreyGasSW'>
   insolation: <class 'climlab.radiation.insolation.DailyInsolation'>
   convective adjustment: <class 'climlab.convection.convadj.ConvectiveAdjustment'>


In [30]:
diffmodel = climlab.process_like(model2)

In [31]:
# thermal diffusivity in W/m**2/degC
D = 0.05
# meridional diffusivity in 1/s
K = D / diffmodel.Tatm.domain.heat_capacity[0]
print(K)


1.46414342629e-07

In [32]:
d = climlab.dynamics.MeridionalDiffusion(K=K, state={'Tatm': diffmodel.Tatm}, **diffmodel.param)

In [33]:
diffmodel.add_subprocess('diffusion', d)

In [34]:
print(diffmodel)


climlab Process of type <class 'climlab.model.column.RadiativeConvectiveModel'>. 
State variables and domain shapes: 
  Ts: (90, 1) 
  Tatm: (90, 30) 
The subprocess tree: 
top: <class 'climlab.model.column.RadiativeConvectiveModel'>
   LW: <class 'climlab.radiation.greygas.GreyGas'>
   SW: <class 'climlab.radiation.greygas.GreyGasSW'>
   insolation: <class 'climlab.radiation.insolation.DailyInsolation'>
   convective adjustment: <class 'climlab.convection.convadj.ConvectiveAdjustment'>
   diffusion: <class 'climlab.dynamics.diffusion.MeridionalDiffusion'>


In [35]:
diffmodel.step_forward()

In [36]:
diffmodel.integrate_years(1)


Integrating for 365 steps, 365.2422 days, or 1 years.
/Users/br546577/anaconda3/lib/python3.6/site-packages/climlab/model/column.py:141: RuntimeWarning: divide by zero encountered in true_divide
  self.subprocess['SW'].flux_from_space)
Total elapsed time is 3.000748544390544 years.

In [37]:
diffmodel.integrate_years(1)


Integrating for 365 steps, 365.2422 days, or 1 years.
/Users/br546577/anaconda3/lib/python3.6/site-packages/climlab/model/column.py:141: RuntimeWarning: divide by zero encountered in true_divide
  self.subprocess['SW'].flux_from_space)
Total elapsed time is 4.000085422768781 years.

In [38]:
plot_temp_section(model2)
plot_temp_section(diffmodel)


This works as long as K is a constant.

The diffusion operation is broadcast over all vertical levels without any special code.


In [39]:
def inferred_heat_transport( energy_in, lat_deg ):
    '''Returns the inferred heat transport (in PW) by integrating the net energy imbalance from pole to pole.'''
    from scipy import integrate
    from climlab import constants as const
    lat_rad = np.deg2rad( lat_deg )
    return ( 1E-15 * 2 * np.math.pi * const.a**2 * integrate.cumtrapz( np.cos(lat_rad)*energy_in,
            x=lat_rad, initial=0. ) )

In [40]:
#  Plot the northward heat transport in this model
Rtoa = np.squeeze(diffmodel.timeave['ASR'] - diffmodel.timeave['OLR'])
plt.plot(diffmodel.lat, inferred_heat_transport(Rtoa, diffmodel.lat))


Out[40]:
[<matplotlib.lines.Line2D at 0x1298396a0>]

Band model with diffusion


In [41]:
diffband = climlab.process_like(model3)

In [42]:
# thermal diffusivity in W/m**2/degC
D = 0.05
# meridional diffusivity in 1/s
K = D / diffband.Tatm.domain.heat_capacity[0]
print(K)


8.92760732994e-07

In [43]:
d = climlab.dynamics.MeridionalDiffusion(K=K, state={'Tatm': diffband.Tatm}, **diffband.param)
diffband.add_subprocess('diffusion', d)
print(diffband)


climlab Process of type <class 'climlab.model.column.BandRCModel'>. 
State variables and domain shapes: 
  Ts: (96, 1) 
  Tatm: (96, 26) 
The subprocess tree: 
top: <class 'climlab.model.column.BandRCModel'>
   LW: <class 'climlab.radiation.nband.FourBandLW'>
   SW: <class 'climlab.radiation.nband.ThreeBandSW'>
   insolation: <class 'climlab.radiation.insolation.DailyInsolation'>
   convective adjustment: <class 'climlab.convection.convadj.ConvectiveAdjustment'>
   H2O: <class 'climlab.radiation.water_vapor.ManabeWaterVapor'>
   diffusion: <class 'climlab.dynamics.diffusion.MeridionalDiffusion'>


In [44]:
diffband.integrate_years(1)


Integrating for 365 steps, 365.2422 days, or 1 years.
/Users/br546577/anaconda3/lib/python3.6/site-packages/climlab/model/column.py:141: RuntimeWarning: divide by zero encountered in true_divide
  self.subprocess['SW'].flux_from_space)
Total elapsed time is 3.000748544390544 years.

In [45]:
diffband.integrate_years(1)


Integrating for 365 steps, 365.2422 days, or 1 years.
/Users/br546577/anaconda3/lib/python3.6/site-packages/climlab/model/column.py:141: RuntimeWarning: divide by zero encountered in true_divide
  self.subprocess['SW'].flux_from_space)
Total elapsed time is 4.000085422768781 years.

In [46]:
plot_temp_section(model3)
plot_temp_section(diffband)



In [47]:
plt.plot(diffband.lat, diffband.timeave['ASR'] - diffband.timeave['OLR'])


Out[47]:
[<matplotlib.lines.Line2D at 0x129f0ea20>]

In [48]:
#  Plot the northward heat transport in this model
Rtoa = np.squeeze(diffband.timeave['ASR'] - diffband.timeave['OLR'])
plt.plot(diffband.lat, inferred_heat_transport(Rtoa, diffband.lat))


Out[48]:
[<matplotlib.lines.Line2D at 0x129fd3160>]

In [ ]: