conspire/physics/molecular/single_chain/
mod.rs

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