conspire/physics/molecular/potential/morse/
mod.rs1use crate::{math::Scalar, physics::molecular::potential::Potential};
2
3#[derive(Clone, Debug)]
6pub struct Morse {
7 pub rest_length: Scalar,
9 pub depth: Scalar,
11 pub parameter: Scalar,
13}
14
15impl Potential for Morse {
16 fn energy(&self, length: Scalar) -> Scalar {
20 self.depth * (1.0 - (self.parameter * (self.rest_length - length)).exp()).powi(2)
21 }
22 fn force(&self, length: Scalar) -> Scalar {
26 let exp = (self.parameter * (self.rest_length - length)).exp();
27 2.0 * self.parameter * self.depth * exp * (1.0 - exp)
28 }
29 fn stiffness(&self, length: Scalar) -> Scalar {
33 let exp = (self.parameter * (self.rest_length - length)).exp();
34 2.0 * self.parameter.powi(2) * self.depth * exp * (2.0 * exp - 1.0)
35 }
36 fn anharmonicity(&self, length: Scalar) -> Scalar {
40 let exp = (self.parameter * (self.rest_length - length)).exp();
41 2.0 * self.parameter.powi(3) * self.depth * exp * (1.0 - 4.0 * exp)
42 }
43 fn extension(&self, force: Scalar) -> Scalar {
47 let y = force / self.peak_force();
48 if (0.0..=1.0).contains(&y) {
49 (2.0 / (1.0 + (1.0 - y).sqrt())).ln() / self.parameter
50 } else {
51 Scalar::NAN
52 }
53 }
54 fn compliance(&self, force: Scalar) -> Scalar {
58 let y = force / self.peak_force();
59 if (0.0..1.0).contains(&y) {
60 let s = (1.0 - y).sqrt();
61 1.0 / (self.parameter.powi(2) * self.depth) / (s * (1.0 + s))
62 } else if y == 0.0 {
63 Scalar::INFINITY
64 } else {
65 Scalar::NAN
66 }
67 }
68 fn peak(&self) -> Scalar {
72 self.rest_length + 2.0_f64.ln() / self.parameter
73 }
74 fn peak_force(&self) -> Scalar {
78 0.5 * self.parameter * self.depth
79 }
80 fn rest_length(&self) -> Scalar {
84 self.rest_length
85 }
86}