conspire/physics/molecular/potential/morse/
mod.rs1use crate::{
2 math::{Scalar, ScalarList},
3 physics::molecular::potential::Potential,
4};
5
6#[derive(Clone, Debug)]
9pub struct Morse {
10 pub rest_length: Scalar,
12 pub depth: Scalar,
14 pub parameter: Scalar,
16}
17
18impl Potential for Morse {
19 fn energy(&self, length: Scalar) -> Scalar {
23 self.depth * (1.0 - (self.parameter * (self.rest_length - length)).exp()).powi(2)
24 }
25 fn force(&self, length: Scalar) -> Scalar {
29 let exp = (self.parameter * (self.rest_length - length)).exp();
30 2.0 * self.parameter * self.depth * exp * (1.0 - exp)
31 }
32 fn forces_at_energy(&self, energy: Scalar) -> ScalarList<2> {
36 let y = energy / self.depth;
37 let f = 2.0 * self.parameter * self.depth * y.sqrt();
38 let tensile = if (0.0..=1.0).contains(&y) {
39 f * (1.0 - y.sqrt())
40 } else {
41 Scalar::NAN
42 };
43 [tensile, -f * (1.0 + y.sqrt())].into()
44 }
45 fn stiffness(&self, length: Scalar) -> Scalar {
49 let exp = (self.parameter * (self.rest_length - length)).exp();
50 2.0 * self.parameter.powi(2) * self.depth * exp * (2.0 * exp - 1.0)
51 }
52 fn anharmonicity(&self, length: Scalar) -> Scalar {
56 let exp = (self.parameter * (self.rest_length - length)).exp();
57 2.0 * self.parameter.powi(3) * self.depth * exp * (1.0 - 4.0 * exp)
58 }
59 fn extension(&self, force: Scalar) -> Scalar {
63 let y = force / self.peak_force();
64 if y <= 1.0 {
65 (2.0 / (1.0 + (1.0 - y).sqrt())).ln() / self.parameter
66 } else {
67 Scalar::NAN
68 }
69 }
70 fn extensions_at_energy(&self, energy: Scalar) -> ScalarList<2> {
74 let y = energy / self.depth;
75 let tensile = if (0.0..=1.0).contains(&y) {
76 (1.0 / (1.0 - y.sqrt())).ln() / self.parameter
77 } else {
78 Scalar::NAN
79 };
80 [tensile, (1.0 / (1.0 + y.sqrt())).ln() / self.parameter].into()
81 }
82 fn compliance(&self, force: Scalar) -> Scalar {
86 let y = force / self.peak_force();
87 if (0.0..1.0).contains(&y) {
88 let s = (1.0 - y).sqrt();
89 1.0 / (self.parameter.powi(2) * self.depth) / (s * (1.0 + s))
90 } else if y == 0.0 {
91 Scalar::INFINITY
92 } else {
93 Scalar::NAN
94 }
95 }
96 fn peak(&self) -> Scalar {
100 self.rest_length + 2.0_f64.ln() / self.parameter
101 }
102 fn peak_force(&self) -> Scalar {
106 0.5 * self.parameter * self.depth
107 }
108 fn rest_length(&self) -> Scalar {
112 self.rest_length
113 }
114}