# MeridionalMoistDiffusion¶

Solver for the 1D meridional moist static energy diffusion equation on the sphere:

$C\frac{\partial}{\partial t} T(\phi,t) = \frac{1}{\cos\phi} \frac{\partial}{\partial \phi} \left[ \cos\phi ~ D ~(1+f(T))~ \frac{\partial T}{\partial \phi} \right]$

where $$f(T)$$ is a temperature-dependent moisture amplification factor given by

$f(T) = \frac{L^2 r q^*(T)}{c_p R_v T^2}$

which expresses the effect of latent heat on the near-surface moist static energy, where $$q^*(T)$$ is the saturation specific humidity at temperature $$T$$ and $$r$$ is a relative humidity.

This class operates identically to MeridionalHeatDiffusion but calculates $$f$$ automatically at each timestep and applies it to the diffusivity.

The magnitude of the moisture amplification is controlled by the input parameter relative_humidity (i.e. $$r$$ in the equation above).

It can be used to implement a modified Energy Balance Model accounting for the effects of moisture on the heat transport efficiency.

## Derivation of the moist diffusion equation¶

Assume that heat transport is down the gradient of moist static energy $$m = c_p T + L q + g Z$$

For an EBM we want to parameterize everything in terms of a surface temperature $$T_s$$. So we write $$m_s = c_p T_s + L r q^*(T_s)$$, where $$m_s$$ is the moist static energy of near-surface air parcels, $$r$$ is a near-surface relative humidity, and $$q^*$$ is the saturation specific humidity at a reference surface pressure.

Now express this quantity in temperature units by defining a moist temperature

$T_m = \frac{m_s}{c_p} = T_s + \frac{L r}{c_p} q^*(T_s)$

$$T_m$$ is the temperature a dry air parcel would have that has the same total enthalpy as a moist air parcel at temperature $$T_s$$

The down-gradient heat transport parameterization can then be written

$\mathcal{H} = -2 \pi a^2 D_m \frac{\partial T_m}{\partial \phi}$

where $$D_m$$ is the thermal diffusion coefficient for this moist model, in units of W/m2/K.

The equation we are trying to solve is thus

$C \frac{\partial T_s}{\partial t} = \frac{1}{\cos\phi} \frac{\partial}{\partial \phi} \left( \cos\phi D_m \frac{\partial T_m}{\partial \phi} \right)$

which we can write in terms of $$T_s$$ only by substituting in for $$T_m$$:

$C \frac{\partial T_s}{\partial t} = \frac{1}{\cos\phi} \frac{\partial}{\partial \phi} \left( \cos\phi D_m \left(\frac{\partial T_s}{\partial \phi} + \frac{\partial}{\partial \phi} \left(\frac{L r}{c_p} q^*(T_s)\right)\right)\right)$

If we make the simplifying assumption that the relative humidity :math:r is constant (not a function of latitude), then

$C \frac{\partial T_s}{\partial t} = \frac{1}{\cos\phi} \frac{\partial}{\partial \phi} \left( \cos\phi D_m \left(\frac{\partial T_s}{\partial \phi} + \frac{L r}{c_p} \frac{\partial q^*}{\partial \phi} \right)\right)$

To a good approximation (see Hartmann’s book and others), the Clausius-Clapeyron relation for saturation specific humidity gives

$\frac{\partial q^*}{dT} = \frac{L}{R_v T^2} q^*(T)$

Then using a chain rule we have

$\frac{\partial q^*}{\partial \phi} = \frac{\partial q^*}{\partial T_s} \frac{\partial T_s}{\partial \phi} = \frac{L q^*(T_s)}{R_v T_s^2} \frac{\partial T_s}{\partial \phi}$

Plugging this into our model equation we get

$C \frac{\partial T_s}{\partial t} = \frac{1}{\cos\phi} \frac{\partial}{\partial \phi} \left( \cos\phi D_m \frac{\partial T_s}{\partial \phi} \left(1 + \frac{L^2 r q^*(T_s)}{c_p R_v T_s^2} \right)\right)$

