Skip to main content

polysim_core/polymer/
chain.rs

1/// Composition unit for copolymer chains.
2///
3/// Stores a single repeat unit type with its molar fraction in the chain.
4#[derive(Debug, Clone, PartialEq)]
5pub struct MonomerUnit {
6    /// SMILES string of the repeat unit (e.g. "CC" for ethylene).
7    pub smiles: String,
8    /// Molar fraction of this unit in the chain (0.0–1.0).
9    pub fraction: f64,
10}
11
12impl MonomerUnit {
13    /// Creates a new `MonomerUnit`.
14    pub fn new(smiles: impl Into<String>, fraction: f64) -> Self {
15        Self {
16            smiles: smiles.into(),
17            fraction,
18        }
19    }
20}
21
22/// Polymer chain architecture classification.
23#[derive(Debug, Clone, PartialEq, Default)]
24pub enum Architecture {
25    /// Simple linear chain (default).
26    #[default]
27    Linear,
28    /// Star polymer with `arms` number of arms radiating from a central core.
29    Star { arms: usize },
30    /// Comb polymer with branches every `branch_spacing` backbone units.
31    Comb { branch_spacing: usize },
32    /// Dendrimer of the given `generation`.
33    Dendrimer { generation: usize },
34    /// Cyclic polymer (no chain ends).
35    Cyclic,
36    /// Gradient copolymer with composition varying along the chain.
37    Gradient,
38    /// Graft copolymer with randomly placed branches at `graft_fraction`.
39    Graft { graft_fraction: f64 },
40}
41
42/// A single, fully resolved polymer chain instance.
43///
44/// A `PolymerChain` is the output of a builder: it holds the concrete SMILES
45/// string for the generated chain together with metadata computed at build time.
46#[derive(Debug, Clone)]
47pub struct PolymerChain {
48    /// SMILES string representing this specific chain.
49    pub smiles: String,
50    /// Number of repeat units incorporated into the chain.
51    pub repeat_count: usize,
52    /// Number-average molecular weight in g/mol.
53    pub mn: f64,
54    /// Monomer composition: each unit type with its molar fraction.
55    ///
56    /// Homopolymers have a single element with fraction 1.0.
57    /// Empty when composition was not tracked by the builder.
58    pub composition: Vec<MonomerUnit>,
59    /// Polymer architecture (linear by default).
60    pub architecture: Architecture,
61}
62
63impl PolymerChain {
64    /// Creates a new `PolymerChain` with the given SMILES, repeat count, and Mn.
65    ///
66    /// `composition` defaults to empty and `architecture` to `Linear`.
67    /// Use the builder methods [`Self::with_composition`] and
68    /// [`Self::with_architecture`] to populate these fields.
69    pub fn new(smiles: String, repeat_count: usize, mn: f64) -> Self {
70        Self {
71            smiles,
72            repeat_count,
73            mn,
74            composition: Vec::new(),
75            architecture: Architecture::default(),
76        }
77    }
78
79    /// Attaches monomer composition metadata to this chain.
80    pub fn with_composition(mut self, composition: Vec<MonomerUnit>) -> Self {
81        self.composition = composition;
82        self
83    }
84
85    /// Attaches architecture metadata to this chain.
86    pub fn with_architecture(mut self, architecture: Architecture) -> Self {
87        self.architecture = architecture;
88        self
89    }
90}
91
92impl std::fmt::Display for PolymerChain {
93    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
94        write!(f, "{}", self.smiles)
95    }
96}