Internal wave example

In this example, we initialize an internal wave packet in two-dimensions and watch is propagate.

using Oceananigans, PyPlot, Printf
[ Info: Installing matplotlib via the Conda matplotlib package...
[ Info: Running `conda install -q -y matplotlib` in root environment
Collecting package metadata (current_repodata.json): ...working... done
Solving environment: ...working... done

## Package Plan ##

  environment location: /home/travis/.julia/conda/3

  added / updated specs:
    - matplotlib


The following packages will be downloaded:

    package                    |            build
    ---------------------------|-----------------
    cycler-0.10.0              |           py37_0          13 KB
    dbus-1.13.12               |       h746ee38_0         611 KB
    expat-2.2.6                |       he6710b0_0         146 KB
    fontconfig-2.13.0          |       h9420a91_0         227 KB
    freetype-2.9.1             |       h8a8886c_1         550 KB
    glib-2.63.1                |       h5a9c865_0         3.4 MB
    gst-plugins-base-1.14.0    |       hbbd80ab_1         4.8 MB
    gstreamer-1.14.0           |       hb453b48_1         3.1 MB
    icu-58.2                   |       h9c2bf20_1        10.3 MB
    kiwisolver-1.1.0           |   py37he6710b0_0          82 KB
    libpng-1.6.37              |       hbc83047_0         278 KB
    libuuid-1.0.3              |       h1bed415_2          15 KB
    libxcb-1.13                |       h1bed415_1         421 KB
    libxml2-2.9.9              |       hea5a465_1         1.6 MB
    matplotlib-3.1.1           |   py37h5429711_0         5.0 MB
    pcre-8.43                  |       he6710b0_0         209 KB
    pyparsing-2.4.5            |             py_0          62 KB
    pyqt-5.9.2                 |   py37h05f1152_2         4.5 MB
    python-dateutil-2.8.1      |             py_0         224 KB
    pytz-2019.3                |             py_0         231 KB
    qt-5.9.7                   |       h5867ecd_1        68.5 MB
    sip-4.19.8                 |   py37hf484d3e_0         274 KB
    tornado-6.0.3              |   py37h7b6447c_0         584 KB
    ------------------------------------------------------------
                                           Total:       104.9 MB

The following NEW packages will be INSTALLED:

  cycler             pkgs/main/linux-64::cycler-0.10.0-py37_0
  dbus               pkgs/main/linux-64::dbus-1.13.12-h746ee38_0
  expat              pkgs/main/linux-64::expat-2.2.6-he6710b0_0
  fontconfig         pkgs/main/linux-64::fontconfig-2.13.0-h9420a91_0
  freetype           pkgs/main/linux-64::freetype-2.9.1-h8a8886c_1
  glib               pkgs/main/linux-64::glib-2.63.1-h5a9c865_0
  gst-plugins-base   pkgs/main/linux-64::gst-plugins-base-1.14.0-hbbd80ab_1
  gstreamer          pkgs/main/linux-64::gstreamer-1.14.0-hb453b48_1
  icu                pkgs/main/linux-64::icu-58.2-h9c2bf20_1
  kiwisolver         pkgs/main/linux-64::kiwisolver-1.1.0-py37he6710b0_0
  libpng             pkgs/main/linux-64::libpng-1.6.37-hbc83047_0
  libuuid            pkgs/main/linux-64::libuuid-1.0.3-h1bed415_2
  libxcb             pkgs/main/linux-64::libxcb-1.13-h1bed415_1
  libxml2            pkgs/main/linux-64::libxml2-2.9.9-hea5a465_1
  matplotlib         pkgs/main/linux-64::matplotlib-3.1.1-py37h5429711_0
  pcre               pkgs/main/linux-64::pcre-8.43-he6710b0_0
  pyparsing          pkgs/main/noarch::pyparsing-2.4.5-py_0
  pyqt               pkgs/main/linux-64::pyqt-5.9.2-py37h05f1152_2
  python-dateutil    pkgs/main/noarch::python-dateutil-2.8.1-py_0
  pytz               pkgs/main/noarch::pytz-2019.3-py_0
  qt                 pkgs/main/linux-64::qt-5.9.7-h5867ecd_1
  sip                pkgs/main/linux-64::sip-4.19.8-py37hf484d3e_0
  tornado            pkgs/main/linux-64::tornado-6.0.3-py37h7b6447c_0


Preparing transaction: ...working... done
Verifying transaction: ...working... done
Executing transaction: ...working... done

Numerical, domain, and internal wave parameters

First, we pick some numerical and physical parameters for our model and its rotation rate.

Nx = 128 # resolution
Lx = 2π  # domain extent
6.283185307179586

We set up an internal wave with the pressure field

$ p(x, y, z, t) = a(x, z) cos(kx + mz - ω t) $.

where m is the vertical wavenumber, k is the horizontal wavenumber, ω is the wave frequncy, and a(x, z) is a Gaussian envelope.

# Non-dimensional internal wave parameters
m = 16      # vertical wavenumber
k = 1       # horizontal wavenumber
N = 1       # buoyancy frequency
f = 0.2     # inertial frequency
0.2

A Gaussian wavepacket

Next, we set up an initial condition corresponding to a propagating wave packet with a Gaussian envelope. The internal wave dispersion relation yields

ω² = (N^2 * k^2 + f^2 * m^2) / (k^2 + m^2)

# and thus
ω = sqrt(ω²)
0.20913012351239907

The internal wave polarization relations follow from the linearized Boussinesq equations,

U = k * ω   / (ω^2 - f^2)
V = k * f   / (ω^2 - f^2)
W = m * ω   / (ω^2 - N^2)
B = m * N^2 / (ω^2 - N^2)
-16.731770833333336

Finally, we set-up a small-amplitude, Gaussian envelope for the wave packet

# Some Gaussian parameters
A, x₀, z₀, δ = 1e-9, Lx/2, -Lx/2, Lx/15

# A Gaussian envelope
a(x, z) = A * exp( -( (x - x₀)^2 + (z - z₀)^2 ) / 2δ^2 )
a (generic function with 1 method)

Create initial condition functions

u₀(x, y, z) = a(x, z) * U * cos(k*x + m*z)
v₀(x, y, z) = a(x, z) * V * sin(k*x + m*z)
w₀(x, y, z) = a(x, z) * W * cos(k*x + m*z)
b₀(x, y, z) = a(x, z) * B * sin(k*x + m*z) + N^2 * z
b₀ (generic function with 1 method)

We are now ready to instantiate our model on a uniform grid. We give the model a constant rotation rate with background vorticity f, use temperature as a buoyancy tracer, and use a small constant viscosity and diffusivity to stabilize the model.

model = Model(
        grid = RegularCartesianGrid(size=(Nx, 1, Nx), length=(Lx, Lx, Lx)),
     closure = ConstantIsotropicDiffusivity(ν=1e-6, κ=1e-6),
    coriolis = FPlane(f=f),
     tracers = :b,
    buoyancy = BuoyancyTracer()
)
Oceananigans.Model on a CPU architecture (time = 0.000 ns, iteration = 0) 
├── grid: RegularCartesianGrid{Float64,StepRangeLen{Float64,Base.TwicePrecision{Float64},Base.TwicePrecision{Float64}}}
├── tracers: (:b,)
├── closure: ConstantIsotropicDiffusivity{Float64,NamedTuple{(:b,),Tuple{Float64}}}
├── buoyancy: BuoyancyTracer
├── coriolis: FPlane{Float64}
├── output writers: OrderedCollections.OrderedDict{Symbol,Oceananigans.AbstractOutputWriter} with no entries
└── diagnostics: OrderedCollections.OrderedDict{Symbol,Oceananigans.AbstractDiagnostic} with no entries

We initialize the velocity and buoyancy fields with our internal wave initial condition.

set!(model, u=u₀, v=v₀, w=w₀, b=b₀)

Some plotting utilities

To watch the wave packet propagate interactively as the model runs, we build some plotting utilities.

xplot(u) = repeat(dropdims(xnodes(u), dims=2), 1, u.grid.Nz)
zplot(u) = repeat(dropdims(znodes(u), dims=2), u.grid.Nx, 1)

function plot_field!(ax, w, t)
    pcolormesh(xplot(w), zplot(w), interior(model.velocities.w)[:, 1, :])
    xlabel(L"x")
    ylabel(L"z")
    title(@sprintf("\$ \\omega t / 2 \\pi = %.2f\$", t*ω/2π))
    ax.set_aspect(1)
    pause(0.1)
    return nothing
end

close("all")
fig, ax = subplots();
(PyPlot.Figure(PyObject <Figure size 640x480 with 1 Axes>), PyObject <matplotlib.axes._subplots.AxesSubplot object at 0x7fbf05b6c790>)

A wave packet on the loose

Finally, we release the packet and plot its trajectory:

for i = 1:10
    time_step!(model, Nt = 200, Δt = 0.001 * 2π/ω)
    plot_field!(ax, model.velocities.w, model.clock.time)
end

gcf()

This page was generated using Literate.jl.