Skip to content

Governing Equations

This page describes the fundamental equations solved by NeuralPOM, a neural differentiable implementation of the Princeton Ocean Model (POM). The model solves the three-dimensional primitive equations under the Boussinesq and hydrostatic approximations on a terrain-following sigma vertical coordinate system.


Boussinesq Approximation

The Boussinesq approximation simplifies the Navier-Stokes equations by assuming that density variations are small relative to the background density ρ0, and can therefore be neglected except in the buoyancy term of the vertical momentum equation. Formally:

ρ=ρ0+ρ(x,y,z,t),|ρ|ρ0

The reference density ρ0=1000 kg/m3 is used throughout. Density anomalies are handled by the equation of state, and the density field contributes only to the baroclinic pressure gradient and buoyancy production in the turbulence closure.


Primitive Equations on a Rotating Sphere

Horizontal Momentum Equations

The momentum balance on a rotating Earth (on an f-plane or β-plane) governs the evolution of the horizontal velocity components (u,v):

ut+vufv=1ρ0px+z(KMuz)+Fuvt+vv+fu=1ρ0py+z(KMvz)+Fv

where:

SymbolDescription
u,vHorizontal velocity components in the x (eastward) and y (northward) directions
fCoriolis parameter; f=2Ωsinϕ on a sphere, linear f=f0+βy on a β-plane
ρ0Reference density (1000 kg/m3)
pPressure
KMVertical eddy viscosity (from Mellor-Yamada 2.5 closure)
Fu,FvHorizontal mixing terms (Smagorinsky or constant Laplacian diffusion)
vThree-dimensional advection operator: ux+vy+wz

In the code, these equations are implemented in advu and advv (momentum.py), where the terms are assembled as:

python
uf = advx + vert_div + coriolis + press_grad + drhox

The time discretization uses a leapfrog scheme:

python
uf[s_i, s_j, k_range] = (term_old - 2.0 * dti2 * uf[s_i, s_j, k_range]) / (denom + 1e-20)

where term_old represents Dn1un1, dti2 is 2Δt, and denom is Dn+1 (the total depth at the new time level).

Hydrostatic Approximation

In ocean circulation, the vertical scale of motion (H102--103 m) is much smaller than the horizontal scale (L104--106 m). The hydrostatic approximation therefore replaces the vertical momentum equation with:

pz=ρg

This yields the vertical distribution of pressure by integration from the surface:

p(z)=patm+ρ0gη+gzηρdz

The pressure gradient is decomposed into barotropic (surface slope) and baroclinic (density) components:

1ρ0hp=ghηgρ0hzηρdz

In the code, the baroclinic pressure gradient is computed in baropg() through vertical integration of density gradients with sigma-coordinate correction terms.

Continuity Equation

The continuity equation under the Boussinesq approximation reduces to volume conservation:

ux+vy+wz=0

After sigma-coordinate transformation (see below), this becomes the equation for the free surface elevation η.


Temperature and Salinity Conservation

The scalar transport equations for potential temperature T and salinity S are:

Tt+vT=z(KHTz)+FTSt+vS=z(KHSz)+FS

where:

SymbolDescription
TPotential temperature
SSalinity (psu)
KHVertical eddy diffusivity (from turbulence closure)
FT,FSHorizontal mixing terms

These are solved using a conservative flux-form centered-difference scheme (advt1) or the Smolarkiewicz iterative upstream scheme (advt2) to suppress numerical diffusion. Vertical diffusion is solved implicitly via a Thomas algorithm in proft().


Equation of State

NeuralPOM implements the Mellor (1991) seawater equation of state. The density is computed as a function of potential temperature, salinity, and pressure:

ρ=ρ(T,S,p)

The computation in dens() follows the polynomial form:

python
# Atmospheric pressure contribution
rhor = -0.157406 + 6.793952e-2 * tr - 9.095290e-3 * tr^2
     + 1.001685e-4 * tr^3 - 1.120083e-6 * tr^4 + 6.536332e-9 * tr^5

