CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-seawater

Python implementation of the CSIRO seawater toolbox for calculating properties of sea water using EOS-80 equation of state

Pending
Overview
Eval results
Files

auxiliary.mddocs/

Auxiliary Functions

Additional oceanographic calculations including geographic distance computations, gas solubilities, Coriolis effects, and wave velocities. These functions complement the core EOS-80 calculations for comprehensive marine environment analysis.

Capabilities

Geographic Distance and Navigation

Distance and bearing calculations on Earth's surface using great circle methods.

def dist(lat, lon, units="km"):
    """
    Distance between geographic positions and phase angle.
    
    Calculates great circle distance and initial bearing between
    geographic coordinates using spherical Earth approximation.
    
    Parameters:
    - lat: array_like, latitude coordinates [decimal degrees]
    - lon: array_like, longitude coordinates [decimal degrees]  
    - units: str, distance units ("km" or "nm"), default "km"
    
    Returns:
    - tuple: (distance, phase_angle)
        - distance: array_like, great circle distance [km or nm]
        - phase_angle: array_like, initial bearing [degrees]
    """

Coriolis Effect

Earth rotation effects on ocean and atmospheric motion.

def f(lat):
    """
    Coriolis parameter (Coriolis frequency).
    
    Calculates the Coriolis parameter which represents the component
    of Earth's rotation affecting horizontal motion at given latitude.
    
    Parameters:
    - lat: array_like, latitude [decimal degrees]
    
    Returns:
    - array_like: Coriolis parameter [s⁻¹]
    """

Gas Solubilities

Solubility of atmospheric gases in seawater.

def satO2(s, t):
    """
    Oxygen solubility in seawater.
    
    Calculates equilibrium dissolved oxygen concentration in seawater
    at atmospheric pressure using Weiss (1970) equations.
    
    Parameters:
    - s: array_like, salinity [psu (PSS-78)]
    - t: array_like, temperature [°C (ITS-90)]
    
    Returns:
    - array_like: oxygen solubility [ml/l]
    """

def satN2(s, t):
    """
    Nitrogen solubility in seawater.
    
    Calculates equilibrium dissolved nitrogen concentration in seawater
    at atmospheric pressure.
    
    Parameters:
    - s: array_like, salinity [psu (PSS-78)]
    - t: array_like, temperature [°C (ITS-90)]
    
    Returns:
    - array_like: nitrogen solubility [ml/l]
    """

def satAr(s, t):
    """
    Argon solubility in seawater.
    
    Calculates equilibrium dissolved argon concentration in seawater
    at atmospheric pressure.
    
    Parameters:
    - s: array_like, salinity [psu (PSS-78)]
    - t: array_like, temperature [°C (ITS-90)]
    
    Returns:
    - array_like: argon solubility [ml/l]
    """

Surface Wave Velocity

Surface wave propagation calculations.

def swvel(length, depth):
    """
    Surface wave velocity using shallow/deep water approximations.
    
    Calculates phase velocity of surface gravity waves based on
    wavelength and water depth using linear wave theory.
    
    Parameters:
    - length: array_like, wavelength [m]
    - depth: array_like, water depth [m]
    
    Returns:
    - array_like: wave phase velocity [m/s]
    """

Usage Examples

Geographic Distance Calculations

import seawater as sw
import numpy as np

# Define oceanographic station positions
# Station coordinates (lat, lon in decimal degrees)
stations = {
    'A': (35.0, -75.0),   # Off Cape Hatteras
    'B': (40.0, -70.0),   # Georges Bank
    'C': (45.0, -65.0),   # Nova Scotia shelf
}

# Calculate distances between all station pairs
station_names = list(stations.keys())
coords = list(stations.values())

print("Distance matrix between stations:")
print("     ", end="")
for name in station_names:
    print(f"{name:>8}", end="")
print()

for i, (name1, (lat1, lon1)) in enumerate(stations.items()):
    print(f"{name1:>4} ", end="")
    for j, (name2, (lat2, lon2)) in enumerate(stations.items()):
        if i <= j:
            # Calculate distance
            lats = np.array([lat1, lat2])
            lons = np.array([lon1, lon2])
            distance, bearing = sw.dist(lats, lons, units="km")
            
            if i == j:
                print(f"{'0':>8}", end="")
            else:
                print(f"{distance[1]:.0f}km", end="")
        else:
            print(f"{'':>8}", end="")
    print()

