The Water Column

import xarray as xr
from matplotlib import pyplot as plt
import numpy as np
import gsw
%matplotlib inline
plt.rcParams['figure.figsize'] = (12,7)
plt.rcParams['font.size'] = 16
plt.rcParams['lines.linewidth'] = 2
from IPython.display import SVG, display, Image, display_svg
import holoviews as hv
hv.extension('bokeh')

Get Some ARGO Data

import fsspec

url = 'https://www.ncei.noaa.gov/data/oceans/argo/gadr/data/atlantic/2015/09/nodc_D1901358_079.nc'
with fsspec.open(url) as fp:
    argo = xr.open_dataset(fp).isel(n_prof=0).load()
argo
<xarray.Dataset>
Dimensions:                       (n_calib: 1, n_history: 4, n_levels: 77, n_param: 3)
Dimensions without coordinates: n_calib, n_history, n_levels, n_param
Data variables: (12/65)
    data_type                     object b'Argo profile    '
    format_version                object b'3.1 '
    handbook_version              object b'1.2 '
    reference_date_time           object b'19500101000000'
    date_creation                 object b'20161104225754'
    date_update                   object b'20170714162347'
    ...                            ...
    parameter                     (n_calib, n_param) object b'PRES           ...
    scientific_calib_equation     (n_calib, n_param) object b'PRES_ADJUSTED (...
    scientific_calib_coefficient  (n_calib, n_param) object b'Surface pressur...
    scientific_calib_comment      (n_calib, n_param) object b'Pressure adjust...
    scientific_calib_date         (n_calib, n_param) object b'20170714162348'...
    crs                           int32 -2147483647
Attributes: (12/49)
    title:                           Argo float vertical profile
    institution:                     CORIOLIS
    source:                          Argo float
    history:                         2018-06-09T01:59:23Z csun convAGDAC.f90 ...
    references:                      http://www.nodc.noaa.gov/argo/
    user_manual_version:             3.1
    ...                              ...
    time_coverage_end:               2015-09-07T12:29:26Z
    time_coverage_duration:          point
    time_coverage_resolution:        point
    gadr_ConventionVersion:          GADR-3.0
    gadr_program:                    convAGDAC.f90
    gadr_programVersion:             1.0
argo['s_a'] = gsw.SA_from_SP(argo.psal, argo.pres, argo.longitude, argo.latitude)
argo['c_t'] = gsw.CT_from_t(argo.s_a, argo.temp, argo.pres)
argo['rho'] = gsw.rho(argo.s_a, argo.c_t, argo.pres)
argo['sig0'] = gsw.sigma0(argo.s_a, argo.c_t)
argo['sig2'] = gsw.sigma2(argo.s_a, argo.c_t)
argo['sig4'] = gsw.sigma4(argo.s_a, argo.c_t)
Nsquared, p_mid = gsw.Nsquared(argo.s_a, argo.c_t, argo.pres)

argo_p = argo.swap_dims({'n_levels': 'pres'})
fig, ax = plt.subplots(ncols=2, figsize=(15,6))
argo_p.temp.plot(y='pres', ax=ax[0], yincrease=False, label='T')
argo_p.c_t.plot(y='pres', ax=ax[0], yincrease=False, label=r'$\Theta$')
ax[0].set_xlabel('[deg. C]')
argo_p.psal.plot(y='pres', ax=ax[1], yincrease=False, label=r'$S_p$')
argo_p.s_a.plot(y='pres', ax=ax[1], yincrease=False, label=r'$S_A$')
ax[1].set_xlabel('[PSU / g/kg]')

[a.set_ylim([2000,0]) for a in ax]
[a.set_ylabel(r'$p$ (dbar)') for a in ax]
[a.legend() for a in ax]
[a.grid() for a in ax]
fig.suptitle('ARGO Float ID %s : %g lon, %g lat' % (argo.id, argo.longitude, argo.latitude))
plt.close()
fig
_images/02-b_the_water_column_8_0.png

Temperature - Salinity Relationship

Used to identify water mass properties.

fig, ax = plt.subplots(figsize=(9,7))
plt.plot(argo.s_a, argo.c_t, c='0.7', zorder=-999)
scat = ax.scatter(argo.s_a, argo.c_t, c=argo.pres)
ax.set_xlabel(r'$S_A$ (g/kg)')
ax.set_ylabel(r'$\Theta$ $^\circ$ C')
plt.colorbar(scat, label='pressure [dbar]')
plt.grid()
plt.close()
fig
_images/02-b_the_water_column_11_0.png

Buoyancy

A water parcel experiences a buoyancy force if its density differs from the ambient density.

buoyancy

Static Stability

