1use nalgebra::{Matrix3, Vector3};
2
3#[derive(Clone, Copy, Debug, PartialEq)]
4pub struct Cell {
5 pub m: Matrix3<f64>,
7}
8
9impl Cell {
10 pub fn new(cell: [[f64; 3]; 3]) -> Self {
11 Cell {
12 m: Matrix3::from_row_slice(cell.as_flattened()),
13 }
14 }
15
16 pub fn is_orthorhombic(&self) -> bool {
17 let eps = 1e-12;
18
19 let off_diagonal = self.m - Matrix3::from_diagonal(&self.m.diagonal());
21
22 let is_diagonal = off_diagonal.abs().max() < eps;
24
25 let has_positive_diagonal = self.m.diagonal().iter().all(|&x| x > eps);
27
28 is_diagonal && has_positive_diagonal
29 }
30
31 pub fn a(&self) -> Vector3<f64> {
32 self.m.row(0).transpose()
33 }
34
35 pub fn b(&self) -> Vector3<f64> {
36 self.m.row(1).transpose()
37 }
38
39 pub fn c(&self) -> Vector3<f64> {
40 self.m.row(2).transpose()
41 }
42
43 pub fn reduced(&self, a: f64, b: f64, c: f64) -> Vector3<f64> {
44 self.m.transpose() * Vector3::new(a, b, c)
45 }
46}
47
48#[cfg(test)]
49mod tests {
50
51 use nalgebra::Vector3;
52
53 use crate::Cell;
54
55 #[test]
56 fn test_ortho() {
57 let cell = Cell::new([[10.0, 0.0, 0.0], [0.0, 10.0, 0.0], [0.0, 0.0, 10.0]]);
58 assert!(cell.is_orthorhombic())
59 }
60
61 #[test]
62 fn test_not_ortho() {
63 let cell = Cell::new([[10.0, 5.0, 0.0], [0.0, 10.0, 0.0], [0.0, 0.0, 10.0]]);
64 assert!(!cell.is_orthorhombic())
65 }
66
67 #[test]
68 fn test_reduced_1() {
69 let cell = Cell::new([[10.0, 0.0, 0.0], [0.0, 10.0, 0.0], [0.0, 0.0, 10.0]]);
70 let result = cell.reduced(1.0, 0.0, 0.0);
71 let expected = Vector3::new(10.0, 0.0, 0.0);
72 assert_eq!(result, expected);
73 }
74
75 #[test]
76 fn test_reduced_2() {
77 let cell = Cell::new([[10.0, 0.0, 0.0], [0.0, 10.0, 0.0], [0.0, 0.0, 10.0]]);
78 let result = cell.reduced(0.0, 1.0, 0.0);
79 let expected = Vector3::new(0.0, 10.0, 0.0);
80 assert_eq!(result, expected);
81 }
82
83 #[test]
84 fn test_reduced_3() {
85 let cell = Cell::new([[10.0, 0.0, 0.0], [0.0, 10.0, 0.0], [0.0, 0.0, 10.0]]);
86 let result = cell.reduced(0.0, 0.0, 1.0);
87 let expected = Vector3::new(0.0, 0.0, 10.0);
88 assert_eq!(result, expected);
89 }
90
91 #[test]
92 fn test_reduced_4() {
93 let cell = Cell::new([[10.0, 5.0, 0.0], [5.0, 10.0, 0.0], [0.0, 0.0, 10.0]]);
94 let result = cell.reduced(0.5, 0.0, 0.0);
95 let expected = Vector3::new(5.0, 2.5, 0.0);
96 assert_eq!(result, expected);
97 }
98
99 #[test]
100 fn test_reduced_5() {
101 let cell = Cell::new([[10.0, 5.0, 0.0], [5.0, 10.0, 0.0], [0.0, 0.0, 10.0]]);
102 let result = cell.reduced(0.5, 0.5, 0.0);
103 let expected = Vector3::new(7.5, 7.5, 0.0);
104 assert_eq!(result, expected);
105 }
106
107 #[test]
108 fn test_cell_vectors() {
109 let cell = Cell::new([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0], [7.0, 8.0, 9.0]]);
110
111 assert_eq!(cell.a(), Vector3::new(1.0, 2.0, 3.0));
112 assert_eq!(cell.b(), Vector3::new(4.0, 5.0, 6.0));
113 assert_eq!(cell.c(), Vector3::new(7.0, 8.0, 9.0));
114 }
115}