# Calculate bearing from Station A to Station B
lat_ab = np.array([35.0, 40.0])
lon_ab = np.array([-75.0, -70.0])
dist_ab, bearing_ab = sw.dist(lat_ab, lon_ab)
print(f"\\nA→B: {dist_ab[1]:.1f} km at bearing {bearing_ab[1]:.1f}°")

Coriolis Parameter Analysis

import seawater as sw
import numpy as np
import matplotlib.pyplot as plt

# Calculate Coriolis parameter across latitudes
latitudes = np.linspace(-90, 90, 181)
coriolis = sw.f(latitudes)

# Key oceanographic latitudes
key_lats = [-60, -30, 0, 30, 60]  # Southern Ocean, Subtropics, Equator, etc.
key_f = sw.f(key_lats)

print("Coriolis parameter at key latitudes:")
lat_names = ["60°S", "30°S", "Equator", "30°N", "60°N"]
for name, lat, f_val in zip(lat_names, key_lats, key_f):
    print(f"{name:>8}: f = {f_val:.2e} s⁻¹")

# Rossby radius calculation example (first baroclinic mode)
# Typical values for mid-latitude ocean
N = 5e-3  # Brünt-Väisälä frequency [rad/s]
H = 1000  # depth scale [m]
f_30N = sw.f(30)  # Coriolis at 30°N

rossby_radius = N * H / abs(f_30N) / 1000  # convert to km
print(f"\\nTypical Rossby radius at 30°N: {rossby_radius:.0f} km")

# Plot Coriolis parameter
plt.figure(figsize=(10, 6))
plt.plot(latitudes, coriolis * 1e4, 'b-', linewidth=2)
plt.axhline(0, color='k', linestyle='--', alpha=0.5)
plt.xlabel('Latitude (°)')
plt.ylabel('Coriolis Parameter (×10⁻⁴ s⁻¹)')
plt.title('Coriolis Parameter vs Latitude')
plt.grid(True, alpha=0.3)
plt.xlim(-90, 90)

# Mark key latitudes
for lat, f_val, name in zip(key_lats, key_f, lat_names):
    plt.plot(lat, f_val * 1e4, 'ro', markersize=8)
    plt.annotate(name, (lat, f_val * 1e4), xytext=(5, 5), 
                textcoords='offset points', fontsize=9)

plt.tight_layout()
plt.show()

Gas Solubility Analysis

import seawater as sw
import numpy as np
import matplotlib.pyplot as plt

# Temperature and salinity ranges for gas solubility analysis
temperatures = np.linspace(0, 30, 31)  # 0-30°C
salinities = [0, 20, 35]  # Fresh, brackish, seawater

plt.figure(figsize=(15, 5))

# Plot oxygen solubility
plt.subplot(1, 3, 1)
for s in salinities:
    o2_sol = sw.satO2(s, temperatures)
    plt.plot(temperatures, o2_sol, label=f'S = {s} psu', linewidth=2)
plt.xlabel('Temperature (°C)')
plt.ylabel('O₂ Solubility (ml/l)')
plt.title('Oxygen Solubility')
plt.legend()
plt.grid(True, alpha=0.3)

# Plot nitrogen solubility
plt.subplot(1, 3, 2)
for s in salinities:
    n2_sol = sw.satN2(s, temperatures)
    plt.plot(temperatures, n2_sol, label=f'S = {s} psu', linewidth=2)
plt.xlabel('Temperature (°C)')
plt.ylabel('N₂ Solubility (ml/l)')
plt.title('Nitrogen Solubility')
plt.legend()
plt.grid(True, alpha=0.3)

# Plot argon solubility
plt.subplot(1, 3, 3)
for s in salinities:
    ar_sol = sw.satAr(s, temperatures)
    plt.plot(temperatures, ar_sol, label=f'S = {s} psu', linewidth=2)
plt.xlabel('Temperature (°C)')
plt.ylabel('Ar Solubility (ml/l)')
plt.title('Argon Solubility')
plt.legend()
plt.grid(True, alpha=0.3)

plt.tight_layout()
plt.show()

# Calculate gas ratios at standard conditions
std_temp, std_sal = 20.0, 35.0  # Standard seawater conditions
o2_std = sw.satO2(std_sal, std_temp)
n2_std = sw.satN2(std_sal, std_temp)
ar_std = sw.satAr(std_sal, std_temp)