This is now in a form that is compatible with our diffusion solver.

Just let

$D = D_m \left( 1 + f(T_s) \right)$

where

$f(T_s) = \frac{L^2 r q^*(T_s)}{c_p R_v T_s^2}$

or, equivalently,

$f(T_s) = \frac{L r }{c_p} \frac{\partial q^*}{dT}\bigg|_{T_s}$

Given a temperature distribution $$T_s(\phi)$$ at any given time, we can calculate the diffusion coefficient $$D(\phi)$$ from this formula.

This calculation is implemented in the MeridionalMoistDiffusion class.

class climlab.dynamics.meridional_moist_diffusion.MeridionalMoistDiffusion(D=0.24, relative_humidity=0.8, **kwargs)[source]
Attributes
D
K
depth

Depth at grid centers (m)

depth_bounds

Depth at grid interfaces (m)

diagnostics

input

lat

Latitude of grid centers (degrees North)

lat_bounds

Latitude of grid interfaces (degrees North)

lev

Pressure levels at grid centers (hPa or mb)

lev_bounds

Pressure levels at grid interfaces (hPa or mb)

lon

Longitude of grid centers (degrees)

lon_bounds

Longitude of grid interfaces (degrees)

timestep

The amount of time over which step_forward() is integrating in unit seconds.

Methods

 add_diagnostic(name[, value]) Create a new diagnostic variable called name for this process and initialize it with the given value. add_input(name[, value]) Create a new input variable called name for this process and initialize it with the given value. add_subprocess(name, proc) Adds a single subprocess to this process. add_subprocesses(procdict) Adds a dictionary of subproceses to this process. compute() Computes the tendencies for all state variables given current state and specified input. compute_diagnostics([num_iter]) Compute all tendencies and diagnostics, but don’t update model state. declare_diagnostics(diaglist) Add the variable names in inputlist to the list of diagnostics. declare_input(inputlist) Add the variable names in inputlist to the list of necessary inputs. integrate_converge([crit, verbose]) Integrates the model until model states are converging. integrate_days([days, verbose]) Integrates the model forward for a specified number of days. integrate_years([years, verbose]) Integrates the model by a given number of years. remove_diagnostic(name) Removes a diagnostic from the process.diagnostic dictionary and also delete the associated process attribute. remove_subprocess(name[, verbose]) Removes a single subprocess from this process. set_state(name, value) Sets the variable name to a new state value. set_timestep([timestep, num_steps_per_year]) Calculates the timestep in unit seconds and calls the setter function of timestep() step_forward() Updates state variables with computed tendencies. to_xarray([diagnostics]) Convert process variables to xarray.Dataset format.
_implicit_solver()[source]

Invertes and solves the matrix problem for diffusion matrix and temperature T.

The method is called by the _compute() function of the ImplicitProcess class and solves the matrix problem

$A \cdot T_{\textrm{new}} = T_{\textrm{old}}$

for diffusion matrix A and corresponding temperatures. $$T_{\textrm{old}}$$ is in this case the current state variable which already has been adjusted by the explicit processes. $$T_{\textrm{new}}$$ is the new state of the variable. To derive the temperature tendency of the diffusion process the adjustment has to be calculated and muliplied with the timestep which is done by the _compute() function of the ImplicitProcess class.

This method calculates the matrix inversion for every state variable and calling either solve_implicit_banded() or numpy.linalg.solve() dependent on the flag self.use_banded_solver.

Variables
• state (dict) – method uses current state variables but does not modify them

• use_banded_solver (bool) – input flag whether to use _solve_implicit_banded() or numpy.linalg.solve() to do the matrix inversion

• _diffTriDiag (array) – the diffusion matrix which is given with the current state variable to the method solving the matrix problem

_update_diffusivity()[source]
climlab.dynamics.meridional_moist_diffusion.moist_amplification_factor(Tkelvin, relative_humidity=0.8)[source]

Compute the moisture amplification factor for the moist diffusivity given relative humidity and reference temperature profile.