Skip to content

Commit

Permalink
Get generators of reference space group
Browse files Browse the repository at this point in the history
  • Loading branch information
lan496 committed Jan 11, 2025
1 parent fb072d3 commit f109ea8
Show file tree
Hide file tree
Showing 4 changed files with 137 additions and 77 deletions.
1 change: 1 addition & 0 deletions moyo/src/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ pub use arithmetic_crystal_class::ArithmeticNumber;
pub use centering::Centering;
pub use hall_symbol::{HallSymbol, MagneticHallSymbol};
pub use hall_symbol_database::{hall_symbol_entry, HallNumber, HallSymbolEntry, Number};
pub use magnetic_hall_symbol_database::{magnetic_hall_symbol_entry, MagneticHallSymbolEntry};
pub use magnetic_space_group::{
get_magnetic_space_group_type, ConstructType, UNINumber, NUM_MAGNETIC_SPACE_GROUP_TYPES,
};
Expand Down
21 changes: 19 additions & 2 deletions moyo/src/data/magnetic_hall_symbol_database.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
use super::magnetic_space_group::{UNINumber, NUM_MAGNETIC_SPACE_GROUP_TYPES};
use super::hall_symbol_database::HallNumber;
use super::magnetic_space_group::{
get_magnetic_space_group_type, ConstructType, UNINumber, NUM_MAGNETIC_SPACE_GROUP_TYPES,
};
use super::setting::Setting;

#[derive(Debug, Clone)]
pub struct MagneticHallSymbolEntry {
Expand All @@ -13,6 +17,19 @@ impl MagneticHallSymbolEntry {
uni_number,
}
}

pub fn construct_type(&self) -> ConstructType {
get_magnetic_space_group_type(self.uni_number)
.unwrap()
.construct_type
}

pub fn reference_hall_number(&self) -> HallNumber {
let number = get_magnetic_space_group_type(self.uni_number)
.unwrap()
.number;
Setting::Standard.hall_number(number).unwrap()
}
}

