conspire/physics/molecular/potential/
mod.rs

1#[cfg(test)]
2mod test;
3
4mod harmonic;
5// mod lennard_jones;
6mod morse;
7
8pub use harmonic::Harmonic;
9pub use morse::Morse;
10
11use crate::{math::Scalar, physics::BOLTZMANN_CONSTANT};
12use std::fmt::Debug;
13
14pub trait Potential
15where
16    Self: Clone + Debug,
17{
18    /// ```math
19    /// u = u(x)
20    /// ```
21    fn energy(&self, length: Scalar) -> Scalar;
22    /// ```math
23    /// \beta u = \beta u(\lambda)
24    /// ```
25    fn nondimensional_energy(&self, nondimensional_length: Scalar, temperature: Scalar) -> Scalar {
26        let length = self.rest_length() * nondimensional_length;
27        self.energy(length) / BOLTZMANN_CONSTANT / temperature
28    }
29    /// ```math
30    /// f(x) = \frac{\partial u}{\partial x}
31    /// ```
32    fn force(&self, length: Scalar) -> Scalar;
33    /// ```math
34    /// \eta(\lambda) = \frac{\partial\beta u}{\partial \lambda}
35    /// ```
36    fn nondimensional_force(&self, nondimensional_length: Scalar, temperature: Scalar) -> Scalar {
37        let length = self.rest_length() * nondimensional_length;
38        self.force(length) * self.rest_length() / BOLTZMANN_CONSTANT / temperature
39    }
40    /// ```math
41    /// k(x) = \frac{\partial f}{\partial x}
42    /// ```
43    fn stiffness(&self, length: Scalar) -> Scalar;
44    /// ```math
45    /// \kappa(x) = \frac{\partial\eta}{\partial\lambda}
46    /// ```
47    fn nondimensional_stiffness(
48        &self,
49        nondimensional_length: Scalar,
50        temperature: Scalar,
51    ) -> Scalar {
52        let length = self.rest_length() * nondimensional_length;
53        self.stiffness(length) * self.rest_length().powi(2) / BOLTZMANN_CONSTANT / temperature
54    }
55    /// ```math
56    /// h(x) = \frac{\partial k}{\partial x}
57    /// ```
58    fn anharmonicity(&self, length: Scalar) -> Scalar;
59    /// ```math
60    /// g(x) = \frac{\partial\kappa}{\partial\lambda}
61    /// ```
62    fn nondimensional_anharmonicity(
63        &self,
64        nondimensional_length: Scalar,
65        temperature: Scalar,
66    ) -> Scalar {
67        let length = self.rest_length() * nondimensional_length;
68        self.anharmonicity(length) * self.rest_length().powi(3) / BOLTZMANN_CONSTANT / temperature
69    }
70    /// ```math
71    /// v(f) = u(x) - f\Delta x
72    /// ```
73    fn legendre(&self, force: Scalar) -> Scalar {
74        let extension = self.extension(force);
75        let length = self.rest_length() + extension;
76        self.energy(length) - force * extension
77    }
78    /// ```math
79    /// \beta v(\eta) = \beta u(\lambda) - \eta\Delta\lambda
80    /// ```
81    fn nondimensional_legendre(&self, nondimensional_force: Scalar, temperature: Scalar) -> Scalar {
82        let force = nondimensional_force / self.rest_length() * BOLTZMANN_CONSTANT * temperature;
83        self.legendre(force) / BOLTZMANN_CONSTANT / temperature
84    }
85    /// ```math
86    /// \Delta x(f) = -\frac{\partial v}{\partial f}
87    /// ```
88    fn extension(&self, force: Scalar) -> Scalar;
89    /// ```math
90    /// \Delta \lambda(\eta) = -\frac{\partial\beta v}{\partial\eta}
91    /// ```
92    fn nondimensional_extension(
93        &self,
94        nondimensional_force: Scalar,
95        temperature: Scalar,
96    ) -> Scalar {
97        let force = nondimensional_force / self.rest_length() * BOLTZMANN_CONSTANT * temperature;
98        self.extension(force) / self.rest_length()
99    }
100    /// ```math
101    /// c(x) = \frac{\partial\Delta x}{\partial f}
102    /// ```
103    fn compliance(&self, force: Scalar) -> Scalar;
104    /// ```math
105    /// \zeta(x) = \frac{\partial\Delta\lambda}{\partial\eta}
106    /// ```
107    fn nondimensional_compliance(
108        &self,
109        nondimensional_force: Scalar,
110        temperature: Scalar,
111    ) -> Scalar {
112        let force = nondimensional_force / self.rest_length() * BOLTZMANN_CONSTANT * temperature;
113        self.compliance(force) / self.rest_length().powi(2) * BOLTZMANN_CONSTANT * temperature
114    }
115    /// ```math
116    /// \text{arg max }u(x) = x_\mathrm{peak}
117    /// ```
118    fn peak(&self) -> Scalar;
119    /// ```math
120    /// f(x_\mathrm{peak}) = f_\mathrm{peak}
121    /// ```
122    fn peak_force(&self) -> Scalar;
123    /// ```math
124    /// \text{arg min }u(x) = x_0
125    /// ```
126    fn rest_length(&self) -> Scalar;
127}