use sciforge::hub::domain::common::constants::{EARTH_RADIUS, R_GAS, SIGMA_SB};
use sciforge::hub::domain::physics::thermodynamics::clausius_clapeyron;
use sciforge::hub::prelude::constants::elements::atomic_mass;
pub const OCEAN_SURFACE_AREA_M2: f64 = 3.61e14;
pub const MEAN_OCEAN_DEPTH_M: f64 = 3688.0;
pub const OCEAN_VOLUME_M3: f64 = 1.335e18;
pub const MEAN_SALINITY_PSU: f64 = 35.0;
pub const SEAWATER_DENSITY: f64 = 1025.0;
pub struct OceanLayer {
pub name: &'static str,
pub depth_range_m: (f64, f64),
pub mean_temperature_c: f64,
pub mean_salinity_psu: f64,
}
impl OceanLayer {
pub fn density_kg_m3(&self) -> f64 {
let t = self.mean_temperature_c;
let s = self.mean_salinity_psu;
999.842594 + 6.793952e-2 * t - 9.095290e-3 * t * t + 1.001685e-4 * t * t * t + 0.824493 * s
- 4.0899e-3 * t * s
}
pub fn pressure_at_depth(&self, depth_m: f64) -> f64 {
SEAWATER_DENSITY * *crate::SURFACE_GRAVITY * depth_m
}
pub fn sound_speed_m_s(&self) -> f64 {
let t = self.mean_temperature_c;
let s = self.mean_salinity_psu;
let d = (self.depth_range_m.0 + self.depth_range_m.1) / 2.0;
1449.2 + 4.6 * t - 0.055 * t * t
+ 0.00029 * t * t * t
+ (1.34 - 0.01 * t) * (s - 35.0)
+ 0.016 * d
}
}
pub fn surface_mixed_layer() -> OceanLayer {
OceanLayer {
name: "Surface Mixed Layer",
depth_range_m: (0.0, 200.0),
mean_temperature_c: 17.0,
mean_salinity_psu: 35.0,
}
}
pub fn thermocline() -> OceanLayer {
OceanLayer {
name: "Thermocline",
depth_range_m: (200.0, 1000.0),
mean_temperature_c: 8.0,
mean_salinity_psu: 34.8,
}
}
pub fn deep_ocean() -> OceanLayer {
OceanLayer {
name: "Deep Ocean",
depth_range_m: (1000.0, 4000.0),
mean_temperature_c: 2.0,
mean_salinity_psu: 34.7,
}
}
pub fn thermohaline_overturning_rate_sv() -> f64 {
17.0
}
pub fn ocean_heat_content_j(temp_anomaly_k: f64, depth_m: f64) -> f64 {
SEAWATER_DENSITY * crate::CP_SEAWATER * OCEAN_SURFACE_AREA_M2 * depth_m * temp_anomaly_k
}
pub fn sea_level_rise_thermal_m(temp_anomaly_k: f64, depth_m: f64) -> f64 {
let expansion_coeff = 2.0e-4;
expansion_coeff * temp_anomaly_k * depth_m
}
pub fn surface_longwave_radiation_w_m2(sst_c: f64, emissivity: f64) -> f64 {
let t_k = sst_c + crate::CELSIUS_TO_KELVIN;
emissivity * SIGMA_SB * t_k.powi(4)
}
pub fn ocean_area_from_fraction(fraction: f64) -> f64 {
4.0 * std::f64::consts::PI * EARTH_RADIUS * EARTH_RADIUS * fraction
}
pub fn vapor_pressure_over_ocean(sst_c: f64) -> f64 {
let p_ref = crate::VAPOR_PRESSURE_0C;
let t_ref = crate::CELSIUS_TO_KELVIN;
let t2 = sst_c + crate::CELSIUS_TO_KELVIN;
let l_vap = *crate::L_VAPORIZATION;
clausius_clapeyron(p_ref, t_ref, t2, l_vap)
}
pub fn dissolved_gas_henry(
partial_pressure_pa: f64,
temperature_c: f64,
henry_const_mol_m3_pa: f64,
) -> f64 {
let t_k = temperature_c + crate::CELSIUS_TO_KELVIN;
let correction = (-2400.0 * (1.0 / t_k - 1.0 / 298.15) / R_GAS).exp();
henry_const_mol_m3_pa * partial_pressure_pa * correction
}
pub fn nacl_molar_mass() -> f64 {
(atomic_mass(11) + atomic_mass(17)) * 1e-3
}
pub fn nacl_molality_35psu() -> f64 {
0.035 / nacl_molar_mass()
}