use serde::Serialize;
use super::layer_hall_symbol_database::{LayerHallNumber, LayerNumber};
#[derive(Debug, Copy, Clone, PartialEq, Serialize)]
pub enum LayerSetting {
HallNumber(LayerHallNumber),
Spglib,
Standard,
}
impl Default for LayerSetting {
fn default() -> Self {
Self::Standard
}
}
#[rustfmt::skip]
const LAYER_SPGLIB_HALL_NUMBERS: [LayerHallNumber; 80] = [
1, 2, 3, 4, 5, 8, 9, 12, 14, 16,
18, 20, 22, 24, 26, 28, 30, 32, 34, 35,
37, 38, 39, 40, 42, 43, 44, 46, 48, 50,
52, 54, 56, 58, 60, 62, 64, 65, 67, 68,
70, 72, 74, 76, 77, 79, 80, 81, 82, 83,
84, 85, 87, 88, 89, 90, 91, 92, 93, 94,
95, 96, 98, 99, 101, 102, 103, 104, 105, 106,
107, 108, 109, 110, 111, 112, 113, 114, 115, 116,
];
#[rustfmt::skip]
const LAYER_STANDARD_HALL_NUMBERS: [LayerHallNumber; 80] = [
1, 2, 3, 4, 5, 8, 9, 12, 14, 16,
18, 20, 22, 24, 26, 28, 30, 32, 34, 35,
37, 38, 39, 40, 42, 43, 44, 46, 48, 50,
52, 54, 56, 58, 60, 62, 64, 65, 67, 68,
70, 72, 74, 76, 77, 79, 80, 81, 82, 83,
84, 86, 87, 88, 89, 90, 91, 92, 93, 94,
95, 97, 98, 100, 101, 102, 103, 104, 105, 106,
107, 108, 109, 110, 111, 112, 113, 114, 115, 116,
];
impl LayerSetting {
pub fn hall_numbers(&self) -> Vec<LayerHallNumber> {
match self {
LayerSetting::HallNumber(hn) => vec![*hn],
LayerSetting::Spglib => LAYER_SPGLIB_HALL_NUMBERS.to_vec(),
LayerSetting::Standard => LAYER_STANDARD_HALL_NUMBERS.to_vec(),
}
}
pub fn hall_number(&self, number: LayerNumber) -> Option<LayerHallNumber> {
let idx = (number as usize).checked_sub(1)?;
match self {
LayerSetting::HallNumber(_) => None,
LayerSetting::Spglib => LAYER_SPGLIB_HALL_NUMBERS.get(idx).copied(),
LayerSetting::Standard => LAYER_STANDARD_HALL_NUMBERS.get(idx).copied(),
}
}
}
#[cfg(test)]
mod tests {
use std::collections::HashMap;
use super::*;
use crate::data::{iter_layer_hall_symbol_entry, layer_hall_symbol_entry};
#[test]
fn test_layer_spglib_hall_numbers_match_db() {
let mut first_seen: HashMap<LayerNumber, LayerHallNumber> = HashMap::new();
for entry in iter_layer_hall_symbol_entry() {
first_seen.entry(entry.number).or_insert(entry.hall_number);
}
for lg in 1..=80 {
let expected = *first_seen
.get(&lg)
.unwrap_or_else(|| panic!("LG {} missing from database", lg));
assert_eq!(
LAYER_SPGLIB_HALL_NUMBERS[(lg - 1) as usize],
expected,
"spglib Hall number for LG {} drifted from database",
lg
);
}
}
#[test]
fn test_layer_standard_hall_numbers_origin_choice() {
for &(lg, spglib_hall, standard_hall) in &[(52, 85, 86), (62, 96, 97), (64, 99, 100)] {
assert_eq!(
LayerSetting::Spglib.hall_number(lg).unwrap(),
spglib_hall,
"LG {} Spglib Hall mismatch",
lg
);
assert_eq!(
LayerSetting::Standard.hall_number(lg).unwrap(),
standard_hall,
"LG {} Standard Hall mismatch",
lg
);
assert_eq!(
layer_hall_symbol_entry(spglib_hall).unwrap().setting,
"1",
"LG {} Hall {} should be origin choice 1",
lg,
spglib_hall
);
assert_eq!(
layer_hall_symbol_entry(standard_hall).unwrap().setting,
"2",
"LG {} Hall {} should be origin choice 2",
lg,
standard_hall
);
}
}
#[test]
fn test_layer_standard_hall_numbers_match_conventions() {
for lg in 1..=80 {
if matches!(lg, 52 | 62 | 64) {
continue;
}
assert_eq!(
LayerSetting::Standard.hall_number(lg),
LayerSetting::Spglib.hall_number(lg),
"Standard and Spglib disagree for non-centrosymmetric LG {}",
lg
);
}
for lg in [5, 7] {
let hall = LayerSetting::Standard.hall_number(lg).unwrap();
assert_eq!(
layer_hall_symbol_entry(hall).unwrap().setting,
"c1",
"LG {} expected cell choice 1 (c1)",
lg
);
}
for lg in [3, 4, 6] {
let hall = LayerSetting::Standard.hall_number(lg).unwrap();
let s = layer_hall_symbol_entry(hall).unwrap().setting;
assert!(
s.is_empty() || s == "c",
"LG {} (monoclinic-oblique) setting {:?}",
lg,
s
);
}
for lg in 8..=18 {
let hall = LayerSetting::Standard.hall_number(lg).unwrap();
let s = layer_hall_symbol_entry(hall).unwrap().setting;
assert_eq!(
s, "a",
"LG {} (monoclinic-rectangular) expected :a labelling",
lg
);
}
for lg in 19..=48 {
let hall = LayerSetting::Standard.hall_number(lg).unwrap();
let s = layer_hall_symbol_entry(hall).unwrap().setting;
assert_eq!(s, "", "LG {} (orthorhombic) expected abc setting", lg);
}
}
#[test]
fn test_hall_numbers_lengths() {
assert_eq!(LayerSetting::Standard.hall_numbers().len(), 80);
assert_eq!(LayerSetting::Spglib.hall_numbers().len(), 80);
assert_eq!(LayerSetting::HallNumber(7).hall_numbers(), vec![7]);
}
#[test]
fn test_hall_number_lookup() {
assert_eq!(LayerSetting::Standard.hall_number(1), Some(1));
assert_eq!(LayerSetting::Standard.hall_number(5), Some(5));
assert_eq!(LayerSetting::Standard.hall_number(52), Some(86));
assert_eq!(LayerSetting::Standard.hall_number(80), Some(116));
assert_eq!(LayerSetting::Standard.hall_number(0), None);
assert_eq!(LayerSetting::Standard.hall_number(81), None);
assert_eq!(LayerSetting::Spglib.hall_number(52), Some(85));
assert_eq!(LayerSetting::HallNumber(1).hall_number(1), None);
}
#[test]
fn test_default_is_standard() {
assert_eq!(LayerSetting::default(), LayerSetting::Standard);
}
}