use crate::ionic_strength::IonicStrength;
use crate::{permittivity, Temperature, ANGSTROM_PER_METER, LITER_PER_ANGSTROM3};
use crate::{
AVOGADRO_CONSTANT, BOLTZMANN_CONSTANT, ELEMENTARY_CHARGE, VACUUM_ELECTRIC_PERMITTIVITY,
};
use std::f64::consts::PI;
pub trait DebyeLength {
fn debye_length(&self) -> Option<f64> {
self.kappa().map(f64::recip)
}
fn kappa(&self) -> Option<f64>;
fn set_debye_length(&mut self, _debye_length: Option<f64>) -> crate::Result<()> {
Err(crate::Error::Unsupported("setting the Debye length"))
}
}
impl<T> DebyeLength for T
where
T: Temperature + IonicStrength + permittivity::RelativePermittivity,
{
fn debye_length(&self) -> Option<f64> {
let temperature = self.temperature();
let permittivity = self.permittivity(temperature).ok()?;
self.ionic_strength()
.map(|i| debye_length(temperature, permittivity, i))
}
fn kappa(&self) -> Option<f64> {
self.debye_length().map(f64::recip)
}
}
pub const fn bjerrum_length(kelvin: f64, relative_permittivity: f64) -> f64 {
ELEMENTARY_CHARGE * ELEMENTARY_CHARGE * ANGSTROM_PER_METER
/ (4.0
* PI
* relative_permittivity
* VACUUM_ELECTRIC_PERMITTIVITY
* BOLTZMANN_CONSTANT
* kelvin)
}
pub fn debye_length(kelvin: f64, relative_permittivity: f64, ionic_strength: f64) -> f64 {
(8.0 * PI
* bjerrum_length(kelvin, relative_permittivity)
* ionic_strength
* AVOGADRO_CONSTANT
* LITER_PER_ANGSTROM3)
.sqrt()
.recip()
}