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
#![allow(dead_code)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, PartialEq, PartialOrd)]
/// A unit cell of a crystal, containing its dimensions and angles
pub struct UnitCell {
/// a-axis dimension
a: f64,
/// b-axis dimension
b: f64,
/// c-axis dimension
c: f64,
/// alpha angle in degrees
alpha: f64,
/// beta angle in degrees
beta: f64,
/// gamma angle in degrees
gamma: f64,
}
impl UnitCell {
/// Create a new `UnitCell` construct.
/// ## Arguments
/// * `a` - a-axis dimension
/// * `b` - b-axis dimension
/// * `c` - c-axis dimension
/// * `alpha` - alpha angle in degrees
/// * `beta` - beta angle in degrees
/// * `gamma` - gamma angle in degrees
#[must_use]
pub const fn new(a: f64, b: f64, c: f64, alpha: f64, beta: f64, gamma: f64) -> Self {
Self {
a,
b,
c,
alpha,
beta,
gamma,
}
}
/// Get the a-axis dimension
#[must_use]
pub const fn a(&self) -> f64 {
self.a
}
/// Get the b-axis dimension
#[must_use]
pub const fn b(&self) -> f64 {
self.b
}
/// Get the c-axis dimension
#[must_use]
pub const fn c(&self) -> f64 {
self.c
}
/// Set the a-axis dimension
/// ## Panics
/// It panics if the new value is not finite
pub fn set_a(&mut self, new_a: f64) {
assert!(
new_a.is_finite(),
"The new a value of this UnitCell is not finite. Value: {new_a}"
);
self.a = new_a;
}
/// Set the b-axis dimension
/// ## Panics
/// It panics if the new value is not finite
pub fn set_b(&mut self, new_b: f64) {
assert!(
new_b.is_finite(),
"The new b value of this UnitCell is not finite. Value: {new_b}"
);
self.b = new_b;
}
/// Set the c-axis dimension
/// ## Panics
/// It panics if the new value is not finite
pub fn set_c(&mut self, new_c: f64) {
assert!(
new_c.is_finite(),
"The new c value of this UnitCell is not finite. Value: {new_c}"
);
self.c = new_c;
}
/// Get the alpha angle in degrees
#[must_use]
pub const fn alpha(&self) -> f64 {
self.alpha
}
/// Set the alpha angle in degrees
/// ## Panics
/// It panics if the new value is not finite.
/// It also panics if the alpha value is outside of bounds [0, 360)
pub fn set_alpha(&mut self, new_alpha: f64) {
assert!(
new_alpha.is_finite(),
"The new alpha value of this UnitCell is not finite. Value: {new_alpha}"
);
assert!(
(0.0..360.0).contains(&new_alpha),
"The new alpha value of this UnitCell is out of bounds [0, 360). Value: {new_alpha}"
);
self.alpha = new_alpha;
}
/// Get the beta angle in degrees
#[must_use]
pub const fn beta(&self) -> f64 {
self.beta
}
/// Set the beta angle in degrees
/// ## Panics
/// It panics if the new value is not finite.
/// It also panics if the beta value is outside of bounds [0, 360)
pub fn set_beta(&mut self, new_beta: f64) {
assert!(
new_beta.is_finite(),
"The new beta value of this UnitCell is not finite. Value: {new_beta}"
);
assert!(
(0.0..360.0).contains(&new_beta),
"The new beta value of this UnitCell is out of bounds [0, 360).. Value: {new_beta}"
);
self.beta = new_beta;
}
/// Get the gamma angle in degrees
#[must_use]
pub const fn gamma(&self) -> f64 {
self.gamma
}
/// Set the gamma angle in degrees
/// ## Panics
/// It panics if the new value is not finite.
/// It also panics if the gamma value is outside of bounds [0, 360)
pub fn set_gamma(&mut self, new_gamma: f64) {
assert!(
new_gamma.is_finite(),
"The new gamma value of this UnitCell is not finite. Value: {new_gamma}"
);
assert!(
(0.0..360.0).contains(&new_gamma),
"The new gamma value of this UnitCell is out of bounds [0, 360).. Value: {new_gamma}"
);
self.gamma = new_gamma;
}
/// Get the dimensions in a tuple (a, b, c)
#[must_use]
pub const fn size(&self) -> (f64, f64, f64) {
(self.a, self.b, self.c)
}
}
impl Default for UnitCell {
/// Default `UnitCell` with all sizes set to 0.0 and angles to 90.0
fn default() -> Self {
Self::new(0.0, 0.0, 0.0, 90.0, 90.0, 90.0)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn equality() {
let a = UnitCell::new(10.0, 10.0, 15.0, 90.0, 90.0, 87.0);
let b = UnitCell::new(10.0, 10.0, 15.0, 90.0, 90.0, 87.0);
let c = UnitCell::new(12.0, 10.0, 15.0, 90.0, 90.0, 87.0);
assert_eq!(a, b);
assert_ne!(a, c);
}
}