#[cfg(test)]
mod test;
use crate::{
math::Scalar,
physics::molecular::single_chain::{
Ensemble, Isometric, Isotensional, Legendre, SingleChain, SingleChainError, Thermodynamics,
},
};
use std::f64::consts::PI;
#[derive(Clone, Debug)]
pub struct IdealChain {
pub link_length: Scalar,
pub number_of_links: u8,
pub ensemble: Ensemble,
}
impl SingleChain for IdealChain {
fn link_length(&self) -> Scalar {
self.link_length
}
fn number_of_links(&self) -> u8 {
self.number_of_links
}
}
impl Thermodynamics for IdealChain {
fn ensemble(&self) -> Ensemble {
self.ensemble
}
}
impl Isometric for IdealChain {
fn nondimensional_helmholtz_free_energy(
&self,
nondimensional_extension: Scalar,
) -> Result<Scalar, SingleChainError> {
Ok(1.5 * self.number_of_links() as Scalar * nondimensional_extension.powi(2))
}
fn nondimensional_force(
&self,
nondimensional_extension: Scalar,
) -> Result<Scalar, SingleChainError> {
Ok(3.0 * nondimensional_extension)
}
fn nondimensional_stiffness(
&self,
_nondimensional_extension: Scalar,
) -> Result<Scalar, SingleChainError> {
Ok(3.0)
}
fn nondimensional_spherical_distribution(
&self,
nondimensional_extension: Scalar,
) -> Result<Scalar, SingleChainError> {
let number_of_links = self.number_of_links() as Scalar;
Ok((1.5 / PI / number_of_links).powf(1.5)
* (-1.5 * number_of_links * nondimensional_extension.powi(2)).exp())
}
}
impl Isotensional for IdealChain {
fn nondimensional_gibbs_free_energy(
&self,
nondimensional_force: Scalar,
) -> Result<Scalar, SingleChainError> {
Ok(self.number_of_links() as Scalar / -6.0 * nondimensional_force.powi(2))
}
fn nondimensional_extension(
&self,
nondimensional_force: Scalar,
) -> Result<Scalar, SingleChainError> {
Ok(nondimensional_force / 3.0)
}
fn nondimensional_compliance(
&self,
_nondimensional_force: Scalar,
) -> Result<Scalar, SingleChainError> {
Ok(1.0 / 3.0)
}
}
impl Legendre for IdealChain {
fn nondimensional_force(
&self,
nondimensional_extension: Scalar,
) -> Result<Scalar, SingleChainError> {
Isometric::nondimensional_force(self, nondimensional_extension)
}
fn nondimensional_extension(
&self,
nondimensional_force: Scalar,
) -> Result<Scalar, SingleChainError> {
Isotensional::nondimensional_extension(self, nondimensional_force)
}
fn nondimensional_spherical_distribution(
&self,
nondimensional_extension: Scalar,
) -> Result<Scalar, SingleChainError> {
Isometric::nondimensional_spherical_distribution(self, nondimensional_extension)
}
}