use crate::saturation::{SatPressureModel, psat};
use crate::types::Component;
const WILSON_C: f64 = 5.373;
pub fn wilson_k(comp: &Component, t: f64, p: f64) -> f64 {
wilson_ln_k(comp, t, p).exp()
}
pub fn wilson_ln_k(comp: &Component, t: f64, p: f64) -> f64 {
(comp.pc / p).ln() + WILSON_C * (1.0 + comp.omega) * (1.0 - comp.tc / t)
}
pub fn wilson_k_values(components: &[Component], t: f64, p: f64) -> Vec<f64> {
components.iter().map(|c| wilson_k(c, t, p)).collect()
}
pub fn raoult_k_values(
components: &[Component],
sat_models: &[SatPressureModel],
t: f64,
p: f64,
) -> Vec<f64> {
components
.iter()
.enumerate()
.map(|(i, c)| {
let model = sat_models.get(i).copied().unwrap_or(c.sat_model);
match psat(model, c, t) {
Ok(ps) => ps / p,
Err(_) => wilson_k(c, t, p),
}
})
.collect()
}
#[cfg(test)]
mod tests {
use super::*;
fn methane() -> Component {
Component {
name: "methane".into(),
tc: 190.564,
pc: 4599.0,
omega: 0.0115,
..Component::default()
}
}
fn n_butane() -> Component {
Component {
name: "n-butane".into(),
tc: 425.12,
pc: 3796.0,
omega: 0.200,
..Component::default()
}
}
#[test]
fn wilson_k_light_heavy_ordering() {
let km = wilson_k(&methane(), 300.0, 2000.0);
let kb = wilson_k(&n_butane(), 300.0, 2000.0);
assert!(km > kb, "methane K={km} should exceed butane K={kb}");
assert!(km > 1.0, "methane (supercritical here) should be K>1: {km}");
}
#[test]
fn wilson_k_at_critical_point_is_pc_over_p() {
let c = n_butane();
let k = wilson_k(&c, c.tc, 1000.0);
assert!((k - c.pc / 1000.0).abs() < 1e-12);
}
#[test]
fn wilson_k_decreases_with_pressure() {
let c = n_butane();
let k1 = wilson_k(&c, 350.0, 1000.0);
let k2 = wilson_k(&c, 350.0, 2000.0);
assert!((k1 / k2 - 2.0).abs() < 1e-12);
}
#[test]
fn wilson_k_values_vector_matches_scalar() {
let comps = [methane(), n_butane()];
let ks = wilson_k_values(&comps, 300.0, 2000.0);
assert_eq!(ks.len(), 2);
assert!((ks[0] - wilson_k(&comps[0], 300.0, 2000.0)).abs() < 1e-15);
assert!((ks[1] - wilson_k(&comps[1], 300.0, 2000.0)).abs() < 1e-15);
}
#[test]
fn raoult_falls_back_to_wilson_without_sat_data() {
let comps = [methane()];
let ks = raoult_k_values(&comps, &[], 300.0, 2000.0);
assert!(ks[0].is_finite() && ks[0] > 0.0);
assert!((ks[0] - wilson_k(&comps[0], 300.0, 2000.0)).abs() < 1e-12);
}
}