Basic Equations

This module solves two-dimensional incompressible Navier-Stokes equations using the vorticity-streamfunction formulation. The flow $\bm{u} = (u, v)$ is obtained through a streamfunction $\psi$ as $(u, v) = (-\partial_y \psi, \partial_x \psi)$. The only non-zero component of vorticity is that normal to the plane of motion, $\partial_x v - \partial_y u = \nabla^2 \psi$. The module solves the two-dimensional vorticity equation:

\[\partial_t \zeta + \mathsf{J}(\psi, \zeta) = \underbrace{-\left [ \mu (-\nabla^2)^{n_\mu} + \nu (-\nabla^2)^{n_\nu} \right ] \zeta}_{\textrm{dissipation}} + F ,\]

where $\mathsf{J}(\psi, \zeta) = (\partial_x \psi)(\partial_y \zeta) - (\partial_y \psi)(\partial_x \zeta)$ is the two-dimensional Jacobian and $F(x, y, t)$ is forcing. The Jacobian term is the advection of relative vorticity, $\mathsf{J}(ψ, ζ) = \bm{u \cdot \nabla} \zeta$. Both $ν$ and $μ$ terms are viscosities; typically the former is chosen to act at small scales ($n_ν ≥ 1$), while the latter at large scales ($n_ν ≤ 0$). Plain old viscocity corresponds to $n_ν=1$ while $n_μ=0$ corresponds to linear drag. Values of $n_ν ≥ 2$ or $n_μ ≤ -1$ are referred to as hyper- or hypo-viscosities, respectively.


The equation is time-stepped forward in Fourier space:

\[\partial_t \widehat{\zeta} = - \widehat{\mathsf{J}(\psi, \zeta)} - \left ( \mu |𝐤|^{2n_\mu} + \nu |𝐤|^{2n_\nu} \right ) \widehat{\zeta} + \widehat{F} .\]

The state variable sol is the Fourier transform of vorticity, ζh.

The Jacobian is computed in the conservative form: $\mathsf{J}(a, b) = \partial_y [(\partial_x a) b] - \partial_x[(\partial_y a) b]$.

The linear operator is constructed in Equation

Equation(params, grid)

Return the equation for two-dimensional Navier-Stokes with params and grid. The linear operator $L$ includes (hyper)-viscosity of order $n_ν$ with coefficient $ν$ and hypo-viscocity of order $n_μ$ with coefficient $μ$,

\[L = - ν |𝐤|^{2 n_ν} - μ |𝐤|^{2 n_μ} .\]

Plain old viscocity corresponds to $n_ν=1$ while $n_μ=0$ corresponds to linear drag.

The nonlinear term is computed via the function calcN!.


The nonlinear terms are computed via

which in turn calls calcN_advection! and addforcing!.

Parameters and Variables

All required parameters are included inside Params and all module variables are included inside Vars.

For decaying case (no forcing, $F=0$), vars can be constructed with Vars. For the forced case ($F \ne 0$) the vars struct is with ForcedVars or StochasticForcedVars.

Helper functions

Some helper functions included in the module are:


Some useful diagnostics are:


Return the domain-averaged kinetic energy. Since $u² + v² = |{\bf ∇} ψ|²$, the domain-averaged kinetic energy is

\[\int \frac1{2} |{\bf ∇} ψ|² \frac{𝖽x 𝖽y}{L_x L_y} = \sum_{𝐤} \frac1{2} |𝐤|² |ψ̂|² .\]


Other diagnostic include: energy_dissipation, energy_work, enstrophy_dissipation, and enstrophy_work.