conspire/physics/molecular/single_chain/ideal/
mod.rs1#[cfg(test)]
2mod test;
3
4use crate::{
5 math::{Quantity, Scalar},
6 physics::molecular::single_chain::{
7 Ensemble, Isometric, Isotensional, Legendre, SingleChain, SingleChainError, Thermodynamics,
8 },
9 units::Length,
10};
11use std::f64::consts::PI;
12
13#[derive(Clone, Debug)]
15pub struct IdealChain {
16 pub link_length: Scalar,
18 pub number_of_links: u8,
20 pub ensemble: Ensemble,
22}
23
24impl SingleChain for IdealChain {
25 fn link_length(&self) -> Quantity<Length> {
26 Quantity::new(self.link_length)
27 }
28 fn number_of_links(&self) -> u8 {
29 self.number_of_links
30 }
31}
32
33impl Thermodynamics for IdealChain {
34 fn ensemble(&self) -> Ensemble {
35 self.ensemble
36 }
37}
38
39impl Isometric for IdealChain {
40 fn nondimensional_helmholtz_free_energy(
44 &self,
45 nondimensional_extension: Scalar,
46 ) -> Result<Scalar, SingleChainError> {
47 Ok(1.5 * self.number_of_links() as Scalar * nondimensional_extension.powi(2))
48 }
49 fn nondimensional_force(
53 &self,
54 nondimensional_extension: Scalar,
55 ) -> Result<Scalar, SingleChainError> {
56 Ok(3.0 * nondimensional_extension)
57 }
58 fn nondimensional_stiffness(
62 &self,
63 _nondimensional_extension: Scalar,
64 ) -> Result<Scalar, SingleChainError> {
65 Ok(3.0)
66 }
67 fn nondimensional_spherical_distribution(
71 &self,
72 nondimensional_extension: Scalar,
73 ) -> Result<Scalar, SingleChainError> {
74 let number_of_links = self.number_of_links() as Scalar;
75 Ok((1.5 / PI / number_of_links).powf(1.5)
76 * (-1.5 * number_of_links * nondimensional_extension.powi(2)).exp())
77 }
78}
79
80impl Isotensional for IdealChain {
81 fn nondimensional_gibbs_free_energy(
85 &self,
86 nondimensional_force: Scalar,
87 ) -> Result<Scalar, SingleChainError> {
88 Ok(self.number_of_links() as Scalar / -6.0 * nondimensional_force.powi(2))
89 }
90 fn nondimensional_extension(
94 &self,
95 nondimensional_force: Scalar,
96 ) -> Result<Scalar, SingleChainError> {
97 Ok(nondimensional_force / 3.0)
98 }
99 fn nondimensional_compliance(
103 &self,
104 _nondimensional_force: Scalar,
105 ) -> Result<Scalar, SingleChainError> {
106 Ok(1.0 / 3.0)
107 }
108}
109
110impl Legendre for IdealChain {
111 fn nondimensional_force(
115 &self,
116 nondimensional_extension: Scalar,
117 ) -> Result<Scalar, SingleChainError> {
118 Isometric::nondimensional_force(self, nondimensional_extension)
119 }
120 fn nondimensional_extension(
124 &self,
125 nondimensional_force: Scalar,
126 ) -> Result<Scalar, SingleChainError> {
127 Isotensional::nondimensional_extension(self, nondimensional_force)
128 }
129 fn nondimensional_spherical_distribution(
133 &self,
134 nondimensional_extension: Scalar,
135 ) -> Result<Scalar, SingleChainError> {
136 Isometric::nondimensional_spherical_distribution(self, nondimensional_extension)
137 }
138}