pub fn magnetic_hall_symbol_entry(uni_number: UNINumber) -> Option<MagneticHallSymbolEntry> {
Expand Down Expand Up @@ -1679,7 +1696,7 @@ const MAGNETIC_HALL_SYMBOL_DATABASE: [MagneticHallSymbolEntry; NUM_MAGNETIC_SPAC
#[cfg(test)]
mod tests {
use super::*;
use crate::data::hall_symbol::MagneticHallSymbol;
use crate::data::MagneticHallSymbol;

fn iter_magnetic_hall_symbol_entry() -> impl Iterator<Item = &'static MagneticHallSymbolEntry> {
MAGNETIC_HALL_SYMBOL_DATABASE.iter()
Expand Down
75 changes: 40 additions & 35 deletions moyo/src/data/setting.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use super::hall_symbol_database::HallNumber;
use super::hall_symbol_database::{HallNumber, Number};

#[derive(Debug, Copy, Clone, PartialEq)]
/// Preference for the setting of the space group.
Expand All @@ -11,44 +11,49 @@ pub enum Setting {
Standard,
}

const SPGLIB_HALL_NUMBERS: [HallNumber; 230] = [
1, 2, 3, 6, 9, 18, 21, 30, 39, 57, 60, 63, 72, 81, 90, 108, 109, 112, 115, 116, 119, 122, 123,
124, 125, 128, 134, 137, 143, 149, 155, 161, 164, 170, 173, 176, 182, 185, 191, 197, 203, 209,
212, 215, 218, 221, 227, 228, 230, 233, 239, 245, 251, 257, 263, 266, 269, 275, 278, 284, 290,
292, 298, 304, 310, 313, 316, 322, 334, 335, 337, 338, 341, 343, 349, 350, 351, 352, 353, 354,
355, 356, 357, 358, 359, 361, 363, 364, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376,
377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395,
396, 397, 398, 399, 400, 401, 402, 404, 406, 407, 408, 410, 412, 413, 414, 416, 418, 419, 420,
422, 424, 425, 426, 428, 430, 431, 432, 433, 435, 436, 438, 439, 440, 441, 442, 443, 444, 446,
447, 448, 449, 450, 452, 454, 455, 456, 457, 458, 460, 462, 463, 464, 465, 466, 467, 468, 469,
470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488,
489, 490, 491, 492, 493, 494, 495, 497, 498, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509,
510, 511, 512, 513, 514, 515, 516, 517, 518, 520, 521, 523, 524, 525, 527, 529, 530,
];
const STANDARD_HALL_NUMBERS: [HallNumber; 230] = [
1, 2, 3, 6, 9, 18, 21, 30, 39, 57, 60, 63, 72, 81, 90, 108, 109, 112, 115, 116, 119, 122, 123,
124, 125, 128, 134, 137, 143, 149, 155, 161, 164, 170, 173, 176, 182, 185, 191, 197, 203, 209,
212, 215, 218, 221, 227, 229, 230, 234, 239, 245, 251, 257, 263, 266, 269, 275, 279, 284, 290,
292, 298, 304, 310, 313, 316, 323, 334, 336, 337, 338, 341, 343, 349, 350, 351, 352, 353, 354,
355, 356, 357, 358, 360, 362, 363, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376,
377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395,
396, 397, 398, 399, 400, 401, 403, 405, 406, 407, 409, 411, 412, 413, 415, 417, 418, 419, 421,
423, 424, 425, 427, 429, 430, 431, 432, 433, 435, 436, 438, 439, 440, 441, 442, 443, 444, 446,
447, 448, 449, 450, 452, 454, 455, 456, 457, 458, 460, 462, 463, 464, 465, 466, 467, 468, 469,
470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488,
489, 490, 491, 492, 493, 494, 496, 497, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509,
510, 511, 512, 513, 514, 515, 516, 517, 519, 520, 522, 523, 524, 526, 528, 529, 530,
];

impl Setting {
pub fn hall_numbers(&self) -> Vec<HallNumber> {
match self {
Setting::HallNumber(hall_number) => vec![*hall_number],
Setting::Spglib => vec![
1, 2, 3, 6, 9, 18, 21, 30, 39, 57, 60, 63, 72, 81, 90, 108, 109, 112, 115, 116,
119, 122, 123, 124, 125, 128, 134, 137, 143, 149, 155, 161, 164, 170, 173, 176,
182, 185, 191, 197, 203, 209, 212, 215, 218, 221, 227, 228, 230, 233, 239, 245,
251, 257, 263, 266, 269, 275, 278, 284, 290, 292, 298, 304, 310, 313, 316, 322,
334, 335, 337, 338, 341, 343, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358,
359, 361, 363, 364, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377,
378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393,
394, 395, 396, 397, 398, 399, 400, 401, 402, 404, 406, 407, 408, 410, 412, 413,
414, 416, 418, 419, 420, 422, 424, 425, 426, 428, 430, 431, 432, 433, 435, 436,
438, 439, 440, 441, 442, 443, 444, 446, 447, 448, 449, 450, 452, 454, 455, 456,
457, 458, 460, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474,
475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490,
491, 492, 493, 494, 495, 497, 498, 500, 501, 502, 503, 504, 505, 506, 507, 508,
509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 520, 521, 523, 524, 525, 527,
529, 530,
],
Setting::Standard => vec![
1, 2, 3, 6, 9, 18, 21, 30, 39, 57, 60, 63, 72, 81, 90, 108, 109, 112, 115, 116,
119, 122, 123, 124, 125, 128, 134, 137, 143, 149, 155, 161, 164, 170, 173, 176,
182, 185, 191, 197, 203, 209, 212, 215, 218, 221, 227, 229, 230, 234, 239, 245,
251, 257, 263, 266, 269, 275, 279, 284, 290, 292, 298, 304, 310, 313, 316, 323,
334, 336, 337, 338, 341, 343, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358,
360, 362, 363, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377,
378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393,
394, 395, 396, 397, 398, 399, 400, 401, 403, 405, 406, 407, 409, 411, 412, 413,
415, 417, 418, 419, 421, 423, 424, 425, 427, 429, 430, 431, 432, 433, 435, 436,
438, 439, 440, 441, 442, 443, 444, 446, 447, 448, 449, 450, 452, 454, 455, 456,
457, 458, 460, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474,
475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490,
491, 492, 493, 494, 496, 497, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508,
509, 510, 511, 512, 513, 514, 515, 516, 517, 519, 520, 522, 523, 524, 526, 528,
529, 530,
],
Setting::Spglib => SPGLIB_HALL_NUMBERS.to_vec(),
Setting::Standard => STANDARD_HALL_NUMBERS.to_vec(),
}
}

pub fn hall_number(&self, number: Number) -> Option<HallNumber> {
match self {
Setting::HallNumber(_) => None,
Setting::Spglib => SPGLIB_HALL_NUMBERS.get(number as usize - 1).cloned(),
Setting::Standard => STANDARD_HALL_NUMBERS.get(number as usize - 1).cloned(),
}
}
}
117 changes: 77 additions & 40 deletions moyo/src/identify/magnetic_space_group.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ use crate::base::{
UnimodularTransformation,
};
use crate::data::{
get_magnetic_space_group_type, uni_number_range, ConstructType, MagneticHallSymbol, Setting,
UNINumber,
get_magnetic_space_group_type, hall_symbol_entry, magnetic_hall_symbol_entry, uni_number_range,
ConstructType, HallSymbol, MagneticHallSymbol, MagneticHallSymbolEntry, Setting, UNINumber,
};

#[derive(Debug)]
Expand Down Expand Up @@ -54,11 +54,11 @@ impl MagneticSpaceGroup {

// TODO:

let mhs = MagneticHallSymbol::from_uni_number(uni_number)
let entry = magnetic_hall_symbol_entry(uni_number).unwrap();
let mhs = MagneticHallSymbol::new(&entry.magnetic_hall_symbol)
.ok_or(MoyoError::MagneticSpaceGroupTypeIdentificationError)?;
let db_prim_mag_generators = mhs.primitive_generators();
let db_ref_prim_generators =
Self::get_db_reference_space_group_primitive_generators(&mhs, &construct_type);
let db_ref_prim_generators = db_reference_space_group_primitive_generators(&entry);

// The correction transformations keep the reference space group of `tmp_prim_mag_operations`
// TODO: precompute the correction transformation matrices
Expand All @@ -83,40 +83,6 @@ impl MagneticSpaceGroup {
Err(MoyoError::MagneticSpaceGroupTypeIdentificationError)
}

fn get_db_reference_space_group_primitive_generators(
mhs: &MagneticHallSymbol,
construct_type: &ConstructType,
) -> Operations {
let db_prim_mag_operations = mhs.primitive_generators();
match construct_type {
ConstructType::Type1 | ConstructType::Type2 | ConstructType::Type3 => {
// Reference space group: FSG
// -> Remove time-reversal parts
db_prim_mag_operations
.iter()
.map(|mops| mops.operation.clone())
.collect()
}
ConstructType::Type4 => {
// Reference space group: XSG
// -> Remove anti-translation operation
let identity = Rotation::identity();
db_prim_mag_operations
.iter()
.filter_map(|mops| {
// Here we assume the magnetic Hall symbol composes of XSG generators and one anti-translation operation
if mops.time_reversal {
assert_eq!(mops.operation.rotation, identity);
None
} else {
Some(mops.operation.clone())
}
})
.collect()
}
}
}

/// Search for origin_shift such that (trans_mat, origin_shift) transforms `prim_mag_operations` into <db_prim_mag_generators>
/// TODO: unify with identify/space_group.rs::match_origin_shift
fn match_origin_shift(
Expand Down Expand Up @@ -252,14 +218,30 @@ fn family_space_group_from_magnetic_space_group(
(fsg, is_type2)
}

/// Return generators of the reference space group of magnetic space group `entry`.
/// This function assumes the magnetic Hall symbol is extended from the Hall symbol in the standard setting.
fn db_reference_space_group_primitive_generators(entry: &MagneticHallSymbolEntry) -> Operations {
let ref_hall_number = entry.reference_hall_number();
let ref_hall_entry = hall_symbol_entry(ref_hall_number).unwrap();
let identity = Rotation::identity();
HallSymbol::new(&ref_hall_entry.hall_symbol)
.unwrap()
.primitive_generators()
.into_iter()
.filter(|ops| ops.rotation != identity) // In primitive, if rotation part is identity, it is a pure translation
.collect()
}

#[cfg(test)]
mod tests {
use rstest::rstest;
use test_log::test as test_with_log;

use super::*;
use crate::base::Transformation;
use crate::data::{MagneticHallSymbol, NUM_MAGNETIC_SPACE_GROUP_TYPES};
use crate::data::{
magnetic_hall_symbol_entry, MagneticHallSymbol, NUM_MAGNETIC_SPACE_GROUP_TYPES,
};

fn get_prim_mag_operations(uni_number: UNINumber) -> MagneticOperations {
let mhs = MagneticHallSymbol::from_uni_number(uni_number).unwrap();
Expand Down Expand Up @@ -299,6 +281,61 @@ mod tests {
assert_eq!(construct_type_actual, construct_type);
}

// Check generators of reference space group by two methods:
// 1. From the magnetic Hall symbol
// 2. From the Hall symbol with the corresponding Hall number
#[test_with_log]
fn test_db_reference_space_group_primitive_generators() {
for uni_number in 1..=NUM_MAGNETIC_SPACE_GROUP_TYPES {
let entry = magnetic_hall_symbol_entry(uni_number as UNINumber).unwrap();
let actual = db_reference_space_group_primitive_generators(&entry);

let mhs = MagneticHallSymbol::new(&entry.magnetic_hall_symbol).unwrap();
let identity = Rotation::identity();
let expect: Operations = match entry.construct_type() {
ConstructType::Type1 | ConstructType::Type2 => mhs
.primitive_generators()
.iter()
.filter_map(|mops| {
if mops.time_reversal || mops.operation.rotation == identity {
// Ignore 1' for Type2
None
} else {
Some(mops.operation.clone())
}
})
.collect(),
ConstructType::Type3 => mhs
.primitive_generators()
.iter()
.map(|mops| mops.operation.clone()) // Ignore time-reversal parts
.collect(),
ConstructType::Type4 => mhs
.primitive_generators()
.iter()
.filter_map(|mops| {
if mops.operation.rotation == identity {
// Ignore anti-translation
None
} else {
Some(mops.operation.clone())
}
})
.collect(),
};
assert_eq!(actual.len(), expect.len());
let mut hm_translation = HashMap::new();
for ops1 in actual.iter() {
hm_translation.insert(ops1.rotation.clone(), ops1.translation);
}
for ops2 in expect.iter() {
let translation1 = hm_translation.get(&ops2.rotation).unwrap();
let diff = ops2.translation - translation1;
assert_relative_eq!(diff.map(|e| (e - e.round().abs())).max(), 0.0);
}
}
}

#[test_with_log]
fn test_identify_magnetic_space_group() {
// for uni_number in 1..=NUM_MAGNETIC_SPACE_GROUP_TYPES {
Expand Down

0 comments on commit f109ea8

Please sign in to comment.