Source code for disdrodb.physics.water
# -----------------------------------------------------------------------------.
# Copyright (c) 2021-2026 DISDRODB developers
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# -----------------------------------------------------------------------------.
"""DISDRODB water physics module."""
import numpy as np
import xarray as xr
[docs]
def get_pure_water_density(temperature):
"""
Computes the density of pure water at standard pressure.
For temperatures above freezing uses Kell formulation.
For temperatures below freezing use Dorsch & Boyd formulation.
References: Pruppacher & Klett 1978; Weast & Astle 1980
Parameters
----------
temperature : float
Temperature in Kelvin.
Returns
-------
float
Density of pure water in kg/m^3.
"""
# Convert to Celsius
temperature = temperature - 273.15
# Define mask
above_freezing_mask = temperature > 0
# Compute density above freezing temperature
c = [9.9983952e2, 1.6945176e1, -7.9870401e-3, -4.6170461e-5, 1.0556302e-7, -2.8054253e-10, 1.6879850e-2]
density = c[0] + sum(c * temperature**i for i, c in enumerate(c[1:6], start=1))
density_above_0 = density / (1 + c[6] * temperature)
# Compute density below freezing temperature
c = [999.84, 0.086, -0.0108]
density_below_0 = c[0] + sum(c * temperature**i for i, c in enumerate(c[1:], start=1))
# Define final density
density = xr.where(above_freezing_mask, density_above_0, density_below_0)
return density
[docs]
def get_pure_water_compressibility(temperature):
"""
Computes the isothermal compressibility of pure ordinary water.
Reference: Kell, Weast & Astle 1980
Parameters
----------
temperature : float
Temperature in Kelvin.
Returns
-------
float
Compressibility of water in Pascals.
"""
# Convert to Celsius
temperature = temperature - 273.15
# Compute compressibility
c = [5.088496e1, 6.163813e-1, 1.459187e-3, 2.008438e-5, -5.857727e-8, 4.10411e-10, 1.967348e-2]
compressibility = c[0] + sum(c * temperature**i for i, c in enumerate(c[1:6], start=1))
compressibility = compressibility / (1 + c[6] * temperature) * 1e-11
return compressibility
[docs]
def get_pure_water_surface_tension(temperature):
"""
Computes the surface tension of pure ordinary water against air.
Reference: Pruppacher & Klett 1978
Parameters
----------
temperature : float
Temperature in Kelvin.
Returns
-------
float
Surface tension in N/m.
"""
sigma = 0.0761 - 0.000155 * (temperature - 273.15)
return sigma
[docs]
def get_water_density(temperature, air_pressure, sea_level_air_pressure=101_325):
"""
Computes the density of water according to Weast & Astle 1980.
Parameters
----------
temperature : float
Temperature in Kelvin.
air_pressure : float
Air pressure in Pascals.
sea_level_air_pressure : float
Standard atmospheric pressure at sea level in Pascals.
The default is 101_325 Pascal.
freezing_temperature : float, optional
Freezing temperature of water in Kelvin. The default is 273.15 K.
Returns
-------
float
Water density in kg/m^3.
"""
delta_pressure = sea_level_air_pressure - air_pressure
water_compressibility = get_pure_water_compressibility(temperature)
return get_pure_water_density(temperature) * np.exp(-1 * water_compressibility * delta_pressure)