use super::WeeksChandlerAndersen;
use super::hard_sphere::{
dimensionless_diameter_q_wca, packing_fraction, packing_fraction_a_uvb3,
packing_fraction_b_uvb3,
};
use crate::uvtheory::parameters::*;
use feos_core::StateHD;
use num_dual::DualNum;
use std::f64::consts::PI;
#[derive(Debug, Clone)]
pub(super) struct ReferencePerturbationB3;
impl ReferencePerturbationB3 {
pub fn helmholtz_energy_density<D: DualNum<f64> + Copy>(
&self,
parameters: &UVTheoryPars,
state: &StateHD<D>,
) -> D {
let p = parameters;
let n = p.sigma.len();
let x = &state.molefracs;
let d = WeeksChandlerAndersen::diameter_wca(p, state.temperature);
let eta = packing_fraction(&state.partial_density, &d);
let eta_a = packing_fraction_a_uvb3(p, eta, state.temperature);
let eta_b = packing_fraction_b_uvb3(p, eta, state.temperature);
let mut a = D::zero();
for i in 0..n {
for j in 0..n {
let rs_ij = ((p.rep[i] / p.att[i]).powf(1.0 / (p.rep[i] - p.att[i]))
+ (p.rep[j] / p.att[j]).powf(1.0 / (p.rep[j] - p.att[j])))
* 0.5; let d_ij = (d[i] + d[j]) * 0.5;
let t_ij = state.temperature / p.eps_k_ij[(i, j)];
let rep_ij = p.rep_ij[(i, j)];
let att_ij = p.att_ij[(i, j)];
let q_ij = dimensionless_diameter_q_wca(t_ij, D::from(rep_ij), D::from(att_ij))
* p.sigma_ij[(i, j)];
a += x[i]
* x[j]
* ((-eta_a[(i, j)] * 0.5 + 1.0) / (-eta_a[(i, j)] + 1.0).powi(3)
* (-q_ij.powi(3) + (rs_ij * p.sigma_ij[(i, j)]).powi(3))
- ((-eta_b[(i, j)] * 0.5 + 1.0) / (-eta_b[(i, j)] + 1.0).powi(3))
* (-d_ij.powi(3) + (rs_ij * p.sigma_ij[(i, j)]).powi(3)))
}
}
-a * state.partial_density.sum().powi(2) * 2.0 / 3.0 * PI
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::uvtheory::Perturbation::WeeksChandlerAndersenB3 as WCAB3;
use crate::uvtheory::parameters::utils::test_parameters;
use approx::assert_relative_eq;
use nalgebra::dvector;
#[test]
fn test_delta_a0_uvb3_pure() {
let reduced_temperature = 2.0;
let reduced_density = 0.5;
let p = test_parameters(12.0, 6.0, 1.0, 1.0, WCAB3);
let state = StateHD::new(reduced_temperature, 1.0 / reduced_density, &dvector![1.0]);
let a = ReferencePerturbationB3.helmholtz_energy_density(&p, &state) / reduced_density;
dbg!(a);
assert_relative_eq!(a, 0.1130778070897391, epsilon = 1e-10);
let reduced_temperature = 3.0;
let reduced_density = 1.1;
let p = test_parameters(20.0, 6.0, 1.0, 1.0, WCAB3);
let state = StateHD::new(reduced_temperature, 1.0 / reduced_density, &dvector![1.0]);
let a = ReferencePerturbationB3.helmholtz_energy_density(&p, &state) / reduced_density;
assert_relative_eq!(a, 0.3405167374787895, epsilon = 1e-10);
}
}