hoomd_interaction/univariate/
expanded.rs1use serde::{Deserialize, Serialize};
7
8use super::{UnivariateEnergy, UnivariateForce};
9
10#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
37pub struct Expanded<F> {
38 pub f: F,
40 pub delta: f64,
42}
43
44impl<F> Default for Expanded<F>
45where
46 F: Default,
47{
48 #[inline]
54 fn default() -> Self {
55 Self {
56 f: F::default(),
57 delta: 0.0,
58 }
59 }
60}
61
62impl<F: UnivariateEnergy> UnivariateEnergy for Expanded<F> {
63 #[inline]
64 fn energy(&self, r: f64) -> f64 {
65 self.f.energy(r - self.delta)
66 }
67}
68
69impl<F: UnivariateForce> UnivariateForce for Expanded<F> {
70 #[inline]
71 fn force(&self, r: f64) -> f64 {
72 self.f.force(r - self.delta)
73 }
74}
75
76#[cfg(test)]
77mod tests {
78 use super::*;
79 use crate::univariate::LennardJones;
80 use approxim::{assert_abs_diff_eq, assert_relative_eq};
81 use rstest::*;
82
83 #[rstest]
84 fn special_points_12_6(
85 #[values(1.0, 2.0, 12.125, 0.25)] epsilon: f64,
86 #[values(1.0, 2.0, 0.5)] sigma: f64,
87 #[values(0.125, 0.5, 2.0)] delta: f64,
88 ) {
89 let lj: LennardJones = LennardJones { epsilon, sigma };
90 let expanded_lj = Expanded { f: lj, delta };
91
92 assert_abs_diff_eq!(expanded_lj.energy(sigma + delta), 0.0);
94 assert_relative_eq!(expanded_lj.force(sigma + delta), 24.0 * epsilon / sigma);
95
96 assert_relative_eq!(
98 expanded_lj.energy(2.0_f64.powf(1.0 / 6.0) * sigma + delta),
99 -epsilon
100 );
101 assert_abs_diff_eq!(
102 expanded_lj.force(2.0_f64.powf(1.0 / 6.0) * sigma + delta),
103 0.0,
104 epsilon = 1e-12
105 );
106
107 assert_relative_eq!(
109 expanded_lj.energy(2.0 * sigma + delta),
110 -63.0 / 1024.0 * epsilon
111 );
112 assert_relative_eq!(
113 expanded_lj.force(2.0 * sigma + delta),
114 -93.0 / 512.0 * epsilon / sigma
115 );
116 }
117}