1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
//! Data structures to hold physical information about the simulation environment.

pub mod cell;
pub mod elements;

use nalgebra::Vector3;
use serde::{Deserialize, Serialize};

use crate::system::cell::Cell;
use crate::system::elements::Element;

/// Collection of atomic properties and bonding information.
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct System {
    /// Number of atoms in the system.
    size: usize,

    /// Simulation cell with periodic boundary conditions.
    pub cell: Cell,

    /// Element type for each atom in the system.
    pub elements: Vec<Element>,
    /// Molecule type for each atom in the system.
    pub molecules: Vec<usize>,
    /// Position of each atom in the system.
    pub positions: Vec<Vector3<f32>>,
    /// Velocity of each atom in the system.
    pub velocities: Vec<Vector3<f32>>,
    /// Electronic charge of each atom in the system.
    pub charges: Vec<f32>,

    /// Collection of bond indices grouped by bond type.
    pub bonds: Vec<Vec<(usize, usize)>>,
    /// Collection of angle triplet indices grouped by angle type.
    pub angles: Vec<Vec<(usize, usize, usize)>>,
    /// Collection of dihedral quadruplet indices grouped by dihedral type.
    pub dihedrals: Vec<Vec<(usize, usize, usize, usize)>>,
}

impl System {
    /// Returns the number of atoms in the system.
    pub fn size(&self) -> usize {
        self.size
    }
}

/// Constructor for the [`System`](velvet_core::system::System) type.
pub struct SystemBuilder {
    size: usize,
    cell: Option<Cell>,
    elements: Option<Vec<Element>>,
    molecules: Option<Vec<usize>>,
    positions: Option<Vec<Vector3<f32>>>,
    velocities: Option<Vec<Vector3<f32>>>,
    charges: Option<Vec<f32>>,
    bonds: Option<Vec<Vec<(usize, usize)>>>,
    angles: Option<Vec<Vec<(usize, usize, usize)>>>,
    dihedrals: Option<Vec<Vec<(usize, usize, usize, usize)>>>,
}

impl SystemBuilder {
    /// Returns a new system builder.
    ///
    /// # Arguments
    ///
    /// * `size` - The number of atoms in the system
    pub fn new(size: usize) -> SystemBuilder {
        SystemBuilder {
            size,
            cell: None,
            elements: None,
            molecules: None,
            positions: None,
            velocities: None,
            charges: None,
            bonds: None,
            angles: None,
            dihedrals: None,
        }
    }

    /// Sets the system cell.
    pub fn with_cell(mut self, cell: Cell) -> SystemBuilder {
        self.cell = Some(cell);
        self
    }

    /// Sets the element of each atom in the system.
    pub fn with_elements(mut self, elements: Vec<Element>) -> SystemBuilder {
        assert!(elements.len() == self.size);
        self.elements = Some(elements);
        self
    }

    /// Sets the molecule of each atom in the system.
    pub fn with_molecules(mut self, molecules: Vec<usize>) -> SystemBuilder {
        assert!(molecules.len() == self.size);
        self.molecules = Some(molecules);
        self
    }

    /// Sets the position of each atom in the system.
    pub fn with_positions(mut self, positions: Vec<Vector3<f32>>) -> SystemBuilder {
        assert!(positions.len() == self.size);
        self.positions = Some(positions);
        self
    }

    /// Sets the velocity of each atom in the system.
    pub fn with_velocities(mut self, velocities: Vec<Vector3<f32>>) -> SystemBuilder {
        assert!(velocities.len() == self.size);
        self.velocities = Some(velocities);
        self
    }

    /// Sets the charge of each atom in the system.
    pub fn with_charges(mut self, charges: Vec<f32>) -> SystemBuilder {
        assert!(charges.len() == self.size);
        self.charges = Some(charges);
        self
    }

    /// Sets the pairwise bonds in the system.
    pub fn with_bonds(mut self, bonds: Vec<Vec<(usize, usize)>>) -> SystemBuilder {
        self.bonds = Some(bonds);
        self
    }

    /// Sets the angle triplets in the system.
    pub fn with_angles(mut self, angles: Vec<Vec<(usize, usize, usize)>>) -> SystemBuilder {
        self.angles = Some(angles);
        self
    }

    /// Sets the dihedral quadruplets in the system.
    pub fn with_dihedrals(
        mut self,
        dihedrals: Vec<Vec<(usize, usize, usize, usize)>>,
    ) -> SystemBuilder {
        self.dihedrals = Some(dihedrals);
        self
    }

    /// Finalizes the build and returns an initialized system.
    pub fn finish(self) -> System {
        let cell = match self.cell {
            Some(c) => c,
            None => panic!("System requires `cell` attribute"),
        };
        let elements = match self.elements {
            Some(e) => e,
            None => panic!("System requires `elements` attribute"),
        };
        let molecules = match self.molecules {
            Some(m) => m,
            None => vec![0 as usize; self.size],
        };
        let positions = match self.positions {
            Some(p) => p,
            None => panic!("System requires `positions` attribute"),
        };
        let velocities = match self.velocities {
            Some(v) => v,
            None => vec![Vector3::new(0.0, 0.0, 0.0); self.size],
        };
        let charges = match self.charges {
            Some(c) => c,
            None => vec![0.0; self.size],
        };
        let bonds = match self.bonds {
            Some(b) => b,
            None => Vec::new(),
        };
        let angles = match self.angles {
            Some(a) => a,
            None => Vec::new(),
        };
        let dihedrals = match self.dihedrals {
            Some(d) => d,
            None => Vec::new(),
        };
        System {
            size: self.size,
            cell,
            elements,
            molecules,
            positions,
            velocities,
            charges,
            bonds,
            angles,
            dihedrals,
        }
    }
}