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}