Wave length

This is a script I have had to write at different times and in different tools in the past — either to figure out the depth type or when requiring appropriate wave length(s) to calculate hydrostatic pressure. Here’s hoping this will be the last.

For background, dispersion relation1, which expresses wave length (λ)2 in terms of wave number (\( \kappa = \frac{2\pi}{\lambda} \)) and angular wave frequency (\( \omega = \frac{2\pi}{T} \)) is as follows:

$$ \frac{\omega^2}{g} = \kappa \tanh(\kappa d) $$

When \( \lim_{d\to\infty} \tanh(\kappa d) \approx 1 \), it reduces the expression to:

$$ \lambda = \frac{2\pi g}{\omega^2} $$

For practical purposes, water depth (d) is considered deep when d/λ ≥ 0.5. In other words,

$$ \lambda_d = \frac{2 \pi g}{\omega^2} = \frac{gT^2}{2\pi} $$

For shallow water depth (i.e., d/λ ≤ 0.05), wave length is expressed as:

$$ \lambda_s = T \sqrt{gd} $$

This is because \( \lim_{d\to 0} \tanh(\kappa d) \approx \kappa d \). For intermediate water depth (i.e., 0.05 < d/λ < 0.5), wave length can be expressed as:

$$ \lambda_{i} = \lambda_d \sqrt{\tanh\left({\frac{2 \pi d}{\lambda_d}}\right)} $$

Turning this above into code for a list of wave periods:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""Determine water depth type and corresponding wave length
wavelength.py -- 2020 ckunte
"""
import numpy as np

g = 9.81  # Acceleration due to gravity (m/s^2)


def L_d(d, T):
    return list(map(lambda x: g * x ** 2 / (2 * np.pi), T))


def L_s(d, T):
    return list(map(lambda x: x * np.sqrt(g * d), T))


def L_i(d, T):
    return list(
        map(
            lambda x: x * np.sqrt(np.tanh(2 * np.pi * d / x)),
            L_d(d, T),
        )
    )


def typ_check(d, T):
    # Get all wave lengths in to one list
    L_all = [L_d(d, T), L_s(d, T), L_i(d, T)]
    # Collapse all sublists into one list, L
    L = [item for sublist in L_all for item in sublist]
    # Water depth to wave length ratio, r
    r = list(map(lambda x: d / x, L))
    # Depth type check and append `typ_all` list
    typ_all = []
    for item in r:
        if item >= 0.5:
            typ = "Deep"
            typ_all.append(typ)
        elif item <= 0.05:
            typ = "Shallow"
            typ_all.append(typ)
        elif 0.05 < item < 0.5:
            typ = "Intermediate"
            typ_all.append(typ)
        else:
            print("No depth type criteria found.")
        pass
    # Check type by majority
    typ = max(typ_all, key=typ_all.count)
    return typ


def wavelength(d, T):
    typ = typ_check(d, T)
    print("Water depth type (by majority):", typ)
    # Print wave lengths
    if typ == "Deep":
        return print("Wave length, Ld:", L_d(d, T))
    elif typ == "Shallow":
        return print("Wave length, Ls:", L_s(d, T))
    elif typ == "Intermediate":
        return print("Wave length, Li:", L_i(d, T))
    else:
        return print("d/T ratio does not match a criteria.")


def main():
    # -- BEGIN USER INPUTS --
    d = 171.18  # Water depth (m)
    T = [9.4, 11.5, 12.0]  # Wave periods (s)
    # -- END of USER INPUTS --
    print("Water depth:", d)
    print("Wave periods:", T)
    wavelength(d, T)
    pass


if __name__ == "__main__":
    main()

When run, it produces this:

$ python3 wavelength.py
Water depth: 171.18
Wave periods: [9.4, 11.5, 12.0]
Water depth type (by majority): Deep
Wave length, Ld: [137.9573508693948, 206.48324640649003, 224.82863880933505]

I may not have said this before but the other reason I write any of these is (a) to force myself to think in abstractions, and (b) to try and capture good known programming practice(s) (to me) at any moment in time, which a cursory view may not necessarily reveal. Note for instance, this script contains functional programming bits discussed earlier, and a succinct snippet to collapse sublists into one.


  1. Dispersion relation (eq. 24), Wave and Wave Effects (pp. 240–246), J.N. Newman, Marine Hydrodynamics, The MIT Press, 1977. 

  2. λ is not to be confused with lambda the anonymous function in python programming language.