#![deny(missing_docs)]
use pantometry_units::{Density, Diffusivity};
mod channel;
pub use channel::{Channel, Walls, CELL_REYNOLDS_LIMIT};
#[derive(Clone, Copy, Debug)]
pub struct Fluid {
pub density: Density,
pub kinematic_viscosity: Diffusivity,
}
impl Fluid {
pub fn water() -> Fluid {
Fluid {
density: Density::from_si(998.2),
kinematic_viscosity: Diffusivity::from_si(1.004e-6),
}
}
pub fn air() -> Fluid {
Fluid {
density: Density::from_si(1.204),
kinematic_viscosity: Diffusivity::from_si(1.511e-5),
}
}
pub fn new(density: Density, kinematic_viscosity: Diffusivity) -> Fluid {
Fluid {
density,
kinematic_viscosity,
}
}
pub fn dynamic_viscosity(&self) -> f64 {
self.density.to_si() * self.kinematic_viscosity.to_si()
}
}
pub fn poiseuille_mean_speed(force_per_mass: f64, gap: f64, kinematic_viscosity: f64) -> f64 {
force_per_mass * gap * gap / (12.0 * kinematic_viscosity)
}
pub fn taylor_green_rate(wavenumber: f64, kinematic_viscosity: f64) -> f64 {
2.0 * kinematic_viscosity * wavenumber * wavenumber
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn the_kinematic_and_dynamic_viscosities_are_a_density_apart() {
let w = Fluid::water();
assert!(
(w.dynamic_viscosity() / 1.002e-3 - 1.0).abs() < 0.01,
"water is about 1.0 mPa.s: {:.4e}",
w.dynamic_viscosity()
);
let a = Fluid::air();
assert!(
a.kinematic_viscosity.to_si() > 10.0 * w.kinematic_viscosity.to_si()
&& a.dynamic_viscosity() < 0.1 * w.dynamic_viscosity(),
"air: nu {:.3e} against water's {:.3e}, mu {:.3e} against {:.3e}",
a.kinematic_viscosity.to_si(),
w.kinematic_viscosity.to_si(),
a.dynamic_viscosity(),
w.dynamic_viscosity()
);
}
#[test]
fn the_poiseuille_mean_is_the_integral_of_its_profile() {
let (g, h, nu) = (0.5, 0.02, 1e-5);
let closed = poiseuille_mean_speed(g, h, nu);
let n = 100_000;
let mut sum = 0.0;
for i in 0..=n {
let y = h * i as f64 / n as f64;
let w = if i == 0 || i == n { 0.5 } else { 1.0 };
sum += w * (g / (2.0 * nu)) * y * (h - y);
}
let mean = sum * (h / n as f64) / h;
assert!(
(mean / closed - 1.0).abs() < 1e-9,
"gh^2/12nu is the mean of the parabola: {mean:.6e} against {closed:.6e}"
);
}
#[test]
fn the_energy_rate_is_twice_the_velocity_rate() {
let (k, nu) = (100.0, 1e-4);
let rate = taylor_green_rate(k, nu);
assert!((rate - 2.0 * nu * k * k).abs() < 1e-12);
let t = 0.37;
let u = (-rate * t).exp();
assert!(
((u * u) / (-2.0 * rate * t).exp() - 1.0).abs() < 1e-12,
"energy is the square of the velocity"
);
}
}