Skip to content

Commit

Permalink
traverse in primitive cell
Browse files Browse the repository at this point in the history
  • Loading branch information
lan496 committed Jan 11, 2025
1 parent f109ea8 commit 3137a08
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 101 deletions.
13 changes: 13 additions & 0 deletions moyo/src/base/transformation.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::ops::Mul;

use itertools::iproduct;
use nalgebra::base::{Matrix3, Vector3};

Expand Down Expand Up @@ -116,6 +118,17 @@ impl UnimodularTransformation {
}
}

impl Mul for UnimodularTransformation {
type Output = Self;

// (P_lhs, p_lhs) * (P_rhs, p_rhs) = (P_lhs * P_rhs, P_lhs * p_rhs + p_lhs)
fn mul(self, rhs: Self) -> Self::Output {
let new_linear = self.linear * rhs.linear;
let new_origin_shift = self.linear.map(|e| e as f64) * rhs.origin_shift + self.origin_shift;
Self::new(new_linear, new_origin_shift)
}
}

/// Represent change of origin and basis for an affine space
#[derive(Debug, Clone)]
pub struct Transformation {
Expand Down
12 changes: 12 additions & 0 deletions moyo/src/data/hall_symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,12 @@ impl HallSymbol {
operations
}

pub fn primitive_traverse(&self) -> Operations {
let operations = self.traverse();
Transformation::from_linear(self.centering.linear())
.inverse_transform_operations(&operations)
}

pub fn from_hall_number(hall_number: HallNumber) -> Option<Self> {
if let Some(entry) = hall_symbol_entry(hall_number) {
Self::new(entry.hall_symbol)
Expand Down Expand Up @@ -209,6 +215,12 @@ impl MagneticHallSymbol {
operations
}

pub fn primitive_traverse(&self) -> MagneticOperations {
let operations = self.traverse();
Transformation::from_linear(self.centering.linear())
.inverse_transform_magnetic_operations(&operations)
}

pub fn from_uni_number(uni_number: UNINumber) -> Option<Self> {
if let Some(entry) = magnetic_hall_symbol_entry(uni_number) {
Self::new(entry.magnetic_hall_symbol)
Expand Down
118 changes: 32 additions & 86 deletions moyo/src/identify/magnetic_space_group.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
use std::collections::HashMap;

use log::debug;
use nalgebra::{Dyn, OMatrix, OVector, U3};

use super::space_group::{solve_mod1, SpaceGroup};
use super::normalizer::integral_normalizer;
use super::space_group::SpaceGroup;
use crate::base::{
MagneticOperations, MoyoError, Operations, Rotation, Translation, UnimodularLinear,
UnimodularTransformation,
MagneticOperations, MoyoError, Operations, Rotation, Translation, UnimodularTransformation,
};
use crate::data::{
get_magnetic_space_group_type, hall_symbol_entry, magnetic_hall_symbol_entry, uni_number_range,
Expand Down Expand Up @@ -52,78 +51,30 @@ impl MagneticSpaceGroup {
});
}

// TODO:

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 = 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
let correction_transformations = todo!();
// for corr_trans_mat in correction_transformation_matrices {
// // (trans_mat, origin_shift): primitive input -> primitive DB
// let trans_mat = std_ref_spg.transformation.linear * corr_trans_mat;
// if let Some(origin_shift) = Self::match_origin_shift(
// prim_mag_operations,
// &trans_mat,
// &db_prim_mag_generators,
// epsilon,
// ) {
// debug!("Matched with UNI number {}", uni_number);
// return Ok(Self {
// uni_number,
// transformation: UnimodularTransformation::new(trans_mat, origin_shift),
// });
// }
// }
}
Err(MoyoError::MagneticSpaceGroupTypeIdentificationError)
}

/// 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(
prim_mag_operations: &MagneticOperations,
trans_mat: &UnimodularLinear,
db_prim_mag_generators: &MagneticOperations,
epsilon: f64,
) -> Option<Translation> {
let new_prim_mag_operations = UnimodularTransformation::from_linear(*trans_mat)
.transform_magnetic_operations(prim_mag_operations);
let mut hm_translations = HashMap::new();
for mops in new_prim_mag_operations.iter() {
hm_translations.insert(
(mops.operation.rotation, mops.time_reversal),
mops.operation.translation,
);
}

let mut a = OMatrix::<i32, Dyn, U3>::zeros(3 * db_prim_mag_generators.len());
let mut b = OVector::<f64, Dyn>::zeros(3 * db_prim_mag_generators.len());
for (k, mops) in db_prim_mag_generators.iter().enumerate() {
let target_translation =
hm_translations.get(&(mops.operation.rotation, mops.time_reversal))?;

let ak = mops.operation.rotation - Rotation::identity();
let bk = mops.operation.translation - target_translation;
for i in 0..3 {
for j in 0..3 {
a[(3 * k + i, j)] = ak[(i, j)];
}
b[3 * k + i] = bk[i];
let db_prim_mag_operations = mhs.primitive_traverse();
let (db_ref_prim_operations, db_ref_prim_generators) =
db_reference_space_group_primitive(&entry);
let db_ref_prim_normalizer =
integral_normalizer(&db_ref_prim_operations, &db_ref_prim_generators, epsilon); // TODO: precompute the normalizer

for corr_trans in db_ref_prim_normalizer {
// new_transformation * corr_trans: primitive input -> primitive DB
let new_transformation = std_ref_spg.transformation.clone() * corr_trans;
let new_prim_mag_operations =
new_transformation.transform_magnetic_operations(prim_mag_operations);

// TODO:
// debug!("Matched with UNI number {}", uni_number);
// return Ok(Self {
// uni_number,
// transformation: new_transformation,
// });
}
}

match solve_mod1(&a, &b, epsilon) {
Some(s) => {
let origin_shift = (trans_mat.map(|e| e as f64) * s).map(|e| e % 1.);
Some(origin_shift)
}
None => None,
}
Err(MoyoError::MagneticSpaceGroupTypeIdentificationError)
}
}

Expand Down Expand Up @@ -218,18 +169,19 @@ fn family_space_group_from_magnetic_space_group(
(fsg, is_type2)
}

/// Return generators of the reference space group of magnetic space group `entry`.
/// Return operations and 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();
fn db_reference_space_group_primitive(entry: &MagneticHallSymbolEntry) -> (Operations, Operations) {
let ref_hall_entry = hall_symbol_entry(entry.reference_hall_number()).unwrap();
let ref_hall_symbol = HallSymbol::new(&ref_hall_entry.hall_symbol).unwrap();
let ref_prim_operations = ref_hall_symbol.primitive_traverse();
let identity = Rotation::identity();
HallSymbol::new(&ref_hall_entry.hall_symbol)
.unwrap()
let ref_prim_generators = ref_hall_symbol
.primitive_generators()
.into_iter()
.filter(|ops| ops.rotation != identity) // In primitive, if rotation part is identity, it is a pure translation
.collect()
.collect();
(ref_prim_operations, ref_prim_generators)
}

#[cfg(test)]
Expand All @@ -238,19 +190,13 @@ mod tests {
use test_log::test as test_with_log;

use super::*;
use crate::base::Transformation;
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();
let magnetic_operations = mhs.traverse();

// conventional -> primitive
let prim_mag_operations = Transformation::from_linear(mhs.centering.linear())
.inverse_transform_magnetic_operations(&magnetic_operations);
prim_mag_operations
mhs.primitive_traverse()
}

#[rstest]
Expand Down Expand Up @@ -288,7 +234,7 @@ mod tests {
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 (_, actual) = db_reference_space_group_primitive(&entry);

let mhs = MagneticHallSymbol::new(&entry.magnetic_hall_symbol).unwrap();
let identity = Rotation::identity();
Expand Down
19 changes: 4 additions & 15 deletions moyo/src/identify/space_group.rs
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ mod tests {
use rstest::rstest;
use std::collections::HashMap;

use crate::base::{Transformation, UnimodularTransformation, EPS};
use crate::base::{UnimodularTransformation, EPS};
use crate::data::{hall_symbol_entry, HallSymbol, Setting};

use super::{correction_transformation_matrices, solve_mod1, SpaceGroup};
Expand All @@ -272,11 +272,7 @@ mod tests {
fn test_correction_transformation_matrices() {
let hall_number = 21; // P 1 c 1
let hall_symbol = HallSymbol::from_hall_number(hall_number).unwrap();
let operations = hall_symbol.traverse();

// conventional -> primitive
let prim_operations = Transformation::from_linear(hall_symbol.centering.linear())
.inverse_transform_operations(&operations);
let prim_operations = hall_symbol.primitive_traverse();

// The correction transformation matrices should change the group into P1c1, P1a1, and P1n1
let entry = hall_symbol_entry(hall_number).unwrap();
Expand Down Expand Up @@ -309,11 +305,7 @@ mod tests {
fn test_identify_space_group(#[case] setting: Setting) {
for hall_number in 1..=530 {
let hall_symbol = HallSymbol::from_hall_number(hall_number).unwrap();
let operations = hall_symbol.traverse();

// conventional -> primitive
let prim_operations = Transformation::from_linear(hall_symbol.centering.linear())
.inverse_transform_operations(&operations);
let prim_operations = hall_symbol.primitive_traverse();

let space_group = SpaceGroup::new(&prim_operations, setting, 1e-8).unwrap();

Expand All @@ -333,10 +325,7 @@ mod tests {

let matched_hall_symbol =
HallSymbol::from_hall_number(space_group.hall_number).unwrap();
let matched_operations = matched_hall_symbol.traverse();
let matched_prim_operations =
Transformation::from_linear(matched_hall_symbol.centering.linear())
.inverse_transform_operations(&matched_operations);
let matched_prim_operations = matched_hall_symbol.primitive_traverse();

let mut hm_translations = HashMap::new();
for operation in matched_prim_operations.iter() {
Expand Down

0 comments on commit 3137a08

Please sign in to comment.