use serde::{Deserialize, Serialize};
use super::{LennardJones, UnivariateEnergy, UnivariateForce};
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct WeeksChandlerAnderson {
pub epsilon: f64,
pub sigma: f64,
}
impl Default for WeeksChandlerAnderson {
#[inline]
fn default() -> Self {
WeeksChandlerAnderson {
epsilon: 1.0,
sigma: 1.0,
}
}
}
impl UnivariateEnergy for WeeksChandlerAnderson {
#[inline]
fn energy(&self, r: f64) -> f64 {
if r < 2.0_f64.powf(1.0 / 6.0) * self.sigma {
let lj = LennardJones::<12, 6> {
epsilon: self.epsilon,
sigma: self.sigma,
};
lj.energy(r) + self.epsilon
} else {
0.0
}
}
}
impl UnivariateForce for WeeksChandlerAnderson {
#[inline]
fn force(&self, r: f64) -> f64 {
if r < 2.0_f64.powf(1.0 / 6.0) * self.sigma {
let lj = LennardJones::<12, 6> {
epsilon: self.epsilon,
sigma: self.sigma,
};
lj.force(r)
} else {
0.0
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use approxim::{assert_abs_diff_eq, assert_relative_eq};
use rstest::*;
#[rstest]
fn special_points_12_6(
#[values(1.0, 2.0, 12.125, 0.25)] epsilon: f64,
#[values(1.0, 2.0, 0.5)] sigma: f64,
) {
let wca = WeeksChandlerAnderson { epsilon, sigma };
assert_eq!(wca.epsilon, epsilon);
assert_eq!(wca.sigma, sigma);
assert_relative_eq!(wca.energy(sigma), epsilon);
assert_relative_eq!(wca.force(sigma), 24.0 * epsilon / sigma);
assert_abs_diff_eq!(wca.energy(2.0_f64.powf(1.0 / 6.0) * sigma), 0.0);
assert_abs_diff_eq!(
wca.force(2.0_f64.powf(1.0 / 6.0) * sigma),
0.0,
epsilon = 1e-12
);
assert_eq!(wca.energy(2.0 * sigma), 0.0);
assert_eq!(wca.force(2.0 * sigma), 0.0);
}
}