conspire/physics/molecular/single_chain/
mod.rs1mod arbitrary;
2mod efjc;
3mod efrc;
4mod fjc;
5mod frc;
6mod ideal;
7mod swfjc;
8mod ufjc;
9
10mod 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::{Scalar, Style, StyledError, assert::AssertionError, styled_error};
27use std::fmt::Debug;
28
29pub trait SingleChain
30where
31 Self: Clone + Debug,
32{
33 fn link_length(&self) -> Scalar;
34 fn number_of_links(&self) -> u8;
35}
36
37pub trait Inextensible
38where
39 Self: SingleChain,
40{
41 fn maximum_nondimensional_extension(&self) -> Scalar;
42 fn nondimensional_extension_check(
43 &self,
44 nondimensional_extension: Scalar,
45 ) -> Result<(), SingleChainError> {
46 if nondimensional_extension.abs() >= self.maximum_nondimensional_extension() {
47 Err(SingleChainError::MaximumExtensibility(
48 format!("{:?}", self.maximum_nondimensional_extension()),
49 format!("{self:?}"),
50 ))
51 } else {
52 Ok(())
53 }
54 }
55}
56
57pub trait Extensible
58where
59 Self: SingleChain,
60{
61}
62
63pub enum SingleChainError {
64 MaximumExtensibility(String, String),
65 Upstream(String, String),
66}
67
68impl From<SingleChainError> for AssertionError {
69 fn from(error: SingleChainError) -> Self {
70 Self {
71 message: error.to_string(),
72 }
73 }
74}
75
76impl From<SingleChainError> for String {
77 fn from(error: SingleChainError) -> Self {
78 error.message(&Style::detect())
79 }
80}
81
82impl StyledError for SingleChainError {
83 fn message(&self, style: &Style) -> String {
84 let (h, c) = (style.headline, style.frame);
85 match self {
86 Self::MaximumExtensibility(maximum_nondimensional_extension, single_chain_model) => {
87 format!(
88 "{h}Maximum extensibility ({maximum_nondimensional_extension}) reached.{c}\n\
89 In single-chain model: {single_chain_model}."
90 )
91 }
92 Self::Upstream(error, single_chain_model) => format!(
93 "{error}{c}\n\
94 In single-chain model: {single_chain_model}."
95 ),
96 }
97 }
98}
99
100styled_error!(SingleChainError);