#[cfg(test)]
mod test;
mod harmonic;
mod morse;
pub use harmonic::Harmonic;
pub use morse::Morse;
use crate::{
math::{Scalar, ScalarList},
physics::BOLTZMANN_CONSTANT,
};
use std::fmt::Debug;
pub trait Potential
where
Self: Clone + Debug,
{
fn energy(&self, length: Scalar) -> Scalar;
fn nondimensional_energy(&self, nondimensional_length: Scalar, temperature: Scalar) -> Scalar {
let length = self.rest_length() * nondimensional_length;
self.energy(length) / BOLTZMANN_CONSTANT / temperature
}
fn energy_at_force(&self, force: Scalar) -> Scalar {
let extension = self.extension(force);
let length = self.rest_length() + extension;
self.energy(length)
}
fn nondimensional_energy_at_nondimensional_force(
&self,
nondimensional_force: Scalar,
temperature: Scalar,
) -> Scalar {
let force = nondimensional_force / self.rest_length() * BOLTZMANN_CONSTANT * temperature;
self.energy_at_force(force) / BOLTZMANN_CONSTANT / temperature
}
fn force(&self, length: Scalar) -> Scalar;
fn nondimensional_force(&self, nondimensional_length: Scalar, temperature: Scalar) -> Scalar {
let length = self.rest_length() * nondimensional_length;
self.force(length) * self.rest_length() / BOLTZMANN_CONSTANT / temperature
}
fn forces_at_energy(&self, energy: Scalar) -> ScalarList<2>;
fn nondimensional_forces_at_nondimensional_energy(
&self,
nondimensional_energy: Scalar,
temperature: Scalar,
) -> ScalarList<2> {
let energy = nondimensional_energy * BOLTZMANN_CONSTANT * temperature;
self.forces_at_energy(energy) * self.rest_length() / BOLTZMANN_CONSTANT / temperature
}
fn stiffness(&self, length: Scalar) -> Scalar;
fn nondimensional_stiffness(
&self,
nondimensional_length: Scalar,
temperature: Scalar,
) -> Scalar {
let length = self.rest_length() * nondimensional_length;
self.stiffness(length) * self.rest_length().powi(2) / BOLTZMANN_CONSTANT / temperature
}
fn anharmonicity(&self, length: Scalar) -> Scalar;
fn nondimensional_anharmonicity(
&self,
nondimensional_length: Scalar,
temperature: Scalar,
) -> Scalar {
let length = self.rest_length() * nondimensional_length;
self.anharmonicity(length) * self.rest_length().powi(3) / BOLTZMANN_CONSTANT / temperature
}
fn legendre(&self, force: Scalar) -> Scalar {
let extension = self.extension(force);
let length = self.rest_length() + extension;
self.energy(length) - force * extension
}
fn nondimensional_legendre(&self, nondimensional_force: Scalar, temperature: Scalar) -> Scalar {
let force = nondimensional_force / self.rest_length() * BOLTZMANN_CONSTANT * temperature;
self.legendre(force) / BOLTZMANN_CONSTANT / temperature
}
fn extension(&self, force: Scalar) -> Scalar;
fn nondimensional_extension(
&self,
nondimensional_force: Scalar,
temperature: Scalar,
) -> Scalar {
let force = nondimensional_force / self.rest_length() * BOLTZMANN_CONSTANT * temperature;
self.extension(force) / self.rest_length()
}
fn length(&self, force: Scalar) -> Scalar {
self.rest_length() + self.extension(force)
}
fn nondimensional_length(&self, nondimensional_force: Scalar, temperature: Scalar) -> Scalar {
1.0 + self.nondimensional_extension(nondimensional_force, temperature)
}
fn extensions_at_energy(&self, energy: Scalar) -> ScalarList<2>;
fn nondimensional_extensions_at_nondimensional_energy(
&self,
nondimensional_energy: Scalar,
temperature: Scalar,
) -> ScalarList<2> {
let energy = nondimensional_energy * BOLTZMANN_CONSTANT * temperature;
self.extensions_at_energy(energy) / self.rest_length()
}
fn lengths_at_energy(&self, energy: Scalar) -> ScalarList<2> {
self.extensions_at_energy(energy) + ScalarList::from([self.rest_length(); 2])
}
fn nondimensional_lengths_at_nondimensional_energy(
&self,
nondimensional_energy: Scalar,
temperature: Scalar,
) -> ScalarList<2> {
self.nondimensional_extensions_at_nondimensional_energy(nondimensional_energy, temperature)
+ ScalarList::from([1.0; 2])
}
fn compliance(&self, force: Scalar) -> Scalar;
fn nondimensional_compliance(
&self,
nondimensional_force: Scalar,
temperature: Scalar,
) -> Scalar {
let force = nondimensional_force / self.rest_length() * BOLTZMANN_CONSTANT * temperature;
self.compliance(force) / self.rest_length().powi(2) * BOLTZMANN_CONSTANT * temperature
}
fn peak(&self) -> Scalar;
fn peak_force(&self) -> Scalar;
fn rest_length(&self) -> Scalar;
}