use serde::{Deserialize, Serialize};
use super::{UnivariateEnergy, UnivariateForce};
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct Harmonic {
pub k: f64,
pub r_0: f64,
}
impl UnivariateEnergy for Harmonic {
#[inline]
fn energy(&self, r: f64) -> f64 {
0.5 * self.k * (r - self.r_0) * (r - self.r_0)
}
}
impl UnivariateForce for Harmonic {
#[inline]
fn force(&self, r: f64) -> f64 {
-self.k * (r - self.r_0)
}
}
#[cfg(test)]
mod tests {
use super::*;
use approxim::assert_relative_eq;
use rstest::*;
#[rstest]
fn zero_energy_point(#[values(1.0, 2.0, 5.0, 10.0)] k: f64, #[values(0.0, 1.0, 2.0)] r_0: f64) {
let harmonic = Harmonic { k, r_0 };
assert_eq!(harmonic.k, k);
assert_eq!(harmonic.r_0, r_0);
assert_eq!(harmonic.energy(r_0), 0.0);
assert_eq!(harmonic.force(r_0), 0.0);
}
#[rstest]
fn general_case(#[values(1.0, 2.0, 5.0, 10.0)] k: f64, #[values(0.0, 1.0, 2.0)] r_0: f64) {
let r = 5.0;
let harmonic = Harmonic { k, r_0 };
assert_eq!(harmonic.k, k);
assert_eq!(harmonic.r_0, r_0);
let expected_energy = 0.5 * k * (r - r_0) * (r - r_0);
let expected_force = -k * (r - r_0);
assert_relative_eq!(harmonic.energy(r), expected_energy);
assert_relative_eq!(harmonic.force(r), expected_force);
}
}