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
pub use gchemol_lattice::Lattice;
use crate::atom::Vector3f;
use crate::molecule::Molecule;
impl Molecule {
pub fn set_lattice(&mut self, lat: Lattice) {
self.lattice = Some(lat);
}
pub fn is_periodic(&self) -> bool {
self.lattice.is_some()
}
pub fn unbuild_crystal(&mut self) {
self.lattice = None
}
pub fn scaled_positions(&self) -> Option<impl Iterator<Item = [f64; 3]> + '_> {
self.lattice
.map(|lat| self.positions().map(move |cart| lat.to_frac(cart).into()))
}
pub fn set_scaled_positions<T, P>(&mut self, scaled: T)
where
T: IntoIterator<Item = P>,
P: Into<Vector3f>,
{
let lat = self
.lattice
.expect("cannot set scaled positions for aperiodic structure");
let positions = scaled.into_iter().map(|frac| lat.to_cart(frac));
self.set_positions(positions);
}
}
#[cfg(feature = "adhoc")]
impl Molecule {
pub fn supercell(&self, sa: usize, sb: usize, sc: usize) -> Option<Molecule> {
let lat = self.lattice.unwrap();
let (sa, sb, sc) = (sa as isize, sb as isize, sc as isize);
let mut atoms = vec![];
for image in lat.replicate(0..sa, 0..sb, 0..sc) {
let mut m = self.clone();
let t = lat.to_cart(image);
m.translate(t);
for (_, atom) in m.atoms() {
atoms.push(atom.clone());
}
}
let mut mol_new = Molecule::from_atoms(atoms);
let mut vabc = lat.vectors();
let size = [sa, sb, sc];
for v in vabc.iter_mut() {
for i in 0..3 {
v[i] *= size[i] as f64;
}
}
mol_new.lattice = Some(Lattice::new(vabc));
Some(mol_new)
}
}