print(f"Gas solubilities at {std_temp}°C, {std_sal} psu:")
print(f"O₂: {o2_std:.2f} ml/l")
print(f"N₂: {n2_std:.2f} ml/l")
print(f"Ar: {ar_std:.3f} ml/l")
print(f"N₂/Ar ratio: {n2_std/ar_std:.1f}")

Surface Wave Analysis

import seawater as sw
import numpy as np
import matplotlib.pyplot as plt

# Wave analysis for different water depths and wavelengths
wavelengths = np.logspace(0, 3, 100)  # 1 m to 1000 m
depths = [5, 20, 100, 1000]  # Shallow to deep water

plt.figure(figsize=(12, 8))

# Plot wave velocity vs wavelength for different depths
plt.subplot(2, 2, 1)
for depth in depths:
    velocities = sw.swvel(wavelengths, depth)
    plt.loglog(wavelengths, velocities, label=f'h = {depth} m', linewidth=2)

# Add deep water limit (c = sqrt(g*L/(2*pi)))
g = 9.81
c_deep = np.sqrt(g * wavelengths / (2 * np.pi))
plt.loglog(wavelengths, c_deep, 'k--', label='Deep water limit', alpha=0.7)

plt.xlabel('Wavelength (m)')
plt.ylabel('Phase Velocity (m/s)')
plt.title('Wave Velocity vs Wavelength')
plt.legend()
plt.grid(True, alpha=0.3)

# Plot wave velocity vs depth for fixed wavelengths
plt.subplot(2, 2, 2)
depths_fine = np.logspace(0, 3, 100)  # 1 m to 1000 m depth
wave_lengths = [10, 50, 200]  # Different wavelengths

for wl in wave_lengths:
    velocities = sw.swvel(wl, depths_fine)
    plt.semilogx(depths_fine, velocities, label=f'λ = {wl} m', linewidth=2)

plt.xlabel('Water Depth (m)')
plt.ylabel('Phase Velocity (m/s)')
plt.title('Wave Velocity vs Water Depth')
plt.legend()
plt.grid(True, alpha=0.3)

# Calculate wave parameters for typical wind waves
plt.subplot(2, 2, 3)
periods = np.linspace(5, 20, 16)  # Wave periods 5-20 seconds
g = 9.81

# Deep water wavelength: L = g*T²/(2π)
deep_wavelengths = g * periods**2 / (2 * np.pi)
deep_velocities = g * periods / (2 * np.pi)

plt.plot(periods, deep_wavelengths, 'b-', linewidth=2, label='Wavelength')
plt.plot(periods, deep_velocities, 'r-', linewidth=2, label='Phase velocity')
plt.xlabel('Wave Period (s)')
plt.ylabel('Wavelength (m) / Velocity (m/s)')
plt.title('Deep Water Wave Characteristics')
plt.legend()
plt.grid(True, alpha=0.3)

# Calculate relative depth parameter (kh = 2πh/L)
plt.subplot(2, 2, 4)
h_values = [10, 50, 200]  # Water depths
for h in h_values:
    kh = 2 * np.pi * h / deep_wavelengths
    plt.plot(periods, kh, label=f'h = {h} m', linewidth=2)

plt.axhline(np.pi, color='k', linestyle='--', alpha=0.7, label='Deep water (kh > π)')
plt.axhline(np.pi/10, color='k', linestyle=':', alpha=0.7, label='Shallow water (kh < π/10)')
plt.xlabel('Wave Period (s)')
plt.ylabel('Relative Depth (kh)')
plt.title('Wave Dispersion Parameter')
plt.legend()
plt.grid(True, alpha=0.3)

plt.tight_layout()
plt.show()

# Example: Tsunami wave speed calculation
print("\\nTsunami wave analysis:")
tsunami_wavelength = 200000  # 200 km typical tsunami wavelength
ocean_depths = [1000, 3000, 5000]  # Typical ocean depths

for depth in ocean_depths:
    tsunami_speed = sw.swvel(tsunami_wavelength, depth)
    print(f"Depth {depth:4d} m: Tsunami speed = {tsunami_speed:.0f} m/s ({tsunami_speed*3.6:.0f} km/h)")

Install with Tessl CLI

npx tessl i tessl/pypi-seawater

docs

auxiliary.md

core-eos80.md

geostrophic.md

index.md

support.md

tile.json