Skip to main content

conspire/physics/molecular/single_chain/
mod.rs

1mod arbitrary;
2mod efjc;
3mod efrc;
4mod fjc;
5mod frc;
6mod ideal;
7mod swfjc;
8mod ufjc;
9
10/// Single-chain models of polymer statistical thermodynamics.
11mod thermodynamics;
12
13pub use arbitrary::{ArbitraryDiscrete, ArbitraryDiscretePotential};
14pub use efjc::ExtensibleFreelyJointedChain;
15pub use efrc::ExtensibleFreelyRotatingChain;
16pub use fjc::FreelyJointedChain;
17pub use frc::FreelyRotatingChain;
18pub use ideal::IdealChain;
19pub use swfjc::SquareWellFreelyJointedChain;
20pub use thermodynamics::{
21    Configuration, Ensemble, Isometric, Isotensional, IsotensionalExtensible, Legendre, MonteCarlo,
22    MonteCarloExtensible, MonteCarloInextensible, Thermodynamics, ThermodynamicsExtensible,
23};
24pub use ufjc::ArbitraryPotentialFreelyJointedChain;
25
26use crate::math::{Quantity, Scalar, Style, StyledError, assert::AssertionError, styled_error};
27use crate::units::Length;
28use std::fmt::{Debug, Display};
29
30pub trait SingleChain
31where
32    Self: Clone + Debug,
33{
34    fn link_length(&self) -> Quantity<Length>;
35    fn number_of_links(&self) -> u8;
36}
37
38pub trait Inextensible
39where
40    Self: SingleChain,
41{
42    fn maximum_nondimensional_extension(&self) -> Scalar;
43    fn nondimensional_extension_check(
44        &self,
45        nondimensional_extension: Scalar,
46    ) -> Result<(), SingleChainError> {
47        if nondimensional_extension.abs() >= self.maximum_nondimensional_extension() {
48            Err(SingleChainError::MaximumExtensibility(
49                format!("{:?}", self.maximum_nondimensional_extension()),
50                format!("{self:?}"),
51            ))
52        } else {
53            Ok(())
54        }
55    }
56}
57
58pub trait Extensible
59where
60    Self: SingleChain,
61{
62}
63
64pub enum SingleChainError {
65    MaximumExtensibility(String, String),
66    Upstream(String, String),
67}
68
69impl SingleChainError {
70    pub fn upstream(error: impl Display, context: &(impl Debug + ?Sized)) -> Self {
71        Self::Upstream(format!("{error}"), format!("{context:?}"))
72    }
73}
74
75impl From<SingleChainError> for AssertionError {
76    fn from(error: SingleChainError) -> Self {
77        Self {
78            message: error.to_string(),
79        }
80    }
81}
82
83impl From<SingleChainError> for String {
84    fn from(error: SingleChainError) -> Self {
85        error.message(&Style::detect())
86    }
87}
88
89impl StyledError for SingleChainError {
90    fn message(&self, style: &Style) -> String {
91        let (h, c) = (style.headline, style.frame);
92        match self {
93            Self::MaximumExtensibility(maximum_nondimensional_extension, single_chain_model) => {
94                format!(
95                    "{h}Maximum extensibility ({maximum_nondimensional_extension}) reached.{c}\n\
96                    In single-chain model: {single_chain_model}."
97                )
98            }
99            Self::Upstream(error, single_chain_model) => format!(
100                "{error}{c}\n\
101                In single-chain model: {single_chain_model}."
102            ),
103        }
104    }
105}
106
107styled_error!(SingleChainError);