conspire/physics/molecular/potential/
mod.rs1#[cfg(test)]
2mod test;
3
4mod harmonic;
5mod morse;
7
8pub use harmonic::Harmonic;
9pub use morse::Morse;
10
11use crate::{
12 math::{Scalar, ScalarList},
13 physics::BOLTZMANN_CONSTANT,
14};
15use std::fmt::Debug;
16
17pub trait Potential
19where
20 Self: Clone + Debug,
21{
22 fn energy(&self, length: Scalar) -> Scalar;
26 fn nondimensional_energy(&self, nondimensional_length: Scalar, temperature: Scalar) -> Scalar {
30 let length = self.rest_length() * nondimensional_length;
31 self.energy(length) / BOLTZMANN_CONSTANT / temperature
32 }
33 fn energy_at_force(&self, force: Scalar) -> Scalar {
37 let extension = self.extension(force);
38 let length = self.rest_length() + extension;
39 self.energy(length)
40 }
41 fn nondimensional_energy_at_nondimensional_force(
45 &self,
46 nondimensional_force: Scalar,
47 temperature: Scalar,
48 ) -> Scalar {
49 let force = nondimensional_force / self.rest_length() * BOLTZMANN_CONSTANT * temperature;
50 self.energy_at_force(force) / BOLTZMANN_CONSTANT / temperature
51 }
52 fn force(&self, length: Scalar) -> Scalar;
56 fn nondimensional_force(&self, nondimensional_length: Scalar, temperature: Scalar) -> Scalar {
60 let length = self.rest_length() * nondimensional_length;
61 self.force(length) * self.rest_length() / BOLTZMANN_CONSTANT / temperature
62 }
63 fn forces_at_energy(&self, energy: Scalar) -> ScalarList<2>;
67 fn nondimensional_forces_at_nondimensional_energy(
71 &self,
72 nondimensional_energy: Scalar,
73 temperature: Scalar,
74 ) -> ScalarList<2> {
75 let energy = nondimensional_energy * BOLTZMANN_CONSTANT * temperature;
76 self.forces_at_energy(energy) * self.rest_length() / BOLTZMANN_CONSTANT / temperature
77 }
78 fn stiffness(&self, length: Scalar) -> Scalar;
82 fn nondimensional_stiffness(
86 &self,
87 nondimensional_length: Scalar,
88 temperature: Scalar,
89 ) -> Scalar {
90 let length = self.rest_length() * nondimensional_length;
91 self.stiffness(length) * self.rest_length().powi(2) / BOLTZMANN_CONSTANT / temperature
92 }
93 fn anharmonicity(&self, length: Scalar) -> Scalar;
97 fn nondimensional_anharmonicity(
101 &self,
102 nondimensional_length: Scalar,
103 temperature: Scalar,
104 ) -> Scalar {
105 let length = self.rest_length() * nondimensional_length;
106 self.anharmonicity(length) * self.rest_length().powi(3) / BOLTZMANN_CONSTANT / temperature
107 }
108 fn legendre(&self, force: Scalar) -> Scalar {
112 let extension = self.extension(force);
113 let length = self.rest_length() + extension;
114 self.energy(length) - force * extension
115 }
116 fn nondimensional_legendre(&self, nondimensional_force: Scalar, temperature: Scalar) -> Scalar {
120 let force = nondimensional_force / self.rest_length() * BOLTZMANN_CONSTANT * temperature;
121 self.legendre(force) / BOLTZMANN_CONSTANT / temperature
122 }
123 fn extension(&self, force: Scalar) -> Scalar;
127 fn nondimensional_extension(
131 &self,
132 nondimensional_force: Scalar,
133 temperature: Scalar,
134 ) -> Scalar {
135 let force = nondimensional_force / self.rest_length() * BOLTZMANN_CONSTANT * temperature;
136 self.extension(force) / self.rest_length()
137 }
138 fn length(&self, force: Scalar) -> Scalar {
142 self.rest_length() + self.extension(force)
143 }
144 fn nondimensional_length(&self, nondimensional_force: Scalar, temperature: Scalar) -> Scalar {
148 1.0 + self.nondimensional_extension(nondimensional_force, temperature)
149 }
150 fn extensions_at_energy(&self, energy: Scalar) -> ScalarList<2>;
154 fn nondimensional_extensions_at_nondimensional_energy(
158 &self,
159 nondimensional_energy: Scalar,
160 temperature: Scalar,
161 ) -> ScalarList<2> {
162 let energy = nondimensional_energy * BOLTZMANN_CONSTANT * temperature;
163 self.extensions_at_energy(energy) / self.rest_length()
164 }
165 fn lengths_at_energy(&self, energy: Scalar) -> ScalarList<2> {
169 self.extensions_at_energy(energy) + ScalarList::from([self.rest_length(); 2])
170 }
171 fn nondimensional_lengths_at_nondimensional_energy(
175 &self,
176 nondimensional_energy: Scalar,
177 temperature: Scalar,
178 ) -> ScalarList<2> {
179 self.nondimensional_extensions_at_nondimensional_energy(nondimensional_energy, temperature)
180 + ScalarList::from([1.0; 2])
181 }
182 fn compliance(&self, force: Scalar) -> Scalar;
186 fn nondimensional_compliance(
190 &self,
191 nondimensional_force: Scalar,
192 temperature: Scalar,
193 ) -> Scalar {
194 let force = nondimensional_force / self.rest_length() * BOLTZMANN_CONSTANT * temperature;
195 self.compliance(force) / self.rest_length().powi(2) * BOLTZMANN_CONSTANT * temperature
196 }
197 fn peak(&self) -> Scalar;
201 fn peak_force(&self) -> Scalar;
205 fn rest_length(&self) -> Scalar;
209}