# Salinity contribution
rhor += (0.824493 - 4.0899e-3 * tr + 7.6438e-5 * tr^2
         - 8.2467e-7 * tr^3 + 5.3875e-9 * tr^4) * sr

# Salinity^1.5 terms
rhor += (-5.72466e-3 + 1.0227e-4 * tr - 1.6546e-6 * tr^2) * |sr|^{1.5}

# Salinity^2 terms
rhor += 4.8314e-4 * sr^2

The pressure correction uses the speed of sound cs:

ρ=ρ0+105pcs2(12pcs2)

The final density anomaly is output as (ρ1000)/ρref:

python
self.rho[:, :, k_sl] = (rhor / self.rhoref) * _b(self.fsm)

Sigma-Coordinate Transformation

The vertical coordinate is transformed from the physical vertical coordinate z to the terrain-following sigma coordinate σ:

σ=zηH+η,1σ0

where:

SymbolDescription
zPhysical vertical coordinate (positive upward, z=0 at mean sea level)
η(x,y,t)Free surface elevation
H(x,y)Resting water depth
σSigma coordinate (σ=0 at surface, σ=1 at bottom)

This transformation maps the variable ocean domain to a fixed computational domain, simplifying the implementation of surface and bottom boundary conditions. The sigma levels are defined through the z and zz arrays:

python
# z(k): vertical position of sigma level k
# zz(k): vertical spacing between sigma levels (for finite differences)

The transformation introduces metric correction terms in the baroclinic pressure gradient computation to avoid the "sigma coordinate pressure gradient error" over steep topography.


Vertical Boundary Conditions

Surface Boundary Conditions

Momentum (wind stress):

KMuz|z=η=τsxρ0,KMvz|z=η=τsyρ0

where τsx,τsy are the surface wind stress components provided by wusurf and wvsurf.

Tracers (surface heat and freshwater flux):

KHTz|z=η=Qnetρ0cp,KHSz|z=η=S0(EP)

Turbulence (boundary conditions for q2):

Surface boundary condition for TKE is proportional to the friction velocity u:

q2|z=η=(15.8Cbc)2/3u2

Bottom Boundary Conditions

Momentum (bottom friction):

KMuz|z=H=Cd|vb|ub,KMvz|z=H=Cd|vb|vb

where Cd is the bottom drag coefficient (cbc), and |vb| is the bottom velocity magnitude. The implementation in profu/profv computes:

python
mag_vel = safe_sqrt(u_sq + v_avg_sq)
tps_local[s_i_in, s_j_in] = cbc_avg * mag_vel
wubot[s_i_in, s_j_in] = -tps_local[s_i_in, s_j_in] * uf_bot_slice

Turbulence:

Bottom boundary condition for q2l:

q2l|z=H=0

Numerical Framework

Spatial Discretization

NeuralPOM uses the Arakawa C-grid on a curvilinear orthogonal horizontal grid:

  • u and v velocity components are staggered with respect to the tracer/scalar grid
  • aru and arv are area factors at u and v points
  • dt (the metric factor) represents gxx at tracer points
  • dx, dy are grid spacing arrays

Temporal Discretization

The model uses a leapfrog time integration scheme with an Asselin time filter to suppress the computational mode. The baroclinic and barotropic modes are split, with the barotropic time step typically much smaller (see Barotropic-Baroclinic Mode Splitting).

Python Implementation

The governing equations are implemented as PyTorch tensor operations in the following modules:

ModuleFileContents
MomentumMixinmomentum.pyadvu, advv, profu, profv, dens, baropg
BaroclinicMixinbaroclinic.pyadvct (horizontal momentum advection)
TracersMixintracers.pyadvt1, advt2, proft, smol_adif

All tensor operations are fully differentiable, enabling gradient-based optimization and neural network coupling.

Released under the MIT License.