Skip to main content

conspire/physics/molecular/single_chain/ideal/
mod.rs

1#[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/// The ideal chain model.
14#[derive(Clone, Debug)]
15pub struct IdealChain {
16    /// The link length $`\ell_b`$.
17    pub link_length: Scalar,
18    /// The number of links $`N_b`$.
19    pub number_of_links: u8,
20    /// The thermodynamic ensemble.
21    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    /// ```math
41    /// \beta\psi(\gamma) = \frac{3}{2}\,N_b\gamma^2
42    /// ```
43    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    /// ```math
50    /// \eta(\gamma) = 3\gamma
51    /// ```
52    fn nondimensional_force(
53        &self,
54        nondimensional_extension: Scalar,
55    ) -> Result<Scalar, SingleChainError> {
56        Ok(3.0 * nondimensional_extension)
57    }
58    /// ```math
59    /// \kappa(\gamma) = 3
60    /// ```
61    fn nondimensional_stiffness(
62        &self,
63        _nondimensional_extension: Scalar,
64    ) -> Result<Scalar, SingleChainError> {
65        Ok(3.0)
66    }
67    /// ```math
68    /// \mathcal{P}(\gamma) = \left(\frac{3}{2\pi N_b}\right)^{3/2}\exp\left(-\frac{3}{2}\,N_b\gamma^2\right)
69    /// ```
70    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    /// ```math
82    /// \beta\varphi(\eta) = \frac{1}{6}\,N_b\eta^2
83    /// ```
84    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    /// ```math
91    /// \gamma(\eta) = \frac{\eta}{3}
92    /// ```
93    fn nondimensional_extension(
94        &self,
95        nondimensional_force: Scalar,
96    ) -> Result<Scalar, SingleChainError> {
97        Ok(nondimensional_force / 3.0)
98    }
99    /// ```math
100    /// \zeta(\eta) = \frac{1}{3}
101    /// ```
102    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    /// ```math
112    /// \eta(\gamma) = 3\gamma
113    /// ```
114    fn nondimensional_force(
115        &self,
116        nondimensional_extension: Scalar,
117    ) -> Result<Scalar, SingleChainError> {
118        Isometric::nondimensional_force(self, nondimensional_extension)
119    }
120    /// ```math
121    /// \gamma(\eta) = \frac{\eta}{3}
122    /// ```
123    fn nondimensional_extension(
124        &self,
125        nondimensional_force: Scalar,
126    ) -> Result<Scalar, SingleChainError> {
127        Isotensional::nondimensional_extension(self, nondimensional_force)
128    }
129    /// ```math
130    /// \mathcal{P}(\gamma) = \left(\frac{3}{2\pi N_b}\right)^{3/2}\exp\left(-\frac{3}{2}\,N_b\gamma^2\right)
131    /// ```
132    fn nondimensional_spherical_distribution(
133        &self,
134        nondimensional_extension: Scalar,
135    ) -> Result<Scalar, SingleChainError> {
136        Isometric::nondimensional_spherical_distribution(self, nondimensional_extension)
137    }
138}