Static stability measures how quickly a water parcel is restored to its position in the water column if it is displaced vertically. If the stability is negative, the water column has the potential to overturn.

An obvious, but slightly flawed, measure of stability would be

\[ -\frac{g}{\rho} \frac{\partial \rho}{\partial z} \]

Question: What is wrong with this definition?

Density Profile

In-situ density \(\rho(S_A, \Theta, p)\) is not actually very informative about buoyacy because it mostly shows the adiabatic compressibility of seawater.

fig, ax = plt.subplots()
argo_p.rho.plot(y='pres', yincrease=False, ax=ax)
ax.set_ylim([2000, 0])
ax.set_ylabel(r'$p$ (dbar)')
ax.set_xlabel(r'density (kg m$^{-3}$)')
plt.close()
fig
_images/02-b_the_water_column_16_0.png

Buoyancy Frequency

The problem with the previous definition of stability is that it doesn’t account for the adiabatic compressibility of water. If a parcel is displaced vertically, its pressure will change, causing a change in density. We need to subtract this effect.

\[ N^2 = -g \left ( \frac{1}{\rho}\frac{\partial \rho}{\partial z} - \kappa \frac{\partial p}{\partial z} \right ) = g \left (\alpha^\Theta \frac{\partial \Theta}{\partial z} - \beta^\Theta \frac{\partial S_A}{\partial z} \right ) \]

\(N\) is called the buoyancy frequency because a displaced parcel will oscillated with frequency \(N\). This type of oscillation is called an internal wave. If \(N^2\) is negative, the water column is unstable and will overturn.

fig, ax = plt.subplots()
ax.plot(Nsquared**0.5, p_mid)
ax.set_xlabel(r's$^{-2}$')
ax.set_title('Buoyancy Frequency')
ax.vlines(60**-1, 2000, 0, label='1 minute', color='k')
ax.vlines((60*60)**-1, 2000, 0, label='1 hour', colors='k')
ax.set_ylim([2000, 0])
ax.set_ylabel(r'$p$ (dbar)')
ax.set_xlabel(r'$N$ (s$^{-1}$)')
plt.close()
/tmp/ipykernel_1599/960056500.py:2: RuntimeWarning: invalid value encountered in sqrt
  ax.plot(Nsquared**0.5, p_mid)
fig
_images/02-b_the_water_column_19_0.png

Potential Density

To eliminate the effect of adiabatic compressibility, we can calculate the denisty the water would have if brought to some reference pressure \(p_{ref}\). This is called potential density, defined as

\[ \sigma = \rho(S_A, \Theta, p_{ref}) - 1000 \]

Because \(\sigma\) is only a function of quasi-conservative quantities (\(S_A\) and \(\Theta\)) it is itself quasi-conservative.

Near the reference pressure, it is the case that $\( N^2 \simeq -\frac{g}{\rho} \frac{\partial \sigma}{\partial z} \)$ but, due to the nonlinearity in the equation of state, this is not true far from the reference pressure.

It is common to denote the reference pressure using a subscript: \(\sigma_0\) (0 dbar), \(\sigma_2\) (2000 dbar), and \(\sigma_4\) (4000 dbar).

fig, ax = plt.subplots()
(argo_p.rho-1000).plot(y='pres', yincrease=False, label=r'$\rho - 1000$')
argo_p.sig0.plot(y='pres', yincrease=False, label=r'$\sigma_0$')
argo_p.sig2.plot(y='pres', yincrease=False, label=r'$\sigma_2$')
argo_p.sig4.plot(y='pres', yincrease=False, label=r'$\sigma_4$')
ax.set_ylim([2000, 0])
ax.set_ylabel(r'$p$ (dbar)')
ax.set_xlabel(r'density (kg m$^{-3}$)')
ax.legend(frameon=True, loc='lower right')
plt.close()
fig
_images/02-b_the_water_column_23_0.png
fig, ax = plt.subplots()
(argo_p.rho-argo_p.rho[0]).plot(y='pres', yincrease=False, label=r'$\Delta \rho$')
(argo_p.sig0-argo_p.sig0[0]).plot(y='pres', yincrease=False, label=r'$\Delta \sigma_0$')
(argo_p.sig2-argo_p.sig2[0]).plot(y='pres', yincrease=False, label=r'$\Delta \sigma_2$')
(argo_p.sig4-argo_p.sig4[0]).plot(y='pres', yincrease=False, label=r'$\Delta \sigma_4$')
ax.set_ylim([2000, 0])
ax.set_ylabel(r'$p$ (dbar)')
ax.set_xlabel(r'density difference (kg m$^{-3}$)')
ax.legend(frameon=True, loc='upper right')
plt.close()
fig
_images/02-b_the_water_column_25_0.png